@demlik/tea 0.17.0 → 0.19.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.
Files changed (119) hide show
  1. package/README.md +4 -3
  2. package/dist/agent/index.d.ts +182 -35
  3. package/dist/agent/index.js +11 -11
  4. package/dist/{chunk-KWNCM6XM.js → chunk-AHW2CLPT.js} +65 -18
  5. package/dist/chunk-AHW2CLPT.js.map +1 -0
  6. package/dist/{chunk-K4ETBNKS.js → chunk-AIIXV4XB.js} +38 -9
  7. package/dist/chunk-AIIXV4XB.js.map +1 -0
  8. package/dist/{chunk-LYVOGOBC.js → chunk-BRX3243I.js} +3 -3
  9. package/dist/{chunk-LYVOGOBC.js.map → chunk-BRX3243I.js.map} +1 -1
  10. package/dist/{chunk-GWWCCSDH.js → chunk-C3G2QFEZ.js} +4 -4
  11. package/dist/{chunk-GWWCCSDH.js.map → chunk-C3G2QFEZ.js.map} +1 -1
  12. package/dist/{chunk-C4U5D5HP.js → chunk-FNGZMVIT.js} +3 -3
  13. package/dist/chunk-FNGZMVIT.js.map +1 -0
  14. package/dist/{chunk-QWIPH4YH.js → chunk-H2ELKHI6.js} +16 -6
  15. package/dist/chunk-H2ELKHI6.js.map +1 -0
  16. package/dist/chunk-H3MWNH7A.js +119 -0
  17. package/dist/chunk-H3MWNH7A.js.map +1 -0
  18. package/dist/chunk-I7E7AD2S.js +213 -0
  19. package/dist/chunk-I7E7AD2S.js.map +1 -0
  20. package/dist/{chunk-OYR7ENKU.js → chunk-IHUNKHDX.js} +3 -3
  21. package/dist/{chunk-OYR7ENKU.js.map → chunk-IHUNKHDX.js.map} +1 -1
  22. package/dist/chunk-JVE2LBFJ.js +21 -0
  23. package/dist/chunk-JVE2LBFJ.js.map +1 -0
  24. package/dist/chunk-JVKU2UQC.js +34 -0
  25. package/dist/chunk-JVKU2UQC.js.map +1 -0
  26. package/dist/{chunk-OPH6Y4UT.js → chunk-JYNYG5SF.js} +4 -4
  27. package/dist/{chunk-OPH6Y4UT.js.map → chunk-JYNYG5SF.js.map} +1 -1
  28. package/dist/{chunk-XBZQT2TD.js → chunk-PCJA2HTZ.js} +437 -162
  29. package/dist/chunk-PCJA2HTZ.js.map +1 -0
  30. package/dist/{chunk-DFUEAA6L.js → chunk-PQSDUX6B.js} +3 -3
  31. package/dist/{chunk-DFUEAA6L.js.map → chunk-PQSDUX6B.js.map} +1 -1
  32. package/dist/{chunk-6XBEYZME.js → chunk-WTSOW2MD.js} +5 -5
  33. package/dist/{chunk-6XBEYZME.js.map → chunk-WTSOW2MD.js.map} +1 -1
  34. package/dist/{chunk-4PXNZ5UY.js → chunk-XVIKSRCK.js} +4 -4
  35. package/dist/{chunk-4PXNZ5UY.js.map → chunk-XVIKSRCK.js.map} +1 -1
  36. package/dist/{chunk-4NTCPTNQ.js → chunk-YIMOFXST.js} +3 -3
  37. package/dist/{chunk-4NTCPTNQ.js.map → chunk-YIMOFXST.js.map} +1 -1
  38. package/dist/{core-rDbOaJTN.d.ts → core-Ce9ncpuv.d.ts} +5 -4
  39. package/dist/do/index.d.ts +140 -64
  40. package/dist/do/index.js +17 -18
  41. package/dist/do/index.js.map +1 -1
  42. package/dist/drive-loop-CsUsW3Wo.d.ts +127 -0
  43. package/dist/{durable-effects-CNaw97Be.d.ts → durable-effects-BmUrRA-h.d.ts} +1 -1
  44. package/dist/effect/index.d.ts +6 -150
  45. package/dist/effect/index.js +4 -96
  46. package/dist/effect/index.js.map +1 -1
  47. package/dist/extension/index.d.ts +7 -5
  48. package/dist/extension/index.js +2 -3
  49. package/dist/extension/index.js.map +1 -1
  50. package/dist/flow/index.d.ts +13 -13
  51. package/dist/flow/index.js +13 -12
  52. package/dist/flow/index.js.map +1 -1
  53. package/dist/idempotency/index.d.ts +3 -3
  54. package/dist/idempotency/index.js +4 -4
  55. package/dist/{index-q1PoukOZ.d.ts → index-2kNxy6az.d.ts} +2 -2
  56. package/dist/{index-B_BxplWi.d.ts → index-B1Wzarkl.d.ts} +1 -1
  57. package/dist/{index-Cberb5Rr.d.ts → index-Bf9_bNql.d.ts} +2 -2
  58. package/dist/index-BnsAqn0-.d.ts +286 -0
  59. package/dist/{index-Cx0F2M34.d.ts → index-Ce5GYAuI.d.ts} +2 -2
  60. package/dist/{index-CWmsXNdX.d.ts → index-D8sYVzCI.d.ts} +1 -1
  61. package/dist/{index-CcrKLtse.d.ts → index-DWdg7R1l.d.ts} +1 -1
  62. package/dist/{index-BOrsbdAf.d.ts → index-Dy3379ve.d.ts} +5 -5
  63. package/dist/{index-DaX_P35Q.d.ts → index-e36uEyl4.d.ts} +3 -3
  64. package/dist/index.d.ts +109 -36
  65. package/dist/index.js +2 -2
  66. package/dist/jev/index.d.ts +8 -8
  67. package/dist/jev/index.js +6 -7
  68. package/dist/jev/index.js.map +1 -1
  69. package/dist/{machine-BcfCFMYF.d.ts → machine-CuojfZup.d.ts} +353 -57
  70. package/dist/machine-viz/index.d.ts +1 -1
  71. package/dist/machine-viz/index.js +2 -2
  72. package/dist/mem/index.d.ts +6 -6
  73. package/dist/mem/index.js +6 -2
  74. package/dist/mem/index.js.map +1 -1
  75. package/dist/node/index.d.ts +16 -10
  76. package/dist/node/index.js +22 -3
  77. package/dist/node/index.js.map +1 -1
  78. package/dist/otel/index.d.ts +161 -0
  79. package/dist/otel/index.js +403 -0
  80. package/dist/otel/index.js.map +1 -0
  81. package/dist/paginate/index.d.ts +4 -4
  82. package/dist/paginate/index.js +5 -5
  83. package/dist/parity/index.d.ts +3 -3
  84. package/dist/parity/index.js +3 -3
  85. package/dist/pbt/index.d.ts +166 -53
  86. package/dist/pbt/index.js +2 -2
  87. package/dist/pbt/index.js.map +1 -1
  88. package/dist/persistence/index.d.ts +5 -5
  89. package/dist/persistence/index.js +5 -5
  90. package/dist/promise/index.d.ts +2 -2
  91. package/dist/promise/index.js +4 -3
  92. package/dist/react/index.d.ts +2 -2
  93. package/dist/resilience/index.d.ts +13 -9
  94. package/dist/resilience/index.js +5 -5
  95. package/dist/resilience/index.js.map +1 -1
  96. package/dist/{runtime-types-B62Ucnxr.d.ts → runtime-types-BKg2CGMx.d.ts} +88 -14
  97. package/dist/testing/effect/index.d.ts +65 -0
  98. package/dist/testing/effect/index.js +148 -0
  99. package/dist/testing/effect/index.js.map +1 -0
  100. package/dist/testing/index.d.ts +12 -158
  101. package/dist/testing/index.js +4 -130
  102. package/dist/testing/index.js.map +1 -1
  103. package/dist/testing/promise/index.d.ts +41 -0
  104. package/dist/testing/promise/index.js +37 -0
  105. package/dist/testing/promise/index.js.map +1 -0
  106. package/dist/timing/index.d.ts +4 -4
  107. package/dist/timing/index.js +4 -4
  108. package/dist/{types-DPm5YCDQ.d.ts → types-SzNSHKlV.d.ts} +1 -1
  109. package/dist/work-queue/index.d.ts +4 -4
  110. package/dist/work-queue/index.js +4 -3
  111. package/dist/work-queue/index.js.map +1 -1
  112. package/package.json +26 -14
  113. package/dist/chunk-C4U5D5HP.js.map +0 -1
  114. package/dist/chunk-G5E74IJB.js +0 -8
  115. package/dist/chunk-G5E74IJB.js.map +0 -1
  116. package/dist/chunk-K4ETBNKS.js.map +0 -1
  117. package/dist/chunk-KWNCM6XM.js.map +0 -1
  118. package/dist/chunk-QWIPH4YH.js.map +0 -1
  119. package/dist/chunk-XBZQT2TD.js.map +0 -1
