Skip to content

Upgrading Packages ​

This page is the starting point for upgrading @tma.js packages to the current major versions. It summarizes changes affecting all packages, lists migration guides for each package, and describes what to use instead of the removed packages.

Upgrade all @tma.js packages at once. Packages of the previous and the current major versions are not compatible with each other.

Packages ​

Previous packagePrevious majorCurrent packageMigration guide
@tma.js/bridge2.x@tma.js/bridgeMigrating from 2.x
@tma.js/sdk3.x@tma.js/sdkMigrating from 3.x
@tma.js/sdk-react3.x@tma.js/sdk-reactMigrating from 3.x
@tma.js/sdk-solid3.x@tma.js/sdk-solidMigrating from 3.x
@tma.js/sdk-svelte1.x@tma.js/sdk-svelteMigrating from 1.x
@tma.js/sdk-vue1.x@tma.js/sdk-vueMigrating from 1.x
@tma.js/init-data-node2.x@tma.js/init-dataMigrating from @tma.js/init-data-node
@tma.js/signals1.xRemoved@tma.js/signals
@tma.js/toolkit1.xRemoved@tma.js/toolkit
@tma.js/transformers1.xRemoved@tma.js/transformers
@tma.js/types1.xRemoved@tma.js/types

The framework bindings re-export @tma.js/sdk, and the SDK re-exports @tma.js/bridge. If you use a binding, read the bridge and the SDK guides too, as their changes apply to it. The bindings now list @tma.js/sdk as a peer dependency, so install it next to the binding: pnpm i @tma.js/sdk @tma.js/sdk-react.

Changes in All Packages ​

fp-ts Replaced With Result ​

The packages no longer depend on fp-ts. Functions returning Either or TaskEither, named xFp, were replaced with functions named safeX. They return a plain Result object: { ok: true, data } on success, or { ok: false, error } on an expected failure. Functions without the prefix still throw errors.

ts
// Before.
import { retrieveLaunchParamsFp } from '@tma.js/sdk';
import { either as E, function as fn } from 'fp-ts';

fn.pipe(
  retrieveLaunchParamsFp(),
  E.match(
    error => console.error(error),
    lp => console.log(lp.tgWebAppPlatform),
  ),
);

// After.
import { safeRetrieveLaunchParams } from '@tma.js/sdk';

const result = safeRetrieveLaunchParams();
if (result.ok) {
  console.log(result.data.tgWebAppPlatform);
} else {
  console.error(result.error);
}

The Result<E, T> type has the error type first. @tma.js/bridge also exports the ok, err, unwrap and throwing helpers to work with results.

WARNING

Only expected errors, like a timeout or invalid data, are returned in Result. Errors caused by the environment or wrong usage, like calling a method before init(), are thrown even by safeX functions.

Promises and AbortSignal ​

BetterPromise was replaced with the standard Promise. The cancel() method and CancelledError were removed. To abort an operation, pass the standard AbortSignal in the signal option, which replaces the abortSignal option. When aborted, the promise is rejected with signal.reason.

ts
// Before.
const promise = request('web_app_request_phone', 'phone_requested');
promise.cancel();

// After.
const controller = new AbortController();
const promise = request('web_app_request_phone', 'phone_requested', {
  signal: controller.signal,
});
controller.abort();

TimeoutError is now a class of @tma.js/bridge, so instanceof checks against the class from better-promises no longer work.

Signals Replaced With Computed ​

Reactive values of SDK components, like backButton.isVisible, were signals from @tma.js/signals. Now they are computed values of the Computed type. Call such a value to get its current state, and use subscribe to track its changes. subscribe returns a function removing the listener.

ts
// Before.
const off = backButton.isVisible.sub((current, prev) => {
  console.log(prev, '->', current);
});

// After.
const off = backButton.isVisible.subscribe((next, prev) => {
  console.log(prev, '->', next);
});

