@vkma.dev/bridge 0.0.0-stage → 0.2.1
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/LICENSE +21 -0
- package/README.md +88 -2
- package/dist/bridge.d.ts +38 -0
- package/dist/bridge.d.ts.map +1 -0
- package/dist/bridge.js +384 -0
- package/dist/bridge.js.map +1 -0
- package/dist/deprecated.d.ts +47 -0
- package/dist/deprecated.d.ts.map +1 -0
- package/dist/index.d.ts +34 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +64 -0
- package/dist/index.js.map +1 -0
- package/dist/launch-params.d.ts +26 -0
- package/dist/launch-params.d.ts.map +1 -0
- package/dist/launch-params.js +103 -0
- package/dist/launch-params.js.map +1 -0
- package/dist/middleware.d.ts +25 -0
- package/dist/middleware.d.ts.map +1 -0
- package/dist/middleware.js +31 -0
- package/dist/middleware.js.map +1 -0
- package/dist/package.js +6 -0
- package/dist/package.js.map +1 -0
- package/dist/tap.d.ts +35 -0
- package/dist/tap.d.ts.map +1 -0
- package/dist/tap.js +39 -0
- package/dist/tap.js.map +1 -0
- package/dist/types.d.ts +214 -0
- package/dist/types.d.ts.map +1 -0
- package/package.json +61 -3
- package/src/bridge.ts +599 -0
- package/src/deprecated.ts +61 -0
- package/src/index.ts +130 -0
- package/src/launch-params.ts +131 -0
- package/src/middleware.ts +70 -0
- package/src/tap.ts +77 -0
- package/src/types.ts +271 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { BridgeTap, BridgeTapEvent, createTap } from "./tap.js";
|
|
2
|
+
import { AnyIOMethodName, AnyMethodName, AnyReceiveMethodName, AnyReceiveOnlyMethodName, AnyRequestMethodName, AnyRequestOnlyMethodName, ErrorData, ErrorDataAPIError, ErrorDataAuthError, ErrorDataClientError, FailedResponseEventName, ReceiveData, RequestIdProp, RequestProps, ResultResponseEventName, SendOptions, VKBridge, VKBridgeErrorEvent, VKBridgeEvent, VKBridgeEventBase, VKBridgeIOEvent, VKBridgeReceiveOnlyEvent, VKBridgeResultEvent, VKBridgeSend, VKBridgeSubscribeHandler, VkmaBridge } from "./types.js";
|
|
3
|
+
import { RequestIdPolicy, VkmaBridgeOptions, createVKBridge } from "./bridge.js";
|
|
4
|
+
import { Middleware, MiddlewareAPI, applyMiddleware } from "./middleware.js";
|
|
5
|
+
import { LaunchParams, parseURLSearchParamsForGetLaunchParams } from "./launch-params.js";
|
|
6
|
+
import { IOMethodName, MethodName, ReceiveMethodName, ReceiveOnlyMethodName, RequestMethodName, RequestOnlyMethodName, WidgetType } from "./deprecated.js";
|
|
7
|
+
import { ReceiveDataMap, ReceiveEventMap, RequestPropsMap } from "@vkma.dev/bridge-schema";
|
|
8
|
+
export * from "@vkma.dev/bridge-schema";
|
|
9
|
+
//#region src/index.d.ts
|
|
10
|
+
export interface DevtoolsBridgeHandle {
|
|
11
|
+
tap: BridgeTap;
|
|
12
|
+
send: (name: string, params?: Record<string, unknown>) => Promise<unknown>;
|
|
13
|
+
}
|
|
14
|
+
declare const bridge: VkmaBridge;
|
|
15
|
+
/**
|
|
16
|
+
* Subscribe to outgoing `send` calls of the default instance.
|
|
17
|
+
*/
|
|
18
|
+
export declare function onSend(listener: (event: BridgeTapEvent & {
|
|
19
|
+
direction: "out";
|
|
20
|
+
}) => void): () => void;
|
|
21
|
+
/**
|
|
22
|
+
* Subscribe to everything incoming on the default instance: paired responses
|
|
23
|
+
* and unsolicited events.
|
|
24
|
+
*/
|
|
25
|
+
export declare function onEvent(listener: (event: BridgeTapEvent & {
|
|
26
|
+
direction: "in";
|
|
27
|
+
}) => void): () => void;
|
|
28
|
+
/** The shared tap of the default instance (buffered until first subscribe). */
|
|
29
|
+
export declare const bridgeTap: BridgeTap;
|
|
30
|
+
/** The `globalThis` key the devtools collector looks the handle up by. */
|
|
31
|
+
export declare const devtoolsBridgeGlobalKey = "__vkmaDevtoolsBridge";
|
|
32
|
+
//#endregion
|
|
33
|
+
export { type AnyIOMethodName, type AnyMethodName, type AnyReceiveMethodName, type AnyReceiveOnlyMethodName, type AnyRequestMethodName, type AnyRequestOnlyMethodName, type ErrorData, type ErrorDataAPIError, type ErrorDataAuthError, type ErrorDataClientError, type FailedResponseEventName, type IOMethodName, type LaunchParams, type MethodName, type Middleware, type MiddlewareAPI, type ReceiveData, type ReceiveDataMap, type ReceiveEventMap, type ReceiveMethodName, type ReceiveOnlyMethodName, type RequestIdPolicy, type RequestIdProp, type RequestMethodName, type RequestOnlyMethodName, type RequestProps, type RequestPropsMap, type ResultResponseEventName, type SendOptions, type VKBridge, type VKBridgeErrorEvent, type VKBridgeEvent, type VKBridgeEventBase, type VKBridgeIOEvent, type VKBridgeReceiveOnlyEvent, type VKBridgeResultEvent, type VKBridgeSend, type VKBridgeSubscribeHandler, type VkmaBridge, type VkmaBridgeOptions, type WidgetType, applyMiddleware, createTap, createVKBridge, bridge as default, parseURLSearchParamsForGetLaunchParams };
|
|
34
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/index.ts"],"mappings":";;;;;;;;;iBAyEiB;EAChB,KAAK;EACL,OAAO,cAAc,SAAS,4BAA4B;;cA2BrD,QAAQ;;;;wBAKE,OACf,WAAW,OAAO;EAAmB;;;;;;wBAStB,QACf,WAAW,OAAO;EAAmB;;;qBAMzB,WAAW;;qBAGX"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { version } from "./package.js";
|
|
2
|
+
import { createTap } from "./tap.js";
|
|
3
|
+
import { createVKBridge } from "./bridge.js";
|
|
4
|
+
import { applyMiddleware } from "./middleware.js";
|
|
5
|
+
import { parseURLSearchParamsForGetLaunchParams } from "./launch-params.js";
|
|
6
|
+
export * from "@vkma.dev/bridge-schema";
|
|
7
|
+
//#region src/index.ts
|
|
8
|
+
/**
|
|
9
|
+
* @vkma.dev/bridge — an independent VK Bridge for VK Mini Apps.
|
|
10
|
+
*
|
|
11
|
+
* The default export is a ready singleton; `createVKBridge` builds additional
|
|
12
|
+
* instances. Every instance carries an always-on tap (see `onSend`/`onEvent`
|
|
13
|
+
* and `tap`), which is what the VKMA devtools observe — no opt-in required.
|
|
14
|
+
*
|
|
15
|
+
* Merely importing this module publishes the page-wide devtools handle on
|
|
16
|
+
* `globalThis.__vkmaDevtoolsBridge` (`{ tap, send }`), so the devtools
|
|
17
|
+
* collector — loaded as a separate script, never sharing a module graph with
|
|
18
|
+
* the app — can observe and drive the app's own bridge instance.
|
|
19
|
+
*/
|
|
20
|
+
/**
|
|
21
|
+
* The devtools bridge handle shared by every copy of this module on the page,
|
|
22
|
+
* exposed on `globalThis` under a stable key so the devtools collector —
|
|
23
|
+
* loaded as a separate script, never sharing a module graph with the app —
|
|
24
|
+
* can observe and drive the app's own bridge instance:
|
|
25
|
+
*
|
|
26
|
+
* - `tap` — replay-buffered stream of sends, paired responses and events
|
|
27
|
+
* - `send` — execute a bridge send inside the app (devtools "execute")
|
|
28
|
+
*/
|
|
29
|
+
const GLOBAL_KEY = "__vkmaDevtoolsBridge";
|
|
30
|
+
const globalScope = globalThis;
|
|
31
|
+
function sharedTap() {
|
|
32
|
+
const existing = globalScope[GLOBAL_KEY];
|
|
33
|
+
if (existing) return existing.tap;
|
|
34
|
+
const tap = createTap();
|
|
35
|
+
globalScope[GLOBAL_KEY] = {
|
|
36
|
+
tap,
|
|
37
|
+
send: (name, params) => bridge.send(name, params)
|
|
38
|
+
};
|
|
39
|
+
return tap;
|
|
40
|
+
}
|
|
41
|
+
/** Options of the page-wide default instance: it shares the global tap. */
|
|
42
|
+
const defaultOptions = { tap: sharedTap() };
|
|
43
|
+
const bridge = createVKBridge(version, defaultOptions);
|
|
44
|
+
/**
|
|
45
|
+
* Subscribe to outgoing `send` calls of the default instance.
|
|
46
|
+
*/
|
|
47
|
+
function onSend(listener) {
|
|
48
|
+
return bridge.onSend(listener);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Subscribe to everything incoming on the default instance: paired responses
|
|
52
|
+
* and unsolicited events.
|
|
53
|
+
*/
|
|
54
|
+
function onEvent(listener) {
|
|
55
|
+
return bridge.onEvent(listener);
|
|
56
|
+
}
|
|
57
|
+
/** The shared tap of the default instance (buffered until first subscribe). */
|
|
58
|
+
const bridgeTap = bridge.tap;
|
|
59
|
+
/** The `globalThis` key the devtools collector looks the handle up by. */
|
|
60
|
+
const devtoolsBridgeGlobalKey = GLOBAL_KEY;
|
|
61
|
+
//#endregion
|
|
62
|
+
export { applyMiddleware, bridgeTap, createTap, createVKBridge, bridge as default, devtoolsBridgeGlobalKey, onEvent, onSend, parseURLSearchParamsForGetLaunchParams };
|
|
63
|
+
|
|
64
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":["packageJson.version"],"sources":["../src/index.ts"],"sourcesContent":["/**\n * @vkma.dev/bridge — an independent VK Bridge for VK Mini Apps.\n *\n * The default export is a ready singleton; `createVKBridge` builds additional\n * instances. Every instance carries an always-on tap (see `onSend`/`onEvent`\n * and `tap`), which is what the VKMA devtools observe — no opt-in required.\n *\n * Merely importing this module publishes the page-wide devtools handle on\n * `globalThis.__vkmaDevtoolsBridge` (`{ tap, send }`), so the devtools\n * collector — loaded as a separate script, never sharing a module graph with\n * the app — can observe and drive the app's own bridge instance.\n */\n\nimport packageJson from \"../package.json\" with { type: \"json\" };\nimport { createVKBridge, type VkmaBridgeOptions } from \"./bridge.ts\";\nimport { createTap, type BridgeTap, type BridgeTapEvent } from \"./tap.ts\";\n\nexport { createVKBridge, type RequestIdPolicy, type VkmaBridgeOptions } from \"./bridge.ts\";\nimport type { VkmaBridge } from \"./types.ts\";\nexport { applyMiddleware, type Middleware, type MiddlewareAPI } from \"./middleware.ts\";\nexport { parseURLSearchParamsForGetLaunchParams, type LaunchParams } from \"./launch-params.ts\";\nexport { createTap } from \"./tap.ts\";\nexport type {\n\tSendOptions,\n\tVKBridge,\n\tVKBridgeErrorEvent,\n\tVKBridgeEvent,\n\tVKBridgeEventBase,\n\tVKBridgeIOEvent,\n\tVKBridgeReceiveOnlyEvent,\n\tVKBridgeResultEvent,\n\tVKBridgeSend,\n\tVKBridgeSubscribeHandler,\n\tVkmaBridge,\n\tAnyIOMethodName,\n\tAnyMethodName,\n\tAnyReceiveMethodName,\n\tAnyReceiveOnlyMethodName,\n\tAnyRequestMethodName,\n\tAnyRequestOnlyMethodName,\n\tErrorData,\n\tErrorDataAPIError,\n\tErrorDataAuthError,\n\tErrorDataClientError,\n\tFailedResponseEventName,\n\tRequestIdProp,\n\tRequestProps,\n\tReceiveData,\n\tResultResponseEventName,\n} from \"./types.ts\";\nexport type {\n\tRequestMethodName,\n\tReceiveMethodName,\n\tRequestOnlyMethodName,\n\tReceiveOnlyMethodName,\n\tMethodName,\n\tIOMethodName,\n\tWidgetType,\n} from \"./deprecated.ts\";\nexport type { ReceiveDataMap, ReceiveEventMap, RequestPropsMap } from \"@vkma.dev/bridge-schema\";\nexport * from \"@vkma.dev/bridge-schema\";\n\n/**\n * The devtools bridge handle shared by every copy of this module on the page,\n * exposed on `globalThis` under a stable key so the devtools collector —\n * loaded as a separate script, never sharing a module graph with the app —\n * can observe and drive the app's own bridge instance:\n *\n * - `tap` — replay-buffered stream of sends, paired responses and events\n * - `send` — execute a bridge send inside the app (devtools \"execute\")\n */\nconst GLOBAL_KEY = \"__vkmaDevtoolsBridge\";\n\nexport interface DevtoolsBridgeHandle {\n\ttap: BridgeTap;\n\tsend: (name: string, params?: Record<string, unknown>) => Promise<unknown>;\n}\n\nconst globalScope = globalThis as typeof globalThis & {\n\t[GLOBAL_KEY]?: DevtoolsBridgeHandle;\n};\n\nfunction sharedTap(): BridgeTap {\n\tconst existing = globalScope[GLOBAL_KEY];\n\tif (existing) {\n\t\treturn existing.tap;\n\t}\n\tconst tap = createTap();\n\tglobalScope[GLOBAL_KEY] = {\n\t\ttap,\n\t\t// The collector executes arbitrary method names — the handle stays\n\t\t// stringly typed by design.\n\t\tsend: (name, params) => bridge.send(name as never, params as never),\n\t};\n\treturn tap;\n}\n\n/** Options of the page-wide default instance: it shares the global tap. */\nconst defaultOptions: VkmaBridgeOptions = {\n\ttap: sharedTap(),\n};\n\nconst bridge: VkmaBridge = createVKBridge(packageJson.version, defaultOptions);\n\n/**\n * Subscribe to outgoing `send` calls of the default instance.\n */\nexport function onSend(\n\tlistener: (event: BridgeTapEvent & { direction: \"out\" }) => void,\n): () => void {\n\treturn bridge.onSend(listener);\n}\n\n/**\n * Subscribe to everything incoming on the default instance: paired responses\n * and unsolicited events.\n */\nexport function onEvent(\n\tlistener: (event: BridgeTapEvent & { direction: \"in\" }) => void,\n): () => void {\n\treturn bridge.onEvent(listener);\n}\n\n/** The shared tap of the default instance (buffered until first subscribe). */\nexport const bridgeTap: BridgeTap = bridge.tap;\n\n/** The `globalThis` key the devtools collector looks the handle up by. */\nexport const devtoolsBridgeGlobalKey = GLOBAL_KEY;\n\nexport { bridge as default };\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuEA,MAAM,aAAa;AAOnB,MAAM,cAAc;AAIpB,SAAS,YAAuB;CAC/B,MAAM,WAAW,YAAY;CAC7B,IAAI,UACH,OAAO,SAAS;CAEjB,MAAM,MAAM,UAAU;CACtB,YAAY,cAAc;EACzB;EAGA,OAAO,MAAM,WAAW,OAAO,KAAK,MAAe,MAAe;CACnE;CACA,OAAO;AACR;;AAGA,MAAM,iBAAoC,EACzC,KAAK,UAAU,EAChB;AAEA,MAAM,SAAqB,eAAeA,SAAqB,cAAc;;;;AAK7E,SAAgB,OACf,UACa;CACb,OAAO,OAAO,OAAO,QAAQ;AAC9B;;;;;AAMA,SAAgB,QACf,UACa;CACb,OAAO,OAAO,QAAQ,QAAQ;AAC/B;;AAGA,MAAa,YAAuB,OAAO;;AAG3C,MAAa,0BAA0B"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { GetLaunchParamsResponse } from "@vkma.dev/bridge-schema";
|
|
2
|
+
//#region src/launch-params.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* Launch params as they appear in the URL — a superset of
|
|
5
|
+
* `GetLaunchParamsResponse` with the URL-only keys. The OK (Odnoklassniki)
|
|
6
|
+
* keys (`vk_client`, `vk_ok_*`, `vk_original_vk_id`, `vk_are_pushes_enabled`)
|
|
7
|
+
* come from the catalogue as optional — vk.com hosts never send them.
|
|
8
|
+
*/
|
|
9
|
+
export interface LaunchParams extends GetLaunchParamsResponse {
|
|
10
|
+
vk_chat_id: string;
|
|
11
|
+
vk_is_recommended: number;
|
|
12
|
+
vk_profile_id: number;
|
|
13
|
+
vk_has_profile_button: number;
|
|
14
|
+
vk_testing_group_id: number;
|
|
15
|
+
odr_enabled: undefined | 1;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Parses launch params out of a query string (à la
|
|
19
|
+
* `location.search.slice(1)`), field by field, keeping only the known keys
|
|
20
|
+
* with validated values.
|
|
21
|
+
*
|
|
22
|
+
* @see https://dev.vk.ru/mini-apps/development/launch-params
|
|
23
|
+
*/
|
|
24
|
+
export declare const parseURLSearchParamsForGetLaunchParams: (searchParams: string) => Partial<LaunchParams>;
|
|
25
|
+
//#endregion
|
|
26
|
+
//# sourceMappingURL=launch-params.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"launch-params.d.ts","names":[],"sources":["../src/launch-params.ts"],"mappings":";;;;;;;;iBAkCiB,qBAAqB;EACrC;EACA;EACA;EACA;EACA;EACA;;;;;;;;;qBAUY,yCAAsC,yBAEhD,QAAQ"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
//#region src/launch-params.ts
|
|
2
|
+
const LANGUAGES = /* @__PURE__ */ new Set([
|
|
3
|
+
"ru",
|
|
4
|
+
"uk",
|
|
5
|
+
"ua",
|
|
6
|
+
"en",
|
|
7
|
+
"be",
|
|
8
|
+
"kz",
|
|
9
|
+
"pt",
|
|
10
|
+
"es"
|
|
11
|
+
]);
|
|
12
|
+
const GROUP_ROLES = /* @__PURE__ */ new Set([
|
|
13
|
+
"admin",
|
|
14
|
+
"editor",
|
|
15
|
+
"member",
|
|
16
|
+
"moder",
|
|
17
|
+
"none"
|
|
18
|
+
]);
|
|
19
|
+
const PLATFORMS = /* @__PURE__ */ new Set([
|
|
20
|
+
"desktop_web",
|
|
21
|
+
"desktop_web_messenger",
|
|
22
|
+
"desktop_app_messenger",
|
|
23
|
+
"desktop_web_ok",
|
|
24
|
+
"mobile_web",
|
|
25
|
+
"mobile_web_ok",
|
|
26
|
+
"mobile_android",
|
|
27
|
+
"mobile_android_ok",
|
|
28
|
+
"mobile_android_messenger",
|
|
29
|
+
"mobile_iphone",
|
|
30
|
+
"mobile_iphone_ok",
|
|
31
|
+
"mobile_iphone_messenger",
|
|
32
|
+
"mobile_ipad"
|
|
33
|
+
]);
|
|
34
|
+
/**
|
|
35
|
+
* Parses launch params out of a query string (à la
|
|
36
|
+
* `location.search.slice(1)`), field by field, keeping only the known keys
|
|
37
|
+
* with validated values.
|
|
38
|
+
*
|
|
39
|
+
* @see https://dev.vk.ru/mini-apps/development/launch-params
|
|
40
|
+
*/
|
|
41
|
+
const parseURLSearchParamsForGetLaunchParams = (searchParams) => {
|
|
42
|
+
const launchParams = {};
|
|
43
|
+
try {
|
|
44
|
+
const parsedSearchParams = new URLSearchParams(searchParams);
|
|
45
|
+
const convertToggleStateFromStringToNumber = (value) => {
|
|
46
|
+
switch (value) {
|
|
47
|
+
case "0":
|
|
48
|
+
case "false": return 0;
|
|
49
|
+
case "1":
|
|
50
|
+
case "true": return 1;
|
|
51
|
+
default: return;
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
parsedSearchParams.forEach((value, query) => {
|
|
55
|
+
switch (query) {
|
|
56
|
+
case "vk_ts":
|
|
57
|
+
case "vk_is_recommended":
|
|
58
|
+
case "vk_profile_id":
|
|
59
|
+
case "vk_has_profile_button":
|
|
60
|
+
case "vk_testing_group_id":
|
|
61
|
+
case "vk_user_id":
|
|
62
|
+
case "vk_app_id":
|
|
63
|
+
case "vk_group_id":
|
|
64
|
+
case "vk_ok_app_id":
|
|
65
|
+
case "vk_ok_user_id":
|
|
66
|
+
case "vk_original_vk_id":
|
|
67
|
+
launchParams[query] = Number(value);
|
|
68
|
+
break;
|
|
69
|
+
case "sign":
|
|
70
|
+
case "vk_chat_id":
|
|
71
|
+
case "vk_ref":
|
|
72
|
+
case "vk_ok_ref":
|
|
73
|
+
case "vk_client":
|
|
74
|
+
case "vk_access_token_settings":
|
|
75
|
+
launchParams[query] = value;
|
|
76
|
+
break;
|
|
77
|
+
case "odr_enabled":
|
|
78
|
+
launchParams.odr_enabled = value === "1" ? 1 : void 0;
|
|
79
|
+
break;
|
|
80
|
+
case "vk_is_app_user":
|
|
81
|
+
case "vk_are_notifications_enabled":
|
|
82
|
+
case "vk_are_pushes_enabled":
|
|
83
|
+
case "vk_is_favorite":
|
|
84
|
+
launchParams[query] = convertToggleStateFromStringToNumber(value);
|
|
85
|
+
break;
|
|
86
|
+
case "vk_language":
|
|
87
|
+
launchParams.vk_language = LANGUAGES.has(value) ? value : void 0;
|
|
88
|
+
break;
|
|
89
|
+
case "vk_viewer_group_role":
|
|
90
|
+
launchParams.vk_viewer_group_role = GROUP_ROLES.has(value) ? value : void 0;
|
|
91
|
+
break;
|
|
92
|
+
case "vk_platform": launchParams.vk_platform = PLATFORMS.has(value) ? value : void 0;
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
} catch (error) {
|
|
96
|
+
console.warn(error);
|
|
97
|
+
}
|
|
98
|
+
return launchParams;
|
|
99
|
+
};
|
|
100
|
+
//#endregion
|
|
101
|
+
export { parseURLSearchParamsForGetLaunchParams };
|
|
102
|
+
|
|
103
|
+
//# sourceMappingURL=launch-params.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"launch-params.js","names":[],"sources":["../src/launch-params.ts"],"sourcesContent":["/**\n * Launch params: parsing the `vk_*` query string every mini app is opened\n * with, into the typed shape of the catalogue's `GetLaunchParamsResponse`\n * plus the extra keys only present in the URL form.\n */\n\nimport type { GetLaunchParamsResponse } from \"@vkma.dev/bridge-schema\";\n\nconst LANGUAGES = new Set([\"ru\", \"uk\", \"ua\", \"en\", \"be\", \"kz\", \"pt\", \"es\"]);\n\nconst GROUP_ROLES = new Set([\"admin\", \"editor\", \"member\", \"moder\", \"none\"]);\n\nconst PLATFORMS = new Set([\n\t\"desktop_web\",\n\t\"desktop_web_messenger\",\n\t\"desktop_app_messenger\",\n\t\"desktop_web_ok\",\n\t\"mobile_web\",\n\t\"mobile_web_ok\",\n\t\"mobile_android\",\n\t\"mobile_android_ok\",\n\t\"mobile_android_messenger\",\n\t\"mobile_iphone\",\n\t\"mobile_iphone_ok\",\n\t\"mobile_iphone_messenger\",\n\t\"mobile_ipad\",\n]);\n\n/**\n * Launch params as they appear in the URL — a superset of\n * `GetLaunchParamsResponse` with the URL-only keys. The OK (Odnoklassniki)\n * keys (`vk_client`, `vk_ok_*`, `vk_original_vk_id`, `vk_are_pushes_enabled`)\n * come from the catalogue as optional — vk.com hosts never send them.\n */\nexport interface LaunchParams extends GetLaunchParamsResponse {\n\tvk_chat_id: string;\n\tvk_is_recommended: number;\n\tvk_profile_id: number;\n\tvk_has_profile_button: number;\n\tvk_testing_group_id: number;\n\todr_enabled: undefined | 1;\n}\n\n/**\n * Parses launch params out of a query string (à la\n * `location.search.slice(1)`), field by field, keeping only the known keys\n * with validated values.\n *\n * @see https://dev.vk.ru/mini-apps/development/launch-params\n */\nexport const parseURLSearchParamsForGetLaunchParams = (\n\tsearchParams: string,\n): Partial<LaunchParams> => {\n\tconst launchParams: Partial<LaunchParams> = {};\n\n\ttry {\n\t\tconst parsedSearchParams = new URLSearchParams(searchParams);\n\n\t\tconst convertToggleStateFromStringToNumber = (value: string): 0 | 1 | undefined => {\n\t\t\t// OK hosts serialize toggles both ways (\"true\"/\"false\" and \"0\"/\"1\")\n\t\t\tswitch (value) {\n\t\t\t\tcase \"0\":\n\t\t\t\tcase \"false\":\n\t\t\t\t\treturn 0;\n\t\t\t\tcase \"1\":\n\t\t\t\tcase \"true\":\n\t\t\t\t\treturn 1;\n\t\t\t\tdefault:\n\t\t\t\t\treturn undefined;\n\t\t\t}\n\t\t};\n\n\t\tparsedSearchParams.forEach((value, query) => {\n\t\t\tswitch (query) {\n\t\t\t\tcase \"vk_ts\":\n\t\t\t\tcase \"vk_is_recommended\":\n\t\t\t\tcase \"vk_profile_id\":\n\t\t\t\tcase \"vk_has_profile_button\":\n\t\t\t\tcase \"vk_testing_group_id\":\n\t\t\t\tcase \"vk_user_id\":\n\t\t\t\tcase \"vk_app_id\":\n\t\t\t\tcase \"vk_group_id\":\n\t\t\t\tcase \"vk_ok_app_id\":\n\t\t\t\tcase \"vk_ok_user_id\":\n\t\t\t\tcase \"vk_original_vk_id\":\n\t\t\t\t\tlaunchParams[query] = Number(value);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"sign\":\n\t\t\t\tcase \"vk_chat_id\":\n\t\t\t\tcase \"vk_ref\":\n\t\t\t\tcase \"vk_ok_ref\":\n\t\t\t\tcase \"vk_client\":\n\t\t\t\tcase \"vk_access_token_settings\":\n\t\t\t\t\tlaunchParams[query] = value;\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"odr_enabled\":\n\t\t\t\t\tlaunchParams.odr_enabled = value === \"1\" ? 1 : undefined;\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"vk_is_app_user\":\n\t\t\t\tcase \"vk_are_notifications_enabled\":\n\t\t\t\tcase \"vk_are_pushes_enabled\":\n\t\t\t\tcase \"vk_is_favorite\": {\n\t\t\t\t\tlaunchParams[query] = convertToggleStateFromStringToNumber(value);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase \"vk_language\": {\n\t\t\t\t\tlaunchParams.vk_language = LANGUAGES.has(value)\n\t\t\t\t\t\t? (value as Partial<LaunchParams>[\"vk_language\"])\n\t\t\t\t\t\t: undefined;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase \"vk_viewer_group_role\": {\n\t\t\t\t\tlaunchParams.vk_viewer_group_role = GROUP_ROLES.has(value)\n\t\t\t\t\t\t? (value as Partial<LaunchParams>[\"vk_viewer_group_role\"])\n\t\t\t\t\t\t: undefined;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase \"vk_platform\": {\n\t\t\t\t\tlaunchParams.vk_platform = PLATFORMS.has(value)\n\t\t\t\t\t\t? (value as Partial<LaunchParams>[\"vk_platform\"])\n\t\t\t\t\t\t: undefined;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t} catch (error) {\n\t\tconsole.warn(error);\n\t}\n\n\treturn launchParams;\n};\n"],"mappings":";AAQA,MAAM,4BAAY,IAAI,IAAI;CAAC;CAAM;CAAM;CAAM;CAAM;CAAM;CAAM;CAAM;AAAI,CAAC;AAE1E,MAAM,8BAAc,IAAI,IAAI;CAAC;CAAS;CAAU;CAAU;CAAS;AAAM,CAAC;AAE1E,MAAM,4BAAY,IAAI,IAAI;CACzB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACD,CAAC;;;;;;;;AAwBD,MAAa,0CACZ,iBAC2B;CAC3B,MAAM,eAAsC,CAAC;CAE7C,IAAI;EACH,MAAM,qBAAqB,IAAI,gBAAgB,YAAY;EAE3D,MAAM,wCAAwC,UAAqC;GAElF,QAAQ,OAAR;IACC,KAAK;IACL,KAAK,SACJ,OAAO;IACR,KAAK;IACL,KAAK,QACJ,OAAO;IACR,SACC;GACF;EACD;EAEA,mBAAmB,SAAS,OAAO,UAAU;GAC5C,QAAQ,OAAR;IACC,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;KACJ,aAAa,SAAS,OAAO,KAAK;KAClC;IACD,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;KACJ,aAAa,SAAS;KACtB;IACD,KAAK;KACJ,aAAa,cAAc,UAAU,MAAM,IAAI,KAAA;KAC/C;IACD,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;KACJ,aAAa,SAAS,qCAAqC,KAAK;KAChE;IAED,KAAK;KACJ,aAAa,cAAc,UAAU,IAAI,KAAK,IAC1C,QACD,KAAA;KACH;IAED,KAAK;KACJ,aAAa,uBAAuB,YAAY,IAAI,KAAK,IACrD,QACD,KAAA;KACH;IAED,KAAK,eACJ,aAAa,cAAc,UAAU,IAAI,KAAK,IAC1C,QACD,KAAA;GAGL;EACD,CAAC;CACF,SAAS,OAAO;EACf,QAAQ,KAAK,KAAK;CACnB;CAEA,OAAO;AACR"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { VKBridge, VKBridgeSend, VKBridgeSubscribeHandler } from "./types.js";
|
|
2
|
+
//#region src/middleware.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* API that can use middleware.
|
|
5
|
+
*/
|
|
6
|
+
export interface MiddlewareAPI<S extends VKBridgeSend = VKBridgeSend, L extends VKBridgeSubscribeHandler = VKBridgeSubscribeHandler> {
|
|
7
|
+
send: S;
|
|
8
|
+
subscribe(listener: L): void;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* A middleware is a higher-order function that composes a dispatch function
|
|
12
|
+
* to return a new `send` function.
|
|
13
|
+
*/
|
|
14
|
+
export type Middleware<S extends VKBridgeSend = VKBridgeSend> = (api: MiddlewareAPI<S>) => (next: S) => S;
|
|
15
|
+
/**
|
|
16
|
+
* Creates the VK Bridge enhancer that applies middleware to the `send`
|
|
17
|
+
* method. This is handy for a variety of tasks such as logging every sent
|
|
18
|
+
* event.
|
|
19
|
+
*
|
|
20
|
+
* @param middlewares The middleware chain to be applied.
|
|
21
|
+
* @returns The VK Bridge enhancer applying the middleware.
|
|
22
|
+
*/
|
|
23
|
+
export declare function applyMiddleware(...middlewares: Array<Middleware | undefined | null>): (bridge: VKBridge) => VKBridge;
|
|
24
|
+
//#endregion
|
|
25
|
+
//# sourceMappingURL=middleware.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middleware.d.ts","names":[],"sources":["../src/middleware.ts"],"mappings":";;;;;iBAUiB,cAChB,UAAU,eAAe,cACzB,UAAU,2BAA2B;EAErC,MAAM;EACN,UAAU,UAAU;;;;;;YAOT,WAAW,UAAU,eAAe,iBAC/C,KAAK,cAAc,QACd,MAAM,MAAM;;;;;;;;;wBAUF,mBACZ,aAAa,MAAM,kCACnB,QAAQ,aAAa"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
//#region src/middleware.ts
|
|
2
|
+
/**
|
|
3
|
+
* Creates the VK Bridge enhancer that applies middleware to the `send`
|
|
4
|
+
* method. This is handy for a variety of tasks such as logging every sent
|
|
5
|
+
* event.
|
|
6
|
+
*
|
|
7
|
+
* @param middlewares The middleware chain to be applied.
|
|
8
|
+
* @returns The VK Bridge enhancer applying the middleware.
|
|
9
|
+
*/
|
|
10
|
+
function applyMiddleware(...middlewares) {
|
|
11
|
+
if (middlewares.includes(void 0) || middlewares.includes(null)) return applyMiddleware(...middlewares.filter((item) => typeof item === "function"));
|
|
12
|
+
return (bridge) => {
|
|
13
|
+
if (middlewares.length === 0) return bridge;
|
|
14
|
+
let send = () => {
|
|
15
|
+
throw new Error("Sending events while constructing your middleware is not allowed. Other middleware would not be applied to this send.");
|
|
16
|
+
};
|
|
17
|
+
const middlewareAPI = {
|
|
18
|
+
subscribe: bridge.subscribe,
|
|
19
|
+
send: ((...args) => bridge.send(...args))
|
|
20
|
+
};
|
|
21
|
+
send = middlewares.filter((item) => typeof item === "function").map((middleware) => middleware(middlewareAPI)).reduce((a, b) => (next) => a(b(next)))(bridge.send);
|
|
22
|
+
return {
|
|
23
|
+
...bridge,
|
|
24
|
+
send
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
//#endregion
|
|
29
|
+
export { applyMiddleware };
|
|
30
|
+
|
|
31
|
+
//# sourceMappingURL=middleware.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middleware.js","names":[],"sources":["../src/middleware.ts"],"sourcesContent":["/**\n * Redux-style middleware over `send`: compose logging, metrics or caching\n * around the dispatch without touching the transport.\n */\n\nimport type { VKBridge, VKBridgeSend, VKBridgeSubscribeHandler } from \"./types.ts\";\n\n/**\n * API that can use middleware.\n */\nexport interface MiddlewareAPI<\n\tS extends VKBridgeSend = VKBridgeSend,\n\tL extends VKBridgeSubscribeHandler = VKBridgeSubscribeHandler,\n> {\n\tsend: S;\n\tsubscribe(listener: L): void;\n}\n\n/**\n * A middleware is a higher-order function that composes a dispatch function\n * to return a new `send` function.\n */\nexport type Middleware<S extends VKBridgeSend = VKBridgeSend> = (\n\tapi: MiddlewareAPI<S>,\n) => (next: S) => S;\n\n/**\n * Creates the VK Bridge enhancer that applies middleware to the `send`\n * method. This is handy for a variety of tasks such as logging every sent\n * event.\n *\n * @param middlewares The middleware chain to be applied.\n * @returns The VK Bridge enhancer applying the middleware.\n */\nexport function applyMiddleware(\n\t...middlewares: Array<Middleware | undefined | null>\n): (bridge: VKBridge) => VKBridge {\n\tif (middlewares.includes(undefined) || middlewares.includes(null)) {\n\t\treturn applyMiddleware(\n\t\t\t...middlewares.filter((item): item is Middleware => typeof item === \"function\"),\n\t\t);\n\t}\n\n\treturn bridge => {\n\t\tif (middlewares.length === 0) {\n\t\t\treturn bridge;\n\t\t}\n\n\t\tlet send: VKBridgeSend = () => {\n\t\t\tthrow new Error(\n\t\t\t\t\"Sending events while constructing your middleware is not allowed. \" +\n\t\t\t\t\t\"Other middleware would not be applied to this send.\",\n\t\t\t);\n\t\t};\n\n\t\tconst middlewareAPI: MiddlewareAPI = {\n\t\t\tsubscribe: bridge.subscribe,\n\t\t\tsend: ((...args: Parameters<VKBridgeSend>) => bridge.send(...args)) as VKBridgeSend,\n\t\t};\n\n\t\tconst chain = middlewares\n\t\t\t.filter((item): item is Middleware => typeof item === \"function\")\n\t\t\t.map(middleware => middleware(middlewareAPI))\n\t\t\t.reduce((a, b) => next => a(b(next)));\n\n\t\tsend = chain(bridge.send);\n\n\t\treturn { ...bridge, send };\n\t};\n}\n"],"mappings":";;;;;;;;;AAkCA,SAAgB,gBACf,GAAG,aAC8B;CACjC,IAAI,YAAY,SAAS,KAAA,CAAS,KAAK,YAAY,SAAS,IAAI,GAC/D,OAAO,gBACN,GAAG,YAAY,QAAQ,SAA6B,OAAO,SAAS,UAAU,CAC/E;CAGD,QAAO,WAAU;EAChB,IAAI,YAAY,WAAW,GAC1B,OAAO;EAGR,IAAI,aAA2B;GAC9B,MAAM,IAAI,MACT,uHAED;EACD;EAEA,MAAM,gBAA+B;GACpC,WAAW,OAAO;GAClB,QAAQ,GAAG,SAAmC,OAAO,KAAK,GAAG,IAAI;EAClE;EAOA,OALc,YACZ,QAAQ,SAA6B,OAAO,SAAS,UAAU,CAAC,CAChE,KAAI,eAAc,WAAW,aAAa,CAAC,CAAC,CAC5C,QAAQ,GAAG,OAAM,SAAQ,EAAE,EAAE,IAAI,CAAC,CAEzB,CAAC,CAAC,OAAO,IAAI;EAExB,OAAO;GAAE,GAAG;GAAQ;EAAK;CAC1B;AACD"}
|
package/dist/package.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"package.js","names":[],"sources":["../package.json"],"sourcesContent":[""],"mappings":""}
|
package/dist/tap.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
//#region src/tap.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Pure tap machinery: a tiny fan-out hub with a bounded replay buffer,
|
|
4
|
+
* detached from vk-bridge so it is unit-testable and tree-shakeable.
|
|
5
|
+
*
|
|
6
|
+
* The bridge wrapper always emits into the tap. When no devtools collector
|
|
7
|
+
* is attached (production), the buffer fills up once and every later emit
|
|
8
|
+
* costs a dropped-head push — effectively free.
|
|
9
|
+
*/
|
|
10
|
+
export interface BridgeTapEvent {
|
|
11
|
+
/** Monotonic within a page load; pairs a `response` with its `send`. */
|
|
12
|
+
id: number;
|
|
13
|
+
ts: number;
|
|
14
|
+
/** `out` — the app called send; `in` — VK sent something to the app. */
|
|
15
|
+
direction: "out" | "in";
|
|
16
|
+
/** `send` (out), `response` (in, paired), `event` (in, unsolicited). */
|
|
17
|
+
kind: "send" | "response" | "event";
|
|
18
|
+
name: string;
|
|
19
|
+
payload?: unknown;
|
|
20
|
+
/** Response pairing: the id of the originating `send` event. */
|
|
21
|
+
reqId?: number;
|
|
22
|
+
/** Only for `response`: whether the promise resolved or rejected. */
|
|
23
|
+
ok?: boolean;
|
|
24
|
+
}
|
|
25
|
+
export interface BridgeTap {
|
|
26
|
+
emit(event: Omit<BridgeTapEvent, "id" | "ts"> & {
|
|
27
|
+
ts?: number;
|
|
28
|
+
}): number;
|
|
29
|
+
subscribe(listener: (event: BridgeTapEvent) => void): () => void;
|
|
30
|
+
/** Events buffered before the first subscriber attached, oldest first. */
|
|
31
|
+
drain(): BridgeTapEvent[];
|
|
32
|
+
}
|
|
33
|
+
export declare function createTap(limit?: number): BridgeTap;
|
|
34
|
+
//#endregion
|
|
35
|
+
//# sourceMappingURL=tap.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tap.d.ts","names":[],"sources":["../src/tap.ts"],"mappings":";;;;;;;;;iBASiB;;EAEhB;EACA;;EAEA;;EAEA;EACA;EACA;;EAEA;;EAEA;;iBAGgB;EAChB,KAAK,OAAO,KAAK;IAAiC;;EAClD,UAAU,WAAW,OAAO;;EAE5B,SAAS;;wBAKM,UAAU,iBAAuC"}
|
package/dist/tap.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
//#region src/tap.ts
|
|
2
|
+
const DEFAULT_BUFFER_LIMIT = 500;
|
|
3
|
+
function createTap(limit = DEFAULT_BUFFER_LIMIT) {
|
|
4
|
+
let nextId = 0;
|
|
5
|
+
let buffer = [];
|
|
6
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
7
|
+
return {
|
|
8
|
+
emit(partial) {
|
|
9
|
+
const event = {
|
|
10
|
+
...partial,
|
|
11
|
+
id: ++nextId,
|
|
12
|
+
ts: partial.ts ?? Date.now()
|
|
13
|
+
};
|
|
14
|
+
if (listeners.size === 0) {
|
|
15
|
+
if (buffer && buffer.length >= limit) buffer.shift();
|
|
16
|
+
buffer?.push(event);
|
|
17
|
+
return event.id;
|
|
18
|
+
}
|
|
19
|
+
for (const listener of listeners) listener(event);
|
|
20
|
+
return event.id;
|
|
21
|
+
},
|
|
22
|
+
subscribe(listener) {
|
|
23
|
+
listeners.add(listener);
|
|
24
|
+
const replay = buffer ?? [];
|
|
25
|
+
buffer = void 0;
|
|
26
|
+
for (const event of replay) listener(event);
|
|
27
|
+
return () => {
|
|
28
|
+
listeners.delete(listener);
|
|
29
|
+
};
|
|
30
|
+
},
|
|
31
|
+
drain() {
|
|
32
|
+
return buffer ? [...buffer] : [];
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
//#endregion
|
|
37
|
+
export { createTap };
|
|
38
|
+
|
|
39
|
+
//# sourceMappingURL=tap.js.map
|
package/dist/tap.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tap.js","names":[],"sources":["../src/tap.ts"],"sourcesContent":["/**\n * Pure tap machinery: a tiny fan-out hub with a bounded replay buffer,\n * detached from vk-bridge so it is unit-testable and tree-shakeable.\n *\n * The bridge wrapper always emits into the tap. When no devtools collector\n * is attached (production), the buffer fills up once and every later emit\n * costs a dropped-head push — effectively free.\n */\n\nexport interface BridgeTapEvent {\n\t/** Monotonic within a page load; pairs a `response` with its `send`. */\n\tid: number;\n\tts: number;\n\t/** `out` — the app called send; `in` — VK sent something to the app. */\n\tdirection: \"out\" | \"in\";\n\t/** `send` (out), `response` (in, paired), `event` (in, unsolicited). */\n\tkind: \"send\" | \"response\" | \"event\";\n\tname: string;\n\tpayload?: unknown;\n\t/** Response pairing: the id of the originating `send` event. */\n\treqId?: number;\n\t/** Only for `response`: whether the promise resolved or rejected. */\n\tok?: boolean;\n}\n\nexport interface BridgeTap {\n\temit(event: Omit<BridgeTapEvent, \"id\" | \"ts\"> & { ts?: number }): number;\n\tsubscribe(listener: (event: BridgeTapEvent) => void): () => void;\n\t/** Events buffered before the first subscriber attached, oldest first. */\n\tdrain(): BridgeTapEvent[];\n}\n\nconst DEFAULT_BUFFER_LIMIT = 500;\n\nexport function createTap(limit: number = DEFAULT_BUFFER_LIMIT): BridgeTap {\n\tlet nextId = 0;\n\tlet buffer: BridgeTapEvent[] | undefined = [];\n\tconst listeners = new Set<(event: BridgeTapEvent) => void>();\n\n\treturn {\n\t\temit(partial) {\n\t\t\tconst event: BridgeTapEvent = {\n\t\t\t\t...partial,\n\t\t\t\tid: ++nextId,\n\t\t\t\tts: partial.ts ?? Date.now(),\n\t\t\t};\n\t\t\tif (listeners.size === 0) {\n\t\t\t\t// No collector yet (production or devtools not loaded): keep a\n\t\t\t\t// bounded replay so a late-attaching collector still sees recent\n\t\t\t\t// history, then stop growing work at the cap.\n\t\t\t\tif (buffer && buffer.length >= limit) {\n\t\t\t\t\tbuffer.shift();\n\t\t\t\t}\n\t\t\t\tbuffer?.push(event);\n\t\t\t\treturn event.id;\n\t\t\t}\n\t\t\tfor (const listener of listeners) {\n\t\t\t\tlistener(event);\n\t\t\t}\n\t\t\treturn event.id;\n\t\t},\n\t\tsubscribe(listener) {\n\t\t\tlisteners.add(listener);\n\t\t\tconst replay = buffer ?? [];\n\t\t\tbuffer = undefined;\n\t\t\tfor (const event of replay) {\n\t\t\t\tlistener(event);\n\t\t\t}\n\t\t\treturn () => {\n\t\t\t\tlisteners.delete(listener);\n\t\t\t};\n\t\t},\n\t\tdrain() {\n\t\t\treturn buffer ? [...buffer] : [];\n\t\t},\n\t};\n}\n"],"mappings":";AAgCA,MAAM,uBAAuB;AAE7B,SAAgB,UAAU,QAAgB,sBAAiC;CAC1E,IAAI,SAAS;CACb,IAAI,SAAuC,CAAC;CAC5C,MAAM,4BAAY,IAAI,IAAqC;CAE3D,OAAO;EACN,KAAK,SAAS;GACb,MAAM,QAAwB;IAC7B,GAAG;IACH,IAAI,EAAE;IACN,IAAI,QAAQ,MAAM,KAAK,IAAI;GAC5B;GACA,IAAI,UAAU,SAAS,GAAG;IAIzB,IAAI,UAAU,OAAO,UAAU,OAC9B,OAAO,MAAM;IAEd,QAAQ,KAAK,KAAK;IAClB,OAAO,MAAM;GACd;GACA,KAAK,MAAM,YAAY,WACtB,SAAS,KAAK;GAEf,OAAO,MAAM;EACd;EACA,UAAU,UAAU;GACnB,UAAU,IAAI,QAAQ;GACtB,MAAM,SAAS,UAAU,CAAC;GAC1B,SAAS,KAAA;GACT,KAAK,MAAM,SAAS,QACnB,SAAS,KAAK;GAEf,aAAa;IACZ,UAAU,OAAO,QAAQ;GAC1B;EACD;EACA,QAAQ;GACP,OAAO,SAAS,CAAC,GAAG,MAAM,IAAI,CAAC;EAChC;CACD;AACD"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import { BridgeTap, BridgeTapEvent } from "./tap.js";
|
|
2
|
+
import { ReceiveDataMap, ReceiveEventMap, RequestPropsMap } from "@vkma.dev/bridge-schema";
|
|
3
|
+
//#region src/types.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Name of a method that can be sent.
|
|
6
|
+
*/
|
|
7
|
+
export type AnyRequestMethodName = keyof RequestPropsMap;
|
|
8
|
+
/**
|
|
9
|
+
* Name of a method that can be received.
|
|
10
|
+
*/
|
|
11
|
+
export type AnyReceiveMethodName = keyof ReceiveDataMap;
|
|
12
|
+
/**
|
|
13
|
+
* Name of a method that can be only sent.
|
|
14
|
+
*/
|
|
15
|
+
export type AnyRequestOnlyMethodName = Exclude<AnyRequestMethodName, AnyReceiveMethodName>;
|
|
16
|
+
/**
|
|
17
|
+
* Name of a method that can be only received.
|
|
18
|
+
*/
|
|
19
|
+
export type AnyReceiveOnlyMethodName = Exclude<AnyReceiveMethodName, AnyRequestMethodName>;
|
|
20
|
+
/**
|
|
21
|
+
* Type of any method name.
|
|
22
|
+
*/
|
|
23
|
+
export type AnyMethodName = AnyRequestMethodName | AnyReceiveMethodName;
|
|
24
|
+
/**
|
|
25
|
+
* The name of the method that can be both sent and received.
|
|
26
|
+
*/
|
|
27
|
+
export type AnyIOMethodName = AnyRequestMethodName & AnyReceiveMethodName;
|
|
28
|
+
/**
|
|
29
|
+
* Getter of request properties of a method.
|
|
30
|
+
*/
|
|
31
|
+
export type RequestProps<M extends AnyRequestMethodName = AnyRequestMethodName> = RequestPropsMap[M];
|
|
32
|
+
/**
|
|
33
|
+
* Getter of response data of a method.
|
|
34
|
+
*/
|
|
35
|
+
export type ReceiveData<M extends AnyReceiveMethodName> = ReceiveDataMap[M];
|
|
36
|
+
/**
|
|
37
|
+
* Property for matching a sent request with the received message.
|
|
38
|
+
*/
|
|
39
|
+
export type RequestIdProp = {
|
|
40
|
+
request_id?: number | string;
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Extra per-send controls on top of the classic two-argument call.
|
|
44
|
+
*/
|
|
45
|
+
export interface SendOptions {
|
|
46
|
+
/** Reject the promise if no response arrives within this many milliseconds. */
|
|
47
|
+
timeout?: number;
|
|
48
|
+
/** Reject the promise when the signal aborts. */
|
|
49
|
+
signal?: AbortSignal;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Type of send function for methods that have props.
|
|
53
|
+
*
|
|
54
|
+
* @param method The method (event) name to send.
|
|
55
|
+
* @param props Method properties.
|
|
56
|
+
* @param options Timeout / abort controls.
|
|
57
|
+
* @returns The Promise object with response data.
|
|
58
|
+
*/
|
|
59
|
+
export type VKBridgeSend = <K extends AnyRequestMethodName>(method: K, props?: RequestProps<K> & RequestIdProp, options?: SendOptions) => Promise<K extends AnyReceiveMethodName ? ReceiveData<K> : void>;
|
|
60
|
+
/**
|
|
61
|
+
* Name of the Result response event of a method (per the catalogue wiring).
|
|
62
|
+
*/
|
|
63
|
+
export type ResultResponseEventName<M extends AnyRequestMethodName> = M extends keyof ReceiveEventMap ? ReceiveEventMap[M]["result"] : never;
|
|
64
|
+
/**
|
|
65
|
+
* Name of the Failed response event of a method (per the catalogue wiring).
|
|
66
|
+
*/
|
|
67
|
+
export type FailedResponseEventName<M extends AnyRequestMethodName> = M extends keyof ReceiveEventMap ? ReceiveEventMap[M]["failed"] : never;
|
|
68
|
+
/**
|
|
69
|
+
* Client error data.
|
|
70
|
+
*/
|
|
71
|
+
export type ErrorDataClientError = {
|
|
72
|
+
error_code: number;
|
|
73
|
+
error_reason: string;
|
|
74
|
+
error_description?: string;
|
|
75
|
+
};
|
|
76
|
+
/**
|
|
77
|
+
* API error data.
|
|
78
|
+
*/
|
|
79
|
+
export type ErrorDataAPIError = {
|
|
80
|
+
error_code: number;
|
|
81
|
+
error_msg: string;
|
|
82
|
+
request_params: string[];
|
|
83
|
+
};
|
|
84
|
+
/**
|
|
85
|
+
* Auth error data.
|
|
86
|
+
*/
|
|
87
|
+
export type ErrorDataAuthError = {
|
|
88
|
+
error_code: number;
|
|
89
|
+
error_reason: string;
|
|
90
|
+
error_description?: string[];
|
|
91
|
+
};
|
|
92
|
+
/**
|
|
93
|
+
* Error data of a Failed response event.
|
|
94
|
+
*/
|
|
95
|
+
export type ErrorData = {
|
|
96
|
+
error_type: "client_error";
|
|
97
|
+
error_data: ErrorDataClientError;
|
|
98
|
+
request_id?: number | string;
|
|
99
|
+
} | {
|
|
100
|
+
error_type: "api_error";
|
|
101
|
+
error_data: ErrorDataAPIError;
|
|
102
|
+
request_id?: number | string;
|
|
103
|
+
} | {
|
|
104
|
+
error_type: "auth_error";
|
|
105
|
+
error_data: ErrorDataAuthError;
|
|
106
|
+
request_id?: number | string;
|
|
107
|
+
};
|
|
108
|
+
/**
|
|
109
|
+
* Generic event type for creating event types.
|
|
110
|
+
*/
|
|
111
|
+
export type VKBridgeEventBase<Type extends string, Data> = {
|
|
112
|
+
detail: {
|
|
113
|
+
type: Type;
|
|
114
|
+
data: Data;
|
|
115
|
+
};
|
|
116
|
+
};
|
|
117
|
+
/**
|
|
118
|
+
* Type of error event data.
|
|
119
|
+
*/
|
|
120
|
+
export type VKBridgeErrorEvent<M extends AnyReceiveMethodName> = VKBridgeEventBase<M extends AnyRequestMethodName ? FailedResponseEventName<M> : never, ErrorData>;
|
|
121
|
+
/**
|
|
122
|
+
* Type of event that is a response to a request.
|
|
123
|
+
*/
|
|
124
|
+
export type VKBridgeIOEvent<M extends AnyIOMethodName> = { [K in M]: VKBridgeEventBase<ResultResponseEventName<K>, ReceiveData<K> & RequestIdProp>; }[M];
|
|
125
|
+
/**
|
|
126
|
+
* Type of event that is not a response to a request.
|
|
127
|
+
*/
|
|
128
|
+
export type VKBridgeReceiveOnlyEvent<M extends AnyReceiveOnlyMethodName> = { [K in M]: VKBridgeEventBase<K, ReceiveData<K>>; }[M];
|
|
129
|
+
/**
|
|
130
|
+
* Type of result event data.
|
|
131
|
+
*/
|
|
132
|
+
export type VKBridgeResultEvent<M extends AnyReceiveMethodName> = M extends AnyReceiveOnlyMethodName ? VKBridgeReceiveOnlyEvent<M> : M extends AnyIOMethodName ? VKBridgeIOEvent<M> : never;
|
|
133
|
+
/**
|
|
134
|
+
* VK Bridge event.
|
|
135
|
+
*/
|
|
136
|
+
export type VKBridgeEvent<M extends AnyReceiveMethodName> = VKBridgeErrorEvent<M> | VKBridgeResultEvent<M>;
|
|
137
|
+
/**
|
|
138
|
+
* Type of function that can be subscribed to VK Bridge events.
|
|
139
|
+
*/
|
|
140
|
+
export type VKBridgeSubscribeHandler = (event: VKBridgeEvent<AnyReceiveMethodName>) => void;
|
|
141
|
+
/**
|
|
142
|
+
* VK Bridge interface — the classic drop-in surface.
|
|
143
|
+
*/
|
|
144
|
+
export interface VKBridge {
|
|
145
|
+
/**
|
|
146
|
+
* Sends an event to the runtime env and returns the Promise object with
|
|
147
|
+
* response data. In the case of Android/iOS application env is the
|
|
148
|
+
* application itself. In the case of the browser, the parent frame in
|
|
149
|
+
* which the event handlers is located.
|
|
150
|
+
*
|
|
151
|
+
* @param method The method (event) name to send.
|
|
152
|
+
* @param [props] Method properties.
|
|
153
|
+
* @param [options] Timeout / abort controls.
|
|
154
|
+
* @returns The Promise object with response data.
|
|
155
|
+
*/
|
|
156
|
+
send: VKBridgeSend;
|
|
157
|
+
/**
|
|
158
|
+
* @alias send
|
|
159
|
+
* @deprecated
|
|
160
|
+
*/
|
|
161
|
+
sendPromise: VKBridgeSend;
|
|
162
|
+
/**
|
|
163
|
+
* Adds an event listener. It will be called any time a data is received.
|
|
164
|
+
*
|
|
165
|
+
* @param listener A callback to be invoked on every event receive.
|
|
166
|
+
*/
|
|
167
|
+
subscribe: (listener: VKBridgeSubscribeHandler) => void;
|
|
168
|
+
/**
|
|
169
|
+
* Removes an event listener which has been subscribed for event listening.
|
|
170
|
+
*
|
|
171
|
+
* @param listener A callback to unsubscribe.
|
|
172
|
+
*/
|
|
173
|
+
unsubscribe: (listener: VKBridgeSubscribeHandler) => void;
|
|
174
|
+
/**
|
|
175
|
+
* Checks if a method is supported on runtime platform.
|
|
176
|
+
*
|
|
177
|
+
* @param method Method (event) name to check.
|
|
178
|
+
* @returns Result of checking.
|
|
179
|
+
* @deprecated This method is deprecated. Use supportsAsync instead.
|
|
180
|
+
*/
|
|
181
|
+
supports: <K extends AnyRequestMethodName>(method: K) => boolean;
|
|
182
|
+
/**
|
|
183
|
+
* Checks if a method is supported on runtime platform.
|
|
184
|
+
*
|
|
185
|
+
* @param method Method (event) name to check.
|
|
186
|
+
* @returns The Promise object with result of checking.
|
|
187
|
+
*/
|
|
188
|
+
supportsAsync: <K extends AnyRequestMethodName>(method: K) => Promise<boolean>;
|
|
189
|
+
/**
|
|
190
|
+
* Checks whether the runtime is a WebView.
|
|
191
|
+
*/
|
|
192
|
+
isWebView: () => boolean;
|
|
193
|
+
isIframe: () => boolean;
|
|
194
|
+
isEmbedded: () => boolean;
|
|
195
|
+
isStandalone: () => boolean;
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* The full instance surface: the classic VK Bridge plus the always-on tap
|
|
199
|
+
* and its subscription helpers.
|
|
200
|
+
*/
|
|
201
|
+
export interface VkmaBridge extends VKBridge {
|
|
202
|
+
/** The replay-buffered stream of sends, paired responses and events. */
|
|
203
|
+
tap: BridgeTap;
|
|
204
|
+
/** Subscribe to outgoing `send` calls. */
|
|
205
|
+
onSend: (listener: (event: BridgeTapEvent & {
|
|
206
|
+
direction: "out";
|
|
207
|
+
}) => void) => () => void;
|
|
208
|
+
/** Subscribe to everything incoming: paired responses and unsolicited events. */
|
|
209
|
+
onEvent: (listener: (event: BridgeTapEvent & {
|
|
210
|
+
direction: "in";
|
|
211
|
+
}) => void) => () => void;
|
|
212
|
+
}
|
|
213
|
+
//#endregion
|
|
214
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","names":[],"sources":["../src/types.ts"],"mappings":";;;;;;YAcY,6BAA6B;;;;YAK7B,6BAA6B;;;;YAK7B,2BAA2B,QAAQ,sBAAsB;;;;YAKzD,2BAA2B,QAAQ,sBAAsB;;;;YAKzD,gBAAgB,uBAAuB;;;;YAKvC,kBAAkB,uBAAuB;;;;YAKzC,aAAa,UAAU,uBAAuB,wBACzD,gBAAgB;;;;YAKL,YAAY,UAAU,wBAAwB,eAAe;;;;YAK7D;EAAkB;;;;;iBAKb;;EAEhB;;EAEA,SAAS;;;;;;;;;;YAWE,gBAAgB,UAAU,sBACrC,QAAQ,GACR,QAAQ,aAAa,KAAK,eAC1B,UAAU,gBACN,QAAQ,UAAU,uBAAuB,YAAY;;;;YAK9C,wBAAwB,UAAU,wBAC7C,gBAAgB,kBAAkB,gBAAgB;;;;YAKvC,wBAAwB,UAAU,wBAC7C,gBAAgB,kBAAkB,gBAAgB;;;;YAKvC;EACX;EACA;EACA;;;;;YAMW;EACX;EACA;EACA;;;;;YAMW;EACX;EACA;EACA;;;;;YAMW;EAET;EACA,YAAY;EACZ;;EAGA;EACA,YAAY;EACZ;;EAGA;EACA,YAAY;EACZ;;;;;YAMS,kBAAkB,qBAAqB;EAClD;IACC,MAAM;IACN,MAAM;;;;;;YAOI,mBAAmB,UAAU,wBAAwB,kBAChE,UAAU,uBAAuB,wBAAwB,YACzD;;;;YAMW,gBAAgB,UAAU,sBACpC,KAAK,IAAI,kBAAkB,wBAAwB,IAAI,YAAY,KAAK,kBACxE;;;;YAKU,yBAAyB,UAAU,+BAC7C,KAAK,IAAI,kBAAkB,GAAG,YAAY,OAC1C;;;;YAKU,oBAAoB,UAAU,wBAAwB,UAAU,2BACzE,yBAAyB,KACzB,UAAU,kBACT,gBAAgB;;;;YAMR,cAAc,UAAU,wBACjC,mBAAmB,KACnB,oBAAoB;;;;YAKX,4BAA4B,OAAO,cAAc;;;;iBAK5C;;;;;;;;;;;;EAYhB,MAAM;;;;;EAMN,aAAa;;;;;;EAOb,YAAY,UAAU;;;;;;EAOtB,cAAc,UAAU;;;;;;;;EASxB,WAAW,UAAU,sBAAsB,QAAQ;;;;;;;EAQnD,gBAAgB,UAAU,sBAAsB,QAAQ,MAAM;;;;EAK9D;EAEA;EAEA;EAEA;;;;;;iBAOgB,mBAAmB;;EAEnC,KAAK;;EAEL,SAAS,WAAW,OAAO;IAAmB;;;EAE9C,UAAU,WAAW,OAAO;IAAmB"}
|