doxum 0.1.28 → 0.1.30
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 +3 -2
- package/dist/advanced.cjs +1 -1
- package/dist/advanced.js +1 -1
- package/dist/{driver-B5vdPohL.js → driver-B7RR-VfX.js} +31 -12
- package/dist/driver-B7RR-VfX.js.map +1 -0
- package/dist/{driver-BL91gn7_.cjs → driver-CN3dGxQI.cjs} +31 -12
- package/dist/driver-CN3dGxQI.cjs.map +1 -0
- package/dist/index.cjs +206 -133
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +206 -133
- package/dist/index.js.map +1 -1
- package/dist/local-sync.cjs +1 -1
- package/dist/local-sync.js +1 -1
- package/dist/{transform-DUleAsG0.cjs → transform-B6YxfR0R.cjs} +176 -50
- package/dist/transform-B6YxfR0R.cjs.map +1 -0
- package/dist/{transform-B4T3AcJr.js → transform-BQY9I6il.js} +147 -51
- package/dist/transform-BQY9I6il.js.map +1 -0
- package/package.json +3 -2
- package/skills/doxum-runtime/SKILL.md +64 -82
- package/skills/doxum-runtime/agents/openai.yaml +2 -2
- package/skills/doxum-runtime/references/document-runtime.md +370 -0
- package/skills/doxum-runtime/references/integrations.md +215 -0
- package/skills/doxum-runtime/references/{invariants.en.md → invariants.md} +5 -2
- package/skills/doxum-runtime/references/projections.md +467 -0
- package/skills/doxum-runtime/references/public-api.md +623 -0
- package/skills/doxum-runtime/references/recipes.md +493 -0
- package/dist/driver-B5vdPohL.js.map +0 -1
- package/dist/driver-BL91gn7_.cjs.map +0 -1
- package/dist/transform-B4T3AcJr.js.map +0 -1
- package/dist/transform-DUleAsG0.cjs.map +0 -1
- package/skills/doxum-runtime/references/api.en.md +0 -283
- package/skills/doxum-runtime/references/api.zh-CN.md +0 -276
- package/skills/doxum-runtime/references/guide.en.md +0 -138
- package/skills/doxum-runtime/references/guide.zh-CN.md +0 -116
- package/skills/doxum-runtime/references/invariants.zh-CN.md +0 -53
- package/skills/doxum-runtime/references/patterns.en.md +0 -162
- package/skills/doxum-runtime/references/patterns.zh-CN.md +0 -159
- package/skills/doxum-runtime/references/projections.en.md +0 -313
- package/skills/doxum-runtime/references/projections.zh-CN.md +0 -306
package/dist/index.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_transform = require("./transform-
|
|
2
|
+
const require_transform = require("./transform-B6YxfR0R.cjs");
|
|
3
3
|
const require_record = require("./record-ChYUi8PP.cjs");
|
|
4
|
-
const require_driver = require("./driver-
|
|
4
|
+
const require_driver = require("./driver-CN3dGxQI.cjs");
|
|
5
5
|
//#region core/src/schema/model.ts
|
|
6
6
|
const schemaNodeOf = (schema) => schema;
|
|
7
7
|
const collectionEntryNode = (node) => node.kind === "map" || node.kind === "table" || node.kind === "list" ? node.value : void 0;
|
|
@@ -569,18 +569,44 @@ const moveSelection = (current, selection, position) => {
|
|
|
569
569
|
selected.add(key);
|
|
570
570
|
}
|
|
571
571
|
const moved = [];
|
|
572
|
-
|
|
573
|
-
|
|
572
|
+
let remainingLength = 0;
|
|
573
|
+
let anchorIndex = -1;
|
|
574
|
+
const anchoredKey = position && ("before" in position ? position.before : "after" in position ? position.after : void 0);
|
|
575
|
+
for (const key of current) {
|
|
576
|
+
if (selected.has(key)) {
|
|
577
|
+
moved.push(key);
|
|
578
|
+
continue;
|
|
579
|
+
}
|
|
580
|
+
if (key === anchoredKey) anchorIndex = remainingLength;
|
|
581
|
+
remainingLength++;
|
|
582
|
+
}
|
|
574
583
|
if (moved.length !== selected.size) return { kind: "missing" };
|
|
575
|
-
|
|
576
|
-
|
|
584
|
+
let insertion;
|
|
585
|
+
if (!position || "at" in position && position.at === "end") insertion = remainingLength;
|
|
586
|
+
else if ("at" in position) {
|
|
587
|
+
if (position.at !== "start") return { kind: "invalid-anchor" };
|
|
588
|
+
insertion = 0;
|
|
589
|
+
} else {
|
|
590
|
+
if (anchorIndex < 0) return { kind: "invalid-anchor" };
|
|
591
|
+
insertion = "before" in position ? anchorIndex : anchorIndex + 1;
|
|
592
|
+
}
|
|
593
|
+
const order = new Array(current.length);
|
|
594
|
+
let outputIndex = 0;
|
|
595
|
+
let remainingIndex = 0;
|
|
596
|
+
let inserted = false;
|
|
597
|
+
for (const key of current) {
|
|
598
|
+
if (selected.has(key)) continue;
|
|
599
|
+
if (!inserted && remainingIndex === insertion) {
|
|
600
|
+
for (const movedKey of moved) order[outputIndex++] = movedKey;
|
|
601
|
+
inserted = true;
|
|
602
|
+
}
|
|
603
|
+
order[outputIndex++] = key;
|
|
604
|
+
remainingIndex++;
|
|
605
|
+
}
|
|
606
|
+
if (!inserted) for (const movedKey of moved) order[outputIndex++] = movedKey;
|
|
577
607
|
return {
|
|
578
608
|
kind: "ok",
|
|
579
|
-
order
|
|
580
|
-
...remaining.slice(0, insertion),
|
|
581
|
-
...moved,
|
|
582
|
-
...remaining.slice(insertion)
|
|
583
|
-
]
|
|
609
|
+
order
|
|
584
610
|
};
|
|
585
611
|
};
|
|
586
612
|
const index = (keys, anchor) => {
|
|
@@ -1373,6 +1399,17 @@ const contains = (parent, child) => {
|
|
|
1373
1399
|
}
|
|
1374
1400
|
return true;
|
|
1375
1401
|
};
|
|
1402
|
+
/** Compare a virtual `[...base, segment]` address with an existing address without allocating it. */
|
|
1403
|
+
const compareExtended = (base, segment, other) => {
|
|
1404
|
+
require_transform.profile.address.prefixComparison();
|
|
1405
|
+
const length = base.length + 1;
|
|
1406
|
+
const common = Math.min(length, other.length);
|
|
1407
|
+
for (let index = 0; index < common; index += 1) {
|
|
1408
|
+
require_transform.profile.address.segmentCompared();
|
|
1409
|
+
if ((index < base.length ? base[index] : segment) !== other[index]) return "disjoint";
|
|
1410
|
+
}
|
|
1411
|
+
return length === other.length ? "equal" : length < other.length ? "ancestor" : "descendant";
|
|
1412
|
+
};
|
|
1376
1413
|
//#endregion
|
|
1377
1414
|
//#region core/src/impact.ts
|
|
1378
1415
|
const createImpact = (schema, changes) => {
|
|
@@ -1799,7 +1836,7 @@ const reconstructBefore = (node, current, records, offset) => {
|
|
|
1799
1836
|
};
|
|
1800
1837
|
const sealMembers = (fact, changes) => {
|
|
1801
1838
|
const members = [];
|
|
1802
|
-
for (const member of fact.members
|
|
1839
|
+
if (fact.members) for (const member of fact.members.values()) {
|
|
1803
1840
|
if (!member) continue;
|
|
1804
1841
|
const key = memberKey(fact, member.key);
|
|
1805
1842
|
const present = Object.hasOwn(fact.parent, key);
|
|
@@ -1883,7 +1920,7 @@ var ChangeRecorder = class {
|
|
|
1883
1920
|
absorb(at, node, value, present) {
|
|
1884
1921
|
const index = this.indexGroups();
|
|
1885
1922
|
const children = [];
|
|
1886
|
-
index.
|
|
1923
|
+
index.forEachOverlap(at, (fact) => {
|
|
1887
1924
|
if (fact.kind === "members") {
|
|
1888
1925
|
if (fact.at.length < at.length) {
|
|
1889
1926
|
if (fact.at.length + 1 === at.length) {
|
|
@@ -1902,18 +1939,19 @@ var ChangeRecorder = class {
|
|
|
1902
1939
|
at: fact.at,
|
|
1903
1940
|
group: fact
|
|
1904
1941
|
});
|
|
1905
|
-
for (const member of fact.members
|
|
1942
|
+
if (fact.members) for (const member of fact.members.values()) {
|
|
1906
1943
|
if (!member) continue;
|
|
1907
|
-
const
|
|
1908
|
-
if (
|
|
1944
|
+
const compared = compareExtended(fact.at, member.key, at);
|
|
1945
|
+
if (compared !== "equal" && compared !== "descendant") continue;
|
|
1946
|
+
children.push({
|
|
1909
1947
|
kind: "member",
|
|
1910
|
-
at:
|
|
1948
|
+
at: fact.at.concat(member.key),
|
|
1911
1949
|
group: fact,
|
|
1912
1950
|
member
|
|
1913
1951
|
});
|
|
1914
1952
|
}
|
|
1915
1953
|
} else if (contains(at, fact.at)) children.push(fact);
|
|
1916
|
-
})
|
|
1954
|
+
});
|
|
1917
1955
|
if (present) value = reconstructBefore(node, value, children, at.length);
|
|
1918
1956
|
this.releaseCovered(children);
|
|
1919
1957
|
return value;
|
|
@@ -1931,7 +1969,9 @@ var ChangeRecorder = class {
|
|
|
1931
1969
|
(changedGroups ??= /* @__PURE__ */ new Set()).add(child.group);
|
|
1932
1970
|
} else this.unregister(child);
|
|
1933
1971
|
}
|
|
1934
|
-
|
|
1972
|
+
if (changedGroups) {
|
|
1973
|
+
for (const group of changedGroups) if (emptyGroup(group)) this.unregister(group);
|
|
1974
|
+
}
|
|
1935
1975
|
}
|
|
1936
1976
|
register(fact) {
|
|
1937
1977
|
this.facts.add(fact);
|
|
@@ -2880,12 +2920,7 @@ const createKeyedGet = (source, key, equality = Object.is) => {
|
|
|
2880
2920
|
} else if (sourceRevision !== collection.revision) {
|
|
2881
2921
|
const change = collection.change;
|
|
2882
2922
|
if (!change || change.kind === "reset") affected = true;
|
|
2883
|
-
else if (selected !== void 0)
|
|
2884
|
-
for (const changedKey of require_transform.collectionChange.keys(change)) if (changedKey === selected) {
|
|
2885
|
-
affected = true;
|
|
2886
|
-
break;
|
|
2887
|
-
}
|
|
2888
|
-
}
|
|
2923
|
+
else if (selected !== void 0) affected = require_transform.collectionChangeTouchesKey(change, selected);
|
|
2889
2924
|
}
|
|
2890
2925
|
if (affected) output.output.set(selected === void 0 ? void 0 : collection.read.get(selected));
|
|
2891
2926
|
sourceRevision = collection.revision;
|
|
@@ -3049,9 +3084,7 @@ function createKeyedGroupBy(source, dependenciesOrSelector, maybeSelector) {
|
|
|
3049
3084
|
outputs: [{
|
|
3050
3085
|
kind: "collection",
|
|
3051
3086
|
equality: (previous, next) => {
|
|
3052
|
-
|
|
3053
|
-
const right = next;
|
|
3054
|
-
return left.length === right.length && left.every((key, index) => key === right[index]);
|
|
3087
|
+
return require_transform.sameArray(previous, next);
|
|
3055
3088
|
}
|
|
3056
3089
|
}],
|
|
3057
3090
|
create: () => {
|
|
@@ -3095,11 +3128,14 @@ function createKeyedGroupBy(source, dependenciesOrSelector, maybeSelector) {
|
|
|
3095
3128
|
output.output.set(group, Object.freeze(members));
|
|
3096
3129
|
};
|
|
3097
3130
|
const publishGroupOrder = (output) => {
|
|
3098
|
-
const order = [...groupRanks.
|
|
3131
|
+
const order = [...groupRanks.keys()];
|
|
3132
|
+
order.sort((leftKey, rightKey) => {
|
|
3133
|
+
const left = groupRanks.get(leftKey);
|
|
3134
|
+
const right = groupRanks.get(rightKey);
|
|
3099
3135
|
if (left.source !== right.source) return left.source - right.source;
|
|
3100
3136
|
if (left.selector !== right.selector) return left.selector - right.selector;
|
|
3101
3137
|
return leftKey < rightKey ? -1 : leftKey > rightKey ? 1 : 0;
|
|
3102
|
-
})
|
|
3138
|
+
});
|
|
3103
3139
|
output.output.order(order);
|
|
3104
3140
|
};
|
|
3105
3141
|
const rebuild = (driver, sources, output) => {
|
|
@@ -3151,7 +3187,8 @@ function createKeyedGroupBy(source, dependenciesOrSelector, maybeSelector) {
|
|
|
3151
3187
|
return;
|
|
3152
3188
|
} else {
|
|
3153
3189
|
for (const entry of change.removed) {
|
|
3154
|
-
|
|
3190
|
+
const changed = removeSourceKey(entry.key, affected);
|
|
3191
|
+
orderDirty ||= changed;
|
|
3155
3192
|
dependencies.remove(entry.key);
|
|
3156
3193
|
dirty.delete(entry.key);
|
|
3157
3194
|
}
|
|
@@ -3164,7 +3201,10 @@ function createKeyedGroupBy(source, dependenciesOrSelector, maybeSelector) {
|
|
|
3164
3201
|
}
|
|
3165
3202
|
all ||= dependencies.collectInvalidated(evaluation.sources, dirty);
|
|
3166
3203
|
if (all) for (const key of driver.read.ids()) dirty.add(key);
|
|
3167
|
-
for (const key of dirty)
|
|
3204
|
+
for (const key of dirty) {
|
|
3205
|
+
const changed = selectGroups(driver, evaluation.sources, key, affected);
|
|
3206
|
+
orderDirty ||= changed;
|
|
3207
|
+
}
|
|
3168
3208
|
if (structural) markAllGroups(output, affected);
|
|
3169
3209
|
publishAffected(affected, output, orderDirty);
|
|
3170
3210
|
dependencies.remember(evaluation.sources);
|
|
@@ -3368,13 +3408,14 @@ const createPublishedCollection = () => {
|
|
|
3368
3408
|
},
|
|
3369
3409
|
publish: (staged, nextIds, reset) => {
|
|
3370
3410
|
if (reset) {
|
|
3371
|
-
const entries = [];
|
|
3372
|
-
for (const [key, entry] of staged) if (entry.present) entries.push([key, entry.value]);
|
|
3373
|
-
index = PersistentKeyedIndex.from(entries);
|
|
3374
3411
|
values.clear();
|
|
3375
|
-
|
|
3376
|
-
|
|
3377
|
-
else
|
|
3412
|
+
for (const [key, entry] of staged) if (entry.present) values.set(key, entry.value);
|
|
3413
|
+
index = PersistentKeyedIndex.from(values);
|
|
3414
|
+
} else for (const [key, entry] of staged) {
|
|
3415
|
+
index = entry.present ? index.set(key, entry.value) : index.remove(key);
|
|
3416
|
+
if (entry.present) values.set(key, entry.value);
|
|
3417
|
+
else values.delete(key);
|
|
3418
|
+
}
|
|
3378
3419
|
ids = nextIds;
|
|
3379
3420
|
},
|
|
3380
3421
|
release: () => {
|
|
@@ -3387,7 +3428,7 @@ const createPublishedCollection = () => {
|
|
|
3387
3428
|
/** Owns staged keyed intent, exact transitions and published collection state. */
|
|
3388
3429
|
const createCollectionOutput = (binding) => {
|
|
3389
3430
|
const published = createPublishedCollection();
|
|
3390
|
-
|
|
3431
|
+
const staged = /* @__PURE__ */ new Map();
|
|
3391
3432
|
let nextIds = published.ids();
|
|
3392
3433
|
let change;
|
|
3393
3434
|
let initialized = false;
|
|
@@ -3403,12 +3444,15 @@ const createCollectionOutput = (binding) => {
|
|
|
3403
3444
|
return entry ? entry.present ? entry.value : void 0 : cleared ? void 0 : published.get(key);
|
|
3404
3445
|
};
|
|
3405
3446
|
const deriveIds = () => {
|
|
3406
|
-
const result =
|
|
3447
|
+
const result = [];
|
|
3448
|
+
if (!cleared) {
|
|
3449
|
+
for (const key of published.ids()) if (hasNext(key)) result.push(key);
|
|
3450
|
+
}
|
|
3407
3451
|
for (const [key, entry] of staged) if (entry.present && (cleared || !published.has(key))) result.push(key);
|
|
3408
3452
|
return result;
|
|
3409
3453
|
};
|
|
3410
3454
|
const begin = (active, initialize) => {
|
|
3411
|
-
staged
|
|
3455
|
+
staged.clear();
|
|
3412
3456
|
nextIds = published.ids();
|
|
3413
3457
|
change = void 0;
|
|
3414
3458
|
explicitOrder = void 0;
|
|
@@ -3425,7 +3469,9 @@ const createCollectionOutput = (binding) => {
|
|
|
3425
3469
|
},
|
|
3426
3470
|
ids: () => {
|
|
3427
3471
|
require_transform.assertScope(active);
|
|
3428
|
-
|
|
3472
|
+
if (!next) return published.ids();
|
|
3473
|
+
if (explicitOrder) return explicitOrder;
|
|
3474
|
+
return Object.freeze(deriveIds());
|
|
3429
3475
|
}
|
|
3430
3476
|
});
|
|
3431
3477
|
return {
|
|
@@ -3446,7 +3492,7 @@ const createCollectionOutput = (binding) => {
|
|
|
3446
3492
|
},
|
|
3447
3493
|
order: (order) => {
|
|
3448
3494
|
require_transform.assertScope(active);
|
|
3449
|
-
explicitOrder =
|
|
3495
|
+
explicitOrder = require_transform.snapshotArray(order);
|
|
3450
3496
|
}
|
|
3451
3497
|
}
|
|
3452
3498
|
};
|
|
@@ -3456,8 +3502,6 @@ const createCollectionOutput = (binding) => {
|
|
|
3456
3502
|
for (const key of published.keys()) if (!staged.has(key)) staged.set(key, { present: false });
|
|
3457
3503
|
}
|
|
3458
3504
|
require_transform.profile.projection("touchedKeys", staged.size);
|
|
3459
|
-
const added = /* @__PURE__ */ new Set();
|
|
3460
|
-
const removed = /* @__PURE__ */ new Set();
|
|
3461
3505
|
const addedEntries = [];
|
|
3462
3506
|
const updatedEntries = [];
|
|
3463
3507
|
const removedEntries = [];
|
|
@@ -3465,7 +3509,6 @@ const createCollectionOutput = (binding) => {
|
|
|
3465
3509
|
const existed = published.has(key);
|
|
3466
3510
|
if (entry.present) {
|
|
3467
3511
|
if (!existed) {
|
|
3468
|
-
added.add(key);
|
|
3469
3512
|
addedEntries.push({
|
|
3470
3513
|
key,
|
|
3471
3514
|
after: entry.value
|
|
@@ -3481,19 +3524,28 @@ const createCollectionOutput = (binding) => {
|
|
|
3481
3524
|
else if (!nextReset) staged.delete(key);
|
|
3482
3525
|
continue;
|
|
3483
3526
|
}
|
|
3484
|
-
if (existed) {
|
|
3485
|
-
|
|
3486
|
-
|
|
3487
|
-
|
|
3488
|
-
|
|
3489
|
-
});
|
|
3490
|
-
} else staged.delete(key);
|
|
3527
|
+
if (existed) removedEntries.push({
|
|
3528
|
+
key,
|
|
3529
|
+
before: published.get(key)
|
|
3530
|
+
});
|
|
3531
|
+
else staged.delete(key);
|
|
3491
3532
|
}
|
|
3492
3533
|
const ids = published.ids();
|
|
3493
|
-
if (explicitOrder
|
|
3494
|
-
const
|
|
3495
|
-
|
|
3496
|
-
|
|
3534
|
+
if (explicitOrder) {
|
|
3535
|
+
const expectedLength = published.size() + addedEntries.length - removedEntries.length;
|
|
3536
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3537
|
+
for (const key of explicitOrder) {
|
|
3538
|
+
if (seen.has(key) || !hasNext(key)) throw new TypeError("Projection order must contain every key exactly once.");
|
|
3539
|
+
seen.add(key);
|
|
3540
|
+
}
|
|
3541
|
+
if (seen.size !== expectedLength) throw new TypeError("Projection order must contain every key exactly once.");
|
|
3542
|
+
nextIds = require_transform.sameArray(ids, explicitOrder) ? ids : explicitOrder;
|
|
3543
|
+
} else if (addedEntries.length || removedEntries.length) {
|
|
3544
|
+
const order = new Array(published.size() + addedEntries.length - removedEntries.length);
|
|
3545
|
+
let index = 0;
|
|
3546
|
+
for (const key of ids) if (hasNext(key)) order[index++] = key;
|
|
3547
|
+
for (const entry of addedEntries) order[index++] = entry.key;
|
|
3548
|
+
nextIds = require_transform.sameArray(ids, order) ? ids : Object.freeze(order);
|
|
3497
3549
|
} else nextIds = ids;
|
|
3498
3550
|
require_transform.profile.projection("changedKeys", addedEntries.length + updatedEntries.length + removedEntries.length);
|
|
3499
3551
|
change = nextReset ? Object.freeze({ kind: "reset" }) : require_transform.createCollectionChange({
|
|
@@ -3810,18 +3862,19 @@ const createProcessor = (scheduler, definition, dependencies) => {
|
|
|
3810
3862
|
};
|
|
3811
3863
|
//#endregion
|
|
3812
3864
|
//#region core/src/projection/readable/listeners.ts
|
|
3813
|
-
/** Exhaustively notifies
|
|
3814
|
-
const
|
|
3815
|
-
|
|
3816
|
-
const
|
|
3817
|
-
for (const listener of snapshot) try {
|
|
3865
|
+
/** Exhaustively notifies an already-stable projection listener snapshot. */
|
|
3866
|
+
const notifyProjectionListenerSnapshot = (listeners, message) => {
|
|
3867
|
+
let failures;
|
|
3868
|
+
for (const listener of listeners) try {
|
|
3818
3869
|
listener();
|
|
3819
3870
|
} catch (error) {
|
|
3820
|
-
failures.push(error);
|
|
3871
|
+
(failures ??= []).push(error);
|
|
3821
3872
|
}
|
|
3822
|
-
if (failures
|
|
3823
|
-
if (failures
|
|
3873
|
+
if (failures?.length === 1) throw failures[0];
|
|
3874
|
+
if (failures?.length) throw new AggregateError(failures, message);
|
|
3824
3875
|
};
|
|
3876
|
+
/** Snapshots a mutable listener collection before exhaustive notification. */
|
|
3877
|
+
const notifyProjectionListeners = (listeners, message) => notifyProjectionListenerSnapshot([...listeners], message);
|
|
3825
3878
|
//#endregion
|
|
3826
3879
|
//#region core/src/projection/readable/selection.ts
|
|
3827
3880
|
let activeTracker;
|
|
@@ -3876,8 +3929,7 @@ const selectionAffects = (selection, change) => {
|
|
|
3876
3929
|
if (!change || change.kind === "reset") return true;
|
|
3877
3930
|
if (selection.all) return true;
|
|
3878
3931
|
if (selection.structure && require_transform.collectionHasStructuralChange(change)) return true;
|
|
3879
|
-
|
|
3880
|
-
return false;
|
|
3932
|
+
return require_transform.collectionChangeIntersects(change, selection.keys);
|
|
3881
3933
|
};
|
|
3882
3934
|
const createDirectReadable = (source) => Object.freeze({
|
|
3883
3935
|
current: source.current,
|
|
@@ -3919,7 +3971,7 @@ const createSelectorReadable = (source, selector, equality = Object.is) => {
|
|
|
3919
3971
|
activeTracker = previousTracker;
|
|
3920
3972
|
}
|
|
3921
3973
|
const nextSelection = Object.freeze({
|
|
3922
|
-
keys:
|
|
3974
|
+
keys: tracker.keys,
|
|
3923
3975
|
all: tracker.all || isMapLike(current) && tracker.keys.size === 0 && !tracker.structure,
|
|
3924
3976
|
structure: tracker.structure
|
|
3925
3977
|
});
|
|
@@ -4161,10 +4213,11 @@ const clearDocumentDirty = (dirty) => {
|
|
|
4161
4213
|
dirty.treeNodes.clear();
|
|
4162
4214
|
dirty.children.clear();
|
|
4163
4215
|
};
|
|
4164
|
-
const
|
|
4216
|
+
const locateRange = (dirty, path, start, tail) => {
|
|
4165
4217
|
let current = dirty;
|
|
4166
|
-
for (
|
|
4218
|
+
for (let index = start; index < path.length; index++) {
|
|
4167
4219
|
if (current.replace) return void 0;
|
|
4220
|
+
const key = path[index];
|
|
4168
4221
|
let child = current.children.get(key);
|
|
4169
4222
|
if (!child) {
|
|
4170
4223
|
child = createDocumentDirty();
|
|
@@ -4172,10 +4225,17 @@ const locate = (dirty, path) => {
|
|
|
4172
4225
|
}
|
|
4173
4226
|
current = child;
|
|
4174
4227
|
}
|
|
4175
|
-
return current;
|
|
4228
|
+
if (tail === void 0) return current;
|
|
4229
|
+
if (current.replace) return void 0;
|
|
4230
|
+
let child = current.children.get(tail);
|
|
4231
|
+
if (!child) {
|
|
4232
|
+
child = createDocumentDirty();
|
|
4233
|
+
current.children.set(tail, child);
|
|
4234
|
+
}
|
|
4235
|
+
return child;
|
|
4176
4236
|
};
|
|
4177
|
-
const
|
|
4178
|
-
const current =
|
|
4237
|
+
const replaceAt = (dirty, path, start, tail) => {
|
|
4238
|
+
const current = locateRange(dirty, path, start, tail);
|
|
4179
4239
|
if (!current) return;
|
|
4180
4240
|
current.replace = true;
|
|
4181
4241
|
current.order = false;
|
|
@@ -4183,15 +4243,18 @@ const markDocumentReplace = (dirty, path) => {
|
|
|
4183
4243
|
current.treeNodes.clear();
|
|
4184
4244
|
current.children.clear();
|
|
4185
4245
|
};
|
|
4186
|
-
const
|
|
4187
|
-
|
|
4246
|
+
const markDocumentReplace = (dirty, path) => {
|
|
4247
|
+
replaceAt(dirty, path, 0);
|
|
4248
|
+
};
|
|
4249
|
+
const markDocumentOrderRange = (dirty, path, start) => {
|
|
4250
|
+
const current = locateRange(dirty, path, start);
|
|
4188
4251
|
if (current && !current.replace) current.order = true;
|
|
4189
4252
|
};
|
|
4190
|
-
const markDocumentTree = (dirty, path, root, nodes) => {
|
|
4191
|
-
const current =
|
|
4253
|
+
const markDocumentTree = (dirty, path, start, root, nodes) => {
|
|
4254
|
+
const current = locateRange(dirty, path, start);
|
|
4192
4255
|
if (!current || current.replace) return;
|
|
4193
4256
|
current.treeRoot ||= root;
|
|
4194
|
-
for (const
|
|
4257
|
+
for (const node of nodes) current.treeNodes.add(node.id);
|
|
4195
4258
|
};
|
|
4196
4259
|
const createCollectionPending = () => ({
|
|
4197
4260
|
reset: false,
|
|
@@ -4221,19 +4284,19 @@ const mergeValueChanges = (selector, dirty, changes) => {
|
|
|
4221
4284
|
const at = selector.address;
|
|
4222
4285
|
for (const change of changes.changes) {
|
|
4223
4286
|
if (change.kind === "reset") {
|
|
4224
|
-
|
|
4287
|
+
replaceAt(dirty, at, at.length);
|
|
4225
4288
|
return;
|
|
4226
4289
|
}
|
|
4227
4290
|
if (change.kind === "members") {
|
|
4228
4291
|
for (const member of change.members) {
|
|
4229
|
-
const
|
|
4230
|
-
if (
|
|
4231
|
-
else if (
|
|
4292
|
+
const compared = compareExtended(change.at, member.key, at);
|
|
4293
|
+
if (compared === "ancestor" || compared === "equal") replaceAt(dirty, at, at.length);
|
|
4294
|
+
else if (compared === "descendant") replaceAt(dirty, change.at, at.length, member.key);
|
|
4232
4295
|
}
|
|
4233
|
-
if (change.order && contains(at, change.at))
|
|
4296
|
+
if (change.order && contains(at, change.at)) markDocumentOrderRange(dirty, change.at, at.length);
|
|
4234
4297
|
continue;
|
|
4235
4298
|
}
|
|
4236
|
-
if (contains(at, change.at)) markDocumentTree(dirty, change.at
|
|
4299
|
+
if (contains(at, change.at)) markDocumentTree(dirty, change.at, at.length, change.before !== change.after, change.nodes);
|
|
4237
4300
|
}
|
|
4238
4301
|
};
|
|
4239
4302
|
const mergeCollectionChanges = (selector, pending, changes) => {
|
|
@@ -4245,13 +4308,15 @@ const mergeCollectionChanges = (selector, pending, changes) => {
|
|
|
4245
4308
|
return;
|
|
4246
4309
|
}
|
|
4247
4310
|
if (selector.tree?.kind === "nodes") {
|
|
4248
|
-
if (change.kind === "members") {
|
|
4249
|
-
|
|
4311
|
+
if (change.kind === "members") for (const member of change.members) {
|
|
4312
|
+
const compared = compareExtended(change.at, member.key, at);
|
|
4313
|
+
if (compared === "ancestor" || compared === "equal") {
|
|
4250
4314
|
resetCollectionPending(pending);
|
|
4251
4315
|
return;
|
|
4252
4316
|
}
|
|
4253
|
-
}
|
|
4254
|
-
|
|
4317
|
+
}
|
|
4318
|
+
else if (change.at.length === at.length && contains(change.at, at)) for (const node of change.nodes) {
|
|
4319
|
+
replaceAt(dirtyEntry(pending, node.id), at, at.length);
|
|
4255
4320
|
pending.order ||= node.kind !== "updated";
|
|
4256
4321
|
}
|
|
4257
4322
|
else if (contains(change.at, at)) {
|
|
@@ -4262,34 +4327,27 @@ const mergeCollectionChanges = (selector, pending, changes) => {
|
|
|
4262
4327
|
}
|
|
4263
4328
|
if (change.kind === "members") {
|
|
4264
4329
|
for (const member of change.members) {
|
|
4265
|
-
const
|
|
4266
|
-
if (
|
|
4267
|
-
resetCollectionPending(pending);
|
|
4268
|
-
return;
|
|
4269
|
-
}
|
|
4270
|
-
if (!contains(at, changed)) continue;
|
|
4271
|
-
const relative = changed.slice(at.length);
|
|
4272
|
-
if (!relative.length) {
|
|
4330
|
+
const compared = compareExtended(change.at, member.key, at);
|
|
4331
|
+
if (compared === "ancestor" || compared === "equal") {
|
|
4273
4332
|
resetCollectionPending(pending);
|
|
4274
4333
|
return;
|
|
4275
4334
|
}
|
|
4276
|
-
|
|
4277
|
-
if (
|
|
4278
|
-
|
|
4279
|
-
|
|
4280
|
-
|
|
4281
|
-
if (!relative.length) pending.order = true;
|
|
4282
|
-
else markDocumentOrder(dirtyEntry(pending, relative[0]), relative.slice(1));
|
|
4335
|
+
if (compared !== "descendant") continue;
|
|
4336
|
+
if (at.length === change.at.length) {
|
|
4337
|
+
replaceAt(dirtyEntry(pending, member.key), change.at, change.at.length);
|
|
4338
|
+
if (member.kind !== "updated") pending.order = true;
|
|
4339
|
+
} else replaceAt(dirtyEntry(pending, change.at[at.length]), change.at, at.length + 1, member.key);
|
|
4283
4340
|
}
|
|
4341
|
+
if (change.order && contains(at, change.at)) if (change.at.length === at.length) pending.order = true;
|
|
4342
|
+
else markDocumentOrderRange(dirtyEntry(pending, change.at[at.length]), change.at, at.length + 1);
|
|
4284
4343
|
continue;
|
|
4285
4344
|
}
|
|
4286
4345
|
if (!contains(at, change.at)) continue;
|
|
4287
|
-
|
|
4288
|
-
if (!relative.length) {
|
|
4346
|
+
if (change.at.length === at.length) {
|
|
4289
4347
|
resetCollectionPending(pending);
|
|
4290
4348
|
return;
|
|
4291
4349
|
}
|
|
4292
|
-
markDocumentTree(dirtyEntry(pending,
|
|
4350
|
+
markDocumentTree(dirtyEntry(pending, change.at[at.length]), change.at, at.length + 1, change.before !== change.after, change.nodes);
|
|
4293
4351
|
}
|
|
4294
4352
|
};
|
|
4295
4353
|
//#endregion
|
|
@@ -4418,16 +4476,29 @@ const stageCollectionRead = (state, read, active, options) => {
|
|
|
4418
4476
|
evaluation.output.order(ids);
|
|
4419
4477
|
} else {
|
|
4420
4478
|
const previous = state.current();
|
|
4421
|
-
|
|
4422
|
-
|
|
4423
|
-
for (const key of
|
|
4479
|
+
let currentIds;
|
|
4480
|
+
const ids = () => currentIds ??= read.ids();
|
|
4481
|
+
if (options.candidates) for (const key of options.candidates) if (read.has(key)) {
|
|
4424
4482
|
require_transform.profile.collectionView.mapped();
|
|
4425
4483
|
evaluation.output.set(key, read.get(key));
|
|
4426
4484
|
} else evaluation.output.remove(key);
|
|
4485
|
+
else {
|
|
4486
|
+
const previousIds = previous.ids();
|
|
4487
|
+
const nextIds = ids();
|
|
4488
|
+
require_transform.profile.collectionView.idsScanned(previousIds.length + nextIds.length);
|
|
4489
|
+
for (const key of previousIds) if (read.has(key)) {
|
|
4490
|
+
require_transform.profile.collectionView.mapped();
|
|
4491
|
+
evaluation.output.set(key, read.get(key));
|
|
4492
|
+
} else evaluation.output.remove(key);
|
|
4493
|
+
for (const key of nextIds) if (!previous.has(key)) {
|
|
4494
|
+
require_transform.profile.collectionView.mapped();
|
|
4495
|
+
evaluation.output.set(key, read.get(key));
|
|
4496
|
+
}
|
|
4497
|
+
}
|
|
4427
4498
|
if (options.orderMayChange || !options.candidates) {
|
|
4428
|
-
const
|
|
4429
|
-
if (options.candidates) require_transform.profile.collectionView.idsScanned(
|
|
4430
|
-
evaluation.output.order(
|
|
4499
|
+
const nextIds = ids();
|
|
4500
|
+
if (options.candidates) require_transform.profile.collectionView.idsScanned(nextIds.length);
|
|
4501
|
+
evaluation.output.order(nextIds);
|
|
4431
4502
|
}
|
|
4432
4503
|
}
|
|
4433
4504
|
return state.seal(options.reset, options.isEqual ?? Object.is);
|
|
@@ -4721,13 +4792,15 @@ const createDocumentSourceRegistry = (scheduler) => {
|
|
|
4721
4792
|
const snapshots = /* @__PURE__ */ new Map();
|
|
4722
4793
|
const replacement = createDocumentDirty();
|
|
4723
4794
|
if (pending.reset) markDocumentReplace(replacement, []);
|
|
4795
|
+
let cachedIds;
|
|
4724
4796
|
const ids = () => {
|
|
4725
4797
|
require_transform.assertScope(active);
|
|
4726
|
-
if (
|
|
4727
|
-
if (node?.kind === "
|
|
4728
|
-
if (node?.kind === "
|
|
4729
|
-
if (node?.kind === "
|
|
4730
|
-
return Object.freeze(
|
|
4798
|
+
if (cachedIds) return cachedIds;
|
|
4799
|
+
if (treeNodes) return cachedIds = node?.kind === "tree" && require_record.isRecord(value) && require_record.isRecord(value.nodes) ? Object.freeze(Object.keys(value.nodes)) : Object.freeze([]);
|
|
4800
|
+
if (node?.kind === "map" && require_record.isRecord(value)) return cachedIds = Object.freeze(Object.keys(value));
|
|
4801
|
+
if (node?.kind === "table" && require_record.isRecord(value) && Array.isArray(value.ids)) return cachedIds = Object.freeze([...value.ids]);
|
|
4802
|
+
if (node?.kind === "list" && Array.isArray(value)) return cachedIds = Object.freeze(toArray(indexedKeys(value, node.keyOf)));
|
|
4803
|
+
return cachedIds = Object.freeze([]);
|
|
4731
4804
|
};
|
|
4732
4805
|
const has = (key) => {
|
|
4733
4806
|
require_transform.assertScope(active);
|
|
@@ -5215,7 +5288,6 @@ const createSourceRegistry = (scheduler) => {
|
|
|
5215
5288
|
};
|
|
5216
5289
|
//#endregion
|
|
5217
5290
|
//#region core/src/projection/readable/keyed.ts
|
|
5218
|
-
const sameKeys = (previous, next) => previous.length === next.length && previous.every((key, index) => key === next[index]);
|
|
5219
5291
|
/** Runtime-owned keyed consumer family over one materialized collection output. */
|
|
5220
5292
|
const createProjectionItems = (source, checkOwner) => {
|
|
5221
5293
|
if (source.kind !== "collection") throw new TypeError("Projection items require a keyed collection projection.");
|
|
@@ -5235,7 +5307,11 @@ const createProjectionItems = (source, checkOwner) => {
|
|
|
5235
5307
|
for (const listener of listeners) notifications.push(listener);
|
|
5236
5308
|
};
|
|
5237
5309
|
const flushNotifications = () => {
|
|
5238
|
-
|
|
5310
|
+
try {
|
|
5311
|
+
notifyProjectionListenerSnapshot(notifications, "Projection item listeners failed.");
|
|
5312
|
+
} finally {
|
|
5313
|
+
notifications.length = 0;
|
|
5314
|
+
}
|
|
5239
5315
|
};
|
|
5240
5316
|
const unregisterWaiting = (state) => {
|
|
5241
5317
|
const states = waiting.get(state.key);
|
|
@@ -5278,16 +5354,11 @@ const createProjectionItems = (source, checkOwner) => {
|
|
|
5278
5354
|
publishState(state, void 0);
|
|
5279
5355
|
state.ended = true;
|
|
5280
5356
|
};
|
|
5281
|
-
const
|
|
5282
|
-
const result = [];
|
|
5357
|
+
const terminateKey = (key) => {
|
|
5283
5358
|
const canonical = active.get(key);
|
|
5284
|
-
if (canonical)
|
|
5359
|
+
if (canonical) terminateState(canonical);
|
|
5285
5360
|
const extra = followers.get(key);
|
|
5286
|
-
if (extra)
|
|
5287
|
-
return result;
|
|
5288
|
-
};
|
|
5289
|
-
const terminateKey = (key) => {
|
|
5290
|
-
for (const state of statesFor(key)) terminateState(state);
|
|
5361
|
+
if (extra) for (const state of extra) terminateState(state);
|
|
5291
5362
|
active.delete(key);
|
|
5292
5363
|
followers.delete(key);
|
|
5293
5364
|
};
|
|
@@ -5298,12 +5369,14 @@ const createProjectionItems = (source, checkOwner) => {
|
|
|
5298
5369
|
for (const state of states) attachActive(state, value);
|
|
5299
5370
|
};
|
|
5300
5371
|
const updateKey = (key, value) => {
|
|
5301
|
-
|
|
5372
|
+
const canonical = active.get(key);
|
|
5373
|
+
if (canonical) publishState(canonical, value);
|
|
5374
|
+
const extra = followers.get(key);
|
|
5375
|
+
if (extra) for (const state of extra) publishState(state, value);
|
|
5302
5376
|
};
|
|
5303
5377
|
const updateKeys = (current) => {
|
|
5304
|
-
|
|
5305
|
-
|
|
5306
|
-
keysValue = next;
|
|
5378
|
+
if (require_transform.iterableMatchesArray(current.keys(), keysValue)) return;
|
|
5379
|
+
keysValue = Object.freeze([...current.keys()]);
|
|
5307
5380
|
keysRevision++;
|
|
5308
5381
|
notify(keyListeners);
|
|
5309
5382
|
};
|
|
@@ -5346,9 +5419,9 @@ const createProjectionItems = (source, checkOwner) => {
|
|
|
5346
5419
|
return state;
|
|
5347
5420
|
};
|
|
5348
5421
|
const reconcile = (current) => {
|
|
5349
|
-
for (const key of
|
|
5422
|
+
for (const key of active.keys()) if (!current.has(key)) terminateKey(key);
|
|
5350
5423
|
else updateKey(key, current.get(key));
|
|
5351
|
-
for (const key of
|
|
5424
|
+
for (const key of waiting.keys()) if (current.has(key)) activateWaiting(key, current.get(key));
|
|
5352
5425
|
updateKeys(current);
|
|
5353
5426
|
};
|
|
5354
5427
|
const onChange = (change) => {
|