@statewalker/fsm 0.31.0 → 0.32.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
@@ -227,10 +227,17 @@ declare function toStageHandlers<C>(value: unknown, accept: (key: string, value:
227
227
  type ProcessConfig = {
228
228
  name: string;
229
229
  config?: FsmStateConfig;
230
- handlers?: (StageHandler | {
230
+ } & ({
231
+ handler?: StageHandler;
232
+ } | {
233
+ handlers?: StageHandler | (StageHandler | {
231
234
  [state: string]: StageHandler | StageHandler[];
232
235
  })[];
233
- };
236
+ } | {
237
+ default?: StageHandler | (StageHandler | {
238
+ [state: string]: StageHandler | StageHandler[];
239
+ })[];
240
+ });
234
241
  declare function launcher(options: unknown): Promise<() => Promise<void>>;
235
242
 
236
243
  interface IProcessConfigManager {
package/dist/index.js CHANGED
@@ -610,6 +610,11 @@ async function startFsmProcess(context, config, load, startEvent = "") {
610
610
  }
611
611
 
612
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
+ }
613
618
  async function launcher(options) {
614
619
  const configsManager = new ProcessConfigManager();
615
620
  async function launch(processName, context, startEvent = "start") {
@@ -632,17 +637,24 @@ async function launcher(options) {
632
637
  );
633
638
  }
634
639
  if (processConfig) {
635
- configsManager2.registerConfig(process.name, processConfig);
640
+ configsManager2.registerConfig(processName, processConfig);
636
641
  }
637
- let processHandlers = process.handlers;
638
- if (processHandlers) {
639
- if (typeof processHandlers !== "object") {
642
+ const processHandlers = asArray(
643
+ process.handlers ?? process.handler ?? process.default,
644
+ (v, idx) => {
645
+ if (typeof v === "function") return v;
646
+ if (typeof v === "object" && v !== null) return v;
640
647
  throw new Error(
641
- `Invalid process configuration: handlers is not an array or object in process ${process.name}`
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")
642
653
  );
643
654
  }
644
- processHandlers = Array.isArray(processHandlers) ? processHandlers : [processHandlers];
645
- configsManager2.registerHandlers(process.name, ...processHandlers);
655
+ );
656
+ if (processHandlers.length > 0) {
657
+ configsManager2.registerHandlers(processName, ...processHandlers);
646
658
  }
647
659
  }
648
660
  const rootContext = { "fsm:launch": launch };
@@ -651,16 +663,31 @@ async function launcher(options) {
651
663
  if (typeof config !== "object" || !config) {
652
664
  throw new Error("Invalid launcher configuration");
653
665
  }
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 : [];
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
+ );
659
683
  for (const process of processes) {
660
684
  registerProcess(configsManager, process);
661
685
  }
662
686
  const shutdowns = [];
663
- const startProcesses = Array.isArray(config.start) ? config.start : [];
687
+ let startProcesses = asArray(config.start);
688
+ if (startProcesses.length === 0) {
689
+ startProcesses = processes.map((p) => p.name).filter(Boolean);
690
+ }
664
691
  let initContext = (context) => context;
665
692
  const configContext = config.context ?? config.init;
666
693
  if (configContext) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@statewalker/fsm",
3
- "version": "0.31.0",
3
+ "version": "0.32.0",
4
4
  "description": "HFSM Implementation",
5
5
  "keywords": [],
6
6
  "homepage": "https://github.com/statewalker/statewalker-fsm",
@@ -6,26 +6,40 @@ import type { StageHandler } from "./types.ts";
6
6
  export type ProcessConfig = {
7
7
  name: string;
8
8
  config?: FsmStateConfig;
9
- handlers?: (
10
- | StageHandler
11
- | {
12
- [state: string]: StageHandler | StageHandler[];
13
- }
14
- )[];
15
- };
16
- // export type ProcessLauncherConfig = {
17
- // start: string[];
18
- // context?: Record<string, unknown>;
19
- // processes: ProcessConfig[];
20
- // };
9
+ } & (
10
+ | {
11
+ handler?: StageHandler;
12
+ }
13
+ | {
14
+ handlers?:
15
+ | StageHandler
16
+ | (
17
+ | StageHandler
18
+ | {
19
+ [state: string]: StageHandler | StageHandler[];
20
+ }
21
+ )[];
22
+ }
23
+ | {
24
+ default?:
25
+ | StageHandler
26
+ | (
27
+ | StageHandler
28
+ | {
29
+ [state: string]: StageHandler | StageHandler[];
30
+ }
31
+ )[];
32
+ }
33
+ );
21
34
 
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
- // };
35
+ function asArray<T>(
36
+ value: T | T[] | undefined,
37
+ filter: (v: T, idx: number) => T | undefined = (v) => v,
38
+ ): T[] {
39
+ if (value === undefined) return [];
40
+ const array = Array.isArray(value) ? value : [value];
41
+ return array.filter(Boolean).map(filter).filter(Boolean) as T[];
42
+ }
29
43
 
30
44
  export async function launcher(options: unknown) {
31
45
  const configsManager = new ProcessConfigManager();
@@ -42,7 +56,7 @@ export async function launcher(options: unknown) {
42
56
 
43
57
  function registerProcess(
44
58
  configsManager: ProcessConfigManager,
45
- process: ProcessConfig,
59
+ process: Record<string, unknown>,
46
60
  ) {
47
61
  if (!process || typeof process !== "object") {
48
62
  throw new Error("Invalid process configuration: not an object");
@@ -52,26 +66,32 @@ export async function launcher(options: unknown) {
52
66
  throw new Error("Invalid process configuration: missing or invalid name");
53
67
  }
54
68
 
55
- const processConfig = process.config;
69
+ const processConfig = process.config as FsmStateConfig | undefined;
56
70
  if (processConfig && typeof processConfig !== "object") {
57
71
  throw new Error(
58
72
  `Invalid process configuration: config is not an object in process ${process.name}`,
59
73
  );
60
74
  }
61
75
  if (processConfig) {
62
- configsManager.registerConfig(process.name, processConfig);
76
+ configsManager.registerConfig(processName, processConfig);
63
77
  }
64
- let processHandlers = process.handlers;
65
- if (processHandlers) {
66
- if (typeof processHandlers !== "object") {
78
+
79
+ const processHandlers = asArray(
80
+ process.handlers ?? process.handler ?? process.default,
81
+ (v, idx) => {
82
+ if (typeof v === "function") return v;
83
+ if (typeof v === "object" && v !== null) return v;
67
84
  throw new Error(
68
- `Invalid process configuration: handlers is not an array or object in process ${process.name}`,
85
+ [
86
+ `Invalid process configuration:`,
87
+ `a process handler is not object nor function in process ${processName} at index ${idx}`,
88
+ `Recieved: ${v === null ? "null" : typeof v}`,
89
+ ].join("\n"),
69
90
  );
70
- }
71
- processHandlers = Array.isArray(processHandlers)
72
- ? processHandlers
73
- : [processHandlers];
74
- configsManager.registerHandlers(process.name, ...processHandlers);
91
+ },
92
+ );
93
+ if (processHandlers.length > 0) {
94
+ configsManager.registerHandlers(processName, ...processHandlers);
75
95
  }
76
96
  }
77
97
 
@@ -81,21 +101,37 @@ export async function launcher(options: unknown) {
81
101
  if (typeof config !== "object" || !config) {
82
102
  throw new Error("Invalid launcher configuration");
83
103
  }
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 : [];
104
+
105
+ const processes = asArray(
106
+ config.processes ?? config.process ?? config.default,
107
+ (v) => {
108
+ if (typeof v === "function") {
109
+ return {
110
+ name: v.name || "",
111
+ handler: v,
112
+ };
113
+ }
114
+ if (typeof v !== "object") {
115
+ throw new Error(
116
+ "Invalid launcher configuration: process is not an object",
117
+ );
118
+ }
119
+ return v;
120
+ },
121
+ );
89
122
  for (const process of processes) {
90
123
  registerProcess(configsManager, process);
91
124
  }
92
125
 
93
126
  const shutdowns: (() => Promise<void>)[] = [];
94
- const startProcesses = Array.isArray(config.start) ? config.start : [];
127
+ let startProcesses = asArray<string>(config.start);
128
+ if (startProcesses.length === 0) {
129
+ startProcesses = processes.map((p) => p.name).filter(Boolean) as string[];
130
+ }
131
+
95
132
  let initContext: (
96
133
  parent: Record<string, unknown>,
97
134
  ) => Record<string, unknown> = (context) => context;
98
-
99
135
  const configContext = config.context ?? config.init;
100
136
  if (configContext) {
101
137
  if (typeof configContext === "function") {