@camcima/finita 1.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/README.md +176 -0
- package/dist/Dispatcher.d.ts +11 -0
- package/dist/Dispatcher.d.ts.map +1 -0
- package/dist/Dispatcher.js +30 -0
- package/dist/Dispatcher.js.map +1 -0
- package/dist/Event.d.ts +22 -0
- package/dist/Event.d.ts.map +1 -0
- package/dist/Event.js +54 -0
- package/dist/Event.js.map +1 -0
- package/dist/MaybePromise.d.ts +2 -0
- package/dist/MaybePromise.d.ts.map +1 -0
- package/dist/MaybePromise.js +2 -0
- package/dist/MaybePromise.js.map +1 -0
- package/dist/Process.d.ts +15 -0
- package/dist/Process.d.ts.map +1 -0
- package/dist/Process.js +43 -0
- package/dist/Process.js.map +1 -0
- package/dist/State.d.ts +22 -0
- package/dist/State.d.ts.map +1 -0
- package/dist/State.js +65 -0
- package/dist/State.js.map +1 -0
- package/dist/StateCollection.d.ts +14 -0
- package/dist/StateCollection.d.ts.map +1 -0
- package/dist/StateCollection.js +37 -0
- package/dist/StateCollection.js.map +1 -0
- package/dist/Statemachine.d.ts +45 -0
- package/dist/Statemachine.d.ts.map +1 -0
- package/dist/Statemachine.js +206 -0
- package/dist/Statemachine.js.map +1 -0
- package/dist/Transition.d.ts +19 -0
- package/dist/Transition.d.ts.map +1 -0
- package/dist/Transition.js +46 -0
- package/dist/Transition.js.map +1 -0
- package/dist/condition/AndComposite.d.ts +9 -0
- package/dist/condition/AndComposite.d.ts.map +1 -0
- package/dist/condition/AndComposite.js +23 -0
- package/dist/condition/AndComposite.js.map +1 -0
- package/dist/condition/CallbackCondition.d.ts +11 -0
- package/dist/condition/CallbackCondition.d.ts.map +1 -0
- package/dist/condition/CallbackCondition.js +15 -0
- package/dist/condition/CallbackCondition.js.map +1 -0
- package/dist/condition/Contradiction.d.ts +8 -0
- package/dist/condition/Contradiction.d.ts.map +1 -0
- package/dist/condition/Contradiction.js +13 -0
- package/dist/condition/Contradiction.js.map +1 -0
- package/dist/condition/Not.d.ts +8 -0
- package/dist/condition/Not.d.ts.map +1 -0
- package/dist/condition/Not.js +13 -0
- package/dist/condition/Not.js.map +1 -0
- package/dist/condition/OrComposite.d.ts +9 -0
- package/dist/condition/OrComposite.d.ts.map +1 -0
- package/dist/condition/OrComposite.js +23 -0
- package/dist/condition/OrComposite.js.map +1 -0
- package/dist/condition/Tautology.d.ts +8 -0
- package/dist/condition/Tautology.d.ts.map +1 -0
- package/dist/condition/Tautology.js +13 -0
- package/dist/condition/Tautology.js.map +1 -0
- package/dist/condition/Timeout.d.ts +10 -0
- package/dist/condition/Timeout.d.ts.map +1 -0
- package/dist/condition/Timeout.js +30 -0
- package/dist/condition/Timeout.js.map +1 -0
- package/dist/condition/index.d.ts +9 -0
- package/dist/condition/index.d.ts.map +1 -0
- package/dist/condition/index.js +8 -0
- package/dist/condition/index.js.map +1 -0
- package/dist/error/DuplicateStateError.d.ts +5 -0
- package/dist/error/DuplicateStateError.d.ts.map +1 -0
- package/dist/error/DuplicateStateError.js +9 -0
- package/dist/error/DuplicateStateError.js.map +1 -0
- package/dist/error/LockCanNotBeAcquiredError.d.ts +4 -0
- package/dist/error/LockCanNotBeAcquiredError.d.ts.map +1 -0
- package/dist/error/LockCanNotBeAcquiredError.js +7 -0
- package/dist/error/LockCanNotBeAcquiredError.js.map +1 -0
- package/dist/error/WrongEventForStateError.d.ts +6 -0
- package/dist/error/WrongEventForStateError.d.ts.map +1 -0
- package/dist/error/WrongEventForStateError.js +11 -0
- package/dist/error/WrongEventForStateError.js.map +1 -0
- package/dist/error/index.d.ts +4 -0
- package/dist/error/index.d.ts.map +1 -0
- package/dist/error/index.js +4 -0
- package/dist/error/index.js.map +1 -0
- package/dist/factory/AbstractNamedProcessDetector.d.ts +10 -0
- package/dist/factory/AbstractNamedProcessDetector.d.ts.map +1 -0
- package/dist/factory/AbstractNamedProcessDetector.js +18 -0
- package/dist/factory/AbstractNamedProcessDetector.js.map +1 -0
- package/dist/factory/Factory.d.ts +22 -0
- package/dist/factory/Factory.d.ts.map +1 -0
- package/dist/factory/Factory.js +42 -0
- package/dist/factory/Factory.js.map +1 -0
- package/dist/factory/SingleProcessDetector.d.ts +8 -0
- package/dist/factory/SingleProcessDetector.d.ts.map +1 -0
- package/dist/factory/SingleProcessDetector.js +10 -0
- package/dist/factory/SingleProcessDetector.js.map +1 -0
- package/dist/factory/StatefulStateNameDetector.d.ts +5 -0
- package/dist/factory/StatefulStateNameDetector.d.ts.map +1 -0
- package/dist/factory/StatefulStateNameDetector.js +15 -0
- package/dist/factory/StatefulStateNameDetector.js.map +1 -0
- package/dist/factory/index.d.ts +5 -0
- package/dist/factory/index.d.ts.map +1 -0
- package/dist/factory/index.js +5 -0
- package/dist/factory/index.js.map +1 -0
- package/dist/filter/ActiveTransitionFilter.d.ts +6 -0
- package/dist/filter/ActiveTransitionFilter.d.ts.map +1 -0
- package/dist/filter/ActiveTransitionFilter.js +12 -0
- package/dist/filter/ActiveTransitionFilter.js.map +1 -0
- package/dist/filter/FilterStateByEvent.d.ts +5 -0
- package/dist/filter/FilterStateByEvent.d.ts.map +1 -0
- package/dist/filter/FilterStateByEvent.js +10 -0
- package/dist/filter/FilterStateByEvent.js.map +1 -0
- package/dist/filter/FilterStateByFinalState.d.ts +5 -0
- package/dist/filter/FilterStateByFinalState.d.ts.map +1 -0
- package/dist/filter/FilterStateByFinalState.js +15 -0
- package/dist/filter/FilterStateByFinalState.js.map +1 -0
- package/dist/filter/FilterStateByTransition.d.ts +8 -0
- package/dist/filter/FilterStateByTransition.d.ts.map +1 -0
- package/dist/filter/FilterStateByTransition.js +16 -0
- package/dist/filter/FilterStateByTransition.js.map +1 -0
- package/dist/filter/FilterTransitionByEvent.d.ts +5 -0
- package/dist/filter/FilterTransitionByEvent.d.ts.map +1 -0
- package/dist/filter/FilterTransitionByEvent.js +10 -0
- package/dist/filter/FilterTransitionByEvent.js.map +1 -0
- package/dist/filter/index.d.ts +6 -0
- package/dist/filter/index.d.ts.map +1 -0
- package/dist/filter/index.js +6 -0
- package/dist/filter/index.js.map +1 -0
- package/dist/graph/GraphBuilder.d.ts +37 -0
- package/dist/graph/GraphBuilder.d.ts.map +1 -0
- package/dist/graph/GraphBuilder.js +132 -0
- package/dist/graph/GraphBuilder.js.map +1 -0
- package/dist/graph/index.d.ts +3 -0
- package/dist/graph/index.d.ts.map +1 -0
- package/dist/graph/index.js +2 -0
- package/dist/graph/index.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +27 -0
- package/dist/index.js.map +1 -0
- package/dist/interfaces/ConditionInterface.d.ts +6 -0
- package/dist/interfaces/ConditionInterface.d.ts.map +1 -0
- package/dist/interfaces/ConditionInterface.js +2 -0
- package/dist/interfaces/ConditionInterface.js.map +1 -0
- package/dist/interfaces/DispatcherInterface.d.ts +11 -0
- package/dist/interfaces/DispatcherInterface.d.ts.map +1 -0
- package/dist/interfaces/DispatcherInterface.js +2 -0
- package/dist/interfaces/DispatcherInterface.js.map +1 -0
- package/dist/interfaces/EventInterface.d.ts +12 -0
- package/dist/interfaces/EventInterface.d.ts.map +1 -0
- package/dist/interfaces/EventInterface.js +2 -0
- package/dist/interfaces/EventInterface.js.map +1 -0
- package/dist/interfaces/FactoryInterface.d.ts +13 -0
- package/dist/interfaces/FactoryInterface.d.ts.map +1 -0
- package/dist/interfaces/FactoryInterface.js +2 -0
- package/dist/interfaces/FactoryInterface.js.map +1 -0
- package/dist/interfaces/LastStateHasChangedDateInterface.d.ts +4 -0
- package/dist/interfaces/LastStateHasChangedDateInterface.d.ts.map +1 -0
- package/dist/interfaces/LastStateHasChangedDateInterface.js +2 -0
- package/dist/interfaces/LastStateHasChangedDateInterface.js.map +1 -0
- package/dist/interfaces/LockAdapterInterface.d.ts +7 -0
- package/dist/interfaces/LockAdapterInterface.d.ts.map +1 -0
- package/dist/interfaces/LockAdapterInterface.js +2 -0
- package/dist/interfaces/LockAdapterInterface.js.map +1 -0
- package/dist/interfaces/LoggerInterface.d.ts +4 -0
- package/dist/interfaces/LoggerInterface.d.ts.map +1 -0
- package/dist/interfaces/LoggerInterface.js +2 -0
- package/dist/interfaces/LoggerInterface.js.map +1 -0
- package/dist/interfaces/Metadata.d.ts +4 -0
- package/dist/interfaces/Metadata.d.ts.map +1 -0
- package/dist/interfaces/Metadata.js +2 -0
- package/dist/interfaces/Metadata.js.map +1 -0
- package/dist/interfaces/MutexFactoryInterface.d.ts +6 -0
- package/dist/interfaces/MutexFactoryInterface.d.ts.map +1 -0
- package/dist/interfaces/MutexFactoryInterface.js +2 -0
- package/dist/interfaces/MutexFactoryInterface.js.map +1 -0
- package/dist/interfaces/MutexInterface.d.ts +8 -0
- package/dist/interfaces/MutexInterface.d.ts.map +1 -0
- package/dist/interfaces/MutexInterface.js +2 -0
- package/dist/interfaces/MutexInterface.js.map +1 -0
- package/dist/interfaces/Named.d.ts +4 -0
- package/dist/interfaces/Named.d.ts.map +1 -0
- package/dist/interfaces/Named.js +2 -0
- package/dist/interfaces/Named.js.map +1 -0
- package/dist/interfaces/Observer.d.ts +11 -0
- package/dist/interfaces/Observer.d.ts.map +1 -0
- package/dist/interfaces/Observer.js +2 -0
- package/dist/interfaces/Observer.js.map +1 -0
- package/dist/interfaces/ProcessDetectorInterface.d.ts +5 -0
- package/dist/interfaces/ProcessDetectorInterface.d.ts.map +1 -0
- package/dist/interfaces/ProcessDetectorInterface.js +2 -0
- package/dist/interfaces/ProcessDetectorInterface.js.map +1 -0
- package/dist/interfaces/ProcessInterface.d.ts +7 -0
- package/dist/interfaces/ProcessInterface.d.ts.map +1 -0
- package/dist/interfaces/ProcessInterface.js +2 -0
- package/dist/interfaces/ProcessInterface.js.map +1 -0
- package/dist/interfaces/StateCollectionInterface.d.ts +7 -0
- package/dist/interfaces/StateCollectionInterface.d.ts.map +1 -0
- package/dist/interfaces/StateCollectionInterface.js +2 -0
- package/dist/interfaces/StateCollectionInterface.js.map +1 -0
- package/dist/interfaces/StateInterface.d.ts +16 -0
- package/dist/interfaces/StateInterface.d.ts.map +1 -0
- package/dist/interfaces/StateInterface.js +2 -0
- package/dist/interfaces/StateInterface.js.map +1 -0
- package/dist/interfaces/StateNameDetectorInterface.d.ts +4 -0
- package/dist/interfaces/StateNameDetectorInterface.d.ts.map +1 -0
- package/dist/interfaces/StateNameDetectorInterface.js +2 -0
- package/dist/interfaces/StateNameDetectorInterface.js.map +1 -0
- package/dist/interfaces/StatefulInterface.d.ts +5 -0
- package/dist/interfaces/StatefulInterface.d.ts.map +1 -0
- package/dist/interfaces/StatefulInterface.js +2 -0
- package/dist/interfaces/StatefulInterface.js.map +1 -0
- package/dist/interfaces/StatemachineInterface.d.ts +20 -0
- package/dist/interfaces/StatemachineInterface.d.ts.map +1 -0
- package/dist/interfaces/StatemachineInterface.js +2 -0
- package/dist/interfaces/StatemachineInterface.js.map +1 -0
- package/dist/interfaces/TransitionInterface.d.ts +12 -0
- package/dist/interfaces/TransitionInterface.d.ts.map +1 -0
- package/dist/interfaces/TransitionInterface.js +2 -0
- package/dist/interfaces/TransitionInterface.js.map +1 -0
- package/dist/interfaces/TransitionSelectorInterface.d.ts +5 -0
- package/dist/interfaces/TransitionSelectorInterface.d.ts.map +1 -0
- package/dist/interfaces/TransitionSelectorInterface.js +2 -0
- package/dist/interfaces/TransitionSelectorInterface.js.map +1 -0
- package/dist/interfaces/Weighted.d.ts +4 -0
- package/dist/interfaces/Weighted.d.ts.map +1 -0
- package/dist/interfaces/Weighted.js +2 -0
- package/dist/interfaces/Weighted.js.map +1 -0
- package/dist/interfaces/index.d.ts +24 -0
- package/dist/interfaces/index.d.ts.map +1 -0
- package/dist/interfaces/index.js +2 -0
- package/dist/interfaces/index.js.map +1 -0
- package/dist/mutex/LockAdapterMutex.d.ts +13 -0
- package/dist/mutex/LockAdapterMutex.d.ts.map +1 -0
- package/dist/mutex/LockAdapterMutex.js +32 -0
- package/dist/mutex/LockAdapterMutex.js.map +1 -0
- package/dist/mutex/MutexFactory.d.ts +11 -0
- package/dist/mutex/MutexFactory.d.ts.map +1 -0
- package/dist/mutex/MutexFactory.js +13 -0
- package/dist/mutex/MutexFactory.js.map +1 -0
- package/dist/mutex/NullMutex.d.ts +9 -0
- package/dist/mutex/NullMutex.d.ts.map +1 -0
- package/dist/mutex/NullMutex.js +18 -0
- package/dist/mutex/NullMutex.js.map +1 -0
- package/dist/mutex/index.d.ts +5 -0
- package/dist/mutex/index.d.ts.map +1 -0
- package/dist/mutex/index.js +4 -0
- package/dist/mutex/index.js.map +1 -0
- package/dist/observer/CallbackObserver.d.ts +8 -0
- package/dist/observer/CallbackObserver.d.ts.map +1 -0
- package/dist/observer/CallbackObserver.js +14 -0
- package/dist/observer/CallbackObserver.js.map +1 -0
- package/dist/observer/OnEnterObserver.d.ts +8 -0
- package/dist/observer/OnEnterObserver.d.ts.map +1 -0
- package/dist/observer/OnEnterObserver.js +28 -0
- package/dist/observer/OnEnterObserver.js.map +1 -0
- package/dist/observer/StatefulStatusChanger.d.ts +5 -0
- package/dist/observer/StatefulStatusChanger.d.ts.map +1 -0
- package/dist/observer/StatefulStatusChanger.js +24 -0
- package/dist/observer/StatefulStatusChanger.js.map +1 -0
- package/dist/observer/TransitionLogger.d.ts +9 -0
- package/dist/observer/TransitionLogger.d.ts.map +1 -0
- package/dist/observer/TransitionLogger.js +62 -0
- package/dist/observer/TransitionLogger.js.map +1 -0
- package/dist/observer/index.d.ts +5 -0
- package/dist/observer/index.d.ts.map +1 -0
- package/dist/observer/index.js +5 -0
- package/dist/observer/index.js.map +1 -0
- package/dist/selector/OneOrNoneActiveTransition.d.ts +6 -0
- package/dist/selector/OneOrNoneActiveTransition.d.ts.map +1 -0
- package/dist/selector/OneOrNoneActiveTransition.js +14 -0
- package/dist/selector/OneOrNoneActiveTransition.js.map +1 -0
- package/dist/selector/ScoreTransition.d.ts +9 -0
- package/dist/selector/ScoreTransition.d.ts.map +1 -0
- package/dist/selector/ScoreTransition.js +33 -0
- package/dist/selector/ScoreTransition.js.map +1 -0
- package/dist/selector/WeightTransition.d.ts +9 -0
- package/dist/selector/WeightTransition.d.ts.map +1 -0
- package/dist/selector/WeightTransition.js +26 -0
- package/dist/selector/WeightTransition.js.map +1 -0
- package/dist/selector/index.d.ts +4 -0
- package/dist/selector/index.d.ts.map +1 -0
- package/dist/selector/index.js +4 -0
- package/dist/selector/index.js.map +1 -0
- package/dist/util/SetupHelper.d.ts +17 -0
- package/dist/util/SetupHelper.d.ts.map +1 -0
- package/dist/util/SetupHelper.js +48 -0
- package/dist/util/SetupHelper.js.map +1 -0
- package/dist/util/StateCollectionMerger.d.ts +23 -0
- package/dist/util/StateCollectionMerger.d.ts.map +1 -0
- package/dist/util/StateCollectionMerger.js +83 -0
- package/dist/util/StateCollectionMerger.js.map +1 -0
- package/dist/util/index.d.ts +3 -0
- package/dist/util/index.d.ts.map +1 -0
- package/dist/util/index.js +3 -0
- package/dist/util/index.js.map +1 -0
- package/package.json +52 -0
package/README.md
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
<picture>
|
|
4
|
+
<img alt="finita" src="assets/logo.svg" width="480">
|
|
5
|
+
</picture>
|
|
6
|
+
|
|
7
|
+
<br>
|
|
8
|
+
|
|
9
|
+
[](https://github.com/camcima/finita/actions/workflows/ci.yml)
|
|
10
|
+
[](https://codecov.io/gh/camcima/finita)
|
|
11
|
+
[](https://www.npmjs.com/package/finita)
|
|
12
|
+
[](https://opensource.org/licenses/MIT)
|
|
13
|
+
[](https://www.typescriptlang.org/)
|
|
14
|
+
[](https://nodejs.org/)
|
|
15
|
+
|
|
16
|
+
</div>
|
|
17
|
+
|
|
18
|
+
A full-featured finite state machine (FSM) library for TypeScript.
|
|
19
|
+
|
|
20
|
+
This library is a TypeScript port of [metabor/statemachine](https://github.com/Metabor/Statemachine), the PHP state machine library created by **Oliver Tischlinger**. The original library was the engine behind _Bob_ -- the backend component of the _Alice & Bob_ retail system that [Rocket Internet](https://www.rocket-internet.com/) used to power its e-commerce ventures worldwide. The author of this TypeScript port and Oliver worked together at Rocket Internet, where the state machine proved itself at scale across multiple global operations.
|
|
21
|
+
|
|
22
|
+
## Features
|
|
23
|
+
|
|
24
|
+
- **Async-First** -- all conditions, observers, and mutexes support async operations via `MaybePromise<T>` return types
|
|
25
|
+
- **States, Transitions, Events** -- define complex workflows declaratively
|
|
26
|
+
- **Conditions (Guards)** -- control when transitions are allowed, with composable AND/OR/NOT logic
|
|
27
|
+
- **Observers (Commands)** -- execute side effects when events fire or states change
|
|
28
|
+
- **Automatic Transitions** -- transitions that fire when a condition becomes true, without an explicit event
|
|
29
|
+
- **Transition Selectors** -- pluggable strategies for resolving ambiguous transitions (score-based, weight-based)
|
|
30
|
+
- **Mutex/Locking** -- concurrency control with pluggable lock adapters
|
|
31
|
+
- **Factory Pattern** -- create pre-configured state machines from subject objects
|
|
32
|
+
- **Process Merging** -- combine state collections with optional name prefixing
|
|
33
|
+
- **Graph Visualization** -- build graph data structures for rendering with GraphViz or other tools
|
|
34
|
+
- **Setup Helper** -- fluent API for building state machines from configuration
|
|
35
|
+
- **Zero Dependencies** -- no runtime dependencies
|
|
36
|
+
|
|
37
|
+
## Installation
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
npm install finita
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Quick Start
|
|
44
|
+
|
|
45
|
+
```mermaid
|
|
46
|
+
stateDiagram-v2
|
|
47
|
+
[*] --> draft
|
|
48
|
+
draft --> published : publish
|
|
49
|
+
published --> archived : archive
|
|
50
|
+
archived --> draft : reopen
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
import { State, Transition, Process, Statemachine } from "finita";
|
|
55
|
+
|
|
56
|
+
// Define states
|
|
57
|
+
const draft = new State("draft");
|
|
58
|
+
const published = new State("published");
|
|
59
|
+
const archived = new State("archived");
|
|
60
|
+
|
|
61
|
+
// Define transitions
|
|
62
|
+
draft.addTransition(new Transition(published, "publish"));
|
|
63
|
+
published.addTransition(new Transition(archived, "archive"));
|
|
64
|
+
archived.addTransition(new Transition(draft, "reopen"));
|
|
65
|
+
|
|
66
|
+
// Create process and state machine
|
|
67
|
+
const process = new Process("article-workflow", draft);
|
|
68
|
+
const article = { title: "Hello World" };
|
|
69
|
+
const sm = new Statemachine(article, process);
|
|
70
|
+
|
|
71
|
+
console.log(sm.getCurrentState().getName()); // 'draft'
|
|
72
|
+
|
|
73
|
+
await sm.triggerEvent("publish");
|
|
74
|
+
console.log(sm.getCurrentState().getName()); // 'published'
|
|
75
|
+
|
|
76
|
+
await sm.triggerEvent("archive");
|
|
77
|
+
console.log(sm.getCurrentState().getName()); // 'archived'
|
|
78
|
+
|
|
79
|
+
// Note: use top-level await (supported in ES modules) or wrap in an async function.
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Concepts
|
|
83
|
+
|
|
84
|
+
A state machine consists of:
|
|
85
|
+
|
|
86
|
+
| Concept | Description |
|
|
87
|
+
| ---------------- | -------------------------------------------------------------------------------------------------------------------- |
|
|
88
|
+
| **State** | A named node in the workflow graph. Holds transitions, events, and metadata. |
|
|
89
|
+
| **Transition** | A directed edge from one state to another, optionally guarded by a condition and triggered by an event. |
|
|
90
|
+
| **Event** | A named trigger attached to a state. When invoked, it fires observers (commands) and initiates transitions. |
|
|
91
|
+
| **Condition** | A guard that determines whether a transition is active. |
|
|
92
|
+
| **Process** | A named collection of states that defines a complete workflow, starting from an initial state. |
|
|
93
|
+
| **Statemachine** | The runtime orchestrator that manages the current state, triggers events, checks conditions, and notifies observers. |
|
|
94
|
+
| **Observer** | A callback that reacts to events or state changes. |
|
|
95
|
+
|
|
96
|
+
```mermaid
|
|
97
|
+
classDiagram
|
|
98
|
+
direction LR
|
|
99
|
+
Process *-- State : contains
|
|
100
|
+
State *-- Transition : has outgoing
|
|
101
|
+
State *-- Event : has named
|
|
102
|
+
Transition --> State : targets
|
|
103
|
+
Transition --> Condition : guarded by
|
|
104
|
+
Event --> Observer : notifies
|
|
105
|
+
Statemachine --> Process : uses
|
|
106
|
+
Statemachine --> State : tracks current
|
|
107
|
+
Statemachine --> Observer : notifies on change
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Documentation
|
|
111
|
+
|
|
112
|
+
Detailed documentation for every component:
|
|
113
|
+
|
|
114
|
+
- **[Core](docs/core.md)** -- State, Transition, Event, Process, Statemachine, Dispatcher, StateCollection
|
|
115
|
+
- **[Conditions](docs/conditions.md)** -- Tautology, Contradiction, CallbackCondition, Timeout, AndComposite, OrComposite, Not
|
|
116
|
+
- **[Observers](docs/observers.md)** -- CallbackObserver, StatefulStatusChanger, OnEnterObserver, TransitionLogger
|
|
117
|
+
- **[Filters](docs/filters.md)** -- ActiveTransitionFilter, FilterStateByEvent, FilterStateByTransition, FilterStateByFinalState, FilterTransitionByEvent
|
|
118
|
+
- **[Selectors](docs/selectors.md)** -- OneOrNoneActiveTransition, ScoreTransition, WeightTransition
|
|
119
|
+
- **[Mutex](docs/mutex.md)** -- NullMutex, LockAdapterMutex, MutexFactory
|
|
120
|
+
- **[Factory](docs/factory.md)** -- Factory, SingleProcessDetector, AbstractNamedProcessDetector, StatefulStateNameDetector
|
|
121
|
+
- **[Utilities](docs/utilities.md)** -- SetupHelper, StateCollectionMerger
|
|
122
|
+
- **[Graph](docs/graph.md)** -- GraphBuilder
|
|
123
|
+
- **[Errors](docs/errors.md)** -- WrongEventForStateError, LockCanNotBeAcquiredError, DuplicateStateError
|
|
124
|
+
- **[Interfaces](docs/interfaces.md)** -- All TypeScript interfaces
|
|
125
|
+
|
|
126
|
+
## Examples
|
|
127
|
+
|
|
128
|
+
A complete working example (order processing with prepayment and postpayment workflows) is available in the [finita-example](https://github.com/camcima/finita-example) repository.
|
|
129
|
+
|
|
130
|
+
## Architecture
|
|
131
|
+
|
|
132
|
+
```
|
|
133
|
+
src/
|
|
134
|
+
index.ts # Barrel export
|
|
135
|
+
MaybePromise.ts # MaybePromise<T> = T | Promise<T> utility type
|
|
136
|
+
Event.ts # Event implementation
|
|
137
|
+
State.ts # State implementation
|
|
138
|
+
Transition.ts # Transition implementation
|
|
139
|
+
StateCollection.ts # Named collection of states
|
|
140
|
+
Process.ts # Process (workflow definition)
|
|
141
|
+
Statemachine.ts # Runtime state machine
|
|
142
|
+
Dispatcher.ts # Deferred event dispatcher
|
|
143
|
+
interfaces/ # All TypeScript interfaces
|
|
144
|
+
condition/ # Condition (guard) implementations
|
|
145
|
+
observer/ # Observer implementations
|
|
146
|
+
filter/ # State and transition filters
|
|
147
|
+
selector/ # Transition selection strategies
|
|
148
|
+
mutex/ # Locking implementations
|
|
149
|
+
factory/ # State machine factory pattern
|
|
150
|
+
util/ # SetupHelper, StateCollectionMerger
|
|
151
|
+
graph/ # Graph visualization builder
|
|
152
|
+
error/ # Custom error classes
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
## Development
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
# Install dependencies
|
|
159
|
+
npm install
|
|
160
|
+
|
|
161
|
+
# Run tests
|
|
162
|
+
npm test
|
|
163
|
+
|
|
164
|
+
# Run tests in watch mode
|
|
165
|
+
npm run test:watch
|
|
166
|
+
|
|
167
|
+
# Type check
|
|
168
|
+
npm run lint
|
|
169
|
+
|
|
170
|
+
# Build
|
|
171
|
+
npm run build
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## License
|
|
175
|
+
|
|
176
|
+
MIT
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { DispatcherInterface, CallbackInterface } from "./interfaces/DispatcherInterface.js";
|
|
2
|
+
import type { EventInterface } from "./interfaces/EventInterface.js";
|
|
3
|
+
export declare class Dispatcher implements DispatcherInterface {
|
|
4
|
+
private commands;
|
|
5
|
+
private onReadyCallbacks;
|
|
6
|
+
private ready;
|
|
7
|
+
dispatch(event: EventInterface, args?: unknown[], onReadyCallback?: CallbackInterface): void;
|
|
8
|
+
invoke(): Promise<void>;
|
|
9
|
+
isReady(): boolean;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=Dispatcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Dispatcher.d.ts","sourceRoot":"","sources":["../src/Dispatcher.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,mBAAmB,EACnB,iBAAiB,EAClB,MAAM,qCAAqC,CAAC;AAC7C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAErE,qBAAa,UAAW,YAAW,mBAAmB;IACpD,OAAO,CAAC,QAAQ,CAAyD;IACzE,OAAO,CAAC,gBAAgB,CAA2B;IACnD,OAAO,CAAC,KAAK,CAAS;IAEtB,QAAQ,CACN,KAAK,EAAE,cAAc,EACrB,IAAI,GAAE,OAAO,EAAO,EACpB,eAAe,CAAC,EAAE,iBAAiB,GAClC,IAAI;IAUD,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAa7B,OAAO,IAAI,OAAO;CAGnB"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export class Dispatcher {
|
|
2
|
+
commands = [];
|
|
3
|
+
onReadyCallbacks = [];
|
|
4
|
+
ready = false;
|
|
5
|
+
dispatch(event, args = [], onReadyCallback) {
|
|
6
|
+
if (this.ready) {
|
|
7
|
+
throw new Error("Was already invoked!");
|
|
8
|
+
}
|
|
9
|
+
this.commands.push({ event, args });
|
|
10
|
+
if (onReadyCallback) {
|
|
11
|
+
this.onReadyCallbacks.push(onReadyCallback);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
async invoke() {
|
|
15
|
+
if (this.ready) {
|
|
16
|
+
throw new Error("Was already invoked!");
|
|
17
|
+
}
|
|
18
|
+
for (const { event, args } of this.commands) {
|
|
19
|
+
await event.invoke(...args);
|
|
20
|
+
}
|
|
21
|
+
this.ready = true;
|
|
22
|
+
for (const callback of this.onReadyCallbacks) {
|
|
23
|
+
await callback.invoke();
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
isReady() {
|
|
27
|
+
return this.ready;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=Dispatcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Dispatcher.js","sourceRoot":"","sources":["../src/Dispatcher.ts"],"names":[],"mappings":"AAMA,MAAM,OAAO,UAAU;IACb,QAAQ,GAAsD,EAAE,CAAC;IACjE,gBAAgB,GAAwB,EAAE,CAAC;IAC3C,KAAK,GAAG,KAAK,CAAC;IAEtB,QAAQ,CACN,KAAqB,EACrB,OAAkB,EAAE,EACpB,eAAmC;QAEnC,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;QAC1C,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACpC,IAAI,eAAe,EAAE,CAAC;YACpB,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;IAED,KAAK,CAAC,MAAM;QACV,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;QAC1C,CAAC;QACD,KAAK,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC5C,MAAM,KAAK,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC;QAC9B,CAAC;QACD,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QAClB,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC7C,MAAM,QAAQ,CAAC,MAAM,EAAE,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,OAAO;QACL,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;CACF"}
|
package/dist/Event.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { EventInterface } from "./interfaces/EventInterface.js";
|
|
2
|
+
import type { Observer } from "./interfaces/Observer.js";
|
|
3
|
+
export declare class Event implements EventInterface {
|
|
4
|
+
private readonly name;
|
|
5
|
+
private readonly observers;
|
|
6
|
+
private readonly metadata;
|
|
7
|
+
private invokeArgs;
|
|
8
|
+
constructor(name: string);
|
|
9
|
+
getName(): string;
|
|
10
|
+
getInvokeArgs(): unknown[];
|
|
11
|
+
invoke(...args: unknown[]): Promise<void>;
|
|
12
|
+
attach(observer: Observer): void;
|
|
13
|
+
detach(observer: Observer): void;
|
|
14
|
+
notify(): Promise<void>;
|
|
15
|
+
getObservers(): Iterable<Observer>;
|
|
16
|
+
getMetadata(): Record<string, unknown>;
|
|
17
|
+
getMetadataValue(key: string): unknown;
|
|
18
|
+
setMetadataValue(key: string, value: unknown): void;
|
|
19
|
+
hasMetadataValue(key: string): boolean;
|
|
20
|
+
deleteMetadataValue(key: string): void;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=Event.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Event.d.ts","sourceRoot":"","sources":["../src/Event.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAEzD,qBAAa,KAAM,YAAW,cAAc;IAC1C,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA4B;IACtD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAmC;IAC5D,OAAO,CAAC,UAAU,CAAiB;gBAEvB,IAAI,EAAE,MAAM;IAIxB,OAAO,IAAI,MAAM;IAIjB,aAAa,IAAI,OAAO,EAAE;IAIpB,MAAM,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAS/C,MAAM,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IAIhC,MAAM,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IAI1B,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAM7B,YAAY,IAAI,QAAQ,CAAC,QAAQ,CAAC;IAIlC,WAAW,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAItC,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAItC,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI;IAInD,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAItC,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;CAGvC"}
|
package/dist/Event.js
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
export class Event {
|
|
2
|
+
name;
|
|
3
|
+
observers = new Set();
|
|
4
|
+
metadata = new Map();
|
|
5
|
+
invokeArgs = [];
|
|
6
|
+
constructor(name) {
|
|
7
|
+
this.name = name;
|
|
8
|
+
}
|
|
9
|
+
getName() {
|
|
10
|
+
return this.name;
|
|
11
|
+
}
|
|
12
|
+
getInvokeArgs() {
|
|
13
|
+
return this.invokeArgs;
|
|
14
|
+
}
|
|
15
|
+
async invoke(...args) {
|
|
16
|
+
this.invokeArgs = args;
|
|
17
|
+
try {
|
|
18
|
+
await this.notify();
|
|
19
|
+
}
|
|
20
|
+
finally {
|
|
21
|
+
this.invokeArgs = [];
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
attach(observer) {
|
|
25
|
+
this.observers.add(observer);
|
|
26
|
+
}
|
|
27
|
+
detach(observer) {
|
|
28
|
+
this.observers.delete(observer);
|
|
29
|
+
}
|
|
30
|
+
async notify() {
|
|
31
|
+
for (const observer of this.observers) {
|
|
32
|
+
await observer.update(this);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
getObservers() {
|
|
36
|
+
return this.observers;
|
|
37
|
+
}
|
|
38
|
+
getMetadata() {
|
|
39
|
+
return Object.fromEntries(this.metadata);
|
|
40
|
+
}
|
|
41
|
+
getMetadataValue(key) {
|
|
42
|
+
return this.metadata.get(key);
|
|
43
|
+
}
|
|
44
|
+
setMetadataValue(key, value) {
|
|
45
|
+
this.metadata.set(key, value);
|
|
46
|
+
}
|
|
47
|
+
hasMetadataValue(key) {
|
|
48
|
+
return this.metadata.has(key);
|
|
49
|
+
}
|
|
50
|
+
deleteMetadataValue(key) {
|
|
51
|
+
this.metadata.delete(key);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=Event.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Event.js","sourceRoot":"","sources":["../src/Event.ts"],"names":[],"mappings":"AAGA,MAAM,OAAO,KAAK;IACC,IAAI,CAAS;IACb,SAAS,GAAkB,IAAI,GAAG,EAAE,CAAC;IACrC,QAAQ,GAAyB,IAAI,GAAG,EAAE,CAAC;IACpD,UAAU,GAAc,EAAE,CAAC;IAEnC,YAAY,IAAY;QACtB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IAED,OAAO;QACL,OAAO,IAAI,CAAC,IAAI,CAAC;IACnB,CAAC;IAED,aAAa;QACX,OAAO,IAAI,CAAC,UAAU,CAAC;IACzB,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,GAAG,IAAe;QAC7B,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACvB,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC;QACtB,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,UAAU,GAAG,EAAE,CAAC;QACvB,CAAC;IACH,CAAC;IAED,MAAM,CAAC,QAAkB;QACvB,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC/B,CAAC;IAED,MAAM,CAAC,QAAkB;QACvB,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAClC,CAAC;IAED,KAAK,CAAC,MAAM;QACV,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACtC,MAAM,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC9B,CAAC;IACH,CAAC;IAED,YAAY;QACV,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;IAED,WAAW;QACT,OAAO,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC3C,CAAC;IAED,gBAAgB,CAAC,GAAW;QAC1B,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAChC,CAAC;IAED,gBAAgB,CAAC,GAAW,EAAE,KAAc;QAC1C,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAChC,CAAC;IAED,gBAAgB,CAAC,GAAW;QAC1B,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAChC,CAAC;IAED,mBAAmB,CAAC,GAAW;QAC7B,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC5B,CAAC;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MaybePromise.d.ts","sourceRoot":"","sources":["../src/MaybePromise.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MaybePromise.js","sourceRoot":"","sources":["../src/MaybePromise.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ProcessInterface } from "./interfaces/ProcessInterface.js";
|
|
2
|
+
import type { StateInterface } from "./interfaces/StateInterface.js";
|
|
3
|
+
export declare class Process implements ProcessInterface {
|
|
4
|
+
private readonly name;
|
|
5
|
+
private readonly initialState;
|
|
6
|
+
private readonly states;
|
|
7
|
+
constructor(name: string, initialState: StateInterface);
|
|
8
|
+
private registerState;
|
|
9
|
+
getName(): string;
|
|
10
|
+
getInitialState(): StateInterface;
|
|
11
|
+
getStates(): Iterable<StateInterface>;
|
|
12
|
+
getState(name: string): StateInterface;
|
|
13
|
+
hasState(name: string): boolean;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=Process.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Process.d.ts","sourceRoot":"","sources":["../src/Process.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AACzE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAKrE,qBAAa,OAAQ,YAAW,gBAAgB;IAC9C,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAiB;IAC9C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkB;gBAE7B,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,cAAc;IAOtD,OAAO,CAAC,aAAa;IAerB,OAAO,IAAI,MAAM;IAIjB,eAAe,IAAI,cAAc;IAIjC,SAAS,IAAI,QAAQ,CAAC,cAAc,CAAC;IAIrC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc;IAItC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;CAGhC"}
|
package/dist/Process.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { StateCollection } from "./StateCollection.js";
|
|
2
|
+
import { DuplicateStateError } from "./error/DuplicateStateError.js";
|
|
3
|
+
export class Process {
|
|
4
|
+
name;
|
|
5
|
+
initialState;
|
|
6
|
+
states;
|
|
7
|
+
constructor(name, initialState) {
|
|
8
|
+
this.name = name;
|
|
9
|
+
this.initialState = initialState;
|
|
10
|
+
this.states = new StateCollection();
|
|
11
|
+
this.registerState(initialState);
|
|
12
|
+
}
|
|
13
|
+
registerState(state) {
|
|
14
|
+
const name = state.getName();
|
|
15
|
+
if (this.states.hasState(name)) {
|
|
16
|
+
if (this.states.getState(name) !== state) {
|
|
17
|
+
throw new DuplicateStateError(name);
|
|
18
|
+
}
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
this.states.addState(state);
|
|
22
|
+
for (const transition of state.getTransitions()) {
|
|
23
|
+
const targetState = transition.getTargetState();
|
|
24
|
+
this.registerState(targetState);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
getName() {
|
|
28
|
+
return this.name;
|
|
29
|
+
}
|
|
30
|
+
getInitialState() {
|
|
31
|
+
return this.initialState;
|
|
32
|
+
}
|
|
33
|
+
getStates() {
|
|
34
|
+
return this.states.getStates();
|
|
35
|
+
}
|
|
36
|
+
getState(name) {
|
|
37
|
+
return this.states.getState(name);
|
|
38
|
+
}
|
|
39
|
+
hasState(name) {
|
|
40
|
+
return this.states.hasState(name);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=Process.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Process.js","sourceRoot":"","sources":["../src/Process.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AAErE,MAAM,OAAO,OAAO;IACD,IAAI,CAAS;IACb,YAAY,CAAiB;IAC7B,MAAM,CAAkB;IAEzC,YAAY,IAAY,EAAE,YAA4B;QACpD,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;QACjC,IAAI,CAAC,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;QACpC,IAAI,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC;IACnC,CAAC;IAEO,aAAa,CAAC,KAAqB;QACzC,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,EAAE,CAAC;QAC7B,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YAC/B,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,KAAK,EAAE,CAAC;gBACzC,MAAM,IAAI,mBAAmB,CAAC,IAAI,CAAC,CAAC;YACtC,CAAC;YACD,OAAO;QACT,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QAC5B,KAAK,MAAM,UAAU,IAAI,KAAK,CAAC,cAAc,EAAE,EAAE,CAAC;YAChD,MAAM,WAAW,GAAI,UAAkC,CAAC,cAAc,EAAE,CAAC;YACzE,IAAI,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC;QAClC,CAAC;IACH,CAAC;IAED,OAAO;QACL,OAAO,IAAI,CAAC,IAAI,CAAC;IACnB,CAAC;IAED,eAAe;QACb,OAAO,IAAI,CAAC,YAAY,CAAC;IAC3B,CAAC;IAED,SAAS;QACP,OAAO,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;IACjC,CAAC;IAED,QAAQ,CAAC,IAAY;QACnB,OAAO,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC;IAED,QAAQ,CAAC,IAAY;QACnB,OAAO,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC;CACF"}
|
package/dist/State.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { StateInterface } from "./interfaces/StateInterface.js";
|
|
2
|
+
import type { TransitionInterface } from "./interfaces/TransitionInterface.js";
|
|
3
|
+
import type { EventInterface } from "./interfaces/EventInterface.js";
|
|
4
|
+
export declare class State implements StateInterface {
|
|
5
|
+
private readonly name;
|
|
6
|
+
private readonly transitions;
|
|
7
|
+
private readonly events;
|
|
8
|
+
private readonly metadata;
|
|
9
|
+
constructor(name: string);
|
|
10
|
+
getName(): string;
|
|
11
|
+
getTransitions(): Iterable<TransitionInterface>;
|
|
12
|
+
addTransition(transition: TransitionInterface): void;
|
|
13
|
+
getEventNames(): string[];
|
|
14
|
+
hasEvent(name: string): boolean;
|
|
15
|
+
getEvent(name: string): EventInterface;
|
|
16
|
+
getMetadata(): Record<string, unknown>;
|
|
17
|
+
getMetadataValue(key: string): unknown;
|
|
18
|
+
setMetadataValue(key: string, value: unknown): void;
|
|
19
|
+
hasMetadataValue(key: string): boolean;
|
|
20
|
+
deleteMetadataValue(key: string): void;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=State.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"State.d.ts","sourceRoot":"","sources":["../src/State.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AAC/E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAGrE,qBAAa,KAAM,YAAW,cAAc;IAC1C,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAuC;IACnE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA0C;IACjE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAmC;gBAEhD,IAAI,EAAE,MAAM;IAIxB,OAAO,IAAI,MAAM;IAIjB,cAAc,IAAI,QAAQ,CAAC,mBAAmB,CAAC;IAI/C,aAAa,CAAC,UAAU,EAAE,mBAAmB,GAAG,IAAI;IAsBpD,aAAa,IAAI,MAAM,EAAE;IAIzB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAI/B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc;IAStC,WAAW,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAItC,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAItC,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI;IAInD,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAItC,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;CAGvC"}
|
package/dist/State.js
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { Event } from "./Event.js";
|
|
2
|
+
export class State {
|
|
3
|
+
name;
|
|
4
|
+
transitions = new Set();
|
|
5
|
+
events = new Map();
|
|
6
|
+
metadata = new Map();
|
|
7
|
+
constructor(name) {
|
|
8
|
+
this.name = name;
|
|
9
|
+
}
|
|
10
|
+
getName() {
|
|
11
|
+
return this.name;
|
|
12
|
+
}
|
|
13
|
+
getTransitions() {
|
|
14
|
+
return this.transitions;
|
|
15
|
+
}
|
|
16
|
+
addTransition(transition) {
|
|
17
|
+
if (this.transitions.has(transition)) {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
const targetName = transition.getTargetState().getName();
|
|
21
|
+
const eventName = transition.getEventName();
|
|
22
|
+
const conditionName = transition.getConditionName();
|
|
23
|
+
for (const existing of this.transitions) {
|
|
24
|
+
if (existing.getTargetState().getName() === targetName &&
|
|
25
|
+
existing.getEventName() === eventName &&
|
|
26
|
+
existing.getConditionName() === conditionName) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
this.transitions.add(transition);
|
|
31
|
+
if (eventName) {
|
|
32
|
+
this.getEvent(eventName);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
getEventNames() {
|
|
36
|
+
return Array.from(this.events.keys());
|
|
37
|
+
}
|
|
38
|
+
hasEvent(name) {
|
|
39
|
+
return this.events.has(name);
|
|
40
|
+
}
|
|
41
|
+
getEvent(name) {
|
|
42
|
+
let event = this.events.get(name);
|
|
43
|
+
if (!event) {
|
|
44
|
+
event = new Event(name);
|
|
45
|
+
this.events.set(name, event);
|
|
46
|
+
}
|
|
47
|
+
return event;
|
|
48
|
+
}
|
|
49
|
+
getMetadata() {
|
|
50
|
+
return Object.fromEntries(this.metadata);
|
|
51
|
+
}
|
|
52
|
+
getMetadataValue(key) {
|
|
53
|
+
return this.metadata.get(key);
|
|
54
|
+
}
|
|
55
|
+
setMetadataValue(key, value) {
|
|
56
|
+
this.metadata.set(key, value);
|
|
57
|
+
}
|
|
58
|
+
hasMetadataValue(key) {
|
|
59
|
+
return this.metadata.has(key);
|
|
60
|
+
}
|
|
61
|
+
deleteMetadataValue(key) {
|
|
62
|
+
this.metadata.delete(key);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=State.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"State.js","sourceRoot":"","sources":["../src/State.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC,MAAM,OAAO,KAAK;IACC,IAAI,CAAS;IACb,WAAW,GAA6B,IAAI,GAAG,EAAE,CAAC;IAClD,MAAM,GAAgC,IAAI,GAAG,EAAE,CAAC;IAChD,QAAQ,GAAyB,IAAI,GAAG,EAAE,CAAC;IAE5D,YAAY,IAAY;QACtB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IAED,OAAO;QACL,OAAO,IAAI,CAAC,IAAI,CAAC;IACnB,CAAC;IAED,cAAc;QACZ,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IAED,aAAa,CAAC,UAA+B;QAC3C,IAAI,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;YACrC,OAAO;QACT,CAAC;QACD,MAAM,UAAU,GAAG,UAAU,CAAC,cAAc,EAAE,CAAC,OAAO,EAAE,CAAC;QACzD,MAAM,SAAS,GAAG,UAAU,CAAC,YAAY,EAAE,CAAC;QAC5C,MAAM,aAAa,GAAG,UAAU,CAAC,gBAAgB,EAAE,CAAC;QACpD,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACxC,IACE,QAAQ,CAAC,cAAc,EAAE,CAAC,OAAO,EAAE,KAAK,UAAU;gBAClD,QAAQ,CAAC,YAAY,EAAE,KAAK,SAAS;gBACrC,QAAQ,CAAC,gBAAgB,EAAE,KAAK,aAAa,EAC7C,CAAC;gBACD,OAAO;YACT,CAAC;QACH,CAAC;QACD,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QACjC,IAAI,SAAS,EAAE,CAAC;YACd,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC;IAED,aAAa;QACX,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;IACxC,CAAC;IAED,QAAQ,CAAC,IAAY;QACnB,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC/B,CAAC;IAED,QAAQ,CAAC,IAAY;QACnB,IAAI,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAClC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,KAAK,GAAG,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC;YACxB,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAC/B,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,WAAW;QACT,OAAO,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC3C,CAAC;IAED,gBAAgB,CAAC,GAAW;QAC1B,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAChC,CAAC;IAED,gBAAgB,CAAC,GAAW,EAAE,KAAc;QAC1C,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAChC,CAAC;IAED,gBAAgB,CAAC,GAAW;QAC1B,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAChC,CAAC;IAED,mBAAmB,CAAC,GAAW;QAC7B,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC5B,CAAC;CACF"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { StateCollectionInterface } from "./interfaces/StateCollectionInterface.js";
|
|
2
|
+
import type { StateInterface } from "./interfaces/StateInterface.js";
|
|
3
|
+
import { StateCollectionMerger } from "./util/StateCollectionMerger.js";
|
|
4
|
+
export declare class StateCollection implements StateCollectionInterface {
|
|
5
|
+
private readonly states;
|
|
6
|
+
private stateCollectionMerger;
|
|
7
|
+
getState(name: string): StateInterface;
|
|
8
|
+
getStates(): Iterable<StateInterface>;
|
|
9
|
+
hasState(name: string): boolean;
|
|
10
|
+
addState(state: StateInterface): void;
|
|
11
|
+
getStateCollectionMerger(): StateCollectionMerger;
|
|
12
|
+
merge(source: StateCollectionInterface): void;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=StateCollection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StateCollection.d.ts","sourceRoot":"","sources":["../src/StateCollection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,0CAA0C,CAAC;AACzF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AAGxE,qBAAa,eAAgB,YAAW,wBAAwB;IAC9D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA0C;IACjE,OAAO,CAAC,qBAAqB,CAAsC;IAEnE,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc;IAQtC,SAAS,IAAI,QAAQ,CAAC,cAAc,CAAC;IAIrC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAI/B,QAAQ,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI;IAQrC,wBAAwB,IAAI,qBAAqB;IAOjD,KAAK,CAAC,MAAM,EAAE,wBAAwB,GAAG,IAAI;CAI9C"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { StateCollectionMerger } from "./util/StateCollectionMerger.js";
|
|
2
|
+
import { DuplicateStateError } from "./error/DuplicateStateError.js";
|
|
3
|
+
export class StateCollection {
|
|
4
|
+
states = new Map();
|
|
5
|
+
stateCollectionMerger = null;
|
|
6
|
+
getState(name) {
|
|
7
|
+
const state = this.states.get(name);
|
|
8
|
+
if (!state) {
|
|
9
|
+
throw new Error(`State "${name}" not found`);
|
|
10
|
+
}
|
|
11
|
+
return state;
|
|
12
|
+
}
|
|
13
|
+
getStates() {
|
|
14
|
+
return this.states.values();
|
|
15
|
+
}
|
|
16
|
+
hasState(name) {
|
|
17
|
+
return this.states.has(name);
|
|
18
|
+
}
|
|
19
|
+
addState(state) {
|
|
20
|
+
const existing = this.states.get(state.getName());
|
|
21
|
+
if (existing && existing !== state) {
|
|
22
|
+
throw new DuplicateStateError(state.getName());
|
|
23
|
+
}
|
|
24
|
+
this.states.set(state.getName(), state);
|
|
25
|
+
}
|
|
26
|
+
getStateCollectionMerger() {
|
|
27
|
+
if (!this.stateCollectionMerger) {
|
|
28
|
+
this.stateCollectionMerger = new StateCollectionMerger(this);
|
|
29
|
+
}
|
|
30
|
+
return this.stateCollectionMerger;
|
|
31
|
+
}
|
|
32
|
+
merge(source) {
|
|
33
|
+
const merger = this.getStateCollectionMerger();
|
|
34
|
+
merger.merge(source);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=StateCollection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StateCollection.js","sourceRoot":"","sources":["../src/StateCollection.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AACxE,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AAErE,MAAM,OAAO,eAAe;IACT,MAAM,GAAgC,IAAI,GAAG,EAAE,CAAC;IACzD,qBAAqB,GAAiC,IAAI,CAAC;IAEnE,QAAQ,CAAC,IAAY;QACnB,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACpC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,KAAK,CAAC,UAAU,IAAI,aAAa,CAAC,CAAC;QAC/C,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,SAAS;QACP,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;IAC9B,CAAC;IAED,QAAQ,CAAC,IAAY;QACnB,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC/B,CAAC;IAED,QAAQ,CAAC,KAAqB;QAC5B,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QAClD,IAAI,QAAQ,IAAI,QAAQ,KAAK,KAAK,EAAE,CAAC;YACnC,MAAM,IAAI,mBAAmB,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QACjD,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,KAAK,CAAC,CAAC;IAC1C,CAAC;IAED,wBAAwB;QACtB,IAAI,CAAC,IAAI,CAAC,qBAAqB,EAAE,CAAC;YAChC,IAAI,CAAC,qBAAqB,GAAG,IAAI,qBAAqB,CAAC,IAAI,CAAC,CAAC;QAC/D,CAAC;QACD,OAAO,IAAI,CAAC,qBAAqB,CAAC;IACpC,CAAC;IAED,KAAK,CAAC,MAAgC;QACpC,MAAM,MAAM,GAAG,IAAI,CAAC,wBAAwB,EAAE,CAAC;QAC/C,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACvB,CAAC;CACF"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { StatemachineInterface } from "./interfaces/StatemachineInterface.js";
|
|
2
|
+
import type { StateInterface } from "./interfaces/StateInterface.js";
|
|
3
|
+
import type { ProcessInterface } from "./interfaces/ProcessInterface.js";
|
|
4
|
+
import type { TransitionInterface } from "./interfaces/TransitionInterface.js";
|
|
5
|
+
import type { MutexInterface } from "./interfaces/MutexInterface.js";
|
|
6
|
+
import type { TransitionSelectorInterface } from "./interfaces/TransitionSelectorInterface.js";
|
|
7
|
+
import type { DispatcherInterface } from "./interfaces/DispatcherInterface.js";
|
|
8
|
+
import type { Observer } from "./interfaces/Observer.js";
|
|
9
|
+
export declare class Statemachine implements StatemachineInterface {
|
|
10
|
+
private readonly subject;
|
|
11
|
+
private currentState;
|
|
12
|
+
private lastState;
|
|
13
|
+
private readonly transitionSelector;
|
|
14
|
+
private selectedTransition;
|
|
15
|
+
private readonly process;
|
|
16
|
+
private readonly mutex;
|
|
17
|
+
private autoreleaseLock;
|
|
18
|
+
private dispatcher;
|
|
19
|
+
private currentEvent;
|
|
20
|
+
private currentContext;
|
|
21
|
+
private readonly observers;
|
|
22
|
+
constructor(subject: unknown, process: ProcessInterface, stateName?: string | null, transitionSelector?: TransitionSelectorInterface | null, mutex?: MutexInterface | null);
|
|
23
|
+
getProcess(): ProcessInterface;
|
|
24
|
+
getCurrentState(): StateInterface;
|
|
25
|
+
getLastState(): StateInterface | null;
|
|
26
|
+
getSubject(): unknown;
|
|
27
|
+
getSelectedTransition(): TransitionInterface | null;
|
|
28
|
+
getCurrentContext(): Map<string, unknown> | null;
|
|
29
|
+
private doCheckTransitions;
|
|
30
|
+
private onDispatcherReady;
|
|
31
|
+
dispatchEvent(dispatcher: DispatcherInterface, name: string, context?: Map<string, unknown>): Promise<void>;
|
|
32
|
+
triggerEvent(name: string, context?: Map<string, unknown>): Promise<void>;
|
|
33
|
+
checkTransitions(context?: Map<string, unknown>): Promise<void>;
|
|
34
|
+
private acquireLockOrThrowException;
|
|
35
|
+
isAutoreleaseLock(): boolean;
|
|
36
|
+
setAutoreleaseLock(autorelease: boolean): void;
|
|
37
|
+
acquireLock(): Promise<boolean>;
|
|
38
|
+
releaseLock(): Promise<void>;
|
|
39
|
+
isLockAcquired(): boolean;
|
|
40
|
+
attach(observer: Observer): void;
|
|
41
|
+
detach(observer: Observer): void;
|
|
42
|
+
notify(): Promise<void>;
|
|
43
|
+
getObservers(): Iterable<Observer>;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=Statemachine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Statemachine.d.ts","sourceRoot":"","sources":["../src/Statemachine.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uCAAuC,CAAC;AACnF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AACzE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AAE/E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,6CAA6C,CAAC;AAC/F,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AAC/E,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AASzD,qBAAa,YAAa,YAAW,qBAAqB;IACxD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;IAClC,OAAO,CAAC,YAAY,CAAiB;IACrC,OAAO,CAAC,SAAS,CAA+B;IAChD,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAA8B;IACjE,OAAO,CAAC,kBAAkB,CAAoC;IAC9D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAmB;IAC3C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAiB;IACvC,OAAO,CAAC,eAAe,CAAQ;IAC/B,OAAO,CAAC,UAAU,CAAoC;IACtD,OAAO,CAAC,YAAY,CAA+B;IACnD,OAAO,CAAC,cAAc,CAAqC;IAC3D,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA4B;gBAGpD,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,gBAAgB,EACzB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,EACzB,kBAAkB,CAAC,EAAE,2BAA2B,GAAG,IAAI,EACvD,KAAK,CAAC,EAAE,cAAc,GAAG,IAAI;IAc/B,UAAU,IAAI,gBAAgB;IAI9B,eAAe,IAAI,cAAc;IAIjC,YAAY,IAAI,cAAc,GAAG,IAAI;IAIrC,UAAU,IAAI,OAAO;IAIrB,qBAAqB,IAAI,mBAAmB,GAAG,IAAI;IAInD,iBAAiB,IAAI,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;YAIlC,kBAAkB;YAyDlB,iBAAiB;IAiBzB,aAAa,CACjB,UAAU,EAAE,mBAAmB,EAC/B,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,OAAO,CAAC,IAAI,CAAC;IA6BV,YAAY,CAChB,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,OAAO,CAAC,IAAI,CAAC;IAeV,gBAAgB,CAAC,OAAO,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;YAYvD,2BAA2B;IAMzC,iBAAiB,IAAI,OAAO;IAI5B,kBAAkB,CAAC,WAAW,EAAE,OAAO,GAAG,IAAI;IAIxC,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAO/B,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;IAIlC,cAAc,IAAI,OAAO;IAIzB,MAAM,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IAIhC,MAAM,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IAI1B,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAM7B,YAAY,IAAI,QAAQ,CAAC,QAAQ,CAAC;CAGnC"}
|