@tma.js/sdk 1.4.1 → 1.4.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.
- package/dist/dts/bridge/index.d.ts +2 -1
- package/dist/dts/bridge/parseMessage.d.ts +18 -0
- package/dist/dts/classnames/mergeClassNames.d.ts +9 -12
- package/dist/dts/index.d.ts +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.iife.js +1 -1
- package/dist/index.iife.js.map +1 -1
- package/dist/index.mjs +155 -151
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/bridge/__tests__/parseMessage.ts +23 -0
- package/src/bridge/events/__tests__/onTelegramEvent.ts +5 -7
- package/src/bridge/events/onTelegramEvent.ts +9 -11
- package/src/bridge/index.ts +2 -1
- package/src/bridge/parseMessage.ts +28 -0
- package/src/classnames/__tests__/mergeClassNames.ts +1 -1
- package/src/classnames/mergeClassNames.ts +16 -24
- package/src/index.ts +1 -0
- /package/dist/dts/bridge/{invoke-custom-method.d.ts → invokeCustomMethod.d.ts} +0 -0
- /package/src/bridge/{invoke-custom-method.ts → invokeCustomMethod.ts} +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tma.js/sdk",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.3",
|
|
4
4
|
"description": "TypeScript Source Development Kit for Telegram Mini Apps client application.",
|
|
5
5
|
"author": "Vladislav Kibenko <wolfram.deus@gmail.com>",
|
|
6
6
|
"homepage": "https://github.com/Telegram-Mini-Apps/tma.js#readme",
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { it, expect } from 'vitest';
|
|
2
|
+
|
|
3
|
+
import { parseMessage } from '../parseMessage';
|
|
4
|
+
|
|
5
|
+
it('should parse value as JSON with properties { eventType: string; eventData?: unknown }', () => {
|
|
6
|
+
expect(parseMessage({ eventType: 1 })).toEqual({ eventType: '1' });
|
|
7
|
+
expect(parseMessage({ eventType: 'test' })).toEqual({ eventType: 'test' });
|
|
8
|
+
expect(parseMessage({ eventType: 'test', eventData: 123 })).toEqual({
|
|
9
|
+
eventType: 'test',
|
|
10
|
+
eventData: 123,
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
expect(parseMessage('{"eventType":1}')).toEqual({ eventType: '1' });
|
|
14
|
+
expect(parseMessage('{"eventType":"test"}')).toEqual({ eventType: 'test' });
|
|
15
|
+
expect(parseMessage('{"eventType":"test","eventData":123}')).toEqual({
|
|
16
|
+
eventType: 'test',
|
|
17
|
+
eventData: 123,
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it('should throw if eventType property is missing', () => {
|
|
22
|
+
expect(() => parseMessage({})).toThrow();
|
|
23
|
+
});
|
|
@@ -4,17 +4,12 @@ import { createWindow, type WindowSpy } from '../../../../test-utils/createWindo
|
|
|
4
4
|
import { dispatchWindowMessageEvent } from '../../../../test-utils/dispatchWindowMessageEvent';
|
|
5
5
|
import { onTelegramEvent } from '../onTelegramEvent';
|
|
6
6
|
|
|
7
|
-
let windowSpy: WindowSpy;
|
|
8
|
-
|
|
9
|
-
beforeEach(() => {
|
|
10
|
-
windowSpy = createWindow();
|
|
11
|
-
});
|
|
12
|
-
|
|
13
7
|
afterEach(() => {
|
|
14
|
-
|
|
8
|
+
vi.restoreAllMocks()
|
|
15
9
|
});
|
|
16
10
|
|
|
17
11
|
it('should call passed callback with event type and data in case, window generated "message" event with data, presented as object with properties "eventType" (string) and "eventData" (unknown). Object is converted to string.', () => {
|
|
12
|
+
createWindow({ env: 'iframe' });
|
|
18
13
|
const callback = vi.fn();
|
|
19
14
|
onTelegramEvent(callback);
|
|
20
15
|
|
|
@@ -25,6 +20,7 @@ it('should call passed callback with event type and data in case, window generat
|
|
|
25
20
|
});
|
|
26
21
|
|
|
27
22
|
it('should not define event handlers twice in case, window object contains "TelegramGameProxy_receiveEvent" property.', () => {
|
|
23
|
+
createWindow();
|
|
28
24
|
(window as any).TelegramGameProxy_receiveEvent = true;
|
|
29
25
|
|
|
30
26
|
onTelegramEvent(vi.fn());
|
|
@@ -32,6 +28,7 @@ it('should not define event handlers twice in case, window object contains "Tele
|
|
|
32
28
|
});
|
|
33
29
|
|
|
34
30
|
it('should call passed callback with event type and data in case, external environment generated event.', () => {
|
|
31
|
+
createWindow();
|
|
35
32
|
const callback = vi.fn();
|
|
36
33
|
onTelegramEvent(callback);
|
|
37
34
|
|
|
@@ -42,6 +39,7 @@ it('should call passed callback with event type and data in case, external envir
|
|
|
42
39
|
});
|
|
43
40
|
|
|
44
41
|
it('should ignore a message event with unexpected data', () => {
|
|
42
|
+
createWindow();
|
|
45
43
|
const callback = vi.fn();
|
|
46
44
|
onTelegramEvent(callback);
|
|
47
45
|
|
|
@@ -1,24 +1,18 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Extracts event data from native application event.
|
|
5
|
-
*/
|
|
6
|
-
const eventDataJson = json<{ eventType: string; eventData?: unknown }>({
|
|
7
|
-
eventType: string(),
|
|
8
|
-
eventData: (value) => value,
|
|
9
|
-
});
|
|
1
|
+
import { parseMessage } from '~/bridge/parseMessage.js';
|
|
10
2
|
|
|
11
3
|
/**
|
|
12
4
|
* Emits event sent from Telegram native application like it was sent in
|
|
13
5
|
* default web environment between 2 iframes. It dispatches new MessageEvent
|
|
14
6
|
* and expects it to be handled via `window.addEventListener('message', ...)`
|
|
15
|
-
* as developer would do it to handle messages sent from parent iframe.
|
|
7
|
+
* as developer would do it to handle messages sent from the parent iframe.
|
|
16
8
|
* @param eventType - event name.
|
|
17
9
|
* @param eventData - event payload.
|
|
18
10
|
*/
|
|
19
11
|
function emitEvent(eventType: string, eventData: unknown): void {
|
|
20
12
|
window.dispatchEvent(new MessageEvent('message', {
|
|
21
13
|
data: JSON.stringify({ eventType, eventData }),
|
|
14
|
+
// We specify window.parent to imitate the case, it sent us this event.
|
|
15
|
+
source: window.parent,
|
|
22
16
|
}));
|
|
23
17
|
}
|
|
24
18
|
|
|
@@ -73,8 +67,12 @@ export function onTelegramEvent(cb: (eventType: string, eventData: unknown) => v
|
|
|
73
67
|
|
|
74
68
|
// We expect Telegram to send us new event through "message" event.
|
|
75
69
|
window.addEventListener('message', (event) => {
|
|
70
|
+
if (event.source !== window.parent) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
|
|
76
74
|
try {
|
|
77
|
-
const { eventType, eventData } =
|
|
75
|
+
const { eventType, eventData } = parseMessage(event.data);
|
|
78
76
|
cb(eventType, eventData);
|
|
79
77
|
} catch {
|
|
80
78
|
// We ignore incorrect messages as they could be generated by any other code.
|
package/src/bridge/index.ts
CHANGED
|
@@ -2,5 +2,6 @@ export * from './env/index.js';
|
|
|
2
2
|
export * from './errors/index.js';
|
|
3
3
|
export * from './events/index.js';
|
|
4
4
|
export * from './methods/index.js';
|
|
5
|
-
export * from './
|
|
5
|
+
export * from './invokeCustomMethod.js';
|
|
6
|
+
export * from './parseMessage.js';
|
|
6
7
|
export * from './request.js';
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { json, string } from '~/parsing/index.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Message format used in communication between client and Telegram applications.
|
|
5
|
+
*/
|
|
6
|
+
export interface MiniAppsMessage {
|
|
7
|
+
/**
|
|
8
|
+
* Event name.
|
|
9
|
+
*/
|
|
10
|
+
eventType: string;
|
|
11
|
+
/**
|
|
12
|
+
* Event parameters.
|
|
13
|
+
*/
|
|
14
|
+
eventData?: unknown;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const parser = json<MiniAppsMessage>({
|
|
18
|
+
eventType: string(),
|
|
19
|
+
eventData: (value) => value,
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Parses value as a message between client and Telegram applications.
|
|
24
|
+
* @param value - value to parse.
|
|
25
|
+
*/
|
|
26
|
+
export function parseMessage(value: unknown): MiniAppsMessage {
|
|
27
|
+
return parser.parse(value);
|
|
28
|
+
}
|
|
@@ -3,7 +3,7 @@ import { expect, it } from 'vitest';
|
|
|
3
3
|
import { mergeClassNames } from '../mergeClassNames';
|
|
4
4
|
|
|
5
5
|
it('should ignore non-object values', () => {
|
|
6
|
-
expect(mergeClassNames({}, null, undefined, false, true, {}));
|
|
6
|
+
expect(mergeClassNames({}, null, undefined, false, true, { tma: 'good' })).toStrictEqual({ tma: 'good' });
|
|
7
7
|
});
|
|
8
8
|
|
|
9
9
|
it('should merge objects keys by values applying classNames function', () => {
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isRecord } from '~/misc/index.js';
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
import { classNames } from './classNames.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Returns union keys removing those, which values are not strings.
|
|
7
7
|
*/
|
|
8
|
-
type
|
|
8
|
+
type UnionStringKeys<U> = U extends U
|
|
9
9
|
? {
|
|
10
|
-
[K in keyof U]
|
|
10
|
+
[K in keyof U]-?: U[K] extends string | undefined ? K : never;
|
|
11
11
|
}[keyof U]
|
|
12
12
|
: never;
|
|
13
13
|
|
|
@@ -16,32 +16,24 @@ type UnionFilteredKeys<U> = U extends U
|
|
|
16
16
|
*/
|
|
17
17
|
type UnionRequiredKeys<U> = U extends U
|
|
18
18
|
? {
|
|
19
|
-
[K in
|
|
20
|
-
}[
|
|
19
|
+
[K in UnionStringKeys<U>]: ({} extends Pick<U, K> ? never : K)
|
|
20
|
+
}[UnionStringKeys<U>]
|
|
21
21
|
: never;
|
|
22
22
|
|
|
23
23
|
/**
|
|
24
24
|
* Returns union optional keys.
|
|
25
25
|
*/
|
|
26
|
-
type UnionOptionalKeys<U> = Exclude<
|
|
26
|
+
type UnionOptionalKeys<U> = Exclude<UnionStringKeys<U>, UnionRequiredKeys<U>>;
|
|
27
27
|
|
|
28
|
-
type MergeClassNames<Tuple extends any[]> =
|
|
29
|
-
|
|
28
|
+
type MergeClassNames<Tuple extends any[]> =
|
|
29
|
+
// Removes all types from union which will be ignored by the mergeClassNames function.
|
|
30
|
+
Exclude<Tuple[number], number | string | null | undefined | any[] | boolean> extends infer Union
|
|
30
31
|
? {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
: never
|
|
36
|
-
: never;
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Returns true in case, passed value is Record.
|
|
40
|
-
* @param value
|
|
41
|
-
*/
|
|
42
|
-
function isObject(value: unknown): value is Record<string, unknown> {
|
|
43
|
-
return typeof value === 'object' && value !== null && !Array.isArray(null);
|
|
44
|
-
}
|
|
32
|
+
[K in UnionRequiredKeys<Union>]: string;
|
|
33
|
+
} & {
|
|
34
|
+
[K in UnionOptionalKeys<Union>]?: string;
|
|
35
|
+
}
|
|
36
|
+
: never;
|
|
45
37
|
|
|
46
38
|
/**
|
|
47
39
|
* Merges 2 sets of parameters. Function expects passing an array of objects with values, which
|
|
@@ -51,7 +43,7 @@ function isObject(value: unknown): value is Record<string, unknown> {
|
|
|
51
43
|
*/
|
|
52
44
|
export function mergeClassNames<T extends any[]>(...partials: T): MergeClassNames<T> {
|
|
53
45
|
return partials.reduce<MergeClassNames<T>>((acc, partial) => {
|
|
54
|
-
if (!
|
|
46
|
+
if (!isRecord(partial)) {
|
|
55
47
|
return acc;
|
|
56
48
|
}
|
|
57
49
|
|
package/src/index.ts
CHANGED
|
File without changes
|
|
File without changes
|