@mantaq/core 0.5.3 → 0.5.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -133,6 +133,10 @@ interface AnyActor<C = Record<string, unknown>> {
133
133
  type RuntimeTransitionHandler<States extends readonly AnyStateRef[], ActorContext> = (event: InternalEvent, options: {
134
134
  context: Context<ActorContext>;
135
135
  actor: AnyActor<ActorContext>;
136
+ state: {
137
+ name: string;
138
+ payload: unknown;
139
+ };
136
140
  }) => TransitionResult<States[number], string>;
137
141
  type EventTypeOf<E extends AnyEventRef> = E extends EventRef<infer Type, object | void> ? Type : never;
138
142
  type PayloadOf<S extends AnyStateRef> = S extends StateRef<infer _Name, infer Payload, infer _IsFinal> ? Payload : never;
@@ -150,19 +154,24 @@ interface BuiltMaps<States extends readonly AnyStateRef[], ActorContext> {
150
154
  targets: Record<string, Record<string, string[]>>;
151
155
  effects: Record<string, Array<EffectEntry<ActorContext>>>;
152
156
  }
157
+ type StateInput<S> = S extends AnyStateRef ? {
158
+ name: S["name"];
159
+ payload: PayloadOf<S>;
160
+ } : never;
153
161
  /** Handler may only return states listed in `to`; no `to` means it can only stay. */
154
- type HandlerFn<To extends AnyStateRef, Outputs extends readonly AnyEventRef[], ActorContext, E extends AnyEventRef> = (event: E extends EventRef<infer Type, infer P> ? CreatedOfEvent<Type, P> : never, opts: {
162
+ type HandlerFn<Current extends AnyStateRef, To extends AnyStateRef, Outputs extends readonly AnyEventRef[], ActorContext, E extends AnyEventRef> = (event: E extends EventRef<infer Type, infer P> ? CreatedOfEvent<Type, P> : never, opts: {
155
163
  context: Context<ActorContext>;
156
164
  actor: AnyActor<ActorContext>;
165
+ state: StateInput<Current>;
157
166
  }) => TransitionResult<To, EventTypeOf<Outputs[number]>>;
158
- interface HandlerOptions<To extends readonly AnyStateRef[], Outputs extends readonly AnyEventRef[], ActorContext, E extends AnyEventRef> {
167
+ interface HandlerOptions<Current extends AnyStateRef, To extends readonly AnyStateRef[], Outputs extends readonly AnyEventRef[], ActorContext, E extends AnyEventRef> {
159
168
  event: E;
160
169
  to?: To;
161
- handler: HandlerFn<NoInfer<To[number]>, Outputs, ActorContext, E>;
170
+ handler: HandlerFn<Current, NoInfer<To[number]>, Outputs, ActorContext, E>;
162
171
  }
163
172
  interface ActorBuilder<States extends readonly AnyStateRef[], Inputs extends readonly AnyEventRef[], Internal extends readonly AnyEventRef[], Outputs extends readonly AnyEventRef[], ActorContext> {
164
- on<S extends States[number], E extends Inputs[number] | Internal[number], const To extends readonly States[number][] = readonly []>(stateRef: S, options: HandlerOptions<To, Outputs, ActorContext, E>): ActorBuilder<States, Inputs, Internal, Outputs, ActorContext>;
165
- onAny<E extends Inputs[number] | Internal[number], const To extends readonly States[number][] = readonly []>(options: HandlerOptions<To, Outputs, ActorContext, E>): ActorBuilder<States, Inputs, Internal, Outputs, ActorContext>;
173
+ on<S extends States[number], E extends Inputs[number] | Internal[number], const To extends readonly States[number][] = readonly []>(stateRef: S, options: HandlerOptions<S, To, Outputs, ActorContext, E>): ActorBuilder<States, Inputs, Internal, Outputs, ActorContext>;
174
+ onAny<E extends Inputs[number] | Internal[number], const To extends readonly States[number][] = readonly []>(options: HandlerOptions<States[number], To, Outputs, ActorContext, E>): ActorBuilder<States, Inputs, Internal, Outputs, ActorContext>;
166
175
  /** `sends`: internal events `fn` may emit; `emit` only accepts those. Omit for untyped `emit`. */
167
176
  effect<S extends States[number], const E extends SendList<Internal> = undefined>(stateRef: S, definition: {
168
177
  name: string;
@@ -242,6 +251,10 @@ type TransitionDispatch<States extends readonly AnyStateRef[], ActorContext> = R
242
251
  type TransitionStepFn<States extends readonly AnyStateRef[], ActorContext> = (event: InternalEvent, options: {
243
252
  context: Context<ActorContext>;
244
253
  actor: AnyActor<ActorContext>;
254
+ state: {
255
+ name: string;
256
+ payload: unknown;
257
+ };
245
258
  }) => TransitionResult<States[number], string>;
246
259
  export interface Actor<States extends readonly AnyStateRef[], Inputs extends readonly AnyEventRef[], Internal extends readonly AnyEventRef[] = readonly [], Outputs extends readonly AnyEventRef[] = readonly [], ActorContext = Record<string, unknown>> extends AnyActor<ActorContext> {
247
260
  state: States[number] | ErrorState;
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import{Either as e}from"@mantaq/utils";function t(e){let t=e;return typeof t==`function`?t:()=>({})}function n(e){return e}function r(){let e={},r={},i={};function a(n,i){let a=i.event.type;(e[n]??={})[a]=t(i.handler),(r[n]??={})[a]=(i.to??[]).map(e=>e.name)}let o={on(e,t){return a(e.name,t),o},onAny(e){return a(`Any`,e),o},effect(e,{name:t,sends:r,fn:a}){return(i[e.name]??=[]).push({name:t,...r&&{sends:r.map(e=>e.type)},fn:n(a)}),o},build(){return{transitions:e,targets:r,effects:i}}};return o}function i(e){return{get:e.get,set:e.set}}function a(e){return()=>c(e,{isFinal:!1})}const o=/* @__PURE__ */ new WeakSet;function s(e){return typeof e==`object`&&!!e&&o.has(e)}function c(e,t){let n={name:e,isFinal:t.isFinal,regions(e){return n._regions=e,n},final(){let e=c(n.name,{isFinal:!0});return e._regions=n._regions,e},create(e){return{state:n,payload:e}}};return o.add(n),n}function l(e){let t=e.state;if(t)return`state`in t?{state:t.state,payload:t.payload}:{state:t,payload:e.payload}}function u(e){if(e instanceof Promise)return!0;let t=e;return typeof t==`object`&&!!t&&typeof t.then==`function`}function d(t){let n=[],r=[],i=t.effects[t.state.name];if(!i)return{pending:n,ran:r};for(let{name:a,fn:o}of i){if(t.abort.signal.aborted)break;let i,s=e.from(()=>(i=o({signal:t.abort.signal,state:{name:t.state.name,payload:t.statePayload},event:t.event,context:t.context,emit:t.emit,clock:t.clock}),!0));if(s[0]!==void 0){t.onError(s[0],t.lastGood);break}if(r.push(a),u(i)){let e=Promise.resolve(i).then(()=>void 0,e=>{t.abort.signal.aborted||t.onError(e,t.lastGood)});n.push(e)}}return{pending:n,ran:r}}function ee(e){return e??{}}function f(){let e=[],t=0,n=!1,r=!1,i=[];function a(){let e=i.splice(0);for(let t of e)t()}function o(i){if(!n){n=!0;try{for(;t<e.length&&!r;){let n=e[t];if(t++,!i(n)){r=!0;break}}}finally{e.length=0,t=0,n=!1,r=!1,a()}}}return{get length(){return e.length-t},push(...t){r||e.push(...t)},clear(){e.length=0,t=0,a()},settled(){return e.length-t===0&&!n?Promise.resolve():new Promise(e=>{i.push(e)})},processCancellable(e){o(e)}}}function p(){let e=Date.now(),t=/* @__PURE__ */ new Map;function n(e){let n=t.get(e);n&&(n.signal.removeEventListener(`abort`,n.onAbort),t.delete(e))}return{now(){return Date.now()-e},setTimeout(e,{signal:r,cb:i}){if(r?.aborted)return-1;let a=Number(globalThis.setTimeout(()=>{n(a),i()},e));if(r){function e(){globalThis.clearTimeout(a),n(a)}t.set(a,{signal:r,onAbort:e}),r.addEventListener(`abort`,e,{once:!0})}return a},clearTimeout(e){globalThis.clearTimeout(e),n(e)},setInterval(e,{signal:r,cb:i}){if(r?.aborted)return-1;let a=Number(globalThis.setInterval(i,e));if(r){function e(){globalThis.clearInterval(a),n(a)}t.set(a,{signal:r,onAbort:e}),r.addEventListener(`abort`,e,{once:!0})}return a},clearInterval(e){globalThis.clearInterval(e),n(e)}}}function m(e){let{stateRef:t,regions:n,context:r}=e,i=[t.name],a={};for(let[e,t]of Object.entries(n))a[e]=t.snapshot();let o={path:i,context:r,regions:a};return e.payload!==void 0&&(o.payload=e.payload),t.isFinal&&(o.done=!0),e.error!==void 0&&(o.error={...e.error,context:h(e.error.context)}),o}function h(e){return typeof structuredClone==`function`?structuredClone(e):JSON.parse(JSON.stringify(e))}function g(){let t=/* @__PURE__ */ new Set,n=/* @__PURE__ */ new Set,r=/* @__PURE__ */ new Set,i=/* @__PURE__ */ new Set,a=/* @__PURE__ */ new Set,o;function s(t){e.from(()=>(t(),!0))}return{change:t,done:n,transition:r,error:i,output:a,seed(e){o=e},addChange(e){t.add(e);let n=o;return n&&s(()=>e(n,n)),()=>t.delete(e)},addDone(e){return n.add(e),()=>n.delete(e)},addTransition(e){return r.add(e),()=>r.delete(e)},addError(e){i.add(e);let t=o?.error;return t&&s(()=>e(t)),()=>i.delete(e)},addOutput(e){return a.add(e),()=>a.delete(e)},emitChange(e){let n=o??e;o=e;for(let r of t)s(()=>r(e,n))},emitDone(){for(let e of n)s(e)},emitTransition(e){for(let t of r)s(()=>t(e))},emitError(e){for(let t of i)s(()=>t(e))},emitOutput(e){for(let t of a)t(e)},clear(){t.clear(),n.clear(),r.clear(),i.clear(),a.clear()}}}function _(){if(typeof globalThis.AbortController==`function`)return new globalThis.AbortController;let e=[],t={aborted:!1,reason:void 0,onabort:void 0,addEventListener(t,n,r){t===`abort`&&!e.some(e=>e.fn===n)&&e.push({fn:n,once:r?.once===!0,removed:!1})},removeEventListener(t,n){if(t===`abort`){for(let t of e)t.fn===n&&(t.removed=!0);e=e.filter(e=>e.fn!==n)}},throwIfAborted(){if(t.aborted)throw t.reason}};function n(n){if(t.aborted)return;t.aborted=!0,t.reason=n===void 0?/* @__PURE__ */ Error(`This operation was aborted`):n;let r={type:`abort`,target:t},i=e;e=i.filter(e=>!e.once);let a=[];try{t.onabort?.(r)}catch(e){a.push(e)}for(let e of i)if(!e.removed)try{e.fn(r)}catch(e){a.push(e)}if(a.length>0)throw a[0]}return v({signal:t,abort:n})}function v(e){return e}function y(e,t){let n=e?()=>{t.entries.delete(t.timerId)}:void 0;return e&&n&&e.addEventListener(`abort`,n,{once:!0}),n}function b(e){e.signal&&e.onAbort&&e.signal.removeEventListener(`abort`,e.onAbort)}function x(){let e=0,t=/* @__PURE__ */ new Map,n=/* @__PURE__ */ new Map,r=1,i=/* @__PURE__ */ new Set;function a(e,t){if(!Number.isFinite(e))throw RangeError(`[VirtualClock] invalid ${t.method} ms value: ${e}`);return!0}function o(e,t){return a(e,{method:t.method}),e<=0?+!!t.interval:e}function s(e){let r=e,i=!1;for(let n of t.values())n.deadline<=e&&n.deadline<=r&&(r=n.deadline,i=!0);for(let t of n.values())t.next<=e&&t.next<=r&&(r=t.next,i=!0);return i?r:void 0}function c(e){let n=[];for(let[r,i]of t)i.deadline===e&&n.push(r);for(let e of n){let n=t.get(e);n&&(b(n),t.delete(e),n.cb())}}function l(t){let r=[];for(let[e,i]of n)i.next===t&&r.push(e);for(let t of r){let r=n.get(t);r&&(r.cb(),n.has(t)&&(r.next=e+r.ms))}}return{now(){return e},setTimeout(n,{signal:i,cb:a,eventName:s}){if(i?.aborted)return-1;let c=r++,l=y(i,{timerId:c,entries:t});return t.set(c,{deadline:e+o(n,{method:`setTimeout`,interval:!1}),cb:a,signal:i,onAbort:l,eventName:s}),c},clearTimeout(e){let n=t.get(e);n&&(b(n),t.delete(e))},setInterval(t,{signal:i,cb:a}){if(i?.aborted)return-1;let s=r++,c=y(i,{timerId:s,entries:n}),l=o(t,{method:`setInterval`,interval:!0});return n.set(s,{ms:l,next:e+l,cb:a,signal:i,onAbort:c}),s},clearInterval(e){let t=n.get(e);t&&(b(t),n.delete(e))},advance(t){a(t,{method:`advance`});let n=e+Math.max(0,t),r=-1,o=0;for(;;){let t=s(n);if(t===void 0)break;if(t===r){if(++o>=1e6)break}else o=0,r=t;e=t,c(t),l(t)}e=n;for(let e of i)e()},hasPending(){return t.size>0||n.size>0},pendingTimers(){let n=[];for(let[r,i]of t)n.push({id:r,deadline:i.deadline,ms:i.deadline-e,eventName:i.eventName});return n},setDrain(e){i.add(e)}}}function te(e){return`state`in e?e.state:e}function ne(e,t){if(!e.has(t.candidate.name))throw Error(`[Actor] initial state "${t.candidate.name}" not found in declared states [${[...e].join(`, `)}]`);return!0}function S(t){let n=r();t.setup(n);let a=n.build(),o={...t,transitions:a.transitions,targets:a.targets,effects:a.effects},u=new Set((t.internal??[]).map(e=>e.type)),v=new Set(t.inputs.map(e=>e.type)),y=t.internalBudget??1e4,b=t.clock??p();b.setDrain?.(Y);let x,S,C=ee(t.context),w,T=!0,E,D={},O=f(),k=g(),A,j=!1,M=[],N,P,F=!1,I=!1,L=c(`__error`,{isFinal:!0}),R=i({get:()=>C,set:e=>{C=e,I=!0,T=!0}}),z=te(t.initial);ne(new Set(t.states.map(e=>e.name)),{candidate:z}),x=z;let B=t.initial;if(S=!s(B)&&`payload`in B?B.payload:void 0,E=z,t.regions)for(let[e,n]of Object.entries(t.regions))D[e]=n,n.on(`output`,{fn:e=>{O.push(e),Y()}});let V={get state(){return x},clock:b,get regions(){return D},get context(){return C},get options(){return o},on(e,t){return{change:e=>k.addChange(e),done:e=>k.addDone(e),transition:e=>k.addTransition(e),error:e=>k.addError(e),output:e=>k.addOutput(e)}[e](t.fn)},settled(){return Q()},pendingEffectCount(){return M.length},send(e){F||(W(e),H())},recover:U,snapshot(){return K()},inject(e){oe(e)},dispose(){se()}};J({type:`__init`},{payloadForState:S}),k.seed(K());function H(){(x!==E||I)&&(E=x,I=!1,k.emitChange(K()))}function U(e){N===void 0||F||(A?.abort(),A=void 0,O.clear(),O=f(),N=void 0,x=e.state,S=void 0,C=e.context,E=e.state,I=!1,T=!0,w=void 0,P=void 0,M=[],k.emitChange(K()))}function W(e){if(N!==void 0||x.isFinal)return;let t={...e,payload:e.payload??{}},n=x.name,r=P;P={state:x,context:C};try{let r=o.transitions,i=r[x.name]?.[e.type],a=r.Any?.[e.type],s=G(t,{stateTransition:i,anyTransition:a});re(t,{from:n,handled:!!(i||a),outcome:s}),s.emitted||O.length>0?Y():!i&&!a&&u.has(e.type)&&Z(`unhandled`,{event:e,error:/* @__PURE__ */ Error(`[Actor] internal event "${e.type}" emitted but no handler in state "${x.name}"`)})}finally{P=r}}function G(e,t){let n=t.stateTransition?ie(e,{transition:t.stateTransition}):{applied:!1,target:void 0,effects:void 0};if(N===void 0){let r=ae(e,{transition:t.anyTransition,allowTransition:!n.applied});return{emitted:r.emitted,transitioned:n.applied||r.transitioned,target:n.target??r.target,effects:n.effects??r.effects}}return{emitted:!1,transitioned:!1}}function re(e,t){N===void 0&&t.handled&&k.emitTransition({event:e,from:t.from,to:t.outcome.target??x.name,transitioned:t.outcome.transitioned,effects:t.outcome.effects??[]})}function ie(e,t){let n=!1,r,i;return X(`transition`,{event:e,operation:()=>{let a=t.transition(e,{context:R,actor:$()});if(a.emit&&O.push(...a.emit),a.state){let t=q(e,{step:a});r=t.target,i=t.effects,n=!0}}}),{applied:n,target:r,effects:i}}function ae(e,t){if(t.transition===void 0)return{emitted:!1,transitioned:!1};let n=t.transition,r=!1,i=!1,a,o;return X(`transition`,{event:e,operation:()=>{let s=n(e,{context:R,actor:$()});if(s.state&&t.allowTransition){let t=q(e,{step:s});a=t.target,o=t.effects,i=!0}s.emit&&(O.push(...s.emit),r=!0)}}),{emitted:r,transitioned:i,target:a,effects:o}}function K(){return(w===void 0||T)&&(w=h(C),T=!1),m({stateRef:x,regions:D,context:w,error:N,payload:S})}function q(e,t){if(N!==void 0||!t.step.state)return{};let n=l(t.step);if(!n)return{};if(!s(n.state))return Z(`transition`,{event:e,error:/* @__PURE__ */ Error(`invalid transition target`)}),{};A?.abort(),x=n.state;let r=x.name;S=n.payload,P={state:x,context:C};let i=J(e,{payloadForState:n.payload});return n.state.isFinal&&N===void 0&&k.emitDone(),{target:r,effects:i}}function J(e,t){if(F)return[];let n=o.effects[x.name];if(!n)return A=void 0,[];let r=_();A=r;let i=P??{state:x,context:C},a=d({effects:{[x.name]:n},state:x,statePayload:t.payloadForState,event:e,context:R,emit:e=>{N!==void 0||r.signal.aborted||(O.push(e),Y())},clock:b,abort:r,lastGood:i,onError:t=>Z(`effect`,{event:e,error:t})});for(let e of a.pending)M.push(e),e.finally(()=>{let t=M.indexOf(e);t!==-1&&M.splice(t,1)}).catch(()=>{});return a.ran}function Y(){if(!(j||F)){j=!0;try{let e=0;O.processCancellable(t=>{if(N!==void 0)return!1;if(e>=y)return Z(`budget`,{event:t,error:/* @__PURE__ */ Error(`internal event budget exceeded`)}),!1;if(e++,u.has(t.type)||v.has(t.type))W(t);else if(!X(`output`,{event:t,operation:()=>k.emitOutput(t)}))return!1;return!0})}finally{j=!1,H()}}}function X(t,n){let r=e.from(()=>(n.operation(),!0));return r[0]===void 0||(Z(t,{event:n.event,error:r[0]}),!1)}function Z(e,t){if(N!==void 0)return;let n=t.lastGood??P??{state:x,context:C};N={error:t.error,state:n.state,context:n.context,event:t.event,reason:e},A?.abort(),x=L,S=void 0,E=L,I=!1,k.emitError(N),k.emitChange(K()),k.emitDone()}function oe(e){F||(O.push(e),Y())}function se(){if(!F){F=!0,A?.abort(),A=void 0;for(let e of Object.values(D))e.dispose();D={},O.clear(),k.clear(),M=[]}}function Q(){return O.settled().then(()=>{if(M.length!==0)return Promise.all(M).then(()=>Q())})}function $(){return V}return V}function C(e){return Symbol.for(`mantaq:event:${e}`)}function w(e){return()=>T(e)}function T(e){let t=C(e),n=function(e){return typeof e==`object`&&!!e&&Object.hasOwn(e,t)};function r(n){return Object.defineProperty(n===void 0?{type:e}:{type:e,payload:n},t,{value:!0})}return{type:e,is:n,create:r}}export{S as Actor,i as Context,T as EventRef,p as RealClock,c as StateRef,x as VirtualClock,w as event,s as isStateRef,a as state};
1
+ import{Either as e}from"@mantaq/utils";function t(e){let t=e;return typeof t==`function`?t:()=>({})}function n(e){return e}function r(){let e={},r={},i={};function a(n,i){let a=i.event.type;(e[n]??={})[a]=t(i.handler),(r[n]??={})[a]=(i.to??[]).map(e=>e.name)}let o={on(e,t){return a(e.name,t),o},onAny(e){return a(`Any`,e),o},effect(e,{name:t,sends:r,fn:a}){return(i[e.name]??=[]).push({name:t,...r&&{sends:r.map(e=>e.type)},fn:n(a)}),o},build(){return{transitions:e,targets:r,effects:i}}};return o}function i(e){return{get:e.get,set:e.set}}function a(e){return()=>c(e,{isFinal:!1})}const o=/* @__PURE__ */ new WeakSet;function s(e){return typeof e==`object`&&!!e&&o.has(e)}function c(e,t){let n={name:e,isFinal:t.isFinal,regions(e){return n._regions=e,n},final(){let e=c(n.name,{isFinal:!0});return e._regions=n._regions,e},create(e){return{state:n,payload:e}}};return o.add(n),n}function l(e){let t=e.state;if(t)return`state`in t?{state:t.state,payload:t.payload}:{state:t,payload:e.payload}}function u(e){if(e instanceof Promise)return!0;let t=e;return typeof t==`object`&&!!t&&typeof t.then==`function`}function d(t){let n=[],r=[],i=t.effects[t.state.name];if(!i)return{pending:n,ran:r};for(let{name:a,fn:o}of i){if(t.abort.signal.aborted)break;let i,s=e.from(()=>(i=o({signal:t.abort.signal,state:{name:t.state.name,payload:t.statePayload},event:t.event,context:t.context,emit:t.emit,clock:t.clock}),!0));if(s[0]!==void 0){t.onError(s[0],t.lastGood);break}if(r.push(a),u(i)){let e=Promise.resolve(i).then(()=>void 0,e=>{t.abort.signal.aborted||t.onError(e,t.lastGood)});n.push(e)}}return{pending:n,ran:r}}function ee(e){return e??{}}function f(){let e=[],t=0,n=!1,r=!1,i=[];function a(){let e=i.splice(0);for(let t of e)t()}function o(i){if(!n){n=!0;try{for(;t<e.length&&!r;){let n=e[t];if(t++,!i(n)){r=!0;break}}}finally{e.length=0,t=0,n=!1,r=!1,a()}}}return{get length(){return e.length-t},push(...t){r||e.push(...t)},clear(){e.length=0,t=0,a()},settled(){return e.length-t===0&&!n?Promise.resolve():new Promise(e=>{i.push(e)})},processCancellable(e){o(e)}}}function p(){let e=Date.now(),t=/* @__PURE__ */ new Map;function n(e){let n=t.get(e);n&&(n.signal.removeEventListener(`abort`,n.onAbort),t.delete(e))}return{now(){return Date.now()-e},setTimeout(e,{signal:r,cb:i}){if(r?.aborted)return-1;let a=Number(globalThis.setTimeout(()=>{n(a),i()},e));if(r){function e(){globalThis.clearTimeout(a),n(a)}t.set(a,{signal:r,onAbort:e}),r.addEventListener(`abort`,e,{once:!0})}return a},clearTimeout(e){globalThis.clearTimeout(e),n(e)},setInterval(e,{signal:r,cb:i}){if(r?.aborted)return-1;let a=Number(globalThis.setInterval(i,e));if(r){function e(){globalThis.clearInterval(a),n(a)}t.set(a,{signal:r,onAbort:e}),r.addEventListener(`abort`,e,{once:!0})}return a},clearInterval(e){globalThis.clearInterval(e),n(e)}}}function m(e){let{stateRef:t,regions:n,context:r}=e,i=[t.name],a={};for(let[e,t]of Object.entries(n))a[e]=t.snapshot();let o={path:i,context:r,regions:a};return e.payload!==void 0&&(o.payload=e.payload),t.isFinal&&(o.done=!0),e.error!==void 0&&(o.error={...e.error,context:h(e.error.context)}),o}function h(e){return typeof structuredClone==`function`?structuredClone(e):JSON.parse(JSON.stringify(e))}function g(){let t=/* @__PURE__ */ new Set,n=/* @__PURE__ */ new Set,r=/* @__PURE__ */ new Set,i=/* @__PURE__ */ new Set,a=/* @__PURE__ */ new Set,o;function s(t){e.from(()=>(t(),!0))}return{change:t,done:n,transition:r,error:i,output:a,seed(e){o=e},addChange(e){t.add(e);let n=o;return n&&s(()=>e(n,n)),()=>t.delete(e)},addDone(e){return n.add(e),()=>n.delete(e)},addTransition(e){return r.add(e),()=>r.delete(e)},addError(e){i.add(e);let t=o?.error;return t&&s(()=>e(t)),()=>i.delete(e)},addOutput(e){return a.add(e),()=>a.delete(e)},emitChange(e){let n=o??e;o=e;for(let r of t)s(()=>r(e,n))},emitDone(){for(let e of n)s(e)},emitTransition(e){for(let t of r)s(()=>t(e))},emitError(e){for(let t of i)s(()=>t(e))},emitOutput(e){for(let t of a)t(e)},clear(){t.clear(),n.clear(),r.clear(),i.clear(),a.clear()}}}function _(){if(typeof globalThis.AbortController==`function`)return new globalThis.AbortController;let e=[],t={aborted:!1,reason:void 0,onabort:void 0,addEventListener(t,n,r){t===`abort`&&!e.some(e=>e.fn===n)&&e.push({fn:n,once:r?.once===!0,removed:!1})},removeEventListener(t,n){if(t===`abort`){for(let t of e)t.fn===n&&(t.removed=!0);e=e.filter(e=>e.fn!==n)}},throwIfAborted(){if(t.aborted)throw t.reason}};function n(n){if(t.aborted)return;t.aborted=!0,t.reason=n===void 0?/* @__PURE__ */ Error(`This operation was aborted`):n;let r={type:`abort`,target:t},i=e;e=i.filter(e=>!e.once);let a=[];try{t.onabort?.(r)}catch(e){a.push(e)}for(let e of i)if(!e.removed)try{e.fn(r)}catch(e){a.push(e)}if(a.length>0)throw a[0]}return v({signal:t,abort:n})}function v(e){return e}function y(e,t){let n=e?()=>{t.entries.delete(t.timerId)}:void 0;return e&&n&&e.addEventListener(`abort`,n,{once:!0}),n}function b(e){e.signal&&e.onAbort&&e.signal.removeEventListener(`abort`,e.onAbort)}function x(){let e=0,t=/* @__PURE__ */ new Map,n=/* @__PURE__ */ new Map,r=1,i=/* @__PURE__ */ new Set;function a(e,t){if(!Number.isFinite(e))throw RangeError(`[VirtualClock] invalid ${t.method} ms value: ${e}`);return!0}function o(e,t){return a(e,{method:t.method}),e<=0?+!!t.interval:e}function s(e){let r=e,i=!1;for(let n of t.values())n.deadline<=e&&n.deadline<=r&&(r=n.deadline,i=!0);for(let t of n.values())t.next<=e&&t.next<=r&&(r=t.next,i=!0);return i?r:void 0}function c(e){let n=[];for(let[r,i]of t)i.deadline===e&&n.push(r);for(let e of n){let n=t.get(e);n&&(b(n),t.delete(e),n.cb())}}function l(t){let r=[];for(let[e,i]of n)i.next===t&&r.push(e);for(let t of r){let r=n.get(t);r&&(r.cb(),n.has(t)&&(r.next=e+r.ms))}}return{now(){return e},setTimeout(n,{signal:i,cb:a,eventName:s}){if(i?.aborted)return-1;let c=r++,l=y(i,{timerId:c,entries:t});return t.set(c,{deadline:e+o(n,{method:`setTimeout`,interval:!1}),cb:a,signal:i,onAbort:l,eventName:s}),c},clearTimeout(e){let n=t.get(e);n&&(b(n),t.delete(e))},setInterval(t,{signal:i,cb:a}){if(i?.aborted)return-1;let s=r++,c=y(i,{timerId:s,entries:n}),l=o(t,{method:`setInterval`,interval:!0});return n.set(s,{ms:l,next:e+l,cb:a,signal:i,onAbort:c}),s},clearInterval(e){let t=n.get(e);t&&(b(t),n.delete(e))},advance(t){a(t,{method:`advance`});let n=e+Math.max(0,t),r=-1,o=0;for(;;){let t=s(n);if(t===void 0)break;if(t===r){if(++o>=1e6)break}else o=0,r=t;e=t,c(t),l(t)}e=n;for(let e of i)e()},hasPending(){return t.size>0||n.size>0},pendingTimers(){let n=[];for(let[r,i]of t)n.push({id:r,deadline:i.deadline,ms:i.deadline-e,eventName:i.eventName});return n},setDrain(e){i.add(e)}}}function te(e){return`state`in e?e.state:e}function ne(e,t){if(!e.has(t.candidate.name))throw Error(`[Actor] initial state "${t.candidate.name}" not found in declared states [${[...e].join(`, `)}]`);return!0}function S(t){let n=r();t.setup(n);let a=n.build(),o={...t,transitions:a.transitions,targets:a.targets,effects:a.effects},u=new Set((t.internal??[]).map(e=>e.type)),v=new Set(t.inputs.map(e=>e.type)),y=t.internalBudget??1e4,b=t.clock??p();b.setDrain?.(Y);let x,S,C=ee(t.context),w,T=!0,E,D={},O=f(),k=g(),A,j=!1,M=[],N,P,F=!1,I=!1,L=c(`__error`,{isFinal:!0}),R=i({get:()=>C,set:e=>{C=e,I=!0,T=!0}}),z=te(t.initial);ne(new Set(t.states.map(e=>e.name)),{candidate:z}),x=z;let B=t.initial;if(S=!s(B)&&`payload`in B?B.payload:void 0,E=z,t.regions)for(let[e,n]of Object.entries(t.regions))D[e]=n,n.on(`output`,{fn:e=>{O.push(e),Y()}});let V={get state(){return x},clock:b,get regions(){return D},get context(){return C},get options(){return o},on(e,t){return{change:e=>k.addChange(e),done:e=>k.addDone(e),transition:e=>k.addTransition(e),error:e=>k.addError(e),output:e=>k.addOutput(e)}[e](t.fn)},settled(){return Q()},pendingEffectCount(){return M.length},send(e){F||(W(e),H())},recover:U,snapshot(){return K()},inject(e){oe(e)},dispose(){se()}};J({type:`__init`},{payloadForState:S}),k.seed(K());function H(){(x!==E||I)&&(E=x,I=!1,k.emitChange(K()))}function U(e){N===void 0||F||(A?.abort(),A=void 0,O.clear(),O=f(),N=void 0,x=e.state,S=void 0,C=e.context,E=e.state,I=!1,T=!0,w=void 0,P=void 0,M=[],k.emitChange(K()))}function W(e){if(N!==void 0||x.isFinal)return;let t={...e,payload:e.payload??{}},n=x.name,r=P;P={state:x,context:C};try{let r=o.transitions,i=r[x.name]?.[e.type],a=r.Any?.[e.type],s=G(t,{stateTransition:i,anyTransition:a});re(t,{from:n,handled:!!(i||a),outcome:s}),s.emitted||O.length>0?Y():!i&&!a&&u.has(e.type)&&Z(`unhandled`,{event:e,error:/* @__PURE__ */ Error(`[Actor] internal event "${e.type}" emitted but no handler in state "${x.name}"`)})}finally{P=r}}function G(e,t){let n=t.stateTransition?ie(e,{transition:t.stateTransition}):{applied:!1,target:void 0,effects:void 0};if(N===void 0){let r=ae(e,{transition:t.anyTransition,allowTransition:!n.applied});return{emitted:r.emitted,transitioned:n.applied||r.transitioned,target:n.target??r.target,effects:n.effects??r.effects}}return{emitted:!1,transitioned:!1}}function re(e,t){N===void 0&&t.handled&&k.emitTransition({event:e,from:t.from,to:t.outcome.target??x.name,transitioned:t.outcome.transitioned,effects:t.outcome.effects??[]})}function ie(e,t){let n=!1,r,i;return X(`transition`,{event:e,operation:()=>{let a=t.transition(e,{context:R,actor:$(),state:{name:x.name,payload:S}});if(a.emit&&O.push(...a.emit),a.state){let t=q(e,{step:a});r=t.target,i=t.effects,n=!0}}}),{applied:n,target:r,effects:i}}function ae(e,t){if(t.transition===void 0)return{emitted:!1,transitioned:!1};let n=t.transition,r=!1,i=!1,a,o;return X(`transition`,{event:e,operation:()=>{let s=n(e,{context:R,actor:$(),state:{name:x.name,payload:S}});if(s.state&&t.allowTransition){let t=q(e,{step:s});a=t.target,o=t.effects,i=!0}s.emit&&(O.push(...s.emit),r=!0)}}),{emitted:r,transitioned:i,target:a,effects:o}}function K(){return(w===void 0||T)&&(w=h(C),T=!1),m({stateRef:x,regions:D,context:w,error:N,payload:S})}function q(e,t){if(N!==void 0||!t.step.state)return{};let n=l(t.step);if(!n)return{};if(!s(n.state))return Z(`transition`,{event:e,error:/* @__PURE__ */ Error(`invalid transition target`)}),{};A?.abort(),x=n.state;let r=x.name;S=n.payload,P={state:x,context:C};let i=J(e,{payloadForState:n.payload});return n.state.isFinal&&N===void 0&&k.emitDone(),{target:r,effects:i}}function J(e,t){if(F)return[];let n=o.effects[x.name];if(!n)return A=void 0,[];let r=_();A=r;let i=P??{state:x,context:C},a=d({effects:{[x.name]:n},state:x,statePayload:t.payloadForState,event:e,context:R,emit:e=>{N!==void 0||r.signal.aborted||(O.push(e),Y())},clock:b,abort:r,lastGood:i,onError:t=>Z(`effect`,{event:e,error:t})});for(let e of a.pending)M.push(e),e.finally(()=>{let t=M.indexOf(e);t!==-1&&M.splice(t,1)}).catch(()=>{});return a.ran}function Y(){if(!(j||F)){j=!0;try{let e=0;O.processCancellable(t=>{if(N!==void 0)return!1;if(e>=y)return Z(`budget`,{event:t,error:/* @__PURE__ */ Error(`internal event budget exceeded`)}),!1;if(e++,u.has(t.type)||v.has(t.type))W(t);else if(!X(`output`,{event:t,operation:()=>k.emitOutput(t)}))return!1;return!0})}finally{j=!1,H()}}}function X(t,n){let r=e.from(()=>(n.operation(),!0));return r[0]===void 0||(Z(t,{event:n.event,error:r[0]}),!1)}function Z(e,t){if(N!==void 0)return;let n=t.lastGood??P??{state:x,context:C};N={error:t.error,state:n.state,context:n.context,event:t.event,reason:e},A?.abort(),x=L,S=void 0,E=L,I=!1,k.emitError(N),k.emitChange(K()),k.emitDone()}function oe(e){F||(O.push(e),Y())}function se(){if(!F){F=!0,A?.abort(),A=void 0;for(let e of Object.values(D))e.dispose();D={},O.clear(),k.clear(),M=[]}}function Q(){return O.settled().then(()=>{if(M.length!==0)return Promise.all(M).then(()=>Q())})}function $(){return V}return V}function C(e){return Symbol.for(`mantaq:event:${e}`)}function w(e){return()=>T(e)}function T(e){let t=C(e),n=function(e){return typeof e==`object`&&!!e&&Object.hasOwn(e,t)};function r(n){return Object.defineProperty(n===void 0?{type:e}:{type:e,payload:n},t,{value:!0})}return{type:e,is:n,create:r}}export{S as Actor,i as Context,T as EventRef,p as RealClock,c as StateRef,x as VirtualClock,w as event,s as isStateRef,a as state};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mantaq/core",
3
- "version": "0.5.3",
3
+ "version": "0.5.4",
4
4
  "description": "State machine runtime with actor model, event system, state hierarchy, effects, and virtual clock.",
5
5
  "license": "MIT",
6
6
  "repository": {