doxum 0.1.19 → 0.1.21
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 +30 -11
- package/dist/{scope-d-L87NeC.js → access-BeSV5ve-.js} +114 -20
- package/dist/access-BeSV5ve-.js.map +1 -0
- package/dist/{scope-Ezs-Y3TY.cjs → access-Bienf28h.cjs} +149 -19
- package/dist/access-Bienf28h.cjs.map +1 -0
- package/dist/advanced-BRL5pN0y.cjs +1361 -0
- package/dist/advanced-BRL5pN0y.cjs.map +1 -0
- package/dist/advanced-COFJtWMT.js +1188 -0
- package/dist/advanced-COFJtWMT.js.map +1 -0
- package/dist/{advanced-C2fpjbK3.d.ts → advanced-DfKc7TZR.d.cts} +27 -22
- package/dist/{advanced-DlOYk1vi.d.cts → advanced-FgdTwu5b.d.ts} +27 -22
- package/dist/advanced.cjs +1 -1
- package/dist/advanced.d.cts +2 -2
- package/dist/advanced.d.ts +2 -2
- package/dist/advanced.js +1 -1
- package/dist/{contract-XmKnroJq.d.cts → contract-CdmDHRUq.d.cts} +8 -6
- package/dist/{contract-CATCCVu5.d.ts → contract-KG5XnQZt.d.ts} +8 -6
- package/dist/{driver-CSnhMjbP.js → driver-CLYJOGDQ.js} +2 -2
- package/dist/{driver-CSnhMjbP.js.map → driver-CLYJOGDQ.js.map} +1 -1
- package/dist/{driver-BCyfqxsl.cjs → driver-Djr3BVvo.cjs} +2 -2
- package/dist/{driver-BCyfqxsl.cjs.map → driver-Djr3BVvo.cjs.map} +1 -1
- package/dist/index.cjs +1150 -1993
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1105 -1948
- package/dist/index.js.map +1 -1
- package/dist/{integration-CxVhq-KD.js → integration-C4Isp8lJ.js} +3 -2
- package/dist/{integration-CxVhq-KD.js.map → integration-C4Isp8lJ.js.map} +1 -1
- package/dist/{integration-B7VDgAOJ.cjs → integration-Z6MsfFI7.cjs} +4 -3
- package/dist/{integration-B7VDgAOJ.cjs.map → integration-Z6MsfFI7.cjs.map} +1 -1
- package/dist/integration.cjs +3 -3
- package/dist/integration.d.cts +1 -1
- package/dist/integration.d.ts +1 -1
- package/dist/integration.js +3 -3
- package/dist/{issue-DhrNdQNg.cjs → issue-DjK1xp5K.cjs} +106 -22
- package/dist/issue-DjK1xp5K.cjs.map +1 -0
- package/dist/{issue-DVaGQGeP.js → issue-W0hT8u8D.js} +81 -15
- package/dist/issue-W0hT8u8D.js.map +1 -0
- package/dist/local-sync.cjs +2 -2
- package/dist/local-sync.d.cts +1 -1
- package/dist/local-sync.d.ts +1 -1
- package/dist/local-sync.js +2 -2
- package/dist/{notification-IQIJyH3Q.js → notification-Bkjau6B6.js} +3 -56
- package/dist/notification-Bkjau6B6.js.map +1 -0
- package/dist/{notification-CDSUfiip.cjs → notification-DJfouMEb.cjs} +2 -91
- package/dist/notification-DJfouMEb.cjs.map +1 -0
- package/dist/react.cjs +2 -2
- package/dist/react.js +2 -2
- package/package.json +1 -1
- package/skills/doxum-runtime/SKILL.md +4 -1
- package/skills/doxum-runtime/references/guide.en.md +5 -2
- package/skills/doxum-runtime/references/guide.zh-CN.md +5 -2
- package/skills/doxum-runtime/references/projections.en.md +23 -9
- package/skills/doxum-runtime/references/projections.zh-CN.md +18 -6
- package/dist/advanced-BYZCjNWL.js +0 -680
- package/dist/advanced-BYZCjNWL.js.map +0 -1
- package/dist/advanced-CMMNk49G.cjs +0 -763
- package/dist/advanced-CMMNk49G.cjs.map +0 -1
- package/dist/issue-DVaGQGeP.js.map +0 -1
- package/dist/issue-DhrNdQNg.cjs.map +0 -1
- package/dist/notification-CDSUfiip.cjs.map +0 -1
- package/dist/notification-IQIJyH3Q.js.map +0 -1
- package/dist/scope-Ezs-Y3TY.cjs.map +0 -1
- package/dist/scope-d-L87NeC.js.map +0 -1
|
@@ -1,680 +0,0 @@
|
|
|
1
|
-
import { L as profile } from "./issue-DVaGQGeP.js";
|
|
2
|
-
import { i as snapshot } from "./scope-d-L87NeC.js";
|
|
3
|
-
//#region core/src/projection/definition.ts
|
|
4
|
-
const definitions = /* @__PURE__ */ new WeakMap();
|
|
5
|
-
const owners = /* @__PURE__ */ new WeakMap();
|
|
6
|
-
const define = (definition) => {
|
|
7
|
-
const handle = Object.freeze({});
|
|
8
|
-
definitions.set(handle, definition);
|
|
9
|
-
return handle;
|
|
10
|
-
};
|
|
11
|
-
const definitionOf = (projection) => {
|
|
12
|
-
const definition = definitions.get(projection);
|
|
13
|
-
if (!definition) throw new TypeError("Unknown projection definition.");
|
|
14
|
-
return definition;
|
|
15
|
-
};
|
|
16
|
-
const isProjection = (value) => value !== null && typeof value === "object" && definitions.has(value);
|
|
17
|
-
const ownerOf = (projection) => owners.get(projection);
|
|
18
|
-
const ownDefinition = (projection, owner) => {
|
|
19
|
-
if (!definitions.has(projection) || owners.has(projection)) throw new TypeError("Projection definition already has an owner.");
|
|
20
|
-
owners.set(projection, owner);
|
|
21
|
-
return projection;
|
|
22
|
-
};
|
|
23
|
-
const valueInput = (initial, equality = Object.is) => define({
|
|
24
|
-
kind: "input",
|
|
25
|
-
initial,
|
|
26
|
-
isEqual: equality
|
|
27
|
-
});
|
|
28
|
-
const collectionInput = (initial = /* @__PURE__ */ new Map()) => {
|
|
29
|
-
const entries = /* @__PURE__ */ new Map();
|
|
30
|
-
for (const [key, value] of initial) {
|
|
31
|
-
if (typeof key !== "string") throw new TypeError("Projection keys must be strings.");
|
|
32
|
-
entries.set(key, value);
|
|
33
|
-
}
|
|
34
|
-
return define({
|
|
35
|
-
kind: "collection-input",
|
|
36
|
-
initial: entries
|
|
37
|
-
});
|
|
38
|
-
};
|
|
39
|
-
const input = Object.assign(valueInput, { collection: collectionInput });
|
|
40
|
-
function observe(document, selector) {
|
|
41
|
-
if (isExternalSource(document)) return document.kind === "collection" ? defineExternalCollection(document) : defineExternalValue(document);
|
|
42
|
-
if ("current" in document && typeof document.current === "function") return defineReadable(document);
|
|
43
|
-
return define({
|
|
44
|
-
kind: "document",
|
|
45
|
-
document,
|
|
46
|
-
selector
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
const isExternalSource = (source) => {
|
|
50
|
-
if (!source || typeof source !== "object") return false;
|
|
51
|
-
const candidate = source;
|
|
52
|
-
return (candidate.kind === "value" || candidate.kind === "collection") && typeof candidate.current === "function" && typeof candidate.revision === "function" && typeof candidate.subscribe === "function";
|
|
53
|
-
};
|
|
54
|
-
function derive(dependencies, compute, equality = Object.is) {
|
|
55
|
-
if (!Array.isArray(dependencies) || dependencies.some((value) => !definitions.has(value))) throw new TypeError("derive dependencies must be projections.");
|
|
56
|
-
return define({
|
|
57
|
-
kind: "derive",
|
|
58
|
-
dependencies: Object.freeze([...dependencies]),
|
|
59
|
-
compute,
|
|
60
|
-
isEqual: equality
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
const defineReadable = (readable, equality = Object.is) => define({
|
|
64
|
-
kind: "readable",
|
|
65
|
-
readable,
|
|
66
|
-
isEqual: equality
|
|
67
|
-
});
|
|
68
|
-
const defineExternalValue = (source) => define({
|
|
69
|
-
kind: "source-value",
|
|
70
|
-
source
|
|
71
|
-
});
|
|
72
|
-
const defineExternalCollection = (source) => define({
|
|
73
|
-
kind: "source-collection",
|
|
74
|
-
source
|
|
75
|
-
});
|
|
76
|
-
const defineIncrementalValue = (definition) => define({
|
|
77
|
-
kind: "incremental-value",
|
|
78
|
-
dependencies: definition.dependencies,
|
|
79
|
-
build: definition.build,
|
|
80
|
-
isEqual: definition.isEqual,
|
|
81
|
-
name: definition.name
|
|
82
|
-
});
|
|
83
|
-
const defineIncrementalCollection = (definition) => define({
|
|
84
|
-
kind: "incremental-collection",
|
|
85
|
-
dependencies: definition.dependencies,
|
|
86
|
-
build: definition.build,
|
|
87
|
-
isEqual: definition.isEqual,
|
|
88
|
-
name: definition.name
|
|
89
|
-
});
|
|
90
|
-
const defineIncrementalGroup = (definition) => {
|
|
91
|
-
const group = {
|
|
92
|
-
dependencies: definition.dependencies,
|
|
93
|
-
outputs: Object.freeze(definition.outputs.map((output) => Object.freeze({
|
|
94
|
-
path: Object.freeze([...output.path]),
|
|
95
|
-
isEqual: output.isEqual
|
|
96
|
-
}))),
|
|
97
|
-
build: definition.build,
|
|
98
|
-
projections: []
|
|
99
|
-
};
|
|
100
|
-
const projections = group.outputs.map((_, output) => define({
|
|
101
|
-
kind: "incremental-group-output",
|
|
102
|
-
group,
|
|
103
|
-
output
|
|
104
|
-
}));
|
|
105
|
-
group.projections = Object.freeze(projections);
|
|
106
|
-
return Object.freeze(group);
|
|
107
|
-
};
|
|
108
|
-
//#endregion
|
|
109
|
-
//#region core/src/projection/contract.ts
|
|
110
|
-
var ProjectionError = class extends Error {
|
|
111
|
-
constructor(phase, identity, revisions, cause) {
|
|
112
|
-
super(`Projection ${phase} failed: ${identity}`, { cause });
|
|
113
|
-
this.phase = phase;
|
|
114
|
-
this.identity = identity;
|
|
115
|
-
this.revisions = revisions;
|
|
116
|
-
this.name = "ProjectionError";
|
|
117
|
-
}
|
|
118
|
-
};
|
|
119
|
-
var ProjectionDisposedError = class extends Error {
|
|
120
|
-
constructor() {
|
|
121
|
-
super("Projection has been disposed.");
|
|
122
|
-
this.name = "ProjectionDisposedError";
|
|
123
|
-
}
|
|
124
|
-
};
|
|
125
|
-
//#endregion
|
|
126
|
-
//#region core/src/projection/scheduler.ts
|
|
127
|
-
const projectionHandles = /* @__PURE__ */ new WeakSet();
|
|
128
|
-
const createScheduler = (onError) => {
|
|
129
|
-
let disposed = false;
|
|
130
|
-
let depth = 0;
|
|
131
|
-
let batchSequence = 0;
|
|
132
|
-
let activeBatch;
|
|
133
|
-
let phase = "idle";
|
|
134
|
-
let sequence = 0;
|
|
135
|
-
const records = /* @__PURE__ */ new Map();
|
|
136
|
-
const nodes = /* @__PURE__ */ new Set();
|
|
137
|
-
const pending = /* @__PURE__ */ new Set();
|
|
138
|
-
const heap = [];
|
|
139
|
-
const queued = /* @__PURE__ */ new Set();
|
|
140
|
-
const completed = [];
|
|
141
|
-
const emissions = /* @__PURE__ */ new Set();
|
|
142
|
-
const errors = [];
|
|
143
|
-
let reportingFailures = [];
|
|
144
|
-
const guards = /* @__PURE__ */ new Set();
|
|
145
|
-
const cleanups = /* @__PURE__ */ new Set();
|
|
146
|
-
const assertActive = () => {
|
|
147
|
-
if (disposed) throw new ProjectionDisposedError();
|
|
148
|
-
};
|
|
149
|
-
const assertIdle = () => {
|
|
150
|
-
assertActive();
|
|
151
|
-
if (phase !== "idle") throw new Error("Projection cannot be re-entered during processing or notification.");
|
|
152
|
-
};
|
|
153
|
-
const lock = (value) => guards.forEach((guard) => guard(value));
|
|
154
|
-
const enqueue = (node) => {
|
|
155
|
-
if (node.disposed || queued.has(node)) return;
|
|
156
|
-
queued.add(node);
|
|
157
|
-
profile.projection("scheduledNodes");
|
|
158
|
-
let i = heap.length;
|
|
159
|
-
heap.push(node);
|
|
160
|
-
while (i > 0) {
|
|
161
|
-
const p = i - 1 >> 1;
|
|
162
|
-
if (heap[p].order < node.order) break;
|
|
163
|
-
heap[i] = heap[p];
|
|
164
|
-
i = p;
|
|
165
|
-
}
|
|
166
|
-
heap[i] = node;
|
|
167
|
-
};
|
|
168
|
-
const pop = () => {
|
|
169
|
-
const first = heap[0];
|
|
170
|
-
const last = heap.pop();
|
|
171
|
-
if (heap.length) {
|
|
172
|
-
let i = 0;
|
|
173
|
-
while (i * 2 + 1 < heap.length) {
|
|
174
|
-
let c = i * 2 + 1;
|
|
175
|
-
if (c + 1 < heap.length && heap[c + 1].order < heap[c].order) c++;
|
|
176
|
-
if (last.order < heap[c].order) break;
|
|
177
|
-
heap[i] = heap[c];
|
|
178
|
-
i = c;
|
|
179
|
-
}
|
|
180
|
-
heap[i] = last;
|
|
181
|
-
}
|
|
182
|
-
return first;
|
|
183
|
-
};
|
|
184
|
-
const errorFor = (node, cause, kind = "processor") => new ProjectionError(kind, node.name, node.sources.map((source) => source.revision()), cause);
|
|
185
|
-
const capture = (source) => {
|
|
186
|
-
if (disposed) return;
|
|
187
|
-
if (phase !== "idle") {
|
|
188
|
-
source.fault = new ProjectionError("source", "reentrant source", [source.revision()], /* @__PURE__ */ new Error("Source changed while projection was running."));
|
|
189
|
-
errors.push(source.fault);
|
|
190
|
-
throw source.fault;
|
|
191
|
-
}
|
|
192
|
-
pending.add(source);
|
|
193
|
-
profile.projection("sourceEvents");
|
|
194
|
-
if (source.fault) errors.push(source.fault);
|
|
195
|
-
};
|
|
196
|
-
const settle = () => {
|
|
197
|
-
if (disposed || depth || phase !== "idle") return;
|
|
198
|
-
phase = "compute";
|
|
199
|
-
lock(true);
|
|
200
|
-
try {
|
|
201
|
-
pending.forEach((source) => {
|
|
202
|
-
if (source.shouldSettle?.() ?? true) source.consumers.forEach(enqueue);
|
|
203
|
-
});
|
|
204
|
-
while (heap.length) {
|
|
205
|
-
const node = pop();
|
|
206
|
-
if (node.disposed) continue;
|
|
207
|
-
const wasFaulted = node.fault !== void 0;
|
|
208
|
-
profile.projection("processedNodes");
|
|
209
|
-
let changed = false;
|
|
210
|
-
const blocked = node.sources.find((source) => source.fault || source.disposed);
|
|
211
|
-
if (blocked) node.fault = errorFor(node, blocked.fault ?? new ProjectionDisposedError(), "blocked");
|
|
212
|
-
else {
|
|
213
|
-
const build = wasFaulted || node.sources.some((source) => source.reset());
|
|
214
|
-
try {
|
|
215
|
-
changed = node.evaluate(build);
|
|
216
|
-
const failure = node.sources.find((source) => source.fault)?.fault;
|
|
217
|
-
if (failure) throw failure;
|
|
218
|
-
node.fault = void 0;
|
|
219
|
-
} catch (cause) {
|
|
220
|
-
const error = errorFor(node, cause);
|
|
221
|
-
node.fault = error;
|
|
222
|
-
if (!build) try {
|
|
223
|
-
changed = node.evaluate(true);
|
|
224
|
-
const failure = node.sources.find((source) => source.fault)?.fault;
|
|
225
|
-
if (failure) throw failure;
|
|
226
|
-
node.fault = void 0;
|
|
227
|
-
errors.push(error);
|
|
228
|
-
} catch (cause) {
|
|
229
|
-
node.fault = errorFor(node, cause);
|
|
230
|
-
errors.push(node.fault);
|
|
231
|
-
}
|
|
232
|
-
else errors.push(error);
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
completed.push(node);
|
|
236
|
-
const outputs = node.changedOutputs?.() ?? (changed ? [node] : []);
|
|
237
|
-
const affected = node.fault ? node.outputs ?? [node] : outputs.length ? outputs : wasFaulted ? node.outputs ?? [node] : [];
|
|
238
|
-
if (affected.length) {
|
|
239
|
-
profile.projection("publishedNodes");
|
|
240
|
-
node.publish();
|
|
241
|
-
affected.forEach((output) => {
|
|
242
|
-
emissions.add(output);
|
|
243
|
-
output.consumers.forEach(enqueue);
|
|
244
|
-
});
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
} finally {
|
|
248
|
-
lock(false);
|
|
249
|
-
phase = "idle";
|
|
250
|
-
}
|
|
251
|
-
};
|
|
252
|
-
const flush = () => {
|
|
253
|
-
if (disposed || depth) return [];
|
|
254
|
-
if (pending.size || completed.length) profile.projection("flushes");
|
|
255
|
-
phase = "notify";
|
|
256
|
-
lock(true);
|
|
257
|
-
const reportFailures = [];
|
|
258
|
-
try {
|
|
259
|
-
emissions.forEach((output) => output.emit((listener) => {
|
|
260
|
-
try {
|
|
261
|
-
listener();
|
|
262
|
-
} catch (cause) {
|
|
263
|
-
errors.push(errorFor(output.owner, cause, "listener"));
|
|
264
|
-
}
|
|
265
|
-
}));
|
|
266
|
-
for (const error of errors.slice()) try {
|
|
267
|
-
onError(error);
|
|
268
|
-
} catch (cause) {
|
|
269
|
-
reportFailures.push(cause);
|
|
270
|
-
}
|
|
271
|
-
return Object.freeze([...errors.map((error) => Object.freeze({
|
|
272
|
-
phase: error.phase === "listener" ? "listener" : "processor",
|
|
273
|
-
error
|
|
274
|
-
})), ...reportFailures.map((error) => Object.freeze({
|
|
275
|
-
phase: "listener",
|
|
276
|
-
error
|
|
277
|
-
}))]);
|
|
278
|
-
} finally {
|
|
279
|
-
pending.forEach((source) => source.clear());
|
|
280
|
-
completed.forEach((node) => node.clear());
|
|
281
|
-
pending.clear();
|
|
282
|
-
queued.clear();
|
|
283
|
-
completed.length = 0;
|
|
284
|
-
emissions.clear();
|
|
285
|
-
errors.length = 0;
|
|
286
|
-
reportingFailures = reportFailures;
|
|
287
|
-
lock(false);
|
|
288
|
-
phase = "idle";
|
|
289
|
-
}
|
|
290
|
-
};
|
|
291
|
-
const run = () => {
|
|
292
|
-
settle();
|
|
293
|
-
const result = flush();
|
|
294
|
-
const failures = reportingFailures;
|
|
295
|
-
reportingFailures = [];
|
|
296
|
-
if (failures.length) throw new AggregateError(failures, "Projection error reporter failed.");
|
|
297
|
-
return result;
|
|
298
|
-
};
|
|
299
|
-
const batch = (optionsOrCallback, maybeCallback) => {
|
|
300
|
-
assertIdle();
|
|
301
|
-
const options = typeof optionsOrCallback === "function" ? void 0 : optionsOrCallback;
|
|
302
|
-
const callback = typeof optionsOrCallback === "function" ? optionsOrCallback : maybeCallback;
|
|
303
|
-
if (!callback) throw new TypeError("Projection batch requires a callback.");
|
|
304
|
-
if (depth === 0) activeBatch = Object.freeze({
|
|
305
|
-
id: ++batchSequence,
|
|
306
|
-
...options?.cause === void 0 ? {} : { cause: options.cause }
|
|
307
|
-
});
|
|
308
|
-
depth++;
|
|
309
|
-
let failed = false;
|
|
310
|
-
try {
|
|
311
|
-
const value = callback();
|
|
312
|
-
assertSynchronous(value);
|
|
313
|
-
return value;
|
|
314
|
-
} catch (error) {
|
|
315
|
-
failed = true;
|
|
316
|
-
throw error;
|
|
317
|
-
} finally {
|
|
318
|
-
depth--;
|
|
319
|
-
if (!depth) try {
|
|
320
|
-
if (failed) try {
|
|
321
|
-
run();
|
|
322
|
-
} catch {}
|
|
323
|
-
else run();
|
|
324
|
-
} finally {
|
|
325
|
-
activeBatch = void 0;
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
};
|
|
329
|
-
return {
|
|
330
|
-
assertActive,
|
|
331
|
-
assertIdle,
|
|
332
|
-
capture,
|
|
333
|
-
settle,
|
|
334
|
-
flush,
|
|
335
|
-
run,
|
|
336
|
-
records,
|
|
337
|
-
guards,
|
|
338
|
-
cleanups,
|
|
339
|
-
get active() {
|
|
340
|
-
return !disposed;
|
|
341
|
-
},
|
|
342
|
-
register(handle, record) {
|
|
343
|
-
assertIdle();
|
|
344
|
-
records.set(handle, record);
|
|
345
|
-
projectionHandles.add(handle);
|
|
346
|
-
},
|
|
347
|
-
unregisterSource(handle) {
|
|
348
|
-
const record = records.get(handle);
|
|
349
|
-
if (record) {
|
|
350
|
-
assertIdle();
|
|
351
|
-
if (record.consumers.size) throw new Error("Projection source is still used by a node.");
|
|
352
|
-
record.disposed = true;
|
|
353
|
-
pending.delete(record);
|
|
354
|
-
record.clear();
|
|
355
|
-
records.delete(handle);
|
|
356
|
-
}
|
|
357
|
-
},
|
|
358
|
-
releaseNode(handle) {
|
|
359
|
-
assertIdle();
|
|
360
|
-
const record = records.get(handle);
|
|
361
|
-
const node = record && "owner" in record ? record.owner : record;
|
|
362
|
-
if (!node || !nodes.has(node)) throw new Error("Unknown projection node.");
|
|
363
|
-
if ((node.outputs ?? [node]).some((output) => output.consumers.size)) throw new Error("Projection node is still used by another node.");
|
|
364
|
-
node.disposed = true;
|
|
365
|
-
node.sources.forEach((source) => source.consumers.delete(node));
|
|
366
|
-
node.release();
|
|
367
|
-
node.clear();
|
|
368
|
-
nodes.delete(node);
|
|
369
|
-
for (const [registered, value] of records) if (value === node || "owner" in value && value.owner === node) records.delete(registered);
|
|
370
|
-
pending.delete(node);
|
|
371
|
-
queued.delete(node);
|
|
372
|
-
for (const output of node.outputs ?? [node]) emissions.delete(output);
|
|
373
|
-
},
|
|
374
|
-
source(handle) {
|
|
375
|
-
assertActive();
|
|
376
|
-
const source = records.get(handle);
|
|
377
|
-
if (!source || source.disposed) throw new Error("Unknown, disposed, or foreign projection source.");
|
|
378
|
-
return source;
|
|
379
|
-
},
|
|
380
|
-
addNode(node) {
|
|
381
|
-
nodes.add(node);
|
|
382
|
-
node.sources.forEach((source) => source.consumers.add(node));
|
|
383
|
-
},
|
|
384
|
-
order: () => sequence++,
|
|
385
|
-
initialize(run) {
|
|
386
|
-
assertIdle();
|
|
387
|
-
phase = "compute";
|
|
388
|
-
lock(true);
|
|
389
|
-
try {
|
|
390
|
-
return run();
|
|
391
|
-
} finally {
|
|
392
|
-
lock(false);
|
|
393
|
-
phase = "idle";
|
|
394
|
-
}
|
|
395
|
-
},
|
|
396
|
-
batch,
|
|
397
|
-
batchContext: () => activeBatch,
|
|
398
|
-
dispose() {
|
|
399
|
-
if (disposed) return;
|
|
400
|
-
assertIdle();
|
|
401
|
-
disposed = true;
|
|
402
|
-
const failures = [];
|
|
403
|
-
cleanups.forEach((cleanup) => {
|
|
404
|
-
try {
|
|
405
|
-
cleanup();
|
|
406
|
-
} catch (error) {
|
|
407
|
-
failures.push(error);
|
|
408
|
-
}
|
|
409
|
-
});
|
|
410
|
-
cleanups.clear();
|
|
411
|
-
nodes.forEach((node) => {
|
|
412
|
-
node.disposed = true;
|
|
413
|
-
node.release();
|
|
414
|
-
node.consumers.clear();
|
|
415
|
-
});
|
|
416
|
-
records.forEach((source) => {
|
|
417
|
-
source.disposed = true;
|
|
418
|
-
source.consumers.clear();
|
|
419
|
-
source.clear();
|
|
420
|
-
});
|
|
421
|
-
nodes.clear();
|
|
422
|
-
records.clear();
|
|
423
|
-
pending.clear();
|
|
424
|
-
heap.length = 0;
|
|
425
|
-
completed.length = 0;
|
|
426
|
-
queued.clear();
|
|
427
|
-
emissions.clear();
|
|
428
|
-
guards.clear();
|
|
429
|
-
errors.length = 0;
|
|
430
|
-
reportingFailures = [];
|
|
431
|
-
if (failures.length) throw new AggregateError(failures, "Projection cleanup failed.");
|
|
432
|
-
}
|
|
433
|
-
};
|
|
434
|
-
};
|
|
435
|
-
const assertSynchronous = (value) => {
|
|
436
|
-
if (value != null && (typeof value === "object" || typeof value === "function") && "then" in value && typeof value.then === "function") throw new TypeError("Projection callbacks must be synchronous.");
|
|
437
|
-
};
|
|
438
|
-
const assertScope = (active) => {
|
|
439
|
-
if (!active()) throw new Error("Projection reader or writer is no longer active.");
|
|
440
|
-
};
|
|
441
|
-
//#endregion
|
|
442
|
-
//#region core/src/projection/advanced.ts
|
|
443
|
-
const resetCollectionChange = Object.freeze({ kind: "reset" });
|
|
444
|
-
const isRebuild = (value) => value !== null && typeof value === "object" && value.kind === "rebuild";
|
|
445
|
-
const collectionChange = (source) => {
|
|
446
|
-
if (!source || typeof source !== "object" || !("kind" in source)) return void 0;
|
|
447
|
-
if (source.kind !== "collection") return void 0;
|
|
448
|
-
return source.change;
|
|
449
|
-
};
|
|
450
|
-
const sourceCause = (sources) => {
|
|
451
|
-
for (const source of Object.values(sources)) if (source && typeof source === "object" && "kind" in source) {
|
|
452
|
-
const cause = source.cause;
|
|
453
|
-
if (cause !== void 0) return cause;
|
|
454
|
-
}
|
|
455
|
-
};
|
|
456
|
-
const collectionView = (read) => {
|
|
457
|
-
const entries = function* () {
|
|
458
|
-
for (const key of read.ids()) yield [key, read.get(key)];
|
|
459
|
-
};
|
|
460
|
-
const values = function* () {
|
|
461
|
-
for (const key of read.ids()) yield read.get(key);
|
|
462
|
-
};
|
|
463
|
-
const view = {
|
|
464
|
-
get: (key) => read.get(key),
|
|
465
|
-
has: (key) => read.has(key),
|
|
466
|
-
get size() {
|
|
467
|
-
return read.ids().length;
|
|
468
|
-
},
|
|
469
|
-
keys: () => read.ids()[Symbol.iterator](),
|
|
470
|
-
values,
|
|
471
|
-
entries,
|
|
472
|
-
forEach: (callback, thisArg) => {
|
|
473
|
-
for (const key of read.ids()) callback.call(thisArg, read.get(key), key, view);
|
|
474
|
-
},
|
|
475
|
-
[Symbol.iterator]: entries
|
|
476
|
-
};
|
|
477
|
-
return Object.freeze(view);
|
|
478
|
-
};
|
|
479
|
-
const publicSource = (source) => {
|
|
480
|
-
if (!source || typeof source !== "object") return source;
|
|
481
|
-
if (!("kind" in source)) return source;
|
|
482
|
-
if (source.kind === "value") return source.value;
|
|
483
|
-
if (source.kind === "document") return snapshot(source.read);
|
|
484
|
-
if (source.kind === "collection") {
|
|
485
|
-
const read = source.read;
|
|
486
|
-
return collectionView(read);
|
|
487
|
-
}
|
|
488
|
-
return source;
|
|
489
|
-
};
|
|
490
|
-
const publicInputs = (sources, initial = false) => {
|
|
491
|
-
const values = [];
|
|
492
|
-
const changes = [];
|
|
493
|
-
for (const key of Object.keys(sources).sort((left, right) => Number(left.slice(1)) - Number(right.slice(1)))) {
|
|
494
|
-
const source = sources[key];
|
|
495
|
-
values.push(publicSource(source));
|
|
496
|
-
changes.push(initial && source && typeof source === "object" && "kind" in source && source.kind === "collection" ? resetCollectionChange : collectionChange(source));
|
|
497
|
-
}
|
|
498
|
-
return {
|
|
499
|
-
values,
|
|
500
|
-
changes
|
|
501
|
-
};
|
|
502
|
-
};
|
|
503
|
-
function createIncrementalValue(dependencies, processor) {
|
|
504
|
-
const dependencyMap = dependenciesOf(dependencies);
|
|
505
|
-
const build = (sources) => {
|
|
506
|
-
const state = Object.create(null);
|
|
507
|
-
let current;
|
|
508
|
-
const publicInputsForBuild = publicInputs(sources, true);
|
|
509
|
-
const result = processor({
|
|
510
|
-
sources: publicInputsForBuild.values,
|
|
511
|
-
changes: publicInputsForBuild.changes,
|
|
512
|
-
previous: void 0,
|
|
513
|
-
reset: true,
|
|
514
|
-
cause: sourceCause(sources),
|
|
515
|
-
state
|
|
516
|
-
});
|
|
517
|
-
if (isRebuild(result)) throw new TypeError("Initial incremental processor cannot rebuild.");
|
|
518
|
-
current = result;
|
|
519
|
-
return {
|
|
520
|
-
value: current,
|
|
521
|
-
update: (nextSources) => {
|
|
522
|
-
const publicInputsForUpdate = publicInputs(nextSources);
|
|
523
|
-
const next = processor({
|
|
524
|
-
sources: publicInputsForUpdate.values,
|
|
525
|
-
changes: publicInputsForUpdate.changes,
|
|
526
|
-
previous: current,
|
|
527
|
-
reset: false,
|
|
528
|
-
cause: sourceCause(nextSources),
|
|
529
|
-
state
|
|
530
|
-
});
|
|
531
|
-
if (isRebuild(next)) return next;
|
|
532
|
-
current = next;
|
|
533
|
-
return {
|
|
534
|
-
kind: "changed",
|
|
535
|
-
value: current
|
|
536
|
-
};
|
|
537
|
-
}
|
|
538
|
-
};
|
|
539
|
-
};
|
|
540
|
-
return defineIncrementalValue({
|
|
541
|
-
dependencies: dependencyMap,
|
|
542
|
-
build
|
|
543
|
-
});
|
|
544
|
-
}
|
|
545
|
-
function dependenciesOf(dependencies) {
|
|
546
|
-
if (!Array.isArray(dependencies)) throw new TypeError("Incremental dependencies must be projections.");
|
|
547
|
-
dependencies.forEach((dependency) => definitionOf(dependency));
|
|
548
|
-
return Object.freeze(Object.fromEntries(dependencies.map((dependency, index) => [`d${index}`, dependency])));
|
|
549
|
-
}
|
|
550
|
-
function createIncrementalCollection(dependencies, processor) {
|
|
551
|
-
const dependencyMap = dependenciesOf(dependencies);
|
|
552
|
-
const build = (input) => {
|
|
553
|
-
const state = Object.create(null);
|
|
554
|
-
const publicInputsForBuild = publicInputs(input.sources, true);
|
|
555
|
-
if (processor({
|
|
556
|
-
sources: publicInputsForBuild.values,
|
|
557
|
-
changes: publicInputsForBuild.changes,
|
|
558
|
-
previous: input.previous,
|
|
559
|
-
next: input.next,
|
|
560
|
-
reset: true,
|
|
561
|
-
cause: sourceCause(input.sources),
|
|
562
|
-
state,
|
|
563
|
-
output: input.output
|
|
564
|
-
})?.kind === "rebuild") throw new TypeError("Initial incremental collection processor cannot rebuild.");
|
|
565
|
-
return { update: (nextInput) => {
|
|
566
|
-
const publicInputsForUpdate = publicInputs(nextInput.sources);
|
|
567
|
-
return processor({
|
|
568
|
-
sources: publicInputsForUpdate.values,
|
|
569
|
-
changes: publicInputsForUpdate.changes,
|
|
570
|
-
previous: nextInput.previous,
|
|
571
|
-
next: nextInput.next,
|
|
572
|
-
reset: false,
|
|
573
|
-
cause: sourceCause(nextInput.sources),
|
|
574
|
-
state,
|
|
575
|
-
output: nextInput.output
|
|
576
|
-
});
|
|
577
|
-
} };
|
|
578
|
-
};
|
|
579
|
-
return defineIncrementalCollection({
|
|
580
|
-
dependencies: dependencyMap,
|
|
581
|
-
build
|
|
582
|
-
});
|
|
583
|
-
}
|
|
584
|
-
const groupOutputMetadata = /* @__PURE__ */ new WeakMap();
|
|
585
|
-
const isPlainGroupNamespace = (value) => value !== null && typeof value === "object" && !groupOutputMetadata.has(value) && !Array.isArray(value) && (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null);
|
|
586
|
-
const compileGroupShape = (value, path, declaredOutputs, used, outputs) => {
|
|
587
|
-
if (value !== null && typeof value === "object") {
|
|
588
|
-
const metadata = groupOutputMetadata.get(value);
|
|
589
|
-
if (metadata) {
|
|
590
|
-
if (!declaredOutputs.has(value)) throw new TypeError("Incremental group outputs must be declared by this group.");
|
|
591
|
-
if (used.has(value)) throw new TypeError("An incremental group output cannot be reused.");
|
|
592
|
-
used.add(value);
|
|
593
|
-
const index = outputs.length;
|
|
594
|
-
outputs.push({
|
|
595
|
-
path: Object.freeze([...path]),
|
|
596
|
-
isEqual: metadata.isEqual
|
|
597
|
-
});
|
|
598
|
-
return index;
|
|
599
|
-
}
|
|
600
|
-
}
|
|
601
|
-
if (!isPlainGroupNamespace(value)) throw new TypeError("Incremental group outputs must be a static object tree.");
|
|
602
|
-
for (const key of Reflect.ownKeys(value)) {
|
|
603
|
-
if (typeof key !== "string") throw new TypeError("Incremental group output names must be strings.");
|
|
604
|
-
if (!Object.prototype.propertyIsEnumerable.call(value, key)) throw new TypeError("Incremental group namespaces must contain enumerable properties.");
|
|
605
|
-
}
|
|
606
|
-
const keys = Object.keys(value);
|
|
607
|
-
if (!keys.length) throw new TypeError("Incremental group namespaces cannot be empty.");
|
|
608
|
-
const result = Object.create(null);
|
|
609
|
-
for (const key of keys) {
|
|
610
|
-
if (key === "__proto__" || key === "prototype" || key === "constructor") throw new TypeError(`Invalid incremental group output name: ${key}`);
|
|
611
|
-
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
612
|
-
if (!descriptor || !("value" in descriptor)) throw new TypeError("Incremental group namespaces cannot contain accessors.");
|
|
613
|
-
result[key] = compileGroupShape(descriptor.value, [...path, key], declaredOutputs, used, outputs);
|
|
614
|
-
}
|
|
615
|
-
return Object.freeze(result);
|
|
616
|
-
};
|
|
617
|
-
const hydrateGroupShape = (shape, values) => {
|
|
618
|
-
if (typeof shape === "number") return values[shape];
|
|
619
|
-
const result = {};
|
|
620
|
-
for (const [key, child] of Object.entries(shape)) result[key] = hydrateGroupShape(child, values);
|
|
621
|
-
return Object.freeze(result);
|
|
622
|
-
};
|
|
623
|
-
function createIncrementalGroup(dependencies, defineOutputs, processor) {
|
|
624
|
-
const dependencyMap = dependenciesOf(dependencies);
|
|
625
|
-
if (typeof defineOutputs !== "function") throw new TypeError("Incremental group outputs must be declared by a callback.");
|
|
626
|
-
if (typeof processor !== "function") throw new TypeError("Incremental group processor must be a function.");
|
|
627
|
-
let active = true;
|
|
628
|
-
const declaredOutputs = /* @__PURE__ */ new Set();
|
|
629
|
-
const declared = defineOutputs({ collection: (equality) => {
|
|
630
|
-
if (!active) throw new TypeError("Incremental group output declarations are synchronous.");
|
|
631
|
-
const descriptor = Object.freeze({});
|
|
632
|
-
groupOutputMetadata.set(descriptor, { isEqual: equality });
|
|
633
|
-
declaredOutputs.add(descriptor);
|
|
634
|
-
return descriptor;
|
|
635
|
-
} });
|
|
636
|
-
assertSynchronous(declared);
|
|
637
|
-
active = false;
|
|
638
|
-
const outputs = [];
|
|
639
|
-
const used = /* @__PURE__ */ new Set();
|
|
640
|
-
const shape = compileGroupShape(declared, [], declaredOutputs, used, outputs);
|
|
641
|
-
if (typeof shape === "number") throw new TypeError("Incremental group declarations must return an output namespace.");
|
|
642
|
-
if (used.size === 0 || used.size !== declaredOutputs.size) throw new TypeError("Every incremental group output must be returned by the declaration.");
|
|
643
|
-
const stateFactory = () => Object.create(null);
|
|
644
|
-
const build = (input) => {
|
|
645
|
-
const state = stateFactory();
|
|
646
|
-
const run = (nextInput, reset) => {
|
|
647
|
-
const publicInput = publicInputs(nextInput.sources, reset);
|
|
648
|
-
const result = processor({
|
|
649
|
-
sources: publicInput.values,
|
|
650
|
-
changes: publicInput.changes,
|
|
651
|
-
previous: hydrateGroupShape(shape, nextInput.previous),
|
|
652
|
-
next: hydrateGroupShape(shape, nextInput.next),
|
|
653
|
-
outputs: hydrateGroupShape(shape, nextInput.outputs),
|
|
654
|
-
reset,
|
|
655
|
-
cause: sourceCause(nextInput.sources),
|
|
656
|
-
state
|
|
657
|
-
});
|
|
658
|
-
assertSynchronous(result);
|
|
659
|
-
return result;
|
|
660
|
-
};
|
|
661
|
-
if (isRebuild(run(input, true))) throw new TypeError("Initial incremental group processor cannot rebuild.");
|
|
662
|
-
return { update: (nextInput) => {
|
|
663
|
-
const result = run(nextInput, false);
|
|
664
|
-
return isRebuild(result) ? result : void 0;
|
|
665
|
-
} };
|
|
666
|
-
};
|
|
667
|
-
return hydrateGroupShape(shape, defineIncrementalGroup({
|
|
668
|
-
dependencies: dependencyMap,
|
|
669
|
-
outputs,
|
|
670
|
-
build
|
|
671
|
-
}).projections);
|
|
672
|
-
}
|
|
673
|
-
const incremental = Object.assign(createIncrementalValue, {
|
|
674
|
-
collection: createIncrementalCollection,
|
|
675
|
-
group: createIncrementalGroup
|
|
676
|
-
});
|
|
677
|
-
//#endregion
|
|
678
|
-
export { projectionHandles as a, definitionOf as c, isProjection as d, observe as f, createScheduler as i, derive as l, ownerOf as m, assertScope as n, ProjectionDisposedError as o, ownDefinition as p, assertSynchronous as r, ProjectionError as s, incremental as t, input as u };
|
|
679
|
-
|
|
680
|
-
//# sourceMappingURL=advanced-BYZCjNWL.js.map
|