Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

async-call-rpc

Package Overview
Dependencies
Maintainers
1
Versions
34
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

async-call-rpc - npm Package Compare versions

Comparing version 3.2.2 to 3.3.0

src/types.ts

17

CHANGELOG.md

@@ -5,2 +5,19 @@ # Changelog

## [3.3.0](https://github.com/Jack-Works/async-call/compare/v3.2.2...v3.3.0) (2020-07-19)
### Deprecation
* Old MessageChannel is deprecated, please use new [CallbackBasedChannel](https://jack-works.github.io/async-call-rpc/async-call-rpc.callbackbasedchannel.html) or [EventBasedChannel](https://jack-works.github.io/async-call-rpc/async-call-rpc.eventbasedchannel.html).
### Features
* impl requestReplay in log, close [#22](https://github.com/Jack-Works/async-call/issues/22) ([d241b34](https://github.com/Jack-Works/async-call/commit/d241b34ddcb47313e74c96662cb16e39d7876d43))
* new interface for messageChannel and deprecates old, close [#19](https://github.com/Jack-Works/async-call/issues/19) ([7022b8c](https://github.com/Jack-Works/async-call/commit/7022b8c78235e53cd1215c12990f1e11bdfff01b))
### Bug Fixes
* install error ([4b3d78f](https://github.com/Jack-Works/async-call/commit/4b3d78fd106bd9384de001db33eb41b0958339be))
### [3.2.2](https://github.com/Jack-Works/async-call/compare/v3.2.1...v3.2.2) (2020-06-28)

@@ -7,0 +24,0 @@

97

out/base.d.ts

@@ -40,2 +40,3 @@ /**

declare const JSONSerialization: (replacerAndReceiver?: [(((key: string, value: any) => any) | undefined)?, (((key: string, value: any) => any) | undefined)?], space?: string | number | undefined, undefinedKeepingBehavior?: 'keep' | 'null' | false) => Serialization;
//# sourceMappingURL=serialization.d.ts.map

@@ -52,21 +53,60 @@ /**

error?(...args: unknown[]): void;
}
warn?(...args: unknown[]): void;
}//# sourceMappingURL=console.d.ts.map
/**
* Wrap the AsyncCall instance to send notification.
* @param instanceOrFnOnInstance The AsyncCall instance or function on the AsyncCall instance
* @param instanceOrFnOnInstance - The AsyncCall instance or function on the AsyncCall instance
* @example
* const notifyOnly = notify(AsyncCall(...))
* @public
*/
declare function notify<T extends object>(instanceOrFnOnInstance: T): _IgnoreResponse<T>;
//# sourceMappingURL=notify.d.ts.map
/**
* Wrap the AsyncCall instance to use batch call.
* @param asyncCallInstance
* @param asyncCallInstance - The AsyncCall instance
* @example
* const [batched, send, drop] = batch(AsyncCall(...))
* @public
*/
declare function batch<T extends object>(asyncCallInstance: T): [T, () => void, (error?: unknown) => void];
declare function batch<T extends object>(asyncCallInstance: T): [T, () => void, (error?: unknown) => void];//# sourceMappingURL=batch.d.ts.map
/**
* This interface represents a "on message"-"send response" model.
* @remarks
* Usually used for there is only 1 remote (act like a client).
* @public
*/
interface EventBasedChannel<Data = unknown> {
/**
* Register the message listener.
* @param listener - The message listener.
* @returns a function that unregister the listener.
*/
on(listener: (data: Data) => void): void | (() => void);
/**
* Send the data to the remote side.
* @param data - The data should send to the remote side.
*/
send(data: Data): void;
}
/**
* This interface represents a "callback" model.
* @remarks
* Usually used for there are many remotes (act like a server).
* @public
*/
interface CallbackBasedChannel<Data = unknown> extends Partial<EventBasedChannel<Data>> {
/**
* Setup the CallbackBasedChannel..
* @param jsonRPCHandlerCallback - A function that will execute the JSON RPC request then give the result back. If the result is undefined, it means no response is created.
* @param isValidPayload - A util function that will try to validate if the message is a valid JSON RPC request. It will be asynchronous if possible.
*/
setup(jsonRPCHandlerCallback: (jsonRPCPayload: unknown) => Promise<unknown | undefined>, isValidJSONRPCPayload: (data: unknown) => boolean | Promise<boolean>): (() => void) | void;
}
//# sourceMappingURL=types.d.ts.map
/**
* What should AsyncCall log to console.

@@ -101,2 +141,7 @@ * @public

type?: 'basic' | 'pretty';
/**
* Log a function that allows to execute the request again.
* @defaultValue false
*/
requestReplay?: boolean;
}

@@ -122,2 +167,3 @@ /**

* @public
* @deprecated Will be removed in the next major version.
*/

@@ -127,4 +173,4 @@ interface MessageChannel<Context = unknown> {

* AsyncCall will attach a listener to receive messages.
* @param event The emitting event name (if supported).
* @param eventListener The listener have two parameters. The first one is the received data. The second one is an identifier to identify who send this request. When responding, AsyncCall will call the emit with the same context.
* @param event - The emitting event name (if supported).
* @param eventListener - The listener have two parameters. The first one is the received data. The second one is an identifier to identify who send this request. When responding, AsyncCall will call the emit with the same context.
*/

@@ -134,5 +180,5 @@ on(event: string, eventListener: (data: unknown, context?: Context) => void): void;

* AsyncCall will send message by this method.
* @param event The emitting event name (if supported).
* @param data The sending data.
* @param context The same context provided to the second parameter of on.eventListener.
* @param event - The emitting event name (if supported).
* @param data - The sending data.
* @param context - The same context provided to the second parameter of on.eventListener.
*/

@@ -150,13 +196,6 @@ emit(event: string, data: unknown, context?: Context): void;

* @remarks
* The value can be anything, but need to be same on both sides.
* The value can be anything, but need to be same on both sides if you're using the deprecated MessageChannel interface.
* If you're using other recommended interface for channel like EventBasedChannel or CallbackBasedChannel,
* this option will only used for better logging.
*
* This option is useful when you want to run multiple AsyncCall instances on the same message channel.
*
* @example
* these two AsyncCall run on the same channel but they won't affect each other.
* ```ts
* AsyncCall({}, { messageChannel, key: 'app1' })
* AsyncCall({}, { messageChannel, key: 'app2' })
* ```
*
* @defaultValue `default-jsonrpc`

@@ -190,3 +229,3 @@ */

* ```ts
* const messageChannel = {
* const channel = {
* on(event, callback) {

@@ -200,5 +239,12 @@ * document.addEventListener('remote-data', x => callback(x.details))

* ```
* @remarks
* If you're using this new property, you can use "messageChannel: undefined!" to disable the type system error.
*/
messageChannel: MessageChannel;
channel?: CallbackBasedChannel | EventBasedChannel;
/**
* Leave this option "undefined!" if you're providing channel.
* @deprecated renamed to "channel". In next major version, this option will be removed and the "channel" property will be required.
*/
messageChannel: MessageChannel | CallbackBasedChannel | EventBasedChannel;
/**
* Choose log level. See {@link AsyncCallLogLevel}

@@ -241,3 +287,3 @@ * @defaultValue true

* The ID generator of each JSON RPC request
* @defaultValue () => Math.random().toString(36).slice(2)
* @defaultValue () =\> Math.random().toString(36).slice(2)
*/

@@ -247,4 +293,4 @@ idGenerator?(): string | number;

* Control the error response data
* @param error The happened Error
* @param request The request object
* @param error - The happened Error
* @param request - The request object
*/

@@ -298,3 +344,4 @@ mapError?: ErrorMapFunction<unknown>;

declare function AsyncCall<OtherSideImplementedFunctions = {}>(thisSideImplementation: object | Promise<object> | undefined, options: AsyncCallOptions): _AsyncVersionOf<OtherSideImplementedFunctions>;
//# sourceMappingURL=Async-Call.d.ts.map
export { AsyncCall, AsyncCallLogLevel, AsyncCallOptions, AsyncCallStrictJSONRPC, Console, ErrorMapFunction, JSONSerialization, MessageChannel, NoSerialization, Serialization, _AsyncVersionOf, _IgnoreResponse, batch, notify };
export { AsyncCall, AsyncCallLogLevel, AsyncCallOptions, AsyncCallStrictJSONRPC, CallbackBasedChannel, Console, ErrorMapFunction, EventBasedChannel, JSONSerialization, MessageChannel, NoSerialization, Serialization, _AsyncVersionOf, _IgnoreResponse, batch, notify };
/// <reference types="./base.d.ts" />
((e,r)=>{"object"==typeof exports&&"undefined"!=typeof module?r(exports):"function"==typeof define&&define.amd?define(["exports"],r):r((e=e||self).AsyncCall={})})(this,(function(e){"use strict"
class r extends Error{constructor(e,r,t,o){super(r),this.name=e,this.code=t,this.stack=o}}const t={Error,EvalError,RangeError,ReferenceError,SyntaxError,TypeError,URIError}
function o(e=""){return e.replace(/^.+\n.+\n/,"")}const n=(()=>{const e=Reflect.get(globalThis,"DOMException")
if("function"==typeof e)return e})()
function i(e,r,t,o){void 0===e&&(e=null),Number.isNaN(r=Math.floor(r))&&(r=-1)
const n={jsonrpc:"2.0",id:e,error:{code:r,message:t,data:o}}
return d(n.error,"data"),n}function a(e,r,t){const{id:o}=e,{code:n,message:a,data:s}=t(r,e)
return i(o,n,a,s)}i.ParseError=(e,r)=>{const t=a({},e,r),o=t.error
return o.code=-32700,o.message="Parse error",t},i.InvalidRequest=e=>i(e,-32600,"Invalid Request"),i.MethodNotFound=e=>i(e,-32601,"Method not found")
const s=(e="",r=-1)=>t=>{let o=""
l(t)&&u(t,"message")&&"string"==typeof t.message&&(o=t.message)
let i=((e,r)=>{let o="Error"
try{o=null===(i=null===(n=t)||void 0===n?void 0:n.constructor)||void 0===i?void 0:i.name}catch(n){}var n,i
return"string"!=typeof o?"Error":o})()
return n&&t instanceof n&&(i="DOMException:"+t.name),"string"!=typeof t&&"number"!=typeof t&&"boolean"!=typeof t&&"bigint"!=typeof t||(i="Error",o=t+""),{code:r,message:o,data:e?{stack:e,type:i}:{type:i}}}
function c(e){if(!l(e))return!1
if(!u(e,"jsonrpc"))return!1
if("2.0"!==e.jsonrpc)return!1
if(u(e,"params")){const r=e.params
if(!Array.isArray(r)&&!l(r))return!1}return!0}function l(e){return"object"==typeof e&&null!==e}function u(e,r){return r in e}function d(e,r){void 0===e[r]&&delete e[r]}const f={serialization:e=>e,deserialization:e=>e},p=Symbol.for("AsyncCall/ignored"),y=Symbol.for("AsyncCall/notify"),m=Symbol.for("AsyncCall/batch")
function g(e,r){return e[r][y]}async function h(e,r,t,n){return new Promise((i,a)=>{var s
let c={}
try{c=document.createElement("iframe"),c.style.display="none",document.body.appendChild(c)
{const s=c.contentDocument,l=c.contentWindow,u=s.createElement("button")
s.body.appendChild(u),u.onclick=()=>new l.Promise(a=>{(async()=>{e(o(Error().stack)),i(await r.apply(t,n))})().then(a)}),l.onunhandledrejection=e=>a(e.reason),u.click()}}catch(e){try{console.error("Please close preservePauseOnException.",e)}catch(e){}return i(r(...n))}finally{null===(s=null==c?void 0:c.remove)||void 0===s||s.call(c)}})}const v={serializer:f,key:"default-jsonrpc",strict:!0,log:!0,parameterStructures:"by-position",preferLocalImplementation:!1,preservePauseOnException:!1,idGenerator:()=>Math.random().toString(36).slice(2)}
e.AsyncCall=function(e={},f){let g=void 0
e instanceof Promise||(g=e),Promise.resolve(e).then(e=>g=e)
const{serializer:E,key:b,strict:k,log:w,parameterStructures:$,preferLocalImplementation:P,preservePauseOnException:S,idGenerator:A,mapError:j}={...v,...f},x=f.messageChannel,{methodNotFound:C=!1,unknownMessage:O=!1}=(e=>"boolean"!=typeof e?e:{methodNotFound:e,unknownMessage:e})(k),{beCalled:M=!0,localError:z=!0,remoteError:N=!0,type:R="pretty",sendLocalStack:I=!1}=(e=>"boolean"!=typeof e?e:{beCalled:e,localError:e,remoteError:e,type:e?"pretty":"basic"})(w),D=(e=>{const r=e||globalThis.console,t=(...e)=>r.log(...e)
return Object.assign({},{debug:t,error:t,groupCollapsed:t,groupEnd:t,log:t},r)})(f.logger),F=new Map
return x.on(b,async(e,r)=>{var t
let o,n=void 0
try{if(o=await E.deserialization(e),c(o))n=await q(o),n&&await a(n)
else if(Array.isArray(o)&&o.every(c)&&0!==o.length){const e=await Promise.all(o.map(q))
if(o.every(e=>void 0===e))return
await a(e.filter(e=>e))}else O&&await a(i.InvalidRequest(null!==(t=o.id)&&void 0!==t?t:null))}catch(e){z&&D.error(e,o,n),a(i.ParseError(e,j||s(null==e?void 0:e.stack)))}async function a(e){if(Array.isArray(e)){const t=e.filter(e=>u(e,"id"))
if(0===t.length)return
x.emit(b,await E.serialization(t),r)}else{if(!e)return
if(!u(e,"id"))return
x.emit(b,await E.serialization(e),r)}}}),new Proxy({},{get(e,r){let t=o(Error().stack)
const n=e=>(...o)=>{let n=void 0
if(r===m&&(n=o.shift(),r=o.shift()),"symbol"==typeof r){const e=Symbol.keyFor(r)||r.description
if(e){if(!e.startsWith("rpc."))return Promise.reject('[AsyncCall] An internal method must start with "rpc."')
r=e}}else if(r.startsWith("rpc."))return Promise.reject(new TypeError("[AsyncCall] Can't call internal methods directly"))
if(P&&g&&"string"==typeof r){const e=g[r]
if(e&&"function"==typeof e)return new Promise(r=>r(e(...o)))}return new Promise((i,a)=>{const s=A(),[c]=o,u=I?t:"",f="by-name"===$&&1===o.length&&l(c)?c:o,p=((e,r,t,o)=>{const n={jsonrpc:"2.0",id:e,method:r,params:t,remoteStack:o}
return d(n,"id"),((e,r)=>{e[r]||delete e[r]})(n,"remoteStack"),n})(e?void 0:s,r,f,u)
if(n?(n.push(p),n.r||(n.r=[()=>T(n),W.bind(n)])):T(p).catch(a),e)return i()
F.set(s,{f:[i,a],stack:t})})},i=n(!1)
return i[y]=n(!0),i[y][y]=i[y],i}})
async function T(e){const r=await E.serialization(e)
x.emit(b,r)}function W(e){var r
for(const t of this)u(t,"id")&&(null===(r=F.get(t.id))||void 0===r||r.f[1](e))}async function q(c){return u(c,"method")?async function(r){g||await e
let t=""
try{const e=r.method.startsWith("rpc.")?Symbol.for(r.method):r.method,n=g[e]
if("function"!=typeof n)return C?i.MethodNotFound(r.id):void(z&&D.debug("Receive remote call, but not implemented.",e,r))
const{params:a}=r,s=Array.isArray(a)?a:[a]
t=o(Error().stack)
const c=S?h(e=>t=e,n,g,s):new Promise(e=>e(n.apply(g,s)))
if(M)if("basic"===R)D.log(`${f.key}.${r.method}(${""+[...s]}) @${r.id}`)
else{const e=[`${f.key}.%c${r.method}%c(${s.map(()=>"%o").join(", ")}%c)\n%o %c@${r.id}`,"color: #d2c057","",...s,"",c,"color: gray; font-style: italic;"]
r.remoteStack?(D.groupCollapsed(...e),D.log(r.remoteStack),D.groupEnd()):D.log(...e)}if(await c===p)return
return((e,r)=>{const t={jsonrpc:"2.0",id:e,result:r}
return d(t,"id"),t})(r.id,await c)}catch(e){return"object"==typeof e&&"stack"in e&&(e.stack=t.split("\n").reduce((e,r)=>e.replace(r+"\n",""),e.stack||"")),z&&D.error(e),a(r,e,j||s(I?e.stack:void 0))}}(c):async function(e){let o="",i="",a=0,s="Error"
if(u(e,"error")){const r=e.error
o=r.message,a=r.code
const t=r.data
i=l(t)&&u(t,"stack")&&"string"==typeof t.stack?t.stack:"<remote stack not available>",s=l(t)&&u(t,"type")&&"string"==typeof t.type?t.type:"Error",N&&("basic"===R?D.error(`${s}: ${o}(${a}) @${e.id}\n${i}`):D.error(`${s}: ${o}(${a}) %c@${e.id}\n%c${i}`,"color: gray",""))}if(null===e.id||void 0===e.id)return
const{f:[c,d],stack:f}=F.get(e.id)||{stack:"",f:[null,null]}
c&&(F.delete(e.id),u(e,"error")?d(((e,o,i,a)=>{try{if(e.startsWith("DOMException:")&&n){const[,r]=e.split("DOMException:")
return new n(o,r)}if(e in t){const r=new t[e](o)
return r.stack=a,Object.assign(r,{code:i}),r}return new r(e,o,i,a)}catch(r){return Error(`E${i} ${e}: ${o}\n${a}`)}})(s,o,a,i+"\n аt AsyncCall (rpc) \n"+f)):c(e.result))}(c)}},e.JSONSerialization=(e=[void 0,void 0],r,t="null")=>({serialization(o){if(t&&l(o)&&u(o,"result")&&void 0===o.result){const e=Object.assign({},o)
e.result=null,"keep"===t&&(e.undef=!0),o=e}return JSON.stringify(o,e[0],r)},deserialization(r){const t=JSON.parse(r,e[1])
return l(t)&&u(t,"result")&&null===t.result&&u(t,"undef")&&!0===t.undef&&(t.result=void 0,delete t.undef),t}}),e.NoSerialization=f,e.batch=e=>{let r=[]
return[new Proxy(e,{get(e,t){const o=(...o)=>e[m](r,t,...o)
return(o[y]=(...o)=>e[m][y](r,t,...o))[y]=o[y],o}}),()=>{var e
return null===(e=r.r)||void 0===e?void 0:e[0]()},(e=Error("Aborted"))=>{var t
null===(t=r.r)||void 0===t||t[1](e),r=[]}]},e.notify=e=>"function"==typeof e?e[y]:new Proxy(e,{get:g}),Object.defineProperty(e,"__esModule",{value:!0})}))
((e,r)=>{"object"==typeof exports&&"undefined"!=typeof module?r(exports):"function"==typeof define&&define.amd?define(["exports"],r):r((e=e||self).AsyncCall={})})(this,(function(e){"use strict";class r extends Error{constructor(e,r,t,n){super(r),this.name=e,this.code=t,this.stack=n}}const t={Error,EvalError,RangeError,ReferenceError,SyntaxError,TypeError,URIError};function n(e=""){return e.replace(/^.+\n.+\n/,"")}const o=(()=>{const e=Reflect.get(globalThis,"DOMException");if("function"==typeof e)return e})();function i(e,r,t,n){void 0===e&&(e=null),Number.isNaN(r=Math.floor(r))&&(r=-1);const o={jsonrpc:"2.0",id:e,error:{code:r,message:t,data:n}};return d(o.error,"data"),o}function a(e,r,t){const{id:n}=e,{code:o,message:a,data:s}=t(r,e);return i(n,o,a,s)}i.ParseError=(e,r)=>{const t=a({},e,r),n=t.error;return n.code=-32700,n.message="Parse error",t},i.InvalidRequest=e=>i(e,-32600,"Invalid Request"),i.MethodNotFound=e=>i(e,-32601,"Method not found");const s=(e="",r=-1)=>t=>{let n="";l(t)&&u(t,"message")&&"string"==typeof t.message&&(n=t.message);let i=((e,r)=>{let n="Error";try{n=null===(i=null===(o=t)||void 0===o?void 0:o.constructor)||void 0===i?void 0:i.name}catch(o){}var o,i;return"string"!=typeof n?"Error":n})();return o&&t instanceof o&&(i="DOMException:"+t.name),"string"!=typeof t&&"number"!=typeof t&&"boolean"!=typeof t&&"bigint"!=typeof t||(i="Error",n=t+""),{code:r,message:n,data:e?{stack:e,type:i}:{type:i}}};function c(e){if(!l(e))return!1;if(!u(e,"jsonrpc"))return!1;if("2.0"!==e.jsonrpc)return!1;if(u(e,"params")){const r=e.params;if(!Array.isArray(r)&&!l(r))return!1}return!0}function l(e){return"object"==typeof e&&null!==e}function u(e,r){return r in e}function d(e,r){void 0===e[r]&&delete e[r]}const f={serialization:e=>e,deserialization:e=>e},p=Symbol.for("AsyncCall/ignored"),y=Symbol.for("AsyncCall/notify"),m=Symbol.for("AsyncCall/batch");function h(e,r){return e[r][y]}async function g(e,r,t,o){return new Promise((i,a)=>{var s;let c={};try{c=document.createElement("iframe"),c.style.display="none",document.body.appendChild(c);{const s=c.contentDocument,l=c.contentWindow,u=s.createElement("button");s.body.appendChild(u),u.onclick=()=>new l.Promise(a=>{(async()=>{e(n(Error().stack)),i(await r.apply(t,o))})().then(a)}),l.onunhandledrejection=e=>a(e.reason),u.click()}}catch(e){try{console.error("Please close preservePauseOnException.",e)}catch(e){}return i(r(...o))}finally{null===(s=null==c?void 0:c.remove)||void 0===s||s.call(c)}})}const v={serializer:f,key:"default-jsonrpc",strict:!0,log:!0,parameterStructures:"by-position",preferLocalImplementation:!1,preservePauseOnException:!1,idGenerator:()=>Math.random().toString(36).slice(2)};e.AsyncCall=function(e={},f){var h;let E=void 0;e instanceof Promise||(E=e),Promise.resolve(e).then(e=>E=e);const{serializer:b,key:w,strict:k,log:P,parameterStructures:$,preferLocalImplementation:S,preservePauseOnException:C,idGenerator:A,mapError:j,logger:x,channel:O,channel:z}={...v,...f},{methodNotFound:M=!1,unknownMessage:R=!1}=(e=>"boolean"!=typeof e?e:{methodNotFound:e,unknownMessage:e})(k),{beCalled:N=!0,localError:I=!0,remoteError:T=!0,type:D="pretty",sendLocalStack:F=!1,requestReplay:W=!1}=(e=>"boolean"!=typeof e?e:{beCalled:e,localError:e,remoteError:e,type:e?"pretty":"basic"})(P),q=(e=>{const r=e||globalThis.console,t=(...e)=>r.log(...e);return Object.assign({},{debug:t,error:t,groupCollapsed:t,groupEnd:t,log:t,warn:t},r)})(x),J=z||O;if(O&&!z&&q.warn("Deprecation: messageChannel has renamed to channel"),!J)throw Error();const L=new Map;async function B(e){var r;let t;try{if(t=await b.deserialization(e),c(t))return await Q(t);if(Array.isArray(t)&&t.every(c)&&0!==t.length){const e=await Promise.all(t.map(Q));if(t.every(e=>void 0===e))return;return e.filter(e=>e)}return R?i.InvalidRequest(null!==(r=t.id)&&void 0!==r?r:null):void 0}catch(e){return I&&q.error(e,t,void 0),i.ParseError(e,j||s(null==e?void 0:e.stack))}}async function G(e){if(e){if(Array.isArray(e)){const r=e.filter(e=>u(e,"id"));if(0===r.length)return;return b.serialization(r)}if(u(e,"id"))return b.serialization(e)}}function U(e){return u(e,"send")&&"function"==typeof e.send}if(u(_=J,"emit")&&"function"==typeof _.emit)q.warn("The interface you're using in channel is deprecated. Please switch to EventBasedChannel or CallbackBasedChannel"),J.on(w,async(e,r)=>{const t=await B(e);t&&J.emit(w,t,r)});else if((e=>u(e,"setup")&&"function"==typeof e.setup)(J))J.setup(e=>B(e).then(G),e=>{const r=b.deserialization(e);return!!c(r)||Promise.resolve(r).then(c)});else if(!U(J))throw new TypeError("Invalid channel");var _;if(U(J)){const e=J;null===(h=e.on)||void 0===h||h.call(e,r=>B(r).then(G).then(r=>r&&e.send(r)))}return new Proxy({},{get(e,r){let t=n(Error().stack);const o=e=>(...n)=>{let o=void 0;if(r===m&&(o=n.shift(),r=n.shift()),"symbol"==typeof r){const e=Symbol.keyFor(r)||r.description;if(e){if(!e.startsWith("rpc."))return Promise.reject('[AsyncCall] An internal method must start with "rpc."');r=e}}else if(r.startsWith("rpc."))return Promise.reject(new TypeError("[AsyncCall] Can't call internal methods directly"));if(S&&E&&"string"==typeof r){const e=E[r];if(e&&"function"==typeof e)return new Promise(r=>r(e(...n)))}return new Promise((i,a)=>{const s=A(),[c]=n,u=F?t:"",f="by-name"===$&&1===n.length&&l(c)?c:n,p=((e,r,t,n)=>{const o={jsonrpc:"2.0",id:e,method:r,params:t,remoteStack:n};return d(o,"id"),((e,r)=>{e[r]||delete e[r]})(o,"remoteStack"),o})(e?void 0:s,r,f,u);if(o?(o.push(p),o.r||(o.r=[()=>H(o),K.bind(o)])):H(p).catch(a),e)return i();L.set(s,{f:[i,a],stack:t})})},i=o(!1);return i[y]=o(!0),i[y][y]=i[y],i}});async function H(e){const r=await b.serialization(e);return u(J,"emit")?J.emit(w,r):J.send(r)}function K(e){var r;for(const t of this)u(t,"id")&&(null===(r=L.get(t.id))||void 0===r||r.f[1](e))}async function Q(c){return u(c,"method")?async function(r){E||await e;let t="";try{const e=r.method.startsWith("rpc.")?Symbol.for(r.method):r.method,o=E[e];if("function"!=typeof o)return M?i.MethodNotFound(r.id):void(I&&q.debug("Receive remote call, but not implemented.",e,r));const{params:a}=r,s=Array.isArray(a)?a:[a];t=n(Error().stack);const c=C?g(e=>t=e,o,E,s):new Promise(e=>e(o.apply(E,s)));if(N)if("basic"===D)q.log(`${w}.${r.method}(${""+[...s]}) @${r.id}`);else{const e=[`${w}.%c${r.method}%c(${s.map(()=>"%o").join(", ")}%c)\n%o %c@${r.id}`,"color: #d2c057","",...s,"",c,"color: gray; font-style: italic;"];W&&e.push(()=>{debugger;return o.apply(E,s)}),r.remoteStack?(q.groupCollapsed(...e),q.log(r.remoteStack),q.groupEnd()):q.log(...e)}if(await c===p)return;return((e,r)=>{const t={jsonrpc:"2.0",id:e,result:r};return d(t,"id"),t})(r.id,await c)}catch(e){return"object"==typeof e&&"stack"in e&&(e.stack=t.split("\n").reduce((e,r)=>e.replace(r+"\n",""),e.stack||"")),I&&q.error(e),a(r,e,j||s(F?e.stack:void 0))}}(c):async function(e){let n="",i="",a=0,s="Error";if(u(e,"error")){const r=e.error;n=r.message,a=r.code;const t=r.data;i=l(t)&&u(t,"stack")&&"string"==typeof t.stack?t.stack:"<remote stack not available>",s=l(t)&&u(t,"type")&&"string"==typeof t.type?t.type:"Error",T&&("basic"===D?q.error(`${s}: ${n}(${a}) @${e.id}\n${i}`):q.error(`${s}: ${n}(${a}) %c@${e.id}\n%c${i}`,"color: gray",""))}if(null===e.id||void 0===e.id)return;const{f:[c,d],stack:f}=L.get(e.id)||{stack:"",f:[null,null]};c&&(L.delete(e.id),u(e,"error")?d(((e,n,i,a)=>{try{if(e.startsWith("DOMException:")&&o){const[,r]=e.split("DOMException:");return new o(n,r)}if(e in t){const r=new t[e](n);return r.stack=a,Object.assign(r,{code:i}),r}return new r(e,n,i,a)}catch(r){return Error(`E${i} ${e}: ${n}\n${a}`)}})(s,n,a,i+"\n аt AsyncCall (rpc) \n"+f)):c(e.result))}(c)}},e.JSONSerialization=(e=[void 0,void 0],r,t="null")=>({serialization(n){if(t&&l(n)&&u(n,"result")&&void 0===n.result){const e=Object.assign({},n);e.result=null,"keep"===t&&(e.undef=!0),n=e}return JSON.stringify(n,e[0],r)},deserialization(r){const t=JSON.parse(r,e[1]);return l(t)&&u(t,"result")&&null===t.result&&u(t,"undef")&&!0===t.undef&&(t.result=void 0,delete t.undef),t}}),e.NoSerialization=f,e.batch=e=>{let r=[];return[new Proxy(e,{get(e,t){const n=(...n)=>e[m](r,t,...n);return(n[y]=(...n)=>e[m][y](r,t,...n))[y]=n[y],n}}),()=>{var e;return null===(e=r.r)||void 0===e?void 0:e[0]()},(e=Error("Aborted"))=>{var t;null===(t=r.r)||void 0===t||t[1](e),r=[]}]},e.notify=e=>"function"==typeof e?e[y]:new Proxy(e,{get:h}),Object.defineProperty(e,"__esModule",{value:!0})}));
//# sourceMappingURL=base.js.map

@@ -40,2 +40,3 @@ /**

declare const JSONSerialization: (replacerAndReceiver?: [(((key: string, value: any) => any) | undefined)?, (((key: string, value: any) => any) | undefined)?], space?: string | number | undefined, undefinedKeepingBehavior?: 'keep' | 'null' | false) => Serialization;
//# sourceMappingURL=serialization.d.ts.map

@@ -52,21 +53,60 @@ /**

error?(...args: unknown[]): void;
}
warn?(...args: unknown[]): void;
}//# sourceMappingURL=console.d.ts.map
/**
* Wrap the AsyncCall instance to send notification.
* @param instanceOrFnOnInstance The AsyncCall instance or function on the AsyncCall instance
* @param instanceOrFnOnInstance - The AsyncCall instance or function on the AsyncCall instance
* @example
* const notifyOnly = notify(AsyncCall(...))
* @public
*/
declare function notify<T extends object>(instanceOrFnOnInstance: T): _IgnoreResponse<T>;
//# sourceMappingURL=notify.d.ts.map
/**
* Wrap the AsyncCall instance to use batch call.
* @param asyncCallInstance
* @param asyncCallInstance - The AsyncCall instance
* @example
* const [batched, send, drop] = batch(AsyncCall(...))
* @public
*/
declare function batch<T extends object>(asyncCallInstance: T): [T, () => void, (error?: unknown) => void];
declare function batch<T extends object>(asyncCallInstance: T): [T, () => void, (error?: unknown) => void];//# sourceMappingURL=batch.d.ts.map
/**
* This interface represents a "on message"-"send response" model.
* @remarks
* Usually used for there is only 1 remote (act like a client).
* @public
*/
interface EventBasedChannel<Data = unknown> {
/**
* Register the message listener.
* @param listener - The message listener.
* @returns a function that unregister the listener.
*/
on(listener: (data: Data) => void): void | (() => void);
/**
* Send the data to the remote side.
* @param data - The data should send to the remote side.
*/
send(data: Data): void;
}
/**
* This interface represents a "callback" model.
* @remarks
* Usually used for there are many remotes (act like a server).
* @public
*/
interface CallbackBasedChannel<Data = unknown> extends Partial<EventBasedChannel<Data>> {
/**
* Setup the CallbackBasedChannel..
* @param jsonRPCHandlerCallback - A function that will execute the JSON RPC request then give the result back. If the result is undefined, it means no response is created.
* @param isValidPayload - A util function that will try to validate if the message is a valid JSON RPC request. It will be asynchronous if possible.
*/
setup(jsonRPCHandlerCallback: (jsonRPCPayload: unknown) => Promise<unknown | undefined>, isValidJSONRPCPayload: (data: unknown) => boolean | Promise<boolean>): (() => void) | void;
}
//# sourceMappingURL=types.d.ts.map
/**
* What should AsyncCall log to console.

@@ -101,2 +141,7 @@ * @public

type?: 'basic' | 'pretty';
/**
* Log a function that allows to execute the request again.
* @defaultValue false
*/
requestReplay?: boolean;
}

@@ -122,2 +167,3 @@ /**

* @public
* @deprecated Will be removed in the next major version.
*/

@@ -127,4 +173,4 @@ interface MessageChannel<Context = unknown> {

* AsyncCall will attach a listener to receive messages.
* @param event The emitting event name (if supported).
* @param eventListener The listener have two parameters. The first one is the received data. The second one is an identifier to identify who send this request. When responding, AsyncCall will call the emit with the same context.
* @param event - The emitting event name (if supported).
* @param eventListener - The listener have two parameters. The first one is the received data. The second one is an identifier to identify who send this request. When responding, AsyncCall will call the emit with the same context.
*/

@@ -134,5 +180,5 @@ on(event: string, eventListener: (data: unknown, context?: Context) => void): void;

* AsyncCall will send message by this method.
* @param event The emitting event name (if supported).
* @param data The sending data.
* @param context The same context provided to the second parameter of on.eventListener.
* @param event - The emitting event name (if supported).
* @param data - The sending data.
* @param context - The same context provided to the second parameter of on.eventListener.
*/

@@ -150,13 +196,6 @@ emit(event: string, data: unknown, context?: Context): void;

* @remarks
* The value can be anything, but need to be same on both sides.
* The value can be anything, but need to be same on both sides if you're using the deprecated MessageChannel interface.
* If you're using other recommended interface for channel like EventBasedChannel or CallbackBasedChannel,
* this option will only used for better logging.
*
* This option is useful when you want to run multiple AsyncCall instances on the same message channel.
*
* @example
* these two AsyncCall run on the same channel but they won't affect each other.
* ```ts
* AsyncCall({}, { messageChannel, key: 'app1' })
* AsyncCall({}, { messageChannel, key: 'app2' })
* ```
*
* @defaultValue `default-jsonrpc`

@@ -190,3 +229,3 @@ */

* ```ts
* const messageChannel = {
* const channel = {
* on(event, callback) {

@@ -200,5 +239,12 @@ * document.addEventListener('remote-data', x => callback(x.details))

* ```
* @remarks
* If you're using this new property, you can use "messageChannel: undefined!" to disable the type system error.
*/
messageChannel: MessageChannel;
channel?: CallbackBasedChannel | EventBasedChannel;
/**
* Leave this option "undefined!" if you're providing channel.
* @deprecated renamed to "channel". In next major version, this option will be removed and the "channel" property will be required.
*/
messageChannel: MessageChannel | CallbackBasedChannel | EventBasedChannel;
/**
* Choose log level. See {@link AsyncCallLogLevel}

@@ -241,3 +287,3 @@ * @defaultValue true

* The ID generator of each JSON RPC request
* @defaultValue () => Math.random().toString(36).slice(2)
* @defaultValue () =\> Math.random().toString(36).slice(2)
*/

@@ -247,4 +293,4 @@ idGenerator?(): string | number;

* Control the error response data
* @param error The happened Error
* @param request The request object
* @param error - The happened Error
* @param request - The request object
*/

@@ -298,2 +344,3 @@ mapError?: ErrorMapFunction<unknown>;

declare function AsyncCall<OtherSideImplementedFunctions = {}>(thisSideImplementation: object | Promise<object> | undefined, options: AsyncCallOptions): _AsyncVersionOf<OtherSideImplementedFunctions>;
//# sourceMappingURL=Async-Call.d.ts.map

@@ -343,3 +390,3 @@ /**

* type Server = typeof server
* const serverRPC = AsyncGeneratorCall<Server>({}, { messageChannel })
* const serverRPC = AsyncGeneratorCall<Server>({}, { channel })
* async function main() {

@@ -354,3 +401,4 @@ * for await (const x of serverRPC.generator()) {

declare function AsyncGeneratorCall<OtherSideImplementedFunctions = {}>(thisSideImplementation: object | Promise<object> | undefined, options: AsyncCallOptions): _AsyncGeneratorVersionOf<OtherSideImplementedFunctions>;
//# sourceMappingURL=Async-Call-Generator.d.ts.map
export { AsyncCall, AsyncCallLogLevel, AsyncCallOptions, AsyncCallStrictJSONRPC, AsyncGeneratorCall, Console, ErrorMapFunction, JSONSerialization, MessageChannel, NoSerialization, Serialization, _AsyncGeneratorVersionOf, _AsyncVersionOf, _IgnoreResponse, _UnboxPromise, batch, notify };
export { AsyncCall, AsyncCallLogLevel, AsyncCallOptions, AsyncCallStrictJSONRPC, AsyncGeneratorCall, CallbackBasedChannel, Console, ErrorMapFunction, EventBasedChannel, JSONSerialization, MessageChannel, NoSerialization, Serialization, _AsyncGeneratorVersionOf, _AsyncVersionOf, _IgnoreResponse, _UnboxPromise, batch, notify };
/// <reference types="./full.d.ts" />
((t,r)=>{"object"==typeof exports&&"undefined"!=typeof module?r(exports):"function"==typeof define&&define.amd?define(["exports"],r):r((t=t||self).AsyncCall={})})(this,(function(t){"use strict"
class r extends Error{constructor(t,r,e,n){super(r),this.name=t,this.code=e,this.stack=n}}const e={Error,EvalError,RangeError,ReferenceError,SyntaxError,TypeError,URIError}
function n(t=""){return t.replace(/^.+\n.+\n/,"")}const o=(()=>{const t=Reflect.get(globalThis,"DOMException")
if("function"==typeof t)return t})()
function i(t,r,e,n){void 0===t&&(t=null),Number.isNaN(r=Math.floor(r))&&(r=-1)
const o={jsonrpc:"2.0",id:t,error:{code:r,message:e,data:n}}
return d(o.error,"data"),o}function a(t,r,e){const{id:n}=t,{code:o,message:a,data:s}=e(r,t)
return i(n,o,a,s)}i.ParseError=(t,r)=>{const e=a({},t,r),n=e.error
return n.code=-32700,n.message="Parse error",e},i.InvalidRequest=t=>i(t,-32600,"Invalid Request"),i.MethodNotFound=t=>i(t,-32601,"Method not found")
const s=(t="",r=-1)=>e=>{let n=""
l(e)&&u(e,"message")&&"string"==typeof e.message&&(n=e.message)
let i=((t,r)=>{let n="Error"
try{n=null===(i=null===(o=e)||void 0===o?void 0:o.constructor)||void 0===i?void 0:i.name}catch(o){}var o,i
return"string"!=typeof n?"Error":n})()
return o&&e instanceof o&&(i="DOMException:"+e.name),"string"!=typeof e&&"number"!=typeof e&&"boolean"!=typeof e&&"bigint"!=typeof e||(i="Error",n=e+""),{code:r,message:n,data:t?{stack:t,type:i}:{type:i}}}
function c(t){if(!l(t))return!1
if(!u(t,"jsonrpc"))return!1
if("2.0"!==t.jsonrpc)return!1
if(u(t,"params")){const r=t.params
if(!Array.isArray(r)&&!l(r))return!1}return!0}function l(t){return"object"==typeof t&&null!==t}function u(t,r){return r in t}function d(t,r){void 0===t[r]&&delete t[r]}const f={serialization:t=>t,deserialization:t=>t},y=Symbol.for("AsyncCall/ignored"),p=Symbol.for("AsyncCall/notify"),m=Symbol.for("AsyncCall/batch")
function h(t,r){return t[r][p]}function g(){return Math.random().toString(36).slice(2)}function v(t){return"boolean"!=typeof t?t:{methodNotFound:t,unknownMessage:t}}async function w(t,r,e,o){return new Promise((i,a)=>{var s
let c={}
try{c=document.createElement("iframe"),c.style.display="none",document.body.appendChild(c)
{const s=c.contentDocument,l=c.contentWindow,u=s.createElement("button")
s.body.appendChild(u),u.onclick=()=>new l.Promise(a=>{(async()=>{t(n(Error().stack)),i(await r.apply(e,o))})().then(a)}),l.onunhandledrejection=t=>a(t.reason),u.click()}}catch(t){try{console.error("Please close preservePauseOnException.",t)}catch(t){}return i(r(...o))}finally{null===(s=null==c?void 0:c.remove)||void 0===s||s.call(c)}})}const E={serializer:f,key:"default-jsonrpc",strict:!0,log:!0,parameterStructures:"by-position",preferLocalImplementation:!1,preservePauseOnException:!1,idGenerator:g}
function b(t={},f){let h=void 0
t instanceof Promise||(h=t),Promise.resolve(t).then(t=>h=t)
const{serializer:g,key:b,strict:k,log:P,parameterStructures:S,preferLocalImplementation:$,preservePauseOnException:x,idGenerator:O,mapError:j}={...E,...f},A=f.messageChannel,{methodNotFound:C=!1,unknownMessage:M=!1}=v(k),{beCalled:N=!0,localError:z=!0,remoteError:R=!0,type:I="pretty",sendLocalStack:F=!1}=(t=>"boolean"!=typeof t?t:{beCalled:t,localError:t,remoteError:t,type:t?"pretty":"basic"})(P),T=(t=>{const r=t||globalThis.console,e=(...t)=>r.log(...t)
return Object.assign({},{debug:e,error:e,groupCollapsed:e,groupEnd:e,log:e},r)})(f.logger),D=new Map
return A.on(b,async(t,r)=>{var e
let n,o=void 0
try{if(n=await g.deserialization(t),c(n))o=await q(n),o&&await a(o)
else if(Array.isArray(n)&&n.every(c)&&0!==n.length){const t=await Promise.all(n.map(q))
if(n.every(t=>void 0===t))return
await a(t.filter(t=>t))}else M&&await a(i.InvalidRequest(null!==(e=n.id)&&void 0!==e?e:null))}catch(t){z&&T.error(t,n,o),a(i.ParseError(t,j||s(null==t?void 0:t.stack)))}async function a(t){if(Array.isArray(t)){const e=t.filter(t=>u(t,"id"))
if(0===e.length)return
A.emit(b,await g.serialization(e),r)}else{if(!t)return
if(!u(t,"id"))return
A.emit(b,await g.serialization(t),r)}}}),new Proxy({},{get(t,r){let e=n(Error().stack)
const o=t=>(...n)=>{let o=void 0
if(r===m&&(o=n.shift(),r=n.shift()),"symbol"==typeof r){const t=Symbol.keyFor(r)||r.description
if(t){if(!t.startsWith("rpc."))return Promise.reject('[AsyncCall] An internal method must start with "rpc."')
r=t}}else if(r.startsWith("rpc."))return Promise.reject(new TypeError("[AsyncCall] Can't call internal methods directly"))
if($&&h&&"string"==typeof r){const t=h[r]
if(t&&"function"==typeof t)return new Promise(r=>r(t(...n)))}return new Promise((i,a)=>{const s=O(),[c]=n,u=F?e:"",f="by-name"===S&&1===n.length&&l(c)?c:n,y=((t,r,e,n)=>{const o={jsonrpc:"2.0",id:t,method:r,params:e,remoteStack:n}
return d(o,"id"),((t,r)=>{t[r]||delete t[r]})(o,"remoteStack"),o})(t?void 0:s,r,f,u)
if(o?(o.push(y),o.r||(o.r=[()=>W(o),G.bind(o)])):W(y).catch(a),t)return i()
D.set(s,{f:[i,a],stack:e})})},i=o(!1)
return i[p]=o(!0),i[p][p]=i[p],i}})
async function W(t){const r=await g.serialization(t)
A.emit(b,r)}function G(t){var r
for(const e of this)u(e,"id")&&(null===(r=D.get(e.id))||void 0===r||r.f[1](t))}async function q(c){return u(c,"method")?async function(r){h||await t
let e=""
try{const t=r.method.startsWith("rpc.")?Symbol.for(r.method):r.method,o=h[t]
if("function"!=typeof o)return C?i.MethodNotFound(r.id):void(z&&T.debug("Receive remote call, but not implemented.",t,r))
const{params:a}=r,s=Array.isArray(a)?a:[a]
e=n(Error().stack)
const c=x?w(t=>e=t,o,h,s):new Promise(t=>t(o.apply(h,s)))
if(N)if("basic"===I)T.log(`${f.key}.${r.method}(${""+[...s]}) @${r.id}`)
else{const t=[`${f.key}.%c${r.method}%c(${s.map(()=>"%o").join(", ")}%c)\n%o %c@${r.id}`,"color: #d2c057","",...s,"",c,"color: gray; font-style: italic;"]
r.remoteStack?(T.groupCollapsed(...t),T.log(r.remoteStack),T.groupEnd()):T.log(...t)}if(await c===y)return
return((t,r)=>{const e={jsonrpc:"2.0",id:t,result:r}
return d(e,"id"),e})(r.id,await c)}catch(t){return"object"==typeof t&&"stack"in t&&(t.stack=e.split("\n").reduce((t,r)=>t.replace(r+"\n",""),t.stack||"")),z&&T.error(t),a(r,t,j||s(F?t.stack:void 0))}}(c):async function(t){let n="",i="",a=0,s="Error"
if(u(t,"error")){const r=t.error
n=r.message,a=r.code
const e=r.data
i=l(e)&&u(e,"stack")&&"string"==typeof e.stack?e.stack:"<remote stack not available>",s=l(e)&&u(e,"type")&&"string"==typeof e.type?e.type:"Error",R&&("basic"===I?T.error(`${s}: ${n}(${a}) @${t.id}\n${i}`):T.error(`${s}: ${n}(${a}) %c@${t.id}\n%c${i}`,"color: gray",""))}if(null===t.id||void 0===t.id)return
const{f:[c,d],stack:f}=D.get(t.id)||{stack:"",f:[null,null]}
c&&(D.delete(t.id),u(t,"error")?d(((t,n,i,a)=>{try{if(t.startsWith("DOMException:")&&o){const[,r]=t.split("DOMException:")
return new o(n,r)}if(t in e){const r=new e[t](n)
return r.stack=a,Object.assign(r,{code:i}),r}return new r(t,n,i,a)}catch(r){return Error(`E${i} ${t}: ${n}\n${a}`)}})(s,n,a,i+"\n аt AsyncCall (rpc) \n"+f)):c(t.result))}(c)}}const k=Symbol.for("rpc.async-iterator.start"),P=Symbol.for("rpc.async-iterator.next"),S=Symbol.for("rpc.async-iterator.return"),$=Symbol.for("rpc.async-iterator.throw")
class x{constructor(t,r){this.r=t,this.i=r,this.d=!1,this.c=async t=>(await A(t,()=>this.d=!0),t)}async return(t){return this.d||this.c(this.r[S](await this.i,t)).catch(()=>{}),this.d=!0,C(!0,t)}async next(t){return this.d?C(!0):await this.c(this.r[P](await this.i,t))}async throw(t){if(!this.d)return await this.c(this.r[$](await this.i,t))
throw t}}const O=async function*(){}.constructor.prototype
Object.setPrototypeOf(x,O)
const j=Object.getPrototypeOf(async function*(){}())
async function A(t,r){try{const e=await t;(null==e?void 0:e.done)&&r()}catch(t){}}function C(t,r){return{done:t,value:r}}Object.setPrototypeOf(x.prototype,j),t.AsyncCall=b,t.AsyncGeneratorCall=(t={},r)=>{var e
const n=new Map,o=v(null===(e=r.strict)||void 0===e||e),{idGenerator:i=g}=r
function a(t,r,e){const i=n.get(t)
if(!i){if(o.methodNotFound)throw Error(`Iterator ${t} not found, ${r}() failed.`)
return y}const a=e(i)
return A(a,()=>n.delete(t)),a}const s=b({async[k](r,e){const a=Reflect.get(await t,r)
if("function"!=typeof a){if(o.methodNotFound)throw Error(r+" is not a function")
return y}const s=a(...e),c=i()
return n.set(c,s),Promise.resolve(c)},[P]:(t,r)=>a(t,"next",t=>t.next(r)),[S]:(t,r)=>a(t,"return",t=>{var e
return null===(e=t.return)||void 0===e?void 0:e.call(t,r)}),[$]:(t,r)=>a(t,"throw",t=>{var e
return null===(e=t.throw)||void 0===e?void 0:e.call(t,r)})},r)
return new Proxy({},{get:(t,r)=>{if("string"!=typeof r)throw new TypeError("[*AsyncCall] Only string can be the method name")
return(...t)=>{const e=s[k](r,t)
return new x(s,e)}}})},t.JSONSerialization=(t=[void 0,void 0],r,e="null")=>({serialization(n){if(e&&l(n)&&u(n,"result")&&void 0===n.result){const t=Object.assign({},n)
t.result=null,"keep"===e&&(t.undef=!0),n=t}return JSON.stringify(n,t[0],r)},deserialization(r){const e=JSON.parse(r,t[1])
return l(e)&&u(e,"result")&&null===e.result&&u(e,"undef")&&!0===e.undef&&(e.result=void 0,delete e.undef),e}}),t.NoSerialization=f,t.batch=t=>{let r=[]
return[new Proxy(t,{get(t,e){const n=(...n)=>t[m](r,e,...n)
return(n[p]=(...n)=>t[m][p](r,e,...n))[p]=n[p],n}}),()=>{var t
return null===(t=r.r)||void 0===t?void 0:t[0]()},(t=Error("Aborted"))=>{var e
null===(e=r.r)||void 0===e||e[1](t),r=[]}]},t.notify=t=>"function"==typeof t?t[p]:new Proxy(t,{get:h}),Object.defineProperty(t,"__esModule",{value:!0})}))
((e,r)=>{"object"==typeof exports&&"undefined"!=typeof module?r(exports):"function"==typeof define&&define.amd?define(["exports"],r):r((e=e||self).AsyncCall={})})(this,(function(e){"use strict";class r extends Error{constructor(e,r,t,n){super(r),this.name=e,this.code=t,this.stack=n}}const t={Error,EvalError,RangeError,ReferenceError,SyntaxError,TypeError,URIError};function n(e=""){return e.replace(/^.+\n.+\n/,"")}const o=(()=>{const e=Reflect.get(globalThis,"DOMException");if("function"==typeof e)return e})();function i(e,r,t,n){void 0===e&&(e=null),Number.isNaN(r=Math.floor(r))&&(r=-1);const o={jsonrpc:"2.0",id:e,error:{code:r,message:t,data:n}};return d(o.error,"data"),o}function a(e,r,t){const{id:n}=e,{code:o,message:a,data:s}=t(r,e);return i(n,o,a,s)}i.ParseError=(e,r)=>{const t=a({},e,r),n=t.error;return n.code=-32700,n.message="Parse error",t},i.InvalidRequest=e=>i(e,-32600,"Invalid Request"),i.MethodNotFound=e=>i(e,-32601,"Method not found");const s=(e="",r=-1)=>t=>{let n="";l(t)&&u(t,"message")&&"string"==typeof t.message&&(n=t.message);let i=((e,r)=>{let n="Error";try{n=null===(i=null===(o=t)||void 0===o?void 0:o.constructor)||void 0===i?void 0:i.name}catch(o){}var o,i;return"string"!=typeof n?"Error":n})();return o&&t instanceof o&&(i="DOMException:"+t.name),"string"!=typeof t&&"number"!=typeof t&&"boolean"!=typeof t&&"bigint"!=typeof t||(i="Error",n=t+""),{code:r,message:n,data:e?{stack:e,type:i}:{type:i}}};function c(e){if(!l(e))return!1;if(!u(e,"jsonrpc"))return!1;if("2.0"!==e.jsonrpc)return!1;if(u(e,"params")){const r=e.params;if(!Array.isArray(r)&&!l(r))return!1}return!0}function l(e){return"object"==typeof e&&null!==e}function u(e,r){return r in e}function d(e,r){void 0===e[r]&&delete e[r]}const f={serialization:e=>e,deserialization:e=>e},y=Symbol.for("AsyncCall/ignored"),p=Symbol.for("AsyncCall/notify"),h=Symbol.for("AsyncCall/batch");function m(e,r){return e[r][p]}function v(){return Math.random().toString(36).slice(2)}function g(e){return"boolean"!=typeof e?e:{methodNotFound:e,unknownMessage:e}}async function w(e,r,t,o){return new Promise((i,a)=>{var s;let c={};try{c=document.createElement("iframe"),c.style.display="none",document.body.appendChild(c);{const s=c.contentDocument,l=c.contentWindow,u=s.createElement("button");s.body.appendChild(u),u.onclick=()=>new l.Promise(a=>{(async()=>{e(n(Error().stack)),i(await r.apply(t,o))})().then(a)}),l.onunhandledrejection=e=>a(e.reason),u.click()}}catch(e){try{console.error("Please close preservePauseOnException.",e)}catch(e){}return i(r(...o))}finally{null===(s=null==c?void 0:c.remove)||void 0===s||s.call(c)}})}const E={serializer:f,key:"default-jsonrpc",strict:!0,log:!0,parameterStructures:"by-position",preferLocalImplementation:!1,preservePauseOnException:!1,idGenerator:v};function b(e={},f){var m;let v=void 0;e instanceof Promise||(v=e),Promise.resolve(e).then(e=>v=e);const{serializer:b,key:k,strict:P,log:S,parameterStructures:$,preferLocalImplementation:x,preservePauseOnException:C,idGenerator:O,mapError:j,logger:A,channel:M,channel:z}={...E,...f},{methodNotFound:N=!1,unknownMessage:R=!1}=g(P),{beCalled:I=!0,localError:T=!0,remoteError:F=!0,type:D="pretty",sendLocalStack:W=!1,requestReplay:q=!1}=(e=>"boolean"!=typeof e?e:{beCalled:e,localError:e,remoteError:e,type:e?"pretty":"basic"})(S),G=(e=>{const r=e||globalThis.console,t=(...e)=>r.log(...e);return Object.assign({},{debug:t,error:t,groupCollapsed:t,groupEnd:t,log:t,warn:t},r)})(A),J=z||M;if(M&&!z&&G.warn("Deprecation: messageChannel has renamed to channel"),!J)throw Error();const L=new Map;async function B(e){var r;let t;try{if(t=await b.deserialization(e),c(t))return await V(t);if(Array.isArray(t)&&t.every(c)&&0!==t.length){const e=await Promise.all(t.map(V));if(t.every(e=>void 0===e))return;return e.filter(e=>e)}return R?i.InvalidRequest(null!==(r=t.id)&&void 0!==r?r:null):void 0}catch(e){return T&&G.error(e,t,void 0),i.ParseError(e,j||s(null==e?void 0:e.stack))}}async function U(e){if(e){if(Array.isArray(e)){const r=e.filter(e=>u(e,"id"));if(0===r.length)return;return b.serialization(r)}if(u(e,"id"))return b.serialization(e)}}function _(e){return u(e,"send")&&"function"==typeof e.send}if(u(H=J,"emit")&&"function"==typeof H.emit)G.warn("The interface you're using in channel is deprecated. Please switch to EventBasedChannel or CallbackBasedChannel"),J.on(k,async(e,r)=>{const t=await B(e);t&&J.emit(k,t,r)});else if((e=>u(e,"setup")&&"function"==typeof e.setup)(J))J.setup(e=>B(e).then(U),e=>{const r=b.deserialization(e);return!!c(r)||Promise.resolve(r).then(c)});else if(!_(J))throw new TypeError("Invalid channel");var H;if(_(J)){const e=J;null===(m=e.on)||void 0===m||m.call(e,r=>B(r).then(U).then(r=>r&&e.send(r)))}return new Proxy({},{get(e,r){let t=n(Error().stack);const o=e=>(...n)=>{let o=void 0;if(r===h&&(o=n.shift(),r=n.shift()),"symbol"==typeof r){const e=Symbol.keyFor(r)||r.description;if(e){if(!e.startsWith("rpc."))return Promise.reject('[AsyncCall] An internal method must start with "rpc."');r=e}}else if(r.startsWith("rpc."))return Promise.reject(new TypeError("[AsyncCall] Can't call internal methods directly"));if(x&&v&&"string"==typeof r){const e=v[r];if(e&&"function"==typeof e)return new Promise(r=>r(e(...n)))}return new Promise((i,a)=>{const s=O(),[c]=n,u=W?t:"",f="by-name"===$&&1===n.length&&l(c)?c:n,y=((e,r,t,n)=>{const o={jsonrpc:"2.0",id:e,method:r,params:t,remoteStack:n};return d(o,"id"),((e,r)=>{e[r]||delete e[r]})(o,"remoteStack"),o})(e?void 0:s,r,f,u);if(o?(o.push(y),o.r||(o.r=[()=>K(o),Q.bind(o)])):K(y).catch(a),e)return i();L.set(s,{f:[i,a],stack:t})})},i=o(!1);return i[p]=o(!0),i[p][p]=i[p],i}});async function K(e){const r=await b.serialization(e);return u(J,"emit")?J.emit(k,r):J.send(r)}function Q(e){var r;for(const t of this)u(t,"id")&&(null===(r=L.get(t.id))||void 0===r||r.f[1](e))}async function V(c){return u(c,"method")?async function(r){v||await e;let t="";try{const e=r.method.startsWith("rpc.")?Symbol.for(r.method):r.method,o=v[e];if("function"!=typeof o)return N?i.MethodNotFound(r.id):void(T&&G.debug("Receive remote call, but not implemented.",e,r));const{params:a}=r,s=Array.isArray(a)?a:[a];t=n(Error().stack);const c=C?w(e=>t=e,o,v,s):new Promise(e=>e(o.apply(v,s)));if(I)if("basic"===D)G.log(`${k}.${r.method}(${""+[...s]}) @${r.id}`);else{const e=[`${k}.%c${r.method}%c(${s.map(()=>"%o").join(", ")}%c)\n%o %c@${r.id}`,"color: #d2c057","",...s,"",c,"color: gray; font-style: italic;"];q&&e.push(()=>{debugger;return o.apply(v,s)}),r.remoteStack?(G.groupCollapsed(...e),G.log(r.remoteStack),G.groupEnd()):G.log(...e)}if(await c===y)return;return((e,r)=>{const t={jsonrpc:"2.0",id:e,result:r};return d(t,"id"),t})(r.id,await c)}catch(e){return"object"==typeof e&&"stack"in e&&(e.stack=t.split("\n").reduce((e,r)=>e.replace(r+"\n",""),e.stack||"")),T&&G.error(e),a(r,e,j||s(W?e.stack:void 0))}}(c):async function(e){let n="",i="",a=0,s="Error";if(u(e,"error")){const r=e.error;n=r.message,a=r.code;const t=r.data;i=l(t)&&u(t,"stack")&&"string"==typeof t.stack?t.stack:"<remote stack not available>",s=l(t)&&u(t,"type")&&"string"==typeof t.type?t.type:"Error",F&&("basic"===D?G.error(`${s}: ${n}(${a}) @${e.id}\n${i}`):G.error(`${s}: ${n}(${a}) %c@${e.id}\n%c${i}`,"color: gray",""))}if(null===e.id||void 0===e.id)return;const{f:[c,d],stack:f}=L.get(e.id)||{stack:"",f:[null,null]};c&&(L.delete(e.id),u(e,"error")?d(((e,n,i,a)=>{try{if(e.startsWith("DOMException:")&&o){const[,r]=e.split("DOMException:");return new o(n,r)}if(e in t){const r=new t[e](n);return r.stack=a,Object.assign(r,{code:i}),r}return new r(e,n,i,a)}catch(r){return Error(`E${i} ${e}: ${n}\n${a}`)}})(s,n,a,i+"\n аt AsyncCall (rpc) \n"+f)):c(e.result))}(c)}}const k=Symbol.for("rpc.async-iterator.start"),P=Symbol.for("rpc.async-iterator.next"),S=Symbol.for("rpc.async-iterator.return"),$=Symbol.for("rpc.async-iterator.throw");class x{constructor(e,r){this.r=e,this.i=r,this.d=!1,this.c=async e=>(await j(e,()=>this.d=!0),e)}async return(e){return this.d||this.c(this.r[S](await this.i,e)).catch(()=>{}),this.d=!0,A(!0,e)}async next(e){return this.d?A(!0):await this.c(this.r[P](await this.i,e))}async throw(e){if(!this.d)return await this.c(this.r[$](await this.i,e));throw e}}const C=async function*(){}.constructor.prototype;Object.setPrototypeOf(x,C);const O=Object.getPrototypeOf(async function*(){}());async function j(e,r){try{const t=await e;(null==t?void 0:t.done)&&r()}catch(e){}}function A(e,r){return{done:e,value:r}}Object.setPrototypeOf(x.prototype,O),e.AsyncCall=b,e.AsyncGeneratorCall=(e={},r)=>{var t;const n=new Map,o=g(null===(t=r.strict)||void 0===t||t),{idGenerator:i=v}=r;function a(e,r,t){const i=n.get(e);if(!i){if(o.methodNotFound)throw Error(`Iterator ${e} not found, ${r}() failed.`);return y}const a=t(i);return j(a,()=>n.delete(e)),a}const s=b({async[k](r,t){const a=Reflect.get(await e,r);if("function"!=typeof a){if(o.methodNotFound)throw Error(r+" is not a function");return y}const s=a(...t),c=i();return n.set(c,s),Promise.resolve(c)},[P]:(e,r)=>a(e,"next",e=>e.next(r)),[S]:(e,r)=>a(e,"return",e=>{var t;return null===(t=e.return)||void 0===t?void 0:t.call(e,r)}),[$]:(e,r)=>a(e,"throw",e=>{var t;return null===(t=e.throw)||void 0===t?void 0:t.call(e,r)})},r);return new Proxy({},{get:(e,r)=>{if("string"!=typeof r)throw new TypeError("[*AsyncCall] Only string can be the method name");return(...e)=>{const t=s[k](r,e);return new x(s,t)}}})},e.JSONSerialization=(e=[void 0,void 0],r,t="null")=>({serialization(n){if(t&&l(n)&&u(n,"result")&&void 0===n.result){const e=Object.assign({},n);e.result=null,"keep"===t&&(e.undef=!0),n=e}return JSON.stringify(n,e[0],r)},deserialization(r){const t=JSON.parse(r,e[1]);return l(t)&&u(t,"result")&&null===t.result&&u(t,"undef")&&!0===t.undef&&(t.result=void 0,delete t.undef),t}}),e.NoSerialization=f,e.batch=e=>{let r=[];return[new Proxy(e,{get(e,t){const n=(...n)=>e[h](r,t,...n);return(n[p]=(...n)=>e[h][p](r,t,...n))[p]=n[p],n}}),()=>{var e;return null===(e=r.r)||void 0===e?void 0:e[0]()},(e=Error("Aborted"))=>{var t;null===(t=r.r)||void 0===t||t[1](e),r=[]}]},e.notify=e=>"function"==typeof e?e[p]:new Proxy(e,{get:m}),Object.defineProperty(e,"__esModule",{value:!0})}));
//# sourceMappingURL=full.js.map
{
"name": "async-call-rpc",
"version": "3.2.2",
"version": "3.3.0",
"description": "A lightweight JSON RPC server & client",

@@ -24,14 +24,16 @@ "main": "out/base.js",

"scripts": {
"start": "node ./watch.js",
"prepublishOnly": "npm run build",
"release": "rimraf ./out && rimraf ./utils/web && rimraf ./utils/node && standard-version",
"build:utils": "tsc -p ./utils-src/tsconfig.es.json && tsc -p ./utils-src/tsconfig.node.json",
"build:tsc": "tsc --declaration --outDir ./es/",
"build:roll": "rollup -c",
"build": "npm run build:tsc && npm run build:roll && npm run build:utils && npm run doc",
"clean": "rimraf ./out ./utils/web ./utils/node ./es ./coverage ./temp",
"release": "npm run clean && npm run test && standard-version",
"watch:tsc": "tsc -b ./tsconfig.es.json ./utils-src/tsconfig.es.json ./utils-src/tsconfig.node.json -w",
"build:tsc": "tsc -b ./tsconfig.es.json ./utils-src/tsconfig.es.json ./utils-src/tsconfig.node.json",
"watch:rollup": "rollup -c -w",
"build:rollup": "rollup -c",
"build": "npm run build:tsc && npm run build:rollup && npm run doc",
"doc:api": "api-extractor run --local --verbose",
"doc:md": "api-documenter markdown -o docs -i temp",
"doc:preview": "docsify serve .",
"doc": "npm run doc:api && npm run doc:md",
"test": "jest --coverage --coverage-provider=v8"
"doc": "run-s doc:api doc:md",
"start": "run-p watch:rollup watch:tsc watch:test",
"test": "jest --coverage --coverage-provider=v8",
"watch:test": "jest --watch"
},

@@ -52,20 +54,21 @@ "repository": {

"devDependencies": {
"@microsoft/api-documenter": "latest",
"@microsoft/api-extractor": "latest",
"@rollup/plugin-typescript": "^4.1.2",
"@types/jest": "^26.0.0",
"@types/node": "^14.0.13",
"@types/ws": "^7.2.5",
"docsify-cli": "^4.4.1",
"jest": "^26.0.1",
"@microsoft/api-documenter": "^7.8.21",
"@microsoft/api-extractor": "^7.9.2",
"@rollup/plugin-typescript": "^5.0.1",
"@types/jest": "^26.0.4",
"@types/node": "^14.0.22",
"@types/ws": "^7.2.6",
"jest": "^26.1.0",
"npm-run-all": "^4.1.5",
"prettier": "^2.0.5",
"rimraf": "^3.0.2",
"rollup": "^2.16.1",
"rollup": "^2.21.0",
"rollup-plugin-dts": "^1.4.7",
"rollup-plugin-terser": "^6.1.0",
"standard-version": "^8.0.0",
"ts-jest": "^26.1.0",
"ts-jest": "^26.1.1",
"tslib": "^2.0.0",
"typescript": "^3.9.5",
"ws": "^7.3.0"
"typescript": "^3.9.6",
"ws": "^7.3.1",
"async-call-rpc": "./"
},

@@ -72,0 +75,0 @@ "files": [

@@ -16,3 +16,3 @@ # Async Call

- [The first concept: `messageChannel`](#the-first-concept-messagechannel)
- [The first concept: `channel`](#the-first-concept-messagechannel)
- [Example](#example)

@@ -23,3 +23,3 @@ - [Notifications and Batch requests](#notifications-and-batch-requests)

- [Utils available if both server and client are created by this library](#utils-available-if-both-server-and-client-are-created-by-this-library)
- [Builtin `messageChannels` (including WebSocket)](#builtin-messageChannels)
- [Builtin `channels` (including WebSocket)](#builtin-channels)
- [Implemented JSON RPC internal methods](#implemented-json-rpc-internal-methods)

@@ -44,7 +44,7 @@ - [Non-standard extension to JSON RPC specification](#non-standard-extension-to-json-rpc-specification)

## The first concept: `messageChannel`
## The first concept: `channel`
<a id="messageChannel"></a>
<a id="channel"></a>
The `messageChannel` is the only thing you need to learn to use this library.
The `channel` is the only thing you need to learn to use this library.

@@ -54,20 +54,11 @@ This library is designed to not rely on any specific platform. Only require things defined in the ECMAScript specification.

Therefore, this library require you to provide an object in the following shape:
You need to implement one of the following interfaces:
```ts
interface MessageChannel {
on(event: string, callback: (data: unknown) => void): void
emit(event: string, data: unknown): void
}
```
- [CallbackBasedChannel](https://jack-works.github.io/async-call-rpc/async-call-rpc.callbackbasedchannel.html), generally used in the server. [Example](https://github.com/Jack-Works/async-call-rpc/blob/master/utils-src/web/websocket.client.ts).
- [EventBasedChannel](https://jack-works.github.io/async-call-rpc/async-call-rpc.eventbasedchannel.html), generally used in the client. [Example](https://github.com/Jack-Works/async-call-rpc/blob/master/utils-src/node/websocket.server.ts)
In general, the `MessageChannel` should have the following semantics:
There are some [built-in channel](#builtin-channels) you can simplify the usage.
- When the `data` from the remote arrives (by `addEventListener('message', ...)`, etc), the `callback` should be called.
- When the `emit` method is called, the `data` should be sent to the remote properly (by `postMessage` or `fetch`, etc).
The following document will assume you have defined your `channel`.
> There is a [plan to add built-in messageChannel for Web, Node.JS, and Deno](https://github.com/Jack-Works/async-call/issues/15) to simplify the setup.
The following document will assume you have defined your `messageChannel`.
## Example

@@ -88,3 +79,3 @@

// create a server
AsyncCall(server, { messageChannel })
AsyncCall(server, { channel, messageChannel: undefined! })
```

@@ -96,3 +87,3 @@

import { AsyncCall } from 'async-call-rpc'
const server = AsyncCall<typeof server>({}, { messageChannel })
const server = AsyncCall<typeof server>({}, { channel, messageChannel: undefined! })
server.add(2, 40).then(console.log) // 42

@@ -116,3 +107,3 @@ ```

import { AsyncCall, notify } from 'async-call-rpc'
const server = notify(AsyncCall<typeof server>({}, { messageChannel }))
const server = notify(AsyncCall<typeof server>({}, { channel, messageChannel: undefined! }))
server.online().then(console.log) // undefined

@@ -125,3 +116,3 @@ ```

import { AsyncCall, batch } from 'async-call-rpc'
const [server, emit, drop] = batch(AsyncCall<typeof server>({}, { messageChannel }))
const [server, emit, drop] = batch(AsyncCall<typeof server>({}, { channel, messageChannel: undefined! }))
const a = server.req1() // pending

@@ -189,3 +180,3 @@ const b = server.req2() // pending

## Builtin messageChannels
## Builtin channels

@@ -192,0 +183,0 @@ They're not part of the core library but provided as utils to increase usability.

@@ -73,3 +73,3 @@ /**

* type Server = typeof server
* const serverRPC = AsyncGeneratorCall<Server>({}, { messageChannel })
* const serverRPC = AsyncGeneratorCall<Server>({}, { channel })
* async function main() {

@@ -76,0 +76,0 @@ * for await (const x of serverRPC.generator()) {

@@ -28,2 +28,3 @@ /**

import { BatchQueue } from './core/batch'
import { CallbackBasedChannel, EventBasedChannel } from './index'

@@ -60,2 +61,7 @@ /**

type?: 'basic' | 'pretty'
/**
* Log a function that allows to execute the request again.
* @defaultValue false
*/
requestReplay?: boolean
}

@@ -83,2 +89,3 @@

* @public
* @deprecated Will be removed in the next major version.
*/

@@ -88,4 +95,4 @@ export interface MessageChannel<Context = unknown> {

* AsyncCall will attach a listener to receive messages.
* @param event The emitting event name (if supported).
* @param eventListener The listener have two parameters. The first one is the received data. The second one is an identifier to identify who send this request. When responding, AsyncCall will call the emit with the same context.
* @param event - The emitting event name (if supported).
* @param eventListener - The listener have two parameters. The first one is the received data. The second one is an identifier to identify who send this request. When responding, AsyncCall will call the emit with the same context.
*/

@@ -95,9 +102,9 @@ on(event: string, eventListener: (data: unknown, context?: Context) => void): void

* AsyncCall will send message by this method.
* @param event The emitting event name (if supported).
* @param data The sending data.
* @param context The same context provided to the second parameter of on.eventListener.
* @param event - The emitting event name (if supported).
* @param data - The sending data.
* @param context - The same context provided to the second parameter of on.eventListener.
*/
emit(event: string, data: unknown, context?: Context): void
}
export type { CallbackBasedChannel, EventBasedChannel } from './types'
/**

@@ -112,13 +119,6 @@ * Options for {@link AsyncCall}

* @remarks
* The value can be anything, but need to be same on both sides.
* The value can be anything, but need to be same on both sides if you're using the deprecated MessageChannel interface.
* If you're using other recommended interface for channel like EventBasedChannel or CallbackBasedChannel,
* this option will only used for better logging.
*
* This option is useful when you want to run multiple AsyncCall instances on the same message channel.
*
* @example
* these two AsyncCall run on the same channel but they won't affect each other.
* ```ts
* AsyncCall({}, { messageChannel, key: 'app1' })
* AsyncCall({}, { messageChannel, key: 'app2' })
* ```
*
* @defaultValue `default-jsonrpc`

@@ -152,3 +152,3 @@ */

* ```ts
* const messageChannel = {
* const channel = {
* on(event, callback) {

@@ -162,5 +162,12 @@ * document.addEventListener('remote-data', x => callback(x.details))

* ```
* @remarks
* If you're using this new property, you can use "messageChannel: undefined!" to disable the type system error.
*/
messageChannel: MessageChannel
channel?: CallbackBasedChannel | EventBasedChannel
/**
* Leave this option "undefined!" if you're providing channel.
* @deprecated renamed to "channel". In next major version, this option will be removed and the "channel" property will be required.
*/
messageChannel: MessageChannel | CallbackBasedChannel | EventBasedChannel
/**
* Choose log level. See {@link AsyncCallLogLevel}

@@ -203,3 +210,3 @@ * @defaultValue true

* The ID generator of each JSON RPC request
* @defaultValue () => Math.random().toString(36).slice(2)
* @defaultValue () =\> Math.random().toString(36).slice(2)
*/

@@ -209,4 +216,4 @@ idGenerator?(): string | number

* Control the error response data
* @param error The happened Error
* @param request The request object
* @param error - The happened Error
* @param request - The request object
*/

@@ -253,3 +260,5 @@ mapError?: ErrorMapFunction<unknown>

const AsyncCallDefaultOptions = (<T extends Omit<Required<AsyncCallOptions>, 'messageChannel' | 'logger' | 'mapError'>>(
const AsyncCallDefaultOptions = (<
T extends Omit<Required<AsyncCallOptions>, 'messageChannel' | 'channel' | 'logger' | 'mapError'>
>(
a: T,

@@ -294,3 +303,3 @@ ) => a)({

serializer,
key,
key: logKey,
strict,

@@ -303,2 +312,5 @@ log,

mapError,
logger,
channel: oldChannel,
channel,
} = {

@@ -308,3 +320,2 @@ ...AsyncCallDefaultOptions,

}
const message = options.messageChannel
const {

@@ -320,4 +331,8 @@ methodNotFound: banMethodNotFound = false,

sendLocalStack = false,
requestReplay = false,
} = normalizeLogOptions(log)
const console = getConsole(options.logger)
const console = getConsole(logger)
const message: EventBasedChannel | CallbackBasedChannel | MessageChannel = (channel || oldChannel)!
if (oldChannel && !channel) console.warn('Deprecation: messageChannel has renamed to channel')
if (!message) throw new Error()
type PromiseParam = Parameters<ConstructorParameters<typeof Promise>[0]>

@@ -350,7 +365,6 @@ const requestContext = new Map<string | number, { f: PromiseParam; stack: string }>()

if (logBeCalled) {
if (logType === 'basic')
console.log(`${options.key}.${data.method}(${[...args].toString()}) @${data.id}`)
if (logType === 'basic') console.log(`${logKey}.${data.method}(${[...args].toString()}) @${data.id}`)
else {
const logArgs = [
`${options.key}.%c${data.method}%c(${args.map(() => '%o').join(', ')}%c)\n%o %c@${data.id}`,
const logArgs: unknown[] = [
`${logKey}.%c${data.method}%c(${args.map(() => '%o').join(', ')}%c)\n%o %c@${data.id}`,
'color: #d2c057',

@@ -363,2 +377,7 @@ '',

]
if (requestReplay)
logArgs.push(() => {
debugger
return executor.apply(resolvedThisSideImplementation, args)
})
if (data.remoteStack) {

@@ -432,3 +451,3 @@ console.groupCollapsed(...logArgs)

}
message.on(key, async (_, source) => {
async function rawMessageReceiver(_: unknown): Promise<undefined | Response | (Response | undefined)[]> {
let data: unknown

@@ -439,4 +458,3 @@ let result: Response | undefined = undefined

if (isJSONRPCObject(data)) {
result = await handleSingleMessage(data)
if (result) await send(result)
return (result = await handleSingleMessage(data))
} else if (Array.isArray(data) && data.every(isJSONRPCObject) && data.length !== 0) {

@@ -446,8 +464,9 @@ const result = await Promise.all(data.map(handleSingleMessage))

if (data.every((x) => x === undefined)) return
await send(result.filter((x) => x))
return result.filter((x) => x)
} else {
if (banUnknownMessage) {
await send(ErrorResponse.InvalidRequest((data as any).id ?? null))
return ErrorResponse.InvalidRequest((data as any).id ?? null)
} else {
// ? Ignore this message. The message channel maybe also used to transfer other message too.
return undefined
}

@@ -457,17 +476,54 @@ }

if (logLocalError) console.error(e, data, result)
send(ErrorResponse.ParseError(e, mapError || defaultErrorMapper(e?.stack)))
return ErrorResponse.ParseError(e, mapError || defaultErrorMapper(e?.stack))
}
async function send(res?: Response | (Response | undefined)[]) {
if (Array.isArray(res)) {
const reply = res.filter((x) => hasKey(x, 'id'))
if (reply.length === 0) return
message.emit(key, await serializer.serialization(reply), source)
} else {
if (!res) return
// ? This is a Notification, we MUST not return it.
if (!hasKey(res, 'id')) return
message.emit(key, await serializer.serialization(res), source)
}
}
async function rawMessageSender(res: undefined | Response | (Response | undefined)[]) {
if (!res) return
if (Array.isArray(res)) {
const reply = res.filter((x) => hasKey(x, 'id'))
if (reply.length === 0) return
return serializer.serialization(reply)
} else {
// ? This is a Notification, we MUST not return it.
if (!hasKey(res, 'id')) return
return serializer.serialization(res)
}
})
}
function isMessageChannel(x: typeof message): x is MessageChannel {
return hasKey(x, 'emit') && typeof x.emit === 'function'
}
function isEventBasedChannel(x: typeof message): x is EventBasedChannel {
return hasKey(x, 'send') && typeof x.send === 'function'
}
function isCallbackBasedChannel(x: typeof message): x is CallbackBasedChannel {
return hasKey(x, 'setup') && typeof x.setup === 'function'
}
if (isMessageChannel(message)) {
console.warn(
"The interface you're using in channel is deprecated. Please switch to EventBasedChannel or CallbackBasedChannel",
)
message.on(logKey, async (_, context) => {
const r = await rawMessageReceiver(_)
if (r) message.emit(logKey, r, context)
})
} else if (isCallbackBasedChannel(message)) {
message.setup(
(data) => rawMessageReceiver(data).then(rawMessageSender),
(data) => {
const _ = serializer.deserialization(data)
if (isJSONRPCObject(_)) return true
return Promise.resolve(_).then(isJSONRPCObject)
},
)
} else if (!isEventBasedChannel(message)) {
throw new TypeError('Invalid channel')
}
if (isEventBasedChannel(message)) {
const m = message as EventBasedChannel | CallbackBasedChannel
m.on?.((_) =>
rawMessageReceiver(_)
.then(rawMessageSender)
.then((x) => x && m.send!(x)),
)
}
return new Proxy(

@@ -529,3 +585,5 @@ {},

const data = await serializer.serialization(payload)
message.emit(key, data)
if (hasKey(message, 'emit')) return message.emit(logKey, data)
// CallbackBasedChannel might have no send method. let it throw
return message.send!(data)
}

@@ -532,0 +590,0 @@ function rejectsQueue(this: BatchQueue, error: unknown) {

@@ -5,5 +5,6 @@ import { AsyncCallBatch, AsyncCallNotify } from '../utils/internalSymbol'

* Wrap the AsyncCall instance to use batch call.
* @param asyncCallInstance
* @param asyncCallInstance - The AsyncCall instance
* @example
* const [batched, send, drop] = batch(AsyncCall(...))
* @public
*/

@@ -10,0 +11,0 @@ export function batch<T extends object>(asyncCallInstance: T): [T, () => void, (error?: unknown) => void] {

@@ -5,5 +5,6 @@ import { AsyncCallNotify } from '../utils/internalSymbol'

* Wrap the AsyncCall instance to send notification.
* @param instanceOrFnOnInstance The AsyncCall instance or function on the AsyncCall instance
* @param instanceOrFnOnInstance - The AsyncCall instance or function on the AsyncCall instance
* @example
* const notifyOnly = notify(AsyncCall(...))
* @public
*/

@@ -10,0 +11,0 @@

@@ -12,2 +12,3 @@ //#region Console

error?(...args: unknown[]): void
warn?(...args: unknown[]): void
}

@@ -24,4 +25,5 @@ export function getConsole(_console?: Console): Required<Console> {

log: defaultLog,
warn: defaultLog,
}
return Object.assign({}, defaultConsole, console)
}

@@ -9,2 +9,5 @@ import { AsyncCallOptions, AsyncCallLogLevel, AsyncCallStrictJSONRPC } from '../Async-Call'

type: log ? 'pretty' : 'basic',
// these two options need opt in
// requestReplay: undefined,
// sendLocalStack: undefined,
}

@@ -11,0 +14,0 @@ }

@@ -1,12 +0,12 @@

import { Server } from 'https://deno.land/std/http/server.ts'
import { acceptWebSocket, WebSocket } from 'https://deno.land/std/ws/mod.ts'
import { Server } from 'https://deno.land/std@0.61.0/http/server.ts'
import { acceptWebSocket, WebSocket } from 'https://deno.land/std@0.61.0/ws/mod.ts'
import { CallbackBasedChannel } from '../../src/types.ts'
type CE = CustomEvent<[unknown, WebSocket]>
export class WebSocketChannel extends EventTarget {
constructor(public server: Server, private key: string = 'async-call') {
export class WebSocketChannel extends EventTarget implements CallbackBasedChannel {
constructor(public server: Server) {
super()
this.acceptRequest().catch((error) => this.dispatchEvent(new ErrorEvent('error', { error })))
}
async acceptRequest() {
private async acceptRequest(callback: (data: unknown) => Promise<unknown>, signal: AbortController) {
for await (const req of this.server) {
if (signal.signal.aborted) return
const { conn, r: bufReader, w: bufWriter, headers } = req

@@ -19,19 +19,24 @@ const ws = await acceptWebSocket({

})
this.handledWebSocket(ws).catch((error) => this.dispatchEvent(new ErrorEvent('wserror', { error })))
signal.signal.addEventListener('abort', () => ws.close(), { once: true })
this.handledWebSocket(ws, callback, signal).catch(this.error)
}
}
async handledWebSocket(websocket: WebSocket) {
private async handledWebSocket(
websocket: WebSocket,
callback: (data: unknown) => Promise<unknown>,
signal: AbortController,
) {
for await (const event of websocket) {
this.dispatchEvent(new CustomEvent(this.key, { detail: [event, websocket] }) as CE)
if (signal.signal.aborted) return
callback(event).then((x) => x && websocket.send(x as any), this.error)
}
}
on(event: string, eventListener: (data: unknown, source: WebSocket) => void): void {
this.addEventListener(this.key, (e) => {
const ee = e as CE
eventListener(ee.detail[0], ee.detail[1])
})
private error = (error: any) => {
this.dispatchEvent(new ErrorEvent('error', { error }))
}
emit(event: string, data: any, source: WebSocket): void {
source.send(data)
setup(callback: (data: unknown) => Promise<unknown>) {
const signal = new AbortController()
this.acceptRequest(callback, signal).catch(this.error)
return () => signal.abort()
}
}
import type { Server } from 'ws';
import type WebSocket from 'ws';
import type { AsyncCallMessageChannel } from '../shared';
export declare class WebSocketChannel implements AsyncCallMessageChannel {
import type { CallbackBasedChannel } from '../../src/Async-Call';
declare type JSONRPCHandlerCallback = (data: unknown) => Promise<unknown>;
export declare class WebSocketChannel implements CallbackBasedChannel {
server: Server;
private key;
private emitter;
constructor(server: Server, key?: string);
on(event: string, eventListener: (data: unknown, source: WebSocket) => void): void;
emit(event: string, data: unknown, source: WebSocket): void;
constructor(server: Server);
setup(callback: JSONRPCHandlerCallback): () => Server;
}
export {};
//# sourceMappingURL=websocket.server.d.ts.map
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.WebSocketChannel = void 0;
const events_1 = require("events");
class WebSocketChannel {
constructor(server, key = '') {
constructor(server) {
this.server = server;
this.key = key;
this.emitter = new events_1.EventEmitter();
server.on('connection', (ws) => ws.on('message', (data) => this.emitter.emit(this.key, data, ws)));
}
on(event, eventListener) {
this.emitter.on(this.key, eventListener);
setup(callback) {
const f = (ws) => {
ws.on('message', (data) => callback(data).then((x) => x && ws.send(x)));
};
this.server.on('connection', f);
return () => this.server.off('connection', f);
}
emit(event, data, source) {
source.send(data);
}
}
exports.WebSocketChannel = WebSocketChannel;
//# sourceMappingURL=websocket.server.js.map

@@ -1,2 +0,2 @@

import type { AsyncCallMessageChannel } from '../shared';
import type { EventBasedChannel } from '../../src/Async-Call';
/**

@@ -7,6 +7,6 @@ * BroadcastChannel support for AsyncCall.

*/
export declare class BroadcastMessageChannel extends BroadcastChannel implements AsyncCallMessageChannel {
on(event: string, eventListener: (data: unknown) => void): void;
emit(event: string, data: any): void;
export declare class BroadcastMessageChannel extends BroadcastChannel implements EventBasedChannel {
on(eventListener: (data: unknown) => void): () => void;
send(data: any): void;
}
//# sourceMappingURL=broadcast.channel.d.ts.map

@@ -7,6 +7,8 @@ /**

export class BroadcastMessageChannel extends BroadcastChannel {
on(event, eventListener) {
this.addEventListener('message', (e) => eventListener(e.data));
on(eventListener) {
const f = (e) => eventListener(e.data);
this.addEventListener('message', f);
return () => this.removeEventListener('message', f);
}
emit(event, data) {
send(data) {
super.postMessage(data);

@@ -13,0 +15,0 @@ }

@@ -1,2 +0,2 @@

import type { AsyncCallMessageChannel } from '../shared';
import type { EventBasedChannel } from '../../src/Async-Call';
/**

@@ -12,6 +12,6 @@ * WebSocket support for AsyncCall.

*/
export declare class WebSocketMessageChannel extends WebSocket implements AsyncCallMessageChannel {
on(event: string, eventListener: (data: unknown) => void): void;
emit(event: string, data: any): void;
export declare class WebSocketMessageChannel extends WebSocket implements EventBasedChannel {
on(listener: (data: unknown) => void): () => void;
send(data: any): void;
}
//# sourceMappingURL=websocket.client.d.ts.map

@@ -12,8 +12,11 @@ /**

export class WebSocketMessageChannel extends WebSocket {
on(event, eventListener) {
this.addEventListener('message', (e) => eventListener(e.data));
on(listener) {
const f = (e) => listener(e.data);
this.addEventListener('message', f);
return () => this.removeEventListener('message', f);
}
emit(event, data) {
if (this.readyState === this.CONNECTING)
send(data) {
if (this.readyState === this.CONNECTING) {
this.addEventListener('open', () => this.send(data), { once: true });
}
else

@@ -20,0 +23,0 @@ super.send(data);

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc