rpc-shooter
Version:
A tool library for handling window && iframe && worker communication based on the JSON RPC specification
2 lines (1 loc) • 5.56 kB
JavaScript
"use strict";var A=Object.defineProperty,C=Object.defineProperties;var M=Object.getOwnPropertyDescriptors;var x=Object.getOwnPropertySymbols;var S=Object.prototype.hasOwnProperty,k=Object.prototype.propertyIsEnumerable;var p=(a,e,t)=>e in a?A(a,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):a[e]=t,g=(a,e)=>{for(var t in e||(e={}))S.call(e,t)&&p(a,t,e[t]);if(x)for(var t of x(e))k.call(e,t)&&p(a,t,e[t]);return a},f=(a,e)=>C(a,M(e));var c=(a,e,t)=>(p(a,typeof e!="symbol"?e+"":e,t),t);Object.defineProperty(exports,"__esModule",{value:!0});exports[Symbol.toStringTag]="Module";const d={CONNECT_TIMEOUT:{code:-32300,message:"Connect timeout"},APPLICATION_ERROR:{code:-32500,message:"Application error"},METHOD_NOT_FOUND:{code:-32601,message:"Method not found"}};class I{constructor(e){c(this,"_currentEndpoint");c(this,"_targetEndpoint");c(this,"_events");c(this,"_originOnmessage");c(this,"_receiveMessage");c(this,"onerror",null);c(this,"config");c(this,"sendAdapter");c(this,"receiveAdapter");this._events={},this._currentEndpoint=e.currentEndpoint,this._targetEndpoint=e.targetEndpoint,this._originOnmessage=null,this.config=e.config,this.receiveAdapter=e.receiveAdapter,this.sendAdapter=e.sendAdapter;const t=n=>{const s=this.receiveAdapter?this.receiveAdapter(n):n.data;if(s&&typeof s.event=="string"){const i=this._events[s.event]||[];if(i.length){i.forEach(o=>{o(...s.args||[])});return}this.onerror&&this.onerror(f(g({},d.METHOD_NOT_FOUND),{data:s}))}};if(this._currentEndpoint.addEventListener){"start"in this._currentEndpoint&&this._currentEndpoint.start&&this._currentEndpoint.start(),this._currentEndpoint.addEventListener("message",t,!1),this._receiveMessage=t;return}this._originOnmessage=this._currentEndpoint.onmessage,this._currentEndpoint.onmessage=n=>{this._originOnmessage&&this._originOnmessage(n),t(n)},this._receiveMessage=this._currentEndpoint.onmessage}emit(e,...t){const n={event:e,args:t},s=this.sendAdapter?this.sendAdapter(n,this._targetEndpoint):{data:n},i=s.data||n,o=this.config?typeof this.config=="function"?this.config(i,this._targetEndpoint)||{}:this.config||{}:{};Array.isArray(s.transfer)&&s.transfer.length&&(o.transfer=s.transfer),this._targetEndpoint.postMessage(i,o)}on(e,t){this._events[e]||(this._events[e]=[]),this._events[e].push(t)}off(e,t){if(!this._events[e])return;if(!t){this._events[e]=[];return}const n=this._events[e]||[];this._events[e]=n.filter(s=>s!==t)}destroy(){if(this._currentEndpoint.removeEventListener){this._currentEndpoint.removeEventListener("message",this._receiveMessage,!1);return}try{this._currentEndpoint.onmessage=this._originOnmessage}catch(e){console.warn(e)}}}const _=class{constructor(e){c(this,"_event");c(this,"_methods",{});c(this,"_timeout",0);c(this,"_$connect",null);this._event=e.event,this._timeout=e.timeout||0,e.methods&&Object.entries(e.methods).forEach(([t,n])=>{this.registerMethod(t,n)}),this._event.onerror=t=>{const{code:n,message:s,data:i}=t;if(i.event&&Array.isArray(i.args)&&i.args.length){const o=i.args[0],r=this._getAckEventName(o.method),h={jsonrpc:"2.0",id:o==null?void 0:o.id,error:{code:n,message:s,data:o}};this._event.emit(r,h)}else console.error(t)},this.connect()}static uuid(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{const t=Math.random()*16|0;return(e=="x"?t:t&3|8).toString(16)})}_getSynEventName(e){return`${_.EVENT.SYN_SIGN}${e}`}_getAckEventName(e){return`${_.EVENT.ACK_SIGN}${e}`}connect(e){return this._$connect?this._$connect:(this._$connect=new Promise((t,n)=>{const s=e||this._timeout;let i;s&&(i=setTimeout(()=>{const N=f(g({},d.TIMEOUT),{data:{timeout:s}});n(N)},s));const o=_.EVENT.CONNECT,r=this._getAckEventName(o),h=this._getSynEventName(o),v=()=>{clearTimeout(i),t()};this._event.on(r,v);const m=()=>{this._event.emit(r),v()};this._event.on(h,m),this._event.emit(h)}),this._$connect)}registerMethod(e,t){if(this._methods[e])throw new Error(`${e} already registered`);this._methods[e]=t;const n=this._getSynEventName(e),s=i=>{const o=this._getAckEventName(e);if(!i.id){t(...i.params);return}Promise.resolve(t(...i.params)).then(r=>{const h={jsonrpc:"2.0",result:r,id:i.id};this._event.emit(o,h)}).catch(r=>{const h={jsonrpc:"2.0",id:i.id,error:{code:(r==null?void 0:r.code)||d.APPLICATION_ERROR.code,message:(r==null?void 0:r.message)||d.APPLICATION_ERROR.message,data:null}};this._event.emit(o,h)})};this._event.on(n,s)}removeMethod(e){this._methods[e]||delete this._methods[e];const t=this._getSynEventName(e);this._event.off(t)}invoke(e,...t){return new Promise((n,s)=>{const i=t[t.length-1],o=i&&typeof i=="object"&&(Reflect.has(i,"isNotify")||Reflect.has(i,"timeout")),r=o?i:{isNotify:!1,timeout:0},h=o?t.slice(0,-1):t,v=this._getSynEventName(e),m=_.uuid(),N={jsonrpc:"2.0",method:e,params:h,id:m};if(this._event.emit(v,N),r.isNotify)n(void 0);else{const y=this._getAckEventName(e),l=r.timeout||this._timeout;let O;l&&(O=setTimeout(()=>{const E=f(g({},d.CONNECT_TIMEOUT),{data:{timeout:l}});s(E)},l));const T=E=>{E.id===m&&(clearTimeout(O),this._event.off(y,T),E.error?s(E.error):n(E.result))};this._event.on(y,T)}})}destroy(){Object.entries(this._methods).forEach(([n])=>{const s=this._getSynEventName(n);this._event.off(s)});const e=this._getAckEventName(_.EVENT.CONNECT),t=this._getSynEventName(_.EVENT.CONNECT);this._event.off(t),this._event.off(e),this._event.destroy&&this._event.destroy()}};let u=_;c(u,"CODES",d),c(u,"EVENT",{SYN_SIGN:"syn:",ACK_SIGN:"ack:",CONNECT:"__rpc_connect_event",SYNC_METHODS:"__rpc_sync_methods_event"});exports.RPC=u;exports.RPCCodes=d;exports.RPCMessageEvent=I;