@onting/rpc 0.0.0-0 → 0.1.0-main.202606142104.1d538a8
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/LICENSE +21 -0
- package/README.md +0 -0
- package/dist/{client.mjs → client.js} +1 -1
- package/dist/{client.mjs.map → client.js.map} +1 -1
- package/dist/index.js +1 -0
- package/dist/{server.d.mts → server.d.ts} +1 -1
- package/dist/{server.mjs → server.js} +2 -2
- package/package.json +20 -6
- package/dist/index.mjs +0 -1
- package/dist/rpc.d.mts +0 -2
- package/dist/rpc.d.ts +0 -2
- package/dist/rpc.js +0 -5
- package/dist/rpc.js.map +0 -1
- package/dist/rpc.mjs +0 -3
- package/dist/rpc.mjs.map +0 -1
- /package/dist/{client.d.mts → client.d.ts} +0 -0
- /package/dist/{index.d.mts → index.d.ts} +0 -0
- /package/dist/{index.mjs.map → index.js.map} +0 -0
- /package/dist/{server.mjs.map → server.js.map} +0 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) William Wong
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
File without changes
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../node_modules/workthru/src/workthru.ts","../../../node_modules/message-port-rpc/src/isTransferable.ts","../../../node_modules/message-port-rpc/src/getAllTransfer.ts","../../../node_modules/message-port-rpc/src/messagePortRPC.ts","../../../node_modules/message-port-rpc/src/forGenerator.ts","../src/client/createClientStub.ts"],"sourcesContent":["/**\n * Internal recursive helper for {@link workthru}.\n *\n * For arrays and plain objects, calls transformer first. If transformer returns the same reference,\n * recursively walks children and rebuilds the container only when a child changes (structural sharing).\n * Class instances, primitives, functions, and null are passed directly to transformer without recursion.\n *\n * The `walked` map tracks already-visited nodes to handle circular references and avoid duplicate work.\n *\n * @param target - Value to transform.\n * @param transformer - Called on every visited value; return the original value to recurse into children.\n * @param walked - Cycle-detection map from original value to its transformed counterpart.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction workthru_(target: any, transformer: (value: any) => any, walked: Map<any, any>): any {\n if (Array.isArray(target)) {\n if (walked.has(target)) {\n return walked.get(target);\n }\n\n let nextArray = transformer(target);\n\n if (nextArray !== target) {\n walked.set(target, nextArray);\n\n return nextArray;\n }\n\n walked.set(target, target);\n\n // for-in loop can handle sparse array.\n for (const index in target) {\n const value = target[index];\n const nextValue = workthru_(value, transformer, walked);\n\n if (nextValue !== value) {\n if (nextArray === target) {\n nextArray = [...target];\n }\n\n nextArray[index] = nextValue;\n }\n }\n\n walked.set(target, nextArray);\n\n return nextArray;\n }\n\n if (typeof target === 'object' && target !== null) {\n if (walked.has(target)) {\n return walked.get(target);\n }\n\n const prototype = Object.getPrototypeOf(target);\n\n if (prototype === null || prototype === Object.prototype) {\n const nextTarget = transformer(target);\n\n if (nextTarget !== target) {\n walked.set(target, nextTarget);\n\n return nextTarget;\n }\n\n walked.set(target, target);\n\n const entries = Object.entries(target);\n let nextMap = undefined;\n\n for (const [key, value] of entries) {\n const nextValue = workthru_(value, transformer, walked);\n\n if (nextValue !== value) {\n if (!nextMap) {\n nextMap = new Map(entries);\n }\n\n nextMap.set(key, nextValue);\n }\n }\n\n const nextObject = nextMap ? Object.fromEntries(nextMap.entries()) : target;\n\n walked.set(target, nextObject);\n\n return nextObject;\n }\n }\n\n return transformer(target);\n}\n\n/**\n * Recursively walks the input in a depth-first search manner and transforms value as needed.\n *\n * Every traversed value will be passed to the `transformer` function.\n *\n * - If the `transformer` return the original value, the traversal for this branch will be continued\n * - If the `transformer` return a new value, the traversal for this branch will be ended\n *\n * The following data types are supported:\n *\n * - boolean, number, string\n * - array will be transformed on itself and every of the element\n * - plain object will be transformed on itself and every of its member value\n *\n * Notes:\n *\n * - Values with unsupported will be kept as-is;\n * - Values that are not transformed will be kept as-is\n *\n * @param target - The value to be worked through\n * @param transformer - The function to transform the value\n * @returns - The transformed value if the input has been transformed, otherwise, return the original value\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction workthru(target: any, transformer: (value: any) => any): any {\n return workthru_(target, transformer, new Map());\n}\n\nexport default workthru;\n","function isArrayBuffer(value: unknown): value is ArrayBuffer {\n return !!('ArrayBuffer' in globalThis) && value instanceof ArrayBuffer;\n}\n\nfunction isAudioData(value: unknown): value is AudioData {\n return !!('AudioData' in globalThis) && value instanceof AudioData;\n}\n\nfunction isImageBitmap(value: unknown): value is ImageBitmap {\n return !!('ImageBitmap' in globalThis) && value instanceof ImageBitmap;\n}\n\nfunction isMediaSourceHandle(value: unknown): value is MediaSourceHandle {\n return !!('MediaSourceHandle' in globalThis) && value instanceof MediaSourceHandle;\n}\n\nfunction isMediaStreamTrack(value: unknown): value is MediaStreamTrack {\n return !!('MediaStreamTrack' in globalThis) && value instanceof MediaStreamTrack;\n}\n\nfunction isMessagePort(value: unknown): value is MessagePort {\n return !!('MessagePort' in globalThis) && value instanceof MessagePort;\n}\n\nfunction isMIDIAccess(value: unknown): value is MIDIAccess {\n return !!('MIDIAccess' in globalThis) && value instanceof MIDIAccess;\n}\n\nfunction isOffscreenCanvas(value: unknown): value is OffscreenCanvas {\n return !!('OffscreenCanvas' in globalThis) && value instanceof OffscreenCanvas;\n}\n\nfunction isReadableStream(value: unknown): value is ReadableStream {\n return !!('ReadableStream' in globalThis) && value instanceof ReadableStream;\n}\n\nfunction isRTCDataChannel(value: unknown): value is RTCDataChannel {\n return !!('RTCDataChannel' in globalThis) && value instanceof RTCDataChannel;\n}\n\nfunction isTransformStream(value: unknown): value is TransformStream {\n return !!('TransformStream' in globalThis) && value instanceof TransformStream;\n}\n\nfunction isVideoFrame(value: unknown): value is VideoFrame {\n return !!('VideoFrame' in globalThis) && value instanceof VideoFrame;\n}\n\nfunction isWebTransportReceiveStream(value: unknown): boolean {\n return (\n !!(\n (\n 'WebTransportReceiveStream' in globalThis &&\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n typeof (globalThis as any)['WebTransportReceiveStream'] === 'function'\n )\n // @ts-expect-error WebTransportReceiveStream is not in TypeScript yet\n ) && value instanceof globalThis.WebTransportReceiveStream\n );\n}\n\nfunction isWebTransportSendStream(value: unknown): boolean {\n return (\n !!(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ('WebTransportSendStream' in globalThis && typeof (globalThis as any)['WebTransportSendStream'] === 'function')\n // @ts-expect-error WebTransportSendStream is not in TypeScript yet\n ) && value instanceof globalThis.WebTransportSendStream\n );\n}\n\nfunction isWritableStream(value: unknown): value is WritableStream {\n return !!('WritableStream' in globalThis) && value instanceof WritableStream;\n}\n\nfunction isTransferable(value: unknown): boolean {\n return (\n isArrayBuffer(value) ||\n isAudioData(value) ||\n isImageBitmap(value) ||\n isMediaSourceHandle(value) ||\n isMediaStreamTrack(value) ||\n isMessagePort(value) ||\n isMIDIAccess(value) ||\n isOffscreenCanvas(value) ||\n isReadableStream(value) ||\n isRTCDataChannel(value) ||\n isTransformStream(value) ||\n isVideoFrame(value) ||\n isWebTransportReceiveStream(value) ||\n isWebTransportSendStream(value) ||\n isWritableStream(value)\n );\n}\n\nexport default isTransferable;\n","import { workthru } from 'workthru';\nimport isTransferable from './isTransferable.ts';\n\nexport default function getAllTransfer(data: unknown): Transferable[] {\n const transferSet = new Set<Transferable>();\n\n workthru(data, value => {\n if (isTransferable(value)) {\n transferSet.add(value as Transferable);\n }\n\n return value;\n });\n\n return Array.from(transferSet);\n}\n","// Naming is from https://www.w3.org/History/1992/nfs_dxcern_mirror/rpc/doc/Introduction/HowItWorks.html.\n\nimport getAllTransfer from './getAllTransfer.ts';\nimport type { CallInit, ClientStub, ServerStub, Subroutine } from './types.ts';\n\nconst ABORT = 'ABORT';\nconst CALL = 'CALL';\nconst REJECT = 'REJECT';\nconst RESOLVE = 'RESOLVE';\n\ntype RPCCallMessage<T extends Subroutine> = [typeof CALL, ...Parameters<T>];\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype RPCRejectMessage = [typeof REJECT, any];\ntype RPCResolveMessage<T extends Subroutine> = [typeof RESOLVE, Awaited<ReturnType<T>>];\n\n/**\n * Binds a function to a `MessagePort` in RPC fashion and/or create a RPC function stub connected to a `MessagePort`.\n *\n * In a traditional RPC setting:\n *\n * - server should call this function with `fn` argument, the returned function should be ignored;\n * - client should call this function without `fn` argument, the returned function is the stub to call the server.\n *\n * This function supports bidirectional RPC when both sides are passing the `fn` argument.\n *\n * When calling the returned function stub, the arguments and return value are sent over `MessagePort`.\n * They would be sent by the underlying structured clone algorithm provided by the `MessagePort` implementation.\n * Transferable are auto-populated and will be passed to `MessagePort.postMessage` call.\n *\n * The returned stub has a variant `withOptions` for passing abort signal.\n *\n * @param {MessagePort} port - The `MessagePort` object to send the calls. The underlying `MessageChannel` must be exclusively used by this function only.\n * @param {Function} fn - The function to invoke. If not set, this RPC cannot be invoked by the other side of `MessagePort`.\n *\n * @returns An asynchronous function, when called, will invoke the function on the other side of `MessagePort`.\n */\nfunction messagePortRPC<C extends Subroutine>(port: MessagePort): ClientStub<C>;\n\nfunction messagePortRPC<C extends Subroutine, S extends Subroutine = C>(\n port: MessagePort,\n fn: ServerStub<S>\n): ClientStub<C>;\n\nfunction messagePortRPC<C extends Subroutine, S extends Subroutine = C>(\n port: MessagePort,\n fn: ServerStub<S>,\n options: { signal: AbortSignal }\n): ClientStub<C>;\n\nfunction messagePortRPC<C extends Subroutine, S extends Subroutine = C>(\n port: MessagePort,\n fn?: ServerStub<S>\n): ClientStub<C> {\n // We cannot neuter the input port because it would cause memory leak:\n // - We can neuter a port by passing it through Structured Clone Algorithm so the input port will become non-functional\n // - After a port is neutered, closing the neutered port will not close the cloned port\n // - Thus, the port owner will no longer able to close the port\n // - This defeated our philosophy: whoever pass a resources to a function, should own the resources unless it is intentional and no other workarounds\n\n type ClientSubroutineParameters = Parameters<C>;\n type ClientSubroutineReturnValue = Awaited<ReturnType<C>>;\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const handleMessage = (event: MessageEvent<RPCCallMessage<S>>): void => {\n const data = event.data as RPCCallMessage<S> | undefined;\n\n if (Array.isArray(data) && data[0] === CALL) {\n event.stopImmediatePropagation();\n\n const [returnPort] = event.ports;\n\n if (!returnPort) {\n throw new Error('RPCCallMessage must contains a port.');\n }\n\n if (fn) {\n (async () => {\n const abortController = new AbortController();\n\n try {\n returnPort.onmessage = ({ data }) => Array.isArray(data) && data[0] === ABORT && abortController.abort();\n\n const result = await fn.call({ signal: abortController.signal }, ...(data.slice(1) as Parameters<S>));\n\n returnPort.postMessage([RESOLVE, result], getAllTransfer(result));\n } catch (error) {\n returnPort.postMessage([REJECT, error]);\n } finally {\n returnPort.close();\n }\n })();\n } else {\n returnPort.postMessage([\n REJECT,\n new Error(\n 'No function was registered on this RPC. This is probably calling a client which do not implement the function.'\n )\n ]);\n returnPort.close();\n }\n }\n };\n\n port.addEventListener('message', handleMessage);\n port.start();\n\n const createWithOptions =\n (init: CallInit): ((...args: ClientSubroutineParameters) => Promise<ClientSubroutineReturnValue>) =>\n (...args) => {\n return new Promise<ClientSubroutineReturnValue>((resolve, reject) => {\n const { port1, port2 } = new MessageChannel();\n\n port1.onmessage = event => {\n const data = event.data as RPCRejectMessage | RPCResolveMessage<C>;\n\n if (data[0] === RESOLVE) {\n resolve(data[1]);\n } else {\n reject(data[1]);\n }\n\n port1.close();\n };\n\n init?.signal?.addEventListener('abort', () => {\n port1.postMessage([ABORT]);\n port1.close();\n\n reject(new Error('Aborted.'));\n });\n\n const transfer = getAllTransfer(args);\n\n port.postMessage([CALL, ...args] satisfies RPCCallMessage<C>, [port2, ...transfer]);\n });\n };\n\n const stub = createWithOptions({}) as ClientStub<C>;\n\n stub.withOptions = createWithOptions;\n\n return stub;\n}\n\nexport default messagePortRPC;\n","// Naming is from https://www.w3.org/History/1992/nfs_dxcern_mirror/rpc/doc/Introduction/HowItWorks.html.\n\nimport messagePortRPC from './messagePortRPC.ts';\n\nconst GENERATE = 'GENERATOR_GENERATE';\n\ntype ClientDisposeReason = 'abort' | 'dispose' | 'done';\n\n// type GeneratorSubroutine<TArgs extends unknown[] = any[], T = unknown, TReturn = any, TNext = unknown> = (\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype GeneratorSubroutine = (...args: any[]) => AsyncGenerator | Generator | AsyncIterator<unknown> | Iterator<unknown>;\ntype RPCGeneratorGenerateMessage<T extends GeneratorSubroutine> = [\n typeof GENERATE,\n Readonly<{\n asyncDispose: MessagePort;\n next: MessagePort;\n return: MessagePort;\n throw: MessagePort;\n }>,\n ...Parameters<T>\n];\n\ntype CallInit = {\n signal?: AbortSignal;\n transfer?: Transferable[];\n};\n\ntype NextOfGenerator<T extends AsyncGenerator | Generator | AsyncIterator<unknown> | Iterator<unknown>> =\n T extends AsyncGenerator<unknown, unknown, infer U> ? U : T extends Generator<unknown, unknown, infer V> ? V : never;\ntype ReturnOfGenerator<T extends AsyncGenerator | Generator | AsyncIterator<unknown> | Iterator<unknown>> =\n T extends AsyncGenerator<unknown, infer U> ? U : T extends Generator<unknown, infer V> ? V : never;\ntype YieldOfGenerator<T extends AsyncGenerator | Generator | AsyncIterator<unknown> | Iterator<unknown>> =\n T extends AsyncGenerator<infer U>\n ? U\n : T extends Generator<infer U>\n ? U\n : T extends AsyncIterator<infer U>\n ? U\n : T extends Iterator<infer U>\n ? U\n : never;\n\n// Regardless whether T returns Promise or not, the client stub must return Promise.\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype ClientGeneratorStub<T extends GeneratorSubroutine> = (\n ...args: Parameters<T>\n) => AsyncGenerator<YieldOfGenerator<ReturnType<T>>, ReturnOfGenerator<ReturnType<T>>, NextOfGenerator<ReturnType<T>>>;\n\ntype ClientGeneratorStubWithExtra<T extends GeneratorSubroutine> = ClientGeneratorStub<T> & {\n /**\n * Creates a new stub with options.\n *\n * @param {AbortSignal} init.signal - Abort signal to abort the call to the stub.\n * @param {Transferable[]} init.transfer - Transfer ownership of objects specified in `args`.\n */\n withOptions: (init: CallInit) => ClientGeneratorStub<T>;\n};\n\ntype ServerStub<T extends GeneratorSubroutine> = (...args: Parameters<T>) => ReturnType<T>;\n\n/**\n * Binds a generator function to a `MessagePort` in RPC fashion and/or create a RPC function stub connected to a `MessagePort`.\n *\n * In a traditional RPC setting:\n *\n * - server should call this generator function with `fn` argument, the returned function should be ignored;\n * - client should call this generator function without `fn` argument, the returned function is the stub to call the server.\n *\n * This function supports bidirectional RPC when both sides are passing the `fn` argument.\n *\n * When calling the returned function stub, the arguments and return value are transferred over `MessagePort`.\n * Thus, they will be cloned by the underlying structured clone algorithm.\n *\n * The returned stub has a variant `withOptions` for passing transferables and abort signal.\n *\n * Notes: if `next()` is used on the client stub and did not iterate until `{ done: true }`, caller must use the `withOptions({ signal: AbortSignal })`\n * to release resources.\n *\n * @param {MessagePort} port - The `MessagePort` object to send the calls. The underlying `MessageChannel` must be exclusively used by this function only.\n * @param {Function} fn - The generator function to invoke. If not set, this RPC cannot be invoked by the other side of `MessagePort`.\n *\n * @returns An asynchronous generator function, when called, will invoke the generator function on the other side of `MessagePort`.\n */\nexport default function forGenerator<C extends GeneratorSubroutine>(port: MessagePort): ClientGeneratorStubWithExtra<C>;\n\nexport default function forGenerator<C extends GeneratorSubroutine, S extends GeneratorSubroutine = C>(\n port: MessagePort,\n fn: ServerStub<S>\n): ClientGeneratorStubWithExtra<C>;\n\nexport default function forGenerator<C extends GeneratorSubroutine, S extends GeneratorSubroutine = C>(\n port: MessagePort,\n fn: ServerStub<S>,\n options: { signal: AbortSignal }\n): ClientGeneratorStubWithExtra<C>;\n\nexport default function forGenerator<C extends GeneratorSubroutine, S extends GeneratorSubroutine = C>(\n port: MessagePort,\n fn?: ServerStub<S>\n): ClientGeneratorStubWithExtra<C> {\n // We cannot neuter the input port because it would cause memory leak:\n // - We can neuter a port by passing it through Structured Clone Algorithm so the input port will become non-functional\n // - After a port is neutered, closing the neutered port will not close the cloned port\n // - Thus, the port owner will no longer able to close the port\n // - This defeated our philosophy: whoever pass a resources to a function, should own the resources unless it is intentional and no other workarounds\n\n type ClientSubroutineParameters = Parameters<C>;\n type ClientSubroutineYield = YieldOfGenerator<ReturnType<C>>;\n type ClientSubroutineReturn = ReturnOfGenerator<ReturnType<C>>;\n type ClientSubroutineNext = NextOfGenerator<ReturnType<C>>;\n type ClientSubroutineIteratorResult = IteratorResult<ClientSubroutineYield, ClientSubroutineReturn>;\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const handleMessage = (event: MessageEvent<RPCGeneratorGenerateMessage<S>>): void => {\n const data = event.data as RPCGeneratorGenerateMessage<S> | undefined;\n\n if (Array.isArray(data) && data[0] === GENERATE) {\n event.stopImmediatePropagation();\n\n const [_, messagePorts, ...args] = data;\n\n const serverClosePorts = () => {\n messagePorts.asyncDispose.close();\n messagePorts.next.close();\n messagePorts.return.close();\n messagePorts.throw.close();\n };\n\n if (!fn) {\n // TODO: Throwing exception in onMessage is no-op, need to fix.\n console.warn(\n '`message-port-rpc`: No function was registered on this RPC. This is probably calling a client which do not implement the function.'\n );\n\n serverClosePorts();\n\n return;\n }\n\n const generator = fn(...args);\n\n messagePortRPC(messagePorts.next, async (...args: ClientSubroutineNext) => {\n const result = await generator.next(...args);\n\n // Automatically close server ports when iteration is done.\n // Client will fake the next()/return()/throw() output after iteration is done.\n result.done && serverClosePorts();\n\n return result;\n });\n\n // This is a slight deviation from the actual `Iterator`.\n // In the original approach, `Iterator.return` is not defined.\n // In our approach, the client stub does not know if the server stub has `Iterator.return` defined or not, instead, we simply return `{ done: true }`.\n messagePortRPC(messagePorts.return, async value => {\n return (await generator.return?.(value)) ?? { done: true };\n });\n\n messagePortRPC(messagePorts.throw, async error => {\n return (await generator.throw?.(error)) ?? Promise.reject(error);\n });\n\n messagePortRPC(messagePorts.asyncDispose, async (): Promise<void> => {\n try {\n const symbolAsyncDispose: typeof Symbol.asyncDispose =\n Symbol.asyncDispose || Symbol.for('Symbol.asyncDispose');\n const symbolDispose: typeof Symbol.dispose = Symbol.dispose || Symbol.for('Symbol.dispose');\n\n symbolAsyncDispose in generator\n ? await generator[symbolAsyncDispose]()\n : symbolDispose in generator && generator[symbolDispose]();\n } finally {\n serverClosePorts();\n }\n });\n }\n };\n\n port.addEventListener('message', handleMessage);\n port.start();\n\n const createWithOptions = (\n init: CallInit\n ): ((\n ...args: ClientSubroutineParameters\n ) => AsyncGenerator<ClientSubroutineYield, ClientSubroutineReturn, ClientSubroutineNext>) => {\n return (...args: ClientSubroutineParameters) => {\n const { port1: asyncDisposePort1, port2: asyncDisposePort2 } = new MessageChannel();\n const { port1: nextPort1, port2: nextPort2 } = new MessageChannel();\n const { port1: returnPort1, port2: returnPort2 } = new MessageChannel();\n const { port1: throwPort1, port2: throwPort2 } = new MessageChannel();\n\n const subInit = { signal: init.signal };\n\n const asyncDisposeRPC = messagePortRPC<() => void>(asyncDisposePort1).withOptions(subInit);\n\n const nextRPC =\n messagePortRPC<(next: ClientSubroutineNext | void) => ClientSubroutineIteratorResult>(nextPort1).withOptions(\n subInit\n );\n\n const returnRPC =\n messagePortRPC<(returnValue: ClientSubroutineReturn) => ClientSubroutineIteratorResult>(\n returnPort1\n ).withOptions(subInit);\n\n const throwRPC =\n messagePortRPC<(error: unknown) => ClientSubroutineIteratorResult>(throwPort1).withOptions(subInit);\n\n const callAsyncDispose = async (disposeReason: ClientDisposeReason) => {\n if (isDone(false)) {\n return;\n }\n\n // AsyncDispose has never been called.\n if (disposeReason === 'abort' || disposeReason === 'dispose') {\n // Only call server for AsyncDispose if the user intentionally abort or dispose.\n // Otherwise, the server-side object should have already disposed due to \"done\" and \"error\".\n await asyncDisposeRPC();\n }\n\n if (disposeReason === 'done') {\n isDone = () => true;\n } else {\n disposeReason satisfies 'abort' | 'dispose';\n\n isDone = (throwOnDispose = true) => {\n if (throwOnDispose === true) {\n // Already disposed, the MessagePort are all closed, return previous result.\n throw new Error('This generator has been disposed.');\n }\n\n return true;\n };\n }\n\n asyncDisposePort1.close();\n asyncDisposePort2.close();\n nextPort1.close();\n nextPort2.close();\n returnPort1.close();\n returnPort2.close();\n throwPort1.close();\n throwPort2.close();\n };\n\n let isDone: (throwOnDispose?: boolean | undefined) => boolean = () => false;\n\n const generator: AsyncGenerator<ClientSubroutineYield, ClientSubroutineReturn, ClientSubroutineNext> = {\n next: async (value: NextOfGenerator<ReturnType<C>> | void) => {\n if (isDone()) {\n // Return type of any generators should allow `undefined`.\n // For example, after the generator is exhausted, the return value will be `undefined`.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return { done: true, value: undefined } satisfies IteratorReturnResult<undefined> as any;\n }\n\n const result = await nextRPC(value);\n\n if (result.done) {\n await callAsyncDispose('done');\n }\n\n return result;\n },\n return: async (value: ReturnOfGenerator<ReturnType<C>>) => {\n if (isDone()) {\n return { done: true, value };\n }\n\n return await returnRPC(value);\n },\n throw: async (error: unknown) => {\n if (isDone()) {\n throw error;\n }\n\n return await throwRPC(error);\n },\n // Ponyfills for Symbol.asyncDispose\n [Symbol.asyncDispose || Symbol.for('Symbol.asyncDispose')]: async () => {\n await callAsyncDispose('dispose');\n },\n [Symbol.asyncIterator]: () => generator\n };\n\n port.postMessage(\n [\n GENERATE,\n { asyncDispose: asyncDisposePort2, next: nextPort2, return: returnPort2, throw: throwPort2 },\n ...args\n ] satisfies RPCGeneratorGenerateMessage<C>,\n [...(init.transfer || []), asyncDisposePort2, nextPort2, returnPort2, throwPort2]\n );\n\n init.signal?.addEventListener('abort', () => callAsyncDispose('abort').catch(() => {}), { once: true });\n\n return generator;\n };\n };\n\n const stub = createWithOptions({}) as ClientGeneratorStubWithExtra<C>;\n\n stub.withOptions = createWithOptions;\n\n return stub;\n}\n","import { messagePortRPC as rpc } from 'message-port-rpc';\nimport type { InferClient } from '../types/internal/InferClient.ts';\nimport type { InferHandshake } from '../types/internal/InferHandshake.ts';\nimport type { StubDeclaration } from '../types/StubDeclaration.ts';\nimport type { StubImplementation } from '../types/StubImplementation.ts';\n\nfunction lazyStub<TArgs extends unknown[], TSyncReturn extends unknown>(\n fnFactory: () => Promise<(...args: TArgs) => Promise<TSyncReturn>>\n): (...args: TArgs) => Promise<TSyncReturn> {\n let fnPromise: Promise<(...args: TArgs) => Promise<TSyncReturn>> | undefined;\n\n return async (...args) => (await (fnPromise ?? (fnPromise = fnFactory())))(...args);\n}\n\nfunction createClientStub<T extends StubDeclaration<S>, S extends StubImplementation>(\n declaration: Pick<T, 'keys'>,\n messagePort: MessagePort\n): InferClient<S> {\n type Handshake = InferHandshake<S>;\n\n const clientStubMap = new Map<keyof S, (...args: unknown[]) => Promise<unknown>>();\n const handshakePromise = rpc<() => Handshake>(messagePort)();\n\n for (const key of declaration.keys) {\n clientStubMap.set(\n key,\n lazyStub(async () => rpc((await handshakePromise)[key]))\n );\n }\n\n return Object.fromEntries(clientStubMap.entries()) satisfies Record<\n string,\n (...args: unknown[]) => Promise<unknown>\n // TODO: We should not use \"as unknown\".\n > as unknown as InferClient<S>;\n}\n\nexport default createClientStub;\n"],"mappings":";AAcA,SAAS,UAAU,QAAa,aAAkC,QAA4B;AAC5F,MAAI,MAAM,QAAQ,MAAM,GAAG;AACzB,QAAI,OAAO,IAAI,MAAM,GAAG;AACtB,aAAO,OAAO,IAAI,MAAM;IAC1B;AAEA,QAAI,YAAY,YAAY,MAAM;AAElC,QAAI,cAAc,QAAQ;AACxB,aAAO,IAAI,QAAQ,SAAS;AAE5B,aAAO;IACT;AAEA,WAAO,IAAI,QAAQ,MAAM;AAGzB,eAAW,SAAS,QAAQ;AAC1B,YAAM,QAAQ,OAAO,KAAK;AAC1B,YAAM,YAAY,UAAU,OAAO,aAAa,MAAM;AAEtD,UAAI,cAAc,OAAO;AACvB,YAAI,cAAc,QAAQ;AACxB,sBAAY,CAAC,GAAG,MAAM;QACxB;AAEA,kBAAU,KAAK,IAAI;MACrB;IACF;AAEA,WAAO,IAAI,QAAQ,SAAS;AAE5B,WAAO;EACT;AAEA,MAAI,OAAO,WAAW,YAAY,WAAW,MAAM;AACjD,QAAI,OAAO,IAAI,MAAM,GAAG;AACtB,aAAO,OAAO,IAAI,MAAM;IAC1B;AAEA,UAAM,YAAY,OAAO,eAAe,MAAM;AAE9C,QAAI,cAAc,QAAQ,cAAc,OAAO,WAAW;AACxD,YAAM,aAAa,YAAY,MAAM;AAErC,UAAI,eAAe,QAAQ;AACzB,eAAO,IAAI,QAAQ,UAAU;AAE7B,eAAO;MACT;AAEA,aAAO,IAAI,QAAQ,MAAM;AAEzB,YAAM,UAAU,OAAO,QAAQ,MAAM;AACrC,UAAI,UAAU;AAEd,iBAAW,CAAC,KAAK,KAAK,KAAK,SAAS;AAClC,cAAM,YAAY,UAAU,OAAO,aAAa,MAAM;AAEtD,YAAI,cAAc,OAAO;AACvB,cAAI,CAAC,SAAS;AACZ,sBAAU,IAAI,IAAI,OAAO;UAC3B;AAEA,kBAAQ,IAAI,KAAK,SAAS;QAC5B;MACF;AAEA,YAAM,aAAa,UAAU,OAAO,YAAY,QAAQ,QAAQ,CAAC,IAAI;AAErE,aAAO,IAAI,QAAQ,UAAU;AAE7B,aAAO;IACT;EACF;AAEA,SAAO,YAAY,MAAM;AAC3B;AA0BA,SAAS,SAAS,QAAa,aAAuC;AACpE,SAAO,UAAU,QAAQ,aAAa,oBAAI,IAAI,CAAC;AACjD;AAEA,IAAO,mBAAQ;ACzHf,SAAS,cAAc,OAAsC;AAC3D,SAAO,CAAC,EAAE,iBAAiB,eAAe,iBAAiB;AAC7D;AAEA,SAAS,YAAY,OAAoC;AACvD,SAAO,CAAC,EAAE,eAAe,eAAe,iBAAiB;AAC3D;AAEA,SAAS,cAAc,OAAsC;AAC3D,SAAO,CAAC,EAAE,iBAAiB,eAAe,iBAAiB;AAC7D;AAEA,SAAS,oBAAoB,OAA4C;AACvE,SAAO,CAAC,EAAE,uBAAuB,eAAe,iBAAiB;AACnE;AAEA,SAAS,mBAAmB,OAA2C;AACrE,SAAO,CAAC,EAAE,sBAAsB,eAAe,iBAAiB;AAClE;AAEA,SAAS,cAAc,OAAsC;AAC3D,SAAO,CAAC,EAAE,iBAAiB,eAAe,iBAAiB;AAC7D;AAEA,SAAS,aAAa,OAAqC;AACzD,SAAO,CAAC,EAAE,gBAAgB,eAAe,iBAAiB;AAC5D;AAEA,SAAS,kBAAkB,OAA0C;AACnE,SAAO,CAAC,EAAE,qBAAqB,eAAe,iBAAiB;AACjE;AAEA,SAAS,iBAAiB,OAAyC;AACjE,SAAO,CAAC,EAAE,oBAAoB,eAAe,iBAAiB;AAChE;AAEA,SAAS,iBAAiB,OAAyC;AACjE,SAAO,CAAC,EAAE,oBAAoB,eAAe,iBAAiB;AAChE;AAEA,SAAS,kBAAkB,OAA0C;AACnE,SAAO,CAAC,EAAE,qBAAqB,eAAe,iBAAiB;AACjE;AAEA,SAAS,aAAa,OAAqC;AACzD,SAAO,CAAC,EAAE,gBAAgB,eAAe,iBAAiB;AAC5D;AAEA,SAAS,4BAA4B,OAAyB;AAC5D,SACE,CAAC,EAEG,+BAA+B;EAE/B,OAAQ,WAAmB,2BAA2B,MAAM,eAG3D,iBAAiB,WAAW;AAErC;AAEA,SAAS,yBAAyB,OAAyB;AACzD,SACE,CAAC;GAEE,4BAA4B,cAAc,OAAQ,WAAmB,wBAAwB,MAAM,eAEjG,iBAAiB,WAAW;AAErC;AAEA,SAAS,iBAAiB,OAAyC;AACjE,SAAO,CAAC,EAAE,oBAAoB,eAAe,iBAAiB;AAChE;AAEA,SAAS,eAAe,OAAyB;AAC/C,SACE,cAAc,KAAK,KACnB,YAAY,KAAK,KACjB,cAAc,KAAK,KACnB,oBAAoB,KAAK,KACzB,mBAAmB,KAAK,KACxB,cAAc,KAAK,KACnB,aAAa,KAAK,KAClB,kBAAkB,KAAK,KACvB,iBAAiB,KAAK,KACtB,iBAAiB,KAAK,KACtB,kBAAkB,KAAK,KACvB,aAAa,KAAK,KAClB,4BAA4B,KAAK,KACjC,yBAAyB,KAAK,KAC9B,iBAAiB,KAAK;AAE1B;AAEA,IAAO,yBAAQ;AC5FA,SAAR,eAAgC,MAA+B;AACpE,QAAM,cAAc,oBAAI,IAAkB;AAE1C,mBAAS,MAAM,CAAA,UAAS;AACtB,QAAI,uBAAe,KAAK,GAAG;AACzB,kBAAY,IAAI,KAAqB;IACvC;AAEA,WAAO;EACT,CAAC;AAED,SAAO,MAAM,KAAK,WAAW;AAC/B;ACVA,IAAM,QAAQ;AACd,IAAM,OAAO;AACb,IAAM,SAAS;AACf,IAAM,UAAU;AAyChB,SAAS,eACP,MACA,IACe;AAWf,QAAM,gBAAgB,CAAC,UAAiD;AACtE,UAAM,OAAO,MAAM;AAEnB,QAAI,MAAM,QAAQ,IAAI,KAAK,KAAK,CAAC,MAAM,MAAM;AAC3C,YAAM,yBAAyB;AAE/B,YAAM,CAAC,UAAU,IAAI,MAAM;AAE3B,UAAI,CAAC,YAAY;AACf,cAAM,IAAI,MAAM,sCAAsC;MACxD;AAEA,UAAI,IAAI;AACN,SAAC,YAAY;AACX,gBAAM,kBAAkB,IAAI,gBAAgB;AAE5C,cAAI;AACF,uBAAW,YAAY,CAAC,EAAE,MAAAA,MAAK,MAAM,MAAM,QAAQA,KAAI,KAAKA,MAAK,CAAC,MAAM,SAAS,gBAAgB,MAAM;AAEvG,kBAAM,SAAS,MAAM,GAAG,KAAK,EAAE,QAAQ,gBAAgB,OAAO,GAAG,GAAI,KAAK,MAAM,CAAC,CAAmB;AAEpG,uBAAW,YAAY,CAAC,SAAS,MAAM,GAAG,eAAe,MAAM,CAAC;UAClE,SAAS,OAAO;AACd,uBAAW,YAAY,CAAC,QAAQ,KAAK,CAAC;UACxC,UAAA;AACE,uBAAW,MAAM;UACnB;QACF,GAAG;MACL,OAAO;AACL,mBAAW,YAAY;UACrB;UACA,IAAI;YACF;UACF;QACF,CAAC;AACD,mBAAW,MAAM;MACnB;IACF;EACF;AAEA,OAAK,iBAAiB,WAAW,aAAa;AAC9C,OAAK,MAAM;AAEX,QAAM,oBACJ,CAAC,SACD,IAAI,SAAS;AACX,WAAO,IAAI,QAAqC,CAAC,SAAS,WAAW;AACnE,YAAM,EAAE,OAAO,MAAM,IAAI,IAAI,eAAe;AAE5C,YAAM,YAAY,CAAA,UAAS;AACzB,cAAM,OAAO,MAAM;AAEnB,YAAI,KAAK,CAAC,MAAM,SAAS;AACvB,kBAAQ,KAAK,CAAC,CAAC;QACjB,OAAO;AACL,iBAAO,KAAK,CAAC,CAAC;QAChB;AAEA,cAAM,MAAM;MACd;AAEA,YAAM,QAAQ,iBAAiB,SAAS,MAAM;AAC5C,cAAM,YAAY,CAAC,KAAK,CAAC;AACzB,cAAM,MAAM;AAEZ,eAAO,IAAI,MAAM,UAAU,CAAC;MAC9B,CAAC;AAED,YAAM,WAAW,eAAe,IAAI;AAEpC,WAAK,YAAY,CAAC,MAAM,GAAG,IAAI,GAA+B,CAAC,OAAO,GAAG,QAAQ,CAAC;IACpF,CAAC;EACH;AAEF,QAAM,OAAO,kBAAkB,CAAC,CAAC;AAEjC,OAAK,cAAc;AAEnB,SAAO;AACT;AAEA,IAAO,yBAAQ;;;AE1If,SAAS,SACP,WAC0C;AAC1C,MAAI;AAEJ,SAAO,UAAU,UAAU,OAAO,cAAc,YAAY,UAAU,KAAK,GAAG,IAAI;AACpF;AAEA,SAAS,iBACP,aACA,aACgB;AAGhB,QAAM,gBAAgB,oBAAI,IAAuD;AACjF,QAAM,mBAAmB,uBAAqB,WAAW,EAAE;AAE3D,aAAW,OAAO,YAAY,MAAM;AAClC,kBAAc;AAAA,MACZ;AAAA,MACA,SAAS,YAAY,wBAAK,MAAM,kBAAkB,GAAG,CAAC,CAAC;AAAA,IACzD;AAAA,EACF;AAEA,SAAO,OAAO,YAAY,cAAc,QAAQ,CAAC;AAKnD;AAEA,IAAO,2BAAQ;","names":["data"]}
|
|
1
|
+
{"version":3,"sources":["../../../node_modules/workthru/src/workthru.ts","../../../node_modules/message-port-rpc/src/isTransferable.ts","../../../node_modules/message-port-rpc/src/getAllTransfer.ts","../../../node_modules/message-port-rpc/src/messagePortRPC.ts","../../../node_modules/message-port-rpc/src/forGenerator.ts","../src/client/createClientStub.ts"],"sourcesContent":["/**\n * Internal recursive helper for {@link workthru}.\n *\n * For arrays and plain objects, calls transformer first. If transformer returns the same reference,\n * recursively walks children and rebuilds the container only when a child changes (structural sharing).\n * Class instances, primitives, functions, and null are passed directly to transformer without recursion.\n *\n * The `walked` map tracks already-visited nodes to handle circular references and avoid duplicate work.\n *\n * @param target - Value to transform.\n * @param transformer - Called on every visited value; return the original value to recurse into children.\n * @param walked - Cycle-detection map from original value to its transformed counterpart.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction workthru_(target: any, transformer: (value: any) => any, walked: Map<any, any>): any {\n if (Array.isArray(target)) {\n if (walked.has(target)) {\n return walked.get(target);\n }\n\n let nextArray = transformer(target);\n\n if (nextArray !== target) {\n walked.set(target, nextArray);\n\n return nextArray;\n }\n\n walked.set(target, target);\n\n // for-in loop can handle sparse array.\n for (const index in target) {\n const value = target[index];\n const nextValue = workthru_(value, transformer, walked);\n\n if (nextValue !== value) {\n if (nextArray === target) {\n nextArray = [...target];\n }\n\n nextArray[index] = nextValue;\n }\n }\n\n walked.set(target, nextArray);\n\n return nextArray;\n }\n\n if (typeof target === 'object' && target !== null) {\n if (walked.has(target)) {\n return walked.get(target);\n }\n\n const prototype = Object.getPrototypeOf(target);\n\n if (prototype === null || prototype === Object.prototype) {\n const nextTarget = transformer(target);\n\n if (nextTarget !== target) {\n walked.set(target, nextTarget);\n\n return nextTarget;\n }\n\n walked.set(target, target);\n\n const entries = Object.entries(target);\n let nextMap = undefined;\n\n for (const [key, value] of entries) {\n const nextValue = workthru_(value, transformer, walked);\n\n if (nextValue !== value) {\n if (!nextMap) {\n nextMap = new Map(entries);\n }\n\n nextMap.set(key, nextValue);\n }\n }\n\n const nextObject = nextMap ? Object.fromEntries(nextMap.entries()) : target;\n\n walked.set(target, nextObject);\n\n return nextObject;\n }\n }\n\n return transformer(target);\n}\n\n/**\n * Recursively walks the input in a depth-first search manner and transforms value as needed.\n *\n * Every traversed value will be passed to the `transformer` function.\n *\n * - If the `transformer` return the original value, the traversal for this branch will be continued\n * - If the `transformer` return a new value, the traversal for this branch will be ended\n *\n * The following data types are supported:\n *\n * - boolean, number, string\n * - array will be transformed on itself and every of the element\n * - plain object will be transformed on itself and every of its member value\n *\n * Notes:\n *\n * - Values with unsupported will be kept as-is;\n * - Values that are not transformed will be kept as-is\n *\n * @param target - The value to be worked through\n * @param transformer - The function to transform the value\n * @returns - The transformed value if the input has been transformed, otherwise, return the original value\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction workthru(target: any, transformer: (value: any) => any): any {\n return workthru_(target, transformer, new Map());\n}\n\nexport default workthru;\n","function isArrayBuffer(value: unknown): value is ArrayBuffer {\n return !!('ArrayBuffer' in globalThis) && value instanceof ArrayBuffer;\n}\n\nfunction isAudioData(value: unknown): value is AudioData {\n return !!('AudioData' in globalThis) && value instanceof AudioData;\n}\n\nfunction isImageBitmap(value: unknown): value is ImageBitmap {\n return !!('ImageBitmap' in globalThis) && value instanceof ImageBitmap;\n}\n\nfunction isMediaSourceHandle(value: unknown): value is MediaSourceHandle {\n return !!('MediaSourceHandle' in globalThis) && value instanceof MediaSourceHandle;\n}\n\nfunction isMediaStreamTrack(value: unknown): value is MediaStreamTrack {\n return !!('MediaStreamTrack' in globalThis) && value instanceof MediaStreamTrack;\n}\n\nfunction isMessagePort(value: unknown): value is MessagePort {\n return !!('MessagePort' in globalThis) && value instanceof MessagePort;\n}\n\nfunction isMIDIAccess(value: unknown): value is MIDIAccess {\n return !!('MIDIAccess' in globalThis) && value instanceof MIDIAccess;\n}\n\nfunction isOffscreenCanvas(value: unknown): value is OffscreenCanvas {\n return !!('OffscreenCanvas' in globalThis) && value instanceof OffscreenCanvas;\n}\n\nfunction isReadableStream(value: unknown): value is ReadableStream {\n return !!('ReadableStream' in globalThis) && value instanceof ReadableStream;\n}\n\nfunction isRTCDataChannel(value: unknown): value is RTCDataChannel {\n return !!('RTCDataChannel' in globalThis) && value instanceof RTCDataChannel;\n}\n\nfunction isTransformStream(value: unknown): value is TransformStream {\n return !!('TransformStream' in globalThis) && value instanceof TransformStream;\n}\n\nfunction isVideoFrame(value: unknown): value is VideoFrame {\n return !!('VideoFrame' in globalThis) && value instanceof VideoFrame;\n}\n\nfunction isWebTransportReceiveStream(value: unknown): boolean {\n return (\n !!(\n (\n 'WebTransportReceiveStream' in globalThis &&\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n typeof (globalThis as any)['WebTransportReceiveStream'] === 'function'\n )\n // @ts-expect-error WebTransportReceiveStream is not in TypeScript yet\n ) && value instanceof globalThis.WebTransportReceiveStream\n );\n}\n\nfunction isWebTransportSendStream(value: unknown): boolean {\n return (\n !!(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ('WebTransportSendStream' in globalThis && typeof (globalThis as any)['WebTransportSendStream'] === 'function')\n // @ts-expect-error WebTransportSendStream is not in TypeScript yet\n ) && value instanceof globalThis.WebTransportSendStream\n );\n}\n\nfunction isWritableStream(value: unknown): value is WritableStream {\n return !!('WritableStream' in globalThis) && value instanceof WritableStream;\n}\n\nfunction isTransferable(value: unknown): boolean {\n return (\n isArrayBuffer(value) ||\n isAudioData(value) ||\n isImageBitmap(value) ||\n isMediaSourceHandle(value) ||\n isMediaStreamTrack(value) ||\n isMessagePort(value) ||\n isMIDIAccess(value) ||\n isOffscreenCanvas(value) ||\n isReadableStream(value) ||\n isRTCDataChannel(value) ||\n isTransformStream(value) ||\n isVideoFrame(value) ||\n isWebTransportReceiveStream(value) ||\n isWebTransportSendStream(value) ||\n isWritableStream(value)\n );\n}\n\nexport default isTransferable;\n","import { workthru } from 'workthru';\nimport isTransferable from './isTransferable.ts';\n\nexport default function getAllTransfer(data: unknown): Transferable[] {\n const transferSet = new Set<Transferable>();\n\n workthru(data, value => {\n if (isTransferable(value)) {\n transferSet.add(value as Transferable);\n }\n\n return value;\n });\n\n return Array.from(transferSet);\n}\n","// Naming is from https://www.w3.org/History/1992/nfs_dxcern_mirror/rpc/doc/Introduction/HowItWorks.html.\n\nimport getAllTransfer from './getAllTransfer.ts';\nimport type { CallInit, ClientStub, ServerStub, Subroutine } from './types.ts';\n\nconst ABORT = 'ABORT';\nconst CALL = 'CALL';\nconst REJECT = 'REJECT';\nconst RESOLVE = 'RESOLVE';\n\ntype RPCCallMessage<T extends Subroutine> = [typeof CALL, ...Parameters<T>];\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype RPCRejectMessage = [typeof REJECT, any];\ntype RPCResolveMessage<T extends Subroutine> = [typeof RESOLVE, Awaited<ReturnType<T>>];\n\n/**\n * Binds a function to a `MessagePort` in RPC fashion and/or create a RPC function stub connected to a `MessagePort`.\n *\n * In a traditional RPC setting:\n *\n * - server should call this function with `fn` argument, the returned function should be ignored;\n * - client should call this function without `fn` argument, the returned function is the stub to call the server.\n *\n * This function supports bidirectional RPC when both sides are passing the `fn` argument.\n *\n * When calling the returned function stub, the arguments and return value are sent over `MessagePort`.\n * They would be sent by the underlying structured clone algorithm provided by the `MessagePort` implementation.\n * Transferable are auto-populated and will be passed to `MessagePort.postMessage` call.\n *\n * The returned stub has a variant `withOptions` for passing abort signal.\n *\n * @param {MessagePort} port - The `MessagePort` object to send the calls. The underlying `MessageChannel` must be exclusively used by this function only.\n * @param {Function} fn - The function to invoke. If not set, this RPC cannot be invoked by the other side of `MessagePort`.\n *\n * @returns An asynchronous function, when called, will invoke the function on the other side of `MessagePort`.\n */\nfunction messagePortRPC<C extends Subroutine>(port: MessagePort): ClientStub<C>;\n\nfunction messagePortRPC<C extends Subroutine, S extends Subroutine = C>(\n port: MessagePort,\n fn: ServerStub<S>\n): ClientStub<C>;\n\nfunction messagePortRPC<C extends Subroutine, S extends Subroutine = C>(\n port: MessagePort,\n fn: ServerStub<S>,\n options: { signal: AbortSignal }\n): ClientStub<C>;\n\nfunction messagePortRPC<C extends Subroutine, S extends Subroutine = C>(\n port: MessagePort,\n fn?: ServerStub<S>\n): ClientStub<C> {\n // We cannot neuter the input port because it would cause memory leak:\n // - We can neuter a port by passing it through Structured Clone Algorithm so the input port will become non-functional\n // - After a port is neutered, closing the neutered port will not close the cloned port\n // - Thus, the port owner will no longer able to close the port\n // - This defeated our philosophy: whoever pass a resources to a function, should own the resources unless it is intentional and no other workarounds\n\n type ClientSubroutineParameters = Parameters<C>;\n type ClientSubroutineReturnValue = Awaited<ReturnType<C>>;\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const handleMessage = (event: MessageEvent<RPCCallMessage<S>>): void => {\n const data = event.data as RPCCallMessage<S> | undefined;\n\n if (Array.isArray(data) && data[0] === CALL) {\n event.stopImmediatePropagation();\n\n const [returnPort] = event.ports;\n\n if (!returnPort) {\n throw new Error('RPCCallMessage must contains a port.');\n }\n\n if (fn) {\n (async () => {\n const abortController = new AbortController();\n\n try {\n returnPort.onmessage = ({ data }) => Array.isArray(data) && data[0] === ABORT && abortController.abort();\n\n const result = await fn.call({ signal: abortController.signal }, ...(data.slice(1) as Parameters<S>));\n\n returnPort.postMessage([RESOLVE, result], getAllTransfer(result));\n } catch (error) {\n returnPort.postMessage([REJECT, error]);\n } finally {\n returnPort.close();\n }\n })();\n } else {\n returnPort.postMessage([\n REJECT,\n new Error(\n 'No function was registered on this RPC. This is probably calling a client which do not implement the function.'\n )\n ]);\n returnPort.close();\n }\n }\n };\n\n port.addEventListener('message', handleMessage);\n port.start();\n\n const createWithOptions =\n (init: CallInit): ((...args: ClientSubroutineParameters) => Promise<ClientSubroutineReturnValue>) =>\n (...args) => {\n return new Promise<ClientSubroutineReturnValue>((resolve, reject) => {\n const { port1, port2 } = new MessageChannel();\n\n port1.onmessage = event => {\n const data = event.data as RPCRejectMessage | RPCResolveMessage<C>;\n\n if (data[0] === RESOLVE) {\n resolve(data[1]);\n } else {\n reject(data[1]);\n }\n\n port1.close();\n };\n\n init?.signal?.addEventListener('abort', () => {\n port1.postMessage([ABORT]);\n port1.close();\n\n reject(new Error('Aborted.'));\n });\n\n const transfer = getAllTransfer(args);\n\n port.postMessage([CALL, ...args] satisfies RPCCallMessage<C>, [port2, ...transfer]);\n });\n };\n\n const stub = createWithOptions({}) as ClientStub<C>;\n\n stub.withOptions = createWithOptions;\n\n return stub;\n}\n\nexport default messagePortRPC;\n","// Naming is from https://www.w3.org/History/1992/nfs_dxcern_mirror/rpc/doc/Introduction/HowItWorks.html.\n\nimport messagePortRPC from './messagePortRPC.ts';\n\nconst GENERATE = 'GENERATOR_GENERATE';\n\ntype ClientDisposeReason = 'abort' | 'dispose' | 'done';\n\n// type GeneratorSubroutine<TArgs extends unknown[] = any[], T = unknown, TReturn = any, TNext = unknown> = (\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype GeneratorSubroutine = (...args: any[]) => AsyncGenerator | Generator | AsyncIterator<unknown> | Iterator<unknown>;\ntype RPCGeneratorGenerateMessage<T extends GeneratorSubroutine> = [\n typeof GENERATE,\n Readonly<{\n asyncDispose: MessagePort;\n next: MessagePort;\n return: MessagePort;\n throw: MessagePort;\n }>,\n ...Parameters<T>\n];\n\ntype CallInit = {\n signal?: AbortSignal;\n transfer?: Transferable[];\n};\n\ntype NextOfGenerator<T extends AsyncGenerator | Generator | AsyncIterator<unknown> | Iterator<unknown>> =\n T extends AsyncGenerator<unknown, unknown, infer U> ? U : T extends Generator<unknown, unknown, infer V> ? V : never;\ntype ReturnOfGenerator<T extends AsyncGenerator | Generator | AsyncIterator<unknown> | Iterator<unknown>> =\n T extends AsyncGenerator<unknown, infer U> ? U : T extends Generator<unknown, infer V> ? V : never;\ntype YieldOfGenerator<T extends AsyncGenerator | Generator | AsyncIterator<unknown> | Iterator<unknown>> =\n T extends AsyncGenerator<infer U>\n ? U\n : T extends Generator<infer U>\n ? U\n : T extends AsyncIterator<infer U>\n ? U\n : T extends Iterator<infer U>\n ? U\n : never;\n\n// Regardless whether T returns Promise or not, the client stub must return Promise.\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype ClientGeneratorStub<T extends GeneratorSubroutine> = (\n ...args: Parameters<T>\n) => AsyncGenerator<YieldOfGenerator<ReturnType<T>>, ReturnOfGenerator<ReturnType<T>>, NextOfGenerator<ReturnType<T>>>;\n\ntype ClientGeneratorStubWithExtra<T extends GeneratorSubroutine> = ClientGeneratorStub<T> & {\n /**\n * Creates a new stub with options.\n *\n * @param {AbortSignal} init.signal - Abort signal to abort the call to the stub.\n * @param {Transferable[]} init.transfer - Transfer ownership of objects specified in `args`.\n */\n withOptions: (init: CallInit) => ClientGeneratorStub<T>;\n};\n\ntype ServerStub<T extends GeneratorSubroutine> = (...args: Parameters<T>) => ReturnType<T>;\n\n/**\n * Binds a generator function to a `MessagePort` in RPC fashion and/or create a RPC function stub connected to a `MessagePort`.\n *\n * In a traditional RPC setting:\n *\n * - server should call this generator function with `fn` argument, the returned function should be ignored;\n * - client should call this generator function without `fn` argument, the returned function is the stub to call the server.\n *\n * This function supports bidirectional RPC when both sides are passing the `fn` argument.\n *\n * When calling the returned function stub, the arguments and return value are transferred over `MessagePort`.\n * Thus, they will be cloned by the underlying structured clone algorithm.\n *\n * The returned stub has a variant `withOptions` for passing transferables and abort signal.\n *\n * Notes: if `next()` is used on the client stub and did not iterate until `{ done: true }`, caller must use the `withOptions({ signal: AbortSignal })`\n * to release resources.\n *\n * @param {MessagePort} port - The `MessagePort` object to send the calls. The underlying `MessageChannel` must be exclusively used by this function only.\n * @param {Function} fn - The generator function to invoke. If not set, this RPC cannot be invoked by the other side of `MessagePort`.\n *\n * @returns An asynchronous generator function, when called, will invoke the generator function on the other side of `MessagePort`.\n */\nexport default function forGenerator<C extends GeneratorSubroutine>(port: MessagePort): ClientGeneratorStubWithExtra<C>;\n\nexport default function forGenerator<C extends GeneratorSubroutine, S extends GeneratorSubroutine = C>(\n port: MessagePort,\n fn: ServerStub<S>\n): ClientGeneratorStubWithExtra<C>;\n\nexport default function forGenerator<C extends GeneratorSubroutine, S extends GeneratorSubroutine = C>(\n port: MessagePort,\n fn: ServerStub<S>,\n options: { signal: AbortSignal }\n): ClientGeneratorStubWithExtra<C>;\n\nexport default function forGenerator<C extends GeneratorSubroutine, S extends GeneratorSubroutine = C>(\n port: MessagePort,\n fn?: ServerStub<S>\n): ClientGeneratorStubWithExtra<C> {\n // We cannot neuter the input port because it would cause memory leak:\n // - We can neuter a port by passing it through Structured Clone Algorithm so the input port will become non-functional\n // - After a port is neutered, closing the neutered port will not close the cloned port\n // - Thus, the port owner will no longer able to close the port\n // - This defeated our philosophy: whoever pass a resources to a function, should own the resources unless it is intentional and no other workarounds\n\n type ClientSubroutineParameters = Parameters<C>;\n type ClientSubroutineYield = YieldOfGenerator<ReturnType<C>>;\n type ClientSubroutineReturn = ReturnOfGenerator<ReturnType<C>>;\n type ClientSubroutineNext = NextOfGenerator<ReturnType<C>>;\n type ClientSubroutineIteratorResult = IteratorResult<ClientSubroutineYield, ClientSubroutineReturn>;\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const handleMessage = (event: MessageEvent<RPCGeneratorGenerateMessage<S>>): void => {\n const data = event.data as RPCGeneratorGenerateMessage<S> | undefined;\n\n if (Array.isArray(data) && data[0] === GENERATE) {\n event.stopImmediatePropagation();\n\n const [_, messagePorts, ...args] = data;\n\n const serverClosePorts = () => {\n messagePorts.asyncDispose.close();\n messagePorts.next.close();\n messagePorts.return.close();\n messagePorts.throw.close();\n };\n\n if (!fn) {\n // TODO: Throwing exception in onMessage is no-op, need to fix.\n console.warn(\n '`message-port-rpc`: No function was registered on this RPC. This is probably calling a client which do not implement the function.'\n );\n\n serverClosePorts();\n\n return;\n }\n\n const generator = fn(...args);\n\n messagePortRPC(messagePorts.next, async (...args: ClientSubroutineNext) => {\n const result = await generator.next(...args);\n\n // Automatically close server ports when iteration is done.\n // Client will fake the next()/return()/throw() output after iteration is done.\n result.done && serverClosePorts();\n\n return result;\n });\n\n // This is a slight deviation from the actual `Iterator`.\n // In the original approach, `Iterator.return` is not defined.\n // In our approach, the client stub does not know if the server stub has `Iterator.return` defined or not, instead, we simply return `{ done: true }`.\n messagePortRPC(messagePorts.return, async value => {\n return (await generator.return?.(value)) ?? { done: true };\n });\n\n messagePortRPC(messagePorts.throw, async error => {\n return (await generator.throw?.(error)) ?? Promise.reject(error);\n });\n\n messagePortRPC(messagePorts.asyncDispose, async (): Promise<void> => {\n try {\n const symbolAsyncDispose: typeof Symbol.asyncDispose =\n Symbol.asyncDispose || Symbol.for('Symbol.asyncDispose');\n const symbolDispose: typeof Symbol.dispose = Symbol.dispose || Symbol.for('Symbol.dispose');\n\n symbolAsyncDispose in generator\n ? await generator[symbolAsyncDispose]()\n : symbolDispose in generator && generator[symbolDispose]();\n } finally {\n serverClosePorts();\n }\n });\n }\n };\n\n port.addEventListener('message', handleMessage);\n port.start();\n\n const createWithOptions = (\n init: CallInit\n ): ((\n ...args: ClientSubroutineParameters\n ) => AsyncGenerator<ClientSubroutineYield, ClientSubroutineReturn, ClientSubroutineNext>) => {\n return (...args: ClientSubroutineParameters) => {\n const { port1: asyncDisposePort1, port2: asyncDisposePort2 } = new MessageChannel();\n const { port1: nextPort1, port2: nextPort2 } = new MessageChannel();\n const { port1: returnPort1, port2: returnPort2 } = new MessageChannel();\n const { port1: throwPort1, port2: throwPort2 } = new MessageChannel();\n\n const subInit = { signal: init.signal };\n\n const asyncDisposeRPC = messagePortRPC<() => void>(asyncDisposePort1).withOptions(subInit);\n\n const nextRPC =\n messagePortRPC<(next: ClientSubroutineNext | void) => ClientSubroutineIteratorResult>(nextPort1).withOptions(\n subInit\n );\n\n const returnRPC =\n messagePortRPC<(returnValue: ClientSubroutineReturn) => ClientSubroutineIteratorResult>(\n returnPort1\n ).withOptions(subInit);\n\n const throwRPC =\n messagePortRPC<(error: unknown) => ClientSubroutineIteratorResult>(throwPort1).withOptions(subInit);\n\n const callAsyncDispose = async (disposeReason: ClientDisposeReason) => {\n if (isDone(false)) {\n return;\n }\n\n // AsyncDispose has never been called.\n if (disposeReason === 'abort' || disposeReason === 'dispose') {\n // Only call server for AsyncDispose if the user intentionally abort or dispose.\n // Otherwise, the server-side object should have already disposed due to \"done\" and \"error\".\n await asyncDisposeRPC();\n }\n\n if (disposeReason === 'done') {\n isDone = () => true;\n } else {\n disposeReason satisfies 'abort' | 'dispose';\n\n isDone = (throwOnDispose = true) => {\n if (throwOnDispose === true) {\n // Already disposed, the MessagePort are all closed, return previous result.\n throw new Error('This generator has been disposed.');\n }\n\n return true;\n };\n }\n\n asyncDisposePort1.close();\n asyncDisposePort2.close();\n nextPort1.close();\n nextPort2.close();\n returnPort1.close();\n returnPort2.close();\n throwPort1.close();\n throwPort2.close();\n };\n\n let isDone: (throwOnDispose?: boolean | undefined) => boolean = () => false;\n\n const generator: AsyncGenerator<ClientSubroutineYield, ClientSubroutineReturn, ClientSubroutineNext> = {\n next: async (value: NextOfGenerator<ReturnType<C>> | void) => {\n if (isDone()) {\n // Return type of any generators should allow `undefined`.\n // For example, after the generator is exhausted, the return value will be `undefined`.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return { done: true, value: undefined } satisfies IteratorReturnResult<undefined> as any;\n }\n\n const result = await nextRPC(value);\n\n if (result.done) {\n await callAsyncDispose('done');\n }\n\n return result;\n },\n return: async (value: ReturnOfGenerator<ReturnType<C>>) => {\n if (isDone()) {\n return { done: true, value };\n }\n\n return await returnRPC(value);\n },\n throw: async (error: unknown) => {\n if (isDone()) {\n throw error;\n }\n\n return await throwRPC(error);\n },\n // Ponyfills for Symbol.asyncDispose\n [Symbol.asyncDispose || Symbol.for('Symbol.asyncDispose')]: async () => {\n await callAsyncDispose('dispose');\n },\n [Symbol.asyncIterator]: () => generator\n };\n\n port.postMessage(\n [\n GENERATE,\n { asyncDispose: asyncDisposePort2, next: nextPort2, return: returnPort2, throw: throwPort2 },\n ...args\n ] satisfies RPCGeneratorGenerateMessage<C>,\n [...(init.transfer || []), asyncDisposePort2, nextPort2, returnPort2, throwPort2]\n );\n\n init.signal?.addEventListener('abort', () => callAsyncDispose('abort').catch(() => {}), { once: true });\n\n return generator;\n };\n };\n\n const stub = createWithOptions({}) as ClientGeneratorStubWithExtra<C>;\n\n stub.withOptions = createWithOptions;\n\n return stub;\n}\n","import { messagePortRPC as rpc } from 'message-port-rpc';\nimport type { InferClient } from '../types/internal/InferClient.ts';\nimport type { InferHandshake } from '../types/internal/InferHandshake.ts';\nimport type { StubDeclaration } from '../types/StubDeclaration.ts';\nimport type { StubImplementation } from '../types/StubImplementation.ts';\n\nfunction lazyStub<TArgs extends unknown[], TSyncReturn>(\n fnFactory: () => Promise<(...args: TArgs) => Promise<TSyncReturn>>\n): (...args: TArgs) => Promise<TSyncReturn> {\n let fnPromise: Promise<(...args: TArgs) => Promise<TSyncReturn>> | undefined;\n\n return async (...args) => (await (fnPromise ?? (fnPromise = fnFactory())))(...args);\n}\n\nfunction createClientStub<T extends StubDeclaration<S>, S extends StubImplementation>(\n declaration: Pick<T, 'keys'>,\n messagePort: MessagePort\n): InferClient<S> {\n type Handshake = InferHandshake<S>;\n\n const clientStubMap = new Map<keyof S, (...args: unknown[]) => Promise<unknown>>();\n const handshakePromise = rpc<() => Handshake>(messagePort)();\n\n for (const key of declaration.keys) {\n clientStubMap.set(\n key,\n lazyStub(async () => rpc((await handshakePromise)[key]))\n );\n }\n\n return Object.fromEntries(clientStubMap.entries()) satisfies Record<\n string,\n (...args: unknown[]) => Promise<unknown>\n // TODO: We should not use \"as unknown\".\n > as unknown as InferClient<S>;\n}\n\nexport default createClientStub;\n"],"mappings":";AAcA,SAAS,UAAU,QAAa,aAAkC,QAA4B;AAC5F,MAAI,MAAM,QAAQ,MAAM,GAAG;AACzB,QAAI,OAAO,IAAI,MAAM,GAAG;AACtB,aAAO,OAAO,IAAI,MAAM;IAC1B;AAEA,QAAI,YAAY,YAAY,MAAM;AAElC,QAAI,cAAc,QAAQ;AACxB,aAAO,IAAI,QAAQ,SAAS;AAE5B,aAAO;IACT;AAEA,WAAO,IAAI,QAAQ,MAAM;AAGzB,eAAW,SAAS,QAAQ;AAC1B,YAAM,QAAQ,OAAO,KAAK;AAC1B,YAAM,YAAY,UAAU,OAAO,aAAa,MAAM;AAEtD,UAAI,cAAc,OAAO;AACvB,YAAI,cAAc,QAAQ;AACxB,sBAAY,CAAC,GAAG,MAAM;QACxB;AAEA,kBAAU,KAAK,IAAI;MACrB;IACF;AAEA,WAAO,IAAI,QAAQ,SAAS;AAE5B,WAAO;EACT;AAEA,MAAI,OAAO,WAAW,YAAY,WAAW,MAAM;AACjD,QAAI,OAAO,IAAI,MAAM,GAAG;AACtB,aAAO,OAAO,IAAI,MAAM;IAC1B;AAEA,UAAM,YAAY,OAAO,eAAe,MAAM;AAE9C,QAAI,cAAc,QAAQ,cAAc,OAAO,WAAW;AACxD,YAAM,aAAa,YAAY,MAAM;AAErC,UAAI,eAAe,QAAQ;AACzB,eAAO,IAAI,QAAQ,UAAU;AAE7B,eAAO;MACT;AAEA,aAAO,IAAI,QAAQ,MAAM;AAEzB,YAAM,UAAU,OAAO,QAAQ,MAAM;AACrC,UAAI,UAAU;AAEd,iBAAW,CAAC,KAAK,KAAK,KAAK,SAAS;AAClC,cAAM,YAAY,UAAU,OAAO,aAAa,MAAM;AAEtD,YAAI,cAAc,OAAO;AACvB,cAAI,CAAC,SAAS;AACZ,sBAAU,IAAI,IAAI,OAAO;UAC3B;AAEA,kBAAQ,IAAI,KAAK,SAAS;QAC5B;MACF;AAEA,YAAM,aAAa,UAAU,OAAO,YAAY,QAAQ,QAAQ,CAAC,IAAI;AAErE,aAAO,IAAI,QAAQ,UAAU;AAE7B,aAAO;IACT;EACF;AAEA,SAAO,YAAY,MAAM;AAC3B;AA0BA,SAAS,SAAS,QAAa,aAAuC;AACpE,SAAO,UAAU,QAAQ,aAAa,oBAAI,IAAI,CAAC;AACjD;AAEA,IAAO,mBAAQ;ACzHf,SAAS,cAAc,OAAsC;AAC3D,SAAO,CAAC,EAAE,iBAAiB,eAAe,iBAAiB;AAC7D;AAEA,SAAS,YAAY,OAAoC;AACvD,SAAO,CAAC,EAAE,eAAe,eAAe,iBAAiB;AAC3D;AAEA,SAAS,cAAc,OAAsC;AAC3D,SAAO,CAAC,EAAE,iBAAiB,eAAe,iBAAiB;AAC7D;AAEA,SAAS,oBAAoB,OAA4C;AACvE,SAAO,CAAC,EAAE,uBAAuB,eAAe,iBAAiB;AACnE;AAEA,SAAS,mBAAmB,OAA2C;AACrE,SAAO,CAAC,EAAE,sBAAsB,eAAe,iBAAiB;AAClE;AAEA,SAAS,cAAc,OAAsC;AAC3D,SAAO,CAAC,EAAE,iBAAiB,eAAe,iBAAiB;AAC7D;AAEA,SAAS,aAAa,OAAqC;AACzD,SAAO,CAAC,EAAE,gBAAgB,eAAe,iBAAiB;AAC5D;AAEA,SAAS,kBAAkB,OAA0C;AACnE,SAAO,CAAC,EAAE,qBAAqB,eAAe,iBAAiB;AACjE;AAEA,SAAS,iBAAiB,OAAyC;AACjE,SAAO,CAAC,EAAE,oBAAoB,eAAe,iBAAiB;AAChE;AAEA,SAAS,iBAAiB,OAAyC;AACjE,SAAO,CAAC,EAAE,oBAAoB,eAAe,iBAAiB;AAChE;AAEA,SAAS,kBAAkB,OAA0C;AACnE,SAAO,CAAC,EAAE,qBAAqB,eAAe,iBAAiB;AACjE;AAEA,SAAS,aAAa,OAAqC;AACzD,SAAO,CAAC,EAAE,gBAAgB,eAAe,iBAAiB;AAC5D;AAEA,SAAS,4BAA4B,OAAyB;AAC5D,SACE,CAAC,EAEG,+BAA+B;EAE/B,OAAQ,WAAmB,2BAA2B,MAAM,eAG3D,iBAAiB,WAAW;AAErC;AAEA,SAAS,yBAAyB,OAAyB;AACzD,SACE,CAAC;GAEE,4BAA4B,cAAc,OAAQ,WAAmB,wBAAwB,MAAM,eAEjG,iBAAiB,WAAW;AAErC;AAEA,SAAS,iBAAiB,OAAyC;AACjE,SAAO,CAAC,EAAE,oBAAoB,eAAe,iBAAiB;AAChE;AAEA,SAAS,eAAe,OAAyB;AAC/C,SACE,cAAc,KAAK,KACnB,YAAY,KAAK,KACjB,cAAc,KAAK,KACnB,oBAAoB,KAAK,KACzB,mBAAmB,KAAK,KACxB,cAAc,KAAK,KACnB,aAAa,KAAK,KAClB,kBAAkB,KAAK,KACvB,iBAAiB,KAAK,KACtB,iBAAiB,KAAK,KACtB,kBAAkB,KAAK,KACvB,aAAa,KAAK,KAClB,4BAA4B,KAAK,KACjC,yBAAyB,KAAK,KAC9B,iBAAiB,KAAK;AAE1B;AAEA,IAAO,yBAAQ;AC5FA,SAAR,eAAgC,MAA+B;AACpE,QAAM,cAAc,oBAAI,IAAkB;AAE1C,mBAAS,MAAM,CAAA,UAAS;AACtB,QAAI,uBAAe,KAAK,GAAG;AACzB,kBAAY,IAAI,KAAqB;IACvC;AAEA,WAAO;EACT,CAAC;AAED,SAAO,MAAM,KAAK,WAAW;AAC/B;ACVA,IAAM,QAAQ;AACd,IAAM,OAAO;AACb,IAAM,SAAS;AACf,IAAM,UAAU;AAyChB,SAAS,eACP,MACA,IACe;AAWf,QAAM,gBAAgB,CAAC,UAAiD;AACtE,UAAM,OAAO,MAAM;AAEnB,QAAI,MAAM,QAAQ,IAAI,KAAK,KAAK,CAAC,MAAM,MAAM;AAC3C,YAAM,yBAAyB;AAE/B,YAAM,CAAC,UAAU,IAAI,MAAM;AAE3B,UAAI,CAAC,YAAY;AACf,cAAM,IAAI,MAAM,sCAAsC;MACxD;AAEA,UAAI,IAAI;AACN,SAAC,YAAY;AACX,gBAAM,kBAAkB,IAAI,gBAAgB;AAE5C,cAAI;AACF,uBAAW,YAAY,CAAC,EAAE,MAAAA,MAAK,MAAM,MAAM,QAAQA,KAAI,KAAKA,MAAK,CAAC,MAAM,SAAS,gBAAgB,MAAM;AAEvG,kBAAM,SAAS,MAAM,GAAG,KAAK,EAAE,QAAQ,gBAAgB,OAAO,GAAG,GAAI,KAAK,MAAM,CAAC,CAAmB;AAEpG,uBAAW,YAAY,CAAC,SAAS,MAAM,GAAG,eAAe,MAAM,CAAC;UAClE,SAAS,OAAO;AACd,uBAAW,YAAY,CAAC,QAAQ,KAAK,CAAC;UACxC,UAAA;AACE,uBAAW,MAAM;UACnB;QACF,GAAG;MACL,OAAO;AACL,mBAAW,YAAY;UACrB;UACA,IAAI;YACF;UACF;QACF,CAAC;AACD,mBAAW,MAAM;MACnB;IACF;EACF;AAEA,OAAK,iBAAiB,WAAW,aAAa;AAC9C,OAAK,MAAM;AAEX,QAAM,oBACJ,CAAC,SACD,IAAI,SAAS;AACX,WAAO,IAAI,QAAqC,CAAC,SAAS,WAAW;AACnE,YAAM,EAAE,OAAO,MAAM,IAAI,IAAI,eAAe;AAE5C,YAAM,YAAY,CAAA,UAAS;AACzB,cAAM,OAAO,MAAM;AAEnB,YAAI,KAAK,CAAC,MAAM,SAAS;AACvB,kBAAQ,KAAK,CAAC,CAAC;QACjB,OAAO;AACL,iBAAO,KAAK,CAAC,CAAC;QAChB;AAEA,cAAM,MAAM;MACd;AAEA,YAAM,QAAQ,iBAAiB,SAAS,MAAM;AAC5C,cAAM,YAAY,CAAC,KAAK,CAAC;AACzB,cAAM,MAAM;AAEZ,eAAO,IAAI,MAAM,UAAU,CAAC;MAC9B,CAAC;AAED,YAAM,WAAW,eAAe,IAAI;AAEpC,WAAK,YAAY,CAAC,MAAM,GAAG,IAAI,GAA+B,CAAC,OAAO,GAAG,QAAQ,CAAC;IACpF,CAAC;EACH;AAEF,QAAM,OAAO,kBAAkB,CAAC,CAAC;AAEjC,OAAK,cAAc;AAEnB,SAAO;AACT;AAEA,IAAO,yBAAQ;;;AE1If,SAAS,SACP,WAC0C;AAC1C,MAAI;AAEJ,SAAO,UAAU,UAAU,OAAO,cAAc,YAAY,UAAU,KAAK,GAAG,IAAI;AACpF;AAEA,SAAS,iBACP,aACA,aACgB;AAGhB,QAAM,gBAAgB,oBAAI,IAAuD;AACjF,QAAM,mBAAmB,uBAAqB,WAAW,EAAE;AAE3D,aAAW,OAAO,YAAY,MAAM;AAClC,kBAAc;AAAA,MACZ;AAAA,MACA,SAAS,YAAY,wBAAK,MAAM,kBAAkB,GAAG,CAAC,CAAC;AAAA,IACzD;AAAA,EACF;AAEA,SAAO,OAAO,YAAY,cAAc,QAAQ,CAAC;AAKnD;AAEA,IAAO,2BAAQ;","names":["data"]}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -16,4 +16,4 @@ type StubDeclaration<T extends StubImplementation> = {
|
|
|
16
16
|
|
|
17
17
|
declare function listen<T extends StubDeclaration<S>, S extends StubImplementation>(declaration: T, environment: StubEnvironment, messagePort: MessagePort): () => void;
|
|
18
18
|
|
|
19
|
-
export { listen
|
|
19
|
+
export { listen };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onting/rpc",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.1.0-main.202606142104.1d538a8",
|
|
4
4
|
"description": "",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -30,12 +30,21 @@
|
|
|
30
30
|
"./*.js",
|
|
31
31
|
"./dist/"
|
|
32
32
|
],
|
|
33
|
-
"
|
|
34
|
-
"
|
|
33
|
+
"type": "module",
|
|
34
|
+
"main": "./dist/index.js",
|
|
35
|
+
"typings": "./dist/index.d.ts",
|
|
35
36
|
"exports": {
|
|
37
|
+
"./client.js": {
|
|
38
|
+
"types": "./dist/client.js",
|
|
39
|
+
"default": "./dist/client.d.ts"
|
|
40
|
+
},
|
|
41
|
+
"./server.js": {
|
|
42
|
+
"types": "./dist/server.js",
|
|
43
|
+
"default": "./dist/server.d.ts"
|
|
44
|
+
},
|
|
36
45
|
".": {
|
|
37
|
-
"types": "./dist/
|
|
38
|
-
"default": "./dist/
|
|
46
|
+
"types": "./dist/index.js",
|
|
47
|
+
"default": "./dist/index.d.ts"
|
|
39
48
|
}
|
|
40
49
|
},
|
|
41
50
|
"repository": {
|
|
@@ -59,6 +68,7 @@
|
|
|
59
68
|
"@tsconfig/recommended": "^1.0.13",
|
|
60
69
|
"@tsconfig/strictest": "^2.0.8",
|
|
61
70
|
"@types/node": "^25.9.3",
|
|
71
|
+
"@types/selenium-webdriver": "^4.35.6",
|
|
62
72
|
"esbuild": "^0.28.1",
|
|
63
73
|
"escape-string-regexp": "^5.0.0",
|
|
64
74
|
"expect": "^30.4.1",
|
|
@@ -68,5 +78,9 @@
|
|
|
68
78
|
"typescript": "^6.0.3"
|
|
69
79
|
},
|
|
70
80
|
"license": "MIT",
|
|
71
|
-
"pinDependencies": {}
|
|
81
|
+
"pinDependencies": {},
|
|
82
|
+
"dependencies": {
|
|
83
|
+
"@onting/rpc": "^0.1.0-main.202606142104.1d538a8",
|
|
84
|
+
"message-port-rpc": "^3.0.1"
|
|
85
|
+
}
|
|
72
86
|
}
|
package/dist/index.mjs
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
//# sourceMappingURL=index.mjs.map
|
package/dist/rpc.d.mts
DELETED
package/dist/rpc.d.ts
DELETED
package/dist/rpc.js
DELETED
package/dist/rpc.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["console.log('Hello, World!');\n"],"mappings":";;;AAAA,QAAQ,IAAI,eAAe;","names":[]}
|
package/dist/rpc.mjs
DELETED
package/dist/rpc.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["console.log('Hello, World!');\n"],"mappings":";AAAA,QAAQ,IAAI,eAAe;","names":[]}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|