rpc-shooter
Version:
A tool library for handling window && iframe && worker communication based on the JSON RPC specification
2 lines (1 loc) • 5.57 kB
JavaScript
var x=Object.defineProperty,S=Object.defineProperties;var M=Object.getOwnPropertyDescriptors;var C=Object.getOwnPropertySymbols;var k=Object.prototype.hasOwnProperty,I=Object.prototype.propertyIsEnumerable;var y=(c,o,_)=>o in c?x(c,o,{enumerable:!0,configurable:!0,writable:!0,value:_}):c[o]=_,u=(c,o)=>{for(var _ in o||(o={}))k.call(o,_)&&y(c,_,o[_]);if(C)for(var _ of C(o))I.call(o,_)&&y(c,_,o[_]);return c},N=(c,o)=>S(c,M(o));var h=(c,o,_)=>(y(c,typeof o!="symbol"?o+"":o,_),_);var RPCShooter=function(c){"use strict";const o={CONNECT_TIMEOUT:{code:-32300,message:"Connect timeout"},APPLICATION_ERROR:{code:-32500,message:"Application error"},METHOD_NOT_FOUND:{code:-32601,message:"Method not found"}};class _{constructor(e){h(this,"_currentEndpoint");h(this,"_targetEndpoint");h(this,"_events");h(this,"_originOnmessage");h(this,"_receiveMessage");h(this,"onerror",null);h(this,"config");h(this,"sendAdapter");h(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(r=>{r(...s.args||[])});return}this.onerror&&this.onerror(N(u({},o.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,r=this.config?typeof this.config=="function"?this.config(i,this._targetEndpoint)||{}:this.config||{}:{};Array.isArray(s.transfer)&&s.transfer.length&&(r.transfer=s.transfer),this._targetEndpoint.postMessage(i,r)}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 v=class{constructor(e){h(this,"_event");h(this,"_methods",{});h(this,"_timeout",0);h(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 r=i.args[0],a=this._getAckEventName(r.method),d={jsonrpc:"2.0",id:r==null?void 0:r.id,error:{code:n,message:s,data:r}};this._event.emit(a,d)}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`${v.EVENT.SYN_SIGN}${e}`}_getAckEventName(e){return`${v.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 l=N(u({},o.TIMEOUT),{data:{timeout:s}});n(l)},s));const r=v.EVENT.CONNECT,a=this._getAckEventName(r),d=this._getSynEventName(r),g=()=>{clearTimeout(i),t()};this._event.on(a,g);const f=()=>{this._event.emit(a),g()};this._event.on(d,f),this._event.emit(d)}),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 r=this._getAckEventName(e);if(!i.id){t(...i.params);return}Promise.resolve(t(...i.params)).then(a=>{const d={jsonrpc:"2.0",result:a,id:i.id};this._event.emit(r,d)}).catch(a=>{const d={jsonrpc:"2.0",id:i.id,error:{code:(a==null?void 0:a.code)||o.APPLICATION_ERROR.code,message:(a==null?void 0:a.message)||o.APPLICATION_ERROR.message,data:null}};this._event.emit(r,d)})};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],r=i&&typeof i=="object"&&(Reflect.has(i,"isNotify")||Reflect.has(i,"timeout")),a=r?i:{isNotify:!1,timeout:0},d=r?t.slice(0,-1):t,g=this._getSynEventName(e),f=v.uuid(),l={jsonrpc:"2.0",method:e,params:d,id:f};if(this._event.emit(g,l),a.isNotify)n(void 0);else{const O=this._getAckEventName(e),p=a.timeout||this._timeout;let T;p&&(T=setTimeout(()=>{const E=N(u({},o.CONNECT_TIMEOUT),{data:{timeout:p}});s(E)},p));const A=E=>{E.id===f&&(clearTimeout(T),this._event.off(O,A),E.error?s(E.error):n(E.result))};this._event.on(O,A)}})}destroy(){Object.entries(this._methods).forEach(([n])=>{const s=this._getSynEventName(n);this._event.off(s)});const e=this._getAckEventName(v.EVENT.CONNECT),t=this._getSynEventName(v.EVENT.CONNECT);this._event.off(t),this._event.off(e),this._event.destroy&&this._event.destroy()}};let m=v;return h(m,"CODES",o),h(m,"EVENT",{SYN_SIGN:"syn:",ACK_SIGN:"ack:",CONNECT:"__rpc_connect_event",SYNC_METHODS:"__rpc_sync_methods_event"}),c.RPC=m,c.RPCCodes=o,c.RPCMessageEvent=_,Object.defineProperty(c,"__esModule",{value:!0}),c[Symbol.toStringTag]="Module",c}({});