@ibodr/store 0.2.5 → 0.2.7
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/dist/index.d.ts +45 -7
- package/dist/index.mjs +250 -209
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { registerDrawLibraryVersion, assert, STRUCTURED_CLONE_OBJECT_PROTOTYPE, objectMapEntries, structuredClone, uniqueId,
|
|
1
|
+
import { registerDrawLibraryVersion, assert, STRUCTURED_CLONE_OBJECT_PROTOTYPE, objectMapEntries, objectMapValues, structuredClone, uniqueId, areArraysShallowEqual, isEqual, throttleToNextFrame, filterEntries, getOwnProperty, objectMapKeys, WeakCache, Result, exhaustiveSwitchError, objectMapFromEntries } from '@ibodr/utils';
|
|
2
2
|
import { atom, UNINITIALIZED, transact, computed, isUninitialized, RESET_VALUE, withDiff, EMPTY_ARRAY, reactor } from '@ibodr/state';
|
|
3
3
|
|
|
4
4
|
// src/index.ts
|
|
@@ -64,7 +64,7 @@ function cachedHashString(string) {
|
|
|
64
64
|
hashed = hashString(string);
|
|
65
65
|
if (stringHashCacheCount === STRING_HASH_CACHE_SIZE) {
|
|
66
66
|
stringHashCacheCount = 0;
|
|
67
|
-
stringHashCache =
|
|
67
|
+
stringHashCache = /* @__PURE__ */ Object.create(null);
|
|
68
68
|
}
|
|
69
69
|
stringHashCache[string] = hashed;
|
|
70
70
|
stringHashCacheCount++;
|
|
@@ -109,7 +109,7 @@ function nextHash() {
|
|
|
109
109
|
var weakMap = /* @__PURE__ */ new WeakMap();
|
|
110
110
|
var symbolMap = /* @__PURE__ */ Object.create(null);
|
|
111
111
|
var _objHashUID = 0;
|
|
112
|
-
var stringHashCache =
|
|
112
|
+
var stringHashCache = /* @__PURE__ */ Object.create(null);
|
|
113
113
|
var stringHashCacheCount = 0;
|
|
114
114
|
var STRING_HASH_CACHE_SIZE = 24e3;
|
|
115
115
|
var SHIFT = 5;
|
|
@@ -127,6 +127,9 @@ function SetRef(ref) {
|
|
|
127
127
|
function arrCopy(arr, offset = 0) {
|
|
128
128
|
return arr.slice(offset);
|
|
129
129
|
}
|
|
130
|
+
function is(a, b) {
|
|
131
|
+
return a === b || a !== a && b !== b;
|
|
132
|
+
}
|
|
130
133
|
var OwnerID = class {
|
|
131
134
|
};
|
|
132
135
|
var ImmutableMap = class _ImmutableMap {
|
|
@@ -164,19 +167,6 @@ var ImmutableMap = class _ImmutableMap {
|
|
|
164
167
|
}
|
|
165
168
|
});
|
|
166
169
|
}
|
|
167
|
-
/**
|
|
168
|
-
* Gets the value associated with the specified key, with a fallback value.
|
|
169
|
-
*
|
|
170
|
-
* @param k - The key to look up
|
|
171
|
-
* @param notSetValue - The value to return if the key is not found
|
|
172
|
-
* @returns The value associated with the key, or the fallback value if not found
|
|
173
|
-
* @example
|
|
174
|
-
* ```ts
|
|
175
|
-
* const map = new ImmutableMap([['key1', 'value1']])
|
|
176
|
-
* console.log(map.get('key1', 'default')) // 'value1'
|
|
177
|
-
* console.log(map.get('missing', 'default')) // 'default'
|
|
178
|
-
* ```
|
|
179
|
-
*/
|
|
180
170
|
get(k, notSetValue) {
|
|
181
171
|
return this._root ? this._root.get(0, void 0, k, notSetValue) : notSetValue;
|
|
182
172
|
}
|
|
@@ -353,7 +343,7 @@ var ArrayMapNode = class _ArrayMapNode {
|
|
|
353
343
|
get(_shift, _keyHash, key, notSetValue) {
|
|
354
344
|
const entries = this.entries;
|
|
355
345
|
for (let ii = 0, len = entries.length; ii < len; ii++) {
|
|
356
|
-
if (
|
|
346
|
+
if (is(key, entries[ii][0])) {
|
|
357
347
|
return entries[ii][1];
|
|
358
348
|
}
|
|
359
349
|
}
|
|
@@ -365,7 +355,7 @@ var ArrayMapNode = class _ArrayMapNode {
|
|
|
365
355
|
let idx = 0;
|
|
366
356
|
const len = entries.length;
|
|
367
357
|
for (; idx < len; idx++) {
|
|
368
|
-
if (
|
|
358
|
+
if (is(key, entries[idx][0])) {
|
|
369
359
|
break;
|
|
370
360
|
}
|
|
371
361
|
}
|
|
@@ -539,7 +529,7 @@ var HashCollisionNode = class _HashCollisionNode {
|
|
|
539
529
|
get(shift, keyHash, key, notSetValue) {
|
|
540
530
|
const entries = this.entries;
|
|
541
531
|
for (let ii = 0, len = entries.length; ii < len; ii++) {
|
|
542
|
-
if (
|
|
532
|
+
if (is(key, entries[ii][0])) {
|
|
543
533
|
return entries[ii][1];
|
|
544
534
|
}
|
|
545
535
|
}
|
|
@@ -562,7 +552,7 @@ var HashCollisionNode = class _HashCollisionNode {
|
|
|
562
552
|
let idx = 0;
|
|
563
553
|
const len = entries.length;
|
|
564
554
|
for (; idx < len; idx++) {
|
|
565
|
-
if (
|
|
555
|
+
if (is(key, entries[idx][0])) {
|
|
566
556
|
break;
|
|
567
557
|
}
|
|
568
558
|
}
|
|
@@ -607,11 +597,11 @@ var ValueNode = class _ValueNode {
|
|
|
607
597
|
keyHash;
|
|
608
598
|
entry;
|
|
609
599
|
get(shift, keyHash, key, notSetValue) {
|
|
610
|
-
return
|
|
600
|
+
return is(key, this.entry[0]) ? this.entry[1] : notSetValue;
|
|
611
601
|
}
|
|
612
602
|
update(ownerID, shift, keyHash, key, value, didChangeSize, didAlter) {
|
|
613
603
|
const removed = value === NOT_SET;
|
|
614
|
-
const keyMatch =
|
|
604
|
+
const keyMatch = is(key, this.entry[0]);
|
|
615
605
|
if (keyMatch ? value === this.entry[1] : removed) {
|
|
616
606
|
return this;
|
|
617
607
|
}
|
|
@@ -999,6 +989,47 @@ var AtomMap = class {
|
|
|
999
989
|
}
|
|
1000
990
|
return this;
|
|
1001
991
|
}
|
|
992
|
+
/**
|
|
993
|
+
* Gets the value associated with a key, inserting `defaultValue` first if the key doesn't exist.
|
|
994
|
+
* This method is reactive and will cause reactive contexts to update when the value changes.
|
|
995
|
+
*
|
|
996
|
+
* @param key - The key to retrieve the value for
|
|
997
|
+
* @param defaultValue - The value to insert if the key doesn't exist
|
|
998
|
+
* @returns The existing value, or `defaultValue` if the key was missing
|
|
999
|
+
* @example
|
|
1000
|
+
* ```ts
|
|
1001
|
+
* const map = new AtomMap('myMap')
|
|
1002
|
+
* console.log(map.getOrInsert('count', 0)) // 0, and 'count' is now set
|
|
1003
|
+
* console.log(map.getOrInsert('count', 10)) // 0
|
|
1004
|
+
* ```
|
|
1005
|
+
*/
|
|
1006
|
+
getOrInsert(key, defaultValue) {
|
|
1007
|
+
return this.getOrInsertComputed(key, () => defaultValue);
|
|
1008
|
+
}
|
|
1009
|
+
/**
|
|
1010
|
+
* Gets the value associated with a key, inserting the result of `callback` first if the key
|
|
1011
|
+
* doesn't exist. The callback only runs when the key is missing.
|
|
1012
|
+
* This method is reactive and will cause reactive contexts to update when the value changes.
|
|
1013
|
+
*
|
|
1014
|
+
* @param key - The key to retrieve the value for
|
|
1015
|
+
* @param callback - Called with the key to produce the value to insert
|
|
1016
|
+
* @returns The existing value, or the newly computed value if the key was missing
|
|
1017
|
+
* @example
|
|
1018
|
+
* ```ts
|
|
1019
|
+
* const map = new AtomMap<string, string[]>('myMap')
|
|
1020
|
+
* map.getOrInsertComputed('tags', () => []).push('new')
|
|
1021
|
+
* ```
|
|
1022
|
+
*/
|
|
1023
|
+
getOrInsertComputed(key, callback) {
|
|
1024
|
+
const valueAtom = this.getAtom(key);
|
|
1025
|
+
if (valueAtom) {
|
|
1026
|
+
const value2 = valueAtom.get();
|
|
1027
|
+
if (value2 !== UNINITIALIZED) return value2;
|
|
1028
|
+
}
|
|
1029
|
+
const value = callback(key);
|
|
1030
|
+
this.set(key, value);
|
|
1031
|
+
return value;
|
|
1032
|
+
}
|
|
1002
1033
|
/**
|
|
1003
1034
|
* Updates an existing value using an updater function.
|
|
1004
1035
|
*
|
|
@@ -1116,7 +1147,7 @@ var AtomMap = class {
|
|
|
1116
1147
|
*entries() {
|
|
1117
1148
|
for (const [key, valueAtom] of this.atoms.get()) {
|
|
1118
1149
|
const value = valueAtom.get();
|
|
1119
|
-
|
|
1150
|
+
if (value === UNINITIALIZED) continue;
|
|
1120
1151
|
yield [key, value];
|
|
1121
1152
|
}
|
|
1122
1153
|
}
|
|
@@ -1135,7 +1166,8 @@ var AtomMap = class {
|
|
|
1135
1166
|
* ```
|
|
1136
1167
|
*/
|
|
1137
1168
|
*keys() {
|
|
1138
|
-
for (const key of this.atoms.get()
|
|
1169
|
+
for (const [key, valueAtom] of this.atoms.get()) {
|
|
1170
|
+
if (valueAtom.__unsafe__getWithoutCapture() === UNINITIALIZED) continue;
|
|
1139
1171
|
yield key;
|
|
1140
1172
|
}
|
|
1141
1173
|
}
|
|
@@ -1156,7 +1188,7 @@ var AtomMap = class {
|
|
|
1156
1188
|
*values() {
|
|
1157
1189
|
for (const valueAtom of this.atoms.get().values()) {
|
|
1158
1190
|
const value = valueAtom.get();
|
|
1159
|
-
|
|
1191
|
+
if (value === UNINITIALIZED) continue;
|
|
1160
1192
|
yield value;
|
|
1161
1193
|
}
|
|
1162
1194
|
}
|
|
@@ -1361,6 +1393,8 @@ var IncrementalSetConstructor = class {
|
|
|
1361
1393
|
if (numRemoved === 0 && numAdded === 0) {
|
|
1362
1394
|
return void 0;
|
|
1363
1395
|
}
|
|
1396
|
+
if (numAdded === 0) delete this.diff.added;
|
|
1397
|
+
if (numRemoved === 0) delete this.diff.removed;
|
|
1364
1398
|
return { value: this.nextValue, diff: this.diff };
|
|
1365
1399
|
}
|
|
1366
1400
|
/**
|
|
@@ -1500,13 +1534,11 @@ function createRecordMigrationSequence(opts) {
|
|
|
1500
1534
|
return createMigrationSequence({
|
|
1501
1535
|
sequenceId,
|
|
1502
1536
|
retroactive: opts.retroactive ?? true,
|
|
1503
|
-
sequence: opts.sequence.map(
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
} : m
|
|
1509
|
-
)
|
|
1537
|
+
sequence: opts.sequence.map((m) => ({
|
|
1538
|
+
...m,
|
|
1539
|
+
scope: "record",
|
|
1540
|
+
filter: (r) => r.typeName === opts.recordType && (m.filter?.(r) ?? true) && (opts.filter?.(r) ?? true)
|
|
1541
|
+
}))
|
|
1510
1542
|
});
|
|
1511
1543
|
}
|
|
1512
1544
|
function sortMigrations(migrations) {
|
|
@@ -1529,11 +1561,12 @@ function sortMigrations(migrations) {
|
|
|
1529
1561
|
}
|
|
1530
1562
|
if (m.dependsOn) {
|
|
1531
1563
|
for (const depId of m.dependsOn) {
|
|
1532
|
-
if (byId.has(depId))
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1564
|
+
if (!byId.has(depId)) continue;
|
|
1565
|
+
explicitDeps.get(m.id).add(depId);
|
|
1566
|
+
const dependentsOfDep = dependents.get(depId);
|
|
1567
|
+
if (dependentsOfDep.has(m.id)) continue;
|
|
1568
|
+
dependentsOfDep.add(m.id);
|
|
1569
|
+
inDegree.set(m.id, inDegree.get(m.id) + 1);
|
|
1537
1570
|
}
|
|
1538
1571
|
}
|
|
1539
1572
|
}
|
|
@@ -1629,59 +1662,115 @@ function createEmptyRecordsDiff() {
|
|
|
1629
1662
|
return { added: {}, updated: {}, removed: {} };
|
|
1630
1663
|
}
|
|
1631
1664
|
function reverseRecordsDiff(diff) {
|
|
1632
|
-
const result = {
|
|
1633
|
-
|
|
1665
|
+
const result = {
|
|
1666
|
+
added: { ...diff.removed },
|
|
1667
|
+
removed: { ...diff.added },
|
|
1668
|
+
updated: {}
|
|
1669
|
+
};
|
|
1670
|
+
for (const [from, to] of objectMapValues(diff.updated)) {
|
|
1634
1671
|
result.updated[from.id] = [to, from];
|
|
1635
1672
|
}
|
|
1636
1673
|
return result;
|
|
1637
1674
|
}
|
|
1638
1675
|
function isRecordsDiffEmpty(diff) {
|
|
1639
|
-
return
|
|
1676
|
+
return !hasAnyKey(diff.added) && !hasAnyKey(diff.updated) && !hasAnyKey(diff.removed);
|
|
1677
|
+
}
|
|
1678
|
+
function hasAnyKey(obj) {
|
|
1679
|
+
for (const _ in obj) return true;
|
|
1680
|
+
return false;
|
|
1640
1681
|
}
|
|
1641
1682
|
function squashRecordDiffs(diffs, options) {
|
|
1642
|
-
|
|
1643
|
-
|
|
1683
|
+
if (options?.mutateFirstDiff) {
|
|
1684
|
+
const result2 = diffs[0];
|
|
1685
|
+
if (!result2) return createEmptyRecordsDiff();
|
|
1686
|
+
for (const _id in result2.updated) {
|
|
1687
|
+
const id = _id;
|
|
1688
|
+
const [from, to] = result2.updated[id];
|
|
1689
|
+
result2.updated[id] = [from, to];
|
|
1690
|
+
}
|
|
1691
|
+
squashRecordDiffsMutable(result2, diffs, 1);
|
|
1692
|
+
return result2;
|
|
1693
|
+
}
|
|
1694
|
+
const result = { added: {}, removed: {}, updated: {} };
|
|
1695
|
+
squashRecordDiffsMutable(result, diffs);
|
|
1644
1696
|
return result;
|
|
1645
1697
|
}
|
|
1646
|
-
function squashRecordDiffsMutable(target, diffs) {
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1698
|
+
function squashRecordDiffsMutable(target, diffs, fromIndex = 0) {
|
|
1699
|
+
squashRecordDiffsMutableImpl(target, diffs, fromIndex);
|
|
1700
|
+
}
|
|
1701
|
+
function squashRecordDiffsMutableByType(target, diffs, typeName) {
|
|
1702
|
+
return squashRecordDiffsMutableImpl(target, diffs, 0, typeName);
|
|
1703
|
+
}
|
|
1704
|
+
function squashRecordDiffsMutableImpl(target, diffs, fromIndex, typeName) {
|
|
1705
|
+
let sizeChange = 0;
|
|
1706
|
+
const trackSize = typeName !== void 0;
|
|
1707
|
+
for (let i = fromIndex; i < diffs.length; i++) {
|
|
1708
|
+
const diff = diffs[i];
|
|
1709
|
+
const targetHasRemoved = hasAnyKey(target.removed);
|
|
1710
|
+
for (const _id in diff.added) {
|
|
1711
|
+
const id = _id;
|
|
1712
|
+
const value = diff.added[id];
|
|
1713
|
+
if (typeName !== void 0 && value.typeName !== typeName) continue;
|
|
1714
|
+
if (targetHasRemoved && target.removed[id]) {
|
|
1650
1715
|
const original = target.removed[id];
|
|
1651
1716
|
delete target.removed[id];
|
|
1717
|
+
if (trackSize) sizeChange--;
|
|
1652
1718
|
if (original !== value) {
|
|
1653
1719
|
target.updated[id] = [original, value];
|
|
1720
|
+
if (trackSize) sizeChange++;
|
|
1654
1721
|
}
|
|
1655
1722
|
} else {
|
|
1723
|
+
if (trackSize && !target.added[id]) sizeChange++;
|
|
1656
1724
|
target.added[id] = value;
|
|
1657
1725
|
}
|
|
1658
1726
|
}
|
|
1659
|
-
|
|
1660
|
-
|
|
1727
|
+
const targetHasAdded = hasAnyKey(target.added);
|
|
1728
|
+
for (const _id in diff.updated) {
|
|
1729
|
+
const id = _id;
|
|
1730
|
+
const to = diff.updated[id][1];
|
|
1731
|
+
if (typeName !== void 0 && to.typeName !== typeName) continue;
|
|
1732
|
+
if (targetHasAdded && target.added[id]) {
|
|
1661
1733
|
target.added[id] = to;
|
|
1734
|
+
if (trackSize && target.updated[id]) sizeChange--;
|
|
1662
1735
|
delete target.updated[id];
|
|
1663
|
-
|
|
1736
|
+
if (targetHasRemoved) {
|
|
1737
|
+
if (trackSize && target.removed[id]) sizeChange--;
|
|
1738
|
+
delete target.removed[id];
|
|
1739
|
+
}
|
|
1664
1740
|
continue;
|
|
1665
1741
|
}
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1742
|
+
const existing = target.updated[id];
|
|
1743
|
+
if (existing) {
|
|
1744
|
+
existing[1] = to;
|
|
1745
|
+
if (targetHasRemoved) {
|
|
1746
|
+
if (trackSize && target.removed[id]) sizeChange--;
|
|
1747
|
+
delete target.removed[id];
|
|
1748
|
+
}
|
|
1669
1749
|
continue;
|
|
1670
1750
|
}
|
|
1671
|
-
target.updated[id] = diff.updated[id];
|
|
1672
|
-
|
|
1751
|
+
target.updated[id] = [diff.updated[id][0], to];
|
|
1752
|
+
if (trackSize) sizeChange++;
|
|
1753
|
+
if (targetHasRemoved) {
|
|
1754
|
+
if (trackSize && target.removed[id]) sizeChange--;
|
|
1755
|
+
delete target.removed[id];
|
|
1756
|
+
}
|
|
1673
1757
|
}
|
|
1674
|
-
for (const
|
|
1758
|
+
for (const _id in diff.removed) {
|
|
1759
|
+
const id = _id;
|
|
1760
|
+
if (typeName !== void 0 && diff.removed[id].typeName !== typeName) continue;
|
|
1675
1761
|
if (target.added[id]) {
|
|
1676
1762
|
delete target.added[id];
|
|
1763
|
+
if (trackSize) sizeChange--;
|
|
1677
1764
|
} else if (target.updated[id]) {
|
|
1678
1765
|
target.removed[id] = target.updated[id][0];
|
|
1679
1766
|
delete target.updated[id];
|
|
1680
1767
|
} else {
|
|
1681
|
-
target.removed[id]
|
|
1768
|
+
if (trackSize && !target.removed[id]) sizeChange++;
|
|
1769
|
+
target.removed[id] = diff.removed[id];
|
|
1682
1770
|
}
|
|
1683
1771
|
}
|
|
1684
1772
|
}
|
|
1773
|
+
return sizeChange;
|
|
1685
1774
|
}
|
|
1686
1775
|
var RecordType = class _RecordType {
|
|
1687
1776
|
/**
|
|
@@ -1758,9 +1847,9 @@ var RecordType = class _RecordType {
|
|
|
1758
1847
|
create(properties) {
|
|
1759
1848
|
const result = {
|
|
1760
1849
|
...this.createDefaultProperties(),
|
|
1761
|
-
id:
|
|
1850
|
+
id: properties.id ?? this.createId()
|
|
1762
1851
|
};
|
|
1763
|
-
for (const [k, v] of
|
|
1852
|
+
for (const [k, v] of objectMapEntries(properties)) {
|
|
1764
1853
|
if (v !== void 0) {
|
|
1765
1854
|
result[k] = v;
|
|
1766
1855
|
}
|
|
@@ -1988,7 +2077,7 @@ function objectMatchesQuery(query, object) {
|
|
|
1988
2077
|
const value = object[key];
|
|
1989
2078
|
if (isQueryValueMatcher(matcher)) {
|
|
1990
2079
|
if ("eq" in matcher && value !== matcher.eq) return false;
|
|
1991
|
-
if ("neq" in matcher && value === matcher.neq) return false;
|
|
2080
|
+
if ("neq" in matcher && (value === matcher.neq || value === void 0)) return false;
|
|
1992
2081
|
if ("gt" in matcher && (typeof value !== "number" || value <= matcher.gt)) return false;
|
|
1993
2082
|
continue;
|
|
1994
2083
|
}
|
|
@@ -2001,7 +2090,9 @@ function objectMatchesQuery(query, object) {
|
|
|
2001
2090
|
}
|
|
2002
2091
|
function executeQuery(store, typeName, query) {
|
|
2003
2092
|
const matcherPaths = extractMatcherPaths(query);
|
|
2004
|
-
const matchIds =
|
|
2093
|
+
const matchIds = objectMapFromEntries(
|
|
2094
|
+
matcherPaths.map(({ path }) => [path, /* @__PURE__ */ new Set()])
|
|
2095
|
+
);
|
|
2005
2096
|
for (const { path, matcher } of matcherPaths) {
|
|
2006
2097
|
const index = store.index(typeName, path);
|
|
2007
2098
|
if ("eq" in matcher) {
|
|
@@ -2032,7 +2123,7 @@ function executeQuery(store, typeName, query) {
|
|
|
2032
2123
|
return /* @__PURE__ */ new Set();
|
|
2033
2124
|
}
|
|
2034
2125
|
}
|
|
2035
|
-
return intersectSets(
|
|
2126
|
+
return intersectSets(objectMapValues(matchIds));
|
|
2036
2127
|
}
|
|
2037
2128
|
|
|
2038
2129
|
// src/lib/StoreQueries.ts
|
|
@@ -2103,17 +2194,19 @@ var StoreQueries = class {
|
|
|
2103
2194
|
* have been added, updated, or removed.
|
|
2104
2195
|
*
|
|
2105
2196
|
* @param typeName - The type name to filter the history by
|
|
2106
|
-
* @returns A computed value containing
|
|
2197
|
+
* @returns A computed value containing a change counter and diffs of changes for the specified type
|
|
2107
2198
|
*
|
|
2108
2199
|
* @example
|
|
2109
2200
|
* ```ts
|
|
2110
2201
|
* // Track changes to book records only
|
|
2111
2202
|
* const bookHistory = store.query.filterHistory('book')
|
|
2112
2203
|
*
|
|
2113
|
-
* //
|
|
2114
|
-
* react('book-changes', () => {
|
|
2115
|
-
* const
|
|
2116
|
-
*
|
|
2204
|
+
* // Log the books added since the last run
|
|
2205
|
+
* react('book-changes', (lastReactedEpoch) => {
|
|
2206
|
+
* const diffs = bookHistory.getDiffSince(lastReactedEpoch)
|
|
2207
|
+
* // no diffs to give, e.g. on the first run: rebuild anything derived from scratch
|
|
2208
|
+
* if (diffs === RESET_VALUE) return
|
|
2209
|
+
* for (const diff of diffs) console.log('Added:', Object.keys(diff.added))
|
|
2117
2210
|
* })
|
|
2118
2211
|
* ```
|
|
2119
2212
|
*
|
|
@@ -2129,60 +2222,13 @@ var StoreQueries = class {
|
|
|
2129
2222
|
if (isUninitialized(lastValue)) {
|
|
2130
2223
|
return this.history.get();
|
|
2131
2224
|
}
|
|
2225
|
+
const next = Math.max(this.history.get(), lastValue + 1);
|
|
2132
2226
|
const diff = this.history.getDiffSince(lastComputedEpoch);
|
|
2133
|
-
if (diff === RESET_VALUE) return
|
|
2227
|
+
if (diff === RESET_VALUE) return next;
|
|
2134
2228
|
const res = { added: {}, removed: {}, updated: {} };
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
for (const changes of diff) {
|
|
2139
|
-
for (const added of objectMapValues(changes.added)) {
|
|
2140
|
-
if (added.typeName === typeName) {
|
|
2141
|
-
if (res.removed[added.id]) {
|
|
2142
|
-
const original = res.removed[added.id];
|
|
2143
|
-
delete res.removed[added.id];
|
|
2144
|
-
numRemoved--;
|
|
2145
|
-
if (original !== added) {
|
|
2146
|
-
res.updated[added.id] = [original, added];
|
|
2147
|
-
numUpdated++;
|
|
2148
|
-
}
|
|
2149
|
-
} else {
|
|
2150
|
-
res.added[added.id] = added;
|
|
2151
|
-
numAdded++;
|
|
2152
|
-
}
|
|
2153
|
-
}
|
|
2154
|
-
}
|
|
2155
|
-
for (const [from, to] of objectMapValues(changes.updated)) {
|
|
2156
|
-
if (to.typeName === typeName) {
|
|
2157
|
-
if (res.added[to.id]) {
|
|
2158
|
-
res.added[to.id] = to;
|
|
2159
|
-
} else if (res.updated[to.id]) {
|
|
2160
|
-
res.updated[to.id] = [res.updated[to.id][0], to];
|
|
2161
|
-
} else {
|
|
2162
|
-
res.updated[to.id] = [from, to];
|
|
2163
|
-
numUpdated++;
|
|
2164
|
-
}
|
|
2165
|
-
}
|
|
2166
|
-
}
|
|
2167
|
-
for (const removed of objectMapValues(changes.removed)) {
|
|
2168
|
-
if (removed.typeName === typeName) {
|
|
2169
|
-
if (res.added[removed.id]) {
|
|
2170
|
-
delete res.added[removed.id];
|
|
2171
|
-
numAdded--;
|
|
2172
|
-
} else if (res.updated[removed.id]) {
|
|
2173
|
-
res.removed[removed.id] = res.updated[removed.id][0];
|
|
2174
|
-
delete res.updated[removed.id];
|
|
2175
|
-
numUpdated--;
|
|
2176
|
-
numRemoved++;
|
|
2177
|
-
} else {
|
|
2178
|
-
res.removed[removed.id] = removed;
|
|
2179
|
-
numRemoved++;
|
|
2180
|
-
}
|
|
2181
|
-
}
|
|
2182
|
-
}
|
|
2183
|
-
}
|
|
2184
|
-
if (numAdded || numRemoved || numUpdated) {
|
|
2185
|
-
return withDiff(this.history.get(), res);
|
|
2229
|
+
const size = squashRecordDiffsMutableByType(res, diff, typeName);
|
|
2230
|
+
if (size) {
|
|
2231
|
+
return withDiff(next, res);
|
|
2186
2232
|
} else {
|
|
2187
2233
|
return lastValue;
|
|
2188
2234
|
}
|
|
@@ -2278,7 +2324,7 @@ var StoreQueries = class {
|
|
|
2278
2324
|
setConstructor.add(id);
|
|
2279
2325
|
setConstructors.set(value, setConstructor);
|
|
2280
2326
|
};
|
|
2281
|
-
const
|
|
2327
|
+
const remove = (value, id) => {
|
|
2282
2328
|
let set = setConstructors.get(value);
|
|
2283
2329
|
if (!set) set = new IncrementalSetConstructor(prevValue.get(value) ?? /* @__PURE__ */ new Set());
|
|
2284
2330
|
set.remove(id);
|
|
@@ -2299,7 +2345,7 @@ var StoreQueries = class {
|
|
|
2299
2345
|
const next = getPropertyValue(to);
|
|
2300
2346
|
if (prev !== next) {
|
|
2301
2347
|
if (prev !== void 0) {
|
|
2302
|
-
|
|
2348
|
+
remove(prev, to.id);
|
|
2303
2349
|
}
|
|
2304
2350
|
if (next !== void 0) {
|
|
2305
2351
|
add(next, to.id);
|
|
@@ -2311,7 +2357,7 @@ var StoreQueries = class {
|
|
|
2311
2357
|
if (record.typeName === typeName) {
|
|
2312
2358
|
const value = getPropertyValue(record);
|
|
2313
2359
|
if (value !== void 0) {
|
|
2314
|
-
|
|
2360
|
+
remove(value, record.id);
|
|
2315
2361
|
}
|
|
2316
2362
|
}
|
|
2317
2363
|
}
|
|
@@ -2360,7 +2406,7 @@ var StoreQueries = class {
|
|
|
2360
2406
|
*
|
|
2361
2407
|
* @public
|
|
2362
2408
|
*/
|
|
2363
|
-
record(typeName, queryCreator = () => ({}), name = "record:" + typeName +
|
|
2409
|
+
record(typeName, queryCreator = () => ({}), name = "record:" + typeName + ":" + queryCreator.toString()) {
|
|
2364
2410
|
const ids = this.ids(typeName, queryCreator, name);
|
|
2365
2411
|
return computed(name, () => {
|
|
2366
2412
|
for (const id of ids.get()) {
|
|
@@ -2393,7 +2439,7 @@ var StoreQueries = class {
|
|
|
2393
2439
|
*
|
|
2394
2440
|
* @public
|
|
2395
2441
|
*/
|
|
2396
|
-
records(typeName, queryCreator = () => ({}), name = "records:" + typeName +
|
|
2442
|
+
records(typeName, queryCreator = () => ({}), name = "records:" + typeName + ":" + queryCreator.toString()) {
|
|
2397
2443
|
const ids = this.ids(typeName, queryCreator, "ids:" + name);
|
|
2398
2444
|
return computed(
|
|
2399
2445
|
name,
|
|
@@ -2430,12 +2476,12 @@ var StoreQueries = class {
|
|
|
2430
2476
|
*
|
|
2431
2477
|
* @public
|
|
2432
2478
|
*/
|
|
2433
|
-
ids(typeName, queryCreator = () => ({}), name = "ids:" + typeName +
|
|
2479
|
+
ids(typeName, queryCreator = () => ({}), name = "ids:" + typeName + ":" + queryCreator.toString()) {
|
|
2434
2480
|
const typeHistory = this.filterHistory(typeName);
|
|
2435
2481
|
const fromScratch = () => {
|
|
2436
2482
|
typeHistory.get();
|
|
2437
2483
|
const query = queryCreator();
|
|
2438
|
-
if (
|
|
2484
|
+
if (!hasAnyKey(query)) {
|
|
2439
2485
|
return this.getAllIdsForType(typeName);
|
|
2440
2486
|
}
|
|
2441
2487
|
return executeQuery(this, typeName, query);
|
|
@@ -2449,7 +2495,7 @@ var StoreQueries = class {
|
|
|
2449
2495
|
return prevValue;
|
|
2450
2496
|
}
|
|
2451
2497
|
};
|
|
2452
|
-
const cachedQuery = computed("ids_query:" + name, queryCreator, {
|
|
2498
|
+
const cachedQuery = computed("ids_query:" + name, () => queryCreator(), {
|
|
2453
2499
|
isEqual
|
|
2454
2500
|
});
|
|
2455
2501
|
return computed(
|
|
@@ -2548,6 +2594,15 @@ var StoreSideEffects = class {
|
|
|
2548
2594
|
_afterDeleteHandlers = {};
|
|
2549
2595
|
_operationCompleteHandlers = [];
|
|
2550
2596
|
_isEnabled = true;
|
|
2597
|
+
// Handler arrays are replaced, never mutated in place: dispatch iterates the array it looked up,
|
|
2598
|
+
// so a handler that removes itself (or registers another) while running must not shift the
|
|
2599
|
+
// entries out from under that iteration.
|
|
2600
|
+
addHandler(handlers, typeName, handler) {
|
|
2601
|
+
handlers[typeName] = [...handlers[typeName] ?? [], handler];
|
|
2602
|
+
return () => {
|
|
2603
|
+
handlers[typeName] = withoutFirst(handlers[typeName] ?? [], handler);
|
|
2604
|
+
};
|
|
2605
|
+
}
|
|
2551
2606
|
/**
|
|
2552
2607
|
* Checks whether side effects are currently enabled.
|
|
2553
2608
|
* When disabled, all side effect handlers are bypassed.
|
|
@@ -2779,10 +2834,7 @@ var StoreSideEffects = class {
|
|
|
2779
2834
|
* @returns A callback that removes the handler.
|
|
2780
2835
|
*/
|
|
2781
2836
|
registerBeforeCreateHandler(typeName, handler) {
|
|
2782
|
-
|
|
2783
|
-
if (!handlers) this._beforeCreateHandlers[typeName] = [];
|
|
2784
|
-
this._beforeCreateHandlers[typeName].push(handler);
|
|
2785
|
-
return () => remove(this._beforeCreateHandlers[typeName], handler);
|
|
2837
|
+
return this.addHandler(this._beforeCreateHandlers, typeName, handler);
|
|
2786
2838
|
}
|
|
2787
2839
|
/**
|
|
2788
2840
|
* Register a handler to be called after a record is created. This is useful for side-effects
|
|
@@ -2807,10 +2859,7 @@ var StoreSideEffects = class {
|
|
|
2807
2859
|
* @returns A callback that removes the handler.
|
|
2808
2860
|
*/
|
|
2809
2861
|
registerAfterCreateHandler(typeName, handler) {
|
|
2810
|
-
|
|
2811
|
-
if (!handlers) this._afterCreateHandlers[typeName] = [];
|
|
2812
|
-
this._afterCreateHandlers[typeName].push(handler);
|
|
2813
|
-
return () => remove(this._afterCreateHandlers[typeName], handler);
|
|
2862
|
+
return this.addHandler(this._afterCreateHandlers, typeName, handler);
|
|
2814
2863
|
}
|
|
2815
2864
|
/**
|
|
2816
2865
|
* Register a handler to be called before a record is changed. The handler is given the old and
|
|
@@ -2839,10 +2888,7 @@ var StoreSideEffects = class {
|
|
|
2839
2888
|
* @returns A callback that removes the handler.
|
|
2840
2889
|
*/
|
|
2841
2890
|
registerBeforeChangeHandler(typeName, handler) {
|
|
2842
|
-
|
|
2843
|
-
if (!handlers) this._beforeChangeHandlers[typeName] = [];
|
|
2844
|
-
this._beforeChangeHandlers[typeName].push(handler);
|
|
2845
|
-
return () => remove(this._beforeChangeHandlers[typeName], handler);
|
|
2891
|
+
return this.addHandler(this._beforeChangeHandlers, typeName, handler);
|
|
2846
2892
|
}
|
|
2847
2893
|
/**
|
|
2848
2894
|
* Register a handler to be called after a record is changed. This is useful for side-effects
|
|
@@ -2866,10 +2912,7 @@ var StoreSideEffects = class {
|
|
|
2866
2912
|
* @returns A callback that removes the handler.
|
|
2867
2913
|
*/
|
|
2868
2914
|
registerAfterChangeHandler(typeName, handler) {
|
|
2869
|
-
|
|
2870
|
-
if (!handlers) this._afterChangeHandlers[typeName] = [];
|
|
2871
|
-
this._afterChangeHandlers[typeName].push(handler);
|
|
2872
|
-
return () => remove(this._afterChangeHandlers[typeName], handler);
|
|
2915
|
+
return this.addHandler(this._afterChangeHandlers, typeName, handler);
|
|
2873
2916
|
}
|
|
2874
2917
|
/**
|
|
2875
2918
|
* Register a handler to be called before a record is deleted. The handler can return `false` to
|
|
@@ -2895,10 +2938,7 @@ var StoreSideEffects = class {
|
|
|
2895
2938
|
* @returns A callback that removes the handler.
|
|
2896
2939
|
*/
|
|
2897
2940
|
registerBeforeDeleteHandler(typeName, handler) {
|
|
2898
|
-
|
|
2899
|
-
if (!handlers) this._beforeDeleteHandlers[typeName] = [];
|
|
2900
|
-
this._beforeDeleteHandlers[typeName].push(handler);
|
|
2901
|
-
return () => remove(this._beforeDeleteHandlers[typeName], handler);
|
|
2941
|
+
return this.addHandler(this._beforeDeleteHandlers, typeName, handler);
|
|
2902
2942
|
}
|
|
2903
2943
|
/**
|
|
2904
2944
|
* Register a handler to be called after a record is deleted. This is useful for side-effects
|
|
@@ -2925,10 +2965,7 @@ var StoreSideEffects = class {
|
|
|
2925
2965
|
* @returns A callback that removes the handler.
|
|
2926
2966
|
*/
|
|
2927
2967
|
registerAfterDeleteHandler(typeName, handler) {
|
|
2928
|
-
|
|
2929
|
-
if (!handlers) this._afterDeleteHandlers[typeName] = [];
|
|
2930
|
-
this._afterDeleteHandlers[typeName].push(handler);
|
|
2931
|
-
return () => remove(this._afterDeleteHandlers[typeName], handler);
|
|
2968
|
+
return this.addHandler(this._afterDeleteHandlers, typeName, handler);
|
|
2932
2969
|
}
|
|
2933
2970
|
/**
|
|
2934
2971
|
* Register a handler to be called when a store completes an atomic operation.
|
|
@@ -2957,15 +2994,16 @@ var StoreSideEffects = class {
|
|
|
2957
2994
|
* @public
|
|
2958
2995
|
*/
|
|
2959
2996
|
registerOperationCompleteHandler(handler) {
|
|
2960
|
-
this._operationCompleteHandlers.
|
|
2961
|
-
return () =>
|
|
2997
|
+
this._operationCompleteHandlers = [...this._operationCompleteHandlers, handler];
|
|
2998
|
+
return () => {
|
|
2999
|
+
this._operationCompleteHandlers = withoutFirst(this._operationCompleteHandlers, handler);
|
|
3000
|
+
};
|
|
2962
3001
|
}
|
|
2963
3002
|
};
|
|
2964
|
-
function
|
|
3003
|
+
function withoutFirst(array, item) {
|
|
2965
3004
|
const index = array.indexOf(item);
|
|
2966
|
-
if (index
|
|
2967
|
-
|
|
2968
|
-
}
|
|
3005
|
+
if (index < 0) return array;
|
|
3006
|
+
return [...array.slice(0, index), ...array.slice(index + 1)];
|
|
2969
3007
|
}
|
|
2970
3008
|
|
|
2971
3009
|
// src/lib/Store.ts
|
|
@@ -3031,12 +3069,11 @@ var Store = class {
|
|
|
3031
3069
|
*/
|
|
3032
3070
|
historyReactor;
|
|
3033
3071
|
/**
|
|
3034
|
-
*
|
|
3072
|
+
* Cancels the history flush scheduled for the next frame, if any.
|
|
3035
3073
|
*
|
|
3036
3074
|
* @internal
|
|
3037
3075
|
*/
|
|
3038
|
-
cancelHistoryReactor
|
|
3039
|
-
}
|
|
3076
|
+
cancelHistoryReactor = null;
|
|
3040
3077
|
/**
|
|
3041
3078
|
* The schema that defines the structure and validation rules for records in this store.
|
|
3042
3079
|
*
|
|
@@ -3109,52 +3146,51 @@ var Store = class {
|
|
|
3109
3146
|
},
|
|
3110
3147
|
{ scheduleEffect: (cb) => this.cancelHistoryReactor = throttleToNextFrame(cb) }
|
|
3111
3148
|
);
|
|
3112
|
-
|
|
3113
|
-
document: new Set(
|
|
3114
|
-
|
|
3115
|
-
)
|
|
3116
|
-
session: new Set(
|
|
3117
|
-
objectMapValues(this.schema.types).filter((t) => t.scope === "session").map((t) => t.typeName)
|
|
3118
|
-
),
|
|
3119
|
-
presence: new Set(
|
|
3120
|
-
objectMapValues(this.schema.types).filter((t) => t.scope === "presence").map((t) => t.typeName)
|
|
3121
|
-
)
|
|
3149
|
+
const scopedTypes = {
|
|
3150
|
+
document: /* @__PURE__ */ new Set(),
|
|
3151
|
+
session: /* @__PURE__ */ new Set(),
|
|
3152
|
+
presence: /* @__PURE__ */ new Set()
|
|
3122
3153
|
};
|
|
3154
|
+
for (const type of objectMapValues(this.schema.types)) {
|
|
3155
|
+
scopedTypes[type.scope].add(type.typeName);
|
|
3156
|
+
}
|
|
3157
|
+
this.scopedTypes = scopedTypes;
|
|
3123
3158
|
}
|
|
3124
3159
|
_flushHistory() {
|
|
3125
3160
|
if (this.historyAccumulator.hasChanges()) {
|
|
3126
3161
|
const entries = this.historyAccumulator.flush();
|
|
3162
|
+
const errors = [];
|
|
3127
3163
|
for (const { changes, source } of entries) {
|
|
3128
|
-
|
|
3129
|
-
let documentChanges = null;
|
|
3130
|
-
let presenceChanges = null;
|
|
3164
|
+
const scopedChanges = /* @__PURE__ */ new Map();
|
|
3131
3165
|
for (const { onHistory, filters } of this.listeners) {
|
|
3132
3166
|
if (filters.source !== "all" && filters.source !== source) {
|
|
3133
3167
|
continue;
|
|
3134
3168
|
}
|
|
3169
|
+
let listenerChanges = changes;
|
|
3135
3170
|
if (filters.scope !== "all") {
|
|
3136
|
-
if (filters.scope
|
|
3137
|
-
|
|
3138
|
-
if (!documentChanges) continue;
|
|
3139
|
-
onHistory({ changes: documentChanges, source });
|
|
3140
|
-
} else if (filters.scope === "session") {
|
|
3141
|
-
instanceChanges ??= this.filterChangesByScope(changes, "session");
|
|
3142
|
-
if (!instanceChanges) continue;
|
|
3143
|
-
onHistory({ changes: instanceChanges, source });
|
|
3144
|
-
} else {
|
|
3145
|
-
presenceChanges ??= this.filterChangesByScope(changes, "presence");
|
|
3146
|
-
if (!presenceChanges) continue;
|
|
3147
|
-
onHistory({ changes: presenceChanges, source });
|
|
3171
|
+
if (!scopedChanges.has(filters.scope)) {
|
|
3172
|
+
scopedChanges.set(filters.scope, this.filterChangesByScope(changes, filters.scope));
|
|
3148
3173
|
}
|
|
3149
|
-
|
|
3150
|
-
|
|
3174
|
+
const filtered = scopedChanges.get(filters.scope);
|
|
3175
|
+
if (!filtered) continue;
|
|
3176
|
+
listenerChanges = filtered;
|
|
3177
|
+
}
|
|
3178
|
+
try {
|
|
3179
|
+
onHistory({ changes: listenerChanges, source });
|
|
3180
|
+
} catch (error) {
|
|
3181
|
+
errors.push(error);
|
|
3151
3182
|
}
|
|
3152
3183
|
}
|
|
3153
3184
|
}
|
|
3185
|
+
if (errors.length > 0) throw errors[0];
|
|
3154
3186
|
}
|
|
3155
3187
|
}
|
|
3156
3188
|
dispose() {
|
|
3157
|
-
|
|
3189
|
+
try {
|
|
3190
|
+
this._flushHistory();
|
|
3191
|
+
} finally {
|
|
3192
|
+
this.cancelHistoryReactor?.();
|
|
3193
|
+
}
|
|
3158
3194
|
}
|
|
3159
3195
|
/**
|
|
3160
3196
|
* Filters out non-document changes from a diff. Returns null if there are no changes left.
|
|
@@ -3168,7 +3204,7 @@ var Store = class {
|
|
|
3168
3204
|
updated: filterEntries(change.updated, (_, r) => this.scopedTypes[scope].has(r[1].typeName)),
|
|
3169
3205
|
removed: filterEntries(change.removed, (_, r) => this.scopedTypes[scope].has(r.typeName))
|
|
3170
3206
|
};
|
|
3171
|
-
if (
|
|
3207
|
+
if (isRecordsDiffEmpty(result)) {
|
|
3172
3208
|
return null;
|
|
3173
3209
|
}
|
|
3174
3210
|
return result;
|
|
@@ -3228,7 +3264,7 @@ var Store = class {
|
|
|
3228
3264
|
initialValue
|
|
3229
3265
|
);
|
|
3230
3266
|
if (validated === initialValue) continue;
|
|
3231
|
-
record = devFreeze(
|
|
3267
|
+
record = devFreeze(validated);
|
|
3232
3268
|
this.records.set(record.id, record);
|
|
3233
3269
|
didChange = true;
|
|
3234
3270
|
updates[record.id] = [initialValue, record];
|
|
@@ -3430,7 +3466,7 @@ var Store = class {
|
|
|
3430
3466
|
this.clear();
|
|
3431
3467
|
this.put(Object.values(migrationResult.value));
|
|
3432
3468
|
this.ensureStoreIsUsable();
|
|
3433
|
-
});
|
|
3469
|
+
}, false);
|
|
3434
3470
|
} finally {
|
|
3435
3471
|
this.sideEffects.setIsEnabled(prevSideEffectsEnabled);
|
|
3436
3472
|
}
|
|
@@ -3617,6 +3653,11 @@ var Store = class {
|
|
|
3617
3653
|
if (!changed) changed = { ...existing };
|
|
3618
3654
|
changed[key] = value;
|
|
3619
3655
|
}
|
|
3656
|
+
for (const key of Object.keys(existing)) {
|
|
3657
|
+
if (type.ephemeralKeySet.has(key) || Object.hasOwn(to, key)) continue;
|
|
3658
|
+
if (!changed) changed = { ...existing };
|
|
3659
|
+
delete changed[key];
|
|
3660
|
+
}
|
|
3620
3661
|
if (changed) toPut.push(changed);
|
|
3621
3662
|
} else {
|
|
3622
3663
|
toPut.push(to);
|
|
@@ -3722,9 +3763,8 @@ var Store = class {
|
|
|
3722
3763
|
}
|
|
3723
3764
|
if (!this.pendingAfterEvents) {
|
|
3724
3765
|
this.sideEffects.handleOperationComplete(source);
|
|
3725
|
-
} else {
|
|
3726
|
-
source = "user";
|
|
3727
3766
|
}
|
|
3767
|
+
source = "user";
|
|
3728
3768
|
}
|
|
3729
3769
|
}
|
|
3730
3770
|
_isInAtomicOp = false;
|
|
@@ -3746,7 +3786,7 @@ var Store = class {
|
|
|
3746
3786
|
}
|
|
3747
3787
|
this.pendingAfterEvents = /* @__PURE__ */ new Map();
|
|
3748
3788
|
const prevSideEffectsEnabled = this.sideEffects.isEnabled();
|
|
3749
|
-
this.sideEffects.setIsEnabled(runCallbacks
|
|
3789
|
+
this.sideEffects.setIsEnabled(runCallbacks && prevSideEffectsEnabled);
|
|
3750
3790
|
this._isInAtomicOp = true;
|
|
3751
3791
|
if (isMergingRemoteChanges) {
|
|
3752
3792
|
this.isMergingRemoteChanges = true;
|
|
@@ -3788,7 +3828,8 @@ function squashHistoryEntries(entries) {
|
|
|
3788
3828
|
return devFreeze(
|
|
3789
3829
|
chunked.map((chunk2) => ({
|
|
3790
3830
|
source: chunk2[0].source,
|
|
3791
|
-
|
|
3831
|
+
// a single-entry chunk needs no squashing — skip the O(N) copy of its diff
|
|
3832
|
+
changes: chunk2.length === 1 ? chunk2[0].changes : squashRecordDiffs(chunk2.map((e) => e.changes))
|
|
3792
3833
|
}))
|
|
3793
3834
|
);
|
|
3794
3835
|
}
|
|
@@ -4007,9 +4048,13 @@ var StoreSchema = class _StoreSchema {
|
|
|
4007
4048
|
if (cached) {
|
|
4008
4049
|
return cached;
|
|
4009
4050
|
}
|
|
4051
|
+
const result = this.computeMigrationsSince(persistedSchema);
|
|
4052
|
+
this.migrationCache.set(persistedSchema, result);
|
|
4053
|
+
return result;
|
|
4054
|
+
}
|
|
4055
|
+
computeMigrationsSince(persistedSchema) {
|
|
4010
4056
|
const upgradeResult = upgradeSchema(persistedSchema);
|
|
4011
4057
|
if (!upgradeResult.ok) {
|
|
4012
|
-
this.migrationCache.set(persistedSchema, upgradeResult);
|
|
4013
4058
|
return upgradeResult;
|
|
4014
4059
|
}
|
|
4015
4060
|
const schema = upgradeResult.value;
|
|
@@ -4023,9 +4068,7 @@ var StoreSchema = class _StoreSchema {
|
|
|
4023
4068
|
}
|
|
4024
4069
|
}
|
|
4025
4070
|
if (sequenceIdsToInclude.size === 0) {
|
|
4026
|
-
|
|
4027
|
-
this.migrationCache.set(persistedSchema, result2);
|
|
4028
|
-
return result2;
|
|
4071
|
+
return Result.ok([]);
|
|
4029
4072
|
}
|
|
4030
4073
|
const allMigrationsToInclude = /* @__PURE__ */ new Set();
|
|
4031
4074
|
for (const sequenceId of sequenceIdsToInclude) {
|
|
@@ -4039,19 +4082,13 @@ var StoreSchema = class _StoreSchema {
|
|
|
4039
4082
|
const theirVersionId = `${sequenceId}/${theirVersion}`;
|
|
4040
4083
|
const idx = this.migrations[sequenceId].sequence.findIndex((m) => m.id === theirVersionId);
|
|
4041
4084
|
if (idx === -1) {
|
|
4042
|
-
|
|
4043
|
-
this.migrationCache.set(persistedSchema, result2);
|
|
4044
|
-
return result2;
|
|
4085
|
+
return Result.err("Incompatible schema?");
|
|
4045
4086
|
}
|
|
4046
4087
|
for (const migration of this.migrations[sequenceId].sequence.slice(idx + 1)) {
|
|
4047
4088
|
allMigrationsToInclude.add(migration.id);
|
|
4048
4089
|
}
|
|
4049
4090
|
}
|
|
4050
|
-
|
|
4051
|
-
this.sortedMigrations.filter(({ id }) => allMigrationsToInclude.has(id))
|
|
4052
|
-
);
|
|
4053
|
-
this.migrationCache.set(persistedSchema, result);
|
|
4054
|
-
return result;
|
|
4091
|
+
return Result.ok(this.sortedMigrations.filter(({ id }) => allMigrationsToInclude.has(id)));
|
|
4055
4092
|
}
|
|
4056
4093
|
/**
|
|
4057
4094
|
* Migrates a single persisted record to match the current schema version.
|
|
@@ -4177,11 +4214,15 @@ var StoreSchema = class _StoreSchema {
|
|
|
4177
4214
|
exhaustiveSwitchError(migration);
|
|
4178
4215
|
}
|
|
4179
4216
|
}
|
|
4217
|
+
const idsToDelete = [];
|
|
4180
4218
|
for (const [id, state] of storage.entries()) {
|
|
4181
4219
|
if (this.getType(state.typeName).scope !== "document") {
|
|
4182
|
-
|
|
4220
|
+
idsToDelete.push(id);
|
|
4183
4221
|
}
|
|
4184
4222
|
}
|
|
4223
|
+
for (const id of idsToDelete) {
|
|
4224
|
+
storage.delete(id);
|
|
4225
|
+
}
|
|
4185
4226
|
}
|
|
4186
4227
|
/**
|
|
4187
4228
|
* Migrates an entire store snapshot to match the current schema version.
|
|
@@ -4345,7 +4386,7 @@ var StoreSchema = class _StoreSchema {
|
|
|
4345
4386
|
*/
|
|
4346
4387
|
getType(typeName) {
|
|
4347
4388
|
const type = getOwnProperty(this.types, typeName);
|
|
4348
|
-
assert(type, "record type does not
|
|
4389
|
+
assert(type, "record type does not exist");
|
|
4349
4390
|
return type;
|
|
4350
4391
|
}
|
|
4351
4392
|
};
|
|
@@ -4353,7 +4394,7 @@ var StoreSchema = class _StoreSchema {
|
|
|
4353
4394
|
// src/index.ts
|
|
4354
4395
|
registerDrawLibraryVersion(
|
|
4355
4396
|
"@ibodr/store",
|
|
4356
|
-
"0.2.
|
|
4397
|
+
"0.2.7",
|
|
4357
4398
|
"esm"
|
|
4358
4399
|
);
|
|
4359
4400
|
/*!
|