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.
Files changed (46) hide show
  1. package/README.md +46 -5
  2. package/dist/{contract-4E3moCbY.d.ts → contract-I99DUMbN.d.ts} +1 -1
  3. package/dist/index.cjs +73 -608
  4. package/dist/index.cjs.map +1 -1
  5. package/dist/index.d.cts +2 -63
  6. package/dist/index.d.ts +3 -64
  7. package/dist/index.js +11 -547
  8. package/dist/index.js.map +1 -1
  9. package/dist/integration-Bs3pOk65.cjs +35 -0
  10. package/dist/integration-Bs3pOk65.cjs.map +1 -0
  11. package/dist/integration-xupBIKjU.js +30 -0
  12. package/dist/integration-xupBIKjU.js.map +1 -0
  13. package/dist/integration.cjs +4 -14
  14. package/dist/integration.d.cts +2 -1
  15. package/dist/integration.d.ts +3 -2
  16. package/dist/integration.js +3 -14
  17. package/dist/local-sync.cjs +1 -1
  18. package/dist/local-sync.d.ts +1 -1
  19. package/dist/local-sync.js +1 -1
  20. package/dist/{ownership-CU-9DKJQ.cjs → ownership-CY0nPXGF.cjs} +4 -1
  21. package/dist/ownership-CY0nPXGF.cjs.map +1 -0
  22. package/dist/{ownership-B-VAPcce.js → ownership-CduRygE7.js} +4 -1
  23. package/dist/ownership-CduRygE7.js.map +1 -0
  24. package/dist/react.cjs +1 -1
  25. package/dist/react.js +1 -1
  26. package/dist/runtime-BJRXF0gq.js +1735 -0
  27. package/dist/runtime-BJRXF0gq.js.map +1 -0
  28. package/dist/runtime-CRijXjYp.cjs +1991 -0
  29. package/dist/runtime-CRijXjYp.cjs.map +1 -0
  30. package/dist/runtime-CUcvhFNP.d.ts +152 -0
  31. package/dist/runtime-C_vKHmhy.d.cts +152 -0
  32. package/package.json +1 -1
  33. package/skills/doxum-runtime/references/guide.en.md +30 -18
  34. package/skills/doxum-runtime/references/guide.zh-CN.md +22 -14
  35. package/skills/doxum-runtime/references/invariants.en.md +12 -9
  36. package/skills/doxum-runtime/references/invariants.zh-CN.md +2 -2
  37. package/skills/doxum-runtime/references/patterns.en.md +29 -56
  38. package/skills/doxum-runtime/references/patterns.zh-CN.md +21 -45
  39. package/dist/dependency-C5_R1tvQ.js +0 -496
  40. package/dist/dependency-C5_R1tvQ.js.map +0 -1
  41. package/dist/dependency-Dfzs3khk.cjs +0 -722
  42. package/dist/dependency-Dfzs3khk.cjs.map +0 -1
  43. package/dist/integration.cjs.map +0 -1
  44. package/dist/integration.js.map +0 -1
  45. package/dist/ownership-B-VAPcce.js.map +0 -1
  46. package/dist/ownership-CU-9DKJQ.cjs.map +0 -1
package/dist/index.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_dependency = require("./dependency-Dfzs3khk.cjs");
3
- const require_ownership = require("./ownership-CU-9DKJQ.cjs");
2
+ const require_runtime = require("./runtime-CRijXjYp.cjs");
3
+ const require_ownership = require("./ownership-CY0nPXGF.cjs");
4
4
  const require_driver = require("./driver-CNxqMVFH.cjs");
5
5
  //#region core/src/impact.ts
