@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.
- package/README.md +112 -0
- package/bin/cli.js +1 -1
- package/dist/bin/node-runner-UJp8T_oP.d.ts +16 -0
- package/dist/bin/node-runner-UJp8T_oP.d.ts.map +1 -0
- package/dist/bin/node-runner.js +40 -0
- package/dist/bin/node-runner.js.map +1 -0
- package/dist/index-vTjnkbGW.d.ts +129 -0
- package/dist/index-vTjnkbGW.d.ts.map +1 -0
- package/dist/index.js +38 -779
- package/dist/index.js.map +1 -1
- package/dist/launcher-6VUDviTj.d.ts +48 -0
- package/dist/launcher-6VUDviTj.d.ts.map +1 -0
- package/dist/launcher-CASrMAOa.js +443 -0
- package/dist/launcher-CASrMAOa.js.map +1 -0
- package/package.json +8 -8
- package/src/bin/node-runner.ts +57 -0
- package/src/core/fsm-base-class.ts +1 -26
- package/src/core/fsm-process.ts +14 -11
- package/src/core/fsm-state.ts +1 -21
- package/src/core/index.ts +1 -1
- package/src/index.ts +0 -3
- package/src/orchestrator/handler-registry.ts +108 -0
- package/src/orchestrator/index.ts +15 -9
- package/src/orchestrator/launcher.ts +42 -141
- package/src/orchestrator/start-process.ts +141 -26
- package/src/utils/index.ts +0 -2
- package/src/utils/printer.ts +5 -11
- package/src/utils/tracer.ts +1 -1
- package/CHANGELOG.md +0 -59
- package/dist/index.d.ts +0 -335
- package/src/core/new-fsm-process.ts +0 -83
- package/src/orchestrator/constants.ts +0 -130
- package/src/orchestrator/is-generator.ts +0 -12
- package/src/orchestrator/process-config-manager.ts +0 -70
- package/src/orchestrator/resolve-module-refs.ts +0 -52
- package/src/orchestrator/start-node-processes.ts +0 -19
- package/src/orchestrator/start-processes.ts +0 -32
- package/src/orchestrator/types.ts +0 -34
- package/src/utils/handlers.ts +0 -35
- package/src/utils/process.ts +0 -26
- package/src/utils/transitions.ts +0 -56
package/dist/index.d.ts
DELETED
|
@@ -1,335 +0,0 @@
|
|
|
1
|
-
type Handler<P extends unknown[] = unknown[], R = unknown> = (...args: P) => R;
|
|
2
|
-
declare class FsmBaseClass {
|
|
3
|
-
handlers: Record<string, Handler[]>;
|
|
4
|
-
data: Record<string, unknown>;
|
|
5
|
-
constructor();
|
|
6
|
-
setData<T>(key: string, value: T): this;
|
|
7
|
-
getData<T>(key: string): T | undefined;
|
|
8
|
-
protected _addHandler<T>(type: string, handler: T, direct?: boolean): () => void;
|
|
9
|
-
protected _removeHandler<T>(type: string, handler: T): void;
|
|
10
|
-
_runHandlerParallel(type: string, ...args: unknown[]): Promise<void>;
|
|
11
|
-
_runHandler(type: string, ...args: unknown[]): Promise<void>;
|
|
12
|
-
_handleError(error: Error | unknown): Promise<void>;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
declare const STATE_ANY = "*";
|
|
16
|
-
declare const STATE_INITIAL = "";
|
|
17
|
-
declare const STATE_FINAL = "";
|
|
18
|
-
declare const EVENT_ANY = "*";
|
|
19
|
-
declare const EVENT_EMPTY = "";
|
|
20
|
-
type FsmStateKey = string;
|
|
21
|
-
type FsmEventKey = string;
|
|
22
|
-
type FsmStateConfig = {
|
|
23
|
-
key: FsmStateKey;
|
|
24
|
-
transitions?: [from: FsmStateKey, event: FsmEventKey, to: FsmStateKey][];
|
|
25
|
-
states?: FsmStateConfig[];
|
|
26
|
-
} & Record<string, unknown>;
|
|
27
|
-
|
|
28
|
-
declare class FsmStateDescriptor {
|
|
29
|
-
transitions: Record<string, Record<string, string>>;
|
|
30
|
-
states: Record<string, FsmStateDescriptor>;
|
|
31
|
-
static build(config: FsmStateConfig): FsmStateDescriptor;
|
|
32
|
-
getTargetStateKey(stateKey: string, eventKey: string): string;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
type FsmStateDump = Record<string, unknown> & {
|
|
36
|
-
key: string;
|
|
37
|
-
data: Record<string, unknown>;
|
|
38
|
-
};
|
|
39
|
-
type FsmStateHandler = (state: FsmState, ...args: unknown[]) => void | Promise<void>;
|
|
40
|
-
type FsmStateDumpHandler = (state: FsmState, dump: FsmStateDump) => void | Promise<void>;
|
|
41
|
-
type FsmStateErrorHandler = (state: FsmState, error: unknown) => void | Promise<void>;
|
|
42
|
-
declare class FsmState extends FsmBaseClass {
|
|
43
|
-
process: FsmProcess;
|
|
44
|
-
key: string;
|
|
45
|
-
parent?: FsmState;
|
|
46
|
-
descriptor?: FsmStateDescriptor;
|
|
47
|
-
constructor(process: FsmProcess, parent: FsmState | undefined, key: string, descriptor?: FsmStateDescriptor);
|
|
48
|
-
onEnter(handler: FsmStateHandler): () => void;
|
|
49
|
-
onExit(handler: FsmStateHandler): () => void;
|
|
50
|
-
onStateError(handler: FsmStateErrorHandler): () => void;
|
|
51
|
-
dump(handler: FsmStateDumpHandler): () => void;
|
|
52
|
-
restore(handler: FsmStateDumpHandler): () => void;
|
|
53
|
-
getData<T>(key: string, recursive?: boolean): T | undefined;
|
|
54
|
-
useData<T>(key: string): (((recursive?: boolean) => T | undefined) | ((value: T) => this))[];
|
|
55
|
-
_handleError(error: Error | unknown): Promise<void>;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
declare const STATUS_NONE = 0;
|
|
59
|
-
declare const STATUS_FIRST = 1;
|
|
60
|
-
declare const STATUS_NEXT = 2;
|
|
61
|
-
declare const STATUS_LEAF = 4;
|
|
62
|
-
declare const STATUS_LAST = 8;
|
|
63
|
-
declare const STATUS_FINISHED = 16;
|
|
64
|
-
declare const STATUS_ENTER: number;
|
|
65
|
-
declare const STATUS_EXIT: number;
|
|
66
|
-
type FsmProcessHandler = (process: FsmProcess, ...args: unknown[]) => void | Promise<void>;
|
|
67
|
-
type FsmProcessDump = Record<string, unknown> & {
|
|
68
|
-
status: number;
|
|
69
|
-
event?: string;
|
|
70
|
-
stack: FsmStateDump[];
|
|
71
|
-
};
|
|
72
|
-
type FsmProcessDumpHandler = (process: FsmProcess, dump: FsmProcessDump) => void | Promise<void>;
|
|
73
|
-
declare class FsmProcess extends FsmBaseClass {
|
|
74
|
-
state?: FsmState;
|
|
75
|
-
event?: string;
|
|
76
|
-
nextEvent?: string;
|
|
77
|
-
running: boolean;
|
|
78
|
-
mask: number;
|
|
79
|
-
status: number;
|
|
80
|
-
config: FsmStateConfig;
|
|
81
|
-
rootDescriptor: FsmStateDescriptor;
|
|
82
|
-
constructor(config: FsmStateConfig);
|
|
83
|
-
shutdown(event?: string): Promise<void>;
|
|
84
|
-
dispatch(event: string): Promise<boolean>;
|
|
85
|
-
dump(...args: unknown[]): Promise<FsmProcessDump>;
|
|
86
|
-
restore(dump: FsmProcessDump, ...args: unknown[]): Promise<this>;
|
|
87
|
-
onStateCreate(handler: FsmStateHandler): () => void;
|
|
88
|
-
onStateError(handler: (state: FsmState, error: unknown) => void | Promise<void>): () => void;
|
|
89
|
-
_handleStateError(state: FsmState, error: Error | unknown): Promise<void>;
|
|
90
|
-
_newState(parent: FsmState | undefined, key: string, descriptor: FsmStateDescriptor | undefined): FsmState;
|
|
91
|
-
_getSubstate(parent: FsmState | undefined, prevStateKey: string | undefined): FsmState | undefined;
|
|
92
|
-
_newSubstate(parent: FsmState | undefined, toState: string): FsmState;
|
|
93
|
-
_update(): boolean;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
type Module<C = unknown> = (context: C) => void | (() => void | Promise<void>) | Promise<void | (() => void | Promise<void>)> | Generator<string> | AsyncGenerator<string>;
|
|
97
|
-
declare function newFsmProcess<C>(context: C, config: FsmStateConfig, load: (state: string, event: undefined | string) => undefined | Module<C> | Module<C>[] | Promise<undefined | Module<C> | Module<C>[]>): [
|
|
98
|
-
dispatch: (event: string) => Promise<boolean>,
|
|
99
|
-
shutdown: () => Promise<void>
|
|
100
|
-
];
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* Key used to bind the dispatch function to the process context.
|
|
104
|
-
* The dispatch function allows triggering state transitions by dispatching events.
|
|
105
|
-
*
|
|
106
|
-
* Example usage:
|
|
107
|
-
* ```typescript
|
|
108
|
-
* const context: Record<string, unknown> = {};
|
|
109
|
-
* // Initialize the FSM process using `startFsmProcess`
|
|
110
|
-
* const dispatch = context["fsm:dispatch"] as (event: string) => Promise<void>;
|
|
111
|
-
* await dispatch("someEvent");
|
|
112
|
-
*/
|
|
113
|
-
declare const KEY_DISPATCH: "fsm:dispatch";
|
|
114
|
-
/**
|
|
115
|
-
* Key used to bind the terminate function to the process context.
|
|
116
|
-
* The terminate function is used to gracefully shut down the FSM process.
|
|
117
|
-
* It returns a Promise that resolves when the process has been fully terminated.
|
|
118
|
-
* Example usage:
|
|
119
|
-
* ```typescript
|
|
120
|
-
* const context: Record<string, unknown> = {};
|
|
121
|
-
* // Initialize the FSM process using `startFsmProcess`
|
|
122
|
-
* const terminate = context["fsm:terminate"] as () => Promise<void>;
|
|
123
|
-
* await terminate();
|
|
124
|
-
* ```
|
|
125
|
-
*/
|
|
126
|
-
declare const KEY_TERMINATE: "fsm:terminate";
|
|
127
|
-
/**
|
|
128
|
-
* Key used to bind the current stack of active states to the process context.
|
|
129
|
-
* This provides a snapshot of the states the FSM process has entered.
|
|
130
|
-
* It is represented as an array of strings -- state keys.
|
|
131
|
-
*
|
|
132
|
-
* Example usage:
|
|
133
|
-
* ```typescript
|
|
134
|
-
* const context: Record<string, unknown> = {};
|
|
135
|
-
* // Initialize the FSM process using `startFsmProcess`
|
|
136
|
-
* const states = context["fsm:states"] as string[];
|
|
137
|
-
* console.log("Current active states:", states);
|
|
138
|
-
* ```
|
|
139
|
-
*/
|
|
140
|
-
declare const KEY_STATES: "fsm:states";
|
|
141
|
-
/**
|
|
142
|
-
* Key used to bind the current event being processed to the process context.
|
|
143
|
-
* This represents the event that triggered the current state transition.
|
|
144
|
-
* It is represented as a string.
|
|
145
|
-
* Example usage:
|
|
146
|
-
* ```typescript
|
|
147
|
-
* const context: Record<string, unknown> = {};
|
|
148
|
-
* // Initialize the FSM process using `startFsmProcess`
|
|
149
|
-
* const event = context["fsm:event"] as string;
|
|
150
|
-
* console.log("Current event:", event);
|
|
151
|
-
* ```
|
|
152
|
-
*/
|
|
153
|
-
declare const KEY_EVENT: "fsm:event";
|
|
154
|
-
/**
|
|
155
|
-
* Key used to register a new FSM process configuration in the process context.
|
|
156
|
-
* This key is associated with a function that allows adding new FSM configurations.
|
|
157
|
-
* The function takes a process name and its configuration, and returns a cleanup function
|
|
158
|
-
* to remove the registered configuration.
|
|
159
|
-
* Example usage:
|
|
160
|
-
* ```typescript
|
|
161
|
-
* const context: Record<string, unknown> = {};
|
|
162
|
-
* initProcessManager(context); // Initialize the process manager in the context
|
|
163
|
-
* ...
|
|
164
|
-
* type StateConfig = { key: string; transitions?: string[][]; states?: StateConfig[] };
|
|
165
|
-
* const registerConfig = context["fsm:sys:registerConfig"] as (name: string, config: StateConfig) => () => void;
|
|
166
|
-
* const unregister = registerConfig("myProcess", { key: "Main", transitions: [...] });
|
|
167
|
-
* // To unregister the configuration later
|
|
168
|
-
* unregister();
|
|
169
|
-
* ```
|
|
170
|
-
*/
|
|
171
|
-
declare const KEY_REGISTER_CONFIG: "fsm:sys:registerConfig";
|
|
172
|
-
/**
|
|
173
|
-
* Key used to register state and event handlers for FSM processes in the process context.
|
|
174
|
-
* This key is associated with a function that allows adding handler modules for a specific process.
|
|
175
|
-
* The function takes a process name and a variable number of handler modules, returning a cleanup function
|
|
176
|
-
* to remove the registered handlers.
|
|
177
|
-
* Example usage:
|
|
178
|
-
* ```typescript
|
|
179
|
-
* const context: Record<string, unknown> = {};
|
|
180
|
-
* initProcessManager(context); // Initialize the process manager in the context
|
|
181
|
-
* ...
|
|
182
|
-
* const registerHandlers = context["fsm:sys:registerHandlers"] as (name: string, ...modules: unknown[]) => () => void;
|
|
183
|
-
* const handlerModule1 = {
|
|
184
|
-
* Main: async (context) => { ... },
|
|
185
|
-
* SomeState: async (context) => { ... },
|
|
186
|
-
* }
|
|
187
|
-
* // Views layer can be defined in the same or separate modules
|
|
188
|
-
* const handlerModule3 = {
|
|
189
|
-
* MainView: async (context) => { ... },
|
|
190
|
-
* SomeStateView: async (context) => { ... },
|
|
191
|
-
* }
|
|
192
|
-
* // A common handler function to call for all states
|
|
193
|
-
* const handlerModule2 = (context) => { ... };
|
|
194
|
-
* const unregister = registerHandlers(
|
|
195
|
-
* "myProcess",
|
|
196
|
-
* handlerModule1,
|
|
197
|
-
* handlerModule2,
|
|
198
|
-
* handlerModule3
|
|
199
|
-
* );
|
|
200
|
-
* // To unregister the handlers later
|
|
201
|
-
* unregister();
|
|
202
|
-
* ```
|
|
203
|
-
*/
|
|
204
|
-
declare const KEY_REGISTER_HANDLERS: "fsm:sys:registerHandlers";
|
|
205
|
-
/**
|
|
206
|
-
* Key used to launch an FSM process in the process context.
|
|
207
|
-
* This key is associated with a function that initiates the FSM process based on its name and context.
|
|
208
|
-
* The function takes the process name and context, returning either nothing, a cleanup function,
|
|
209
|
-
* or a Promise that resolves to either nothing or a cleanup function.
|
|
210
|
-
* Example usage:
|
|
211
|
-
* ```typescript
|
|
212
|
-
* const context: Record<string, unknown> = {};
|
|
213
|
-
* initProcessManager(context); // Initialize the process manager in the context
|
|
214
|
-
* // Register process configurations and handlers as needed
|
|
215
|
-
*
|
|
216
|
-
* const launchProcess = context["fsm:sys:launch"] as (name: string, context: Record<string, unknown>) => () => Promise<void>;
|
|
217
|
-
* const terminate = await launchProcess("myProcess", context);
|
|
218
|
-
* // To terminate the process later
|
|
219
|
-
* terminate?.();
|
|
220
|
-
* ```
|
|
221
|
-
*/
|
|
222
|
-
declare const KEY_LAUNCH_PROCESS: "fsm:sys:launch";
|
|
223
|
-
|
|
224
|
-
type StageHandler<C = Record<string, unknown>> = (context: C) => void | (() => void | Promise<void>) | Promise<void | (() => void | Promise<void>)> | AsyncGenerator<string, void, unknown> | Generator<string, void, unknown>;
|
|
225
|
-
declare function toStageHandlers<C>(value: unknown, accept: (key: string, value: unknown) => boolean): StageHandler<C>[];
|
|
226
|
-
|
|
227
|
-
type ProcessConfig = {
|
|
228
|
-
name: string;
|
|
229
|
-
config?: FsmStateConfig;
|
|
230
|
-
} & ({
|
|
231
|
-
handler?: StageHandler;
|
|
232
|
-
} | {
|
|
233
|
-
handlers?: StageHandler | (StageHandler | {
|
|
234
|
-
[state: string]: StageHandler | StageHandler[];
|
|
235
|
-
})[];
|
|
236
|
-
} | {
|
|
237
|
-
default?: StageHandler | (StageHandler | {
|
|
238
|
-
[state: string]: StageHandler | StageHandler[];
|
|
239
|
-
})[];
|
|
240
|
-
});
|
|
241
|
-
declare function launcher(options: unknown): Promise<() => Promise<void>>;
|
|
242
|
-
|
|
243
|
-
interface IProcessConfigManager {
|
|
244
|
-
getProcessConfig(processName: string): FsmStateConfig;
|
|
245
|
-
getHandlersLoader<C = unknown>(processName: string): (state: string, event: undefined | string) => StageHandler<C>[];
|
|
246
|
-
registerConfig(name: string, config: FsmStateConfig): () => void;
|
|
247
|
-
registerHandlers(name: string, ...modules: unknown[]): () => void;
|
|
248
|
-
}
|
|
249
|
-
declare class ProcessConfigManager implements IProcessConfigManager {
|
|
250
|
-
protected configs: Record<string, FsmStateConfig>;
|
|
251
|
-
protected handlers: Record<string, unknown[]>;
|
|
252
|
-
getProcessConfig(processName: string): FsmStateConfig;
|
|
253
|
-
getHandlersLoader<C = unknown>(processName: string): (state: string, event: undefined | string) => StageHandler<C>[];
|
|
254
|
-
registerConfig(name: string, config: FsmStateConfig): () => void;
|
|
255
|
-
registerHandlers(name: string, ...modules: unknown[]): () => void;
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
/**
|
|
259
|
-
* Resolve module paths relative to a base URL.
|
|
260
|
-
* This is useful for converting relative paths to absolute URLs.
|
|
261
|
-
*
|
|
262
|
-
* @param baseUrl - The base URL to resolve against.
|
|
263
|
-
* @param refs - An array of module references (relative or absolute).
|
|
264
|
-
* @returns An array of resolved absolute module URLs as strings.
|
|
265
|
-
* @example
|
|
266
|
-
* ```ts
|
|
267
|
-
* const urls = resolveModulesUrls(
|
|
268
|
-
* 'file:///home/user/project/', // base URL
|
|
269
|
-
* 'https://example.com/js/my-module.js', // absolute URL
|
|
270
|
-
* './module1.js', // relative path
|
|
271
|
-
* '../module2.js' // relative path
|
|
272
|
-
* );
|
|
273
|
-
* console.log(urls);
|
|
274
|
-
* // Output: [
|
|
275
|
-
* // 'https://example.com/js/my-module.js',
|
|
276
|
-
* // 'file:///home/user/project/module1.js',
|
|
277
|
-
* // 'file:///home/user/module2.js'
|
|
278
|
-
* // ] *
|
|
279
|
-
* ```
|
|
280
|
-
*/
|
|
281
|
-
declare function resolveModulesUrls(baseUrl: URL | string, ...refs: (URL | string)[]): string[];
|
|
282
|
-
/**
|
|
283
|
-
* Resolves module paths relative to a base URL.
|
|
284
|
-
* This is useful for converting relative paths to absolute file system paths.
|
|
285
|
-
* @param baseUrl - The base URL to resolve against
|
|
286
|
-
* @param refs - An array of module references (relative or absolute)
|
|
287
|
-
* @returns - An array of resolved absolute module paths as strings
|
|
288
|
-
* @example
|
|
289
|
-
* ```ts
|
|
290
|
-
* const paths = resolveModulesPaths('file:///home/user/project/', './module1.js', '../module2.js');
|
|
291
|
-
* console.log(paths);
|
|
292
|
-
* // Output: [
|
|
293
|
-
* // '/home/user/project/module1.js',
|
|
294
|
-
* // '/home/user/module2.js'
|
|
295
|
-
* // ]
|
|
296
|
-
* ```
|
|
297
|
-
*/
|
|
298
|
-
declare function resolveModulesPaths(baseUrl: URL | string, ...refs: (URL | string)[]): string[];
|
|
299
|
-
|
|
300
|
-
declare function startNodeProcesses(modules?: string[]): Promise<void>;
|
|
301
|
-
|
|
302
|
-
declare function startFsmProcess<C = unknown>(context: C, config: FsmStateConfig, load: (state: string, event: undefined | string) => StageHandler<C>[] | Promise<StageHandler<C>[]>, startEvent?: string): Promise<() => Promise<void>>;
|
|
303
|
-
|
|
304
|
-
declare function startProcesses({ onExit, modules, init, }: {
|
|
305
|
-
onExit?: () => Promise<void> | void;
|
|
306
|
-
modules: unknown[];
|
|
307
|
-
init?: (context: Record<string, unknown>) => Promise<Record<string, unknown>> | Record<string, unknown>;
|
|
308
|
-
}): Promise<() => Promise<void>>;
|
|
309
|
-
|
|
310
|
-
type Printer = (...args: unknown[]) => void;
|
|
311
|
-
type PrinterConfig = {
|
|
312
|
-
prefix?: string;
|
|
313
|
-
print?: (...args: unknown[]) => void;
|
|
314
|
-
lineNumbers?: boolean;
|
|
315
|
-
};
|
|
316
|
-
declare const KEY_PRINTER = "printer";
|
|
317
|
-
declare function preparePrinter(process: FsmProcess, { prefix, print, lineNumbers }: PrinterConfig): Printer;
|
|
318
|
-
declare function setPrinter(state: FsmState, config?: PrinterConfig): void;
|
|
319
|
-
declare function setProcessPrinter(process: FsmProcess, config?: PrinterConfig): void;
|
|
320
|
-
declare function getProcessPrinter(process: FsmProcess): Printer;
|
|
321
|
-
declare function getPrinter(state: FsmState): Printer;
|
|
322
|
-
|
|
323
|
-
declare function newProcess(config: FsmStateConfig, { prefix, print, lineNumbers, }: {
|
|
324
|
-
prefix?: string;
|
|
325
|
-
print?: (...args: any[]) => void;
|
|
326
|
-
lineNumbers?: boolean;
|
|
327
|
-
}): FsmProcess;
|
|
328
|
-
|
|
329
|
-
declare function setProcessTracer(process: FsmProcess, print?: Printer): () => void;
|
|
330
|
-
declare function setStateTracer(state: FsmState, print?: Printer): void;
|
|
331
|
-
|
|
332
|
-
declare function isStateTransitionEnabled(process: FsmProcess, event: string): boolean;
|
|
333
|
-
declare function getStateTransitions(state?: FsmState): [from: string, event: string, to: string][];
|
|
334
|
-
|
|
335
|
-
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, startNodeProcesses as default, getPrinter, getProcessPrinter, getStateTransitions, isStateTransitionEnabled, launcher, newFsmProcess, newProcess, preparePrinter, resolveModulesPaths, resolveModulesUrls, setPrinter, setProcessPrinter, setProcessTracer, setStateTracer, startFsmProcess, startNodeProcesses, startProcesses, toStageHandlers };
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
import { isStateTransitionEnabled } from "../utils/transitions.ts";
|
|
2
|
-
import { FsmProcess } from "./fsm-process.ts";
|
|
3
|
-
import type { FsmStateConfig } from "./fsm-state-config.ts";
|
|
4
|
-
|
|
5
|
-
export type Module<C = unknown> = (context: C) =>
|
|
6
|
-
| void
|
|
7
|
-
| (() => void | Promise<void>)
|
|
8
|
-
| Promise<void | (() => void | Promise<void>)>
|
|
9
|
-
// Event emitters / triggers
|
|
10
|
-
| Generator<string>
|
|
11
|
-
| AsyncGenerator<string>;
|
|
12
|
-
|
|
13
|
-
export function newFsmProcess<C>(
|
|
14
|
-
context: C,
|
|
15
|
-
config: FsmStateConfig,
|
|
16
|
-
load: (
|
|
17
|
-
state: string,
|
|
18
|
-
event: undefined | string,
|
|
19
|
-
) =>
|
|
20
|
-
| undefined
|
|
21
|
-
| Module<C>
|
|
22
|
-
| Module<C>[]
|
|
23
|
-
| Promise<undefined | Module<C> | Module<C>[]>,
|
|
24
|
-
): [
|
|
25
|
-
dispatch: (event: string) => Promise<boolean>,
|
|
26
|
-
shutdown: () => Promise<void>,
|
|
27
|
-
] {
|
|
28
|
-
let started = false;
|
|
29
|
-
let terminated = false;
|
|
30
|
-
const process = new FsmProcess(config);
|
|
31
|
-
async function dispatch(event: string): Promise<boolean> {
|
|
32
|
-
return terminated ||
|
|
33
|
-
(event !== undefined &&
|
|
34
|
-
(!started || isStateTransitionEnabled(process, event)))
|
|
35
|
-
? process.dispatch(event)
|
|
36
|
-
: false;
|
|
37
|
-
}
|
|
38
|
-
process.onStateCreate((state) => {
|
|
39
|
-
started = true;
|
|
40
|
-
state.onEnter(async () => {
|
|
41
|
-
const modules = (await load(state.key, process.event)) ?? [];
|
|
42
|
-
for (const module of Array.isArray(modules) ? modules : [modules]) {
|
|
43
|
-
const result = await module?.(context);
|
|
44
|
-
if (isGenerator(result)) {
|
|
45
|
-
state.onExit(() => {
|
|
46
|
-
result.return?.(void 0);
|
|
47
|
-
});
|
|
48
|
-
(async () => {
|
|
49
|
-
for await (const event of result) {
|
|
50
|
-
if (terminated) {
|
|
51
|
-
break;
|
|
52
|
-
}
|
|
53
|
-
await dispatch(event);
|
|
54
|
-
if (terminated) {
|
|
55
|
-
break;
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
})();
|
|
59
|
-
} else if (typeof result === "function") {
|
|
60
|
-
state.onExit(result);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
});
|
|
64
|
-
});
|
|
65
|
-
async function shutdown(): Promise<void> {
|
|
66
|
-
await process.shutdown();
|
|
67
|
-
terminated = true;
|
|
68
|
-
}
|
|
69
|
-
return [dispatch, shutdown] as const;
|
|
70
|
-
|
|
71
|
-
function isGenerator(
|
|
72
|
-
value: unknown,
|
|
73
|
-
): value is
|
|
74
|
-
| Generator<string, void, unknown>
|
|
75
|
-
| AsyncGenerator<string, void, unknown> {
|
|
76
|
-
return (
|
|
77
|
-
typeof value === "object" &&
|
|
78
|
-
value !== null &&
|
|
79
|
-
"next" in value &&
|
|
80
|
-
typeof (value as Generator<string, void, unknown>).next === "function"
|
|
81
|
-
);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Key used to bind the dispatch function to the process context.
|
|
3
|
-
* The dispatch function allows triggering state transitions by dispatching events.
|
|
4
|
-
*
|
|
5
|
-
* Example usage:
|
|
6
|
-
* ```typescript
|
|
7
|
-
* const context: Record<string, unknown> = {};
|
|
8
|
-
* // Initialize the FSM process using `startFsmProcess`
|
|
9
|
-
* const dispatch = context["fsm:dispatch"] as (event: string) => Promise<void>;
|
|
10
|
-
* await dispatch("someEvent");
|
|
11
|
-
*/
|
|
12
|
-
export const KEY_DISPATCH = "fsm:dispatch" as const;
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Key used to bind the terminate function to the process context.
|
|
16
|
-
* The terminate function is used to gracefully shut down the FSM process.
|
|
17
|
-
* It returns a Promise that resolves when the process has been fully terminated.
|
|
18
|
-
* Example usage:
|
|
19
|
-
* ```typescript
|
|
20
|
-
* const context: Record<string, unknown> = {};
|
|
21
|
-
* // Initialize the FSM process using `startFsmProcess`
|
|
22
|
-
* const terminate = context["fsm:terminate"] as () => Promise<void>;
|
|
23
|
-
* await terminate();
|
|
24
|
-
* ```
|
|
25
|
-
*/
|
|
26
|
-
export const KEY_TERMINATE = "fsm:terminate" as const;
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Key used to bind the current stack of active states to the process context.
|
|
30
|
-
* This provides a snapshot of the states the FSM process has entered.
|
|
31
|
-
* It is represented as an array of strings -- state keys.
|
|
32
|
-
*
|
|
33
|
-
* Example usage:
|
|
34
|
-
* ```typescript
|
|
35
|
-
* const context: Record<string, unknown> = {};
|
|
36
|
-
* // Initialize the FSM process using `startFsmProcess`
|
|
37
|
-
* const states = context["fsm:states"] as string[];
|
|
38
|
-
* console.log("Current active states:", states);
|
|
39
|
-
* ```
|
|
40
|
-
*/
|
|
41
|
-
export const KEY_STATES = "fsm:states" as const;
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Key used to bind the current event being processed to the process context.
|
|
45
|
-
* This represents the event that triggered the current state transition.
|
|
46
|
-
* It is represented as a string.
|
|
47
|
-
* Example usage:
|
|
48
|
-
* ```typescript
|
|
49
|
-
* const context: Record<string, unknown> = {};
|
|
50
|
-
* // Initialize the FSM process using `startFsmProcess`
|
|
51
|
-
* const event = context["fsm:event"] as string;
|
|
52
|
-
* console.log("Current event:", event);
|
|
53
|
-
* ```
|
|
54
|
-
*/
|
|
55
|
-
export const KEY_EVENT = "fsm:event" as const;
|
|
56
|
-
|
|
57
|
-
//-------------------------------------------------
|
|
58
|
-
|
|
59
|
-
// export const KEY_START_PROCESS = "fsm:sys:start" as const;
|
|
60
|
-
/**
|
|
61
|
-
* Key used to register a new FSM process configuration in the process context.
|
|
62
|
-
* This key is associated with a function that allows adding new FSM configurations.
|
|
63
|
-
* The function takes a process name and its configuration, and returns a cleanup function
|
|
64
|
-
* to remove the registered configuration.
|
|
65
|
-
* Example usage:
|
|
66
|
-
* ```typescript
|
|
67
|
-
* const context: Record<string, unknown> = {};
|
|
68
|
-
* initProcessManager(context); // Initialize the process manager in the context
|
|
69
|
-
* ...
|
|
70
|
-
* type StateConfig = { key: string; transitions?: string[][]; states?: StateConfig[] };
|
|
71
|
-
* const registerConfig = context["fsm:sys:registerConfig"] as (name: string, config: StateConfig) => () => void;
|
|
72
|
-
* const unregister = registerConfig("myProcess", { key: "Main", transitions: [...] });
|
|
73
|
-
* // To unregister the configuration later
|
|
74
|
-
* unregister();
|
|
75
|
-
* ```
|
|
76
|
-
*/
|
|
77
|
-
export const KEY_REGISTER_CONFIG = "fsm:sys:registerConfig" as const;
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* Key used to register state and event handlers for FSM processes in the process context.
|
|
81
|
-
* This key is associated with a function that allows adding handler modules for a specific process.
|
|
82
|
-
* The function takes a process name and a variable number of handler modules, returning a cleanup function
|
|
83
|
-
* to remove the registered handlers.
|
|
84
|
-
* Example usage:
|
|
85
|
-
* ```typescript
|
|
86
|
-
* const context: Record<string, unknown> = {};
|
|
87
|
-
* initProcessManager(context); // Initialize the process manager in the context
|
|
88
|
-
* ...
|
|
89
|
-
* const registerHandlers = context["fsm:sys:registerHandlers"] as (name: string, ...modules: unknown[]) => () => void;
|
|
90
|
-
* const handlerModule1 = {
|
|
91
|
-
* Main: async (context) => { ... },
|
|
92
|
-
* SomeState: async (context) => { ... },
|
|
93
|
-
* }
|
|
94
|
-
* // Views layer can be defined in the same or separate modules
|
|
95
|
-
* const handlerModule3 = {
|
|
96
|
-
* MainView: async (context) => { ... },
|
|
97
|
-
* SomeStateView: async (context) => { ... },
|
|
98
|
-
* }
|
|
99
|
-
* // A common handler function to call for all states
|
|
100
|
-
* const handlerModule2 = (context) => { ... };
|
|
101
|
-
* const unregister = registerHandlers(
|
|
102
|
-
* "myProcess",
|
|
103
|
-
* handlerModule1,
|
|
104
|
-
* handlerModule2,
|
|
105
|
-
* handlerModule3
|
|
106
|
-
* );
|
|
107
|
-
* // To unregister the handlers later
|
|
108
|
-
* unregister();
|
|
109
|
-
* ```
|
|
110
|
-
*/
|
|
111
|
-
export const KEY_REGISTER_HANDLERS = "fsm:sys:registerHandlers" as const;
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* Key used to launch an FSM process in the process context.
|
|
115
|
-
* This key is associated with a function that initiates the FSM process based on its name and context.
|
|
116
|
-
* The function takes the process name and context, returning either nothing, a cleanup function,
|
|
117
|
-
* or a Promise that resolves to either nothing or a cleanup function.
|
|
118
|
-
* Example usage:
|
|
119
|
-
* ```typescript
|
|
120
|
-
* const context: Record<string, unknown> = {};
|
|
121
|
-
* initProcessManager(context); // Initialize the process manager in the context
|
|
122
|
-
* // Register process configurations and handlers as needed
|
|
123
|
-
*
|
|
124
|
-
* const launchProcess = context["fsm:sys:launch"] as (name: string, context: Record<string, unknown>) => () => Promise<void>;
|
|
125
|
-
* const terminate = await launchProcess("myProcess", context);
|
|
126
|
-
* // To terminate the process later
|
|
127
|
-
* terminate?.();
|
|
128
|
-
* ```
|
|
129
|
-
*/
|
|
130
|
-
export const KEY_LAUNCH_PROCESS = "fsm:sys:launch" as const;
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
export function isGenerator(
|
|
2
|
-
value: unknown,
|
|
3
|
-
): value is
|
|
4
|
-
| Generator<string, void, unknown>
|
|
5
|
-
| AsyncGenerator<string, void, unknown> {
|
|
6
|
-
return (
|
|
7
|
-
typeof value === "object" &&
|
|
8
|
-
value !== null &&
|
|
9
|
-
"next" in value &&
|
|
10
|
-
typeof (value as Generator<string, void, unknown>).next === "function"
|
|
11
|
-
);
|
|
12
|
-
}
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import type { FsmStateConfig } from "../core/fsm-state-config.ts";
|
|
2
|
-
import { type StageHandler, toStageHandlers } from "./types.ts";
|
|
3
|
-
|
|
4
|
-
export interface IProcessConfigManager {
|
|
5
|
-
getProcessConfig(processName: string): FsmStateConfig;
|
|
6
|
-
getHandlersLoader<C = unknown>(
|
|
7
|
-
processName: string,
|
|
8
|
-
): (state: string, event: undefined | string) => StageHandler<C>[];
|
|
9
|
-
registerConfig(name: string, config: FsmStateConfig): () => void;
|
|
10
|
-
registerHandlers(name: string, ...modules: unknown[]): () => void;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export class ProcessConfigManager implements IProcessConfigManager {
|
|
14
|
-
protected configs: Record<string, FsmStateConfig> = {};
|
|
15
|
-
protected handlers: Record<string, unknown[]> = {};
|
|
16
|
-
|
|
17
|
-
getProcessConfig(processName: string): FsmStateConfig {
|
|
18
|
-
return this.configs[processName] ?? { key: "Main" };
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
getHandlersLoader<C = unknown>(
|
|
22
|
-
processName: string,
|
|
23
|
-
): (state: string, event: undefined | string) => StageHandler<C>[] {
|
|
24
|
-
const config = this.getProcessConfig(processName);
|
|
25
|
-
return (stateKey: string) => {
|
|
26
|
-
const modulesKeys: string[] = [];
|
|
27
|
-
if (stateKey === config.key) {
|
|
28
|
-
modulesKeys.push("default");
|
|
29
|
-
}
|
|
30
|
-
modulesKeys.push(
|
|
31
|
-
stateKey,
|
|
32
|
-
`${stateKey}Controller`,
|
|
33
|
-
`${stateKey}StateController`,
|
|
34
|
-
`${stateKey}View`,
|
|
35
|
-
`${stateKey}StateView`,
|
|
36
|
-
`${stateKey}Trigger`,
|
|
37
|
-
`${stateKey}StateTrigger`,
|
|
38
|
-
`${stateKey}Test`,
|
|
39
|
-
`${stateKey}StateTest`,
|
|
40
|
-
);
|
|
41
|
-
const keysSet = new Set(modulesKeys);
|
|
42
|
-
const processHandlers = this.handlers[processName] ?? [];
|
|
43
|
-
const handlers = toStageHandlers(processHandlers, (key: string) =>
|
|
44
|
-
keysSet.has(key),
|
|
45
|
-
);
|
|
46
|
-
return handlers;
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
registerConfig(name: string, config: FsmStateConfig): () => void {
|
|
51
|
-
this.configs[name] = config;
|
|
52
|
-
return () => {
|
|
53
|
-
delete this.configs[name];
|
|
54
|
-
};
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
registerHandlers(name: string, ...modules: unknown[]): () => void {
|
|
58
|
-
let list: unknown[] = this.handlers[name];
|
|
59
|
-
if (!list) {
|
|
60
|
-
list = this.handlers[name] = [];
|
|
61
|
-
}
|
|
62
|
-
list.push(modules);
|
|
63
|
-
return () => {
|
|
64
|
-
list = list.filter((v) => v !== modules);
|
|
65
|
-
if (list.length === 0) {
|
|
66
|
-
delete this.handlers[name];
|
|
67
|
-
}
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
}
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Resolve module paths relative to a base URL.
|
|
3
|
-
* This is useful for converting relative paths to absolute URLs.
|
|
4
|
-
*
|
|
5
|
-
* @param baseUrl - The base URL to resolve against.
|
|
6
|
-
* @param refs - An array of module references (relative or absolute).
|
|
7
|
-
* @returns An array of resolved absolute module URLs as strings.
|
|
8
|
-
* @example
|
|
9
|
-
* ```ts
|
|
10
|
-
* const urls = resolveModulesUrls(
|
|
11
|
-
* 'file:///home/user/project/', // base URL
|
|
12
|
-
* 'https://example.com/js/my-module.js', // absolute URL
|
|
13
|
-
* './module1.js', // relative path
|
|
14
|
-
* '../module2.js' // relative path
|
|
15
|
-
* );
|
|
16
|
-
* console.log(urls);
|
|
17
|
-
* // Output: [
|
|
18
|
-
* // 'https://example.com/js/my-module.js',
|
|
19
|
-
* // 'file:///home/user/project/module1.js',
|
|
20
|
-
* // 'file:///home/user/module2.js'
|
|
21
|
-
* // ] *
|
|
22
|
-
* ```
|
|
23
|
-
*/
|
|
24
|
-
export function resolveModulesUrls(
|
|
25
|
-
baseUrl: URL | string,
|
|
26
|
-
...refs: (URL | string)[]
|
|
27
|
-
): string[] {
|
|
28
|
-
return refs.map((ref) => new URL(ref, baseUrl).href);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Resolves module paths relative to a base URL.
|
|
33
|
-
* This is useful for converting relative paths to absolute file system paths.
|
|
34
|
-
* @param baseUrl - The base URL to resolve against
|
|
35
|
-
* @param refs - An array of module references (relative or absolute)
|
|
36
|
-
* @returns - An array of resolved absolute module paths as strings
|
|
37
|
-
* @example
|
|
38
|
-
* ```ts
|
|
39
|
-
* const paths = resolveModulesPaths('file:///home/user/project/', './module1.js', '../module2.js');
|
|
40
|
-
* console.log(paths);
|
|
41
|
-
* // Output: [
|
|
42
|
-
* // '/home/user/project/module1.js',
|
|
43
|
-
* // '/home/user/module2.js'
|
|
44
|
-
* // ]
|
|
45
|
-
* ```
|
|
46
|
-
*/
|
|
47
|
-
export function resolveModulesPaths(
|
|
48
|
-
baseUrl: URL | string,
|
|
49
|
-
...refs: (URL | string)[]
|
|
50
|
-
): string[] {
|
|
51
|
-
return refs.map((ref) => new URL(ref, baseUrl).pathname);
|
|
52
|
-
}
|