@@ -0,0 +1,127 @@
1
+ import { C as CtxArg } from './runtime-types-BKg2CGMx.js';
2
+
3
+ /**
4
+ * The default round bound when `opts.maxRounds` is omitted: **100**.
5
+ *
6
+ * A round is one drain of the pending Msgs plus one drain of the Cmds those
7
+ * folds emitted, so a settling machine costs a handful; 100 is loose enough
8
+ * that a legitimate retry ladder finishes inside it and tight enough that a
9
+ * genuine cycle stops rather than hangs.
10
+ */
11
+ declare const DEFAULT_MAX_ROUNDS = 100;
12
+ /**
13
+ * One entry of a driven run's history, in dispatch order.
14
+ *
15
+ * - `msg` — a Msg folded through the machine's reducer. The seed Msg is the
16
+ * first entry of every trace; every later one is a settle Msg a handler
17
+ * returned (or fired through its injected `dispatch`), or a Msg a running
18
+ * Sub emitted.
19
+ * - `cmd` — a Cmd handed to an interpret handler. It is recorded BEFORE the
20
+ * handler runs, so a trace recovered from a failed handler names the Cmd
21
+ * that failed as its last entry.
22
+ */
23
+ type DriveTraceEntry<M, C> = {
24
+ readonly kind: "msg";
25
+ readonly msg: M;
26
+ } | {
27
+ readonly kind: "cmd";
28
+ readonly cmd: C;
29
+ };
30
+ /** What a settled `drive` hands back. */
31
+ interface DriveResult<S, M, C> {
32
+ /** The state after the machine went quiet — no Msg pending, no Cmd unperformed. */
33
+ readonly state: S;
34
+ /**
35
+ * Every Msg folded and every Cmd dispatched, in order. Filtering it to its
36
+ * `msg` entries and replaying those through `replay` from the same initial
37
+ * state reproduces {@link DriveResult.state}.
38
+ */
39
+ readonly trace: readonly DriveTraceEntry<M, C>[];
40
+ }
41
+ /**
42
+ * `drive`'s `ctx` field. `CtxArg` widened by exactly one case: a machine
43
+ * declaring `ctx: undefined` in its `types` block — the pure shape every
44
+ * how-to on this package writes — may omit it too. `CtxArg` alone keeps `ctx`
45
+ * REQUIRED there, because `{}` is not assignable to `undefined`, which would
46
+ * make the common pure call site spell `{ ctx: undefined }` to say nothing.
47
+ * A machine whose `Ctx` carries a field a handler reads still requires it.
48
+ */
49
+ type DriveCtxArg<Ctx> = [undefined] extends [Ctx] ? {
50
+ readonly ctx?: Ctx;
51
+ } : CtxArg<Ctx>;
52
+ /**
53
+ * The options both `drive`s take. `ctx` is conditionally optional (see
54
+ * {@link DriveCtxArg}).
55
+ */
56
+ type DriveOptions<Ctx> = DriveCtxArg<Ctx> & {
57
+ /**
58
+ * The round bound. Exceeding it fails the drive with
59
+ * {@link DriveRoundsExceededError}; `drive` never returns a half-driven
60
+ * state. Defaults to {@link DEFAULT_MAX_ROUNDS} (100).
61
+ */
62
+ readonly maxRounds?: number;
63
+ /**
64
+ * The clock that stamps `at` on a `Cmd.define`d Cmd's minted `_ok` / `_err`
65
+ * Msg — the one `run` takes. Defaults to `Date.now`; pin it for a test that
66
+ * asserts on `at`.
67
+ */
68
+ readonly clock?: () => number;
69
+ };
70
+ /**
71
+ * Raised when a driven machine is still emitting work after `maxRounds` rounds.
72
+ * Follows the tea error dialect (`override readonly name`) and carries a `_tag`
73
+ * discriminant, so a test branches on it by `instanceof` or on the tag.
74
+ *
75
+ * It carries the round count it stopped at and the PARTIAL trace up to that
76
+ * point, which is what a test needs to see the cycle — the bound alone says
77
+ * only that one exists.
78
+ */
79
+ declare class DriveRoundsExceededError<M, C> extends Error {
80
+ /** The bound that was exceeded. */
81
+ readonly maxRounds: number;
82
+ /** The round the driver stopped at — always `maxRounds + 1`. */
83
+ readonly rounds: number;
84
+ /** Every Msg folded and Cmd dispatched before the driver gave up. */
85
+ readonly trace: readonly DriveTraceEntry<M, C>[];
86
+ readonly name = "DriveRoundsExceededError";
87
+ readonly _tag: "DriveRoundsExceededError";
88
+ constructor(
89
+ /** The bound that was exceeded. */
90
+ maxRounds: number,
91
+ /** The round the driver stopped at — always `maxRounds + 1`. */
92
+ rounds: number,
93
+ /** Every Msg folded and Cmd dispatched before the driver gave up. */
94
+ trace: readonly DriveTraceEntry<M, C>[]);
95
+ }
96
+ /**
97
+ * Raised when a Cmd reaches `drive` with no handler for its `type` in the
98
+ * handler record. The record's mapped type makes that a compile error at a
99
+ * well-typed call site; this is the runtime arm for a handler record assembled
100
+ * dynamically or cast.
101
+ */
102
+ declare class DriveNoHandlerError<M, C> extends Error {
103
+ /** The Cmd `type` nothing in the handler record answered. */
104
+ readonly cmdType: string;
105
+ /** Every Msg folded and Cmd dispatched before the miss. */
106
+ readonly trace: readonly DriveTraceEntry<M, C>[];
107
+ readonly name = "DriveNoHandlerError";
108
+ readonly _tag: "DriveNoHandlerError";
109
+ constructor(
110
+ /** The Cmd `type` nothing in the handler record answered. */
111
+ cmdType: string,
112
+ /** Every Msg folded and Cmd dispatched before the miss. */
113
+ trace: readonly DriveTraceEntry<M, C>[]);
114
+ }
115
+ /**
116
+ * Read back the partial trace `drive` attached to an error a handler failed
117
+ * with. Returns `undefined` for anything `drive` did not annotate.
118
+ *
119
+ * A failing handler's error leaves `drive` UNSWALLOWED — same value, same
120
+ * `instanceof`, same `_tag` — so a test that already branches on the handler's
121
+ * own error type keeps doing so. The trace rides along on a non-enumerable
122
+ * property so it is recoverable without changing how the error prints or
123
+ * serializes.
124
+ */
125
+ declare function driveTraceOf<M, C>(err: unknown): readonly DriveTraceEntry<M, C>[] | undefined;
126
+
127
+ export { DriveRoundsExceededError as D, DriveNoHandlerError as a, type DriveOptions as b, type DriveResult as c, DEFAULT_MAX_ROUNDS as d, type DriveCtxArg as e, type DriveTraceEntry as f, driveTraceOf as g };
@@ -1,4 +1,4 @@
1
- import { C as Cmd } from './core-rDbOaJTN.js';
1
+ import { C as Cmd } from './core-Ce9ncpuv.js';
2
2
 
