@hardlydifficult/workflow-engine 1.0.3 → 1.0.5

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 CHANGED
@@ -75,9 +75,25 @@ engine.isTerminal; // true
75
75
  | `transition(to, updater?)` | Change status, optionally mutate data. Validates transition, persists immediately. |
76
76
  | `update(updater)` | Mutate data without changing status. Persists immediately. |
77
77
  | `save()` | Force-save current state to disk. |
78
+ | `cursor(selector)` | Create a `DataCursor` for safe nested data access with `get()`, `find()`, `update()`. |
78
79
  | `canTransition(to)` | Check if a transition is allowed from current status. |
79
80
  | `allowedTransitions()` | List statuses reachable from current status. |
80
81
 
82
+ ### `cursor<TItem>(selector)`
83
+
84
+ Creates a reusable cursor for safe navigation into nested engine data. Define the selector once, then use `get()`, `find()`, or `update()` without repeating navigation logic.
85
+
86
+ ```typescript
87
+ interface Data { items: Array<{ name: string; done: boolean }>; currentIndex?: number; }
88
+
89
+ const item = engine.cursor((d) => d.items[d.currentIndex ?? -1]);
90
+
91
+ item.get(); // returns item or throws "Cursor target not found"
92
+ item.find(); // returns item or undefined
93
+ await item.update((it) => { it.done = true; }); // persists, no-op if undefined
94
+ await item.update((it, d) => { d.currentIndex = undefined; }); // access parent data too
95
+ ```
96
+
81
97
  ### Updater Pattern
82
98
 
83
99
  `transition()` and `update()` accept an updater callback that receives a `structuredClone` of the data. Mutate it directly — if the updater throws, nothing changes.
@@ -0,0 +1,22 @@
1
+ import type { WorkflowEngine } from "./WorkflowEngine.js";
2
+ /**
3
+ * Reusable cursor for safe navigation into nested engine data.
4
+ *
5
+ * Define a selector once, then use `get()` / `find()` / `update()` to
6
+ * interact with the selected item without repeating navigation logic.
7
+ */
8
+ export declare class DataCursor<TStatus extends string, TData, TItem> {
9
+ private readonly engine;
10
+ private readonly selector;
11
+ constructor(engine: WorkflowEngine<TStatus, TData>, selector: (data: TData) => TItem | undefined);
12
+ /** Get the selected item. Throws if the selector returns undefined. */
13
+ get(): TItem;
14
+ /** Get the selected item, or undefined. */
15
+ find(): TItem | undefined;
16
+ /**
17
+ * Update the selected item (and optionally the parent data).
18
+ * No-op if the selector returns undefined.
19
+ */
20
+ update(updater: (item: TItem, data: TData) => void): Promise<void>;
21
+ }
22
+ //# sourceMappingURL=DataCursor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DataCursor.d.ts","sourceRoot":"","sources":["../src/DataCursor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D;;;;;GAKG;AACH,qBAAa,UAAU,CAAC,OAAO,SAAS,MAAM,EAAE,KAAK,EAAE,KAAK;IAC1D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiC;IACxD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqC;gBAG5D,MAAM,EAAE,cAAc,CAAC,OAAO,EAAE,KAAK,CAAC,EACtC,QAAQ,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,KAAK,GAAG,SAAS;IAM9C,uEAAuE;IACvE,GAAG,IAAI,KAAK;IAQZ,2CAA2C;IAC3C,IAAI,IAAI,KAAK,GAAG,SAAS;IAIzB;;;OAGG;IACG,MAAM,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;CAQzE"}
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DataCursor = void 0;
4
+ /**
5
+ * Reusable cursor for safe navigation into nested engine data.
6
+ *
7
+ * Define a selector once, then use `get()` / `find()` / `update()` to
8
+ * interact with the selected item without repeating navigation logic.
9
+ */
10
+ class DataCursor {
11
+ engine;
12
+ selector;
13
+ constructor(engine, selector) {
14
+ this.engine = engine;
15
+ this.selector = selector;
16
+ }
17
+ /** Get the selected item. Throws if the selector returns undefined. */
18
+ get() {
19
+ const item = this.selector(this.engine.data);
20
+ if (item === undefined) {
21
+ throw new Error("Cursor target not found");
22
+ }
23
+ return item;
24
+ }
25
+ /** Get the selected item, or undefined. */
26
+ find() {
27
+ return this.selector(this.engine.data);
28
+ }
29
+ /**
30
+ * Update the selected item (and optionally the parent data).
31
+ * No-op if the selector returns undefined.
32
+ */
33
+ async update(updater) {
34
+ await this.engine.update((d) => {
35
+ const item = this.selector(d);
36
+ if (item !== undefined) {
37
+ updater(item, d);
38
+ }
39
+ });
40
+ }
41
+ }
42
+ exports.DataCursor = DataCursor;
43
+ //# sourceMappingURL=DataCursor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DataCursor.js","sourceRoot":"","sources":["../src/DataCursor.ts"],"names":[],"mappings":";;;AAEA;;;;;GAKG;AACH,MAAa,UAAU;IACJ,MAAM,CAAiC;IACvC,QAAQ,CAAqC;IAE9D,YACE,MAAsC,EACtC,QAA4C;QAE5C,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;IAED,uEAAuE;IACvE,GAAG;QACD,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,IAAa,CAAC,CAAC;QACtD,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACvB,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;QAC7C,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,2CAA2C;IAC3C,IAAI;QACF,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,IAAa,CAAC,CAAC;IAClD,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,MAAM,CAAC,OAA2C;QACtD,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE;YAC7B,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;YAC9B,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;gBACvB,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;YACnB,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;CACF;AAtCD,gCAsCC"}
@@ -1,4 +1,5 @@
1
- import type { DataUpdater, WorkflowEngineOptions } from "./types.js";
1
+ import { DataCursor } from "./DataCursor.js";
2
+ import type { ChangeListener, DataUpdater, WorkflowEngineOptions, WorkflowSnapshot } from "./types.js";
2
3
  /**
3
4
  * General-purpose state machine with typed statuses, validated transitions,
4
5
  * and persistent state via StateTracker.
@@ -7,6 +8,7 @@ export declare class WorkflowEngine<TStatus extends string, TData> {
7
8
  private readonly tracker;
8
9
  private readonly transitions;
9
10
  private readonly onTransitionCb?;
11
+ private readonly listeners;
10
12
  private loaded;
11
13
  constructor(options: WorkflowEngineOptions<TStatus, TData>);
12
14
  /** Current status */
