@tma.js/sdk 0.11.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (127) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +29 -0
  3. package/dist/lib/browser.js +2 -0
  4. package/dist/lib/browser.js.map +1 -0
  5. package/dist/lib/index.cjs +2 -0
  6. package/dist/lib/index.cjs.map +1 -0
  7. package/dist/lib/index.mjs +2 -0
  8. package/dist/lib/index.mjs.map +1 -0
  9. package/dist/types/components/BackButton/BackButton.d.ts +44 -0
  10. package/dist/types/components/BackButton/index.d.ts +2 -0
  11. package/dist/types/components/BackButton/types.d.ts +9 -0
  12. package/dist/types/components/ClosingBehaviour/ClosingBehaviour.d.ts +35 -0
  13. package/dist/types/components/ClosingBehaviour/index.d.ts +2 -0
  14. package/dist/types/components/ClosingBehaviour/types.d.ts +7 -0
  15. package/dist/types/components/CloudStorage/CloudStorage.d.ts +47 -0
  16. package/dist/types/components/CloudStorage/index.d.ts +1 -0
  17. package/dist/types/components/HapticFeedback/HapticFeedback.d.ts +37 -0
  18. package/dist/types/components/HapticFeedback/index.d.ts +1 -0
  19. package/dist/types/components/InitData/InitData.d.ts +52 -0
  20. package/dist/types/components/InitData/index.d.ts +1 -0
  21. package/dist/types/components/MainButton/MainButton.d.ts +114 -0
  22. package/dist/types/components/MainButton/index.d.ts +2 -0
  23. package/dist/types/components/MainButton/types.d.ts +15 -0
  24. package/dist/types/components/Popup/Popup.d.ts +44 -0
  25. package/dist/types/components/Popup/index.d.ts +2 -0
  26. package/dist/types/components/Popup/types.d.ts +60 -0
  27. package/dist/types/components/Popup/utils.d.ts +7 -0
  28. package/dist/types/components/QRScanner/QRScanner.d.ts +40 -0
  29. package/dist/types/components/QRScanner/index.d.ts +2 -0
  30. package/dist/types/components/QRScanner/types.d.ts +7 -0
  31. package/dist/types/components/ThemeParams/ThemeParams.d.ts +73 -0
  32. package/dist/types/components/ThemeParams/index.d.ts +2 -0
  33. package/dist/types/components/ThemeParams/types.d.ts +9 -0
  34. package/dist/types/components/Viewport/Viewport.d.ts +108 -0
  35. package/dist/types/components/Viewport/index.d.ts +2 -0
  36. package/dist/types/components/Viewport/types.d.ts +10 -0
  37. package/dist/types/components/WebApp/WebApp.d.ts +145 -0
  38. package/dist/types/components/WebApp/index.d.ts +2 -0
  39. package/dist/types/components/WebApp/types.d.ts +11 -0
  40. package/dist/types/components/index.d.ts +11 -0
  41. package/dist/types/env.d.ts +8 -0
  42. package/dist/types/errors/MethodNotSupportedError.d.ts +6 -0
  43. package/dist/types/errors/ParameterNotSupportedError.d.ts +6 -0
  44. package/dist/types/errors/index.d.ts +2 -0
  45. package/dist/types/index.d.ts +8 -0
  46. package/dist/types/init/creators/createBackButton.d.ts +9 -0
  47. package/dist/types/init/creators/createClosingBehavior.d.ts +8 -0
  48. package/dist/types/init/creators/createMainButton.d.ts +11 -0
  49. package/dist/types/init/creators/createPostEvent.d.ts +7 -0
  50. package/dist/types/init/creators/createRequestIdGenerator.d.ts +5 -0
  51. package/dist/types/init/creators/createSyncedThemeParams.d.ts +7 -0
  52. package/dist/types/init/creators/createViewport.d.ts +10 -0
  53. package/dist/types/init/creators/createWebApp.d.ts +14 -0
  54. package/dist/types/init/creators/index.d.ts +8 -0
  55. package/dist/types/init/css.d.ts +57 -0
  56. package/dist/types/init/index.d.ts +2 -0
  57. package/dist/types/init/init.d.ts +6 -0
  58. package/dist/types/init/types.d.ts +107 -0
  59. package/dist/types/launch-params.d.ts +20 -0
  60. package/dist/types/state/State.d.ts +15 -0
  61. package/dist/types/state/index.d.ts +2 -0
  62. package/dist/types/state/types.d.ts +30 -0
  63. package/dist/types/storage.d.ts +48 -0
  64. package/dist/types/supports.d.ts +22 -0
  65. package/dist/types/theme-params.d.ts +18 -0
  66. package/dist/types/types.d.ts +14 -0
  67. package/dist/types/url.d.ts +7 -0
  68. package/package.json +67 -0
  69. package/src/components/BackButton/BackButton.ts +90 -0
  70. package/src/components/BackButton/index.ts +2 -0
  71. package/src/components/BackButton/types.ts +13 -0
  72. package/src/components/ClosingBehaviour/ClosingBehaviour.ts +62 -0
  73. package/src/components/ClosingBehaviour/index.ts +6 -0
  74. package/src/components/ClosingBehaviour/types.ts +12 -0
  75. package/src/components/CloudStorage/CloudStorage.ts +135 -0
  76. package/src/components/CloudStorage/index.ts +1 -0
  77. package/src/components/HapticFeedback/HapticFeedback.ts +62 -0
  78. package/src/components/HapticFeedback/index.ts +1 -0
  79. package/src/components/InitData/InitData.ts +116 -0
  80. package/src/components/InitData/index.ts +1 -0
  81. package/src/components/MainButton/MainButton.ts +243 -0
  82. package/src/components/MainButton/index.ts +2 -0
  83. package/src/components/MainButton/types.ts +20 -0
  84. package/src/components/Popup/Popup.ts +81 -0
  85. package/src/components/Popup/index.ts +8 -0
  86. package/src/components/Popup/types.ts +69 -0
  87. package/src/components/Popup/utils.ts +59 -0
  88. package/src/components/QRScanner/QRScanner.ts +87 -0
  89. package/src/components/QRScanner/index.ts +2 -0
  90. package/src/components/QRScanner/types.ts +11 -0
  91. package/src/components/ThemeParams/ThemeParams.ts +154 -0
  92. package/src/components/ThemeParams/index.ts +2 -0
  93. package/src/components/ThemeParams/types.ts +18 -0
  94. package/src/components/Viewport/Viewport.ts +197 -0
  95. package/src/components/Viewport/index.ts +2 -0
  96. package/src/components/Viewport/types.ts +14 -0
  97. package/src/components/WebApp/WebApp.ts +310 -0
  98. package/src/components/WebApp/index.ts +2 -0
  99. package/src/components/WebApp/types.ts +17 -0
  100. package/src/components/index.ts +11 -0
  101. package/src/env.ts +17 -0
  102. package/src/errors/MethodNotSupportedError.ts +9 -0
  103. package/src/errors/ParameterNotSupportedError.ts +9 -0
  104. package/src/errors/index.ts +2 -0
  105. package/src/index.ts +8 -0
  106. package/src/init/creators/createBackButton.ts +22 -0
  107. package/src/init/creators/createClosingBehavior.ts +22 -0
  108. package/src/init/creators/createMainButton.ts +56 -0
  109. package/src/init/creators/createPostEvent.ts +36 -0
  110. package/src/init/creators/createRequestIdGenerator.ts +13 -0
  111. package/src/init/creators/createSyncedThemeParams.ts +14 -0
  112. package/src/init/creators/createViewport.ts +50 -0
  113. package/src/init/creators/createWebApp.ts +49 -0
  114. package/src/init/creators/index.ts +8 -0
  115. package/src/init/css.ts +166 -0
  116. package/src/init/index.ts +2 -0
  117. package/src/init/init.ts +160 -0
  118. package/src/init/types.ts +133 -0
  119. package/src/launch-params.ts +70 -0
  120. package/src/state/State.ts +53 -0
  121. package/src/state/index.ts +2 -0
  122. package/src/state/types.ts +34 -0
  123. package/src/storage.ts +65 -0
  124. package/src/supports.ts +44 -0
  125. package/src/theme-params.ts +34 -0
  126. package/src/types.ts +28 -0
  127. package/src/url.ts +24 -0
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Computes state property changed event.
3
+ */
4
+ export type PropChangedEvent<K extends string> = `${K}Changed`;
5
+ /**
6
+ * Returns object string keys.
7
+ */
8
+ export type StringKeys<T extends object> = Extract<keyof T, string>;
9
+ /**
10
+ * Extracts state property type by its computed change event name.
11
+ */
12
+ export type PropertyType<State extends object, Event extends string> = {
13
+ [Key in StringKeys<State>]: Event extends PropChangedEvent<Key> ? State[Key] : never;
14
+ }[StringKeys<State>];
15
+ /**
16
+ * Creates map, where key is event name which is used, when state property was changed.
17
+ * Value is according listener.
18
+ */
19
+ export type PropChangedEventsMap<State extends object> = {
20
+ [Event in `${StringKeys<State>}Changed`]: (value: PropertyType<State, Event>) => void;
21
+ };
22
+ /**
23
+ * Creates map with all events emitted by state.
24
+ */
25
+ export type StateEvents<State extends object> = PropChangedEventsMap<State> & {
26
+ /**
27
+ * Being called whenever any property was updated.
28
+ */
29
+ changed: () => void;
30
+ };
@@ -0,0 +1,48 @@
1
+ import type { HeaderColorKey } from '@tma.js/bridge';
2
+ import type { RGB } from '@tma.js/colors';
3
+ /**
4
+ * Describes storage keys and according values.
5
+ */
6
+ interface StorageParams {
7
+ 'back-button': {
8
+ isVisible: boolean;
9
+ };
10
+ 'closing-behavior': {
11
+ isConfirmationNeeded: boolean;
12
+ };
13
+ 'main-button': {
14
+ backgroundColor: RGB;
15
+ isEnabled: boolean;
16
+ isVisible: boolean;
17
+ isProgressVisible: boolean;
18
+ text: string;
19
+ textColor: RGB;
20
+ };
21
+ viewport: {
22
+ height: number;
23
+ isExpanded: boolean;
24
+ stableHeight: number;
25
+ width: number;
26
+ };
27
+ 'web-app': {
28
+ backgroundColor: RGB;
29
+ headerColor: HeaderColorKey | RGB;
30
+ };
31
+ 'launch-params': string;
32
+ }
33
+ /**
34
+ * Key which could be used to store data in storage.
35
+ */
36
+ type StorageKey = keyof StorageParams;
37
+ /**
38
+ * Saves value in sessionStorage.
39
+ * @param key - storage key.
40
+ * @param value - storage value.
41
+ */
42
+ export declare function saveStorageValue<K extends StorageKey>(key: K, value: StorageParams[K]): void;
43
+ /**
44
+ * Extracts value from the sessionStorage.
45
+ * @param key - storage key.
46
+ */
47
+ export declare function getStorageValue<K extends StorageKey>(key: K): StorageParams[K] | null;
48
+ export {};
@@ -0,0 +1,22 @@
1
+ import type { Version } from '@tma.js/utils';
2
+ import { type MethodName, type HasCheckSupportMethodName, type HasCheckSupportMethodParam } from '@tma.js/bridge';
3
+ export type SupportsFunc<M extends string> = (method: M) => boolean;
4
+ type HasCheckSupportMethodTuple = {
5
+ [M in HasCheckSupportMethodName]: [M, HasCheckSupportMethodParam<M>];
6
+ }[HasCheckSupportMethodName];
7
+ /**
8
+ * Returns function, which accepts predefined method name and checks if it is supported
9
+ * via passed schema and version.
10
+ * @param schema - object which contains methods names and TWA method as a dependency.
11
+ * @param version - platform version.
12
+ */
13
+ export declare function createSupportsFunc<M extends string>(version: Version, schema: Record<M, MethodName>): SupportsFunc<M>;
14
+ /**
15
+ * Returns function, which accepts predefined method name and checks if it is supported
16
+ * via passed schema and version.
17
+ * @param schema - object which contains methods names and TWA methods with specified parameter
18
+ * as a dependency.
19
+ * @param version - platform version.
20
+ */
21
+ export declare function createSupportsParamFunc<P extends string>(version: Version, schema: Record<P, HasCheckSupportMethodTuple>): SupportsFunc<P>;
22
+ export {};
@@ -0,0 +1,18 @@
1
+ import type { RGB } from '@tma.js/colors';
2
+ /**
3
+ * Application theme parameters. Defines palette used by the Telegram application.
4
+ */
5
+ export interface ThemeParamsType {
6
+ backgroundColor?: RGB;
7
+ buttonColor?: RGB;
8
+ buttonTextColor?: RGB;
9
+ hintColor?: RGB;
10
+ linkColor?: RGB;
11
+ secondaryBackgroundColor?: RGB;
12
+ textColor?: RGB;
13
+ }
14
+ /**
15
+ * Parses incoming value as theme parameters.
16
+ * @param value - value to parse.
17
+ */
18
+ export declare function parseThemeParams(value: unknown): ThemeParamsType;
@@ -0,0 +1,14 @@
1
+ import type { PostEvent as BridgePostEvent } from '@tma.js/bridge';
2
+ export type PostEvent = BridgePostEvent;
3
+ /**
4
+ * Color scheme.
5
+ */
6
+ export type ColorScheme = 'dark' | 'light';
7
+ /**
8
+ * Native Telegram application identifier.
9
+ */
10
+ export type Platform = 'android' | 'android_x' | 'ios' | 'macos' | 'tdesktop' | 'web' | 'weba' | 'unigram' | 'unknown' | string;
11
+ /**
12
+ * Function which generates unique request identifiers.
13
+ */
14
+ export type CreateRequestIdFunc = () => string;
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Converts passed URL to its full form.
3
+ * @param url - URL to format.
4
+ * @throws {Error} URL protocol is not supported by OS, or link has not allowed
5
+ * protocol.
6
+ */
7
+ export declare function formatURL(url: string): string;
package/package.json ADDED
@@ -0,0 +1,67 @@
1
+ {
2
+ "name": "@tma.js/sdk",
3
+ "version": "0.11.3",
4
+ "description": "TypeScript Source Development Kit for Telegram Web Apps client application.",
5
+ "author": "Vladislav Kibenko <wolfram.deus@gmail.com>",
6
+ "homepage": "https://github.com/Telegram-Mini-Apps/tma.js#readme",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git@github.com:Telegram-Mini-Apps/tma.js.git",
10
+ "directory": "packages/sdk"
11
+ },
12
+ "bugs": {
13
+ "url": "https://github.com/Telegram-Mini-Apps/tma.js/issues"
14
+ },
15
+ "keywords": [
16
+ "telegram-mini-apps",
17
+ "typescript",
18
+ "sdk"
19
+ ],
20
+ "license": "MIT",
21
+ "type": "module",
22
+ "sideEffects": false,
23
+ "files": [
24
+ "dist",
25
+ "src"
26
+ ],
27
+ "main": "dist/lib/index.cjs",
28
+ "browser": "dist/lib/browser.js",
29
+ "module": "dist/lib/index.mjs",
30
+ "types": "dist/types/index.d.ts",
31
+ "exports": {
32
+ ".": {
33
+ "types": "./dist/types/index.d.ts",
34
+ "import": "./dist/lib/index.mjs",
35
+ "require": "./dist/lib/index.cjs",
36
+ "default": "./dist/lib/index.cjs"
37
+ },
38
+ "./*": {
39
+ "types": "./dist/types/*.d.ts",
40
+ "import": "./dist/lib/*.mjs",
41
+ "require": "./dist/lib/*.cjs",
42
+ "default": "./dist/lib/*.cjs"
43
+ }
44
+ },
45
+ "dependencies": {
46
+ "@tma.js/bridge": "1.3.2",
47
+ "@tma.js/colors": "0.0.2",
48
+ "@tma.js/init-data": "0.2.14",
49
+ "@tma.js/utils": "0.5.2",
50
+ "@tma.js/util-types": "0.0.2",
51
+ "@tma.js/parsing": "0.0.2",
52
+ "@tma.js/event-emitter": "0.0.2"
53
+ },
54
+ "devDependencies": {
55
+ "tsconfig": "0.0.2",
56
+ "eslint-config-custom": "0.1.0",
57
+ "jest-config-custom": "0.1.0"
58
+ },
59
+ "publishConfig": {
60
+ "access": "public"
61
+ },
62
+ "scripts": {
63
+ "test": "jest",
64
+ "lint": "eslint -c .eslintrc.cjs src/**/* __tests__/**/*",
65
+ "build": "rimraf dist && rollup --config rollup.config.js"
66
+ }
67
+ }
@@ -0,0 +1,90 @@
1
+ import { EventEmitter } from '@tma.js/event-emitter';
2
+ import { on, off, postEvent as defaultPostEvent, type PostEvent } from '@tma.js/bridge';
3
+
4
+ import type { Version } from '@tma.js/utils';
5
+
6
+ import { createSupportsFunc, type SupportsFunc } from '../../supports.js';
7
+ import { State } from '../../state/index.js';
8
+
9
+ import type { BackButtonEvents, BackButtonState, BackButtonEventListener } from './types.js';
10
+
11
+ /**
12
+ * Class which controls the back button displayed in the header
13
+ * of the Web App in the Telegram interface. It is mostly used in case, when
14
+ * you want to provide a way to go bach in routing history or "rollback" some
15
+ * action.
16
+ */
17
+ export class BackButton {
18
+ private readonly ee = new EventEmitter<BackButtonEvents>();
19
+
20
+ private readonly state: State<BackButtonState>;
21
+
22
+ constructor(
23
+ isVisible: boolean,
24
+ version: Version,
25
+ private readonly postEvent: PostEvent = defaultPostEvent,
26
+ ) {
27
+ this.state = new State({ isVisible }, this.ee);
28
+ this.supports = createSupportsFunc(version, {
29
+ show: 'web_app_setup_back_button',
30
+ hide: 'web_app_setup_back_button',
31
+ });
32
+ }
33
+
34
+ private set isVisible(visible: boolean) {
35
+ this.state.set('isVisible', visible);
36
+ this.postEvent('web_app_setup_back_button', { is_visible: visible });
37
+ }
38
+
39
+ /**
40
+ * True if BackButton is currently visible.
41
+ */
42
+ get isVisible(): boolean {
43
+ return this.state.get('isVisible');
44
+ }
45
+
46
+ /**
47
+ * Hides the BackButton.
48
+ */
49
+ hide(): void {
50
+ this.isVisible = false;
51
+ }
52
+
53
+ /**
54
+ * Adds event listener.
55
+ * @param event - event name.
56
+ * @param listener - event listener.
57
+ */
58
+ on: typeof this.ee.on = (event, listener) => {
59
+ if (event === 'click') {
60
+ return on('back_button_pressed', listener as BackButtonEventListener<'click'>);
61
+ }
62
+
63
+ this.ee.on(event, listener);
64
+ };
65
+
66
+ /**
67
+ * Removes event listener.
68
+ * @param event - event name.
69
+ * @param listener - event listener.
70
+ */
71
+ off: typeof this.ee.off = (event, listener) => {
72
+ if (event === 'click') {
73
+ return off('back_button_pressed', listener as BackButtonEventListener<'click'>);
74
+ }
75
+
76
+ this.ee.off(event, listener);
77
+ };
78
+
79
+ /**
80
+ * Shows the BackButton.
81
+ */
82
+ show(): void {
83
+ this.isVisible = true;
84
+ }
85
+
86
+ /**
87
+ * Checks if specified method is supported by current component.
88
+ */
89
+ supports: SupportsFunc<'show' | 'hide'>;
90
+ }
@@ -0,0 +1,2 @@
1
+ export * from './BackButton.js';
2
+ export type { BackButtonEventListener, BackButtonEventName, BackButtonEvents } from './types.js';
@@ -0,0 +1,13 @@
1
+ import type { StateEvents } from '../../state/index.js';
2
+
3
+ export interface BackButtonState {
4
+ isVisible: boolean;
5
+ }
6
+
7
+ export interface BackButtonEvents extends StateEvents<BackButtonState> {
8
+ click: () => void;
9
+ }
10
+
11
+ export type BackButtonEventName = keyof BackButtonEvents;
12
+
13
+ export type BackButtonEventListener<E extends BackButtonEventName> = BackButtonEvents[E];
@@ -0,0 +1,62 @@
1
+ import { EventEmitter } from '@tma.js/event-emitter';
2
+ import { postEvent as defaultPostEvent, type PostEvent } from '@tma.js/bridge';
3
+
4
+ import { State } from '../../state/index.js';
5
+
6
+ import type { ClosingBehaviourEvents, ClosingBehaviourState } from './types.js';
7
+
8
+ /**
9
+ * Component responsible for controlling current closing confirmation
10
+ * status.
11
+ */
12
+ export class ClosingBehaviour {
13
+ private readonly ee = new EventEmitter<ClosingBehaviourEvents>();
14
+
15
+ private readonly state: State<ClosingBehaviourState>;
16
+
17
+ constructor(
18
+ isConfirmationNeeded: boolean,
19
+ private readonly postEvent: PostEvent = defaultPostEvent,
20
+ ) {
21
+ this.state = new State({ isConfirmationNeeded }, this.ee);
22
+ }
23
+
24
+ private set isConfirmationNeeded(value: boolean) {
25
+ this.state.set('isConfirmationNeeded', value);
26
+ this.postEvent('web_app_setup_closing_behavior', { need_confirmation: value });
27
+ }
28
+
29
+ /**
30
+ * Returns true, if the confirmation dialog enabled while the user is trying
31
+ * to close the Web App.
32
+ */
33
+ get isConfirmationNeeded(): boolean {
34
+ return this.state.get('isConfirmationNeeded');
35
+ }
36
+
37
+ /**
38
+ * Disables the confirmation dialog while the user is trying to close the
39
+ * Web App.
40
+ */
41
+ disableConfirmation(): void {
42
+ this.isConfirmationNeeded = false;
43
+ }
44
+
45
+ /**
46
+ * Enables the confirmation dialog while the user is trying to close the
47
+ * Web App.
48
+ */
49
+ enableConfirmation(): void {
50
+ this.isConfirmationNeeded = true;
51
+ }
52
+
53
+ /**
54
+ * Adds new event listener.
55
+ */
56
+ on: typeof this.ee.on = this.ee.on.bind(this.ee);
57
+
58
+ /**
59
+ * Removes event listener.
60
+ */
61
+ off: typeof this.ee.off = this.ee.off.bind(this.ee);
62
+ }
@@ -0,0 +1,6 @@
1
+ export * from './ClosingBehaviour.js';
2
+ export type {
3
+ ClosingBehaviourEventName,
4
+ ClosingBehaviourEventListener,
5
+ ClosingBehaviourEvents,
6
+ } from './types.js';
@@ -0,0 +1,12 @@
1
+ import type { StateEvents } from '../../state/index.js';
2
+
3
+ export interface ClosingBehaviourState {
4
+ isConfirmationNeeded: boolean;
5
+ }
6
+
7
+ export type ClosingBehaviourEvents = StateEvents<ClosingBehaviourState>;
8
+
9
+ export type ClosingBehaviourEventName = keyof ClosingBehaviourEvents;
10
+
11
+ export type ClosingBehaviourEventListener<E extends ClosingBehaviourEventName> =
12
+ ClosingBehaviourEvents[E];
@@ -0,0 +1,135 @@
1
+ import {
2
+ postEvent as defaultPostEvent,
3
+ request,
4
+ type RequestOptions,
5
+ } from '@tma.js/bridge';
6
+ import { array, json, string } from '@tma.js/parsing';
7
+
8
+ import type { Version } from '@tma.js/utils';
9
+
10
+ import { createSupportsFunc, type SupportsFunc } from '../../supports.js';
11
+
12
+ import type { CreateRequestIdFunc } from '../../types.js';
13
+
14
+ type WiredRequestOptions = Omit<RequestOptions, 'postEvent'>;
15
+
16
+ interface Methods {
17
+ deleteStorageValues: { keys: string | string[] };
18
+ getStorageValues: { keys: string | string[] };
19
+ getStorageKeys: {};
20
+ saveStorageValue: { key: string; value: string };
21
+ }
22
+
23
+ const stringArray = array().of(string());
24
+
25
+ function objectFromKeys<K extends string, V>(keys: K[], value: V): Record<K, V> {
26
+ return keys.reduce<Record<K, V>>((acc, key) => {
27
+ acc[key] = value;
28
+ return acc;
29
+ }, {} as Record<K, V>);
30
+ }
31
+
32
+ export class CloudStorage {
33
+ constructor(
34
+ version: Version,
35
+ private readonly createRequestId: CreateRequestIdFunc,
36
+ private readonly postEvent = defaultPostEvent,
37
+ ) {
38
+ this.supports = createSupportsFunc(version, {
39
+ deleteKeys: 'web_app_invoke_custom_method',
40
+ getKeys: 'web_app_invoke_custom_method',
41
+ getValues: 'web_app_invoke_custom_method',
42
+ saveValue: 'web_app_invoke_custom_method',
43
+ });
44
+ }
45
+
46
+ /**
47
+ * Invokes custom method related to CloudStorage.
48
+ * @param method - method name.
49
+ * @param params - method parameters.
50
+ * @param options - execution options.
51
+ */
52
+ private async invokeCustomMethod<M extends keyof Methods>(
53
+ method: M,
54
+ params: Methods[M],
55
+ options: WiredRequestOptions = {},
56
+ ): Promise<unknown> {
57
+ const { result, error } = await request(
58
+ 'web_app_invoke_custom_method',
59
+ { method, params, req_id: this.createRequestId() },
60
+ 'custom_method_invoked',
61
+ { ...options, postEvent: this.postEvent },
62
+ );
63
+
64
+ if (error) {
65
+ throw new Error(typeof error === 'string' ? error : `Unknown error: ${JSON.stringify(error)}`);
66
+ }
67
+
68
+ return result;
69
+ }
70
+
71
+ /**
72
+ * Deletes specified keys from the CloudStorage.
73
+ * @param keys - keys list.
74
+ * @param options - request execution options.
75
+ */
76
+ async deleteKeys(keys: string[], options?: WiredRequestOptions): Promise<void> {
77
+ if (keys.length === 0) {
78
+ return;
79
+ }
80
+
81
+ await this.invokeCustomMethod('deleteStorageValues', { keys }, options);
82
+ }
83
+
84
+ /**
85
+ * Returns list of all keys presented in CloudStorage.
86
+ * @param options - request execution options.
87
+ */
88
+ async getKeys(options?: WiredRequestOptions): Promise<string[]> {
89
+ const result = await this.invokeCustomMethod('getStorageKeys', {}, options);
90
+
91
+ return stringArray.parse(result);
92
+ }
93
+
94
+ /**
95
+ * Returns map, where key is one of the specified in keys argument, and value is according
96
+ * storage value.
97
+ * @param keys - keys list.
98
+ * @param options - request execution options.
99
+ */
100
+ async getValues<K extends string>(
101
+ keys: K[],
102
+ options?: WiredRequestOptions,
103
+ ): Promise<Record<K, string>> {
104
+ if (keys.length === 0) {
105
+ return objectFromKeys(keys, '');
106
+ }
107
+
108
+ const schema = json<Record<K, string>>(
109
+ objectFromKeys(keys, string()) as any, // fixme
110
+ );
111
+ const result = await this.invokeCustomMethod('getStorageValues', { keys }, options);
112
+
113
+ return schema.parse(result);
114
+ }
115
+
116
+ /**
117
+ * Saves specified value by key.
118
+ * @param key - storage key.
119
+ * @param value - storage value.
120
+ * @param options - request execution options.
121
+ */
122
+ async saveValue(key: string, value: string, options?: WiredRequestOptions): Promise<void> {
123
+ await this.invokeCustomMethod('saveStorageValue', { key, value }, options);
124
+ }
125
+
126
+ /**
127
+ * Checks if specified method is supported by current component.
128
+ */
129
+ supports: SupportsFunc<
130
+ | 'deleteKeys'
131
+ | 'getKeys'
132
+ | 'getValues'
133
+ | 'saveValue'
134
+ >;
135
+ }
@@ -0,0 +1 @@
1
+ export * from './CloudStorage.js';
@@ -0,0 +1,62 @@
1
+ import type { Version } from '@tma.js/utils';
2
+ import {
3
+ postEvent as defaultPostEvent,
4
+ type PostEvent,
5
+ type ImpactHapticFeedbackStyle,
6
+ type NotificationHapticFeedbackType,
7
+ } from '@tma.js/bridge';
8
+
9
+ import { createSupportsFunc, type SupportsFunc } from '../../supports.js';
10
+
11
+ /**
12
+ * Class which controls haptic feedback. It allows calling different types of
13
+ * haptic notifications which usually occur after user interaction with
14
+ * application.
15
+ */
16
+ export class HapticFeedback {
17
+ constructor(version: Version, private readonly postEvent: PostEvent = defaultPostEvent) {
18
+ this.supports = createSupportsFunc(version, {
19
+ impactOccurred: 'web_app_trigger_haptic_feedback',
20
+ notificationOccurred: 'web_app_trigger_haptic_feedback',
21
+ selectionChanged: 'web_app_trigger_haptic_feedback',
22
+ });
23
+ }
24
+
25
+ /**
26
+ * A method tells that an impact occurred. The Telegram app may play the
27
+ * appropriate haptics based on style value passed.
28
+ * @param style - impact style.
29
+ */
30
+ impactOccurred(style: ImpactHapticFeedbackStyle): void {
31
+ this.postEvent('web_app_trigger_haptic_feedback', { type: 'impact', impact_style: style });
32
+ }
33
+
34
+ /**
35
+ * A method tells that a task or action has succeeded, failed, or produced
36
+ * a warning. The Telegram app may play the appropriate haptics based on
37
+ * type value passed.
38
+ * @param type - notification type.
39
+ */
40
+ notificationOccurred(type: NotificationHapticFeedbackType): void {
41
+ this.postEvent('web_app_trigger_haptic_feedback', {
42
+ type: 'notification',
43
+ notification_type: type,
44
+ });
45
+ }
46
+
47
+ /**
48
+ * A method tells that the user has changed a selection. The Telegram app
49
+ * may play the appropriate haptics.
50
+ *
51
+ * Do not use this feedback when the user makes or confirms a selection;
52
+ * use it only when the selection changes.
53
+ */
54
+ selectionChanged(): void {
55
+ this.postEvent('web_app_trigger_haptic_feedback', { type: 'selection_change' });
56
+ }
57
+
58
+ /**
59
+ * Checks if specified method is supported by current component.
60
+ */
61
+ supports: SupportsFunc<'impactOccurred' | 'notificationOccurred' | 'selectionChanged'>;
62
+ }
@@ -0,0 +1 @@
1
+ export * from './HapticFeedback.js';