3
3
  /**
4
4
  * @demlik/tea/do — the durable pending-effects ledger (substrate primitive #1).
@@ -1,151 +1,7 @@
1
- import { Effect, Stream, Scope } from 'effect';
2
- import { C as Cmd, E as ErrorsOf, O as OkOfCmd, D as DeclaredErrorsOf, S as Sub, B as BuiltinSubType, a as BuiltinSub, M as Machine } from '../core-rDbOaJTN.js';
3
- import { C as CtxArg, S as Store, O as OnError, a as Supervision, T as TelemetrySink, B as BootingRuntime } from '../runtime-types-B62Ucnxr.js';
1
+ export { C as CellErrors, c as EffectBootingRuntime, E as EffectInterpret, d as EffectInterpretCell, e as EffectRunOptions, f as EffectRunner, g as EffectRuntime, a as EffectSubscribe, I as InterpretServices, h as Stopped, i as StoreFailed, b as SubscribeServices, r as run } from '../index-BnsAqn0-.js';
2
+ import 'effect/Cause';
3
+ import 'effect/Types';
4
+ import 'effect';
5
+ import '../core-Ce9ncpuv.js';
4
6
  import '@standard-schema/spec';
5
-
6
- /**
7
- * The Effect engine's `run` (#283): the same machine the Promise engine runs,
8
- * with Effect handlers, Effect sub runners, the caller's Layers and
9
- * interruption on stop.
10
- *
11
- * It runs the one core loop both engines share (`src/internal/engine/loop.ts`)
12
- * with the same built-ins in the same order, so a machine folds the same way on
13
- * either engine. What this file adds is the Effect edge:
14
- *
15
- * - an `interpret` cell returns `Effect<Ok, E, R>`, read with
16
- * `Effect.result`: a success settles `_ok`, a declared failure settles
17
- * `_err`, a defect goes to the error sink;
18
- * - a `subscribe` runner returns a `Stream<Msg>`, drained on its own fiber;
19
- * - every handler and runner fiber runs with the services the caller
20
- * provided, so `R` reaches them from the caller's Layers;
21
- * - stopping interrupts every handler fiber still in flight.
22
- */
23
-
24
- /**
25
- * One Effect `interpret` cell. For a `Cmd.define`d Cmd it succeeds with the
26
- * Cmd's `Ok` and fails with one of its declared tags, and the engine mints
27
- * `<name>_ok` / `<name>_err` from that (ADR 0021). For a hand-written Cmd it
28
- * succeeds with a follow-up Msg or nothing, and a failure rejects the dispatch,
29
- * as a throw does on the Promise engine. `R` is whatever services it reads.
30
- */
31
- type EffectInterpretCell<M extends {
32
- type: string;
33
- }, C extends Cmd, R = unknown> = unknown extends ErrorsOf<C> ? (cmd: C) => Effect.Effect<M | void, unknown, R> : (cmd: C) => Effect.Effect<OkOfCmd<C>, DeclaredErrorsOf<C>, R>;
34
- /**
35
- * The Effect engine's `interpret` map: one cell per Cmd variant, each reading
36
- * services within `R`.
37
- */
38
- type EffectInterpret<M extends {
39
- type: string;
40
- }, C extends Cmd, R = unknown> = {
41
- readonly [K in C["type"]]: EffectInterpretCell<M, Extract<C, {
42
- type: K;
43
- }>, R>;
44
- };
45
- /**
46
- * One Effect sub runner: the Sub in, a `Stream` of Msgs out. The engine drains
47
- * it on its own fiber and interrupts that fiber when the Sub stops. A stream
48
- * that fails reaches the error sink under `"follow-up"`.
49
- */
50
- type EffectRunner<M extends {
51
- type: string;
52
- }, U extends Sub, R = unknown> = (sub: U) => Stream.Stream<M, unknown, R>;
53
- /**
54
- * The Effect engine's `subscribe` map: a runner for every Sub type the machine
55
- * declares beyond the built-ins, and optionally one for a built-in, which
56
- * replaces the engine's own (#270 R2.1).
57
- */
58
- type EffectSubscribe<M extends {
59
- type: string;
60
- }, U extends Sub, R = unknown> = {
61
- readonly [K in Exclude<U["type"], BuiltinSubType>]: EffectRunner<M, Extract<U, {
62
- type: K;
63
- }>, R>;
64
- } & {
65
- readonly [K in BuiltinSubType]?: EffectRunner<M, Extract<BuiltinSub<M>, {
66
- type: K;
67
- }>, R>;
68
- };
69
- /** The services every cell of an `interpret` map reads. */
70
- type InterpretServices<I> = {
71
- [K in keyof I]: ServicesOfCell<I[K]>;
72
- }[keyof I];
73
- type ServicesOfCell<F> = F extends (cmd: never) => Effect.Effect<unknown, unknown, infer R> ? R : never;
74
- /** The services every runner of a `subscribe` map reads. */
75
- type SubscribeServices<B> = {
76
- [K in keyof B]-?: ServicesOfRunner<NonNullable<B[K]>>;
77
- }[keyof B];
78
- type ServicesOfRunner<F> = F extends (sub: never) => Stream.Stream<unknown, unknown, infer R> ? R : never;
79
- type InterpretOption<C extends Cmd, I> = [C] extends [Cmd<never>] ? {
80
- readonly interpret?: I;
81
- } : {
82
- readonly interpret: I;
83
- };
84
- type SubscribeOption<U extends Sub, B> = [
85
- Exclude<U["type"], BuiltinSubType>
86
- ] extends [never] ? {
87
- readonly subscribe?: B;
88
- } : {
89
- readonly subscribe: B;
90
- };
91
- /**
92
- * The options of the Effect engine's `run`. Beside `interpret` and
93
- * `subscribe`, they are the Promise engine's, with the same meaning; see `run`
94
- * in `@demlik/tea/promise` for each one's contract.
95
- */
96
- type EffectRunOptions<S, M extends {
97
- type: string;
98
- }, C extends Cmd, U extends Sub, Ctx, E extends {
99
- type: string;
100
- }, I, B> = CtxArg<Ctx> & InterpretOption<C, I> & SubscribeOption<U, B> & {
101
- readonly store?: Store<S>;
102
- readonly onError?: OnError;
103
- /** Stamps `at` on minted Msgs and telemetry. Defaults to `Date.now`. */
104
- readonly clock?: () => number;
105
- /** Projects each applied transition to the public events `on` serves. */
106
- readonly events?: (msg: M, state: S) => readonly E[];
107
- /** The policy for a reducer throw. Defaults to `"stop"`. */
108
- readonly supervision?: Supervision<S, M>;
109
- /** The terminal predicate `result()` and `done()` read. */
110
- readonly terminal?: (state: S) => boolean;
111
- /** A fire-and-forget sink for every applied transition. */
112
- readonly telemetry?: TelemetrySink;
113
- /** How long `stop()` waits for async teardown. Defaults to 5_000ms. */
114
- readonly disposeTimeoutMs?: number;
115
- };
116
- /**
117
- * Run `machine` on the Effect engine. The returned Effect needs a `Scope` and
118
- * the services its handlers and runners read, and yields the run handle —
119
- * the same handle the Promise engine returns, so a host adapter typed against
120
- * `RunHandle` takes either.
121
- *
122
- * Closing the scope stops the run: every handler still in flight is
123
- * interrupted (its finalizers run), its Msg is never dispatched, and no Msg is
124
- * dispatched after stop. Calling `stop()` on the handle does the same.
125
- *
126
- * A fenced store is fenced here exactly as on the Promise engine: the check is
127
- * one of the built-ins both engines run.
128
- *
129
- * ```ts
130
- * const program = Effect.gen(function* () {
131
- * const rt = yield* run(machine, {
132
- * interpret: {
133
- * fetch: (cmd) =>
134
- * Effect.gen(function* () {
135
- * const api = yield* Api;
136
- * return yield* api.get(cmd.id);
137
- * }),
138
- * },
139
- * });
140
- * yield* Effect.promise(() => rt.dispatch({ type: "go", id: "7" }));
141
- * });
142
- * Effect.runPromise(program.pipe(Effect.scoped, Effect.provide(ApiLive)));
143
- * ```
144
- */
145
- declare function run<S, M extends {
146
- type: string;
147
- }, C extends Cmd, U extends Sub, Ctx, I extends EffectInterpret<M, C> = EffectInterpret<M, C, never>, B extends EffectSubscribe<M, U> = EffectSubscribe<M, U, never>, E extends {
148
- type: string;
149
- } = never>(machine: Machine<S, M, C, U, Ctx>, opts: EffectRunOptions<S, M, C, U, Ctx, E, I, B>): Effect.Effect<BootingRuntime<S, M, E>, never, Scope.Scope | InterpretServices<I> | SubscribeServices<B>>;
150
-
151
- export { type EffectInterpret, type EffectInterpretCell, type EffectRunOptions, type EffectRunner, type EffectSubscribe, type InterpretServices, type SubscribeServices, run };
7
+ import '../runtime-types-BKg2CGMx.js';
@@ -1,98 +1,6 @@
1
- import { startLoop, builtinExtensions } from '../chunk-KWNCM6XM.js';
2
- import { subEntriesOf, applyCell, Outcome } from '../chunk-K4ETBNKS.js';
3
- import { Effect, Stream, Cause, Fiber, Exit, Result } from 'effect';
4
-
5
- function timer(sub) {
6
- return Stream.fromEffect(Effect.as(Effect.sleep(sub.deps.ms), sub.deps.msg));
7
- }
8
- var builtinRunners = { timer };
9
- function run(machine, opts) {
10
- return Effect.gen(function* () {
11
- const services = yield* Effect.context();
12
- return yield* Effect.acquireRelease(
13
- Effect.sync(
14
- () => start(
15
- machine,
16
- opts,
17
- Effect.runPromiseExitWith(services),
18
- Effect.runForkWith(services)
19
- )
20
- ),
21
- (runtime) => Effect.promise(() => runtime.stop())
22
- );
23
- });
24
- }
25
- function start(machine, opts, runEffect, fork) {
26
- const interpret = opts.interpret ?? {};
27
- const subscribe = opts.subscribe ?? {};
28
- const builtins = builtinRunners;
29
- const defined = new Set((machine.cmds ?? []).map((def) => def.cmdType));
30
- const interruption = new AbortController();
31
- let report = () => {
32
- };
33
- const edge = (loop) => {
34
- report = loop.report;
35
- return {};
36
- };
37
- async function settle(cell, cmd) {
38
- const type = cmd.type;
39
- const exit = await runEffect(Effect.result(cell(cmd)), {
40
- signal: interruption.signal
41
- });
42
- if (Exit.isFailure(exit)) {
43
- if (Cause.hasInterruptsOnly(exit.cause)) return void 0;
44
- throw Cause.squash(exit.cause);
45
- }
46
- const result = exit.value;
47
- if (defined.has(type)) {
48
- return Result.isSuccess(result) ? Outcome.ok(result.success) : Outcome.err(result.failure);
49
- }
50
- if (Result.isFailure(result)) throw result.failure;
51
- return result.success;
52
- }
53
- function handlerFor(type) {
54
- const cell = interpret[type];
55
- if (cell === void 0) return void 0;
56
- return (cmd) => settle(cell, cmd);
57
- }
58
- function runnerFor(type) {
59
- const make = subscribe[type] ?? builtins[type];
60
- if (make === void 0) return void 0;
61
- return (sub, _ctx, dispatch) => {
62
- const drain = Stream.runForEach(
63
- make(sub),
64
- (msg) => Effect.sync(() => dispatch(msg))
65
- ).pipe(
66
- Effect.catchCause(
67
- (cause) => Cause.hasInterruptsOnly(cause) ? Effect.void : Effect.sync(() => report(Cause.squash(cause), "follow-up"))
68
- )
69
- );
70
- const fiber = fork(drain);
71
- return () => Effect.runPromise(Fiber.interrupt(fiber));
72
- };
73
- }
74
- const handle = startLoop({
75
- init: machine.init,
76
- reduce: (state, msg) => applyCell(machine, state, msg),
77
- subs: subEntriesOf(machine),
78
- runnerFor,
79
- handlerFor,
80
- store: opts.store,
81
- ctx: opts.ctx ?? {},
82
- onError: opts.onError,
83
- disposeTimeoutMs: opts.disposeTimeoutMs ?? 5e3,
84
- idleCap: 1e5,
85
- extensions: [...builtinExtensions(machine, opts), edge]
86
- });
87
- const stopLoop = handle.stop;
88
- handle.stop = () => {
89
- const stopped = stopLoop();
90
- interruption.abort();
91
- return stopped;
92
- };
93
- return handle;
94
- }
95
-
96
- export { run };
1
+ export { Stopped, StoreFailed, run } from '../chunk-I7E7AD2S.js';
2
+ import '../chunk-AHW2CLPT.js';
3
+ import '../chunk-JVE2LBFJ.js';
4
+ import '../chunk-AIIXV4XB.js';
97
5
  //# sourceMappingURL=index.js.map
