comctx
Version:
Cross-context RPC solution with type safety and flexible adapters.
2 lines • 2.86 kB
JavaScript
var I=()=>[...Array(4)].map(()=>Math.floor(Math.random()*Number.MAX_SAFE_INTEGER).toString(16)).join("-"),M=I;var k=(a,e,...t)=>{let s=setTimeout(()=>{clearTimeout(s),a(...t),s=setInterval(a,e,...t)},0);return()=>clearInterval(s)},h=k;var b=a=>!a||!a.type||!a.id||!a.path||!a.sender||!a.args||!a.namespace||!a.timeStamp,w=async(a,e)=>{let t,s,r=new Set,o=new Promise((i,m)=>{t=h(async()=>{try{let d=M(),y=await a.onMessage(g=>{if(b(g))return;let c=g;c.namespace===e.namespace&&c.sender==="provide"&&c.type==="pong"&&c.id===d&&i()});y&&r.add(y),a.sendMessage({type:"ping",id:d,path:[],sender:"inject",args:[],namespace:e.namespace,timeStamp:Date.now()})}catch(d){m(d)}},e.heartbeatInterval)}),p=new Promise((i,m)=>{let d=setTimeout(()=>m(new Error(`Provider unavailable: heartbeat check timeout ${e.heartbeatTimeout}ms.`)),e.heartbeatTimeout);s=()=>clearTimeout(d)});await Promise.race([o,p]).finally(()=>{t(),s(),r.forEach(i=>i()),r.clear()})},P=(a,e,t)=>(e.onMessage(async s=>{if(b(s))return;let r=s;if(r.namespace===t.namespace&&r.sender==="inject")switch(r.type){case"ping":{e.sendMessage({...r,type:"pong",sender:"provide",namespace:t.namespace,timeStamp:Date.now()});break}case"apply":{try{let o=r.args?.map(p=>r.callbackIds?.includes(p)?(...i)=>{e.sendMessage({...r,id:p,data:i,type:"callback",sender:"provide",namespace:t.namespace,timeStamp:Date.now()})}:p);r.data=await(r.path?.reduce((p,i)=>p[i],a)).apply(a,o)}catch(o){r.error=o.message}e.sendMessage({...r,type:"apply",sender:"provide",namespace:t.namespace,timeStamp:Date.now()});break}}}),a),R=(a,e,t)=>{let s=(r,o)=>new Proxy(r,{get(i,m){return s(()=>{},[...o,m])},apply(i,m,d){return new Promise(async(y,g)=>{try{t.heartbeatCheck&&await w(e,t);let c=[],v=d.map(u=>{if(typeof u=="function"){let n=M();return c.push(n),e.onMessage(T=>{if(b(T))return;let l=T;l.namespace===t.namespace&&l.sender==="provide"&&l.type==="callback"&&l.id===n&&u(...l.data)}),n}else return u}),f=M(),x=await e.onMessage(u=>{if(b(u))return;let n=u;n.namespace===t.namespace&&n.sender==="provide"&&n.type==="apply"&&n.id===f&&(n.error?g(new Error(n.error)):y(n.data),x?.())});e.sendMessage({type:"apply",id:f,path:o,sender:"inject",callbackIds:c,args:v,timeStamp:Date.now(),namespace:t.namespace})}catch(c){g(c)}})}});return s(a,[])},A=(a,e)=>{let t;return(s,...r)=>t??=P(a(...r),s,e)},O=(a,e)=>{let t;return s=>t??=R(e.backup?Object.freeze(a()):{},s,e)},_=(a,e)=>{let t={namespace:e?.namespace??"__comctx__",heartbeatCheck:e?.heartbeatCheck??!0,heartbeatInterval:e?.heartbeatInterval??300,heartbeatTimeout:e?.heartbeatTimeout??1e3,backup:e?.backup??!1};if(t.heartbeatTimeout<=t.heartbeatInterval)throw new Error(`Invalid heartbeat config: timeout (${t.heartbeatTimeout}ms) must exceed interval (${t.heartbeatInterval}ms).`);return[A(a,t),O(a,t)]},q=_;export{q as default,_ as defineProxy};
//# sourceMappingURL=index.js.map