6
6
  const emptyCollectionImpact = Object.freeze({
@@ -29,7 +29,7 @@ const createImpact = (input) => {
29
29
  if (pathBuckets.get(void 0)?.some(test)) return true;
30
30
  return pathBuckets.get(address[0])?.some(test) ?? false;
31
31
  };
32
- const pathsAffect = (address) => address.length === 0 ? paths.length > 0 : somePath(address, (changed) => require_dependency.overlaps(changed, address));
32
+ const pathsAffect = (address) => address.length === 0 ? paths.length > 0 : somePath(address, (changed) => require_runtime.overlaps(changed, address));
33
33
  let collectionCache;
34
34
  const findCollection = (address) => input.collections?.find((entry) => entry.address.length === address.length && entry.address.every((segment, index) => segment === address[index]));
35
35
  return {
@@ -38,12 +38,12 @@ const createImpact = (input) => {
38
38
  affects: (value) => {
39
39
  require_ownership.profile.impact.affects();
40
40
  if (kind === "reset") return true;
41
- if (!require_dependency.belongs(value, input.schema)) return false;
42
- if (pathsAffect(require_dependency.address(value))) return true;
41
+ if (!require_runtime.belongs(value, input.schema)) return false;
42
+ if (pathsAffect(require_runtime.address(value))) return true;
43
43
  if (value.kind === "collection") {
44
- const collection = findCollection(require_dependency.address(value));
44
+ const collection = findCollection(require_runtime.address(value));
45
45
  if (!collection) return false;
46
- const id$1 = require_dependency.id(value);
46
+ const id$1 = require_runtime.id(value);
47
47
  if (id$1 !== void 0) return collection.added.has(id$1) || collection.removed.has(id$1) || collection.updated.has(id$1);
48
48
  return collection.added.size > 0 || collection.removed.size > 0 || collection.updated.size > 0 || collection.orderChanged;
49
49
  }
@@ -55,7 +55,7 @@ const createImpact = (input) => {
55
55
  const cached = collectionCache?.find((entry) => entry.address.length === selector.address.length && entry.address.every((segment, index) => segment === selector.address[index]))?.value;
56
56
  if (cached) return cached;
57
57
  const exact = findCollection(selector.address);
58
- if (somePath(selector.address, (changed) => require_dependency.contains(changed, selector.address) && changed.length < selector.address.length)) {
58
+ if (somePath(selector.address, (changed) => require_runtime.contains(changed, selector.address) && changed.length < selector.address.length)) {
59
59
  const reset = { kind: "reset" };
60
60
  (collectionCache ??= []).push({
61
61
  address: selector.address,
@@ -165,7 +165,7 @@ const createHistory = (input) => {
165
165
  };
166
166
  //#endregion
167
167
  //#region core/src/access/writer.ts
168
- const schemaRoot = (schema) => require_dependency.object(schema.shape);
168
+ const schemaRoot = (schema) => require_runtime.object(schema.shape);
169
169
  const emit = (sink, operation) => sink(operation);
170
170
  const writerFor = (node, inputAddress, sink) => {
171
171
  const address = Object.freeze(inputAddress);
@@ -1076,7 +1076,7 @@ const executeTree = (root, target, operation, copyPayload) => {
1076
1076
  issue: from(operation, "invalid-address", "Tree target is invalid.")
1077
1077
  };
1078
1078
  const result = replace(target.value, operation);
1079
- if (result.status === "changed") require_dependency.set(root, operation.at, require_ownership.ownPayload(operation.value));
1079
+ if (result.status === "changed") require_runtime.set(root, operation.at, require_ownership.ownPayload(operation.value));
1080
1080
  return outcome(operation, result);
1081
1081
  }
1082
1082
  if (!is(target.value)) return {
@@ -1326,14 +1326,14 @@ const indexedSubjects = (root, address) => {
1326
1326
  return subjects;
1327
1327
  };
1328
1328
  const writePresence = (root, address, before) => {
1329
- const target = require_dependency.locate(root, address);
1329
+ const target = require_runtime.locate(root, address);
1330
1330
  if (!target) return;
1331
1331
  if (before.status === "present") target.parent[target.key] = before.value;
1332
1332
  else if (Array.isArray(target.parent)) target.parent.splice(Number(target.key), 1);
1333
1333
  else delete target.parent[String(target.key)];
1334
1334
  };
1335
1335
  const writeContainer = (root, address, value) => {
1336
- const target = require_dependency.locate(root, address);
1336
+ const target = require_runtime.locate(root, address);
1337
1337
  if (!target) return;
1338
1338
  target.parent[target.key] = value;
1339
1339
  };
@@ -1401,7 +1401,7 @@ const restoreSubject = (value, prefix, subject) => {
1401
1401
  writeContainer(value, address, subject.before);
1402
1402
  return value;
1403
1403
  }
1404
- const current = require_dependency.read(value, address);
1404
+ const current = require_runtime.read(value, address);
1405
1405
  if (subject.kind === "dict") {
1406
1406
  if (require_ownership.isRecord(current)) restoreDict(current, subject.state);
1407
1407
  return value;
@@ -1419,13 +1419,13 @@ const restoreSubject = (value, prefix, subject) => {
1419
1419
  return value;
1420
1420
  };
1421
1421
  const valueChanged = (root, subject) => {
1422
- const target = require_dependency.locate(root, subject.address);
1422
+ const target = require_runtime.locate(root, subject.address);
1423
1423
  const exists = !!target && hasOwn(target.parent, target.key);
1424
1424
  if (subject.before.status === "absent") return exists;
1425
1425
  return !exists || !Object.is(subject.before.value, target?.value);
1426
1426
  };
1427
1427
  const dictChanged = (root, subject) => {
1428
- const value = require_dependency.read(root, subject.address);
1428
+ const value = require_runtime.read(root, subject.address);
1429
1429
  if (!require_ownership.isRecord(value)) return true;
1430
1430
  if (subject.state.mode === "whole") return !require_ownership.sameStructuralValue(subject.state.value, value);
1431
1431
  for (const [key, before] of subject.state.entries) {
@@ -1435,7 +1435,7 @@ const dictChanged = (root, subject) => {
1435
1435
  return false;
1436
1436
  };
1437
1437
  const listChanged = (root, subject) => {
1438
- const value = require_dependency.read(root, subject.address);
1438
+ const value = require_runtime.read(root, subject.address);
1439
1439
  if (!Array.isArray(value)) return true;
1440
1440
  if (subject.state.mode === "whole") return !require_ownership.sameStructuralValue(subject.state.value, value);
1441
1441
  const positions = /* @__PURE__ */ new Map();
@@ -1467,7 +1467,7 @@ const commonOrderChanged = (before, after) => {
1467
1467
  return false;
1468
1468
  };
1469
1469
  const analyzeEntity = (root, subject) => {
1470
- const resolution = entityCollection(subject, require_dependency.read(root, subject.address));
1470
+ const resolution = entityCollection(subject, require_runtime.read(root, subject.address));
1471
1471
  const added = /* @__PURE__ */ new Set();
1472
1472
  const removed = /* @__PURE__ */ new Set();
1473
1473
  const updated = /* @__PURE__ */ new Set();
@@ -1499,10 +1499,10 @@ const analyzeEntity = (root, subject) => {
1499
1499
  };
1500
1500
  const subjectChanged = (root, subject) => {
1501
1501
  if (subject.kind === "value") return valueChanged(root, subject);
1502
- if (subject.kind === "variant") return !require_ownership.sameStructuralValue(subject.before, require_dependency.read(root, subject.address));
1502
+ if (subject.kind === "variant") return !require_ownership.sameStructuralValue(subject.before, require_runtime.read(root, subject.address));
1503
1503
  if (subject.kind === "dict") return dictChanged(root, subject);
1504
1504
  if (subject.kind === "list") return listChanged(root, subject);
1505
- return changeChanged(subject.state, require_dependency.read(root, subject.address));
1505
+ return changeChanged(subject.state, require_runtime.read(root, subject.address));
1506
1506
  };
1507
1507
  const listOrderBefore = (value, node, inverse) => {
1508
1508
  const order = value.map(node.keyOf);
@@ -1722,7 +1722,7 @@ const createChangeJournal = (root) => {
1722
1722
  });
1723
1723
  return;
1724
1724
  }
1725
- const value = require_dependency.read(root, operation.at);
1725
+ const value = require_runtime.read(root, operation.at);
1726
1726
  if (!Array.isArray(value)) return inverseMismatch(operation);
1727
1727
  subject = add({
1728
1728
  ...base(resolved, operation),
@@ -1760,7 +1760,7 @@ const createChangeJournal = (root) => {
1760
1760
  };
1761
1761
  const recordEntity = (resolved, operation, inverse) => {
1762
1762
  if (resolved.node.kind !== "table" && resolved.node.kind !== "map") return inverseMismatch(operation);
1763
- const resolution = resolveEntityCollection(resolved.node, require_dependency.read(root, operation.at));
1763
+ const resolution = resolveEntityCollection(resolved.node, require_runtime.read(root, operation.at));
1764
1764
  if (resolution.status === "invalid") return inverseMismatch(operation);
1765
1765
  const collection = resolution.collection;
1766
1766
  const subject = find("entity", operation.at, resolved.addressHash) ?? add({
@@ -1796,7 +1796,7 @@ const createChangeJournal = (root) => {
1796
1796
  return inverseMismatch(operation);
1797
1797
  };
1798
1798
  const recordTree = (resolved, operation, inverse) => {
1799
- const current = require_dependency.read(root, operation.at);
1799
+ const current = require_runtime.read(root, operation.at);
1800
1800
  if (inverse.length === 1 && inverse[0].type === "value.clear" && operation.type === "tree.replace") {
1801
1801
  const subject = find("tree", operation.at, resolved.addressHash);
1802
1802
  if (subject) subject.state = {
@@ -2026,7 +2026,7 @@ const createMutationSession = (root, schema, options = {}) => {
2026
2026
  const rollback = () => {
2027
2027
  if (state === "rolled-back") return;
2028
2028
  for (let stepIndex = steps.length - 1; stepIndex >= 0; stepIndex -= 1) for (const inverse of steps[stepIndex].inverse) {
2029
- const result = execute(root, inverse, require_dependency.resolveLocated(schema, root, inverse.at), true);
2029
+ const result = execute(root, inverse, require_runtime.resolveLocated(schema, root, inverse.at), true);
2030
2030
  if (result.status === "rejected") throw new Error(`Document rollback failed: ${result.issue.message}`);
2031
2031
  }
2032
2032
  state = "rolled-back";
@@ -2042,7 +2042,7 @@ const createMutationSession = (root, schema, options = {}) => {
2042
2042
  }
2043
2043
  const normalized = normalize(decoded.operation);
2044
2044
  require_ownership.profile.batch.entry(normalized.type === "entity.create" ? normalized.entries.length : normalized.type === "entity.remove" ? normalized.ids.length : 1);
2045
- const resolved = require_dependency.resolveLocated(schema, root, normalized.at);
2045
+ const resolved = require_runtime.resolveLocated(schema, root, normalized.at);
2046
2046
  if (resolved?.collection) require_ownership.profile.batch.collectionResolved();
2047
2047
  require_ownership.profile.mutation.executed();
2048
2048
  const result = execute(root, normalized, resolved, options.copyPayload === true || requiresPayloadCopy(normalized));
@@ -2297,166 +2297,6 @@ const decodeCommandFootprint = (value) => {
2297
2297
  return Object.freeze(Array.from(targets.values()));
2298
2298
  };
2299
2299
  //#endregion
2300
- //#region core/src/runtime/notification.ts
2301
- const ROOT_BUCKET = Symbol("document-root");
2302
- const notifications = /* @__PURE__ */ new WeakMap();
2303
- const key = (value) => require_dependency.bucket(value) ?? ROOT_BUCKET;
2304
- const createNotification = (runtime) => {
2305
- const notification = {
2306
- root: /* @__PURE__ */ new Set(),
2307
- filtered: /* @__PURE__ */ new Set(),
2308
- buckets: /* @__PURE__ */ new Map(),
2309
- processors: [],
2310
- candidates: /* @__PURE__ */ new Set(),
2311
- rootSnapshot: [],
2312
- notifying: false
2313
- };
2314
- notifications.set(runtime, notification);
2315
- return notification;
2316
- };
2317
- const notificationOf = (runtime) => {
2318
- const value = notifications.get(runtime);
2319
- if (!value) throw new Error("Unknown Doxum runtime.");
2320
- return value;
2321
- };
2322
- const shareNotification = (source, target) => {
2323
- notifications.set(target, notificationOf(source));
2324
- };
2325
- const registerProcessor = (runtime, processor) => {
2326
- const notification = notificationOf(runtime);
2327
- const entry = {
2328
- processor,
2329
- active: true
2330
- };
2331
- notification.processors.push(entry);
2332
- return () => {
2333
- if (!entry.active) return;
2334
- entry.active = false;
2335
- if (!notification.notifying) {
2336
- const index = notification.processors.indexOf(entry);
2337
- if (index >= 0) notification.processors.splice(index, 1);
2338
- }
2339
- };
2340
- };
2341
- const subscribeRoot = (notification, listener) => {
2342
- const entry = {
2343
- listener,
2344
- active: true
2345
- };
2346
- notification.root.add(entry);
2347
- return () => {
2348
- entry.active = false;
2349
- if (!notification.notifying) notification.root.delete(entry);
2350
- };
2351
- };
2352
- const subscribeTargets = (notification, targets, listener) => {
2353
- const entry = {
2354
- targets: Object.freeze(targets.slice()),
2355
- listener,
2356
- active: true
2357
- };
2358
- notification.filtered.add(entry);
2359
- const keys = new Set(targets.map(key));
2360
- keys.forEach((key) => {
2361
- const bucket = notification.buckets.get(key) ?? /* @__PURE__ */ new Set();
2362
- bucket.add(entry);
2363
- notification.buckets.set(key, bucket);
2364
- });
2365
- return () => {
2366
- if (!entry.active) return;
2367
- entry.active = false;
2368
- if (notification.notifying) return;
2369
- notification.filtered.delete(entry);
2370
- keys.forEach((key) => {
2371
- const bucket = notification.buckets.get(key);
2372
- bucket?.delete(entry);
2373
- if (bucket?.size === 0) notification.buckets.delete(key);
2374
- });
2375
- };
2376
- };
2377
- const notify = (notification, commit) => {
2378
- notification.notifying = true;
2379
- const errors = [];
2380
- const call = (listener) => {
2381
- try {
2382
- listener(commit);
2383
- } catch (error) {
2384
- errors.push(Object.freeze({
2385
- phase: "listener",
2386
- error
2387
- }));
2388
- }
2389
- };
2390
- try {
2391
- const processorCount = notification.processors.length;
2392
- for (let index = 0; index < processorCount; index += 1) {
2393
- const entry = notification.processors[index];
2394
- if (!entry?.active) continue;
2395
- try {
2396
- entry.processor.process(commit);
2397
- } catch (error) {
2398
- errors.push(Object.freeze({
2399
- phase: "processor",
2400
- error
2401
- }));
2402
- }
2403
- }
2404
- for (let index = 0; index < processorCount; index += 1) {
2405
- const entry = notification.processors[index];
2406
- if (!entry?.active) continue;
2407
- try {
2408
- entry.processor.flush();
2409
- } catch (error) {
2410
- errors.push(Object.freeze({
2411
- phase: "flush",
2412
- error
2413
- }));
2414
- }
2415
- }
2416
- const candidates = notification.candidates;
2417
- candidates.clear();
2418
- if (commit.impact.kind === "reset") notification.filtered.forEach((entry) => candidates.add(entry));
2419
- else for (const operation of commit.operations) {
2420
- const key = operation.at[0] ?? ROOT_BUCKET;
2421
- notification.buckets.get(key)?.forEach((entry) => candidates.add(entry));
2422
- notification.buckets.get(ROOT_BUCKET)?.forEach((entry) => candidates.add(entry));
2423
- }
2424
- candidates.forEach((entry) => {
2425
- if (entry.active && entry.targets.some(commit.impact.affects)) call(entry.listener);
2426
- });
2427
- const rootSnapshot = notification.rootSnapshot;
2428
- rootSnapshot.length = 0;
2429
- notification.root.forEach((entry) => rootSnapshot.push(entry));
2430
- for (const entry of rootSnapshot) if (entry.active) call(entry.listener);
2431
- } finally {
2432
- notification.notifying = false;
2433
- let writeIndex = 0;
2434
- for (const entry of notification.processors) if (entry.active) notification.processors[writeIndex++] = entry;
2435
- notification.processors.length = writeIndex;
2436
- notification.root.forEach((entry) => {
2437
- if (!entry.active) notification.root.delete(entry);
2438
- });
2439
- notification.filtered.forEach((entry) => {
2440
- if (!entry.active) notification.filtered.delete(entry);
2441
- });
2442
- notification.buckets.forEach((bucket, key) => {
2443
- bucket.forEach((entry) => {
2444
- if (!entry.active) bucket.delete(entry);
2445
- });
2446
- if (bucket.size === 0) notification.buckets.delete(key);
2447
- });
2448
- }
2449
- return Object.freeze(errors);
2450
- };
2451
- const disposeNotification = (notification) => {
2452
- notification.root.clear();
2453
- notification.filtered.clear();
2454
- notification.buckets.clear();
2455
- notification.processors.length = 0;
2456
- notification.candidates.clear();
2457
- notification.rootSnapshot.length = 0;
2458
- };
2459
- //#endregion
2460
2300
  //#region core/src/runtime.ts
2461
2301
  var RejectedUpdate = class extends Error {
2462
2302
  issues;
@@ -2484,15 +2324,16 @@ const createDocument = (input) => {
2484
2324
  let runtime;
2485
2325
  let notification;
2486
2326
  const assertWritable = (intent) => {
2487
- if (state.disposed) throw new require_dependency.DocumentDisposedError();
2488
- if (busy) throw new require_dependency.DocumentReentrancyError();
2327
+ if (state.disposed) throw new require_runtime.DocumentDisposedError();
2328
+ if (busy) throw new require_runtime.DocumentReentrancyError();
2329
+ if (require_runtime.accessOf(runtime).projectionLocks) throw new require_runtime.DocumentReentrancyError();
2489
2330
  require_driver.assertRuntimeWritable(runtime, intent);
2490
2331
  };
2491
2332
  const runTransaction = (session, run) => {
2492
2333
  let reports;
2493
2334
  let active = true;
2494
2335
  const transaction = {
2495
- read: require_dependency.documentReader(input.schema, () => state.document, () => active),
2336
+ read: require_runtime.documentReader(input.schema, () => state.document, () => active),
2496
2337
  write: documentWriter(input.schema, (operation) => {
2497
2338
  if (!active) throw new Error("Document writer is no longer active.");
2498
2339
  const rejected = session.apply(operation);
@@ -2544,7 +2385,7 @@ const createDocument = (input) => {
2544
2385
  busy = true;
2545
2386
  let observerErrors;
2546
2387
  try {
2547
- observerErrors = notify(notification, commit);
2388
+ observerErrors = require_runtime.notify(notification, commit);
2548
2389
  } finally {
2549
2390
  busy = false;
2550
2391
  }
@@ -2574,11 +2415,11 @@ const createDocument = (input) => {
2574
2415
  runtime = {
2575
2416
  schema: input.schema,
2576
2417
  address: {
2577
- resolve: (address) => require_dependency.resolveAddress(input.schema, address, state.document),
2578
- read: (address) => require_dependency.read(state.document, address),
2579
- contains: require_dependency.contains,
2580
- overlaps: require_dependency.overlaps,
2581
- debugKey: require_dependency.debugKey
2418
+ resolve: (address) => require_runtime.resolveAddress(input.schema, address, state.document),
2419
+ read: (address) => require_runtime.read(state.document, address),
2420
+ contains: require_runtime.contains,
2421
+ overlaps: require_runtime.overlaps,
2422
+ debugKey: require_runtime.debugKey
2582
2423
  },
2583
2424
  revision: () => revision,
2584
2425
  update: (run, options) => {
@@ -2704,28 +2545,32 @@ const createDocument = (input) => {
2704
2545
  }, source, "replace", false);
2705
2546
  },
2706
2547
  snapshot: () => {
2707
- if (state.disposed) throw new require_dependency.DocumentDisposedError();
2548
+ if (state.disposed) throw new require_runtime.DocumentDisposedError();
2708
2549
  return require_ownership.cloneValue(state.document, "snapshot");
2709
2550
  },
2710
2551
  subscribe: ((targetOrListener, listener) => {
2711
- if (state.disposed) throw new require_dependency.DocumentDisposedError();
2712
- if (typeof targetOrListener === "function") return subscribeRoot(notification, targetOrListener);
2552
+ if (state.disposed) throw new require_runtime.DocumentDisposedError();
2553
+ if (typeof targetOrListener === "function") return require_runtime.subscribeRoot(notification, targetOrListener);
2713
2554
  const targets = Array.isArray(targetOrListener) ? targetOrListener : [targetOrListener];
2714
2555
  if (targets.length === 0 || !listener) throw new TypeError("Filtered subscribe requires at least one target and a listener.");
2715
- return subscribeTargets(notification, targets, listener);
2556
+ return require_runtime.subscribeTargets(notification, targets, listener);
2716
2557
  }),
2717
2558
  history: history.api,
2718
2559
  dispose: () => {
2719
2560
  if (state.disposed) return;
2561
+ if (busy || require_runtime.accessOf(runtime).projectionLocks) throw new require_runtime.DocumentReentrancyError();
2720
2562
  state.disposed = true;
2721
- disposeNotification(notification);
2722
- history.api.clear();
2723
- require_driver.disposeRuntimeDriver(runtime);
2563
+ try {
2564
+ require_runtime.disposeNotification(notification);
2565
+ } finally {
2566
+ history.api.clear();
2567
+ require_driver.disposeRuntimeDriver(runtime);
2568
+ }
2724
2569
  }
2725
2570
  };
2726
- require_dependency.bindRuntimeAccess(runtime, state);
2571
+ require_runtime.bindRuntimeAccess(runtime, state);
2727
2572
  require_driver.bindRuntimeDriver(runtime);
2728
- notification = createNotification(runtime);
2573
+ notification = require_runtime.createNotification(runtime);
2729
2574
  return runtime;
2730
2575
  };
2731
2576
  //#endregion
@@ -2736,427 +2581,47 @@ const asReadable = (runtime) => {
2736
2581
  revision: runtime.revision,
2737
2582
  subscribe: runtime.subscribe
2738
2583
  };
2739
- require_dependency.bindRuntimeAccess(readable, require_dependency.accessOf(runtime));
2740
- shareNotification(runtime, readable);
2584
+ require_runtime.bindRuntimeAccess(readable, require_runtime.accessOf(runtime));
2585
+ require_runtime.shareNotification(runtime, readable);
2741
2586
  return Object.freeze(readable);
2742
2587
  };
2743
2588
  //#endregion
2744
2589
  //#region core/src/projection/select.ts
2745
- const select = (runtime, selector) => require_dependency.readWith(runtime, selector);
2746
- //#endregion
2747
- //#region core/src/projection/collection-view.ts
2748
- const createCollectionView = (input) => {
2749
- if (require_dependency.schemaOf(input.runtime) !== input.source.schema) throw new Error("Collection selector belongs to another schema.");
2750
- const idsListeners = /* @__PURE__ */ new Set();
2751
- const allListeners = /* @__PURE__ */ new Set();
2752
- const itemListeners = /* @__PURE__ */ new Map();
2753
- const itemReadables = /* @__PURE__ */ new Map();
2754
- let disposed = false;
2755
- const sourceNode = require_dependency.nodeAt(input.source.schema, input.source.address);
2756
- const entryNode = sourceNode?.kind === "table" || sourceNode?.kind === "map" ? sourceNode.value : {
2757
- kind: "object",
2758
- shape: {}
2759
- };
2760
- const mapEntry = (document, id) => {
2761
- require_ownership.profile.collectionView.mapped();
2762
- const address = [...input.source.address, String(id)];
2763
- let active = true;
2764
- try {
2765
- return input.map(id, require_dependency.readerFor(entryNode, {
2766
- root: () => document,
2767
- active: () => active
2768
- }, address));
2769
- } finally {
2770
- active = false;
2771
- }
2772
- };
2773
- const build = (previous, changed) => {
2774
- const document = require_dependency.documentOf(input.runtime);
2775
- const collection = require_dependency.read(document, input.source.address);
2776
- const ids = collection && typeof collection === "object" && "ids" in collection && Array.isArray(collection.ids) ? [...collection.ids] : Object.keys(collection ?? {});
2777
- require_ownership.profile.collectionView.idsScanned(ids.length);
2778
- const values = previous && changed ? previous.values : /* @__PURE__ */ new Map();
2779
- if (previous && changed) {
2780
- const nextIds = new Set(ids);
2781
- for (const id of previous.ids) if (!nextIds.has(id)) values.delete(id);
2782
- }
2783
- for (const id of ids) {
2784
- if (previous && changed && previous.values.has(id) && !changed.has(id)) continue;
2785
- const next = mapEntry(document, id);
2786
- if (previous && changed && previous.values.has(id)) {
2787
- const before = previous.values.get(id);
2788
- if (input.isEqual ? input.isEqual(before, next) : Object.is(before, next)) {
2789
- changed.delete(id);
2790
- continue;
2791
- }
2792
- }
2793
- values.set(id, next);
2794
- }
2795
- return {
2796
- ids: Object.freeze(ids),
2797
- values,
2798
- all: void 0,
2799
- allDirty: true
2800
- };
2801
- };
2802
- let state = build();
2803
- const ensureAll = () => {
2804
- if (!state.allDirty && state.all) return state.all;
2805
- require_ownership.profile.collectionView.arrayCopied();
2806
- const all = new Array(state.ids.length);
2807
- for (let index = 0; index < state.ids.length; index += 1) all[index] = state.values.get(state.ids[index]);
2808
- const stable = Object.freeze(all);
2809
- state.all = stable;
2810
- state.allDirty = false;
2811
- return stable;
2812
- };
2813
- const emit = (listeners) => {
2814
- Array.from(listeners).forEach((listener) => listener());
2815
- };
2816
- const unsubscribe = input.runtime.subscribe(input.source, (commit) => {
2817
- if (disposed) return;
2818
- const impact = commit.impact.collection(input.source);
2819
- if (impact.kind === "incremental" && impact.added.size === 0 && impact.removed.size === 0 && !impact.orderChanged) {
2820
- const previous = state;
2821
- const changes = [];
2822
- const document = require_dependency.documentOf(input.runtime);
2823
- impact.updated.forEach((id) => {
2824
- if (!previous.values.has(id)) return;
2825
- const before = previous.values.get(id);
2826
- const after = mapEntry(document, id);
2827
- if (input.isEqual ? input.isEqual(before, after) : Object.is(before, after)) return;
2828
- changes.push([id, after]);
2829
- });
2830
- if (changes.length === 0) return;
2831
- for (const [id, value] of changes) previous.values.set(id, value);
2832
- previous.all = void 0;
2833
- previous.allDirty = true;
2834
- emit(allListeners);
2835
- for (const [id] of changes) {
2836
- const listeners = itemListeners.get(id);
2837
- if (listeners) emit(listeners);
2838
- }
2839
- return;
2840
- }
2841
- const changed = impact.kind === "reset" ? void 0 : new Set([...impact.added, ...impact.updated]);
2842
- const previous = state;
2843
- const next = build(previous, changed);
2844
- const changedIds = /* @__PURE__ */ new Set();
2845
- if (changed) {
2846
- changed.forEach((id) => changedIds.add(id));
2847
- previous.ids.forEach((id) => {
2848
- if (!next.values.has(id)) changedIds.add(id);
2849
- });
2850
- next.ids.forEach((id) => {
2851
- if (!previous.values.has(id)) changedIds.add(id);
2852
- });
2853
- } else {
2854
- previous.ids.forEach((id) => {
2855
- if (!next.values.has(id)) changedIds.add(id);
2856
- 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);
2857
- });
2858
- next.ids.forEach((id) => {
2859
- if (!previous.values.has(id)) changedIds.add(id);
2860
- });
2861
- }
2862
- 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);
2863
- state = idsChanged || changedIds.size ? next : previous;
2864
- if (idsChanged) emit(idsListeners);
2865
- if (idsChanged || changedIds.size) emit(allListeners);
2866
- changedIds.forEach((id) => {
2867
- const listeners = itemListeners.get(id);
2868
- if (listeners) emit(listeners);
2869
- });
2870
- });
2871
- return {
2872
- ids: {
2873
- current: () => state.ids,
2874
- revision: () => input.runtime.revision(),
2875
- subscribe: (listener) => {
2876
- if (disposed) return () => void 0;
2877
- idsListeners.add(listener);
2878
- return () => idsListeners.delete(listener);
2879
- }
2880
- },
2881
- all: {
2882
- current: ensureAll,
2883
- revision: () => input.runtime.revision(),
2884
- subscribe: (listener) => {
2885
- if (disposed) return () => void 0;
2886
- allListeners.add(listener);
2887
- return () => allListeners.delete(listener);
2888
- }
2889
- },
2890
- item: (id) => {
2891
- const cached = itemReadables.get(id);
2892
- if (cached) return cached;
2893
- const readable = {
2894
- current: () => state.values.get(id),
2895
- revision: () => input.runtime.revision(),
2896
- subscribe: (listener) => {
2897
- if (disposed) return () => void 0;
2898
- const listeners = itemListeners.get(id) ?? /* @__PURE__ */ new Set();
2899
- itemListeners.set(id, listeners);
2900
- listeners.add(listener);
2901
- return () => {
2902
- listeners.delete(listener);
2903
- if (listeners.size === 0) itemListeners.delete(id);
2904
- };
2905
- }
2906
- };
2907
- itemReadables.set(id, readable);
2908
- return readable;
2909
- },
2910
- revision: () => input.runtime.revision(),
2911
- dispose: () => {
2912
- if (disposed) return;
2913
- disposed = true;
2914
- unsubscribe();
2915
- idsListeners.clear();
2916
- allListeners.clear();
2917
- itemListeners.clear();
2918
- itemReadables.clear();
2919
- state.values.clear();
2920
- state = {
2921
- ids: Object.freeze([]),
2922
- values: /* @__PURE__ */ new Map(),
2923
- all: Object.freeze([]),
2924
- allDirty: false
2925
- };
2926
- }
2927
- };
2928
- };
2929
- //#endregion
2930
- //#region core/src/projection/materialized-view.ts
2931
- const materializedMeta = /* @__PURE__ */ new WeakMap();
2932
- const createMaterializedView = (runtime, spec) => {
2933
- const listeners = /* @__PURE__ */ new Set();
2934
- let disposed = false;
2935
- let fault;
2936
- let revision = runtime.revision();
2937
- let instance;
2938
- let currentValue;
2939
- let pendingEmit = false;
2940
- const dependencies = require_dependency.createDependencyTracker();
2941
- const sources = spec.sources ?? {};
2942
- const sourceEntries = Object.keys(sources).map((key) => [key, sources[key]]);
2943
- sourceEntries.forEach(([, source]) => {
2944
- const meta = materializedMeta.get(source);
2945
- if (!meta || meta.runtime !== runtime) throw new Error("Materialized sources must belong to the same runtime and be created first.");
2946
- });
2947
- const sourceValuesRecord = {};
2948
- let sourceChanged = false;
2949
- for (const [key] of sourceEntries) sourceValuesRecord[key] = {
2950
- value: void 0,
2951
- change: void 0
2952
- };
2953
- const sourceValues = (commitRevision) => {
2954
- sourceChanged = false;
2955
- for (const [key, source] of sourceEntries) {
2956
- const meta = materializedMeta.get(source);
2957
- const entry = sourceValuesRecord[key];
2958
- entry.value = meta?.value ?? source.current();
2959
- entry.change = meta?.change;
2960
- if (commitRevision !== void 0 && meta?.changedRevision === commitRevision) {
2961
- sourceChanged = true;
2962
- require_ownership.profile.materialized.sourceChanged();
2963
- }
2964
- }
2965
- return sourceValuesRecord;
2966
- };
2967
- let activeImpact;
2968
- const assertImpact = () => {
2969
- if (!activeImpact) throw new Error("Materialized impact is no longer active.");
2970
- return activeImpact;
2971
- };
2972
- const trackedImpact = {
2973
- get kind() {
2974
- return assertImpact().kind;
2975
- },
2976
- affects: (target) => {
2977
- dependencies.record(target);
2978
- return assertImpact().affects(target);
2979
- },
2980
- collection: (selector) => {
2981
- dependencies.record(selector);
2982
- return assertImpact().collection(selector);
2983
- },
2984
- get operations() {
2985
- dependencies.record({
2986
- kind: "value",
2987
- at: []
2988
- });
2989
- return assertImpact().operations;
2990
- }
2991
- };
2992
- let view;
2993
- const writeMeta = (change, value, nextRevision, changed) => {
2994
- const meta = materializedMeta.get(view);
2995
- if (meta) {
2996
- meta.value = value;
2997
- meta.change = change;
2998
- meta.revision = nextRevision;
2999
- if (changed) meta.changedRevision = nextRevision;
3000
- } else materializedMeta.set(view, {
3001
- runtime,
3002
- value,
3003
- change,
3004
- revision: nextRevision,
3005
- changedRevision: changed ? nextRevision : -1
3006
- });
3007
- };
3008
- const build = () => {
3009
- require_ownership.profile.materialized.rebuilt();
3010
- dependencies.clear();
3011
- let active = true;
3012
- try {
3013
- instance = spec.build({
3014
- read: require_dependency.documentReader(require_dependency.schemaOf(runtime), () => require_dependency.documentOf(runtime), () => active),
3015
- sources: sourceValues()
3016
- });
3017
- currentValue = instance.value;
3018
- fault = void 0;
3019
- revision = runtime.revision();
3020
- } finally {
3021
- active = false;
3022
- }
3023
- };
3024
- build();
3025
- const emit = () => {
3026
- require_ownership.profile.materialized.notification();
3027
- Array.from(listeners).forEach((listener) => listener());
3028
- };
3029
- const process = (commit) => {
3030
- if (disposed) return;
3031
- try {
3032
- if (commit.kind === "replace" || fault) {
3033
- build();
3034
- writeMeta(void 0, currentValue, commit.revision, true);
3035
- pendingEmit = true;
3036
- return;
3037
- }
3038
- const sourceSnapshot = sourceValues(commit.revision);
3039
- if (!sourceChanged && dependencies.size() > 0 && !dependencies.some(commit.impact.affects)) {
3040
- require_ownership.profile.materialized.skipped();
3041
- revision = commit.revision;
3042
- writeMeta(void 0, currentValue, commit.revision, false);
3043
- return;
3044
- }
3045
- dependencies.clear();
3046
- require_ownership.profile.materialized.updated();
3047
- let active = true;
3048
- let result;
3049
- try {
3050
- activeImpact = commit.impact;
3051
- result = instance.update({
3052
- read: require_dependency.documentReader(require_dependency.schemaOf(runtime), () => require_dependency.documentOf(runtime), () => active),
3053
- revision: commit.revision,
3054
- source: commit.source,
3055
- impact: trackedImpact,
3056
- sources: sourceSnapshot
3057
- });
3058
- } finally {
3059
- activeImpact = void 0;
3060
- active = false;
3061
- }
3062
- if (result.kind === "rebuild") {
3063
- build();
3064
- writeMeta(void 0, currentValue, commit.revision, true);
3065
- pendingEmit = true;
3066
- } else if (result.kind === "changed") {
3067
- currentValue = result.value;
3068
- revision = commit.revision;
3069
- writeMeta(result.change, currentValue, commit.revision, true);
3070
- pendingEmit = true;
3071
- } else {
3072
- revision = commit.revision;
3073
- writeMeta(void 0, currentValue, commit.revision, false);
3074
- }
3075
- } catch (error) {
3076
- try {
3077
- build();
3078
- writeMeta(void 0, currentValue, commit.revision, true);
3079
- pendingEmit = true;
3080
- } catch (rebuildError) {
3081
- fault = rebuildError;
3082
- throw rebuildError;
3083
- }
3084
- throw error;
3085
- }
3086
- };
3087
- view = {
3088
- current: () => {
3089
- if (fault) throw fault;
3090
- return currentValue;
3091
- },
3092
- revision: () => revision,
3093
- subscribe: (listener) => {
3094
- listeners.add(listener);
3095
- return () => listeners.delete(listener);
3096
- },
3097
- rebuild: () => {
3098
- build();
3099
- writeMeta(void 0, currentValue, runtime.revision(), true);
3100
- emit();
3101
- },
3102
- dispose: () => {
3103
- if (disposed) return;
3104
- disposed = true;
3105
- unregister();
3106
- listeners.clear();
3107
- materializedMeta.delete(view);
3108
- }
3109
- };
3110
- materializedMeta.set(view, {
3111
- runtime,
3112
- value: currentValue,
3113
- change: void 0,
3114
- revision,
3115
- changedRevision: -1
3116
- });
3117
- const unregister = registerProcessor(runtime, {
3118
- process,
3119
- flush: () => {
3120
- if (!pendingEmit) return;
3121
- pendingEmit = false;
3122
- emit();
3123
- }
3124
- });
3125
- return view;
3126
- };
2590
+ const select = (runtime, selector) => require_runtime.readWith(runtime, selector);
3127
2591
  //#endregion
3128
- exports.DocumentDisposedError = require_dependency.DocumentDisposedError;
3129
- exports.DocumentReentrancyError = require_dependency.DocumentReentrancyError;
2592
+ exports.DocumentDisposedError = require_runtime.DocumentDisposedError;
2593
+ exports.DocumentReentrancyError = require_runtime.DocumentReentrancyError;
2594
+ exports.ProjectionDisposedError = require_runtime.ProjectionDisposedError;
2595
+ exports.ProjectionError = require_runtime.ProjectionError;
3130
2596
  exports.asReadable = asReadable;
3131
2597
  exports.commandFootprint = commandFootprint;
3132
- exports.contains = require_dependency.contains;
3133
- exports.createCollectionView = createCollectionView;
2598
+ exports.contains = require_runtime.contains;
3134
2599
  exports.createDocument = createDocument;
3135
- exports.createMaterializedView = createMaterializedView;
3136
- exports.debugKey = require_dependency.debugKey;
2600
+ exports.createProjectionRuntime = require_runtime.createProjectionRuntime;
2601
+ exports.debugKey = require_runtime.debugKey;
3137
2602
  exports.decodeCommandFootprint = decodeCommandFootprint;
3138
- exports.dict = require_dependency.dict;
3139
- exports.field = require_dependency.field;
2603
+ exports.dict = require_runtime.dict;
2604
+ exports.field = require_runtime.field;
3140
2605
  exports.footprintsOverlap = footprintsOverlap;
3141
- exports.list = require_dependency.list;
3142
- exports.map = require_dependency.map;
3143
- exports.object = require_dependency.object;
3144
- exports.optional = require_dependency.optional;
3145
- exports.overlaps = require_dependency.overlaps;
3146
- exports.readAddress = require_dependency.read;
3147
- exports.record = require_dependency.record;
3148
- exports.resolveAddress = require_dependency.resolveAddress;
3149
- exports.schema = require_dependency.schema;
2606
+ exports.list = require_runtime.list;
2607
+ exports.map = require_runtime.map;
2608
+ exports.object = require_runtime.object;
2609
+ exports.optional = require_runtime.optional;
2610
+ exports.overlaps = require_runtime.overlaps;
2611
+ exports.readAddress = require_runtime.read;
2612
+ exports.record = require_runtime.record;
2613
+ exports.resolveAddress = require_runtime.resolveAddress;
2614
+ exports.schema = require_runtime.schema;
3150
2615
  exports.select = select;
3151
- exports.single = require_dependency.single;
3152
- exports.table = require_dependency.table;
2616
+ exports.single = require_runtime.single;
2617
+ exports.table = require_runtime.table;
3153
2618
  Object.defineProperty(exports, "target", {
3154
2619
  enumerable: true,
3155
2620
  get: function() {
3156
- return require_dependency.impact_target_exports;
2621
+ return require_runtime.impact_target_exports;
3157
2622
  }
3158
2623
  });
3159
- exports.tree = require_dependency.tree;
3160
- exports.variant = require_dependency.variant;
2624
+ exports.tree = require_runtime.tree;
2625
+ exports.variant = require_runtime.variant;
3161
2626
 
3162
2627
  //# sourceMappingURL=index.cjs.map