@demlik/tea 0.14.0 → 0.16.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 (116) hide show
  1. package/README.md +30 -7
  2. package/dist/agent/index.d.ts +49 -36
  3. package/dist/agent/index.js +12 -8
  4. package/dist/chunk-4LPY67E4.js +18 -0
  5. package/dist/chunk-4LPY67E4.js.map +1 -0
  6. package/dist/chunk-5XU6ZJO2.js +533 -0
  7. package/dist/chunk-5XU6ZJO2.js.map +1 -0
  8. package/dist/{chunk-AQ6ZIMEA.js → chunk-6NG4V5SB.js} +89 -115
  9. package/dist/chunk-6NG4V5SB.js.map +1 -0
  10. package/dist/{chunk-HYDWG35Q.js → chunk-7MGXQZPW.js} +11 -9
  11. package/dist/chunk-7MGXQZPW.js.map +1 -0
  12. package/dist/{chunk-BLJ2JQSH.js → chunk-BCTEOVOU.js} +3 -3
  13. package/dist/{chunk-BLJ2JQSH.js.map → chunk-BCTEOVOU.js.map} +1 -1
  14. package/dist/chunk-CH5KTOEZ.js +710 -0
  15. package/dist/chunk-CH5KTOEZ.js.map +1 -0
  16. package/dist/chunk-CIHSHLQX.js +64 -0
  17. package/dist/chunk-CIHSHLQX.js.map +1 -0
  18. package/dist/{chunk-Z2L3LSNV.js → chunk-EHUDXAKC.js} +246 -210
  19. package/dist/chunk-EHUDXAKC.js.map +1 -0
  20. package/dist/chunk-GOX2CYIM.js +380 -0
  21. package/dist/chunk-GOX2CYIM.js.map +1 -0
  22. package/dist/chunk-IVJP3GKJ.js +104 -0
  23. package/dist/chunk-IVJP3GKJ.js.map +1 -0
  24. package/dist/{chunk-F7FMAWLA.js → chunk-MVZS5FDM.js} +13 -6
  25. package/dist/chunk-MVZS5FDM.js.map +1 -0
  26. package/dist/{chunk-LYLTKJWM.js → chunk-MYNLY3HP.js} +9 -8
  27. package/dist/chunk-MYNLY3HP.js.map +1 -0
  28. package/dist/{chunk-I5MQMJDW.js → chunk-NSIAORRY.js} +20 -30
  29. package/dist/chunk-NSIAORRY.js.map +1 -0
  30. package/dist/{chunk-MYXFNWAJ.js → chunk-QNGYQMZB.js} +4 -4
  31. package/dist/chunk-QNGYQMZB.js.map +1 -0
  32. package/dist/chunk-WT5PBPLB.js +98 -0
  33. package/dist/chunk-WT5PBPLB.js.map +1 -0
  34. package/dist/{core-CTzMJ82M.d.ts → core-BbgtiXdg.d.ts} +231 -139
  35. package/dist/do/index.d.ts +37 -32
  36. package/dist/do/index.js +21 -14
  37. package/dist/do/index.js.map +1 -1
  38. package/dist/{durable-effects-B0-qGQDy.d.ts → durable-effects-7MTK_jnj.d.ts} +1 -1
  39. package/dist/effect/index.d.ts +151 -0
  40. package/dist/effect/index.js +98 -0
  41. package/dist/effect/index.js.map +1 -0
  42. package/dist/extension/index.d.ts +6 -7
  43. package/dist/extension/index.js +3 -2
  44. package/dist/extension/index.js.map +1 -1
  45. package/dist/flow/index.d.ts +68 -70
  46. package/dist/flow/index.js +32 -27
  47. package/dist/flow/index.js.map +1 -1
  48. package/dist/idempotency/index.d.ts +6 -7
  49. package/dist/idempotency/index.js +4 -2
  50. package/dist/{index-DJWIER_3.d.ts → index-7vV8xmsD.d.ts} +1 -1
  51. package/dist/{index-NjrT3fL2.d.ts → index-Bz5Rh9Ga.d.ts} +19 -96
  52. package/dist/index-CjFDUBeq.d.ts +207 -0
  53. package/dist/{index-6A7dB8f6.d.ts → index-CkFYA9Y6.d.ts} +14 -16
  54. package/dist/{index-B5BZ-_cT.d.ts → index-Cou86-GX.d.ts} +189 -108
  55. package/dist/{index-TvRb1KVf.d.ts → index-DU6JpQ8G.d.ts} +1 -1
  56. package/dist/{index-q0hXFeZ0.d.ts → index-Xufl55W8.d.ts} +286 -215
  57. package/dist/{index-4vZzljCD.d.ts → index-_dOR3xqA.d.ts} +57 -45
  58. package/dist/index.d.ts +181 -385
  59. package/dist/index.js +2 -1
  60. package/dist/jev/index.d.ts +147 -99
  61. package/dist/jev/index.js +329 -233
  62. package/dist/jev/index.js.map +1 -1
  63. package/dist/{machine-CdIcN2Xm.d.ts → machine-BQzTV8On.d.ts} +171 -280
  64. package/dist/machine-viz/index.d.ts +5 -5
  65. package/dist/machine-viz/index.js +8 -4
  66. package/dist/machine-viz/index.js.map +1 -1
  67. package/dist/mem/index.d.ts +3 -4
  68. package/dist/mem/index.js +2 -1
  69. package/dist/mem/index.js.map +1 -1
  70. package/dist/node/index.d.ts +119 -78
  71. package/dist/node/index.js +52 -38
  72. package/dist/node/index.js.map +1 -1
  73. package/dist/paginate/index.d.ts +27 -33
  74. package/dist/paginate/index.js +6 -4
  75. package/dist/parity/index.d.ts +4 -5
  76. package/dist/parity/index.js +3 -2
  77. package/dist/parity/index.js.map +1 -1
  78. package/dist/pbt/index.d.ts +2 -2
  79. package/dist/pbt/index.js +2 -1
  80. package/dist/pbt/index.js.map +1 -1
  81. package/dist/persistence/index.d.ts +6 -7
  82. package/dist/persistence/index.js +5 -3
  83. package/dist/promise/index.d.ts +186 -0
  84. package/dist/promise/index.js +5 -0
  85. package/dist/promise/index.js.map +1 -0
  86. package/dist/protocol-ClRZBhHQ.d.ts +53 -0
  87. package/dist/react/index.d.ts +36 -17
  88. package/dist/react/index.js +27 -4
  89. package/dist/react/index.js.map +1 -1
  90. package/dist/resilience/index.d.ts +63 -455
  91. package/dist/resilience/index.js +37 -483
  92. package/dist/resilience/index.js.map +1 -1
  93. package/dist/{runtime-types-LWDoi943.d.ts → runtime-types-CiVpC0HN.d.ts} +131 -388
  94. package/dist/testing/index.d.ts +165 -15
  95. package/dist/testing/index.js +104 -3
  96. package/dist/testing/index.js.map +1 -1
  97. package/dist/timing/index.d.ts +25 -22
  98. package/dist/timing/index.js +4 -3
  99. package/dist/timing/index.js.map +1 -1
  100. package/dist/{types-DP3f5NIl.d.ts → types-LxZxGYda.d.ts} +2 -2
  101. package/dist/work-queue/index.d.ts +5 -6
  102. package/package.json +18 -5
  103. package/dist/chunk-AQ6ZIMEA.js.map +0 -1
  104. package/dist/chunk-F2US5BW6.js +0 -72
  105. package/dist/chunk-F2US5BW6.js.map +0 -1
  106. package/dist/chunk-F7FMAWLA.js.map +0 -1
  107. package/dist/chunk-HUKZQX6U.js +0 -97
  108. package/dist/chunk-HUKZQX6U.js.map +0 -1
  109. package/dist/chunk-HYDWG35Q.js.map +0 -1
  110. package/dist/chunk-I5MQMJDW.js.map +0 -1
  111. package/dist/chunk-LYLTKJWM.js.map +0 -1
  112. package/dist/chunk-MYXFNWAJ.js.map +0 -1
  113. package/dist/chunk-RQULHGYH.js +0 -1804
  114. package/dist/chunk-RQULHGYH.js.map +0 -1
  115. package/dist/chunk-Z2L3LSNV.js.map +0 -1
  116. package/dist/index-DMCeMPMJ.d.ts +0 -272
