@camcima/finita 2.1.0 → 3.0.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
@@ -65,110 +65,205 @@ interface TransitionInterface<TSubject = unknown> extends Weighted {
65
65
 
66
66
  interface StateInterface extends Named, Metadata {
67
67
  getTransitions(): Iterable<TransitionInterface>;
68
- addTransition(transition: TransitionInterface): void;
69
68
  getEventNames(): string[];
70
69
  hasEvent(name: string): boolean;
71
70
  getEvent(name: string): EventInterface;
72
71
  getMetadataValue(key: string): unknown;
73
- setMetadataValue(key: string, value: unknown): void;
74
72
  hasMetadataValue(key: string): boolean;
75
- deleteMetadataValue(key: string): void;
73
+ }
74
+
75
+ interface StateCollectionInterface {
76
+ getStates(): Iterable<StateInterface>;
77
+ getState(name: string): StateInterface;
78
+ hasState(name: string): boolean;
79
+ }
80
+
81
+ interface ProcessInterface extends Named, StateCollectionInterface {
82
+ getInitialState(): StateInterface;
83
+ }
84
+
85
+ /**
86
+ * Symbol-based construction guard for State / Transition / Process.
87
+ *
88
+ * These classes' constructors require this symbol as the first argument.
89
+ * Only ProcessBuilder imports it, ensuring only the builder can instantiate
90
+ * the graph. User code receives an opaque type error if it tries to call
91
+ * `new State(...)` directly.
92
+ */
93
+ declare const INTERNAL_CONSTRUCTION_KEY: unique symbol;
94
+ type InternalConstructionKey = typeof INTERNAL_CONSTRUCTION_KEY;
95
+
96
+ declare class Process implements ProcessInterface {
97
+ private readonly name;
98
+ private readonly initialState;
99
+ private readonly states;
100
+ constructor(key: InternalConstructionKey, name: string, initialState: StateInterface, states: Iterable<StateInterface>);
101
+ getName(): string;
102
+ getInitialState(): StateInterface;
103
+ getStates(): Iterable<StateInterface>;
104
+ getState(name: string): StateInterface;
105
+ hasState(name: string): boolean;
76
106
  }
77
107
 
78
108
  declare class State implements StateInterface {
79
109
  private readonly name;
80
- private readonly transitions;
110
+ private _transitions;
81
111
  private readonly events;
82
112
  private readonly metadata;
83
- constructor(name: string);
113
+ constructor(key: InternalConstructionKey, name: string, eventNames: Iterable<string>, metadata: ReadonlyMap<string, unknown>);
114
+ /**
115
+ * Internal: populate transitions after State construction.
116
+ * May only be called once and only with the construction key.
117
+ * Used by ProcessBuilder to break the cycle: State must exist before
118
+ * Transitions can target it, but State needs its transitions to be useful.
119
+ */
120
+ _initTransitions(key: InternalConstructionKey, transitions: Iterable<TransitionInterface>): void;
84
121
  getName(): string;
85
122
  getTransitions(): Iterable<TransitionInterface>;
86
- addTransition(transition: TransitionInterface): void;
87
123
  getEventNames(): string[];
88
124
  hasEvent(name: string): boolean;
89
125
  getEvent(name: string): EventInterface;
90
126
  getMetadata(): Record<string, unknown>;
91
127
  getMetadataValue(key: string): unknown;
92
- setMetadataValue(key: string, value: unknown): void;
93
128
  hasMetadataValue(key: string): boolean;
94
- deleteMetadataValue(key: string): void;
95
129
  }
96
130
 
97
131
  declare class Transition<TSubject = unknown> implements TransitionInterface<TSubject> {
98
132
  private readonly targetState;
99
133
  private readonly eventName;
100
134
  private readonly condition;
101
- private weight;
102
- constructor(targetState: StateInterface, eventName?: string | null, condition?: ConditionInterface<TSubject> | null);
135
+ private readonly weight;
136
+ constructor(key: InternalConstructionKey, targetState: StateInterface, eventName: string | null, condition: ConditionInterface<TSubject> | null, weight: number);
103
137
  getTargetState(): StateInterface;
104
138
  getEventName(): string | null;
105
139
  getConditionName(): string | null;
106
140
  getCondition(): ConditionInterface<TSubject> | null;
107
141
  isActive(subject: TSubject, context: Map<string, unknown>, event?: EventInterface): Promise<boolean>;
108
142
  getWeight(): number;
109
- setWeight(weight: number): void;
110
143
  }
111
144
 
112
- interface StateCollectionInterface {
113
- getStates(): Iterable<StateInterface>;
114
- getState(name: string): StateInterface;
115
- hasState(name: string): boolean;
145
+ interface AddStateOptions {
146
+ initial?: boolean;
147
+ metadata?: Record<string, unknown>;
148
+ }
149
+ interface AddTransitionOptions<TSubject = unknown> {
150
+ event?: string;
151
+ condition?: ConditionInterface<TSubject>;
152
+ weight?: number;
153
+ }
154
+ interface BuildOptions {
155
+ /**
156
+ * When true, orphan/unreachable states cause GraphValidationError.
157
+ * When false (default), orphan states are silently allowed.
158
+ */
159
+ strictOrphans?: boolean;
160
+ }
161
+ declare class ProcessBuilder<TSubject = unknown> {
162
+ private readonly processName;
163
+ private readonly stateSpecs;
164
+ private readonly transitionSpecs;
165
+ private built;
166
+ constructor(processName: string);
167
+ addState(name: string, options?: AddStateOptions): this;
168
+ addTransition(fromState: string, toState: string, options?: AddTransitionOptions<TSubject>): this;
169
+ build(options?: BuildOptions): Process;
170
+ private validateInitialState;
171
+ private findInitialStateName;
172
+ private validateTransitionEndpoints;
173
+ private validateNoConflictingDuplicates;
174
+ private collectEventNamesByState;
175
+ /**
176
+ * Two-phase construction:
177
+ * Phase 1 — create all final State instances with no transitions.
178
+ * Phase 2 — build Transitions targeting the Phase-1 States, then attach
179
+ * them via State._initTransitions.
180
+ *
181
+ * Because every Transition is created after every State exists, target
182
+ * identity holds by construction for any graph topology (acyclic, cyclic,
183
+ * self-loop).
184
+ */
185
+ private buildAllStates;
186
+ private validateOrphans;
116
187
  }
117
188
 
118
- declare class StateCollectionMerger {
119
- private readonly targetCollection;
120
- private stateNamePrefix;
121
- constructor(targetCollection: StateCollection);
122
- getStateNamePrefix(): string;
123
- setStateNamePrefix(prefix: string): void;
124
- getTargetCollection(): StateCollection;
125
- protected createState(name: string): StateInterface;
126
- protected findOrCreateState(name: string): StateInterface;
127
- protected createCondition(sourceTransition: TransitionInterface): ConditionInterface | null;
128
- protected createTransition(sourceTransition: TransitionInterface): Transition;
129
- protected mergeMetadata(source: StateInterface, target: StateInterface): void;
130
- protected mergeEvent(source: StateInterface, target: StateInterface, eventName: string): void;
131
- protected mergeState(sourceState: StateInterface): void;
132
- merge(source: StateCollectionInterface | StateInterface): void;
133
- }
134
-
135
- declare class StateCollection implements StateCollectionInterface {
136
- private readonly states;
137
- private stateCollectionMerger;
138
- getState(name: string): StateInterface;
139
- getStates(): Iterable<StateInterface>;
140
- hasState(name: string): boolean;
141
- addState(state: StateInterface): void;
142
- getStateCollectionMerger(): StateCollectionMerger;
143
- merge(source: StateCollectionInterface): void;
189
+ /**
190
+ * Immutable snapshot passed to AfterTransitionObserver.notify().
191
+ *
192
+ * Captures the post-commit transition: state has already moved from
193
+ * fromState to toState. Reading any field is safe and stable for the
194
+ * duration of the observer call (and beyond — the frame is frozen).
195
+ */
196
+ interface TransitionFrame<TSubject = unknown> {
197
+ readonly fromState: StateInterface;
198
+ readonly toState: StateInterface;
199
+ readonly transition: TransitionInterface<TSubject>;
200
+ readonly event: EventInterface | null;
201
+ readonly condition: ConditionInterface<TSubject> | null;
202
+ readonly context: ReadonlyMap<string, unknown>;
203
+ readonly timestamp: number;
204
+ readonly machineName: string | null;
205
+ }
206
+ /**
207
+ * Immutable snapshot passed to BeforeTransitionObserver.notify().
208
+ *
209
+ * Same shape as TransitionFrame but represents a *proposed* transition
210
+ * — fromState is still the current state at notification time. Throwing
211
+ * from a before-observer aborts the transition; otherwise commit proceeds.
212
+ */
213
+ interface ProposedTransitionFrame<TSubject = unknown> extends TransitionFrame<TSubject> {
144
214
  }
145
215
 
146
- interface ProcessInterface extends Named, StateCollectionInterface {
147
- getInitialState(): StateInterface;
216
+ /**
217
+ * Runs before a transition commits. Throwing aborts the transition —
218
+ * state is not mutated and the original caller's promise rejects with
219
+ * the thrown error.
220
+ *
221
+ * Implementations must be pure relative to the FSM: they MUST NOT call
222
+ * triggerEvent / checkTransitions on the same Statemachine. There is no
223
+ * enqueue handle in the before phase by design — vetoes and validations
224
+ * complete synchronously per observer; chained behaviour belongs in
225
+ * AfterTransitionObserver.
226
+ */
227
+ interface BeforeTransitionObserver<TSubject = unknown> {
228
+ notify(frame: ProposedTransitionFrame<TSubject>): MaybePromise<void>;
148
229
  }
149
230
 
150
- declare class Process implements ProcessInterface {
151
- private readonly name;
152
- private readonly initialState;
153
- private readonly states;
154
- constructor(name: string, initialState: StateInterface);
155
- private registerState;
156
- getName(): string;
157
- getInitialState(): StateInterface;
158
- getStates(): Iterable<StateInterface>;
159
- getState(name: string): StateInterface;
160
- hasState(name: string): boolean;
231
+ /**
232
+ * Handle passed to AfterTransitionObserver.notify so observers can
233
+ * append events to the FSM's queue without reentering it.
234
+ *
235
+ * enqueue() never runs the event inline — it returns immediately. The
236
+ * event runs as its own top-level operation after the current operation
237
+ * (and any auto-follow-on transitions) completes.
238
+ */
239
+ interface EnqueueContext {
240
+ enqueue(event: string, context?: Map<string, unknown>): void;
241
+ }
242
+ /**
243
+ * Runs after a transition has committed. State has already moved.
244
+ *
245
+ * Errors thrown by an after-observer do NOT roll back the transition.
246
+ * All after-observers are still invoked (no early bail). After all have
247
+ * run, the caller's promise rejects: with the thrown error if exactly
248
+ * one observer threw, or with a standard AggregateError if multiple did.
249
+ */
250
+ interface AfterTransitionObserver<TSubject = unknown> {
251
+ notify(frame: TransitionFrame<TSubject>, ctx: EnqueueContext): MaybePromise<void>;
161
252
  }
162
253
 
163
- interface StatemachineInterface<TSubject = unknown> extends ObservableSubject {
254
+ interface StatemachineInterface<TSubject = unknown> {
164
255
  getCurrentState(): StateInterface;
256
+ getLastState(): StateInterface | null;
165
257
  getSubject(): TSubject;
166
258
  getProcess(): ProcessInterface;
167
259
  triggerEvent(name: string, context?: Map<string, unknown>): Promise<void>;
168
260
  checkTransitions(context?: Map<string, unknown>): Promise<void>;
169
- getSelectedTransition(): TransitionInterface<TSubject> | null;
170
- getLastState(): StateInterface | null;
171
- getCurrentContext(): Map<string, unknown> | null;
261
+ attachBefore(observer: BeforeTransitionObserver<TSubject>): void;
262
+ detachBefore(observer: BeforeTransitionObserver<TSubject>): void;
263
+ getBeforeObservers(): Iterable<BeforeTransitionObserver<TSubject>>;
264
+ attachAfter(observer: AfterTransitionObserver<TSubject>): void;
265
+ detachAfter(observer: AfterTransitionObserver<TSubject>): void;
266
+ getAfterObservers(): Iterable<AfterTransitionObserver<TSubject>>;
172
267
  acquireLock(): Promise<boolean>;
173
268
  releaseLock(): Promise<void>;
174
269
  isLockAcquired(): boolean;
@@ -187,59 +282,57 @@ interface TransitionSelectorInterface<TSubject = unknown> {
187
282
  selectTransition(transitions: Iterable<TransitionInterface<TSubject>>): TransitionInterface<TSubject> | null;
188
283
  }
189
284
 
190
- interface CallbackInterface {
191
- invoke(): MaybePromise<void>;
192
- }
193
- interface DispatcherInterface extends CallbackInterface {
194
- dispatch(event: EventInterface, args?: unknown[], onReadyCallback?: CallbackInterface): void;
195
- isReady(): boolean;
196
- invoke(): Promise<void>;
285
+ interface StatemachineOptions<TSubject = unknown> {
286
+ /** Override the process's initial state. Defaults to process.getInitialState(). */
287
+ initialStateName?: string;
288
+ /** Defaults to OneOrNoneActiveTransition. */
289
+ transitionSelector?: TransitionSelectorInterface<TSubject>;
290
+ /** Defaults to NullMutex (no cross-process serialization). */
291
+ mutex?: MutexInterface;
292
+ /** When true, the engine releases the mutex at the end of each top-level operation. Defaults to true. */
293
+ autoreleaseLock?: boolean;
197
294
  }
198
295
 
199
296
  declare class Statemachine<TSubject = unknown> implements StatemachineInterface<TSubject> {
200
297
  private readonly subject;
201
- private currentState;
202
- private lastState;
203
- private readonly transitionSelector;
204
- private selectedTransition;
205
298
  private readonly process;
299
+ private readonly transitionSelector;
206
300
  private readonly mutex;
301
+ private currentState;
302
+ private lastState;
207
303
  private autoreleaseLock;
208
- private dispatcher;
209
- private currentEvent;
210
- private currentContext;
211
- private readonly observers;
212
- constructor(subject: TSubject, process: ProcessInterface, stateName?: string | null, transitionSelector?: TransitionSelectorInterface<TSubject> | null, mutex?: MutexInterface | null);
213
- getProcess(): ProcessInterface;
304
+ private readonly queue;
305
+ private running;
306
+ private readonly beforeObservers;
307
+ private readonly afterObservers;
308
+ constructor(subject: TSubject, process: ProcessInterface, options?: StatemachineOptions<TSubject>);
214
309
  getCurrentState(): StateInterface;
215
310
  getLastState(): StateInterface | null;
216
311
  getSubject(): TSubject;
217
- getSelectedTransition(): TransitionInterface<TSubject> | null;
218
- getCurrentContext(): Map<string, unknown> | null;
219
- private doCheckTransitions;
220
- private onDispatcherReady;
221
- dispatchEvent(dispatcher: DispatcherInterface, name: string, context?: Map<string, unknown>): Promise<void>;
222
- triggerEvent(name: string, context?: Map<string, unknown>): Promise<void>;
223
- checkTransitions(context?: Map<string, unknown>): Promise<void>;
224
- private acquireLockOrThrowException;
225
- isAutoreleaseLock(): boolean;
226
- setAutoreleaseLock(autorelease: boolean): void;
312
+ getProcess(): ProcessInterface;
313
+ attachBefore(observer: BeforeTransitionObserver<TSubject>): void;
314
+ detachBefore(observer: BeforeTransitionObserver<TSubject>): void;
315
+ getBeforeObservers(): Iterable<BeforeTransitionObserver<TSubject>>;
316
+ attachAfter(observer: AfterTransitionObserver<TSubject>): void;
317
+ detachAfter(observer: AfterTransitionObserver<TSubject>): void;
318
+ getAfterObservers(): Iterable<AfterTransitionObserver<TSubject>>;
227
319
  acquireLock(): Promise<boolean>;
228
320
  releaseLock(): Promise<void>;
229
321
  isLockAcquired(): boolean;
230
- attach(observer: Observer): void;
231
- detach(observer: Observer): void;
232
- notify(): Promise<void>;
233
- getObservers(): Iterable<Observer>;
234
- }
235
-
236
- declare class Dispatcher implements DispatcherInterface {
237
- private commands;
238
- private onReadyCallbacks;
239
- private ready;
240
- dispatch(event: EventInterface, args?: unknown[], onReadyCallback?: CallbackInterface): void;
241
- invoke(): Promise<void>;
242
- isReady(): boolean;
322
+ isAutoreleaseLock(): boolean;
323
+ setAutoreleaseLock(autorelease: boolean): void;
324
+ triggerEvent(name: string, context?: Map<string, unknown>): Promise<void>;
325
+ checkTransitions(context?: Map<string, unknown>): Promise<void>;
326
+ private runIfIdle;
327
+ private runOperation;
328
+ private resolveEvent;
329
+ /**
330
+ * Drive transitions starting from the current state, following automatic
331
+ * transitions until quiescent. The first iteration may use the supplied
332
+ * event; subsequent iterations are automatic.
333
+ */
334
+ private processOperation;
335
+ private readonlyContext;
243
336
  }
244
337
 
245
338
  interface MutexFactoryInterface<TSubject = unknown> {
@@ -261,12 +354,13 @@ interface StateNameDetectorInterface<TSubject = unknown> {
261
354
  }
262
355
 
263
356
  interface FactoryInterface<TSubject = unknown> {
264
- createStatemachine(subject: TSubject): Promise<StatemachineInterface<TSubject>>;
265
357
  setMutexFactory(factory: MutexFactoryInterface<TSubject> | null): void;
266
358
  setTransitionSelector(selector: TransitionSelectorInterface<TSubject>): void;
267
- attachStatemachineObserver(observer: Observer): void;
268
- detachStatemachineObserver(observer: Observer): void;
269
- getStatemachineObservers(): Iterable<Observer>;
359
+ attachBeforeObserver(observer: BeforeTransitionObserver<TSubject>): void;
360
+ detachBeforeObserver(observer: BeforeTransitionObserver<TSubject>): void;
361
+ attachAfterObserver(observer: AfterTransitionObserver<TSubject>): void;
362
+ detachAfterObserver(observer: AfterTransitionObserver<TSubject>): void;
363
+ createStatemachine(subject: TSubject): Promise<StatemachineInterface<TSubject>>;
270
364
  }
271
365
 
272
366
  interface StatefulInterface {
@@ -278,6 +372,14 @@ interface LastStateHasChangedDateInterface {
278
372
  getLastStateHasChangedDate(): Date;
279
373
  }
280
374
 
375
+ interface CallbackInterface {
376
+ invoke(): MaybePromise<void>;
377
+ }
378
+ interface DispatcherInterface extends CallbackInterface {
379
+ dispatch(event: EventInterface, args?: unknown[]): void;
380
+ invoke(): Promise<void>;
381
+ }
382
+
281
383
  interface LoggerInterface {
282
384
  log(level: string, message: string, context?: Record<string, unknown>): void;
283
385
  }
@@ -337,28 +439,46 @@ declare class Not<TSubject = unknown> implements ConditionInterface<TSubject> {
337
439
  checkCondition(subject: TSubject, context: Map<string, unknown>): Promise<boolean>;
338
440
  }
339
441
 
442
+ /**
443
+ * Legacy Observer for Event observers (commands attached to specific events).
444
+ *
445
+ * In v3 this is no longer used as a Statemachine observer. To run a
446
+ * callback after every transition, implement AfterTransitionObserver
447
+ * directly or compose a small wrapper.
448
+ */
340
449
  declare class CallbackObserver implements Observer {
341
450
  private readonly callback;
342
451
  constructor(callback: (...args: unknown[]) => MaybePromise<void>);
343
452
  update(subject: ObservableSubject): MaybePromise<void>;
344
453
  }
345
454
 
346
- declare class StatefulStatusChanger implements Observer {
347
- update(subject: ObservableSubject): void;
455
+ declare class StatefulStatusChanger<TSubject extends StatefulInterface> implements AfterTransitionObserver<TSubject> {
456
+ private readonly subject;
457
+ constructor(subject: TSubject);
458
+ notify(frame: TransitionFrame<TSubject>): void;
348
459
  }
349
460
 
350
- declare class OnEnterObserver implements Observer {
461
+ /**
462
+ * After-transition observer that fires an event named DEFAULT_EVENT_NAME
463
+ * (or a custom name) when entering any state that has that event declared.
464
+ *
465
+ * The chained event is *enqueued*, not invoked inline: it runs as its own
466
+ * top-level operation after the current operation completes. Other
467
+ * after-observers registered after OnEnterObserver still see the original
468
+ * frame, not the chained one.
469
+ */
470
+ declare class OnEnterObserver<TSubject = unknown> implements AfterTransitionObserver<TSubject> {
351
471
  static readonly DEFAULT_EVENT_NAME = "onEnter";
352
472
  private readonly eventName;
353
473
  constructor(eventName?: string);
354
- update(subject: ObservableSubject): Promise<void>;
474
+ notify(frame: TransitionFrame<TSubject>, ctx: EnqueueContext): void;
355
475
  }
356
476
 
357
- declare class TransitionLogger implements Observer {
477
+ declare class TransitionLogger<TSubject = unknown> implements AfterTransitionObserver<TSubject> {
358
478
  private readonly logger;
359
479
  private readonly loggerLevel;
360
480
  constructor(logger: LoggerInterface, loggerLevel?: string);
361
- update(subject: ObservableSubject): void;
481
+ notify(frame: TransitionFrame<TSubject>): void;
362
482
  }
363
483
 
364
484
  declare class ActiveTransitionFilter {
@@ -432,15 +552,17 @@ declare class MutexFactory<TSubject = unknown> implements MutexFactoryInterface<
432
552
  declare class Factory<TSubject = unknown> implements FactoryInterface<TSubject> {
433
553
  private readonly processDetector;
434
554
  private readonly stateNameDetector;
435
- private readonly statemachineObservers;
555
+ private readonly beforeObservers;
556
+ private readonly afterObservers;
436
557
  private transitionSelector;
437
558
  private mutexFactory;
438
559
  constructor(processDetector: ProcessDetectorInterface<TSubject>, stateNameDetector?: StateNameDetectorInterface<TSubject> | null);
439
560
  setMutexFactory(factory: MutexFactoryInterface<TSubject> | null): void;
440
561
  setTransitionSelector(selector: TransitionSelectorInterface<TSubject>): void;
441
- attachStatemachineObserver(observer: Observer): void;
442
- detachStatemachineObserver(observer: Observer): void;
443
- getStatemachineObservers(): Iterable<Observer>;
562
+ attachBeforeObserver(observer: BeforeTransitionObserver<TSubject>): void;
563
+ detachBeforeObserver(observer: BeforeTransitionObserver<TSubject>): void;
564
+ attachAfterObserver(observer: AfterTransitionObserver<TSubject>): void;
565
+ detachAfterObserver(observer: AfterTransitionObserver<TSubject>): void;
444
566
  createStatemachine(subject: TSubject): Promise<StatemachineInterface<TSubject>>;
445
567
  }
446
568
 
@@ -462,17 +584,6 @@ declare class StatefulStateNameDetector implements StateNameDetectorInterface<St
462
584
  detectCurrentStateName(subject: StatefulInterface): string | null;
463
585
  }
464
586
 
465
- declare class SetupHelper {
466
- protected readonly stateCollection: StateCollection;
467
- constructor(stateCollection: StateCollection);
468
- findOrCreateState(name: string): StateInterface;
469
- protected findTransition(sourceState: StateInterface, targetState: StateInterface, eventName?: string | null, condition?: ConditionInterface | null): TransitionInterface | null;
470
- findOrCreateTransition(sourceStateName: string, targetStateName: string, eventName?: string | null, condition?: ConditionInterface | null): TransitionInterface;
471
- findOrCreateEvent(sourceStateName: string, eventName: string): EventInterface;
472
- addCommand(sourceStateName: string, eventName: string, command: Observer): void;
473
- addCommandAndSelfTransition(sourceStateName: string, eventName: string, command: Observer): void;
474
- }
475
-
476
587
  interface GraphNode {
477
588
  id: string;
478
589
  label: string;
@@ -497,6 +608,7 @@ interface MermaidOptions {
497
608
  declare class GraphBuilder {
498
609
  private readonly nodes;
499
610
  private readonly edges;
611
+ private readonly statesWithEdges;
500
612
  private getOrCreateNode;
501
613
  protected getTransitionLabel(state: StateInterface, transition: TransitionInterface): string;
502
614
  addState(state: StateInterface): void;
@@ -507,19 +619,94 @@ declare class GraphBuilder {
507
619
  toMermaid(options?: MermaidOptions): string;
508
620
  }
509
621
 
510
- declare class WrongEventForStateError extends Error {
622
+ declare abstract class FinitaError extends Error {
623
+ abstract readonly code: string;
624
+ constructor(message?: string);
625
+ }
626
+
627
+ declare class WrongEventForStateError extends FinitaError {
628
+ readonly code = "wrongEventForState";
511
629
  readonly stateName: string;
512
630
  readonly eventName: string;
513
631
  constructor(stateName: string, eventName: string);
514
632
  }
515
633
 
516
- declare class LockCanNotBeAcquiredError extends Error {
634
+ declare class LockCanNotBeAcquiredError extends FinitaError {
635
+ readonly code = "lockCanNotBeAcquired";
517
636
  constructor(message?: string);
518
637
  }
519
638
 
520
- declare class DuplicateStateError extends Error {
639
+ declare class DuplicateStateError extends FinitaError {
640
+ readonly code = "duplicateState";
521
641
  readonly stateName: string;
522
642
  constructor(stateName: string);
523
643
  }
524
644
 
525
- export { AbstractNamedProcessDetector, ActiveTransitionFilter, AndComposite, CallbackCondition, type CallbackInterface, CallbackObserver, type ConditionCallbackFn, type ConditionInterface, Contradiction, Dispatcher, type DispatcherInterface, type DotOptions, DuplicateStateError, Event, type EventInterface, Factory, type FactoryInterface, FilterStateByEvent, FilterStateByFinalState, FilterStateByTransition, FilterTransitionByEvent, type Graph, GraphBuilder, type GraphEdge, type GraphNode, type LastStateHasChangedDateInterface, type LockAdapterInterface, LockAdapterMutex, LockCanNotBeAcquiredError, type LoggerInterface, type MaybePromise, type MermaidOptions, type Metadata, MutexFactory, type MutexFactoryInterface, type MutexInterface, type Named, Not, NullMutex, type ObservableSubject, type Observer, OnEnterObserver, OneOrNoneActiveTransition, OrComposite, Process, type ProcessDetectorInterface, type ProcessInterface, ScoreTransition, SetupHelper, SingleProcessDetector, State, StateCollection, type StateCollectionInterface, StateCollectionMerger, type StateInterface, type StateNameDetectorInterface, type StatefulInterface, StatefulStateNameDetector, StatefulStatusChanger, Statemachine, type StatemachineInterface, type StringConverter, Tautology, Timeout, Transition, type TransitionInterface, TransitionLogger, type TransitionSelectorInterface, WeightTransition, type Weighted, WrongEventForStateError };
645
+ declare class ProcessFinalizedError extends FinitaError {
646
+ readonly code = "processFinalized";
647
+ readonly processName: string;
648
+ constructor(processName: string);
649
+ }
650
+
651
+ type GraphValidationCode = "unknownTarget" | "unknownSource" | "missingInitialState" | "multipleInitialStates" | "invalidEventName" | "invalidConditionName" | "orphanState";
652
+ declare class GraphValidationError extends FinitaError {
653
+ readonly code: GraphValidationCode;
654
+ readonly details: Readonly<Record<string, unknown>>;
655
+ constructor(code: GraphValidationCode, message: string, details?: Record<string, unknown>);
656
+ }
657
+
658
+ interface DuplicateTransitionConflict {
659
+ fromState: string;
660
+ toState: string;
661
+ eventName: string | null;
662
+ existingConditionName: string | null;
663
+ newConditionName: string | null;
664
+ }
665
+ declare class DuplicateTransitionError extends FinitaError {
666
+ readonly code = "duplicateTransition";
667
+ readonly conflict: Readonly<DuplicateTransitionConflict>;
668
+ constructor(conflict: DuplicateTransitionConflict);
669
+ }
670
+
671
+ declare class StateNotFoundError extends FinitaError {
672
+ readonly code = "stateNotFound";
673
+ readonly stateName: string;
674
+ readonly availableStates: readonly string[];
675
+ constructor(stateName: string, availableStates: Iterable<string>);
676
+ }
677
+
678
+ declare class StateEventNotFoundError extends FinitaError {
679
+ readonly code = "stateEventNotFound";
680
+ readonly stateName: string;
681
+ readonly eventName: string;
682
+ constructor(stateName: string, eventName: string);
683
+ }
684
+
685
+ declare class ProcessNotFoundError extends FinitaError {
686
+ readonly code = "processNotFound";
687
+ readonly processName: string;
688
+ readonly availableProcesses: readonly string[];
689
+ constructor(processName: string, availableProcesses: Iterable<string>);
690
+ }
691
+
692
+ declare class InvalidSubjectError extends FinitaError {
693
+ readonly code = "invalidSubject";
694
+ readonly expectedInterface: string;
695
+ readonly missingMembers: readonly string[];
696
+ constructor(expectedInterface: string, missingMembers: Iterable<string>);
697
+ }
698
+
699
+ declare class AmbiguousTransitionError extends FinitaError {
700
+ readonly code = "ambiguousTransition";
701
+ readonly activeCount: number;
702
+ constructor(activeCount: number);
703
+ }
704
+
705
+ declare class AutomaticTransitionCycleError extends FinitaError {
706
+ readonly code = "automaticTransitionCycle";
707
+ readonly targetStateName: string;
708
+ readonly visitedStateNames: readonly string[];
709
+ constructor(targetStateName: string, visitedStateNames: Iterable<string>);
710
+ }
711
+
712
+ export { AbstractNamedProcessDetector, ActiveTransitionFilter, type AddStateOptions, type AddTransitionOptions, type AfterTransitionObserver, AmbiguousTransitionError, AndComposite, AutomaticTransitionCycleError, type BeforeTransitionObserver, type BuildOptions, CallbackCondition, type CallbackInterface, CallbackObserver, type ConditionCallbackFn, type ConditionInterface, Contradiction, type DispatcherInterface, type DotOptions, DuplicateStateError, type DuplicateTransitionConflict, DuplicateTransitionError, type EnqueueContext, Event, type EventInterface, Factory, type FactoryInterface, FilterStateByEvent, FilterStateByFinalState, FilterStateByTransition, FilterTransitionByEvent, FinitaError, type Graph, GraphBuilder, type GraphEdge, type GraphNode, type GraphValidationCode, GraphValidationError, InvalidSubjectError, type LastStateHasChangedDateInterface, type LockAdapterInterface, LockAdapterMutex, LockCanNotBeAcquiredError, type LoggerInterface, type MaybePromise, type MermaidOptions, type Metadata, MutexFactory, type MutexFactoryInterface, type MutexInterface, type Named, Not, NullMutex, type ObservableSubject, type Observer, OnEnterObserver, OneOrNoneActiveTransition, OrComposite, Process, ProcessBuilder, type ProcessDetectorInterface, ProcessFinalizedError, type ProcessInterface, ProcessNotFoundError, type ProposedTransitionFrame, ScoreTransition, SingleProcessDetector, State, type StateCollectionInterface, StateEventNotFoundError, type StateInterface, type StateNameDetectorInterface, StateNotFoundError, type StatefulInterface, StatefulStateNameDetector, StatefulStatusChanger, Statemachine, type StatemachineInterface, type StatemachineOptions, type StringConverter, Tautology, Timeout, Transition, type TransitionFrame, type TransitionInterface, TransitionLogger, type TransitionSelectorInterface, WeightTransition, type Weighted, WrongEventForStateError };