The sub, unsub, unsubAll methods and the once option were removed. The packages no longer export functions creating signals. See @tma.js/signals for details.

In the framework bindings, the useSignal hook was replaced with useComputed.

isAvailable and ifAvailable Removed ​

The isAvailable() and ifAvailable() helpers of SDK methods were removed. Use isSupported(), which is now a plain function instead of a signal, and supports(feature) where available. Calling an unsupported method, a method before init(), or a method of an unmounted component throws an error. See the SDK migration guide for details.

init() Is Required ​

Call init() from @tma.js/sdk (or a binding) before using any SDK functionality. Some functions previously worked without it. Now they throw NotInitializedError.

LaunchParams.tgWebAppData Is a Raw String ​

Launch parameters returned by retrieveLaunchParams and parseLaunchParams contain init data in the raw format, not a parsed object. Pass it to your server as is. To parse it, use parse from @tma.js/init-data, or the SDK initData component.

ts
// Before.
retrieveLaunchParams().tgWebAppData?.user;

// After.
import { parse } from '@tma.js/init-data';

const { tgWebAppData } = retrieveLaunchParams();
tgWebAppData && parse(tgWebAppData).user;

Bridge IIFE Global Renamed ​

The IIFE build of @tma.js/bridge loaded via a <script> tag now exposes the tmajs.bridge global instead of tapps.bridge. The @tma.js/sdk global is still tmajs.sdk.

Session Storage Keys Changed ​

The packages save launch parameters and components state in the session storage, so they survive page reloads. The keys and the format have changed:

DataPrevious keyCurrent key
Launch parameterstapps/launchParams (JSON)tma.js/launch-params (query)
SDK components statetapps/<component name>tma.js/sdk/<component name>

Values saved by the previous versions are ignored. It matters only if the page is reloaded within the same mini app session while the update is rolled out.

Removed Packages ​

@tma.js/signals ​

The package contained signals used by the SDK to describe the components state. The SDK now uses its own computed values and doesn't export functions creating them.

To store your own reactive state, use the state management of your framework, or any signals library, like @preact/signals-core or alien-signals. To connect such state with SDK values, subscribe to them using subscribe.

What it exportedWhat to use instead
signal, computed, batchNo replacement. Use your framework state or any signals library.
Computed typeComputed type from @tma.js/sdk
Signal, SignalOptions typesNo replacement
SubscribeListenerFn type(next: T, prev: T) => void
RemoveListenerFn typeVoidFunction

Methods of SDK reactive values:

BeforeAfter
value()value()
value.sub(listener)value.subscribe(listener)
value.sub(listener, true)Call the function returned by subscribe inside the listener
value.unsub(listener)Call the function returned by subscribe
value.unsubAll()Call the functions returned by subscribe
value.set(), value.reset()Component methods, e.g. backButton.show()
value.destroy()No replacement
ts
// Before.
backButton.isVisible.sub(isVisible => {
  console.log('Visibility changed once:', isVisible);
}, true);

// After.
const off = backButton.isVisible.subscribe(isVisible => {
  off();
  console.log('Visibility changed once:', isVisible);
});

TIP

Like before, listeners receive the next and the previous values, and are called only when the value changes. They are not called on subscribe.

@tma.js/toolkit ​

The package contained internal utilities shared by other packages.

What it exportedWhat to use instead
createLogger and the Logger, LoggerFn, LoggerForceFn, LoggerOptions, LogLevel typesNo factory. To replace the logger used by the packages, call setLogger from @tma.js/bridge. getLogger returns the current one, and setDebug enables debug logs.
snakeToCamel, camelToSnake, snakeToKebab, camelToKebab, snakeToCamelObjKeys, camelToSnakeObjKeys, deepSnakeToCamelObjKeys and their typesNo replacement. The SDK components provide camel-cased getters, e.g. initData.authDate.
getStorageValue, setStorageValueNo replacement. Use sessionStorage directly.
throwifyFpFn, throwifyAnyEitherthrowing and unwrap from @tma.js/bridge, working with Result
BetterTaskEither and the fp-ts related types (AnyEither, RightOfEither, LeftOfEither and others)Result from @tma.js/bridge
createCbCollectorNo replacement
Utility types: If, Or, Maybe, AnyFn, IsNever, IsUndefined, UnionStringKeys, UnionRequiredKeys, UnionOptionalKeysNo replacement. Define them yourself or use a library like type-fest.