@@ -1,4 +1,4 @@
1
- import { C as Cmd } from './core-CTzMJ82M.js';
1
+ import { C as Cmd } from './core-BbgtiXdg.js';
2
2
 
3
3
  /**
4
4
  * @demlik/tea/do — the durable pending-effects ledger (substrate primitive #1).
@@ -0,0 +1,151 @@
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-BbgtiXdg.js';
3
+ import { C as CtxArg, S as Store, O as OnError, a as Supervision, T as TelemetrySink, B as BootingRuntime } from '../runtime-types-CiVpC0HN.js';
4
+ 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 };
@@ -0,0 +1,98 @@
1
+ import { startLoop, builtinExtensions } from '../chunk-5XU6ZJO2.js';
2
+ import { subEntriesOf, applyCell, Outcome } from '../chunk-CH5KTOEZ.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 };
97
+ //# sourceMappingURL=index.js.map
98
+ //# sourceMappingURL=index.js.map
@@ -0,0 +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,9 +1,8 @@
1
- import { R as Runtime, S as Store } from '../runtime-types-LWDoi943.js';
1
+ import { R as Runtime, S as Store } from '../runtime-types-CiVpC0HN.js';
2
2
  import { ReactNode } from 'react';
3
- import { S as Sub } from '../core-CTzMJ82M.js';
4
- import { S as SubscribeHandler } from '../types-DP3f5NIl.js';
5
- import 'better-result';
6
- import 'zod';
3
+ import { S as Sub } from '../core-BbgtiXdg.js';
4
+ import { S as SubscribeHandler } from '../types-LxZxGYda.js';
5
+ import '@standard-schema/spec';
7
6
 
8
7
  /**
9
8
  * Runtime bridge — expose a `@demlik/tea` runtime running in one chrome context
@@ -327,9 +326,9 @@ declare function createBackgroundRuntimeContext<S, M extends {
327
326
  }>(): BackgroundRuntimeContext<S, M>;
328
327
 
329
328
  type AlarmSubData = {
330
- alarmName: string;
329
+ readonly alarmName: string;
331
330
  };
332
- declare function fromChromeAlarm<S extends Sub & AlarmSubData, M>(msgFn: (alarm: chrome.alarms.Alarm, sub: S) => M | null): SubscribeHandler<S, M, unknown>;
331
+ declare function fromChromeAlarm<S extends Sub<string, AlarmSubData>, M>(msgFn: (alarm: chrome.alarms.Alarm, sub: S) => M | null): SubscribeHandler<S, M, unknown>;
333
332
 
334
333
  interface ChromeMessageOpts<S extends Sub, M> {
335
334
  /**
@@ -1,5 +1,6 @@
1
1
  import { describeError } from '../chunk-G5E74IJB.js';
2
- import { historyTracker, dispatchIfPresent } from '../chunk-RQULHGYH.js';
2
+ import { historyTracker, dispatchIfPresent } from '../chunk-GOX2CYIM.js';
3
+ import '../chunk-CH5KTOEZ.js';
3
4
  import { useRef, useSyncExternalStore, useEffect, useCallback, createContext, useMemo, useContext } from 'react';
4
5
  import { jsx } from 'react/jsx-runtime';
5
6
 
@@ -249,7 +250,7 @@ function createBackgroundRuntimeContext() {
249
250
  function fromChromeAlarm(msgFn) {
250
251
  return (sub, _ctx, dispatch) => {
251
252
  const listener = (alarm) => {
252
- if (alarm.name !== sub.alarmName) return;
253
+ if (alarm.name !== sub.deps.alarmName) return;
253
254
  dispatchIfPresent(dispatch, msgFn(alarm, sub));
254
255
  };
255
256
  chrome.alarms.onAlarm.addListener(listener);