98
6
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/effect/run.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * The Effect engine's `run` (#283): the same machine the Promise engine runs,\n * with Effect handlers, Effect sub runners, the caller's Layers and\n * interruption on stop.\n *\n * It runs the one core loop both engines share (`src/internal/engine/loop.ts`)\n * with the same built-ins in the same order, so a machine folds the same way on\n * either engine. What this file adds is the Effect edge:\n *\n * - an `interpret` cell returns `Effect<Ok, E, R>`, read with\n * `Effect.result`: a success settles `_ok`, a declared failure settles\n * `_err`, a defect goes to the error sink;\n * - a `subscribe` runner returns a `Stream<Msg>`, drained on its own fiber;\n * - every handler and runner fiber runs with the services the caller\n * provided, so `R` reaches them from the caller's Layers;\n * - stopping interrupts every handler fiber still in flight.\n */\n\nimport { Cause, Effect, Exit, Fiber, Result, type Scope, Stream } from \"effect\";\nimport { builtinExtensions } from \"../internal/engine/builtins\";\nimport {\n type ExtensionFactory,\n type LoopHandler,\n type LoopRunner,\n startLoop,\n} from \"../internal/engine/loop\";\nimport type {\n BuiltinSub,\n BuiltinSubType,\n Cmd,\n DeclaredErrorsOf,\n ErrorsOf,\n Machine,\n OkOfCmd,\n Sub,\n TimerSub,\n} from \"../pure/core\";\nimport { applyCell, Outcome, subEntriesOf } from \"../pure/core\";\nimport type {\n BootingRuntime,\n CtxArg,\n OnError,\n RuntimeErrorPhase,\n Store,\n Supervision,\n TelemetrySink,\n} from \"../runtime-types\";\n\n// === The handler and runner shapes ===\n\n/**\n * One Effect `interpret` cell. For a `Cmd.define`d Cmd it succeeds with the\n * Cmd's `Ok` and fails with one of its declared tags, and the engine mints\n * `<name>_ok` / `<name>_err` from that (ADR 0021). For a hand-written Cmd it\n * succeeds with a follow-up Msg or nothing, and a failure rejects the dispatch,\n * as a throw does on the Promise engine. `R` is whatever services it reads.\n */\nexport type EffectInterpretCell<\n M extends { type: string },\n C extends Cmd,\n R = unknown,\n> =\n unknown extends ErrorsOf<C>\n ? // biome-ignore lint/suspicious/noConfusingVoidType: a hand-written Cmd's handler may settle with nothing\n (cmd: C) => Effect.Effect<M | void, unknown, R>\n : (cmd: C) => Effect.Effect<OkOfCmd<C>, DeclaredErrorsOf<C>, R>;\n\n/**\n * The Effect engine's `interpret` map: one cell per Cmd variant, each reading\n * services within `R`.\n */\nexport type EffectInterpret<\n M extends { type: string },\n C extends Cmd,\n R = unknown,\n> = {\n readonly [K in C[\"type\"]]: EffectInterpretCell<M, Extract<C, { type: K }>, R>;\n};\n\n/**\n * One Effect sub runner: the Sub in, a `Stream` of Msgs out. The engine drains\n * it on its own fiber and interrupts that fiber when the Sub stops. A stream\n * that fails reaches the error sink under `\"follow-up\"`.\n */\nexport type EffectRunner<\n M extends { type: string },\n U extends Sub,\n R = unknown,\n> = (sub: U) => Stream.Stream<M, unknown, R>;\n\n/**\n * The Effect engine's `subscribe` map: a runner for every Sub type the machine\n * declares beyond the built-ins, and optionally one for a built-in, which\n * replaces the engine's own (#270 R2.1).\n */\nexport type EffectSubscribe<\n M extends { type: string },\n U extends Sub,\n R = unknown,\n> = {\n readonly [K in Exclude<U[\"type\"], BuiltinSubType>]: EffectRunner<\n M,\n Extract<U, { type: K }>,\n R\n >;\n} & {\n readonly [K in BuiltinSubType]?: EffectRunner<\n M,\n Extract<BuiltinSub<M>, { type: K }>,\n R\n >;\n};\n\n/** The services every cell of an `interpret` map reads. */\nexport type InterpretServices<I> = {\n [K in keyof I]: ServicesOfCell<I[K]>;\n}[keyof I];\n\ntype ServicesOfCell<F> = F extends (\n cmd: never,\n) => Effect.Effect<unknown, unknown, infer R>\n ? R\n : never;\n\n/** The services every runner of a `subscribe` map reads. */\nexport type SubscribeServices<B> = {\n [K in keyof B]-?: ServicesOfRunner<NonNullable<B[K]>>;\n}[keyof B];\n\ntype ServicesOfRunner<F> = F extends (\n sub: never,\n) => Stream.Stream<unknown, unknown, infer R>\n ? R\n : never;\n\n// `interpret` is optional for a machine that emits no Cmd, and `subscribe` for\n// one that declares only built-in Subs — the same requiredness the Promise\n// engine's `RunHandlers` carries.\ntype InterpretOption<C extends Cmd, I> = [C] extends [Cmd<never>]\n ? { readonly interpret?: I }\n : { readonly interpret: I };\n\ntype SubscribeOption<U extends Sub, B> = [\n Exclude<U[\"type\"], BuiltinSubType>,\n] extends [never]\n ? { readonly subscribe?: B }\n : { readonly subscribe: B };\n\n/**\n * The options of the Effect engine's `run`. Beside `interpret` and\n * `subscribe`, they are the Promise engine's, with the same meaning; see `run`\n * in `@demlik/tea/promise` for each one's contract.\n */\nexport type EffectRunOptions<\n S,\n M extends { type: string },\n C extends Cmd,\n U extends Sub,\n Ctx,\n E extends { type: string },\n I,\n B,\n> = CtxArg<Ctx> &\n InterpretOption<C, I> &\n SubscribeOption<U, B> & {\n readonly store?: Store<S>;\n readonly onError?: OnError;\n /** Stamps `at` on minted Msgs and telemetry. Defaults to `Date.now`. */\n readonly clock?: () => number;\n /** Projects each applied transition to the public events `on` serves. */\n readonly events?: (msg: M, state: S) => readonly E[];\n /** The policy for a reducer throw. Defaults to `\"stop\"`. */\n readonly supervision?: Supervision<S, M>;\n /** The terminal predicate `result()` and `done()` read. */\n readonly terminal?: (state: S) => boolean;\n /** A fire-and-forget sink for every applied transition. */\n readonly telemetry?: TelemetrySink;\n /** How long `stop()` waits for async teardown. Defaults to 5_000ms. */\n readonly disposeTimeoutMs?: number;\n };\n\n// === Built-in runners ===\n\n/** `timer`: emit `deps.msg` once, `deps.ms` after the Sub starts. */\nfunction timer<M>(sub: TimerSub<M>): Stream.Stream<M> {\n return Stream.fromEffect(Effect.as(Effect.sleep(sub.deps.ms), sub.deps.msg));\n}\n\n/** The Effect engine's built-in runners, keyed by the Sub type each runs. */\nconst builtinRunners = { timer } as const satisfies Record<\n BuiltinSubType,\n unknown\n>;\n\n// === run ===\n\n/**\n * Run `machine` on the Effect engine. The returned Effect needs a `Scope` and\n * the services its handlers and runners read, and yields the run handle —\n * the same handle the Promise engine returns, so a host adapter typed against\n * `RunHandle` takes either.\n *\n * Closing the scope stops the run: every handler still in flight is\n * interrupted (its finalizers run), its Msg is never dispatched, and no Msg is\n * dispatched after stop. Calling `stop()` on the handle does the same.\n *\n * A fenced store is fenced here exactly as on the Promise engine: the check is\n * one of the built-ins both engines run.\n *\n * ```ts\n * const program = Effect.gen(function* () {\n * const rt = yield* run(machine, {\n * interpret: {\n * fetch: (cmd) =>\n * Effect.gen(function* () {\n * const api = yield* Api;\n * return yield* api.get(cmd.id);\n * }),\n * },\n * });\n * yield* Effect.promise(() => rt.dispatch({ type: \"go\", id: \"7\" }));\n * });\n * Effect.runPromise(program.pipe(Effect.scoped, Effect.provide(ApiLive)));\n * ```\n */\nexport function run<\n S,\n M extends { type: string },\n C extends Cmd,\n U extends Sub,\n Ctx,\n // The defaults read no services, so an omitted map adds none to `R`.\n I extends EffectInterpret<M, C> = EffectInterpret<M, C, never>,\n B extends EffectSubscribe<M, U> = EffectSubscribe<M, U, never>,\n E extends { type: string } = never,\n>(\n machine: Machine<S, M, C, U, Ctx>,\n opts: EffectRunOptions<S, M, C, U, Ctx, E, I, B>,\n): Effect.Effect<\n BootingRuntime<S, M, E>,\n never,\n Scope.Scope | InterpretServices<I> | SubscribeServices<B>\n> {\n return Effect.gen(function* () {\n const services = yield* Effect.context<\n InterpretServices<I> | SubscribeServices<B>\n >();\n return yield* Effect.acquireRelease(\n Effect.sync(() =>\n start<S, M, C, U, Ctx, E>(\n machine,\n opts as EffectRunOptions<S, M, C, U, Ctx, E, unknown, unknown>,\n Effect.runPromiseExitWith(services) as RunEffect,\n Effect.runForkWith(services) as ForkEffect,\n ),\n ),\n (runtime) => Effect.promise(() => runtime.stop()),\n );\n });\n}\n\n/** Run an erased Effect to its Exit, interruptible through `signal`. */\ntype RunEffect = (\n effect: Effect.Effect<unknown, unknown>,\n options: { readonly signal: AbortSignal },\n) => Promise<Exit.Exit<unknown, unknown>>;\n\n/** Fork an erased Effect onto its own fiber. */\ntype ForkEffect = (\n effect: Effect.Effect<unknown, unknown>,\n) => Fiber.Fiber<unknown, unknown>;\n\ntype AnyCell = (cmd: unknown) => Effect.Effect<unknown, unknown>;\ntype AnyRunner = (sub: Sub) => Stream.Stream<unknown, unknown>;\n\nfunction start<\n S,\n M extends { type: string },\n C extends Cmd,\n U extends Sub,\n Ctx,\n E extends { type: string },\n>(\n machine: Machine<S, M, C, U, Ctx>,\n opts: EffectRunOptions<S, M, C, U, Ctx, E, unknown, unknown>,\n runEffect: RunEffect,\n fork: ForkEffect,\n): BootingRuntime<S, M, E> {\n const interpret = ((opts as { interpret?: unknown }).interpret ??\n {}) as Readonly<Record<string, AnyCell | undefined>>;\n const subscribe = ((opts as { subscribe?: unknown }).subscribe ??\n {}) as Readonly<Record<string, AnyRunner | undefined>>;\n const builtins = builtinRunners as unknown as Readonly<\n Record<string, AnyRunner | undefined>\n >;\n const defined = new Set((machine.cmds ?? []).map((def) => def.cmdType));\n\n // Aborted on stop: every handler fiber runs under this signal, so aborting\n // it interrupts all of them at once.\n const interruption = new AbortController();\n\n // The loop's error sink, lent to the runners below: a stream that fails\n // after it started has no caller to reject at.\n let report: (error: unknown, phase: RuntimeErrorPhase) => void = () => {};\n const edge: ExtensionFactory<S, M, C> = (loop) => {\n report = loop.report;\n return {};\n };\n\n // Read the cell's Effect with `Effect.result`, so a declared failure is a\n // value and only a defect or an interruption is left in the Exit's cause.\n async function settle(cell: AnyCell, cmd: unknown): Promise<unknown> {\n const type = (cmd as { type: string }).type;\n const exit = await runEffect(Effect.result(cell(cmd)), {\n signal: interruption.signal,\n });\n if (Exit.isFailure(exit)) {\n // Interrupted by stop: nothing to dispatch.\n if (Cause.hasInterruptsOnly(exit.cause)) return undefined;\n // A defect. For a defined Cmd the `Cmd.define` edge routes this throw to\n // the error sink; for a hand-written one it rejects the dispatch.\n throw Cause.squash(exit.cause);\n }\n const result = exit.value as Result.Result<unknown, unknown>;\n if (defined.has(type)) {\n return Result.isSuccess(result)\n ? Outcome.ok(result.success)\n : Outcome.err(result.failure);\n }\n if (Result.isFailure(result)) throw result.failure;\n return result.success;\n }\n\n function handlerFor(type: string): LoopHandler<M> | undefined {\n const cell = interpret[type];\n if (cell === undefined) return undefined;\n return (cmd) => settle(cell, cmd);\n }\n\n // A runner's Msgs reach the loop through its `dispatch`, which queues each\n // one behind the step in progress — never a transition on the stream's own\n // fiber (spike #260).\n function runnerFor(type: string): LoopRunner<Ctx, M> | undefined {\n const make = subscribe[type] ?? builtins[type];\n if (make === undefined) return undefined;\n return (sub, _ctx, dispatch) => {\n const drain = Stream.runForEach(make(sub), (msg) =>\n Effect.sync(() => dispatch(msg as M)),\n ).pipe(\n Effect.catchCause((cause) =>\n Cause.hasInterruptsOnly(cause)\n ? Effect.void\n : Effect.sync(() => report(Cause.squash(cause), \"follow-up\")),\n ),\n );\n const fiber = fork(drain);\n return () => Effect.runPromise(Fiber.interrupt(fiber));\n };\n }\n\n const handle = startLoop<S, M, C, Ctx>({\n init: machine.init,\n reduce: (state, msg) => applyCell<S, M, C>(machine, state, msg),\n subs: subEntriesOf<S>(machine),\n runnerFor,\n handlerFor,\n store: opts.store,\n ctx: (opts.ctx ?? {}) as Ctx,\n onError: opts.onError,\n disposeTimeoutMs: opts.disposeTimeoutMs ?? 5_000,\n idleCap: 100_000,\n extensions: [...builtinExtensions<S, M, C, E>(machine, opts), edge],\n });\n\n // Stop closes the gate first, so nothing an interrupted handler leaves\n // behind is dispatched, then interrupts every handler still in flight so the\n // drain it waits on can finish.\n const stopLoop = handle.stop;\n handle.stop = () => {\n const stopped = stopLoop();\n interruption.abort();\n return stopped;\n };\n return handle as unknown as BootingRuntime<S, M, E>;\n}\n"]}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
@@ -1,7 +1,7 @@
1
- import { R as Runtime, S as Store } from '../runtime-types-B62Ucnxr.js';
1
+ import { R as Runtime, M as Migrated, S as Store } from '../runtime-types-BKg2CGMx.js';
2
2
  import { ReactNode } from 'react';
