@dynamic-labs/message-transport 4.0.0-alpha.6 → 4.0.0-alpha.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/package.cjs +1 -1
  3. package/package.js +1 -1
  4. package/package.json +5 -5
  5. package/src/index.cjs +11 -0
  6. package/src/index.d.ts +3 -2
  7. package/src/index.js +5 -0
  8. package/src/messageTransport/decorators/makeWaitForInitEvent/makeWaitForInitEvent.d.ts +4 -9
  9. package/src/messageTransport/decorators/makeWaitForUnblock/makeWaitForUnblock.cjs +23 -15
  10. package/src/messageTransport/decorators/makeWaitForUnblock/makeWaitForUnblock.d.ts +16 -8
  11. package/src/messageTransport/decorators/makeWaitForUnblock/makeWaitForUnblock.js +23 -15
  12. package/src/messageTypes/AccountAbstractionMessages.d.ts +15 -0
  13. package/src/messageTypes/AuthModuleMessages.cjs +14 -0
  14. package/src/messageTypes/AuthModuleMessages.d.ts +12 -1
  15. package/src/messageTypes/AuthModuleMessages.js +10 -0
  16. package/src/messageTypes/EmbeddedWalletsModuleMessages.cjs +10 -0
  17. package/src/messageTypes/EmbeddedWalletsModuleMessages.d.ts +5 -1
  18. package/src/messageTypes/EmbeddedWalletsModuleMessages.js +6 -0
  19. package/src/messageTypes/OtpMessages.cjs +14 -0
  20. package/src/messageTypes/OtpMessages.d.ts +10 -0
  21. package/src/messageTypes/OtpMessages.js +9 -0
  22. package/src/messageTypes/ProjectSettingsMessages.d.ts +6 -0
  23. package/src/messageTypes/UserInterfaceModuleMessages.cjs +12 -0
  24. package/src/messageTypes/UserInterfaceModuleMessages.d.ts +4 -0
  25. package/src/messageTypes/UserInterfaceModuleMessages.js +8 -0
  26. package/src/messageTypes/WalletsModuleMessages.cjs +12 -0
  27. package/src/messageTypes/WalletsModuleMessages.d.ts +29 -0
  28. package/src/messageTypes/WalletsModuleMessages.js +8 -0
  29. package/src/messageTypes/ZeroDevExtensionMessages.d.ts +10 -0
  30. package/src/messageTypes/index.d.ts +3 -0
  31. package/src/requestChannel/createRequestChannelMessageSender/createRequestChannelMessageSender.cjs +43 -0
  32. package/src/requestChannel/createRequestChannelMessageSender/createRequestChannelMessageSender.d.ts +18 -0
  33. package/src/requestChannel/createRequestChannelMessageSender/createRequestChannelMessageSender.js +39 -0
  34. package/src/requestChannel/createRequestChannelMessageSender/index.d.ts +1 -0
  35. package/src/requestChannel/index.d.ts +1 -0
  36. package/src/requestChannel/requestChannel.cjs +46 -76
  37. package/src/requestChannel/requestChannel.d.ts +3 -69
  38. package/src/requestChannel/requestChannel.js +42 -68
  39. package/src/requestChannel/types.d.ts +55 -0
  40. package/src/requestChannel/utils/index.d.ts +1 -0
  41. package/src/requestChannel/utils/utils.cjs +33 -0
  42. package/src/requestChannel/utils/utils.d.ts +16 -0
  43. package/src/requestChannel/utils/utils.js +25 -0
  44. package/src/store/createEventEmitterForMessages/createEventEmitterForMessages.cjs +4 -5
  45. package/src/store/createEventEmitterForMessages/createEventEmitterForMessages.d.ts +5 -8
  46. package/src/store/createEventEmitterForMessages/createEventEmitterForMessages.js +4 -5
  47. package/src/store/types.d.ts +3 -11
  48. package/src/types.d.ts +5 -0
@@ -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 {};
@@ -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';
@@ -1 +1,2 @@
1
1
  export * from './requestChannel';
2
+ export * from './types';
@@ -4,32 +4,12 @@
4
4
  Object.defineProperty(exports, '__esModule', { value: true });
5
5
 
6
6
  var _tslib = require('../../_virtual/_tslib.cjs');
7
- var utils = require('@dynamic-labs/utils');
8
7
  var isSerializedError = require('../utils/isSerializedError/isSerializedError.cjs');