@@ -42,6 +44,15 @@ export declare class WorkflowEngine<TStatus extends string, TData> {
42
44
  * On success, state is persisted immediately.
43
45
  */
44
46
  update(updater: DataUpdater<TData>): Promise<void>;
47
+ /** Create a cursor for safe navigation into nested data. */
48
+ cursor<TItem>(selector: (data: TData) => TItem | undefined): DataCursor<TStatus, TData, TItem>;
49
+ /**
50
+ * Register a listener for all engine events (transition, update, load).
51
+ * Returns an unsubscribe function.
52
+ */
53
+ on(listener: ChangeListener<TStatus, TData>): () => void;
54
+ /** Return a read-only snapshot of the engine's current state. */
55
+ toSnapshot(): WorkflowSnapshot<TStatus, TData>;
45
56
  /** Check if a specific transition is allowed from current status */
46
57
  canTransition(to: TStatus): boolean;
47
58
  /** Get statuses reachable from current status */
@@ -1 +1 @@
1
- {"version":3,"file":"WorkflowEngine.d.ts","sourceRoot":"","sources":["../src/WorkflowEngine.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,WAAW,EAIX,qBAAqB,EACtB,MAAM,YAAY,CAAC;AAEpB;;;GAGG;AACH,qBAAa,cAAc,CAAC,OAAO,SAAS,MAAM,EAAE,KAAK;IACvD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA+C;IACvE,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAyB;IACrD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,CAEtB;IACV,OAAO,CAAC,MAAM,CAAS;gBAEX,OAAO,EAAE,qBAAqB,CAAC,OAAO,EAAE,KAAK,CAAC;IAwB1D,qBAAqB;IACrB,IAAI,MAAM,IAAI,OAAO,CAEpB;IAED,+BAA+B;IAC/B,IAAI,IAAI,IAAI,QAAQ,CAAC,KAAK,CAAC,CAE1B;IAED,qCAAqC;IACrC,IAAI,QAAQ,IAAI,OAAO,CAEtB;IAED,wCAAwC;IACxC,IAAI,YAAY,IAAI,OAAO,CAE1B;IAED,qDAAqD;IACrD,IAAI,SAAS,IAAI,MAAM,CAEtB;IAED,uEAAuE;IACvE,IAAI,UAAU,IAAI,OAAO,CAExB;IAED;;;OAGG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAM3B;;;;;;OAMG;IACG,UAAU,CAAC,EAAE,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,WAAW,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IA+B1E;;;;;;OAMG;IACG,MAAM,CAAC,OAAO,EAAE,WAAW,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAexD,oEAAoE;IACpE,aAAa,CAAC,EAAE,EAAE,OAAO,GAAG,OAAO;IAInC,iDAAiD;IACjD,kBAAkB,IAAI,SAAS,OAAO,EAAE;IAIxC,uCAAuC;IACjC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAI3B,OAAO,CAAC,SAAS;CAclB"}
1
+ {"version":3,"file":"WorkflowEngine.d.ts","sourceRoot":"","sources":["../src/WorkflowEngine.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,KAAK,EACV,cAAc,EACd,WAAW,EAIX,qBAAqB,EACrB,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAEpB;;;GAGG;AACH,qBAAa,cAAc,CAAC,OAAO,SAAS,MAAM,EAAE,KAAK;IACvD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA+C;IACvE,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAyB;IACrD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,CAEtB;IACV,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA6C;IACvE,OAAO,CAAC,MAAM,CAAS;gBAEX,OAAO,EAAE,qBAAqB,CAAC,OAAO,EAAE,KAAK,CAAC;IAwB1D,qBAAqB;IACrB,IAAI,MAAM,IAAI,OAAO,CAEpB;IAED,+BAA+B;IAC/B,IAAI,IAAI,IAAI,QAAQ,CAAC,KAAK,CAAC,CAE1B;IAED,qCAAqC;IACrC,IAAI,QAAQ,IAAI,OAAO,CAEtB;IAED,wCAAwC;IACxC,IAAI,YAAY,IAAI,OAAO,CAE1B;IAED,qDAAqD;IACrD,IAAI,SAAS,IAAI,MAAM,CAEtB;IAED,uEAAuE;IACvE,IAAI,UAAU,IAAI,OAAO,CAExB;IAED;;;OAGG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAM3B;;;;;;OAMG;IACG,UAAU,CAAC,EAAE,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,WAAW,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IA+B1E;;;;;;OAMG;IACG,MAAM,CAAC,OAAO,EAAE,WAAW,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAexD,4DAA4D;IAC5D,MAAM,CAAC,KAAK,EACV,QAAQ,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,KAAK,GAAG,SAAS,GAC3C,UAAU,CAAC,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC;IAIpC;;;OAGG;IACH,EAAE,CAAC,QAAQ,EAAE,cAAc,CAAC,OAAO,EAAE,KAAK,CAAC,GAAG,MAAM,IAAI;IAOxD,iEAAiE;IACjE,UAAU,IAAI,gBAAgB,CAAC,OAAO,EAAE,KAAK,CAAC;IAS9C,oEAAoE;IACpE,aAAa,CAAC,EAAE,EAAE,OAAO,GAAG,OAAO;IAInC,iDAAiD;IACjD,kBAAkB,IAAI,SAAS,OAAO,EAAE;IAIxC,uCAAuC;IACjC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAI3B,OAAO,CAAC,SAAS;CAkBlB"}
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.WorkflowEngine = void 0;
4
4
  const state_tracker_1 = require("@hardlydifficult/state-tracker");
5
+ const DataCursor_js_1 = require("./DataCursor.js");
5
6
  /**
6
7
  * General-purpose state machine with typed statuses, validated transitions,
7
8
  * and persistent state via StateTracker.
@@ -10,6 +11,7 @@ class WorkflowEngine {
10
11
  tracker;
11
12
  transitions;
12
13
  onTransitionCb;
14
+ listeners = new Set();
13
15
  loaded = false;
14
16
  constructor(options) {
15
17
  const { transitions, initialStatus } = options;
@@ -109,6 +111,29 @@ class WorkflowEngine {
109
111
  await this.tracker.saveAsync();
110
112
  this.emitEvent("update");
111
113
  }
114
+ /** Create a cursor for safe navigation into nested data. */
115
+ cursor(selector) {
116
+ return new DataCursor_js_1.DataCursor(this, selector);
117
+ }
118
+ /**
119
+ * Register a listener for all engine events (transition, update, load).
120
+ * Returns an unsubscribe function.
121
+ */
122
+ on(listener) {
123
+ this.listeners.add(listener);
124
+ return () => {
125
+ this.listeners.delete(listener);
126
+ };
127
+ }
128
+ /** Return a read-only snapshot of the engine's current state. */
129
+ toSnapshot() {
130
+ return {
131
+ status: this.status,
132
+ data: structuredClone(this.data),
133
+ updatedAt: this.updatedAt,
134
+ isTerminal: this.isTerminal,
135
+ };
136
+ }
112
137
  /** Check if a specific transition is allowed from current status */
113
138
  canTransition(to) {
114
139
  return this.transitions[this.status].includes(to);
@@ -122,14 +147,18 @@ class WorkflowEngine {
122
147
  await this.tracker.saveAsync();
123
148
  }
124
149
  emitEvent(type, from, to) {
125
- this.onTransitionCb?.({
150
+ const event = {
126
151
  type,
127
152
  from,
128
153
  to,
129
154
  status: this.status,
130
155
  data: this.data,
131
156
  timestamp: new Date().toISOString(),
132
- });
157
+ };
158
+ this.onTransitionCb?.(event);
159
+ for (const listener of this.listeners) {
160
+ listener(event);
161
+ }
133
162
  }
134
163
  }
135
164
  exports.WorkflowEngine = WorkflowEngine;
@@ -1 +1 @@
1
- {"version":3,"file":"WorkflowEngine.js","sourceRoot":"","sources":["../src/WorkflowEngine.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"WorkflowEngine.js","sourceRoot":"","sources":["../src/WorkflowEngine.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ export { DataCursor } from "./DataCursor.js";
1
2
  export { WorkflowEngine } from "./WorkflowEngine.js";
2
- export type { WorkflowEngineOptions, TransitionEvent, TransitionMap, DataUpdater, } from "./types.js";
3
+ export type { ChangeListener, WorkflowEngineOptions, WorkflowSnapshot, TransitionEvent, TransitionMap, DataUpdater, } from "./types.js";
3
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,YAAY,EACV,qBAAqB,EACrB,eAAe,EACf,aAAa,EACb,WAAW,GACZ,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,YAAY,EACV,cAAc,EACd,qBAAqB,EACrB,gBAAgB,EAChB,eAAe,EACf,aAAa,EACb,WAAW,GACZ,MAAM,YAAY,CAAC"}
package/dist/index.js CHANGED
@@ -1,6 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.WorkflowEngine = void 0;
3
+ exports.WorkflowEngine = exports.DataCursor = void 0;
4
+ var DataCursor_js_1 = require("./DataCursor.js");
5
+ Object.defineProperty(exports, "DataCursor", { enumerable: true, get: function () { return DataCursor_js_1.DataCursor; } });
4
6
  var WorkflowEngine_js_1 = require("./WorkflowEngine.js");
5
7
  Object.defineProperty(exports, "WorkflowEngine", { enumerable: true, get: function () { return WorkflowEngine_js_1.WorkflowEngine; } });
6
8
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,yDAAqD;AAA5C,mHAAA,cAAc,OAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,iDAA6C;AAApC,2GAAA,UAAU,OAAA;AACnB,yDAAqD;AAA5C,mHAAA,cAAc,OAAA"}
package/dist/types.d.ts CHANGED
@@ -39,6 +39,21 @@ export interface WorkflowEngineOptions<TStatus extends string, TData> {
39
39
  /** Called on transitions, updates, and loads */
40
40
  onTransition?: (event: TransitionEvent<TStatus, TData>) => void;
41
41
  }
42
+ /**
43
+ * Listener callback for engine change events.
44
+ * Receives the same event as onTransition.
45
+ */
46
+ export type ChangeListener<TStatus extends string, TData> = (event: TransitionEvent<TStatus, TData>) => void;
47
+ /**
48
+ * Read-only snapshot of an engine's current state.
49
+ * Useful for serialization or external consumers.
50
+ */
51
+ export interface WorkflowSnapshot<TStatus extends string, TData> {
52
+ status: TStatus;
53
+ data: Readonly<TData>;
54
+ updatedAt: string;
55
+ isTerminal: boolean;
56
+ }
42
57
  /**
43
58
  * Internal persisted shape: status + data + updatedAt together.
44
59
  */
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,MAAM,aAAa,CAAC,OAAO,SAAS,MAAM,IAAI,MAAM,CACxD,OAAO,EACP,SAAS,OAAO,EAAE,CACnB,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,WAAW,CAAC,KAAK,IAAI,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;AAExD;;GAEG;AACH,MAAM,WAAW,eAAe,CAAC,OAAO,SAAS,MAAM,EAAE,KAAK;IAC5D,IAAI,EAAE,YAAY,GAAG,QAAQ,GAAG,MAAM,CAAC;IACvC,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB,CAAC,OAAO,SAAS,MAAM,EAAE,KAAK;IAClE,8CAA8C;IAC9C,GAAG,EAAE,MAAM,CAAC;IACZ,kDAAkD;IAClD,aAAa,EAAE,OAAO,CAAC;IACvB,gDAAgD;IAChD,WAAW,EAAE,KAAK,CAAC;IACnB,kEAAkE;IAClE,WAAW,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC;IACpC,sCAAsC;IACtC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,8CAA8C;IAC9C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gDAAgD;IAChD,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,CAAC,OAAO,EAAE,KAAK,CAAC,KAAK,IAAI,CAAC;CACjE;AAED;;GAEG;AACH,MAAM,WAAW,cAAc,CAAC,OAAO,SAAS,MAAM,EAAE,KAAK;IAC3D,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,KAAK,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;CACnB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,MAAM,aAAa,CAAC,OAAO,SAAS,MAAM,IAAI,MAAM,CACxD,OAAO,EACP,SAAS,OAAO,EAAE,CACnB,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,WAAW,CAAC,KAAK,IAAI,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;AAExD;;GAEG;AACH,MAAM,WAAW,eAAe,CAAC,OAAO,SAAS,MAAM,EAAE,KAAK;IAC5D,IAAI,EAAE,YAAY,GAAG,QAAQ,GAAG,MAAM,CAAC;IACvC,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB,CAAC,OAAO,SAAS,MAAM,EAAE,KAAK;IAClE,8CAA8C;IAC9C,GAAG,EAAE,MAAM,CAAC;IACZ,kDAAkD;IAClD,aAAa,EAAE,OAAO,CAAC;IACvB,gDAAgD;IAChD,WAAW,EAAE,KAAK,CAAC;IACnB,kEAAkE;IAClE,WAAW,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC;IACpC,sCAAsC;IACtC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,8CAA8C;IAC9C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gDAAgD;IAChD,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,CAAC,OAAO,EAAE,KAAK,CAAC,KAAK,IAAI,CAAC;CACjE;AAED;;;GAGG;AACH,MAAM,MAAM,cAAc,CAAC,OAAO,SAAS,MAAM,EAAE,KAAK,IAAI,CAC1D,KAAK,EAAE,eAAe,CAAC,OAAO,EAAE,KAAK,CAAC,KACnC,IAAI,CAAC;AAEV;;;GAGG;AACH,MAAM,WAAW,gBAAgB,CAAC,OAAO,SAAS,MAAM,EAAE,KAAK;IAC7D,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,OAAO,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc,CAAC,OAAO,SAAS,MAAM,EAAE,KAAK;IAC3D,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,KAAK,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;CACnB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hardlydifficult/workflow-engine",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "main": "./dist/index.js",
5
5
  "types": "./dist/index.d.ts",
6
6
  "files": [
@@ -15,7 +15,7 @@
15
15
  "clean": "rm -rf dist"
16
16
  },
17
17
  "dependencies": {
18
- "@hardlydifficult/state-tracker": "2.0.2"
18
+ "@hardlydifficult/state-tracker": "file:../state-tracker"
19
19
  },
20
20
  "devDependencies": {
21
21
  "@types/node": "20.19.31",
@@ -23,7 +23,7 @@
23
23
  "vitest": "1.6.1"
24
24
  },
25
25
  "peerDependencies": {
26
- "@hardlydifficult/state-tracker": "2.0.2"
26
+ "@hardlydifficult/state-tracker": ">=2.0.0"
27
27
  },
28
28
  "engines": {
29
29
  "node": ">=18.0.0"