3
- import { S as Sub } from '../core-rDbOaJTN.js';
4
- import { S as SubscribeHandler } from '../types-DPm5YCDQ.js';
3
+ import { c as Sub } from '../core-Ce9ncpuv.js';
4
+ import { S as SubscribeHandler } from '../types-SzNSHKlV.js';
5
5
  import '@standard-schema/spec';
6
6
 
7
7
  /**
@@ -516,7 +516,9 @@ declare function fakeChrome(): FakeChrome;
516
516
  * at the key, or unparseable JSON) — matches @demlik/tea/do's "throw at boot via
517
517
  * store.load" contract so tea's `run()` surfaces it predictably. The
518
518
  * `parse` callback handles the semantic layer (shape mismatch → return
519
- * `null`); it must NOT throw, per the `Store<S>.migrate` contract.
519
+ * `refuse(reason)`, nothing saved → `null`); it must NOT throw, per the
520
+ * `Store<S>.migrate` contract. A throw or a refusal makes `ready` reject
521
+ * with `StoreRefusedError`, and nothing is saved.
520
522
  *
521
523
  * `parse` is REQUIRED because chrome.storage is a real serialization boundary
522
524
  * — JSON to disk, then back — and the structural type of what comes back is
@@ -536,6 +538,6 @@ declare function fakeChrome(): FakeChrome;
536
538
  * single writer, and that is a precondition to keep, not one this store can
537
539
  * enforce. See `docs/explanation/durability-model.md`.
538
540
  */