9
- var logger = require('../utils/logger.cjs');
10
8
  var parseErrorFromTransport = require('../utils/parseErrorFromTransport/parseErrorFromTransport.cjs');
11
9
  var serializeErrorForTransport = require('../utils/serializeErrorForTransport/serializeErrorForTransport.cjs');
10
+ var createRequestChannelMessageSender = require('./createRequestChannelMessageSender/createRequestChannelMessageSender.cjs');
11
+ var utils = require('./utils/utils.cjs');
12
12
 
13
- /** Given a request event name, returns the event name for its resolve */
14
- const getResolveMessageType = (type) => `${type}__resolve`;
15
- /** Given a request event name, returns the event name for its reject */
16
- const getRejectMessageType = (type) => `${type}__reject`;
17
- /** Given a request event name, returns the event name for its acknowledgement */
18
- const getAckMessageType = (type) => `${type}__ack`;
19
- /** Returns a "no handlers registered" error for a message type */
20
- const createNoHandlerError = (type, cleanup) => {
21
- const message = `No handlers were registered for message of type ${type}`;
22
- logger.logger.error(message);
23
- cleanup();
24
- return new utils.RequestChannelNotHandledError(message);
25
- };
26
- /**
27
- * When a request is sent, a timer will be started. If it times out before
28
- * a corresponding ack message is received, we reject the request with NO_HANDLERS_REGISTERED.
29
- *
30
- * This controls how many ms we should wait before we time out.
31
- */
32
- const TIMEOUT_DURATION = 3000;
33
13
  /**
34
14
  * Allows handling and submitting requests to and from a webview.
35
15
  * Requests are messages that (can) expect some response.
@@ -63,31 +43,24 @@ const createRequestChannel = (messageTransport) => {
63
43
  // Although we won't listen for a response, it must still be unique
64
44
  // to avoid tangling with other requests.
65
45
  const messageSessionId = getUniqueId();
66
- const ackMessageType = getAckMessageType(requestType);
67
- // Before actually emitting the event, we start listening to the
68
- // response events
69
- const handleMessage = ({ messageSessionId: incomingSessionId, type: incomingType, }) => {
70
- if (incomingSessionId !== messageSessionId ||
71
- incomingType !== ackMessageType)
72
- return;
73
- clearTimeout(timeoutMap[messageSessionId]);
74
- delete timeoutMap[messageSessionId];
75
- resolve();
76
- cleanup();
77
- };
78
- const cleanup = () => messageTransport.off(handleMessage);
79
- messageTransport.on(handleMessage);
80
- // Now we emit the event to set off the request
81
- messageTransport.emit({
82
- args: params,
46
+ const { handleAckMessage, sendMessage } = createRequestChannelMessageSender.createRequestChannelMessageSender({
83
47
  messageSessionId,
84
- type: requestType,
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,
85
60
  });
86
- // And start the time out timer
87
- const timeoutTimer = setTimeout(() => {
88
- reject(createNoHandlerError(requestType, cleanup));
89
- }, TIMEOUT_DURATION);
90
- timeoutMap[messageSessionId] = timeoutTimer;
61
+ const cleanupMessageHandler = () => messageTransport.off(handleAckMessage);
62
+ messageTransport.on(handleAckMessage);
63
+ sendMessage();
91
64
  }),
92
65
  handle: (requestType, handler) => {
93
66
  const messageHandler = (_a) => _tslib.__awaiter(void 0, [_a], void 0, function* ({ args, messageSessionId, type: incomingType, }) {
@@ -97,7 +70,7 @@ const createRequestChannel = (messageTransport) => {
97
70
  messageTransport.emit({
98
71
  args: [],
99
72
  messageSessionId,
100
- type: getAckMessageType(requestType),
73
+ type: utils.getAckMessageType(requestType),
101
74
  });
102
75
  const result = handler(...args);
103
76
  // If the handler doesn't return a promise,
@@ -109,14 +82,14 @@ const createRequestChannel = (messageTransport) => {
109
82
  messageTransport.emit({
110
83
  args: [response],
111
84
  messageSessionId,
112
- type: getResolveMessageType(requestType),
85
+ type: utils.getResolveMessageType(requestType),
113
86
  });
114
87
  }
115
88
  catch (error) {
116
89
  messageTransport.emit({
117
90
  args: [serializeErrorForTransport.serializeErrorForTransport(error)],
118
91
  messageSessionId,
119
- type: getRejectMessageType(requestType),
92
+ type: utils.getRejectMessageType(requestType),
120
93
  });
121
94
  }
122
95
  });
@@ -127,52 +100,49 @@ const createRequestChannel = (messageTransport) => {
127
100
  },
128
101
  request: (requestType, ...params) => new Promise((resolve, reject) => {
129
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.
130
105
  const messageSessionId = getUniqueId();
131
- const resolveMessageType = getResolveMessageType(requestType);
132
- const rejectMessageType = getRejectMessageType(requestType);
133
- const ackMessageType = getAckMessageType(requestType);
134
- // Before actually emitting the event, we start listening to the
135
- // response events
136
- const handleMessage = ({ args: [result], messageSessionId: incomingSessionId, type: incomingType, }) => {
137
- if (incomingSessionId !== messageSessionId)
138
- return;
139
- if (incomingType === ackMessageType) {
140
- clearTimeout(timeoutMap[messageSessionId]);
141
- delete timeoutMap[messageSessionId];
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)
142
122
  return;
143
- }
123
+ const { args: [result], type: incomingType, } = message;
144
124
  if (incomingType === resolveMessageType) {
125
+ cleanupMessageHandler();
145
126
  resolve(result);
146
- cleanup();
147
127
  return;
148
128
  }
149
129
  if (incomingType === rejectMessageType) {
130
+ cleanupMessageHandler();
150
131
  if (isSerializedError.isSerializedError(result)) {
151
132
  reject(parseErrorFromTransport.parseErrorFromTransport(result));
152
133
  }
153
134
  else {
154
135
  reject(result);
155
136
  }
156
- cleanup();
137
+ return;
157
138
  }
139
+ handleAckMessage(message);
158
140
  };
159
- const cleanup = () => messageTransport.off(handleMessage);
141
+ const cleanupMessageHandler = () => messageTransport.off(handleMessage);
160
142
  messageTransport.on(handleMessage);
161
- // And start the time out timer
162
- const timeoutTimer = setTimeout(() => reject(createNoHandlerError(requestType, cleanup)), TIMEOUT_DURATION);
163
- timeoutMap[messageSessionId] = timeoutTimer;
164
- // Now we emit the event to set off the request
165
- messageTransport.emit({
166
- args: params,
167
- messageSessionId,
168
- type: requestType,
169
- });
143
+ sendMessage();
170
144
  }),
171
145
  };
172
146
  };
173
147
 
174
- exports.TIMEOUT_DURATION = TIMEOUT_DURATION;
175
148
  exports.createRequestChannel = createRequestChannel;
176
- exports.getAckMessageType = getAckMessageType;
177
- exports.getRejectMessageType = getRejectMessageType;
178
- exports.getResolveMessageType = getResolveMessageType;
@@ -1,71 +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> = Extract<{
11
- [K in keyof T]: ReturnType<T[K]> extends Promise<any> ? K : never;
12
- }[keyof T], string>;
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
- *
19
- * @returns an unsubscribe function.
20
- */
21
- handle: <K extends Extract<keyof T, string>>(requestType: K, handler: T[K]) => VoidFunction;
22
- /**
23
- * Triggers handlers for this request type, with the given params.
24
- * Doesn't expect a response. Resolves as soon as the message is acknowledged by
25
- * any handler.
26
- *
27
- * If no handlers emit an ack for this message, this will reject.
28
- *
29
- * Lifetime of an "emit" message:
30
- * 1. "Emit" message is sent.
31
- * 2. A handler receives the message.
32
- * 3. The handler immediately emits an ack message for it, acknowledging it.
33
- * 4. This method's promise resolves.
34
- */
35
- emit: <K extends Extract<keyof T, string>>(requestName: K, ...params: Parameters<T[K]>) => Promise<void>;
36
- /**
37
- * Triggers handlers for this request type, with the given params.
38
- * As opposed to emit, this expects a response message. A handler must still
39
- * acknowledge this message, but the promise will only resolve when the handler
40
- * emits back a response message. The promise resolves with whatever data was sent
41
- * in the response.
42
- *
43
- * If no handlers emit an ack for this message, or if a handler responds
44
- * with a failure, this will reject.
45
- *
46
- * Lifetime of a "request" message:
47
- * 1. "Request" message is sent.
48
- * 2. A handler receives the message.
49
- * 3. The handler immediately emits an ack message for it, acknowledging it.
50
- * 4. The handler performs the requested action.
51
- * 5. The handler emits a response message.
52
- * 6. This method's promise resolves with the response's data.
53
- */
54
- request: <K extends TypesExpectingResponse<T>>(requestName: K, ...params: Parameters<T[K]>) => ReturnType<T[K]>;
55
- };
56
- /** Given a request event name, returns the event name for its resolve */
57
- export declare const getResolveMessageType: (type: string) => string;
58
- /** Given a request event name, returns the event name for its reject */
59
- export declare const getRejectMessageType: (type: string) => string;
60
- /** Given a request event name, returns the event name for its acknowledgement */
61
- export declare const getAckMessageType: (type: string) => string;
62
- /**
63
- * When a request is sent, a timer will be started. If it times out before
64
- * a corresponding ack message is received, we reject the request with NO_HANDLERS_REGISTERED.
65
- *
66
- * This controls how many ms we should wait before we time out.
67
- */
68
- export declare const TIMEOUT_DURATION = 3000;
3
+ import { RequestChannel, RequestTypes } from './types';
69
4
  /**
70
5
  * Allows handling and submitting requests to and from a webview.
71
6
  * Requests are messages that (can) expect some response.
@@ -84,5 +19,4 @@ export declare const TIMEOUT_DURATION = 3000;
84
19
  *
85
20
  * This is an abstraction built on top of the MessageTransport interface.
86
21
  */
