UNPKG

35.2 kBSource Map (JSON)View Raw
1{"version":3,"file":"base.js","sources":["../src/utils/error.ts","../src/utils/jsonrpc.ts","../src/utils/serialization.ts","../src/utils/internalSymbol.ts","../src/core/notify.ts","../src/core/batch.ts","../src/utils/normalizeOptions.ts","../src/Async-Call.ts"],"sourcesContent":["class CustomError extends Error {\n constructor(public name: string, message: string, public code: number, public stack: string) {\n super(message)\n }\n}\nexport const Err_Cannot_find_a_running_iterator_with_given_ID = {} as Symbol\nexport const Err_Only_string_can_be_the_RPC_method_name = {} as Symbol\nexport const Err_Cannot_call_method_starts_with_rpc_dot_directly = {} as Symbol\nexport const Err_Then_is_accessed_on_local_implementation_Please_explicitly_mark_if_it_is_thenable_in_the_options = {} as Symbol\nconst Messages = [\n Err_Cannot_find_a_running_iterator_with_given_ID,\n Err_Only_string_can_be_the_RPC_method_name,\n Err_Cannot_call_method_starts_with_rpc_dot_directly,\n Err_Then_is_accessed_on_local_implementation_Please_explicitly_mark_if_it_is_thenable_in_the_options,\n]\n// https://github.com/Jack-Works/async-call-rpc/wiki/Error-messages\nexport function makeHostedMessage(id: Symbol, error: Error) {\n const n = Messages.indexOf(id)\n error.message += `Error ${n}: https://github.com/Jack-Works/async-call-rpc/wiki/Errors#` + n\n return error\n}\n// ! side effect\n/** These Error is defined in ECMAScript spec */\nconst errors: Record<string, typeof EvalError> = {\n // @ts-ignore\n __proto__: null,\n Error,\n EvalError,\n RangeError,\n ReferenceError,\n SyntaxError,\n TypeError,\n URIError,\n}\nexport const DOMExceptionHeader = 'DOMException:'\n/**\n * AsyncCall support somehow transfer ECMAScript Error\n */\nexport const RecoverError = (type: string, message: string, code: number, stack: string): Error => {\n try {\n const E = globalDOMException()\n if (type.startsWith(DOMExceptionHeader) && E) {\n const name = type.slice(DOMExceptionHeader.length)\n return new E(message, name)\n } else if (type in errors) {\n const e = new errors[type]!(message)\n e.stack = stack\n // @ts-ignore\n e.code = code\n return e\n } else {\n return new CustomError(type, message, code, stack)\n }\n } catch {\n return new Error(`E${code} ${type}: ${message}\\n${stack}`)\n }\n}\nexport const removeStackHeader = (stack: unknown) => String(stack).replace(/^.+\\n.+\\n/, '')\n// ! side effect\nexport const globalDOMException = (() => {\n try {\n // @ts-ignore\n return DOMException\n } catch {}\n}) as () => DOMException | undefined\ntype DOMException = { new (message: string, name: string): any }\n","import { globalDOMException as DOMException, DOMExceptionHeader } from './error'\nimport type { ErrorMapFunction } from '../Async-Call'\nimport { ERROR, isArray, isBoolean, isFunction, isObject, isString, undefined } from './constants'\n\nexport const jsonrpc = '2.0'\nexport type ID = string | number | null | undefined\n/**\n * JSONRPC Request object.\n */\nexport interface Request\n extends Readonly<{\n jsonrpc: typeof jsonrpc\n id?: ID\n method: string\n params: readonly unknown[] | object\n remoteStack?: string\n }> {}\n\nexport const Request = (id: ID, method: string, params: readonly unknown[] | object, remoteStack?: string): Request => {\n const x: Request = { jsonrpc, id, method, params, remoteStack }\n deleteUndefined(x, 'id')\n deleteFalsy(x, 'remoteStack')\n return x\n}\n\n/**\n * JSONRPC SuccessResponse object.\n */\nexport interface SuccessResponse\n extends Readonly<{\n jsonrpc: typeof jsonrpc\n id?: ID\n result: unknown\n }> {}\nexport const SuccessResponse = (id: ID, result: unknown): SuccessResponse => {\n const x: SuccessResponse = { jsonrpc, id, result }\n deleteUndefined(x, 'id')\n return x\n}\n\n/**\n * JSONRPC ErrorResponse object.\n * @public\n */\nexport interface ErrorResponse<E = unknown>\n extends Readonly<{\n jsonrpc: typeof jsonrpc\n id?: ID\n error: Readonly<{ code: number; message: string; data?: E }>\n }> {}\n\nexport const ErrorResponse = <T>(id: ID, code: number, message: string, data?: T): ErrorResponse<T> => {\n if (id === undefined) id = null\n code = Math.floor(code)\n if (Number.isNaN(code)) code = -1\n const x: ErrorResponse<T> = { jsonrpc, id, error: { code, message, data } }\n deleteUndefined(x.error, 'data')\n return x\n}\n// Pre defined error in section 5.1\n// ! side effect\nexport const ErrorResponseParseError = <T>(e: unknown, mapper: ErrorMapFunction<T>): ErrorResponse<T> => {\n const obj = ErrorResponseMapped({} as any, e, mapper)\n const o = obj.error as Mutable<ErrorResponse['error']>\n o.code = -32700\n o.message = 'Parse error'\n return obj\n}\n\n// Not using.\n// InvalidParams -32602 'Invalid params'\n// InternalError -32603 'Internal error'\nexport const ErrorResponseInvalidRequest = (id: ID) => ErrorResponse(id, -32600, 'Invalid Request')\nexport const ErrorResponseMethodNotFound = (id: ID) => ErrorResponse(id, -32601, 'Method not found')\n\ntype AsyncCallErrorDetail = {\n stack?: string\n type?: string\n}\nexport const ErrorResponseMapped = <T>(request: Request, e: unknown, mapper: ErrorMapFunction<T>): ErrorResponse<T> => {\n const { id } = request\n const { code, message, data } = mapper(e, request)\n return ErrorResponse(id, code, message, data)\n}\n\nexport const defaultErrorMapper = (stack = '', code = -1): ErrorMapFunction<AsyncCallErrorDetail> => (e) => {\n let message = toString('', () => (e as any).message)\n let type = toString(ERROR, (ctor = (e as any).constructor) => isFunction(ctor) && ctor.name)\n const E = DOMException()\n if (E && e instanceof E) type = DOMExceptionHeader + e.name\n if (isString(e) || typeof e === 'number' || isBoolean(e) || typeof e === 'bigint') {\n type = ERROR\n message = String(e)\n }\n const data: AsyncCallErrorDetail = stack ? { stack, type } : { type }\n return { code, message, data }\n}\n\n/**\n * A JSONRPC response object\n */\nexport type Response = SuccessResponse | ErrorResponse\n\nexport const isJSONRPCObject = (data: any): data is Response | Request => {\n if (!isObject(data)) return false\n if (!hasKey(data, 'jsonrpc')) return false\n if (data.jsonrpc !== jsonrpc) return false\n if (hasKey(data, 'params')) {\n const params = (data as Request).params\n if (!isArray(params) && !isObject(params)) return false\n }\n return true\n}\n\nexport { isObject } from './constants'\n\nexport const hasKey = <T, Q extends string>(\n obj: T,\n key: Q,\n): obj is T &\n {\n [key in Q]: unknown\n } => key in obj\n\nconst toString = (_default: string, val: () => any) => {\n try {\n const v = val()\n if (v === undefined) return _default\n return String(v)\n } catch {\n return _default\n }\n}\nconst deleteUndefined = <O>(x: O, key: keyof O) => {\n if (x[key] === undefined) delete x[key]\n}\nconst deleteFalsy = <T>(x: T, key: keyof T) => {\n if (!x[key]) delete x[key]\n}\ntype Mutable<T> = { -readonly [key in keyof T]: T[key] }\n","//#region Serialization\n\nimport { isObject, hasKey } from './jsonrpc'\nimport { undefined } from './constants'\nimport type { Serialization } from '../types'\n\n\n/**\n * Serialization implementation that do nothing\n * @remarks {@link Serialization}\n * @public\n */\nexport const NoSerialization: Serialization = {\n serialization(from) {\n return from\n },\n deserialization(serialized) {\n return serialized\n },\n}\n\n/**\n * Create a serialization by JSON.parse/stringify\n *\n * @param replacerAndReceiver - Replacer and receiver of JSON.parse/stringify\n * @param space - Adds indentation, white space, and line break characters to the return-value JSON text to make it easier to read.\n * @param undefinedKeepingBehavior - How to keep \"undefined\" in result of SuccessResponse?\n *\n * If it is not handled properly, JSON.stringify will emit an invalid JSON RPC object.\n *\n * Options:\n * - `\"null\"`(**default**): convert it to null.\n * - `\"keep\"`: try to keep it by additional property \"undef\".\n * - `false`: Don't keep it, let it break.\n * @remarks {@link Serialization}\n * @public\n */\nexport const JSONSerialization = (\n replacerAndReceiver: [((key: string, value: any) => any)?, ((key: string, value: any) => any)?] = [\n undefined,\n undefined,\n ],\n space?: string | number | undefined,\n undefinedKeepingBehavior: 'keep' | 'null' | false = 'null',\n): Serialization => ({\n serialization(from) {\n if (undefinedKeepingBehavior && isObject(from) && hasKey(from, 'result') && from.result === undefined) {\n const alt = { ...from }\n alt.result = null\n if (undefinedKeepingBehavior === 'keep') (alt as any).undef = true\n from = alt\n }\n return JSON.stringify(from, replacerAndReceiver[0], space)\n },\n deserialization(serialized) {\n const result = JSON.parse(serialized as string, replacerAndReceiver[1])\n if (\n isObject(result) &&\n hasKey(result, 'result') &&\n result.result === null &&\n hasKey(result, 'undef') &&\n result.undef === true\n ) {\n result.result = undefined\n delete result.undef\n }\n return result\n },\n})\n//#endregion\n","const i = 'AsyncCall/'\n// ! side effect\nexport const AsyncCallIgnoreResponse = Symbol.for(i + 'ignored')\nexport const AsyncCallNotify = Symbol.for(i + 'notify')\nexport const AsyncCallBatch = Symbol.for(i + 'batch')\n","import { AsyncCallNotify } from '../utils/internalSymbol'\nimport { isFunction } from '../utils/constants'\n\n/**\n * Make the returning type to `Promise<void>`\n * @internal\n * @remarks\n * Due to the limitation of TypeScript, generic signatures cannot be preserved\n * if the function is the top level parameter of this utility type,\n * or the function is not returning `Promise<void>`.\n */\nexport type _IgnoreResponse<T> = T extends (...args: infer Args) => unknown\n ? (...args: Args) => Promise<void>\n : {\n [key in keyof T as T[key] extends Function ? key : never]: T[key] extends (\n ...args: infer Args\n ) => infer Return\n ? Return extends Promise<void>\n ? T[key]\n : (...args: Args) => Promise<void>\n : never\n }\n/**\n * Wrap the AsyncCall instance to send notification.\n * @param instanceOrFnOnInstance - The AsyncCall instance or function on the AsyncCall instance\n * @example\n * const notifyOnly = notify(AsyncCall(...))\n * @public\n */\n\nexport function notify<T extends object>(instanceOrFnOnInstance: T): _IgnoreResponse<T> {\n if (isFunction(instanceOrFnOnInstance)) return (instanceOrFnOnInstance as any)[AsyncCallNotify]\n return new Proxy(instanceOrFnOnInstance, { get: notifyTrap }) as any\n}\nconst notifyTrap = (target: any, p: string | number | symbol) => {\n return target[p][AsyncCallNotify]\n}\n","import { isString } from '../utils/constants'\nimport { AsyncCallBatch, AsyncCallNotify } from '../utils/internalSymbol'\nimport type { Request } from '../utils/jsonrpc'\n/**\n * Wrap the AsyncCall instance to use batch call.\n * @param asyncCallInstance - The AsyncCall instance\n * @example\n * const [batched, send, drop] = batch(AsyncCall(...))\n * batched.call1() // pending\n * batched.call2() // pending\n * send() // send all pending requests\n * drop() // drop all pending requests\n * @returns It will return a tuple.\n *\n * The first item is the batched version of AsyncCall instance passed in.\n *\n * The second item is a function to send all pending requests.\n *\n * The third item is a function to drop and reject all pending requests.\n * @public\n */\nexport function batch<T extends object>(asyncCallInstance: T): [T, () => void, (error?: unknown) => void] {\n let queue: BatchQueue = [] as any\n return [\n new Proxy({ __proto__: null } as any, {\n get(cache, p) {\n if (isString(p) && cache[p]) return cache[p]\n // @ts-ignore\n const f = (...args: any) => asyncCallInstance[AsyncCallBatch](queue, p, ...args)\n // @ts-ignore\n f[AsyncCallNotify] = (...args: any) =>\n // @ts-ignore\n asyncCallInstance[AsyncCallBatch][AsyncCallNotify](queue, p, ...args)\n // @ts-ignore\n f[AsyncCallNotify][AsyncCallNotify] = f[AsyncCallNotify]\n isString(p) && Object.defineProperty(cache, p, { value: f, configurable: true })\n return f\n },\n }),\n (r = queue.r) => r && r[0](),\n (error = new Error('Aborted'), r = queue.r) => {\n r && r[1](error)\n queue = []\n },\n ]\n}\nexport type BatchQueue = Request[] & { r?: [() => void, (error?: unknown) => void] }\n","import type { AsyncCallOptions } from '../Async-Call'\nimport { isBoolean } from './constants'\nconst undefinedToTrue = (x: undefined | boolean) => (x === void 0 ? true : x)\ntype NormalizedLogOptions = readonly [\n beCalled: boolean,\n localError: boolean,\n remoteError: boolean,\n isPretty?: boolean,\n requestReplay?: boolean,\n sendLocalStack?: boolean,\n]\n\nexport const normalizeLogOptions = (log: NonNullable<AsyncCallOptions['log']>): NormalizedLogOptions | [] => {\n if (log === 'all') return [true, true, true, true, true, true]\n if (!isBoolean(log)) {\n const { beCalled, localError, remoteError, type, requestReplay, sendLocalStack } = log\n return [\n undefinedToTrue(beCalled),\n undefinedToTrue(localError),\n undefinedToTrue(remoteError),\n type !== 'basic',\n requestReplay,\n sendLocalStack,\n ]\n }\n if (log) return [true, true, true, true] as const\n return []\n}\n\nexport const normalizeStrictOptions = (strict: NonNullable<AsyncCallOptions['strict']>) => {\n if (!isBoolean(strict)) {\n const { methodNotFound, unknownMessage } = strict\n return [methodNotFound, unknownMessage] as const\n }\n return [strict, strict] as const\n}\n","export * from './types'\nexport type { _IgnoreResponse } from './core/notify'\nexport { JSONSerialization, NoSerialization } from './utils/serialization'\nexport { notify } from './core/notify'\nexport { batch } from './core/batch'\n\nimport { NoSerialization } from './utils/serialization'\nimport {\n Request,\n Response,\n ErrorResponseMapped,\n SuccessResponse,\n hasKey,\n isJSONRPCObject,\n isObject,\n ErrorResponse,\n defaultErrorMapper,\n ErrorResponseMethodNotFound,\n ErrorResponseInvalidRequest,\n ErrorResponseParseError,\n} from './utils/jsonrpc'\nimport {\n removeStackHeader,\n RecoverError,\n makeHostedMessage,\n Err_Cannot_call_method_starts_with_rpc_dot_directly,\n Err_Then_is_accessed_on_local_implementation_Please_explicitly_mark_if_it_is_thenable_in_the_options,\n} from './utils/error'\nimport { generateRandomID } from './utils/generateRandomID'\nimport { normalizeStrictOptions, normalizeLogOptions } from './utils/normalizeOptions'\nimport { AsyncCallIgnoreResponse, AsyncCallNotify, AsyncCallBatch } from './utils/internalSymbol'\nimport type { BatchQueue } from './core/batch'\nimport type { CallbackBasedChannel, EventBasedChannel, AsyncCallOptions, ConsoleInterface, _AsyncVersionOf } from './types'\nimport {\n ERROR,\n isArray,\n isFunction,\n isString,\n Promise_reject,\n Promise_resolve,\n replayFunction,\n undefined,\n} from './utils/constants'\n\n/**\n * Create a RPC server & client.\n *\n * @remarks\n * See {@link AsyncCallOptions}\n *\n * thisSideImplementation can be a Promise so you can write:\n *\n * ```ts\n * export const service = AsyncCall(typeof window === 'object' ? {} : import('./backend/service.js'), {})\n * ```\n *\n * @param thisSideImplementation - The implementation when this AsyncCall acts as a JSON RPC server. Can be a Promise.\n * @param options - {@link AsyncCallOptions}\n * @typeParam OtherSideImplementedFunctions - The type of the API that server expose. For any function on this interface, it will be converted to the async version.\n * @returns Same as the `OtherSideImplementedFunctions` type parameter, but every function in that interface becomes async and non-function value is removed. Method called \"then\" are also removed.\n * @public\n */\nexport function AsyncCall<OtherSideImplementedFunctions = {}>(\n thisSideImplementation: null | undefined | object | Promise<object>,\n options: AsyncCallOptions,\n): _AsyncVersionOf<OtherSideImplementedFunctions> {\n let isThisSideImplementationPending = true\n let resolvedThisSideImplementationValue: unknown = undefined\n let rejectedThisSideImplementation: unknown = undefined\n // This promise should never fail\n const awaitThisSideImplementation = async () => {\n try {\n resolvedThisSideImplementationValue = await thisSideImplementation\n } catch (e) {\n rejectedThisSideImplementation = e\n console_error('AsyncCall failed to start', e)\n } finally {\n isThisSideImplementationPending = false\n }\n }\n\n const {\n serializer = NoSerialization,\n key: logKey = 'rpc',\n strict = true,\n log = true,\n parameterStructures = 'by-position',\n preferLocalImplementation = false,\n idGenerator = generateRandomID,\n mapError,\n logger,\n channel,\n thenable,\n } = options\n\n if (thisSideImplementation instanceof Promise) awaitThisSideImplementation()\n else {\n resolvedThisSideImplementationValue = thisSideImplementation\n isThisSideImplementationPending = false\n }\n\n const [banMethodNotFound, banUnknownMessage] = normalizeStrictOptions(strict)\n const [\n log_beCalled,\n log_localError,\n log_remoteError,\n log_pretty,\n log_requestReplay,\n log_sendLocalStack,\n ] = normalizeLogOptions(log)\n const {\n log: console_log,\n error: console_error = console_log,\n debug: console_debug = console_log,\n groupCollapsed: console_groupCollapsed = console_log,\n groupEnd: console_groupEnd = console_log,\n warn: console_warn = console_log,\n } = (logger || console) as ConsoleInterface\n type PromiseParam = [resolve: (value?: any) => void, reject: (reason?: any) => void]\n const requestContext = new Map<string | number, { f: PromiseParam; stack: string }>()\n const onRequest = async (data: Request): Promise<Response | undefined> => {\n if (isThisSideImplementationPending) await awaitThisSideImplementation()\n else {\n // not pending\n if (rejectedThisSideImplementation) return makeErrorObject(rejectedThisSideImplementation, '', data)\n }\n let frameworkStack: string = ''\n try {\n const { params, method, id: req_id, remoteStack } = data\n // ? We're mapping any method starts with 'rpc.' to a Symbol.for\n const key = (method.startsWith('rpc.') ? Symbol.for(method) : method) as keyof object\n const executor: unknown =\n resolvedThisSideImplementationValue && (resolvedThisSideImplementationValue as any)[key]\n if (!isFunction(executor)) {\n if (!banMethodNotFound) {\n if (log_localError) console_debug('Missing method', key, data)\n return\n } else return ErrorResponseMethodNotFound(req_id)\n }\n const args = isArray(params) ? params : [params]\n frameworkStack = removeStackHeader(new Error().stack)\n const promise = new Promise((resolve) => resolve(executor.apply(resolvedThisSideImplementationValue, args)))\n if (log_beCalled) {\n if (log_pretty) {\n const logArgs: unknown[] = [\n `${logKey}.%c${method}%c(${args.map(() => '%o').join(', ')}%c)\\n%o %c@${req_id}`,\n 'color: #d2c057',\n '',\n ...args,\n '',\n promise,\n 'color: gray; font-style: italic;',\n ]\n if (log_requestReplay) {\n // This function will be logged to the console so it must be 1 line\n // prettier-ignore\n const replay = () => { debugger; return executor.apply(resolvedThisSideImplementationValue, args) }\n replay.toString = replayFunction\n logArgs.push(replay)\n }\n if (remoteStack) {\n console_groupCollapsed(...logArgs)\n console_log(remoteStack)\n console_groupEnd()\n } else console_log(...logArgs)\n } else console_log(`${logKey}.${method}(${[...args].toString()}) @${req_id}`)\n }\n const result = await promise\n if (result === AsyncCallIgnoreResponse) return\n return SuccessResponse(req_id, await promise)\n } catch (e) {\n return makeErrorObject(e, frameworkStack, data)\n }\n }\n const onResponse = async (data: Response): Promise<void> => {\n let errorMessage = '',\n remoteErrorStack = '',\n errorCode = 0,\n errorType = ERROR\n if (hasKey(data, 'error')) {\n const e = data.error\n errorMessage = e.message\n errorCode = e.code\n const detail = e.data\n\n if (isObject(detail) && hasKey(detail, 'stack') && isString(detail.stack)) remoteErrorStack = detail.stack\n else remoteErrorStack = '<remote stack not available>'\n\n if (isObject(detail) && hasKey(detail, 'type') && isString(detail.type)) errorType = detail.type\n else errorType = ERROR\n\n if (log_remoteError)\n log_pretty\n ? console_error(\n `${errorType}: ${errorMessage}(${errorCode}) %c@${data.id}\\n%c${remoteErrorStack}`,\n 'color: gray',\n '',\n )\n : console_error(`${errorType}: ${errorMessage}(${errorCode}) @${data.id}\\n${remoteErrorStack}`)\n }\n if (data.id === null || data.id === undefined) return\n const { f: [resolve, reject] = [null, null], stack: localErrorStack = '' } = requestContext.get(data.id) || {}\n if (!resolve || !reject) return // drop this response\n requestContext.delete(data.id)\n if (hasKey(data, 'error')) {\n reject(\n RecoverError(\n errorType,\n errorMessage,\n errorCode,\n // ? We use \\u0430 which looks like \"a\" to prevent browser think \"at AsyncCall\" is a real stack\n remoteErrorStack + '\\n \\u0430t AsyncCall (rpc) \\n' + localErrorStack,\n ),\n )\n } else {\n resolve(data.result)\n }\n return\n }\n const rawMessageReceiver = async (_: unknown): Promise<undefined | Response | (Response | undefined)[]> => {\n let data: unknown\n let result: Response | undefined = undefined\n try {\n data = await deserialization(_)\n if (isJSONRPCObject(data)) {\n return (result = await handleSingleMessage(data))\n } else if (isArray(data) && data.every(isJSONRPCObject) && data.length !== 0) {\n return Promise.all(data.map(handleSingleMessage))\n } else {\n if (banUnknownMessage) {\n let id = (data as any).id\n if (id === undefined) id = null\n return ErrorResponseInvalidRequest(id)\n } else {\n // ? Ignore this message. The message channel maybe also used to transfer other message too.\n return undefined\n }\n }\n } catch (e) {\n if (log_localError) console_error(e, data, result)\n return ErrorResponseParseError(e, mapError || defaultErrorMapper(e && e.stack))\n }\n }\n const rawMessageSender = async (res: undefined | Response | (Response | undefined)[]) => {\n if (!res) return\n if (isArray(res)) {\n const reply = res.filter((x) => x && hasKey(x, 'id'))\n if (reply.length === 0) return\n return serialization(reply)\n } else {\n return serialization(res)\n }\n }\n const serialization = (x: unknown) => serializer.serialization(x)\n const deserialization = (x: unknown) => serializer.deserialization(x)\n const isEventBasedChannel = (x: typeof channel): x is EventBasedChannel => hasKey(x, 'send') && isFunction(x.send)\n const isCallbackBasedChannel = (x: typeof channel): x is CallbackBasedChannel =>\n hasKey(x, 'setup') && isFunction(x.setup)\n\n if (isCallbackBasedChannel(channel)) {\n channel.setup(\n (data) => rawMessageReceiver(data).then(rawMessageSender),\n (data) => {\n const _ = deserialization(data)\n if (isJSONRPCObject(_)) return true\n return Promise_resolve(_).then(isJSONRPCObject)\n },\n )\n }\n if (isEventBasedChannel(channel)) {\n const m = channel as EventBasedChannel | CallbackBasedChannel\n m.on &&\n m.on((_) =>\n rawMessageReceiver(_)\n .then(rawMessageSender)\n .then((x) => x && m.send!(x)),\n )\n }\n function makeErrorObject(e: any, frameworkStack: string, data: Request) {\n if (isObject(e) && hasKey(e, 'stack'))\n e.stack = frameworkStack\n .split('\\n')\n .reduce((stack, fstack) => stack.replace(fstack + '\\n', ''), '' + e.stack)\n if (log_localError) console_error(e)\n return ErrorResponseMapped(data, e, mapError || defaultErrorMapper(log_sendLocalStack ? e.stack : undefined))\n }\n\n async function sendPayload(payload: unknown, removeQueueR = false) {\n if (removeQueueR) payload = [...(payload as BatchQueue)]\n const data = await serialization(payload)\n return channel.send!(data)\n }\n function rejectsQueue(queue: BatchQueue, error: unknown) {\n for (const x of queue) {\n if (hasKey(x, 'id')) {\n const ctx = requestContext.get(x.id!)\n ctx && ctx.f[1](error)\n }\n }\n }\n const handleSingleMessage = async (\n data: SuccessResponse | ErrorResponse | Request,\n ): Promise<SuccessResponse | ErrorResponse | undefined> => {\n if (hasKey(data, 'method')) {\n const r = onRequest(data)\n if (hasKey(data, 'id')) return r\n try {\n await r\n } catch {}\n return undefined // Does not care about return result for notifications\n }\n return onResponse(data) as Promise<undefined>\n }\n return new Proxy({ __proto__: null } as any, {\n get(cache, method: string | symbol) {\n if (method === 'then') {\n if (thenable === undefined) {\n console_warn(\n makeHostedMessage(\n Err_Then_is_accessed_on_local_implementation_Please_explicitly_mark_if_it_is_thenable_in_the_options,\n new TypeError('RPC used as Promise: '),\n ),\n )\n }\n if (thenable !== true) return undefined\n }\n if (isString(method) && cache[method]) return cache[method]\n const factory = (notify: boolean) => (...params: unknown[]) => {\n let stack = removeStackHeader(new Error().stack)\n let queue: BatchQueue | undefined = undefined\n if (method === AsyncCallBatch) {\n queue = params.shift() as any\n method = params.shift() as any\n }\n if (typeof method === 'symbol') {\n const RPCInternalMethod = Symbol.keyFor(method) || (method as any).description\n if (RPCInternalMethod) {\n if (RPCInternalMethod.startsWith('rpc.')) method = RPCInternalMethod\n else return Promise_reject(new TypeError('Not start with rpc.'))\n }\n } else if (method.startsWith('rpc.'))\n return Promise_reject(\n makeHostedMessage(Err_Cannot_call_method_starts_with_rpc_dot_directly, new TypeError()),\n )\n return new Promise<void>((resolve, reject) => {\n if (preferLocalImplementation && !isThisSideImplementationPending && isString(method)) {\n const localImpl: unknown =\n resolvedThisSideImplementationValue && (resolvedThisSideImplementationValue as any)[method]\n if (isFunction(localImpl)) return resolve(localImpl(...params))\n }\n const id = idGenerator()\n const [param0] = params\n const sendingStack = log_sendLocalStack ? stack : ''\n const param =\n parameterStructures === 'by-name' && params.length === 1 && isObject(param0) ? param0 : params\n const request = Request(notify ? undefined : id, method as string, param, sendingStack)\n if (queue) {\n queue.push(request)\n if (!queue.r) queue.r = [() => sendPayload(queue, true), (e) => rejectsQueue(queue!, e)]\n } else sendPayload(request).catch(reject)\n if (notify) return resolve()\n requestContext.set(id, {\n f: [resolve, reject],\n stack,\n })\n })\n }\n const f = factory(false)\n // @ts-ignore\n f[AsyncCallNotify] = factory(true)\n // @ts-ignore\n f[AsyncCallNotify][AsyncCallNotify] = f[AsyncCallNotify]\n isString(method) && Object.defineProperty(cache, method, { value: f, configurable: true })\n return f\n },\n }) as _AsyncVersionOf<OtherSideImplementedFunctions>\n}\n// Assume a console object in global if there is no custom logger provided\ndeclare const console: ConsoleInterface\n"],"names":[],"mappings":";;;;;;;IAAA;IACA;IACA;IACA;IACA;;;;;IAKA;IACA;IACA;IACA;IACA;IACA;IACA;;IAEA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;;IAEA;IACA;IACA;;IAEA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;;IAEA;;IAEA;IACA;IACA;IACA;IACA;;;;;;;;;;;;;;AC3DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;IAEA;IACA;IACA;IACA;IACA;AACA;IACA;IACA;IACA;AACA;AACA;AACA;AACA;AACA;AACA;;IAEA;IACA;IACA;IACA;AACA;IACA;IACA;IACA;IACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;IAEA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;;IAEA;IACA;IACA;IACA;IACA;IACA;AACA;IACA;IACA;IACA;;;AAGA;AACA;AACA;AACA;AACA;;IAEA;IACA;IACA;IACA;AACA;;IAEA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;AACA;IACA;IACA;IACA;AACA;AACA;;IAEA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;AAGA;;IAEA;IACA;AACA;AACA;AACA;IACA;AACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;;IC1IA;AAIA;AACA;AACA;IACA;IACA;IACA;IACA;IACA;;IAEA;IACA;IACA;IACA;IACA;IACA;IACA;AACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;;IAEA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;;ICrEA;IACA;;;;;ICEA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;AACA;;IAEA;IACA;IACA;IACA;IACA;IACA;;ICjCA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;;IAEA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;;;;IC3CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;IAEA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;AACA;;IAEA;IACA;IACA;IACA;IACA;IACA;;ICSA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;;IAEA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;AACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;AACA;IACA;IACA;IACA;IACA;IACA;AACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;AACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;AACA;IACA;IACA;AACA;IACA;IACA;AACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;AACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;AACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;;;;;;;;;;;;;;"}
\No newline at end of file