539
- declare function chromeStorageStore<S>(key: string, parse: (raw: unknown) => S | null, area?: chrome.storage.StorageArea): Store<S>;
541
+ declare function chromeStorageStore<S>(key: string, parse: (raw: unknown) => Migrated<S>, area?: chrome.storage.StorageArea): Store<S>;
540
542
 
541
543
  export { type BackgroundRuntimeContext, type BridgeClient, type BridgeClientOpts, type BridgeRuntimeOpts, type BridgeTabClientOpts, type ChromeMessageOpts, type ChromeStorageChangeOpts, type ChromeTabsEventOpts, type FakeChrome, type TabsEventName, type UseBackgroundRuntimeOpts, type UseBackgroundRuntimeResult, bridgeClient, bridgeRuntime, bridgeTabClient, chromeStorageStore, createBackgroundRuntimeContext, fakeChrome, fromChromeAlarm, fromChromeMessage, fromChromeStorageChange, fromChromeTabsEvent, passThroughMsg, useBackgroundRuntime };
@@ -1,6 +1,5 @@
1
- import { describeError } from '../chunk-G5E74IJB.js';
2
- import { historyTracker, dispatchIfPresent } from '../chunk-C4U5D5HP.js';
3
- import '../chunk-K4ETBNKS.js';
1
+ import { historyTracker, dispatchIfPresent } from '../chunk-FNGZMVIT.js';
2
+ import { describeError } from '../chunk-AIIXV4XB.js';
4
3
  import { useRef, useSyncExternalStore, useEffect, useCallback, createContext, useMemo, useContext } from 'react';
5
4
  import { jsx } from 'react/jsx-runtime';
6
5