@demlik/tea 0.19.0 → 0.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +36 -20
- package/dist/agent/index.d.ts +48 -17
- package/dist/agent/index.js +10 -10
- package/dist/{chunk-IHUNKHDX.js → chunk-4I2LCQKB.js} +3 -3
- package/dist/{chunk-IHUNKHDX.js.map → chunk-4I2LCQKB.js.map} +1 -1
- package/dist/{chunk-XVIKSRCK.js → chunk-6NIQIUGR.js} +4 -4
- package/dist/{chunk-XVIKSRCK.js.map → chunk-6NIQIUGR.js.map} +1 -1
- package/dist/{chunk-JVKU2UQC.js → chunk-7Z2IDZ7R.js} +3 -3
- package/dist/{chunk-JVKU2UQC.js.map → chunk-7Z2IDZ7R.js.map} +1 -1
- package/dist/{chunk-H3MWNH7A.js → chunk-BFSZ4L6Y.js} +4 -4
- package/dist/{chunk-H3MWNH7A.js.map → chunk-BFSZ4L6Y.js.map} +1 -1
- package/dist/{chunk-H2ELKHI6.js → chunk-EB5OMOXX.js} +4 -4
- package/dist/chunk-EB5OMOXX.js.map +1 -0
- package/dist/{chunk-AIIXV4XB.js → chunk-GAVLND5C.js} +19 -4
- package/dist/chunk-GAVLND5C.js.map +1 -0
- package/dist/{chunk-I7E7AD2S.js → chunk-HU3Y2AZY.js} +4 -4
- package/dist/chunk-HU3Y2AZY.js.map +1 -0
- package/dist/{chunk-WTSOW2MD.js → chunk-MBQR3LFW.js} +5 -5
- package/dist/{chunk-WTSOW2MD.js.map → chunk-MBQR3LFW.js.map} +1 -1
- package/dist/{chunk-C3G2QFEZ.js → chunk-QIE4Y6BK.js} +4 -4
- package/dist/{chunk-C3G2QFEZ.js.map → chunk-QIE4Y6BK.js.map} +1 -1
- package/dist/{chunk-BRX3243I.js → chunk-TMYUDZLE.js} +3 -3
- package/dist/{chunk-BRX3243I.js.map → chunk-TMYUDZLE.js.map} +1 -1
- package/dist/{chunk-FNGZMVIT.js → chunk-VHKDUBXC.js} +3 -3
- package/dist/chunk-VHKDUBXC.js.map +1 -0
- package/dist/{chunk-AHW2CLPT.js → chunk-VM7PMFV5.js} +70 -47
- package/dist/chunk-VM7PMFV5.js.map +1 -0
- package/dist/{chunk-PCJA2HTZ.js → chunk-W6XWI6QE.js} +20 -20
- package/dist/chunk-W6XWI6QE.js.map +1 -0
- package/dist/{chunk-JYNYG5SF.js → chunk-YCJPLPQQ.js} +3 -3
- package/dist/chunk-YCJPLPQQ.js.map +1 -0
- package/dist/{chunk-YIMOFXST.js → chunk-YDF6P74H.js} +3 -3
- package/dist/chunk-YDF6P74H.js.map +1 -0
- package/dist/{chunk-JVE2LBFJ.js → chunk-Z7IL735U.js} +3 -3
- package/dist/{chunk-JVE2LBFJ.js.map → chunk-Z7IL735U.js.map} +1 -1
- package/dist/{chunk-PQSDUX6B.js → chunk-ZV4WGW74.js} +3 -3
- package/dist/{chunk-PQSDUX6B.js.map → chunk-ZV4WGW74.js.map} +1 -1
- package/dist/{core-Ce9ncpuv.d.ts → core-BKJW1Kmq.d.ts} +154 -2
- package/dist/devtools/index.d.ts +17 -0
- package/dist/devtools/index.js.map +1 -1
- package/dist/do/index.d.ts +17 -15
- package/dist/do/index.js +11 -11
- package/dist/do/index.js.map +1 -1
- package/dist/{drive-loop-CsUsW3Wo.d.ts → drive-loop-Dc6Z8Vbs.d.ts} +1 -1
- package/dist/{durable-effects-BmUrRA-h.d.ts → durable-effects-CgrLNccA.d.ts} +1 -1
- package/dist/effect/index.d.ts +191 -5
- package/dist/effect/index.js +71 -4
- package/dist/effect/index.js.map +1 -1
- package/dist/extension/index.d.ts +84 -3
- package/dist/extension/index.js +2 -2
- package/dist/extension/index.js.map +1 -1
- package/dist/flow/index.d.ts +33 -13
- package/dist/flow/index.js +13 -12
- package/dist/flow/index.js.map +1 -1
- package/dist/idempotency/index.d.ts +11 -3
- package/dist/idempotency/index.js +3 -3
- package/dist/{index-Ce5GYAuI.d.ts → index-1hit3dJ9.d.ts} +2 -2
- package/dist/{index-2kNxy6az.d.ts → index-B-VC4qjx.d.ts} +16 -4
- package/dist/{index-Bf9_bNql.d.ts → index-BjwRcjBi.d.ts} +2 -2
- package/dist/{index-Dy3379ve.d.ts → index-CYrUWi1c.d.ts} +4 -4
- package/dist/{index-DWdg7R1l.d.ts → index-Cuy1_xTh.d.ts} +5 -1
- package/dist/{index-D8sYVzCI.d.ts → index-DB8Yn0-K.d.ts} +6 -1
- package/dist/{index-e36uEyl4.d.ts → index-Diyo8WBO.d.ts} +2 -2
- package/dist/{index-B1Wzarkl.d.ts → index-Z6Uw7C9t.d.ts} +1 -1
- package/dist/index.d.ts +70 -9
- package/dist/index.js +2 -2
- package/dist/jev/index.d.ts +46 -34
- package/dist/jev/index.js +12 -8
- package/dist/jev/index.js.map +1 -1
- package/dist/{machine-CuojfZup.d.ts → machine-BuPTS1QH.d.ts} +11 -9
- package/dist/machine-viz/index.d.ts +2 -1
- package/dist/machine-viz/index.js +2 -2
- package/dist/machine-viz/index.js.map +1 -1
- package/dist/mem/index.d.ts +2 -2
- package/dist/mem/index.js +2 -2
- package/dist/node/index.d.ts +11 -2
- package/dist/node/index.js +2 -2
- package/dist/node/index.js.map +1 -1
- package/dist/otel/index.d.ts +10 -10
- package/dist/otel/index.js +10 -10
- package/dist/paginate/index.d.ts +5 -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/parity/index.js.map +1 -1
- package/dist/pbt/index.d.ts +1 -1
- package/dist/pbt/index.js +2 -2
- package/dist/persistence/index.d.ts +5 -5
- package/dist/persistence/index.js +4 -4
- package/dist/promise/index.d.ts +30 -10
- package/dist/promise/index.js +4 -4
- package/dist/react/index.d.ts +7 -6
- package/dist/react/index.js.map +1 -1
- package/dist/resilience/index.d.ts +7 -6
- package/dist/resilience/index.js +5 -5
- package/dist/resilience/index.js.map +1 -1
- package/dist/{index-BnsAqn0-.d.ts → run-D0sxbyno.d.ts} +23 -7
- package/dist/{runtime-types-BKg2CGMx.d.ts → runtime-types-BPKp2bGo.d.ts} +120 -9
- package/dist/testing/effect/index.d.ts +5 -5
- package/dist/testing/effect/index.js +8 -8
- package/dist/testing/index.d.ts +2 -2
- package/dist/testing/index.js +3 -3
- package/dist/testing/promise/index.d.ts +4 -4
- package/dist/testing/promise/index.js +5 -5
- package/dist/timing/index.d.ts +4 -4
- package/dist/timing/index.js +4 -4
- package/dist/types-BiXj7k_k.d.ts +9 -0
- package/dist/work-queue/index.d.ts +4 -4
- package/dist/work-queue/index.js +2 -2
- package/dist/work-queue/index.js.map +1 -1
- package/package.json +6 -3
- package/dist/chunk-AHW2CLPT.js.map +0 -1
- package/dist/chunk-AIIXV4XB.js.map +0 -1
- package/dist/chunk-FNGZMVIT.js.map +0 -1
- package/dist/chunk-H2ELKHI6.js.map +0 -1
- package/dist/chunk-I7E7AD2S.js.map +0 -1
- package/dist/chunk-JYNYG5SF.js.map +0 -1
- package/dist/chunk-PCJA2HTZ.js.map +0 -1
- package/dist/chunk-YIMOFXST.js.map +0 -1
- package/dist/types-SzNSHKlV.d.ts +0 -5
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as Cmd, c as Sub, M as Machine, R as RunHandlers, P as Port, N as NoCellError, g as Reducer, A as AnyCmdDef, h as Settled, a as CmdOf, i as Transitions, B as BuiltinSub, U as UpdateForm, O as Outcome, j as InterpretDetached, H as HandlerCtx } from './core-
|
|
1
|
+
import { C as Cmd, c as Sub, M as Machine, R as RunHandlers, P as Port, N as NoCellError, g as Reducer, A as AnyCmdDef, h as Settled, a as CmdOf, i as Transitions, B as BuiltinSub, U as UpdateForm, O as Outcome, j as InterpretDetached, H as HandlerCtx } from './core-BKJW1Kmq.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* @demlik/tea runtime interface surface + pure helpers — the public types,
|
|
@@ -12,6 +12,11 @@ import { C as Cmd, c as Sub, M as Machine, R as RunHandlers, P as Port, N as NoC
|
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
14
|
declare const ReducerBrand: unique symbol;
|
|
15
|
+
/**
|
|
16
|
+
* A `Reducer` or `Transitions` value that went through `asReducer` or
|
|
17
|
+
* `defineMachine`. It carries the phantom brand and otherwise behaves exactly
|
|
18
|
+
* like the unbranded value.
|
|
19
|
+
*/
|
|
15
20
|
type Branded<T> = T & {
|
|
16
21
|
readonly [ReducerBrand]: true;
|
|
17
22
|
};
|
|
@@ -38,6 +43,10 @@ type Branded<T> = T & {
|
|
|
38
43
|
* ```
|
|
39
44
|
*/
|
|
40
45
|
declare function absurd(x: never): never;
|
|
46
|
+
/**
|
|
47
|
+
* An update cell that ignores its Msg: it returns the state unchanged, with no
|
|
48
|
+
* Cmds. Use it to say a state deliberately does nothing for a Msg.
|
|
49
|
+
*/
|
|
41
50
|
declare const noop: <S, M, C extends Cmd>(state: S, _msg: M) => readonly [S, readonly C[]];
|
|
42
51
|
/**
|
|
43
52
|
* Thrown by `definePort` when a name has already been registered in the current
|
|
@@ -89,12 +98,14 @@ declare function __resetPortRegistry(): void;
|
|
|
89
98
|
* run stops — on the Effect engine by closing its Scope with the failure. A
|
|
90
99
|
* Sub that expects an error maps it to a Msg itself; there is no hook for it
|
|
91
100
|
* here.
|
|
92
|
-
* - `"discard"` — work lost to a teardown the host asked for.
|
|
93
|
-
*
|
|
94
|
-
* handlers were still awaiting (`RuntimeDiscardedError`),
|
|
95
|
-
* arrived DURING `stop()`'s drain
|
|
96
|
-
*
|
|
97
|
-
* `disposeTimeoutMs` (`
|
|
101
|
+
* - `"discard"` — work lost to a teardown the host asked for. Four witnesses,
|
|
102
|
+
* each carrying a `RuntimeDiscardNotice`: `stop()` was called while interpret
|
|
103
|
+
* handlers were still awaiting (`RuntimeDiscardedError`), a Msg that
|
|
104
|
+
* arrived DURING `stop()`'s drain, or was still queued when `stop()` gave up
|
|
105
|
+
* on it, and so could not be delivered (`DispatchDiscardedError`), a drain
|
|
106
|
+
* that did not finish inside `disposeTimeoutMs` (`DrainTimeoutNotice`), and
|
|
107
|
+
* teardown work that did not settle inside `disposeTimeoutMs`
|
|
108
|
+
* (`DisposeTimeoutNotice`). The one phase that is a
|
|
98
109
|
* LIFECYCLE report rather than a failure: legal, merely lossy.
|
|
99
110
|
* - `"identity-drop"` — the `Identity` filter dropped a message addressed to a
|
|
100
111
|
* different instance (`IdentityDropNotice`). Its own phase rather than
|
|
@@ -228,7 +239,8 @@ declare abstract class RuntimeDiscardNotice extends Error {
|
|
|
228
239
|
/**
|
|
229
240
|
* Reported to the `OnError` sink under `phase: "discard"` when `stop()` is
|
|
230
241
|
* called while `interpret` handlers are still awaiting. The host is dropping
|
|
231
|
-
* its only handle on that work: `stop()` drains the tail,
|
|
242
|
+
* its only handle on that work: `stop()` drains the tail, up to
|
|
243
|
+
* `disposeTimeoutMs`, but the listeners,
|
|
232
244
|
* observers and event handlers that would have consumed the resulting
|
|
233
245
|
* transitions are gone, so the Cmds' results reach nobody.
|
|
234
246
|
*
|
|
@@ -285,12 +297,48 @@ declare class DisposeTimeoutNotice extends RuntimeDiscardNotice {
|
|
|
285
297
|
readonly _tag: "DisposeTimeoutNotice";
|
|
286
298
|
constructor(pendingDisposals: number, timeoutMs: number);
|
|
287
299
|
}
|
|
300
|
+
/**
|
|
301
|
+
* Reported to the `OnError` sink under `phase: "discard"` when `stop()`'s wait
|
|
302
|
+
* for the queue hits `disposeTimeoutMs` (ADR 0025): a Cmd handler, a save or
|
|
303
|
+
* detached work had not returned.
|
|
304
|
+
*
|
|
305
|
+
* `stop()` resolves by contract, so it gives up on that work instead of waiting
|
|
306
|
+
* for it without limit. It then stops the Subs and runs the final save as it
|
|
307
|
+
* always does. The work it gave up on is not recalled — a Promise cannot be
|
|
308
|
+
* cancelled — so a handler may still be running after `stop()` has returned.
|
|
309
|
+
* Whatever it returns later is dropped, and so are the Msgs queued behind it:
|
|
310
|
+
* each dropped Msg is a `DispatchDiscardedError`. The rest of its step's
|
|
311
|
+
* Cmds are skipped: no handler starts for them, and they get no notice of
|
|
312
|
+
* their own. None of it is saved.
|
|
313
|
+
*
|
|
314
|
+
* tea starts no store call after `stop()` has returned. A store call already
|
|
315
|
+
* under way when `stop()` gave up is not cancelled and can finish afterwards;
|
|
316
|
+
* on a plain store that late save can overwrite what a newer run saved, and a
|
|
317
|
+
* fenced store refuses it.
|
|
318
|
+
*
|
|
319
|
+
* `cmdTypes` names the Cmd of each handler call still awaiting, one entry per
|
|
320
|
+
* call. `pendingCmds` counts those plus any detached work, the same count
|
|
321
|
+
* `RuntimeDiscardedError` carries.
|
|
322
|
+
*/
|
|
323
|
+
declare class DrainTimeoutNotice extends RuntimeDiscardNotice {
|
|
324
|
+
readonly cmdTypes: readonly string[];
|
|
325
|
+
readonly pendingCmds: number;
|
|
326
|
+
readonly timeoutMs: number;
|
|
327
|
+
readonly name = "DrainTimeoutNotice";
|
|
328
|
+
readonly _tag: "DrainTimeoutNotice";
|
|
329
|
+
constructor(cmdTypes: readonly string[], pendingCmds: number, timeoutMs: number);
|
|
330
|
+
}
|
|
288
331
|
/**
|
|
289
332
|
* The rejection of a dispatch that arrived DURING `stop()`'s drain — an in-flight
|
|
290
333
|
* interpret handler's follow-up Msg, a detached handler's terminal Msg, or a Sub
|
|
291
334
|
* that is still live because subs are torn down only after the drain. The stop
|
|
292
335
|
* barrier is absolute (the Msg is refused, never folded), so this names the loss.
|
|
293
336
|
*
|
|
337
|
+
* It is also the rejection of the work `stop()` gave up on (see
|
|
338
|
+
* `DrainTimeoutNotice`): a Msg a stuck handler produces after `stop()` has
|
|
339
|
+
* returned, and a Msg that was accepted before `stop()` and was still queued
|
|
340
|
+
* behind that handler.
|
|
341
|
+
*
|
|
294
342
|
* It is the SECOND witness of `RuntimeDiscardedError`'s fact, and it is why the
|
|
295
343
|
* drain window is a distinct runtime state rather than a plain `stopped` flag:
|
|
296
344
|
* a Msg refused inside the window was discarded BY the teardown, while the same
|
|
@@ -313,6 +361,11 @@ declare class DispatchDiscardedError extends RuntimeDiscardNotice {
|
|
|
313
361
|
* telemetry) that should NOT be folded into State. Strengthens invariant 7.
|
|
314
362
|
*/
|
|
315
363
|
declare function definePort<T>(name: string): Port<T>;
|
|
364
|
+
/**
|
|
365
|
+
* Where an engine loads and saves a machine's state. Implement `load`, `save`
|
|
366
|
+
* and `migrate` to persist to your own storage, or use a store an adapter
|
|
367
|
+
* ships.
|
|
368
|
+
*/
|
|
316
369
|
interface Store<S> {
|
|
317
370
|
load(): Promise<unknown>;
|
|
318
371
|
save(state: S): Promise<void>;
|
|
@@ -361,6 +414,10 @@ declare class StoreRefusedError extends Error {
|
|
|
361
414
|
readonly cause?: unknown;
|
|
362
415
|
});
|
|
363
416
|
}
|
|
417
|
+
/**
|
|
418
|
+
* What a fenced store's `loadFenced` returns: the raw saved value and the
|
|
419
|
+
* version it was written at.
|
|
420
|
+
*/
|
|
364
421
|
interface FencedRead {
|
|
365
422
|
/** Raw bytes at the key, the `Store.load` contract unchanged. */
|
|
366
423
|
readonly raw: unknown;
|
|
@@ -429,6 +486,10 @@ declare class StoreConflictError extends Error {
|
|
|
429
486
|
readonly _tag: "store_conflict";
|
|
430
487
|
constructor(expectedVersion: number, actualVersion: number);
|
|
431
488
|
}
|
|
489
|
+
/**
|
|
490
|
+
* The minimal validator shape `schemaMigrate` accepts: an object with
|
|
491
|
+
* `safeParse`. A zod schema satisfies it.
|
|
492
|
+
*/
|
|
432
493
|
interface Schema<S> {
|
|
433
494
|
safeParse(raw: unknown): {
|
|
434
495
|
success: true;
|
|
@@ -447,7 +508,16 @@ interface Schema<S> {
|
|
|
447
508
|
* return a {@link refuse}, so `run` fails instead of booting fresh over them.
|
|
448
509
|
*/
|
|
449
510
|
declare function schemaMigrate<S>(schema: Schema<S>, upcast?: (raw: unknown) => unknown): (raw: unknown) => Migrated<S>;
|
|
511
|
+
/**
|
|
512
|
+
* How long a `dispatch` waits before it resolves: `quiescent`, the default,
|
|
513
|
+
* waits for every follow-up Msg to drain, and `once` waits for the single
|
|
514
|
+
* transition.
|
|
515
|
+
*/
|
|
450
516
|
type DispatchSettle = "quiescent" | "once";
|
|
517
|
+
/**
|
|
518
|
+
* The dispatch-only view of a runtime. Use it as the type of a handle one
|
|
519
|
+
* runtime holds in order to send Msgs to another.
|
|
520
|
+
*/
|
|
451
521
|
interface RuntimeRef<M extends {
|
|
452
522
|
type: string;
|
|
453
523
|
}> {
|
|
@@ -699,6 +769,11 @@ type MachineTypes<S, M extends {
|
|
|
699
769
|
readonly sub?: U;
|
|
700
770
|
readonly ctx?: Ctx;
|
|
701
771
|
};
|
|
772
|
+
/**
|
|
773
|
+
* Define a machine: its `init`, its `update` (a reducer or a transitions
|
|
774
|
+
* table), and optionally its `subs`, `cmds` and `identity`. Every tea program
|
|
775
|
+
* starts here; the result is plain data you hand to an engine's `run`.
|
|
776
|
+
*/
|
|
702
777
|
declare function defineMachine<S, M extends {
|
|
703
778
|
type: string;
|
|
704
779
|
}, D extends AnyCmdDef, U extends Sub = Sub<never>, Ctx = unknown>(m: NoInfer<Omit<Machine<S, M | Settled<D>, CmdOf<D>, U, Ctx>, "cmds">> & {
|
|
@@ -736,14 +811,35 @@ declare function defineMachine<S, M extends {
|
|
|
736
811
|
}, C extends Cmd, U extends Sub, Ctx>(m: Omit<Machine<S, M, C, U, Ctx>, "update"> & {
|
|
737
812
|
update: Reducer<S, M, C>;
|
|
738
813
|
}): Machine<S, M, C, U, Ctx>;
|
|
814
|
+
/**
|
|
815
|
+
* Type-check a standalone reducer record and return it branded. Use it when you
|
|
816
|
+
* write `update` apart from `defineMachine`.
|
|
817
|
+
*/
|
|
739
818
|
declare function asReducer<S, M extends {
|
|
740
819
|
type: string;
|
|
741
820
|
}, C extends Cmd>(reducer: Reducer<S, M, C>): Branded<Reducer<S, M, C>>;
|
|
821
|
+
/**
|
|
822
|
+
* The `ctx` field of an engine's options: optional when the machine's `Ctx` is
|
|
823
|
+
* empty, required otherwise.
|
|
824
|
+
*/
|
|
742
825
|
type CtxArg<Ctx> = [Record<never, never>] extends [Ctx] ? {
|
|
743
826
|
ctx?: Ctx;
|
|
744
827
|
} : {
|
|
745
828
|
ctx: Ctx;
|
|
746
829
|
};
|
|
830
|
+
/**
|
|
831
|
+
* Run a machine's `init` and then its `update` over a list of Msgs, with no
|
|
832
|
+
* engine, store or effects. Use it in unit tests to assert the final state, the
|
|
833
|
+
* Cmds emitted, and the Subs that would be running.
|
|
834
|
+
*
|
|
835
|
+
* It composes `init(loaded ?? null, ctx)` and then `update(state, msg)` for each
|
|
836
|
+
* Msg. No Cmd handler is called, no `Store` is touched and no Sub is started.
|
|
837
|
+
*
|
|
838
|
+
* `subs` is each `machine.subs` entry that is on at the final state, as its
|
|
839
|
+
* runner would see it: `{ id, type, deps }`, the id derived exactly as the
|
|
840
|
+
* engine derives it, deduplicated by id the way the engine runs them. So a test
|
|
841
|
+
* asserts "the retry timer is armed in `waiting`" without wiring a runner.
|
|
842
|
+
*/
|
|
747
843
|
declare function replay<S, M extends {
|
|
748
844
|
type: string;
|
|
749
845
|
}, C extends Cmd, U extends Sub, Ctx>(machine: Machine<S, M, C, U, Ctx>, opts: {
|
|
@@ -755,6 +851,11 @@ declare function replay<S, M extends {
|
|
|
755
851
|
cmds: C[];
|
|
756
852
|
subs: (U | BuiltinSub<M>)[];
|
|
757
853
|
};
|
|
854
|
+
/**
|
|
855
|
+
* Adapt an `InterpretDetached` handler into an ordinary `interpret` cell. Use
|
|
856
|
+
* it for a Cmd whose work finishes after the handler returns and reports back
|
|
857
|
+
* through `dispatch`.
|
|
858
|
+
*/
|
|
758
859
|
declare function wrapDetached<C extends Cmd, M extends {
|
|
759
860
|
type: string;
|
|
760
861
|
}, Allowed extends M, Ctx>(handler: InterpretDetached<C, Allowed, Ctx>): (cmd: C, ctx: HandlerCtx<Ctx>, dispatch?: (msg: M) => void) => Promise<void>;
|
|
@@ -810,6 +911,16 @@ declare function tryFoldMsgs<S, M extends {
|
|
|
810
911
|
update: object;
|
|
811
912
|
__form?: UpdateForm;
|
|
812
913
|
}, base: S, msgs: readonly M[]): Outcome<S, FoldRefusal<M>>;
|
|
914
|
+
/**
|
|
915
|
+
* Wrap a function that may throw into a Cmd handler that never rejects: success
|
|
916
|
+
* maps to one Msg through `onOk`, failure to another through `onErr`. Use it
|
|
917
|
+
* for a hand-written Cmd; a `Cmd.define`d Cmd does not need it, because its
|
|
918
|
+
* handler returns an `Outcome` and the engine mints the Msg (ADR 0021).
|
|
919
|
+
*
|
|
920
|
+
* A rejection and a synchronous throw both reach `onErr(error, cmd)`, with the
|
|
921
|
+
* original error untouched so `instanceof` checks inside `onErr` hold. The
|
|
922
|
+
* never-rejects promise assumes `onOk` and `onErr` do not throw.
|
|
923
|
+
*/
|
|
813
924
|
declare function tryInterpret<C extends Cmd, Ok, M, Ctx>(work: (cmd: C, ctx: Ctx) => Promise<Ok>, onOk: (value: Ok, cmd: C) => M, onErr: (error: unknown, cmd: C) => M): (cmd: C, ctx: Ctx) => Promise<M>;
|
|
814
925
|
|
|
815
|
-
export {
|
|
926
|
+
export { asReducer as A, type BootingRuntime as B, type CtxArg as C, type DeletableStore as D, type EngineRun as E, type FencedStore as F, defineMachine as G, definePort as H, IdentityDropNotice as I, isFencedStore as J, noop as K, refuse as L, type Migrated as M, replay as N, type OnError as O, PortNameCollisionError as P, QuiescenceTimeoutError as Q, type Runtime as R, type Store as S, type TelemetrySink as T, schemaMigrate as U, tryApplyCell as V, tryFoldMsgs as W, tryInterpret as X, wrapDetached as Y, __resetPortRegistry as _, type Supervision as a, type BootedRunHandle as b, type DispatchSettle as c, type RunHandle as d, type Branded as e, DispatchDiscardedError as f, DisposeTimeoutNotice as g, DrainTimeoutNotice as h, DriveFailedError as i, DriveStalledError as j, type FencedRead as k, type FoldRefusal as l, type MachineTypes as m, Refusal as n, type RunOptions as o, RuntimeDiscardNotice as p, RuntimeDiscardedError as q, type RuntimeErrorContext as r, type RuntimeErrorPhase as s, type RuntimeRef as t, type Schema as u, StoreConflictError as v, StoreRefusedError as w, type SupervisionStrategy as x, type TelemetryEvent as y, absurd as z };
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { D as DriveRoundsExceededError, a as DriveNoHandlerError, b as DriveOptions, c as DriveResult } from '../../drive-loop-
|
|
2
|
-
export { d as DEFAULT_MAX_ROUNDS, e as DriveCtxArg, f as DriveTraceEntry, g as driveTraceOf } from '../../drive-loop-
|
|
1
|
+
import { D as DriveRoundsExceededError, a as DriveNoHandlerError, b as DriveOptions, c as DriveResult } from '../../drive-loop-Dc6Z8Vbs.js';
|
|
2
|
+
export { d as DEFAULT_MAX_ROUNDS, e as DriveCtxArg, f as DriveTraceEntry, g as driveTraceOf } from '../../drive-loop-Dc6Z8Vbs.js';
|
|
3
3
|
import { Effect } from 'effect';
|
|
4
|
-
import { C as CellErrors, S as SubscribeOption, E as EffectInterpret, a as EffectSubscribe, I as InterpretServices, b as SubscribeServices } from '../../
|
|
5
|
-
import { C as Cmd, c as Sub, M as Machine } from '../../core-
|
|
6
|
-
import '../../runtime-types-
|
|
4
|
+
import { C as CellErrors, S as SubscribeOption, E as EffectInterpret, a as EffectSubscribe, I as InterpretServices, b as SubscribeServices } from '../../run-D0sxbyno.js';
|
|
5
|
+
import { C as Cmd, c as Sub, M as Machine } from '../../core-BKJW1Kmq.js';
|
|
6
|
+
import '../../runtime-types-BPKp2bGo.js';
|
|
7
7
|
import 'effect/Cause';
|
|
8
8
|
import 'effect/Types';
|
|
9
9
|
import '@standard-schema/spec';
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { CellFailure, builtinRunners, cellResult, settleCellExit } from '../../chunk-
|
|
2
|
-
import { driveLoop, DEFAULT_MAX_ROUNDS, driveContractOf, DriveRoundsExceededError, DriveNoHandlerError, annotateTrace, driveTraceOf, desiredSubs } from '../../chunk-
|
|
3
|
-
export { DEFAULT_MAX_ROUNDS, DriveNoHandlerError, DriveRoundsExceededError, driveTraceOf } from '../../chunk-
|
|
4
|
-
import '../../chunk-
|
|
5
|
-
import '../../chunk-
|
|
6
|
-
import '../../chunk-
|
|
7
|
-
import '../../chunk-
|
|
8
|
-
import '../../chunk-
|
|
1
|
+
import { CellFailure, builtinRunners, cellResult, settleCellExit } from '../../chunk-HU3Y2AZY.js';
|
|
2
|
+
import { driveLoop, DEFAULT_MAX_ROUNDS, driveContractOf, DriveRoundsExceededError, DriveNoHandlerError, annotateTrace, driveTraceOf, desiredSubs } from '../../chunk-BFSZ4L6Y.js';
|
|
3
|
+
export { DEFAULT_MAX_ROUNDS, DriveNoHandlerError, DriveRoundsExceededError, driveTraceOf } from '../../chunk-BFSZ4L6Y.js';
|
|
4
|
+
import '../../chunk-7Z2IDZ7R.js';
|
|
5
|
+
import '../../chunk-VM7PMFV5.js';
|
|
6
|
+
import '../../chunk-Z7IL735U.js';
|
|
7
|
+
import '../../chunk-VHKDUBXC.js';
|
|
8
|
+
import '../../chunk-GAVLND5C.js';
|
|
9
9
|
import { Effect, Stream, Exit, Cause, Fiber } from 'effect';
|
|
10
10
|
|
|
11
11
|
var DriveInterrupted = class {
|
package/dist/testing/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { C as Cmd, c as Sub, M as Machine, B as BuiltinSub } from '../core-
|
|
2
|
-
import { R as Runtime } from '../runtime-types-
|
|
1
|
+
import { C as Cmd, c as Sub, M as Machine, B as BuiltinSub } from '../core-BKJW1Kmq.js';
|
|
2
|
+
import { R as Runtime } from '../runtime-types-BPKp2bGo.js';
|
|
3
3
|
import '@standard-schema/spec';
|
|
4
4
|
|
|
5
5
|
/**
|
package/dist/testing/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export { bindMachine } from '../chunk-
|
|
2
|
-
import '../chunk-
|
|
3
|
-
import { replay } from '../chunk-
|
|
1
|
+
export { bindMachine } from '../chunk-7Z2IDZ7R.js';
|
|
2
|
+
import '../chunk-VHKDUBXC.js';
|
|
3
|
+
import { replay } from '../chunk-GAVLND5C.js';
|
|
4
4
|
import { expect, vi } from 'vitest';
|
|
5
5
|
|
|
6
6
|
function expectFinalState(machine, opts, expected) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { b as DriveOptions, c as DriveResult } from '../../drive-loop-
|
|
2
|
-
export { d as DEFAULT_MAX_ROUNDS, e as DriveCtxArg, a as DriveNoHandlerError, D as DriveRoundsExceededError, f as DriveTraceEntry, g as driveTraceOf } from '../../drive-loop-
|
|
3
|
-
import { C as Cmd, c as Sub, M as Machine, I as Interpret } from '../../core-
|
|
4
|
-
import '../../runtime-types-
|
|
1
|
+
import { b as DriveOptions, c as DriveResult } from '../../drive-loop-Dc6Z8Vbs.js';
|
|
2
|
+
export { d as DEFAULT_MAX_ROUNDS, e as DriveCtxArg, a as DriveNoHandlerError, D as DriveRoundsExceededError, f as DriveTraceEntry, g as driveTraceOf } from '../../drive-loop-Dc6Z8Vbs.js';
|
|
3
|
+
import { C as Cmd, c as Sub, M as Machine, I as Interpret } from '../../core-BKJW1Kmq.js';
|
|
4
|
+
import '../../runtime-types-BPKp2bGo.js';
|
|
5
5
|
import '@standard-schema/spec';
|
|
6
6
|
|
|
7
7
|
/**
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { driveContractOf, driveLoop, DEFAULT_MAX_ROUNDS } from '../../chunk-
|
|
2
|
-
export { DEFAULT_MAX_ROUNDS, DriveNoHandlerError, DriveRoundsExceededError, driveTraceOf } from '../../chunk-
|
|
3
|
-
import '../../chunk-
|
|
4
|
-
import '../../chunk-
|
|
5
|
-
import { cmdEdge, Outcome } from '../../chunk-
|
|
1
|
+
import { driveContractOf, driveLoop, DEFAULT_MAX_ROUNDS } from '../../chunk-BFSZ4L6Y.js';
|
|
2
|
+
export { DEFAULT_MAX_ROUNDS, DriveNoHandlerError, DriveRoundsExceededError, driveTraceOf } from '../../chunk-BFSZ4L6Y.js';
|
|
3
|
+
import '../../chunk-7Z2IDZ7R.js';
|
|
4
|
+
import '../../chunk-VHKDUBXC.js';
|
|
5
|
+
import { cmdEdge, Outcome } from '../../chunk-GAVLND5C.js';
|
|
6
6
|
|
|
7
7
|
// src/testing/promise/drive.ts
|
|
8
8
|
async function drive(machine, initial, msg, handlers, ...[opts]) {
|
package/dist/timing/index.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
export { D as Debounced, d as debounce } from '../index-DHSUmQTR.js';
|
|
2
|
-
import { C as Cmd } from '../core-
|
|
3
|
-
import { T as TtlCache, a as DeadlineSub } from '../index-
|
|
4
|
-
export { D as ThrottledInputSettled, s as subscribeThrottledInput, d as throttledInputSettled } from '../index-
|
|
2
|
+
import { C as Cmd } from '../core-BKJW1Kmq.js';
|
|
3
|
+
import { T as TtlCache, a as DeadlineSub } from '../index-Diyo8WBO.js';
|
|
4
|
+
export { D as ThrottledInputSettled, s as subscribeThrottledInput, d as throttledInputSettled } from '../index-Diyo8WBO.js';
|
|
5
5
|
import '@standard-schema/spec';
|
|
6
|
-
import '../types-
|
|
6
|
+
import '../types-BiXj7k_k.js';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* internal/timing/throttle — a timer-based call transformer that caps invocation
|
package/dist/timing/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
export { debounce } from '../chunk-LFZUK6J2.js';
|
|
2
|
-
import { deadlineSub, initCache, get, set } from '../chunk-
|
|
3
|
-
export { subscribeDeadline as subscribeThrottledInput, deadlineExceeded as throttledInputSettled } from '../chunk-
|
|
4
|
-
import '../chunk-
|
|
5
|
-
import '../chunk-
|
|
2
|
+
import { deadlineSub, initCache, get, set } from '../chunk-QIE4Y6BK.js';
|
|
3
|
+
export { subscribeDeadline as subscribeThrottledInput, deadlineExceeded as throttledInputSettled } from '../chunk-QIE4Y6BK.js';
|
|
4
|
+
import '../chunk-VHKDUBXC.js';
|
|
5
|
+
import '../chunk-GAVLND5C.js';
|
|
6
6
|
|
|
7
7
|
// src/internal/timing/throttle/index.ts
|
|
8
8
|
function throttle(fn, ms, opts) {
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { c as Sub, D as Dispose } from './core-BKJW1Kmq.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* A Sub runner: given the Sub, the `ctx` and a `dispatch`, it opens the
|
|
5
|
+
* resource and returns a `Dispose`. Every `from*` factory returns one.
|
|
6
|
+
*/
|
|
7
|
+
type SubscribeHandler<S extends Sub, M, Ctx> = (sub: S, ctx: Ctx, dispatch: (msg: M) => void) => Dispose;
|
|
8
|
+
|
|
9
|
+
export type { SubscribeHandler as S };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { Q as QueueItem } from '../index-
|
|
2
|
-
export { E as EnqueueInput, a as QueueItemStatus, c as createQueue } from '../index-
|
|
3
|
-
import '../runtime-types-
|
|
4
|
-
import '../core-
|
|
1
|
+
import { Q as QueueItem } from '../index-Cuy1_xTh.js';
|
|
2
|
+
export { E as EnqueueInput, a as QueueItemStatus, c as createQueue } from '../index-Cuy1_xTh.js';
|
|
3
|
+
import '../runtime-types-BPKp2bGo.js';
|
|
4
|
+
import '../core-BKJW1Kmq.js';
|
|
5
5
|
import '@standard-schema/spec';
|
|
6
6
|
|
|
7
7
|
/**
|
package/dist/work-queue/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { enqueueOp, claimNextOp, markDoneOp, patchItemOp, resetRunningOp, removeOp } from '../chunk-TXN2KFHF.js';
|
|
2
2
|
export { claimNextOp, enqueueOp, markDoneOp, patchItemOp, queueAdapter, removeOp, resetRunningOp } from '../chunk-TXN2KFHF.js';
|
|
3
|
-
import { restore } from '../chunk-
|
|
4
|
-
import '../chunk-
|
|
3
|
+
import { restore } from '../chunk-Z7IL735U.js';
|
|
4
|
+
import '../chunk-GAVLND5C.js';
|
|
5
5
|
|
|
6
6
|
// src/internal/work-queue/index.ts
|
|
7
7
|
function genId() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/internal/work-queue/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * internal/work-queue — substrate-agnostic work-queue lifecycle on `Store<S>`.\n *\n * Two public surfaces, one shape:\n * - `createQueue(store)` (this file) is the in-process adapter — it binds the\n * pure ops to an injected `Store` and runs `load → mutate → save`.\n * - `internal/work-queue/ops` (`./ops`) is the BLESSED, importable surface\n * of those same pure ops. L2 compositions that own their own Model slice\n * (`monitored-run`, `idempotent-intake`, …) import the ops directly and\n * delegate status flips to them instead of re-rolling the transitions.\n * Both routes call the identical ops, so the lifecycle rules live in exactly\n * one place. This mirrors `@demlik/tea/do`'s one-shape-per-package rule.\n *\n * The package is generic in the input payload `I` (audit-specific fields go\n * here in the extension host). `output` is a free-form side-channel correlation\n * token (a backend id, URL, trace id) — typed as `string` because that's its\n * only honest type. Consumers that need structured per-item data persist it in\n * their own store and put the foreign-key string in `output`.\n */\n\nimport type { Store } from \"../../index\";\nimport { restore } from \"../engine/restore\";\nimport {\n claimNextOp,\n enqueueOp,\n markDoneOp,\n patchItemOp,\n removeOp,\n resetRunningOp,\n} from \"./ops\";\n\n/**\n * Generate a queue-item id at the adapter boundary. Reads `Date.now()` and\n * `Math.random()` — impure helpers belong in the adapter (`index.ts`),\n * never in `ops.ts` (which is purely-functional by contract). Uses native\n * UUID when available, falls back to timestamp + random for environments\n * without `crypto.randomUUID`.\n */\nfunction genId(): string {\n return (\n globalThis.crypto?.randomUUID?.() ??\n `q_${Date.now()}_${Math.random().toString(36).slice(2)}`\n );\n}\n\nexport type QueueItemStatus =\n | \"pending\"\n | \"running\"\n | \"done\"\n | \"failed\"\n | \"cancelled\";\n\n/**\n * A single queue entry. Every field is `readonly`: a persisted slice is\n * immutable, so a transition returns a NEW item (the ops always spread —\n * `{ ...item, status: … }`) rather than mutating in place. This type-enforces\n * the durability invariant the consumers already honor by convention, and\n * keeps a slice round-trippable through JSON unchanged across a reload.\n */\nexport interface QueueItem<I> {\n readonly id: string;\n readonly status: QueueItemStatus;\n readonly input: I;\n readonly enqueuedAt: number;\n readonly startedAt?: number;\n readonly finishedAt?: number;\n readonly output?: string;\n readonly error?: string;\n}\n\n/**\n * Caller-facing enqueue payload. Just `I` today — kept named so future\n * variants (priority, deferUntil, …) can grow without breaking callers.\n */\nexport type EnqueueInput<I> = I;\n\n/**\n * Adapter that binds the pure ops to an injected `Store<QueueItem<I>[]>`.\n *\n * `load → mutate → save` is the only durability discipline this package\n * imposes. The store decides what \"save\" means (chrome.storage, KV, DO\n * storage, in-memory) — that decision belongs at the caller.\n *\n * Ops that don't change the queue (e.g. `markDone` on an unknown id) skip the\n * save call so the underlying store doesn't observe a write churn.\n */\nexport function createQueue<I>(store: Store<QueueItem<I>[]>) {\n // `Store<S>.load()` returns `unknown` (invariant 8 boundary). Route\n // through `store.migrate(raw)` to get the typed value before any\n // queue operation reads it — the same `restore` the substrate's `run()` uses\n // at boot, so a queue it cannot read throws `StoreRefusedError` and no op\n // saves over it. The work queue is a substrate-agnostic primitive on top of\n // `Store<S>`, so it honors the same contract.\n function loadParsed(): Promise<QueueItem<I>[] | null> {\n return restore(store);\n }\n\n async function list(): Promise<QueueItem<I>[]> {\n return (await loadParsed()) ?? [];\n }\n\n async function enqueue(input: EnqueueInput<I>): Promise<QueueItem<I>> {\n const queue = await list();\n const { next, item } = enqueueOp<I>(queue, input, Date.now(), genId());\n await store.save(next);\n return item;\n }\n\n async function claimNext(): Promise<QueueItem<I> | null> {\n const queue = await list();\n const result = claimNextOp<I>(queue, Date.now());\n if (!result) return null;\n await store.save(result.next);\n return result.claimed;\n }\n\n // `markDone` ignores the optional second arg by design: completed runs leave\n // the queue, and the consumer is expected to persist any output (auditId,\n // etc.) wherever those completed records belong. Kept in the signature for\n // call-site readability and forward-compat with `bindOutput`.\n async function markDone(id: string): Promise<void> {\n const queue = await list();\n const { next, changed } = markDoneOp<I>(queue, id);\n if (changed) await store.save(next);\n }\n\n async function markFailed(id: string, error: string): Promise<void> {\n const queue = await list();\n const { next, changed } = patchItemOp<I>(queue, id, (item) => ({\n ...item,\n status: \"failed\",\n finishedAt: Date.now(),\n error,\n }));\n if (changed) await store.save(next);\n }\n\n async function markCancelled(id: string): Promise<void> {\n const queue = await list();\n const { next, changed } = patchItemOp<I>(queue, id, (item) => ({\n ...item,\n status: \"cancelled\",\n finishedAt: Date.now(),\n }));\n if (changed) await store.save(next);\n }\n\n async function resetRunningToPending(): Promise<void> {\n const queue = await list();\n const { next, changed } = resetRunningOp<I>(queue);\n if (changed) await store.save(next);\n }\n\n async function removeItem(id: string): Promise<void> {\n const queue = await list();\n const { next, changed } = removeOp<I>(queue, id);\n if (changed) await store.save(next);\n }\n\n async function retryItem(id: string): Promise<void> {\n const queue = await list();\n const { next, changed } = patchItemOp<I>(queue, id, (item) => ({\n ...item,\n status: \"pending\",\n startedAt: undefined,\n finishedAt: undefined,\n error: undefined,\n output: undefined,\n }));\n if (changed) await store.save(next);\n }\n\n // `bindOutput` attaches a side-channel correlation token (string) to a\n // running item without changing its status. The queue can't reach into\n // `I` to mutate it (the substrate is domain-agnostic), so callers that\n // need to thread a backend id / URL / trace id through the lifecycle\n // route it here. Consumers needing structured payloads should persist\n // them in their own store and put the foreign-key string in `output`.\n async function bindOutput(id: string, value: string): Promise<void> {\n const queue = await list();\n const { next, changed } = patchItemOp<I>(queue, id, (item) => ({\n ...item,\n output: value,\n }));\n if (changed) await store.save(next);\n }\n\n return {\n enqueue,\n claimNext,\n markDone,\n markFailed,\n markCancelled,\n resetRunningToPending,\n removeItem,\n retryItem,\n bindOutput,\n list,\n };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/internal/work-queue/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * internal/work-queue — substrate-agnostic work-queue lifecycle on `Store<S>`.\n *\n * Two public surfaces, one shape:\n * - `createQueue(store)` (this file) is the in-process adapter — it binds the\n * pure ops to an injected `Store` and runs `load → mutate → save`.\n * - `internal/work-queue/ops` (`./ops`) is the BLESSED, importable surface\n * of those same pure ops. L2 compositions that own their own Model slice\n * (`monitored-run`, `idempotent-intake`, …) import the ops directly and\n * delegate status flips to them instead of re-rolling the transitions.\n * Both routes call the identical ops, so the lifecycle rules live in exactly\n * one place. This mirrors `@demlik/tea/do`'s one-shape-per-package rule.\n *\n * The package is generic in the input payload `I` (audit-specific fields go\n * here in the extension host). `output` is a free-form side-channel correlation\n * token (a backend id, URL, trace id) — typed as `string` because that's its\n * only honest type. Consumers that need structured per-item data persist it in\n * their own store and put the foreign-key string in `output`.\n */\n\nimport type { Store } from \"../../index\";\nimport { restore } from \"../engine/restore\";\nimport {\n claimNextOp,\n enqueueOp,\n markDoneOp,\n patchItemOp,\n removeOp,\n resetRunningOp,\n} from \"./ops\";\n\n/**\n * Generate a queue-item id at the adapter boundary. Reads `Date.now()` and\n * `Math.random()` — impure helpers belong in the adapter (`index.ts`),\n * never in `ops.ts` (which is purely-functional by contract). Uses native\n * UUID when available, falls back to timestamp + random for environments\n * without `crypto.randomUUID`.\n */\nfunction genId(): string {\n return (\n globalThis.crypto?.randomUUID?.() ??\n `q_${Date.now()}_${Math.random().toString(36).slice(2)}`\n );\n}\n\n/**\n * Where a queue item is in its lifecycle: `pending`, `running`, `done`,\n * `failed` or `cancelled`.\n */\nexport type QueueItemStatus =\n | \"pending\"\n | \"running\"\n | \"done\"\n | \"failed\"\n | \"cancelled\";\n\n/**\n * A single queue entry. Every field is `readonly`: a persisted slice is\n * immutable, so a transition returns a NEW item (the ops always spread —\n * `{ ...item, status: … }`) rather than mutating in place. This type-enforces\n * the durability invariant the consumers already honor by convention, and\n * keeps a slice round-trippable through JSON unchanged across a reload.\n */\nexport interface QueueItem<I> {\n readonly id: string;\n readonly status: QueueItemStatus;\n readonly input: I;\n readonly enqueuedAt: number;\n readonly startedAt?: number;\n readonly finishedAt?: number;\n readonly output?: string;\n readonly error?: string;\n}\n\n/**\n * Caller-facing enqueue payload. Just `I` today — kept named so future\n * variants (priority, deferUntil, …) can grow without breaking callers.\n */\nexport type EnqueueInput<I> = I;\n\n/**\n * Adapter that binds the pure ops to an injected `Store<QueueItem<I>[]>`.\n *\n * `load → mutate → save` is the only durability discipline this package\n * imposes. The store decides what \"save\" means (chrome.storage, KV, DO\n * storage, in-memory) — that decision belongs at the caller.\n *\n * Ops that don't change the queue (e.g. `markDone` on an unknown id) skip the\n * save call so the underlying store doesn't observe a write churn.\n */\nexport function createQueue<I>(store: Store<QueueItem<I>[]>) {\n // `Store<S>.load()` returns `unknown` (invariant 8 boundary). Route\n // through `store.migrate(raw)` to get the typed value before any\n // queue operation reads it — the same `restore` the substrate's `run()` uses\n // at boot, so a queue it cannot read throws `StoreRefusedError` and no op\n // saves over it. The work queue is a substrate-agnostic primitive on top of\n // `Store<S>`, so it honors the same contract.\n function loadParsed(): Promise<QueueItem<I>[] | null> {\n return restore(store);\n }\n\n async function list(): Promise<QueueItem<I>[]> {\n return (await loadParsed()) ?? [];\n }\n\n async function enqueue(input: EnqueueInput<I>): Promise<QueueItem<I>> {\n const queue = await list();\n const { next, item } = enqueueOp<I>(queue, input, Date.now(), genId());\n await store.save(next);\n return item;\n }\n\n async function claimNext(): Promise<QueueItem<I> | null> {\n const queue = await list();\n const result = claimNextOp<I>(queue, Date.now());\n if (!result) return null;\n await store.save(result.next);\n return result.claimed;\n }\n\n // `markDone` ignores the optional second arg by design: completed runs leave\n // the queue, and the consumer is expected to persist any output (auditId,\n // etc.) wherever those completed records belong. Kept in the signature for\n // call-site readability and forward-compat with `bindOutput`.\n async function markDone(id: string): Promise<void> {\n const queue = await list();\n const { next, changed } = markDoneOp<I>(queue, id);\n if (changed) await store.save(next);\n }\n\n async function markFailed(id: string, error: string): Promise<void> {\n const queue = await list();\n const { next, changed } = patchItemOp<I>(queue, id, (item) => ({\n ...item,\n status: \"failed\",\n finishedAt: Date.now(),\n error,\n }));\n if (changed) await store.save(next);\n }\n\n async function markCancelled(id: string): Promise<void> {\n const queue = await list();\n const { next, changed } = patchItemOp<I>(queue, id, (item) => ({\n ...item,\n status: \"cancelled\",\n finishedAt: Date.now(),\n }));\n if (changed) await store.save(next);\n }\n\n async function resetRunningToPending(): Promise<void> {\n const queue = await list();\n const { next, changed } = resetRunningOp<I>(queue);\n if (changed) await store.save(next);\n }\n\n async function removeItem(id: string): Promise<void> {\n const queue = await list();\n const { next, changed } = removeOp<I>(queue, id);\n if (changed) await store.save(next);\n }\n\n async function retryItem(id: string): Promise<void> {\n const queue = await list();\n const { next, changed } = patchItemOp<I>(queue, id, (item) => ({\n ...item,\n status: \"pending\",\n startedAt: undefined,\n finishedAt: undefined,\n error: undefined,\n output: undefined,\n }));\n if (changed) await store.save(next);\n }\n\n // `bindOutput` attaches a side-channel correlation token (string) to a\n // running item without changing its status. The queue can't reach into\n // `I` to mutate it (the substrate is domain-agnostic), so callers that\n // need to thread a backend id / URL / trace id through the lifecycle\n // route it here. Consumers needing structured payloads should persist\n // them in their own store and put the foreign-key string in `output`.\n async function bindOutput(id: string, value: string): Promise<void> {\n const queue = await list();\n const { next, changed } = patchItemOp<I>(queue, id, (item) => ({\n ...item,\n output: value,\n }));\n if (changed) await store.save(next);\n }\n\n return {\n enqueue,\n claimNext,\n markDone,\n markFailed,\n markCancelled,\n resetRunningToPending,\n removeItem,\n retryItem,\n bindOutput,\n list,\n };\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@demlik/tea",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.21.0",
|
|
4
4
|
"description": "TEA-faithful state machine substrate — one package, every host adapter. Core + subs + testing, plus React, Durable Object, Chrome extension, Node, in-memory, devtools, and property-testing modules as subpaths.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"tea",
|
|
@@ -193,7 +193,8 @@
|
|
|
193
193
|
"vite": "^8.2.1",
|
|
194
194
|
"vitest": "~5.0.1",
|
|
195
195
|
"ws": "^8.21.0",
|
|
196
|
-
"zod": "^4.5.4"
|
|
196
|
+
"zod": "^4.5.4",
|
|
197
|
+
"@demlik/code-graph": "0.8.0"
|
|
197
198
|
},
|
|
198
199
|
"publishConfig": {
|
|
199
200
|
"access": "public"
|
|
@@ -211,7 +212,9 @@
|
|
|
211
212
|
"typecheck:test": "tsc --noEmit -p tsconfig.test.json",
|
|
212
213
|
"typecheck:consumers": "tsc -p tsconfig.consumers.json",
|
|
213
214
|
"docs:reference": "TEA_DOCS_WRITE=1 vitest run src/docs/reference/generate-reference.test.ts",
|
|
214
|
-
"docs:reference:
|
|
215
|
+
"docs:reference:strays": "vitest run src/docs/reference/generate-reference.test.ts -t 'holds nothing the generator does not write'",
|
|
216
|
+
"api:ratchet": "node scripts/api-ratchet.mjs",
|
|
217
|
+
"docs:reference:check": "pnpm run docs:reference:strays && pnpm run docs:reference && git diff --exit-code -- docs/reference",
|
|
215
218
|
"verify:exports": "node scripts/verify-exports.mjs",
|
|
216
219
|
"verify-optional-peer-install": "node scripts/verify-optional-peer-install.mjs"
|
|
217
220
|
}
|