@doeixd/machine 0.0.6 → 0.0.7
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/README.md +158 -0
- package/dist/cjs/development/index.js +275 -5
- package/dist/cjs/development/index.js.map +4 -4
- package/dist/cjs/production/index.js +5 -5
- package/dist/esm/development/index.js +275 -5
- package/dist/esm/development/index.js.map +4 -4
- package/dist/esm/production/index.js +5 -5
- package/dist/types/extract.d.ts +40 -4
- package/dist/types/extract.d.ts.map +1 -1
- package/dist/types/generators.d.ts +40 -9
- package/dist/types/generators.d.ts.map +1 -1
- package/dist/types/higher-order.d.ts +221 -0
- package/dist/types/higher-order.d.ts.map +1 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/utils.d.ts +208 -0
- package/dist/types/utils.d.ts.map +1 -0
- package/package.json +1 -1
- package/src/extract.ts +180 -8
- package/src/generators.ts +25 -25
- package/src/higher-order.ts +364 -0
- package/src/index.ts +18 -1
- package/src/utils.ts +171 -5
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
"use strict";var
|
|
2
|
-
🔍 Analyzing machine: ${t.id}`),console.error(` Source: ${t.input}`));let
|
|
3
|
-
📊 Starting statechart extraction`),console.error(` Machines to extract: ${t.machines.length}`));let
|
|
4
|
-
✅ Extraction complete: ${
|
|
5
|
-
`);let e=new c.Project;e.addSourceFilesAtPaths("src/**/*.ts"),e.addSourceFilesAtPaths("examples/**/*.ts");try{let
|
|
1
|
+
"use strict";var w=Object.defineProperty;var ue=Object.getOwnPropertyDescriptor;var xe=Object.getOwnPropertyNames;var ye=Object.prototype.hasOwnProperty;var de=(t,e)=>{for(var n in e)w(t,n,{get:e[n],enumerable:!0})},Me=(t,e,n,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of xe(e))!ye.call(t,r)&&r!==n&&w(t,r,{get:()=>e[r],enumerable:!(i=ue(e,r))||i.enumerable});return t};var fe=t=>Me(w({},"__esModule",{value:!0}),t);var De={};de(De,{BoundMachine:()=>S,META_KEY:()=>U,MachineBase:()=>y,MultiMachineBase:()=>v,RUNTIME_META:()=>h,action:()=>H,bindTransitions:()=>L,call:()=>le,createAsyncMachine:()=>ke,createEnsemble:()=>Ce,createEvent:()=>oe,createFetchMachine:()=>we,createFlow:()=>G,createMachine:()=>f,createMachineBuilder:()=>ve,createMachineFactory:()=>Fe,createMultiMachine:()=>Ee,createMutableMachine:()=>be,createParallelMachine:()=>$,createRunner:()=>re,delegateToChild:()=>Se,describe:()=>J,extendTransitions:()=>Re,extractFromInstance:()=>ne,extractFunctionMetadata:()=>R,extractMachine:()=>E,extractMachines:()=>ee,extractStateNode:()=>b,generateChart:()=>P,generateStatechart:()=>te,guarded:()=>Y,hasState:()=>je,invoke:()=>X,isState:()=>ie,logState:()=>ce,matchMachine:()=>Ne,mergeContext:()=>ae,metadata:()=>Q,next:()=>Ke,overrideTransitions:()=>Pe,pipeTransitions:()=>se,run:()=>k,runAsync:()=>V,runMachine:()=>Oe,runSequence:()=>W,runWithDebug:()=>B,runWithEnsemble:()=>me,runWithRunner:()=>Te,setContext:()=>p,step:()=>I,stepAsync:()=>z,toggle:()=>Ae,transitionTo:()=>q,yieldMachine:()=>_});module.exports=fe(De);function k(t,e){let n=t(e),i=e;for(;;){let{value:r,done:o}=n.next(i);if(o)return r;i=r}}function I(t){return function*(){return yield t}()}function _(t){return t}function W(t,e){return e.reduce((n,i)=>k(i,n),t)}function G(t){return t}function B(t,e,n=(i,r)=>{console.log(`Step ${i}:`,r.context)}){let i=t(e),r=e,o=0;for(n(o,r);;){let{value:a,done:s}=i.next(r);if(s)return console.log("Final:",a),a;r=a,o++,n(o,r)}}async function V(t,e){let n=t(e),i=e;for(;;){let{value:r,done:o}=await n.next(i);if(o)return r;i=r}}async function*z(t){return yield t}var U=Symbol("MachineMeta"),h=Symbol("__machine_runtime_meta__");function C(t,e){let n=t[h]||{},i={...n,...e};e.guards&&n.guards?i.guards=[...e.guards,...n.guards]:e.guards&&(i.guards=[...e.guards]),e.actions&&n.actions?i.actions=[...e.actions,...n.actions]:e.actions&&(i.actions=[...e.actions]),Object.defineProperty(t,h,{value:i,enumerable:!1,writable:!1,configurable:!0})}function q(t,e){return C(e,{target:t.name||t.toString()}),e}function J(t,e){return C(e,{description:t}),e}function Y(t,e){return C(e,{guards:[t]}),e}function X(t,e){return C(e,{invoke:{src:t.src,onDone:t.onDone.name||t.onDone.toString(),onError:t.onError.name||t.onError.toString(),description:t.description}}),e}function H(t,e){return C(e,{actions:[t]}),e}function Q(t,e){return e}var c=require("ts-morph");function Z(t){return c.Node.isIdentifier(t)?t.getText():c.Node.isTypeOfExpression(t)?t.getExpression().getText():"unknown"}function m(t){if(!c.Node.isObjectLiteralExpression(t))return{};let e={};for(let n of t.getProperties())if(c.Node.isPropertyAssignment(n)){let i=n.getName(),r=n.getInitializer();r&&(c.Node.isStringLiteral(r)||c.Node.isNumericLiteral(r)?e[i]=r.getLiteralValue():r.getText()==="true"||r.getText()==="false"?e[i]=r.getText()==="true":c.Node.isIdentifier(r)?e[i]=r.getText():c.Node.isObjectLiteralExpression(r)?e[i]=m(r):c.Node.isArrayLiteralExpression(r)&&(e[i]=r.getElements().map(o=>c.Node.isObjectLiteralExpression(o)?m(o):o.getText())))}return e}function ge(t){if(!c.Node.isObjectLiteralExpression(t))return{};let e={};for(let n of t.getProperties())if(c.Node.isPropertyAssignment(n)){let i=n.getName(),r=n.getInitializer();if(!r)continue;i==="onDone"||i==="onError"?e[i]=Z(r):c.Node.isStringLiteral(r)?e[i]=r.getLiteralValue():c.Node.isIdentifier(r)&&(e[i]=r.getText())}return e}function T(t,e=!1){if(!c.Node.isCallExpression(t))return null;let n=t.getExpression(),i=c.Node.isIdentifier(n)?n.getText():null;if(!i)return null;let r={},o=t.getArguments();switch(i){case"transitionTo":o[0]&&(r.target=Z(o[0]));break;case"describe":if(o[0]&&c.Node.isStringLiteral(o[0])&&(r.description=o[0].getLiteralValue()),o[1]&&c.Node.isCallExpression(o[1])){let a=T(o[1],e);a&&Object.assign(r,a)}break;case"guarded":if(o[0]){let a=m(o[0]);Object.keys(a).length>0&&(r.guards=[a])}if(o[1]&&c.Node.isCallExpression(o[1])){let a=T(o[1],e);a&&Object.assign(r,a)}break;case"invoke":if(o[0]){let a=ge(o[0]);Object.keys(a).length>0&&(r.invoke=a)}break;case"action":if(o[0]){let a=m(o[0]);Object.keys(a).length>0&&(r.actions=[a])}if(o[1]&&c.Node.isCallExpression(o[1])){let a=T(o[1],e);a&&Object.assign(r,a)}break;default:return null}return Object.keys(r).length>0?r:null}function he(t,e=!1){if(!c.Node.isPropertyDeclaration(t))return e&&console.error(" ⚠️ Not a property declaration"),null;let n=t.getInitializer();if(!n)return e&&console.error(" ⚠️ No initializer"),null;if(!c.Node.isCallExpression(n))return e&&console.error(" ⚠️ Initializer is not a call expression"),null;let i=T(n,e);return i&&e&&console.error(" ✅ Extracted metadata:",JSON.stringify(i,null,2)),i}function F(t,e=!1){let n={on:{}},i=t.getDeclarations()[0];if(!i||!c.Node.isClassDeclaration(i))return e&&console.error(`⚠️ Warning: Could not get class declaration for ${t.getName()}`),n;let r=t.getName();e&&console.error(` Analyzing state: ${r}`);for(let o of i.getInstanceMembers()){let a=o.getName();e&&console.error(` Checking member: ${a}`);let s=he(o,e);if(!s)continue;e&&console.error(` Found transition: ${a}`);let{invoke:l,actions:u,guards:x,...d}=s;if(l&&(n.invoke||(n.invoke=[]),n.invoke.push({src:l.src,onDone:{target:l.onDone},onError:{target:l.onError},description:l.description}),e&&console.error(` → Invoke: ${l.src}`)),d.target){let M={target:d.target};d.description&&(M.description=d.description),x&&(M.cond=x.map(A=>A.name).join(" && "),e&&console.error(` → Guard: ${M.cond}`)),u&&u.length>0&&(M.actions=u.map(A=>A.name),e&&console.error(` → Actions: ${M.actions.join(", ")}`)),n.on[a]=M,e&&console.error(` → Target: ${d.target}`)}}return n}function pe(t,e,n,i,r=!1){let o=F(e,r);if(i){r&&console.error(` 👪 Analyzing children for state: ${t}`),o.initial=i.initialState,o.states={};for(let a of i.classes){let s=n.getClass(a);if(s){let l=s.getSymbolOrThrow();o.states[a]=F(l,r)}else console.warn(`⚠️ Warning: Child class '${a}' not found.`)}}return o}function E(t,e,n=!1){n&&(console.error(`
|
|
2
|
+
🔍 Analyzing machine: ${t.id}`),console.error(` Source: ${t.input}`));let i=e.getSourceFile(t.input);if(!i)throw new Error(`Source file not found: ${t.input}`);if(t.parallel){n&&console.error(" ⏹️ Parallel machine detected. Analyzing regions.");let o={id:t.id,type:"parallel",states:{}};t.description&&(o.description=t.description);for(let a of t.parallel.regions){n&&console.error(` 📍 Analyzing region: ${a.name}`);let s={};for(let l of a.classes){let u=i.getClass(l);if(u){let x=u.getSymbolOrThrow();s[l]=F(x,n)}else console.warn(`⚠️ Warning: Class '${l}' not found for region '${a.name}'.`)}o.states[a.name]={initial:a.initialState,states:s}}return n&&console.error(` ✅ Extracted ${t.parallel.regions.length} parallel regions`),o}if(!t.initialState||!t.classes)throw new Error(`Machine config for '${t.id}' must have either 'parallel' or 'initialState'/'classes'.`);let r={id:t.id,initial:t.initialState,states:{}};t.description&&(r.description=t.description);for(let o of t.classes){let a=i.getClass(o);if(!a){console.warn(`⚠️ Warning: Class '${o}' not found in '${t.input}'. Skipping.`);continue}let s=a.getSymbolOrThrow(),l=o===t.initialState&&t.children,u=pe(o,s,i,l?t.children:void 0,n);r.states[o]=u}return n&&console.error(` ✅ Extracted ${t.classes.length} states`),r}function ee(t){var r;let e=(r=t.verbose)!=null?r:!1;e&&(console.error(`
|
|
3
|
+
📊 Starting statechart extraction`),console.error(` Machines to extract: ${t.machines.length}`));let n=new c.Project;n.addSourceFilesAtPaths("src/**/*.ts"),n.addSourceFilesAtPaths("examples/**/*.ts");let i=[];for(let o of t.machines)try{let a=E(o,n,e);i.push(a)}catch(a){console.error(`❌ Error extracting machine '${o.id}':`,a),e||console.error(" Run with --verbose for more details")}return e&&console.error(`
|
|
4
|
+
✅ Extraction complete: ${i.length}/${t.machines.length} machines extracted`),i}function P(){let t={input:"examples/authMachine.ts",classes:["LoggedOutMachine","LoggingInMachine","LoggedInMachine","SessionExpiredMachine","ErrorMachine"],id:"auth",initialState:"LoggedOutMachine",description:"Authentication state machine"};console.error("🔍 Using legacy generateChart function"),console.error(`⚠️ Consider using extractMachines() with a config file instead
|
|
5
|
+
`);let e=new c.Project;e.addSourceFilesAtPaths("src/**/*.ts"),e.addSourceFilesAtPaths("examples/**/*.ts");try{let n=E(t,e,!0);console.log(JSON.stringify(n,null,2))}catch(n){console.error("❌ Error:",n),process.exit(1)}}require.main===module&&P();function R(t){return typeof t!="function"?null:t[h]||null}function b(t){let e={on:{}},n=[];for(let i in t){let r=t[i];if(typeof r!="function")continue;let o=R(r);if(o&&(o.invoke&&n.push({src:o.invoke.src,onDone:{target:o.invoke.onDone},onError:{target:o.invoke.onError},description:o.invoke.description}),o.target)){let a={target:o.target};o.description&&(a.description=o.description),o.guards&&o.guards.length>0&&(a.cond=o.guards.map(s=>s.name).join(" && ")),o.actions&&o.actions.length>0&&(a.actions=o.actions.map(s=>s.name)),e.on[i]=a}}return n.length>0&&(e.invoke=n),e}function te(t,e){let n={id:e.id,initial:e.initial,states:{}};e.description&&(n.description=e.description);for(let[i,r]of Object.entries(t))n.states[i]=b(r);return n}function ne(t,e){let n=e.stateName||t.constructor.name||"State";return{id:e.id,initial:n,states:{[n]:b(t)}}}function re(t,e){let n=t,i=s=>{n=s,e==null||e(s)},{context:r,...o}=t,a=new Proxy({},{get(s,l){let u=n[l];if(typeof u=="function")return(...x)=>{let d=u.apply(n.context,x),M=Object.assign({context:d.context},o);return i(M),M}}});return{get state(){return n},get context(){return n.context},actions:a,setState:i}}function Ce(t,e,n){let i=()=>{let o=t.getContext(),a=n(o),s=e[a];if(!s)throw new Error(`[Ensemble] Invalid state: No factory found for state "${String(a)}".`);return s(o)},r=new Proxy({},{get(o,a){let s=i(),l=s[a];if(typeof l!="function")throw new Error(`[Ensemble] Transition "${a}" is not valid in the current state.`);return(...u)=>l.apply(s.context,u)}});return{get context(){return t.getContext()},get state(){return i()},actions:r}}function Te(t,e){let n=re(e),i=t(n),r=i.next();for(;!r.done;)r=i.next();return r.value}function me(t,e){let n=t(e),i=n.next();for(;!i.done;)i=n.next();return i.value}var v=class{constructor(e){this.store=e}get context(){return this.store.getContext()}setContext(e){this.store.setContext(e)}};function Ee(t,e){let n=new t(e);return new Proxy({},{get(i,r){let o=e.getContext();if(r in o)return o[r];let a=n[r];if(typeof a=="function")return(...s)=>a.apply(n,s)},set(i,r,o){let a=e.getContext();if(r in a){let s={...a,[r]:o};return e.setContext(s),!0}return!1},has(i,r){let o=e.getContext();return r in o||typeof n[r]=="function"},ownKeys(i){let r=e.getContext(),o=Object.keys(r),a=Object.getOwnPropertyNames(Object.getPrototypeOf(n)).filter(s=>s!=="constructor"&&typeof n[s]=="function");return Array.from(new Set([...o,...a]))},getOwnPropertyDescriptor(i,r){let o=e.getContext();if(r in o||typeof n[r]=="function")return{value:void 0,writable:!0,enumerable:!0,configurable:!0}}})}function be(t,e,n){let i=()=>{let r=n(t),o=e[r];if(!o)throw new Error(`[MutableMachine] Invalid state: No factory for state "${String(r)}".`);return o(t)};return new Proxy(t,{get(r,o,a){if(o in r)return r[o];let s=i(),l=s[o];if(typeof l=="function")return(...u)=>{let x=l.apply(s.context,u);if(typeof x!="object"||x===null){console.warn(`[MutableMachine] Transition "${String(o)}" did not return a valid context object. State may be inconsistent.`);return}Object.keys(r).forEach(d=>delete r[d]),Object.assign(r,x)}},set(r,o,a,s){return r[o]=a,!0},has(r,o){let a=i();return o in r||typeof a[o]=="function"}})}function Se(t){return function(...e){let n=this.context.child;if(typeof n[t]=="function"){let i=n[t](...e);return p(this,{...this.context,child:i})}return this}}function Ae(t){return function(){return typeof this.context[t]!="boolean"&&console.warn(`[toggle primitive] Property '${String(t)}' is not a boolean. Toggling may have unexpected results.`),p(this,{...this.context,[t]:!this.context[t]})}}var N=class extends y{constructor(n){super({status:"idle"});this.config=n;this.fetch=n=>new g(this.config,n!=null?n:this.config.initialParams,1)}},g=class extends y{constructor(n,i,r){super({status:"loading",abortController:new AbortController,attempts:r});this.config=n;this.params=i;this.succeed=n=>{var i,r;return(r=(i=this.config).onSuccess)==null||r.call(i,n),new O(this.config,{status:"success",data:n})};this.fail=n=>{var r,o,a;let i=(r=this.config.maxRetries)!=null?r:3;return this.context.attempts<i?new j(this.config,this.params,n,this.context.attempts):((a=(o=this.config).onError)==null||a.call(o,n),new K(this.config,{status:"error",error:n}))};this.cancel=()=>(this.context.abortController.abort(),new D(this.config));this.execute()}async execute(){}},j=class extends y{constructor(n,i,r,o){super({status:"retrying",error:r,attempts:o});this.config=n;this.params=i;this.retry=n=>new g(this.config,n!=null?n:this.params,this.context.attempts+1)}},O=class extends y{constructor(n,i){super(i);this.config=n;this.refetch=n=>new g(this.config,n!=null?n:this.config.initialParams,1)}},K=class extends y{constructor(n,i){super(i);this.config=n;this.retry=n=>new g(this.config,n!=null?n:this.config.initialParams,1)}},D=class extends y{constructor(n){super({status:"canceled"});this.config=n;this.refetch=n=>new g(this.config,n!=null?n:this.config.initialParams,1)}};function we(t){return new N(t)}function $(t,e){let n={...t.context,...e.context},i={...t},r={...e};delete i.context,delete r.context;let o={};for(let a in i){let s=i[a];o[a]=(...l)=>{let u=s.apply(t.context,l);return $(u,e)}}for(let a in r){let s=r[a];o[a]=(...l)=>{let u=s.apply(e.context,l);return $(t,u)}}return{context:n,...o}}function ie(t,e){return t instanceof e}function oe(t,...e){return{type:t,args:e}}function ae(t,e){return p(t,n=>({...n,...e}))}async function se(t,...e){let n=t;for(let i of e)n=await i(n);return n}function ce(t,e){return e?console.log(e,t.context):console.log(t.context),t}function le(t,e,...n){return t.apply(e,n)}function L(t){return new Proxy(t,{get(e,n){let i=e[n];return typeof i=="function"?function(...r){let o=i.apply(e.context,r);return o&&typeof o=="object"&&"context"in o?L(o):o}:i}})}var S=class t{constructor(e){return this.wrappedMachine=e,new Proxy(this,{get:(n,i)=>{if(i==="wrappedMachine"||i==="context")return Reflect.get(n,i);let r=this.wrappedMachine[i];return typeof r=="function"?(...o)=>{let a=r.apply(this.wrappedMachine.context,o);return a&&typeof a=="object"&&"context"in a?new t(a):a}:r}})}get context(){return this.wrappedMachine.context}};function f(t,e){return Object.assign({context:t},e)}function ke(t,e){return Object.assign({context:t},e)}function Fe(){return t=>{let e=Object.fromEntries(Object.entries(t).map(([n,i])=>[n,function(...r){let o=i(this,...r);return f(o,e)}]));return n=>f(n,e)}}function p(t,e){let{context:n,...i}=t,r=typeof e=="function"?e(n):e;return f(r,i)}function Pe(t,e){let{context:n,...i}=t,r={...i,...e};return f(n,r)}function Re(t,e){let{context:n,...i}=t,r={...i,...e};return f(n,r)}function ve(t){let{context:e,...n}=t;return i=>f(i,n)}function Ne(t,e,n){let i=t.context[e],r=n[i];if(!r)throw new Error(`No handler found for state: ${String(i)}`);return r(t.context)}function je(t,e,n){return t.context[e]===n}function Oe(t,e){let n=t;async function i(r){let o=n[r.type];if(typeof o!="function")throw new Error(`[Machine] Unknown event type '${String(r.type)}' on current state.`);return n=await o.apply(n.context,r.args),e==null||e(n),n}return{get state(){return n.context},dispatch:i}}var y=class{constructor(e){this.context=e}};function Ke(t,e){let{context:n,...i}=t;return f(e(n),i)}
|
|
@@ -196,17 +196,17 @@ function parseInvokeService(obj) {
|
|
|
196
196
|
}
|
|
197
197
|
return service;
|
|
198
198
|
}
|
|
199
|
-
function extractFromCallExpression(
|
|
200
|
-
if (!Node.isCallExpression(
|
|
199
|
+
function extractFromCallExpression(call2, verbose = false) {
|
|
200
|
+
if (!Node.isCallExpression(call2)) {
|
|
201
201
|
return null;
|
|
202
202
|
}
|
|
203
|
-
const expression =
|
|
203
|
+
const expression = call2.getExpression();
|
|
204
204
|
const fnName = Node.isIdentifier(expression) ? expression.getText() : null;
|
|
205
205
|
if (!fnName) {
|
|
206
206
|
return null;
|
|
207
207
|
}
|
|
208
208
|
const metadata2 = {};
|
|
209
|
-
const args =
|
|
209
|
+
const args = call2.getArguments();
|
|
210
210
|
switch (fnName) {
|
|
211
211
|
case "transitionTo":
|
|
212
212
|
if (args[0]) {
|
|
@@ -346,6 +346,26 @@ function analyzeStateNode(classSymbol, verbose = false) {
|
|
|
346
346
|
}
|
|
347
347
|
return chartNode;
|
|
348
348
|
}
|
|
349
|
+
function analyzeStateNodeWithNesting(className, classSymbol, sourceFile, childConfig, verbose = false) {
|
|
350
|
+
const stateNode = analyzeStateNode(classSymbol, verbose);
|
|
351
|
+
if (childConfig) {
|
|
352
|
+
if (verbose) {
|
|
353
|
+
console.error(` 👪 Analyzing children for state: ${className}`);
|
|
354
|
+
}
|
|
355
|
+
stateNode.initial = childConfig.initialState;
|
|
356
|
+
stateNode.states = {};
|
|
357
|
+
for (const childClassName of childConfig.classes) {
|
|
358
|
+
const childClassDeclaration = sourceFile.getClass(childClassName);
|
|
359
|
+
if (childClassDeclaration) {
|
|
360
|
+
const childSymbol = childClassDeclaration.getSymbolOrThrow();
|
|
361
|
+
stateNode.states[childClassName] = analyzeStateNode(childSymbol, verbose);
|
|
362
|
+
} else {
|
|
363
|
+
console.warn(`⚠️ Warning: Child class '${childClassName}' not found.`);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
return stateNode;
|
|
368
|
+
}
|
|
349
369
|
function extractMachine(config, project, verbose = false) {
|
|
350
370
|
if (verbose) {
|
|
351
371
|
console.error(`
|
|
@@ -356,6 +376,45 @@ function extractMachine(config, project, verbose = false) {
|
|
|
356
376
|
if (!sourceFile) {
|
|
357
377
|
throw new Error(`Source file not found: ${config.input}`);
|
|
358
378
|
}
|
|
379
|
+
if (config.parallel) {
|
|
380
|
+
if (verbose) {
|
|
381
|
+
console.error(` ⏹️ Parallel machine detected. Analyzing regions.`);
|
|
382
|
+
}
|
|
383
|
+
const parallelChart = {
|
|
384
|
+
id: config.id,
|
|
385
|
+
type: "parallel",
|
|
386
|
+
states: {}
|
|
387
|
+
};
|
|
388
|
+
if (config.description) {
|
|
389
|
+
parallelChart.description = config.description;
|
|
390
|
+
}
|
|
391
|
+
for (const region of config.parallel.regions) {
|
|
392
|
+
if (verbose) {
|
|
393
|
+
console.error(` 📍 Analyzing region: ${region.name}`);
|
|
394
|
+
}
|
|
395
|
+
const regionStates = {};
|
|
396
|
+
for (const className of region.classes) {
|
|
397
|
+
const classDeclaration = sourceFile.getClass(className);
|
|
398
|
+
if (classDeclaration) {
|
|
399
|
+
const classSymbol = classDeclaration.getSymbolOrThrow();
|
|
400
|
+
regionStates[className] = analyzeStateNode(classSymbol, verbose);
|
|
401
|
+
} else {
|
|
402
|
+
console.warn(`⚠️ Warning: Class '${className}' not found for region '${region.name}'.`);
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
parallelChart.states[region.name] = {
|
|
406
|
+
initial: region.initialState,
|
|
407
|
+
states: regionStates
|
|
408
|
+
};
|
|
409
|
+
}
|
|
410
|
+
if (verbose) {
|
|
411
|
+
console.error(` ✅ Extracted ${config.parallel.regions.length} parallel regions`);
|
|
412
|
+
}
|
|
413
|
+
return parallelChart;
|
|
414
|
+
}
|
|
415
|
+
if (!config.initialState || !config.classes) {
|
|
416
|
+
throw new Error(`Machine config for '${config.id}' must have either 'parallel' or 'initialState'/'classes'.`);
|
|
417
|
+
}
|
|
359
418
|
const fullChart = {
|
|
360
419
|
id: config.id,
|
|
361
420
|
initial: config.initialState,
|
|
@@ -371,7 +430,14 @@ function extractMachine(config, project, verbose = false) {
|
|
|
371
430
|
continue;
|
|
372
431
|
}
|
|
373
432
|
const classSymbol = classDeclaration.getSymbolOrThrow();
|
|
374
|
-
const
|
|
433
|
+
const hasChildren = className === config.initialState && config.children;
|
|
434
|
+
const stateNode = analyzeStateNodeWithNesting(
|
|
435
|
+
className,
|
|
436
|
+
classSymbol,
|
|
437
|
+
sourceFile,
|
|
438
|
+
hasChildren ? config.children : void 0,
|
|
439
|
+
verbose
|
|
440
|
+
);
|
|
375
441
|
fullChart.states[className] = stateNode;
|
|
376
442
|
}
|
|
377
443
|
if (verbose) {
|
|
@@ -737,6 +803,198 @@ function createMutableMachine(sharedContext, factories, getDiscriminant) {
|
|
|
737
803
|
});
|
|
738
804
|
}
|
|
739
805
|
|
|
806
|
+
// src/higher-order.ts
|
|
807
|
+
function delegateToChild(actionName) {
|
|
808
|
+
return function(...args) {
|
|
809
|
+
const child = this.context.child;
|
|
810
|
+
if (typeof child[actionName] === "function") {
|
|
811
|
+
const newChildState = child[actionName](...args);
|
|
812
|
+
return setContext(this, { ...this.context, child: newChildState });
|
|
813
|
+
}
|
|
814
|
+
return this;
|
|
815
|
+
};
|
|
816
|
+
}
|
|
817
|
+
function toggle(prop) {
|
|
818
|
+
return function() {
|
|
819
|
+
if (typeof this.context[prop] !== "boolean") {
|
|
820
|
+
console.warn(`[toggle primitive] Property '${String(prop)}' is not a boolean. Toggling may have unexpected results.`);
|
|
821
|
+
}
|
|
822
|
+
return setContext(this, {
|
|
823
|
+
...this.context,
|
|
824
|
+
[prop]: !this.context[prop]
|
|
825
|
+
});
|
|
826
|
+
};
|
|
827
|
+
}
|
|
828
|
+
var IdleMachine = class extends MachineBase {
|
|
829
|
+
constructor(config) {
|
|
830
|
+
super({ status: "idle" });
|
|
831
|
+
this.config = config;
|
|
832
|
+
this.fetch = (params) => new LoadingMachine(this.config, params != null ? params : this.config.initialParams, 1);
|
|
833
|
+
}
|
|
834
|
+
};
|
|
835
|
+
var LoadingMachine = class extends MachineBase {
|
|
836
|
+
constructor(config, params, attempts) {
|
|
837
|
+
super({ status: "loading", abortController: new AbortController(), attempts });
|
|
838
|
+
this.config = config;
|
|
839
|
+
this.params = params;
|
|
840
|
+
this.succeed = (data) => {
|
|
841
|
+
var _a, _b;
|
|
842
|
+
(_b = (_a = this.config).onSuccess) == null ? void 0 : _b.call(_a, data);
|
|
843
|
+
return new SuccessMachine(this.config, { status: "success", data });
|
|
844
|
+
};
|
|
845
|
+
this.fail = (error) => {
|
|
846
|
+
var _a, _b, _c;
|
|
847
|
+
const maxRetries = (_a = this.config.maxRetries) != null ? _a : 3;
|
|
848
|
+
if (this.context.attempts < maxRetries) {
|
|
849
|
+
return new RetryingMachine(this.config, this.params, error, this.context.attempts);
|
|
850
|
+
}
|
|
851
|
+
(_c = (_b = this.config).onError) == null ? void 0 : _c.call(_b, error);
|
|
852
|
+
return new ErrorMachine(this.config, { status: "error", error });
|
|
853
|
+
};
|
|
854
|
+
this.cancel = () => {
|
|
855
|
+
this.context.abortController.abort();
|
|
856
|
+
return new CanceledMachine(this.config);
|
|
857
|
+
};
|
|
858
|
+
this.execute();
|
|
859
|
+
}
|
|
860
|
+
async execute() {
|
|
861
|
+
}
|
|
862
|
+
};
|
|
863
|
+
var RetryingMachine = class extends MachineBase {
|
|
864
|
+
constructor(config, params, error, attempts) {
|
|
865
|
+
super({ status: "retrying", error, attempts });
|
|
866
|
+
this.config = config;
|
|
867
|
+
this.params = params;
|
|
868
|
+
// This would be called after a delay.
|
|
869
|
+
this.retry = (params) => new LoadingMachine(this.config, params != null ? params : this.params, this.context.attempts + 1);
|
|
870
|
+
}
|
|
871
|
+
};
|
|
872
|
+
var SuccessMachine = class extends MachineBase {
|
|
873
|
+
constructor(config, context) {
|
|
874
|
+
super(context);
|
|
875
|
+
this.config = config;
|
|
876
|
+
this.refetch = (params) => new LoadingMachine(this.config, params != null ? params : this.config.initialParams, 1);
|
|
877
|
+
}
|
|
878
|
+
};
|
|
879
|
+
var ErrorMachine = class extends MachineBase {
|
|
880
|
+
constructor(config, context) {
|
|
881
|
+
super(context);
|
|
882
|
+
this.config = config;
|
|
883
|
+
this.retry = (params) => new LoadingMachine(this.config, params != null ? params : this.config.initialParams, 1);
|
|
884
|
+
}
|
|
885
|
+
};
|
|
886
|
+
var CanceledMachine = class extends MachineBase {
|
|
887
|
+
constructor(config) {
|
|
888
|
+
super({ status: "canceled" });
|
|
889
|
+
this.config = config;
|
|
890
|
+
this.refetch = (params) => new LoadingMachine(this.config, params != null ? params : this.config.initialParams, 1);
|
|
891
|
+
}
|
|
892
|
+
};
|
|
893
|
+
function createFetchMachine(config) {
|
|
894
|
+
return new IdleMachine(config);
|
|
895
|
+
}
|
|
896
|
+
function createParallelMachine(m1, m2) {
|
|
897
|
+
const combinedContext = { ...m1.context, ...m2.context };
|
|
898
|
+
const transitions1 = { ...m1 };
|
|
899
|
+
const transitions2 = { ...m2 };
|
|
900
|
+
delete transitions1.context;
|
|
901
|
+
delete transitions2.context;
|
|
902
|
+
const combinedTransitions = {};
|
|
903
|
+
for (const key in transitions1) {
|
|
904
|
+
const transitionFn = transitions1[key];
|
|
905
|
+
combinedTransitions[key] = (...args) => {
|
|
906
|
+
const nextM1 = transitionFn.apply(m1.context, args);
|
|
907
|
+
return createParallelMachine(nextM1, m2);
|
|
908
|
+
};
|
|
909
|
+
}
|
|
910
|
+
for (const key in transitions2) {
|
|
911
|
+
const transitionFn = transitions2[key];
|
|
912
|
+
combinedTransitions[key] = (...args) => {
|
|
913
|
+
const nextM2 = transitionFn.apply(m2.context, args);
|
|
914
|
+
return createParallelMachine(m1, nextM2);
|
|
915
|
+
};
|
|
916
|
+
}
|
|
917
|
+
return {
|
|
918
|
+
context: combinedContext,
|
|
919
|
+
...combinedTransitions
|
|
920
|
+
};
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
// src/utils.ts
|
|
924
|
+
function isState(machine, machineClass) {
|
|
925
|
+
return machine instanceof machineClass;
|
|
926
|
+
}
|
|
927
|
+
function createEvent(type, ...args) {
|
|
928
|
+
return { type, args };
|
|
929
|
+
}
|
|
930
|
+
function mergeContext(machine, partialContext) {
|
|
931
|
+
return setContext(machine, (ctx) => ({ ...ctx, ...partialContext }));
|
|
932
|
+
}
|
|
933
|
+
async function pipeTransitions(initialMachine, ...transitions) {
|
|
934
|
+
let current = initialMachine;
|
|
935
|
+
for (const transitionFn of transitions) {
|
|
936
|
+
current = await transitionFn(current);
|
|
937
|
+
}
|
|
938
|
+
return current;
|
|
939
|
+
}
|
|
940
|
+
function logState(machine, label) {
|
|
941
|
+
if (label) {
|
|
942
|
+
console.log(label, machine.context);
|
|
943
|
+
} else {
|
|
944
|
+
console.log(machine.context);
|
|
945
|
+
}
|
|
946
|
+
return machine;
|
|
947
|
+
}
|
|
948
|
+
function call(fn, context, ...args) {
|
|
949
|
+
return fn.apply(context, args);
|
|
950
|
+
}
|
|
951
|
+
function bindTransitions(machine) {
|
|
952
|
+
return new Proxy(machine, {
|
|
953
|
+
get(target, prop) {
|
|
954
|
+
const value = target[prop];
|
|
955
|
+
if (typeof value === "function") {
|
|
956
|
+
return function(...args) {
|
|
957
|
+
const result = value.apply(target.context, args);
|
|
958
|
+
if (result && typeof result === "object" && "context" in result) {
|
|
959
|
+
return bindTransitions(result);
|
|
960
|
+
}
|
|
961
|
+
return result;
|
|
962
|
+
};
|
|
963
|
+
}
|
|
964
|
+
return value;
|
|
965
|
+
}
|
|
966
|
+
});
|
|
967
|
+
}
|
|
968
|
+
var BoundMachine = class _BoundMachine {
|
|
969
|
+
constructor(machine) {
|
|
970
|
+
this.wrappedMachine = machine;
|
|
971
|
+
return new Proxy(this, {
|
|
972
|
+
get: (target, prop) => {
|
|
973
|
+
if (prop === "wrappedMachine" || prop === "context") {
|
|
974
|
+
return Reflect.get(target, prop);
|
|
975
|
+
}
|
|
976
|
+
const value = this.wrappedMachine[prop];
|
|
977
|
+
if (typeof value === "function") {
|
|
978
|
+
return (...args) => {
|
|
979
|
+
const result = value.apply(this.wrappedMachine.context, args);
|
|
980
|
+
if (result && typeof result === "object" && "context" in result) {
|
|
981
|
+
return new _BoundMachine(result);
|
|
982
|
+
}
|
|
983
|
+
return result;
|
|
984
|
+
};
|
|
985
|
+
}
|
|
986
|
+
return value;
|
|
987
|
+
}
|
|
988
|
+
});
|
|
989
|
+
}
|
|
990
|
+
/**
|
|
991
|
+
* Access the underlying machine's context directly.
|
|
992
|
+
*/
|
|
993
|
+
get context() {
|
|
994
|
+
return this.wrappedMachine.context;
|
|
995
|
+
}
|
|
996
|
+
};
|
|
997
|
+
|
|
740
998
|
// src/index.ts
|
|
741
999
|
function createMachine(context, fns) {
|
|
742
1000
|
return Object.assign({ context }, fns);
|
|
@@ -827,20 +1085,27 @@ function next(m, update) {
|
|
|
827
1085
|
return createMachine(update(context), transitions);
|
|
828
1086
|
}
|
|
829
1087
|
export {
|
|
1088
|
+
BoundMachine,
|
|
830
1089
|
META_KEY,
|
|
831
1090
|
MachineBase,
|
|
832
1091
|
MultiMachineBase,
|
|
833
1092
|
RUNTIME_META,
|
|
834
1093
|
action,
|
|
1094
|
+
bindTransitions,
|
|
1095
|
+
call,
|
|
835
1096
|
createAsyncMachine,
|
|
836
1097
|
createEnsemble,
|
|
1098
|
+
createEvent,
|
|
1099
|
+
createFetchMachine,
|
|
837
1100
|
createFlow,
|
|
838
1101
|
createMachine,
|
|
839
1102
|
createMachineBuilder,
|
|
840
1103
|
createMachineFactory,
|
|
841
1104
|
createMultiMachine,
|
|
842
1105
|
createMutableMachine,
|
|
1106
|
+
createParallelMachine,
|
|
843
1107
|
createRunner,
|
|
1108
|
+
delegateToChild,
|
|
844
1109
|
describe,
|
|
845
1110
|
extendTransitions,
|
|
846
1111
|
extractFromInstance,
|
|
@@ -853,10 +1118,14 @@ export {
|
|
|
853
1118
|
guarded,
|
|
854
1119
|
hasState,
|
|
855
1120
|
invoke,
|
|
1121
|
+
isState,
|
|
1122
|
+
logState,
|
|
856
1123
|
matchMachine,
|
|
1124
|
+
mergeContext,
|
|
857
1125
|
metadata,
|
|
858
1126
|
next,
|
|
859
1127
|
overrideTransitions,
|
|
1128
|
+
pipeTransitions,
|
|
860
1129
|
run,
|
|
861
1130
|
runAsync,
|
|
862
1131
|
runMachine,
|
|
@@ -867,6 +1136,7 @@ export {
|
|
|
867
1136
|
setContext,
|
|
868
1137
|
step,
|
|
869
1138
|
stepAsync,
|
|
1139
|
+
toggle,
|
|
870
1140
|
transitionTo,
|
|
871
1141
|
yieldMachine
|
|
872
1142
|
};
|