@statewalker/fsm 0.36.0 → 0.37.0

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.
Files changed (41) hide show
  1. package/README.md +112 -0
  2. package/bin/cli.js +1 -1
  3. package/dist/bin/node-runner-UJp8T_oP.d.ts +16 -0
  4. package/dist/bin/node-runner-UJp8T_oP.d.ts.map +1 -0
  5. package/dist/bin/node-runner.js +40 -0
  6. package/dist/bin/node-runner.js.map +1 -0
  7. package/dist/index-vTjnkbGW.d.ts +129 -0
  8. package/dist/index-vTjnkbGW.d.ts.map +1 -0
  9. package/dist/index.js +38 -779
  10. package/dist/index.js.map +1 -1
  11. package/dist/launcher-6VUDviTj.d.ts +48 -0
  12. package/dist/launcher-6VUDviTj.d.ts.map +1 -0
  13. package/dist/launcher-CASrMAOa.js +443 -0
  14. package/dist/launcher-CASrMAOa.js.map +1 -0
  15. package/package.json +8 -8
  16. package/src/bin/node-runner.ts +57 -0
  17. package/src/core/fsm-base-class.ts +1 -26
  18. package/src/core/fsm-process.ts +14 -11
  19. package/src/core/fsm-state.ts +1 -21
  20. package/src/core/index.ts +1 -1
  21. package/src/index.ts +0 -3
  22. package/src/orchestrator/handler-registry.ts +108 -0
  23. package/src/orchestrator/index.ts +15 -9
  24. package/src/orchestrator/launcher.ts +42 -141
  25. package/src/orchestrator/start-process.ts +141 -26
  26. package/src/utils/index.ts +0 -2
  27. package/src/utils/printer.ts +5 -11
  28. package/src/utils/tracer.ts +1 -1
  29. package/CHANGELOG.md +0 -59
  30. package/dist/index.d.ts +0 -335
  31. package/src/core/new-fsm-process.ts +0 -83
  32. package/src/orchestrator/constants.ts +0 -130
  33. package/src/orchestrator/is-generator.ts +0 -12
  34. package/src/orchestrator/process-config-manager.ts +0 -70
  35. package/src/orchestrator/resolve-module-refs.ts +0 -52
  36. package/src/orchestrator/start-node-processes.ts +0 -19
  37. package/src/orchestrator/start-processes.ts +0 -32
  38. package/src/orchestrator/types.ts +0 -34
  39. package/src/utils/handlers.ts +0 -35
  40. package/src/utils/process.ts +0 -26
  41. package/src/utils/transitions.ts +0 -56
