@frak-labs/frame-connector 0.1.0-beta.afa252b0 → 0.1.0-beta.c7e026e5
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/dist/index-BSzskALu.d.cts +402 -0
- package/dist/index-Dpf6XGl9.d.ts +402 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +410 -837
- package/dist/index.d.ts +410 -837
- package/dist/index.js +1 -1
- package/dist/middleware-CgzGY8RV.cjs +1 -0
- package/dist/middleware-CzR6Oq6V.js +1 -0
- package/dist/middleware.cjs +1 -1
- package/dist/middleware.d.cts +2 -251
- package/dist/middleware.d.ts +2 -251
- package/dist/middleware.js +1 -1
- package/package.json +10 -13
|
@@ -0,0 +1,402 @@
|
|
|
1
|
+
import { Prettify } from "viem";
|
|
2
|
+
|
|
3
|
+
//#region src/rpc-schema.d.ts
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Generic shape of a single RPC schema entry
|
|
7
|
+
*
|
|
8
|
+
* Each entry defines a method with its parameters, return type, and response kind
|
|
9
|
+
*
|
|
10
|
+
* @typeParam TMethod - The method name (string literal)
|
|
11
|
+
* @typeParam TParams - The parameters type (can be undefined for no parameters)
|
|
12
|
+
* @typeParam TReturn - The return type
|
|
13
|
+
* @typeParam TResponseKind - Either "promise" or "stream"
|
|
14
|
+
*/
|
|
15
|
+
type RpcSchemaEntry<TMethod extends string = string, TParams = unknown, TReturn = unknown> = {
|
|
16
|
+
/**
|
|
17
|
+
* The method name (e.g., "frak_sendInteraction")
|
|
18
|
+
*/
|
|
19
|
+
Method: TMethod;
|
|
20
|
+
/**
|
|
21
|
+
* The parameters type (undefined if no parameters)
|
|
22
|
+
*/
|
|
23
|
+
Parameters?: TParams;
|
|
24
|
+
/**
|
|
25
|
+
* The return type
|
|
26
|
+
*/
|
|
27
|
+
ReturnType: TReturn;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* An RPC schema is a readonly array of schema entries
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```ts
|
|
34
|
+
* type MySchema = [
|
|
35
|
+
* {
|
|
36
|
+
* Method: "greet";
|
|
37
|
+
* Parameters: [name: string];
|
|
38
|
+
* ReturnType: string;
|
|
39
|
+
* ResponseType: "promise";
|
|
40
|
+
* },
|
|
41
|
+
* {
|
|
42
|
+
* Method: "watchTime";
|
|
43
|
+
* Parameters?: undefined;
|
|
44
|
+
* ReturnType: number;
|
|
45
|
+
* ResponseType: "stream";
|
|
46
|
+
* }
|
|
47
|
+
* ]
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
type RpcSchema = readonly RpcSchemaEntry[];
|
|
51
|
+
/**
|
|
52
|
+
* Extract method names from a schema
|
|
53
|
+
*
|
|
54
|
+
* @typeParam TSchema - The RPC schema type
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* ```ts
|
|
58
|
+
* type Methods = ExtractMethod<MySchema>
|
|
59
|
+
* // "greet" | "watchTime"
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
type ExtractMethod<TSchema extends RpcSchema> = TSchema[number]["Method"];
|
|
63
|
+
/**
|
|
64
|
+
* Extract a specific schema entry by method name
|
|
65
|
+
*
|
|
66
|
+
* @typeParam TSchema - The RPC schema type
|
|
67
|
+
* @typeParam TMethod - The method name to extract
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* ```ts
|
|
71
|
+
* type GreetEntry = ExtractSchemaEntry<MySchema, "greet">
|
|
72
|
+
* // { Method: "greet"; Parameters: [name: string]; ReturnType: string; ResponseType: "promise" }
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
75
|
+
type ExtractSchemaEntry<TSchema extends RpcSchema, TMethod extends ExtractMethod<TSchema>> = Extract<TSchema[number], {
|
|
76
|
+
Method: TMethod;
|
|
77
|
+
}>;
|
|
78
|
+
/**
|
|
79
|
+
* Extract parameters type for a specific method
|
|
80
|
+
*
|
|
81
|
+
* @typeParam TSchema - The RPC schema type
|
|
82
|
+
* @typeParam TMethod - The method name
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* ```ts
|
|
86
|
+
* type GreetParams = ExtractParams<MySchema, "greet">
|
|
87
|
+
* // [name: string]
|
|
88
|
+
* ```
|
|
89
|
+
*/
|
|
90
|
+
type ExtractParams<TSchema extends RpcSchema, TMethod extends ExtractMethod<TSchema>> = ExtractSchemaEntry<TSchema, TMethod>["Parameters"];
|
|
91
|
+
/**
|
|
92
|
+
* Type that extract the possible parameters from a RPC Schema
|
|
93
|
+
* @ignore
|
|
94
|
+
*/
|
|
95
|
+
type ExtractedParametersFromRpc<TRpcSchema extends RpcSchema> = { [K in keyof TRpcSchema]: Prettify<{
|
|
96
|
+
method: TRpcSchema[K] extends TRpcSchema[number] ? TRpcSchema[K]["Method"] : string;
|
|
97
|
+
} & (TRpcSchema[K] extends TRpcSchema[number] ? TRpcSchema[K]["Parameters"] extends undefined ? {
|
|
98
|
+
params?: never;
|
|
99
|
+
} : {
|
|
100
|
+
params: TRpcSchema[K]["Parameters"];
|
|
101
|
+
} : never)> }[number];
|
|
102
|
+
/**
|
|
103
|
+
* Type that extract the possible parameters from a RPC Schema
|
|
104
|
+
* @ignore
|
|
105
|
+
*/
|
|
106
|
+
type ExtractedSpecificParametersFromRpc<TRpcSchema extends RpcSchema, TMethod extends ExtractMethod<TRpcSchema>> = Extract<ExtractedParametersFromRpc<TRpcSchema>, {
|
|
107
|
+
method: TMethod;
|
|
108
|
+
}>;
|
|
109
|
+
/**
|
|
110
|
+
* Extract return type for a specific method
|
|
111
|
+
*
|
|
112
|
+
* @typeParam TSchema - The RPC schema type
|
|
113
|
+
* @typeParam TMethod - The method name
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* ```ts
|
|
117
|
+
* type GreetReturn = ExtractReturnType<MySchema, "greet">
|
|
118
|
+
* // string
|
|
119
|
+
* ```
|
|
120
|
+
*/
|
|
121
|
+
type ExtractReturnType<TSchema extends RpcSchema, TMethod extends ExtractMethod<TSchema>> = ExtractSchemaEntry<TSchema, TMethod>["ReturnType"];
|
|
122
|
+
//#endregion
|
|
123
|
+
//#region src/types.d.ts
|
|
124
|
+
/**
|
|
125
|
+
* Transport interface for RPC communication
|
|
126
|
+
* Abstracts the underlying message passing mechanism (postMessage, etc)
|
|
127
|
+
*/
|
|
128
|
+
type RpcTransport = {
|
|
129
|
+
/**
|
|
130
|
+
* Send a message through the transport
|
|
131
|
+
*/
|
|
132
|
+
postMessage: (message: RpcMessage, targetOrigin: string) => void;
|
|
133
|
+
/**
|
|
134
|
+
* Listen for messages
|
|
135
|
+
*/
|
|
136
|
+
addEventListener: (type: "message", listener: (event: MessageEvent<RpcMessage>) => void) => void;
|
|
137
|
+
/**
|
|
138
|
+
* Remove message listener
|
|
139
|
+
*/
|
|
140
|
+
removeEventListener: (type: "message", listener: (event: MessageEvent<RpcMessage>) => void) => void;
|
|
141
|
+
};
|
|
142
|
+
/**
|
|
143
|
+
* RPC message format (maintains backward compatibility)
|
|
144
|
+
* This is the exact format sent over the wire
|
|
145
|
+
*
|
|
146
|
+
* @typeParam TMethod - The method name type (defaults to string for flexibility)
|
|
147
|
+
*/
|
|
148
|
+
type RpcMessage<TMethod extends string = string> = {
|
|
149
|
+
/**
|
|
150
|
+
* Unique message identifier for correlating requests and responses
|
|
151
|
+
*/
|
|
152
|
+
id: string;
|
|
153
|
+
/**
|
|
154
|
+
* The RPC method name (topic for backward compatibility)
|
|
155
|
+
*/
|
|
156
|
+
topic: TMethod;
|
|
157
|
+
/**
|
|
158
|
+
* The message payload (compressed data) or raw params
|
|
159
|
+
*/
|
|
160
|
+
data: unknown;
|
|
161
|
+
};
|
|
162
|
+
/**
|
|
163
|
+
* Lifecycle message format for client-to-iframe communication
|
|
164
|
+
* These messages handle connection lifecycle events (handshake, heartbeat, etc.)
|
|
165
|
+
*/
|
|
166
|
+
type ClientLifecycleMessage = {
|
|
167
|
+
clientLifecycle: string;
|
|
168
|
+
data?: unknown;
|
|
169
|
+
};
|
|
170
|
+
/**
|
|
171
|
+
* Lifecycle message format for iframe-to-client communication
|
|
172
|
+
*/
|
|
173
|
+
type IFrameLifecycleMessage = {
|
|
174
|
+
iframeLifecycle: string;
|
|
175
|
+
data?: unknown;
|
|
176
|
+
};
|
|
177
|
+
/**
|
|
178
|
+
* Union of all lifecycle message types
|
|
179
|
+
*/
|
|
180
|
+
type LifecycleMessage = ClientLifecycleMessage | IFrameLifecycleMessage;
|
|
181
|
+
/**
|
|
182
|
+
* Union of all message types that can be received
|
|
183
|
+
*/
|
|
184
|
+
type AnyMessage = RpcMessage | LifecycleMessage;
|
|
185
|
+
/**
|
|
186
|
+
* RPC response wrapper
|
|
187
|
+
* Contains either a successful result or an error
|
|
188
|
+
*/
|
|
189
|
+
type RpcResponse<TResult = unknown> = {
|
|
190
|
+
result: TResult;
|
|
191
|
+
error?: never;
|
|
192
|
+
} | {
|
|
193
|
+
result?: never;
|
|
194
|
+
error: RpcError;
|
|
195
|
+
};
|
|
196
|
+
/**
|
|
197
|
+
* RPC error object
|
|
198
|
+
*/
|
|
199
|
+
type RpcError = {
|
|
200
|
+
code: number;
|
|
201
|
+
message: string;
|
|
202
|
+
data?: unknown;
|
|
203
|
+
};
|
|
204
|
+
/**
|
|
205
|
+
* Request context for handlers
|
|
206
|
+
* Contains information about the origin and source of the request
|
|
207
|
+
*/
|
|
208
|
+
type RpcRequestContext = {
|
|
209
|
+
/**
|
|
210
|
+
* Origin of the request
|
|
211
|
+
*/
|
|
212
|
+
origin: string;
|
|
213
|
+
/**
|
|
214
|
+
* Message source (for responding)
|
|
215
|
+
*/
|
|
216
|
+
source: MessageEventSource | null;
|
|
217
|
+
};
|
|
218
|
+
/**
|
|
219
|
+
* Middleware context that can be augmented with custom fields
|
|
220
|
+
* Generic type parameter allows domain-specific context augmentation
|
|
221
|
+
*
|
|
222
|
+
* @typeParam TCustomContext - Custom context fields to merge with base context
|
|
223
|
+
*
|
|
224
|
+
* @example
|
|
225
|
+
* ```ts
|
|
226
|
+
* type WalletContext = RpcMiddlewareContext<{
|
|
227
|
+
* productId: string
|
|
228
|
+
* sourceUrl: string
|
|
229
|
+
* isAutoContext: boolean
|
|
230
|
+
* }>
|
|
231
|
+
* // { origin: string, source: MessageEventSource | null, productId: string, sourceUrl: string, isAutoContext: boolean }
|
|
232
|
+
* ```
|
|
233
|
+
*/
|
|
234
|
+
type RpcMiddlewareContext<TCustomContext = Record<string, never>> = RpcRequestContext & TCustomContext;
|
|
235
|
+
/**
|
|
236
|
+
* Type-safe request parameters
|
|
237
|
+
*
|
|
238
|
+
* @typeParam TSchema - The RPC schema type
|
|
239
|
+
* @typeParam TMethod - The method name from the schema
|
|
240
|
+
*/
|
|
241
|
+
type TypedRpcRequest<TSchema extends RpcSchema, TMethod extends ExtractMethod<TSchema>> = {
|
|
242
|
+
method: TMethod;
|
|
243
|
+
params: ExtractParams<TSchema, TMethod>;
|
|
244
|
+
};
|
|
245
|
+
/**
|
|
246
|
+
* Stream emitter function
|
|
247
|
+
* Used by stream handlers to emit multiple values
|
|
248
|
+
*/
|
|
249
|
+
type StreamEmitter<TResult> = (chunk: TResult) => void;
|
|
250
|
+
/**
|
|
251
|
+
* Lifecycle handler function
|
|
252
|
+
* Handles lifecycle events using discriminated unions for automatic type narrowing
|
|
253
|
+
*
|
|
254
|
+
* @typeParam TLifecycleEvent - The lifecycle event union type (e.g., ClientLifecycleEvent | IFrameLifecycleEvent)
|
|
255
|
+
*
|
|
256
|
+
* @param event - The full lifecycle event object with discriminated union
|
|
257
|
+
* @param context - Request context with origin and source
|
|
258
|
+
*
|
|
259
|
+
* @example
|
|
260
|
+
* ```ts
|
|
261
|
+
* const handler: LifecycleHandler<ClientLifecycleEvent> = (event, context) => {
|
|
262
|
+
* if (event.clientLifecycle === "modal-css") {
|
|
263
|
+
* // event.data is automatically typed as { cssLink: string }
|
|
264
|
+
* console.log(event.data.cssLink)
|
|
265
|
+
* }
|
|
266
|
+
* }
|
|
267
|
+
* ```
|
|
268
|
+
*/
|
|
269
|
+
type LifecycleHandler<TLifecycleEvent = unknown> = (event: TLifecycleEvent, context: RpcRequestContext) => void | Promise<void>;
|
|
270
|
+
/**
|
|
271
|
+
* Unified middleware function for RPC requests (both listener and client)
|
|
272
|
+
* Works on both listener-side (with context augmentation) and client-side (empty context)
|
|
273
|
+
*
|
|
274
|
+
* Key features:
|
|
275
|
+
* - Can mutate message.data directly for efficiency (compression, validation)
|
|
276
|
+
* - Can mutate response.result directly for transformation
|
|
277
|
+
* - Listener-side: Can augment context by returning modified context
|
|
278
|
+
* - Client-side: Uses TContext = {} (empty context), always returns unchanged
|
|
279
|
+
*
|
|
280
|
+
* @typeParam TSchema - The RPC schema type
|
|
281
|
+
* @typeParam TContext - Custom context type to augment base context (empty {} for client-side)
|
|
282
|
+
*
|
|
283
|
+
* @example Listener-side with context augmentation
|
|
284
|
+
* ```ts
|
|
285
|
+
* type WalletContext = { productId: string, sourceUrl: string }
|
|
286
|
+
* const contextMiddleware: RpcMiddleware<MySchema, WalletContext> = {
|
|
287
|
+
* onRequest: async (message, context) => {
|
|
288
|
+
* // Read from store and augment context
|
|
289
|
+
* const productId = await getProductId(context.origin)
|
|
290
|
+
* return { ...context, productId, sourceUrl: context.origin }
|
|
291
|
+
* }
|
|
292
|
+
* }
|
|
293
|
+
* ```
|
|
294
|
+
*
|
|
295
|
+
* @example Client-side (empty context)
|
|
296
|
+
* ```ts
|
|
297
|
+
* const compressionMiddleware: RpcMiddleware<MySchema> = {
|
|
298
|
+
* onRequest: async (message, context) => {
|
|
299
|
+
* // Mutate message.data directly
|
|
300
|
+
* message.data = compress(message.data)
|
|
301
|
+
* return context // Empty context, unchanged
|
|
302
|
+
* },
|
|
303
|
+
* onResponse: async (message, response, context) => {
|
|
304
|
+
* // Mutate response.result directly
|
|
305
|
+
* response.result = decompress(response.result)
|
|
306
|
+
* return response
|
|
307
|
+
* }
|
|
308
|
+
* }
|
|
309
|
+
* ```
|
|
310
|
+
*
|
|
311
|
+
* @example Shared middleware (works on both sides)
|
|
312
|
+
* ```ts
|
|
313
|
+
* const loggingMiddleware: RpcMiddleware<MySchema> = {
|
|
314
|
+
* onRequest: async (message, context) => {
|
|
315
|
+
* console.log(`[RPC] ${message.topic}`, context.origin || 'client')
|
|
316
|
+
* return context
|
|
317
|
+
* },
|
|
318
|
+
* onResponse: async (message, response, context) => {
|
|
319
|
+
* console.log(`[RPC] ${message.topic} completed`)
|
|
320
|
+
* return response
|
|
321
|
+
* }
|
|
322
|
+
* }
|
|
323
|
+
* ```
|
|
324
|
+
*/
|
|
325
|
+
type RpcMiddleware<TSchema extends RpcSchema, TContext = Record<string, never>> = {
|
|
326
|
+
/**
|
|
327
|
+
* Called before handler execution (listener) or before sending (client)
|
|
328
|
+
*
|
|
329
|
+
* For listener: Can augment context and mutate message
|
|
330
|
+
* For client: Can mutate message, context is empty {}
|
|
331
|
+
*
|
|
332
|
+
* @param message - The RPC message (can be mutated)
|
|
333
|
+
* @param context - Request context (listener-side) or empty (client-side)
|
|
334
|
+
* @returns Updated context (listener mutates this, client returns unchanged)
|
|
335
|
+
* @throws FrakRpcError to reject the request with a specific error code
|
|
336
|
+
*/
|
|
337
|
+
onRequest?: (message: RpcMessage<ExtractMethod<TSchema>>, context: RpcMiddlewareContext<TContext>) => Promise<RpcMiddlewareContext<TContext>> | RpcMiddlewareContext<TContext>;
|
|
338
|
+
/**
|
|
339
|
+
* Called after handler execution (listener) or after receiving (client)
|
|
340
|
+
*
|
|
341
|
+
* @param message - The original RPC message
|
|
342
|
+
* @param response - The response (can be mutated)
|
|
343
|
+
* @param context - Request context (listener-side) or empty (client-side)
|
|
344
|
+
* @returns Transformed response
|
|
345
|
+
* @throws Error to send an error response instead
|
|
346
|
+
*/
|
|
347
|
+
onResponse?: (message: RpcMessage<ExtractMethod<TSchema>>, response: RpcResponse, context: RpcMiddlewareContext<TContext>) => Promise<RpcResponse> | RpcResponse;
|
|
348
|
+
};
|
|
349
|
+
/**
|
|
350
|
+
* Promise handler function type
|
|
351
|
+
* Handles one-shot requests that return a single promise
|
|
352
|
+
*
|
|
353
|
+
* @typeParam TSchema - The RPC schema type
|
|
354
|
+
* @typeParam TMethod - The method name from the schema
|
|
355
|
+
* @typeParam TContext - Custom context type augmented by middleware
|
|
356
|
+
*/
|
|
357
|
+
type RpcPromiseHandler<TSchema extends RpcSchema, TMethod extends ExtractMethod<TSchema>, TContext = Record<string, never>> = (params: ExtractParams<TSchema, TMethod>, context: RpcMiddlewareContext<TContext>) => Promise<ExtractReturnType<TSchema, TMethod>>;
|
|
358
|
+
/**
|
|
359
|
+
* Stream handler function type
|
|
360
|
+
* Handles streaming requests that can emit multiple values
|
|
361
|
+
*
|
|
362
|
+
* @typeParam TSchema - The RPC schema type
|
|
363
|
+
* @typeParam TMethod - The method name from the schema
|
|
364
|
+
* @typeParam TContext - Custom context type augmented by middleware
|
|
365
|
+
*/
|
|
366
|
+
type RpcStreamHandler<TSchema extends RpcSchema, TMethod extends ExtractMethod<TSchema>, TContext = Record<string, never>> = (params: ExtractParams<TSchema, TMethod>, emitter: StreamEmitter<ExtractReturnType<TSchema, TMethod>>, context: RpcMiddlewareContext<TContext>) => Promise<void> | void;
|
|
367
|
+
//#endregion
|
|
368
|
+
//#region src/middleware/compression.d.ts
|
|
369
|
+
/**
|
|
370
|
+
* Client-side compression middleware
|
|
371
|
+
*
|
|
372
|
+
* Compresses outgoing requests and decompresses incoming responses.
|
|
373
|
+
* Always uses the format: {method: string, params: unknown}
|
|
374
|
+
*
|
|
375
|
+
* @example Client side
|
|
376
|
+
* ```ts
|
|
377
|
+
* const client = createRpcClient({
|
|
378
|
+
* transport: iframe.contentWindow,
|
|
379
|
+
* targetOrigin: 'https://wallet.frak.id',
|
|
380
|
+
* middleware: [createClientCompressionMiddleware()]
|
|
381
|
+
* })
|
|
382
|
+
* ```
|
|
383
|
+
*/
|
|
384
|
+
declare const createClientCompressionMiddleware: <TSchema extends RpcSchema, TContext>() => RpcMiddleware<TSchema, TContext>;
|
|
385
|
+
/**
|
|
386
|
+
* Listener-side compression middleware
|
|
387
|
+
*
|
|
388
|
+
* Decompresses incoming requests and compresses outgoing responses.
|
|
389
|
+
* Always uses the format: {method: string, params: unknown}
|
|
390
|
+
*
|
|
391
|
+
* @example Listener side
|
|
392
|
+
* ```ts
|
|
393
|
+
* const listener = createRpcListener({
|
|
394
|
+
* transport: window,
|
|
395
|
+
* allowedOrigins: ['https://example.com'],
|
|
396
|
+
* middleware: [createListenerCompressionMiddleware()]
|
|
397
|
+
* })
|
|
398
|
+
* ```
|
|
399
|
+
*/
|
|
400
|
+
declare const createListenerCompressionMiddleware: <TSchema extends RpcSchema, TContext>() => RpcMiddleware<TSchema, TContext>;
|
|
401
|
+
//#endregion
|
|
402
|
+
export { ExtractedParametersFromRpc as C, RpcSchemaEntry as E, ExtractSchemaEntry as S, RpcSchema as T, StreamEmitter as _, IFrameLifecycleMessage as a, ExtractParams as b, RpcError as c, RpcMiddlewareContext as d, RpcPromiseHandler as f, RpcTransport as g, RpcStreamHandler as h, ClientLifecycleMessage as i, RpcMessage as l, RpcResponse as m, createListenerCompressionMiddleware as n, LifecycleHandler as o, RpcRequestContext as p, AnyMessage as r, LifecycleMessage as s, createClientCompressionMiddleware as t, RpcMiddleware as u, TypedRpcRequest as v, ExtractedSpecificParametersFromRpc as w, ExtractReturnType as x, ExtractMethod as y };
|