@dynamic-labs/message-transport 4.0.0-alpha.0 → 4.0.0-alpha.10
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 +132 -0
- package/package.cjs +8 -0
- package/package.js +4 -0
- package/package.json +9 -11
- package/src/index.cjs +14 -1
- package/src/index.d.ts +3 -2
- package/src/index.js +9 -0
- package/src/messageTransport/decorators/makeWaitForInitEvent/makeWaitForInitEvent.d.ts +4 -9
- package/src/messageTransport/decorators/makeWaitForUnblock/makeWaitForUnblock.cjs +23 -15
- package/src/messageTransport/decorators/makeWaitForUnblock/makeWaitForUnblock.d.ts +16 -8
- package/src/messageTransport/decorators/makeWaitForUnblock/makeWaitForUnblock.js +23 -15
- package/src/messageTypes/AccountAbstractionMessages.d.ts +15 -0
- package/src/messageTypes/AuthModuleMessages.cjs +14 -0
- package/src/messageTypes/AuthModuleMessages.d.ts +12 -1
- package/src/messageTypes/AuthModuleMessages.js +10 -0
- package/src/messageTypes/EmbeddedWalletsModuleMessages.cjs +10 -0
- package/src/messageTypes/EmbeddedWalletsModuleMessages.d.ts +9 -1
- package/src/messageTypes/EmbeddedWalletsModuleMessages.js +6 -0
- package/src/messageTypes/ExternalAuthMessages.d.ts +3 -2
- package/src/messageTypes/OtpMessages.cjs +14 -0
- package/src/messageTypes/OtpMessages.d.ts +10 -0
- package/src/messageTypes/OtpMessages.js +9 -0
- package/src/messageTypes/ProjectSettingsMessages.d.ts +6 -0
- package/src/messageTypes/SecureStorageMessages.d.ts +5 -0
- package/src/messageTypes/UserInterfaceModuleMessages.cjs +12 -0
- package/src/messageTypes/UserInterfaceModuleMessages.d.ts +6 -0
- package/src/messageTypes/UserInterfaceModuleMessages.js +8 -0
- package/src/messageTypes/WalletsModuleMessages.cjs +12 -0
- package/src/messageTypes/WalletsModuleMessages.d.ts +29 -0
- package/src/messageTypes/WalletsModuleMessages.js +8 -0
- package/src/messageTypes/ZeroDevExtensionMessages.d.ts +10 -0
- package/src/messageTypes/index.d.ts +4 -0
- package/src/requestChannel/createRequestChannelMessageSender/createRequestChannelMessageSender.cjs +43 -0
- package/src/requestChannel/createRequestChannelMessageSender/createRequestChannelMessageSender.d.ts +18 -0
- package/src/requestChannel/createRequestChannelMessageSender/createRequestChannelMessageSender.js +39 -0
- package/src/requestChannel/createRequestChannelMessageSender/index.d.ts +1 -0
- package/src/requestChannel/index.d.ts +1 -0
- package/src/requestChannel/requestChannel.cjs +58 -31
- package/src/requestChannel/requestChannel.d.ts +3 -36
- package/src/requestChannel/requestChannel.js +55 -26
- package/src/requestChannel/types.d.ts +55 -0
- package/src/requestChannel/utils/index.d.ts +1 -0
- package/src/requestChannel/utils/utils.cjs +33 -0
- package/src/requestChannel/utils/utils.d.ts +16 -0
- package/src/requestChannel/utils/utils.js +25 -0
- package/src/store/createEventEmitterForMessages/createEventEmitterForMessages.cjs +4 -5
- package/src/store/createEventEmitterForMessages/createEventEmitterForMessages.d.ts +5 -8
- package/src/store/createEventEmitterForMessages/createEventEmitterForMessages.js +4 -5
- package/src/store/types.d.ts +3 -11
- package/src/types.d.ts +5 -0
- package/src/utils/logger.cjs +10 -0
- package/src/utils/logger.d.ts +2 -0
- package/src/utils/logger.js +6 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
5
|
+
|
|
6
|
+
const userInterfaceEventNames = [
|
|
7
|
+
'authFlowCancelled',
|
|
8
|
+
'authFlowClosed',
|
|
9
|
+
'authFlowOpened',
|
|
10
|
+
];
|
|
11
|
+
|
|
12
|
+
exports.userInterfaceEventNames = userInterfaceEventNames;
|
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
export type UserInterfaceModuleMessages = {
|
|
2
2
|
openUserProfile: () => void;
|
|
3
|
+
hideUserProfile: () => void;
|
|
3
4
|
openAuthFlow: () => void;
|
|
5
|
+
hideAuthFlow: () => void;
|
|
4
6
|
/** Opens the secret key export for embedded wallets */
|
|
5
7
|
revealEmbeddedWalletKey: (params: {
|
|
6
8
|
type: 'recovery-phrase' | 'private-key';
|
|
7
9
|
}) => void;
|
|
10
|
+
authFlowCancelled: () => void;
|
|
11
|
+
authFlowClosed: () => void;
|
|
12
|
+
authFlowOpened: () => void;
|
|
8
13
|
};
|
|
14
|
+
export declare const userInterfaceEventNames: ("authFlowCancelled" | "authFlowClosed" | "authFlowOpened")[];
|
|
@@ -27,4 +27,33 @@ export type WalletsModuleMessages = {
|
|
|
27
27
|
setPrimary: (params: {
|
|
28
28
|
walletId: string;
|
|
29
29
|
}) => Promise<void>;
|
|
30
|
+
onWalletEvent: (params: WalletEventArguments & {
|
|
31
|
+
walletId: string;
|
|
32
|
+
}) => void;
|
|
33
|
+
handleConnectedWallet: (wallet: Partial<BaseWallet>) => Promise<boolean>;
|
|
34
|
+
messageSigned: (params: {
|
|
35
|
+
messageToSign: string;
|
|
36
|
+
signedMessage: string;
|
|
37
|
+
}) => void;
|
|
38
|
+
walletAdded: (params: {
|
|
39
|
+
wallet: BaseWallet;
|
|
40
|
+
userWallets: BaseWallet[];
|
|
41
|
+
}) => void;
|
|
42
|
+
walletRemoved: (params: {
|
|
43
|
+
wallet: BaseWallet;
|
|
44
|
+
userWallets: BaseWallet[];
|
|
45
|
+
}) => void;
|
|
46
|
+
};
|
|
47
|
+
export type WalletEvents = {
|
|
48
|
+
chainChange: (props: {
|
|
49
|
+
chain: string;
|
|
50
|
+
}) => void;
|
|
30
51
|
};
|
|
52
|
+
type WalletEventArguments = {
|
|
53
|
+
[E in keyof WalletEvents]: {
|
|
54
|
+
event: E;
|
|
55
|
+
eventParams: Parameters<WalletEvents[E]>;
|
|
56
|
+
};
|
|
57
|
+
}[keyof WalletEvents];
|
|
58
|
+
export declare const userWalletsEventNames: ("messageSigned" | "walletAdded" | "walletRemoved")[];
|
|
59
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type KernelAccountSettings = {
|
|
2
|
+
entryPointAddress: string;
|
|
3
|
+
chainId: number;
|
|
4
|
+
ecdsaProviderType: string | null;
|
|
5
|
+
kernelVersion: string;
|
|
6
|
+
projectId: string;
|
|
7
|
+
};
|
|
8
|
+
export type ZeroDevExtensionMessages = {
|
|
9
|
+
getKernelAccountSettings: () => Promise<KernelAccountSettings>;
|
|
10
|
+
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export * from './AccountAbstractionMessages';
|
|
1
2
|
export * from './AuthModuleMessages';
|
|
2
3
|
export * from './ConsoleMessages';
|
|
3
4
|
export * from './EmbeddedWalletsModuleMessages';
|
|
@@ -8,9 +9,12 @@ export * from './NetworksModuleMessages';
|
|
|
8
9
|
export * from './OtpMessages';
|
|
9
10
|
export * from './PasskeyMessages';
|
|
10
11
|
export * from './PlatformServiceMessages';
|
|
12
|
+
export * from './ProjectSettingsMessages';
|
|
11
13
|
export * from './SdkModuleMessages';
|
|
14
|
+
export * from './SecureStorageMessages';
|
|
12
15
|
export * from './SocialAuthModuleMessages';
|
|
13
16
|
export * from './SolanaMessages';
|
|
14
17
|
export * from './UserInterfaceModuleMessages';
|
|
15
18
|
export * from './WalletsModuleMessages';
|
|
16
19
|
export * from './WebViewVisibilityMessages';
|
|
20
|
+
export * from './ZeroDevExtensionMessages';
|
package/src/requestChannel/createRequestChannelMessageSender/createRequestChannelMessageSender.cjs
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
5
|
+
|
|
6
|
+
var utils = require('../utils/utils.cjs');
|
|
7
|
+
|
|
8
|
+
const createRequestChannelMessageSender = ({ requestType, messageSessionId, timeoutMap, onReceiveAck, messageTransport, onTimeout, params, }) => {
|
|
9
|
+
const ackMessageType = utils.getAckMessageType(requestType);
|
|
10
|
+
const message = {
|
|
11
|
+
args: params,
|
|
12
|
+
messageSessionId,
|
|
13
|
+
type: requestType,
|
|
14
|
+
};
|
|
15
|
+
// We must listen for acks
|
|
16
|
+
const handleAckMessage = ({ messageSessionId: incomingSessionId, type: incomingType, }) => {
|
|
17
|
+
if (incomingSessionId !== messageSessionId ||
|
|
18
|
+
incomingType !== ackMessageType)
|
|
19
|
+
return;
|
|
20
|
+
clearTimeout(timeoutMap[messageSessionId]);
|
|
21
|
+
delete timeoutMap[messageSessionId];
|
|
22
|
+
onReceiveAck === null || onReceiveAck === void 0 ? void 0 : onReceiveAck();
|
|
23
|
+
};
|
|
24
|
+
const sendMessage = () => {
|
|
25
|
+
const startTimer = () => {
|
|
26
|
+
const timeoutTimer = setTimeout(onTimeout, utils.TIMEOUT_DURATION);
|
|
27
|
+
timeoutMap[messageSessionId] = timeoutTimer;
|
|
28
|
+
};
|
|
29
|
+
// If this message transport is currently blocked, we must only start
|
|
30
|
+
// the timeout once the message is actually emitted
|
|
31
|
+
if ('isBlocked' in messageTransport && messageTransport.isBlocked) {
|
|
32
|
+
messageTransport.emit(message, { onEmit: startTimer });
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
// Now we emit the event to set off the request
|
|
36
|
+
messageTransport.emit(message);
|
|
37
|
+
// We start the timer immediately since the message was not blocked
|
|
38
|
+
startTimer();
|
|
39
|
+
};
|
|
40
|
+
return { handleAckMessage, sendMessage };
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
exports.createRequestChannelMessageSender = createRequestChannelMessageSender;
|
package/src/requestChannel/createRequestChannelMessageSender/createRequestChannelMessageSender.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { MessageTransportData, WithBlock } from '../../messageTransport';
|
|
3
|
+
import { MessageTransportWithDefaultOrigin } from '../../messageTransport/decorators/applyDefaultMessageOrigin/applyDefaultMessageOrigin';
|
|
4
|
+
import { RequestTypes } from '../types';
|
|
5
|
+
type RequestChannelMessageSenderParams<T extends RequestTypes, K extends Extract<keyof T, string>> = {
|
|
6
|
+
requestType: K;
|
|
7
|
+
messageSessionId: string;
|
|
8
|
+
timeoutMap: Record<string, NodeJS.Timer>;
|
|
9
|
+
onReceiveAck?: VoidFunction;
|
|
10
|
+
onTimeout: VoidFunction;
|
|
11
|
+
messageTransport: MessageTransportWithDefaultOrigin | WithBlock<MessageTransportWithDefaultOrigin>;
|
|
12
|
+
params: Parameters<T[K]>;
|
|
13
|
+
};
|
|
14
|
+
export declare const createRequestChannelMessageSender: <T extends RequestTypes, K extends Extract<keyof T, string>>({ requestType, messageSessionId, timeoutMap, onReceiveAck, messageTransport, onTimeout, params, }: RequestChannelMessageSenderParams<T, K>) => {
|
|
15
|
+
handleAckMessage: ({ messageSessionId: incomingSessionId, type: incomingType, }: MessageTransportData) => void;
|
|
16
|
+
sendMessage: () => void;
|
|
17
|
+
};
|
|
18
|
+
export {};
|
package/src/requestChannel/createRequestChannelMessageSender/createRequestChannelMessageSender.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
import { getAckMessageType, TIMEOUT_DURATION } from '../utils/utils.js';
|
|
3
|
+
|
|
4
|
+
const createRequestChannelMessageSender = ({ requestType, messageSessionId, timeoutMap, onReceiveAck, messageTransport, onTimeout, params, }) => {
|
|
5
|
+
const ackMessageType = getAckMessageType(requestType);
|
|
6
|
+
const message = {
|
|
7
|
+
args: params,
|
|
8
|
+
messageSessionId,
|
|
9
|
+
type: requestType,
|
|
10
|
+
};
|
|
11
|
+
// We must listen for acks
|
|
12
|
+
const handleAckMessage = ({ messageSessionId: incomingSessionId, type: incomingType, }) => {
|
|
13
|
+
if (incomingSessionId !== messageSessionId ||
|
|
14
|
+
incomingType !== ackMessageType)
|
|
15
|
+
return;
|
|
16
|
+
clearTimeout(timeoutMap[messageSessionId]);
|
|
17
|
+
delete timeoutMap[messageSessionId];
|
|
18
|
+
onReceiveAck === null || onReceiveAck === void 0 ? void 0 : onReceiveAck();
|
|
19
|
+
};
|
|
20
|
+
const sendMessage = () => {
|
|
21
|
+
const startTimer = () => {
|
|
22
|
+
const timeoutTimer = setTimeout(onTimeout, TIMEOUT_DURATION);
|
|
23
|
+
timeoutMap[messageSessionId] = timeoutTimer;
|
|
24
|
+
};
|
|
25
|
+
// If this message transport is currently blocked, we must only start
|
|
26
|
+
// the timeout once the message is actually emitted
|
|
27
|
+
if ('isBlocked' in messageTransport && messageTransport.isBlocked) {
|
|
28
|
+
messageTransport.emit(message, { onEmit: startTimer });
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
// Now we emit the event to set off the request
|
|
32
|
+
messageTransport.emit(message);
|
|
33
|
+
// We start the timer immediately since the message was not blocked
|
|
34
|
+
startTimer();
|
|
35
|
+
};
|
|
36
|
+
return { handleAckMessage, sendMessage };
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export { createRequestChannelMessageSender };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './createRequestChannelMessageSender';
|
|
@@ -4,14 +4,12 @@
|
|
|
4
4
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
5
5
|
|
|
6
6
|
var _tslib = require('../../_virtual/_tslib.cjs');
|
|
7
|
+
var isSerializedError = require('../utils/isSerializedError/isSerializedError.cjs');
|
|
7
8
|
var parseErrorFromTransport = require('../utils/parseErrorFromTransport/parseErrorFromTransport.cjs');
|
|
8
9
|
var serializeErrorForTransport = require('../utils/serializeErrorForTransport/serializeErrorForTransport.cjs');
|
|
9
|
-
var
|
|
10
|
+
var createRequestChannelMessageSender = require('./createRequestChannelMessageSender/createRequestChannelMessageSender.cjs');
|
|
11
|
+
var utils = require('./utils/utils.cjs');
|
|
10
12
|
|
|
11
|
-
/** Given a request event name, returns the event name for its resolve */
|
|
12
|
-
const getResolveMessageType = (type) => `${type}__resolve`;
|
|
13
|
-
/** Given a request event name, returns the event name for its reject */
|
|
14
|
-
const getRejectMessageType = (type) => `${type}__reject`;
|
|
15
13
|
/**
|
|
16
14
|
* Allows handling and submitting requests to and from a webview.
|
|
17
15
|
* Requests are messages that (can) expect some response.
|
|
@@ -37,22 +35,43 @@ const createRequestChannel = (messageTransport) => {
|
|
|
37
35
|
const idPrefix = Math.random().toString();
|
|
38
36
|
/** Always returns a different string */
|
|
39
37
|
const getUniqueId = () => `${idPrefix}-${uniqueIdCounter++}`;
|
|
38
|
+
/** Maps a request's session ID to its time out timer */
|
|
39
|
+
const timeoutMap = {};
|
|
40
40
|
return {
|
|
41
|
-
emit: (
|
|
41
|
+
emit: (requestType, ...params) => new Promise((resolve, reject) => {
|
|
42
42
|
// Generate the unique id for this message exchange session
|
|
43
43
|
// Although we won't listen for a response, it must still be unique
|
|
44
44
|
// to avoid tangling with other requests.
|
|
45
45
|
const messageSessionId = getUniqueId();
|
|
46
|
-
|
|
47
|
-
args: params,
|
|
46
|
+
const { handleAckMessage, sendMessage } = createRequestChannelMessageSender.createRequestChannelMessageSender({
|
|
48
47
|
messageSessionId,
|
|
49
|
-
|
|
48
|
+
messageTransport,
|
|
49
|
+
onReceiveAck: () => {
|
|
50
|
+
cleanupMessageHandler();
|
|
51
|
+
resolve();
|
|
52
|
+
},
|
|
53
|
+
onTimeout: () => {
|
|
54
|
+
cleanupMessageHandler();
|
|
55
|
+
reject(utils.createNoHandlerError(requestType));
|
|
56
|
+
},
|
|
57
|
+
params,
|
|
58
|
+
requestType,
|
|
59
|
+
timeoutMap,
|
|
50
60
|
});
|
|
51
|
-
|
|
61
|
+
const cleanupMessageHandler = () => messageTransport.off(handleAckMessage);
|
|
62
|
+
messageTransport.on(handleAckMessage);
|
|
63
|
+
sendMessage();
|
|
64
|
+
}),
|
|
52
65
|
handle: (requestType, handler) => {
|
|
53
66
|
const messageHandler = (_a) => _tslib.__awaiter(void 0, [_a], void 0, function* ({ args, messageSessionId, type: incomingType, }) {
|
|
54
67
|
if (requestType !== incomingType)
|
|
55
68
|
return;
|
|
69
|
+
// Emit an Ack since the message will time out unless some handler acks it in time
|
|
70
|
+
messageTransport.emit({
|
|
71
|
+
args: [],
|
|
72
|
+
messageSessionId,
|
|
73
|
+
type: utils.getAckMessageType(requestType),
|
|
74
|
+
});
|
|
56
75
|
const result = handler(...args);
|
|
57
76
|
// If the handler doesn't return a promise,
|
|
58
77
|
// that means we don't need to respond.
|
|
@@ -63,14 +82,14 @@ const createRequestChannel = (messageTransport) => {
|
|
|
63
82
|
messageTransport.emit({
|
|
64
83
|
args: [response],
|
|
65
84
|
messageSessionId,
|
|
66
|
-
type: getResolveMessageType(requestType),
|
|
85
|
+
type: utils.getResolveMessageType(requestType),
|
|
67
86
|
});
|
|
68
87
|
}
|
|
69
88
|
catch (error) {
|
|
70
89
|
messageTransport.emit({
|
|
71
90
|
args: [serializeErrorForTransport.serializeErrorForTransport(error)],
|
|
72
91
|
messageSessionId,
|
|
73
|
-
type: getRejectMessageType(requestType),
|
|
92
|
+
type: utils.getRejectMessageType(requestType),
|
|
74
93
|
});
|
|
75
94
|
}
|
|
76
95
|
});
|
|
@@ -79,43 +98,51 @@ const createRequestChannel = (messageTransport) => {
|
|
|
79
98
|
messageTransport.off(messageHandler);
|
|
80
99
|
};
|
|
81
100
|
},
|
|
82
|
-
request: (
|
|
83
|
-
const requestType = requestName;
|
|
101
|
+
request: (requestType, ...params) => new Promise((resolve, reject) => {
|
|
84
102
|
// Generate the unique id for this message exchange session
|
|
103
|
+
// Although we won't listen for a response, it must still be unique
|
|
104
|
+
// to avoid tangling with other requests.
|
|
85
105
|
const messageSessionId = getUniqueId();
|
|
86
|
-
const resolveMessageType = getResolveMessageType(requestType);
|
|
87
|
-
const rejectMessageType = getRejectMessageType(requestType);
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
106
|
+
const resolveMessageType = utils.getResolveMessageType(requestType);
|
|
107
|
+
const rejectMessageType = utils.getRejectMessageType(requestType);
|
|
108
|
+
const { handleAckMessage, sendMessage } = createRequestChannelMessageSender.createRequestChannelMessageSender({
|
|
109
|
+
messageSessionId,
|
|
110
|
+
messageTransport,
|
|
111
|
+
onTimeout: () => {
|
|
112
|
+
cleanupMessageHandler();
|
|
113
|
+
reject(utils.createNoHandlerError(requestType));
|
|
114
|
+
},
|
|
115
|
+
params,
|
|
116
|
+
requestType,
|
|
117
|
+
timeoutMap,
|
|
118
|
+
});
|
|
119
|
+
// We also need to listen to resolve and reject messages, besides acks
|
|
120
|
+
const handleMessage = (message) => {
|
|
121
|
+
if (message.messageSessionId !== messageSessionId)
|
|
92
122
|
return;
|
|
123
|
+
const { args: [result], type: incomingType, } = message;
|
|
93
124
|
if (incomingType === resolveMessageType) {
|
|
125
|
+
cleanupMessageHandler();
|
|
94
126
|
resolve(result);
|
|
95
|
-
|
|
127
|
+
return;
|
|
96
128
|
}
|
|
97
129
|
if (incomingType === rejectMessageType) {
|
|
130
|
+
cleanupMessageHandler();
|
|
98
131
|
if (isSerializedError.isSerializedError(result)) {
|
|
99
132
|
reject(parseErrorFromTransport.parseErrorFromTransport(result));
|
|
100
133
|
}
|
|
101
134
|
else {
|
|
102
135
|
reject(result);
|
|
103
136
|
}
|
|
104
|
-
|
|
137
|
+
return;
|
|
105
138
|
}
|
|
139
|
+
handleAckMessage(message);
|
|
106
140
|
};
|
|
107
|
-
const
|
|
141
|
+
const cleanupMessageHandler = () => messageTransport.off(handleMessage);
|
|
108
142
|
messageTransport.on(handleMessage);
|
|
109
|
-
|
|
110
|
-
messageTransport.emit({
|
|
111
|
-
args: params,
|
|
112
|
-
messageSessionId,
|
|
113
|
-
type: requestType,
|
|
114
|
-
});
|
|
143
|
+
sendMessage();
|
|
115
144
|
}),
|
|
116
145
|
};
|
|
117
146
|
};
|
|
118
147
|
|
|
119
148
|
exports.createRequestChannel = createRequestChannel;
|
|
120
|
-
exports.getRejectMessageType = getRejectMessageType;
|
|
121
|
-
exports.getResolveMessageType = getResolveMessageType;
|
|
@@ -1,38 +1,6 @@
|
|
|
1
|
+
import { WithBlock } from '../messageTransport';
|
|
1
2
|
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;
|
|
3
|
+
import { RequestChannel, RequestTypes } from './types';
|
|
36
4
|
/**
|
|
37
5
|
* Allows handling and submitting requests to and from a webview.
|
|
38
6
|
* Requests are messages that (can) expect some response.
|
|
@@ -51,5 +19,4 @@ export declare const getRejectMessageType: (type: string) => string;
|
|
|
51
19
|
*
|
|
52
20
|
* This is an abstraction built on top of the MessageTransport interface.
|
|
53
21
|
*/
|
|
54
|
-
export declare const createRequestChannel: <T extends RequestTypes = never>(messageTransport: MessageTransportWithDefaultOrigin) => RequestChannel<T>;
|
|
55
|
-
export {};
|
|
22
|
+
export declare const createRequestChannel: <T extends RequestTypes = never>(messageTransport: MessageTransportWithDefaultOrigin | WithBlock<MessageTransportWithDefaultOrigin>) => RequestChannel<T>;
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
'use client'
|
|
2
2
|
import { __awaiter } from '../../_virtual/_tslib.js';
|
|
3
|
+
import { isSerializedError } from '../utils/isSerializedError/isSerializedError.js';
|
|
3
4
|
import { parseErrorFromTransport } from '../utils/parseErrorFromTransport/parseErrorFromTransport.js';
|
|
4
5
|
import { serializeErrorForTransport } from '../utils/serializeErrorForTransport/serializeErrorForTransport.js';
|
|
5
|
-
import {
|
|
6
|
+
import { createRequestChannelMessageSender } from './createRequestChannelMessageSender/createRequestChannelMessageSender.js';
|
|
7
|
+
import { createNoHandlerError, getAckMessageType, getResolveMessageType, getRejectMessageType } from './utils/utils.js';
|
|
6
8
|
|
|
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
9
|
/**
|
|
12
10
|
* Allows handling and submitting requests to and from a webview.
|
|
13
11
|
* Requests are messages that (can) expect some response.
|
|
@@ -33,22 +31,43 @@ const createRequestChannel = (messageTransport) => {
|
|
|
33
31
|
const idPrefix = Math.random().toString();
|
|
34
32
|
/** Always returns a different string */
|
|
35
33
|
const getUniqueId = () => `${idPrefix}-${uniqueIdCounter++}`;
|
|
34
|
+
/** Maps a request's session ID to its time out timer */
|
|
35
|
+
const timeoutMap = {};
|
|
36
36
|
return {
|
|
37
|
-
emit: (
|
|
37
|
+
emit: (requestType, ...params) => new Promise((resolve, reject) => {
|
|
38
38
|
// Generate the unique id for this message exchange session
|
|
39
39
|
// Although we won't listen for a response, it must still be unique
|
|
40
40
|
// to avoid tangling with other requests.
|
|
41
41
|
const messageSessionId = getUniqueId();
|
|
42
|
-
|
|
43
|
-
args: params,
|
|
42
|
+
const { handleAckMessage, sendMessage } = createRequestChannelMessageSender({
|
|
44
43
|
messageSessionId,
|
|
45
|
-
|
|
44
|
+
messageTransport,
|
|
45
|
+
onReceiveAck: () => {
|
|
46
|
+
cleanupMessageHandler();
|
|
47
|
+
resolve();
|
|
48
|
+
},
|
|
49
|
+
onTimeout: () => {
|
|
50
|
+
cleanupMessageHandler();
|
|
51
|
+
reject(createNoHandlerError(requestType));
|
|
52
|
+
},
|
|
53
|
+
params,
|
|
54
|
+
requestType,
|
|
55
|
+
timeoutMap,
|
|
46
56
|
});
|
|
47
|
-
|
|
57
|
+
const cleanupMessageHandler = () => messageTransport.off(handleAckMessage);
|
|
58
|
+
messageTransport.on(handleAckMessage);
|
|
59
|
+
sendMessage();
|
|
60
|
+
}),
|
|
48
61
|
handle: (requestType, handler) => {
|
|
49
62
|
const messageHandler = (_a) => __awaiter(void 0, [_a], void 0, function* ({ args, messageSessionId, type: incomingType, }) {
|
|
50
63
|
if (requestType !== incomingType)
|
|
51
64
|
return;
|
|
65
|
+
// Emit an Ack since the message will time out unless some handler acks it in time
|
|
66
|
+
messageTransport.emit({
|
|
67
|
+
args: [],
|
|
68
|
+
messageSessionId,
|
|
69
|
+
type: getAckMessageType(requestType),
|
|
70
|
+
});
|
|
52
71
|
const result = handler(...args);
|
|
53
72
|
// If the handler doesn't return a promise,
|
|
54
73
|
// that means we don't need to respond.
|
|
@@ -75,41 +94,51 @@ const createRequestChannel = (messageTransport) => {
|
|
|
75
94
|
messageTransport.off(messageHandler);
|
|
76
95
|
};
|
|
77
96
|
},
|
|
78
|
-
request: (
|
|
79
|
-
const requestType = requestName;
|
|
97
|
+
request: (requestType, ...params) => new Promise((resolve, reject) => {
|
|
80
98
|
// Generate the unique id for this message exchange session
|
|
99
|
+
// Although we won't listen for a response, it must still be unique
|
|
100
|
+
// to avoid tangling with other requests.
|
|
81
101
|
const messageSessionId = getUniqueId();
|
|
82
102
|
const resolveMessageType = getResolveMessageType(requestType);
|
|
83
103
|
const rejectMessageType = getRejectMessageType(requestType);
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
104
|
+
const { handleAckMessage, sendMessage } = createRequestChannelMessageSender({
|
|
105
|
+
messageSessionId,
|
|
106
|
+
messageTransport,
|
|
107
|
+
onTimeout: () => {
|
|
108
|
+
cleanupMessageHandler();
|
|
109
|
+
reject(createNoHandlerError(requestType));
|
|
110
|
+
},
|
|
111
|
+
params,
|
|
112
|
+
requestType,
|
|
113
|
+
timeoutMap,
|
|
114
|
+
});
|
|
115
|
+
// We also need to listen to resolve and reject messages, besides acks
|
|
116
|
+
const handleMessage = (message) => {
|
|
117
|
+
if (message.messageSessionId !== messageSessionId)
|
|
88
118
|
return;
|
|
119
|
+
const { args: [result], type: incomingType, } = message;
|
|
89
120
|
if (incomingType === resolveMessageType) {
|
|
121
|
+
cleanupMessageHandler();
|
|
90
122
|
resolve(result);
|
|
91
|
-
|
|
123
|
+
return;
|
|
92
124
|
}
|
|
93
125
|
if (incomingType === rejectMessageType) {
|
|
126
|
+
cleanupMessageHandler();
|
|
94
127
|
if (isSerializedError(result)) {
|
|
95
128
|
reject(parseErrorFromTransport(result));
|
|
96
129
|
}
|
|
97
130
|
else {
|
|
98
131
|
reject(result);
|
|
99
132
|
}
|
|
100
|
-
|
|
133
|
+
return;
|
|
101
134
|
}
|
|
135
|
+
handleAckMessage(message);
|
|
102
136
|
};
|
|
103
|
-
const
|
|
137
|
+
const cleanupMessageHandler = () => messageTransport.off(handleMessage);
|
|
104
138
|
messageTransport.on(handleMessage);
|
|
105
|
-
|
|
106
|
-
messageTransport.emit({
|
|
107
|
-
args: params,
|
|
108
|
-
messageSessionId,
|
|
109
|
-
type: requestType,
|
|
110
|
-
});
|
|
139
|
+
sendMessage();
|
|
111
140
|
}),
|
|
112
141
|
};
|
|
113
142
|
};
|
|
114
143
|
|
|
115
|
-
export { createRequestChannel
|
|
144
|
+
export { createRequestChannel };
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* An object that defines request types, and whether they expect a response
|
|
3
|
+
*/
|
|
4
|
+
export type RequestTypes = Record<string, (...params: any[]) => Promise<any> | void>;
|
|
5
|
+
/**
|
|
6
|
+
* Only the request types from T that return promises
|
|
7
|
+
* i.e. those that expect a response
|
|
8
|
+
*/
|
|
9
|
+
type TypesExpectingResponse<T extends RequestTypes> = Extract<{
|
|
10
|
+
[K in keyof T]: ReturnType<T[K]> extends Promise<any> ? K : never;
|
|
11
|
+
}[keyof T], string>;
|
|
12
|
+
export type RequestChannel<T extends RequestTypes> = {
|
|
13
|
+
/**
|
|
14
|
+
* Listens to incoming requests of this type, and calls the handler when they arrive.
|
|
15
|
+
* If the type of this request expects some response, the handler must return a promise
|
|
16
|
+
* that resolves to this response.
|
|
17
|
+
*
|
|
18
|
+
* @returns an unsubscribe function.
|
|
19
|
+
*/
|
|
20
|
+
handle: <K extends Extract<keyof T, string>>(requestType: K, handler: T[K]) => VoidFunction;
|
|
21
|
+
/**
|
|
22
|
+
* Triggers handlers for this request type, with the given params.
|
|
23
|
+
* Doesn't expect a response. Resolves as soon as the message is acknowledged by
|
|
24
|
+
* any handler.
|
|
25
|
+
*
|
|
26
|
+
* If no handlers emit an ack for this message, this will reject.
|
|
27
|
+
*
|
|
28
|
+
* Lifetime of an "emit" message:
|
|
29
|
+
* 1. "Emit" message is sent.
|
|
30
|
+
* 2. A handler receives the message.
|
|
31
|
+
* 3. The handler immediately emits an ack message for it, acknowledging it.
|
|
32
|
+
* 4. This method's promise resolves.
|
|
33
|
+
*/
|
|
34
|
+
emit: <K extends Extract<keyof T, string>>(requestName: K, ...params: Parameters<T[K]>) => Promise<void>;
|
|
35
|
+
/**
|
|
36
|
+
* Triggers handlers for this request type, with the given params.
|
|
37
|
+
* As opposed to emit, this expects a response message. A handler must still
|
|
38
|
+
* acknowledge this message, but the promise will only resolve when the handler
|
|
39
|
+
* emits back a response message. The promise resolves with whatever data was sent
|
|
40
|
+
* in the response.
|
|
41
|
+
*
|
|
42
|
+
* If no handlers emit an ack for this message, or if a handler responds
|
|
43
|
+
* with a failure, this will reject.
|
|
44
|
+
*
|
|
45
|
+
* Lifetime of a "request" message:
|
|
46
|
+
* 1. "Request" message is sent.
|
|
47
|
+
* 2. A handler receives the message.
|
|
48
|
+
* 3. The handler immediately emits an ack message for it, acknowledging it.
|
|
49
|
+
* 4. The handler performs the requested action.
|
|
50
|
+
* 5. The handler emits a response message.
|
|
51
|
+
* 6. This method's promise resolves with the response's data.
|
|
52
|
+
*/
|
|
53
|
+
request: <K extends TypesExpectingResponse<T>>(requestName: K, ...params: Parameters<T[K]>) => ReturnType<T[K]>;
|
|
54
|
+
};
|
|
55
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './utils';
|