@graphrefly/ts 0.0.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/LICENSE +21 -0
- package/dist/adapters/index.cjs +9015 -0
- package/dist/adapters/index.cjs.map +1 -0
- package/dist/adapters/index.d.cts +678 -0
- package/dist/adapters/index.d.ts +678 -0
- package/dist/adapters/index.js +2894 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/observe-storage.cjs +260 -0
- package/dist/adapters/observe-storage.cjs.map +1 -0
- package/dist/adapters/observe-storage.d.cts +77 -0
- package/dist/adapters/observe-storage.d.ts +77 -0
- package/dist/adapters/observe-storage.js +161 -0
- package/dist/adapters/observe-storage.js.map +1 -0
- package/dist/append-log-DisvEReb.d.cts +189 -0
- package/dist/append-log-DzKMmjxx.d.ts +189 -0
- package/dist/chunk-2ILL7HQI.js +1189 -0
- package/dist/chunk-2ILL7HQI.js.map +1 -0
- package/dist/chunk-4VLAQHZI.js +330 -0
- package/dist/chunk-4VLAQHZI.js.map +1 -0
- package/dist/chunk-6PHB5CJS.js +229 -0
- package/dist/chunk-6PHB5CJS.js.map +1 -0
- package/dist/chunk-COHO25CZ.js +2449 -0
- package/dist/chunk-COHO25CZ.js.map +1 -0
- package/dist/chunk-D6BG7U6A.js +161 -0
- package/dist/chunk-D6BG7U6A.js.map +1 -0
- package/dist/chunk-DJC4CHLQ.js +818 -0
- package/dist/chunk-DJC4CHLQ.js.map +1 -0
- package/dist/chunk-DK554R7P.js +67 -0
- package/dist/chunk-DK554R7P.js.map +1 -0
- package/dist/chunk-DKP56CSW.js +322 -0
- package/dist/chunk-DKP56CSW.js.map +1 -0
- package/dist/chunk-G4M3NHRJ.js +688 -0
- package/dist/chunk-G4M3NHRJ.js.map +1 -0
- package/dist/chunk-GAJW5I5P.js +1 -0
- package/dist/chunk-GAJW5I5P.js.map +1 -0
- package/dist/chunk-GDL26N2T.js +282 -0
- package/dist/chunk-GDL26N2T.js.map +1 -0
- package/dist/chunk-GTPCOEOZ.js +741 -0
- package/dist/chunk-GTPCOEOZ.js.map +1 -0
- package/dist/chunk-H2HTHFVN.js +1 -0
- package/dist/chunk-H2HTHFVN.js.map +1 -0
- package/dist/chunk-HDRL4VQQ.js +218 -0
- package/dist/chunk-HDRL4VQQ.js.map +1 -0
- package/dist/chunk-I3IHOHCJ.js +2267 -0
- package/dist/chunk-I3IHOHCJ.js.map +1 -0
- package/dist/chunk-JIMUDQN3.js +965 -0
- package/dist/chunk-JIMUDQN3.js.map +1 -0
- package/dist/chunk-JR4IKCR2.js +462 -0
- package/dist/chunk-JR4IKCR2.js.map +1 -0
- package/dist/chunk-K3FXTC3I.js +165 -0
- package/dist/chunk-K3FXTC3I.js.map +1 -0
- package/dist/chunk-OOEN33FB.js +65 -0
- package/dist/chunk-OOEN33FB.js.map +1 -0
- package/dist/chunk-PKVBHGBM.js +554 -0
- package/dist/chunk-PKVBHGBM.js.map +1 -0
- package/dist/chunk-RIIOUTGM.js +1857 -0
- package/dist/chunk-RIIOUTGM.js.map +1 -0
- package/dist/chunk-SCRFRCGR.js +33 -0
- package/dist/chunk-SCRFRCGR.js.map +1 -0
- package/dist/chunk-SWTLEQL6.js +53 -0
- package/dist/chunk-SWTLEQL6.js.map +1 -0
- package/dist/chunk-SZAETNNA.js +1 -0
- package/dist/chunk-SZAETNNA.js.map +1 -0
- package/dist/chunk-TEW47IVR.js +49 -0
- package/dist/chunk-TEW47IVR.js.map +1 -0
- package/dist/chunk-Y3ZLRGHC.js +1482 -0
- package/dist/chunk-Y3ZLRGHC.js.map +1 -0
- package/dist/chunk-Z2ANQ6JW.js +149 -0
- package/dist/chunk-Z2ANQ6JW.js.map +1 -0
- package/dist/codec-BB7p8fJc.d.cts +38 -0
- package/dist/codec-BB7p8fJc.d.ts +38 -0
- package/dist/composition/index.cjs +2505 -0
- package/dist/composition/index.cjs.map +1 -0
- package/dist/composition/index.d.cts +95 -0
- package/dist/composition/index.d.ts +95 -0
- package/dist/composition/index.js +19 -0
- package/dist/composition/index.js.map +1 -0
- package/dist/core/index.cjs +2475 -0
- package/dist/core/index.cjs.map +1 -0
- package/dist/core/index.d.cts +25 -0
- package/dist/core/index.d.ts +25 -0
- package/dist/core/index.js +74 -0
- package/dist/core/index.js.map +1 -0
- package/dist/cqrs/index.cjs +595 -0
- package/dist/cqrs/index.cjs.map +1 -0
- package/dist/cqrs/index.d.cts +200 -0
- package/dist/cqrs/index.d.ts +200 -0
- package/dist/cqrs/index.js +557 -0
- package/dist/cqrs/index.js.map +1 -0
- package/dist/data-structures/index.cjs +4277 -0
- package/dist/data-structures/index.cjs.map +1 -0
- package/dist/data-structures/index.d.cts +22 -0
- package/dist/data-structures/index.d.ts +22 -0
- package/dist/data-structures/index.js +31 -0
- package/dist/data-structures/index.js.map +1 -0
- package/dist/describe-BZb7AS2y.d.ts +57 -0
- package/dist/describe-Ciu8SUnN.d.cts +57 -0
- package/dist/graph/index.cjs +7832 -0
- package/dist/graph/index.cjs.map +1 -0
- package/dist/graph/index.d.cts +251 -0
- package/dist/graph/index.d.ts +251 -0
- package/dist/graph/index.js +131 -0
- package/dist/graph/index.js.map +1 -0
- package/dist/graph-DfdF9zy4.d.ts +666 -0
- package/dist/graph-s23RbbFO.d.cts +666 -0
- package/dist/index-CAEmLCYF.d.cts +166 -0
- package/dist/index-SnzZu3x7.d.ts +166 -0
- package/dist/index.cjs +15409 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +23 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.js +582 -0
- package/dist/index.js.map +1 -0
- package/dist/messages-BZqrGGm1.d.cts +55 -0
- package/dist/messages-BZqrGGm1.d.ts +55 -0
- package/dist/messaging/index.cjs +818 -0
- package/dist/messaging/index.cjs.map +1 -0
- package/dist/messaging/index.d.cts +235 -0
- package/dist/messaging/index.d.ts +235 -0
- package/dist/messaging/index.js +767 -0
- package/dist/messaging/index.js.map +1 -0
- package/dist/observe-event-log-0SVsx7JG.d.cts +88 -0
- package/dist/observe-event-log-Dnm76owp.d.ts +88 -0
- package/dist/operators/index.cjs +3774 -0
- package/dist/operators/index.cjs.map +1 -0
- package/dist/operators/index.d.cts +308 -0
- package/dist/operators/index.d.ts +308 -0
- package/dist/operators/index.js +112 -0
- package/dist/operators/index.js.map +1 -0
- package/dist/orchestration/index.cjs +3541 -0
- package/dist/orchestration/index.cjs.map +1 -0
- package/dist/orchestration/index.d.cts +302 -0
- package/dist/orchestration/index.d.ts +302 -0
- package/dist/orchestration/index.js +1004 -0
- package/dist/orchestration/index.js.map +1 -0
- package/dist/patterns/index.cjs +1045 -0
- package/dist/patterns/index.cjs.map +1 -0
- package/dist/patterns/index.d.cts +39 -0
- package/dist/patterns/index.d.ts +39 -0
- package/dist/patterns/index.js +33 -0
- package/dist/patterns/index.js.map +1 -0
- package/dist/reactive-collection-BxBqtIOE.d.cts +344 -0
- package/dist/reactive-collection-Cb1II1Fi.d.ts +344 -0
- package/dist/reactive-collection-storage-BNiEc-Gd.d.ts +217 -0
- package/dist/reactive-collection-storage-D-KmjE0J.d.cts +217 -0
- package/dist/reactive-map-BcB4KsQR.d.ts +256 -0
- package/dist/reactive-map-D-g3dv8I.d.cts +256 -0
- package/dist/read-through-B1CYPfq_.d.cts +82 -0
- package/dist/read-through-DwyJhGs1.d.ts +82 -0
- package/dist/render/index.cjs +250 -0
- package/dist/render/index.cjs.map +1 -0
- package/dist/render/index.d.cts +58 -0
- package/dist/render/index.d.ts +58 -0
- package/dist/render/index.js +20 -0
- package/dist/render/index.js.map +1 -0
- package/dist/resilience-Dig3Q7n0.d.cts +45 -0
- package/dist/resilience-Dig3Q7n0.d.ts +45 -0
- package/dist/semantic-memory-graph-BYoIlP35.d.cts +356 -0
- package/dist/semantic-memory-graph-CxyXLms3.d.ts +356 -0
- package/dist/solutions/index.cjs +3249 -0
- package/dist/solutions/index.cjs.map +1 -0
- package/dist/solutions/index.d.cts +520 -0
- package/dist/solutions/index.d.ts +520 -0
- package/dist/solutions/index.js +31 -0
- package/dist/solutions/index.js.map +1 -0
- package/dist/sources/browser.cjs +3095 -0
- package/dist/sources/browser.cjs.map +1 -0
- package/dist/sources/browser.d.cts +39 -0
- package/dist/sources/browser.d.ts +39 -0
- package/dist/sources/browser.js +137 -0
- package/dist/sources/browser.js.map +1 -0
- package/dist/sources/index.cjs +3021 -0
- package/dist/sources/index.cjs.map +1 -0
- package/dist/sources/index.d.cts +7 -0
- package/dist/sources/index.d.ts +7 -0
- package/dist/sources/index.js +63 -0
- package/dist/sources/index.js.map +1 -0
- package/dist/sources/node.cjs +675 -0
- package/dist/sources/node.cjs.map +1 -0
- package/dist/sources/node.d.cts +109 -0
- package/dist/sources/node.d.ts +109 -0
- package/dist/sources/node.js +639 -0
- package/dist/sources/node.js.map +1 -0
- package/dist/storage/browser.cjs +777 -0
- package/dist/storage/browser.cjs.map +1 -0
- package/dist/storage/browser.d.cts +40 -0
- package/dist/storage/browser.d.ts +40 -0
- package/dist/storage/browser.js +275 -0
- package/dist/storage/browser.js.map +1 -0
- package/dist/storage/index.cjs +1989 -0
- package/dist/storage/index.cjs.map +1 -0
- package/dist/storage/index.d.cts +92 -0
- package/dist/storage/index.d.ts +92 -0
- package/dist/storage/index.js +161 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/node.cjs +898 -0
- package/dist/storage/node.cjs.map +1 -0
- package/dist/storage/node.d.cts +66 -0
- package/dist/storage/node.d.ts +66 -0
- package/dist/storage/node.js +402 -0
- package/dist/storage/node.js.map +1 -0
- package/dist/testing/index.cjs +95 -0
- package/dist/testing/index.cjs.map +1 -0
- package/dist/testing/index.d.cts +20 -0
- package/dist/testing/index.d.ts +20 -0
- package/dist/testing/index.js +8 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/types-bNMSWKqF.d.cts +732 -0
- package/dist/types-h12mNYbq.d.ts +732 -0
- package/package.json +250 -0
|
@@ -0,0 +1,1482 @@
|
|
|
1
|
+
import {
|
|
2
|
+
tieredReadThrough
|
|
3
|
+
} from "./chunk-Z2ANQ6JW.js";
|
|
4
|
+
import {
|
|
5
|
+
graph,
|
|
6
|
+
restoreNodeInGraph,
|
|
7
|
+
restoreStateNodeInGraph
|
|
8
|
+
} from "./chunk-2ILL7HQI.js";
|
|
9
|
+
import {
|
|
10
|
+
hasKvVersioned
|
|
11
|
+
} from "./chunk-DKP56CSW.js";
|
|
12
|
+
import {
|
|
13
|
+
reactiveList,
|
|
14
|
+
reactiveLog,
|
|
15
|
+
restoreReactiveIndexFromBackendState,
|
|
16
|
+
restoreReactiveMapFromBackendState
|
|
17
|
+
} from "./chunk-RIIOUTGM.js";
|
|
18
|
+
import {
|
|
19
|
+
timer
|
|
20
|
+
} from "./chunk-G4M3NHRJ.js";
|
|
21
|
+
import {
|
|
22
|
+
GRAPH_CHECKPOINT_VERSION,
|
|
23
|
+
map,
|
|
24
|
+
operatorNodeFn,
|
|
25
|
+
take,
|
|
26
|
+
toCheckpointJson
|
|
27
|
+
} from "./chunk-PKVBHGBM.js";
|
|
28
|
+
import {
|
|
29
|
+
restoreStateOfNode,
|
|
30
|
+
validateNodeVersionJson
|
|
31
|
+
} from "./chunk-I3IHOHCJ.js";
|
|
32
|
+
import {
|
|
33
|
+
strictCanonicalJsonBytes
|
|
34
|
+
} from "./chunk-4VLAQHZI.js";
|
|
35
|
+
import {
|
|
36
|
+
depBatch,
|
|
37
|
+
depLatest
|
|
38
|
+
} from "./chunk-SWTLEQL6.js";
|
|
39
|
+
import {
|
|
40
|
+
SENTINEL,
|
|
41
|
+
errorPayload
|
|
42
|
+
} from "./chunk-DK554R7P.js";
|
|
43
|
+
|
|
44
|
+
// src/graph/cascading-cache.ts
|
|
45
|
+
function reactiveCascadingCache(opts) {
|
|
46
|
+
const {
|
|
47
|
+
graph: g,
|
|
48
|
+
request,
|
|
49
|
+
policy,
|
|
50
|
+
invalidate,
|
|
51
|
+
tiers,
|
|
52
|
+
tierNames,
|
|
53
|
+
promoteTo,
|
|
54
|
+
load,
|
|
55
|
+
name,
|
|
56
|
+
meta
|
|
57
|
+
} = opts;
|
|
58
|
+
const eventDeps = [request];
|
|
59
|
+
const policyIndex = policy === void 0 ? -1 : eventDeps.push(policy) - 1;
|
|
60
|
+
const invalidateIndex = invalidate === void 0 ? -1 : eventDeps.push(invalidate) - 1;
|
|
61
|
+
const baseName = name ?? "reactiveCascadingCache";
|
|
62
|
+
const eventOpts = {
|
|
63
|
+
name: `${baseName}.events`,
|
|
64
|
+
meta,
|
|
65
|
+
partial: true,
|
|
66
|
+
pool: "async"
|
|
67
|
+
};
|
|
68
|
+
const events = g.node(
|
|
69
|
+
eventDeps,
|
|
70
|
+
(ctx) => {
|
|
71
|
+
const st = ctx.state.get() ?? {
|
|
72
|
+
seq: 0,
|
|
73
|
+
active: true,
|
|
74
|
+
dropBeforeSeq: 0
|
|
75
|
+
};
|
|
76
|
+
st.active = true;
|
|
77
|
+
ctx.onDeactivation(() => {
|
|
78
|
+
st.active = false;
|
|
79
|
+
st.seq += 1;
|
|
80
|
+
st.dropBeforeSeq = st.seq;
|
|
81
|
+
});
|
|
82
|
+
const requestBatch = depBatch(ctx, 0);
|
|
83
|
+
const invalidateBatch = invalidateIndex === -1 ? null : depBatch(ctx, invalidateIndex);
|
|
84
|
+
const policyBatch = policyIndex === -1 ? null : depBatch(ctx, policyIndex);
|
|
85
|
+
const currentPolicy = policyIndex === -1 ? void 0 : depLatest(ctx, policyIndex);
|
|
86
|
+
if (requestBatch !== null) {
|
|
87
|
+
for (const key of requestBatch) {
|
|
88
|
+
startLookup(ctx, st, {
|
|
89
|
+
kind: "request",
|
|
90
|
+
key,
|
|
91
|
+
tiers,
|
|
92
|
+
tierNames,
|
|
93
|
+
load,
|
|
94
|
+
promoteTo: currentPolicy?.promoteTo ?? promoteTo ?? false
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
if (invalidateBatch !== null) {
|
|
99
|
+
for (const key of invalidateBatch) {
|
|
100
|
+
startLookup(ctx, st, {
|
|
101
|
+
kind: "invalidate",
|
|
102
|
+
key,
|
|
103
|
+
tiers,
|
|
104
|
+
tierNames,
|
|
105
|
+
load,
|
|
106
|
+
promoteTo: currentPolicy?.promoteTo ?? promoteTo ?? false
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
if (requestBatch === null && invalidateBatch === null && policyBatch !== null) {
|
|
111
|
+
const key = st.latestKey;
|
|
112
|
+
if (key !== void 0) {
|
|
113
|
+
startLookup(ctx, st, {
|
|
114
|
+
kind: "request",
|
|
115
|
+
key,
|
|
116
|
+
tiers,
|
|
117
|
+
tierNames,
|
|
118
|
+
load,
|
|
119
|
+
promoteTo: currentPolicy?.promoteTo ?? promoteTo ?? false
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
ctx.state.set(st);
|
|
124
|
+
},
|
|
125
|
+
eventOpts
|
|
126
|
+
);
|
|
127
|
+
const status = g.node(
|
|
128
|
+
[events],
|
|
129
|
+
(ctx) => {
|
|
130
|
+
const st = ctx.state.get() ?? { seq: 0 };
|
|
131
|
+
const batch = depBatch(ctx, 0);
|
|
132
|
+
if (batch === null) return;
|
|
133
|
+
for (const event of batch) {
|
|
134
|
+
if (event.kind === "request" || event.kind === "invalidate") {
|
|
135
|
+
st.seq = event.requestSeq;
|
|
136
|
+
ctx.down([["DATA", { kind: "loading", key: event.key, requestSeq: event.requestSeq }]]);
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
if (event.requestSeq !== st.seq) continue;
|
|
140
|
+
if (event.kind === "fill") {
|
|
141
|
+
if (event.status === "hit") {
|
|
142
|
+
ctx.down([
|
|
143
|
+
[
|
|
144
|
+
"DATA",
|
|
145
|
+
{
|
|
146
|
+
kind: "hit",
|
|
147
|
+
key: event.key,
|
|
148
|
+
requestSeq: event.requestSeq,
|
|
149
|
+
tier: event.tier
|
|
150
|
+
}
|
|
151
|
+
]
|
|
152
|
+
]);
|
|
153
|
+
} else if (event.status === "miss") {
|
|
154
|
+
ctx.down([["DATA", { kind: "miss", key: event.key, requestSeq: event.requestSeq }]]);
|
|
155
|
+
} else {
|
|
156
|
+
ctx.down([
|
|
157
|
+
[
|
|
158
|
+
"DATA",
|
|
159
|
+
{
|
|
160
|
+
kind: "error",
|
|
161
|
+
key: event.key,
|
|
162
|
+
requestSeq: event.requestSeq,
|
|
163
|
+
error: event.error
|
|
164
|
+
}
|
|
165
|
+
]
|
|
166
|
+
]);
|
|
167
|
+
}
|
|
168
|
+
} else if (event.kind === "error") {
|
|
169
|
+
ctx.down([
|
|
170
|
+
[
|
|
171
|
+
"DATA",
|
|
172
|
+
{
|
|
173
|
+
kind: "error",
|
|
174
|
+
key: event.key,
|
|
175
|
+
requestSeq: event.requestSeq,
|
|
176
|
+
error: event.error
|
|
177
|
+
}
|
|
178
|
+
]
|
|
179
|
+
]);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
ctx.state.set(st);
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
name: `${baseName}.status`,
|
|
186
|
+
initial: { kind: "idle" },
|
|
187
|
+
meta,
|
|
188
|
+
partial: true
|
|
189
|
+
}
|
|
190
|
+
);
|
|
191
|
+
const value = g.node(
|
|
192
|
+
[events],
|
|
193
|
+
(ctx) => {
|
|
194
|
+
const st = ctx.state.get() ?? { seq: 0 };
|
|
195
|
+
const batch = depBatch(ctx, 0);
|
|
196
|
+
if (batch === null) return;
|
|
197
|
+
for (const event of batch) {
|
|
198
|
+
if (event.kind === "request") {
|
|
199
|
+
st.seq = event.requestSeq;
|
|
200
|
+
continue;
|
|
201
|
+
}
|
|
202
|
+
if (event.kind === "invalidate") {
|
|
203
|
+
st.seq = event.requestSeq;
|
|
204
|
+
ctx.down([["INVALIDATE"]]);
|
|
205
|
+
continue;
|
|
206
|
+
}
|
|
207
|
+
if (event.kind !== "fill" || event.requestSeq !== st.seq) continue;
|
|
208
|
+
if (event.status === "hit" && event.value !== void 0) {
|
|
209
|
+
ctx.down([["DATA", event.value]]);
|
|
210
|
+
} else {
|
|
211
|
+
ctx.down([["INVALIDATE"]]);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
ctx.state.set(st);
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
name: `${baseName}.value`,
|
|
218
|
+
meta,
|
|
219
|
+
partial: true
|
|
220
|
+
}
|
|
221
|
+
);
|
|
222
|
+
return { value, status, events };
|
|
223
|
+
}
|
|
224
|
+
function startLookup(ctx, st, opts) {
|
|
225
|
+
const requestSeq = st.seq + 1;
|
|
226
|
+
st.seq = requestSeq;
|
|
227
|
+
st.latestKey = opts.key;
|
|
228
|
+
ctx.down([["DATA", { kind: opts.kind, key: opts.key, requestSeq }]]);
|
|
229
|
+
tieredReadThrough({
|
|
230
|
+
key: opts.key,
|
|
231
|
+
tiers: opts.tiers,
|
|
232
|
+
tierNames: opts.tierNames,
|
|
233
|
+
load: opts.load === void 0 ? void 0 : (key) => opts.load?.(key),
|
|
234
|
+
promoteTo: false
|
|
235
|
+
}).then(
|
|
236
|
+
(result) => {
|
|
237
|
+
promoteFresh(ctx, st, requestSeq, {
|
|
238
|
+
key: opts.key,
|
|
239
|
+
tiers: opts.tiers,
|
|
240
|
+
tierNames: opts.tierNames,
|
|
241
|
+
promoteTo: opts.promoteTo,
|
|
242
|
+
result
|
|
243
|
+
});
|
|
244
|
+
},
|
|
245
|
+
(error) => {
|
|
246
|
+
if (!isLiveRequest(st, requestSeq)) return;
|
|
247
|
+
ctx.down([
|
|
248
|
+
[
|
|
249
|
+
"DATA",
|
|
250
|
+
{
|
|
251
|
+
kind: "error",
|
|
252
|
+
key: opts.key,
|
|
253
|
+
requestSeq,
|
|
254
|
+
stage: "lookup",
|
|
255
|
+
error: errorPayload(error)
|
|
256
|
+
}
|
|
257
|
+
]
|
|
258
|
+
]);
|
|
259
|
+
}
|
|
260
|
+
);
|
|
261
|
+
}
|
|
262
|
+
function promoteFresh(ctx, st, requestSeq, opts, promotions = [], offset = 0) {
|
|
263
|
+
if (!isLiveRequest(st, requestSeq)) return;
|
|
264
|
+
const { result } = opts;
|
|
265
|
+
const sourceIndex = result.hitTier?.index === -1 ? opts.tiers.length : result.hitTier?.index;
|
|
266
|
+
const targets = result.value === void 0 || sourceIndex === void 0 ? [] : buildPromotionTargets(opts.tiers.length, sourceIndex, opts.promoteTo);
|
|
267
|
+
if (st.seq !== requestSeq || offset >= targets.length) {
|
|
268
|
+
const messages = eventsFromResult(opts.key, requestSeq, result, promotions);
|
|
269
|
+
if (messages.length > 0) ctx.down(messages);
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
const index = targets[offset];
|
|
273
|
+
const tier = { index, name: opts.tierNames?.[index] };
|
|
274
|
+
try {
|
|
275
|
+
const target = opts.tiers[index];
|
|
276
|
+
const generation = generationForTier(result.facts, index);
|
|
277
|
+
const write = hasKvVersioned(target) && generation !== void 0 ? target.setIfMatch(opts.key, result.value, generation) : target.set(opts.key, result.value).then(() => true);
|
|
278
|
+
write.then(
|
|
279
|
+
(ok) => {
|
|
280
|
+
promotions.push({ tier, ok });
|
|
281
|
+
promoteFresh(ctx, st, requestSeq, opts, promotions, offset + 1);
|
|
282
|
+
},
|
|
283
|
+
(error) => {
|
|
284
|
+
promotions.push({ tier, ok: false, error });
|
|
285
|
+
promoteFresh(ctx, st, requestSeq, opts, promotions, offset + 1);
|
|
286
|
+
}
|
|
287
|
+
);
|
|
288
|
+
} catch (error) {
|
|
289
|
+
promotions.push({ tier, ok: false, error });
|
|
290
|
+
promoteFresh(ctx, st, requestSeq, opts, promotions, offset + 1);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
function generationForTier(facts, index) {
|
|
294
|
+
return facts.find((fact) => fact.tier.index === index)?.generation;
|
|
295
|
+
}
|
|
296
|
+
function isLiveRequest(st, requestSeq) {
|
|
297
|
+
return st.active && requestSeq >= st.dropBeforeSeq;
|
|
298
|
+
}
|
|
299
|
+
function buildPromotionTargets(tierCount, hitIndex, promoteTo) {
|
|
300
|
+
if (promoteTo === false || tierCount <= 0) return [];
|
|
301
|
+
const maxPromote = Math.max(0, Math.min(hitIndex, tierCount));
|
|
302
|
+
if (promoteTo === void 0) return [...Array(maxPromote).keys()];
|
|
303
|
+
const normalized = [];
|
|
304
|
+
const seen = /* @__PURE__ */ new Set();
|
|
305
|
+
for (const index of promoteTo) {
|
|
306
|
+
if (!Number.isSafeInteger(index) || index < 0 || index >= tierCount || index >= maxPromote) {
|
|
307
|
+
continue;
|
|
308
|
+
}
|
|
309
|
+
if (!seen.has(index)) {
|
|
310
|
+
seen.add(index);
|
|
311
|
+
normalized.push(index);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
return normalized;
|
|
315
|
+
}
|
|
316
|
+
function eventsFromResult(key, requestSeq, result, promotions = result.promotions) {
|
|
317
|
+
const out = [];
|
|
318
|
+
let firstError;
|
|
319
|
+
for (const fact of result.facts) {
|
|
320
|
+
const lookupEvent = {
|
|
321
|
+
kind: "lookup",
|
|
322
|
+
key,
|
|
323
|
+
requestSeq,
|
|
324
|
+
outcome: fact.kind,
|
|
325
|
+
tier: fact.tier,
|
|
326
|
+
value: fact.value,
|
|
327
|
+
error: fact.error
|
|
328
|
+
};
|
|
329
|
+
out.push(["DATA", lookupEvent]);
|
|
330
|
+
if (fact.kind === "error") {
|
|
331
|
+
firstError ??= fact.error;
|
|
332
|
+
out.push([
|
|
333
|
+
"DATA",
|
|
334
|
+
{
|
|
335
|
+
kind: "error",
|
|
336
|
+
key,
|
|
337
|
+
requestSeq,
|
|
338
|
+
stage: "lookup",
|
|
339
|
+
tier: fact.tier,
|
|
340
|
+
error: fact.error
|
|
341
|
+
}
|
|
342
|
+
]);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
for (const promotion of promotions) {
|
|
346
|
+
out.push([
|
|
347
|
+
"DATA",
|
|
348
|
+
{
|
|
349
|
+
kind: "promotion",
|
|
350
|
+
key,
|
|
351
|
+
requestSeq,
|
|
352
|
+
tier: promotion.tier,
|
|
353
|
+
ok: promotion.ok,
|
|
354
|
+
error: promotion.error
|
|
355
|
+
}
|
|
356
|
+
]);
|
|
357
|
+
if (!promotion.ok) {
|
|
358
|
+
firstError ??= promotion.error;
|
|
359
|
+
if (promotion.error !== void 0) {
|
|
360
|
+
out.push([
|
|
361
|
+
"DATA",
|
|
362
|
+
{
|
|
363
|
+
kind: "error",
|
|
364
|
+
key,
|
|
365
|
+
requestSeq,
|
|
366
|
+
stage: "promotion",
|
|
367
|
+
tier: promotion.tier,
|
|
368
|
+
error: promotion.error
|
|
369
|
+
}
|
|
370
|
+
]);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
out.push([
|
|
375
|
+
"DATA",
|
|
376
|
+
{
|
|
377
|
+
kind: "fill",
|
|
378
|
+
key,
|
|
379
|
+
requestSeq,
|
|
380
|
+
status: result.status,
|
|
381
|
+
value: result.value,
|
|
382
|
+
tier: result.hitTier,
|
|
383
|
+
error: firstError
|
|
384
|
+
}
|
|
385
|
+
]);
|
|
386
|
+
return out;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
// src/graph/diagnostics.ts
|
|
390
|
+
function compareCodeUnit(a, b) {
|
|
391
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
392
|
+
}
|
|
393
|
+
function assertMaxDepth(caller, maxDepth) {
|
|
394
|
+
if (maxDepth !== void 0 && (!Number.isInteger(maxDepth) || maxDepth < 0)) {
|
|
395
|
+
throw new Error(`${caller}: maxDepth must be an integer >= 0`);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
function addEdge(map2, from, to) {
|
|
399
|
+
let set = map2.get(from);
|
|
400
|
+
if (set === void 0) {
|
|
401
|
+
set = /* @__PURE__ */ new Set();
|
|
402
|
+
map2.set(from, set);
|
|
403
|
+
}
|
|
404
|
+
set.add(to);
|
|
405
|
+
}
|
|
406
|
+
function flattenSnapshots(snapshot) {
|
|
407
|
+
const out = [];
|
|
408
|
+
const stack = [snapshot];
|
|
409
|
+
while (stack.length > 0) {
|
|
410
|
+
const cur = stack.pop();
|
|
411
|
+
out.push(cur);
|
|
412
|
+
if (cur.subgraphs) {
|
|
413
|
+
for (let i = cur.subgraphs.length - 1; i >= 0; i -= 1) stack.push(cur.subgraphs[i]);
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
return out;
|
|
417
|
+
}
|
|
418
|
+
function indexSnapshot(snapshot) {
|
|
419
|
+
const nodes = /* @__PURE__ */ new Map();
|
|
420
|
+
const outgoing = /* @__PURE__ */ new Map();
|
|
421
|
+
const incoming = /* @__PURE__ */ new Map();
|
|
422
|
+
for (const snap of flattenSnapshots(snapshot)) {
|
|
423
|
+
for (const n of snap.nodes) {
|
|
424
|
+
nodes.set(n.id, n);
|
|
425
|
+
if (!outgoing.has(n.id)) outgoing.set(n.id, /* @__PURE__ */ new Set());
|
|
426
|
+
if (!incoming.has(n.id)) incoming.set(n.id, /* @__PURE__ */ new Set());
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
for (const n of nodes.values()) {
|
|
430
|
+
for (const dep of n.deps) {
|
|
431
|
+
if (!dep || !nodes.has(dep)) continue;
|
|
432
|
+
addEdge(outgoing, dep, n.id);
|
|
433
|
+
addEdge(incoming, n.id, dep);
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
for (const snap of flattenSnapshots(snapshot)) {
|
|
437
|
+
for (const edge of snap.edges) {
|
|
438
|
+
if (!edge.from || !edge.to) continue;
|
|
439
|
+
if (!nodes.has(edge.from) || !nodes.has(edge.to)) continue;
|
|
440
|
+
addEdge(outgoing, edge.from, edge.to);
|
|
441
|
+
addEdge(incoming, edge.to, edge.from);
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
return { nodes, outgoing, incoming };
|
|
445
|
+
}
|
|
446
|
+
function adjacent(idx, id, direction, both) {
|
|
447
|
+
return both === true ? /* @__PURE__ */ new Set([...idx.incoming.get(id) ?? [], ...idx.outgoing.get(id) ?? []]) : direction === "upstream" ? idx.incoming.get(id) ?? /* @__PURE__ */ new Set() : idx.outgoing.get(id) ?? /* @__PURE__ */ new Set();
|
|
448
|
+
}
|
|
449
|
+
function reachable(snapshot, from, direction, options = {}) {
|
|
450
|
+
if (!options.both && direction !== "upstream" && direction !== "downstream") {
|
|
451
|
+
throw new Error(`reachable: direction must be "upstream" or "downstream"`);
|
|
452
|
+
}
|
|
453
|
+
assertMaxDepth("reachable", options.maxDepth);
|
|
454
|
+
const empty = { paths: [], depths: {}, truncated: false };
|
|
455
|
+
if (from === "") return options.withDetail ? empty : empty.paths;
|
|
456
|
+
const idx = indexSnapshot(snapshot);
|
|
457
|
+
if (!idx.nodes.has(from)) return options.withDetail ? empty : empty.paths;
|
|
458
|
+
if (options.maxDepth === 0) {
|
|
459
|
+
const truncated2 = adjacent(idx, from, direction, options.both).size > 0;
|
|
460
|
+
return options.withDetail ? { ...empty, truncated: truncated2 } : empty.paths;
|
|
461
|
+
}
|
|
462
|
+
const depths = /* @__PURE__ */ new Map();
|
|
463
|
+
const seen = /* @__PURE__ */ new Set([from]);
|
|
464
|
+
const queue = [{ id: from, depth: 0 }];
|
|
465
|
+
let truncated = false;
|
|
466
|
+
for (let head = 0; head < queue.length; head += 1) {
|
|
467
|
+
const cur = queue[head];
|
|
468
|
+
const next = adjacent(idx, cur.id, direction, options.both);
|
|
469
|
+
if (options.maxDepth !== void 0 && cur.depth >= options.maxDepth) {
|
|
470
|
+
if (next.size > 0) truncated = true;
|
|
471
|
+
continue;
|
|
472
|
+
}
|
|
473
|
+
for (const id of next) {
|
|
474
|
+
if (seen.has(id)) continue;
|
|
475
|
+
seen.add(id);
|
|
476
|
+
const depth = cur.depth + 1;
|
|
477
|
+
depths.set(id, depth);
|
|
478
|
+
queue.push({ id, depth });
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
const paths = [...depths.keys()].sort(compareCodeUnit);
|
|
482
|
+
if (!options.withDetail) return paths;
|
|
483
|
+
return {
|
|
484
|
+
paths,
|
|
485
|
+
depths: Object.fromEntries([...depths.entries()].sort(([a], [b]) => compareCodeUnit(a, b))),
|
|
486
|
+
truncated
|
|
487
|
+
};
|
|
488
|
+
}
|
|
489
|
+
function depIndices(next, prevId) {
|
|
490
|
+
if (next === void 0) return void 0;
|
|
491
|
+
const indices = [];
|
|
492
|
+
for (let i = 0; i < next.deps.length; i += 1) {
|
|
493
|
+
if (next.deps[i] === prevId) indices.push(i);
|
|
494
|
+
}
|
|
495
|
+
return indices.length > 0 ? indices : void 0;
|
|
496
|
+
}
|
|
497
|
+
function stepFor(node, hop, edgeToNext) {
|
|
498
|
+
const indices = edgeToNext ? depIndices(edgeToNext.next, edgeToNext.prevId) : void 0;
|
|
499
|
+
const out = {
|
|
500
|
+
id: node.id,
|
|
501
|
+
factory: node.factory,
|
|
502
|
+
status: node.status,
|
|
503
|
+
hop
|
|
504
|
+
};
|
|
505
|
+
if ("value" in node) out.value = node.value;
|
|
506
|
+
if (indices !== void 0) {
|
|
507
|
+
out.depIndex = indices[0];
|
|
508
|
+
if (indices.length > 1) out.depIndices = indices;
|
|
509
|
+
}
|
|
510
|
+
return out;
|
|
511
|
+
}
|
|
512
|
+
function makeChain(from, to, reason, steps) {
|
|
513
|
+
const found = reason === "ok";
|
|
514
|
+
const text = found ? steps.map((s) => s.id).join(" -> ") : `explainPath: ${reason} from '${from}' to '${to}'`;
|
|
515
|
+
return {
|
|
516
|
+
from,
|
|
517
|
+
to,
|
|
518
|
+
found,
|
|
519
|
+
reason,
|
|
520
|
+
steps,
|
|
521
|
+
text,
|
|
522
|
+
toJSON: () => ({ from, to, found, reason, steps })
|
|
523
|
+
};
|
|
524
|
+
}
|
|
525
|
+
function shortestPath(idx, from, to, maxDepth) {
|
|
526
|
+
const pred = /* @__PURE__ */ new Map();
|
|
527
|
+
const seen = /* @__PURE__ */ new Set([from]);
|
|
528
|
+
const queue = [{ id: from, depth: 0 }];
|
|
529
|
+
let truncated = false;
|
|
530
|
+
for (let head = 0; head < queue.length; head += 1) {
|
|
531
|
+
const cur = queue[head];
|
|
532
|
+
const next = idx.outgoing.get(cur.id) ?? /* @__PURE__ */ new Set();
|
|
533
|
+
if (maxDepth !== void 0 && cur.depth >= maxDepth) {
|
|
534
|
+
if (next.size > 0) truncated = true;
|
|
535
|
+
continue;
|
|
536
|
+
}
|
|
537
|
+
for (const id of next) {
|
|
538
|
+
if (seen.has(id)) continue;
|
|
539
|
+
seen.add(id);
|
|
540
|
+
pred.set(id, cur.id);
|
|
541
|
+
if (id === to) {
|
|
542
|
+
const path = [to];
|
|
543
|
+
let p = to;
|
|
544
|
+
while (p !== from) {
|
|
545
|
+
p = pred.get(p);
|
|
546
|
+
path.push(p);
|
|
547
|
+
}
|
|
548
|
+
path.reverse();
|
|
549
|
+
return { path, truncated };
|
|
550
|
+
}
|
|
551
|
+
queue.push({ id, depth: cur.depth + 1 });
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
return truncated ? { path: [], truncated: true } : void 0;
|
|
555
|
+
}
|
|
556
|
+
function shortestCycle(idx, from, maxDepth) {
|
|
557
|
+
const first = idx.outgoing.get(from) ?? /* @__PURE__ */ new Set();
|
|
558
|
+
if (maxDepth === 0) return first.size > 0 ? { path: [], truncated: true } : void 0;
|
|
559
|
+
const queue = [];
|
|
560
|
+
const seen = /* @__PURE__ */ new Set();
|
|
561
|
+
for (const id of first) {
|
|
562
|
+
if (id === from) return { path: [from, from], truncated: false };
|
|
563
|
+
seen.add(id);
|
|
564
|
+
queue.push({ id, depth: 1, path: [from, id] });
|
|
565
|
+
}
|
|
566
|
+
let truncated = false;
|
|
567
|
+
for (let head = 0; head < queue.length; head += 1) {
|
|
568
|
+
const cur = queue[head];
|
|
569
|
+
const next = idx.outgoing.get(cur.id) ?? /* @__PURE__ */ new Set();
|
|
570
|
+
if (maxDepth !== void 0 && cur.depth >= maxDepth) {
|
|
571
|
+
if (next.size > 0) truncated = true;
|
|
572
|
+
continue;
|
|
573
|
+
}
|
|
574
|
+
for (const id of next) {
|
|
575
|
+
if (id === from) return { path: [...cur.path, from], truncated: false };
|
|
576
|
+
if (seen.has(id)) continue;
|
|
577
|
+
seen.add(id);
|
|
578
|
+
queue.push({ id, depth: cur.depth + 1, path: [...cur.path, id] });
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
return truncated ? { path: [], truncated: true } : void 0;
|
|
582
|
+
}
|
|
583
|
+
function materializePath(idx, path) {
|
|
584
|
+
return path.map((id, i) => {
|
|
585
|
+
const node = idx.nodes.get(id);
|
|
586
|
+
const next = path[i + 1] ? idx.nodes.get(path[i + 1]) : void 0;
|
|
587
|
+
return stepFor(node, i, next ? { next, prevId: id } : void 0);
|
|
588
|
+
});
|
|
589
|
+
}
|
|
590
|
+
function explainPath(snapshot, from, to, options = {}) {
|
|
591
|
+
assertMaxDepth("explainPath", options.maxDepth);
|
|
592
|
+
const idx = indexSnapshot(snapshot);
|
|
593
|
+
if (!idx.nodes.has(from)) return makeChain(from, to, "no-such-from", []);
|
|
594
|
+
if (!idx.nodes.has(to)) return makeChain(from, to, "no-such-to", []);
|
|
595
|
+
if (options.maxDepth === 0 && from !== to) return makeChain(from, to, "no-path", []);
|
|
596
|
+
if (from === to && options.findCycle !== true) {
|
|
597
|
+
return makeChain(from, to, "ok", [stepFor(idx.nodes.get(from), 0)]);
|
|
598
|
+
}
|
|
599
|
+
if (from === to && options.findCycle === true) {
|
|
600
|
+
const cycle = shortestCycle(idx, from, options.maxDepth);
|
|
601
|
+
if (cycle !== void 0 && cycle.path.length > 0) {
|
|
602
|
+
return makeChain(from, to, "ok", materializePath(idx, cycle.path));
|
|
603
|
+
}
|
|
604
|
+
if (cycle?.truncated) return makeChain(from, to, "max-depth-exceeded", []);
|
|
605
|
+
return makeChain(from, to, "ok", [stepFor(idx.nodes.get(from), 0)]);
|
|
606
|
+
}
|
|
607
|
+
const found = shortestPath(idx, from, to, options.maxDepth);
|
|
608
|
+
if (found !== void 0 && found.path.length > 0) {
|
|
609
|
+
return makeChain(from, to, "ok", materializePath(idx, found.path));
|
|
610
|
+
}
|
|
611
|
+
return makeChain(from, to, found?.truncated ? "max-depth-exceeded" : "no-path", []);
|
|
612
|
+
}
|
|
613
|
+
function validateNoIslands(snapshot) {
|
|
614
|
+
const idx = indexSnapshot(snapshot);
|
|
615
|
+
const orphans = [];
|
|
616
|
+
for (const node of idx.nodes.values()) {
|
|
617
|
+
const hasDeps = node.deps.length > 0 || (idx.incoming.get(node.id)?.size ?? 0) > 0;
|
|
618
|
+
const hasDependents = (idx.outgoing.get(node.id)?.size ?? 0) > 0;
|
|
619
|
+
if (!hasDeps && !hasDependents && !node.id.startsWith("__internal__/")) {
|
|
620
|
+
orphans.push({ id: node.id, factory: node.factory });
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
orphans.sort((a, b) => compareCodeUnit(a.id, b.id));
|
|
624
|
+
return {
|
|
625
|
+
ok: orphans.length === 0,
|
|
626
|
+
orphans,
|
|
627
|
+
summary() {
|
|
628
|
+
if (orphans.length === 0) return "validateNoIslands: ok (no islands)";
|
|
629
|
+
const head = orphans.slice(0, 3).map((o) => `${o.id} (${o.factory})`).join(", ");
|
|
630
|
+
return `validateNoIslands: ${orphans.length} island node(s) - ${head}${orphans.length > 3 ? ", ..." : ""}`;
|
|
631
|
+
}
|
|
632
|
+
};
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
// src/graph/inspect.ts
|
|
636
|
+
function filterObserve(stream, predicate) {
|
|
637
|
+
return {
|
|
638
|
+
subscribe(sink) {
|
|
639
|
+
return stream.subscribe((event) => {
|
|
640
|
+
if (predicate(event)) {
|
|
641
|
+
sink(event);
|
|
642
|
+
}
|
|
643
|
+
});
|
|
644
|
+
}
|
|
645
|
+
};
|
|
646
|
+
}
|
|
647
|
+
function sameObserveEvent(prev, next) {
|
|
648
|
+
return prev.path === next.path && prev.tier === next.tier && prev.msg[0] === next.msg[0] && Object.is(messagePayload(prev.msg), messagePayload(next.msg));
|
|
649
|
+
}
|
|
650
|
+
function messagePayload(msg) {
|
|
651
|
+
return msg.length > 1 ? msg[1] : void 0;
|
|
652
|
+
}
|
|
653
|
+
function coalesceObserve(stream, equals = sameObserveEvent) {
|
|
654
|
+
return {
|
|
655
|
+
subscribe(sink) {
|
|
656
|
+
let previous;
|
|
657
|
+
return stream.subscribe((event) => {
|
|
658
|
+
if (previous && equals(previous, event)) {
|
|
659
|
+
return;
|
|
660
|
+
}
|
|
661
|
+
previous = event;
|
|
662
|
+
sink(event);
|
|
663
|
+
});
|
|
664
|
+
}
|
|
665
|
+
};
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
// src/graph/restore.ts
|
|
669
|
+
var stateRestoreDescriptor = {
|
|
670
|
+
ref: "state",
|
|
671
|
+
validateConfig(config, configVersion) {
|
|
672
|
+
if (config !== void 0 || configVersion !== void 0) {
|
|
673
|
+
throw new Error("restoreGraph: built-in state descriptor does not accept config");
|
|
674
|
+
}
|
|
675
|
+
return void 0;
|
|
676
|
+
},
|
|
677
|
+
create(ctx) {
|
|
678
|
+
if (ctx.deps.length !== 0) {
|
|
679
|
+
throw new Error(`restoreGraph: state node '${ctx.checkpoint.id}' cannot restore deps`);
|
|
680
|
+
}
|
|
681
|
+
return ctx.registerState({
|
|
682
|
+
name: ctx.name,
|
|
683
|
+
meta: ctx.checkpoint.meta
|
|
684
|
+
});
|
|
685
|
+
}
|
|
686
|
+
};
|
|
687
|
+
function objectConfig(config, ref) {
|
|
688
|
+
if (config === void 0 || config === null || Array.isArray(config) || typeof config !== "object") {
|
|
689
|
+
throw new Error(`restoreGraph: '${ref}' descriptor requires object config`);
|
|
690
|
+
}
|
|
691
|
+
return config;
|
|
692
|
+
}
|
|
693
|
+
function finiteNumber(value, ref, key) {
|
|
694
|
+
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
695
|
+
throw new Error(`restoreGraph: '${ref}' config.${key} must be a finite number`);
|
|
696
|
+
}
|
|
697
|
+
return value;
|
|
698
|
+
}
|
|
699
|
+
var takeRestoreDescriptor = {
|
|
700
|
+
ref: "take",
|
|
701
|
+
validateConfig(config, configVersion) {
|
|
702
|
+
if (configVersion !== void 0) {
|
|
703
|
+
throw new Error("restoreGraph: built-in take descriptor does not accept configVersion");
|
|
704
|
+
}
|
|
705
|
+
return { n: finiteNumber(objectConfig(config, "take").n, "take", "n") };
|
|
706
|
+
},
|
|
707
|
+
create(ctx) {
|
|
708
|
+
if (ctx.deps.length !== 1) {
|
|
709
|
+
throw new Error(`restoreGraph: take node '${ctx.checkpoint.id}' requires exactly one dep`);
|
|
710
|
+
}
|
|
711
|
+
const op = take(ctx.config.n);
|
|
712
|
+
return ctx.registerNode("take", ctx.deps, operatorNodeFn(op), {
|
|
713
|
+
name: ctx.name,
|
|
714
|
+
meta: ctx.checkpoint.meta,
|
|
715
|
+
restore: op.restore
|
|
716
|
+
});
|
|
717
|
+
}
|
|
718
|
+
};
|
|
719
|
+
var mapRestoreDescriptor = {
|
|
720
|
+
ref: "map",
|
|
721
|
+
validateConfig(config, configVersion) {
|
|
722
|
+
if (configVersion !== void 0) {
|
|
723
|
+
throw new Error("restoreGraph: built-in map descriptor does not accept configVersion");
|
|
724
|
+
}
|
|
725
|
+
const obj = objectConfig(config, "map");
|
|
726
|
+
if (typeof obj.fn !== "string") {
|
|
727
|
+
throw new Error("restoreGraph: 'map' config.fn must be a string definition ref");
|
|
728
|
+
}
|
|
729
|
+
return { fn: obj.fn };
|
|
730
|
+
},
|
|
731
|
+
create(ctx) {
|
|
732
|
+
if (ctx.deps.length !== 1) {
|
|
733
|
+
throw new Error(`restoreGraph: map node '${ctx.checkpoint.id}' requires exactly one dep`);
|
|
734
|
+
}
|
|
735
|
+
const definition = ctx.resolveDefinition(ctx.config.fn);
|
|
736
|
+
const op = map(definition);
|
|
737
|
+
return ctx.registerNode("map", ctx.deps, operatorNodeFn(op), {
|
|
738
|
+
name: ctx.name,
|
|
739
|
+
meta: ctx.checkpoint.meta,
|
|
740
|
+
restore: op.restore
|
|
741
|
+
});
|
|
742
|
+
}
|
|
743
|
+
};
|
|
744
|
+
var timerRestoreDescriptor = {
|
|
745
|
+
ref: "timer",
|
|
746
|
+
validateConfig(config, configVersion) {
|
|
747
|
+
if (configVersion !== void 0) {
|
|
748
|
+
throw new Error("restoreGraph: built-in timer descriptor does not accept configVersion");
|
|
749
|
+
}
|
|
750
|
+
return { ms: finiteNumber(objectConfig(config, "timer").ms, "timer", "ms") };
|
|
751
|
+
},
|
|
752
|
+
create(ctx) {
|
|
753
|
+
if (ctx.deps.length !== 0) {
|
|
754
|
+
throw new Error(`restoreGraph: timer node '${ctx.checkpoint.id}' cannot restore deps`);
|
|
755
|
+
}
|
|
756
|
+
const op = timer(ctx.config.ms);
|
|
757
|
+
return ctx.registerNode("timer", ctx.deps, operatorNodeFn(op), {
|
|
758
|
+
name: ctx.name,
|
|
759
|
+
meta: ctx.checkpoint.meta,
|
|
760
|
+
restore: op.restore,
|
|
761
|
+
...op.opts
|
|
762
|
+
});
|
|
763
|
+
}
|
|
764
|
+
};
|
|
765
|
+
var restoredCollections = /* @__PURE__ */ new WeakMap();
|
|
766
|
+
function restoredCollectionMap(graph2) {
|
|
767
|
+
let map2 = restoredCollections.get(graph2);
|
|
768
|
+
if (map2 === void 0) {
|
|
769
|
+
map2 = /* @__PURE__ */ new Map();
|
|
770
|
+
restoredCollections.set(graph2, map2);
|
|
771
|
+
}
|
|
772
|
+
return map2;
|
|
773
|
+
}
|
|
774
|
+
function clearRestoredCollectionMap(graph2) {
|
|
775
|
+
restoredCollections.delete(graph2);
|
|
776
|
+
}
|
|
777
|
+
function collectionBaseId(id, suffix, ref) {
|
|
778
|
+
if (!id.endsWith(suffix)) {
|
|
779
|
+
throw new Error(`restoreGraph: '${ref}' node '${id}' must end with '${suffix}'`);
|
|
780
|
+
}
|
|
781
|
+
const base = id.slice(0, -suffix.length);
|
|
782
|
+
if (base.length === 0) {
|
|
783
|
+
throw new Error(`restoreGraph: '${ref}' node '${id}' has no collection name`);
|
|
784
|
+
}
|
|
785
|
+
return base;
|
|
786
|
+
}
|
|
787
|
+
function noCollectionConfig(config, configVersion, ref) {
|
|
788
|
+
if (config !== void 0 || configVersion !== void 0) {
|
|
789
|
+
throw new Error(`restoreGraph: '${ref}' descriptor does not accept config`);
|
|
790
|
+
}
|
|
791
|
+
return void 0;
|
|
792
|
+
}
|
|
793
|
+
function backendArray(checkpoint, ref) {
|
|
794
|
+
const state = checkpoint.backendState;
|
|
795
|
+
if (!Array.isArray(state)) {
|
|
796
|
+
throw new Error(`restoreGraph: '${ref}' node '${checkpoint.id}' requires array backendState`);
|
|
797
|
+
}
|
|
798
|
+
return state;
|
|
799
|
+
}
|
|
800
|
+
function primitiveJsonKey(value, path) {
|
|
801
|
+
if (value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
802
|
+
return value;
|
|
803
|
+
}
|
|
804
|
+
throw new Error(`restoreGraph: ${path} must be a JSON primitive primary key`);
|
|
805
|
+
}
|
|
806
|
+
function indexRows(checkpoint, ref) {
|
|
807
|
+
const rows = [];
|
|
808
|
+
const seen = /* @__PURE__ */ new Set();
|
|
809
|
+
for (const [i, row] of backendArray(checkpoint, ref).entries()) {
|
|
810
|
+
const path = `${checkpoint.id}.backendState[${i}]`;
|
|
811
|
+
if (row === null || Array.isArray(row) || typeof row !== "object") {
|
|
812
|
+
throw new Error(`restoreGraph: ${path} must be an index row object`);
|
|
813
|
+
}
|
|
814
|
+
if (!Object.hasOwn(row, "primary") || !Object.hasOwn(row, "secondary") || !Object.hasOwn(row, "value")) {
|
|
815
|
+
throw new Error(`restoreGraph: ${path} must contain primary, secondary, and value`);
|
|
816
|
+
}
|
|
817
|
+
const obj = row;
|
|
818
|
+
const primary = primitiveJsonKey(obj.primary, `${path}.primary`);
|
|
819
|
+
const stablePrimary = JSON.stringify(primary);
|
|
820
|
+
if (seen.has(stablePrimary)) {
|
|
821
|
+
throw new Error(`restoreGraph: ${path}.primary duplicates an earlier index row`);
|
|
822
|
+
}
|
|
823
|
+
seen.add(stablePrimary);
|
|
824
|
+
rows.push({
|
|
825
|
+
primary,
|
|
826
|
+
secondary: obj.secondary,
|
|
827
|
+
value: obj.value
|
|
828
|
+
});
|
|
829
|
+
}
|
|
830
|
+
return rows;
|
|
831
|
+
}
|
|
832
|
+
function stableJsonKey(value) {
|
|
833
|
+
return Array.from(strictCanonicalJsonBytes(value)).join(",");
|
|
834
|
+
}
|
|
835
|
+
function mapEntries(checkpoint, ref) {
|
|
836
|
+
const entries = [];
|
|
837
|
+
const seen = /* @__PURE__ */ new Set();
|
|
838
|
+
for (const [i, entry] of backendArray(checkpoint, ref).entries()) {
|
|
839
|
+
const path = `${checkpoint.id}.backendState[${i}]`;
|
|
840
|
+
if (!Array.isArray(entry) || entry.length !== 2) {
|
|
841
|
+
throw new Error(`restoreGraph: ${path} must be a [key, value] map entry`);
|
|
842
|
+
}
|
|
843
|
+
const key = entry[0];
|
|
844
|
+
const stableKey = stableJsonKey(key);
|
|
845
|
+
if (seen.has(stableKey)) {
|
|
846
|
+
throw new Error(`restoreGraph: ${path}[0] duplicates an earlier map key`);
|
|
847
|
+
}
|
|
848
|
+
seen.add(stableKey);
|
|
849
|
+
entries.push([key, entry[1]]);
|
|
850
|
+
}
|
|
851
|
+
return entries;
|
|
852
|
+
}
|
|
853
|
+
function restoredList(ctx, ref) {
|
|
854
|
+
const base = collectionBaseId(ctx.id, ".delta", ref);
|
|
855
|
+
if (ctx.deps.length !== 0) {
|
|
856
|
+
throw new Error(`restoreGraph: '${ref}' node '${ctx.id}' cannot restore deps`);
|
|
857
|
+
}
|
|
858
|
+
const collection = reactiveList(backendArray(ctx.checkpoint, ref), {
|
|
859
|
+
graph: ctx.graph,
|
|
860
|
+
name: base
|
|
861
|
+
});
|
|
862
|
+
restoredCollectionMap(ctx.graph).set(base, { kind: "reactiveList", collection });
|
|
863
|
+
return collection;
|
|
864
|
+
}
|
|
865
|
+
function restoredIndex(ctx, ref) {
|
|
866
|
+
const base = collectionBaseId(ctx.id, ".delta", ref);
|
|
867
|
+
if (ctx.deps.length !== 0) {
|
|
868
|
+
throw new Error(`restoreGraph: '${ref}' node '${ctx.id}' cannot restore deps`);
|
|
869
|
+
}
|
|
870
|
+
const rows = indexRows(ctx.checkpoint, ref);
|
|
871
|
+
const collection = restoreReactiveIndexFromBackendState(rows, {
|
|
872
|
+
graph: ctx.graph,
|
|
873
|
+
name: base
|
|
874
|
+
});
|
|
875
|
+
restoredCollectionMap(ctx.graph).set(base, { kind: "reactiveIndex", collection });
|
|
876
|
+
return collection;
|
|
877
|
+
}
|
|
878
|
+
function restoredLog(ctx, ref) {
|
|
879
|
+
const base = collectionBaseId(ctx.id, ".delta", ref);
|
|
880
|
+
if (ctx.deps.length !== 0) {
|
|
881
|
+
throw new Error(`restoreGraph: '${ref}' node '${ctx.id}' cannot restore deps`);
|
|
882
|
+
}
|
|
883
|
+
const state = backendArray(ctx.checkpoint, ref);
|
|
884
|
+
if (ctx.config.maxSize !== void 0 && state.length > ctx.config.maxSize) {
|
|
885
|
+
throw new Error(`restoreGraph: '${ref}' node '${ctx.id}' backendState exceeds config.maxSize`);
|
|
886
|
+
}
|
|
887
|
+
const collection = reactiveLog(state, {
|
|
888
|
+
graph: ctx.graph,
|
|
889
|
+
name: base,
|
|
890
|
+
...ctx.config.maxSize !== void 0 ? { maxSize: ctx.config.maxSize } : {}
|
|
891
|
+
});
|
|
892
|
+
restoredCollectionMap(ctx.graph).set(base, { kind: "reactiveLog", collection });
|
|
893
|
+
return collection;
|
|
894
|
+
}
|
|
895
|
+
function restoredMapNode(ctx, ref) {
|
|
896
|
+
const base = collectionBaseId(ctx.id, ".intent", ref);
|
|
897
|
+
if (ctx.deps.length !== 0) {
|
|
898
|
+
throw new Error(`restoreGraph: '${ref}' node '${ctx.id}' cannot restore deps`);
|
|
899
|
+
}
|
|
900
|
+
const entries = mapEntries(ctx.checkpoint, ref);
|
|
901
|
+
const collection = restoreReactiveMapFromBackendState(entries, {
|
|
902
|
+
graph: ctx.graph,
|
|
903
|
+
name: base
|
|
904
|
+
});
|
|
905
|
+
restoredCollectionMap(ctx.graph).set(base, { kind: "reactiveMap", collection });
|
|
906
|
+
const node = ctx.graph.find(ctx.id);
|
|
907
|
+
if (node === void 0) {
|
|
908
|
+
throw new Error(`restoreGraph: '${ref}' node '${ctx.id}' was not restored`);
|
|
909
|
+
}
|
|
910
|
+
return node;
|
|
911
|
+
}
|
|
912
|
+
function existingMapNode(ctx, ref, suffix) {
|
|
913
|
+
const base = collectionBaseId(ctx.id, suffix, ref);
|
|
914
|
+
const item = restoredCollectionMap(ctx.graph).get(base);
|
|
915
|
+
if (item === void 0 || item.kind !== "reactiveMap") {
|
|
916
|
+
throw new Error(`restoreGraph: '${ref}' node '${ctx.id}' is missing restored '${base}.intent'`);
|
|
917
|
+
}
|
|
918
|
+
const node = ctx.graph.find(ctx.id);
|
|
919
|
+
if (node === void 0) {
|
|
920
|
+
throw new Error(`restoreGraph: '${ref}' node '${ctx.id}' was not restored`);
|
|
921
|
+
}
|
|
922
|
+
return node;
|
|
923
|
+
}
|
|
924
|
+
function existingCollection(ctx, ref, kind) {
|
|
925
|
+
const base = collectionBaseId(ctx.id, ".snapshot", ref);
|
|
926
|
+
if (ctx.deps.length !== 1) {
|
|
927
|
+
throw new Error(`restoreGraph: '${ref}' node '${ctx.id}' requires exactly one dep`);
|
|
928
|
+
}
|
|
929
|
+
const item = restoredCollectionMap(ctx.graph).get(base);
|
|
930
|
+
if (item === void 0 || item.kind !== kind) {
|
|
931
|
+
throw new Error(`restoreGraph: '${ref}' node '${ctx.id}' is missing restored '${base}.delta'`);
|
|
932
|
+
}
|
|
933
|
+
return item;
|
|
934
|
+
}
|
|
935
|
+
function validateLogConfig(config, configVersion, ref) {
|
|
936
|
+
if (configVersion !== void 0) {
|
|
937
|
+
throw new Error(`restoreGraph: '${ref}' descriptor does not accept configVersion`);
|
|
938
|
+
}
|
|
939
|
+
if (config === void 0) return {};
|
|
940
|
+
const obj = objectConfig(config, ref);
|
|
941
|
+
if (obj.maxSize === void 0) return {};
|
|
942
|
+
const maxSize = finiteNumber(obj.maxSize, ref, "maxSize");
|
|
943
|
+
if (!Number.isInteger(maxSize) || maxSize < 1) {
|
|
944
|
+
throw new Error(`restoreGraph: '${ref}' config.maxSize must be a positive integer`);
|
|
945
|
+
}
|
|
946
|
+
return { maxSize };
|
|
947
|
+
}
|
|
948
|
+
var reactiveListDeltaRestoreDescriptor = {
|
|
949
|
+
ref: "reactiveList.delta",
|
|
950
|
+
validateConfig(config, configVersion) {
|
|
951
|
+
return noCollectionConfig(config, configVersion, "reactiveList.delta");
|
|
952
|
+
},
|
|
953
|
+
create(ctx) {
|
|
954
|
+
return restoredList(ctx, "reactiveList.delta").delta;
|
|
955
|
+
}
|
|
956
|
+
};
|
|
957
|
+
var reactiveListSnapshotRestoreDescriptor = {
|
|
958
|
+
ref: "reactiveList.snapshot",
|
|
959
|
+
validateConfig(config, configVersion) {
|
|
960
|
+
return noCollectionConfig(config, configVersion, "reactiveList.snapshot");
|
|
961
|
+
},
|
|
962
|
+
create(ctx) {
|
|
963
|
+
return existingCollection(ctx, "reactiveList.snapshot", "reactiveList").collection.snapshot;
|
|
964
|
+
}
|
|
965
|
+
};
|
|
966
|
+
var reactiveIndexDeltaRestoreDescriptor = {
|
|
967
|
+
ref: "reactiveIndex.delta",
|
|
968
|
+
validateConfig(config, configVersion) {
|
|
969
|
+
return noCollectionConfig(config, configVersion, "reactiveIndex.delta");
|
|
970
|
+
},
|
|
971
|
+
create(ctx) {
|
|
972
|
+
return restoredIndex(ctx, "reactiveIndex.delta").delta;
|
|
973
|
+
}
|
|
974
|
+
};
|
|
975
|
+
var reactiveIndexSnapshotRestoreDescriptor = {
|
|
976
|
+
ref: "reactiveIndex.snapshot",
|
|
977
|
+
validateConfig(config, configVersion) {
|
|
978
|
+
return noCollectionConfig(config, configVersion, "reactiveIndex.snapshot");
|
|
979
|
+
},
|
|
980
|
+
create(ctx) {
|
|
981
|
+
return existingCollection(ctx, "reactiveIndex.snapshot", "reactiveIndex").collection.snapshot;
|
|
982
|
+
}
|
|
983
|
+
};
|
|
984
|
+
var reactiveLogDeltaRestoreDescriptor = {
|
|
985
|
+
ref: "reactiveLog.delta",
|
|
986
|
+
validateConfig(config, configVersion) {
|
|
987
|
+
return validateLogConfig(config, configVersion, "reactiveLog.delta");
|
|
988
|
+
},
|
|
989
|
+
create(ctx) {
|
|
990
|
+
return restoredLog(ctx, "reactiveLog.delta").delta;
|
|
991
|
+
}
|
|
992
|
+
};
|
|
993
|
+
var reactiveLogSnapshotRestoreDescriptor = {
|
|
994
|
+
ref: "reactiveLog.snapshot",
|
|
995
|
+
validateConfig(config, configVersion) {
|
|
996
|
+
return validateLogConfig(config, configVersion, "reactiveLog.snapshot");
|
|
997
|
+
},
|
|
998
|
+
create(ctx) {
|
|
999
|
+
return existingCollection(ctx, "reactiveLog.snapshot", "reactiveLog").collection.snapshot;
|
|
1000
|
+
}
|
|
1001
|
+
};
|
|
1002
|
+
var reactiveMapIntentRestoreDescriptor = {
|
|
1003
|
+
ref: "reactiveMap.intent",
|
|
1004
|
+
validateConfig(config, configVersion) {
|
|
1005
|
+
return noCollectionConfig(config, configVersion, "reactiveMap.intent");
|
|
1006
|
+
},
|
|
1007
|
+
create(ctx) {
|
|
1008
|
+
return restoredMapNode(ctx, "reactiveMap.intent");
|
|
1009
|
+
}
|
|
1010
|
+
};
|
|
1011
|
+
var reactiveMapApplyRestoreDescriptor = {
|
|
1012
|
+
ref: "reactiveMap.apply",
|
|
1013
|
+
validateConfig(config, configVersion) {
|
|
1014
|
+
return noCollectionConfig(config, configVersion, "reactiveMap.apply");
|
|
1015
|
+
},
|
|
1016
|
+
create(ctx) {
|
|
1017
|
+
return existingMapNode(ctx, "reactiveMap.apply", ".apply");
|
|
1018
|
+
}
|
|
1019
|
+
};
|
|
1020
|
+
var reactiveMapSnapshotPrepRestoreDescriptor = {
|
|
1021
|
+
ref: "reactiveMap.snapshotPrep",
|
|
1022
|
+
validateConfig(config, configVersion) {
|
|
1023
|
+
return noCollectionConfig(config, configVersion, "reactiveMap.snapshotPrep");
|
|
1024
|
+
},
|
|
1025
|
+
create(ctx) {
|
|
1026
|
+
return existingMapNode(ctx, "reactiveMap.snapshotPrep", ".snapshotPrep");
|
|
1027
|
+
}
|
|
1028
|
+
};
|
|
1029
|
+
var reactiveMapDeltaRestoreDescriptor = {
|
|
1030
|
+
ref: "reactiveMap.delta",
|
|
1031
|
+
validateConfig(config, configVersion) {
|
|
1032
|
+
return noCollectionConfig(config, configVersion, "reactiveMap.delta");
|
|
1033
|
+
},
|
|
1034
|
+
create(ctx) {
|
|
1035
|
+
return existingMapNode(ctx, "reactiveMap.delta", ".delta");
|
|
1036
|
+
}
|
|
1037
|
+
};
|
|
1038
|
+
var reactiveMapSnapshotRestoreDescriptor = {
|
|
1039
|
+
ref: "reactiveMap.snapshot",
|
|
1040
|
+
validateConfig(config, configVersion) {
|
|
1041
|
+
return noCollectionConfig(config, configVersion, "reactiveMap.snapshot");
|
|
1042
|
+
},
|
|
1043
|
+
create(ctx) {
|
|
1044
|
+
return existingMapNode(ctx, "reactiveMap.snapshot", ".snapshot");
|
|
1045
|
+
}
|
|
1046
|
+
};
|
|
1047
|
+
var defaultRestoreRegistry = {
|
|
1048
|
+
state: stateRestoreDescriptor,
|
|
1049
|
+
map: mapRestoreDescriptor,
|
|
1050
|
+
take: takeRestoreDescriptor,
|
|
1051
|
+
timer: timerRestoreDescriptor,
|
|
1052
|
+
"reactiveList.delta": reactiveListDeltaRestoreDescriptor,
|
|
1053
|
+
"reactiveList.snapshot": reactiveListSnapshotRestoreDescriptor,
|
|
1054
|
+
"reactiveIndex.delta": reactiveIndexDeltaRestoreDescriptor,
|
|
1055
|
+
"reactiveIndex.snapshot": reactiveIndexSnapshotRestoreDescriptor,
|
|
1056
|
+
"reactiveLog.delta": reactiveLogDeltaRestoreDescriptor,
|
|
1057
|
+
"reactiveLog.snapshot": reactiveLogSnapshotRestoreDescriptor,
|
|
1058
|
+
"reactiveMap.intent": reactiveMapIntentRestoreDescriptor,
|
|
1059
|
+
"reactiveMap.apply": reactiveMapApplyRestoreDescriptor,
|
|
1060
|
+
"reactiveMap.snapshotPrep": reactiveMapSnapshotPrepRestoreDescriptor,
|
|
1061
|
+
"reactiveMap.delta": reactiveMapDeltaRestoreDescriptor,
|
|
1062
|
+
"reactiveMap.snapshot": reactiveMapSnapshotRestoreDescriptor
|
|
1063
|
+
};
|
|
1064
|
+
function registryGet(registry, ref) {
|
|
1065
|
+
return registry instanceof Map ? registry.get(ref) : registry[ref];
|
|
1066
|
+
}
|
|
1067
|
+
function isRestoreDescriptor(entry) {
|
|
1068
|
+
return entry !== void 0 && "create" in entry;
|
|
1069
|
+
}
|
|
1070
|
+
function isRestoreDefinition(entry) {
|
|
1071
|
+
return entry !== void 0 && "kind" in entry && entry.kind === "definition";
|
|
1072
|
+
}
|
|
1073
|
+
function assertString(value, label) {
|
|
1074
|
+
if (typeof value !== "string") throw new Error(`restoreGraph: ${label} must be a string`);
|
|
1075
|
+
return value;
|
|
1076
|
+
}
|
|
1077
|
+
function assertStatus(value, id) {
|
|
1078
|
+
if (value !== "sentinel" && value !== "pending" && value !== "dirty" && value !== "settled" && value !== "resolved" && value !== "completed" && value !== "errored") {
|
|
1079
|
+
throw new Error(`restoreGraph: node '${id}' has invalid status '${value}'`);
|
|
1080
|
+
}
|
|
1081
|
+
if (value === "pending" || value === "dirty") {
|
|
1082
|
+
throw new Error(
|
|
1083
|
+
`restoreGraph: node '${id}' has non-quiescent status '${value}' that cannot be checkpoint-restored yet`
|
|
1084
|
+
);
|
|
1085
|
+
}
|
|
1086
|
+
return value;
|
|
1087
|
+
}
|
|
1088
|
+
function checkpointDataValue(value, id) {
|
|
1089
|
+
if (value.kind === "SENTINEL") return { cache: SENTINEL, hasData: false };
|
|
1090
|
+
if (value.kind === "DATA") return { cache: value.data, hasData: true };
|
|
1091
|
+
throw new Error(`restoreGraph: node '${id}' has invalid checkpoint value`);
|
|
1092
|
+
}
|
|
1093
|
+
function checkpointTerminal(value, id) {
|
|
1094
|
+
if (value.kind === "none") return void 0;
|
|
1095
|
+
if (value.kind === "COMPLETE") return true;
|
|
1096
|
+
if (value.kind === "ERROR") return value.error;
|
|
1097
|
+
throw new Error(`restoreGraph: node '${id}' has invalid terminal state`);
|
|
1098
|
+
}
|
|
1099
|
+
function prepareRuntime(node) {
|
|
1100
|
+
const nonAuthoritativeCollectionHelper = isCollectionHelperNonAuthoritative(node);
|
|
1101
|
+
const value = nonAuthoritativeCollectionHelper ? { cache: SENTINEL, hasData: false } : checkpointDataValue(node.value, node.id);
|
|
1102
|
+
const terminal = checkpointTerminal(node.terminal, node.id);
|
|
1103
|
+
const status = assertStatus(node.status, node.id);
|
|
1104
|
+
if (terminal === true && status !== "completed") {
|
|
1105
|
+
throw new Error(`restoreGraph: node '${node.id}' COMPLETE terminal requires completed status`);
|
|
1106
|
+
}
|
|
1107
|
+
if (terminal !== void 0 && terminal !== true && status !== "errored") {
|
|
1108
|
+
throw new Error(`restoreGraph: node '${node.id}' ERROR terminal requires errored status`);
|
|
1109
|
+
}
|
|
1110
|
+
if (terminal === void 0 && (status === "completed" || status === "errored")) {
|
|
1111
|
+
throw new Error(`restoreGraph: node '${node.id}' terminal status requires terminal state`);
|
|
1112
|
+
}
|
|
1113
|
+
if (typeof node.lifecycle.activated !== "boolean") {
|
|
1114
|
+
throw new Error(`restoreGraph: node '${node.id}' lifecycle.activated must be boolean`);
|
|
1115
|
+
}
|
|
1116
|
+
if (typeof node.lifecycle.hasCalledFnOnce !== "boolean") {
|
|
1117
|
+
throw new Error(`restoreGraph: node '${node.id}' lifecycle.hasCalledFnOnce must be boolean`);
|
|
1118
|
+
}
|
|
1119
|
+
if (typeof node.ctxState.persist !== "boolean") {
|
|
1120
|
+
throw new Error(`restoreGraph: node '${node.id}' ctxState.persist must be boolean`);
|
|
1121
|
+
}
|
|
1122
|
+
const ctxState = nonAuthoritativeCollectionHelper ? { cache: SENTINEL, hasData: false } : checkpointDataValue(node.ctxState.value, `${node.id}.ctxState`);
|
|
1123
|
+
const version = node.version === void 0 ? false : validateNodeVersionJson(node.version, `${node.id}.version`);
|
|
1124
|
+
return {
|
|
1125
|
+
cache: value.cache,
|
|
1126
|
+
hasData: value.hasData,
|
|
1127
|
+
status,
|
|
1128
|
+
terminal,
|
|
1129
|
+
hasCalledFnOnce: node.lifecycle.hasCalledFnOnce,
|
|
1130
|
+
ctxState: { value: ctxState.cache, persist: node.ctxState.persist },
|
|
1131
|
+
version
|
|
1132
|
+
};
|
|
1133
|
+
}
|
|
1134
|
+
function isCollectionHelperNonAuthoritative(node) {
|
|
1135
|
+
if (node.factory.kind !== "registry-ref") return false;
|
|
1136
|
+
return node.factory.ref === "reactiveList.delta" || node.factory.ref === "reactiveList.snapshot" || node.factory.ref === "reactiveIndex.delta" || node.factory.ref === "reactiveIndex.snapshot" || node.factory.ref === "reactiveLog.delta" || node.factory.ref === "reactiveLog.snapshot" || node.factory.ref === "reactiveMap.intent" || node.factory.ref === "reactiveMap.apply" || node.factory.ref === "reactiveMap.delta" || node.factory.ref === "reactiveMap.snapshotPrep" || node.factory.ref === "reactiveMap.snapshot";
|
|
1137
|
+
}
|
|
1138
|
+
function validateFactory(factory, registry, id) {
|
|
1139
|
+
if (factory.kind === "local-only") {
|
|
1140
|
+
throw new Error(
|
|
1141
|
+
`restoreGraph: node '${id}' uses local-only factory '${factory.name}' (${factory.reason})`
|
|
1142
|
+
);
|
|
1143
|
+
}
|
|
1144
|
+
const ref = assertString(factory.ref, `factory ref for node '${id}'`);
|
|
1145
|
+
const entry = registryGet(registry, ref);
|
|
1146
|
+
if (!isRestoreDescriptor(entry)) {
|
|
1147
|
+
throw new Error(`restoreGraph: missing registry descriptor for '${ref}' (node '${id}')`);
|
|
1148
|
+
}
|
|
1149
|
+
const descriptor = entry;
|
|
1150
|
+
if (descriptor.ref !== ref) {
|
|
1151
|
+
throw new Error(
|
|
1152
|
+
`restoreGraph: registry descriptor for '${ref}' reports ref '${descriptor.ref}'`
|
|
1153
|
+
);
|
|
1154
|
+
}
|
|
1155
|
+
if (factory.config !== void 0) toCheckpointJson(factory.config, `${id}.factory.config`);
|
|
1156
|
+
if (factory.configVersion !== void 0)
|
|
1157
|
+
toCheckpointJson(factory.configVersion, `${id}.factory.configVersion`);
|
|
1158
|
+
return descriptor;
|
|
1159
|
+
}
|
|
1160
|
+
function resolveDefinition(registry, ref, nodeId) {
|
|
1161
|
+
const entry = registryGet(registry, ref);
|
|
1162
|
+
if (!isRestoreDefinition(entry)) {
|
|
1163
|
+
throw new Error(`restoreGraph: missing function definition for '${ref}' (node '${nodeId}')`);
|
|
1164
|
+
}
|
|
1165
|
+
return entry;
|
|
1166
|
+
}
|
|
1167
|
+
function prepareCheckpoint(checkpoint, registry, path = "checkpoint", mountAt) {
|
|
1168
|
+
if (checkpoint.version !== GRAPH_CHECKPOINT_VERSION) {
|
|
1169
|
+
throw new Error(`restoreGraph: unsupported checkpoint version at ${path}`);
|
|
1170
|
+
}
|
|
1171
|
+
toCheckpointJson(checkpoint, path);
|
|
1172
|
+
const nodes = /* @__PURE__ */ new Map();
|
|
1173
|
+
const localIds = /* @__PURE__ */ new Set();
|
|
1174
|
+
for (const node of checkpoint.nodes) {
|
|
1175
|
+
assertString(node.id, `${path}.nodes[].id`);
|
|
1176
|
+
if (nodes.has(node.id)) throw new Error(`restoreGraph: duplicate node id '${node.id}'`);
|
|
1177
|
+
if (mountAt !== void 0 && node.id.startsWith(`${mountAt}::`)) {
|
|
1178
|
+
throw new Error(
|
|
1179
|
+
`restoreGraph: mounted checkpoint at '${mountAt}' must use child-local node id '${node.id.slice(`${mountAt}::`.length)}', not '${node.id}'`
|
|
1180
|
+
);
|
|
1181
|
+
}
|
|
1182
|
+
const id = node.id;
|
|
1183
|
+
if (localIds.has(id)) {
|
|
1184
|
+
throw new Error(`restoreGraph: duplicate restored local node id '${id}'`);
|
|
1185
|
+
}
|
|
1186
|
+
localIds.add(id);
|
|
1187
|
+
const factory = node.factory;
|
|
1188
|
+
const descriptor = validateFactory(factory, registry, node.id);
|
|
1189
|
+
const rawConfig = factory.kind === "registry-ref" ? factory.config : void 0;
|
|
1190
|
+
const configVersion = factory.kind === "registry-ref" ? factory.configVersion : void 0;
|
|
1191
|
+
const config = descriptor.validateConfig ? descriptor.validateConfig(rawConfig, configVersion, node) : rawConfig;
|
|
1192
|
+
assertStatus(node.status, node.id);
|
|
1193
|
+
nodes.set(node.id, {
|
|
1194
|
+
checkpoint: node,
|
|
1195
|
+
localId: id,
|
|
1196
|
+
descriptor,
|
|
1197
|
+
config,
|
|
1198
|
+
runtime: prepareRuntime(node),
|
|
1199
|
+
deps: node.deps.map((dep, i) => assertString(dep, `${node.id}.deps[${i}]`))
|
|
1200
|
+
});
|
|
1201
|
+
}
|
|
1202
|
+
for (const prepared of nodes.values()) {
|
|
1203
|
+
for (const dep of prepared.deps) {
|
|
1204
|
+
if (!nodes.has(dep)) {
|
|
1205
|
+
throw new Error(`restoreGraph: node '${prepared.checkpoint.id}' has missing dep '${dep}'`);
|
|
1206
|
+
}
|
|
1207
|
+
}
|
|
1208
|
+
}
|
|
1209
|
+
const edgeKeys = /* @__PURE__ */ new Set();
|
|
1210
|
+
for (const edge of checkpoint.edges) {
|
|
1211
|
+
const edgeKey = `${edge.from}\0${edge.to}`;
|
|
1212
|
+
if (edgeKeys.has(edgeKey)) {
|
|
1213
|
+
throw new Error(`restoreGraph: duplicate edge '${edge.from}' -> '${edge.to}'`);
|
|
1214
|
+
}
|
|
1215
|
+
edgeKeys.add(edgeKey);
|
|
1216
|
+
if (!nodes.has(edge.from) || !nodes.has(edge.to)) {
|
|
1217
|
+
throw new Error(
|
|
1218
|
+
`restoreGraph: edge '${edge.from}' -> '${edge.to}' references a missing node`
|
|
1219
|
+
);
|
|
1220
|
+
}
|
|
1221
|
+
const target = nodes.get(edge.to);
|
|
1222
|
+
if (!target.deps.includes(edge.from)) {
|
|
1223
|
+
throw new Error(
|
|
1224
|
+
`restoreGraph: edge '${edge.from}' -> '${edge.to}' is not present in target deps`
|
|
1225
|
+
);
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1228
|
+
for (const prepared of nodes.values()) {
|
|
1229
|
+
for (const dep of prepared.deps) {
|
|
1230
|
+
if (!edgeKeys.has(`${dep}\0${prepared.checkpoint.id}`)) {
|
|
1231
|
+
throw new Error(
|
|
1232
|
+
`restoreGraph: node '${prepared.checkpoint.id}' dep '${dep}' is missing its edge`
|
|
1233
|
+
);
|
|
1234
|
+
}
|
|
1235
|
+
}
|
|
1236
|
+
}
|
|
1237
|
+
const mountPaths = /* @__PURE__ */ new Set();
|
|
1238
|
+
const mounts = [];
|
|
1239
|
+
for (const mount of checkpoint.mounts ?? []) {
|
|
1240
|
+
const at = assertString(mount.at, `${path}.mounts[].at`);
|
|
1241
|
+
if (at.length === 0) throw new Error("restoreGraph: mount path must not be empty");
|
|
1242
|
+
if (mountPaths.has(at)) throw new Error(`restoreGraph: duplicate mount path '${at}'`);
|
|
1243
|
+
mountPaths.add(at);
|
|
1244
|
+
mounts.push({
|
|
1245
|
+
at,
|
|
1246
|
+
prepared: prepareCheckpoint(mount.checkpoint, registry, `${path}.mounts.${at}`, at)
|
|
1247
|
+
});
|
|
1248
|
+
}
|
|
1249
|
+
return { checkpoint, nodes, mounts };
|
|
1250
|
+
}
|
|
1251
|
+
function constructPrepared(prepared, registry, dispatcher, versioning) {
|
|
1252
|
+
const out = graph({ name: prepared.checkpoint.name, dispatcher, versioning });
|
|
1253
|
+
try {
|
|
1254
|
+
const built = /* @__PURE__ */ new Map();
|
|
1255
|
+
const visiting = /* @__PURE__ */ new Set();
|
|
1256
|
+
const buildNode = (id) => {
|
|
1257
|
+
const existing = built.get(id);
|
|
1258
|
+
if (existing) return existing;
|
|
1259
|
+
const item = prepared.nodes.get(id);
|
|
1260
|
+
if (item === void 0) throw new Error(`restoreGraph: missing prepared node '${id}'`);
|
|
1261
|
+
if (visiting.has(id)) throw new Error(`restoreGraph: dependency cycle at '${id}'`);
|
|
1262
|
+
visiting.add(id);
|
|
1263
|
+
const deps = item.deps.map(buildNode);
|
|
1264
|
+
const node = item.descriptor.create({
|
|
1265
|
+
graph: out,
|
|
1266
|
+
id: item.localId,
|
|
1267
|
+
name: item.checkpoint.name,
|
|
1268
|
+
deps,
|
|
1269
|
+
config: item.config,
|
|
1270
|
+
configVersion: item.checkpoint.factory.kind === "registry-ref" ? item.checkpoint.factory.configVersion : void 0,
|
|
1271
|
+
checkpoint: item.checkpoint,
|
|
1272
|
+
resolveDefinition: (ref) => resolveDefinition(registry, ref, item.checkpoint.id),
|
|
1273
|
+
registerState: (opts) => restoreStateNodeInGraph(out, item.localId, opts),
|
|
1274
|
+
registerNode: (factory, nodeDeps, fn, opts) => restoreNodeInGraph(out, item.localId, factory, nodeDeps, fn, opts)
|
|
1275
|
+
});
|
|
1276
|
+
if (out.find(item.localId) !== node) {
|
|
1277
|
+
throw new Error(
|
|
1278
|
+
`restoreGraph: descriptor '${item.descriptor.ref}' did not register node '${item.localId}'`
|
|
1279
|
+
);
|
|
1280
|
+
}
|
|
1281
|
+
if (node.deps.length !== deps.length || node.deps.some((dep, i) => dep !== deps[i])) {
|
|
1282
|
+
throw new Error(
|
|
1283
|
+
`restoreGraph: descriptor '${item.descriptor.ref}' registered node '${item.localId}' with deps that do not match the checkpoint`
|
|
1284
|
+
);
|
|
1285
|
+
}
|
|
1286
|
+
built.set(id, node);
|
|
1287
|
+
visiting.delete(id);
|
|
1288
|
+
return node;
|
|
1289
|
+
};
|
|
1290
|
+
for (const id of prepared.nodes.keys()) buildNode(id);
|
|
1291
|
+
for (const mount of prepared.mounts) {
|
|
1292
|
+
out.mount(constructPrepared(mount.prepared, registry, dispatcher, versioning), {
|
|
1293
|
+
at: mount.at
|
|
1294
|
+
});
|
|
1295
|
+
}
|
|
1296
|
+
for (const [id, node] of built) {
|
|
1297
|
+
const runtime = prepared.nodes.get(id).runtime;
|
|
1298
|
+
restoreStateOfNode(node, {
|
|
1299
|
+
cache: runtime.cache,
|
|
1300
|
+
hasData: runtime.hasData,
|
|
1301
|
+
status: runtime.status,
|
|
1302
|
+
terminal: runtime.terminal,
|
|
1303
|
+
hasCalledFnOnce: runtime.hasCalledFnOnce,
|
|
1304
|
+
ctxState: runtime.ctxState,
|
|
1305
|
+
version: runtime.version
|
|
1306
|
+
});
|
|
1307
|
+
}
|
|
1308
|
+
} finally {
|
|
1309
|
+
clearRestoredCollectionMap(out);
|
|
1310
|
+
}
|
|
1311
|
+
return out;
|
|
1312
|
+
}
|
|
1313
|
+
function restoreGraph(checkpoint, options) {
|
|
1314
|
+
if (options == null || options.registry === void 0) {
|
|
1315
|
+
throw new Error("restoreGraph: registry is required");
|
|
1316
|
+
}
|
|
1317
|
+
if (!(options.registry instanceof Map) && (typeof options.registry !== "object" || options.registry === null)) {
|
|
1318
|
+
throw new Error("restoreGraph: registry must be a Map or object");
|
|
1319
|
+
}
|
|
1320
|
+
for (const key of Object.keys(options)) {
|
|
1321
|
+
if (key !== "registry" && key !== "dispatcher" && key !== "versioning") {
|
|
1322
|
+
throw new Error(`restoreGraph: unknown option '${key}'`);
|
|
1323
|
+
}
|
|
1324
|
+
}
|
|
1325
|
+
const prepared = prepareCheckpoint(checkpoint, options.registry);
|
|
1326
|
+
return constructPrepared(prepared, options.registry, options.dispatcher, options.versioning);
|
|
1327
|
+
}
|
|
1328
|
+
|
|
1329
|
+
// src/graph/worker.ts
|
|
1330
|
+
function workerDerived(graph2, deps, opts) {
|
|
1331
|
+
if (typeof opts.prepare !== "function") {
|
|
1332
|
+
throw new TypeError("workerDerived: prepare must be a function");
|
|
1333
|
+
}
|
|
1334
|
+
if (typeof opts.compute !== "function") {
|
|
1335
|
+
throw new TypeError("workerDerived: compute must be a function");
|
|
1336
|
+
}
|
|
1337
|
+
if (opts.backend === void 0 || typeof opts.backend.run !== "function") {
|
|
1338
|
+
throw new TypeError("workerDerived: backend is required");
|
|
1339
|
+
}
|
|
1340
|
+
let latestInvocation = 0;
|
|
1341
|
+
let cancelActive;
|
|
1342
|
+
const fn = (ctx) => {
|
|
1343
|
+
cancelActive?.();
|
|
1344
|
+
cancelActive = void 0;
|
|
1345
|
+
latestInvocation += 1;
|
|
1346
|
+
const invocation = latestInvocation;
|
|
1347
|
+
let input;
|
|
1348
|
+
try {
|
|
1349
|
+
input = opts.prepare(ctx);
|
|
1350
|
+
} catch (error) {
|
|
1351
|
+
ctx.down([["ERROR", errorPayload(error, "workerDerived prepare failed")]]);
|
|
1352
|
+
return;
|
|
1353
|
+
}
|
|
1354
|
+
if (input === void 0) {
|
|
1355
|
+
ctx.down([["RESOLVED"]]);
|
|
1356
|
+
return;
|
|
1357
|
+
}
|
|
1358
|
+
const ownedInput = cloneWorkerInput(input);
|
|
1359
|
+
if (!ownedInput.ok) {
|
|
1360
|
+
ctx.down([["ERROR", errorPayload(new Error(ownedInput.message), ownedInput.message)]]);
|
|
1361
|
+
return;
|
|
1362
|
+
}
|
|
1363
|
+
let live = true;
|
|
1364
|
+
let cancel;
|
|
1365
|
+
let canceled = false;
|
|
1366
|
+
let submitting = true;
|
|
1367
|
+
let settled = false;
|
|
1368
|
+
let synchronousSettlementError;
|
|
1369
|
+
const cancelThis = () => {
|
|
1370
|
+
if (canceled) return;
|
|
1371
|
+
canceled = true;
|
|
1372
|
+
live = false;
|
|
1373
|
+
cancel?.();
|
|
1374
|
+
cancel = void 0;
|
|
1375
|
+
};
|
|
1376
|
+
cancelActive = cancelThis;
|
|
1377
|
+
ctx.onDeactivation(() => {
|
|
1378
|
+
cancelThis();
|
|
1379
|
+
if (cancelActive === cancelThis) cancelActive = void 0;
|
|
1380
|
+
});
|
|
1381
|
+
const assertNotSynchronousCompletion = () => {
|
|
1382
|
+
if (submitting) {
|
|
1383
|
+
synchronousSettlementError = new Error(
|
|
1384
|
+
"workerDerived: backend completions must arrive after backend.run returns"
|
|
1385
|
+
);
|
|
1386
|
+
throw synchronousSettlementError;
|
|
1387
|
+
}
|
|
1388
|
+
};
|
|
1389
|
+
const clearAcceptedSettlement = () => {
|
|
1390
|
+
cancelActive = void 0;
|
|
1391
|
+
cancel = void 0;
|
|
1392
|
+
live = false;
|
|
1393
|
+
};
|
|
1394
|
+
const settle = (settlement) => {
|
|
1395
|
+
if (settled) return;
|
|
1396
|
+
settled = true;
|
|
1397
|
+
assertNotSynchronousCompletion();
|
|
1398
|
+
if (!live || invocation !== latestInvocation) return;
|
|
1399
|
+
clearAcceptedSettlement();
|
|
1400
|
+
if (settlement.ok) {
|
|
1401
|
+
ctx.down([["DATA", settlement.value]]);
|
|
1402
|
+
} else {
|
|
1403
|
+
ctx.down([["ERROR", errorPayload(settlement.error, "workerDerived compute failed")]]);
|
|
1404
|
+
}
|
|
1405
|
+
};
|
|
1406
|
+
let thrown = false;
|
|
1407
|
+
let thrownError;
|
|
1408
|
+
try {
|
|
1409
|
+
cancel = opts.backend.run(
|
|
1410
|
+
{
|
|
1411
|
+
input: ownedInput.value,
|
|
1412
|
+
compute: opts.compute
|
|
1413
|
+
},
|
|
1414
|
+
settle
|
|
1415
|
+
) ?? void 0;
|
|
1416
|
+
} catch (error) {
|
|
1417
|
+
thrown = true;
|
|
1418
|
+
thrownError = error;
|
|
1419
|
+
} finally {
|
|
1420
|
+
submitting = false;
|
|
1421
|
+
}
|
|
1422
|
+
if (synchronousSettlementError !== void 0) {
|
|
1423
|
+
if (live && invocation === latestInvocation) {
|
|
1424
|
+
ctx.down([
|
|
1425
|
+
["ERROR", errorPayload(synchronousSettlementError, "workerDerived compute failed")]
|
|
1426
|
+
]);
|
|
1427
|
+
}
|
|
1428
|
+
cancelThis();
|
|
1429
|
+
if (cancelActive === cancelThis) cancelActive = void 0;
|
|
1430
|
+
return;
|
|
1431
|
+
}
|
|
1432
|
+
if (thrown) {
|
|
1433
|
+
if (live && invocation === latestInvocation) {
|
|
1434
|
+
ctx.down([["ERROR", errorPayload(thrownError, "workerDerived compute failed")]]);
|
|
1435
|
+
}
|
|
1436
|
+
cancelThis();
|
|
1437
|
+
if (cancelActive === cancelThis) cancelActive = void 0;
|
|
1438
|
+
}
|
|
1439
|
+
};
|
|
1440
|
+
return graph2.node(deps, fn, {
|
|
1441
|
+
name: opts.name ?? "workerDerived",
|
|
1442
|
+
factory: "workerDerived",
|
|
1443
|
+
pool: "async",
|
|
1444
|
+
completeWhenDepsComplete: false,
|
|
1445
|
+
errorWhenDepsError: false
|
|
1446
|
+
});
|
|
1447
|
+
}
|
|
1448
|
+
function cloneWorkerInput(input) {
|
|
1449
|
+
if (typeof input === "function" || typeof input === "symbol") {
|
|
1450
|
+
return { ok: false, message: "workerDerived: input must be owned and cloneable" };
|
|
1451
|
+
}
|
|
1452
|
+
if (typeof input !== "object" || input === null) return { ok: true, value: input };
|
|
1453
|
+
if (typeof globalThis.structuredClone !== "function") {
|
|
1454
|
+
return { ok: false, message: "workerDerived: structuredClone is required for object inputs" };
|
|
1455
|
+
}
|
|
1456
|
+
try {
|
|
1457
|
+
return { ok: true, value: globalThis.structuredClone(input) };
|
|
1458
|
+
} catch (error) {
|
|
1459
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1460
|
+
return {
|
|
1461
|
+
ok: false,
|
|
1462
|
+
message: `workerDerived: input must be owned and cloneable (${message})`
|
|
1463
|
+
};
|
|
1464
|
+
}
|
|
1465
|
+
}
|
|
1466
|
+
|
|
1467
|
+
export {
|
|
1468
|
+
reactiveCascadingCache,
|
|
1469
|
+
reachable,
|
|
1470
|
+
explainPath,
|
|
1471
|
+
validateNoIslands,
|
|
1472
|
+
filterObserve,
|
|
1473
|
+
coalesceObserve,
|
|
1474
|
+
stateRestoreDescriptor,
|
|
1475
|
+
takeRestoreDescriptor,
|
|
1476
|
+
mapRestoreDescriptor,
|
|
1477
|
+
timerRestoreDescriptor,
|
|
1478
|
+
defaultRestoreRegistry,
|
|
1479
|
+
restoreGraph,
|
|
1480
|
+
workerDerived
|
|
1481
|
+
};
|
|
1482
|
+
//# sourceMappingURL=chunk-Y3ZLRGHC.js.map
|