@statewalker/fsm 0.30.1 → 0.31.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.
package/dist/index.d.ts CHANGED
@@ -231,15 +231,7 @@ type ProcessConfig = {
231
231
  [state: string]: StageHandler | StageHandler[];
232
232
  })[];
233
233
  };
234
- type ProcessLauncherConfig = {
235
- start: string[];
236
- context?: Record<string, unknown>;
237
- processes: ProcessConfig[];
238
- };
239
- type LauncherRootContext = Record<string, unknown> & {
240
- launch: (processName: string, context: Record<string, unknown>, startEvent?: string) => Promise<() => Promise<void>>;
241
- };
242
- declare function launcher(init: (root: LauncherRootContext) => ProcessLauncherConfig | Promise<ProcessLauncherConfig>): Promise<() => Promise<void>>;
234
+ declare function launcher(options: unknown): Promise<() => Promise<void>>;
243
235
 
244
236
  interface IProcessConfigManager {
245
237
  getProcessConfig(processName: string): FsmStateConfig;
@@ -283,4 +275,4 @@ declare function setStateTracer(state: FsmState, print?: Printer): void;
283
275
  declare function isStateTransitionEnabled(process: FsmProcess, event: string): boolean;
284
276
  declare function getStateTransitions(state?: FsmState): [from: string, event: string, to: string][];
285
277
 
286
- export { EVENT_ANY, EVENT_EMPTY, type FsmEventKey, FsmProcess, type FsmProcessDump, type FsmProcessDumpHandler, type FsmProcessHandler, FsmState, type FsmStateConfig, FsmStateDescriptor, type FsmStateDump, type FsmStateDumpHandler, type FsmStateErrorHandler, type FsmStateHandler, type FsmStateKey, type IProcessConfigManager, KEY_DISPATCH, KEY_EVENT, KEY_LAUNCH_PROCESS, KEY_PRINTER, KEY_REGISTER_CONFIG, KEY_REGISTER_HANDLERS, KEY_STATES, KEY_TERMINATE, type LauncherRootContext, type Module, type Printer, type PrinterConfig, type ProcessConfig, ProcessConfigManager, type ProcessLauncherConfig, STATE_ANY, STATE_FINAL, STATE_INITIAL, STATUS_ENTER, STATUS_EXIT, STATUS_FINISHED, STATUS_FIRST, STATUS_LAST, STATUS_LEAF, STATUS_NEXT, STATUS_NONE, type StageHandler, getPrinter, getProcessPrinter, getStateTransitions, isStateTransitionEnabled, launcher, newFsmProcess, newProcess, preparePrinter, setPrinter, setProcessPrinter, setProcessTracer, setStateTracer, startFsmProcess, toStageHandlers };
278
+ export { EVENT_ANY, EVENT_EMPTY, type FsmEventKey, FsmProcess, type FsmProcessDump, type FsmProcessDumpHandler, type FsmProcessHandler, FsmState, type FsmStateConfig, FsmStateDescriptor, type FsmStateDump, type FsmStateDumpHandler, type FsmStateErrorHandler, type FsmStateHandler, type FsmStateKey, type IProcessConfigManager, KEY_DISPATCH, KEY_EVENT, KEY_LAUNCH_PROCESS, KEY_PRINTER, KEY_REGISTER_CONFIG, KEY_REGISTER_HANDLERS, KEY_STATES, KEY_TERMINATE, type Module, type Printer, type PrinterConfig, type ProcessConfig, ProcessConfigManager, STATE_ANY, STATE_FINAL, STATE_INITIAL, STATUS_ENTER, STATUS_EXIT, STATUS_FINISHED, STATUS_FIRST, STATUS_LAST, STATUS_LEAF, STATUS_NEXT, STATUS_NONE, type StageHandler, getPrinter, getProcessPrinter, getStateTransitions, isStateTransitionEnabled, launcher, newFsmProcess, newProcess, preparePrinter, setPrinter, setProcessPrinter, setProcessTracer, setStateTracer, startFsmProcess, toStageHandlers };
package/dist/index.js CHANGED
@@ -610,29 +610,79 @@ async function startFsmProcess(context, config, load, startEvent = "") {
610
610
  }
611
611
 
612
612
  // src/orchestrator/launcher.ts
613
- async function launcher(init) {
613
+ async function launcher(options) {
614
614
  const configsManager = new ProcessConfigManager();
615
615
  async function launch(processName, context, startEvent = "start") {
616
616
  const config2 = configsManager.getProcessConfig(processName);
617
617
  const load = configsManager.getHandlersLoader(processName);
618
618
  return startFsmProcess(context, config2, load, startEvent);
619
619
  }
620
- const rootContext = {
621
- launch
622
- };
623
- const config = await init(rootContext);
624
- for (const process of config.processes) {
625
- if (process.config) {
626
- configsManager.registerConfig(process.name, process.config);
620
+ function registerProcess(configsManager2, process) {
621
+ if (!process || typeof process !== "object") {
622
+ throw new Error("Invalid process configuration: not an object");
623
+ }
624
+ const processName = process.name;
625
+ if (!processName || typeof processName !== "string") {
626
+ throw new Error("Invalid process configuration: missing or invalid name");
627
+ }
628
+ const processConfig = process.config;
629
+ if (processConfig && typeof processConfig !== "object") {
630
+ throw new Error(
631
+ `Invalid process configuration: config is not an object in process ${process.name}`
632
+ );
627
633
  }
628
- if (process.handlers) {
629
- configsManager.registerHandlers(process.name, ...process.handlers);
634
+ if (processConfig) {
635
+ configsManager2.registerConfig(process.name, processConfig);
630
636
  }
637
+ let processHandlers = process.handlers;
638
+ if (processHandlers) {
639
+ if (typeof processHandlers !== "object") {
640
+ throw new Error(
641
+ `Invalid process configuration: handlers is not an array or object in process ${process.name}`
642
+ );
643
+ }
644
+ processHandlers = Array.isArray(processHandlers) ? processHandlers : [processHandlers];
645
+ configsManager2.registerHandlers(process.name, ...processHandlers);
646
+ }
647
+ }
648
+ const rootContext = { "fsm:launch": launch };
649
+ const init = typeof options === "function" ? options : async () => options;
650
+ const config = await init(rootContext);
651
+ if (typeof config !== "object" || !config) {
652
+ throw new Error("Invalid launcher configuration");
653
+ }
654
+ let processes = config.processes ?? config.default;
655
+ if (!processes || typeof processes !== "object") {
656
+ throw new Error("Invalid launcher configuration: missing processes");
657
+ }
658
+ processes = Array.isArray(processes) ? processes : [];
659
+ for (const process of processes) {
660
+ registerProcess(configsManager, process);
631
661
  }
632
662
  const shutdowns = [];
633
- for (const processName of config.start ?? []) {
634
- const parent = config.context ?? rootContext;
635
- const context = { parent };
663
+ const startProcesses = Array.isArray(config.start) ? config.start : [];
664
+ let initContext = (context) => context;
665
+ const configContext = config.context ?? config.init;
666
+ if (configContext) {
667
+ if (typeof configContext === "function") {
668
+ initContext = configContext;
669
+ } else if (typeof configContext === "object") {
670
+ initContext = () => ({ parent: configContext });
671
+ } else {
672
+ throw new Error("Invalid launcher configuration: context");
673
+ }
674
+ }
675
+ for (const processName of startProcesses) {
676
+ let context = {
677
+ parent: rootContext,
678
+ "fsm:name": processName
679
+ };
680
+ context = initContext(context) ?? context;
681
+ if (typeof context !== "object") {
682
+ throw new Error(
683
+ `Invalid launcher context for process "${processName}". Expected an object, but recieved ${typeof context}.`
684
+ );
685
+ }
636
686
  const shutdown = await launch(processName, context);
637
687
  shutdowns.push(shutdown);
638
688
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@statewalker/fsm",
3
- "version": "0.30.1",
3
+ "version": "0.31.0",
4
4
  "description": "HFSM Implementation",
5
5
  "keywords": [],
6
6
  "homepage": "https://github.com/statewalker/statewalker-fsm",
@@ -13,24 +13,21 @@ export type ProcessConfig = {
13
13
  }
14
14
  )[];
15
15
  };
16
- export type ProcessLauncherConfig = {
17
- start: string[];
18
- context?: Record<string, unknown>;
19
- processes: ProcessConfig[];
20
- };
16
+ // export type ProcessLauncherConfig = {
17
+ // start: string[];
18
+ // context?: Record<string, unknown>;
19
+ // processes: ProcessConfig[];
20
+ // };
21
21
 
22
- export type LauncherRootContext = Record<string, unknown> & {
23
- launch: (
24
- processName: string,
25
- context: Record<string, unknown>,
26
- startEvent?: string,
27
- ) => Promise<() => Promise<void>>;
28
- };
29
- export async function launcher(
30
- init: (
31
- root: LauncherRootContext,
32
- ) => ProcessLauncherConfig | Promise<ProcessLauncherConfig>,
33
- ) {
22
+ // export type LauncherRootContext = Record<string, unknown> & {
23
+ // launch: (
24
+ // processName: string,
25
+ // context: Record<string, unknown>,
26
+ // startEvent?: string,
27
+ // ) => Promise<() => Promise<void>>;
28
+ // };
29
+
30
+ export async function launcher(options: unknown) {
34
31
  const configsManager = new ProcessConfigManager();
35
32
 
36
33
  async function launch(
@@ -43,23 +40,83 @@ export async function launcher(
43
40
  return startFsmProcess(context, config, load, startEvent);
44
41
  }
45
42
 
46
- const rootContext: LauncherRootContext = {
47
- launch,
48
- };
49
- const config = await init(rootContext);
50
- for (const process of config.processes) {
51
- if (process.config) {
52
- configsManager.registerConfig(process.name, process.config);
43
+ function registerProcess(
44
+ configsManager: ProcessConfigManager,
45
+ process: ProcessConfig,
46
+ ) {
47
+ if (!process || typeof process !== "object") {
48
+ throw new Error("Invalid process configuration: not an object");
49
+ }
50
+ const processName = process.name;
51
+ if (!processName || typeof processName !== "string") {
52
+ throw new Error("Invalid process configuration: missing or invalid name");
53
+ }
54
+
55
+ const processConfig = process.config;
56
+ if (processConfig && typeof processConfig !== "object") {
57
+ throw new Error(
58
+ `Invalid process configuration: config is not an object in process ${process.name}`,
59
+ );
53
60
  }
54
- if (process.handlers) {
55
- configsManager.registerHandlers(process.name, ...process.handlers);
61
+ if (processConfig) {
62
+ configsManager.registerConfig(process.name, processConfig);
63
+ }
64
+ let processHandlers = process.handlers;
65
+ if (processHandlers) {
66
+ if (typeof processHandlers !== "object") {
67
+ throw new Error(
68
+ `Invalid process configuration: handlers is not an array or object in process ${process.name}`,
69
+ );
70
+ }
71
+ processHandlers = Array.isArray(processHandlers)
72
+ ? processHandlers
73
+ : [processHandlers];
74
+ configsManager.registerHandlers(process.name, ...processHandlers);
56
75
  }
57
76
  }
58
77
 
78
+ const rootContext = { "fsm:launch": launch };
79
+ const init = typeof options === "function" ? options : async () => options;
80
+ const config = await init(rootContext);
81
+ if (typeof config !== "object" || !config) {
82
+ throw new Error("Invalid launcher configuration");
83
+ }
84
+ let processes = config.processes ?? config.default;
85
+ if (!processes || typeof processes !== "object") {
86
+ throw new Error("Invalid launcher configuration: missing processes");
87
+ }
88
+ processes = Array.isArray(processes) ? processes : [];
89
+ for (const process of processes) {
90
+ registerProcess(configsManager, process);
91
+ }
92
+
59
93
  const shutdowns: (() => Promise<void>)[] = [];
60
- for (const processName of config.start ?? []) {
61
- const parent = config.context ?? rootContext;
62
- const context = { parent };
94
+ const startProcesses = Array.isArray(config.start) ? config.start : [];
95
+ let initContext: (
96
+ parent: Record<string, unknown>,
97
+ ) => Record<string, unknown> = (context) => context;
98
+
99
+ const configContext = config.context ?? config.init;
100
+ if (configContext) {
101
+ if (typeof configContext === "function") {
102
+ initContext = configContext;
103
+ } else if (typeof configContext === "object") {
104
+ initContext = () => ({ parent: configContext });
105
+ } else {
106
+ throw new Error("Invalid launcher configuration: context");
107
+ }
108
+ }
109
+ for (const processName of startProcesses) {
110
+ let context: Record<string, unknown> = {
111
+ parent: rootContext,
112
+ "fsm:name": processName,
113
+ };
114
+ context = initContext(context) ?? context;
115
+ if (typeof context !== "object") {
116
+ throw new Error(
117
+ `Invalid launcher context for process "${processName}". Expected an object, but recieved ${typeof context}.`,
118
+ );
119
+ }
63
120
  const shutdown = await launch(processName, context);
64
121
  shutdowns.push(shutdown);
65
122
  }