@demlik/tea 0.16.0 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent/index.d.ts +13 -13
- package/dist/agent/index.js +9 -9
- package/dist/{chunk-CIHSHLQX.js → chunk-4NTCPTNQ.js} +3 -3
- package/dist/{chunk-CIHSHLQX.js.map → chunk-4NTCPTNQ.js.map} +1 -1
- package/dist/{chunk-7MGXQZPW.js → chunk-4PXNZ5UY.js} +4 -4
- package/dist/{chunk-7MGXQZPW.js.map → chunk-4PXNZ5UY.js.map} +1 -1
- package/dist/{chunk-6NG4V5SB.js → chunk-6XBEYZME.js} +5 -5
- package/dist/{chunk-6NG4V5SB.js.map → chunk-6XBEYZME.js.map} +1 -1
- package/dist/{chunk-GOX2CYIM.js → chunk-C4U5D5HP.js} +3 -3
- package/dist/{chunk-GOX2CYIM.js.map → chunk-C4U5D5HP.js.map} +1 -1
- package/dist/{chunk-MVZS5FDM.js → chunk-DFUEAA6L.js} +3 -3
- package/dist/{chunk-MVZS5FDM.js.map → chunk-DFUEAA6L.js.map} +1 -1
- package/dist/{chunk-IVJP3GKJ.js → chunk-GWWCCSDH.js} +4 -4
- package/dist/{chunk-IVJP3GKJ.js.map → chunk-GWWCCSDH.js.map} +1 -1
- package/dist/{chunk-CH5KTOEZ.js → chunk-K4ETBNKS.js} +32 -9
- package/dist/chunk-K4ETBNKS.js.map +1 -0
- package/dist/{chunk-5XU6ZJO2.js → chunk-KWNCM6XM.js} +19 -13
- package/dist/chunk-KWNCM6XM.js.map +1 -0
- package/dist/{chunk-BCTEOVOU.js → chunk-LYVOGOBC.js} +3 -3
- package/dist/{chunk-BCTEOVOU.js.map → chunk-LYVOGOBC.js.map} +1 -1
- package/dist/{chunk-MYNLY3HP.js → chunk-OPH6Y4UT.js} +3 -3
- package/dist/{chunk-MYNLY3HP.js.map → chunk-OPH6Y4UT.js.map} +1 -1
- package/dist/{chunk-NSIAORRY.js → chunk-OYR7ENKU.js} +3 -3
- package/dist/{chunk-NSIAORRY.js.map → chunk-OYR7ENKU.js.map} +1 -1
- package/dist/{chunk-WT5PBPLB.js → chunk-QWIPH4YH.js} +4 -4
- package/dist/{chunk-WT5PBPLB.js.map → chunk-QWIPH4YH.js.map} +1 -1
- package/dist/{chunk-EHUDXAKC.js → chunk-XBZQT2TD.js} +7 -7
- package/dist/chunk-XBZQT2TD.js.map +1 -0
- package/dist/{core-BbgtiXdg.d.ts → core-rDbOaJTN.d.ts} +7 -3
- package/dist/do/index.d.ts +12 -12
- package/dist/do/index.js +10 -10
- package/dist/{durable-effects-7MTK_jnj.d.ts → durable-effects-CNaw97Be.d.ts} +1 -1
- package/dist/effect/index.d.ts +2 -2
- package/dist/effect/index.js +2 -2
- package/dist/extension/index.d.ts +3 -3
- package/dist/extension/index.js +2 -2
- package/dist/flow/index.d.ts +13 -13
- package/dist/flow/index.js +10 -10
- package/dist/idempotency/index.d.ts +3 -3
- package/dist/idempotency/index.js +3 -3
- package/dist/{index-Bz5Rh9Ga.d.ts → index-BOrsbdAf.d.ts} +4 -4
- package/dist/{index-DU6JpQ8G.d.ts → index-B_BxplWi.d.ts} +1 -1
- package/dist/{index-CjFDUBeq.d.ts → index-CWmsXNdX.d.ts} +1 -1
- package/dist/{index-_dOR3xqA.d.ts → index-Cberb5Rr.d.ts} +2 -2
- package/dist/{index-7vV8xmsD.d.ts → index-CcrKLtse.d.ts} +1 -1
- package/dist/{index-CkFYA9Y6.d.ts → index-Cx0F2M34.d.ts} +2 -2
- package/dist/{index-Xufl55W8.d.ts → index-DaX_P35Q.d.ts} +2 -2
- package/dist/{index-Cou86-GX.d.ts → index-q1PoukOZ.d.ts} +2 -2
- package/dist/index.d.ts +5 -5
- package/dist/index.js +2 -2
- package/dist/jev/index.d.ts +8 -8
- package/dist/jev/index.js +5 -5
- package/dist/{machine-BQzTV8On.d.ts → machine-BcfCFMYF.d.ts} +7 -7
- package/dist/machine-viz/index.d.ts +1 -1
- package/dist/machine-viz/index.js +2 -2
- package/dist/mem/index.d.ts +2 -2
- package/dist/mem/index.js +2 -2
- package/dist/node/index.d.ts +2 -2
- package/dist/node/index.js +2 -2
- package/dist/paginate/index.d.ts +4 -4
- package/dist/paginate/index.js +5 -5
- package/dist/parity/index.d.ts +3 -3
- package/dist/parity/index.js +3 -3
- package/dist/pbt/index.d.ts +1 -1
- package/dist/pbt/index.js +2 -2
- package/dist/persistence/index.d.ts +9 -10
- package/dist/persistence/index.js +4 -4
- package/dist/promise/index.d.ts +2 -2
- package/dist/promise/index.js +3 -3
- package/dist/react/index.d.ts +2 -2
- package/dist/resilience/index.d.ts +6 -6
- package/dist/resilience/index.js +5 -5
- package/dist/{runtime-types-CiVpC0HN.d.ts → runtime-types-B62Ucnxr.d.ts} +2 -2
- package/dist/testing/index.d.ts +22 -108
- package/dist/testing/index.js +27 -177
- package/dist/testing/index.js.map +1 -1
- package/dist/timing/index.d.ts +4 -4
- package/dist/timing/index.js +4 -4
- package/dist/{types-LxZxGYda.d.ts → types-DPm5YCDQ.d.ts} +1 -1
- package/dist/work-queue/index.d.ts +4 -4
- package/package.json +3 -3
- package/dist/chunk-5XU6ZJO2.js.map +0 -1
- package/dist/chunk-CH5KTOEZ.js.map +0 -1
- package/dist/chunk-EHUDXAKC.js.map +0 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { T as Trace } from '../index-
|
|
2
|
-
export { B as BreadcrumbsOptions, a as Recorder, R as RecorderOptions, b as TraceAttachment, c as TraceBreadcrumb, d as breadcrumbsFromTrace, p as parseJSONL, r as recorder, t as traceAttachment } from '../index-
|
|
3
|
-
export { c as SnapshotConfig, d as SnapshotFailedMsg, e as SnapshotKnob, f as SnapshotLoadCmd, g as SnapshotLoadFailedMsg, h as SnapshotLoadedMsg, b as SnapshotSavedMsg, a as SnapshotState, S as SnapshotWriteCmd, i as createSnapshot, s as snapshotLoadDef, j as snapshotWriteDef } from '../index-
|
|
4
|
-
import { C as Cmd, S as Sub, M as Machine } from '../core-
|
|
5
|
-
import '../runtime-types-
|
|
1
|
+
import { T as Trace } from '../index-B_BxplWi.js';
|
|
2
|
+
export { B as BreadcrumbsOptions, a as Recorder, R as RecorderOptions, b as TraceAttachment, c as TraceBreadcrumb, d as breadcrumbsFromTrace, p as parseJSONL, r as recorder, t as traceAttachment } from '../index-B_BxplWi.js';
|
|
3
|
+
export { c as SnapshotConfig, d as SnapshotFailedMsg, e as SnapshotKnob, f as SnapshotLoadCmd, g as SnapshotLoadFailedMsg, h as SnapshotLoadedMsg, b as SnapshotSavedMsg, a as SnapshotState, S as SnapshotWriteCmd, i as createSnapshot, s as snapshotLoadDef, j as snapshotWriteDef } from '../index-CWmsXNdX.js';
|
|
4
|
+
import { C as Cmd, S as Sub, M as Machine } from '../core-rDbOaJTN.js';
|
|
5
|
+
import '../runtime-types-B62Ucnxr.js';
|
|
6
6
|
import '@standard-schema/spec';
|
|
7
7
|
|
|
8
8
|
/**
|
|
@@ -55,12 +55,11 @@ declare function replayTrace<S, M extends {
|
|
|
55
55
|
/**
|
|
56
56
|
* Order-insensitive structural deep-equality — the comparator the
|
|
57
57
|
* record/replay lane owns, exposed so consumers (e.g. `@demlik/tea/parity`'s
|
|
58
|
-
* `parityEqual`) reuse it rather than adding a
|
|
59
|
-
* of
|
|
58
|
+
* `parityEqual`) reuse it rather than adding a third deep-compare. It is one
|
|
59
|
+
* of two structural walkers in the package, divergent on purpose:
|
|
60
60
|
* this `deepEqual` returns a boolean verdict (order-insensitive, for
|
|
61
|
-
* replay/parity equality), `devtools`'s `diffState` returns a change list
|
|
62
|
-
* a human-readable diff view),
|
|
63
|
-
* helpers' internal compare — same shape, three jobs, not one to collapse.
|
|
61
|
+
* replay/parity equality), and `devtools`'s `diffState` returns a change list
|
|
62
|
+
* (for a human-readable diff view) — same shape, two jobs, not one to collapse.
|
|
64
63
|
* `true` iff `a` and `b` are structurally equal under {@link firstDivergence}'s
|
|
65
64
|
* walk (object keys compared order-insensitively, arrays index-by-index).
|
|
66
65
|
*/
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
export { breadcrumbsFromTrace, deepEqual, parseJSONL, recorder, replayTrace, traceAttachment } from '../chunk-
|
|
2
|
-
export { createSnapshot, snapshotLoadDef, snapshotWriteDef } from '../chunk-
|
|
1
|
+
export { breadcrumbsFromTrace, deepEqual, parseJSONL, recorder, replayTrace, traceAttachment } from '../chunk-LYVOGOBC.js';
|
|
2
|
+
export { createSnapshot, snapshotLoadDef, snapshotWriteDef } from '../chunk-4NTCPTNQ.js';
|
|
3
3
|
import '../chunk-4LPY67E4.js';
|
|
4
|
-
import '../chunk-
|
|
5
|
-
import '../chunk-
|
|
4
|
+
import '../chunk-C4U5D5HP.js';
|
|
5
|
+
import '../chunk-K4ETBNKS.js';
|
|
6
6
|
import '../chunk-HWVW4AXC.js';
|
|
7
7
|
//# sourceMappingURL=index.js.map
|
|
8
8
|
//# sourceMappingURL=index.js.map
|
package/dist/promise/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { C as Cmd, S as Sub, M as Machine, R as RunHandlers } from '../core-
|
|
2
|
-
import { B as BootingRuntime, C as CtxArg, S as Store, O as OnError, a as Supervision, T as TelemetrySink } from '../runtime-types-
|
|
1
|
+
import { C as Cmd, S as Sub, M as Machine, R as RunHandlers } from '../core-rDbOaJTN.js';
|
|
2
|
+
import { B as BootingRuntime, C as CtxArg, S as Store, O as OnError, a as Supervision, T as TelemetrySink } from '../runtime-types-B62Ucnxr.js';
|
|
3
3
|
import '@standard-schema/spec';
|
|
4
4
|
|
|
5
5
|
/**
|
package/dist/promise/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { driveToDone, run } from '../chunk-
|
|
2
|
-
import '../chunk-
|
|
3
|
-
import '../chunk-
|
|
1
|
+
export { driveToDone, run } from '../chunk-QWIPH4YH.js';
|
|
2
|
+
import '../chunk-KWNCM6XM.js';
|
|
3
|
+
import '../chunk-K4ETBNKS.js';
|
|
4
4
|
//# sourceMappingURL=index.js.map
|
|
5
5
|
//# sourceMappingURL=index.js.map
|
package/dist/react/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { E as EngineRun, S as Store, b as BootedRunHandle } from '../runtime-types-
|
|
2
|
-
import { C as Cmd, S as Sub, R as RunHandlers, M as Machine } from '../core-
|
|
1
|
+
import { E as EngineRun, S as Store, b as BootedRunHandle } from '../runtime-types-B62Ucnxr.js';
|
|
2
|
+
import { C as Cmd, S as Sub, R as RunHandlers, M as Machine } from '../core-rDbOaJTN.js';
|
|
3
3
|
import '@standard-schema/spec';
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { c as CmdOf, b as CmdDef, f as SettledErr, g as TaggedError, e as SettledOk, T as TimerDeps, C as Cmd } from '../core-
|
|
1
|
+
import { c as CmdOf, b as CmdDef, f as SettledErr, g as TaggedError, e as SettledOk, T as TimerDeps, C as Cmd } from '../core-rDbOaJTN.js';
|
|
2
2
|
import { M as MsgType } from '../protocol-ClRZBhHQ.js';
|
|
3
|
-
import { a as DeadlineSub } from '../index-
|
|
4
|
-
export { A as ArmTimer, g as CacheEntry, f as CacheEvictMsg, h as CacheEvictionDeps, C as CacheEvictionSub, D as DeadlineExceeded, i as DeadlineMsgType, j as DeadlineOpts, b as DeadlinesSub, T as TtlCache, k as cacheEvictMsg, l as cacheEvictionSub, m as cacheEvictionSubscribe, d as deadlineExceeded, n as deadlineMsgType, c as deadlineSub, o as deadlines, e as deadlinesSub, p as evictExpired, q as get, r as has, t as initCache, u as nextTimer, v as remove, w as set, x as setTimeoutArmTimer, s as subscribeDeadline, y as subscribeWith } from '../index-
|
|
5
|
-
import { c as ResilientConfig, a as ResilientState, R as RunCmd, S as SucceedMsg, F as FailMsg, b as ResilientTimerMsg } from '../index-
|
|
6
|
-
export { C as CacheConfig, d as CallBudget, e as CallPhase, f as CircuitConfig, g as CircuitPolicy, h as CircuitState, D as DEFAULT_RESILIENT_NAME, i as DeadlineExceededError, j as DeadlineNameOf, k as DefaultResilientName, l as RateLimitConfig, m as ResilientCallDeadlineConfig, n as ResilientDeadlineType, o as ResilientErrType, p as ResilientOkType, q as ResilientRunType, r as RunCmdDef, s as RunErr, t as SettleMsg, u as SettleOutcome, v as SettleResult, w as SlidingWindow, T as TokenBucket, x as canPass, y as createResilientCall, z as defaultCircuitPolicy, A as initBucket, B as initCircuit, E as initWindow, G as liftResilience, H as onFailure, I as onSuccess, J as record, K as refill, L as remaining, M as runCmdDef, N as tryConsume } from '../index-
|
|
3
|
+
import { a as DeadlineSub } from '../index-DaX_P35Q.js';
|
|
4
|
+
export { A as ArmTimer, g as CacheEntry, f as CacheEvictMsg, h as CacheEvictionDeps, C as CacheEvictionSub, D as DeadlineExceeded, i as DeadlineMsgType, j as DeadlineOpts, b as DeadlinesSub, T as TtlCache, k as cacheEvictMsg, l as cacheEvictionSub, m as cacheEvictionSubscribe, d as deadlineExceeded, n as deadlineMsgType, c as deadlineSub, o as deadlines, e as deadlinesSub, p as evictExpired, q as get, r as has, t as initCache, u as nextTimer, v as remove, w as set, x as setTimeoutArmTimer, s as subscribeDeadline, y as subscribeWith } from '../index-DaX_P35Q.js';
|
|
5
|
+
import { c as ResilientConfig, a as ResilientState, R as RunCmd, S as SucceedMsg, F as FailMsg, b as ResilientTimerMsg } from '../index-q1PoukOZ.js';
|
|
6
|
+
export { C as CacheConfig, d as CallBudget, e as CallPhase, f as CircuitConfig, g as CircuitPolicy, h as CircuitState, D as DEFAULT_RESILIENT_NAME, i as DeadlineExceededError, j as DeadlineNameOf, k as DefaultResilientName, l as RateLimitConfig, m as ResilientCallDeadlineConfig, n as ResilientDeadlineType, o as ResilientErrType, p as ResilientOkType, q as ResilientRunType, r as RunCmdDef, s as RunErr, t as SettleMsg, u as SettleOutcome, v as SettleResult, w as SlidingWindow, T as TokenBucket, x as canPass, y as createResilientCall, z as defaultCircuitPolicy, A as initBucket, B as initCircuit, E as initWindow, G as liftResilience, H as onFailure, I as onSuccess, J as record, K as refill, L as remaining, M as runCmdDef, N as tryConsume } from '../index-q1PoukOZ.js';
|
|
7
7
|
import { Rng, RetryPolicy } from '../retry-backoff/index.js';
|
|
8
8
|
import '@standard-schema/spec';
|
|
9
|
-
import '../types-
|
|
9
|
+
import '../types-DPm5YCDQ.js';
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* A minted credential: the opaque `value` to send on the wire, and the absolute
|
package/dist/resilience/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { createResilientCall } from '../chunk-
|
|
2
|
-
export { DEFAULT_RESILIENT_NAME, canPass, createResilientCall, defaultCircuitPolicy, initBucket, initCircuit, initWindow, liftResilience, onFailure, onSuccess, record, refill, remaining, runCmdDef, tryConsume } from '../chunk-
|
|
1
|
+
import { createResilientCall } from '../chunk-6XBEYZME.js';
|
|
2
|
+
export { DEFAULT_RESILIENT_NAME, canPass, createResilientCall, defaultCircuitPolicy, initBucket, initCircuit, initWindow, liftResilience, onFailure, onSuccess, record, refill, remaining, runCmdDef, tryConsume } from '../chunk-6XBEYZME.js';
|
|
3
3
|
import { defaultRng, initRetry, recordFailure, shouldRetry, nextDelayMs } from '../chunk-VBDU4JL6.js';
|
|
4
4
|
import { unchecked } from '../chunk-4LPY67E4.js';
|
|
5
|
-
export { cacheEvictMsg, cacheEvictionSub, cacheEvictionSubscribe, deadlineExceeded, deadlineMsgType, deadlineSub, deadlines, deadlinesSub, evictExpired, get, has, initCache, nextTimer, remove, set, setTimeoutArmTimer, subscribeDeadline, subscribeWith } from '../chunk-
|
|
6
|
-
import '../chunk-
|
|
7
|
-
import { Cmd, without } from '../chunk-
|
|
5
|
+
export { cacheEvictMsg, cacheEvictionSub, cacheEvictionSubscribe, deadlineExceeded, deadlineMsgType, deadlineSub, deadlines, deadlinesSub, evictExpired, get, has, initCache, nextTimer, remove, set, setTimeoutArmTimer, subscribeDeadline, subscribeWith } from '../chunk-GWWCCSDH.js';
|
|
6
|
+
import '../chunk-C4U5D5HP.js';
|
|
7
|
+
import { Cmd, without } from '../chunk-K4ETBNKS.js';
|
|
8
8
|
|
|
9
9
|
// src/internal/resilience/token-refresh/index.ts
|
|
10
10
|
function initTokenRefresh() {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as Cmd, S as Sub, M as Machine, R as RunHandlers, P as Port, N as NoCellError, i as Reducer, A as AnyCmdDef, j as Settled, c as CmdOf, k as Transitions, a as BuiltinSub, U as UpdateForm, l as Outcome, I as InterpretDetached,
|
|
1
|
+
import { C as Cmd, S as Sub, M as Machine, R as RunHandlers, P as Port, N as NoCellError, i as Reducer, A as AnyCmdDef, j as Settled, c as CmdOf, k as Transitions, a as BuiltinSub, U as UpdateForm, l as Outcome, I as InterpretDetached, H as HandlerCtx } from './core-rDbOaJTN.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* @demlik/tea runtime interface surface + pure helpers — the public types,
|
|
@@ -683,7 +683,7 @@ declare function replay<S, M extends {
|
|
|
683
683
|
};
|
|
684
684
|
declare function wrapDetached<C extends Cmd, M extends {
|
|
685
685
|
type: string;
|
|
686
|
-
}, Allowed extends M, Ctx>(handler: InterpretDetached<C, Allowed, Ctx>): (cmd: C, ctx: Ctx
|
|
686
|
+
}, Allowed extends M, Ctx>(handler: InterpretDetached<C, Allowed, Ctx>): (cmd: C, ctx: HandlerCtx<Ctx>, dispatch?: (msg: M) => void) => Promise<void>;
|
|
687
687
|
/**
|
|
688
688
|
* `applyCell`, with "no handler for this Msg" moved into the return type
|
|
689
689
|
* instead of a throw.
|
package/dist/testing/index.d.ts
CHANGED
|
@@ -1,112 +1,7 @@
|
|
|
1
|
-
import { C as Cmd, S as Sub, M as Machine, a as BuiltinSub,
|
|
2
|
-
import { C as CtxArg, R as Runtime } from '../runtime-types-
|
|
1
|
+
import { C as Cmd, S as Sub, M as Machine, a as BuiltinSub, o as Interpret } from '../core-rDbOaJTN.js';
|
|
2
|
+
import { C as CtxArg, R as Runtime } from '../runtime-types-B62Ucnxr.js';
|
|
3
3
|
import '@standard-schema/spec';
|
|
4
4
|
|
|
5
|
-
/**
|
|
6
|
-
* The composed Model shape every `withX` wrapper produces: the base machine's
|
|
7
|
-
* state nested under `base`, and the wrapper's own NAMED, serializable slice
|
|
8
|
-
* under a single `$`-prefixed key. This helper does not care WHICH `$`-key the
|
|
9
|
-
* wrapper uses — it discovers it structurally (the one non-`base` field).
|
|
10
|
-
*/
|
|
11
|
-
type WrapperModel<S> = {
|
|
12
|
-
readonly base: S;
|
|
13
|
-
} & {
|
|
14
|
-
readonly [K: `$${string}`]: unknown;
|
|
15
|
-
};
|
|
16
|
-
/** Options for the conformance replay. Mirrors `replay`'s second argument. */
|
|
17
|
-
interface AssertWrapperFaithfulOpts<S, WM, BaseM, BaseCtx, WrapperCtx> {
|
|
18
|
-
/** The Msg sequence to fold through BOTH machines. Use the base's Msgs. */
|
|
19
|
-
readonly msgs: readonly BaseM[];
|
|
20
|
-
/** Ctx for the WRAPPED machine (base ctx + wrapper ports). */
|
|
21
|
-
readonly ctx: WrapperCtx;
|
|
22
|
-
/** Ctx for the BARE base machine. Defaults to `ctx` when omitted. */
|
|
23
|
-
readonly baseCtx?: BaseCtx;
|
|
24
|
-
/** Optional pre-`init` snapshot of the COMPOSED Model (wrapped rehydrate). */
|
|
25
|
-
readonly loaded?: WM | null;
|
|
26
|
-
/**
|
|
27
|
-
* Optional pre-`init` snapshot of the BARE base state. Supply when the
|
|
28
|
-
* wrapped `loaded` is non-null so the base-equivalence check rehydrates the
|
|
29
|
-
* base machine from the matching nested slice. Defaults to `loaded?.base`.
|
|
30
|
-
*/
|
|
31
|
-
readonly baseLoaded?: S | null;
|
|
32
|
-
/**
|
|
33
|
-
* Opt-in relaxation for an INTERCEPTING wrapper (e.g. a retry wrapper).
|
|
34
|
-
*
|
|
35
|
-
* DEFAULT (`undefined` / `false`) — the OBSERVE-ONLY contract that a
|
|
36
|
-
* deadline wrapper satisfies: every bare base Cmd must appear
|
|
37
|
-
* UNCHANGED, in order, as a subsequence of the wrapped Cmd stream (properties
|
|
38
|
-
* 1 and 3b). The wrapper may APPEND its own Cmds but may NOT alter, drop, or
|
|
39
|
-
* retime a base Cmd. This is the strict default and it is NOT weakened.
|
|
40
|
-
*
|
|
41
|
-
* WHEN SET — for a wrapper whose whole job is to INTERCEPT a chosen base Cmd
|
|
42
|
-
* (retag it into a wrapper-owned carrier so the concern — cache / breaker /
|
|
43
|
-
* rate-limit / retry — can gate it), a target base Cmd LEGITIMATELY does not
|
|
44
|
-
* appear raw at the top level of the wrapped stream. The contract is still
|
|
45
|
-
* **retag-and-re-emit, never swallow** (rule 2): the Cmd must be RECORDED, not
|
|
46
|
-
* vanished. So when a bare base Cmd is ABSENT from the top-level wrapped
|
|
47
|
-
* subsequence, this option accepts it IFF, in that SAME transition window, it
|
|
48
|
-
* is recorded by the wrapper as one of:
|
|
49
|
-
*
|
|
50
|
-
* - the inner payload of a `$x:*` "run" carrier Cmd (`carrierCmdType` +
|
|
51
|
-
* `innerField`) — the retag path; OR
|
|
52
|
-
* - any other `$x:*` divergence Cmd whose `recordsField` deep-equals the
|
|
53
|
-
* base Cmd — the gate/defer path (e.g. a "fast-failed" or "deferred"
|
|
54
|
-
* record Cmd that carries the base Cmd it diverged on).
|
|
55
|
-
*
|
|
56
|
-
* A target base Cmd that is NEITHER present raw NOR recorded by any `$x:*`
|
|
57
|
-
* Cmd in its window is a SWALLOW betrayal and still fails the gate.
|
|
58
|
-
*
|
|
59
|
-
* Provide the field names the carrier uses so the gate can unwrap it
|
|
60
|
-
* structurally without hard-coding any one wrapper's vocabulary.
|
|
61
|
-
*/
|
|
62
|
-
readonly intercepting?: InterceptingOpt;
|
|
63
|
-
}
|
|
64
|
-
/**
|
|
65
|
-
* Configures the intercepting relaxation (see
|
|
66
|
-
* `AssertWrapperFaithfulOpts.intercepting`). All fields name the carrier /
|
|
67
|
-
* divergence shape so the gate can structurally find a retagged base Cmd
|
|
68
|
-
* inside a `$x:*` Cmd. The gate only EVER inspects `$x:*`-prefixed wrapped
|
|
69
|
-
* Cmds for a recorded base Cmd — it never relaxes the check for a base Cmd
|
|
70
|
-
* that appears under any non-wrapper Cmd type.
|
|
71
|
-
*/
|
|
72
|
-
interface InterceptingOpt {
|
|
73
|
-
/**
|
|
74
|
-
* The `Cmd.type` of the wrapper's run-carrier (e.g. `"$resilience:run"`).
|
|
75
|
-
* A bare base Cmd that is retagged appears as `carrier[innerField]`.
|
|
76
|
-
*/
|
|
77
|
-
readonly carrierCmdType: string;
|
|
78
|
-
/** The field on the carrier Cmd that holds the original base Cmd. */
|
|
79
|
-
readonly innerField: string;
|
|
80
|
-
/**
|
|
81
|
-
* OPTIONAL field on ANY OTHER `$x:*` Cmd that records a base Cmd the wrapper
|
|
82
|
-
* gated/deferred without running it (e.g. a fast-fail record). When present
|
|
83
|
-
* on a `$x:*` Cmd and deep-equal to the missing base Cmd, it counts as a
|
|
84
|
-
* recorded divergence. Omit when the wrapper only ever retags via the
|
|
85
|
-
* carrier.
|
|
86
|
-
*/
|
|
87
|
-
readonly recordsField?: string;
|
|
88
|
-
}
|
|
89
|
-
/**
|
|
90
|
-
* Assert a `withX` wrapper is TEA-faithful. Replays the wrapped machine and the
|
|
91
|
-
* bare base machine over the same Msgs and checks the four conformance
|
|
92
|
-
* properties (see file header).
|
|
93
|
-
*
|
|
94
|
-
* @param base the bare base `Machine`.
|
|
95
|
-
* @param makeWrapped a thunk that wraps `base` and returns the composed machine
|
|
96
|
-
* (e.g. `() => withTimeout(wired, cfg).machine`, where `wired.machine` is
|
|
97
|
-
* `base`). A thunk — not the wrapped value — so a wrapper that registers
|
|
98
|
-
* process-scoped ports (`definePort`) is constructed inside the assertion's
|
|
99
|
-
* control, and so the same betrayal-detector reads as
|
|
100
|
-
* `assertWrapperFaithful(wired.machine, () => withX(wired, cfg).machine, ...)`
|
|
101
|
-
* at every wrapper's test site.
|
|
102
|
-
* @param opts the conformance replay options.
|
|
103
|
-
*/
|
|
104
|
-
declare function assertWrapperFaithful<S, BaseM extends {
|
|
105
|
-
type: string;
|
|
106
|
-
}, BaseC extends Cmd, BaseU extends Sub, BaseCtx, WM extends WrapperModel<S>, WrapperM extends {
|
|
107
|
-
type: string;
|
|
108
|
-
}, WrapperC extends Cmd, WrapperU extends Sub, WrapperCtx>(base: Machine<S, BaseM, BaseC, BaseU, BaseCtx>, makeWrapped: () => Machine<WM, WrapperM, WrapperC, WrapperU, WrapperCtx>, opts: AssertWrapperFaithfulOpts<S, WM, BaseM, BaseCtx, WrapperCtx>): void;
|
|
109
|
-
|
|
110
5
|
/**
|
|
111
6
|
* Shared options shape for every test assertion below. Mirrors the
|
|
112
7
|
* second argument of `replay(machine, opts)` — `msgs` is the sequence to
|
|
@@ -415,6 +310,25 @@ declare function drive<S, M extends {
|
|
|
415
310
|
type: string;
|
|
416
311
|
}, C extends Cmd, U extends Sub, Ctx>(machine: Machine<S, M, C, U, Ctx>, initial: S, msg: M, handlers: Interpret<M, C, Ctx>, ...[opts]: Record<never, never> extends DriveOptions<Ctx> ? [opts?: DriveOptions<Ctx>] : [opts: DriveOptions<Ctx>]): Promise<DriveResult<S, M, C>>;
|
|
417
312
|
|
|
313
|
+
/**
|
|
314
|
+
* Assert that replaying `opts.msgs` is a pure function of the Msg log: the
|
|
315
|
+
* final state and every emitted Cmd come out the same under two different
|
|
316
|
+
* global wall-clocks and RNG seeds.
|
|
317
|
+
*
|
|
318
|
+
* `init` and `update` never receive a clock, so a cell that reads
|
|
319
|
+
* `Date.now()` or `Math.random()` reaches for the global one, and a replay of
|
|
320
|
+
* the same log on another day or another host lands somewhere else. Two
|
|
321
|
+
* back-to-back replays under one clock would hide that; this helper stubs
|
|
322
|
+
* two distinct ambients and compares. Time belongs in the Msg (an `at`
|
|
323
|
+
* field), where it is identical across replays.
|
|
324
|
+
*
|
|
325
|
+
* Subs are not compared: they are derived from the final state, so a state
|
|
326
|
+
* that matches yields the same Subs.
|
|
327
|
+
*/
|
|
328
|
+
declare function expectReplayDeterministic<S, M extends {
|
|
329
|
+
type: string;
|
|
330
|
+
}, C extends Cmd, U extends Sub, Ctx>(machine: Machine<S, M, C, U, Ctx>, opts: NoInfer<ReplayOpts<S, M, Ctx>>): void;
|
|
331
|
+
|
|
418
332
|
/**
|
|
419
333
|
* Construct an inert `Runtime<S, M>` value. Use at ctx sites that require
|
|
420
334
|
* a Runtime reference but where the test never invokes `interpret` (so
|
|
@@ -474,4 +388,4 @@ declare function stateFactory<S extends {
|
|
|
474
388
|
type: string;
|
|
475
389
|
}>(defaults: StateFactoryDefaults<S>): StateFactoryAPI<S>;
|
|
476
390
|
|
|
477
|
-
export { type
|
|
391
|
+
export { type BoundMachine, DEFAULT_MAX_ROUNDS, type DriveCtxArg, DriveNoHandlerError, type DriveOptions, type DriveResult, DriveRoundsExceededError, type DriveTraceEntry, type ReplayOpts, type StateFactoryAPI, type StateFactoryDefaults, bindMachine, drive, driveTraceOf, expectActiveSubs, expectCmdEmitted, expectCmdSequence, expectFinalState, expectReplayDeterministic, noopRuntime, stateFactory, step };
|
package/dist/testing/index.js
CHANGED
|
@@ -1,181 +1,7 @@
|
|
|
1
|
-
import '../chunk-
|
|
2
|
-
import { replay, cmdEdgeOver, Outcome, cmdEdge } from '../chunk-
|
|
1
|
+
import '../chunk-C4U5D5HP.js';
|
|
2
|
+
import { replay, cmdEdgeOver, Outcome, cmdEdge } from '../chunk-K4ETBNKS.js';
|
|
3
3
|
import { expect, vi } from 'vitest';
|
|
4
4
|
|
|
5
|
-
function assertWrapperFaithful(base, makeWrapped, opts) {
|
|
6
|
-
const baseCtx = opts.baseCtx ?? opts.ctx;
|
|
7
|
-
const wrappedMsgs = opts.msgs;
|
|
8
|
-
const baseLoaded = opts.baseLoaded ?? (opts.loaded != null ? opts.loaded.base : null);
|
|
9
|
-
const A0 = { now: 1e6, rng: 0.123 };
|
|
10
|
-
const A1 = { now: 9876543, rng: 0.987 };
|
|
11
|
-
const bare = underAmbient(
|
|
12
|
-
A0,
|
|
13
|
-
() => replay(base, { msgs: opts.msgs, ctx: baseCtx, loaded: baseLoaded })
|
|
14
|
-
);
|
|
15
|
-
const wrapped = underAmbient(A0, () => makeWrapped());
|
|
16
|
-
const wrappedA = underAmbient(
|
|
17
|
-
A0,
|
|
18
|
-
() => replay(wrapped, {
|
|
19
|
-
msgs: wrappedMsgs,
|
|
20
|
-
ctx: opts.ctx,
|
|
21
|
-
loaded: opts.loaded ?? null
|
|
22
|
-
})
|
|
23
|
-
);
|
|
24
|
-
const wrappedB = underAmbient(
|
|
25
|
-
A1,
|
|
26
|
-
() => replay(makeWrapped(), {
|
|
27
|
-
msgs: wrappedMsgs,
|
|
28
|
-
ctx: opts.ctx,
|
|
29
|
-
loaded: opts.loaded ?? null
|
|
30
|
-
})
|
|
31
|
-
);
|
|
32
|
-
expect(wrappedA.state.base).toEqual(bare.state);
|
|
33
|
-
expectCmdSubsequence(bare.cmds, wrappedA.cmds, void 0, opts.intercepting);
|
|
34
|
-
const sliceKey = wrapperSliceKey(wrappedA.state);
|
|
35
|
-
expect(
|
|
36
|
-
sliceOf(wrappedB.state, sliceKey),
|
|
37
|
-
`wrapper slice changed under a different ambient clock/RNG \u2192 update is reading Date.now()/Math.random(); time must enter only as Msg \`at\` data`
|
|
38
|
-
).toEqual(sliceOf(wrappedA.state, sliceKey));
|
|
39
|
-
const wrapperFamily = `${sliceKey}:`;
|
|
40
|
-
const wrapperCmdsA = wrappedA.cmds.filter(
|
|
41
|
-
(c) => c.type.startsWith(wrapperFamily)
|
|
42
|
-
);
|
|
43
|
-
const wrapperCmdsB = wrappedB.cmds.filter(
|
|
44
|
-
(c) => c.type.startsWith(wrapperFamily)
|
|
45
|
-
);
|
|
46
|
-
expect(
|
|
47
|
-
wrapperCmdsB,
|
|
48
|
-
`wrapper Cmds ("${wrapperFamily}*") changed under a different ambient clock/RNG \u2192 a wrapper Cmd PAYLOAD is reading Date.now()/Math.random(); wrapper Cmds must be a pure function of the Msg log, time entering only as Msg \`at\` data`
|
|
49
|
-
).toEqual(wrapperCmdsA);
|
|
50
|
-
if (opts.msgs.length > 0) {
|
|
51
|
-
expect(
|
|
52
|
-
wrapperCmdsA.length,
|
|
53
|
-
`expected at least one "${wrapperFamily}*" wrapper-decision Cmd in the replay log (found none across ${opts.msgs.length} transition(s)) \u2014 a wrapper whose decisions are invisible to the Msg/Cmd log has betrayed total visibility`
|
|
54
|
-
).toBeGreaterThan(0);
|
|
55
|
-
}
|
|
56
|
-
for (let i = 0; i < opts.msgs.length; i++) {
|
|
57
|
-
const bareStep = stepCmds(
|
|
58
|
-
() => underAmbient(
|
|
59
|
-
A0,
|
|
60
|
-
() => replay(base, {
|
|
61
|
-
msgs: opts.msgs.slice(0, i),
|
|
62
|
-
ctx: baseCtx,
|
|
63
|
-
loaded: baseLoaded
|
|
64
|
-
})
|
|
65
|
-
).cmds,
|
|
66
|
-
() => underAmbient(
|
|
67
|
-
A0,
|
|
68
|
-
() => replay(base, {
|
|
69
|
-
msgs: opts.msgs.slice(0, i + 1),
|
|
70
|
-
ctx: baseCtx,
|
|
71
|
-
loaded: baseLoaded
|
|
72
|
-
})
|
|
73
|
-
).cmds
|
|
74
|
-
);
|
|
75
|
-
const wrappedStep = stepCmds(
|
|
76
|
-
() => underAmbient(
|
|
77
|
-
A0,
|
|
78
|
-
() => replay(wrapped, {
|
|
79
|
-
msgs: wrappedMsgs.slice(0, i),
|
|
80
|
-
ctx: opts.ctx,
|
|
81
|
-
loaded: opts.loaded ?? null
|
|
82
|
-
})
|
|
83
|
-
).cmds,
|
|
84
|
-
() => underAmbient(
|
|
85
|
-
A0,
|
|
86
|
-
() => replay(wrapped, {
|
|
87
|
-
msgs: wrappedMsgs.slice(0, i + 1),
|
|
88
|
-
ctx: opts.ctx,
|
|
89
|
-
loaded: opts.loaded ?? null
|
|
90
|
-
})
|
|
91
|
-
).cmds
|
|
92
|
-
);
|
|
93
|
-
expectCmdSubsequence(bareStep, wrappedStep, i, opts.intercepting);
|
|
94
|
-
}
|
|
95
|
-
const slice = sliceOf(wrappedA.state, sliceKey);
|
|
96
|
-
expect(JSON.parse(JSON.stringify(slice))).toEqual(slice);
|
|
97
|
-
}
|
|
98
|
-
function underAmbient(ambient, fn) {
|
|
99
|
-
const nowSpy = vi.spyOn(Date, "now").mockReturnValue(ambient.now);
|
|
100
|
-
const rngSpy = vi.spyOn(Math, "random").mockReturnValue(ambient.rng);
|
|
101
|
-
try {
|
|
102
|
-
return fn();
|
|
103
|
-
} finally {
|
|
104
|
-
nowSpy.mockRestore();
|
|
105
|
-
rngSpy.mockRestore();
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
function sliceOf(model, sliceKey) {
|
|
109
|
-
return model[sliceKey];
|
|
110
|
-
}
|
|
111
|
-
function stepCmds(prefixCmds, throughCmds) {
|
|
112
|
-
const before = prefixCmds();
|
|
113
|
-
const after = throughCmds();
|
|
114
|
-
return after.slice(before.length);
|
|
115
|
-
}
|
|
116
|
-
function wrapperSliceKey(model) {
|
|
117
|
-
const dollarKeys = Object.keys(model).filter((k) => k.startsWith("$"));
|
|
118
|
-
if (dollarKeys.length !== 1) {
|
|
119
|
-
throw new Error(
|
|
120
|
-
`assertWrapperFaithful: expected exactly one "$"-prefixed wrapper slice on the composed Model, found ${dollarKeys.length} (${dollarKeys.join(", ") || "none"}). Every withX wrapper owns exactly one named slice (e.g. "$deadline").`
|
|
121
|
-
);
|
|
122
|
-
}
|
|
123
|
-
return dollarKeys[0];
|
|
124
|
-
}
|
|
125
|
-
function expectCmdSubsequence(needle, haystack, step2, intercepting) {
|
|
126
|
-
let i = 0;
|
|
127
|
-
for (const cmd of haystack) {
|
|
128
|
-
if (i >= needle.length) break;
|
|
129
|
-
if (__deepEqual(needle[i], cmd)) {
|
|
130
|
-
i++;
|
|
131
|
-
continue;
|
|
132
|
-
}
|
|
133
|
-
if (intercepting !== void 0 && recordsBaseCmd(cmd, needle[i], intercepting)) {
|
|
134
|
-
i++;
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
const where = step2 === void 0 ? "the wrapped Cmd stream" : `the wrapped Cmd stream AT TRANSITION ${step2} (a base Cmd deferred to a later transition is an intra-window retiming betrayal)`;
|
|
138
|
-
const swallowHint = intercepting === void 0 ? "a missing/rewritten/retimed base Cmd is a swallow betrayal" : `an intercepting wrapper must RETAG each target base Cmd into a "${intercepting.carrierCmdType}" carrier (inner field "${intercepting.innerField}") or record it on a "$*:" divergence Cmd \u2014 a base Cmd neither present raw NOR recorded by any "$*:" Cmd is a swallow betrayal`;
|
|
139
|
-
expect(
|
|
140
|
-
i,
|
|
141
|
-
`expected every base Cmd to pass through unchanged (matched ${i} of ${needle.length} base Cmds as an ordered subsequence of ${where}) \u2014 ${swallowHint}`
|
|
142
|
-
).toBe(needle.length);
|
|
143
|
-
}
|
|
144
|
-
function recordsBaseCmd(cmd, baseCmd, opt) {
|
|
145
|
-
if (!cmd.type.startsWith("$")) return false;
|
|
146
|
-
const rec = cmd;
|
|
147
|
-
if (cmd.type === opt.carrierCmdType && __deepEqual(rec[opt.innerField], baseCmd))
|
|
148
|
-
return true;
|
|
149
|
-
if (opt.recordsField !== void 0 && __deepEqual(rec[opt.recordsField], baseCmd))
|
|
150
|
-
return true;
|
|
151
|
-
return false;
|
|
152
|
-
}
|
|
153
|
-
function __deepEqual(a, b) {
|
|
154
|
-
if (Object.is(a, b)) return true;
|
|
155
|
-
if (typeof a !== "object" || typeof b !== "object" || a === null || b === null) {
|
|
156
|
-
return false;
|
|
157
|
-
}
|
|
158
|
-
const aIsArray = Array.isArray(a);
|
|
159
|
-
if (aIsArray !== Array.isArray(b)) return false;
|
|
160
|
-
if (aIsArray) {
|
|
161
|
-
const bArr = b;
|
|
162
|
-
if (a.length !== bArr.length) return false;
|
|
163
|
-
for (let i = 0; i < a.length; i++) {
|
|
164
|
-
if (!__deepEqual(a[i], bArr[i])) return false;
|
|
165
|
-
}
|
|
166
|
-
return true;
|
|
167
|
-
}
|
|
168
|
-
const aRec = a;
|
|
169
|
-
const bRec = b;
|
|
170
|
-
const aKeys = Object.keys(aRec);
|
|
171
|
-
const bKeys = Object.keys(bRec);
|
|
172
|
-
if (aKeys.length !== bKeys.length) return false;
|
|
173
|
-
for (const key of aKeys) {
|
|
174
|
-
if (!Object.hasOwn(bRec, key)) return false;
|
|
175
|
-
if (!__deepEqual(aRec[key], bRec[key])) return false;
|
|
176
|
-
}
|
|
177
|
-
return true;
|
|
178
|
-
}
|
|
179
5
|
function expectFinalState(machine, opts, expected) {
|
|
180
6
|
const { state } = replay(machine, opts);
|
|
181
7
|
expect(state).toEqual(expected);
|
|
@@ -323,6 +149,30 @@ async function drive(machine, initial, msg, handlers, ...[opts]) {
|
|
|
323
149
|
}
|
|
324
150
|
return { state, trace };
|
|
325
151
|
}
|
|
152
|
+
var AMBIENT_A = { now: 1e6, rng: 0.123 };
|
|
153
|
+
var AMBIENT_B = { now: 9876543, rng: 0.987 };
|
|
154
|
+
function expectReplayDeterministic(machine, opts) {
|
|
155
|
+
const a = underAmbient(AMBIENT_A, () => replay(machine, opts));
|
|
156
|
+
const b = underAmbient(AMBIENT_B, () => replay(machine, opts));
|
|
157
|
+
expect(
|
|
158
|
+
b.state,
|
|
159
|
+
"final state changed under a different clock/RNG: init or update reads Date.now()/Math.random(); time must enter as Msg data"
|
|
160
|
+
).toEqual(a.state);
|
|
161
|
+
expect(
|
|
162
|
+
b.cmds,
|
|
163
|
+
"emitted Cmds changed under a different clock/RNG: a Cmd payload reads Date.now()/Math.random(); time must enter as Msg data"
|
|
164
|
+
).toEqual(a.cmds);
|
|
165
|
+
}
|
|
166
|
+
function underAmbient(ambient, fn) {
|
|
167
|
+
const nowSpy = vi.spyOn(Date, "now").mockReturnValue(ambient.now);
|
|
168
|
+
const rngSpy = vi.spyOn(Math, "random").mockReturnValue(ambient.rng);
|
|
169
|
+
try {
|
|
170
|
+
return fn();
|
|
171
|
+
} finally {
|
|
172
|
+
nowSpy.mockRestore();
|
|
173
|
+
rngSpy.mockRestore();
|
|
174
|
+
}
|
|
175
|
+
}
|
|
326
176
|
|
|
327
177
|
// src/testing/noop-runtime.ts
|
|
328
178
|
function noopRuntime(opts) {
|
|
@@ -398,6 +248,6 @@ function stateFactory(defaults) {
|
|
|
398
248
|
return api;
|
|
399
249
|
}
|
|
400
250
|
|
|
401
|
-
export { DEFAULT_MAX_ROUNDS, DriveNoHandlerError, DriveRoundsExceededError,
|
|
251
|
+
export { DEFAULT_MAX_ROUNDS, DriveNoHandlerError, DriveRoundsExceededError, bindMachine, drive, driveTraceOf, expectActiveSubs, expectCmdEmitted, expectCmdSequence, expectFinalState, expectReplayDeterministic, noopRuntime, stateFactory, step };
|
|
402
252
|
//# sourceMappingURL=index.js.map
|
|
403
253
|
//# sourceMappingURL=index.js.map
|