87
- export declare const createRequestChannel: <T extends RequestTypes = never>(messageTransport: MessageTransportWithDefaultOrigin) => RequestChannel<T>;
88
- export {};
22
+ export declare const createRequestChannel: <T extends RequestTypes = never>(messageTransport: MessageTransportWithDefaultOrigin | WithBlock<MessageTransportWithDefaultOrigin>) => RequestChannel<T>;
@@ -1,31 +1,11 @@
1
1
  'use client'
2
2
  import { __awaiter } from '../../_virtual/_tslib.js';
3
- import { RequestChannelNotHandledError } from '@dynamic-labs/utils';
4
3
  import { isSerializedError } from '../utils/isSerializedError/isSerializedError.js';
5
- import { logger } from '../utils/logger.js';
6
4
  import { parseErrorFromTransport } from '../utils/parseErrorFromTransport/parseErrorFromTransport.js';
7
5
  import { serializeErrorForTransport } from '../utils/serializeErrorForTransport/serializeErrorForTransport.js';
6
+ import { createRequestChannelMessageSender } from './createRequestChannelMessageSender/createRequestChannelMessageSender.js';
7
+ import { createNoHandlerError, getAckMessageType, getResolveMessageType, getRejectMessageType } from './utils/utils.js';
8
8
 