The Logger interface of @tma.js/bridge has the log, warn and error methods:

ts
import { setLogger } from '@tma.js/bridge';

setLogger({
  log: (...args) => console.log('[tma.js]', ...args),
  warn: (...args) => console.warn('[tma.js]', ...args),
  error: (...args) => console.error('[tma.js]', ...args),
});

@tma.js/transformers ​

The package contained Valibot schemas and functions parsing and serializing launch parameters, init data and colors. The schemas are no longer public, and the functions moved to other packages.

What it exportedWhat to use instead
parseLaunchParamsQuery, parseLaunchParamsQueryFpparseLaunchParams, safeParseLaunchParams from @tma.js/bridge
serializeLaunchParamsQueryserializeLaunchParams from @tma.js/bridge
isLaunchParamsQuerysafeParseLaunchParams(value).ok from @tma.js/bridge
parseInitDataQuery, parseInitDataQueryFpparse, safeParse from @tma.js/init-data
serializeInitDataQueryserialize from @tma.js/init-data
ParseLaunchParamsQueryError, ParseInitDataQueryError typesInvalidLaunchParamsError from @tma.js/bridge, InvalidInitDataError from @tma.js/init-data
LaunchParamsLike, InitDataLike typesLaunchParams from @tma.js/bridge, Partial<InitData> with InitData from @tma.js/init-data
isRGBisRGB from @tma.js/sdk
toRGB, toRGBFptoRGB, safeToRGB from @tma.js/sdk
isRGBShort, isRGBA, isRGBAShort, isAnyRGBsafeToRGB(value).ok from @tma.js/sdk checks any supported format
toRGBFull, toRGBFullFpNo replacement. Colors are converted to the #RRGGBB format only.
Schemas: launchParams, launchParamsQuery, initData, initDataQuery, initDataUser, initDataChat, themeParams, miniAppsMessageNo replacement. Use the parsing functions above.
InitDataGenSchema, InitDataGenType, LaunchParamsGenSchema, LaunchParamsGenType, MiniAppsMessageGenSchema, MiniAppsMessageGenType typesInitData from @tma.js/init-data, LaunchParams from @tma.js/bridge
pipeJsonToSchema, pipeQueryToSchema and the JsonToSchemaPipe, QueryToSchemaPipe typesNo replacement. Use Valibot's parseJson() action directly.

@tma.js/sdk re-exports @tma.js/bridge, so the bridge functions above can be imported from the SDK or a binding. The init data functions require installing @tma.js/init-data.

TIP

Like before, toRGB drops the alpha channel: toRGB('#ff000080') returns '#ff0000'. For an unknown color format, it now throws InvalidColorError, and safeToRGB returns it.

@tma.js/types ​

The package contained types shared by other packages. They moved to the packages using them.

What it exportedWhat to use instead
InitData, User, Chat, ChatType@tma.js/init-data. @tma.js/sdk re-exports them.
LaunchParams@tma.js/bridge. @tma.js/sdk re-exports it. tgWebAppData is now a string.
Platform, Version, RGB, ThemeParams@tma.js/bridge. @tma.js/sdk re-exports them.
KnownThemeParamsKeyNo replacement. ThemeParams lists the known keys as optional properties.

TIP

The previous @tma.js/sdk exported the InitData and ThemeParams types as InitDataType and ThemeParamsType, as the original names were taken by components. Now InitData and ThemeParams are the data types, and the component types are InitDataComponent and ThemeParamsComponent.

Released under the MIT License.