aifsmjs 0.5.1 → 0.5.3
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 +43 -9
- package/README_ZHTW.md +44 -10
- package/dist/effects/index.d.cts +1 -1
- package/dist/effects/index.d.ts +1 -1
- package/dist/guards/index.d.cts +1 -1
- package/dist/guards/index.d.ts +1 -1
- package/dist/index.cjs +29 -21
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +40 -14
- package/dist/index.d.ts +40 -14
- package/dist/index.js +28 -22
- package/dist/index.js.map +1 -1
- package/dist/inspect/index.d.cts +1 -1
- package/dist/inspect/index.d.ts +1 -1
- package/dist/pbt/index.cjs +17 -8
- package/dist/pbt/index.cjs.map +1 -1
- package/dist/pbt/index.d.cts +1 -1
- package/dist/pbt/index.d.ts +1 -1
- package/dist/pbt/index.js +17 -8
- package/dist/pbt/index.js.map +1 -1
- package/dist/replay/index.cjs +13 -2
- package/dist/replay/index.cjs.map +1 -1
- package/dist/replay/index.d.cts +1 -1
- package/dist/replay/index.d.ts +1 -1
- package/dist/replay/index.js +13 -2
- package/dist/replay/index.js.map +1 -1
- package/dist/{types-CGKk6Rur.d.cts → types-DIM7QTtf.d.cts} +32 -2
- package/dist/{types-CGKk6Rur.d.ts → types-DIM7QTtf.d.ts} +32 -2
- package/llms-full.txt +55 -9
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -164,13 +164,34 @@ aifsmjs follows the XState v5 two-phase pattern (`setup().createMachine()`): the
|
|
|
164
164
|
|
|
165
165
|
```typescript
|
|
166
166
|
function defineMachine<
|
|
167
|
-
Ctx,
|
|
168
|
-
Evt extends { type: string },
|
|
169
|
-
States extends string,
|
|
170
|
-
>(def:
|
|
167
|
+
Ctx = Record<string, never>,
|
|
168
|
+
Evt extends { type: string } = { type: string },
|
|
169
|
+
States extends string = string,
|
|
170
|
+
>(def: MachineConfig<Ctx, Evt, States>): MachineDef<Ctx, Evt, States>;
|
|
171
171
|
```
|
|
172
172
|
|
|
173
|
-
Pure data builder.
|
|
173
|
+
Pure data builder. Validates that `initial` exists in the `states` map and returns the (normalized) definition.
|
|
174
|
+
|
|
175
|
+
`context` is **optional** — omit it for stateless machines and it defaults to `{}` (the type parameter defaults to `Record<string, never>`). Existing definitions that pass `context` are unaffected.
|
|
176
|
+
|
|
177
|
+
```typescript
|
|
178
|
+
// No context needed — defaults to {}
|
|
179
|
+
const toggle = defineMachine({
|
|
180
|
+
id: "toggle",
|
|
181
|
+
initial: "off",
|
|
182
|
+
states: {
|
|
183
|
+
off: { on: { TOGGLE: "on" } }, // string shorthand, see below
|
|
184
|
+
on: { on: { TOGGLE: "off" } },
|
|
185
|
+
},
|
|
186
|
+
});
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
**String-shorthand transitions.** A transition value may be either the full object form or a bare target-state string (à la XState). The string is normalized to `{ target }` before processing — it carries no guard or actions:
|
|
190
|
+
|
|
191
|
+
```typescript
|
|
192
|
+
on: { NEXT: "green" } // shorthand for { target: "green" }
|
|
193
|
+
on: { NEXT: [{ target: "a", guard: "g" }, "b"] } // mixes with the object form
|
|
194
|
+
```
|
|
174
195
|
|
|
175
196
|
### `createRuntime(def, impl, opts?)`
|
|
176
197
|
|
|
@@ -207,7 +228,7 @@ function step<C, E, S>(
|
|
|
207
228
|
): { snapshot: Snapshot<C, S>; effects: readonly Effect[] };
|
|
208
229
|
```
|
|
209
230
|
|
|
210
|
-
**Pure function**. The invariant keeper for the whole library. It never dispatches effects
|
|
231
|
+
**Pure function**. The invariant keeper for the whole library. It never dispatches effects and never mutates the snapshot. A failing guard or unmapped event simply returns the original snapshot unchanged. It does throw on misuse (`UnknownGuardError`, `UnknownActionError`, `AsyncGuardError`) so guard/action wiring errors surface at development time rather than silently passing.
|
|
211
232
|
|
|
212
233
|
### `assign(updater)`
|
|
213
234
|
|
|
@@ -266,7 +287,7 @@ const runtime = createRuntime(def, impl, {
|
|
|
266
287
|
});
|
|
267
288
|
```
|
|
268
289
|
|
|
269
|
-
Koa-style `(ctx, next) => void` pipeline. `ctx` is `{ prev, next, event, effects }`, all
|
|
290
|
+
Koa-style `(ctx, next) => void` pipeline. `ctx` is `{ prev, next, event, effects, changed }`, all deep-frozen. **Cannot cancel a transition** — `next()` must be called; the return value carries no meaning.
|
|
270
291
|
|
|
271
292
|
### `aifsmjs/replay` — Pure event log replay
|
|
272
293
|
|
|
@@ -285,14 +306,25 @@ Never dispatches effects. For PBT, time-travel debugging, and incident reproduct
|
|
|
285
306
|
|
|
286
307
|
```typescript
|
|
287
308
|
import fc from "fast-check";
|
|
288
|
-
import {
|
|
309
|
+
import { createRuntime } from "aifsmjs";
|
|
310
|
+
import { commandsFromMachine, initialModel, properties } from "aifsmjs/pbt";
|
|
311
|
+
|
|
312
|
+
// Use one of the six built-in generic properties, or assertAll for all at once:
|
|
313
|
+
properties.replayEqualsFold(def, impl, {
|
|
314
|
+
NEXT: fc.constant({ type: "NEXT" as const }),
|
|
315
|
+
});
|
|
289
316
|
|
|
317
|
+
// Or build a custom property using commandsFromMachine:
|
|
290
318
|
fc.assert(
|
|
291
319
|
fc.property(
|
|
292
320
|
commandsFromMachine(def, impl, {
|
|
293
321
|
NEXT: fc.constant({ type: "NEXT" as const }),
|
|
294
322
|
}),
|
|
295
|
-
(cmds) =>
|
|
323
|
+
(cmds) => {
|
|
324
|
+
const real = createRuntime(def, impl, { dispatchEffects: false });
|
|
325
|
+
fc.modelRun(() => ({ model: initialModel(def), real }), cmds);
|
|
326
|
+
return true;
|
|
327
|
+
},
|
|
296
328
|
),
|
|
297
329
|
);
|
|
298
330
|
```
|
|
@@ -406,6 +438,8 @@ aifsmjs ships a few opinionated calls that look different from the typical FSM l
|
|
|
406
438
|
- **Guards and reducers are sync.** A non-deterministic guard would break the PBT determinism property (#1 in the generic suite). Move async predicates into events: send `FETCH_REQUEST`, then later `FETCH_DONE` with the resolved value as payload.
|
|
407
439
|
- **Effects are descriptors, not inline callbacks.** Actions enqueue `{ type, payload }` via `enqueue.effect(...)`; the runtime collects them and the dispatcher invokes user handlers. This keeps machine definitions serializable (JSON round-trippable when no inline functions are used), enables `replay()` to fold an event log into the same snapshot, and lets `inspect/persist` middleware capture effects for audit logs.
|
|
408
440
|
- **Two factory paths coexist.** `setup<Ctx, Evt>().defineMachine(...)` is the type-friendly form (States inferred from `keyof states`). `createMachine(def, impl, opts?)` is the spec-style single-factory shortcut from the ai*js ecosystem review. Plain `defineMachine<Ctx, Evt, States>(def)` remains for explicit generic control. Pick whichever reads best at the call site.
|
|
441
|
+
- **Transitions accept a string shorthand.** `on: { EVENT: "targetState" }` is sugar for `on: { EVENT: { target: "targetState" } }`, normalized in the resolver before any guard/action processing. The shorthand has no guard or actions; reach for the object form when you need them. It composes inside the array form too, so guard-fallthrough lists can mix `{ target, guard }` objects with bare target strings. The full object form is unchanged — this is purely additive.
|
|
442
|
+
- **`context` is optional.** Omit it for stateless machines and it defaults to `{}` (`Ctx` defaults to `Record<string, never>`). Definitions that already pass `context` keep their inferred type and behave identically.
|
|
409
443
|
- **`subscribe(listener)` and `on(type, fn, { signal, once })` both exist.** The typed `on()` matches the platform `EventTarget` semantics (signal + once) and emits `'transition'`, `'error'`, `'dispose'`. The older `subscribe()` keeps the React `useSyncExternalStore` shape — pass it directly. They are not exclusive.
|
|
410
444
|
|
|
411
445
|
---
|
package/README_ZHTW.md
CHANGED
|
@@ -163,13 +163,34 @@ aifsmjs 走 XState v5 `setup().createMachine()` 雙階段路線:definition 用
|
|
|
163
163
|
|
|
164
164
|
```typescript
|
|
165
165
|
function defineMachine<
|
|
166
|
-
Ctx,
|
|
167
|
-
Evt extends { type: string },
|
|
168
|
-
States extends string,
|
|
169
|
-
>(def:
|
|
166
|
+
Ctx = Record<string, never>,
|
|
167
|
+
Evt extends { type: string } = { type: string },
|
|
168
|
+
States extends string = string,
|
|
169
|
+
>(def: MachineConfig<Ctx, Evt, States>): MachineDef<Ctx, Evt, States>;
|
|
170
170
|
```
|
|
171
171
|
|
|
172
|
-
純資料 builder
|
|
172
|
+
純資料 builder。會驗證 `initial` 在 `states` 集合內並回傳(正規化後的)def。
|
|
173
|
+
|
|
174
|
+
`context` 為**選填**——無狀態機器可省略,會預設為 `{}`(型別參數預設為 `Record<string, never>`)。原本就有傳 `context` 的定義完全不受影響。
|
|
175
|
+
|
|
176
|
+
```typescript
|
|
177
|
+
// 不需要 context——預設為 {}
|
|
178
|
+
const toggle = defineMachine({
|
|
179
|
+
id: "toggle",
|
|
180
|
+
initial: "off",
|
|
181
|
+
states: {
|
|
182
|
+
off: { on: { TOGGLE: "on" } }, // 字串簡寫,見下
|
|
183
|
+
on: { on: { TOGGLE: "off" } },
|
|
184
|
+
},
|
|
185
|
+
});
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
**字串簡寫 transition。** transition 的值可以是完整物件形式,也可以是單純的目標 state 字串(仿 XState)。字串會在進入任何 guard/action 處理前被正規化成 `{ target }`——它不帶 guard 或 actions:
|
|
189
|
+
|
|
190
|
+
```typescript
|
|
191
|
+
on: { NEXT: "green" } // 等同 { target: "green" }
|
|
192
|
+
on: { NEXT: [{ target: "a", guard: "g" }, "b"] } // 可與物件形式混用
|
|
193
|
+
```
|
|
173
194
|
|
|
174
195
|
### `createRuntime(def, impl, opts?)`
|
|
175
196
|
|
|
@@ -206,7 +227,7 @@ function step<C, E, S>(
|
|
|
206
227
|
): { snapshot: Snapshot<C, S>; effects: readonly Effect[] };
|
|
207
228
|
```
|
|
208
229
|
|
|
209
|
-
**Pure function**。整個 library 的 invariant 守護者。不會 dispatch effects、不會 mutate snapshot
|
|
230
|
+
**Pure function**。整個 library 的 invariant 守護者。不會 dispatch effects、不會 mutate snapshot。Guard 沒過或 event 沒對應 transition 就回原 snapshot(不改變)。誤用(`UnknownGuardError`、`UnknownActionError`、`AsyncGuardError`)才會丟錯,讓配接錯誤在開發期間立即浮現、不被靜默略過。
|
|
210
231
|
|
|
211
232
|
### `assign(updater)`
|
|
212
233
|
|
|
@@ -265,7 +286,7 @@ const runtime = createRuntime(def, impl, {
|
|
|
265
286
|
});
|
|
266
287
|
```
|
|
267
288
|
|
|
268
|
-
Koa-style `(ctx, next) => void` pipeline。`ctx` 是 `{ prev, next, event, effects }`,全部
|
|
289
|
+
Koa-style `(ctx, next) => void` pipeline。`ctx` 是 `{ prev, next, event, effects, changed }`,全部 deep-frozen。**不能中止 transition**——`next()` 必呼叫,回傳值無語意。
|
|
269
290
|
|
|
270
291
|
### `aifsmjs/replay` — Pure event log replay
|
|
271
292
|
|
|
@@ -284,14 +305,25 @@ const finalSnap = replay(initialSnapshot, eventLog, def, impl);
|
|
|
284
305
|
|
|
285
306
|
```typescript
|
|
286
307
|
import fc from "fast-check";
|
|
287
|
-
import {
|
|
308
|
+
import { createRuntime } from "aifsmjs";
|
|
309
|
+
import { commandsFromMachine, initialModel, properties } from "aifsmjs/pbt";
|
|
310
|
+
|
|
311
|
+
// 用任一內建 generic property,或 assertAll 一次跑全部:
|
|
312
|
+
properties.replayEqualsFold(def, impl, {
|
|
313
|
+
NEXT: fc.constant({ type: "NEXT" as const }),
|
|
314
|
+
});
|
|
288
315
|
|
|
316
|
+
// 或用 commandsFromMachine 自訂 property:
|
|
289
317
|
fc.assert(
|
|
290
318
|
fc.property(
|
|
291
319
|
commandsFromMachine(def, impl, {
|
|
292
320
|
NEXT: fc.constant({ type: "NEXT" as const }),
|
|
293
321
|
}),
|
|
294
|
-
(cmds) =>
|
|
322
|
+
(cmds) => {
|
|
323
|
+
const real = createRuntime(def, impl, { dispatchEffects: false });
|
|
324
|
+
fc.modelRun(() => ({ model: initialModel(def), real }), cmds);
|
|
325
|
+
return true;
|
|
326
|
+
},
|
|
295
327
|
),
|
|
296
328
|
);
|
|
297
329
|
```
|
|
@@ -398,8 +430,10 @@ aifsmjs 在幾個常見議題上做了刻意取捨,跟主流 FSM library 寫
|
|
|
398
430
|
|
|
399
431
|
- **`send()` 是同步、回傳 `Snapshot` 而非 `Promise<Snapshot>`**。Pure `step()` 設計上就是 sync,`replay(initial, log)` 與 PBT shrinking 才能單純。Effect handler 仍可 async;runtime 觸發後忽略結果,async rejection 走 `'error'` event channel。要 await effect 完成的人可自己包一層 `Promise.all`。
|
|
400
432
|
- **Guards / reducers 只能 sync**。非確定性 guard 會破壞 PBT determinism property (#1)。把 async 改寫成 event:先送 `FETCH_REQUEST`,handler 完成後送 `FETCH_DONE`,payload 帶結果。
|
|
401
|
-
- **Effects 是描述子,不是 inline callback**。Action 透過 `enqueue.effect(
|
|
433
|
+
- **Effects 是描述子,不是 inline callback**。Action 透過 `enqueue.effect(type, payload?)` 排隊;runtime 收集後 dispatcher 才執行 user handler。好處:machine definition 可序列化(沒 inline fn 時 JSON round-trip)、`replay()` 可把 event log 摺成同樣 snapshot、`inspect/persist` middleware 抓得到 effects 做 audit log。
|
|
402
434
|
- **兩種 factory 並存**。`setup<Ctx, Evt>().defineMachine(...)` 是型別友善版(States 從 `keyof states` 推導)。`createMachine(def, impl, opts?)` 是來自 ai*js 生態 spec 的 single-factory 捷徑。顯式 `defineMachine<Ctx, Evt, States>(def)` 仍保留作完全顯式控制。看 call site 哪個讀起來順手就用哪個。
|
|
435
|
+
- **transition 支援字串簡寫**。`on: { EVENT: "targetState" }` 是 `on: { EVENT: { target: "targetState" } }` 的語法糖,在 resolver 於任何 guard/action 處理前正規化。簡寫不帶 guard 或 actions;需要時改用物件形式。它也能在陣列形式中混用,所以 guard-fallthrough 清單可以同時放 `{ target, guard }` 物件與單純的目標字串。完整物件形式不變——此為純加法。
|
|
436
|
+
- **`context` 為選填**。無狀態機器可省略,預設為 `{}`(`Ctx` 預設為 `Record<string, never>`)。原本就傳 `context` 的定義型別推導與行為完全相同。
|
|
403
437
|
- **`subscribe(listener)` 與 `on(type, fn, { signal, once })` 並存**。Typed `on()` 對齊平台 `EventTarget` 語意(signal + once),emit `'transition'`、`'error'`、`'dispose'`。原本的 `subscribe()` 保留 React `useSyncExternalStore` shape,可直接傳。兩者不互斥。
|
|
404
438
|
|
|
405
439
|
---
|
package/dist/effects/index.d.cts
CHANGED
package/dist/effects/index.d.ts
CHANGED
package/dist/guards/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { e as GuardRef, G as Guard } from '../types-
|
|
1
|
+
import { e as GuardRef, G as Guard } from '../types-DIM7QTtf.cjs';
|
|
2
2
|
|
|
3
3
|
/** Logical AND over guards. Short-circuits on the first `false`. */
|
|
4
4
|
declare function and<Ctx, Evt>(items: readonly GuardRef<Ctx, Evt>[]): Guard<Ctx, Evt>;
|
package/dist/guards/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { e as GuardRef, G as Guard } from '../types-
|
|
1
|
+
import { e as GuardRef, G as Guard } from '../types-DIM7QTtf.js';
|
|
2
2
|
|
|
3
3
|
/** Logical AND over guards. Short-circuits on the first `false`. */
|
|
4
4
|
declare function and<Ctx, Evt>(items: readonly GuardRef<Ctx, Evt>[]): Guard<Ctx, Evt>;
|
package/dist/index.cjs
CHANGED
|
@@ -52,6 +52,23 @@ function evalGuard(ref, context, event, impl, value) {
|
|
|
52
52
|
return result;
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
+
// src/fsm/resolver.ts
|
|
56
|
+
function normalizeTransition(entry) {
|
|
57
|
+
return typeof entry === "string" ? { target: entry } : entry;
|
|
58
|
+
}
|
|
59
|
+
function normalizeTransitions(entry) {
|
|
60
|
+
if (entry === void 0) return [];
|
|
61
|
+
if (Array.isArray(entry)) {
|
|
62
|
+
return entry.some((t) => typeof t === "string") ? entry.map((t) => normalizeTransition(t)) : entry;
|
|
63
|
+
}
|
|
64
|
+
return [normalizeTransition(entry)];
|
|
65
|
+
}
|
|
66
|
+
function resolveTransitions(def, stateValue, eventType) {
|
|
67
|
+
const state = def.states[stateValue];
|
|
68
|
+
if (!state || !state.on) return [];
|
|
69
|
+
return normalizeTransitions(state.on[eventType]);
|
|
70
|
+
}
|
|
71
|
+
|
|
55
72
|
// src/effects/enqueuer.ts
|
|
56
73
|
function createEnqueuer(sink) {
|
|
57
74
|
return Object.freeze({
|
|
@@ -154,8 +171,7 @@ function step(def, snapshot, event, impl) {
|
|
|
154
171
|
if (!state) {
|
|
155
172
|
return Object.freeze({ snapshot, effects: [], changed: false });
|
|
156
173
|
}
|
|
157
|
-
const
|
|
158
|
-
const candidateList = candidates ? Array.isArray(candidates) ? candidates : [candidates] : [];
|
|
174
|
+
const candidateList = normalizeTransitions(state.on?.[event.type]);
|
|
159
175
|
const chosen = pickTransition(candidateList, snapshot.context, event, impl, snapshot.value);
|
|
160
176
|
if (!chosen) {
|
|
161
177
|
return Object.freeze({ snapshot, effects: [], changed: false });
|
|
@@ -282,9 +298,8 @@ function createRuntime(def, impl, opts = {}) {
|
|
|
282
298
|
function findChosenIsExternal(value, event, context) {
|
|
283
299
|
const state = def.states[value];
|
|
284
300
|
if (!state?.on) return false;
|
|
285
|
-
const
|
|
286
|
-
if (
|
|
287
|
-
const list = Array.isArray(candidates) ? candidates : [candidates];
|
|
301
|
+
const list = normalizeTransitions(state.on[event.type]);
|
|
302
|
+
if (list.length === 0) return false;
|
|
288
303
|
for (const t of list) {
|
|
289
304
|
if (!t.guard || evalGuard(t.guard, context, event, impl, value)) {
|
|
290
305
|
return t.target !== void 0;
|
|
@@ -385,9 +400,8 @@ function createRuntime(def, impl, opts = {}) {
|
|
|
385
400
|
if (disposed || snapshot.status === "final") return false;
|
|
386
401
|
const state = def.states[snapshot.value];
|
|
387
402
|
if (!state) return false;
|
|
388
|
-
const
|
|
389
|
-
if (
|
|
390
|
-
const list = Array.isArray(candidates) ? candidates : [candidates];
|
|
403
|
+
const list = normalizeTransitions(state.on?.[event.type]);
|
|
404
|
+
if (list.length === 0) return false;
|
|
391
405
|
for (const t of list) {
|
|
392
406
|
if (!t.guard) return true;
|
|
393
407
|
if (evalGuard(t.guard, snapshot.context, event, impl, snapshot.value)) return true;
|
|
@@ -514,7 +528,7 @@ function validateDefinition(def) {
|
|
|
514
528
|
}
|
|
515
529
|
if (!stateDef.on) continue;
|
|
516
530
|
for (const [evtType, entry] of Object.entries(stateDef.on)) {
|
|
517
|
-
const transitions =
|
|
531
|
+
const transitions = normalizeTransitions(entry);
|
|
518
532
|
for (const t of transitions) {
|
|
519
533
|
if (t.target !== void 0 && !stateKeys.includes(t.target)) {
|
|
520
534
|
throw new InvalidDefinitionError(
|
|
@@ -531,13 +545,14 @@ function validateDefinition(def) {
|
|
|
531
545
|
}
|
|
532
546
|
}
|
|
533
547
|
function defineMachine(def) {
|
|
534
|
-
|
|
535
|
-
|
|
548
|
+
const normalized = !("context" in def) ? { ...def, context: {} } : def;
|
|
549
|
+
validateDefinition(normalized);
|
|
550
|
+
return normalized;
|
|
536
551
|
}
|
|
537
552
|
function setup() {
|
|
538
553
|
return {
|
|
539
554
|
defineMachine: (def) => {
|
|
540
|
-
const cast = def;
|
|
555
|
+
const cast = !("context" in def) ? { ...def, context: {} } : def;
|
|
541
556
|
validateDefinition(cast);
|
|
542
557
|
return cast;
|
|
543
558
|
}
|
|
@@ -555,15 +570,6 @@ function createMachine(def, impl, opts) {
|
|
|
555
570
|
return createRuntime(defineMachine(def), impl, opts ?? {});
|
|
556
571
|
}
|
|
557
572
|
|
|
558
|
-
// src/fsm/resolver.ts
|
|
559
|
-
function resolveTransitions(def, stateValue, eventType) {
|
|
560
|
-
const state = def.states[stateValue];
|
|
561
|
-
if (!state || !state.on) return [];
|
|
562
|
-
const entry = state.on[eventType];
|
|
563
|
-
if (!entry) return [];
|
|
564
|
-
return Array.isArray(entry) ? entry : [entry];
|
|
565
|
-
}
|
|
566
|
-
|
|
567
573
|
exports.AsyncGuardError = AsyncGuardError;
|
|
568
574
|
exports.InvalidDefinitionError = InvalidDefinitionError;
|
|
569
575
|
exports.RESET_EVENT_TYPE = RESET_EVENT_TYPE;
|
|
@@ -582,6 +588,8 @@ exports.freezeSnapshot = freezeSnapshot;
|
|
|
582
588
|
exports.initialSnapshot = initialSnapshot;
|
|
583
589
|
exports.isAsyncGuardFn = isAsyncGuardFn;
|
|
584
590
|
exports.mergeContext = mergeContext;
|
|
591
|
+
exports.normalizeTransition = normalizeTransition;
|
|
592
|
+
exports.normalizeTransitions = normalizeTransitions;
|
|
585
593
|
exports.resolveGuard = resolveGuard;
|
|
586
594
|
exports.resolveTransitions = resolveTransitions;
|
|
587
595
|
exports.setup = setup;
|