@demlik/tea 0.1.0 → 0.1.2
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/LICENSE +21 -0
- package/dist/agent/index.d.ts +907 -0
- package/dist/agent/index.js +20 -0
- package/dist/agent/index.js.map +1 -0
- package/dist/authed-call/index.d.ts +119 -0
- package/dist/authed-call/index.js +148 -0
- package/dist/authed-call/index.js.map +1 -0
- package/dist/await-terminal/index.d.ts +99 -0
- package/dist/await-terminal/index.js +75 -0
- package/dist/await-terminal/index.js.map +1 -0
- package/dist/batch-window/index.d.ts +259 -0
- package/dist/batch-window/index.js +43 -0
- package/dist/batch-window/index.js.map +1 -0
- package/dist/cache/index.d.ts +2 -2
- package/dist/cache/index.js +2 -50
- package/dist/cache/index.js.map +1 -1
- package/dist/chunk-27N2SPTN.js +222 -0
- package/dist/chunk-27N2SPTN.js.map +1 -0
- package/dist/chunk-2YOE5PIS.js +45 -0
- package/dist/chunk-2YOE5PIS.js.map +1 -0
- package/dist/chunk-3545BOYL.js +65 -0
- package/dist/chunk-3545BOYL.js.map +1 -0
- package/dist/chunk-3XJWC7VW.js +61 -0
- package/dist/chunk-3XJWC7VW.js.map +1 -0
- package/dist/chunk-5DEQ5I3U.js +132 -0
- package/dist/chunk-5DEQ5I3U.js.map +1 -0
- package/dist/chunk-5VNWZADP.js +49 -0
- package/dist/chunk-5VNWZADP.js.map +1 -0
- package/dist/chunk-6RGBKODV.js +268 -0
- package/dist/chunk-6RGBKODV.js.map +1 -0
- package/dist/{chunk-ZRUST6BK.js → chunk-7FYQGDMF.js} +2 -2
- package/dist/chunk-7FYQGDMF.js.map +1 -0
- package/dist/chunk-7W4LMPUW.js +186 -0
- package/dist/chunk-7W4LMPUW.js.map +1 -0
- package/dist/chunk-BYQUGDD3.js +16 -0
- package/dist/chunk-BYQUGDD3.js.map +1 -0
- package/dist/{chunk-PYBQREFU.js → chunk-DILMKOZ7.js} +22 -26
- package/dist/chunk-DILMKOZ7.js.map +1 -0
- package/dist/chunk-EHIX7NYZ.js +93 -0
- package/dist/chunk-EHIX7NYZ.js.map +1 -0
- package/dist/chunk-HCEVHFJ7.js +54 -0
- package/dist/chunk-HCEVHFJ7.js.map +1 -0
- package/dist/chunk-HJO6VNQI.js +15 -0
- package/dist/chunk-HJO6VNQI.js.map +1 -0
- package/dist/chunk-IN33Q4VJ.js +52 -0
- package/dist/chunk-IN33Q4VJ.js.map +1 -0
- package/dist/chunk-J6527VRQ.js +56 -0
- package/dist/chunk-J6527VRQ.js.map +1 -0
- package/dist/chunk-JELSZN25.js +47 -0
- package/dist/chunk-JELSZN25.js.map +1 -0
- package/dist/chunk-K575PT4S.js +58 -0
- package/dist/chunk-K575PT4S.js.map +1 -0
- package/dist/chunk-K7Q23EQ4.js +20 -0
- package/dist/chunk-K7Q23EQ4.js.map +1 -0
- package/dist/chunk-LEC4U6CX.js +91 -0
- package/dist/chunk-LEC4U6CX.js.map +1 -0
- package/dist/{chunk-PYOCUBQJ.js → chunk-LP7VQBRG.js} +22 -15
- package/dist/chunk-LP7VQBRG.js.map +1 -0
- package/dist/{chunk-CMG2KMWX.js → chunk-MMH7CW5K.js} +220 -189
- package/dist/chunk-MMH7CW5K.js.map +1 -0
- package/dist/{chunk-Y5JM3UUH.js → chunk-NSDFA6M6.js} +75 -3
- package/dist/chunk-NSDFA6M6.js.map +1 -0
- package/dist/chunk-ON24RKSE.js +60 -0
- package/dist/chunk-ON24RKSE.js.map +1 -0
- package/dist/chunk-PS23H6KQ.js +87 -0
- package/dist/chunk-PS23H6KQ.js.map +1 -0
- package/dist/chunk-QLA76GIT.js +162 -0
- package/dist/chunk-QLA76GIT.js.map +1 -0
- package/dist/chunk-S3FQN4SL.js +506 -0
- package/dist/chunk-S3FQN4SL.js.map +1 -0
- package/dist/chunk-SC3FAFZN.js +53 -0
- package/dist/chunk-SC3FAFZN.js.map +1 -0
- package/dist/chunk-SINXE47Y.js +55 -0
- package/dist/chunk-SINXE47Y.js.map +1 -0
- package/dist/chunk-SQTCS44W.js +33 -0
- package/dist/chunk-SQTCS44W.js.map +1 -0
- package/dist/chunk-TGG26XMK.js +52 -0
- package/dist/chunk-TGG26XMK.js.map +1 -0
- package/dist/chunk-UV6UWGEO.js +147 -0
- package/dist/chunk-UV6UWGEO.js.map +1 -0
- package/dist/chunk-UYWUVEP6.js +158 -0
- package/dist/chunk-UYWUVEP6.js.map +1 -0
- package/dist/chunk-VLGARN6H.js +202 -0
- package/dist/chunk-VLGARN6H.js.map +1 -0
- package/dist/circuit-breaker/index.js +1 -51
- package/dist/circuit-breaker/index.js.map +1 -1
- package/dist/core-BoB6t7dB.d.ts +188 -0
- package/dist/deadline/index.d.ts +24 -5
- package/dist/deadline/index.js +4 -18
- package/dist/deadline/index.js.map +1 -1
- package/dist/debounce/index.d.ts +6 -0
- package/dist/debounce/index.js +1 -54
- package/dist/debounce/index.js.map +1 -1
- package/dist/devtools/index.d.ts +1 -1
- package/dist/devtools/index.js +18 -6
- package/dist/devtools/index.js.map +1 -1
- package/dist/do/index.d.ts +1723 -92
- package/dist/do/index.js +673 -31
- package/dist/do/index.js.map +1 -1
- package/dist/durable-effects-CO9Uh971.d.ts +180 -0
- package/dist/extension/index.d.ts +31 -13
- package/dist/extension/index.js +5 -3
- package/dist/extension/index.js.map +1 -1
- package/dist/extension/react.js +8 -3
- package/dist/extension/react.js.map +1 -1
- package/dist/extension/subs/index.d.ts +2 -2
- package/dist/extension/subs/index.js.map +1 -1
- package/dist/extension/test-utils.js +11 -3
- package/dist/extension/test-utils.js.map +1 -1
- package/dist/fan-out/index.d.ts +239 -0
- package/dist/fan-out/index.js +5 -0
- package/dist/fan-out/index.js.map +1 -0
- package/dist/idempotency/adapter.d.ts +62 -0
- package/dist/idempotency/adapter.js +4 -0
- package/dist/idempotency/adapter.js.map +1 -0
- package/dist/idempotency/index.js +1 -56
- package/dist/idempotency/index.js.map +1 -1
- package/dist/idempotent-intake/index.d.ts +186 -0
- package/dist/idempotent-intake/index.js +7 -0
- package/dist/idempotent-intake/index.js.map +1 -0
- package/dist/index.d.ts +341 -191
- package/dist/index.js +2 -1
- package/dist/llm-call/index.d.ts +309 -0
- package/dist/llm-call/index.js +14 -0
- package/dist/llm-call/index.js.map +1 -0
- package/dist/machine-viz/index.d.ts +4 -4
- package/dist/machine-viz/index.js +5 -9
- package/dist/machine-viz/index.js.map +1 -1
- package/dist/mem/index.d.ts +1 -0
- package/dist/monitored-run/index.d.ts +253 -0
- package/dist/monitored-run/index.js +10 -0
- package/dist/monitored-run/index.js.map +1 -0
- package/dist/node/index.d.ts +5 -5
- package/dist/node/index.js.map +1 -1
- package/dist/paginated-walk/index.d.ts +234 -0
- package/dist/paginated-walk/index.js +15 -0
- package/dist/paginated-walk/index.js.map +1 -0
- package/dist/paginator/index.d.ts +271 -0
- package/dist/paginator/index.js +3 -0
- package/dist/paginator/index.js.map +1 -0
- package/dist/parity/index.d.ts +92 -0
- package/dist/parity/index.js +78 -0
- package/dist/parity/index.js.map +1 -0
- package/dist/pbt/arbitraries/index.d.ts +1 -1
- package/dist/pbt/arbitraries/index.js +1 -1
- package/dist/pbt/index.d.ts +15 -8
- package/dist/pbt/index.js +6 -11
- package/dist/pbt/index.js.map +1 -1
- package/dist/pbt/runners/index.d.ts +1 -1
- package/dist/pbt/runners/index.js +3 -2
- package/dist/poller/index.d.ts +288 -0
- package/dist/poller/index.js +79 -0
- package/dist/poller/index.js.map +1 -0
- package/dist/prediction/index.d.ts +130 -0
- package/dist/prediction/index.js +4 -0
- package/dist/prediction/index.js.map +1 -0
- package/dist/protocol-B5YmJr0d.d.ts +45 -0
- package/dist/pure/index.d.ts +2 -0
- package/dist/pure/index.js +4 -0
- package/dist/pure/index.js.map +1 -0
- package/dist/raft/demo.d.ts +105 -0
- package/dist/raft/demo.js +172 -0
- package/dist/raft/demo.js.map +1 -0
- package/dist/raft/index.d.ts +548 -0
- package/dist/raft/index.js +7 -0
- package/dist/raft/index.js.map +1 -0
- package/dist/raft/sim.d.ts +222 -0
- package/dist/raft/sim.js +8 -0
- package/dist/raft/sim.js.map +1 -0
- package/dist/raft/timeline.d.ts +46 -0
- package/dist/raft/timeline.js +62 -0
- package/dist/raft/timeline.js.map +1 -0
- package/dist/rate-limit/index.js +1 -43
- package/dist/rate-limit/index.js.map +1 -1
- package/dist/react/index.d.ts +2 -1
- package/dist/react/index.js +43 -20
- package/dist/react/index.js.map +1 -1
- package/dist/reconciler/index.d.ts +192 -0
- package/dist/reconciler/index.js +166 -0
- package/dist/reconciler/index.js.map +1 -0
- package/dist/recorder/index.d.ts +7 -3
- package/dist/recorder/index.js +1 -155
- package/dist/recorder/index.js.map +1 -1
- package/dist/resilient-call/index.d.ts +294 -0
- package/dist/resilient-call/index.js +13 -0
- package/dist/resilient-call/index.js.map +1 -0
- package/dist/retry-backoff/index.d.ts +42 -5
- package/dist/retry-backoff/index.js +1 -35
- package/dist/retry-backoff/index.js.map +1 -1
- package/dist/retry-to-success/index.d.ts +109 -0
- package/dist/retry-to-success/index.js +35 -0
- package/dist/retry-to-success/index.js.map +1 -0
- package/dist/saga/index.d.ts +238 -0
- package/dist/saga/index.js +150 -0
- package/dist/saga/index.js.map +1 -0
- package/dist/snapshot/index.d.ts +334 -0
- package/dist/snapshot/index.js +5 -0
- package/dist/snapshot/index.js.map +1 -0
- package/dist/subs/index.d.ts +48 -10
- package/dist/subs/index.js +1 -1
- package/dist/testing/index.d.ts +107 -2
- package/dist/testing/index.js +204 -6
- package/dist/testing/index.js.map +1 -1
- package/dist/throttle/index.d.ts +9 -0
- package/dist/throttle/index.js +1 -52
- package/dist/throttle/index.js.map +1 -1
- package/dist/throttled-input/index.d.ts +380 -0
- package/dist/throttled-input/index.js +88 -0
- package/dist/throttled-input/index.js.map +1 -0
- package/dist/token-refresh/index.d.ts +215 -0
- package/dist/token-refresh/index.js +6 -0
- package/dist/token-refresh/index.js.map +1 -0
- package/dist/trace-replay/index.d.ts +11 -2
- package/dist/trace-replay/index.js +3 -55
- package/dist/trace-replay/index.js.map +1 -1
- package/dist/{types-CwBC5wMn.d.ts → types-B-8bcAp8.d.ts} +1 -1
- package/dist/with-deadline/index.d.ts +196 -0
- package/dist/with-deadline/index.js +111 -0
- package/dist/with-deadline/index.js.map +1 -0
- package/dist/with-resilience/index.d.ts +205 -0
- package/dist/with-resilience/index.js +251 -0
- package/dist/with-resilience/index.js.map +1 -0
- package/dist/with-telemetry/index.d.ts +149 -0
- package/dist/with-telemetry/index.js +70 -0
- package/dist/with-telemetry/index.js.map +1 -0
- package/dist/work-queue/adapter.d.ts +82 -0
- package/dist/work-queue/adapter.js +4 -0
- package/dist/work-queue/adapter.js.map +1 -0
- package/dist/work-queue/index.d.ts +25 -11
- package/dist/work-queue/index.js +1 -46
- package/dist/work-queue/index.js.map +1 -1
- package/dist/work-queue/ops.d.ts +69 -0
- package/dist/work-queue/ops.js +3 -0
- package/dist/work-queue/ops.js.map +1 -0
- package/dist/workflow/index.d.ts +450 -0
- package/dist/workflow/index.js +225 -0
- package/dist/workflow/index.js.map +1 -0
- package/package.json +168 -25
- package/dist/chunk-CMG2KMWX.js.map +0 -1
- package/dist/chunk-PYBQREFU.js.map +0 -1
- package/dist/chunk-PYOCUBQJ.js.map +0 -1
- package/dist/chunk-Y5JM3UUH.js.map +0 -1
- package/dist/chunk-ZRUST6BK.js.map +0 -1
|
@@ -1,126 +1,10 @@
|
|
|
1
|
+
import { detectUpdateForm, foldUpdates, __DEV__, deepFreeze, applyCell, assertPureResult } from './chunk-QLA76GIT.js';
|
|
1
2
|
import { Result } from 'better-result';
|
|
2
3
|
|
|
3
|
-
// src/index.ts
|
|
4
|
-
var __DEV__ = (() => {
|
|
5
|
-
try {
|
|
6
|
-
const meta = import.meta;
|
|
7
|
-
if (meta.env?.DEV !== void 0) {
|
|
8
|
-
return meta.env.DEV;
|
|
9
|
-
}
|
|
10
|
-
} catch {
|
|
11
|
-
}
|
|
12
|
-
try {
|
|
13
|
-
return typeof process !== "undefined" && process.env?.NODE_ENV !== "production";
|
|
14
|
-
} catch {
|
|
15
|
-
return false;
|
|
16
|
-
}
|
|
17
|
-
})();
|
|
18
|
-
function deepFreeze(obj, seen) {
|
|
19
|
-
if (obj === null || typeof obj !== "object") return obj;
|
|
20
|
-
const proto = Object.getPrototypeOf(obj);
|
|
21
|
-
if (proto !== Object.prototype && proto !== Array.prototype && proto !== null) return obj;
|
|
22
|
-
const visited = seen ?? /* @__PURE__ */ new WeakSet();
|
|
23
|
-
if (visited.has(obj)) return obj;
|
|
24
|
-
visited.add(obj);
|
|
25
|
-
Object.freeze(obj);
|
|
26
|
-
for (const v of Object.values(obj)) deepFreeze(v, visited);
|
|
27
|
-
return obj;
|
|
28
|
-
}
|
|
29
|
-
function hasFunctionValues(obj) {
|
|
30
|
-
if (obj === null || typeof obj !== "object") return null;
|
|
31
|
-
for (const [key, value] of Object.entries(obj)) {
|
|
32
|
-
if (typeof value === "function") return key;
|
|
33
|
-
}
|
|
34
|
-
return null;
|
|
35
|
-
}
|
|
36
|
-
function assertPureResult(result, msgType) {
|
|
37
|
-
if (result && typeof result.then === "function") {
|
|
38
|
-
throw new Error(
|
|
39
|
-
`@demlik/tea: update cell "${msgType}" returned a Promise. update must be synchronous. Move async work to interpret.`
|
|
40
|
-
);
|
|
41
|
-
}
|
|
42
|
-
if (!Array.isArray(result) || result.length < 2 || !Array.isArray(result[1])) {
|
|
43
|
-
throw new Error(
|
|
44
|
-
`@demlik/tea: update cell "${msgType}" returned a non-tuple. Expected [State, Cmd[]], got ${typeof result}.`
|
|
45
|
-
);
|
|
46
|
-
}
|
|
47
|
-
const cmds = result[1];
|
|
48
|
-
for (const cmd of cmds) {
|
|
49
|
-
const fnField = hasFunctionValues(cmd);
|
|
50
|
-
if (fnField !== null) {
|
|
51
|
-
throw new Error(
|
|
52
|
-
`@demlik/tea: Cmd "${cmd.type}" has function field "${fnField}". Cmds must be plain data, not closures.`
|
|
53
|
-
);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
4
|
function absurd(x) {
|
|
58
5
|
throw new Error(`unreachable: ${JSON.stringify(x)}`);
|
|
59
6
|
}
|
|
60
|
-
var noop = (state, _msg) => [
|
|
61
|
-
state,
|
|
62
|
-
[]
|
|
63
|
-
];
|
|
64
|
-
var Cmd = {
|
|
65
|
-
/**
|
|
66
|
-
* The empty Cmd array. Typed `readonly never[]` so it's assignable to any
|
|
67
|
-
* `readonly C[]` for any `C extends Cmd`. Use in `init` returns and
|
|
68
|
-
* Transitions cells that emit zero effects:
|
|
69
|
-
*
|
|
70
|
-
* init: (loaded) => [loaded ?? initial, Cmd.none],
|
|
71
|
-
* tick: (state) => [state, Cmd.none],
|
|
72
|
-
*
|
|
73
|
-
* Elm's `Cmd.none` analogue. Cultural signal alongside the runtime help:
|
|
74
|
-
* `[state, Cmd.none]` reads as intent ("this transition emits nothing"),
|
|
75
|
-
* `[state, []]` reads as "empty array of what".
|
|
76
|
-
*
|
|
77
|
-
* Frozen at runtime so a downstream consumer can't `.push()` into the
|
|
78
|
-
* shared reference.
|
|
79
|
-
*/
|
|
80
|
-
none: Object.freeze([]),
|
|
81
|
-
/**
|
|
82
|
-
* Flat concat of cmd arrays. Use when a cell composes effects from
|
|
83
|
-
* multiple conditional sources:
|
|
84
|
-
*
|
|
85
|
-
* return [next, Cmd.batch(
|
|
86
|
-
* Cmd.whenDefined(state.queueItemId, (id) => ({ type: "complete", id })),
|
|
87
|
-
* Cmd.when(state.windowId !== undefined, { type: "close_window", windowId }),
|
|
88
|
-
* [{ type: "detach_debugger", tabId: state.tabId }],
|
|
89
|
-
* )];
|
|
90
|
-
*
|
|
91
|
-
* `<const C>` keeps inline cmd literals' discriminants narrow (same
|
|
92
|
-
* rationale as `when` / `whenDefined` above).
|
|
93
|
-
*/
|
|
94
|
-
batch: (...arrs) => {
|
|
95
|
-
const out = [];
|
|
96
|
-
for (const arr of arrs) out.push(...arr);
|
|
97
|
-
return out;
|
|
98
|
-
},
|
|
99
|
-
/**
|
|
100
|
-
* Emit `cmd` wrapped in a single-element array iff `cond` is true.
|
|
101
|
-
* Otherwise return the empty array. Spreads cleanly into the cmds array
|
|
102
|
-
* returned by a Transitions cell.
|
|
103
|
-
*
|
|
104
|
-
* `const C` (TypeScript 5.0+) keeps the inferred `type:` discriminator
|
|
105
|
-
* literal narrow when called with an object literal — so `Cmd.when(b,
|
|
106
|
-
* { type: "x", ... })` infers as `{ type: "x", ... }`, not `{ type:
|
|
107
|
-
* string, ... }`, and stays assignable to a discriminated-union arm
|
|
108
|
-
* without `as const` at the call site.
|
|
109
|
-
*/
|
|
110
|
-
when: (cond, cmd) => cond ? [cmd] : [],
|
|
111
|
-
/**
|
|
112
|
-
* If `value` is defined, call `build(value)` and emit the resulting cmd
|
|
113
|
-
* wrapped in a single-element array. If `value` is `undefined`, return
|
|
114
|
-
* the empty array. `value` is narrowed to `T` inside `build`.
|
|
115
|
-
*
|
|
116
|
-
* `const C` on the return type keeps the callback's object-literal
|
|
117
|
-
* `type:` field narrow (see `when` above for the full rationale).
|
|
118
|
-
*/
|
|
119
|
-
whenDefined: (value, build) => value !== void 0 ? [build(value)] : []
|
|
120
|
-
};
|
|
121
|
-
function subId(s) {
|
|
122
|
-
return s;
|
|
123
|
-
}
|
|
7
|
+
var noop = (state, _msg) => [state, []];
|
|
124
8
|
var definedPortNames = /* @__PURE__ */ new Set();
|
|
125
9
|
var PortNameCollisionError = class extends Error {
|
|
126
10
|
name = "PortNameCollisionError";
|
|
@@ -133,6 +17,25 @@ var PortNameCollisionError = class extends Error {
|
|
|
133
17
|
function __resetPortRegistry() {
|
|
134
18
|
definedPortNames.clear();
|
|
135
19
|
}
|
|
20
|
+
function defaultOnError(error, _context) {
|
|
21
|
+
setTimeout(() => {
|
|
22
|
+
throw error;
|
|
23
|
+
}, 0);
|
|
24
|
+
}
|
|
25
|
+
function normalizeSupervision(supervision) {
|
|
26
|
+
if (supervision === void 0) return { strategy: "stop" };
|
|
27
|
+
if (typeof supervision === "string") return { strategy: supervision };
|
|
28
|
+
return supervision;
|
|
29
|
+
}
|
|
30
|
+
var QuiescenceTimeoutError = class extends Error {
|
|
31
|
+
constructor(iterations) {
|
|
32
|
+
super(
|
|
33
|
+
`@demlik/tea: idle() did not reach quiescence after ${iterations} iterations \u2014 the dispatch tail kept advancing. The machine is likely livelocking (an interpret handler enqueues a follow-up Msg that enqueues another, without end). Bound the follow-up chain in the reducer, or stop the runtime.`
|
|
34
|
+
);
|
|
35
|
+
this.iterations = iterations;
|
|
36
|
+
}
|
|
37
|
+
name = "QuiescenceTimeoutError";
|
|
38
|
+
};
|
|
136
39
|
function definePort(name) {
|
|
137
40
|
let isHmr = false;
|
|
138
41
|
try {
|
|
@@ -148,16 +51,44 @@ function definePort(name) {
|
|
|
148
51
|
return { __brand: "port", name };
|
|
149
52
|
}
|
|
150
53
|
function defineMachine(m) {
|
|
54
|
+
if (m.__form === void 0) {
|
|
55
|
+
Object.defineProperty(m, "__form", {
|
|
56
|
+
value: detectUpdateForm(m.update),
|
|
57
|
+
enumerable: false,
|
|
58
|
+
writable: false,
|
|
59
|
+
configurable: true
|
|
60
|
+
});
|
|
61
|
+
}
|
|
151
62
|
return m;
|
|
152
63
|
}
|
|
64
|
+
function asReducer(reducer) {
|
|
65
|
+
return reducer;
|
|
66
|
+
}
|
|
153
67
|
function run(machine, opts) {
|
|
154
|
-
const {
|
|
68
|
+
const { store } = opts;
|
|
69
|
+
const ctx = opts.ctx ?? {};
|
|
70
|
+
const idleCap = opts.__idleCap ?? 1e5;
|
|
71
|
+
const projectEvents = opts.events ?? (() => []);
|
|
72
|
+
const isTerminal = opts.terminal ?? (() => false);
|
|
73
|
+
const onError = opts.onError ?? defaultOnError;
|
|
74
|
+
const reportError = (error, context) => {
|
|
75
|
+
try {
|
|
76
|
+
onError(error, context);
|
|
77
|
+
} catch (sinkError) {
|
|
78
|
+
defaultOnError(sinkError);
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
const supervision = normalizeSupervision(opts.supervision);
|
|
155
82
|
let state;
|
|
156
83
|
let bootError = null;
|
|
157
84
|
let stopped = false;
|
|
158
85
|
const subRegistry = /* @__PURE__ */ new Map();
|
|
159
86
|
const listeners = /* @__PURE__ */ new Set();
|
|
160
87
|
const observers = /* @__PURE__ */ new Set();
|
|
88
|
+
const bootHandlers = /* @__PURE__ */ new Set();
|
|
89
|
+
let booted = false;
|
|
90
|
+
const eventHandlers = /* @__PURE__ */ new Map();
|
|
91
|
+
const doneWaiters = /* @__PURE__ */ new Set();
|
|
161
92
|
const portRegistry = /* @__PURE__ */ new Map();
|
|
162
93
|
function portEmit(port, value) {
|
|
163
94
|
const subscribers = portRegistry.get(port);
|
|
@@ -171,28 +102,9 @@ function run(machine, opts) {
|
|
|
171
102
|
}
|
|
172
103
|
}
|
|
173
104
|
const augmentedCtx = { ...ctx, emit: portEmit };
|
|
174
|
-
const updateForm = machine.update;
|
|
175
|
-
const updateMode = (() => {
|
|
176
|
-
const firstKey = Object.keys(updateForm)[0];
|
|
177
|
-
if (firstKey === void 0) {
|
|
178
|
-
return "reducer";
|
|
179
|
-
}
|
|
180
|
-
const firstValue = updateForm[firstKey];
|
|
181
|
-
return typeof firstValue === "function" ? "reducer" : "transitions";
|
|
182
|
-
})();
|
|
183
105
|
function applyUpdate(state2, msg) {
|
|
184
106
|
if (__DEV__) deepFreeze(state2);
|
|
185
|
-
|
|
186
|
-
if (updateMode === "reducer") {
|
|
187
|
-
const record = updateForm;
|
|
188
|
-
const handler = record[msg.type];
|
|
189
|
-
result = handler(state2, msg);
|
|
190
|
-
} else {
|
|
191
|
-
const table = updateForm;
|
|
192
|
-
const stateKey = state2.type;
|
|
193
|
-
const handler = table[stateKey][msg.type];
|
|
194
|
-
result = handler(state2, msg);
|
|
195
|
-
}
|
|
107
|
+
const result = applyCell(machine, state2, msg);
|
|
196
108
|
if (__DEV__) assertPureResult(result, msg.type);
|
|
197
109
|
return result;
|
|
198
110
|
}
|
|
@@ -230,7 +142,11 @@ function run(machine, opts) {
|
|
|
230
142
|
continue;
|
|
231
143
|
}
|
|
232
144
|
try {
|
|
233
|
-
const cleanup = handler(
|
|
145
|
+
const cleanup = handler(
|
|
146
|
+
sub,
|
|
147
|
+
ctx,
|
|
148
|
+
enqueueDispatch
|
|
149
|
+
);
|
|
234
150
|
subRegistry.set(sub.id, cleanup);
|
|
235
151
|
} catch (err) {
|
|
236
152
|
if (firstStartError === null) firstStartError = err;
|
|
@@ -243,9 +159,13 @@ function run(machine, opts) {
|
|
|
243
159
|
for (const cmd of cmds) {
|
|
244
160
|
const handler = interpretMap[cmd.type];
|
|
245
161
|
if (!handler) continue;
|
|
246
|
-
const follow = await handler(
|
|
162
|
+
const follow = await handler(
|
|
163
|
+
cmd,
|
|
164
|
+
augmentedCtx
|
|
165
|
+
);
|
|
247
166
|
if (follow !== void 0 && follow !== null) {
|
|
248
|
-
enqueueDispatch(follow).catch(() => {
|
|
167
|
+
enqueueDispatch(follow).catch((error) => {
|
|
168
|
+
reportError(error, { phase: "follow-up" });
|
|
249
169
|
});
|
|
250
170
|
}
|
|
251
171
|
}
|
|
@@ -270,17 +190,83 @@ function run(machine, opts) {
|
|
|
270
190
|
}
|
|
271
191
|
}
|
|
272
192
|
}
|
|
193
|
+
function fireEvents(msg) {
|
|
194
|
+
if (eventHandlers.size === 0 || state === void 0) return;
|
|
195
|
+
let events;
|
|
196
|
+
try {
|
|
197
|
+
events = projectEvents(msg, state);
|
|
198
|
+
} catch (err) {
|
|
199
|
+
console.error(err);
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
for (const event of events) {
|
|
203
|
+
const bucket = eventHandlers.get(event.type);
|
|
204
|
+
if (bucket === void 0) continue;
|
|
205
|
+
for (const handler of bucket) {
|
|
206
|
+
try {
|
|
207
|
+
handler(event);
|
|
208
|
+
} catch (err) {
|
|
209
|
+
console.error(err);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
function fireBoot() {
|
|
215
|
+
booted = true;
|
|
216
|
+
if (bootHandlers.size === 0 || state === void 0) return;
|
|
217
|
+
const snapshot = state;
|
|
218
|
+
for (const handler of bootHandlers) {
|
|
219
|
+
try {
|
|
220
|
+
handler(snapshot);
|
|
221
|
+
} catch (err) {
|
|
222
|
+
console.error(err);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
function settleDoneWaiters() {
|
|
227
|
+
if (doneWaiters.size === 0 || state === void 0) return;
|
|
228
|
+
if (!isTerminal(state)) return;
|
|
229
|
+
const snapshot = state;
|
|
230
|
+
const parked = [...doneWaiters];
|
|
231
|
+
doneWaiters.clear();
|
|
232
|
+
for (const resolve of parked) resolve(snapshot);
|
|
233
|
+
}
|
|
273
234
|
async function stepDispatch(msg) {
|
|
274
235
|
if (state === void 0) {
|
|
275
236
|
throw new Error("@demlik/tea: runtime not booted");
|
|
276
237
|
}
|
|
277
|
-
|
|
238
|
+
let next;
|
|
239
|
+
let cmds;
|
|
240
|
+
try {
|
|
241
|
+
[next, cmds] = applyUpdate(state, msg);
|
|
242
|
+
} catch (reduceError) {
|
|
243
|
+
reportError(reduceError, { phase: "reduce" });
|
|
244
|
+
switch (supervision.strategy) {
|
|
245
|
+
case "restart": {
|
|
246
|
+
state = supervision.rehydrate(state, msg, reduceError);
|
|
247
|
+
if (store) await store.save(state);
|
|
248
|
+
reconcileSubs();
|
|
249
|
+
fireListeners();
|
|
250
|
+
fireObservers(msg);
|
|
251
|
+
fireEvents(msg);
|
|
252
|
+
settleDoneWaiters();
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
case "escalate":
|
|
256
|
+
throw reduceError;
|
|
257
|
+
default:
|
|
258
|
+
stopped = true;
|
|
259
|
+
throw reduceError;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
278
262
|
state = next;
|
|
279
263
|
if (store) await store.save(state);
|
|
280
264
|
reconcileSubs();
|
|
281
265
|
await runInterpret(cmds);
|
|
282
266
|
fireListeners();
|
|
283
267
|
fireObservers(msg);
|
|
268
|
+
fireEvents(msg);
|
|
269
|
+
settleDoneWaiters();
|
|
284
270
|
}
|
|
285
271
|
let pendingInitCmds = [];
|
|
286
272
|
if (!store) {
|
|
@@ -300,10 +286,12 @@ function run(machine, opts) {
|
|
|
300
286
|
reconcileSubs();
|
|
301
287
|
await runInterpret(pendingInitCmds);
|
|
302
288
|
fireListeners();
|
|
303
|
-
|
|
289
|
+
fireBoot();
|
|
290
|
+
settleDoneWaiters();
|
|
304
291
|
}
|
|
305
292
|
function enqueueDispatch(msg) {
|
|
306
|
-
if (stopped)
|
|
293
|
+
if (stopped)
|
|
294
|
+
return Promise.reject(new Error("@demlik/tea: runtime stopped"));
|
|
307
295
|
const next = tail.then(() => {
|
|
308
296
|
if (bootError !== null) throw bootError;
|
|
309
297
|
return stepDispatch(msg);
|
|
@@ -312,17 +300,30 @@ function run(machine, opts) {
|
|
|
312
300
|
});
|
|
313
301
|
return next;
|
|
314
302
|
}
|
|
303
|
+
async function drainToQuiescence() {
|
|
304
|
+
for (let i = 0; i < idleCap; i++) {
|
|
305
|
+
const observed = tail;
|
|
306
|
+
await observed;
|
|
307
|
+
if (tail === observed) return;
|
|
308
|
+
}
|
|
309
|
+
throw new QuiescenceTimeoutError(idleCap);
|
|
310
|
+
}
|
|
311
|
+
async function dispatchToQuiescence(msg, opts2) {
|
|
312
|
+
await enqueueDispatch(msg);
|
|
313
|
+
if (opts2?.settle === "once") return;
|
|
314
|
+
await drainToQuiescence();
|
|
315
|
+
}
|
|
315
316
|
const bootPromise = stepBootEffects();
|
|
316
317
|
tail = bootPromise.catch((err) => {
|
|
317
318
|
bootError = err;
|
|
318
319
|
});
|
|
320
|
+
const readyPromise = bootPromise.then(
|
|
321
|
+
() => runtime
|
|
322
|
+
);
|
|
319
323
|
const runtime = {
|
|
320
|
-
dispatch:
|
|
324
|
+
dispatch: dispatchToQuiescence,
|
|
325
|
+
dispatchOnce: enqueueDispatch,
|
|
321
326
|
getState() {
|
|
322
|
-
if (bootError !== null) throw bootError;
|
|
323
|
-
if (state === void 0) {
|
|
324
|
-
throw new Error("@demlik/tea: getState() called before runtime booted");
|
|
325
|
-
}
|
|
326
327
|
return state;
|
|
327
328
|
},
|
|
328
329
|
subscribe(listener) {
|
|
@@ -337,6 +338,36 @@ function run(machine, opts) {
|
|
|
337
338
|
observers.delete(observer);
|
|
338
339
|
};
|
|
339
340
|
},
|
|
341
|
+
onBoot(handler) {
|
|
342
|
+
if (booted && state !== void 0) {
|
|
343
|
+
try {
|
|
344
|
+
handler(state);
|
|
345
|
+
} catch (err) {
|
|
346
|
+
console.error(err);
|
|
347
|
+
}
|
|
348
|
+
return () => {
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
bootHandlers.add(handler);
|
|
352
|
+
return () => {
|
|
353
|
+
bootHandlers.delete(handler);
|
|
354
|
+
};
|
|
355
|
+
},
|
|
356
|
+
on(type, handler) {
|
|
357
|
+
let bucket = eventHandlers.get(type);
|
|
358
|
+
if (bucket === void 0) {
|
|
359
|
+
bucket = /* @__PURE__ */ new Set();
|
|
360
|
+
eventHandlers.set(type, bucket);
|
|
361
|
+
}
|
|
362
|
+
const erased = handler;
|
|
363
|
+
bucket.add(erased);
|
|
364
|
+
return () => {
|
|
365
|
+
const set = eventHandlers.get(type);
|
|
366
|
+
if (set === void 0) return;
|
|
367
|
+
set.delete(erased);
|
|
368
|
+
if (set.size === 0) eventHandlers.delete(type);
|
|
369
|
+
};
|
|
370
|
+
},
|
|
340
371
|
subscribePort(port, listener) {
|
|
341
372
|
const key = port;
|
|
342
373
|
let bucket = portRegistry.get(key);
|
|
@@ -356,11 +387,24 @@ function run(machine, opts) {
|
|
|
356
387
|
emitPort(port, value) {
|
|
357
388
|
portEmit(port, value);
|
|
358
389
|
},
|
|
359
|
-
// `ready` is
|
|
360
|
-
//
|
|
361
|
-
//
|
|
362
|
-
|
|
363
|
-
|
|
390
|
+
// `ready` is assigned just below (it must resolve to `runtime` itself,
|
|
391
|
+
// which can't be referenced inside its own object literal). See the
|
|
392
|
+
// assignment + rationale after this block.
|
|
393
|
+
ready: readyPromise,
|
|
394
|
+
idle() {
|
|
395
|
+
return drainToQuiescence();
|
|
396
|
+
},
|
|
397
|
+
result() {
|
|
398
|
+
const current = state;
|
|
399
|
+
return isTerminal(current) ? current : void 0;
|
|
400
|
+
},
|
|
401
|
+
done() {
|
|
402
|
+
const current = state;
|
|
403
|
+
if (isTerminal(current)) return Promise.resolve(current);
|
|
404
|
+
return new Promise((resolve) => {
|
|
405
|
+
doneWaiters.add(resolve);
|
|
406
|
+
});
|
|
407
|
+
},
|
|
364
408
|
async stop() {
|
|
365
409
|
stopped = true;
|
|
366
410
|
await tail;
|
|
@@ -375,8 +419,8 @@ function run(machine, opts) {
|
|
|
375
419
|
if (store && state !== void 0 && bootError === null) {
|
|
376
420
|
try {
|
|
377
421
|
await store.save(state);
|
|
378
|
-
} catch (
|
|
379
|
-
|
|
422
|
+
} catch (error) {
|
|
423
|
+
reportError(error, { phase: "stop-save" });
|
|
380
424
|
}
|
|
381
425
|
}
|
|
382
426
|
}
|
|
@@ -386,10 +430,17 @@ function run(machine, opts) {
|
|
|
386
430
|
function historyTracker(runtime, size) {
|
|
387
431
|
const buffer = [];
|
|
388
432
|
let stopped = false;
|
|
433
|
+
const push = (entry) => {
|
|
434
|
+
buffer.push(entry);
|
|
435
|
+
if (buffer.length > size) buffer.shift();
|
|
436
|
+
};
|
|
389
437
|
const unobserve = size <= 0 ? () => {
|
|
390
438
|
} : runtime.observe((msg, state) => {
|
|
391
|
-
|
|
392
|
-
|
|
439
|
+
push({ msg, state });
|
|
440
|
+
});
|
|
441
|
+
const unboot = size <= 0 ? () => {
|
|
442
|
+
} : runtime.onBoot((state) => {
|
|
443
|
+
push({ msg: null, state });
|
|
393
444
|
});
|
|
394
445
|
return {
|
|
395
446
|
snapshot() {
|
|
@@ -399,6 +450,7 @@ function historyTracker(runtime, size) {
|
|
|
399
450
|
if (stopped) return;
|
|
400
451
|
stopped = true;
|
|
401
452
|
unobserve();
|
|
453
|
+
unboot();
|
|
402
454
|
}
|
|
403
455
|
};
|
|
404
456
|
}
|
|
@@ -410,33 +462,12 @@ function replay(machine, opts) {
|
|
|
410
462
|
"TEA contract violation: machine.init must return [state, []] (no Cmds) when `loaded` is non-null. Init's rehydrate branch is a pure state passthrough \u2014 the migration/parse boundary, not the boot-effect hook.\n\nRoutes for boot effects:\n - Stateless infrastructure (e.g. chrome.alarms ensure) \u2192 host module top level, outside TEA.\n - State-conditional resume (e.g. re-attach a session) \u2192 a `boot` Msg dispatched once from the host after `run(...)` returns, handled in update.\n\nSee .patterns/tea/tea-invariants.md (Invariant 2)."
|
|
411
463
|
);
|
|
412
464
|
}
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
const firstValue = updateForm[firstKey];
|
|
420
|
-
return typeof firstValue === "function" ? "reducer" : "transitions";
|
|
421
|
-
})();
|
|
422
|
-
for (const msg of opts.msgs) {
|
|
423
|
-
if (__DEV__) deepFreeze(state);
|
|
424
|
-
let result;
|
|
425
|
-
if (updateMode === "reducer") {
|
|
426
|
-
result = updateForm[msg.type](
|
|
427
|
-
state,
|
|
428
|
-
msg
|
|
429
|
-
);
|
|
430
|
-
} else {
|
|
431
|
-
const table = updateForm;
|
|
432
|
-
const stateKey = state.type;
|
|
433
|
-
result = table[stateKey][msg.type](state, msg);
|
|
434
|
-
}
|
|
435
|
-
if (__DEV__) assertPureResult(result, msg.type);
|
|
436
|
-
const [next, emitted] = result;
|
|
437
|
-
state = next;
|
|
438
|
-
cmds.push(...emitted);
|
|
439
|
-
}
|
|
465
|
+
const { state, cmds: foldedCmds } = foldUpdates(
|
|
466
|
+
machine,
|
|
467
|
+
initialState,
|
|
468
|
+
opts.msgs
|
|
469
|
+
);
|
|
470
|
+
const cmds = [...initCmds, ...foldedCmds];
|
|
440
471
|
const subs = machine.subscriptions ? [...machine.subscriptions(state)] : [];
|
|
441
472
|
return { state, cmds, subs };
|
|
442
473
|
}
|
|
@@ -453,6 +484,6 @@ function tryInterpret(work, onOk, onErr) {
|
|
|
453
484
|
};
|
|
454
485
|
}
|
|
455
486
|
|
|
456
|
-
export {
|
|
457
|
-
//# sourceMappingURL=chunk-
|
|
458
|
-
//# sourceMappingURL=chunk-
|
|
487
|
+
export { PortNameCollisionError, QuiescenceTimeoutError, __resetPortRegistry, absurd, asReducer, defineMachine, definePort, historyTracker, noop, replay, run, tryInterpret };
|
|
488
|
+
//# sourceMappingURL=chunk-MMH7CW5K.js.map
|
|
489
|
+
//# sourceMappingURL=chunk-MMH7CW5K.js.map
|