actor-kit
Version:
Actor Kit is a library for running state machines in Cloudflare Workers, leveraging XState for robust state management. It provides a framework for managing the logic, lifecycle, persistence, synchronization, and access control of actors in a distributed
3 lines (2 loc) • 3.6 kB
JavaScript
"use client";import e,{createContext as t,memo as r,useRef as n,useEffect as o,useContext as c,useMemo as s,useCallback as i,useSyncExternalStore as a}from"react";import{matchesState as l}from"xstate";import{applyPatch as u}from"fast-json-patch";import{produce as d}from"immer";function m(e){let t=e.initialSnapshot,r=null;const n=new Set;let o=0;const c=async()=>{const s=function(e){const{host:t,actorId:r,actorType:n,accessToken:o,checksum:c}=e,s=`${/^(localhost|127\.0\.0\.1|192\.168\.|10\.|172\.(1[6-9]|2[0-9]|3[0-1])\.)/.test(t)?"ws":"wss"}://${t}/api/${n}/${r}`,i=new URLSearchParams({accessToken:o});c&&i.append("checksum",c);return`${s}?${i.toString()}`}(e);return r=new WebSocket(s),r.addEventListener("open",(()=>{o=0})),r.addEventListener("message",(r=>{try{const o=JSON.parse("string"==typeof r.data?r.data:(new TextDecoder).decode(r.data));t=d(t,(e=>{u(e,o.operations)})),e.onStateChange?.(t),n.forEach((e=>e(t)))}catch(t){console.error("[ActorKitClient] Error processing message:",t),e.onError?.(t)}})),r.addEventListener("error",(t=>{console.error("[ActorKitClient] WebSocket error:",t),console.error("[ActorKitClient] Error details:",{message:t.message,type:t.type,target:t.target,eventPhase:t.eventPhase}),e.onError?.(new Error(`WebSocket error: ${JSON.stringify(t)}`))})),r.addEventListener("close",(e=>{if(o<5){o++;const e=Math.min(1e3*Math.pow(2,o),3e4);setTimeout(c,e)}else console.error("[ActorKitClient] Max reconnection attempts reached")})),new Promise((e=>{r.addEventListener("open",(()=>e()))}))},s=e=>(n.add(e),()=>{n.delete(e)});return{connect:c,disconnect:()=>{r&&(r.close(),r=null)},send:t=>{r&&r.readyState===WebSocket.OPEN?r.send(JSON.stringify(t)):e.onError?.(new Error("Cannot send event: WebSocket is not connected"))},getState:()=>t,subscribe:s,waitFor:async(e,r=5e3)=>e(t)?Promise.resolve():new Promise(((t,n)=>{let o=null;r>0&&(o=setTimeout((()=>{c(),n(new Error(`Timeout waiting for condition after ${r}ms`))}),r));const c=s((r=>{e(r)&&(o&&clearTimeout(o),c(),t())}))}))}}function h(u){const d=t(null),h=r((t=>{const r=n(m({host:t.host,actorId:t.actorId,accessToken:t.accessToken,checksum:t.checksum,initialSnapshot:t.initialSnapshot,actorType:u})),c=n(!1);return o((()=>{c.current||(c.current=!0,r.current.connect().then((()=>{})))}),[c]),e.createElement(d.Provider,{value:r.current},t.children)}));function f(){const e=c(d);if(!e)throw new Error("useClient must be used within an ActorKitContext.Provider");return e}const v=e=>{const t=f();return function(e,t,r,n,o){const[c,l]=s((()=>{let e,c,s=!1;const i=t=>{if(!s)return s=!0,e=t,c=n(t),c;if(Object.is(e,t))return c;const r=n(t);return o&&o(c,r)?(e=t,c):(e=t,c=r,r)};return[()=>i(t()),r?()=>i(r()):void 0]}),[t,r,n,o]),u=i((t=>{let r=c();return e((()=>{const e=c();o&&o(r,e)||(r=e,t())}))}),[e,c,o]);return a(u,c,l)}(t.subscribe,t.getState,t.getState,e,p)};function S(e){return v((t=>l(e,t.value)))}const E=t=>{const r=S(t.state),n=!t.and||S(t.and),o=!!t.or&&S(t.or),c="boolean"==typeof t.initialValueOverride?t.initialValueOverride:r&&n||o;return(t.not?!c:c)?e.createElement(e.Fragment,null,t.children):null};return E.create=(t,r={})=>{const n=({children:n,initialValueOverride:o})=>e.createElement(E,{state:t,and:r.and,or:r.or,not:r.not,initialValueOverride:o},n);return n.displayName=`MatchesComponent(${t.toString()})`,n},{Provider:h,ProviderFromClient:({children:t,client:r})=>e.createElement(d.Provider,{value:r},t),useClient:f,useSelector:v,useSend:function(){return f().send},useMatches:S,Matches:E}}function p(e,t){return e===t}export{h as createActorKitContext};
//# sourceMappingURL=react.js.map