package/dist/index.js CHANGED
@@ -1,786 +1,45 @@
1
- // src/core/fsm-base-class.ts
2
- var FsmBaseClass = class {
3
- constructor() {
4
- this.handlers = {};
5
- this.data = {};
6
- bindMethods(this, "setData", "getData");
7
- }
8
- setData(key, value) {
9
- this.data[key] = value;
10
- return this;
11
- }
12
- getData(key) {
13
- return this.data[key];
14
- }
15
- // ----------------------------------------------
16
- // internal methods
17
- _addHandler(type, handler, direct = true) {
18
- let list = this.handlers[type];
19
- if (!list) {
20
- list = this.handlers[type] = [];
21
- }
22
- const h = handler;
23
- direct ? list.push(h) : list.unshift(h);
24
- return () => this._removeHandler(type, h);
25
- }
26
- _removeHandler(type, handler) {
27
- let list = this.handlers[type];
28
- if (!list) return;
29
- list = list.filter((h) => h !== handler);
30
- if (list.length > 0) {
31
- this.handlers[type] = list;
32
- } else {
33
- delete this.handlers[type];
34
- }
35
- }
36
- async _runHandlerParallel(type, ...args) {
37
- const list = this.handlers[type] || [];
38
- await Promise.all(
39
- list.map(async (handler) => {
40
- try {
41
- await handler(...args);
42
- } catch (error) {
43
- this._handleError(error);
44
- }
45
- })
46
- );
47
- }
48
- async _runHandler(type, ...args) {
49
- const list = this.handlers[type] || [];
50
- for (const handler of list) {
51
- try {
52
- await handler(...args);
53
- } catch (error) {
54
- await this._handleError(error);
55
- }
56
- }
57
- }
58
- async _handleError(error) {
59
- console.error(error);
60
- }
61
- };
62
- function bindMethods(obj, ...methods) {
63
- const o = obj;
64
- for (const methodName of methods) {
65
- const method = o[methodName];
66
- if (typeof method !== "function") continue;
67
- o[methodName] = method.bind(o);
68
- }
69
- return obj;
70
- }
71
-
72
- // src/core/fsm-state.ts
73
- var FsmState = class extends FsmBaseClass {
74
- constructor(process2, parent, key, descriptor) {
75
- super();
76
- this.process = process2;
77
- this.key = key;
78
- this.parent = parent;
79
- this.descriptor = descriptor;
80
- bindMethods(
81
- this,
82
- "onEnter",
83
- "onExit",
84
- "dump",
85
- "restore",
86
- "useData",
87
- "onStateError"
88
- );
89
- }
90
- onEnter(handler) {
91
- return this._addHandler("onEnter", handler, true);
92
- }
93
- onExit(handler) {
94
- return this._addHandler("onExit", handler, false);
95
- }
96
- onStateError(handler) {
97
- return this._addHandler("onStateError", handler);
98
- }
99
- dump(handler) {
100
- return this._addHandler("dump", handler, true);
101
- }
102
- restore(handler) {
103
- return this._addHandler("restore", handler, true);
104
- }
105
- getData(key, recursive = true) {
106
- return this.data[key] ?? (recursive ? this.parent?.getData(key, recursive) : void 0);
107
- }
108
- useData(key) {
109
- return [
110
- (recursive = true) => this.getData(key, recursive),
111
- (value) => this.setData(key, value)
112
- ];
113
- }
114
- async _handleError(error) {
115
- await this._runHandler("onStateError", this, error);
116
- await this.process._handleStateError(this, error);
117
- }
118
- };
119
-
120
- // src/core/fsm-state-config.ts
121
- var STATE_ANY = "*";
122
- var STATE_INITIAL = "";
123
- var STATE_FINAL = "";
124
- var EVENT_ANY = "*";
125
- var EVENT_EMPTY = "";
126
-
127
- // src/core/fsm-state-descriptor.ts
128
- var FsmStateDescriptor = class _FsmStateDescriptor {
129
- constructor() {
130
- this.transitions = {};
131
- this.states = {};
132
- }
133
- static build(config) {
134
- const descriptor = new _FsmStateDescriptor();
135
- for (const [from, event, to] of config.transitions || []) {
136
- let index = descriptor.transitions[from];
137
- if (!index) {
138
- index = descriptor.transitions[from] = {};
139
- }
140
- index[event] = to;
141
- }
142
- if (config.states) {
143
- for (const substateConfig of config.states) {
144
- descriptor.states[substateConfig.key] = _FsmStateDescriptor.build(substateConfig);
145
- }
146
- }
147
- return descriptor;
148
- }
149
- getTargetStateKey(stateKey, eventKey) {
150
- const pairs = [
151
- [stateKey, eventKey],
152
- [STATE_ANY, eventKey],
153
- [stateKey, EVENT_ANY],
154
- [STATE_ANY, EVENT_ANY]
155
- ];
156
- let targetKey;
157
- for (let i = 0, len = pairs.length; targetKey === void 0 && i < len; i++) {
158
- const [stateKey2, eventKey2] = pairs[i];
159
- const stateTransitions = this.transitions[stateKey2];
160
- if (!stateTransitions) continue;
161
- targetKey = stateTransitions[eventKey2];
162
- }
163
- return targetKey !== void 0 ? targetKey : STATE_FINAL;
164
- }
165
- };
166
-
167
- // src/core/fsm-process.ts
168
- var STATUS_NONE = 0;
169
- var STATUS_FIRST = 1;
170
- var STATUS_NEXT = 2;
171
- var STATUS_LEAF = 4;
172
- var STATUS_LAST = 8;
173
- var STATUS_FINISHED = 16;
174
- var STATUS_ENTER = STATUS_FIRST | STATUS_NEXT;
175
- var STATUS_EXIT = STATUS_LEAF | STATUS_LAST;
176
- var FsmProcess = class extends FsmBaseClass {
177
- constructor(config) {
178
- super();
179
- this.running = false;
180
- this.mask = STATUS_LEAF;
181
- this.status = 0;
182
- this.rootDescriptor = FsmStateDescriptor.build(config);
183
- this.config = config;
184
- bindMethods(this, "dispatch", "dump", "restore");
185
- }
186
- async shutdown(event) {
187
- while (this.state) {
188
- this.event = event;
189
- this.status = STATUS_FINISHED;
190
- await this.state?._runHandler("onExit", this.state);
191
- this.state = this.state.parent;
192
- }
193
- }
194
- async dispatch(event) {
195
- this.nextEvent = event;
196
- if (!this.running && !(this.status & STATUS_FINISHED)) {
197
- this.running = true;
198
- try {
199
- this.event = this.nextEvent;
200
- this.nextEvent = void 0;
201
- while (true) {
202
- if (this.status & STATUS_EXIT) {
203
- await this.state?._runHandler("onExit", this.state);
204
- }
205
- if (!this._update()) break;
206
- if (this.status & STATUS_ENTER) {
207
- await this.state?._runHandler("onEnter", this.state);
208
- }
209
- if (this.status & this.mask) break;
210
- }
211
- } finally {
212
- this.running = false;
213
- }
214
- const nextEvent = this.nextEvent;
215
- if (nextEvent !== void 0) {
216
- return Promise.resolve().then(() => this.dispatch(nextEvent));
217
- }
218
- }
219
- return !(this.status & STATUS_FINISHED);
220
- }
221
- async dump(...args) {
222
- const dumpState = async (state) => {
223
- const stateDump = {
224
- key: state.key,
225
- data: {}
226
- };
227
- await state._runHandler("dump", state, stateDump.data, ...args);
228
- return stateDump;
229
- };
230
- const dumpStates = async (state, stack = []) => {
231
- if (!state) return stack;
232
- state.parent && await dumpStates(state.parent, stack);
233
- stack.push(await dumpState(state));
234
- return stack;
235
- };
236
- const dump = {
237
- status: this.status,
238
- event: this.event,
239
- stack: await dumpStates(this.state)
240
- };
241
- return dump;
242
- }
243
- async restore(dump, ...args) {
244
- this.status = dump.status || 0;
245
- this.event = dump.event;
246
- this.state = void 0;
247
- for (let i = 0; i < dump.stack.length; i++) {
248
- const stateDump = dump.stack[i];
249
- this.state = this.state ? this._newSubstate(this.state, stateDump.key) : this._newState(void 0, stateDump.key, this.rootDescriptor);
250
- await this.state._runHandler(
251
- "restore",
252
- this.state,
253
- stateDump.data,
254
- ...args
255
- );
256
- }
257
- return this;
258
- }
259
- onStateCreate(handler) {
260
- return this._addHandler("onStateCreate", handler, true);
261
- }
262
- onStateError(handler) {
263
- return this._addHandler("onStateError", handler);
264
- }
265
- async _handleStateError(state, error) {
266
- await this._runHandler("onStateError", state, error);
267
- this._handleError(error);
268
- }
269
- _newState(parent, key, descriptor) {
270
- const state = new FsmState(this, parent, key, descriptor);
271
- this._runHandlerParallel("onStateCreate", state);
272
- return state;
273
- }
274
- _getSubstate(parent, prevStateKey) {
275
- if (!parent) return;
276
- const toState = parent.descriptor?.getTargetStateKey(
277
- prevStateKey || STATE_INITIAL,
278
- this.event || EVENT_EMPTY
279
- ) || STATE_FINAL;
280
- if (!toState) return;
281
- return this._newSubstate(parent, toState);
282
- }
283
- _newSubstate(parent, toState) {
284
- let descriptor;
285
- for (let state = parent; !descriptor && state; state = state.parent) {
286
- descriptor = state.descriptor?.states[toState];
287
- }
288
- return this._newState(parent, toState, descriptor);
289
- }
290
- _update() {
291
- if (this.status & STATUS_FINISHED) return false;
292
- const nextState = this.status !== STATUS_NONE ? this.status & STATUS_ENTER ? this._getSubstate(this.state, STATE_INITIAL) : this._getSubstate(this.state?.parent, this.state?.key) : this._newState(void 0, this.config.key, this.rootDescriptor);
293
- if (nextState !== void 0) {
294
- this.state = nextState;
295
- this.status = this.status & STATUS_EXIT ? STATUS_NEXT : STATUS_FIRST;
296
- } else {
297
- if (this.status & STATUS_EXIT) {
298
- this.state = this.state?.parent;
299
- this.status = STATUS_LAST;
300
- } else {
301
- this.status = STATUS_LEAF;
302
- }
303
- if (!this.state) this.status = STATUS_FINISHED;
304
- }
305
- return !(this.status & STATUS_FINISHED);
306
- }
307
- };
308
-
309
- // src/utils/transitions.ts
310
- function isStateTransitionEnabled(process2, event) {
311
- const transitions = getStateTransitions(process2.state);
312
- let active = false;
313
- for (const [from, ev, to] of transitions) {
314
- if (ev === event) {
315
- active = true;
316
- break;
317
- }
318
- }
319
- return active;
320
- }
321
- function getStateTransitions(state) {
322
- const result = [];
323
- const index = {};
324
- if (state) {
325
- let prevStateKey = state.key;
326
- for (let parent = state?.parent; parent; parent = parent.parent) {
327
- if (!parent.descriptor) continue;
328
- result.push(
329
- ...getTransitionsFromDescriptor(parent.descriptor, prevStateKey, index)
330
- );
331
- prevStateKey = parent.key;
332
- }
333
- }
334
- return result.reverse();
335
- }
336
- function getTransitionsFromDescriptor(descriptor, prevStateKey, index = {}) {
337
- const result = [];
338
- const prevStateKeys = [prevStateKey, "*"];
339
- for (const prevKey of prevStateKeys) {
340
- const targets = descriptor.transitions[prevKey];
341
- if (targets) {
342
- for (const [event, target] of Object.entries(targets)) {
343
- if (index[event]) continue;
344
- if (target) {
345
- index[event] = true;
346
- }
347
- result.push([prevStateKey, event, target]);
348
- }
349
- }
350
- }
351
- return result;
352
- }
353
-
354
- // src/core/new-fsm-process.ts
355
- function newFsmProcess(context, config, load) {
356
- let started = false;
357
- let terminated = false;
358
- const process2 = new FsmProcess(config);
359
- async function dispatch(event) {
360
- return terminated || event !== void 0 && (!started || isStateTransitionEnabled(process2, event)) ? process2.dispatch(event) : false;
361
- }
362
- process2.onStateCreate((state) => {
363
- started = true;
364
- state.onEnter(async () => {
365
- const modules = await load(state.key, process2.event) ?? [];
366
- for (const module of Array.isArray(modules) ? modules : [modules]) {
367
- const result = await module?.(context);
368
- if (isGenerator2(result)) {
369
- state.onExit(() => {
370
- result.return?.(void 0);
371
- });
372
- (async () => {
373
- for await (const event of result) {
374
- if (terminated) {
375
- break;
376
- }
377
- await dispatch(event);
378
- if (terminated) {
379
- break;
380
- }
381
- }
382
- })();
383
- } else if (typeof result === "function") {
384
- state.onExit(result);
385
- }
386
- }
387
- });
388
- });
389
- async function shutdown() {
390
- await process2.shutdown();
391
- terminated = true;
392
- }
393
- return [dispatch, shutdown];
394
- function isGenerator2(value) {
395
- return typeof value === "object" && value !== null && "next" in value && typeof value.next === "function";
396
- }
397
- }
398
-
399
- // src/orchestrator/constants.ts
400
- var KEY_DISPATCH = "fsm:dispatch";
401
- var KEY_TERMINATE = "fsm:terminate";
402
- var KEY_STATES = "fsm:states";
403
- var KEY_EVENT = "fsm:event";
404
- var KEY_REGISTER_CONFIG = "fsm:sys:registerConfig";
405
- var KEY_REGISTER_HANDLERS = "fsm:sys:registerHandlers";
406
- var KEY_LAUNCH_PROCESS = "fsm:sys:launch";
407
-
408
- // src/orchestrator/types.ts
409
- function toStageHandlers(value, accept) {
410
- return visit(value);
411
- function visit(val) {
412
- if (!val) {
413
- return [];
414
- }
415
- if (typeof val === "function") {
416
- return [val];
417
- }
418
- if (typeof val !== "object") {
419
- return [];
420
- }
421
- if (Array.isArray(val)) {
422
- return val.flatMap(visit);
423
- }
424
- const modulesIndex = val;
425
- return Object.entries(modulesIndex).flatMap(([key, value2]) => {
426
- return accept(key, value2) ? visit(value2) : [];
427
- });
428
- }
429
- }
430
-
431
- // src/orchestrator/process-config-manager.ts
432
- var ProcessConfigManager = class {
433
- constructor() {
434
- this.configs = {};
435
- this.handlers = {};
436
- }
437
- getProcessConfig(processName) {
438
- return this.configs[processName] ?? { key: "Main" };
439
- }
440
- getHandlersLoader(processName) {
441
- const config = this.getProcessConfig(processName);
442
- return (stateKey) => {
443
- const modulesKeys = [];
444
- if (stateKey === config.key) {
445
- modulesKeys.push("default");
446
- }
447
- modulesKeys.push(
448
- stateKey,
449
- `${stateKey}Controller`,
450
- `${stateKey}StateController`,
451
- `${stateKey}View`,
452
- `${stateKey}StateView`,
453
- `${stateKey}Trigger`,
454
- `${stateKey}StateTrigger`,
455
- `${stateKey}Test`,
456
- `${stateKey}StateTest`
457
- );
458
- const keysSet = new Set(modulesKeys);
459
- const processHandlers = this.handlers[processName] ?? [];
460
- const handlers = toStageHandlers(
461
- processHandlers,
462
- (key) => keysSet.has(key)
463
- );
464
- return handlers;
465
- };
466
- }
467
- registerConfig(name, config) {
468
- this.configs[name] = config;
469
- return () => {
470
- delete this.configs[name];
471
- };
472
- }
473
- registerHandlers(name, ...modules) {
474
- let list = this.handlers[name];
475
- if (!list) {
476
- list = this.handlers[name] = [];
477
- }
478
- list.push(modules);
479
- return () => {
480
- list = list.filter((v) => v !== modules);
481
- if (list.length === 0) {
482
- delete this.handlers[name];
483
- }
484
- };
485
- }
486
- };
487
-
488
- // src/utils/printer.ts
489
- var KEY_PRINTER = "printer";
490
- function preparePrinter(process2, { prefix = "", print = console.log, lineNumbers = false }) {
491
- let lineCounter = 0;
492
- const shift = () => {
493
- let prefix2 = "";
494
- for (let s = process2.state?.parent; s; s = s.parent) {
495
- prefix2 += " ";
496
- }
497
- return prefix2;
498
- };
499
- const getPrefix = lineNumbers ? () => `[${++lineCounter}]${shift()}` : shift;
500
- const printer = (...args) => print(prefix, getPrefix(), ...args);
501
- return printer;
502
- }
503
- function setPrinter(state, config = {}) {
504
- const printer = preparePrinter(state.process, config);
505
- state.setData(KEY_PRINTER, printer);
506
- }
507
- function setProcessPrinter(process2, config = {}) {
508
- const printer = preparePrinter(process2, config);
509
- process2.setData(KEY_PRINTER, printer);
510
- }
511
- function getProcessPrinter(process2) {
512
- return process2.getData(KEY_PRINTER) || console.log;
1
+ import { A as bindMethods, C as EVENT_ANY, D as STATE_INITIAL, E as STATE_FINAL, O as FsmState, S as FsmStateDescriptor, T as STATE_ANY, _ as STATUS_FIRST, a as KEY_STATES, b as STATUS_NEXT, c as isStateTransitionEnabled, d as createHandlerRegistry, f as toStageHandlers, g as STATUS_FINISHED, h as STATUS_EXIT, i as KEY_EVENT, k as FsmBaseClass, l as startFsmProcess, m as STATUS_ENTER, n as launcher, o as KEY_TERMINATE, p as FsmProcess, r as KEY_DISPATCH, s as getStateTransitions, t as KEY_LAUNCH_PROCESS, u as startProcess, v as STATUS_LAST, w as EVENT_EMPTY, x as STATUS_NONE, y as STATUS_LEAF } from "./launcher-CASrMAOa.js";
2
+ //#region src/utils/printer.ts
3
+ const printerStore = /* @__PURE__ */ new WeakMap();
4
+ function preparePrinter(process, { prefix = "", print = console.log, lineNumbers = false }) {
5
+ let lineCounter = 0;
6
+ const shift = () => {
7
+ let prefix = "";
8
+ for (let s = process.state?.parent; s; s = s.parent) prefix += " ";
9
+ return prefix;
10
+ };
11
+ const getPrefix = lineNumbers ? () => `[${++lineCounter}]${shift()}` : shift;
12
+ const printer = (...args) => print(prefix, getPrefix(), ...args);
13
+ return printer;
14
+ }
15
+ function setProcessPrinter(process, config = {}) {
16
+ const printer = preparePrinter(process, config);
17
+ printerStore.set(process, printer);
18
+ }
19
+ function getProcessPrinter(process) {
20
+ return printerStore.get(process) || console.log;
513
21
  }
514
22
  function getPrinter(state) {
515
- return state.getData(KEY_PRINTER, true) || getProcessPrinter(state.process);
23
+ return printerStore.get(state) || getProcessPrinter(state.process);
516
24
  }
517
-
518
- // src/utils/tracer.ts
519
- function setProcessTracer(process2, print) {
520
- return process2.onStateCreate((state) => {
521
- setStateTracer(state, print);
522
- });
25
+ //#endregion
26
+ //#region src/utils/tracer.ts
27
+ function setProcessTracer(process, print) {
28
+ return process.onStateCreate((state) => {
29
+ setStateTracer(state, print);
30
+ });
523
31
  }
524
32
  function setStateTracer(state, print) {
525
- state.onEnter(() => {
526
- const printLine = print || getPrinter(state);
527
- printLine(`<${state?.key} event="${state.process.event}">`);
528
- });
529
- state.onExit(async () => {
530
- await Promise.resolve().then(async () => {
531
- const printLine = print || getPrinter(state);
532
- printLine(`</${state.key}> <!-- event="${state.process.event}" -->`);
533
- });
534
- });
535
- }
536
-
537
- // src/utils/process.ts
538
- function newProcess(config, {
539
- prefix,
540
- print,
541
- lineNumbers = true
542
- }) {
543
- const process2 = new FsmProcess(config);
544
- setProcessPrinter(process2, {
545
- prefix,
546
- print,
547
- lineNumbers
548
- });
549
- setProcessTracer(process2);
550
- return process2;
551
- }
552
-
553
- // src/orchestrator/is-generator.ts
554
- function isGenerator(value) {
555
- return typeof value === "object" && value !== null && "next" in value && typeof value.next === "function";
556
- }
557
-
558
- // src/orchestrator/start-process.ts
559
- async function startFsmProcess(context, config, load, startEvent = "") {
560
- let terminated = false;
561
- const ctx = context;
562
- const process2 = new FsmProcess(config);
563
- const statesStack = [];
564
- process2.onStateCreate((state) => {
565
- state.onEnter(async () => {
566
- statesStack.push(state.key);
567
- ctx[KEY_STATES] = [...statesStack];
568
- ctx[KEY_EVENT] = process2.event;
569
- const modules = await load(state.key, process2.event) ?? [];
570
- for (const module of Array.isArray(modules) ? modules : [modules]) {
571
- const result = await module?.(context);
572
- if (isGenerator(result)) {
573
- let stateExited = false;
574
- state.onExit(() => {
575
- stateExited = true;
576
- result.return?.(void 0);
577
- });
578
- (async () => {
579
- for await (const event of result) {
580
- if (stateExited || terminated) {
581
- break;
582
- }
583
- await dispatch(event);
584
- }
585
- })();
586
- } else if (typeof result === "function") {
587
- state.onExit(result);
588
- }
589
- }
590
- });
591
- state.onExit(() => {
592
- statesStack.pop();
593
- ctx[KEY_STATES] = [...statesStack];
594
- ctx[KEY_EVENT] = process2.event;
595
- });
596
- });
597
- async function terminate() {
598
- terminated = true;
599
- await process2.shutdown();
600
- }
601
- async function dispatch(event) {
602
- if (event !== void 0 && isStateTransitionEnabled(process2, event)) {
603
- await process2.dispatch(event);
604
- }
605
- }
606
- ctx[KEY_DISPATCH] = dispatch;
607
- ctx[KEY_TERMINATE] = terminate;
608
- await process2.dispatch(startEvent);
609
- return terminate;
610
- }
611
-
612
- // src/orchestrator/launcher.ts
613
- function asArray(value, filter = (v) => v) {
614
- if (value === void 0) return [];
615
- const array = Array.isArray(value) ? value : [value];
616
- return array.filter(Boolean).map(filter).filter(Boolean);
617
- }
618
- async function launcher(options) {
619
- const configsManager = new ProcessConfigManager();
620
- async function launch(processName, context, startEvent = "start") {
621
- const config2 = configsManager.getProcessConfig(processName);
622
- const load = configsManager.getHandlersLoader(processName);
623
- return startFsmProcess(context, config2, load, startEvent);
624
- }
625
- function registerProcess(configsManager2, process2) {
626
- if (!process2 || typeof process2 !== "object") {
627
- throw new Error("Invalid process configuration: not an object");
628
- }
629
- const processName = process2.name;
630
- if (!processName || typeof processName !== "string") {
631
- throw new Error("Invalid process configuration: missing or invalid name");
632
- }
633
- const processConfig = process2.config;
634
- if (processConfig && typeof processConfig !== "object") {
635
- throw new Error(
636
- `Invalid process configuration: config is not an object in process ${process2.name}`
637
- );
638
- }
639
- if (processConfig) {
640
- configsManager2.registerConfig(processName, processConfig);
641
- }
642
- const processHandlers = asArray(
643
- process2.handlers ?? process2.handler ?? process2.default,
644
- (v, idx) => {
645
- if (typeof v === "function") return v;
646
- if (typeof v === "object" && v !== null) return v;
647
- throw new Error(
648
- [
649
- `Invalid process configuration:`,
650
- `a process handler is not object nor function in process ${processName} at index ${idx}`,
651
- `Recieved: ${v === null ? "null" : typeof v}`
652
- ].join("\n")
653
- );
654
- }
655
- );
656
- if (processHandlers.length > 0) {
657
- configsManager2.registerHandlers(processName, ...processHandlers);
658
- }
659
- }
660
- const rootContext = { "fsm:launch": launch };
661
- const init = typeof options === "function" ? options : async () => options;
662
- const config = await init(rootContext);
663
- if (typeof config !== "object" || !config) {
664
- throw new Error("Invalid launcher configuration");
665
- }
666
- const processes = asArray(
667
- config.processes ?? config.process ?? config.default,
668
- (v) => {
669
- if (typeof v === "function") {
670
- return {
671
- name: v.name || "",
672
- handler: v
673
- };
674
- }
675
- if (typeof v !== "object") {
676
- throw new Error(
677
- "Invalid launcher configuration: process is not an object"
678
- );
679
- }
680
- return v;
681
- }
682
- );
683
- const processesToStart = {};
684
- for (const process2 of processes) {
685
- const processName = process2.name;
686
- const start = process2.start;
687
- if (start === void 0) {
688
- if (!(processName in processesToStart)) {
689
- processesToStart[processName] = void 0;
690
- }
691
- } else {
692
- processesToStart[processName] = start;
693
- }
694
- registerProcess(configsManager, process2);
695
- }
696
- const shutdowns = [];
697
- let initContext = (context) => context;
698
- const configContext = config.context ?? config.init;
699
- if (configContext) {
700
- if (typeof configContext === "function") {
701
- initContext = configContext;
702
- } else if (typeof configContext === "object") {
703
- initContext = () => ({ parent: configContext });
704
- } else {
705
- throw new Error("Invalid launcher configuration: context");
706
- }
707
- }
708
- for (const [processName, start] of Object.entries(processesToStart)) {
709
- if (start === false) continue;
710
- let context = {
711
- parent: rootContext,
712
- "fsm:name": processName
713
- };
714
- context = initContext(context) ?? context;
715
- if (typeof context !== "object") {
716
- throw new Error(
717
- `Invalid launcher context for process "${processName}". Expected an object, but recieved ${typeof context}.`
718
- );
719
- }
720
- const shutdown = await launch(processName, context);
721
- shutdowns.push(shutdown);
722
- }
723
- return async () => {
724
- for (const shutdown of shutdowns) {
725
- await shutdown();
726
- }
727
- };
728
- }
729
-
730
- // src/orchestrator/resolve-module-refs.ts
731
- function resolveModulesUrls(baseUrl, ...refs) {
732
- return refs.map((ref) => new URL(ref, baseUrl).href);
733
- }
734
- function resolveModulesPaths(baseUrl, ...refs) {
735
- return refs.map((ref) => new URL(ref, baseUrl).pathname);
736
- }
737
-
738
- // src/orchestrator/start-processes.ts
739
- async function startProcesses({
740
- onExit,
741
- modules,
742
- init
743
- }) {
744
- const modulesList = [];
745
- for (const module of modules) {
746
- modulesList.push(
747
- typeof module === "string" || module instanceof URL ? await import(String(module)) : module
748
- );
749
- }
750
- return await launcher({
751
- init,
752
- processes: [
753
- ...modulesList,
754
- // This function is called on exit at the end of the process chain
755
- function Exit() {
756
- return onExit;
757
- }
758
- ]
759
- });
760
- }
761
-
762
- // src/orchestrator/start-node-processes.ts
763
- async function startNodeProcesses(modules) {
764
- try {
765
- if (!modules) {
766
- modules = process.argv.slice(2);
767
- }
768
- const terminate = await startProcesses({
769
- modules: resolveModulesPaths(`file://${process.cwd()}/`, ...modules),
770
- onExit: () => process.exit(0)
771
- });
772
- process.on("SIGINT", terminate);
773
- process.on("SIGTERM", terminate);
774
- process.stdin.resume();
775
- } catch (err) {
776
- console.error("Fatal error:", err);
777
- process.exit(1);
778
- }
779
- }
780
-
781
- // src/index.ts
782
- var index_default = startNodeProcesses;
33
+ state.onEnter(() => {
34
+ (print || getPrinter(state))(`<${state?.key} event="${state.process.event}">`);
35
+ });
36
+ state.onExit(async () => {
37
+ await Promise.resolve().then(async () => {
38
+ (print || getPrinter(state))(`</${state.key}> <!-- event="${state.process.event}" -->`);
39
+ });
40
+ });
41
+ }
42
+ //#endregion
43
+ export { EVENT_ANY, EVENT_EMPTY, FsmBaseClass, FsmProcess, FsmState, FsmStateDescriptor, KEY_DISPATCH, KEY_EVENT, KEY_LAUNCH_PROCESS, KEY_STATES, KEY_TERMINATE, STATE_ANY, STATE_FINAL, STATE_INITIAL, STATUS_ENTER, STATUS_EXIT, STATUS_FINISHED, STATUS_FIRST, STATUS_LAST, STATUS_LEAF, STATUS_NEXT, STATUS_NONE, bindMethods, createHandlerRegistry, getPrinter, getProcessPrinter, getStateTransitions, isStateTransitionEnabled, launcher, preparePrinter, setProcessPrinter, setProcessTracer, setStateTracer, startFsmProcess, startProcess, toStageHandlers };
783
44
 
784
- export { EVENT_ANY, EVENT_EMPTY, FsmProcess, FsmState, FsmStateDescriptor, KEY_DISPATCH, KEY_EVENT, KEY_LAUNCH_PROCESS, KEY_PRINTER, KEY_REGISTER_CONFIG, KEY_REGISTER_HANDLERS, KEY_STATES, KEY_TERMINATE, ProcessConfigManager, STATE_ANY, STATE_FINAL, STATE_INITIAL, STATUS_ENTER, STATUS_EXIT, STATUS_FINISHED, STATUS_FIRST, STATUS_LAST, STATUS_LEAF, STATUS_NEXT, STATUS_NONE, index_default as default, getPrinter, getProcessPrinter, getStateTransitions, isStateTransitionEnabled, launcher, newFsmProcess, newProcess, preparePrinter, resolveModulesPaths, resolveModulesUrls, setPrinter, setProcessPrinter, setProcessTracer, setStateTracer, startFsmProcess, startNodeProcesses, startProcesses, toStageHandlers };
785
- //# sourceMappingURL=index.js.map
786
45
  //# sourceMappingURL=index.js.map