doxum 0.1.5 → 0.1.6
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 +46 -5
- package/dist/{contract-4E3moCbY.d.ts → contract-I99DUMbN.d.ts} +1 -1
- package/dist/index.cjs +73 -608
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -63
- package/dist/index.d.ts +3 -64
- package/dist/index.js +11 -547
- package/dist/index.js.map +1 -1
- package/dist/integration-Bs3pOk65.cjs +35 -0
- package/dist/integration-Bs3pOk65.cjs.map +1 -0
- package/dist/integration-xupBIKjU.js +30 -0
- package/dist/integration-xupBIKjU.js.map +1 -0
- package/dist/integration.cjs +4 -14
- package/dist/integration.d.cts +2 -1
- package/dist/integration.d.ts +3 -2
- package/dist/integration.js +3 -14
- package/dist/local-sync.cjs +1 -1
- package/dist/local-sync.d.ts +1 -1
- package/dist/local-sync.js +1 -1
- package/dist/{ownership-CU-9DKJQ.cjs → ownership-CY0nPXGF.cjs} +4 -1
- package/dist/ownership-CY0nPXGF.cjs.map +1 -0
- package/dist/{ownership-B-VAPcce.js → ownership-CduRygE7.js} +4 -1
- package/dist/ownership-CduRygE7.js.map +1 -0
- package/dist/react.cjs +1 -1
- package/dist/react.js +1 -1
- package/dist/runtime-BJRXF0gq.js +1735 -0
- package/dist/runtime-BJRXF0gq.js.map +1 -0
- package/dist/runtime-CRijXjYp.cjs +1991 -0
- package/dist/runtime-CRijXjYp.cjs.map +1 -0
- package/dist/runtime-CUcvhFNP.d.ts +152 -0
- package/dist/runtime-C_vKHmhy.d.cts +152 -0
- package/package.json +1 -1
- package/skills/doxum-runtime/references/guide.en.md +30 -18
- package/skills/doxum-runtime/references/guide.zh-CN.md +22 -14
- package/skills/doxum-runtime/references/invariants.en.md +12 -9
- package/skills/doxum-runtime/references/invariants.zh-CN.md +2 -2
- package/skills/doxum-runtime/references/patterns.en.md +29 -56
- package/skills/doxum-runtime/references/patterns.zh-CN.md +21 -45
- package/dist/dependency-C5_R1tvQ.js +0 -496
- package/dist/dependency-C5_R1tvQ.js.map +0 -1
- package/dist/dependency-Dfzs3khk.cjs +0 -722
- package/dist/dependency-Dfzs3khk.cjs.map +0 -1
- package/dist/integration.cjs.map +0 -1
- package/dist/integration.js.map +0 -1
- package/dist/ownership-B-VAPcce.js.map +0 -1
- package/dist/ownership-CU-9DKJQ.cjs.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { A as
|
|
2
|
-
import { a as isStablePayload, c as snapshotPayload, i as isRecord, l as transferPayload, n as deepEqual, o as ownPayload, r as isPlainObject, s as sameStructuralValue, t as cloneValue, u as profile } from "./ownership-
|
|
1
|
+
import { A as dict, B as tree, C as debugKey, D as resolveAddress, E as read, F as optional, I as record, L as schema, M as list, N as map, O as resolveLocated, P as object, R as single, S as contains, T as overlaps, V as variant, _ as address$2, a as createNotification, b as impact_target_exports, c as shareNotification, d as accessOf, f as bindRuntimeAccess, g as documentReader, h as DocumentReentrancyError, i as ProjectionError, j as field, k as set$1, l as subscribeRoot, m as DocumentDisposedError, o as disposeNotification, p as readWith, r as ProjectionDisposedError, s as notify, t as createProjectionRuntime, u as subscribeTargets, v as belongs, w as locate, y as id, z as table } from "./runtime-BJRXF0gq.js";
|
|
2
|
+
import { a as isStablePayload, c as snapshotPayload, i as isRecord, l as transferPayload, n as deepEqual, o as ownPayload, r as isPlainObject, s as sameStructuralValue, t as cloneValue, u as profile } from "./ownership-CduRygE7.js";
|
|
3
3
|
import { n as bindRuntimeDriver, r as disposeRuntimeDriver, t as assertRuntimeWritable } from "./driver-CbzfW5MR.js";
|
|
4
4
|
//#region core/src/impact.ts
|
|
5
5
|
const emptyCollectionImpact = Object.freeze({
|
|
@@ -2296,166 +2296,6 @@ const decodeCommandFootprint = (value) => {
|
|
|
2296
2296
|
return Object.freeze(Array.from(targets.values()));
|
|
2297
2297
|
};
|
|
2298
2298
|
//#endregion
|
|
2299
|
-
//#region core/src/runtime/notification.ts
|
|
2300
|
-
const ROOT_BUCKET = Symbol("document-root");
|
|
2301
|
-
const notifications = /* @__PURE__ */ new WeakMap();
|
|
2302
|
-
const key = (value) => bucket(value) ?? ROOT_BUCKET;
|
|
2303
|
-
const createNotification = (runtime) => {
|
|
2304
|
-
const notification = {
|
|
2305
|
-
root: /* @__PURE__ */ new Set(),
|
|
2306
|
-
filtered: /* @__PURE__ */ new Set(),
|
|
2307
|
-
buckets: /* @__PURE__ */ new Map(),
|
|
2308
|
-
processors: [],
|
|
2309
|
-
candidates: /* @__PURE__ */ new Set(),
|
|
2310
|
-
rootSnapshot: [],
|
|
2311
|
-
notifying: false
|
|
2312
|
-
};
|
|
2313
|
-
notifications.set(runtime, notification);
|
|
2314
|
-
return notification;
|
|
2315
|
-
};
|
|
2316
|
-
const notificationOf = (runtime) => {
|
|
2317
|
-
const value = notifications.get(runtime);
|
|
2318
|
-
if (!value) throw new Error("Unknown Doxum runtime.");
|
|
2319
|
-
return value;
|
|
2320
|
-
};
|
|
2321
|
-
const shareNotification = (source, target) => {
|
|
2322
|
-
notifications.set(target, notificationOf(source));
|
|
2323
|
-
};
|
|
2324
|
-
const registerProcessor = (runtime, processor) => {
|
|
2325
|
-
const notification = notificationOf(runtime);
|
|
2326
|
-
const entry = {
|
|
2327
|
-
processor,
|
|
2328
|
-
active: true
|
|
2329
|
-
};
|
|
2330
|
-
notification.processors.push(entry);
|
|
2331
|
-
return () => {
|
|
2332
|
-
if (!entry.active) return;
|
|
2333
|
-
entry.active = false;
|
|
2334
|
-
if (!notification.notifying) {
|
|
2335
|
-
const index = notification.processors.indexOf(entry);
|
|
2336
|
-
if (index >= 0) notification.processors.splice(index, 1);
|
|
2337
|
-
}
|
|
2338
|
-
};
|
|
2339
|
-
};
|
|
2340
|
-
const subscribeRoot = (notification, listener) => {
|
|
2341
|
-
const entry = {
|
|
2342
|
-
listener,
|
|
2343
|
-
active: true
|
|
2344
|
-
};
|
|
2345
|
-
notification.root.add(entry);
|
|
2346
|
-
return () => {
|
|
2347
|
-
entry.active = false;
|
|
2348
|
-
if (!notification.notifying) notification.root.delete(entry);
|
|
2349
|
-
};
|
|
2350
|
-
};
|
|
2351
|
-
const subscribeTargets = (notification, targets, listener) => {
|
|
2352
|
-
const entry = {
|
|
2353
|
-
targets: Object.freeze(targets.slice()),
|
|
2354
|
-
listener,
|
|
2355
|
-
active: true
|
|
2356
|
-
};
|
|
2357
|
-
notification.filtered.add(entry);
|
|
2358
|
-
const keys = new Set(targets.map(key));
|
|
2359
|
-
keys.forEach((key) => {
|
|
2360
|
-
const bucket = notification.buckets.get(key) ?? /* @__PURE__ */ new Set();
|
|
2361
|
-
bucket.add(entry);
|
|
2362
|
-
notification.buckets.set(key, bucket);
|
|
2363
|
-
});
|
|
2364
|
-
return () => {
|
|
2365
|
-
if (!entry.active) return;
|
|
2366
|
-
entry.active = false;
|
|
2367
|
-
if (notification.notifying) return;
|
|
2368
|
-
notification.filtered.delete(entry);
|
|
2369
|
-
keys.forEach((key) => {
|
|
2370
|
-
const bucket = notification.buckets.get(key);
|
|
2371
|
-
bucket?.delete(entry);
|
|
2372
|
-
if (bucket?.size === 0) notification.buckets.delete(key);
|
|
2373
|
-
});
|
|
2374
|
-
};
|
|
2375
|
-
};
|
|
2376
|
-
const notify = (notification, commit) => {
|
|
2377
|
-
notification.notifying = true;
|
|
2378
|
-
const errors = [];
|
|
2379
|
-
const call = (listener) => {
|
|
2380
|
-
try {
|
|
2381
|
-
listener(commit);
|
|
2382
|
-
} catch (error) {
|
|
2383
|
-
errors.push(Object.freeze({
|
|
2384
|
-
phase: "listener",
|
|
2385
|
-
error
|
|
2386
|
-
}));
|
|
2387
|
-
}
|
|
2388
|
-
};
|
|
2389
|
-
try {
|
|
2390
|
-
const processorCount = notification.processors.length;
|
|
2391
|
-
for (let index = 0; index < processorCount; index += 1) {
|
|
2392
|
-
const entry = notification.processors[index];
|
|
2393
|
-
if (!entry?.active) continue;
|
|
2394
|
-
try {
|
|
2395
|
-
entry.processor.process(commit);
|
|
2396
|
-
} catch (error) {
|
|
2397
|
-
errors.push(Object.freeze({
|
|
2398
|
-
phase: "processor",
|
|
2399
|
-
error
|
|
2400
|
-
}));
|
|
2401
|
-
}
|
|
2402
|
-
}
|
|
2403
|
-
for (let index = 0; index < processorCount; index += 1) {
|
|
2404
|
-
const entry = notification.processors[index];
|
|
2405
|
-
if (!entry?.active) continue;
|
|
2406
|
-
try {
|
|
2407
|
-
entry.processor.flush();
|
|
2408
|
-
} catch (error) {
|
|
2409
|
-
errors.push(Object.freeze({
|
|
2410
|
-
phase: "flush",
|
|
2411
|
-
error
|
|
2412
|
-
}));
|
|
2413
|
-
}
|
|
2414
|
-
}
|
|
2415
|
-
const candidates = notification.candidates;
|
|
2416
|
-
candidates.clear();
|
|
2417
|
-
if (commit.impact.kind === "reset") notification.filtered.forEach((entry) => candidates.add(entry));
|
|
2418
|
-
else for (const operation of commit.operations) {
|
|
2419
|
-
const key = operation.at[0] ?? ROOT_BUCKET;
|
|
2420
|
-
notification.buckets.get(key)?.forEach((entry) => candidates.add(entry));
|
|
2421
|
-
notification.buckets.get(ROOT_BUCKET)?.forEach((entry) => candidates.add(entry));
|
|
2422
|
-
}
|
|
2423
|
-
candidates.forEach((entry) => {
|
|
2424
|
-
if (entry.active && entry.targets.some(commit.impact.affects)) call(entry.listener);
|
|
2425
|
-
});
|
|
2426
|
-
const rootSnapshot = notification.rootSnapshot;
|
|
2427
|
-
rootSnapshot.length = 0;
|
|
2428
|
-
notification.root.forEach((entry) => rootSnapshot.push(entry));
|
|
2429
|
-
for (const entry of rootSnapshot) if (entry.active) call(entry.listener);
|
|
2430
|
-
} finally {
|
|
2431
|
-
notification.notifying = false;
|
|
2432
|
-
let writeIndex = 0;
|
|
2433
|
-
for (const entry of notification.processors) if (entry.active) notification.processors[writeIndex++] = entry;
|
|
2434
|
-
notification.processors.length = writeIndex;
|
|
2435
|
-
notification.root.forEach((entry) => {
|
|
2436
|
-
if (!entry.active) notification.root.delete(entry);
|
|
2437
|
-
});
|
|
2438
|
-
notification.filtered.forEach((entry) => {
|
|
2439
|
-
if (!entry.active) notification.filtered.delete(entry);
|
|
2440
|
-
});
|
|
2441
|
-
notification.buckets.forEach((bucket, key) => {
|
|
2442
|
-
bucket.forEach((entry) => {
|
|
2443
|
-
if (!entry.active) bucket.delete(entry);
|
|
2444
|
-
});
|
|
2445
|
-
if (bucket.size === 0) notification.buckets.delete(key);
|
|
2446
|
-
});
|
|
2447
|
-
}
|
|
2448
|
-
return Object.freeze(errors);
|
|
2449
|
-
};
|
|
2450
|
-
const disposeNotification = (notification) => {
|
|
2451
|
-
notification.root.clear();
|
|
2452
|
-
notification.filtered.clear();
|
|
2453
|
-
notification.buckets.clear();
|
|
2454
|
-
notification.processors.length = 0;
|
|
2455
|
-
notification.candidates.clear();
|
|
2456
|
-
notification.rootSnapshot.length = 0;
|
|
2457
|
-
};
|
|
2458
|
-
//#endregion
|
|
2459
2299
|
//#region core/src/runtime.ts
|
|
2460
2300
|
var RejectedUpdate = class extends Error {
|
|
2461
2301
|
issues;
|
|
@@ -2485,6 +2325,7 @@ const createDocument = (input) => {
|
|
|
2485
2325
|
const assertWritable = (intent) => {
|
|
2486
2326
|
if (state.disposed) throw new DocumentDisposedError();
|
|
2487
2327
|
if (busy) throw new DocumentReentrancyError();
|
|
2328
|
+
if (accessOf(runtime).projectionLocks) throw new DocumentReentrancyError();
|
|
2488
2329
|
assertRuntimeWritable(runtime, intent);
|
|
2489
2330
|
};
|
|
2490
2331
|
const runTransaction = (session, run) => {
|
|
@@ -2716,10 +2557,14 @@ const createDocument = (input) => {
|
|
|
2716
2557
|
history: history.api,
|
|
2717
2558
|
dispose: () => {
|
|
2718
2559
|
if (state.disposed) return;
|
|
2560
|
+
if (busy || accessOf(runtime).projectionLocks) throw new DocumentReentrancyError();
|
|
2719
2561
|
state.disposed = true;
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2562
|
+
try {
|
|
2563
|
+
disposeNotification(notification);
|
|
2564
|
+
} finally {
|
|
2565
|
+
history.api.clear();
|
|
2566
|
+
disposeRuntimeDriver(runtime);
|
|
2567
|
+
}
|
|
2723
2568
|
}
|
|
2724
2569
|
};
|
|
2725
2570
|
bindRuntimeAccess(runtime, state);
|
|
@@ -2743,387 +2588,6 @@ const asReadable = (runtime) => {
|
|
|
2743
2588
|
//#region core/src/projection/select.ts
|
|
2744
2589
|
const select = (runtime, selector) => readWith(runtime, selector);
|
|
2745
2590
|
//#endregion
|
|
2746
|
-
|
|
2747
|
-
const createCollectionView = (input) => {
|
|
2748
|
-
if (schemaOf(input.runtime) !== input.source.schema) throw new Error("Collection selector belongs to another schema.");
|
|
2749
|
-
const idsListeners = /* @__PURE__ */ new Set();
|
|
2750
|
-
const allListeners = /* @__PURE__ */ new Set();
|
|
2751
|
-
const itemListeners = /* @__PURE__ */ new Map();
|
|
2752
|
-
const itemReadables = /* @__PURE__ */ new Map();
|
|
2753
|
-
let disposed = false;
|
|
2754
|
-
const sourceNode = nodeAt$1(input.source.schema, input.source.address);
|
|
2755
|
-
const entryNode = sourceNode?.kind === "table" || sourceNode?.kind === "map" ? sourceNode.value : {
|
|
2756
|
-
kind: "object",
|
|
2757
|
-
shape: {}
|
|
2758
|
-
};
|
|
2759
|
-
const mapEntry = (document, id) => {
|
|
2760
|
-
profile.collectionView.mapped();
|
|
2761
|
-
const address = [...input.source.address, String(id)];
|
|
2762
|
-
let active = true;
|
|
2763
|
-
try {
|
|
2764
|
-
return input.map(id, readerFor(entryNode, {
|
|
2765
|
-
root: () => document,
|
|
2766
|
-
active: () => active
|
|
2767
|
-
}, address));
|
|
2768
|
-
} finally {
|
|
2769
|
-
active = false;
|
|
2770
|
-
}
|
|
2771
|
-
};
|
|
2772
|
-
const build = (previous, changed) => {
|
|
2773
|
-
const document = documentOf(input.runtime);
|
|
2774
|
-
const collection = read(document, input.source.address);
|
|
2775
|
-
const ids = collection && typeof collection === "object" && "ids" in collection && Array.isArray(collection.ids) ? [...collection.ids] : Object.keys(collection ?? {});
|
|
2776
|
-
profile.collectionView.idsScanned(ids.length);
|
|
2777
|
-
const values = previous && changed ? previous.values : /* @__PURE__ */ new Map();
|
|
2778
|
-
if (previous && changed) {
|
|
2779
|
-
const nextIds = new Set(ids);
|
|
2780
|
-
for (const id of previous.ids) if (!nextIds.has(id)) values.delete(id);
|
|
2781
|
-
}
|
|
2782
|
-
for (const id of ids) {
|
|
2783
|
-
if (previous && changed && previous.values.has(id) && !changed.has(id)) continue;
|
|
2784
|
-
const next = mapEntry(document, id);
|
|
2785
|
-
if (previous && changed && previous.values.has(id)) {
|
|
2786
|
-
const before = previous.values.get(id);
|
|
2787
|
-
if (input.isEqual ? input.isEqual(before, next) : Object.is(before, next)) {
|
|
2788
|
-
changed.delete(id);
|
|
2789
|
-
continue;
|
|
2790
|
-
}
|
|
2791
|
-
}
|
|
2792
|
-
values.set(id, next);
|
|
2793
|
-
}
|
|
2794
|
-
return {
|
|
2795
|
-
ids: Object.freeze(ids),
|
|
2796
|
-
values,
|
|
2797
|
-
all: void 0,
|
|
2798
|
-
allDirty: true
|
|
2799
|
-
};
|
|
2800
|
-
};
|
|
2801
|
-
let state = build();
|
|
2802
|
-
const ensureAll = () => {
|
|
2803
|
-
if (!state.allDirty && state.all) return state.all;
|
|
2804
|
-
profile.collectionView.arrayCopied();
|
|
2805
|
-
const all = new Array(state.ids.length);
|
|
2806
|
-
for (let index = 0; index < state.ids.length; index += 1) all[index] = state.values.get(state.ids[index]);
|
|
2807
|
-
const stable = Object.freeze(all);
|
|
2808
|
-
state.all = stable;
|
|
2809
|
-
state.allDirty = false;
|
|
2810
|
-
return stable;
|
|
2811
|
-
};
|
|
2812
|
-
const emit = (listeners) => {
|
|
2813
|
-
Array.from(listeners).forEach((listener) => listener());
|
|
2814
|
-
};
|
|
2815
|
-
const unsubscribe = input.runtime.subscribe(input.source, (commit) => {
|
|
2816
|
-
if (disposed) return;
|
|
2817
|
-
const impact = commit.impact.collection(input.source);
|
|
2818
|
-
if (impact.kind === "incremental" && impact.added.size === 0 && impact.removed.size === 0 && !impact.orderChanged) {
|
|
2819
|
-
const previous = state;
|
|
2820
|
-
const changes = [];
|
|
2821
|
-
const document = documentOf(input.runtime);
|
|
2822
|
-
impact.updated.forEach((id) => {
|
|
2823
|
-
if (!previous.values.has(id)) return;
|
|
2824
|
-
const before = previous.values.get(id);
|
|
2825
|
-
const after = mapEntry(document, id);
|
|
2826
|
-
if (input.isEqual ? input.isEqual(before, after) : Object.is(before, after)) return;
|
|
2827
|
-
changes.push([id, after]);
|
|
2828
|
-
});
|
|
2829
|
-
if (changes.length === 0) return;
|
|
2830
|
-
for (const [id, value] of changes) previous.values.set(id, value);
|
|
2831
|
-
previous.all = void 0;
|
|
2832
|
-
previous.allDirty = true;
|
|
2833
|
-
emit(allListeners);
|
|
2834
|
-
for (const [id] of changes) {
|
|
2835
|
-
const listeners = itemListeners.get(id);
|
|
2836
|
-
if (listeners) emit(listeners);
|
|
2837
|
-
}
|
|
2838
|
-
return;
|
|
2839
|
-
}
|
|
2840
|
-
const changed = impact.kind === "reset" ? void 0 : new Set([...impact.added, ...impact.updated]);
|
|
2841
|
-
const previous = state;
|
|
2842
|
-
const next = build(previous, changed);
|
|
2843
|
-
const changedIds = /* @__PURE__ */ new Set();
|
|
2844
|
-
if (changed) {
|
|
2845
|
-
changed.forEach((id) => changedIds.add(id));
|
|
2846
|
-
previous.ids.forEach((id) => {
|
|
2847
|
-
if (!next.values.has(id)) changedIds.add(id);
|
|
2848
|
-
});
|
|
2849
|
-
next.ids.forEach((id) => {
|
|
2850
|
-
if (!previous.values.has(id)) changedIds.add(id);
|
|
2851
|
-
});
|
|
2852
|
-
} else {
|
|
2853
|
-
previous.ids.forEach((id) => {
|
|
2854
|
-
if (!next.values.has(id)) changedIds.add(id);
|
|
2855
|
-
else if (!(input.isEqual ? input.isEqual(previous.values.get(id), next.values.get(id)) : Object.is(previous.values.get(id), next.values.get(id)))) changedIds.add(id);
|
|
2856
|
-
});
|
|
2857
|
-
next.ids.forEach((id) => {
|
|
2858
|
-
if (!previous.values.has(id)) changedIds.add(id);
|
|
2859
|
-
});
|
|
2860
|
-
}
|
|
2861
|
-
const idsChanged = impact.kind === "incremental" ? impact.added.size > 0 || impact.removed.size > 0 || impact.orderChanged : previous.ids.length !== next.ids.length || previous.ids.some((id, index) => next.ids[index] !== id);
|
|
2862
|
-
state = idsChanged || changedIds.size ? next : previous;
|
|
2863
|
-
if (idsChanged) emit(idsListeners);
|
|
2864
|
-
if (idsChanged || changedIds.size) emit(allListeners);
|
|
2865
|
-
changedIds.forEach((id) => {
|
|
2866
|
-
const listeners = itemListeners.get(id);
|
|
2867
|
-
if (listeners) emit(listeners);
|
|
2868
|
-
});
|
|
2869
|
-
});
|
|
2870
|
-
return {
|
|
2871
|
-
ids: {
|
|
2872
|
-
current: () => state.ids,
|
|
2873
|
-
revision: () => input.runtime.revision(),
|
|
2874
|
-
subscribe: (listener) => {
|
|
2875
|
-
if (disposed) return () => void 0;
|
|
2876
|
-
idsListeners.add(listener);
|
|
2877
|
-
return () => idsListeners.delete(listener);
|
|
2878
|
-
}
|
|
2879
|
-
},
|
|
2880
|
-
all: {
|
|
2881
|
-
current: ensureAll,
|
|
2882
|
-
revision: () => input.runtime.revision(),
|
|
2883
|
-
subscribe: (listener) => {
|
|
2884
|
-
if (disposed) return () => void 0;
|
|
2885
|
-
allListeners.add(listener);
|
|
2886
|
-
return () => allListeners.delete(listener);
|
|
2887
|
-
}
|
|
2888
|
-
},
|
|
2889
|
-
item: (id) => {
|
|
2890
|
-
const cached = itemReadables.get(id);
|
|
2891
|
-
if (cached) return cached;
|
|
2892
|
-
const readable = {
|
|
2893
|
-
current: () => state.values.get(id),
|
|
2894
|
-
revision: () => input.runtime.revision(),
|
|
2895
|
-
subscribe: (listener) => {
|
|
2896
|
-
if (disposed) return () => void 0;
|
|
2897
|
-
const listeners = itemListeners.get(id) ?? /* @__PURE__ */ new Set();
|
|
2898
|
-
itemListeners.set(id, listeners);
|
|
2899
|
-
listeners.add(listener);
|
|
2900
|
-
return () => {
|
|
2901
|
-
listeners.delete(listener);
|
|
2902
|
-
if (listeners.size === 0) itemListeners.delete(id);
|
|
2903
|
-
};
|
|
2904
|
-
}
|
|
2905
|
-
};
|
|
2906
|
-
itemReadables.set(id, readable);
|
|
2907
|
-
return readable;
|
|
2908
|
-
},
|
|
2909
|
-
revision: () => input.runtime.revision(),
|
|
2910
|
-
dispose: () => {
|
|
2911
|
-
if (disposed) return;
|
|
2912
|
-
disposed = true;
|
|
2913
|
-
unsubscribe();
|
|
2914
|
-
idsListeners.clear();
|
|
2915
|
-
allListeners.clear();
|
|
2916
|
-
itemListeners.clear();
|
|
2917
|
-
itemReadables.clear();
|
|
2918
|
-
state.values.clear();
|
|
2919
|
-
state = {
|
|
2920
|
-
ids: Object.freeze([]),
|
|
2921
|
-
values: /* @__PURE__ */ new Map(),
|
|
2922
|
-
all: Object.freeze([]),
|
|
2923
|
-
allDirty: false
|
|
2924
|
-
};
|
|
2925
|
-
}
|
|
2926
|
-
};
|
|
2927
|
-
};
|
|
2928
|
-
//#endregion
|
|
2929
|
-
//#region core/src/projection/materialized-view.ts
|
|
2930
|
-
const materializedMeta = /* @__PURE__ */ new WeakMap();
|
|
2931
|
-
const createMaterializedView = (runtime, spec) => {
|
|
2932
|
-
const listeners = /* @__PURE__ */ new Set();
|
|
2933
|
-
let disposed = false;
|
|
2934
|
-
let fault;
|
|
2935
|
-
let revision = runtime.revision();
|
|
2936
|
-
let instance;
|
|
2937
|
-
let currentValue;
|
|
2938
|
-
let pendingEmit = false;
|
|
2939
|
-
const dependencies = createDependencyTracker();
|
|
2940
|
-
const sources = spec.sources ?? {};
|
|
2941
|
-
const sourceEntries = Object.keys(sources).map((key) => [key, sources[key]]);
|
|
2942
|
-
sourceEntries.forEach(([, source]) => {
|
|
2943
|
-
const meta = materializedMeta.get(source);
|
|
2944
|
-
if (!meta || meta.runtime !== runtime) throw new Error("Materialized sources must belong to the same runtime and be created first.");
|
|
2945
|
-
});
|
|
2946
|
-
const sourceValuesRecord = {};
|
|
2947
|
-
let sourceChanged = false;
|
|
2948
|
-
for (const [key] of sourceEntries) sourceValuesRecord[key] = {
|
|
2949
|
-
value: void 0,
|
|
2950
|
-
change: void 0
|
|
2951
|
-
};
|
|
2952
|
-
const sourceValues = (commitRevision) => {
|
|
2953
|
-
sourceChanged = false;
|
|
2954
|
-
for (const [key, source] of sourceEntries) {
|
|
2955
|
-
const meta = materializedMeta.get(source);
|
|
2956
|
-
const entry = sourceValuesRecord[key];
|
|
2957
|
-
entry.value = meta?.value ?? source.current();
|
|
2958
|
-
entry.change = meta?.change;
|
|
2959
|
-
if (commitRevision !== void 0 && meta?.changedRevision === commitRevision) {
|
|
2960
|
-
sourceChanged = true;
|
|
2961
|
-
profile.materialized.sourceChanged();
|
|
2962
|
-
}
|
|
2963
|
-
}
|
|
2964
|
-
return sourceValuesRecord;
|
|
2965
|
-
};
|
|
2966
|
-
let activeImpact;
|
|
2967
|
-
const assertImpact = () => {
|
|
2968
|
-
if (!activeImpact) throw new Error("Materialized impact is no longer active.");
|
|
2969
|
-
return activeImpact;
|
|
2970
|
-
};
|
|
2971
|
-
const trackedImpact = {
|
|
2972
|
-
get kind() {
|
|
2973
|
-
return assertImpact().kind;
|
|
2974
|
-
},
|
|
2975
|
-
affects: (target) => {
|
|
2976
|
-
dependencies.record(target);
|
|
2977
|
-
return assertImpact().affects(target);
|
|
2978
|
-
},
|
|
2979
|
-
collection: (selector) => {
|
|
2980
|
-
dependencies.record(selector);
|
|
2981
|
-
return assertImpact().collection(selector);
|
|
2982
|
-
},
|
|
2983
|
-
get operations() {
|
|
2984
|
-
dependencies.record({
|
|
2985
|
-
kind: "value",
|
|
2986
|
-
at: []
|
|
2987
|
-
});
|
|
2988
|
-
return assertImpact().operations;
|
|
2989
|
-
}
|
|
2990
|
-
};
|
|
2991
|
-
let view;
|
|
2992
|
-
const writeMeta = (change, value, nextRevision, changed) => {
|
|
2993
|
-
const meta = materializedMeta.get(view);
|
|
2994
|
-
if (meta) {
|
|
2995
|
-
meta.value = value;
|
|
2996
|
-
meta.change = change;
|
|
2997
|
-
meta.revision = nextRevision;
|
|
2998
|
-
if (changed) meta.changedRevision = nextRevision;
|
|
2999
|
-
} else materializedMeta.set(view, {
|
|
3000
|
-
runtime,
|
|
3001
|
-
value,
|
|
3002
|
-
change,
|
|
3003
|
-
revision: nextRevision,
|
|
3004
|
-
changedRevision: changed ? nextRevision : -1
|
|
3005
|
-
});
|
|
3006
|
-
};
|
|
3007
|
-
const build = () => {
|
|
3008
|
-
profile.materialized.rebuilt();
|
|
3009
|
-
dependencies.clear();
|
|
3010
|
-
let active = true;
|
|
3011
|
-
try {
|
|
3012
|
-
instance = spec.build({
|
|
3013
|
-
read: documentReader(schemaOf(runtime), () => documentOf(runtime), () => active),
|
|
3014
|
-
sources: sourceValues()
|
|
3015
|
-
});
|
|
3016
|
-
currentValue = instance.value;
|
|
3017
|
-
fault = void 0;
|
|
3018
|
-
revision = runtime.revision();
|
|
3019
|
-
} finally {
|
|
3020
|
-
active = false;
|
|
3021
|
-
}
|
|
3022
|
-
};
|
|
3023
|
-
build();
|
|
3024
|
-
const emit = () => {
|
|
3025
|
-
profile.materialized.notification();
|
|
3026
|
-
Array.from(listeners).forEach((listener) => listener());
|
|
3027
|
-
};
|
|
3028
|
-
const process = (commit) => {
|
|
3029
|
-
if (disposed) return;
|
|
3030
|
-
try {
|
|
3031
|
-
if (commit.kind === "replace" || fault) {
|
|
3032
|
-
build();
|
|
3033
|
-
writeMeta(void 0, currentValue, commit.revision, true);
|
|
3034
|
-
pendingEmit = true;
|
|
3035
|
-
return;
|
|
3036
|
-
}
|
|
3037
|
-
const sourceSnapshot = sourceValues(commit.revision);
|
|
3038
|
-
if (!sourceChanged && dependencies.size() > 0 && !dependencies.some(commit.impact.affects)) {
|
|
3039
|
-
profile.materialized.skipped();
|
|
3040
|
-
revision = commit.revision;
|
|
3041
|
-
writeMeta(void 0, currentValue, commit.revision, false);
|
|
3042
|
-
return;
|
|
3043
|
-
}
|
|
3044
|
-
dependencies.clear();
|
|
3045
|
-
profile.materialized.updated();
|
|
3046
|
-
let active = true;
|
|
3047
|
-
let result;
|
|
3048
|
-
try {
|
|
3049
|
-
activeImpact = commit.impact;
|
|
3050
|
-
result = instance.update({
|
|
3051
|
-
read: documentReader(schemaOf(runtime), () => documentOf(runtime), () => active),
|
|
3052
|
-
revision: commit.revision,
|
|
3053
|
-
source: commit.source,
|
|
3054
|
-
impact: trackedImpact,
|
|
3055
|
-
sources: sourceSnapshot
|
|
3056
|
-
});
|
|
3057
|
-
} finally {
|
|
3058
|
-
activeImpact = void 0;
|
|
3059
|
-
active = false;
|
|
3060
|
-
}
|
|
3061
|
-
if (result.kind === "rebuild") {
|
|
3062
|
-
build();
|
|
3063
|
-
writeMeta(void 0, currentValue, commit.revision, true);
|
|
3064
|
-
pendingEmit = true;
|
|
3065
|
-
} else if (result.kind === "changed") {
|
|
3066
|
-
currentValue = result.value;
|
|
3067
|
-
revision = commit.revision;
|
|
3068
|
-
writeMeta(result.change, currentValue, commit.revision, true);
|
|
3069
|
-
pendingEmit = true;
|
|
3070
|
-
} else {
|
|
3071
|
-
revision = commit.revision;
|
|
3072
|
-
writeMeta(void 0, currentValue, commit.revision, false);
|
|
3073
|
-
}
|
|
3074
|
-
} catch (error) {
|
|
3075
|
-
try {
|
|
3076
|
-
build();
|
|
3077
|
-
writeMeta(void 0, currentValue, commit.revision, true);
|
|
3078
|
-
pendingEmit = true;
|
|
3079
|
-
} catch (rebuildError) {
|
|
3080
|
-
fault = rebuildError;
|
|
3081
|
-
throw rebuildError;
|
|
3082
|
-
}
|
|
3083
|
-
throw error;
|
|
3084
|
-
}
|
|
3085
|
-
};
|
|
3086
|
-
view = {
|
|
3087
|
-
current: () => {
|
|
3088
|
-
if (fault) throw fault;
|
|
3089
|
-
return currentValue;
|
|
3090
|
-
},
|
|
3091
|
-
revision: () => revision,
|
|
3092
|
-
subscribe: (listener) => {
|
|
3093
|
-
listeners.add(listener);
|
|
3094
|
-
return () => listeners.delete(listener);
|
|
3095
|
-
},
|
|
3096
|
-
rebuild: () => {
|
|
3097
|
-
build();
|
|
3098
|
-
writeMeta(void 0, currentValue, runtime.revision(), true);
|
|
3099
|
-
emit();
|
|
3100
|
-
},
|
|
3101
|
-
dispose: () => {
|
|
3102
|
-
if (disposed) return;
|
|
3103
|
-
disposed = true;
|
|
3104
|
-
unregister();
|
|
3105
|
-
listeners.clear();
|
|
3106
|
-
materializedMeta.delete(view);
|
|
3107
|
-
}
|
|
3108
|
-
};
|
|
3109
|
-
materializedMeta.set(view, {
|
|
3110
|
-
runtime,
|
|
3111
|
-
value: currentValue,
|
|
3112
|
-
change: void 0,
|
|
3113
|
-
revision,
|
|
3114
|
-
changedRevision: -1
|
|
3115
|
-
});
|
|
3116
|
-
const unregister = registerProcessor(runtime, {
|
|
3117
|
-
process,
|
|
3118
|
-
flush: () => {
|
|
3119
|
-
if (!pendingEmit) return;
|
|
3120
|
-
pendingEmit = false;
|
|
3121
|
-
emit();
|
|
3122
|
-
}
|
|
3123
|
-
});
|
|
3124
|
-
return view;
|
|
3125
|
-
};
|
|
3126
|
-
//#endregion
|
|
3127
|
-
export { DocumentDisposedError, DocumentReentrancyError, asReadable, commandFootprint, contains, createCollectionView, createDocument, createMaterializedView, debugKey, decodeCommandFootprint, dict, field, footprintsOverlap, list, map, object, optional, overlaps, read as readAddress, record, resolveAddress, schema, select, single, table, impact_target_exports as target, tree, variant };
|
|
2591
|
+
export { DocumentDisposedError, DocumentReentrancyError, ProjectionDisposedError, ProjectionError, asReadable, commandFootprint, contains, createDocument, createProjectionRuntime, debugKey, decodeCommandFootprint, dict, field, footprintsOverlap, list, map, object, optional, overlaps, read as readAddress, record, resolveAddress, schema, select, single, table, impact_target_exports as target, tree, variant };
|
|
3128
2592
|
|
|
3129
2593
|
//# sourceMappingURL=index.js.map
|