9
- /** Given a request event name, returns the event name for its resolve */
10
- const getResolveMessageType = (type) => `${type}__resolve`;
11
- /** Given a request event name, returns the event name for its reject */
12
- const getRejectMessageType = (type) => `${type}__reject`;
13
- /** Given a request event name, returns the event name for its acknowledgement */
14
- const getAckMessageType = (type) => `${type}__ack`;
15
- /** Returns a "no handlers registered" error for a message type */
16
- const createNoHandlerError = (type, cleanup) => {
17
- const message = `No handlers were registered for message of type ${type}`;
18
- logger.error(message);
19
- cleanup();
20
- return new RequestChannelNotHandledError(message);
21
- };
22
- /**
23
- * When a request is sent, a timer will be started. If it times out before
24
- * a corresponding ack message is received, we reject the request with NO_HANDLERS_REGISTERED.
25
- *
26
- * This controls how many ms we should wait before we time out.
27
- */
28
- const TIMEOUT_DURATION = 3000;
29
9
  /**
30
10
  * Allows handling and submitting requests to and from a webview.
31
11
  * Requests are messages that (can) expect some response.
@@ -59,31 +39,24 @@ const createRequestChannel = (messageTransport) => {
59
39
  // Although we won't listen for a response, it must still be unique
60
40
  // to avoid tangling with other requests.
61
41
  const messageSessionId = getUniqueId();
62
- const ackMessageType = getAckMessageType(requestType);
63
- // Before actually emitting the event, we start listening to the
64
- // response events
65
- const handleMessage = ({ messageSessionId: incomingSessionId, type: incomingType, }) => {
66
- if (incomingSessionId !== messageSessionId ||
67
- incomingType !== ackMessageType)
68
- return;
69
- clearTimeout(timeoutMap[messageSessionId]);
70
- delete timeoutMap[messageSessionId];
71
- resolve();
72
- cleanup();
73
- };
74
- const cleanup = () => messageTransport.off(handleMessage);
75
- messageTransport.on(handleMessage);
76
- // Now we emit the event to set off the request
77
- messageTransport.emit({
78
- args: params,
42
+ const { handleAckMessage, sendMessage } = createRequestChannelMessageSender({
79
43
  messageSessionId,
80
- type: requestType,
44
+ messageTransport,
45
+ onReceiveAck: () => {
46
+ cleanupMessageHandler();
47
+ resolve();
48
+ },
49
+ onTimeout: () => {
50
+ cleanupMessageHandler();
51
+ reject(createNoHandlerError(requestType));
52
+ },
53
+ params,
54
+ requestType,
55
+ timeoutMap,
81
56
  });
82
- // And start the time out timer
83
- const timeoutTimer = setTimeout(() => {
84
- reject(createNoHandlerError(requestType, cleanup));
85
- }, TIMEOUT_DURATION);
86
- timeoutMap[messageSessionId] = timeoutTimer;
57
+ const cleanupMessageHandler = () => messageTransport.off(handleAckMessage);
58
+ messageTransport.on(handleAckMessage);
59
+ sendMessage();
87
60
  }),
88
61
  handle: (requestType, handler) => {
89
62
  const messageHandler = (_a) => __awaiter(void 0, [_a], void 0, function* ({ args, messageSessionId, type: incomingType, }) {
@@ -123,48 +96,49 @@ const createRequestChannel = (messageTransport) => {
123
96
  },
124
97
  request: (requestType, ...params) => new Promise((resolve, reject) => {
125
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.
126
101
  const messageSessionId = getUniqueId();
127
102
  const resolveMessageType = getResolveMessageType(requestType);
128
103
  const rejectMessageType = getRejectMessageType(requestType);
129
- const ackMessageType = getAckMessageType(requestType);
130
- // Before actually emitting the event, we start listening to the
131
- // response events
132
- const handleMessage = ({ args: [result], messageSessionId: incomingSessionId, type: incomingType, }) => {
133
- if (incomingSessionId !== messageSessionId)
134
- return;
135
- if (incomingType === ackMessageType) {
136
- clearTimeout(timeoutMap[messageSessionId]);
137
- delete timeoutMap[messageSessionId];
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)
138
118
  return;
139
- }
119
+ const { args: [result], type: incomingType, } = message;
140
120
  if (incomingType === resolveMessageType) {
121
+ cleanupMessageHandler();
141
122
  resolve(result);
142
- cleanup();
143
123
  return;
144
124
  }
145
125
  if (incomingType === rejectMessageType) {
126
+ cleanupMessageHandler();
146
127
  if (isSerializedError(result)) {
147
128
  reject(parseErrorFromTransport(result));
148
129
  }
149
130
  else {
150
131
  reject(result);
151
132
  }
152
- cleanup();
133
+ return;
153
134
  }
135
+ handleAckMessage(message);
154
136
  };
155
- const cleanup = () => messageTransport.off(handleMessage);
137
+ const cleanupMessageHandler = () => messageTransport.off(handleMessage);
156
138
  messageTransport.on(handleMessage);
157
- // And start the time out timer
158
- const timeoutTimer = setTimeout(() => reject(createNoHandlerError(requestType, cleanup)), TIMEOUT_DURATION);
159
- timeoutMap[messageSessionId] = timeoutTimer;
160
- // Now we emit the event to set off the request
161
- messageTransport.emit({
162
- args: params,
163
- messageSessionId,
164
- type: requestType,
165
- });
139
+ sendMessage();
166
140
  }),
167
141
  };
168
142
  };
169
143
 
170
- export { TIMEOUT_DURATION, createRequestChannel, getAckMessageType, getRejectMessageType, getResolveMessageType };
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';
@@ -0,0 +1,33 @@
1
+ 'use client'
2
+ 'use strict';
3
+
4
+ Object.defineProperty(exports, '__esModule', { value: true });
5
+
6
+ var utils = require('@dynamic-labs/utils');
7
+ var logger = require('../../utils/logger.cjs');
8
+
9
+ /** Given a request event name, returns the event name for its resolve */
10
+ const getResolveMessageType = (type) => `${type}__resolve`;
11
+ /** Given a request event name, returns the event name for its reject */
12
+ const getRejectMessageType = (type) => `${type}__reject`;
13
+ /** Given a request event name, returns the event name for its acknowledgement */
14
+ const getAckMessageType = (type) => `${type}__ack`;
15
+ /** Returns a "no handlers registered" error for a message type */
16
+ const createNoHandlerError = (type) => {
17
+ const message = `No handlers were registered for message of type ${type}`;
18
+ logger.logger.error(message);
19
+ return new utils.RequestChannelNotHandledError(message);
20
+ };
21
+ /**
22
+ * When a request is sent, a timer will be started. If it times out before
23
+ * a corresponding ack message is received, we reject the request with NO_HANDLERS_REGISTERED.
24
+ *
25
+ * This controls how many ms we should wait before we time out.
26
+ */
27
+ const TIMEOUT_DURATION = 3000;
28
+
29
+ exports.TIMEOUT_DURATION = TIMEOUT_DURATION;
30
+ exports.createNoHandlerError = createNoHandlerError;
31
+ exports.getAckMessageType = getAckMessageType;
32
+ exports.getRejectMessageType = getRejectMessageType;
33
+ exports.getResolveMessageType = getResolveMessageType;
@@ -0,0 +1,16 @@
1
+ import { RequestChannelNotHandledError } from '@dynamic-labs/utils';
2
+ /** Given a request event name, returns the event name for its resolve */
3
+ export declare const getResolveMessageType: (type: string) => string;
4
+ /** Given a request event name, returns the event name for its reject */
5
+ export declare const getRejectMessageType: (type: string) => string;
6
+ /** Given a request event name, returns the event name for its acknowledgement */
7
+ export declare const getAckMessageType: (type: string) => string;
8
+ /** Returns a "no handlers registered" error for a message type */
9
+ export declare const createNoHandlerError: (type: string) => RequestChannelNotHandledError;
10
+ /**
11
+ * When a request is sent, a timer will be started. If it times out before
12
+ * a corresponding ack message is received, we reject the request with NO_HANDLERS_REGISTERED.
13
+ *
14
+ * This controls how many ms we should wait before we time out.
15
+ */
16
+ export declare const TIMEOUT_DURATION = 3000;
@@ -0,0 +1,25 @@
1
+ 'use client'
2
+ import { RequestChannelNotHandledError } from '@dynamic-labs/utils';
3
+ import { logger } from '../../utils/logger.js';
4
+
5
+ /** Given a request event name, returns the event name for its resolve */
6
+ const getResolveMessageType = (type) => `${type}__resolve`;
7
+ /** Given a request event name, returns the event name for its reject */
8
+ const getRejectMessageType = (type) => `${type}__reject`;
9
+ /** Given a request event name, returns the event name for its acknowledgement */
10
+ const getAckMessageType = (type) => `${type}__ack`;
11
+ /** Returns a "no handlers registered" error for a message type */
12
+ const createNoHandlerError = (type) => {
13
+ const message = `No handlers were registered for message of type ${type}`;
14
+ logger.error(message);
15
+ return new RequestChannelNotHandledError(message);
16
+ };
17
+ /**
18
+ * When a request is sent, a timer will be started. If it times out before
19
+ * a corresponding ack message is received, we reject the request with NO_HANDLERS_REGISTERED.
20
+ *
21
+ * This controls how many ms we should wait before we time out.
22
+ */
23
+ const TIMEOUT_DURATION = 3000;
24
+
25
+ export { TIMEOUT_DURATION, createNoHandlerError, getAckMessageType, getRejectMessageType, getResolveMessageType };
@@ -11,13 +11,12 @@ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'defau
11
11
  var EventEmitter__default = /*#__PURE__*/_interopDefaultLegacy(EventEmitter);
12
12
 
13
13
  // There are way too many "any"s in this file. They are necessary because otherwise the generics won't work
14
- function createEventEmitterForMessages({ messageTransport, initialEventEmitter, key, }) {
14
+ function createEventEmitterForMessages({ messageTransport, initialEventEmitter, eventNames, }) {
15
15
  const events = initialEventEmitter !== null && initialEventEmitter !== void 0 ? initialEventEmitter : new EventEmitter__default["default"]();
16
16
  const requestChannel$1 = requestChannel.createRequestChannel(messageTransport);
17
- requestChannel$1.handle('eventEmitted', (eventKey, eventName, payload) => {
18
- if (eventKey === key)
19
- events.emit(eventName, ...payload);
20
- });
17
+ for (const eventName of eventNames) {
18
+ requestChannel$1.handle(eventName, (...payload) => events.emit(eventName, ...payload));
19
+ }
21
20
  return events;
22
21
  }
23
22