@dynamic-labs/message-transport 2.0.0-alpha.26
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/CHANGELOG.md +2899 -0
- package/LICENSE +21 -0
- package/README.md +3 -0
- package/_virtual/_tslib.cjs +35 -0
- package/_virtual/_tslib.js +31 -0
- package/package.json +28 -0
- package/src/index.cjs +21 -0
- package/src/index.d.ts +4 -0
- package/src/index.js +7 -0
- package/src/messageTransport/decorators/applyDefaultMessageOrigin/applyDefaultMessageOrigin.cjs +11 -0
- package/src/messageTransport/decorators/applyDefaultMessageOrigin/applyDefaultMessageOrigin.d.ts +15 -0
- package/src/messageTransport/decorators/applyDefaultMessageOrigin/applyDefaultMessageOrigin.js +7 -0
- package/src/messageTransport/decorators/applyDefaultMessageOrigin/index.d.ts +1 -0
- package/src/messageTransport/decorators/index.d.ts +3 -0
- package/src/messageTransport/decorators/makeWaitForInitEvent/index.d.ts +1 -0
- package/src/messageTransport/decorators/makeWaitForInitEvent/makeWaitForInitEvent.cjs +34 -0
- package/src/messageTransport/decorators/makeWaitForInitEvent/makeWaitForInitEvent.d.ts +25 -0
- package/src/messageTransport/decorators/makeWaitForInitEvent/makeWaitForInitEvent.js +30 -0
- package/src/messageTransport/decorators/makeWaitForUnblock/index.d.ts +1 -0
- package/src/messageTransport/decorators/makeWaitForUnblock/makeWaitForUnblock.cjs +52 -0
- package/src/messageTransport/decorators/makeWaitForUnblock/makeWaitForUnblock.d.ts +23 -0
- package/src/messageTransport/decorators/makeWaitForUnblock/makeWaitForUnblock.js +48 -0
- package/src/messageTransport/index.d.ts +2 -0
- package/src/messageTransport/messageTransport.cjs +15 -0
- package/src/messageTransport/messageTransport.d.ts +44 -0
- package/src/messageTransport/messageTransport.js +11 -0
- package/src/messageTypes/SdkModuleMessages.cjs +8 -0
- package/src/messageTypes/SdkModuleMessages.d.ts +20 -0
- package/src/messageTypes/SdkModuleMessages.js +4 -0
- package/src/messageTypes/index.d.ts +1 -0
- package/src/requestChannel/index.d.ts +1 -0
- package/src/requestChannel/requestChannel.cjs +112 -0
- package/src/requestChannel/requestChannel.d.ts +55 -0
- package/src/requestChannel/requestChannel.js +106 -0
- package/src/utils/parseMessageTransportData/index.d.ts +1 -0
- package/src/utils/parseMessageTransportData/parseMessageTransportData.cjs +26 -0
- package/src/utils/parseMessageTransportData/parseMessageTransportData.d.ts +2 -0
- package/src/utils/parseMessageTransportData/parseMessageTransportData.js +22 -0
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var _tslib = require('../../_virtual/_tslib.cjs');
|
|
6
|
+
|
|
7
|
+
/** Given a request event name, returns the event name for its resolve */
|
|
8
|
+
const getResolveMessageType = (type) => `${type}__resolve`;
|
|
9
|
+
/** Given a request event name, returns the event name for its reject */
|
|
10
|
+
const getRejectMessageType = (type) => `${type}__reject`;
|
|
11
|
+
/**
|
|
12
|
+
* Allows handling and submitting requests to and from a webview.
|
|
13
|
+
* Requests are messages that (can) expect some response.
|
|
14
|
+
*
|
|
15
|
+
* Functions similarly to an event emitter, but adds a response feature:
|
|
16
|
+
* - Emitting an event type is the act of making a "request" of a specific type,
|
|
17
|
+
* and it returns a promise that will resolve to the request's response.
|
|
18
|
+
* - Listening to an event type is the act of "handling" requests of a specific type.
|
|
19
|
+
* This handler callback must return a promise if this request type expects responses.
|
|
20
|
+
*
|
|
21
|
+
* Think of it this way:
|
|
22
|
+
* Whenever I emit an event, I am submitting a request.
|
|
23
|
+
* Whoever listens to the event will handle my request.
|
|
24
|
+
* If the request type expects some kind of response, they will
|
|
25
|
+
* return a promise that resolves (or rejects) after my request is fulfilled.
|
|
26
|
+
*
|
|
27
|
+
* This is an abstraction built on top of the MessageTransport interface.
|
|
28
|
+
*/
|
|
29
|
+
const createRequestChannel = (messageTransport) => {
|
|
30
|
+
/** Used to generated unique ids */
|
|
31
|
+
let uniqueIdCounter = 0;
|
|
32
|
+
/** Id prefix unique to this channel */
|
|
33
|
+
const idPrefix = Math.random().toString();
|
|
34
|
+
/** Always returns a different string */
|
|
35
|
+
const getUniqueId = () => `${idPrefix}-${uniqueIdCounter++}`;
|
|
36
|
+
return {
|
|
37
|
+
emit: (requestName, ...params) => {
|
|
38
|
+
// Generate the unique id for this message exchange session
|
|
39
|
+
// Although we won't listen for a response, it must still be unique
|
|
40
|
+
// to avoid tangling with other requests.
|
|
41
|
+
const messageSessionId = getUniqueId();
|
|
42
|
+
messageTransport.emit({
|
|
43
|
+
args: params,
|
|
44
|
+
messageSessionId,
|
|
45
|
+
type: requestName,
|
|
46
|
+
});
|
|
47
|
+
},
|
|
48
|
+
handle: (requestType, handler) => {
|
|
49
|
+
const messageHandler = ({ args, messageSessionId, type: incomingType, }) => _tslib.__awaiter(void 0, void 0, void 0, function* () {
|
|
50
|
+
if (requestType !== incomingType)
|
|
51
|
+
return;
|
|
52
|
+
const result = handler(...args);
|
|
53
|
+
// If the handler doesn't return a promise,
|
|
54
|
+
// that means we don't need to respond.
|
|
55
|
+
if (!(result instanceof Promise))
|
|
56
|
+
return;
|
|
57
|
+
try {
|
|
58
|
+
const response = yield result;
|
|
59
|
+
messageTransport.emit({
|
|
60
|
+
args: [response],
|
|
61
|
+
messageSessionId,
|
|
62
|
+
type: getResolveMessageType(requestType),
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
messageTransport.emit({
|
|
67
|
+
args: [error],
|
|
68
|
+
messageSessionId,
|
|
69
|
+
type: getRejectMessageType(requestType),
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
messageTransport.on(messageHandler);
|
|
74
|
+
return () => {
|
|
75
|
+
messageTransport.off(messageHandler);
|
|
76
|
+
};
|
|
77
|
+
},
|
|
78
|
+
request: (requestName, ...params) => new Promise((resolve, reject) => {
|
|
79
|
+
const requestType = requestName;
|
|
80
|
+
// Generate the unique id for this message exchange session
|
|
81
|
+
const messageSessionId = getUniqueId();
|
|
82
|
+
const resolveMessageType = getResolveMessageType(requestType);
|
|
83
|
+
const rejectMessageType = getRejectMessageType(requestType);
|
|
84
|
+
// Before actually emitting the event, we start listening to the
|
|
85
|
+
// response events
|
|
86
|
+
const handleMessage = ({ args: [result], messageSessionId: incomingSessionId, type: incomingType, }) => {
|
|
87
|
+
if (incomingSessionId !== messageSessionId)
|
|
88
|
+
return;
|
|
89
|
+
if (incomingType === resolveMessageType) {
|
|
90
|
+
resolve(result);
|
|
91
|
+
cleanup();
|
|
92
|
+
}
|
|
93
|
+
if (incomingType === rejectMessageType) {
|
|
94
|
+
reject(result);
|
|
95
|
+
cleanup();
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
const cleanup = () => messageTransport.off(handleMessage);
|
|
99
|
+
messageTransport.on(handleMessage);
|
|
100
|
+
// Now we emit the event to set off the request
|
|
101
|
+
messageTransport.emit({
|
|
102
|
+
args: params,
|
|
103
|
+
messageSessionId,
|
|
104
|
+
type: requestType,
|
|
105
|
+
});
|
|
106
|
+
}),
|
|
107
|
+
};
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
exports.createRequestChannel = createRequestChannel;
|
|
111
|
+
exports.getRejectMessageType = getRejectMessageType;
|
|
112
|
+
exports.getResolveMessageType = getResolveMessageType;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { MessageTransportWithDefaultOrigin } from '../messageTransport/decorators/applyDefaultMessageOrigin/applyDefaultMessageOrigin';
|
|
2
|
+
/**
|
|
3
|
+
* An object that defines request types, and whether they expect a response
|
|
4
|
+
*/
|
|
5
|
+
export type RequestTypes = Record<string, (...params: any[]) => Promise<any> | void>;
|
|
6
|
+
/**
|
|
7
|
+
* Only the request types from T that return promises
|
|
8
|
+
* i.e. those that expect a response
|
|
9
|
+
*/
|
|
10
|
+
type TypesExpectingResponse<T extends RequestTypes> = {
|
|
11
|
+
[K in keyof T]: ReturnType<T[K]> extends Promise<any> ? K : never;
|
|
12
|
+
}[keyof T];
|
|
13
|
+
export type RequestChannel<T extends RequestTypes> = {
|
|
14
|
+
/**
|
|
15
|
+
* Listens to incoming requests of this type, and calls the handler when they arrive.
|
|
16
|
+
* If the type of this request expects some response, the handler must return a promise
|
|
17
|
+
* that resolves to this response.
|
|
18
|
+
* @returns an unsubscribe function.
|
|
19
|
+
*/
|
|
20
|
+
handle: <K extends keyof T>(requestType: K, handler: T[K]) => VoidFunction;
|
|
21
|
+
/**
|
|
22
|
+
* Triggers handlers for this request type, with the given params.
|
|
23
|
+
* Doesn't care whether this request will have a response or not, so returns void.
|
|
24
|
+
*/
|
|
25
|
+
emit: <K extends keyof T>(requestName: K, ...params: Parameters<T[K]>) => void;
|
|
26
|
+
/**
|
|
27
|
+
* Triggers handlers for this request type, with the given params.
|
|
28
|
+
* @returns a promise that resolves/rejects when a handler fulfills this request.
|
|
29
|
+
*/
|
|
30
|
+
request: <K extends TypesExpectingResponse<T>>(requestName: K, ...params: Parameters<T[K]>) => ReturnType<T[K]>;
|
|
31
|
+
};
|
|
32
|
+
/** Given a request event name, returns the event name for its resolve */
|
|
33
|
+
export declare const getResolveMessageType: (type: string) => string;
|
|
34
|
+
/** Given a request event name, returns the event name for its reject */
|
|
35
|
+
export declare const getRejectMessageType: (type: string) => string;
|
|
36
|
+
/**
|
|
37
|
+
* Allows handling and submitting requests to and from a webview.
|
|
38
|
+
* Requests are messages that (can) expect some response.
|
|
39
|
+
*
|
|
40
|
+
* Functions similarly to an event emitter, but adds a response feature:
|
|
41
|
+
* - Emitting an event type is the act of making a "request" of a specific type,
|
|
42
|
+
* and it returns a promise that will resolve to the request's response.
|
|
43
|
+
* - Listening to an event type is the act of "handling" requests of a specific type.
|
|
44
|
+
* This handler callback must return a promise if this request type expects responses.
|
|
45
|
+
*
|
|
46
|
+
* Think of it this way:
|
|
47
|
+
* Whenever I emit an event, I am submitting a request.
|
|
48
|
+
* Whoever listens to the event will handle my request.
|
|
49
|
+
* If the request type expects some kind of response, they will
|
|
50
|
+
* return a promise that resolves (or rejects) after my request is fulfilled.
|
|
51
|
+
*
|
|
52
|
+
* This is an abstraction built on top of the MessageTransport interface.
|
|
53
|
+
*/
|
|
54
|
+
export declare const createRequestChannel: <T extends RequestTypes = never>(messageTransport: MessageTransportWithDefaultOrigin) => RequestChannel<T>;
|
|
55
|
+
export {};
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { __awaiter } from '../../_virtual/_tslib.js';
|
|
2
|
+
|
|
3
|
+
/** Given a request event name, returns the event name for its resolve */
|
|
4
|
+
const getResolveMessageType = (type) => `${type}__resolve`;
|
|
5
|
+
/** Given a request event name, returns the event name for its reject */
|
|
6
|
+
const getRejectMessageType = (type) => `${type}__reject`;
|
|
7
|
+
/**
|
|
8
|
+
* Allows handling and submitting requests to and from a webview.
|
|
9
|
+
* Requests are messages that (can) expect some response.
|
|
10
|
+
*
|
|
11
|
+
* Functions similarly to an event emitter, but adds a response feature:
|
|
12
|
+
* - Emitting an event type is the act of making a "request" of a specific type,
|
|
13
|
+
* and it returns a promise that will resolve to the request's response.
|
|
14
|
+
* - Listening to an event type is the act of "handling" requests of a specific type.
|
|
15
|
+
* This handler callback must return a promise if this request type expects responses.
|
|
16
|
+
*
|
|
17
|
+
* Think of it this way:
|
|
18
|
+
* Whenever I emit an event, I am submitting a request.
|
|
19
|
+
* Whoever listens to the event will handle my request.
|
|
20
|
+
* If the request type expects some kind of response, they will
|
|
21
|
+
* return a promise that resolves (or rejects) after my request is fulfilled.
|
|
22
|
+
*
|
|
23
|
+
* This is an abstraction built on top of the MessageTransport interface.
|
|
24
|
+
*/
|
|
25
|
+
const createRequestChannel = (messageTransport) => {
|
|
26
|
+
/** Used to generated unique ids */
|
|
27
|
+
let uniqueIdCounter = 0;
|
|
28
|
+
/** Id prefix unique to this channel */
|
|
29
|
+
const idPrefix = Math.random().toString();
|
|
30
|
+
/** Always returns a different string */
|
|
31
|
+
const getUniqueId = () => `${idPrefix}-${uniqueIdCounter++}`;
|
|
32
|
+
return {
|
|
33
|
+
emit: (requestName, ...params) => {
|
|
34
|
+
// Generate the unique id for this message exchange session
|
|
35
|
+
// Although we won't listen for a response, it must still be unique
|
|
36
|
+
// to avoid tangling with other requests.
|
|
37
|
+
const messageSessionId = getUniqueId();
|
|
38
|
+
messageTransport.emit({
|
|
39
|
+
args: params,
|
|
40
|
+
messageSessionId,
|
|
41
|
+
type: requestName,
|
|
42
|
+
});
|
|
43
|
+
},
|
|
44
|
+
handle: (requestType, handler) => {
|
|
45
|
+
const messageHandler = ({ args, messageSessionId, type: incomingType, }) => __awaiter(void 0, void 0, void 0, function* () {
|
|
46
|
+
if (requestType !== incomingType)
|
|
47
|
+
return;
|
|
48
|
+
const result = handler(...args);
|
|
49
|
+
// If the handler doesn't return a promise,
|
|
50
|
+
// that means we don't need to respond.
|
|
51
|
+
if (!(result instanceof Promise))
|
|
52
|
+
return;
|
|
53
|
+
try {
|
|
54
|
+
const response = yield result;
|
|
55
|
+
messageTransport.emit({
|
|
56
|
+
args: [response],
|
|
57
|
+
messageSessionId,
|
|
58
|
+
type: getResolveMessageType(requestType),
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
messageTransport.emit({
|
|
63
|
+
args: [error],
|
|
64
|
+
messageSessionId,
|
|
65
|
+
type: getRejectMessageType(requestType),
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
messageTransport.on(messageHandler);
|
|
70
|
+
return () => {
|
|
71
|
+
messageTransport.off(messageHandler);
|
|
72
|
+
};
|
|
73
|
+
},
|
|
74
|
+
request: (requestName, ...params) => new Promise((resolve, reject) => {
|
|
75
|
+
const requestType = requestName;
|
|
76
|
+
// Generate the unique id for this message exchange session
|
|
77
|
+
const messageSessionId = getUniqueId();
|
|
78
|
+
const resolveMessageType = getResolveMessageType(requestType);
|
|
79
|
+
const rejectMessageType = getRejectMessageType(requestType);
|
|
80
|
+
// Before actually emitting the event, we start listening to the
|
|
81
|
+
// response events
|
|
82
|
+
const handleMessage = ({ args: [result], messageSessionId: incomingSessionId, type: incomingType, }) => {
|
|
83
|
+
if (incomingSessionId !== messageSessionId)
|
|
84
|
+
return;
|
|
85
|
+
if (incomingType === resolveMessageType) {
|
|
86
|
+
resolve(result);
|
|
87
|
+
cleanup();
|
|
88
|
+
}
|
|
89
|
+
if (incomingType === rejectMessageType) {
|
|
90
|
+
reject(result);
|
|
91
|
+
cleanup();
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
const cleanup = () => messageTransport.off(handleMessage);
|
|
95
|
+
messageTransport.on(handleMessage);
|
|
96
|
+
// Now we emit the event to set off the request
|
|
97
|
+
messageTransport.emit({
|
|
98
|
+
args: params,
|
|
99
|
+
messageSessionId,
|
|
100
|
+
type: requestType,
|
|
101
|
+
});
|
|
102
|
+
}),
|
|
103
|
+
};
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
export { createRequestChannel, getRejectMessageType, getResolveMessageType };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './parseMessageTransportData';
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
const parseMessageTransportData = (
|
|
6
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
7
|
+
parsedData) => {
|
|
8
|
+
if (!parsedData || typeof parsedData !== 'object') {
|
|
9
|
+
return undefined;
|
|
10
|
+
}
|
|
11
|
+
const message = {
|
|
12
|
+
args: parsedData.args,
|
|
13
|
+
messageSessionId: parsedData.messageSessionId,
|
|
14
|
+
origin: parsedData.origin,
|
|
15
|
+
type: parsedData.type,
|
|
16
|
+
};
|
|
17
|
+
if (!Array.isArray(message.args) ||
|
|
18
|
+
typeof message.messageSessionId !== 'string' ||
|
|
19
|
+
typeof message.origin !== 'string' ||
|
|
20
|
+
typeof message.type !== 'string') {
|
|
21
|
+
return undefined;
|
|
22
|
+
}
|
|
23
|
+
return message;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
exports.parseMessageTransportData = parseMessageTransportData;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
const parseMessageTransportData = (
|
|
2
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
3
|
+
parsedData) => {
|
|
4
|
+
if (!parsedData || typeof parsedData !== 'object') {
|
|
5
|
+
return undefined;
|
|
6
|
+
}
|
|
7
|
+
const message = {
|
|
8
|
+
args: parsedData.args,
|
|
9
|
+
messageSessionId: parsedData.messageSessionId,
|
|
10
|
+
origin: parsedData.origin,
|
|
11
|
+
type: parsedData.type,
|
|
12
|
+
};
|
|
13
|
+
if (!Array.isArray(message.args) ||
|
|
14
|
+
typeof message.messageSessionId !== 'string' ||
|
|
15
|
+
typeof message.origin !== 'string' ||
|
|
16
|
+
typeof message.type !== 'string') {
|
|
17
|
+
return undefined;
|
|
18
|
+
}
|
|
19
|
+
return message;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export { parseMessageTransportData };
|