@dynamic-labs/message-transport 0.0.0-exp20240808.0
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 +3746 -0
- package/LICENSE +21 -0
- package/README.md +3 -0
- package/_virtual/_tslib.cjs +49 -0
- package/_virtual/_tslib.js +44 -0
- package/package.json +33 -0
- package/src/index.cjs +32 -0
- package/src/index.d.ts +8 -0
- package/src/index.js +13 -0
- package/src/messageTransport/decorators/applyDefaultMessageOrigin/applyDefaultMessageOrigin.cjs +12 -0
- package/src/messageTransport/decorators/applyDefaultMessageOrigin/applyDefaultMessageOrigin.d.ts +15 -0
- package/src/messageTransport/decorators/applyDefaultMessageOrigin/applyDefaultMessageOrigin.js +8 -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 +35 -0
- package/src/messageTransport/decorators/makeWaitForInitEvent/makeWaitForInitEvent.d.ts +25 -0
- package/src/messageTransport/decorators/makeWaitForInitEvent/makeWaitForInitEvent.js +31 -0
- package/src/messageTransport/decorators/makeWaitForUnblock/index.d.ts +1 -0
- package/src/messageTransport/decorators/makeWaitForUnblock/makeWaitForUnblock.cjs +53 -0
- package/src/messageTransport/decorators/makeWaitForUnblock/makeWaitForUnblock.d.ts +23 -0
- package/src/messageTransport/decorators/makeWaitForUnblock/makeWaitForUnblock.js +49 -0
- package/src/messageTransport/index.d.ts +2 -0
- package/src/messageTransport/messageTransport.cjs +16 -0
- package/src/messageTransport/messageTransport.d.ts +44 -0
- package/src/messageTransport/messageTransport.js +12 -0
- package/src/messageTypes/AuthModuleMessages.d.ts +8 -0
- package/src/messageTypes/ConsoleMessages.d.ts +11 -0
- package/src/messageTypes/EmbeddedWalletsModuleMessages.d.ts +8 -0
- package/src/messageTypes/EthMessages.d.ts +13 -0
- package/src/messageTypes/ExternalAuthMessages.d.ts +16 -0
- package/src/messageTypes/FetchMessages.d.ts +8 -0
- package/src/messageTypes/NetworksModuleMessages.d.ts +5 -0
- package/src/messageTypes/OtpMessages.d.ts +17 -0
- package/src/messageTypes/PasskeyMessages.d.ts +32 -0
- package/src/messageTypes/PlatformServiceMessages.d.ts +17 -0
- package/src/messageTypes/SdkModuleMessages.cjs +9 -0
- package/src/messageTypes/SdkModuleMessages.d.ts +25 -0
- package/src/messageTypes/SdkModuleMessages.js +5 -0
- package/src/messageTypes/SocialAuthModuleMessages.d.ts +17 -0
- package/src/messageTypes/SolanaMessages.d.ts +42 -0
- package/src/messageTypes/UserInterfaceModuleMessages.d.ts +8 -0
- package/src/messageTypes/WalletsModuleMessages.d.ts +30 -0
- package/src/messageTypes/WebViewVisibilityMessages.d.ts +3 -0
- package/src/messageTypes/index.d.ts +16 -0
- package/src/requestChannel/index.d.ts +1 -0
- package/src/requestChannel/requestChannel.cjs +121 -0
- package/src/requestChannel/requestChannel.d.ts +55 -0
- package/src/requestChannel/requestChannel.js +115 -0
- package/src/store/createEventEmitterForMessages/createEventEmitterForMessages.cjs +24 -0
- package/src/store/createEventEmitterForMessages/createEventEmitterForMessages.d.ts +22 -0
- package/src/store/createEventEmitterForMessages/createEventEmitterForMessages.js +16 -0
- package/src/store/createEventEmitterForMessages/index.d.ts +1 -0
- package/src/store/index.d.ts +3 -0
- package/src/store/store.cjs +59 -0
- package/src/store/store.d.ts +8 -0
- package/src/store/store.js +51 -0
- package/src/store/storeSetter/index.d.ts +1 -0
- package/src/store/storeSetter/storeSetter.cjs +23 -0
- package/src/store/storeSetter/storeSetter.d.ts +8 -0
- package/src/store/storeSetter/storeSetter.js +19 -0
- package/src/store/types.d.ts +53 -0
- package/src/utils/isSerializedError/index.d.ts +1 -0
- package/src/utils/isSerializedError/isSerializedError.cjs +14 -0
- package/src/utils/isSerializedError/isSerializedError.d.ts +2 -0
- package/src/utils/isSerializedError/isSerializedError.js +10 -0
- package/src/utils/parseErrorFromTransport/index.d.ts +1 -0
- package/src/utils/parseErrorFromTransport/parseErrorFromTransport.cjs +54 -0
- package/src/utils/parseErrorFromTransport/parseErrorFromTransport.d.ts +11 -0
- package/src/utils/parseErrorFromTransport/parseErrorFromTransport.js +50 -0
- package/src/utils/parseMessageTransportData/index.d.ts +1 -0
- package/src/utils/parseMessageTransportData/parseMessageTransportData.cjs +27 -0
- package/src/utils/parseMessageTransportData/parseMessageTransportData.d.ts +2 -0
- package/src/utils/parseMessageTransportData/parseMessageTransportData.js +23 -0
- package/src/utils/serializeErrorForTransport/index.d.ts +1 -0
- package/src/utils/serializeErrorForTransport/serializeErrorForTransport.cjs +33 -0
- package/src/utils/serializeErrorForTransport/serializeErrorForTransport.d.ts +19 -0
- package/src/utils/serializeErrorForTransport/serializeErrorForTransport.js +29 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { OtpDestination, PhoneData } from '@dynamic-labs/types';
|
|
2
|
+
type OtpData = {
|
|
3
|
+
destination: Extract<OtpDestination, 'email'>;
|
|
4
|
+
target: string;
|
|
5
|
+
} | {
|
|
6
|
+
destination: Extract<OtpDestination, 'sms'>;
|
|
7
|
+
target: PhoneData;
|
|
8
|
+
};
|
|
9
|
+
export type OtpMessages = {
|
|
10
|
+
/** Request to send an OTP to a destination for verification */
|
|
11
|
+
sendOTP: (data: OtpData) => Promise<void>;
|
|
12
|
+
/** Performs verification for the latest send OTP */
|
|
13
|
+
verifyOTP: (token: string) => Promise<void>;
|
|
14
|
+
/** Re-sends the OTP for verification */
|
|
15
|
+
resendOTP: () => Promise<void>;
|
|
16
|
+
};
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
type CustomPublicKeyCredentialUserEntity = Omit<PublicKeyCredentialUserEntity, 'id'> & {
|
|
2
|
+
id: string;
|
|
3
|
+
};
|
|
4
|
+
type CustomPublicKeyCredentialRpEntity = Omit<PublicKeyCredentialRpEntity, 'id'> & {
|
|
5
|
+
id: string;
|
|
6
|
+
};
|
|
7
|
+
export type PasskeyMessages = {
|
|
8
|
+
createPasskey: (params: {
|
|
9
|
+
publicKey: {
|
|
10
|
+
authenticatorName: string;
|
|
11
|
+
attestation?: AttestationConveyancePreference;
|
|
12
|
+
authenticatorSelection?: AuthenticatorSelectionCriteria;
|
|
13
|
+
challenge?: string;
|
|
14
|
+
pubKeyCredParams: PublicKeyCredentialParameters[];
|
|
15
|
+
rp: CustomPublicKeyCredentialRpEntity;
|
|
16
|
+
timeout?: number;
|
|
17
|
+
user: CustomPublicKeyCredentialUserEntity;
|
|
18
|
+
};
|
|
19
|
+
}) => Promise<{
|
|
20
|
+
attestation: {
|
|
21
|
+
credentialId: string;
|
|
22
|
+
clientDataJson: string;
|
|
23
|
+
attestationObject: string;
|
|
24
|
+
transports: ('AUTHENTICATOR_TRANSPORT_BLE' | 'AUTHENTICATOR_TRANSPORT_INTERNAL' | 'AUTHENTICATOR_TRANSPORT_NFC' | 'AUTHENTICATOR_TRANSPORT_USB' | 'AUTHENTICATOR_TRANSPORT_HYBRID')[];
|
|
25
|
+
};
|
|
26
|
+
}>;
|
|
27
|
+
passkeyStamp: (rdId: string, payload: string) => Promise<{
|
|
28
|
+
stampHeaderName: string;
|
|
29
|
+
stampHeaderValue: string;
|
|
30
|
+
}>;
|
|
31
|
+
};
|
|
32
|
+
export {};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export type PlatformServiceMessages = {
|
|
2
|
+
/**
|
|
3
|
+
* Origin: Webview.
|
|
4
|
+
* Requests that a deeplink be open by whichever platform the client is running in.
|
|
5
|
+
*/
|
|
6
|
+
openURL: (url: string) => Promise<void>;
|
|
7
|
+
/**
|
|
8
|
+
* Origin: Webview.
|
|
9
|
+
* Opens the URL in a secure browser window for authentication.
|
|
10
|
+
*
|
|
11
|
+
* Resolves with the URL used to deeplink back to this app.
|
|
12
|
+
*/
|
|
13
|
+
openAuthenticationWindow: (props: {
|
|
14
|
+
url: string;
|
|
15
|
+
redirectUrl?: string;
|
|
16
|
+
}) => Promise<string>;
|
|
17
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
5
|
+
|
|
6
|
+
/** Easy access to the event name that indicates the SDK has loaded */
|
|
7
|
+
const sdkHasLoadedEventName = 'sdk__loadedChanged';
|
|
8
|
+
|
|
9
|
+
exports.sdkHasLoadedEventName = sdkHasLoadedEventName;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Defines the settings required by the SDK to be properly initialized
|
|
3
|
+
* inside the webview
|
|
4
|
+
*/
|
|
5
|
+
export type ClientManifest = {
|
|
6
|
+
apiBaseUrl?: string;
|
|
7
|
+
appLogoUrl?: string;
|
|
8
|
+
appName?: string;
|
|
9
|
+
appOrigin?: string;
|
|
10
|
+
clientVersion: string;
|
|
11
|
+
cssOverrides?: string;
|
|
12
|
+
environmentId: string;
|
|
13
|
+
platform: 'browser' | 'react-native' | 'flutter';
|
|
14
|
+
redirectUrl: string;
|
|
15
|
+
};
|
|
16
|
+
export type SdkModuleState = {
|
|
17
|
+
/** Indicates the SDK is set up and ready for requests */
|
|
18
|
+
loaded: boolean;
|
|
19
|
+
};
|
|
20
|
+
export type SdkModuleMessages = {
|
|
21
|
+
/** Sent from the webview app to request the SDK settings */
|
|
22
|
+
manifest: () => Promise<ClientManifest>;
|
|
23
|
+
};
|
|
24
|
+
/** Easy access to the event name that indicates the SDK has loaded */
|
|
25
|
+
export declare const sdkHasLoadedEventName = "sdk__loadedChanged";
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export type SocialProvider = 'apple' | 'coinbaseSocial' | 'discord' | 'facebook' | 'farcaster' | 'github' | 'google' | 'telegram' | 'twitch' | 'twitter';
|
|
2
|
+
export type SocialAuthModuleMessages = {
|
|
3
|
+
connectWithSocial: (args: {
|
|
4
|
+
/**
|
|
5
|
+
* Provider with which to connect
|
|
6
|
+
*/
|
|
7
|
+
provider: SocialProvider;
|
|
8
|
+
/**
|
|
9
|
+
* When using expo-router, which pathname to redirect back to after social connection.
|
|
10
|
+
*
|
|
11
|
+
* The router will create another stack when redirecting back to a different pathname than your
|
|
12
|
+
* app was at originally, which in iOS devices will cause visual flickering. To avoid this, pass
|
|
13
|
+
* `usePathname()` to this property.
|
|
14
|
+
*/
|
|
15
|
+
redirectPathname?: string;
|
|
16
|
+
}) => Promise<void>;
|
|
17
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
type Commitment = 'processed' | 'confirmed' | 'finalized' | 'recent' | 'single' | 'singleGossip' | 'root' | 'max';
|
|
2
|
+
type SendOptions = {
|
|
3
|
+
skipPreflight?: boolean;
|
|
4
|
+
preflightCommitment?: Commitment;
|
|
5
|
+
maxRetries?: number;
|
|
6
|
+
minContextSlot?: number;
|
|
7
|
+
};
|
|
8
|
+
type EncodedTransaction = {
|
|
9
|
+
type: 'legacy' | 'versioned';
|
|
10
|
+
transaction: string;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Messages exchanged for solana requests.
|
|
14
|
+
*/
|
|
15
|
+
export type SolanaMessages = {
|
|
16
|
+
solana_signMessage: (arg: {
|
|
17
|
+
message: string;
|
|
18
|
+
walletId: string;
|
|
19
|
+
}) => Promise<{
|
|
20
|
+
signature: string;
|
|
21
|
+
}>;
|
|
22
|
+
solana_signAndSendTransaction: (arg: {
|
|
23
|
+
walletId: string;
|
|
24
|
+
options?: SendOptions;
|
|
25
|
+
encodedTransaction: EncodedTransaction;
|
|
26
|
+
}) => Promise<{
|
|
27
|
+
signature: string;
|
|
28
|
+
}>;
|
|
29
|
+
solana_signTransaction: (arg: {
|
|
30
|
+
walletId: string;
|
|
31
|
+
encodedTransaction: EncodedTransaction;
|
|
32
|
+
}) => Promise<{
|
|
33
|
+
encodedTransaction: EncodedTransaction;
|
|
34
|
+
}>;
|
|
35
|
+
solana_signAllTransactions: (arg: {
|
|
36
|
+
walletId: string;
|
|
37
|
+
encodedTransactions: EncodedTransaction[];
|
|
38
|
+
}) => Promise<{
|
|
39
|
+
encodedTransactions: EncodedTransaction[];
|
|
40
|
+
}>;
|
|
41
|
+
};
|
|
42
|
+
export {};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { BaseWallet } from '@dynamic-labs/types';
|
|
2
|
+
export type WalletsModuleState = {
|
|
3
|
+
userWallets: BaseWallet[];
|
|
4
|
+
primary: BaseWallet | undefined;
|
|
5
|
+
};
|
|
6
|
+
export type WalletsModuleMessages = {
|
|
7
|
+
getBalance: (params: {
|
|
8
|
+
wallet: BaseWallet;
|
|
9
|
+
}) => Promise<{
|
|
10
|
+
balance: string;
|
|
11
|
+
}>;
|
|
12
|
+
signMessage: (params: {
|
|
13
|
+
wallet: BaseWallet;
|
|
14
|
+
message: string;
|
|
15
|
+
}) => Promise<{
|
|
16
|
+
signedMessage: string;
|
|
17
|
+
}>;
|
|
18
|
+
getNetwork: (params: {
|
|
19
|
+
wallet: BaseWallet;
|
|
20
|
+
}) => Promise<{
|
|
21
|
+
network: string | number;
|
|
22
|
+
}>;
|
|
23
|
+
switchNetwork: (params: {
|
|
24
|
+
wallet: BaseWallet;
|
|
25
|
+
chainId: string | number;
|
|
26
|
+
}) => Promise<void>;
|
|
27
|
+
setPrimary: (params: {
|
|
28
|
+
walletId: string;
|
|
29
|
+
}) => Promise<void>;
|
|
30
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export * from './AuthModuleMessages';
|
|
2
|
+
export * from './ConsoleMessages';
|
|
3
|
+
export * from './EmbeddedWalletsModuleMessages';
|
|
4
|
+
export * from './EthMessages';
|
|
5
|
+
export * from './ExternalAuthMessages';
|
|
6
|
+
export * from './FetchMessages';
|
|
7
|
+
export * from './NetworksModuleMessages';
|
|
8
|
+
export * from './OtpMessages';
|
|
9
|
+
export * from './PasskeyMessages';
|
|
10
|
+
export * from './PlatformServiceMessages';
|
|
11
|
+
export * from './SdkModuleMessages';
|
|
12
|
+
export * from './SocialAuthModuleMessages';
|
|
13
|
+
export * from './SolanaMessages';
|
|
14
|
+
export * from './UserInterfaceModuleMessages';
|
|
15
|
+
export * from './WalletsModuleMessages';
|
|
16
|
+
export * from './WebViewVisibilityMessages';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './requestChannel';
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
5
|
+
|
|
6
|
+
var _tslib = require('../../_virtual/_tslib.cjs');
|
|
7
|
+
var parseErrorFromTransport = require('../utils/parseErrorFromTransport/parseErrorFromTransport.cjs');
|
|
8
|
+
var serializeErrorForTransport = require('../utils/serializeErrorForTransport/serializeErrorForTransport.cjs');
|
|
9
|
+
var isSerializedError = require('../utils/isSerializedError/isSerializedError.cjs');
|
|
10
|
+
|
|
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
|
+
/**
|
|
16
|
+
* Allows handling and submitting requests to and from a webview.
|
|
17
|
+
* Requests are messages that (can) expect some response.
|
|
18
|
+
*
|
|
19
|
+
* Functions similarly to an event emitter, but adds a response feature:
|
|
20
|
+
* - Emitting an event type is the act of making a "request" of a specific type,
|
|
21
|
+
* and it returns a promise that will resolve to the request's response.
|
|
22
|
+
* - Listening to an event type is the act of "handling" requests of a specific type.
|
|
23
|
+
* This handler callback must return a promise if this request type expects responses.
|
|
24
|
+
*
|
|
25
|
+
* Think of it this way:
|
|
26
|
+
* Whenever I emit an event, I am submitting a request.
|
|
27
|
+
* Whoever listens to the event will handle my request.
|
|
28
|
+
* If the request type expects some kind of response, they will
|
|
29
|
+
* return a promise that resolves (or rejects) after my request is fulfilled.
|
|
30
|
+
*
|
|
31
|
+
* This is an abstraction built on top of the MessageTransport interface.
|
|
32
|
+
*/
|
|
33
|
+
const createRequestChannel = (messageTransport) => {
|
|
34
|
+
/** Used to generated unique ids */
|
|
35
|
+
let uniqueIdCounter = 0;
|
|
36
|
+
/** Id prefix unique to this channel */
|
|
37
|
+
const idPrefix = Math.random().toString();
|
|
38
|
+
/** Always returns a different string */
|
|
39
|
+
const getUniqueId = () => `${idPrefix}-${uniqueIdCounter++}`;
|
|
40
|
+
return {
|
|
41
|
+
emit: (requestName, ...params) => {
|
|
42
|
+
// Generate the unique id for this message exchange session
|
|
43
|
+
// Although we won't listen for a response, it must still be unique
|
|
44
|
+
// to avoid tangling with other requests.
|
|
45
|
+
const messageSessionId = getUniqueId();
|
|
46
|
+
messageTransport.emit({
|
|
47
|
+
args: params,
|
|
48
|
+
messageSessionId,
|
|
49
|
+
type: requestName,
|
|
50
|
+
});
|
|
51
|
+
},
|
|
52
|
+
handle: (requestType, handler) => {
|
|
53
|
+
const messageHandler = (_a) => _tslib.__awaiter(void 0, [_a], void 0, function* ({ args, messageSessionId, type: incomingType, }) {
|
|
54
|
+
if (requestType !== incomingType)
|
|
55
|
+
return;
|
|
56
|
+
const result = handler(...args);
|
|
57
|
+
// If the handler doesn't return a promise,
|
|
58
|
+
// that means we don't need to respond.
|
|
59
|
+
if (!(result instanceof Promise))
|
|
60
|
+
return;
|
|
61
|
+
try {
|
|
62
|
+
const response = yield result;
|
|
63
|
+
messageTransport.emit({
|
|
64
|
+
args: [response],
|
|
65
|
+
messageSessionId,
|
|
66
|
+
type: getResolveMessageType(requestType),
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
messageTransport.emit({
|
|
71
|
+
args: [serializeErrorForTransport.serializeErrorForTransport(error)],
|
|
72
|
+
messageSessionId,
|
|
73
|
+
type: getRejectMessageType(requestType),
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
messageTransport.on(messageHandler);
|
|
78
|
+
return () => {
|
|
79
|
+
messageTransport.off(messageHandler);
|
|
80
|
+
};
|
|
81
|
+
},
|
|
82
|
+
request: (requestName, ...params) => new Promise((resolve, reject) => {
|
|
83
|
+
const requestType = requestName;
|
|
84
|
+
// Generate the unique id for this message exchange session
|
|
85
|
+
const messageSessionId = getUniqueId();
|
|
86
|
+
const resolveMessageType = getResolveMessageType(requestType);
|
|
87
|
+
const rejectMessageType = getRejectMessageType(requestType);
|
|
88
|
+
// Before actually emitting the event, we start listening to the
|
|
89
|
+
// response events
|
|
90
|
+
const handleMessage = ({ args: [result], messageSessionId: incomingSessionId, type: incomingType, }) => {
|
|
91
|
+
if (incomingSessionId !== messageSessionId)
|
|
92
|
+
return;
|
|
93
|
+
if (incomingType === resolveMessageType) {
|
|
94
|
+
resolve(result);
|
|
95
|
+
cleanup();
|
|
96
|
+
}
|
|
97
|
+
if (incomingType === rejectMessageType) {
|
|
98
|
+
if (isSerializedError.isSerializedError(result)) {
|
|
99
|
+
reject(parseErrorFromTransport.parseErrorFromTransport(result));
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
reject(result);
|
|
103
|
+
}
|
|
104
|
+
cleanup();
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
const cleanup = () => messageTransport.off(handleMessage);
|
|
108
|
+
messageTransport.on(handleMessage);
|
|
109
|
+
// Now we emit the event to set off the request
|
|
110
|
+
messageTransport.emit({
|
|
111
|
+
args: params,
|
|
112
|
+
messageSessionId,
|
|
113
|
+
type: requestType,
|
|
114
|
+
});
|
|
115
|
+
}),
|
|
116
|
+
};
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
exports.createRequestChannel = createRequestChannel;
|
|
120
|
+
exports.getRejectMessageType = getRejectMessageType;
|
|
121
|
+
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,115 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
import { __awaiter } from '../../_virtual/_tslib.js';
|
|
3
|
+
import { parseErrorFromTransport } from '../utils/parseErrorFromTransport/parseErrorFromTransport.js';
|
|
4
|
+
import { serializeErrorForTransport } from '../utils/serializeErrorForTransport/serializeErrorForTransport.js';
|
|
5
|
+
import { isSerializedError } from '../utils/isSerializedError/isSerializedError.js';
|
|
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 = (_a) => __awaiter(void 0, [_a], void 0, function* ({ args, messageSessionId, type: incomingType, }) {
|
|
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: [serializeErrorForTransport(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
|
+
if (isSerializedError(result)) {
|
|
95
|
+
reject(parseErrorFromTransport(result));
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
reject(result);
|
|
99
|
+
}
|
|
100
|
+
cleanup();
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
const cleanup = () => messageTransport.off(handleMessage);
|
|
104
|
+
messageTransport.on(handleMessage);
|
|
105
|
+
// Now we emit the event to set off the request
|
|
106
|
+
messageTransport.emit({
|
|
107
|
+
args: params,
|
|
108
|
+
messageSessionId,
|
|
109
|
+
type: requestType,
|
|
110
|
+
});
|
|
111
|
+
}),
|
|
112
|
+
};
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
export { createRequestChannel, getRejectMessageType, getResolveMessageType };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
5
|
+
|
|
6
|
+
var EventEmitter = require('eventemitter3');
|
|
7
|
+
var requestChannel = require('../../requestChannel/requestChannel.cjs');
|
|
8
|
+
|
|
9
|
+
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
10
|
+
|
|
11
|
+
var EventEmitter__default = /*#__PURE__*/_interopDefaultLegacy(EventEmitter);
|
|
12
|
+
|
|
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, }) {
|
|
15
|
+
const events = initialEventEmitter !== null && initialEventEmitter !== void 0 ? initialEventEmitter : new EventEmitter__default["default"]();
|
|
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
|
+
});
|
|
21
|
+
return events;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
exports.createEventEmitterForMessages = createEventEmitterForMessages;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import EventEmitter from 'eventemitter3';
|
|
2
|
+
import { MessageTransportWithDefaultOrigin } from '../../messageTransport';
|
|
3
|
+
export type MessagesForEventEmitter<T extends Record<string, (...args: any[]) => any>, U extends string> = {
|
|
4
|
+
eventEmitted: <E extends keyof T>(key: U, eventName: E, payload: Parameters<T[E]>) => void;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Use this function when you want to get an event emitter that will raise events for
|
|
8
|
+
* messages of type MessagesForEventEmitter
|
|
9
|
+
*/
|
|
10
|
+
export declare function createEventEmitterForMessages<T extends Record<string, (...args: any[]) => any> = never, U extends string = never>(params: {
|
|
11
|
+
messageTransport: MessageTransportWithDefaultOrigin;
|
|
12
|
+
key: U;
|
|
13
|
+
}): EventEmitter<T>;
|
|
14
|
+
/**
|
|
15
|
+
* Use this function when you want to get an event emitter that will raise events for
|
|
16
|
+
* messages of type MessagesForEventEmitter
|
|
17
|
+
*/
|
|
18
|
+
export declare function createEventEmitterForMessages<T extends Record<string, (...args: any[]) => any> = never, U extends string = never, E extends EventEmitter<any> = never>(params: {
|
|
19
|
+
messageTransport: MessageTransportWithDefaultOrigin;
|
|
20
|
+
initialEventEmitter: E;
|
|
21
|
+
key: U;
|
|
22
|
+
}): E extends EventEmitter<infer V> ? EventEmitter<T & V> : never;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
import EventEmitter from 'eventemitter3';
|
|
3
|
+
import { createRequestChannel } from '../../requestChannel/requestChannel.js';
|
|
4
|
+
|
|
5
|
+
// There are way too many "any"s in this file. They are necessary because otherwise the generics won't work
|
|
6
|
+
function createEventEmitterForMessages({ messageTransport, initialEventEmitter, key, }) {
|
|
7
|
+
const events = initialEventEmitter !== null && initialEventEmitter !== void 0 ? initialEventEmitter : new EventEmitter();
|
|
8
|
+
const requestChannel = createRequestChannel(messageTransport);
|
|
9
|
+
requestChannel.handle('eventEmitted', (eventKey, eventName, payload) => {
|
|
10
|
+
if (eventKey === key)
|
|
11
|
+
events.emit(eventName, ...payload);
|
|
12
|
+
});
|
|
13
|
+
return events;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export { createEventEmitterForMessages };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './createEventEmitterForMessages';
|