@demlik/tea 0.1.2 → 0.3.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 +49 -0
- package/dist/agent/index.d.ts +16 -770
- package/dist/agent/index.js +18 -16
- package/dist/authed-call/index.d.ts +3 -3
- package/dist/authed-call/index.js +22 -36
- package/dist/authed-call/index.js.map +1 -1
- package/dist/await-terminal/index.d.ts +2 -2
- package/dist/await-terminal/index.js +2 -2
- package/dist/batch-window/index.d.ts +3 -3
- package/dist/batch-window/index.js +3 -3
- package/dist/cache/index.d.ts +2 -2
- package/dist/cache/index.js +5 -2
- package/dist/{chunk-3545BOYL.js → chunk-25LBDCBC.js} +6 -5
- package/dist/chunk-25LBDCBC.js.map +1 -0
- package/dist/{chunk-IN33Q4VJ.js → chunk-2KNLKQVN.js} +3 -3
- package/dist/{chunk-IN33Q4VJ.js.map → chunk-2KNLKQVN.js.map} +1 -1
- package/dist/{chunk-MMH7CW5K.js → chunk-BP2R7TPP.js} +216 -157
- package/dist/chunk-BP2R7TPP.js.map +1 -0
- package/dist/chunk-C6QC273X.js +71 -0
- package/dist/chunk-C6QC273X.js.map +1 -0
- package/dist/{chunk-7W4LMPUW.js → chunk-CAXMQJJ3.js} +17 -24
- package/dist/chunk-CAXMQJJ3.js.map +1 -0
- package/dist/{chunk-UV6UWGEO.js → chunk-D736QUGF.js} +6 -5
- package/dist/chunk-D736QUGF.js.map +1 -0
- package/dist/chunk-EWJP3YYP.js +21 -0
- package/dist/chunk-EWJP3YYP.js.map +1 -0
- package/dist/{chunk-TGG26XMK.js → chunk-FV3Z5MBE.js} +10 -5
- package/dist/chunk-FV3Z5MBE.js.map +1 -0
- package/dist/chunk-G5E74IJB.js +8 -0
- package/dist/chunk-G5E74IJB.js.map +1 -0
- package/dist/{chunk-27N2SPTN.js → chunk-IXBKFQH5.js} +12 -11
- package/dist/chunk-IXBKFQH5.js.map +1 -0
- package/dist/{chunk-SQTCS44W.js → chunk-JFFVBEDI.js} +3 -3
- package/dist/{chunk-SQTCS44W.js.map → chunk-JFFVBEDI.js.map} +1 -1
- package/dist/chunk-LYLDCIPH.js +365 -0
- package/dist/chunk-LYLDCIPH.js.map +1 -0
- package/dist/{chunk-HJO6VNQI.js → chunk-MU6MCIAC.js} +3 -3
- package/dist/{chunk-HJO6VNQI.js.map → chunk-MU6MCIAC.js.map} +1 -1
- package/dist/{chunk-UYWUVEP6.js → chunk-MUUROGIH.js} +2 -2
- package/dist/chunk-MUUROGIH.js.map +1 -0
- package/dist/{chunk-EHIX7NYZ.js → chunk-MVY5DAMF.js} +4 -4
- package/dist/{chunk-EHIX7NYZ.js.map → chunk-MVY5DAMF.js.map} +1 -1
- package/dist/{chunk-LP7VQBRG.js → chunk-NPERUUUE.js} +76 -95
- package/dist/chunk-NPERUUUE.js.map +1 -0
- package/dist/{chunk-QLA76GIT.js → chunk-PBDYW2TU.js} +68 -9
- package/dist/chunk-PBDYW2TU.js.map +1 -0
- package/dist/{chunk-5VNWZADP.js → chunk-Q2UM7BXU.js} +18 -7
- package/dist/chunk-Q2UM7BXU.js.map +1 -0
- package/dist/chunk-RMX4EOQK.js +26 -0
- package/dist/chunk-RMX4EOQK.js.map +1 -0
- package/dist/{chunk-2YOE5PIS.js → chunk-S2EGRPCM.js} +8 -6
- package/dist/chunk-S2EGRPCM.js.map +1 -0
- package/dist/{chunk-ON24RKSE.js → chunk-S4O26D7B.js} +7 -14
- package/dist/chunk-S4O26D7B.js.map +1 -0
- package/dist/{chunk-3XJWC7VW.js → chunk-SK5JGUY7.js} +3 -3
- package/dist/{chunk-3XJWC7VW.js.map → chunk-SK5JGUY7.js.map} +1 -1
- package/dist/{chunk-5DEQ5I3U.js → chunk-TPGASTFF.js} +8 -10
- package/dist/chunk-TPGASTFF.js.map +1 -0
- package/dist/{chunk-SC3FAFZN.js → chunk-UF4MZSLT.js} +2 -2
- package/dist/chunk-UF4MZSLT.js.map +1 -0
- package/dist/{chunk-PS23H6KQ.js → chunk-VBUCHVCV.js} +6 -5
- package/dist/chunk-VBUCHVCV.js.map +1 -0
- package/dist/{chunk-S3FQN4SL.js → chunk-WGGAMW7Y.js} +191 -178
- package/dist/chunk-WGGAMW7Y.js.map +1 -0
- package/dist/chunk-ZJ5AOYBH.js +8 -0
- package/dist/chunk-ZJ5AOYBH.js.map +1 -0
- package/dist/{chunk-LEC4U6CX.js → chunk-ZVJZ72HY.js} +3 -3
- package/dist/{chunk-LEC4U6CX.js.map → chunk-ZVJZ72HY.js.map} +1 -1
- package/dist/circuit-breaker/index.d.ts +1 -0
- package/dist/circuit-breaker/index.js +1 -1
- package/dist/{core-BoB6t7dB.d.ts → core-42kapW0n.d.ts} +105 -6
- package/dist/deadline/index.d.ts +77 -11
- package/dist/deadline/index.js +3 -3
- package/dist/devtools/index.js +8 -28
- package/dist/devtools/index.js.map +1 -1
- package/dist/do/index.d.ts +483 -339
- package/dist/do/index.js +244 -214
- package/dist/do/index.js.map +1 -1
- package/dist/{durable-effects-CO9Uh971.d.ts → durable-effects-CFRngTNA.d.ts} +3 -3
- package/dist/extension/index.d.ts +25 -7
- package/dist/extension/index.js +4 -3
- package/dist/extension/index.js.map +1 -1
- package/dist/extension/react.js +4 -3
- package/dist/extension/react.js.map +1 -1
- package/dist/extension/subs/index.d.ts +2 -2
- package/dist/extension/subs/index.js +7 -10
- package/dist/extension/subs/index.js.map +1 -1
- package/dist/fan-out/index.d.ts +10 -10
- package/dist/fan-out/index.js +3 -3
- package/dist/idempotent-intake/index.d.ts +2 -2
- package/dist/idempotent-intake/index.js +3 -3
- package/dist/index.d.ts +50 -472
- package/dist/index.js +2 -2
- package/dist/llm-call/index.d.ts +3 -2
- package/dist/llm-call/index.js +12 -10
- package/dist/machine-B_BF4jij.d.ts +804 -0
- package/dist/machine-viz/index.d.ts +1 -1
- package/dist/machine-viz/index.js +2 -2
- package/dist/mem/index.d.ts +3 -2
- package/dist/mem/index.js.map +1 -1
- package/dist/monitored-run/index.d.ts +54 -30
- package/dist/monitored-run/index.js +7 -7
- package/dist/node/index.d.ts +3 -2
- package/dist/node/index.js +2 -3
- package/dist/node/index.js.map +1 -1
- package/dist/paginated-walk/index.d.ts +2 -2
- package/dist/paginated-walk/index.js +11 -10
- package/dist/parity/index.d.ts +6 -5
- package/dist/parity/index.js +5 -4
- package/dist/parity/index.js.map +1 -1
- package/dist/pbt/arbitraries/index.d.ts +1 -1
- package/dist/pbt/index.d.ts +1 -1
- package/dist/pbt/index.js +3 -3
- package/dist/pbt/index.js.map +1 -1
- package/dist/pbt/runners/index.d.ts +1 -1
- package/dist/pbt/runners/index.js +3 -3
- package/dist/poller/index.d.ts +59 -17
- package/dist/poller/index.js +56 -20
- package/dist/poller/index.js.map +1 -1
- package/dist/prediction/index.d.ts +1 -1
- package/dist/prediction/index.js +2 -2
- package/dist/pure/index.d.ts +1 -1
- package/dist/pure/index.js +2 -2
- package/dist/rate-limit/index.d.ts +2 -2
- package/dist/rate-limit/index.js +1 -1
- package/dist/react/index.d.ts +3 -2
- package/dist/react/index.js +2 -2
- package/dist/react/index.js.map +1 -1
- package/dist/reconciler/index.d.ts +2 -2
- package/dist/reconciler/index.js +13 -15
- package/dist/reconciler/index.js.map +1 -1
- package/dist/recorder/index.d.ts +20 -20
- package/dist/recorder/index.js +1 -1
- package/dist/resilient-call/index.d.ts +31 -6
- package/dist/resilient-call/index.js +10 -9
- package/dist/retry-backoff/index.d.ts +191 -14
- package/dist/retry-backoff/index.js +1 -1
- package/dist/retry-to-success/index.js +1 -1
- package/dist/runtime-types-gsog27b6.d.ts +337 -0
- package/dist/saga/index.d.ts +3 -2
- package/dist/saga/index.js +2 -2
- package/dist/saga/index.js.map +1 -1
- package/dist/snapshot/index.d.ts +1 -1
- package/dist/snapshot/index.js +3 -3
- package/dist/subs/index.d.ts +372 -4
- package/dist/subs/index.js +4 -1
- package/dist/testing/index.d.ts +2 -2
- package/dist/testing/index.js +2 -2
- package/dist/throttled-input/index.d.ts +2 -2
- package/dist/throttled-input/index.js +14 -13
- package/dist/throttled-input/index.js.map +1 -1
- package/dist/token-refresh/index.d.ts +1 -1
- package/dist/token-refresh/index.js +3 -3
- package/dist/trace-replay/index.d.ts +12 -7
- package/dist/trace-replay/index.js +4 -3
- package/dist/{types-B-8bcAp8.d.ts → types-KbL3W1mj.d.ts} +1 -1
- package/dist/with-deadline/index.d.ts +1 -1
- package/dist/with-deadline/index.js +2 -2
- package/dist/with-resilience/index.d.ts +21 -2
- package/dist/with-resilience/index.js +12 -23
- package/dist/with-resilience/index.js.map +1 -1
- package/dist/with-telemetry/index.d.ts +1 -1
- package/dist/with-telemetry/index.js +2 -2
- package/dist/work-queue/adapter.d.ts +2 -2
- package/dist/work-queue/adapter.js +2 -2
- package/dist/work-queue/index.d.ts +3 -2
- package/dist/work-queue/index.js +1 -1
- package/dist/work-queue/index.js.map +1 -1
- package/dist/work-queue/ops.d.ts +2 -2
- package/dist/work-queue/ops.js +1 -1
- package/dist/workflow/index.d.ts +51 -19
- package/dist/workflow/index.js +71 -52
- package/dist/workflow/index.js.map +1 -1
- package/package.json +4 -19
- package/dist/chunk-27N2SPTN.js.map +0 -1
- package/dist/chunk-2YOE5PIS.js.map +0 -1
- package/dist/chunk-3545BOYL.js.map +0 -1
- package/dist/chunk-5DEQ5I3U.js.map +0 -1
- package/dist/chunk-5VNWZADP.js.map +0 -1
- package/dist/chunk-6RGBKODV.js +0 -268
- package/dist/chunk-6RGBKODV.js.map +0 -1
- package/dist/chunk-7W4LMPUW.js.map +0 -1
- package/dist/chunk-DILMKOZ7.js +0 -91
- package/dist/chunk-DILMKOZ7.js.map +0 -1
- package/dist/chunk-K7Q23EQ4.js +0 -20
- package/dist/chunk-K7Q23EQ4.js.map +0 -1
- package/dist/chunk-LP7VQBRG.js.map +0 -1
- package/dist/chunk-MMH7CW5K.js.map +0 -1
- package/dist/chunk-NSDFA6M6.js +0 -198
- package/dist/chunk-NSDFA6M6.js.map +0 -1
- package/dist/chunk-ON24RKSE.js.map +0 -1
- package/dist/chunk-PS23H6KQ.js.map +0 -1
- package/dist/chunk-QLA76GIT.js.map +0 -1
- package/dist/chunk-S3FQN4SL.js.map +0 -1
- package/dist/chunk-SC3FAFZN.js.map +0 -1
- package/dist/chunk-TGG26XMK.js.map +0 -1
- package/dist/chunk-UV6UWGEO.js.map +0 -1
- package/dist/chunk-UYWUVEP6.js.map +0 -1
- package/dist/chunk-VLGARN6H.js +0 -202
- package/dist/chunk-VLGARN6H.js.map +0 -1
- package/dist/raft/demo.d.ts +0 -105
- package/dist/raft/demo.js +0 -172
- package/dist/raft/demo.js.map +0 -1
- package/dist/raft/index.d.ts +0 -548
- package/dist/raft/index.js +0 -7
- package/dist/raft/index.js.map +0 -1
- package/dist/raft/sim.d.ts +0 -222
- package/dist/raft/sim.js +0 -8
- package/dist/raft/sim.js.map +0 -1
- package/dist/raft/timeline.d.ts +0 -46
- package/dist/raft/timeline.js +0 -62
- package/dist/raft/timeline.js.map +0 -1
|
@@ -1,6 +1,34 @@
|
|
|
1
|
-
import { detectUpdateForm, foldUpdates,
|
|
1
|
+
import { detectUpdateForm, foldUpdates, structuralHash, applyCellChecked } from './chunk-PBDYW2TU.js';
|
|
2
2
|
import { Result } from 'better-result';
|
|
3
3
|
|
|
4
|
+
// src/observability.ts
|
|
5
|
+
function historyTracker(runtime, size) {
|
|
6
|
+
const buffer = [];
|
|
7
|
+
let stopped = false;
|
|
8
|
+
const push = (entry) => {
|
|
9
|
+
buffer.push(entry);
|
|
10
|
+
if (buffer.length > size) buffer.shift();
|
|
11
|
+
};
|
|
12
|
+
const unobserve = size <= 0 ? () => {
|
|
13
|
+
} : runtime.observe((msg, state) => {
|
|
14
|
+
push({ msg, state });
|
|
15
|
+
});
|
|
16
|
+
const unboot = size <= 0 ? () => {
|
|
17
|
+
} : runtime.onBoot((state) => {
|
|
18
|
+
push({ msg: null, state });
|
|
19
|
+
});
|
|
20
|
+
return {
|
|
21
|
+
snapshot() {
|
|
22
|
+
return buffer.slice();
|
|
23
|
+
},
|
|
24
|
+
stop() {
|
|
25
|
+
if (stopped) return;
|
|
26
|
+
stopped = true;
|
|
27
|
+
unobserve();
|
|
28
|
+
unboot();
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
}
|
|
4
32
|
function absurd(x) {
|
|
5
33
|
throw new Error(`unreachable: ${JSON.stringify(x)}`);
|
|
6
34
|
}
|
|
@@ -8,25 +36,25 @@ var noop = (state, _msg) => [state, []];
|
|
|
8
36
|
var definedPortNames = /* @__PURE__ */ new Set();
|
|
9
37
|
var PortNameCollisionError = class extends Error {
|
|
10
38
|
name = "PortNameCollisionError";
|
|
39
|
+
_tag = "PortNameCollisionError";
|
|
11
40
|
constructor(portName) {
|
|
12
41
|
super(
|
|
13
42
|
`definePort: a port named "${portName}" was already defined. Each definePort call must use a unique name. If two modules need the same port, export it from one module and import it.`
|
|
14
43
|
);
|
|
15
44
|
}
|
|
16
45
|
};
|
|
46
|
+
var SubIdCollisionError = class extends Error {
|
|
47
|
+
name = "SubIdCollisionError";
|
|
48
|
+
_tag = "SubIdCollisionError";
|
|
49
|
+
constructor(id, declaredType, conflictingType) {
|
|
50
|
+
super(
|
|
51
|
+
`@demlik/tea: Sub.id collision: id="${id}" declared as type="${declaredType}" and type="${conflictingType}"`
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
};
|
|
17
55
|
function __resetPortRegistry() {
|
|
18
56
|
definedPortNames.clear();
|
|
19
57
|
}
|
|
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
58
|
var QuiescenceTimeoutError = class extends Error {
|
|
31
59
|
constructor(iterations) {
|
|
32
60
|
super(
|
|
@@ -35,6 +63,7 @@ var QuiescenceTimeoutError = class extends Error {
|
|
|
35
63
|
this.iterations = iterations;
|
|
36
64
|
}
|
|
37
65
|
name = "QuiescenceTimeoutError";
|
|
66
|
+
_tag = "QuiescenceTimeoutError";
|
|
38
67
|
};
|
|
39
68
|
function definePort(name) {
|
|
40
69
|
let isHmr = false;
|
|
@@ -50,6 +79,18 @@ function definePort(name) {
|
|
|
50
79
|
definedPortNames.add(name);
|
|
51
80
|
return { __brand: "port", name };
|
|
52
81
|
}
|
|
82
|
+
function schemaMigrate(schema, upcast = (raw) => raw) {
|
|
83
|
+
return (raw) => {
|
|
84
|
+
let migrated;
|
|
85
|
+
try {
|
|
86
|
+
migrated = upcast(raw);
|
|
87
|
+
} catch {
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
const parsed = schema.safeParse(migrated);
|
|
91
|
+
return parsed.success ? parsed.data : null;
|
|
92
|
+
};
|
|
93
|
+
}
|
|
53
94
|
function defineMachine(m) {
|
|
54
95
|
if (m.__form === void 0) {
|
|
55
96
|
Object.defineProperty(m, "__form", {
|
|
@@ -64,6 +105,64 @@ function defineMachine(m) {
|
|
|
64
105
|
function asReducer(reducer) {
|
|
65
106
|
return reducer;
|
|
66
107
|
}
|
|
108
|
+
function replay(machine, opts) {
|
|
109
|
+
const loaded = opts.loaded ?? null;
|
|
110
|
+
const [initialState, initCmds] = machine.init(loaded, opts.ctx);
|
|
111
|
+
if (loaded !== null && initCmds.length > 0) {
|
|
112
|
+
throw new Error(
|
|
113
|
+
"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)."
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
const { state, cmds: foldedCmds } = foldUpdates(
|
|
117
|
+
machine,
|
|
118
|
+
initialState,
|
|
119
|
+
opts.msgs
|
|
120
|
+
);
|
|
121
|
+
const cmds = [...initCmds, ...foldedCmds];
|
|
122
|
+
const subs = machine.subscriptions ? [...machine.subscriptions(state)] : [];
|
|
123
|
+
const depSubs = [];
|
|
124
|
+
if (machine.subs) {
|
|
125
|
+
for (const [index, entry] of machine.subs.entries()) {
|
|
126
|
+
const deps = entry.deps(state);
|
|
127
|
+
if (deps !== null) depSubs.push({ index, id: structuralHash(deps) });
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return { state, cmds, subs, depSubs };
|
|
131
|
+
}
|
|
132
|
+
function wrapDetached(handler) {
|
|
133
|
+
return (cmd, ctx, dispatch) => {
|
|
134
|
+
if (dispatch === void 0) {
|
|
135
|
+
throw new Error(
|
|
136
|
+
"@demlik/tea: a wrapDetached handler was invoked without the injected dispatch. The kernel always supplies it; call the handler through the runtime, not directly."
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
return handler(cmd, ctx, dispatch);
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
function tryInterpret(work, onOk, onErr) {
|
|
143
|
+
return async (cmd, ctx) => {
|
|
144
|
+
const result = await Result.tryPromise({
|
|
145
|
+
try: () => work(cmd, ctx),
|
|
146
|
+
catch: (error) => error
|
|
147
|
+
});
|
|
148
|
+
return result.match({
|
|
149
|
+
ok: (value) => onOk(value, cmd),
|
|
150
|
+
err: (error) => onErr(error, cmd)
|
|
151
|
+
});
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// src/run.ts
|
|
156
|
+
function defaultOnError(error, _context) {
|
|
157
|
+
setTimeout(() => {
|
|
158
|
+
throw error;
|
|
159
|
+
}, 0);
|
|
160
|
+
}
|
|
161
|
+
function normalizeSupervision(supervision) {
|
|
162
|
+
if (supervision === void 0) return { strategy: "stop" };
|
|
163
|
+
if (typeof supervision === "string") return { strategy: supervision };
|
|
164
|
+
return supervision;
|
|
165
|
+
}
|
|
67
166
|
function run(machine, opts) {
|
|
68
167
|
const { store } = opts;
|
|
69
168
|
const ctx = opts.ctx ?? {};
|
|
@@ -78,11 +177,21 @@ function run(machine, opts) {
|
|
|
78
177
|
defaultOnError(sinkError);
|
|
79
178
|
}
|
|
80
179
|
};
|
|
180
|
+
function fanout(items, phase, fn) {
|
|
181
|
+
for (const item of items) {
|
|
182
|
+
try {
|
|
183
|
+
fn(item);
|
|
184
|
+
} catch (err) {
|
|
185
|
+
reportError(err, { phase });
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
81
189
|
const supervision = normalizeSupervision(opts.supervision);
|
|
82
190
|
let state;
|
|
83
191
|
let bootError = null;
|
|
84
192
|
let stopped = false;
|
|
85
193
|
const subRegistry = /* @__PURE__ */ new Map();
|
|
194
|
+
const depSubRegistry = /* @__PURE__ */ new Map();
|
|
86
195
|
const listeners = /* @__PURE__ */ new Set();
|
|
87
196
|
const observers = /* @__PURE__ */ new Set();
|
|
88
197
|
const bootHandlers = /* @__PURE__ */ new Set();
|
|
@@ -93,48 +202,78 @@ function run(machine, opts) {
|
|
|
93
202
|
function portEmit(port, value) {
|
|
94
203
|
const subscribers = portRegistry.get(port);
|
|
95
204
|
if (!subscribers || subscribers.size === 0) return;
|
|
96
|
-
|
|
205
|
+
fanout(subscribers, "port-emit", (listener) => listener(value));
|
|
206
|
+
}
|
|
207
|
+
const augmentedCtx = { ...ctx, emit: portEmit };
|
|
208
|
+
let tail = Promise.resolve();
|
|
209
|
+
function stopSubs(ids) {
|
|
210
|
+
for (const id of ids) {
|
|
211
|
+
const cleanup = subRegistry.get(id);
|
|
212
|
+
if (cleanup === void 0) continue;
|
|
97
213
|
try {
|
|
98
|
-
|
|
214
|
+
cleanup();
|
|
99
215
|
} catch (err) {
|
|
100
|
-
|
|
216
|
+
reportError(err, { phase: "sub-cleanup" });
|
|
101
217
|
}
|
|
218
|
+
subRegistry.delete(id);
|
|
102
219
|
}
|
|
103
220
|
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
221
|
+
function disposeDepSubs(indices) {
|
|
222
|
+
for (const index of indices) {
|
|
223
|
+
const running = depSubRegistry.get(index);
|
|
224
|
+
if (running === void 0) continue;
|
|
225
|
+
try {
|
|
226
|
+
running.dispose();
|
|
227
|
+
} catch (err) {
|
|
228
|
+
reportError(err, { phase: "sub-cleanup" });
|
|
229
|
+
}
|
|
230
|
+
depSubRegistry.delete(index);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
function reconcileDepSubs() {
|
|
234
|
+
let firstError = null;
|
|
235
|
+
const subs = machine.subs;
|
|
236
|
+
if (!subs) return firstError;
|
|
237
|
+
for (const [i, entry] of subs.entries()) {
|
|
238
|
+
const deps = entry.deps(state);
|
|
239
|
+
if (deps === null) {
|
|
240
|
+
disposeDepSubs([i]);
|
|
241
|
+
continue;
|
|
242
|
+
}
|
|
243
|
+
const id = structuralHash(deps);
|
|
244
|
+
const running = depSubRegistry.get(i);
|
|
245
|
+
if (running !== void 0 && running.runningId === id) {
|
|
246
|
+
continue;
|
|
247
|
+
}
|
|
248
|
+
disposeDepSubs([i]);
|
|
249
|
+
try {
|
|
250
|
+
const dispose = entry.source(state, enqueueDispatch, ctx);
|
|
251
|
+
depSubRegistry.set(i, { runningId: id, dispose });
|
|
252
|
+
} catch (err) {
|
|
253
|
+
if (firstError === null) firstError = err;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
return firstError;
|
|
110
257
|
}
|
|
111
|
-
let tail = Promise.resolve();
|
|
112
258
|
function reconcileSubs() {
|
|
113
|
-
|
|
259
|
+
const depError = reconcileDepSubs();
|
|
260
|
+
if (!machine.subscriptions) {
|
|
261
|
+
if (depError !== null) throw depError;
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
114
264
|
const desired = machine.subscriptions(state);
|
|
115
265
|
const desiredIds = /* @__PURE__ */ new Set();
|
|
116
266
|
const desiredTypeById = /* @__PURE__ */ new Map();
|
|
117
267
|
for (const sub of desired) {
|
|
118
268
|
const existing = desiredTypeById.get(sub.id);
|
|
119
269
|
if (existing !== void 0 && existing !== sub.type) {
|
|
120
|
-
throw new
|
|
121
|
-
`@demlik/tea: Sub.id collision: id="${sub.id}" declared as type="${existing}" and type="${sub.type}"`
|
|
122
|
-
);
|
|
270
|
+
throw new SubIdCollisionError(sub.id, existing, sub.type);
|
|
123
271
|
}
|
|
124
272
|
desiredTypeById.set(sub.id, sub.type);
|
|
125
273
|
}
|
|
126
274
|
for (const sub of desired) desiredIds.add(sub.id);
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
try {
|
|
130
|
-
cleanup();
|
|
131
|
-
} catch (err) {
|
|
132
|
-
console.error(err);
|
|
133
|
-
}
|
|
134
|
-
subRegistry.delete(id);
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
let firstStartError = null;
|
|
275
|
+
stopSubs([...subRegistry.keys()].filter((id) => !desiredIds.has(id)));
|
|
276
|
+
let firstStartError = depError;
|
|
138
277
|
for (const sub of desired) {
|
|
139
278
|
if (subRegistry.has(sub.id)) continue;
|
|
140
279
|
const handler = machine.subscribe?.[sub.type];
|
|
@@ -155,13 +294,19 @@ function run(machine, opts) {
|
|
|
155
294
|
if (firstStartError !== null) throw firstStartError;
|
|
156
295
|
}
|
|
157
296
|
const interpretMap = machine.interpret ?? {};
|
|
297
|
+
const interpretDispatch = (msg) => {
|
|
298
|
+
enqueueDispatch(msg).catch((error) => {
|
|
299
|
+
reportError(error, { phase: "follow-up" });
|
|
300
|
+
});
|
|
301
|
+
};
|
|
158
302
|
async function runInterpret(cmds) {
|
|
159
303
|
for (const cmd of cmds) {
|
|
160
304
|
const handler = interpretMap[cmd.type];
|
|
161
305
|
if (!handler) continue;
|
|
162
306
|
const follow = await handler(
|
|
163
307
|
cmd,
|
|
164
|
-
augmentedCtx
|
|
308
|
+
augmentedCtx,
|
|
309
|
+
interpretDispatch
|
|
165
310
|
);
|
|
166
311
|
if (follow !== void 0 && follow !== null) {
|
|
167
312
|
enqueueDispatch(follow).catch((error) => {
|
|
@@ -171,24 +316,12 @@ function run(machine, opts) {
|
|
|
171
316
|
}
|
|
172
317
|
}
|
|
173
318
|
function fireListeners() {
|
|
174
|
-
|
|
175
|
-
try {
|
|
176
|
-
listener();
|
|
177
|
-
} catch (err) {
|
|
178
|
-
console.error(err);
|
|
179
|
-
}
|
|
180
|
-
}
|
|
319
|
+
fanout(listeners, "listener", (listener) => listener());
|
|
181
320
|
}
|
|
182
321
|
function fireObservers(msg) {
|
|
183
322
|
if (observers.size === 0 || state === void 0) return;
|
|
184
323
|
const snapshot = state;
|
|
185
|
-
|
|
186
|
-
try {
|
|
187
|
-
observer(msg, snapshot);
|
|
188
|
-
} catch (err) {
|
|
189
|
-
console.error(err);
|
|
190
|
-
}
|
|
191
|
-
}
|
|
324
|
+
fanout(observers, "observer", (observer) => observer(msg, snapshot));
|
|
192
325
|
}
|
|
193
326
|
function fireEvents(msg) {
|
|
194
327
|
if (eventHandlers.size === 0 || state === void 0) return;
|
|
@@ -196,32 +329,20 @@ function run(machine, opts) {
|
|
|
196
329
|
try {
|
|
197
330
|
events = projectEvents(msg, state);
|
|
198
331
|
} catch (err) {
|
|
199
|
-
|
|
332
|
+
reportError(err, { phase: "event" });
|
|
200
333
|
return;
|
|
201
334
|
}
|
|
202
335
|
for (const event of events) {
|
|
203
336
|
const bucket = eventHandlers.get(event.type);
|
|
204
337
|
if (bucket === void 0) continue;
|
|
205
|
-
|
|
206
|
-
try {
|
|
207
|
-
handler(event);
|
|
208
|
-
} catch (err) {
|
|
209
|
-
console.error(err);
|
|
210
|
-
}
|
|
211
|
-
}
|
|
338
|
+
fanout(bucket, "event", (handler) => handler(event));
|
|
212
339
|
}
|
|
213
340
|
}
|
|
214
341
|
function fireBoot() {
|
|
215
342
|
booted = true;
|
|
216
343
|
if (bootHandlers.size === 0 || state === void 0) return;
|
|
217
344
|
const snapshot = state;
|
|
218
|
-
|
|
219
|
-
try {
|
|
220
|
-
handler(snapshot);
|
|
221
|
-
} catch (err) {
|
|
222
|
-
console.error(err);
|
|
223
|
-
}
|
|
224
|
-
}
|
|
345
|
+
fanout(bootHandlers, "boot", (handler) => handler(snapshot));
|
|
225
346
|
}
|
|
226
347
|
function settleDoneWaiters() {
|
|
227
348
|
if (doneWaiters.size === 0 || state === void 0) return;
|
|
@@ -231,25 +352,38 @@ function run(machine, opts) {
|
|
|
231
352
|
doneWaiters.clear();
|
|
232
353
|
for (const resolve of parked) resolve(snapshot);
|
|
233
354
|
}
|
|
355
|
+
async function commit(next, msg, cmds) {
|
|
356
|
+
state = next;
|
|
357
|
+
if (store) await store.save(next);
|
|
358
|
+
reconcileSubs();
|
|
359
|
+
await runInterpret(cmds);
|
|
360
|
+
fireListeners();
|
|
361
|
+
fireObservers(msg);
|
|
362
|
+
fireEvents(msg);
|
|
363
|
+
settleDoneWaiters();
|
|
364
|
+
}
|
|
234
365
|
async function stepDispatch(msg) {
|
|
235
366
|
if (state === void 0) {
|
|
236
367
|
throw new Error("@demlik/tea: runtime not booted");
|
|
237
368
|
}
|
|
369
|
+
if (machine.identity !== void 0) {
|
|
370
|
+
const addressed = machine.identity.ofMsg(msg);
|
|
371
|
+
if (addressed !== void 0) {
|
|
372
|
+
const own = machine.identity.ofState(state);
|
|
373
|
+
if (own !== void 0 && structuralHash(addressed) !== structuralHash(own)) {
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
}
|
|
238
378
|
let next;
|
|
239
379
|
let cmds;
|
|
240
380
|
try {
|
|
241
|
-
[next, cmds] =
|
|
381
|
+
[next, cmds] = applyCellChecked(machine, state, msg);
|
|
242
382
|
} catch (reduceError) {
|
|
243
383
|
reportError(reduceError, { phase: "reduce" });
|
|
244
384
|
switch (supervision.strategy) {
|
|
245
385
|
case "restart": {
|
|
246
|
-
|
|
247
|
-
if (store) await store.save(state);
|
|
248
|
-
reconcileSubs();
|
|
249
|
-
fireListeners();
|
|
250
|
-
fireObservers(msg);
|
|
251
|
-
fireEvents(msg);
|
|
252
|
-
settleDoneWaiters();
|
|
386
|
+
await commit(supervision.rehydrate(state, msg, reduceError), msg, []);
|
|
253
387
|
return;
|
|
254
388
|
}
|
|
255
389
|
case "escalate":
|
|
@@ -259,14 +393,7 @@ function run(machine, opts) {
|
|
|
259
393
|
throw reduceError;
|
|
260
394
|
}
|
|
261
395
|
}
|
|
262
|
-
|
|
263
|
-
if (store) await store.save(state);
|
|
264
|
-
reconcileSubs();
|
|
265
|
-
await runInterpret(cmds);
|
|
266
|
-
fireListeners();
|
|
267
|
-
fireObservers(msg);
|
|
268
|
-
fireEvents(msg);
|
|
269
|
-
settleDoneWaiters();
|
|
396
|
+
await commit(next, msg, cmds);
|
|
270
397
|
}
|
|
271
398
|
let pendingInitCmds = [];
|
|
272
399
|
if (!store) {
|
|
@@ -340,11 +467,8 @@ function run(machine, opts) {
|
|
|
340
467
|
},
|
|
341
468
|
onBoot(handler) {
|
|
342
469
|
if (booted && state !== void 0) {
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
} catch (err) {
|
|
346
|
-
console.error(err);
|
|
347
|
-
}
|
|
470
|
+
const snapshot = state;
|
|
471
|
+
fanout([handler], "boot", (h) => h(snapshot));
|
|
348
472
|
return () => {
|
|
349
473
|
};
|
|
350
474
|
}
|
|
@@ -387,9 +511,6 @@ function run(machine, opts) {
|
|
|
387
511
|
emitPort(port, value) {
|
|
388
512
|
portEmit(port, value);
|
|
389
513
|
},
|
|
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
514
|
ready: readyPromise,
|
|
394
515
|
idle() {
|
|
395
516
|
return drainToQuiescence();
|
|
@@ -408,14 +529,8 @@ function run(machine, opts) {
|
|
|
408
529
|
async stop() {
|
|
409
530
|
stopped = true;
|
|
410
531
|
await tail;
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
cleanup();
|
|
414
|
-
} catch (err) {
|
|
415
|
-
console.error(err);
|
|
416
|
-
}
|
|
417
|
-
subRegistry.delete(id);
|
|
418
|
-
}
|
|
532
|
+
stopSubs([...subRegistry.keys()]);
|
|
533
|
+
disposeDepSubs([...depSubRegistry.keys()]);
|
|
419
534
|
if (store && state !== void 0 && bootError === null) {
|
|
420
535
|
try {
|
|
421
536
|
await store.save(state);
|
|
@@ -427,63 +542,7 @@ function run(machine, opts) {
|
|
|
427
542
|
};
|
|
428
543
|
return runtime;
|
|
429
544
|
}
|
|
430
|
-
function historyTracker(runtime, size) {
|
|
431
|
-
const buffer = [];
|
|
432
|
-
let stopped = false;
|
|
433
|
-
const push = (entry) => {
|
|
434
|
-
buffer.push(entry);
|
|
435
|
-
if (buffer.length > size) buffer.shift();
|
|
436
|
-
};
|
|
437
|
-
const unobserve = size <= 0 ? () => {
|
|
438
|
-
} : runtime.observe((msg, state) => {
|
|
439
|
-
push({ msg, state });
|
|
440
|
-
});
|
|
441
|
-
const unboot = size <= 0 ? () => {
|
|
442
|
-
} : runtime.onBoot((state) => {
|
|
443
|
-
push({ msg: null, state });
|
|
444
|
-
});
|
|
445
|
-
return {
|
|
446
|
-
snapshot() {
|
|
447
|
-
return buffer.slice();
|
|
448
|
-
},
|
|
449
|
-
stop() {
|
|
450
|
-
if (stopped) return;
|
|
451
|
-
stopped = true;
|
|
452
|
-
unobserve();
|
|
453
|
-
unboot();
|
|
454
|
-
}
|
|
455
|
-
};
|
|
456
|
-
}
|
|
457
|
-
function replay(machine, opts) {
|
|
458
|
-
const loaded = opts.loaded ?? null;
|
|
459
|
-
const [initialState, initCmds] = machine.init(loaded, opts.ctx);
|
|
460
|
-
if (loaded !== null && initCmds.length > 0) {
|
|
461
|
-
throw new Error(
|
|
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)."
|
|
463
|
-
);
|
|
464
|
-
}
|
|
465
|
-
const { state, cmds: foldedCmds } = foldUpdates(
|
|
466
|
-
machine,
|
|
467
|
-
initialState,
|
|
468
|
-
opts.msgs
|
|
469
|
-
);
|
|
470
|
-
const cmds = [...initCmds, ...foldedCmds];
|
|
471
|
-
const subs = machine.subscriptions ? [...machine.subscriptions(state)] : [];
|
|
472
|
-
return { state, cmds, subs };
|
|
473
|
-
}
|
|
474
|
-
function tryInterpret(work, onOk, onErr) {
|
|
475
|
-
return async (cmd, ctx) => {
|
|
476
|
-
const result = await Result.tryPromise({
|
|
477
|
-
try: () => work(cmd, ctx),
|
|
478
|
-
catch: (error) => error
|
|
479
|
-
});
|
|
480
|
-
return result.match({
|
|
481
|
-
ok: (value) => onOk(value, cmd),
|
|
482
|
-
err: (error) => onErr(error, cmd)
|
|
483
|
-
});
|
|
484
|
-
};
|
|
485
|
-
}
|
|
486
545
|
|
|
487
|
-
export { PortNameCollisionError, QuiescenceTimeoutError, __resetPortRegistry, absurd, asReducer, defineMachine, definePort, historyTracker, noop, replay, run, tryInterpret };
|
|
488
|
-
//# sourceMappingURL=chunk-
|
|
489
|
-
//# sourceMappingURL=chunk-
|
|
546
|
+
export { PortNameCollisionError, QuiescenceTimeoutError, SubIdCollisionError, __resetPortRegistry, absurd, asReducer, defineMachine, definePort, historyTracker, noop, replay, run, schemaMigrate, tryInterpret, wrapDetached };
|
|
547
|
+
//# sourceMappingURL=chunk-BP2R7TPP.js.map
|
|
548
|
+
//# sourceMappingURL=chunk-BP2R7TPP.js.map
|