small-state 0.2.0 → 0.3.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.ja.md +29 -14
- package/README.md +27 -14
- package/dist/index.cjs +13 -1
- package/dist/index.d.cts +41 -61
- package/dist/index.d.mts +41 -61
- package/dist/index.mjs +12 -2
- package/package.json +4 -2
package/README.ja.md
CHANGED
|
@@ -9,6 +9,13 @@ A state machine inspired by [XState](https://stately.ai/docs/xstate).
|
|
|
9
9
|
- 迷子になりにくい記述
|
|
10
10
|
|
|
11
11
|
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
npm i small-state
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
|
|
12
19
|
## FSM(Finite State Machine / 有限ステートマシン)とは
|
|
13
20
|
|
|
14
21
|
有限個の状態と、状態間の遷移を定義するモデル。
|
|
@@ -237,8 +244,26 @@ idle 内で LOGIN_SUCCESS を受け取ると、定義に従い "loggedIn" ステ
|
|
|
237
244
|
- 'notStarted' - まだ .start() されていない。
|
|
238
245
|
- 'active' - .start() され、稼働している。
|
|
239
246
|
- 'stopped' - .stop() され、停止している。
|
|
240
|
-
- 'done' -
|
|
247
|
+
- 'done' - 最終状態に入り完了し、正常停止した。
|
|
241
248
|
- 'error' - エラーで停止した。
|
|
249
|
+
- `type Runtime<M extends AnyMachine>`
|
|
250
|
+
- `type Snapshot<M extends AnyMachine>` - Runtime の getSnapshot の項参照。
|
|
251
|
+
|
|
252
|
+
### 補助関数
|
|
253
|
+
|
|
254
|
+
- `isMachine(v: unknown): v is AnyMachine` - 引数がマシンかどうかを判定。
|
|
255
|
+
- `isRuntime(v: unknown): v is Runtime<AnyMachine>` - 引数がランタイムかどうかを判定。
|
|
256
|
+
- `defServiceFn(serviceFn: ServiceFn): ServiceFn`
|
|
257
|
+
- サービス関数を定義する。
|
|
258
|
+
- マシン外部でサービス関数を定義するときか、invoke に直接関数を渡すときに裸の関数だと型推論が崩れてしまうが、この関数でラップすることで型を通すことができる。
|
|
259
|
+
- `waitFor<R extends Runtime<any>>(runtime, cond, options?): Promise<SnapshotFrom<R>>` - 渡した runtime が条件を満たすまで待機する。
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
### メイン関数
|
|
263
|
+
|
|
264
|
+
- `makeMachine(config, states): Machine` - マシンを作る。
|
|
265
|
+
- `makeRuntime(machine, option?): Runtime` - マシンを実際に動かすランタイムを作る。
|
|
266
|
+
|
|
242
267
|
|
|
243
268
|
### 予約されているイベントタイプ
|
|
244
269
|
|
|
@@ -253,16 +278,6 @@ idle 内で LOGIN_SUCCESS を受け取ると、定義に従い "loggedIn" ステ
|
|
|
253
278
|
- `{type: ':done:', output: unknown}` - そのサービスが正常終了したときに発火する
|
|
254
279
|
- `{type: ':error:', error: unknown}` - そのサービスが異常狩猟したときに発火する
|
|
255
280
|
|
|
256
|
-
### 補助関数
|
|
257
|
-
|
|
258
|
-
- `defServiceFn(serviceFn): ServiceFn` - サービス関数を定義する。
|
|
259
|
-
- マシン外部でサービス関数を定義するときか、invoke に直接関数を渡すときに裸の関数だと型推論が崩れてしまうが、この関数でラップすることで型を通すことができる。
|
|
260
|
-
- `waitFor<RT extends Runtime<any>>(runtime, cond, options?): Promise<SnapshotFrom<RT>>` - 渡した runtime が条件を満たすまで待機する。
|
|
261
|
-
|
|
262
|
-
### メイン関数
|
|
263
|
-
|
|
264
|
-
- `makeMachine(config, states): Machine` - マシンを作る。
|
|
265
|
-
- `makeRuntime(machine, option?): Runtime` - マシンを実際に動かすランタイムを作る。
|
|
266
281
|
|
|
267
282
|
### `makeMachine(config: MachineConfig, defineStates: (tools)=>Record<string, StateDefinition>): Machine`
|
|
268
283
|
|
|
@@ -473,7 +488,8 @@ Runtime は以下のメンバーを持つ:
|
|
|
473
488
|
- `output: O | undefined` - ランタイムが最終状態に入るまでは undefined。最終状態に入ったとき計算され結果がここに設定される。
|
|
474
489
|
- `error: unknown` - エラーが生じてランタイムが停止したときにそのエラー内容が入る。それまでは undefined。
|
|
475
490
|
- `_children` - デバッグ用。業務では使用しないのが望ましい。キーにサービス名、値に invoke などで起動中のサービスが入る。subKey を設定して起動している場合、キーは `${serviceName}:${subKey}` になる。
|
|
476
|
-
|
|
491
|
+
- `_runtime` - このスナップショットを作ったランタイム自身。
|
|
492
|
+
- 怠惰のために runtime から直接プロパティでsnapshot を参照できる getter が用意されている。以下のものが設定されている:
|
|
477
493
|
- states, stateValue, context, runtimeStatus, output
|
|
478
494
|
- `subscribe(onSnapshot: ((current: Snapshot, prev: Snapshot)=>void)|undefined, onError?:(err:unknown)=>void): UnsubscribeFn`
|
|
479
495
|
- snapshot が更新されるたびに呼ばれる観測関数を登録する。ただし第一引数の関数はエラーは監視しない。それは省略可能な第二引数の関数の役割である。
|
|
@@ -508,6 +524,7 @@ Runtime は以下のメンバーを持つ:
|
|
|
508
524
|
| | XState | small-state |
|
|
509
525
|
| - | - | - |
|
|
510
526
|
| パス区切り文字 | `.` | `/` |
|
|
527
|
+
| ロジックを持つのは | マシン | ランタイム |
|
|
511
528
|
| context 更新 | assign | update: action内引数 |
|
|
512
529
|
| 子から親への通信 | sendParent | emit |
|
|
513
530
|
| 親から子への通信に使うもの | actor id | service name (と subKey) |
|
|
@@ -545,5 +562,3 @@ Runtime は以下のメンバーを持つ:
|
|
|
545
562
|
- parallel のインターフェースの改修
|
|
546
563
|
- もう少し分かりやすく
|
|
547
564
|
- 連続で入れ子にできないのを改善する
|
|
548
|
-
- error 時に正しく捕捉しランタイムを "error" 状態にする
|
|
549
|
-
- Runtime のエラーメッセージにマシン名を入れる。
|
package/README.md
CHANGED
|
@@ -13,6 +13,13 @@ A state machine library inspired by [XState](https://stately.ai/docs/xstate).
|
|
|
13
13
|
- Clean syntax that is hard to get lost in
|
|
14
14
|
|
|
15
15
|
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
npm i small-state
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
|
|
16
23
|
## What is an FSM (Finite State Machine)?
|
|
17
24
|
|
|
18
25
|
A Finite State Machine is a computational model defined by a finite number of states and transitions between those states.
|
|
@@ -243,8 +250,25 @@ Since `loggedIn` is defined as `null`, it acts as a final state. The machine sto
|
|
|
243
250
|
- `'notStarted'` - `.start()` has not been called yet.
|
|
244
251
|
- `'active'` - `.start()` has been called and the machine is running.
|
|
245
252
|
- `'stopped'` - `.stop()` was called and execution is halted.
|
|
246
|
-
- `'done'` -
|
|
253
|
+
- `'done'` - Entered the final state, completed, and successfully stopped.
|
|
247
254
|
- `'error'` - Execution stopped due to an error.
|
|
255
|
+
- `type Runtime<M AnyMachine extends>`
|
|
256
|
+
- `type Snapshot<M AnyMachine extends>` - Refer to the Runtime getSnapshot section.
|
|
257
|
+
|
|
258
|
+
### Utility Functions
|
|
259
|
+
|
|
260
|
+
- `isMachine(v: unknown): v is AnyMachine` - Determines whether the argument is a machine.
|
|
261
|
+
- `isRuntime(v: unknown): v is Runtime<AnyMachine>` - Determines whether the argument is a runtime.
|
|
262
|
+
- `defServiceFn(serviceFn): ServiceFn`
|
|
263
|
+
- Defines a service function.
|
|
264
|
+
- Passing plain functions directly to `invoke` or defining them outside a machine configuration might cause type inference to break. Wrapping them with `defServiceFn` preserves type inference.
|
|
265
|
+
- `waitFor<R extends Runtime<any>>(runtime, cond, options?): Promise<SnapshotFrom<R>>` - Returns a Promise that resolves when the specified `runtime` satisfies `cond`.
|
|
266
|
+
|
|
267
|
+
### Primary Functions
|
|
268
|
+
|
|
269
|
+
- `makeMachine(config, states): Machine` - Creates a machine definition.
|
|
270
|
+
- `makeRuntime(machine, option?): Runtime` - Creates an executable runtime instance for a machine.
|
|
271
|
+
|
|
248
272
|
|
|
249
273
|
### Reserved Event Types
|
|
250
274
|
|
|
@@ -259,17 +283,6 @@ The following event names are currently reserved:
|
|
|
259
283
|
- `{type: ':done:', output: unknown}` - Fires when the invoked service completes successfully.
|
|
260
284
|
- `{type: ':error:', error: unknown}` - Fires when the invoked service terminates with an error.
|
|
261
285
|
|
|
262
|
-
### Utility Functions
|
|
263
|
-
|
|
264
|
-
- `defServiceFn(serviceFn): ServiceFn` - Defines a service function.
|
|
265
|
-
- Passing plain functions directly to `invoke` or defining them outside a machine configuration might cause type inference to break. Wrapping them with `defServiceFn` preserves type inference.
|
|
266
|
-
- `waitFor<RT extends Runtime<any>>(runtime, cond, options?): Promise<SnapshotFrom<RT>>` - Returns a Promise that resolves when the specified `runtime` satisfies `cond`.
|
|
267
|
-
|
|
268
|
-
### Primary Functions
|
|
269
|
-
|
|
270
|
-
- `makeMachine(config, states): Machine` - Creates a machine definition.
|
|
271
|
-
- `makeRuntime(machine, option?): Runtime` - Creates an executable runtime instance for a machine.
|
|
272
|
-
|
|
273
286
|
### `makeMachine(config: MachineConfig, defineStates: (tools)=>Record<string, StateDefinition>): Machine`
|
|
274
287
|
|
|
275
288
|
#### makeMachine > `MachineConfig`
|
|
@@ -478,6 +491,7 @@ Runtime instances expose the following members:
|
|
|
478
491
|
- `output: O | undefined` - Contains final execution output values when `runtimeStatus === 'done'`; `undefined` otherwise.
|
|
479
492
|
- `error: unknown` - Contains error details if execution halted due to errors; `undefined` otherwise.
|
|
480
493
|
- `_children` - Debugging member. Keyed by service name mapping to running service instances. When `subKey` is present, keys map as `${serviceName}:${subKey}`.
|
|
494
|
+
- `_runtime` - The runtime instance itself that generated this snapshot.
|
|
481
495
|
- Direct shortcut getters exist on `runtime` instances for convenience:
|
|
482
496
|
- `states`, `stateValue`, `context`, `runtimeStatus`, `output`
|
|
483
497
|
- `subscribe(onSnapshot: ((current: Snapshot, prev: Snapshot)=>void)|undefined, onError?:(err:unknown)=>void): UnsubscribeFn`
|
|
@@ -513,6 +527,7 @@ Runtime instances expose the following members:
|
|
|
513
527
|
| Feature / Behavior | XState | small-state |
|
|
514
528
|
| - | - | - |
|
|
515
529
|
| Path Delimiter | `.` | `/` |
|
|
530
|
+
| Logic ownership | Machine | Runtime |
|
|
516
531
|
| Context Updates | `assign` | `update` argument inside action handlers |
|
|
517
532
|
| Child to Parent Messaging | `sendParent` | `emit` |
|
|
518
533
|
| Parent to Child Messaging | actor id | service name (and optional `subKey`) |
|
|
@@ -550,5 +565,3 @@ The following features are not supported:
|
|
|
550
565
|
- Refactor `parallel` interface structure
|
|
551
566
|
- Improve clarity and usability
|
|
552
567
|
- Support nested continuous parallel structures
|
|
553
|
-
- Improve error handling to catch runtime errors reliably and set status to `"error"`
|
|
554
|
-
- Include machine name strings in Runtime error messages
|
package/dist/index.cjs
CHANGED
|
@@ -519,6 +519,11 @@ function getDefinitionAndCatalog(config, defineStates) {
|
|
|
519
519
|
function defServiceFn(fn) {
|
|
520
520
|
return fn;
|
|
521
521
|
}
|
|
522
|
+
function isMachine(v) {
|
|
523
|
+
if (!(v && typeof v === "object" && "internal" in v)) return false;
|
|
524
|
+
const { internal } = v;
|
|
525
|
+
return !!(internal && typeof internal === "object" && MachineSymbol in internal);
|
|
526
|
+
}
|
|
522
527
|
function makeMachine(config, defineStates) {
|
|
523
528
|
const { definition, topLvDefItem, stateCatalog } = getDefinitionAndCatalog(config, defineStates);
|
|
524
529
|
const { name, initContext, output, guards, actions, services } = config;
|
|
@@ -1487,6 +1492,9 @@ function exitAndEntry(tExecs, crrStates, actionRunner, { guards, services, state
|
|
|
1487
1492
|
}
|
|
1488
1493
|
//#endregion
|
|
1489
1494
|
//#region src/runtime/Runtime.ts
|
|
1495
|
+
function isRuntime(v) {
|
|
1496
|
+
return v instanceof Runtime;
|
|
1497
|
+
}
|
|
1490
1498
|
function makeRuntime(machine, options) {
|
|
1491
1499
|
return new Runtime(machine, options);
|
|
1492
1500
|
}
|
|
@@ -1663,8 +1671,10 @@ var Runtime = class {
|
|
|
1663
1671
|
output: void 0
|
|
1664
1672
|
}, this.#input)),
|
|
1665
1673
|
error: void 0,
|
|
1666
|
-
_children: this.#outbound.children
|
|
1674
|
+
_children: this.#outbound.children,
|
|
1675
|
+
_runtime: this
|
|
1667
1676
|
};
|
|
1677
|
+
Object.defineProperty(this.#snapshot, "_runtime", { enumerable: false });
|
|
1668
1678
|
{
|
|
1669
1679
|
const snapshot = this.#snapshot;
|
|
1670
1680
|
for (const { onSnapshot } of this.#subscribers) {
|
|
@@ -1737,6 +1747,8 @@ async function waitFor(runtime, cond, options) {
|
|
|
1737
1747
|
}
|
|
1738
1748
|
//#endregion
|
|
1739
1749
|
exports.defServiceFn = defServiceFn;
|
|
1750
|
+
exports.isMachine = isMachine;
|
|
1751
|
+
exports.isRuntime = isRuntime;
|
|
1740
1752
|
exports.makeMachine = makeMachine;
|
|
1741
1753
|
exports.makeRuntime = makeRuntime;
|
|
1742
1754
|
exports.waitFor = waitFor;
|
package/dist/index.d.cts
CHANGED
|
@@ -59,7 +59,9 @@ type EmittableEvent = {
|
|
|
59
59
|
[key: string]: any;
|
|
60
60
|
};
|
|
61
61
|
type StateName = string;
|
|
62
|
-
type
|
|
62
|
+
type O_PureETypeString<E extends SendableEvent> = E extends unknown ? Exclude<keyof E, "type"> extends never ? E['type'] : never : any;
|
|
63
|
+
type O_InferMachineSendableEvent<M extends AnyMachine> = M extends Machine<any, infer E, any, any, any, any, any, any, any> ? E : never;
|
|
64
|
+
type SendFnEvent<M extends AnyMachine> = O_InferMachineSendableEvent<M> extends (infer E extends SendableEvent) ? E | O_PureETypeString<E> : never;
|
|
63
65
|
type FnBaseParams<C extends MContext, Ex extends SendableEvent, I, Additional = unknown, Prm = any> = [arg: Expand<{
|
|
64
66
|
c: C;
|
|
65
67
|
context: C;
|
|
@@ -98,10 +100,10 @@ type EnqueueFn<C extends MContext, Ex extends SendableEvent, I, EM extends Emitt
|
|
|
98
100
|
};
|
|
99
101
|
type UpdateFnParam<C extends MContext> = { [K in keyof C]?: C[K] | (() => (C[K])); };
|
|
100
102
|
type UpdateFn<C extends MContext> = (updates: UpdateFnParam<C>) => unknown;
|
|
101
|
-
type
|
|
103
|
+
type O_InferServiceSendableEvent<S extends ServiceRecord[string]> = S extends Machine<any, infer E, any, any, any, any, any, any, any> ? E : S extends AnyFn ? (Parameters<S>[2] extends ListenFn<infer Er> ? Er : never) : never;
|
|
102
104
|
type SendToFn<S extends ServiceRecord> = {
|
|
103
|
-
<Sk extends keyof S>(serviceName: Sk, subKey: string | number, event:
|
|
104
|
-
<Sk extends keyof S>(serviceName: Sk, event:
|
|
105
|
+
<Sk extends keyof S>(serviceName: Sk, subKey: string | number, event: O_InferServiceSendableEvent<S[Sk]>): void;
|
|
106
|
+
<Sk extends keyof S>(serviceName: Sk, event: O_InferServiceSendableEvent<S[Sk]>): void;
|
|
105
107
|
};
|
|
106
108
|
type EmitFn<EM extends EmittableEvent> = (event: EM) => void;
|
|
107
109
|
type ListenFn<E extends SendableEvent> = (listener: (event: E) => void) => void;
|
|
@@ -212,7 +214,7 @@ type X_HiddenImpl = any & {
|
|
|
212
214
|
__brand: 'HiddenImpl';
|
|
213
215
|
};
|
|
214
216
|
type X_DefTypeRefluxer<C extends MContext, E extends SendableEvent, I // Input
|
|
215
|
-
, EM extends EmittableEvent, G extends Record<string, Placeholder>, A extends Record<string, Placeholder>, S extends ServiceRecord = ServiceRecord, Eb extends BuiltinEType = BuiltinEType,
|
|
217
|
+
, EM extends EmittableEvent, G extends Record<string, Placeholder>, A extends Record<string, Placeholder>, S extends ServiceRecord = ServiceRecord, Eb extends BuiltinEType = BuiltinEType, Ret = unknown> = () => Ret;
|
|
216
218
|
type X_DefineStatesTools = {
|
|
217
219
|
on: typeof on;
|
|
218
220
|
entryHook: typeof entryHook;
|
|
@@ -292,13 +294,14 @@ declare function invoke<C extends MContext, E extends SendableEvent, I, EM exten
|
|
|
292
294
|
declare function invoke<C extends MContext, E extends SendableEvent, I, EM extends EmittableEvent, const G extends Record<string, Placeholder>, const A extends Record<string, Placeholder>, S extends ServiceRecord, Src extends keyof S | InvokeSrcExpr<[SrcInput] extends [never] ? any : SrcInput>, SrcInput = never>(service: Src, config: InvokeConfig<C, E, I, S, Src, SrcInput>, ...events: InvocationEvents<C, I, EM, G, A, S, O_InferIvkSrcTypes<Src, S>>): readonly [typeof InvokeSymbol, X_DefTypeRefluxer<C, E, I, EM, G, A, S, BuiltinEType, unknown>, null, X_HiddenImpl, X_HiddenImpl, InvocationEvents<C, I, EM, G, A, S, O_InferIvkSrcTypes<Src, S>>];
|
|
293
295
|
type X_GlobalEvents<C extends MContext, E extends SendableEvent, I, EM extends EmittableEvent, G extends Record<string, Placeholder>, A extends Record<string, Placeholder>> = Array<readonly [E['type'] | BuiltinEType, X_DefTypeRefluxer<C, E, I, EM, G, A>, X_HiddenImpl]>;
|
|
294
296
|
export declare function defServiceFn<TFn extends ServiceFn>(fn: TFn): TFn;
|
|
295
|
-
export declare function
|
|
297
|
+
export declare function isMachine(v: unknown): v is AnyMachine;
|
|
298
|
+
export declare function makeMachine<C extends MContext, const E extends SendableEvent, const I, const EM extends EmittableEvent, const O, const S extends ServiceRecord, const D extends { [K in string]: StateDefinition<C, E, I, EM, G, A, S>; }, const G extends Record<string, Placeholder> = Record<string, Placeholder>, const A extends Record<string, Placeholder> = Record<string, Placeholder>>(config: Expand<MachineConfig<C, E, I, EM, O, G, A, S>>, defineStates: (defineStatesTools: Expand<X_DefineStatesTools>) => readonly [X_GlobalEvents<C, E, I, EM, G, A>, D] | readonly [D] | D): Machine<C, E, I, EM, O, G, A, S, {
|
|
296
299
|
initial: string;
|
|
297
300
|
stateOf: { [K in keyof D]: {
|
|
298
301
|
def: NStateItemDef<X_ExtractEType<D[K]>>;
|
|
299
302
|
sub: X_ExtractSubStDefinition<D[K]>;
|
|
300
303
|
}; };
|
|
301
|
-
}
|
|
304
|
+
}>;
|
|
302
305
|
//#endregion
|
|
303
306
|
//#region src/runtime/r.types.d.ts
|
|
304
307
|
type Child<TService> = TService extends AnyMachine ? Runtime<TService> : TService extends AnyFn ? {
|
|
@@ -308,82 +311,59 @@ type Child<TService> = TService extends AnyMachine ? Runtime<TService> : TServic
|
|
|
308
311
|
type Children<S extends ServiceRecord> = { [K in keyof S & string as K | `${K}:${string | number}`]?: Child<S[K]>; } & {
|
|
309
312
|
[key: string]: Child<any>;
|
|
310
313
|
};
|
|
311
|
-
type
|
|
312
|
-
C: any;
|
|
313
|
-
E: any;
|
|
314
|
-
I: any;
|
|
315
|
-
EM: any;
|
|
316
|
-
O: any;
|
|
317
|
-
G: any;
|
|
318
|
-
A: any;
|
|
319
|
-
S: any;
|
|
320
|
-
ND: any;
|
|
321
|
-
M: AnyMachine;
|
|
322
|
-
} : M extends Machine<infer C, infer E, infer I, infer EM, infer O, infer G, infer A, infer S, infer ND> ? {
|
|
323
|
-
C: C;
|
|
324
|
-
E: E;
|
|
325
|
-
I: I;
|
|
326
|
-
EM: EM;
|
|
327
|
-
O: O;
|
|
328
|
-
G: G;
|
|
329
|
-
A: A;
|
|
330
|
-
S: S;
|
|
331
|
-
ND: ND;
|
|
332
|
-
M: Machine<C, E, I, EM, O, G, A, S, ND>;
|
|
333
|
-
} : never;
|
|
334
|
-
type InferMInput<M extends AnyMachine> = M extends Machine<any, any, infer I, any, any, any, any, any, any> ? I : never;
|
|
335
|
-
type SnapshotFrom<RT extends Runtime<any>> = RT extends Runtime<any, infer Mt> ? Snapshot<Mt['C'], Mt['O'], Mt['S']> : never;
|
|
314
|
+
type SnapshotFrom<R extends Runtime<any>> = R extends Runtime<infer M> ? Snapshot<M> : never;
|
|
336
315
|
//#endregion
|
|
337
316
|
//#region src/runtime/Runtime.d.ts
|
|
338
317
|
type RuntimeStatus = 'notStarted' | 'active' | 'stopped' | 'done' | 'error';
|
|
339
|
-
type
|
|
318
|
+
type C<M extends AnyMachine> = M extends Machine<infer C, any, any, any, any, any, any, any, any> ? C : never;
|
|
319
|
+
type I<M extends AnyMachine> = M extends Machine<any, any, infer I, any, any, any, any, any, any> ? I : never;
|
|
320
|
+
type EM$1<M extends AnyMachine> = M extends Machine<any, any, any, infer EM, any, any, any, any, any> ? EM : never;
|
|
321
|
+
type O$1<M extends AnyMachine> = M extends Machine<any, any, any, any, infer O, any, any, any, any> ? O : never;
|
|
322
|
+
type S<M extends AnyMachine> = M extends Machine<any, any, any, any, any, any, any, infer S, any> ? S : never;
|
|
323
|
+
type X_RemovePrivateKeys<T extends Record<string, unknown>> = { [K in keyof T as K extends `_${string}` ? never : K]: T[K]; };
|
|
324
|
+
type Snapshot<M extends AnyMachine> = {
|
|
340
325
|
runtimeId: string;
|
|
341
326
|
states: string[];
|
|
342
327
|
stateValue: string | string[] | undefined;
|
|
343
|
-
context: Expand<X_RemovePrivateKeys<C
|
|
344
|
-
c: Expand<X_RemovePrivateKeys<C
|
|
328
|
+
context: Expand<X_RemovePrivateKeys<C<M>>>;
|
|
329
|
+
c: Expand<X_RemovePrivateKeys<C<M>>>;
|
|
345
330
|
runtimeStatus: RuntimeStatus;
|
|
346
|
-
output: O | undefined;
|
|
331
|
+
output: O$1<M> | undefined;
|
|
347
332
|
error: unknown;
|
|
348
|
-
_children: Children<S
|
|
333
|
+
_children: Children<S<M>>;
|
|
334
|
+
_runtime: Runtime<M>;
|
|
349
335
|
};
|
|
350
|
-
type Subscriber<
|
|
351
|
-
onSnapshot?: (current: Expand<Snapshot<
|
|
336
|
+
type Subscriber<M extends AnyMachine> = {
|
|
337
|
+
onSnapshot?: (current: Expand<Snapshot<M>>, prev: Expand<Snapshot<M>>) => void;
|
|
352
338
|
onError?: (err: unknown) => void;
|
|
353
339
|
};
|
|
354
|
-
|
|
340
|
+
export declare function isRuntime(v: unknown): v is Runtime<AnyMachine>;
|
|
341
|
+
type RuntimeOptions<M extends AnyMachine> = {
|
|
355
342
|
id?: string;
|
|
356
|
-
input?: () => I
|
|
343
|
+
input?: () => I<M>;
|
|
357
344
|
};
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
type C$1<Mt extends InferredMachineTypes<any>> = Mt['C'];
|
|
361
|
-
type E$1<Mt extends InferredMachineTypes<any>> = Mt['E'];
|
|
362
|
-
type I$1<Mt extends InferredMachineTypes<any>> = Mt['I'];
|
|
363
|
-
type EM$1<Mt extends InferredMachineTypes<any>> = Mt['EM'];
|
|
364
|
-
type O$1<Mt extends InferredMachineTypes<any>> = Mt['O'];
|
|
365
|
-
type S$1<Mt extends InferredMachineTypes<any>> = Mt['S'];
|
|
366
|
-
declare class Runtime<M extends AnyMachine, Mt extends InferredMachineTypes<M> = InferredMachineTypes<M>> {
|
|
345
|
+
export declare function makeRuntime<M extends AnyMachine>(machine: M, options?: RuntimeOptions<M>): Runtime<M>;
|
|
346
|
+
declare class Runtime<M extends AnyMachine> {
|
|
367
347
|
#private;
|
|
368
348
|
readonly id: string;
|
|
369
|
-
readonly machine:
|
|
349
|
+
readonly machine: M;
|
|
370
350
|
get states(): string[];
|
|
371
351
|
get stateValue(): string | string[] | undefined;
|
|
372
|
-
get context(): X_RemovePrivateKeys<C
|
|
352
|
+
get context(): X_RemovePrivateKeys<C<M>> extends (infer T) ? { [K in keyof T]: X_RemovePrivateKeys<C<M>>[K]; } : never;
|
|
373
353
|
get runtimeStatus(): RuntimeStatus;
|
|
374
|
-
get output(): O$1<
|
|
375
|
-
getSnapshot(): Snapshot<
|
|
376
|
-
constructor(machine: M, { id, input }?: RuntimeOptions<I
|
|
377
|
-
subscribe(onSnapshot: Subscriber<
|
|
354
|
+
get output(): O$1<M> | undefined;
|
|
355
|
+
getSnapshot(): Snapshot<M>;
|
|
356
|
+
constructor(machine: M, { id, input }?: RuntimeOptions<I<M>>);
|
|
357
|
+
subscribe(onSnapshot: Subscriber<M>['onSnapshot'], onError?: Subscriber<M>['onError']): () => void;
|
|
378
358
|
start(): this;
|
|
379
|
-
send(event:
|
|
359
|
+
send(event: SendFnEvent<M>): this;
|
|
380
360
|
stop(): this;
|
|
381
|
-
onEmitted(emittedEventType: EM$1<
|
|
361
|
+
onEmitted(emittedEventType: EM$1<M>['type'], handler: (emittedEvent: EM$1<M>) => void): () => void;
|
|
382
362
|
}
|
|
383
363
|
//#endregion
|
|
384
364
|
//#region src/tools/waitFor.d.ts
|
|
385
|
-
export declare function waitFor<
|
|
365
|
+
export declare function waitFor<R extends Runtime<any>>(runtime: R, cond: (snapshot: SnapshotFrom<R>) => boolean, options?: {
|
|
386
366
|
timeout?: number;
|
|
387
|
-
}): Promise<SnapshotFrom<
|
|
367
|
+
}): Promise<SnapshotFrom<R>>;
|
|
388
368
|
//#endregion
|
|
389
|
-
export type { AnyMachine, BuiltinEType, EmitFn as Emit, EmittableEvent, ListenFn as Listen, MContext, Runtime, RuntimeOptions, RuntimeStatus, SendableEvent, ServiceFn };
|
|
369
|
+
export type { AnyMachine, BuiltinEType, EmitFn as Emit, EmittableEvent, ListenFn as Listen, MContext, Runtime, RuntimeOptions, RuntimeStatus, SendFnEvent, SendableEvent, ServiceFn, Snapshot };
|
package/dist/index.d.mts
CHANGED
|
@@ -59,7 +59,9 @@ type EmittableEvent = {
|
|
|
59
59
|
[key: string]: any;
|
|
60
60
|
};
|
|
61
61
|
type StateName = string;
|
|
62
|
-
type
|
|
62
|
+
type O_PureETypeString<E extends SendableEvent> = E extends unknown ? Exclude<keyof E, "type"> extends never ? E['type'] : never : any;
|
|
63
|
+
type O_InferMachineSendableEvent<M extends AnyMachine> = M extends Machine<any, infer E, any, any, any, any, any, any, any> ? E : never;
|
|
64
|
+
type SendFnEvent<M extends AnyMachine> = O_InferMachineSendableEvent<M> extends (infer E extends SendableEvent) ? E | O_PureETypeString<E> : never;
|
|
63
65
|
type FnBaseParams<C extends MContext, Ex extends SendableEvent, I, Additional = unknown, Prm = any> = [arg: Expand<{
|
|
64
66
|
c: C;
|
|
65
67
|
context: C;
|
|
@@ -98,10 +100,10 @@ type EnqueueFn<C extends MContext, Ex extends SendableEvent, I, EM extends Emitt
|
|
|
98
100
|
};
|
|
99
101
|
type UpdateFnParam<C extends MContext> = { [K in keyof C]?: C[K] | (() => (C[K])); };
|
|
100
102
|
type UpdateFn<C extends MContext> = (updates: UpdateFnParam<C>) => unknown;
|
|
101
|
-
type
|
|
103
|
+
type O_InferServiceSendableEvent<S extends ServiceRecord[string]> = S extends Machine<any, infer E, any, any, any, any, any, any, any> ? E : S extends AnyFn ? (Parameters<S>[2] extends ListenFn<infer Er> ? Er : never) : never;
|
|
102
104
|
type SendToFn<S extends ServiceRecord> = {
|
|
103
|
-
<Sk extends keyof S>(serviceName: Sk, subKey: string | number, event:
|
|
104
|
-
<Sk extends keyof S>(serviceName: Sk, event:
|
|
105
|
+
<Sk extends keyof S>(serviceName: Sk, subKey: string | number, event: O_InferServiceSendableEvent<S[Sk]>): void;
|
|
106
|
+
<Sk extends keyof S>(serviceName: Sk, event: O_InferServiceSendableEvent<S[Sk]>): void;
|
|
105
107
|
};
|
|
106
108
|
type EmitFn<EM extends EmittableEvent> = (event: EM) => void;
|
|
107
109
|
type ListenFn<E extends SendableEvent> = (listener: (event: E) => void) => void;
|
|
@@ -212,7 +214,7 @@ type X_HiddenImpl = any & {
|
|
|
212
214
|
__brand: 'HiddenImpl';
|
|
213
215
|
};
|
|
214
216
|
type X_DefTypeRefluxer<C extends MContext, E extends SendableEvent, I // Input
|
|
215
|
-
, EM extends EmittableEvent, G extends Record<string, Placeholder>, A extends Record<string, Placeholder>, S extends ServiceRecord = ServiceRecord, Eb extends BuiltinEType = BuiltinEType,
|
|
217
|
+
, EM extends EmittableEvent, G extends Record<string, Placeholder>, A extends Record<string, Placeholder>, S extends ServiceRecord = ServiceRecord, Eb extends BuiltinEType = BuiltinEType, Ret = unknown> = () => Ret;
|
|
216
218
|
type X_DefineStatesTools = {
|
|
217
219
|
on: typeof on;
|
|
218
220
|
entryHook: typeof entryHook;
|
|
@@ -292,13 +294,14 @@ declare function invoke<C extends MContext, E extends SendableEvent, I, EM exten
|
|
|
292
294
|
declare function invoke<C extends MContext, E extends SendableEvent, I, EM extends EmittableEvent, const G extends Record<string, Placeholder>, const A extends Record<string, Placeholder>, S extends ServiceRecord, Src extends keyof S | InvokeSrcExpr<[SrcInput] extends [never] ? any : SrcInput>, SrcInput = never>(service: Src, config: InvokeConfig<C, E, I, S, Src, SrcInput>, ...events: InvocationEvents<C, I, EM, G, A, S, O_InferIvkSrcTypes<Src, S>>): readonly [typeof InvokeSymbol, X_DefTypeRefluxer<C, E, I, EM, G, A, S, BuiltinEType, unknown>, null, X_HiddenImpl, X_HiddenImpl, InvocationEvents<C, I, EM, G, A, S, O_InferIvkSrcTypes<Src, S>>];
|
|
293
295
|
type X_GlobalEvents<C extends MContext, E extends SendableEvent, I, EM extends EmittableEvent, G extends Record<string, Placeholder>, A extends Record<string, Placeholder>> = Array<readonly [E['type'] | BuiltinEType, X_DefTypeRefluxer<C, E, I, EM, G, A>, X_HiddenImpl]>;
|
|
294
296
|
export declare function defServiceFn<TFn extends ServiceFn>(fn: TFn): TFn;
|
|
295
|
-
export declare function
|
|
297
|
+
export declare function isMachine(v: unknown): v is AnyMachine;
|
|
298
|
+
export declare function makeMachine<C extends MContext, const E extends SendableEvent, const I, const EM extends EmittableEvent, const O, const S extends ServiceRecord, const D extends { [K in string]: StateDefinition<C, E, I, EM, G, A, S>; }, const G extends Record<string, Placeholder> = Record<string, Placeholder>, const A extends Record<string, Placeholder> = Record<string, Placeholder>>(config: Expand<MachineConfig<C, E, I, EM, O, G, A, S>>, defineStates: (defineStatesTools: Expand<X_DefineStatesTools>) => readonly [X_GlobalEvents<C, E, I, EM, G, A>, D] | readonly [D] | D): Machine<C, E, I, EM, O, G, A, S, {
|
|
296
299
|
initial: string;
|
|
297
300
|
stateOf: { [K in keyof D]: {
|
|
298
301
|
def: NStateItemDef<X_ExtractEType<D[K]>>;
|
|
299
302
|
sub: X_ExtractSubStDefinition<D[K]>;
|
|
300
303
|
}; };
|
|
301
|
-
}
|
|
304
|
+
}>;
|
|
302
305
|
//#endregion
|
|
303
306
|
//#region src/runtime/r.types.d.ts
|
|
304
307
|
type Child<TService> = TService extends AnyMachine ? Runtime<TService> : TService extends AnyFn ? {
|
|
@@ -308,82 +311,59 @@ type Child<TService> = TService extends AnyMachine ? Runtime<TService> : TServic
|
|
|
308
311
|
type Children<S extends ServiceRecord> = { [K in keyof S & string as K | `${K}:${string | number}`]?: Child<S[K]>; } & {
|
|
309
312
|
[key: string]: Child<any>;
|
|
310
313
|
};
|
|
311
|
-
type
|
|
312
|
-
C: any;
|
|
313
|
-
E: any;
|
|
314
|
-
I: any;
|
|
315
|
-
EM: any;
|
|
316
|
-
O: any;
|
|
317
|
-
G: any;
|
|
318
|
-
A: any;
|
|
319
|
-
S: any;
|
|
320
|
-
ND: any;
|
|
321
|
-
M: AnyMachine;
|
|
322
|
-
} : M extends Machine<infer C, infer E, infer I, infer EM, infer O, infer G, infer A, infer S, infer ND> ? {
|
|
323
|
-
C: C;
|
|
324
|
-
E: E;
|
|
325
|
-
I: I;
|
|
326
|
-
EM: EM;
|
|
327
|
-
O: O;
|
|
328
|
-
G: G;
|
|
329
|
-
A: A;
|
|
330
|
-
S: S;
|
|
331
|
-
ND: ND;
|
|
332
|
-
M: Machine<C, E, I, EM, O, G, A, S, ND>;
|
|
333
|
-
} : never;
|
|
334
|
-
type InferMInput<M extends AnyMachine> = M extends Machine<any, any, infer I, any, any, any, any, any, any> ? I : never;
|
|
335
|
-
type SnapshotFrom<RT extends Runtime<any>> = RT extends Runtime<any, infer Mt> ? Snapshot<Mt['C'], Mt['O'], Mt['S']> : never;
|
|
314
|
+
type SnapshotFrom<R extends Runtime<any>> = R extends Runtime<infer M> ? Snapshot<M> : never;
|
|
336
315
|
//#endregion
|
|
337
316
|
//#region src/runtime/Runtime.d.ts
|
|
338
317
|
type RuntimeStatus = 'notStarted' | 'active' | 'stopped' | 'done' | 'error';
|
|
339
|
-
type
|
|
318
|
+
type C<M extends AnyMachine> = M extends Machine<infer C, any, any, any, any, any, any, any, any> ? C : never;
|
|
319
|
+
type I<M extends AnyMachine> = M extends Machine<any, any, infer I, any, any, any, any, any, any> ? I : never;
|
|
320
|
+
type EM$1<M extends AnyMachine> = M extends Machine<any, any, any, infer EM, any, any, any, any, any> ? EM : never;
|
|
321
|
+
type O$1<M extends AnyMachine> = M extends Machine<any, any, any, any, infer O, any, any, any, any> ? O : never;
|
|
322
|
+
type S<M extends AnyMachine> = M extends Machine<any, any, any, any, any, any, any, infer S, any> ? S : never;
|
|
323
|
+
type X_RemovePrivateKeys<T extends Record<string, unknown>> = { [K in keyof T as K extends `_${string}` ? never : K]: T[K]; };
|
|
324
|
+
type Snapshot<M extends AnyMachine> = {
|
|
340
325
|
runtimeId: string;
|
|
341
326
|
states: string[];
|
|
342
327
|
stateValue: string | string[] | undefined;
|
|
343
|
-
context: Expand<X_RemovePrivateKeys<C
|
|
344
|
-
c: Expand<X_RemovePrivateKeys<C
|
|
328
|
+
context: Expand<X_RemovePrivateKeys<C<M>>>;
|
|
329
|
+
c: Expand<X_RemovePrivateKeys<C<M>>>;
|
|
345
330
|
runtimeStatus: RuntimeStatus;
|
|
346
|
-
output: O | undefined;
|
|
331
|
+
output: O$1<M> | undefined;
|
|
347
332
|
error: unknown;
|
|
348
|
-
_children: Children<S
|
|
333
|
+
_children: Children<S<M>>;
|
|
334
|
+
_runtime: Runtime<M>;
|
|
349
335
|
};
|
|
350
|
-
type Subscriber<
|
|
351
|
-
onSnapshot?: (current: Expand<Snapshot<
|
|
336
|
+
type Subscriber<M extends AnyMachine> = {
|
|
337
|
+
onSnapshot?: (current: Expand<Snapshot<M>>, prev: Expand<Snapshot<M>>) => void;
|
|
352
338
|
onError?: (err: unknown) => void;
|
|
353
339
|
};
|
|
354
|
-
|
|
340
|
+
export declare function isRuntime(v: unknown): v is Runtime<AnyMachine>;
|
|
341
|
+
type RuntimeOptions<M extends AnyMachine> = {
|
|
355
342
|
id?: string;
|
|
356
|
-
input?: () => I
|
|
343
|
+
input?: () => I<M>;
|
|
357
344
|
};
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
type C$1<Mt extends InferredMachineTypes<any>> = Mt['C'];
|
|
361
|
-
type E$1<Mt extends InferredMachineTypes<any>> = Mt['E'];
|
|
362
|
-
type I$1<Mt extends InferredMachineTypes<any>> = Mt['I'];
|
|
363
|
-
type EM$1<Mt extends InferredMachineTypes<any>> = Mt['EM'];
|
|
364
|
-
type O$1<Mt extends InferredMachineTypes<any>> = Mt['O'];
|
|
365
|
-
type S$1<Mt extends InferredMachineTypes<any>> = Mt['S'];
|
|
366
|
-
declare class Runtime<M extends AnyMachine, Mt extends InferredMachineTypes<M> = InferredMachineTypes<M>> {
|
|
345
|
+
export declare function makeRuntime<M extends AnyMachine>(machine: M, options?: RuntimeOptions<M>): Runtime<M>;
|
|
346
|
+
declare class Runtime<M extends AnyMachine> {
|
|
367
347
|
#private;
|
|
368
348
|
readonly id: string;
|
|
369
|
-
readonly machine:
|
|
349
|
+
readonly machine: M;
|
|
370
350
|
get states(): string[];
|
|
371
351
|
get stateValue(): string | string[] | undefined;
|
|
372
|
-
get context(): X_RemovePrivateKeys<C
|
|
352
|
+
get context(): X_RemovePrivateKeys<C<M>> extends (infer T) ? { [K in keyof T]: X_RemovePrivateKeys<C<M>>[K]; } : never;
|
|
373
353
|
get runtimeStatus(): RuntimeStatus;
|
|
374
|
-
get output(): O$1<
|
|
375
|
-
getSnapshot(): Snapshot<
|
|
376
|
-
constructor(machine: M, { id, input }?: RuntimeOptions<I
|
|
377
|
-
subscribe(onSnapshot: Subscriber<
|
|
354
|
+
get output(): O$1<M> | undefined;
|
|
355
|
+
getSnapshot(): Snapshot<M>;
|
|
356
|
+
constructor(machine: M, { id, input }?: RuntimeOptions<I<M>>);
|
|
357
|
+
subscribe(onSnapshot: Subscriber<M>['onSnapshot'], onError?: Subscriber<M>['onError']): () => void;
|
|
378
358
|
start(): this;
|
|
379
|
-
send(event:
|
|
359
|
+
send(event: SendFnEvent<M>): this;
|
|
380
360
|
stop(): this;
|
|
381
|
-
onEmitted(emittedEventType: EM$1<
|
|
361
|
+
onEmitted(emittedEventType: EM$1<M>['type'], handler: (emittedEvent: EM$1<M>) => void): () => void;
|
|
382
362
|
}
|
|
383
363
|
//#endregion
|
|
384
364
|
//#region src/tools/waitFor.d.ts
|
|
385
|
-
export declare function waitFor<
|
|
365
|
+
export declare function waitFor<R extends Runtime<any>>(runtime: R, cond: (snapshot: SnapshotFrom<R>) => boolean, options?: {
|
|
386
366
|
timeout?: number;
|
|
387
|
-
}): Promise<SnapshotFrom<
|
|
367
|
+
}): Promise<SnapshotFrom<R>>;
|
|
388
368
|
//#endregion
|
|
389
|
-
export type { AnyMachine, BuiltinEType, EmitFn as Emit, EmittableEvent, ListenFn as Listen, MContext, Runtime, RuntimeOptions, RuntimeStatus, SendableEvent, ServiceFn };
|
|
369
|
+
export type { AnyMachine, BuiltinEType, EmitFn as Emit, EmittableEvent, ListenFn as Listen, MContext, Runtime, RuntimeOptions, RuntimeStatus, SendFnEvent, SendableEvent, ServiceFn, Snapshot };
|
package/dist/index.mjs
CHANGED
|
@@ -518,6 +518,11 @@ function getDefinitionAndCatalog(config, defineStates) {
|
|
|
518
518
|
function defServiceFn(fn) {
|
|
519
519
|
return fn;
|
|
520
520
|
}
|
|
521
|
+
function isMachine(v) {
|
|
522
|
+
if (!(v && typeof v === "object" && "internal" in v)) return false;
|
|
523
|
+
const { internal } = v;
|
|
524
|
+
return !!(internal && typeof internal === "object" && MachineSymbol in internal);
|
|
525
|
+
}
|
|
521
526
|
function makeMachine(config, defineStates) {
|
|
522
527
|
const { definition, topLvDefItem, stateCatalog } = getDefinitionAndCatalog(config, defineStates);
|
|
523
528
|
const { name, initContext, output, guards, actions, services } = config;
|
|
@@ -1486,6 +1491,9 @@ function exitAndEntry(tExecs, crrStates, actionRunner, { guards, services, state
|
|
|
1486
1491
|
}
|
|
1487
1492
|
//#endregion
|
|
1488
1493
|
//#region src/runtime/Runtime.ts
|
|
1494
|
+
function isRuntime(v) {
|
|
1495
|
+
return v instanceof Runtime;
|
|
1496
|
+
}
|
|
1489
1497
|
function makeRuntime(machine, options) {
|
|
1490
1498
|
return new Runtime(machine, options);
|
|
1491
1499
|
}
|
|
@@ -1662,8 +1670,10 @@ var Runtime = class {
|
|
|
1662
1670
|
output: void 0
|
|
1663
1671
|
}, this.#input)),
|
|
1664
1672
|
error: void 0,
|
|
1665
|
-
_children: this.#outbound.children
|
|
1673
|
+
_children: this.#outbound.children,
|
|
1674
|
+
_runtime: this
|
|
1666
1675
|
};
|
|
1676
|
+
Object.defineProperty(this.#snapshot, "_runtime", { enumerable: false });
|
|
1667
1677
|
{
|
|
1668
1678
|
const snapshot = this.#snapshot;
|
|
1669
1679
|
for (const { onSnapshot } of this.#subscribers) {
|
|
@@ -1735,4 +1745,4 @@ async function waitFor(runtime, cond, options) {
|
|
|
1735
1745
|
});
|
|
1736
1746
|
}
|
|
1737
1747
|
//#endregion
|
|
1738
|
-
export { defServiceFn, makeMachine, makeRuntime, waitFor };
|
|
1748
|
+
export { defServiceFn, isMachine, isRuntime, makeMachine, makeRuntime, waitFor };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "small-state",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "A state machine inspired by XState.",
|
|
5
5
|
"author": "qyvvy",
|
|
6
6
|
"license": "MIT",
|
|
@@ -27,7 +27,9 @@
|
|
|
27
27
|
"dist",
|
|
28
28
|
"THIRD_PARTY_LICENSES.md"
|
|
29
29
|
],
|
|
30
|
-
"engines": {
|
|
30
|
+
"engines": {
|
|
31
|
+
"node": ">=18"
|
|
32
|
+
},
|
|
31
33
|
"dependencies": {
|
|
32
34
|
"arktype": "^2.2.8"
|
|
33
35
|
},
|