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

@sanity/comlink

Package Overview
Dependencies
Maintainers
61
Versions
92
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@sanity/comlink - npm Package Compare versions

Comparing version 1.0.0 to 1.0.1-canary.0

980

dist/index.js

@@ -1,1 +0,979 @@

import{v4 as e}from"uuid";import{fromEventObservable as t,setup as s,sendTo as n,assign as a,fromCallback as r,enqueueActions as o,assertEvent as i,raise as c,stopChild as d,createActor as u,emit as p}from"xstate";import{defer as l,fromEvent as g,map as f,pipe as m,filter as h,bufferCount as b,concatMap as y,take as v,EMPTY as q,takeUntil as k}from"rxjs";const x=e=>({context:t})=>{const{count:s,include:n,exclude:a,responseType:r="message.received"}=e;return{count:s,domain:t.domain,from:t.connectTo,include:n?Array.isArray(n)?n:[n]:[],exclude:a?Array.isArray(a)?a:[a]:[],responseType:r,target:t.target,to:t.name}},T=l((()=>g(window,"message"))),E=e=>t((({input:t})=>{return T.pipe(e?f(e):m(),h((e=>t=>{const{data:s}=t;return(!e.include.length||e.include.includes(s.type))&&(!e.exclude.length||!e.exclude.includes(s.type))&&s.domain===e.domain&&s.from===e.from&&s.to===e.to&&(!e.target||t.source===e.target)})(t)),f((s=t.responseType,e=>({type:s,message:e}))),t.count?m(b(t.count),y((e=>e)),v(t.count)):m());var s})),I="sanity/comlink",w=1e4,S=1e3,R=500,O="comlink/response",$="comlink/heartbeat",A="comlink/disconnect",B="comlink/handshake/syn",M="comlink/handshake/syn-ack",j="comlink/handshake/ack",_=[B,M,j],z=[O,A,$,..._],D=()=>s({types:{},actors:{listen:t((({input:e})=>{const t=e.signal?g(e.signal,"abort").pipe((s=`Request ${e.requestId} aborted`,e=>e.pipe(v(1),f((()=>{throw new Error(s)}))))):q;var s;return g(window,"message").pipe(h((t=>t.data?.type===O&&t.data?.responseTo===e.requestId&&!!t.source&&e.sources.has(t.source))),v(e.sources.size),k(t))}))},actions:{"send message":({context:e},t)=>{const{sources:s,targetOrigin:n}=e,{message:a}=t;s.forEach((e=>{e.postMessage(a,{targetOrigin:n})}))},"on success":n((({context:e})=>e.parentRef),(({context:e,self:t})=>(e.response&&e.resolvable?.resolve(e.response),{type:"request.success",requestId:t.id,response:e.response,responseTo:e.responseTo}))),"on fail":n((({context:e})=>e.parentRef),(({context:e,self:t})=>(console.warn(`Received no response to message '${e.type}' on client '${e.from}' (ID: '${e.id}').`),e.resolvable?.reject(new Error("No response received")),{type:"request.failed",requestId:t.id}))),"on abort":n((({context:e})=>e.parentRef),(({context:e,self:t})=>(e.resolvable?.reject(new Error("Request aborted")),{type:"request.aborted",requestId:t.id})))},guards:{expectsResponse:({context:e})=>e.expectResponse},delays:{initialTimeout:0,responseTimeout:1e4}}).createMachine({context:({input:t})=>({connectionId:t.connectionId,data:t.data,domain:t.domain,expectResponse:t.expectResponse??!1,from:t.from,id:`msg-${e()}`,parentRef:t.parentRef,resolvable:t.resolvable,response:null,responseTo:t.responseTo,signal:t.signal,sources:t.sources instanceof Set?t.sources:new Set([t.sources]),targetOrigin:t.targetOrigin,to:t.to,type:t.type}),initial:"idle",on:{abort:".aborted"},states:{idle:{after:{initialTimeout:[{target:"sending"}]}},sending:{entry:{type:"send message",params:({context:e})=>{const{connectionId:t,data:s,domain:n,from:a,id:r,responseTo:o,to:i,type:c}=e;return{message:{connectionId:t,data:s,domain:n,from:a,id:r,to:i,type:c,responseTo:o}}}},always:[{guard:"expectsResponse",target:"awaiting"},"success"]},awaiting:{invoke:{id:"listen for response",src:"listen",input:({context:e})=>({requestId:e.id,sources:e.sources,signal:e.signal}),onError:"aborted"},after:{responseTimeout:"failed"},on:{message:{actions:a({response:({event:e})=>e.data.data,responseTo:({event:e})=>e.data.responseTo}),target:"success"}}},failed:{type:"final",entry:"on fail"},success:{type:"final",entry:"on success"},aborted:{type:"final",entry:"on abort"}},output:({context:e,self:t})=>({requestId:t.id,response:e.response,responseTo:e.responseTo})}),C=r((({sendBack:e,input:t})=>{const s=()=>{e(t.event)};t.immediate&&s();const n=setInterval(s,t.interval);return()=>{clearInterval(n)}})),N=()=>s({types:{},actors:{requestMachine:D(),listen:E(),sendBackAtInterval:C},actions:{"buffer message":o((({enqueue:e})=>{e.assign({buffer:({event:e,context:t})=>(i(e,"post"),[...t.buffer,e.data])}),e.emit((({event:e})=>(i(e,"post"),{type:"_buffer.added",message:e.data})))})),"create request":a({requests:({context:t,event:s,self:n,spawn:a})=>{i(s,"request");const r=(Array.isArray(s.data)?s.data:[s.data]).map((s=>{const r=`req-${e()}`;return a("requestMachine",{id:r,input:{connectionId:t.connectionId,data:s.data,domain:t.domain,expectResponse:s.expectResponse,from:t.name,parentRef:n,responseTo:s.responseTo,sources:t.target,targetOrigin:t.targetOrigin,to:t.connectTo,type:s.type}})}));return[...t.requests,...r]}}),"emit received message":o((({enqueue:e})=>{e.emit((({event:e})=>(i(e,"message.received"),{type:"_message",message:e.message.data}))),e.emit((({event:e})=>(i(e,"message.received"),{type:e.message.data.type,message:e.message.data})))})),"flush buffer":o((({enqueue:e})=>{e.raise((({context:e})=>({type:"request",data:e.buffer.map((({data:e,type:t})=>({data:e,type:t})))}))),e.emit((({context:e})=>({type:"_buffer.flushed",messages:e.buffer}))),e.assign({buffer:[]})})),post:c((({event:e})=>(i(e,"post"),{type:"request",data:{data:e.data.data,expectResponse:!0,type:e.data.type}}))),"remove request":o((({context:e,enqueue:t,event:s})=>{i(s,["request.success","request.failed","request.aborted"]),d(s.requestId),t.assign({requests:e.requests.filter((({id:e})=>e!==s.requestId))})})),respond:c((({event:e})=>(i(e,"response"),{type:"request",data:{data:e.data,type:O,responseTo:e.respondTo}}))),"send handshake ack":c({type:"request",data:{type:j}}),"send disconnect":c((()=>({type:"request",data:{type:A}}))),"send handshake syn":c({type:"request",data:{type:B}}),"set target":a({target:({event:e})=>(i(e,"target.set"),e.target)})},guards:{"has target":({context:e})=>!!e.target,"should send heartbeats":({context:e})=>e.heartbeat}}).createMachine({id:"channel",context:({input:t})=>({id:t.id||`${t.name}-${e()}`,buffer:[],connectionId:`cnx-${e()}`,connectTo:t.connectTo,domain:t.domain??I,heartbeat:t.heartbeat??!1,name:t.name,requests:[],target:t.target,targetOrigin:t.targetOrigin}),on:{"target.set":{actions:"set target"},"request.success":{actions:"remove request"},"request.failed":{actions:"remove request"}},initial:"idle",states:{idle:{on:{connect:{target:"handshaking",guard:"has target"},post:{actions:"buffer message"}}},handshaking:{id:"handshaking",invoke:[{id:"send syn",src:"sendBackAtInterval",input:()=>({event:{type:"syn"},interval:500,immediate:!0})},{id:"listen for handshake",src:"listen",input:e=>x({include:M,count:1})(e)}],on:{syn:{actions:"send handshake syn"},request:{actions:"create request"},post:{actions:"buffer message"},"message.received":{target:"connected"},disconnect:{target:"disconnected"}},exit:"send handshake ack"},connected:{entry:"flush buffer",invoke:{id:"listen for messages",src:"listen",input:x({exclude:[O,$]})},on:{post:{actions:"post"},request:{actions:"create request"},response:{actions:"respond"},"message.received":{actions:"emit received message"},disconnect:{target:"disconnected"}},initial:"heartbeat",states:{heartbeat:{initial:"checking",states:{checking:{always:{guard:"should send heartbeats",target:"sending"}},sending:{on:{"request.failed":{target:"#handshaking"}},invoke:{id:"send heartbeat",src:"sendBackAtInterval",input:()=>({event:{type:"post",data:{type:$,data:void 0}},interval:2e3,immediate:!1})}}}}}},disconnected:{id:"disconnected",entry:"send disconnect",on:{request:{actions:"create request"},post:{actions:"buffer message"},connect:{target:"handshaking",guard:"has target"}}}}}),P=(t,s=N())=>{const n=t.id||`${t.name}-${e()}`,a=u(s,{input:{...t,id:n}}),r=()=>{a.stop()};return{actor:a,connect:()=>{a.send({type:"connect"})},disconnect:()=>{a.send({type:"disconnect"})},id:n,name:t.name,machine:s,on:(e,t)=>{const{unsubscribe:s}=a.on(e,(async e=>{const s=await t(e.message.data);s&&a.send({type:"response",respondTo:e.message.id,data:s})}));return s},onStatus:e=>{const t=a.getSnapshot();let s="string"==typeof t.value?t.value:Object.keys(t.value)[0];const{unsubscribe:n}=a.subscribe((t=>{const n="string"==typeof t.value?t.value:Object.keys(t.value)[0];s!==n&&(s=n,e(n))}));return n},post:e=>{a.send({type:"post",data:e})},setTarget:e=>{a.send({type:"target.set",target:e})},start:()=>(a.start(),r),stop:r,get target(){return a.getSnapshot().context.target}}},F=()=>{},G=e=>{const{targetOrigin:t}=e,s=new Set,n=new Set,a=e=>{e.disconnect(),setTimeout((()=>{e.stop()}),0)};return{addTarget:e=>{if(s.has(e))return F;if(!s.size||!n.size)return s.add(e),n.forEach((t=>{t.channels.forEach((t=>{t.setTarget(e),t.connect()}))})),()=>{s.delete(e),n.forEach((t=>{t.channels.forEach((t=>{t.target===e&&t.disconnect()}))}))};s.add(e);const r=new Set;return n.forEach((s=>{const n=P({...s.input,target:e,targetOrigin:t},s.machine);r.add(n),s.channels.add(n),s.subscribers.forEach((({type:e,handler:t,unsubscribers:s})=>{s.push(n.on(e,t))})),s.internalEventSubscribers.forEach((({type:e,handler:t,unsubscribers:s})=>{s.push(n.actor.on(e,t).unsubscribe)})),s.statusSubscribers.forEach((({handler:e,unsubscribers:t})=>{t.push(n.onStatus((t=>e({channel:n.id,status:t}))))})),n.start(),n.connect()})),()=>{s.delete(e),r.forEach((e=>{a(e),n.forEach((t=>{t.channels.delete(e)}))}))}},createConnection:(e,a=N())=>{const r={channels:new Set,input:e,internalEventSubscribers:new Set,machine:a,statusSubscribers:new Set,subscribers:new Set};n.add(r);const{channels:o,internalEventSubscribers:i,statusSubscribers:c,subscribers:d}=r;if(s.size)s.forEach((s=>{const n=P({...e,target:s,targetOrigin:t},a);o.add(n)}));else{const s=P({...e,targetOrigin:t},a);o.add(s)}const u=()=>{o.forEach((e=>{e.disconnect(),e.stop()}))};return{on:(e,t)=>{const s=[];o.forEach((n=>{s.push(n.on(e,t))}));const n={type:e,handler:t,unsubscribers:s};return d.add(n),()=>{s.forEach((e=>e())),d.delete(n)}},onInternalEvent:(e,t)=>{const s=[];o.forEach((n=>{s.push(n.actor.on(e,t).unsubscribe)}));const n={type:e,handler:t,unsubscribers:s};return i.add(n),()=>{s.forEach((e=>e())),i.delete(n)}},onStatus:e=>{const t=[];o.forEach((s=>{t.push(s.onStatus((t=>e({channel:s.id,status:t}))))}));const s={handler:e,unsubscribers:t};return c.add(s),()=>{t.forEach((e=>e())),c.delete(s)}},post:e=>{o.forEach((t=>{t.post(e)}))},start:()=>(o.forEach((e=>{e.start(),e.connect()})),u),stop:u}},destroy:()=>{n.forEach((({channels:e})=>{e.forEach((t=>{a(t),e.delete(t)}))}))}}},H=()=>s({types:{},actors:{requestMachine:D(),listen:E()},actions:{"buffer incoming message":a({handshakeBuffer:({event:e,context:t})=>(i(e,"message.received"),[...t.handshakeBuffer,e])}),"buffer message":o((({enqueue:e})=>{e.assign({buffer:({event:e,context:t})=>(i(e,"post"),[...t.buffer,{data:e.data,resolvable:e.resolvable,signal:e.signal}])}),e.emit((({event:e})=>(i(e,"post"),{type:"_buffer.added",message:e.data})))})),"create request":a({requests:({context:t,event:s,self:n,spawn:a})=>{i(s,"request");const r=(Array.isArray(s.data)?s.data:[s.data]).map((s=>{const r=`req-${e()}`;return a("requestMachine",{id:r,input:{connectionId:t.connectionId,data:s.data,domain:t.domain,expectResponse:s.expectResponse,from:t.name,parentRef:n,resolvable:s.resolvable,responseTo:s.responseTo,sources:t.target,targetOrigin:t.targetOrigin,to:t.connectTo,type:s.type,signal:s.signal}})}));return[...t.requests,...r]}}),"emit heartbeat":p((()=>({type:"_heartbeat"}))),"emit received message":o((({enqueue:e})=>{e.emit((({event:e})=>(i(e,"message.received"),{type:"_message",message:e.message.data}))),e.emit((({event:e})=>(i(e,"message.received"),{type:e.message.data.type,message:e.message.data})))})),"flush buffer":o((({enqueue:e})=>{e.raise((({context:e})=>({type:"request",data:e.buffer.map((({data:e,resolvable:t,signal:s})=>({data:e.data,type:e.type,expectResponse:!!t,resolvable:t,signal:s})))}))),e.emit((({context:e})=>({type:"_buffer.flushed",messages:e.buffer.map((({data:e})=>e))}))),e.assign({buffer:[]})})),"flush handshake buffer":o((({context:e,enqueue:t})=>{e.handshakeBuffer.forEach((e=>t.raise(e))),t.assign({handshakeBuffer:[]})})),post:c((({event:e})=>(i(e,"post"),{type:"request",data:{data:e.data.data,expectResponse:!!e.resolvable,type:e.data.type,resolvable:e.resolvable,signal:e.signal}}))),"remove request":o((({context:e,enqueue:t,event:s})=>{i(s,["request.success","request.failed","request.aborted"]),d(s.requestId),t.assign({requests:e.requests.filter((({id:e})=>e!==s.requestId))})})),"send response":c((({event:e})=>(i(e,["message.received","heartbeat.received"]),{type:"request",data:{type:O,responseTo:e.message.data.id,data:void 0}}))),"send handshake syn ack":c({type:"request",data:{type:M}}),"set connection config":a({connectionId:({event:e})=>(i(e,"message.received"),e.message.data.connectionId),target:({event:e})=>(i(e,"message.received"),e.message.source||void 0),targetOrigin:({event:e})=>(i(e,"message.received"),e.message.origin)})},guards:{hasSource:({context:e})=>null!==e.target}}).createMachine({id:"node",context:({input:e})=>({buffer:[],connectionId:null,connectTo:e.connectTo,domain:e.domain??I,handshakeBuffer:[],name:e.name,requests:[],target:void 0,targetOrigin:null}),on:{"request.success":{actions:"remove request"},"request.failed":{actions:"remove request"},"request.aborted":{actions:"remove request"}},initial:"idle",states:{idle:{invoke:{id:"listen for handshake syn",src:"listen",input:x({include:B,count:1}),onDone:{target:"handshaking",guard:"hasSource"}},on:{"message.received":{actions:"set connection config"},post:{actions:"buffer message"}}},handshaking:{entry:"send handshake syn ack",invoke:[{id:"listen for handshake ack",src:"listen",input:x({include:j,count:1,responseType:"handshake.complete"}),onDone:"connected"},{id:"listen for disconnect",src:"listen",input:x({include:A,count:1,responseType:"disconnect"})},{id:"listen for messages",src:"listen",input:x({exclude:[A,j,$,O]})}],on:{request:{actions:"create request"},post:{actions:"buffer message"},"message.received":{actions:"buffer incoming message"},disconnect:{target:"idle"}}},connected:{entry:["flush handshake buffer","flush buffer"],invoke:[{id:"listen for messages",src:"listen",input:x({exclude:[O,$]})},{id:"listen for heartbeat",src:"listen",input:x({include:$,responseType:"heartbeat.received"})},{id:"listen for disconnect",src:"listen",input:x({include:A,count:1,responseType:"disconnect"})}],on:{request:{actions:"create request"},post:{actions:"post"},disconnect:{target:"idle"},"message.received":{actions:["send response","emit received message"]},"heartbeat.received":{actions:["send response","emit heartbeat"]}}}}}),J=(e,t=H())=>{const s=u(t,{input:e}),n=()=>{s.stop()};return{actor:s,fetch:(e,t)=>{const n=Promise.withResolvers();return s.send({type:"post",data:e,resolvable:n,signal:t?.signal}),n.promise},machine:t,on:(e,t)=>{const{unsubscribe:n}=s.on(e,(e=>{t(e.message.data)}));return n},onStatus:e=>{const t=s.getSnapshot();let n="string"==typeof t.value?t.value:Object.keys(t.value)[0];const{unsubscribe:a}=s.subscribe((t=>{const s="string"==typeof t.value?t.value:Object.keys(t.value)[0];n!==s&&(n=s,e(s))}));return a},post:e=>{s.send({type:"post",data:e})},start:()=>(s.start(),n),stop:n}};export{I as DOMAIN,R as HANDSHAKE_INTERVAL,_ as HANDSHAKE_MSG_TYPES,S as HEARTBEAT_INTERVAL,z as INTERNAL_MSG_TYPES,A as MSG_DISCONNECT,j as MSG_HANDSHAKE_ACK,B as MSG_HANDSHAKE_SYN,M as MSG_HANDSHAKE_SYN_ACK,$ as MSG_HEARTBEAT,O as MSG_RESPONSE,w as RESPONSE_TIMEOUT,P as createChannel,N as createChannelMachine,G as createController,E as createListenLogic,J as createNode,H as createNodeMachine,D as createRequestMachine};//# sourceMappingURL=index.js.map
import { v4 } from "uuid";
import { fromEventObservable, setup, sendTo, assign, fromCallback, enqueueActions, assertEvent, raise, stopChild, createActor, emit } from "xstate";
import { defer, fromEvent, map, pipe, filter, bufferCount, concatMap, take, EMPTY, takeUntil } from "rxjs";
const listenInputFromContext = (config) => ({
context
}) => {
const { count, include, exclude, responseType = "message.received" } = config;
return {
count,
domain: context.domain,
from: context.connectTo,
include: include ? Array.isArray(include) ? include : [include] : [],
exclude: exclude ? Array.isArray(exclude) ? exclude : [exclude] : [],
responseType,
target: context.target,
to: context.name
};
}, listenFilter = (input) => (event) => {
const { data } = event;
return (input.include.length ? input.include.includes(data.type) : !0) && (input.exclude.length ? !input.exclude.includes(data.type) : !0) && data.domain === input.domain && data.from === input.from && data.to === input.to && (!input.target || event.source === input.target);
}, eventToMessage = (type) => (event) => ({
type,
message: event
}), messageEvents$ = defer(
() => fromEvent(window, "message")
), createListenLogic = (compatMap) => fromEventObservable(({ input }) => messageEvents$.pipe(
compatMap ? map(compatMap) : pipe(),
filter(listenFilter(input)),
map(eventToMessage(input.responseType)),
input.count ? pipe(
bufferCount(input.count),
concatMap((arr) => arr),
take(input.count)
) : pipe()
)), DOMAIN = "sanity/comlink", RESPONSE_TIMEOUT = 1e4, HEARTBEAT_INTERVAL = 1e3, HANDSHAKE_INTERVAL = 500, MSG_RESPONSE = "comlink/response", MSG_HEARTBEAT = "comlink/heartbeat", MSG_DISCONNECT = "comlink/disconnect", MSG_HANDSHAKE_SYN = "comlink/handshake/syn", MSG_HANDSHAKE_SYN_ACK = "comlink/handshake/syn-ack", MSG_HANDSHAKE_ACK = "comlink/handshake/ack", HANDSHAKE_MSG_TYPES = [
MSG_HANDSHAKE_SYN,
MSG_HANDSHAKE_SYN_ACK,
MSG_HANDSHAKE_ACK
], INTERNAL_MSG_TYPES = [
MSG_RESPONSE,
MSG_DISCONNECT,
MSG_HEARTBEAT,
...HANDSHAKE_MSG_TYPES
], throwOnEvent = (message) => (source) => source.pipe(
take(1),
map(() => {
throw new Error(message);
})
), createRequestMachine = () => setup({
types: {},
actors: {
listen: fromEventObservable(
({
input
}) => {
const abortSignal$ = input.signal ? fromEvent(input.signal, "abort").pipe(
throwOnEvent(`Request ${input.requestId} aborted`)
) : EMPTY, messageFilter = (event) => event.data?.type === MSG_RESPONSE && event.data?.responseTo === input.requestId && !!event.source && input.sources.has(event.source);
return fromEvent(window, "message").pipe(
filter(messageFilter),
take(input.sources.size),
takeUntil(abortSignal$)
);
}
)
},
actions: {
"send message": ({ context }, params) => {
const { sources, targetOrigin } = context, { message } = params;
sources.forEach((source) => {
source.postMessage(message, { targetOrigin });
});
},
"on success": sendTo(
({ context }) => context.parentRef,
({ context, self }) => (context.response && context.resolvable?.resolve(context.response), {
type: "request.success",
requestId: self.id,
response: context.response,
responseTo: context.responseTo
})
),
"on fail": sendTo(
({ context }) => context.parentRef,
({ context, self }) => (console.warn(
`Received no response to message '${context.type}' on client '${context.from}' (ID: '${context.id}').`
), context.resolvable?.reject(new Error("No response received")), { type: "request.failed", requestId: self.id })
),
"on abort": sendTo(
({ context }) => context.parentRef,
({ context, self }) => (context.resolvable?.reject(new Error("Request aborted")), { type: "request.aborted", requestId: self.id })
)
},
guards: {
expectsResponse: ({ context }) => context.expectResponse
},
delays: {
initialTimeout: 0,
responseTimeout: RESPONSE_TIMEOUT
}
}).createMachine({
/** @xstate-layout N4IgpgJg5mDOIC5QAoC2BDAxgCwJYDswBKAOlwgBswBiAD1gBd0GwT0AzFgJ2QNwdzoKAFVyowAewCuDItTRY8hUuSoBtAAwBdRKAAOE2P1wT8ukLUQBGAEwBWEgBYAnK+eOAzB7sB2DzY8rABoQAE9rDQc3V0cNTw8fAA4NHwBfVJCFHAJiElgwfAgCKGpNHSQQAyMBU3NLBDsrDxI7DTaAjQA2OOcNDxDwhHsNJx9Ou0TOq2cJxP9HdMyMbOU8gqL8ErUrcv1DY1qK+sbm1vaPLp6+gcRnGydo9wDGycWQLKVc9AB3dGNN6jiWCwdAwMrmKoHMxHRCJRKOEiJHwuZKBZwXKzBMKIGyYkhtAkXOweTqOHw2RJvD45Ug-P4CAH0JgsNicMA8LhwAz4fKicTSWTyZafWm-f5QcEVSE1aGgepwhFIlF9aYYrGDC4+JzEppjGzOUkeGbpDIgfASCBwczU5QQ-YyuqIAC0nRuCBd+IJXu9KSpwppZEoYDt1RMsosiEcNjdVjiJEeGisiSTHkcVgWpptuXyhWKIahjqGzi1BqRJINnVcdkcbuTLS9VYC8ISfsUAbp4vzDphCHJIyjBvJNlxNmRNexQ3sJGH43GPj8jWJrZWuXYfyoEC7YcLsbrgRsjkcvkmdgNbopVhIPhVfnsh8ClMz-tWsCkmEwcHgUvt257u8v+6Hse4xnhOdZnImVidPqCRNB4JqpEAA */
context: ({ input }) => ({
connectionId: input.connectionId,
data: input.data,
domain: input.domain,
expectResponse: input.expectResponse ?? !1,
from: input.from,
id: `msg-${v4()}`,
parentRef: input.parentRef,
resolvable: input.resolvable,
response: null,
responseTo: input.responseTo,
signal: input.signal,
sources: input.sources instanceof Set ? input.sources : /* @__PURE__ */ new Set([input.sources]),
targetOrigin: input.targetOrigin,
to: input.to,
type: input.type
}),
initial: "idle",
on: {
abort: ".aborted"
},
states: {
idle: {
after: {
initialTimeout: [
{
target: "sending"
}
]
}
},
sending: {
entry: {
type: "send message",
params: ({ context }) => {
const { connectionId, data, domain, from, id, responseTo, to, type } = context;
return { message: {
connectionId,
data,
domain,
from,
id,
to,
type,
responseTo
} };
}
},
always: [
{
guard: "expectsResponse",
target: "awaiting"
},
"success"
]
},
awaiting: {
invoke: {
id: "listen for response",
src: "listen",
input: ({ context }) => ({
requestId: context.id,
sources: context.sources,
signal: context.signal
}),
onError: "aborted"
},
after: {
responseTimeout: "failed"
},
on: {
message: {
actions: assign({
response: ({ event }) => event.data.data,
responseTo: ({ event }) => event.data.responseTo
}),
target: "success"
}
}
},
failed: {
type: "final",
entry: "on fail"
},
success: {
type: "final",
entry: "on success"
},
aborted: {
type: "final",
entry: "on abort"
}
},
output: ({ context, self }) => ({
requestId: self.id,
response: context.response,
responseTo: context.responseTo
})
}), sendBackAtInterval = fromCallback(({ sendBack, input }) => {
const send = () => {
sendBack(input.event);
};
input.immediate && send();
const interval = setInterval(send, input.interval);
return () => {
clearInterval(interval);
};
}), createChannelMachine = () => setup({
types: {},
actors: {
requestMachine: createRequestMachine(),
listen: createListenLogic(),
sendBackAtInterval
},
actions: {
"buffer message": enqueueActions(({ enqueue }) => {
enqueue.assign({
buffer: ({ event, context }) => (assertEvent(event, "post"), [...context.buffer, event.data])
}), enqueue.emit(({ event }) => (assertEvent(event, "post"), {
type: "_buffer.added",
message: event.data
}));
}),
"create request": assign({
requests: ({ context, event, self, spawn }) => {
assertEvent(event, "request");
const requests = (Array.isArray(event.data) ? event.data : [event.data]).map((request) => {
const id = `req-${v4()}`;
return spawn("requestMachine", {
id,
input: {
connectionId: context.connectionId,
data: request.data,
domain: context.domain,
expectResponse: request.expectResponse,
from: context.name,
parentRef: self,
responseTo: request.responseTo,
sources: context.target,
targetOrigin: context.targetOrigin,
to: context.connectTo,
type: request.type
}
});
});
return [...context.requests, ...requests];
}
}),
"emit received message": enqueueActions(({ enqueue }) => {
enqueue.emit(({ event }) => (assertEvent(event, "message.received"), {
type: "_message",
message: event.message.data
})), enqueue.emit(({ event }) => (assertEvent(event, "message.received"), {
type: event.message.data.type,
message: event.message.data
}));
}),
"flush buffer": enqueueActions(({ enqueue }) => {
enqueue.raise(({ context }) => ({
type: "request",
data: context.buffer.map(({ data, type }) => ({ data, type }))
})), enqueue.emit(({ context }) => ({
type: "_buffer.flushed",
messages: context.buffer
})), enqueue.assign({
buffer: []
});
}),
post: raise(({ event }) => (assertEvent(event, "post"), {
type: "request",
data: {
data: event.data.data,
expectResponse: !0,
type: event.data.type
}
})),
"remove request": enqueueActions(({ context, enqueue, event }) => {
assertEvent(event, ["request.success", "request.failed", "request.aborted"]), stopChild(event.requestId), enqueue.assign({ requests: context.requests.filter(({ id }) => id !== event.requestId) });
}),
respond: raise(({ event }) => (assertEvent(event, "response"), {
type: "request",
data: {
data: event.data,
type: MSG_RESPONSE,
responseTo: event.respondTo
}
})),
"send handshake ack": raise({
type: "request",
data: { type: MSG_HANDSHAKE_ACK }
}),
"send disconnect": raise(() => ({
type: "request",
data: { type: MSG_DISCONNECT }
})),
"send handshake syn": raise({
type: "request",
data: { type: MSG_HANDSHAKE_SYN }
}),
"set target": assign({
target: ({ event }) => (assertEvent(event, "target.set"), event.target)
})
},
guards: {
"has target": ({ context }) => !!context.target,
"should send heartbeats": ({ context }) => context.heartbeat
}
}).createMachine({
/** @xstate-layout N4IgpgJg5mDOIC5QGMAWBDAdpsAbAxAC7oBOMhAdLGIQNoAMAuoqAA4D2sAloV+5ixAAPRAHZRAJgoAWABz0ArHICMy2QGZZCgJwAaEAE9EE+tIrb6ANgkLl46fTuj1AXxf60WHARJgAjgCucJSwAcjIcLAMzEggHNy8-IIiCKLS2hQS6qb2yurisrL6RgjK9LIyCuqq0g7WstZuHhjYePi+gcEUAGboXLiQ0YLxPHwCsSmiCgoykpayDtqS6trqxYjKEk0gnq24FFwQA-jI-DjIdEzDnKNJExuOZpZ12eq29OrSCuupypYUojUaTKCnm5Wk2123gORzA+HilxibBuiXGoBSGnUAIU4gU9FWamUtR+lmUM1EllBEkslMUEnpkJa0JaEFgGAA1lxMFB8LADJghrERqjkhtshk3mTtNo5OpqpYfqCKhTptoqpY1WUtu4dky8BQWWz0Jzue1-EFYIjrgkxqLSupqRRPpoPqJtLI0hIioZENJJE7NnJ8ZYHVk1YyvPrDRyuTyEYLkTa7uixVlMh81KGFhS1j6EPkZlpVjTphr8mkI3sDVhWTHTQBbSLoGAUXwRLgAN0GVyFKNt91KimUFEKXvKC2s9R+6X+jipnzJeSqEJ1UKjNaNJp5EC4sFOrQuCbifeTwg2cgoym0RPxDtqkj0eaB9Ao8zSolMEivZVcq71+33c5CEgeFOCtXskzRM8EDxKRpmkSw3QJbQsmpH5tHmV8JHSbJpDsakV2aSMALOMALhAjoLXAxNbiglI-SxWw1Vw0QNDw0Qfg9KQ7EJSxHHxApK2hQCyOAiAzVgDhMGoI9hX7FMEHSF8cWkelpHURCbBsb481xAEgT9BQJCmWQsiE-URPI8TG1gWBmzAVsyLATtuyRY9ILtWoKmlL82Kqd0tAVJ91LMHFZDKIkVlkNVZHMkiDzE-Adz3UjDx7GiRQHCKnheD53k+HSSkDDIwpBVTqQwuKKEssSDTAUhCAAI3qyg0DIrd8Fkk86MQUMnVM+RynoegTDJH48hGp0vR-FDRqqKqasgOqGua9AQjATAd1NSiul6fpXOtWi7Wy19cslD4vnG7IX3oVjVDUVYEJQqrksW8SdstLqPKy0wKgG1RhtMWogqKhoMjkWp6XxUyFBe3c3tAz70vco6fq+V8PTkGUFzdQqNnELEM2yClrwwzQ4ZShKQJqr7UYU98AS0W9pT4z5pHG0yXwMkNNTyGk3B1TB2AgOBBDXXBDsyhSFG9EovQqN5i1JeRcKqw4Bkl+ToMx8x0j+EaqQ9XMSkBURMgMkEwQWKro2NWNNdPFJAzN0lJGM4slDxhBEJfXyplBd03wW1KxIdnrBxBh4JAyW75C8rJpmDqmIGWkgmpasPjqUcaHooMLHA0uU1UkJOgKW1B6rT1bWor5At0zgcTAkK7hrz1irB0D8cW0UvRPLyv07WqgNq2qAG+l9SnXUz0UOXD5xuMs3Y4+DVJBX7UiKrV6Q8gcfoJO54rFefLLqfJYX1WKYNLxL4NO1NwgA */
id: "channel",
context: ({ input }) => ({
id: input.id || `${input.name}-${v4()}`,
buffer: [],
connectionId: `cnx-${v4()}`,
connectTo: input.connectTo,
domain: input.domain ?? DOMAIN,
heartbeat: input.heartbeat ?? !1,
name: input.name,
requests: [],
target: input.target,
targetOrigin: input.targetOrigin
}),
on: {
"target.set": {
actions: "set target"
},
"request.success": {
actions: "remove request"
},
"request.failed": {
actions: "remove request"
}
},
initial: "idle",
states: {
idle: {
on: {
connect: {
target: "handshaking",
guard: "has target"
},
post: {
actions: "buffer message"
}
}
},
handshaking: {
id: "handshaking",
invoke: [
{
id: "send syn",
src: "sendBackAtInterval",
input: () => ({
event: { type: "syn" },
interval: HANDSHAKE_INTERVAL,
immediate: !0
})
},
{
id: "listen for handshake",
src: "listen",
input: (input) => listenInputFromContext({
include: MSG_HANDSHAKE_SYN_ACK,
count: 1
})(input)
/* Below would maybe be more readable than transitioning to
'connected' on 'message', and 'ack' on exit but having onDone when
using passing invocations currently breaks XState Editor */
// onDone: {
// target: 'connected',
// actions: 'ack',
// },
}
],
on: {
syn: {
actions: "send handshake syn"
},
request: {
actions: "create request"
},
post: {
actions: "buffer message"
},
"message.received": {
target: "connected"
},
disconnect: {
target: "disconnected"
}
},
exit: "send handshake ack"
},
connected: {
entry: "flush buffer",
invoke: {
id: "listen for messages",
src: "listen",
input: listenInputFromContext({
exclude: [MSG_RESPONSE, MSG_HEARTBEAT]
})
},
on: {
post: {
actions: "post"
},
request: {
actions: "create request"
},
response: {
actions: "respond"
},
"message.received": {
actions: "emit received message"
},
disconnect: {
target: "disconnected"
}
},
initial: "heartbeat",
states: {
heartbeat: {
initial: "checking",
states: {
checking: {
always: {
guard: "should send heartbeats",
target: "sending"
}
},
sending: {
on: {
"request.failed": {
target: "#handshaking"
}
},
invoke: {
id: "send heartbeat",
src: "sendBackAtInterval",
input: () => ({
event: { type: "post", data: { type: MSG_HEARTBEAT, data: void 0 } },
interval: 2e3,
immediate: !1
})
}
}
}
}
}
},
disconnected: {
id: "disconnected",
entry: "send disconnect",
on: {
request: {
actions: "create request"
},
post: {
actions: "buffer message"
},
connect: {
target: "handshaking",
guard: "has target"
}
}
}
}
}), createChannel = (input, machine = createChannelMachine()) => {
const id = input.id || `${input.name}-${v4()}`, actor = createActor(machine, {
input: { ...input, id }
}), on = (type, handler) => {
const { unsubscribe } = actor.on(
// @ts-expect-error @todo `type` typing
type,
async (event) => {
const response = await handler(event.message.data);
response && actor.send({ type: "response", respondTo: event.message.id, data: response });
}
);
return unsubscribe;
}, connect = () => {
actor.send({ type: "connect" });
}, disconnect = () => {
actor.send({ type: "disconnect" });
}, onStatus = (handler) => {
const currentSnapshot = actor.getSnapshot();
let currentStatus = typeof currentSnapshot.value == "string" ? currentSnapshot.value : Object.keys(currentSnapshot.value)[0];
const { unsubscribe } = actor.subscribe((state) => {
const status = typeof state.value == "string" ? state.value : Object.keys(state.value)[0];
currentStatus !== status && (currentStatus = status, handler(status));
});
return unsubscribe;
}, setTarget = (target) => {
actor.send({ type: "target.set", target });
}, post = (data) => {
actor.send({ type: "post", data });
}, stop = () => {
actor.stop();
}, start = () => (actor.start(), stop);
return {
actor,
connect,
disconnect,
id,
name: input.name,
machine,
on,
onStatus,
post,
setTarget,
start,
stop,
get target() {
return actor.getSnapshot().context.target;
}
};
}, noop = () => {
}, createController = (input) => {
const { targetOrigin } = input, targets = /* @__PURE__ */ new Set(), connections = /* @__PURE__ */ new Set(), addTarget = (target) => {
if (targets.has(target))
return noop;
if (!targets.size || !connections.size)
return targets.add(target), connections.forEach((connection) => {
connection.channels.forEach((channel) => {
channel.setTarget(target), channel.connect();
});
}), () => {
targets.delete(target), connections.forEach((connection) => {
connection.channels.forEach((channel) => {
channel.target === target && channel.disconnect();
});
});
};
targets.add(target);
const targetChannels = /* @__PURE__ */ new Set();
return connections.forEach((connection) => {
const channel = createChannel(
{
...connection.input,
target,
targetOrigin
},
connection.machine
);
targetChannels.add(channel), connection.channels.add(channel), connection.subscribers.forEach(({ type, handler, unsubscribers }) => {
unsubscribers.push(channel.on(type, handler));
}), connection.internalEventSubscribers.forEach(({ type, handler, unsubscribers }) => {
unsubscribers.push(channel.actor.on(type, handler).unsubscribe);
}), connection.statusSubscribers.forEach(({ handler, unsubscribers }) => {
unsubscribers.push(channel.onStatus((status) => handler({ channel: channel.id, status })));
}), channel.start(), channel.connect();
}), () => {
targets.delete(target), targetChannels.forEach((channel) => {
cleanupChannel(channel), connections.forEach((connection) => {
connection.channels.delete(channel);
});
});
};
}, cleanupChannel = (channel) => {
channel.disconnect(), setTimeout(() => {
channel.stop();
}, 0);
};
return {
addTarget,
createConnection: (input2, machine = createChannelMachine()) => {
const connection = {
channels: /* @__PURE__ */ new Set(),
input: input2,
internalEventSubscribers: /* @__PURE__ */ new Set(),
machine,
statusSubscribers: /* @__PURE__ */ new Set(),
subscribers: /* @__PURE__ */ new Set()
};
connections.add(connection);
const { channels, internalEventSubscribers, statusSubscribers, subscribers } = connection;
if (targets.size)
targets.forEach((target) => {
const channel = createChannel(
{
...input2,
target,
targetOrigin
},
machine
);
channels.add(channel);
});
else {
const channel = createChannel({ ...input2, targetOrigin }, machine);
channels.add(channel);
}
const post = (data) => {
channels.forEach((channel) => {
channel.post(data);
});
}, on = (type, handler) => {
const unsubscribers = [];
channels.forEach((channel) => {
unsubscribers.push(channel.on(type, handler));
});
const subscriber = { type, handler, unsubscribers };
return subscribers.add(subscriber), () => {
unsubscribers.forEach((unsub) => unsub()), subscribers.delete(subscriber);
};
}, onInternalEvent = (type, handler) => {
const unsubscribers = [];
channels.forEach((channel) => {
unsubscribers.push(channel.actor.on(type, handler).unsubscribe);
});
const subscriber = { type, handler, unsubscribers };
return internalEventSubscribers.add(subscriber), () => {
unsubscribers.forEach((unsub) => unsub()), internalEventSubscribers.delete(subscriber);
};
}, onStatus = (handler) => {
const unsubscribers = [];
channels.forEach((channel) => {
unsubscribers.push(channel.onStatus((status) => handler({ channel: channel.id, status })));
});
const subscriber = { handler, unsubscribers };
return statusSubscribers.add(subscriber), () => {
unsubscribers.forEach((unsub) => unsub()), statusSubscribers.delete(subscriber);
};
}, stop = () => {
channels.forEach((channel) => {
channel.disconnect(), channel.stop();
});
};
return {
on,
onInternalEvent,
onStatus,
post,
start: () => (channels.forEach((channel) => {
channel.start(), channel.connect();
}), stop),
stop
};
},
destroy: () => {
connections.forEach(({ channels }) => {
channels.forEach((channel) => {
cleanupChannel(channel), channels.delete(channel);
});
});
}
};
}, createNodeMachine = () => setup({
types: {},
actors: {
requestMachine: createRequestMachine(),
listen: createListenLogic()
},
actions: {
"buffer incoming message": assign({
handshakeBuffer: ({ event, context }) => (assertEvent(event, "message.received"), [...context.handshakeBuffer, event])
}),
"buffer message": enqueueActions(({ enqueue }) => {
enqueue.assign({
buffer: ({ event, context }) => (assertEvent(event, "post"), [
...context.buffer,
{
data: event.data,
resolvable: event.resolvable,
signal: event.signal
}
])
}), enqueue.emit(({ event }) => (assertEvent(event, "post"), {
type: "_buffer.added",
message: event.data
}));
}),
"create request": assign({
requests: ({ context, event, self, spawn }) => {
assertEvent(event, "request");
const requests = (Array.isArray(event.data) ? event.data : [event.data]).map((request) => {
const id = `req-${v4()}`;
return spawn("requestMachine", {
id,
input: {
connectionId: context.connectionId,
data: request.data,
domain: context.domain,
expectResponse: request.expectResponse,
from: context.name,
parentRef: self,
resolvable: request.resolvable,
responseTo: request.responseTo,
sources: context.target,
targetOrigin: context.targetOrigin,
to: context.connectTo,
type: request.type,
signal: request.signal
}
});
});
return [...context.requests, ...requests];
}
}),
"emit heartbeat": emit(() => ({
type: "_heartbeat"
})),
"emit received message": enqueueActions(({ enqueue }) => {
enqueue.emit(({ event }) => (assertEvent(event, "message.received"), {
type: "_message",
message: event.message.data
})), enqueue.emit(({ event }) => (assertEvent(event, "message.received"), {
type: event.message.data.type,
message: event.message.data
}));
}),
"flush buffer": enqueueActions(({ enqueue }) => {
enqueue.raise(({ context }) => ({
type: "request",
data: context.buffer.map(({ data, resolvable, signal }) => ({
data: data.data,
type: data.type,
expectResponse: !!resolvable,
resolvable,
signal
}))
})), enqueue.emit(({ context }) => ({
type: "_buffer.flushed",
messages: context.buffer.map(({ data }) => data)
})), enqueue.assign({
buffer: []
});
}),
"flush handshake buffer": enqueueActions(({ context, enqueue }) => {
context.handshakeBuffer.forEach((event) => enqueue.raise(event)), enqueue.assign({
handshakeBuffer: []
});
}),
post: raise(({ event }) => (assertEvent(event, "post"), {
type: "request",
data: {
data: event.data.data,
expectResponse: !!event.resolvable,
type: event.data.type,
resolvable: event.resolvable,
signal: event.signal
}
})),
"remove request": enqueueActions(({ context, enqueue, event }) => {
assertEvent(event, ["request.success", "request.failed", "request.aborted"]), stopChild(event.requestId), enqueue.assign({ requests: context.requests.filter(({ id }) => id !== event.requestId) });
}),
"send response": raise(({ event }) => (assertEvent(event, ["message.received", "heartbeat.received"]), {
type: "request",
data: {
type: MSG_RESPONSE,
responseTo: event.message.data.id,
data: void 0
}
})),
"send handshake syn ack": raise({
type: "request",
data: { type: MSG_HANDSHAKE_SYN_ACK }
}),
"set connection config": assign({
connectionId: ({ event }) => (assertEvent(event, "message.received"), event.message.data.connectionId),
target: ({ event }) => (assertEvent(event, "message.received"), event.message.source || void 0),
targetOrigin: ({ event }) => (assertEvent(event, "message.received"), event.message.origin)
})
},
guards: {
hasSource: ({ context }) => context.target !== null
}
}).createMachine({
/** @xstate-layout N4IgpgJg5mDOIC5QDsD2EwGIBOYCOArnAC4B0sBAxpXLANoAMAuoqAA6qwCWxXqyrEAA9EAVgYAWUgEYJDUQA4JAZmUSJC0coDsAGhABPRNIYLSErdOkBOAGzbx227YUBfV-rQYc+IrDIAZgCGXAA2kIwsSCAc3Lz8giIIoiakqgBMDKbp2tYS0srp+kYI0ununuhgpFwQ4ZgQ-NVcyABuqADW1V7NdWAILe2UQfHIkZGCsTx8AtFJ6aKipAzWOtrpC7Z5BUWGiNoK6aS26RLW2tLaqkqqFSA9NX2YALa0QTCkuDRcrRHMk5xpgk5ogJLZSNZIVDoVCFLZiohbIVSLkXLZRHZDgxbHcHrV6rFiBNolNRolEVJbCsdGUzsoyhiEcllOC1DowelVmVrOUPPcqqQABZBZAQWDCjotKANJo1NqdboC4Wi8VBSXIKADeXDUbjf4kwFkkEILbg8RZMHKOzWKzKJkHJa086Xa4qZS4pUisUSqU+QgkYnsQ0zcnJaRLDbpZwKNQSBYspm2MEyC5KTnaDSSd18h7K71q32EwMxYPA0BJFLKY5yZxIrKSURM0RnFHSBTrQqQ9babQejBCr2q9XSiBcWCUfjIMCUIn6oNxEPGtTWFFR0RUy7iGzt+3Ip0XURXVZKPvVCfIKczyB+vyzqLzoGzcuIG0MGTyCztjRtjaJjbHVMNAUTdu1PUhz0vYhryLOcSwXMthBfK0ZGsLQGBZekCi0Jso1IdI23WG04zOE4wIg6coIgBox3Imdi1JRdnxNOxSHNSQkWtW0mTjMxMQ7fDzgcbNKn7WjKJeN4Pi+MAfj+e84MfUMFHbZZwxOHZNDyO09gQOQjmAhZJCM9IMjIycKOvQUwCCbBiAAI2sshpNkiB6NLJ9EIQBQbWOdJlMhYCUjbJkchXGsFmsJQMVsWl3BzKp4GiHoAXgjykgAWmkZZ6xy3LZF2EobCy6xsQWJQ42kE4FjA-EwBSxTjSRUhDgqkzgO2BxdykU4AvXFQ-KjMC8yHKV6qNJi6WOdcypcZsXGxe0JG0XySKjM5lKsMyLwsiAxsYzylDfONznUEqrmi+1ThkHqXDONbULi1wgA */
id: "node",
context: ({ input }) => ({
buffer: [],
connectionId: null,
connectTo: input.connectTo,
domain: input.domain ?? DOMAIN,
handshakeBuffer: [],
name: input.name,
requests: [],
target: void 0,
targetOrigin: null
}),
on: {
"request.success": {
actions: "remove request"
},
"request.failed": {
actions: "remove request"
},
"request.aborted": {
actions: "remove request"
}
},
initial: "idle",
states: {
idle: {
invoke: {
id: "listen for handshake syn",
src: "listen",
input: listenInputFromContext({
include: MSG_HANDSHAKE_SYN,
count: 1
}),
onDone: {
target: "handshaking",
guard: "hasSource"
}
},
on: {
"message.received": {
actions: "set connection config"
},
post: {
actions: "buffer message"
}
}
},
handshaking: {
entry: "send handshake syn ack",
invoke: [
{
id: "listen for handshake ack",
src: "listen",
input: listenInputFromContext({
include: MSG_HANDSHAKE_ACK,
count: 1,
// Override the default `message.received` responseType to prevent
// buffering the ack message. We transition to the connected state
// using onDone instead of listening to this event using `on`
responseType: "handshake.complete"
}),
onDone: "connected"
},
{
id: "listen for disconnect",
src: "listen",
input: listenInputFromContext({
include: MSG_DISCONNECT,
count: 1,
responseType: "disconnect"
})
},
{
id: "listen for messages",
src: "listen",
input: listenInputFromContext({
exclude: [MSG_DISCONNECT, MSG_HANDSHAKE_ACK, MSG_HEARTBEAT, MSG_RESPONSE]
})
}
],
on: {
request: {
actions: "create request"
},
post: {
actions: "buffer message"
},
"message.received": {
actions: "buffer incoming message"
},
disconnect: {
target: "idle"
}
}
},
connected: {
entry: ["flush handshake buffer", "flush buffer"],
invoke: [
{
id: "listen for messages",
src: "listen",
input: listenInputFromContext({
exclude: [MSG_RESPONSE, MSG_HEARTBEAT]
})
},
{
id: "listen for heartbeat",
src: "listen",
input: listenInputFromContext({
include: MSG_HEARTBEAT,
responseType: "heartbeat.received"
})
},
{
id: "listen for disconnect",
src: "listen",
input: listenInputFromContext({
include: MSG_DISCONNECT,
count: 1,
responseType: "disconnect"
})
}
],
on: {
request: {
actions: "create request"
},
post: {
actions: "post"
},
disconnect: {
target: "idle"
},
"message.received": {
actions: ["send response", "emit received message"]
},
"heartbeat.received": {
actions: ["send response", "emit heartbeat"]
}
}
}
}
}), createNode = (input, machine = createNodeMachine()) => {
const actor = createActor(machine, {
input
}), on = (type, handler) => {
const { unsubscribe } = actor.on(
// @ts-expect-error @todo `type` typing
type,
(event) => {
handler(event.message.data);
}
);
return unsubscribe;
}, onStatus = (handler) => {
const snapshot = actor.getSnapshot();
let currentStatus = typeof snapshot.value == "string" ? snapshot.value : Object.keys(snapshot.value)[0];
const { unsubscribe } = actor.subscribe((state) => {
const status = typeof state.value == "string" ? state.value : Object.keys(state.value)[0];
currentStatus !== status && (currentStatus = status, handler(status));
});
return unsubscribe;
}, post = (data) => {
actor.send({ type: "post", data });
}, fetch = (data, options) => {
const resolvable = Promise.withResolvers();
return actor.send({
type: "post",
data,
resolvable,
signal: options?.signal
}), resolvable.promise;
}, stop = () => {
actor.stop();
};
return {
actor,
fetch,
machine,
on,
onStatus,
post,
start: () => (actor.start(), stop),
stop
};
};
export {
DOMAIN,
HANDSHAKE_INTERVAL,
HANDSHAKE_MSG_TYPES,
HEARTBEAT_INTERVAL,
INTERNAL_MSG_TYPES,
MSG_DISCONNECT,
MSG_HANDSHAKE_ACK,
MSG_HANDSHAKE_SYN,
MSG_HANDSHAKE_SYN_ACK,
MSG_HEARTBEAT,
MSG_RESPONSE,
RESPONSE_TIMEOUT,
createChannel,
createChannelMachine,
createController,
createListenLogic,
createNode,
createNodeMachine,
createRequestMachine
};
//# sourceMappingURL=index.js.map

2

package.json
{
"name": "@sanity/comlink",
"version": "1.0.0",
"version": "1.0.1-canary.0",
"keywords": [

@@ -5,0 +5,0 @@ "sanity.io",

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