@sovereignbase/convergent-replicated-list 1.0.4 → 1.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +22 -15
- package/dist/index.cjs +26 -17
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +47 -29
- package/dist/index.d.ts +47 -29
- package/dist/index.js +25 -16
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -7,6 +7,10 @@
|
|
|
7
7
|
|
|
8
8
|
Convergent Replicated List (CR-List), a delta CRDT for an ordered sequence of entries.
|
|
9
9
|
|
|
10
|
+
Read the specification:
|
|
11
|
+
|
|
12
|
+
- https://sovereignbase.dev/convergent-replicated-list
|
|
13
|
+
|
|
10
14
|
## Compatibility
|
|
11
15
|
|
|
12
16
|
- Runtimes: Node >= 20, modern browsers, Bun, Deno, Cloudflare Workers, Edge Runtime.
|
|
@@ -127,8 +131,8 @@ list[0] = 'up'
|
|
|
127
131
|
list.append('dude!')
|
|
128
132
|
list.prepend('What is')
|
|
129
133
|
|
|
130
|
-
const
|
|
131
|
-
const restored = new CRList<string>(JSON.parse(
|
|
134
|
+
const snapshotJson = JSON.stringify(list)
|
|
135
|
+
const restored = new CRList<string>(JSON.parse(snapshotJson))
|
|
132
136
|
|
|
133
137
|
for (const value of list) {
|
|
134
138
|
console.log(value)
|
|
@@ -145,6 +149,11 @@ list.forEach((value, index, target) => {
|
|
|
145
149
|
console.log([...restored]) // ['What is', 'up', 'dude!']
|
|
146
150
|
```
|
|
147
151
|
|
|
152
|
+
This example assumes your list values are JSON-compatible. For general
|
|
153
|
+
`structuredClone`-compatible values such as `Date`, `Map`, or `BigInt`, persist
|
|
154
|
+
snapshots with a structured-clone-capable store or an application-level codec
|
|
155
|
+
instead of plain `JSON.stringify` / `JSON.parse`.
|
|
156
|
+
|
|
148
157
|
Numeric reads, `for...of`, and `forEach()` return detached copies of visible
|
|
149
158
|
values. Mutating those returned values does not mutate the underlying replica
|
|
150
159
|
state.
|
|
@@ -200,17 +209,18 @@ import {
|
|
|
200
209
|
type CRListSnapshot,
|
|
201
210
|
} from '@sovereignbase/convergent-replicated-list'
|
|
202
211
|
|
|
203
|
-
const
|
|
204
|
-
const
|
|
212
|
+
const source = __create<string>()
|
|
213
|
+
const target = __create<string>()
|
|
214
|
+
const local = __update(0, ['hello', 'world'], source, 'after')
|
|
205
215
|
|
|
206
216
|
if (local) {
|
|
207
217
|
const outgoing: CRListDelta<string> = local.delta
|
|
208
|
-
const remoteChange = __merge(
|
|
218
|
+
const remoteChange = __merge(target, outgoing)
|
|
209
219
|
|
|
210
220
|
console.log(remoteChange)
|
|
211
221
|
}
|
|
212
222
|
|
|
213
|
-
const snapshot: CRListSnapshot<string> = __snapshot(
|
|
223
|
+
const snapshot: CRListSnapshot<string> = __snapshot(target)
|
|
214
224
|
console.log(snapshot)
|
|
215
225
|
```
|
|
216
226
|
|
|
@@ -243,10 +253,13 @@ Ingress stays tolerant:
|
|
|
243
253
|
|
|
244
254
|
### Safety and copying semantics
|
|
245
255
|
|
|
246
|
-
- Snapshots are
|
|
247
|
-
- Deltas are
|
|
256
|
+
- Snapshots are detached structured-clone full-state payloads.
|
|
257
|
+
- Deltas are detached structured-clone gossip payloads intended to be forwarded
|
|
258
|
+
as-is.
|
|
248
259
|
- `change` is a minimal index-keyed local patch.
|
|
249
|
-
- `toJSON()` returns a detached
|
|
260
|
+
- `toJSON()` returns a detached structured-clone snapshot.
|
|
261
|
+
- `JSON.stringify()` and `toString()` are only reliable when list values are
|
|
262
|
+
JSON-compatible.
|
|
250
263
|
- Numeric reads, `for...of`, and `forEach()` expose detached copies of visible values rather than mutable references into replica state.
|
|
251
264
|
- `for...of`, `forEach()`, numeric indexing, `append()`, `prepend()`, `remove()`, `merge()`, `snapshot()`, `acknowledge()`, and `garbageCollect()` all operate on the live list projection.
|
|
252
265
|
|
|
@@ -294,12 +307,6 @@ What the current test suite covers:
|
|
|
294
307
|
npm run bench
|
|
295
308
|
```
|
|
296
309
|
|
|
297
|
-
The benchmark runner currently uses:
|
|
298
|
-
|
|
299
|
-
- `LIST_SIZE = 5_000`
|
|
300
|
-
- `RUN_TIMES = 250`
|
|
301
|
-
- output columns: `group`, `scenario`, `n`, `ops`, `ms`, `ms/op`, `ops/sec`
|
|
302
|
-
|
|
303
310
|
Last measured on Node `v22.14.0` (`win32 x64`):
|
|
304
311
|
|
|
305
312
|
| group | scenario | n | ops | ms | ms/op | ops/sec |
|
package/dist/index.cjs
CHANGED
|
@@ -134,9 +134,10 @@ function flattenAndLinkTrustedState(crListReplica) {
|
|
|
134
134
|
crListReplica.size = crListReplica.parentMap.size;
|
|
135
135
|
}
|
|
136
136
|
|
|
137
|
-
// src/.helpers/
|
|
137
|
+
// src/.helpers/transformSnapshotEntryToStateEntry/index.ts
|
|
138
138
|
var _utils = require('@sovereignbase/utils');
|
|
139
|
-
function
|
|
139
|
+
function transformSnapshotEntryToStateEntry(valueEntry, crListReplica) {
|
|
140
|
+
if (valueEntry === null || valueEntry === void 0) return void 0;
|
|
140
141
|
if (!_utils.isUuidV7.call(void 0, valueEntry.uuidv7) || crListReplica.tombstones.has(valueEntry.uuidv7) || crListReplica.parentMap.has(valueEntry.uuidv7) || !_utils.isUuidV7.call(void 0, valueEntry.predecessor) && valueEntry.predecessor !== "\0" && !crListReplica.tombstones.has(valueEntry.predecessor))
|
|
141
142
|
return void 0;
|
|
142
143
|
const [cloned, copiedValue] = _utils.safeStructuredClone.call(void 0, valueEntry.value);
|
|
@@ -235,7 +236,7 @@ function __create(snapshot) {
|
|
|
235
236
|
if (!Object.hasOwn(snapshot, "values") || !Array.isArray(snapshot.values))
|
|
236
237
|
return crListReplica;
|
|
237
238
|
for (const valueEntry of snapshot.values) {
|
|
238
|
-
const linkedListEntry =
|
|
239
|
+
const linkedListEntry = transformSnapshotEntryToStateEntry(
|
|
239
240
|
valueEntry,
|
|
240
241
|
crListReplica
|
|
241
242
|
);
|
|
@@ -468,6 +469,7 @@ function __merge(crListReplica, crListDelta) {
|
|
|
468
469
|
return change;
|
|
469
470
|
}
|
|
470
471
|
for (const valueEntry of crListDelta.values) {
|
|
472
|
+
if (valueEntry === null || valueEntry === void 0) continue;
|
|
471
473
|
const existingEntry = crListReplica.parentMap.get(valueEntry.uuidv7);
|
|
472
474
|
if (existingEntry) {
|
|
473
475
|
if (crListReplica.tombstones.has(valueEntry.uuidv7) || !_utils.isUuidV7.call(void 0, valueEntry.predecessor) && valueEntry.predecessor !== "\0")
|
|
@@ -482,7 +484,7 @@ function __merge(crListReplica, crListDelta) {
|
|
|
482
484
|
void newVals.push(existingEntry);
|
|
483
485
|
continue;
|
|
484
486
|
}
|
|
485
|
-
const linkedListEntry =
|
|
487
|
+
const linkedListEntry = transformSnapshotEntryToStateEntry(
|
|
486
488
|
valueEntry,
|
|
487
489
|
crListReplica
|
|
488
490
|
);
|
|
@@ -523,21 +525,23 @@ function __merge(crListReplica, crListDelta) {
|
|
|
523
525
|
|
|
524
526
|
// src/core/mags/acknowledge/index.ts
|
|
525
527
|
function __acknowledge(crListReplica) {
|
|
526
|
-
let
|
|
528
|
+
let largest = false;
|
|
527
529
|
crListReplica.tombstones.forEach((tombstone) => {
|
|
528
|
-
if (
|
|
530
|
+
if (largest === false || largest < tombstone) largest = tombstone;
|
|
529
531
|
});
|
|
530
|
-
if (typeof
|
|
532
|
+
if (typeof largest === "string") return largest;
|
|
531
533
|
return false;
|
|
532
534
|
}
|
|
533
535
|
|
|
534
536
|
// src/core/mags/garbageCollect/index.ts
|
|
537
|
+
|
|
535
538
|
function __garbageCollect(frontiers, crListReplica) {
|
|
536
539
|
if (!Array.isArray(frontiers)) return;
|
|
537
|
-
|
|
538
|
-
|
|
540
|
+
frontiers.sort();
|
|
541
|
+
const smallest = frontiers.find((frontier) => _utils.isUuidV7.call(void 0, frontier));
|
|
542
|
+
if (typeof smallest !== "string") return;
|
|
539
543
|
crListReplica.tombstones.forEach((tombstone, __, tombstones) => {
|
|
540
|
-
if (tombstone <=
|
|
544
|
+
if (tombstone <= smallest) {
|
|
541
545
|
tombstones.delete(tombstone);
|
|
542
546
|
}
|
|
543
547
|
});
|
|
@@ -563,7 +567,7 @@ function __snapshot(crListReplica) {
|
|
|
563
567
|
// src/CRList/class.ts
|
|
564
568
|
var CRList = class {
|
|
565
569
|
/**
|
|
566
|
-
* Creates a replicated list from an optional
|
|
570
|
+
* Creates a replicated list from an optional detached structured-clone-compatible snapshot.
|
|
567
571
|
*
|
|
568
572
|
* @param snapshot - A previously emitted CRList snapshot.
|
|
569
573
|
*/
|
|
@@ -609,7 +613,8 @@ var CRList = class {
|
|
|
609
613
|
new CustomEvent("change", { detail: change })
|
|
610
614
|
);
|
|
611
615
|
return true;
|
|
612
|
-
} catch (
|
|
616
|
+
} catch (error) {
|
|
617
|
+
if (error instanceof CRListError) throw error;
|
|
613
618
|
return false;
|
|
614
619
|
}
|
|
615
620
|
},
|
|
@@ -631,7 +636,8 @@ var CRList = class {
|
|
|
631
636
|
);
|
|
632
637
|
}
|
|
633
638
|
return true;
|
|
634
|
-
} catch (
|
|
639
|
+
} catch (error) {
|
|
640
|
+
if (error instanceof CRListError) throw error;
|
|
635
641
|
return false;
|
|
636
642
|
}
|
|
637
643
|
},
|
|
@@ -759,7 +765,7 @@ var CRList = class {
|
|
|
759
765
|
void __garbageCollect(frontiers, this.state);
|
|
760
766
|
}
|
|
761
767
|
/**
|
|
762
|
-
* Emits the current
|
|
768
|
+
* Emits the current detached structured-clone-compatible list snapshot.
|
|
763
769
|
*/
|
|
764
770
|
snapshot() {
|
|
765
771
|
const snapshot = __snapshot(this.state);
|
|
@@ -797,7 +803,7 @@ var CRList = class {
|
|
|
797
803
|
);
|
|
798
804
|
}
|
|
799
805
|
/**
|
|
800
|
-
* Returns a
|
|
806
|
+
* Returns a detached structured-clone-compatible snapshot of this list.
|
|
801
807
|
*
|
|
802
808
|
* Called automatically by `JSON.stringify`.
|
|
803
809
|
*/
|
|
@@ -805,7 +811,9 @@ var CRList = class {
|
|
|
805
811
|
return __snapshot(this.state);
|
|
806
812
|
}
|
|
807
813
|
/**
|
|
808
|
-
*
|
|
814
|
+
* Attempts to return this list snapshot as a JSON string.
|
|
815
|
+
*
|
|
816
|
+
* This can fail when list values are not JSON-compatible.
|
|
809
817
|
*/
|
|
810
818
|
toString() {
|
|
811
819
|
return JSON.stringify(this);
|
|
@@ -856,5 +864,6 @@ var CRList = class {
|
|
|
856
864
|
|
|
857
865
|
|
|
858
866
|
|
|
859
|
-
|
|
867
|
+
|
|
868
|
+
exports.CRList = CRList; exports.CRListError = CRListError; exports.__acknowledge = __acknowledge; exports.__create = __create; exports.__delete = __delete; exports.__garbageCollect = __garbageCollect; exports.__merge = __merge; exports.__read = __read; exports.__snapshot = __snapshot; exports.__update = __update;
|
|
860
869
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/home/runner/work/convergent-replicated-list/convergent-replicated-list/dist/index.cjs","../src/.helpers/assertListIndices/index.ts","../src/.errors/class.ts","../src/.helpers/walkToIndex/index.ts","../src/.helpers/insertBetween/index.ts","../src/.helpers/flattenAndLinkTrustedState/index.ts","../src/.helpers/snapshotValueToLinkedListValue/index.ts","../src/.helpers/updateEntryToMaps/index.ts","../src/.helpers/deleteEntryFromMaps/index.ts","../src/.helpers/deleteLinkedEntry/index.ts","../src/.helpers/moveEntryToPredecessor/index.ts","../src/.helpers/indexFromPropertyKey/index.ts","../src/core/crud/create/index.ts","../src/core/crud/read/index.ts","../src/core/crud/update/index.ts","../src/core/crud/delete/index.ts","../src/core/mags/merge/index.ts","../src/core/mags/acknowledge/index.ts","../src/core/mags/garbageCollect/index.ts","../src/core/mags/snapshot/index.ts","../src/CRList/class.ts"],"names":["isUuidV7"],"mappings":"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","file":"/home/runner/work/convergent-replicated-list/convergent-replicated-list/dist/index.cjs","sourcesContent":[null,"import type { CRListState } from '../../.types/index.js'\n\nexport function assertListIndices<T>(crListReplica: CRListState<T>): void {\n if (!crListReplica.cursor) return\n let index = crListReplica.size\n while (crListReplica.cursor.next)\n crListReplica.cursor = crListReplica.cursor.next\n\n while (index >= 1) {\n index--\n crListReplica.cursor.index = index\n if (crListReplica.cursor.prev === undefined) break\n crListReplica.cursor = crListReplica.cursor.prev\n }\n}\n","/**\n * Error codes thrown by {@link CRList}.\n */\nexport type CRListErrorCode =\n | 'VALUE_NOT_CLONEABLE'\n | 'INDEX_OUT_OF_BOUNDS'\n | 'LIST_EMPTY'\n | 'LIST_INTEGRITY_VIOLATION'\n | 'UPDATE_EXPECTED_AN_ARRAY'\n\n/**\n * Represents a typed CRList runtime error.\n */\nexport class CRListError extends Error {\n /**\n * The semantic error code for the failure.\n */\n readonly code: CRListErrorCode\n\n /**\n * Creates a typed CRList error.\n *\n * @param code - The semantic error code.\n * @param message - An optional human-readable detail message.\n */\n constructor(code: CRListErrorCode, message?: string) {\n const detail = message ?? code\n super(`{@sovereignbase/convergent-replicated-list} ${detail}`)\n this.code = code\n this.name = 'CRListError'\n }\n}\n","import type { CRListState } from '../../.types/index.js'\nimport { CRListError } from '../../.errors/class.js'\n\nexport function walkToIndex<T>(\n targetIndex: number,\n crListReplica: CRListState<T>\n): void {\n if (targetIndex < 0 || targetIndex >= crListReplica.size)\n throw new CRListError('INDEX_OUT_OF_BOUNDS', 'Index out of bounds')\n if (!crListReplica.cursor)\n throw new CRListError('LIST_EMPTY', 'List is empty')\n const direction = crListReplica.cursor.index > targetIndex ? 'prev' : 'next'\n while (crListReplica.cursor && crListReplica.cursor.index !== targetIndex) {\n crListReplica.cursor = crListReplica.cursor[direction]\n }\n}\n","import type { CRListStateEntry } from '../../.types/index.js'\n\nexport function insertBetween<T>(\n prev: CRListStateEntry<T>,\n linkedListEntry: NonNullable<CRListStateEntry<T>>,\n next: CRListStateEntry<T>\n): void {\n linkedListEntry.prev = prev\n linkedListEntry.next = next\n if (prev) prev.next = linkedListEntry\n if (next) next.prev = linkedListEntry\n}\n","import type { CRListState, CRListStateEntry } from '../../.types/index.js'\nimport { insertBetween } from '../insertBetween/index.js'\nexport function flattenAndLinkTrustedState<T>(crListReplica: CRListState<T>) {\n crListReplica.cursor = undefined\n const resolvedSiblingPredecessors = new Set<string>()\n for (const entry of crListReplica.parentMap.values()) {\n if (!entry) continue\n entry.prev = undefined\n entry.next = undefined\n }\n const keys = [...crListReplica.childrenMap.keys()].sort((a, b) =>\n a > b ? 1 : -1\n )\n let hasProgress = true\n while (hasProgress) {\n hasProgress = false\n for (const predecessorIdentifier of keys) {\n if (resolvedSiblingPredecessors.has(predecessorIdentifier)) continue\n const siblings = crListReplica.childrenMap.get(predecessorIdentifier)\n if (!siblings) continue\n\n if (siblings.length > 1)\n siblings.sort((a, b) => (a.uuidv7 > b.uuidv7 ? 1 : -1))\n\n const predecessor =\n predecessorIdentifier === '\\0'\n ? undefined\n : crListReplica.parentMap.get(predecessorIdentifier)\n if (\n predecessor &&\n !predecessor.prev &&\n !predecessor.next &&\n crListReplica.cursor !== predecessor\n )\n continue\n let prev: CRListStateEntry<T> = predecessor ?? crListReplica.cursor\n const predecessorNext = predecessor?.next\n if (siblings.length === 1) {\n const sibling = siblings[0]\n insertBetween<T>(prev, sibling, sibling.next)\n prev = sibling\n if (predecessorNext && predecessorNext !== sibling) {\n prev.next = predecessorNext\n predecessorNext.prev = prev\n } else {\n prev.next = undefined\n }\n if (!predecessorNext) crListReplica.cursor = prev\n resolvedSiblingPredecessors.add(predecessorIdentifier)\n hasProgress = true\n continue\n }\n const siblingSet = new Set(siblings)\n for (let index = 0; index < siblings.length; index++) {\n const sibling = siblings[index]\n const next = siblings[index + 1]\n\n insertBetween<T>(prev, sibling, sibling.next)\n prev = sibling\n\n if (next) {\n prev.next = next\n next.prev = prev\n } else if (predecessorNext && !siblingSet.has(predecessorNext)) {\n prev.next = predecessorNext\n predecessorNext.prev = prev\n } else {\n prev.next = undefined\n }\n }\n if (!predecessorNext) crListReplica.cursor = prev\n resolvedSiblingPredecessors.add(predecessorIdentifier)\n hasProgress = true\n }\n }\n crListReplica.size = crListReplica.parentMap.size\n}\n","import type {\n CRListState,\n CRListSnapshotEntry,\n CRListStateEntry,\n} from '../../.types/index.js'\nimport { isUuidV7, safeStructuredClone } from '@sovereignbase/utils'\nexport function snapshotValueToLinkedListValue<T>(\n valueEntry: CRListSnapshotEntry<T>,\n crListReplica: CRListState<T>\n): CRListStateEntry<T> {\n if (\n !isUuidV7(valueEntry.uuidv7) ||\n crListReplica.tombstones.has(valueEntry.uuidv7) ||\n crListReplica.parentMap.has(valueEntry.uuidv7) ||\n (!isUuidV7(valueEntry.predecessor) &&\n valueEntry.predecessor !== '\\0' &&\n !crListReplica.tombstones.has(valueEntry.predecessor))\n )\n return undefined\n\n const [cloned, copiedValue] = safeStructuredClone(valueEntry.value)\n\n if (!cloned) return undefined\n return {\n uuidv7: valueEntry.uuidv7,\n value: copiedValue,\n predecessor: valueEntry.predecessor,\n index: 0,\n next: undefined,\n prev: undefined,\n }\n}\n","import type {\n CRListState,\n CRListStateEntry,\n CRListDelta,\n} from '../../.types/index.js'\nexport function updateEntryToMaps<T>(\n crListReplica: CRListState<T>,\n linkedListEntry: NonNullable<CRListStateEntry<T>>,\n deltaBuf?: CRListDelta<T>\n): void {\n crListReplica.parentMap.set(linkedListEntry.uuidv7, linkedListEntry)\n const siblings = crListReplica.childrenMap.get(linkedListEntry.predecessor)\n if (siblings) {\n siblings.push(linkedListEntry)\n } else {\n crListReplica.childrenMap.set(linkedListEntry.predecessor, [\n linkedListEntry,\n ])\n }\n if (deltaBuf && !Array.isArray(deltaBuf.values)) deltaBuf.values = []\n if (deltaBuf?.values)\n deltaBuf.values.push({\n uuidv7: linkedListEntry.uuidv7,\n value: linkedListEntry.value,\n predecessor: linkedListEntry.predecessor,\n })\n}\n","import type { CRListState, CRListStateEntry } from '../../.types/index.js'\nexport function deleteEntryFromMaps<T>(\n crListReplica: CRListState<T>,\n linkedListEntry: NonNullable<CRListStateEntry<T>>\n): void {\n crListReplica.parentMap.delete(linkedListEntry.uuidv7)\n const siblings = crListReplica.childrenMap.get(linkedListEntry.predecessor)\n if (!siblings) return\n const index = siblings.indexOf(linkedListEntry)\n if (index !== -1) siblings.splice(index, 1)\n}\n","import type {\n CRListDelta,\n CRListState,\n CRListStateEntry,\n} from '../../.types/index.js'\nimport { deleteEntryFromMaps } from '../deleteEntryFromMaps/index.js'\n\nexport function deleteLinkedEntry<T>(\n crListReplica: CRListState<T>,\n linkedListEntry: NonNullable<CRListStateEntry<T>>,\n deltaBuf?: CRListDelta<T>\n): void {\n const prev = linkedListEntry.prev\n const next = linkedListEntry.next\n crListReplica.tombstones.add(linkedListEntry.uuidv7)\n if (deltaBuf && !Array.isArray(deltaBuf.tombstones)) deltaBuf.tombstones = []\n deltaBuf?.tombstones?.push(linkedListEntry.uuidv7)\n if (prev) prev.next = next\n if (next) {\n next.prev = prev\n }\n void deleteEntryFromMaps<T>(crListReplica, linkedListEntry)\n if (crListReplica.cursor === linkedListEntry)\n crListReplica.cursor = next ?? prev\n linkedListEntry.prev = undefined\n linkedListEntry.next = undefined\n crListReplica.size = crListReplica.parentMap.size\n}\n","import type {\n CRListDelta,\n CRListState,\n CRListStateEntry,\n} from '../../.types/index.js'\nimport { deleteEntryFromMaps } from '../deleteEntryFromMaps/index.js'\nimport { updateEntryToMaps } from '../updateEntryToMaps/index.js'\n\nexport function moveEntryToPredecessor<T>(\n crListReplica: CRListState<T>,\n linkedListEntry: NonNullable<CRListStateEntry<T>>,\n predecessor: string,\n deltaBuf?: CRListDelta<T>\n): void {\n void deleteEntryFromMaps<T>(crListReplica, linkedListEntry)\n linkedListEntry.predecessor = predecessor\n void updateEntryToMaps<T>(crListReplica, linkedListEntry, deltaBuf)\n}\n","export function indexFromPropertyKey(\n index: string | symbol\n): number | undefined {\n if (typeof index !== 'string' || !/^(0|[1-9]\\d*)$/.test(index))\n return undefined\n const listIndex = Number(index)\n return Number.isSafeInteger(listIndex) ? listIndex : undefined\n}\n","import { isUuidV7, prototype } from '@sovereignbase/utils'\nimport {\n CRListSnapshot,\n CRListState,\n CRListStateEntry,\n} from '../../../.types/index.js'\nimport {\n flattenAndLinkTrustedState,\n assertListIndices,\n snapshotValueToLinkedListValue,\n updateEntryToMaps,\n} from '../../../.helpers/index.js'\n\n/**\n * Creates a local CRList replica from an optional snapshot.\n *\n * Invalid snapshot records are ignored. Accepted values are cloned, indexed by\n * UUIDv7, linked through their predecessor buckets, and exposed as a live\n * doubly-linked list.\n *\n * @param snapshot Optional serializable CRList state.\n * @returns A hydrated CRList replica.\n *\n * Time complexity: O(n log n + t + c), worst case O(n^2 + t + c)\n * - n = snapshot value entry count\n * - t = snapshot tombstone count\n * - c = cloned value payload\n *\n * Space complexity: O(n + t + c)\n */\nexport function __create<T>(snapshot?: CRListSnapshot<T>): CRListState<T> {\n const crListReplica: CRListState<T> = {\n size: 0,\n cursor: undefined,\n tombstones: new Set<string>(),\n parentMap: new Map<string, NonNullable<CRListStateEntry<T>>>(),\n childrenMap: new Map<string, Array<NonNullable<CRListStateEntry<T>>>>(),\n }\n if (!snapshot || prototype(snapshot) !== 'record') return crListReplica\n\n /** Hydrate tombstone entries. */\n if (\n Object.hasOwn(snapshot, 'tombstones') &&\n Array.isArray(snapshot.tombstones)\n ) {\n for (const tombstone of snapshot.tombstones) {\n if (crListReplica.tombstones.has(tombstone) || !isUuidV7(tombstone))\n continue\n crListReplica.tombstones.add(tombstone)\n }\n }\n\n /** Hydrate value entries. */\n if (!Object.hasOwn(snapshot, 'values') || !Array.isArray(snapshot.values))\n return crListReplica\n // Build predecessor tree.\n for (const valueEntry of snapshot.values) {\n const linkedListEntry = snapshotValueToLinkedListValue<T>(\n valueEntry,\n crListReplica\n )\n if (!linkedListEntry) continue\n void updateEntryToMaps<T>(crListReplica, linkedListEntry)\n }\n // Flatten tree into a doubly linked list.\n void flattenAndLinkTrustedState<T>(crListReplica)\n // Write live-view indexes.\n void assertListIndices<T>(crListReplica)\n\n return crListReplica\n}\n","import { walkToIndex } from '../../../.helpers/index.js'\nimport { CRListState } from '../../../.types/index.js'\n\n/**\n * Reads the value at an index in the replica live view.\n *\n * The replica cursor is moved as part of the lookup. Successful reads return a\n * detached structured clone of the visible value, so mutating the returned\n * value does not mutate the replica itself. Out-of-bounds and empty list reads\n * resolve to `undefined` instead of throwing.\n *\n * @param targetIndex Index in the live list.\n * @param crListReplica Replica to read from.\n * @returns A detached copy of the value at `targetIndex`, or `undefined` when\n * no value is present.\n *\n * Time complexity: O(d), worst case O(n)\n * - d = distance from cursor to target index\n * - n = list size\n *\n * Space complexity: O(1)\n */\nexport function __read<T>(\n targetIndex: number,\n crListReplica: CRListState<T>\n): T | undefined {\n try {\n void walkToIndex<T>(targetIndex, crListReplica)\n return structuredClone(crListReplica?.cursor?.value)\n } catch {\n return undefined\n }\n}\n","import { CRListError } from '../../../.errors/class.js'\nimport { safeStructuredClone } from '@sovereignbase/utils'\nimport {\n updateEntryToMaps,\n deleteEntryFromMaps,\n walkToIndex,\n moveEntryToPredecessor,\n insertBetween,\n} from '../../../.helpers/index.js'\nimport { v7 as uuidv7 } from 'uuid'\nimport {\n CRListChange,\n CRListDelta,\n CRListState,\n CRListStateEntry,\n} from '../../../.types/index.js'\n/**\n * Applies a local value mutation to the replica live view.\n *\n * The update can replace a range starting at the target entry, insert values\n * before it, or insert values after it. The returned delta is suitable for\n * gossip and the returned change describes the local live-view patch.\n *\n * @param listIndex Target index in the live list.\n * @param listValues Values to insert or overwrite.\n * @param crListReplica Replica to mutate.\n * @param mode Mutation mode relative to `listIndex`.\n * @returns A local change and gossip delta, or `false` if no mutation occurred.\n *\n * Time complexity: O(d + v + r + vk + c), worst case O(vn + c)\n * - d = distance from cursor to target index\n * - v = amount of input values\n * - r = amount of nodes after inserted values whose indexes must be shifted\n * - k = sibling bucket size when predecessor bucket is updated\n * - c = cloned value payload size across all input values\n *\n * Space complexity: O(v + c)\n */\nexport function __update<T>(\n listIndex: number,\n listValues: Array<T>,\n crListReplica: CRListState<T>,\n mode: 'overwrite' | 'before' | 'after'\n): { change: CRListChange<T>; delta: CRListDelta<T> } | false {\n if (listIndex < 0 || listIndex > crListReplica.size)\n throw new CRListError('INDEX_OUT_OF_BOUNDS')\n if (!Array.isArray(listValues))\n throw new CRListError(\n 'UPDATE_EXPECTED_AN_ARRAY',\n '`listValues` must be an Array'\n )\n if (listValues.length === 0) return false\n const change: CRListChange<T> = {}\n const delta: CRListDelta<T> = { values: [], tombstones: [] }\n let shiftCursor: CRListStateEntry<T>\n for (const listValue of listValues) {\n const [cloned, copiedValue] = safeStructuredClone(listValue)\n\n if (!cloned) throw new CRListError('VALUE_NOT_CLONEABLE')\n\n const v7 = uuidv7()\n\n const linkedListEntry: NonNullable<CRListStateEntry<T>> = {\n uuidv7: v7,\n value: copiedValue,\n predecessor: '\\0',\n index: 0,\n next: undefined,\n prev: undefined,\n }\n\n switch (mode) {\n case 'overwrite': {\n if (listIndex === crListReplica.size) {\n if (crListReplica.size === 0) {\n crListReplica.cursor = linkedListEntry\n void updateEntryToMaps<T>(crListReplica, linkedListEntry, delta)\n change[linkedListEntry.index] = linkedListEntry.value\n break\n }\n void walkToIndex<T>(crListReplica.size - 1, crListReplica)\n if (!crListReplica.cursor) return false\n linkedListEntry.index = crListReplica.cursor.index + 1\n linkedListEntry.predecessor = crListReplica.cursor.uuidv7\n insertBetween<T>(crListReplica.cursor, linkedListEntry, undefined)\n void updateEntryToMaps<T>(crListReplica, linkedListEntry, delta)\n crListReplica.cursor = linkedListEntry\n change[linkedListEntry.index] = structuredClone(linkedListEntry.value)\n break\n }\n void walkToIndex<T>(listIndex, crListReplica)\n if (!crListReplica.cursor) return false\n const entryToOverwrite = crListReplica.cursor\n\n linkedListEntry.predecessor = entryToOverwrite.predecessor\n linkedListEntry.index = entryToOverwrite.index\n insertBetween<T>(\n entryToOverwrite.prev,\n linkedListEntry,\n entryToOverwrite.next\n )\n if (entryToOverwrite.next) {\n if (entryToOverwrite.next.predecessor === entryToOverwrite.uuidv7) {\n void moveEntryToPredecessor<T>(\n crListReplica,\n entryToOverwrite.next,\n linkedListEntry.uuidv7,\n delta\n )\n }\n }\n void updateEntryToMaps<T>(crListReplica, linkedListEntry, delta)\n crListReplica.tombstones.add(entryToOverwrite.uuidv7)\n delta.tombstones?.push(entryToOverwrite.uuidv7)\n void deleteEntryFromMaps<T>(crListReplica, entryToOverwrite)\n entryToOverwrite.next = undefined\n entryToOverwrite.prev = undefined\n crListReplica.cursor = linkedListEntry\n change[linkedListEntry.index] = structuredClone(linkedListEntry.value)\n break\n }\n case 'after': {\n if (crListReplica.size === 0 && listIndex === 0) {\n crListReplica.cursor = linkedListEntry\n void updateEntryToMaps<T>(crListReplica, linkedListEntry, delta)\n change[linkedListEntry.index] = structuredClone(linkedListEntry.value)\n break\n }\n if (listIndex === crListReplica.size) {\n void walkToIndex<T>(crListReplica.size - 1, crListReplica)\n } else {\n void walkToIndex<T>(listIndex, crListReplica)\n }\n if (!crListReplica.cursor) return false\n const next =\n listIndex === crListReplica.size\n ? undefined\n : crListReplica.cursor.next\n shiftCursor = next\n linkedListEntry.index = crListReplica.cursor.index + 1\n linkedListEntry.predecessor = crListReplica.cursor.uuidv7\n insertBetween<T>(crListReplica.cursor, linkedListEntry, next)\n if (next) {\n if (next.predecessor === crListReplica.cursor.uuidv7) {\n void moveEntryToPredecessor<T>(\n crListReplica,\n next,\n linkedListEntry.uuidv7,\n delta\n )\n }\n }\n void updateEntryToMaps<T>(crListReplica, linkedListEntry, delta)\n crListReplica.cursor = linkedListEntry\n change[linkedListEntry.index] = structuredClone(linkedListEntry.value)\n break\n }\n case 'before': {\n if (crListReplica.size === 0 && listIndex === 0) {\n crListReplica.cursor = linkedListEntry\n void updateEntryToMaps<T>(crListReplica, linkedListEntry, delta)\n change[linkedListEntry.index] = structuredClone(linkedListEntry.value)\n mode = 'after'\n listIndex = linkedListEntry.index - 1\n break\n }\n void walkToIndex<T>(listIndex, crListReplica)\n if (!crListReplica.cursor) return false\n const prev = crListReplica.cursor.prev\n shiftCursor = crListReplica.cursor\n linkedListEntry.index = crListReplica.cursor.index\n linkedListEntry.predecessor = prev?.uuidv7 ?? '\\0'\n insertBetween<T>(prev, linkedListEntry, crListReplica.cursor)\n if (crListReplica.cursor.predecessor === linkedListEntry.predecessor) {\n void moveEntryToPredecessor<T>(\n crListReplica,\n crListReplica.cursor,\n linkedListEntry.uuidv7,\n delta\n )\n }\n void updateEntryToMaps<T>(crListReplica, linkedListEntry, delta)\n crListReplica.cursor = linkedListEntry\n change[linkedListEntry.index] = structuredClone(linkedListEntry.value)\n mode = 'after'\n listIndex = linkedListEntry.index - 1\n\n break\n }\n }\n crListReplica.size = crListReplica.parentMap.size\n listIndex++\n }\n if (mode !== 'overwrite')\n while (shiftCursor) {\n shiftCursor.index += listValues.length\n shiftCursor = shiftCursor.next\n }\n return { change, delta }\n}\n","import { deleteLinkedEntry, walkToIndex } from '../../../.helpers/index.js'\nimport { CRListError } from '../../../.errors/class.js'\nimport type {\n CRListChange,\n CRListDelta,\n CRListState,\n CRListStateEntry,\n} from '../../../.types/index.js'\n\n/**\n * Deletes a range from the replica live view.\n *\n * With no indexes, the full list is deleted. With only `startIndex`, all entries\n * from `startIndex` onward are deleted. With both indexes, the deleted range is\n * `[startIndex, endIndex)`.\n *\n * @param crListReplica Replica to mutate.\n * @param startIndex Inclusive start index. Defaults to `0`.\n * @param endIndex Exclusive end index. Defaults to the current list size.\n * @returns A local change and gossip delta, or `false` if nothing was deleted.\n *\n * Time complexity: O(d + qk + r), worst case O(n^2)\n * - d = distance from cursor to target index\n * - q = amount of deleted nodes\n * - r = amount of nodes after the deleted range whose indexes must be shifted\n * - k = sibling bucket size when deleted entries are removed from buckets\n *\n * Space complexity: O(q)\n */\nexport function __delete<T>(\n crListReplica: CRListState<T>,\n startIndex?: number,\n endIndex?: number\n): { change: CRListChange<T>; delta: CRListDelta<T> } | false {\n const change: CRListChange<T> = {}\n const delta: CRListDelta<T> = { values: [], tombstones: [] }\n const listIndex = startIndex ?? 0\n const targetEndIndex = endIndex ?? crListReplica.size\n if (\n listIndex < 0 ||\n targetEndIndex < listIndex ||\n listIndex > crListReplica.size\n )\n throw new CRListError('INDEX_OUT_OF_BOUNDS')\n const deleteCount = Math.min(targetEndIndex, crListReplica.size) - listIndex\n if (deleteCount <= 0) return false\n\n void walkToIndex<T>(listIndex, crListReplica)\n if (!crListReplica.cursor) return false\n\n let current: CRListStateEntry<T> = crListReplica.cursor\n let deleted = 0\n\n while (current && deleted < deleteCount) {\n const next: CRListStateEntry<T> = current.next\n change[current.index] = undefined\n void deleteLinkedEntry<T>(crListReplica, current, delta)\n current = next\n deleted++\n }\n\n crListReplica.size = crListReplica.parentMap.size\n\n while (current) {\n current.index -= deleted\n current = current.next\n }\n\n return { change, delta }\n}\n","import type {\n CRListChange,\n CRListDelta,\n CRListState,\n CRListStateEntry,\n} from '../../../.types/index.js'\nimport {\n snapshotValueToLinkedListValue,\n updateEntryToMaps,\n flattenAndLinkTrustedState,\n assertListIndices,\n deleteLinkedEntry,\n moveEntryToPredecessor,\n} from '../../../.helpers/index.js'\nimport { prototype, isUuidV7 } from '@sovereignbase/utils'\n\n/**\n * Merges a remote CRList delta into the local replica.\n *\n * Accepted tombstones update the local live view and accepted values are attached\n * to the predecessor tree. Tail-append deltas are linked incrementally; deltas\n * that can affect ordering fall back to deterministic relinking.\n *\n * @param crListReplica Replica to mutate.\n * @param crListDelta Remote gossip delta.\n * @returns A minimal local change patch, or `false` when the delta is ignored.\n *\n * Time complexity: O(v + t + c) for tail-append deltas; O(n + t + qk) for tombstone-only deletes; otherwise O(n log n + v + t + m*k + c)\n * Worst case: O(n^2 + (v + t)n + c)\n * - n = replica value entry count after merge\n * - v = delta value entry count\n * - t = delta tombstone count\n * - q = amount of live entries deleted by tombstones\n * - m = entries moved between predecessor buckets\n * - k = sibling bucket size when entries are removed from buckets\n * - c = cloned delta value payload size\n *\n * Space complexity: O(n + v + t + c)\n */\nexport function __merge<T>(\n crListReplica: CRListState<T>,\n crListDelta: CRListDelta<T>\n): CRListChange<T> | false {\n if (!crListDelta || prototype(crListDelta) !== 'record') return false\n const newVals: Array<NonNullable<CRListStateEntry<T>>> = []\n const newTombsIndices: Array<number> = []\n const change: CRListChange<T> = {}\n let needsRelink = false\n\n /** Apply tombstone entries. */\n if (\n Object.hasOwn(crListDelta, 'tombstones') &&\n Array.isArray(crListDelta.tombstones)\n ) {\n for (const tombstone of crListDelta.tombstones) {\n if (crListReplica.tombstones.has(tombstone) || !isUuidV7(tombstone))\n continue\n crListReplica.tombstones.add(tombstone)\n const linkedListEntry = crListReplica.parentMap.get(tombstone)\n if (linkedListEntry) {\n void newTombsIndices.push(linkedListEntry.index)\n void deleteLinkedEntry<T>(crListReplica, linkedListEntry)\n needsRelink = true\n }\n }\n }\n\n /** Apply value entries. */\n if (\n !Object.hasOwn(crListDelta, 'values') ||\n !Array.isArray(crListDelta.values)\n ) {\n if (newTombsIndices.length === 0) return false\n void assertListIndices<T>(crListReplica)\n for (const index of newTombsIndices) {\n change[index] = undefined\n }\n return change\n }\n // Attach accepted values to the predecessor tree.\n for (const valueEntry of crListDelta.values) {\n const existingEntry = crListReplica.parentMap.get(valueEntry.uuidv7)\n if (existingEntry) {\n if (\n crListReplica.tombstones.has(valueEntry.uuidv7) ||\n (!isUuidV7(valueEntry.predecessor) && valueEntry.predecessor !== '\\0')\n )\n continue\n if (existingEntry.predecessor >= valueEntry.predecessor) continue\n void moveEntryToPredecessor<T>(\n crListReplica,\n existingEntry,\n valueEntry.predecessor\n )\n needsRelink = true\n void newVals.push(existingEntry)\n continue\n }\n const linkedListEntry = snapshotValueToLinkedListValue<T>(\n valueEntry,\n crListReplica\n )\n if (!linkedListEntry) continue\n const predecessor =\n linkedListEntry.predecessor === '\\0'\n ? undefined\n : crListReplica.parentMap.get(linkedListEntry.predecessor)\n void updateEntryToMaps<T>(crListReplica, linkedListEntry)\n void newVals.push(linkedListEntry)\n if (!needsRelink && linkedListEntry.predecessor === '\\0') {\n if (crListReplica.size === 0) {\n crListReplica.cursor = linkedListEntry\n crListReplica.size = crListReplica.parentMap.size\n } else {\n needsRelink = true\n }\n } else if (!needsRelink && predecessor && !predecessor.next) {\n linkedListEntry.prev = predecessor\n linkedListEntry.index = predecessor.index + 1\n predecessor.next = linkedListEntry\n crListReplica.cursor = linkedListEntry\n crListReplica.size = crListReplica.parentMap.size\n } else {\n needsRelink = true\n }\n }\n if (needsRelink) {\n // Flatten tree into a doubly linked list.\n void flattenAndLinkTrustedState<T>(crListReplica)\n // Write live-view indexes.\n void assertListIndices<T>(crListReplica)\n }\n\n if (newTombsIndices.length === 0 && newVals.length === 0) return false\n\n for (const index of newTombsIndices) {\n change[index] = undefined\n }\n for (const val of newVals) {\n change[val.index] = structuredClone(val.value)\n }\n\n return change\n}\n","import type { CRListAck, CRListState } from '../../../.types/index.js'\n\n/**\n * Returns the replica tombstone acknowledgement frontier.\n *\n * The frontier is the greatest tombstone identifier currently retained by the\n * replica. Peers can use it as input for tombstone garbage collection.\n *\n * @param crListReplica Replica to acknowledge.\n * @returns The acknowledgement frontier, or `false` when there are no tombstones.\n *\n * Time complexity: O(t)\n * - t = replica tombstone count\n *\n * Space complexity: O(1)\n */\nexport function __acknowledge<T>(\n crListReplica: CRListState<T>\n): CRListAck | false {\n let frontier: CRListAck | false = false\n crListReplica.tombstones.forEach((tombstone) => {\n if (frontier === false || frontier < tombstone) frontier = tombstone\n })\n if (typeof frontier === 'string') return frontier\n return false\n}\n","import { CRListAck, CRListState } from '../../../.types/index.js'\n\n/**\n * Removes tombstones acknowledged by all supplied frontiers.\n *\n * The minimum frontier is used as the safe collection boundary. Tombstones less\n * than or equal to that boundary are removed from the local replica.\n *\n * @param frontiers Acknowledgement frontiers received from peers.\n * @param crListReplica Replica whose tombstones will be collected.\n *\n * Time complexity: O(f log f + t)\n * - f = frontier count\n * - t = replica tombstone count\n *\n * Space complexity: O(1)\n */\nexport function __garbageCollect<T>(\n frontiers: Array<CRListAck>,\n crListReplica: CRListState<T>\n): void {\n if (!Array.isArray(frontiers)) return\n const frontier = frontiers.sort().shift()\n if (typeof frontier !== 'string') return\n crListReplica.tombstones.forEach((tombstone, __, tombstones) => {\n if (tombstone <= frontier) {\n tombstones.delete(tombstone)\n }\n })\n}\n","import { CRListError } from '../../../.errors/class.js'\nimport { CRListState, CRListSnapshot } from '../../../.types/index.js'\n\n/**\n * Creates a full serializable CRList snapshot from the current replica state.\n *\n * The snapshot contains every live value entry and all retained tombstones. Value\n * payloads are cloned so callers cannot mutate the replica through the snapshot.\n *\n * @param crListReplica Replica to snapshot.\n * @returns A full snapshot suitable for hydration or transport.\n *\n * Time complexity: O(n + t + c)\n * - n = replica value entry count\n * - t = replica tombstone count\n * - c = cloned value payload size\n *\n * Space complexity: O(n + t + c)\n */\nexport function __snapshot<T>(\n crListReplica: CRListState<T>\n): CRListSnapshot<T> {\n return {\n values: Array.from(crListReplica.parentMap.values()).map(\n (linkedListEntry) => {\n if (!linkedListEntry) throw new CRListError('LIST_INTEGRITY_VIOLATION')\n return {\n uuidv7: linkedListEntry.uuidv7,\n value: structuredClone(linkedListEntry.value),\n predecessor: linkedListEntry.predecessor,\n }\n }\n ),\n tombstones: Array.from(crListReplica.tombstones),\n }\n}\n","import { indexFromPropertyKey } from '../.helpers/index.js'\nimport type {\n CRListState,\n CRListSnapshot,\n CRListEventListenerFor,\n CRListEventMap,\n CRListDelta,\n CRListAck,\n} from '../.types/index.js'\nimport { __create, __read, __update, __delete } from '../core/crud/index.js'\nimport {\n __merge,\n __acknowledge,\n __garbageCollect,\n __snapshot,\n} from '../core/mags/index.js'\n\n/**\n * A convergent replicated list.\n *\n * Numeric property access reads and mutates the live list projection:\n * `list[0]` reads a detached copy of an entry, `list[0] = value` writes an\n * entry, and `delete list[0]` removes one entry. Iteration and `forEach()`\n * likewise expose detached copies rather than mutable references into the\n * replica state. Local mutations emit `delta` and `change` events; remote\n * merges emit `change` events.\n *\n * @typeParam T - The value type stored in the list.\n */\nexport class CRList<T> {\n /**\n * Reads or overwrites an entry in the live list projection by index.\n *\n * Reads return detached copies.\n */\n [index: number]: T\n declare private readonly state: CRListState<T>\n declare private readonly eventTarget: EventTarget\n\n /**\n * Creates a replicated list from an optional serializable snapshot.\n *\n * @param snapshot - A previously emitted CRList snapshot.\n */\n constructor(snapshot?: CRListSnapshot<T>) {\n Object.defineProperties(this, {\n state: {\n value: __create<T>(snapshot),\n enumerable: false,\n configurable: false,\n writable: false,\n },\n eventTarget: {\n value: new EventTarget(),\n enumerable: false,\n configurable: false,\n writable: false,\n },\n })\n\n return new Proxy(this, {\n get(target, index, receiver) {\n const listIndex = indexFromPropertyKey(index)\n // Preserve normal property access for non-index keys.\n if (listIndex === undefined) return Reflect.get(target, index, receiver)\n return __read(listIndex, target.state)\n },\n has(target, index) {\n const listIndex = indexFromPropertyKey(index)\n // Preserve normal property checks for non-index keys.\n if (listIndex === undefined) return Reflect.has(target, index)\n return listIndex >= 0 && listIndex < target.state.size\n },\n set(target, index, value) {\n const listIndex = indexFromPropertyKey(index)\n if (listIndex === undefined) return false\n try {\n const result = __update(listIndex, [value], target.state, 'overwrite')\n if (!result) return false\n const { delta, change } = result\n if (delta)\n void target.eventTarget.dispatchEvent(\n new CustomEvent('delta', { detail: delta })\n )\n if (change)\n void target.eventTarget.dispatchEvent(\n new CustomEvent('change', { detail: change })\n )\n return true\n } catch {\n return false\n }\n },\n deleteProperty(target, index) {\n const listIndex = indexFromPropertyKey(index)\n if (listIndex === undefined) return false\n try {\n const result = __delete(target.state, listIndex, listIndex + 1)\n if (!result) return false\n const { delta, change } = result\n if (delta) {\n void target.eventTarget.dispatchEvent(\n new CustomEvent('delta', { detail: delta })\n )\n }\n if (change) {\n void target.eventTarget.dispatchEvent(\n new CustomEvent('change', { detail: change })\n )\n }\n return true\n } catch {\n return false\n }\n },\n ownKeys(target) {\n return [\n ...Reflect.ownKeys(target),\n ...Array.from({ length: target.size }, (_, index) => String(index)),\n ]\n },\n\n getOwnPropertyDescriptor(target, index) {\n const listIndex = indexFromPropertyKey(index)\n\n if (listIndex !== undefined && listIndex < target.size) {\n return {\n value: __read(listIndex, target.state),\n writable: true,\n enumerable: true,\n configurable: true,\n }\n }\n // Preserve normal property checks for non-index keys.\n return Reflect.getOwnPropertyDescriptor(target, index)\n },\n })\n }\n /**\n * The current number of live entries.\n */\n get size(): number {\n return this.state.size\n }\n /**\n * Inserts a value before an index.\n *\n * If `beforeIndex` is omitted, the value is inserted at the start of the list.\n *\n * @param value - The value to insert.\n * @param beforeIndex - The index to insert before.\n */\n prepend(value: T, beforeIndex?: number): void {\n const result = __update<T>(beforeIndex ?? 0, [value], this.state, 'before')\n if (!result) return\n const { delta, change } = result\n if (delta)\n void this.eventTarget.dispatchEvent(\n new CustomEvent('delta', { detail: delta })\n )\n if (change)\n void this.eventTarget.dispatchEvent(\n new CustomEvent('change', { detail: change })\n )\n }\n /**\n * Inserts a value after an index.\n *\n * If `afterIndex` is omitted, the value is appended at the end of the list.\n *\n * @param value - The value to insert.\n * @param afterIndex - The index to insert after.\n */\n append(value: T, afterIndex?: number): void {\n const result = __update<T>(\n afterIndex ?? this.state.size,\n [value],\n this.state,\n 'after'\n )\n if (!result) return\n const { delta, change } = result\n if (delta)\n void this.eventTarget.dispatchEvent(\n new CustomEvent('delta', { detail: delta })\n )\n if (change)\n void this.eventTarget.dispatchEvent(\n new CustomEvent('change', { detail: change })\n )\n }\n /**\n * Removes the entry at an index.\n *\n * @param index - The index to remove.\n */\n remove(index: number): void {\n const result = __delete(this.state, index, index + 1)\n if (!result) return\n const { delta, change } = result\n if (delta)\n void this.eventTarget.dispatchEvent(\n new CustomEvent('delta', { detail: delta })\n )\n if (change)\n void this.eventTarget.dispatchEvent(\n new CustomEvent('change', { detail: change })\n )\n }\n /**\n * Applies a remote gossip delta to this list.\n *\n * Emits a `change` event when the merge changes the live projection.\n *\n * @param delta - The remote CRList delta to merge.\n */\n merge(delta: CRListDelta<T>): void {\n const change = __merge(this.state, delta)\n if (change)\n void this.eventTarget.dispatchEvent(\n new CustomEvent('change', { detail: change })\n )\n }\n /**\n * Emits an acknowledgement frontier for currently retained tombstones.\n */\n acknowledge(): void {\n const ack = __acknowledge(this.state)\n if (ack)\n void this.eventTarget.dispatchEvent(\n new CustomEvent('ack', { detail: ack })\n )\n }\n /**\n * Garbage-collects tombstones that are covered by acknowledgement frontiers.\n *\n * @param frontiers - Replica acknowledgement frontiers.\n */\n garbageCollect(frontiers: Array<CRListAck>): void {\n void __garbageCollect(frontiers, this.state)\n }\n /**\n * Emits the current serializable list snapshot.\n */\n snapshot(): void {\n const snapshot = __snapshot<T>(this.state)\n if (snapshot)\n void this.eventTarget.dispatchEvent(\n new CustomEvent('snapshot', { detail: snapshot })\n )\n }\n /**\n * Registers an event listener.\n *\n * @param type - The event type to listen for.\n * @param listener - The listener to register.\n * @param options - Listener registration options.\n */\n addEventListener<K extends keyof CRListEventMap<T>>(\n type: K,\n listener: CRListEventListenerFor<T, K> | null,\n options?: boolean | AddEventListenerOptions\n ): void {\n this.eventTarget.addEventListener(\n type,\n listener as EventListenerOrEventListenerObject | null,\n options\n )\n }\n\n /**\n * Removes an event listener.\n *\n * @param type - The event type to stop listening for.\n * @param listener - The listener to remove.\n * @param options - Listener removal options.\n */\n removeEventListener<K extends keyof CRListEventMap<T>>(\n type: K,\n listener: CRListEventListenerFor<T, K> | null,\n options?: boolean | EventListenerOptions\n ): void {\n this.eventTarget.removeEventListener(\n type,\n listener as EventListenerOrEventListenerObject | null,\n options\n )\n }\n /**\n * Returns a serializable snapshot representation of this list.\n *\n * Called automatically by `JSON.stringify`.\n */\n toJSON(): CRListSnapshot<T> {\n return __snapshot<T>(this.state)\n }\n /**\n * Returns this list as a JSON string.\n */\n toString(): string {\n return JSON.stringify(this)\n }\n /**\n * Returns the Node.js console inspection representation.\n */\n [Symbol.for('nodejs.util.inspect.custom')](): CRListSnapshot<T> {\n return this.toJSON()\n }\n /**\n * Returns the Deno console inspection representation.\n */\n [Symbol.for('Deno.customInspect')](): CRListSnapshot<T> {\n return this.toJSON()\n }\n /**\n * Iterates over detached copies of the current live values in index order.\n */\n *[Symbol.iterator](): IterableIterator<T> {\n for (let index = 0; index < this.size; index++) {\n const value = this[index]\n yield value\n }\n }\n /**\n * Calls a function once for each live value copy in index order.\n *\n * Callback values are detached copies, so mutating them does not mutate the\n * list.\n *\n * @param callback - Function to call for each value copy.\n * @param thisArg - Optional `this` value for the callback.\n */\n forEach(\n callback: (value: T, index: number, list: this) => void,\n thisArg?: unknown\n ): void {\n for (let index = 0; index < this.size; index++) {\n callback.call(thisArg, this[index], index, this)\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["/home/runner/work/convergent-replicated-list/convergent-replicated-list/dist/index.cjs","../src/.helpers/assertListIndices/index.ts","../src/.errors/class.ts","../src/.helpers/walkToIndex/index.ts","../src/.helpers/insertBetween/index.ts","../src/.helpers/flattenAndLinkTrustedState/index.ts","../src/.helpers/transformSnapshotEntryToStateEntry/index.ts","../src/.helpers/updateEntryToMaps/index.ts","../src/.helpers/deleteEntryFromMaps/index.ts","../src/.helpers/deleteLinkedEntry/index.ts","../src/.helpers/moveEntryToPredecessor/index.ts","../src/.helpers/indexFromPropertyKey/index.ts","../src/core/crud/create/index.ts","../src/core/crud/read/index.ts","../src/core/crud/update/index.ts","../src/core/crud/delete/index.ts","../src/core/mags/merge/index.ts","../src/core/mags/acknowledge/index.ts","../src/core/mags/garbageCollect/index.ts","../src/core/mags/snapshot/index.ts","../src/CRList/class.ts"],"names":["isUuidV7"],"mappings":"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","file":"/home/runner/work/convergent-replicated-list/convergent-replicated-list/dist/index.cjs","sourcesContent":[null,"import type { CRListState } from '../../.types/index.js'\n\nexport function assertListIndices<T>(crListReplica: CRListState<T>): void {\n if (!crListReplica.cursor) return\n let index = crListReplica.size\n while (crListReplica.cursor.next)\n crListReplica.cursor = crListReplica.cursor.next\n\n while (index >= 1) {\n index--\n crListReplica.cursor.index = index\n if (crListReplica.cursor.prev === undefined) break\n crListReplica.cursor = crListReplica.cursor.prev\n }\n}\n","/**\n * Error codes thrown by {@link CRList}.\n */\nexport type CRListErrorCode =\n | 'VALUE_NOT_CLONEABLE'\n | 'INDEX_OUT_OF_BOUNDS'\n | 'LIST_EMPTY'\n | 'LIST_INTEGRITY_VIOLATION'\n | 'UPDATE_EXPECTED_AN_ARRAY'\n\n/**\n * Represents a typed CRList runtime error.\n */\nexport class CRListError extends Error {\n /**\n * The semantic error code for the failure.\n */\n readonly code: CRListErrorCode\n\n /**\n * Creates a typed CRList error.\n *\n * @param code - The semantic error code.\n * @param message - An optional human-readable detail message.\n */\n constructor(code: CRListErrorCode, message?: string) {\n const detail = message ?? code\n super(`{@sovereignbase/convergent-replicated-list} ${detail}`)\n this.code = code\n this.name = 'CRListError'\n }\n}\n","import type { CRListState } from '../../.types/index.js'\nimport { CRListError } from '../../.errors/class.js'\n\nexport function walkToIndex<T>(\n targetIndex: number,\n crListReplica: CRListState<T>\n): void {\n if (targetIndex < 0 || targetIndex >= crListReplica.size)\n throw new CRListError('INDEX_OUT_OF_BOUNDS', 'Index out of bounds')\n if (!crListReplica.cursor)\n throw new CRListError('LIST_EMPTY', 'List is empty')\n const direction = crListReplica.cursor.index > targetIndex ? 'prev' : 'next'\n while (crListReplica.cursor && crListReplica.cursor.index !== targetIndex) {\n crListReplica.cursor = crListReplica.cursor[direction]\n }\n}\n","import type { CRListStateEntry } from '../../.types/index.js'\n\nexport function insertBetween<T>(\n prev: CRListStateEntry<T>,\n linkedListEntry: NonNullable<CRListStateEntry<T>>,\n next: CRListStateEntry<T>\n): void {\n linkedListEntry.prev = prev\n linkedListEntry.next = next\n if (prev) prev.next = linkedListEntry\n if (next) next.prev = linkedListEntry\n}\n","import type { CRListState, CRListStateEntry } from '../../.types/index.js'\nimport { insertBetween } from '../insertBetween/index.js'\nexport function flattenAndLinkTrustedState<T>(crListReplica: CRListState<T>) {\n crListReplica.cursor = undefined\n const resolvedSiblingPredecessors = new Set<string>()\n for (const entry of crListReplica.parentMap.values()) {\n if (!entry) continue\n entry.prev = undefined\n entry.next = undefined\n }\n const keys = [...crListReplica.childrenMap.keys()].sort((a, b) =>\n a > b ? 1 : -1\n )\n let hasProgress = true\n while (hasProgress) {\n hasProgress = false\n for (const predecessorIdentifier of keys) {\n if (resolvedSiblingPredecessors.has(predecessorIdentifier)) continue\n const siblings = crListReplica.childrenMap.get(predecessorIdentifier)\n if (!siblings) continue\n\n if (siblings.length > 1)\n siblings.sort((a, b) => (a.uuidv7 > b.uuidv7 ? 1 : -1))\n\n const predecessor =\n predecessorIdentifier === '\\0'\n ? undefined\n : crListReplica.parentMap.get(predecessorIdentifier)\n if (\n predecessor &&\n !predecessor.prev &&\n !predecessor.next &&\n crListReplica.cursor !== predecessor\n )\n continue\n let prev: CRListStateEntry<T> = predecessor ?? crListReplica.cursor\n const predecessorNext = predecessor?.next\n if (siblings.length === 1) {\n const sibling = siblings[0]\n insertBetween<T>(prev, sibling, sibling.next)\n prev = sibling\n if (predecessorNext && predecessorNext !== sibling) {\n prev.next = predecessorNext\n predecessorNext.prev = prev\n } else {\n prev.next = undefined\n }\n if (!predecessorNext) crListReplica.cursor = prev\n resolvedSiblingPredecessors.add(predecessorIdentifier)\n hasProgress = true\n continue\n }\n const siblingSet = new Set(siblings)\n for (let index = 0; index < siblings.length; index++) {\n const sibling = siblings[index]\n const next = siblings[index + 1]\n\n insertBetween<T>(prev, sibling, sibling.next)\n prev = sibling\n\n if (next) {\n prev.next = next\n next.prev = prev\n } else if (predecessorNext && !siblingSet.has(predecessorNext)) {\n prev.next = predecessorNext\n predecessorNext.prev = prev\n } else {\n prev.next = undefined\n }\n }\n if (!predecessorNext) crListReplica.cursor = prev\n resolvedSiblingPredecessors.add(predecessorIdentifier)\n hasProgress = true\n }\n }\n crListReplica.size = crListReplica.parentMap.size\n}\n","import type {\n CRListState,\n CRListSnapshotEntry,\n CRListStateEntry,\n} from '../../.types/index.js'\nimport { isUuidV7, safeStructuredClone } from '@sovereignbase/utils'\nexport function transformSnapshotEntryToStateEntry<T>(\n valueEntry: CRListSnapshotEntry<T>,\n crListReplica: CRListState<T>\n): CRListStateEntry<T> {\n if (valueEntry === null || valueEntry === undefined) return undefined\n if (\n !isUuidV7(valueEntry.uuidv7) ||\n crListReplica.tombstones.has(valueEntry.uuidv7) ||\n crListReplica.parentMap.has(valueEntry.uuidv7) ||\n (!isUuidV7(valueEntry.predecessor) &&\n valueEntry.predecessor !== '\\0' &&\n !crListReplica.tombstones.has(valueEntry.predecessor))\n )\n return undefined\n\n const [cloned, copiedValue] = safeStructuredClone(valueEntry.value)\n\n if (!cloned) return undefined\n return {\n uuidv7: valueEntry.uuidv7,\n value: copiedValue,\n predecessor: valueEntry.predecessor,\n index: 0,\n next: undefined,\n prev: undefined,\n }\n}\n","import type {\n CRListState,\n CRListStateEntry,\n CRListDelta,\n} from '../../.types/index.js'\nexport function updateEntryToMaps<T>(\n crListReplica: CRListState<T>,\n linkedListEntry: NonNullable<CRListStateEntry<T>>,\n deltaBuf?: CRListDelta<T>\n): void {\n crListReplica.parentMap.set(linkedListEntry.uuidv7, linkedListEntry)\n const siblings = crListReplica.childrenMap.get(linkedListEntry.predecessor)\n if (siblings) {\n siblings.push(linkedListEntry)\n } else {\n crListReplica.childrenMap.set(linkedListEntry.predecessor, [\n linkedListEntry,\n ])\n }\n if (deltaBuf && !Array.isArray(deltaBuf.values)) deltaBuf.values = []\n if (deltaBuf?.values)\n deltaBuf.values.push({\n uuidv7: linkedListEntry.uuidv7,\n value: linkedListEntry.value,\n predecessor: linkedListEntry.predecessor,\n })\n}\n","import type { CRListState, CRListStateEntry } from '../../.types/index.js'\nexport function deleteEntryFromMaps<T>(\n crListReplica: CRListState<T>,\n linkedListEntry: NonNullable<CRListStateEntry<T>>\n): void {\n crListReplica.parentMap.delete(linkedListEntry.uuidv7)\n const siblings = crListReplica.childrenMap.get(linkedListEntry.predecessor)\n if (!siblings) return\n const index = siblings.indexOf(linkedListEntry)\n if (index !== -1) siblings.splice(index, 1)\n}\n","import type {\n CRListDelta,\n CRListState,\n CRListStateEntry,\n} from '../../.types/index.js'\nimport { deleteEntryFromMaps } from '../deleteEntryFromMaps/index.js'\n\nexport function deleteLinkedEntry<T>(\n crListReplica: CRListState<T>,\n linkedListEntry: NonNullable<CRListStateEntry<T>>,\n deltaBuf?: CRListDelta<T>\n): void {\n const prev = linkedListEntry.prev\n const next = linkedListEntry.next\n crListReplica.tombstones.add(linkedListEntry.uuidv7)\n if (deltaBuf && !Array.isArray(deltaBuf.tombstones)) deltaBuf.tombstones = []\n deltaBuf?.tombstones?.push(linkedListEntry.uuidv7)\n if (prev) prev.next = next\n if (next) {\n next.prev = prev\n }\n void deleteEntryFromMaps<T>(crListReplica, linkedListEntry)\n if (crListReplica.cursor === linkedListEntry)\n crListReplica.cursor = next ?? prev\n linkedListEntry.prev = undefined\n linkedListEntry.next = undefined\n crListReplica.size = crListReplica.parentMap.size\n}\n","import type {\n CRListDelta,\n CRListState,\n CRListStateEntry,\n} from '../../.types/index.js'\nimport { deleteEntryFromMaps } from '../deleteEntryFromMaps/index.js'\nimport { updateEntryToMaps } from '../updateEntryToMaps/index.js'\n\nexport function moveEntryToPredecessor<T>(\n crListReplica: CRListState<T>,\n linkedListEntry: NonNullable<CRListStateEntry<T>>,\n predecessor: string,\n deltaBuf?: CRListDelta<T>\n): void {\n void deleteEntryFromMaps<T>(crListReplica, linkedListEntry)\n linkedListEntry.predecessor = predecessor\n void updateEntryToMaps<T>(crListReplica, linkedListEntry, deltaBuf)\n}\n","export function indexFromPropertyKey(\n index: string | symbol\n): number | undefined {\n if (typeof index !== 'string' || !/^(0|[1-9]\\d*)$/.test(index))\n return undefined\n const listIndex = Number(index)\n return Number.isSafeInteger(listIndex) ? listIndex : undefined\n}\n","import { isUuidV7, prototype } from '@sovereignbase/utils'\nimport {\n CRListSnapshot,\n CRListState,\n CRListStateEntry,\n} from '../../../.types/index.js'\nimport {\n flattenAndLinkTrustedState,\n assertListIndices,\n transformSnapshotEntryToStateEntry,\n updateEntryToMaps,\n} from '../../../.helpers/index.js'\n\n/**\n * Creates a local CRList replica from an optional snapshot.\n *\n * Invalid snapshot records are ignored. Accepted values are cloned, indexed by\n * UUIDv7, linked through their predecessor buckets, and exposed as a live\n * doubly-linked list.\n *\n * @param snapshot - Optional detached structured-clone-compatible CRList snapshot.\n * @returns - A hydrated CRList replica.\n *\n * Time complexity: O(n log n + t + c), worst case O(n^2 + t + c)\n * - n = snapshot value entry count\n * - t = snapshot tombstone count\n * - c = cloned value payload\n *\n * Space complexity: O(n + t + c)\n */\nexport function __create<T>(snapshot?: CRListSnapshot<T>): CRListState<T> {\n const crListReplica: CRListState<T> = {\n size: 0,\n cursor: undefined,\n tombstones: new Set<string>(),\n parentMap: new Map<string, NonNullable<CRListStateEntry<T>>>(),\n childrenMap: new Map<string, Array<NonNullable<CRListStateEntry<T>>>>(),\n }\n if (!snapshot || prototype(snapshot) !== 'record') return crListReplica\n\n /** Hydrate tombstone entries. */\n if (\n Object.hasOwn(snapshot, 'tombstones') &&\n Array.isArray(snapshot.tombstones)\n ) {\n for (const tombstone of snapshot.tombstones) {\n if (crListReplica.tombstones.has(tombstone) || !isUuidV7(tombstone))\n continue\n crListReplica.tombstones.add(tombstone)\n }\n }\n\n /** Hydrate value entries. */\n if (!Object.hasOwn(snapshot, 'values') || !Array.isArray(snapshot.values))\n return crListReplica\n // Build predecessor tree.\n for (const valueEntry of snapshot.values) {\n const linkedListEntry = transformSnapshotEntryToStateEntry<T>(\n valueEntry,\n crListReplica\n )\n if (!linkedListEntry) continue\n void updateEntryToMaps<T>(crListReplica, linkedListEntry)\n }\n // Flatten tree into a doubly linked list.\n void flattenAndLinkTrustedState<T>(crListReplica)\n // Write live-view indexes.\n void assertListIndices<T>(crListReplica)\n\n return crListReplica\n}\n","import { walkToIndex } from '../../../.helpers/index.js'\nimport { CRListState } from '../../../.types/index.js'\n\n/**\n * Reads the value at an index in the replica live view.\n *\n * The replica cursor is moved as part of the lookup. Successful reads return a\n * detached structured clone of the visible value, so mutating the returned\n * value does not mutate the replica itself. Out-of-bounds and empty list reads\n * resolve to `undefined` instead of throwing.\n *\n * @param targetIndex - Index in the live list.\n * @param crListReplica - Replica to read from.\n * @returns - A detached copy of the value at `targetIndex`, or `undefined` when\n * no value is present.\n *\n * Time complexity: O(d), worst case O(n)\n * - d = distance from cursor to target index\n * - n = list size\n *\n * Space complexity: O(1)\n */\nexport function __read<T>(\n targetIndex: number,\n crListReplica: CRListState<T>\n): T | undefined {\n try {\n void walkToIndex<T>(targetIndex, crListReplica)\n return structuredClone(crListReplica?.cursor?.value)\n } catch {\n return undefined\n }\n}\n","import { CRListError } from '../../../.errors/class.js'\nimport { safeStructuredClone } from '@sovereignbase/utils'\nimport {\n updateEntryToMaps,\n deleteEntryFromMaps,\n walkToIndex,\n moveEntryToPredecessor,\n insertBetween,\n} from '../../../.helpers/index.js'\nimport { v7 as uuidv7 } from 'uuid'\nimport {\n CRListChange,\n CRListDelta,\n CRListState,\n CRListStateEntry,\n} from '../../../.types/index.js'\n/**\n * Applies a local value mutation to the replica live view.\n *\n * The update can replace a range starting at the target entry, insert values\n * before it, or insert values after it. The returned delta is suitable for\n * gossip and the returned change describes the local live-view patch.\n *\n * @param listIndex - Target index in the live list.\n * @param listValues - Values to insert or overwrite.\n * @param crListReplica - Replica to mutate.\n * @param mode - Mutation mode relative to `listIndex`.\n * @returns - A local change and gossip delta, or `false` if no mutation occurred.\n *\n * Time complexity: O(d + v + r + vk + c), worst case O(vn + c)\n * - d = distance from cursor to target index\n * - v = amount of input values\n * - r = amount of nodes after inserted values whose indexes must be shifted\n * - k = sibling bucket size when predecessor bucket is updated\n * - c = cloned value payload size across all input values\n *\n * Space complexity: O(v + c)\n */\nexport function __update<T>(\n listIndex: number,\n listValues: Array<T>,\n crListReplica: CRListState<T>,\n mode: 'overwrite' | 'before' | 'after'\n): { change: CRListChange<T>; delta: CRListDelta<T> } | false {\n if (listIndex < 0 || listIndex > crListReplica.size)\n throw new CRListError('INDEX_OUT_OF_BOUNDS')\n if (!Array.isArray(listValues))\n throw new CRListError(\n 'UPDATE_EXPECTED_AN_ARRAY',\n '`listValues` must be an Array'\n )\n if (listValues.length === 0) return false\n const change: CRListChange<T> = {}\n const delta: CRListDelta<T> = { values: [], tombstones: [] }\n let shiftCursor: CRListStateEntry<T>\n for (const listValue of listValues) {\n const [cloned, copiedValue] = safeStructuredClone(listValue)\n\n if (!cloned) throw new CRListError('VALUE_NOT_CLONEABLE')\n\n const v7 = uuidv7()\n\n const linkedListEntry: NonNullable<CRListStateEntry<T>> = {\n uuidv7: v7,\n value: copiedValue,\n predecessor: '\\0',\n index: 0,\n next: undefined,\n prev: undefined,\n }\n\n switch (mode) {\n case 'overwrite': {\n if (listIndex === crListReplica.size) {\n if (crListReplica.size === 0) {\n crListReplica.cursor = linkedListEntry\n void updateEntryToMaps<T>(crListReplica, linkedListEntry, delta)\n change[linkedListEntry.index] = linkedListEntry.value\n break\n }\n void walkToIndex<T>(crListReplica.size - 1, crListReplica)\n if (!crListReplica.cursor) return false\n linkedListEntry.index = crListReplica.cursor.index + 1\n linkedListEntry.predecessor = crListReplica.cursor.uuidv7\n insertBetween<T>(crListReplica.cursor, linkedListEntry, undefined)\n void updateEntryToMaps<T>(crListReplica, linkedListEntry, delta)\n crListReplica.cursor = linkedListEntry\n change[linkedListEntry.index] = structuredClone(linkedListEntry.value)\n break\n }\n void walkToIndex<T>(listIndex, crListReplica)\n if (!crListReplica.cursor) return false\n const entryToOverwrite = crListReplica.cursor\n\n linkedListEntry.predecessor = entryToOverwrite.predecessor\n linkedListEntry.index = entryToOverwrite.index\n insertBetween<T>(\n entryToOverwrite.prev,\n linkedListEntry,\n entryToOverwrite.next\n )\n if (entryToOverwrite.next) {\n if (entryToOverwrite.next.predecessor === entryToOverwrite.uuidv7) {\n void moveEntryToPredecessor<T>(\n crListReplica,\n entryToOverwrite.next,\n linkedListEntry.uuidv7,\n delta\n )\n }\n }\n void updateEntryToMaps<T>(crListReplica, linkedListEntry, delta)\n crListReplica.tombstones.add(entryToOverwrite.uuidv7)\n delta.tombstones?.push(entryToOverwrite.uuidv7)\n void deleteEntryFromMaps<T>(crListReplica, entryToOverwrite)\n entryToOverwrite.next = undefined\n entryToOverwrite.prev = undefined\n crListReplica.cursor = linkedListEntry\n change[linkedListEntry.index] = structuredClone(linkedListEntry.value)\n break\n }\n case 'after': {\n if (crListReplica.size === 0 && listIndex === 0) {\n crListReplica.cursor = linkedListEntry\n void updateEntryToMaps<T>(crListReplica, linkedListEntry, delta)\n change[linkedListEntry.index] = structuredClone(linkedListEntry.value)\n break\n }\n if (listIndex === crListReplica.size) {\n void walkToIndex<T>(crListReplica.size - 1, crListReplica)\n } else {\n void walkToIndex<T>(listIndex, crListReplica)\n }\n if (!crListReplica.cursor) return false\n const next =\n listIndex === crListReplica.size\n ? undefined\n : crListReplica.cursor.next\n shiftCursor = next\n linkedListEntry.index = crListReplica.cursor.index + 1\n linkedListEntry.predecessor = crListReplica.cursor.uuidv7\n insertBetween<T>(crListReplica.cursor, linkedListEntry, next)\n if (next) {\n if (next.predecessor === crListReplica.cursor.uuidv7) {\n void moveEntryToPredecessor<T>(\n crListReplica,\n next,\n linkedListEntry.uuidv7,\n delta\n )\n }\n }\n void updateEntryToMaps<T>(crListReplica, linkedListEntry, delta)\n crListReplica.cursor = linkedListEntry\n change[linkedListEntry.index] = structuredClone(linkedListEntry.value)\n break\n }\n case 'before': {\n if (crListReplica.size === 0 && listIndex === 0) {\n crListReplica.cursor = linkedListEntry\n void updateEntryToMaps<T>(crListReplica, linkedListEntry, delta)\n change[linkedListEntry.index] = structuredClone(linkedListEntry.value)\n mode = 'after'\n listIndex = linkedListEntry.index - 1\n break\n }\n void walkToIndex<T>(listIndex, crListReplica)\n if (!crListReplica.cursor) return false\n const prev = crListReplica.cursor.prev\n shiftCursor = crListReplica.cursor\n linkedListEntry.index = crListReplica.cursor.index\n linkedListEntry.predecessor = prev?.uuidv7 ?? '\\0'\n insertBetween<T>(prev, linkedListEntry, crListReplica.cursor)\n if (crListReplica.cursor.predecessor === linkedListEntry.predecessor) {\n void moveEntryToPredecessor<T>(\n crListReplica,\n crListReplica.cursor,\n linkedListEntry.uuidv7,\n delta\n )\n }\n void updateEntryToMaps<T>(crListReplica, linkedListEntry, delta)\n crListReplica.cursor = linkedListEntry\n change[linkedListEntry.index] = structuredClone(linkedListEntry.value)\n mode = 'after'\n listIndex = linkedListEntry.index - 1\n\n break\n }\n }\n crListReplica.size = crListReplica.parentMap.size\n listIndex++\n }\n if (mode !== 'overwrite')\n while (shiftCursor) {\n shiftCursor.index += listValues.length\n shiftCursor = shiftCursor.next\n }\n return { change, delta }\n}\n","import { deleteLinkedEntry, walkToIndex } from '../../../.helpers/index.js'\nimport { CRListError } from '../../../.errors/class.js'\nimport type {\n CRListChange,\n CRListDelta,\n CRListState,\n CRListStateEntry,\n} from '../../../.types/index.js'\n\n/**\n * Deletes a range from the replica live view.\n *\n * With no indexes, the full list is deleted. With only `startIndex`, all entries\n * from `startIndex` onward are deleted. With both indexes, the deleted range is\n * `[startIndex, endIndex)`.\n *\n * @param crListReplica - Replica to mutate.\n * @param startIndex - Inclusive start index. Defaults to `0`.\n * @param endIndex - Exclusive end index. Defaults to the current list size.\n * @returns - A local change and gossip delta, or `false` if nothing was deleted.\n *\n * Time complexity: O(d + qk + r), worst case O(n^2)\n * - d = distance from cursor to target index\n * - q = amount of deleted nodes\n * - r = amount of nodes after the deleted range whose indexes must be shifted\n * - k = sibling bucket size when deleted entries are removed from buckets\n *\n * Space complexity: O(q)\n */\nexport function __delete<T>(\n crListReplica: CRListState<T>,\n startIndex?: number,\n endIndex?: number\n): { change: CRListChange<T>; delta: CRListDelta<T> } | false {\n const change: CRListChange<T> = {}\n const delta: CRListDelta<T> = { values: [], tombstones: [] }\n const listIndex = startIndex ?? 0\n const targetEndIndex = endIndex ?? crListReplica.size\n if (\n listIndex < 0 ||\n targetEndIndex < listIndex ||\n listIndex > crListReplica.size\n )\n throw new CRListError('INDEX_OUT_OF_BOUNDS')\n const deleteCount = Math.min(targetEndIndex, crListReplica.size) - listIndex\n if (deleteCount <= 0) return false\n\n void walkToIndex<T>(listIndex, crListReplica)\n if (!crListReplica.cursor) return false\n\n let current: CRListStateEntry<T> = crListReplica.cursor\n let deleted = 0\n\n while (current && deleted < deleteCount) {\n const next: CRListStateEntry<T> = current.next\n change[current.index] = undefined\n void deleteLinkedEntry<T>(crListReplica, current, delta)\n current = next\n deleted++\n }\n\n crListReplica.size = crListReplica.parentMap.size\n\n while (current) {\n current.index -= deleted\n current = current.next\n }\n\n return { change, delta }\n}\n","import type {\n CRListChange,\n CRListDelta,\n CRListState,\n CRListStateEntry,\n} from '../../../.types/index.js'\nimport {\n transformSnapshotEntryToStateEntry,\n updateEntryToMaps,\n flattenAndLinkTrustedState,\n assertListIndices,\n deleteLinkedEntry,\n moveEntryToPredecessor,\n} from '../../../.helpers/index.js'\nimport { prototype, isUuidV7 } from '@sovereignbase/utils'\n\n/**\n * Merges a remote CRList delta into the local replica.\n *\n * Accepted tombstones update the local live view and accepted values are attached\n * to the predecessor tree. Tail-append deltas are linked incrementally; deltas\n * that can affect ordering fall back to deterministic relinking.\n *\n * @param crListReplica - Replica to mutate.\n * @param crListDelta - Remote gossip delta.\n * @returns - A minimal local change patch, or `false` when the delta is ignored.\n *\n * Time complexity: O(v + t + c) for tail-append deltas; O(n + t + qk) for tombstone-only deletes; otherwise O(n log n + v + t + m*k + c)\n * Worst case: O(n^2 + (v + t)n + c)\n * - n = replica value entry count after merge\n * - v = delta value entry count\n * - t = delta tombstone count\n * - q = amount of live entries deleted by tombstones\n * - m = entries moved between predecessor buckets\n * - k = sibling bucket size when entries are removed from buckets\n * - c = cloned delta value payload size\n *\n * Space complexity: O(n + v + t + c)\n */\nexport function __merge<T>(\n crListReplica: CRListState<T>,\n crListDelta: CRListDelta<T>\n): CRListChange<T> | false {\n if (!crListDelta || prototype(crListDelta) !== 'record') return false\n const newVals: Array<NonNullable<CRListStateEntry<T>>> = []\n const newTombsIndices: Array<number> = []\n const change: CRListChange<T> = {}\n let needsRelink = false\n\n /** Apply tombstone entries. */\n if (\n Object.hasOwn(crListDelta, 'tombstones') &&\n Array.isArray(crListDelta.tombstones)\n ) {\n for (const tombstone of crListDelta.tombstones) {\n if (crListReplica.tombstones.has(tombstone) || !isUuidV7(tombstone))\n continue\n crListReplica.tombstones.add(tombstone)\n const linkedListEntry = crListReplica.parentMap.get(tombstone)\n if (linkedListEntry) {\n void newTombsIndices.push(linkedListEntry.index)\n void deleteLinkedEntry<T>(crListReplica, linkedListEntry)\n needsRelink = true\n }\n }\n }\n\n /** Apply value entries. */\n if (\n !Object.hasOwn(crListDelta, 'values') ||\n !Array.isArray(crListDelta.values)\n ) {\n if (newTombsIndices.length === 0) return false\n void assertListIndices<T>(crListReplica)\n for (const index of newTombsIndices) {\n change[index] = undefined\n }\n return change\n }\n // Attach accepted values to the predecessor tree.\n for (const valueEntry of crListDelta.values) {\n if (valueEntry === null || valueEntry === undefined) continue\n const existingEntry = crListReplica.parentMap.get(valueEntry.uuidv7)\n if (existingEntry) {\n if (\n crListReplica.tombstones.has(valueEntry.uuidv7) ||\n (!isUuidV7(valueEntry.predecessor) && valueEntry.predecessor !== '\\0')\n )\n continue\n if (existingEntry.predecessor >= valueEntry.predecessor) continue\n void moveEntryToPredecessor<T>(\n crListReplica,\n existingEntry,\n valueEntry.predecessor\n )\n needsRelink = true\n void newVals.push(existingEntry)\n continue\n }\n const linkedListEntry = transformSnapshotEntryToStateEntry<T>(\n valueEntry,\n crListReplica\n )\n if (!linkedListEntry) continue\n const predecessor =\n linkedListEntry.predecessor === '\\0'\n ? undefined\n : crListReplica.parentMap.get(linkedListEntry.predecessor)\n void updateEntryToMaps<T>(crListReplica, linkedListEntry)\n void newVals.push(linkedListEntry)\n if (!needsRelink && linkedListEntry.predecessor === '\\0') {\n if (crListReplica.size === 0) {\n crListReplica.cursor = linkedListEntry\n crListReplica.size = crListReplica.parentMap.size\n } else {\n needsRelink = true\n }\n } else if (!needsRelink && predecessor && !predecessor.next) {\n linkedListEntry.prev = predecessor\n linkedListEntry.index = predecessor.index + 1\n predecessor.next = linkedListEntry\n crListReplica.cursor = linkedListEntry\n crListReplica.size = crListReplica.parentMap.size\n } else {\n needsRelink = true\n }\n }\n if (needsRelink) {\n // Flatten tree into a doubly linked list.\n void flattenAndLinkTrustedState<T>(crListReplica)\n // Write live-view indexes.\n void assertListIndices<T>(crListReplica)\n }\n\n if (newTombsIndices.length === 0 && newVals.length === 0) return false\n\n for (const index of newTombsIndices) {\n change[index] = undefined\n }\n for (const val of newVals) {\n change[val.index] = structuredClone(val.value)\n }\n\n return change\n}\n","import type { CRListAck, CRListState } from '../../../.types/index.js'\n\n/**\n * Returns the replica tombstone acknowledgement frontier.\n *\n * The frontier is the greatest tombstone identifier currently retained by the\n * replica. Peers can use it as input for tombstone garbage collection.\n *\n * @param crListReplica - Replica to acknowledge.\n * @returns - The acknowledgement frontier, or `false` when there are no tombstones.\n *\n * Time complexity: O(t)\n * - t = replica tombstone count\n *\n * Space complexity: O(1)\n */\nexport function __acknowledge<T>(\n crListReplica: CRListState<T>\n): CRListAck | false {\n let largest: CRListAck | false = false\n crListReplica.tombstones.forEach((tombstone) => {\n if (largest === false || largest < tombstone) largest = tombstone\n })\n if (typeof largest === 'string') return largest\n return false\n}\n","import { isUuidV7 } from '@sovereignbase/utils'\nimport { CRListAck, CRListState } from '../../../.types/index.js'\n\n/**\n * Removes tombstones acknowledged by all supplied frontiers.\n *\n * The minimum frontier is used as the safe collection boundary. Tombstones less\n * than or equal to that boundary are removed from the local replica.\n *\n * @param frontiers - Acknowledgement frontiers received from peers.\n * @param crListReplica - Replica whose tombstones will be collected.\n *\n * Time complexity: O(f log f + t)\n * - f = frontier count\n * - t = replica tombstone count\n *\n * Space complexity: O(1)\n */\nexport function __garbageCollect<T>(\n frontiers: Array<CRListAck>,\n crListReplica: CRListState<T>\n): void {\n if (!Array.isArray(frontiers)) return\n frontiers.sort()\n const smallest = frontiers.find((frontier) => isUuidV7(frontier))\n if (typeof smallest !== 'string') return\n crListReplica.tombstones.forEach((tombstone, __, tombstones) => {\n if (tombstone <= smallest) {\n tombstones.delete(tombstone)\n }\n })\n}\n","import { CRListError } from '../../../.errors/class.js'\nimport { CRListState, CRListSnapshot } from '../../../.types/index.js'\n\n/**\n * Creates a full detached structured-clone-compatible CRList snapshot from the current replica state.\n *\n * The snapshot contains every live value entry and all retained tombstones. Value\n * payloads are cloned so callers cannot mutate the replica through the snapshot.\n *\n * @param crListReplica - Replica to snapshot.\n * @returns - A full snapshot suitable for hydration or transport.\n *\n * Time complexity: O(n + t + c)\n * - n = replica value entry count\n * - t = replica tombstone count\n * - c = cloned value payload size\n *\n * Space complexity: O(n + t + c)\n */\nexport function __snapshot<T>(\n crListReplica: CRListState<T>\n): CRListSnapshot<T> {\n return {\n values: Array.from(crListReplica.parentMap.values()).map(\n (linkedListEntry) => {\n if (!linkedListEntry) throw new CRListError('LIST_INTEGRITY_VIOLATION')\n return {\n uuidv7: linkedListEntry.uuidv7,\n value: structuredClone(linkedListEntry.value),\n predecessor: linkedListEntry.predecessor,\n }\n }\n ),\n tombstones: Array.from(crListReplica.tombstones),\n }\n}\n","import { indexFromPropertyKey } from '../.helpers/index.js'\nimport { CRListError } from '../.errors/class.js'\nimport type {\n CRListState,\n CRListSnapshot,\n CRListEventListenerFor,\n CRListEventMap,\n CRListDelta,\n CRListAck,\n} from '../.types/index.js'\nimport { __create, __read, __update, __delete } from '../core/crud/index.js'\nimport {\n __merge,\n __acknowledge,\n __garbageCollect,\n __snapshot,\n} from '../core/mags/index.js'\n\n/**\n * A convergent replicated list.\n *\n * Numeric property access reads and mutates the live list projection:\n * `list[0]` reads a detached copy of an entry, `list[0] = value` writes an\n * entry, and `delete list[0]` removes one entry. Iteration and `forEach()`\n * likewise expose detached copies rather than mutable references into the\n * replica state. Local mutations emit `delta` and `change` events; remote\n * merges emit `change` events.\n *\n * @typeParam T - The value type stored in the list.\n */\nexport class CRList<T> {\n /**\n * Reads or overwrites an entry in the live list projection by index.\n *\n * Reads return detached copies.\n */\n [index: number]: T\n declare private readonly state: CRListState<T>\n declare private readonly eventTarget: EventTarget\n\n /**\n * Creates a replicated list from an optional detached structured-clone-compatible snapshot.\n *\n * @param snapshot - A previously emitted CRList snapshot.\n */\n constructor(snapshot?: CRListSnapshot<T>) {\n Object.defineProperties(this, {\n state: {\n value: __create<T>(snapshot),\n enumerable: false,\n configurable: false,\n writable: false,\n },\n eventTarget: {\n value: new EventTarget(),\n enumerable: false,\n configurable: false,\n writable: false,\n },\n })\n\n return new Proxy(this, {\n get(target, index, receiver) {\n const listIndex = indexFromPropertyKey(index)\n // Preserve normal property access for non-index keys.\n if (listIndex === undefined) return Reflect.get(target, index, receiver)\n return __read(listIndex, target.state)\n },\n has(target, index) {\n const listIndex = indexFromPropertyKey(index)\n // Preserve normal property checks for non-index keys.\n if (listIndex === undefined) return Reflect.has(target, index)\n return listIndex >= 0 && listIndex < target.state.size\n },\n set(target, index, value) {\n const listIndex = indexFromPropertyKey(index)\n if (listIndex === undefined) return false\n try {\n const result = __update(listIndex, [value], target.state, 'overwrite')\n if (!result) return false\n const { delta, change } = result\n if (delta)\n void target.eventTarget.dispatchEvent(\n new CustomEvent('delta', { detail: delta })\n )\n if (change)\n void target.eventTarget.dispatchEvent(\n new CustomEvent('change', { detail: change })\n )\n return true\n } catch (error) {\n if (error instanceof CRListError) throw error\n return false\n }\n },\n deleteProperty(target, index) {\n const listIndex = indexFromPropertyKey(index)\n if (listIndex === undefined) return false\n try {\n const result = __delete(target.state, listIndex, listIndex + 1)\n if (!result) return false\n const { delta, change } = result\n if (delta) {\n void target.eventTarget.dispatchEvent(\n new CustomEvent('delta', { detail: delta })\n )\n }\n if (change) {\n void target.eventTarget.dispatchEvent(\n new CustomEvent('change', { detail: change })\n )\n }\n return true\n } catch (error) {\n if (error instanceof CRListError) throw error\n return false\n }\n },\n ownKeys(target) {\n return [\n ...Reflect.ownKeys(target),\n ...Array.from({ length: target.size }, (_, index) => String(index)),\n ]\n },\n\n getOwnPropertyDescriptor(target, index) {\n const listIndex = indexFromPropertyKey(index)\n\n if (listIndex !== undefined && listIndex < target.size) {\n return {\n value: __read(listIndex, target.state),\n writable: true,\n enumerable: true,\n configurable: true,\n }\n }\n // Preserve normal property checks for non-index keys.\n return Reflect.getOwnPropertyDescriptor(target, index)\n },\n })\n }\n /**\n * The current number of live entries.\n */\n get size(): number {\n return this.state.size\n }\n /**\n * Inserts a value before an index.\n *\n * If `beforeIndex` is omitted, the value is inserted at the start of the list.\n *\n * @param value - The value to insert.\n * @param beforeIndex - The index to insert before.\n */\n prepend(value: T, beforeIndex?: number): void {\n const result = __update<T>(beforeIndex ?? 0, [value], this.state, 'before')\n if (!result) return\n const { delta, change } = result\n if (delta)\n void this.eventTarget.dispatchEvent(\n new CustomEvent('delta', { detail: delta })\n )\n if (change)\n void this.eventTarget.dispatchEvent(\n new CustomEvent('change', { detail: change })\n )\n }\n /**\n * Inserts a value after an index.\n *\n * If `afterIndex` is omitted, the value is appended at the end of the list.\n *\n * @param value - The value to insert.\n * @param afterIndex - The index to insert after.\n */\n append(value: T, afterIndex?: number): void {\n const result = __update<T>(\n afterIndex ?? this.state.size,\n [value],\n this.state,\n 'after'\n )\n if (!result) return\n const { delta, change } = result\n if (delta)\n void this.eventTarget.dispatchEvent(\n new CustomEvent('delta', { detail: delta })\n )\n if (change)\n void this.eventTarget.dispatchEvent(\n new CustomEvent('change', { detail: change })\n )\n }\n /**\n * Removes the entry at an index.\n *\n * @param index - The index to remove.\n */\n remove(index: number): void {\n const result = __delete(this.state, index, index + 1)\n if (!result) return\n const { delta, change } = result\n if (delta)\n void this.eventTarget.dispatchEvent(\n new CustomEvent('delta', { detail: delta })\n )\n if (change)\n void this.eventTarget.dispatchEvent(\n new CustomEvent('change', { detail: change })\n )\n }\n /**\n * Applies a remote gossip delta to this list.\n *\n * Emits a `change` event when the merge changes the live projection.\n *\n * @param delta - The remote CRList delta to merge.\n */\n merge(delta: CRListDelta<T>): void {\n const change = __merge(this.state, delta)\n if (change)\n void this.eventTarget.dispatchEvent(\n new CustomEvent('change', { detail: change })\n )\n }\n /**\n * Emits an acknowledgement frontier for currently retained tombstones.\n */\n acknowledge(): void {\n const ack = __acknowledge(this.state)\n if (ack)\n void this.eventTarget.dispatchEvent(\n new CustomEvent('ack', { detail: ack })\n )\n }\n /**\n * Garbage-collects tombstones that are covered by acknowledgement frontiers.\n *\n * @param frontiers - Replica acknowledgement frontiers.\n */\n garbageCollect(frontiers: Array<CRListAck>): void {\n void __garbageCollect(frontiers, this.state)\n }\n /**\n * Emits the current detached structured-clone-compatible list snapshot.\n */\n snapshot(): void {\n const snapshot = __snapshot<T>(this.state)\n if (snapshot)\n void this.eventTarget.dispatchEvent(\n new CustomEvent('snapshot', { detail: snapshot })\n )\n }\n /**\n * Registers an event listener.\n *\n * @param type - The event type to listen for.\n * @param listener - The listener to register.\n * @param options - Listener registration options.\n */\n addEventListener<K extends keyof CRListEventMap<T>>(\n type: K,\n listener: CRListEventListenerFor<T, K> | null,\n options?: boolean | AddEventListenerOptions\n ): void {\n this.eventTarget.addEventListener(\n type,\n listener as EventListenerOrEventListenerObject | null,\n options\n )\n }\n\n /**\n * Removes an event listener.\n *\n * @param type - The event type to stop listening for.\n * @param listener - The listener to remove.\n * @param options - Listener removal options.\n */\n removeEventListener<K extends keyof CRListEventMap<T>>(\n type: K,\n listener: CRListEventListenerFor<T, K> | null,\n options?: boolean | EventListenerOptions\n ): void {\n this.eventTarget.removeEventListener(\n type,\n listener as EventListenerOrEventListenerObject | null,\n options\n )\n }\n /**\n * Returns a detached structured-clone-compatible snapshot of this list.\n *\n * Called automatically by `JSON.stringify`.\n */\n toJSON(): CRListSnapshot<T> {\n return __snapshot<T>(this.state)\n }\n /**\n * Attempts to return this list snapshot as a JSON string.\n *\n * This can fail when list values are not JSON-compatible.\n */\n toString(): string {\n return JSON.stringify(this)\n }\n /**\n * Returns the Node.js console inspection representation.\n */\n [Symbol.for('nodejs.util.inspect.custom')](): CRListSnapshot<T> {\n return this.toJSON()\n }\n /**\n * Returns the Deno console inspection representation.\n */\n [Symbol.for('Deno.customInspect')](): CRListSnapshot<T> {\n return this.toJSON()\n }\n /**\n * Iterates over detached copies of the current live values in index order.\n */\n *[Symbol.iterator](): IterableIterator<T> {\n for (let index = 0; index < this.size; index++) {\n const value = this[index]\n yield value\n }\n }\n /**\n * Calls a function once for each live value copy in index order.\n *\n * Callback values are detached copies, so mutating them does not mutate the\n * list.\n *\n * @param callback - Function to call for each value copy.\n * @param thisArg - Optional `this` value for the callback.\n */\n forEach(\n callback: (value: T, index: number, list: this) => void,\n thisArg?: unknown\n ): void {\n for (let index = 0; index < this.size; index++) {\n callback.call(thisArg, this[index], index, this)\n }\n }\n}\n"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -114,7 +114,7 @@ declare class CRList<T> {
|
|
|
114
114
|
private readonly state;
|
|
115
115
|
private readonly eventTarget;
|
|
116
116
|
/**
|
|
117
|
-
* Creates a replicated list from an optional
|
|
117
|
+
* Creates a replicated list from an optional detached structured-clone-compatible snapshot.
|
|
118
118
|
*
|
|
119
119
|
* @param snapshot - A previously emitted CRList snapshot.
|
|
120
120
|
*/
|
|
@@ -166,7 +166,7 @@ declare class CRList<T> {
|
|
|
166
166
|
*/
|
|
167
167
|
garbageCollect(frontiers: Array<CRListAck>): void;
|
|
168
168
|
/**
|
|
169
|
-
* Emits the current
|
|
169
|
+
* Emits the current detached structured-clone-compatible list snapshot.
|
|
170
170
|
*/
|
|
171
171
|
snapshot(): void;
|
|
172
172
|
/**
|
|
@@ -186,13 +186,15 @@ declare class CRList<T> {
|
|
|
186
186
|
*/
|
|
187
187
|
removeEventListener<K extends keyof CRListEventMap<T>>(type: K, listener: CRListEventListenerFor<T, K> | null, options?: boolean | EventListenerOptions): void;
|
|
188
188
|
/**
|
|
189
|
-
* Returns a
|
|
189
|
+
* Returns a detached structured-clone-compatible snapshot of this list.
|
|
190
190
|
*
|
|
191
191
|
* Called automatically by `JSON.stringify`.
|
|
192
192
|
*/
|
|
193
193
|
toJSON(): CRListSnapshot<T>;
|
|
194
194
|
/**
|
|
195
|
-
*
|
|
195
|
+
* Attempts to return this list snapshot as a JSON string.
|
|
196
|
+
*
|
|
197
|
+
* This can fail when list values are not JSON-compatible.
|
|
196
198
|
*/
|
|
197
199
|
toString(): string;
|
|
198
200
|
/**
|
|
@@ -215,6 +217,22 @@ declare class CRList<T> {
|
|
|
215
217
|
* Error codes thrown by {@link CRList}.
|
|
216
218
|
*/
|
|
217
219
|
type CRListErrorCode = 'VALUE_NOT_CLONEABLE' | 'INDEX_OUT_OF_BOUNDS' | 'LIST_EMPTY' | 'LIST_INTEGRITY_VIOLATION' | 'UPDATE_EXPECTED_AN_ARRAY';
|
|
220
|
+
/**
|
|
221
|
+
* Represents a typed CRList runtime error.
|
|
222
|
+
*/
|
|
223
|
+
declare class CRListError extends Error {
|
|
224
|
+
/**
|
|
225
|
+
* The semantic error code for the failure.
|
|
226
|
+
*/
|
|
227
|
+
readonly code: CRListErrorCode;
|
|
228
|
+
/**
|
|
229
|
+
* Creates a typed CRList error.
|
|
230
|
+
*
|
|
231
|
+
* @param code - The semantic error code.
|
|
232
|
+
* @param message - An optional human-readable detail message.
|
|
233
|
+
*/
|
|
234
|
+
constructor(code: CRListErrorCode, message?: string);
|
|
235
|
+
}
|
|
218
236
|
|
|
219
237
|
/**
|
|
220
238
|
* Creates a local CRList replica from an optional snapshot.
|
|
@@ -223,8 +241,8 @@ type CRListErrorCode = 'VALUE_NOT_CLONEABLE' | 'INDEX_OUT_OF_BOUNDS' | 'LIST_EMP
|
|
|
223
241
|
* UUIDv7, linked through their predecessor buckets, and exposed as a live
|
|
224
242
|
* doubly-linked list.
|
|
225
243
|
*
|
|
226
|
-
* @param snapshot Optional
|
|
227
|
-
* @returns A hydrated CRList replica.
|
|
244
|
+
* @param snapshot - Optional detached structured-clone-compatible CRList snapshot.
|
|
245
|
+
* @returns - A hydrated CRList replica.
|
|
228
246
|
*
|
|
229
247
|
* Time complexity: O(n log n + t + c), worst case O(n^2 + t + c)
|
|
230
248
|
* - n = snapshot value entry count
|
|
@@ -243,9 +261,9 @@ declare function __create<T>(snapshot?: CRListSnapshot<T>): CRListState<T>;
|
|
|
243
261
|
* value does not mutate the replica itself. Out-of-bounds and empty list reads
|
|
244
262
|
* resolve to `undefined` instead of throwing.
|
|
245
263
|
*
|
|
246
|
-
* @param targetIndex Index in the live list.
|
|
247
|
-
* @param crListReplica Replica to read from.
|
|
248
|
-
* @returns A detached copy of the value at `targetIndex`, or `undefined` when
|
|
264
|
+
* @param targetIndex - Index in the live list.
|
|
265
|
+
* @param crListReplica - Replica to read from.
|
|
266
|
+
* @returns - A detached copy of the value at `targetIndex`, or `undefined` when
|
|
249
267
|
* no value is present.
|
|
250
268
|
*
|
|
251
269
|
* Time complexity: O(d), worst case O(n)
|
|
@@ -263,11 +281,11 @@ declare function __read<T>(targetIndex: number, crListReplica: CRListState<T>):
|
|
|
263
281
|
* before it, or insert values after it. The returned delta is suitable for
|
|
264
282
|
* gossip and the returned change describes the local live-view patch.
|
|
265
283
|
*
|
|
266
|
-
* @param listIndex Target index in the live list.
|
|
267
|
-
* @param listValues Values to insert or overwrite.
|
|
268
|
-
* @param crListReplica Replica to mutate.
|
|
269
|
-
* @param mode Mutation mode relative to `listIndex`.
|
|
270
|
-
* @returns A local change and gossip delta, or `false` if no mutation occurred.
|
|
284
|
+
* @param listIndex - Target index in the live list.
|
|
285
|
+
* @param listValues - Values to insert or overwrite.
|
|
286
|
+
* @param crListReplica - Replica to mutate.
|
|
287
|
+
* @param mode - Mutation mode relative to `listIndex`.
|
|
288
|
+
* @returns - A local change and gossip delta, or `false` if no mutation occurred.
|
|
271
289
|
*
|
|
272
290
|
* Time complexity: O(d + v + r + vk + c), worst case O(vn + c)
|
|
273
291
|
* - d = distance from cursor to target index
|
|
@@ -290,10 +308,10 @@ declare function __update<T>(listIndex: number, listValues: Array<T>, crListRepl
|
|
|
290
308
|
* from `startIndex` onward are deleted. With both indexes, the deleted range is
|
|
291
309
|
* `[startIndex, endIndex)`.
|
|
292
310
|
*
|
|
293
|
-
* @param crListReplica Replica to mutate.
|
|
294
|
-
* @param startIndex Inclusive start index. Defaults to `0`.
|
|
295
|
-
* @param endIndex Exclusive end index. Defaults to the current list size.
|
|
296
|
-
* @returns A local change and gossip delta, or `false` if nothing was deleted.
|
|
311
|
+
* @param crListReplica - Replica to mutate.
|
|
312
|
+
* @param startIndex - Inclusive start index. Defaults to `0`.
|
|
313
|
+
* @param endIndex - Exclusive end index. Defaults to the current list size.
|
|
314
|
+
* @returns - A local change and gossip delta, or `false` if nothing was deleted.
|
|
297
315
|
*
|
|
298
316
|
* Time complexity: O(d + qk + r), worst case O(n^2)
|
|
299
317
|
* - d = distance from cursor to target index
|
|
@@ -315,9 +333,9 @@ declare function __delete<T>(crListReplica: CRListState<T>, startIndex?: number,
|
|
|
315
333
|
* to the predecessor tree. Tail-append deltas are linked incrementally; deltas
|
|
316
334
|
* that can affect ordering fall back to deterministic relinking.
|
|
317
335
|
*
|
|
318
|
-
* @param crListReplica Replica to mutate.
|
|
319
|
-
* @param crListDelta Remote gossip delta.
|
|
320
|
-
* @returns A minimal local change patch, or `false` when the delta is ignored.
|
|
336
|
+
* @param crListReplica - Replica to mutate.
|
|
337
|
+
* @param crListDelta - Remote gossip delta.
|
|
338
|
+
* @returns - A minimal local change patch, or `false` when the delta is ignored.
|
|
321
339
|
*
|
|
322
340
|
* Time complexity: O(v + t + c) for tail-append deltas; O(n + t + qk) for tombstone-only deletes; otherwise O(n log n + v + t + m*k + c)
|
|
323
341
|
* Worst case: O(n^2 + (v + t)n + c)
|
|
@@ -339,8 +357,8 @@ declare function __merge<T>(crListReplica: CRListState<T>, crListDelta: CRListDe
|
|
|
339
357
|
* The frontier is the greatest tombstone identifier currently retained by the
|
|
340
358
|
* replica. Peers can use it as input for tombstone garbage collection.
|
|
341
359
|
*
|
|
342
|
-
* @param crListReplica Replica to acknowledge.
|
|
343
|
-
* @returns The acknowledgement frontier, or `false` when there are no tombstones.
|
|
360
|
+
* @param crListReplica - Replica to acknowledge.
|
|
361
|
+
* @returns - The acknowledgement frontier, or `false` when there are no tombstones.
|
|
344
362
|
*
|
|
345
363
|
* Time complexity: O(t)
|
|
346
364
|
* - t = replica tombstone count
|
|
@@ -355,8 +373,8 @@ declare function __acknowledge<T>(crListReplica: CRListState<T>): CRListAck | fa
|
|
|
355
373
|
* The minimum frontier is used as the safe collection boundary. Tombstones less
|
|
356
374
|
* than or equal to that boundary are removed from the local replica.
|
|
357
375
|
*
|
|
358
|
-
* @param frontiers Acknowledgement frontiers received from peers.
|
|
359
|
-
* @param crListReplica Replica whose tombstones will be collected.
|
|
376
|
+
* @param frontiers - Acknowledgement frontiers received from peers.
|
|
377
|
+
* @param crListReplica - Replica whose tombstones will be collected.
|
|
360
378
|
*
|
|
361
379
|
* Time complexity: O(f log f + t)
|
|
362
380
|
* - f = frontier count
|
|
@@ -367,13 +385,13 @@ declare function __acknowledge<T>(crListReplica: CRListState<T>): CRListAck | fa
|
|
|
367
385
|
declare function __garbageCollect<T>(frontiers: Array<CRListAck>, crListReplica: CRListState<T>): void;
|
|
368
386
|
|
|
369
387
|
/**
|
|
370
|
-
* Creates a full
|
|
388
|
+
* Creates a full detached structured-clone-compatible CRList snapshot from the current replica state.
|
|
371
389
|
*
|
|
372
390
|
* The snapshot contains every live value entry and all retained tombstones. Value
|
|
373
391
|
* payloads are cloned so callers cannot mutate the replica through the snapshot.
|
|
374
392
|
*
|
|
375
|
-
* @param crListReplica Replica to snapshot.
|
|
376
|
-
* @returns A full snapshot suitable for hydration or transport.
|
|
393
|
+
* @param crListReplica - Replica to snapshot.
|
|
394
|
+
* @returns - A full snapshot suitable for hydration or transport.
|
|
377
395
|
*
|
|
378
396
|
* Time complexity: O(n + t + c)
|
|
379
397
|
* - n = replica value entry count
|
|
@@ -384,4 +402,4 @@ declare function __garbageCollect<T>(frontiers: Array<CRListAck>, crListReplica:
|
|
|
384
402
|
*/
|
|
385
403
|
declare function __snapshot<T>(crListReplica: CRListState<T>): CRListSnapshot<T>;
|
|
386
404
|
|
|
387
|
-
export { CRList, type CRListAck, type CRListChange, type CRListDelta, type CRListErrorCode, type CRListEventListener, type CRListEventListenerFor, type CRListEventMap, type CRListSnapshot, type CRListSnapshotEntry, type CRListState, type CRListStateEntry, __acknowledge, __create, __delete, __garbageCollect, __merge, __read, __snapshot, __update };
|
|
405
|
+
export { CRList, type CRListAck, type CRListChange, type CRListDelta, CRListError, type CRListErrorCode, type CRListEventListener, type CRListEventListenerFor, type CRListEventMap, type CRListSnapshot, type CRListSnapshotEntry, type CRListState, type CRListStateEntry, __acknowledge, __create, __delete, __garbageCollect, __merge, __read, __snapshot, __update };
|
package/dist/index.d.ts
CHANGED
|
@@ -114,7 +114,7 @@ declare class CRList<T> {
|
|
|
114
114
|
private readonly state;
|
|
115
115
|
private readonly eventTarget;
|
|
116
116
|
/**
|
|
117
|
-
* Creates a replicated list from an optional
|
|
117
|
+
* Creates a replicated list from an optional detached structured-clone-compatible snapshot.
|
|
118
118
|
*
|
|
119
119
|
* @param snapshot - A previously emitted CRList snapshot.
|
|
120
120
|
*/
|
|
@@ -166,7 +166,7 @@ declare class CRList<T> {
|
|
|
166
166
|
*/
|
|
167
167
|
garbageCollect(frontiers: Array<CRListAck>): void;
|
|
168
168
|
/**
|
|
169
|
-
* Emits the current
|
|
169
|
+
* Emits the current detached structured-clone-compatible list snapshot.
|
|
170
170
|
*/
|
|
171
171
|
snapshot(): void;
|
|
172
172
|
/**
|
|
@@ -186,13 +186,15 @@ declare class CRList<T> {
|
|
|
186
186
|
*/
|
|
187
187
|
removeEventListener<K extends keyof CRListEventMap<T>>(type: K, listener: CRListEventListenerFor<T, K> | null, options?: boolean | EventListenerOptions): void;
|
|
188
188
|
/**
|
|
189
|
-
* Returns a
|
|
189
|
+
* Returns a detached structured-clone-compatible snapshot of this list.
|
|
190
190
|
*
|
|
191
191
|
* Called automatically by `JSON.stringify`.
|
|
192
192
|
*/
|
|
193
193
|
toJSON(): CRListSnapshot<T>;
|
|
194
194
|
/**
|
|
195
|
-
*
|
|
195
|
+
* Attempts to return this list snapshot as a JSON string.
|
|
196
|
+
*
|
|
197
|
+
* This can fail when list values are not JSON-compatible.
|
|
196
198
|
*/
|
|
197
199
|
toString(): string;
|
|
198
200
|
/**
|
|
@@ -215,6 +217,22 @@ declare class CRList<T> {
|
|
|
215
217
|
* Error codes thrown by {@link CRList}.
|
|
216
218
|
*/
|
|
217
219
|
type CRListErrorCode = 'VALUE_NOT_CLONEABLE' | 'INDEX_OUT_OF_BOUNDS' | 'LIST_EMPTY' | 'LIST_INTEGRITY_VIOLATION' | 'UPDATE_EXPECTED_AN_ARRAY';
|
|
220
|
+
/**
|
|
221
|
+
* Represents a typed CRList runtime error.
|
|
222
|
+
*/
|
|
223
|
+
declare class CRListError extends Error {
|
|
224
|
+
/**
|
|
225
|
+
* The semantic error code for the failure.
|
|
226
|
+
*/
|
|
227
|
+
readonly code: CRListErrorCode;
|
|
228
|
+
/**
|
|
229
|
+
* Creates a typed CRList error.
|
|
230
|
+
*
|
|
231
|
+
* @param code - The semantic error code.
|
|
232
|
+
* @param message - An optional human-readable detail message.
|
|
233
|
+
*/
|
|
234
|
+
constructor(code: CRListErrorCode, message?: string);
|
|
235
|
+
}
|
|
218
236
|
|
|
219
237
|
/**
|
|
220
238
|
* Creates a local CRList replica from an optional snapshot.
|
|
@@ -223,8 +241,8 @@ type CRListErrorCode = 'VALUE_NOT_CLONEABLE' | 'INDEX_OUT_OF_BOUNDS' | 'LIST_EMP
|
|
|
223
241
|
* UUIDv7, linked through their predecessor buckets, and exposed as a live
|
|
224
242
|
* doubly-linked list.
|
|
225
243
|
*
|
|
226
|
-
* @param snapshot Optional
|
|
227
|
-
* @returns A hydrated CRList replica.
|
|
244
|
+
* @param snapshot - Optional detached structured-clone-compatible CRList snapshot.
|
|
245
|
+
* @returns - A hydrated CRList replica.
|
|
228
246
|
*
|
|
229
247
|
* Time complexity: O(n log n + t + c), worst case O(n^2 + t + c)
|
|
230
248
|
* - n = snapshot value entry count
|
|
@@ -243,9 +261,9 @@ declare function __create<T>(snapshot?: CRListSnapshot<T>): CRListState<T>;
|
|
|
243
261
|
* value does not mutate the replica itself. Out-of-bounds and empty list reads
|
|
244
262
|
* resolve to `undefined` instead of throwing.
|
|
245
263
|
*
|
|
246
|
-
* @param targetIndex Index in the live list.
|
|
247
|
-
* @param crListReplica Replica to read from.
|
|
248
|
-
* @returns A detached copy of the value at `targetIndex`, or `undefined` when
|
|
264
|
+
* @param targetIndex - Index in the live list.
|
|
265
|
+
* @param crListReplica - Replica to read from.
|
|
266
|
+
* @returns - A detached copy of the value at `targetIndex`, or `undefined` when
|
|
249
267
|
* no value is present.
|
|
250
268
|
*
|
|
251
269
|
* Time complexity: O(d), worst case O(n)
|
|
@@ -263,11 +281,11 @@ declare function __read<T>(targetIndex: number, crListReplica: CRListState<T>):
|
|
|
263
281
|
* before it, or insert values after it. The returned delta is suitable for
|
|
264
282
|
* gossip and the returned change describes the local live-view patch.
|
|
265
283
|
*
|
|
266
|
-
* @param listIndex Target index in the live list.
|
|
267
|
-
* @param listValues Values to insert or overwrite.
|
|
268
|
-
* @param crListReplica Replica to mutate.
|
|
269
|
-
* @param mode Mutation mode relative to `listIndex`.
|
|
270
|
-
* @returns A local change and gossip delta, or `false` if no mutation occurred.
|
|
284
|
+
* @param listIndex - Target index in the live list.
|
|
285
|
+
* @param listValues - Values to insert or overwrite.
|
|
286
|
+
* @param crListReplica - Replica to mutate.
|
|
287
|
+
* @param mode - Mutation mode relative to `listIndex`.
|
|
288
|
+
* @returns - A local change and gossip delta, or `false` if no mutation occurred.
|
|
271
289
|
*
|
|
272
290
|
* Time complexity: O(d + v + r + vk + c), worst case O(vn + c)
|
|
273
291
|
* - d = distance from cursor to target index
|
|
@@ -290,10 +308,10 @@ declare function __update<T>(listIndex: number, listValues: Array<T>, crListRepl
|
|
|
290
308
|
* from `startIndex` onward are deleted. With both indexes, the deleted range is
|
|
291
309
|
* `[startIndex, endIndex)`.
|
|
292
310
|
*
|
|
293
|
-
* @param crListReplica Replica to mutate.
|
|
294
|
-
* @param startIndex Inclusive start index. Defaults to `0`.
|
|
295
|
-
* @param endIndex Exclusive end index. Defaults to the current list size.
|
|
296
|
-
* @returns A local change and gossip delta, or `false` if nothing was deleted.
|
|
311
|
+
* @param crListReplica - Replica to mutate.
|
|
312
|
+
* @param startIndex - Inclusive start index. Defaults to `0`.
|
|
313
|
+
* @param endIndex - Exclusive end index. Defaults to the current list size.
|
|
314
|
+
* @returns - A local change and gossip delta, or `false` if nothing was deleted.
|
|
297
315
|
*
|
|
298
316
|
* Time complexity: O(d + qk + r), worst case O(n^2)
|
|
299
317
|
* - d = distance from cursor to target index
|
|
@@ -315,9 +333,9 @@ declare function __delete<T>(crListReplica: CRListState<T>, startIndex?: number,
|
|
|
315
333
|
* to the predecessor tree. Tail-append deltas are linked incrementally; deltas
|
|
316
334
|
* that can affect ordering fall back to deterministic relinking.
|
|
317
335
|
*
|
|
318
|
-
* @param crListReplica Replica to mutate.
|
|
319
|
-
* @param crListDelta Remote gossip delta.
|
|
320
|
-
* @returns A minimal local change patch, or `false` when the delta is ignored.
|
|
336
|
+
* @param crListReplica - Replica to mutate.
|
|
337
|
+
* @param crListDelta - Remote gossip delta.
|
|
338
|
+
* @returns - A minimal local change patch, or `false` when the delta is ignored.
|
|
321
339
|
*
|
|
322
340
|
* Time complexity: O(v + t + c) for tail-append deltas; O(n + t + qk) for tombstone-only deletes; otherwise O(n log n + v + t + m*k + c)
|
|
323
341
|
* Worst case: O(n^2 + (v + t)n + c)
|
|
@@ -339,8 +357,8 @@ declare function __merge<T>(crListReplica: CRListState<T>, crListDelta: CRListDe
|
|
|
339
357
|
* The frontier is the greatest tombstone identifier currently retained by the
|
|
340
358
|
* replica. Peers can use it as input for tombstone garbage collection.
|
|
341
359
|
*
|
|
342
|
-
* @param crListReplica Replica to acknowledge.
|
|
343
|
-
* @returns The acknowledgement frontier, or `false` when there are no tombstones.
|
|
360
|
+
* @param crListReplica - Replica to acknowledge.
|
|
361
|
+
* @returns - The acknowledgement frontier, or `false` when there are no tombstones.
|
|
344
362
|
*
|
|
345
363
|
* Time complexity: O(t)
|
|
346
364
|
* - t = replica tombstone count
|
|
@@ -355,8 +373,8 @@ declare function __acknowledge<T>(crListReplica: CRListState<T>): CRListAck | fa
|
|
|
355
373
|
* The minimum frontier is used as the safe collection boundary. Tombstones less
|
|
356
374
|
* than or equal to that boundary are removed from the local replica.
|
|
357
375
|
*
|
|
358
|
-
* @param frontiers Acknowledgement frontiers received from peers.
|
|
359
|
-
* @param crListReplica Replica whose tombstones will be collected.
|
|
376
|
+
* @param frontiers - Acknowledgement frontiers received from peers.
|
|
377
|
+
* @param crListReplica - Replica whose tombstones will be collected.
|
|
360
378
|
*
|
|
361
379
|
* Time complexity: O(f log f + t)
|
|
362
380
|
* - f = frontier count
|
|
@@ -367,13 +385,13 @@ declare function __acknowledge<T>(crListReplica: CRListState<T>): CRListAck | fa
|
|
|
367
385
|
declare function __garbageCollect<T>(frontiers: Array<CRListAck>, crListReplica: CRListState<T>): void;
|
|
368
386
|
|
|
369
387
|
/**
|
|
370
|
-
* Creates a full
|
|
388
|
+
* Creates a full detached structured-clone-compatible CRList snapshot from the current replica state.
|
|
371
389
|
*
|
|
372
390
|
* The snapshot contains every live value entry and all retained tombstones. Value
|
|
373
391
|
* payloads are cloned so callers cannot mutate the replica through the snapshot.
|
|
374
392
|
*
|
|
375
|
-
* @param crListReplica Replica to snapshot.
|
|
376
|
-
* @returns A full snapshot suitable for hydration or transport.
|
|
393
|
+
* @param crListReplica - Replica to snapshot.
|
|
394
|
+
* @returns - A full snapshot suitable for hydration or transport.
|
|
377
395
|
*
|
|
378
396
|
* Time complexity: O(n + t + c)
|
|
379
397
|
* - n = replica value entry count
|
|
@@ -384,4 +402,4 @@ declare function __garbageCollect<T>(frontiers: Array<CRListAck>, crListReplica:
|
|
|
384
402
|
*/
|
|
385
403
|
declare function __snapshot<T>(crListReplica: CRListState<T>): CRListSnapshot<T>;
|
|
386
404
|
|
|
387
|
-
export { CRList, type CRListAck, type CRListChange, type CRListDelta, type CRListErrorCode, type CRListEventListener, type CRListEventListenerFor, type CRListEventMap, type CRListSnapshot, type CRListSnapshotEntry, type CRListState, type CRListStateEntry, __acknowledge, __create, __delete, __garbageCollect, __merge, __read, __snapshot, __update };
|
|
405
|
+
export { CRList, type CRListAck, type CRListChange, type CRListDelta, CRListError, type CRListErrorCode, type CRListEventListener, type CRListEventListenerFor, type CRListEventMap, type CRListSnapshot, type CRListSnapshotEntry, type CRListState, type CRListStateEntry, __acknowledge, __create, __delete, __garbageCollect, __merge, __read, __snapshot, __update };
|
package/dist/index.js
CHANGED
|
@@ -134,9 +134,10 @@ function flattenAndLinkTrustedState(crListReplica) {
|
|
|
134
134
|
crListReplica.size = crListReplica.parentMap.size;
|
|
135
135
|
}
|
|
136
136
|
|
|
137
|
-
// src/.helpers/
|
|
137
|
+
// src/.helpers/transformSnapshotEntryToStateEntry/index.ts
|
|
138
138
|
import { isUuidV7, safeStructuredClone } from "@sovereignbase/utils";
|
|
139
|
-
function
|
|
139
|
+
function transformSnapshotEntryToStateEntry(valueEntry, crListReplica) {
|
|
140
|
+
if (valueEntry === null || valueEntry === void 0) return void 0;
|
|
140
141
|
if (!isUuidV7(valueEntry.uuidv7) || crListReplica.tombstones.has(valueEntry.uuidv7) || crListReplica.parentMap.has(valueEntry.uuidv7) || !isUuidV7(valueEntry.predecessor) && valueEntry.predecessor !== "\0" && !crListReplica.tombstones.has(valueEntry.predecessor))
|
|
141
142
|
return void 0;
|
|
142
143
|
const [cloned, copiedValue] = safeStructuredClone(valueEntry.value);
|
|
@@ -235,7 +236,7 @@ function __create(snapshot) {
|
|
|
235
236
|
if (!Object.hasOwn(snapshot, "values") || !Array.isArray(snapshot.values))
|
|
236
237
|
return crListReplica;
|
|
237
238
|
for (const valueEntry of snapshot.values) {
|
|
238
|
-
const linkedListEntry =
|
|
239
|
+
const linkedListEntry = transformSnapshotEntryToStateEntry(
|
|
239
240
|
valueEntry,
|
|
240
241
|
crListReplica
|
|
241
242
|
);
|
|
@@ -468,6 +469,7 @@ function __merge(crListReplica, crListDelta) {
|
|
|
468
469
|
return change;
|
|
469
470
|
}
|
|
470
471
|
for (const valueEntry of crListDelta.values) {
|
|
472
|
+
if (valueEntry === null || valueEntry === void 0) continue;
|
|
471
473
|
const existingEntry = crListReplica.parentMap.get(valueEntry.uuidv7);
|
|
472
474
|
if (existingEntry) {
|
|
473
475
|
if (crListReplica.tombstones.has(valueEntry.uuidv7) || !isUuidV73(valueEntry.predecessor) && valueEntry.predecessor !== "\0")
|
|
@@ -482,7 +484,7 @@ function __merge(crListReplica, crListDelta) {
|
|
|
482
484
|
void newVals.push(existingEntry);
|
|
483
485
|
continue;
|
|
484
486
|
}
|
|
485
|
-
const linkedListEntry =
|
|
487
|
+
const linkedListEntry = transformSnapshotEntryToStateEntry(
|
|
486
488
|
valueEntry,
|
|
487
489
|
crListReplica
|
|
488
490
|
);
|
|
@@ -523,21 +525,23 @@ function __merge(crListReplica, crListDelta) {
|
|
|
523
525
|
|
|
524
526
|
// src/core/mags/acknowledge/index.ts
|
|
525
527
|
function __acknowledge(crListReplica) {
|
|
526
|
-
let
|
|
528
|
+
let largest = false;
|
|
527
529
|
crListReplica.tombstones.forEach((tombstone) => {
|
|
528
|
-
if (
|
|
530
|
+
if (largest === false || largest < tombstone) largest = tombstone;
|
|
529
531
|
});
|
|
530
|
-
if (typeof
|
|
532
|
+
if (typeof largest === "string") return largest;
|
|
531
533
|
return false;
|
|
532
534
|
}
|
|
533
535
|
|
|
534
536
|
// src/core/mags/garbageCollect/index.ts
|
|
537
|
+
import { isUuidV7 as isUuidV74 } from "@sovereignbase/utils";
|
|
535
538
|
function __garbageCollect(frontiers, crListReplica) {
|
|
536
539
|
if (!Array.isArray(frontiers)) return;
|
|
537
|
-
|
|
538
|
-
|
|
540
|
+
frontiers.sort();
|
|
541
|
+
const smallest = frontiers.find((frontier) => isUuidV74(frontier));
|
|
542
|
+
if (typeof smallest !== "string") return;
|
|
539
543
|
crListReplica.tombstones.forEach((tombstone, __, tombstones) => {
|
|
540
|
-
if (tombstone <=
|
|
544
|
+
if (tombstone <= smallest) {
|
|
541
545
|
tombstones.delete(tombstone);
|
|
542
546
|
}
|
|
543
547
|
});
|
|
@@ -563,7 +567,7 @@ function __snapshot(crListReplica) {
|
|
|
563
567
|
// src/CRList/class.ts
|
|
564
568
|
var CRList = class {
|
|
565
569
|
/**
|
|
566
|
-
* Creates a replicated list from an optional
|
|
570
|
+
* Creates a replicated list from an optional detached structured-clone-compatible snapshot.
|
|
567
571
|
*
|
|
568
572
|
* @param snapshot - A previously emitted CRList snapshot.
|
|
569
573
|
*/
|
|
@@ -609,7 +613,8 @@ var CRList = class {
|
|
|
609
613
|
new CustomEvent("change", { detail: change })
|
|
610
614
|
);
|
|
611
615
|
return true;
|
|
612
|
-
} catch {
|
|
616
|
+
} catch (error) {
|
|
617
|
+
if (error instanceof CRListError) throw error;
|
|
613
618
|
return false;
|
|
614
619
|
}
|
|
615
620
|
},
|
|
@@ -631,7 +636,8 @@ var CRList = class {
|
|
|
631
636
|
);
|
|
632
637
|
}
|
|
633
638
|
return true;
|
|
634
|
-
} catch {
|
|
639
|
+
} catch (error) {
|
|
640
|
+
if (error instanceof CRListError) throw error;
|
|
635
641
|
return false;
|
|
636
642
|
}
|
|
637
643
|
},
|
|
@@ -759,7 +765,7 @@ var CRList = class {
|
|
|
759
765
|
void __garbageCollect(frontiers, this.state);
|
|
760
766
|
}
|
|
761
767
|
/**
|
|
762
|
-
* Emits the current
|
|
768
|
+
* Emits the current detached structured-clone-compatible list snapshot.
|
|
763
769
|
*/
|
|
764
770
|
snapshot() {
|
|
765
771
|
const snapshot = __snapshot(this.state);
|
|
@@ -797,7 +803,7 @@ var CRList = class {
|
|
|
797
803
|
);
|
|
798
804
|
}
|
|
799
805
|
/**
|
|
800
|
-
* Returns a
|
|
806
|
+
* Returns a detached structured-clone-compatible snapshot of this list.
|
|
801
807
|
*
|
|
802
808
|
* Called automatically by `JSON.stringify`.
|
|
803
809
|
*/
|
|
@@ -805,7 +811,9 @@ var CRList = class {
|
|
|
805
811
|
return __snapshot(this.state);
|
|
806
812
|
}
|
|
807
813
|
/**
|
|
808
|
-
*
|
|
814
|
+
* Attempts to return this list snapshot as a JSON string.
|
|
815
|
+
*
|
|
816
|
+
* This can fail when list values are not JSON-compatible.
|
|
809
817
|
*/
|
|
810
818
|
toString() {
|
|
811
819
|
return JSON.stringify(this);
|
|
@@ -848,6 +856,7 @@ var CRList = class {
|
|
|
848
856
|
};
|
|
849
857
|
export {
|
|
850
858
|
CRList,
|
|
859
|
+
CRListError,
|
|
851
860
|
__acknowledge,
|
|
852
861
|
__create,
|
|
853
862
|
__delete,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/.helpers/assertListIndices/index.ts","../src/.errors/class.ts","../src/.helpers/walkToIndex/index.ts","../src/.helpers/insertBetween/index.ts","../src/.helpers/flattenAndLinkTrustedState/index.ts","../src/.helpers/snapshotValueToLinkedListValue/index.ts","../src/.helpers/updateEntryToMaps/index.ts","../src/.helpers/deleteEntryFromMaps/index.ts","../src/.helpers/deleteLinkedEntry/index.ts","../src/.helpers/moveEntryToPredecessor/index.ts","../src/.helpers/indexFromPropertyKey/index.ts","../src/core/crud/create/index.ts","../src/core/crud/read/index.ts","../src/core/crud/update/index.ts","../src/core/crud/delete/index.ts","../src/core/mags/merge/index.ts","../src/core/mags/acknowledge/index.ts","../src/core/mags/garbageCollect/index.ts","../src/core/mags/snapshot/index.ts","../src/CRList/class.ts"],"sourcesContent":["import type { CRListState } from '../../.types/index.js'\n\nexport function assertListIndices<T>(crListReplica: CRListState<T>): void {\n if (!crListReplica.cursor) return\n let index = crListReplica.size\n while (crListReplica.cursor.next)\n crListReplica.cursor = crListReplica.cursor.next\n\n while (index >= 1) {\n index--\n crListReplica.cursor.index = index\n if (crListReplica.cursor.prev === undefined) break\n crListReplica.cursor = crListReplica.cursor.prev\n }\n}\n","/**\n * Error codes thrown by {@link CRList}.\n */\nexport type CRListErrorCode =\n | 'VALUE_NOT_CLONEABLE'\n | 'INDEX_OUT_OF_BOUNDS'\n | 'LIST_EMPTY'\n | 'LIST_INTEGRITY_VIOLATION'\n | 'UPDATE_EXPECTED_AN_ARRAY'\n\n/**\n * Represents a typed CRList runtime error.\n */\nexport class CRListError extends Error {\n /**\n * The semantic error code for the failure.\n */\n readonly code: CRListErrorCode\n\n /**\n * Creates a typed CRList error.\n *\n * @param code - The semantic error code.\n * @param message - An optional human-readable detail message.\n */\n constructor(code: CRListErrorCode, message?: string) {\n const detail = message ?? code\n super(`{@sovereignbase/convergent-replicated-list} ${detail}`)\n this.code = code\n this.name = 'CRListError'\n }\n}\n","import type { CRListState } from '../../.types/index.js'\nimport { CRListError } from '../../.errors/class.js'\n\nexport function walkToIndex<T>(\n targetIndex: number,\n crListReplica: CRListState<T>\n): void {\n if (targetIndex < 0 || targetIndex >= crListReplica.size)\n throw new CRListError('INDEX_OUT_OF_BOUNDS', 'Index out of bounds')\n if (!crListReplica.cursor)\n throw new CRListError('LIST_EMPTY', 'List is empty')\n const direction = crListReplica.cursor.index > targetIndex ? 'prev' : 'next'\n while (crListReplica.cursor && crListReplica.cursor.index !== targetIndex) {\n crListReplica.cursor = crListReplica.cursor[direction]\n }\n}\n","import type { CRListStateEntry } from '../../.types/index.js'\n\nexport function insertBetween<T>(\n prev: CRListStateEntry<T>,\n linkedListEntry: NonNullable<CRListStateEntry<T>>,\n next: CRListStateEntry<T>\n): void {\n linkedListEntry.prev = prev\n linkedListEntry.next = next\n if (prev) prev.next = linkedListEntry\n if (next) next.prev = linkedListEntry\n}\n","import type { CRListState, CRListStateEntry } from '../../.types/index.js'\nimport { insertBetween } from '../insertBetween/index.js'\nexport function flattenAndLinkTrustedState<T>(crListReplica: CRListState<T>) {\n crListReplica.cursor = undefined\n const resolvedSiblingPredecessors = new Set<string>()\n for (const entry of crListReplica.parentMap.values()) {\n if (!entry) continue\n entry.prev = undefined\n entry.next = undefined\n }\n const keys = [...crListReplica.childrenMap.keys()].sort((a, b) =>\n a > b ? 1 : -1\n )\n let hasProgress = true\n while (hasProgress) {\n hasProgress = false\n for (const predecessorIdentifier of keys) {\n if (resolvedSiblingPredecessors.has(predecessorIdentifier)) continue\n const siblings = crListReplica.childrenMap.get(predecessorIdentifier)\n if (!siblings) continue\n\n if (siblings.length > 1)\n siblings.sort((a, b) => (a.uuidv7 > b.uuidv7 ? 1 : -1))\n\n const predecessor =\n predecessorIdentifier === '\\0'\n ? undefined\n : crListReplica.parentMap.get(predecessorIdentifier)\n if (\n predecessor &&\n !predecessor.prev &&\n !predecessor.next &&\n crListReplica.cursor !== predecessor\n )\n continue\n let prev: CRListStateEntry<T> = predecessor ?? crListReplica.cursor\n const predecessorNext = predecessor?.next\n if (siblings.length === 1) {\n const sibling = siblings[0]\n insertBetween<T>(prev, sibling, sibling.next)\n prev = sibling\n if (predecessorNext && predecessorNext !== sibling) {\n prev.next = predecessorNext\n predecessorNext.prev = prev\n } else {\n prev.next = undefined\n }\n if (!predecessorNext) crListReplica.cursor = prev\n resolvedSiblingPredecessors.add(predecessorIdentifier)\n hasProgress = true\n continue\n }\n const siblingSet = new Set(siblings)\n for (let index = 0; index < siblings.length; index++) {\n const sibling = siblings[index]\n const next = siblings[index + 1]\n\n insertBetween<T>(prev, sibling, sibling.next)\n prev = sibling\n\n if (next) {\n prev.next = next\n next.prev = prev\n } else if (predecessorNext && !siblingSet.has(predecessorNext)) {\n prev.next = predecessorNext\n predecessorNext.prev = prev\n } else {\n prev.next = undefined\n }\n }\n if (!predecessorNext) crListReplica.cursor = prev\n resolvedSiblingPredecessors.add(predecessorIdentifier)\n hasProgress = true\n }\n }\n crListReplica.size = crListReplica.parentMap.size\n}\n","import type {\n CRListState,\n CRListSnapshotEntry,\n CRListStateEntry,\n} from '../../.types/index.js'\nimport { isUuidV7, safeStructuredClone } from '@sovereignbase/utils'\nexport function snapshotValueToLinkedListValue<T>(\n valueEntry: CRListSnapshotEntry<T>,\n crListReplica: CRListState<T>\n): CRListStateEntry<T> {\n if (\n !isUuidV7(valueEntry.uuidv7) ||\n crListReplica.tombstones.has(valueEntry.uuidv7) ||\n crListReplica.parentMap.has(valueEntry.uuidv7) ||\n (!isUuidV7(valueEntry.predecessor) &&\n valueEntry.predecessor !== '\\0' &&\n !crListReplica.tombstones.has(valueEntry.predecessor))\n )\n return undefined\n\n const [cloned, copiedValue] = safeStructuredClone(valueEntry.value)\n\n if (!cloned) return undefined\n return {\n uuidv7: valueEntry.uuidv7,\n value: copiedValue,\n predecessor: valueEntry.predecessor,\n index: 0,\n next: undefined,\n prev: undefined,\n }\n}\n","import type {\n CRListState,\n CRListStateEntry,\n CRListDelta,\n} from '../../.types/index.js'\nexport function updateEntryToMaps<T>(\n crListReplica: CRListState<T>,\n linkedListEntry: NonNullable<CRListStateEntry<T>>,\n deltaBuf?: CRListDelta<T>\n): void {\n crListReplica.parentMap.set(linkedListEntry.uuidv7, linkedListEntry)\n const siblings = crListReplica.childrenMap.get(linkedListEntry.predecessor)\n if (siblings) {\n siblings.push(linkedListEntry)\n } else {\n crListReplica.childrenMap.set(linkedListEntry.predecessor, [\n linkedListEntry,\n ])\n }\n if (deltaBuf && !Array.isArray(deltaBuf.values)) deltaBuf.values = []\n if (deltaBuf?.values)\n deltaBuf.values.push({\n uuidv7: linkedListEntry.uuidv7,\n value: linkedListEntry.value,\n predecessor: linkedListEntry.predecessor,\n })\n}\n","import type { CRListState, CRListStateEntry } from '../../.types/index.js'\nexport function deleteEntryFromMaps<T>(\n crListReplica: CRListState<T>,\n linkedListEntry: NonNullable<CRListStateEntry<T>>\n): void {\n crListReplica.parentMap.delete(linkedListEntry.uuidv7)\n const siblings = crListReplica.childrenMap.get(linkedListEntry.predecessor)\n if (!siblings) return\n const index = siblings.indexOf(linkedListEntry)\n if (index !== -1) siblings.splice(index, 1)\n}\n","import type {\n CRListDelta,\n CRListState,\n CRListStateEntry,\n} from '../../.types/index.js'\nimport { deleteEntryFromMaps } from '../deleteEntryFromMaps/index.js'\n\nexport function deleteLinkedEntry<T>(\n crListReplica: CRListState<T>,\n linkedListEntry: NonNullable<CRListStateEntry<T>>,\n deltaBuf?: CRListDelta<T>\n): void {\n const prev = linkedListEntry.prev\n const next = linkedListEntry.next\n crListReplica.tombstones.add(linkedListEntry.uuidv7)\n if (deltaBuf && !Array.isArray(deltaBuf.tombstones)) deltaBuf.tombstones = []\n deltaBuf?.tombstones?.push(linkedListEntry.uuidv7)\n if (prev) prev.next = next\n if (next) {\n next.prev = prev\n }\n void deleteEntryFromMaps<T>(crListReplica, linkedListEntry)\n if (crListReplica.cursor === linkedListEntry)\n crListReplica.cursor = next ?? prev\n linkedListEntry.prev = undefined\n linkedListEntry.next = undefined\n crListReplica.size = crListReplica.parentMap.size\n}\n","import type {\n CRListDelta,\n CRListState,\n CRListStateEntry,\n} from '../../.types/index.js'\nimport { deleteEntryFromMaps } from '../deleteEntryFromMaps/index.js'\nimport { updateEntryToMaps } from '../updateEntryToMaps/index.js'\n\nexport function moveEntryToPredecessor<T>(\n crListReplica: CRListState<T>,\n linkedListEntry: NonNullable<CRListStateEntry<T>>,\n predecessor: string,\n deltaBuf?: CRListDelta<T>\n): void {\n void deleteEntryFromMaps<T>(crListReplica, linkedListEntry)\n linkedListEntry.predecessor = predecessor\n void updateEntryToMaps<T>(crListReplica, linkedListEntry, deltaBuf)\n}\n","export function indexFromPropertyKey(\n index: string | symbol\n): number | undefined {\n if (typeof index !== 'string' || !/^(0|[1-9]\\d*)$/.test(index))\n return undefined\n const listIndex = Number(index)\n return Number.isSafeInteger(listIndex) ? listIndex : undefined\n}\n","import { isUuidV7, prototype } from '@sovereignbase/utils'\nimport {\n CRListSnapshot,\n CRListState,\n CRListStateEntry,\n} from '../../../.types/index.js'\nimport {\n flattenAndLinkTrustedState,\n assertListIndices,\n snapshotValueToLinkedListValue,\n updateEntryToMaps,\n} from '../../../.helpers/index.js'\n\n/**\n * Creates a local CRList replica from an optional snapshot.\n *\n * Invalid snapshot records are ignored. Accepted values are cloned, indexed by\n * UUIDv7, linked through their predecessor buckets, and exposed as a live\n * doubly-linked list.\n *\n * @param snapshot Optional serializable CRList state.\n * @returns A hydrated CRList replica.\n *\n * Time complexity: O(n log n + t + c), worst case O(n^2 + t + c)\n * - n = snapshot value entry count\n * - t = snapshot tombstone count\n * - c = cloned value payload\n *\n * Space complexity: O(n + t + c)\n */\nexport function __create<T>(snapshot?: CRListSnapshot<T>): CRListState<T> {\n const crListReplica: CRListState<T> = {\n size: 0,\n cursor: undefined,\n tombstones: new Set<string>(),\n parentMap: new Map<string, NonNullable<CRListStateEntry<T>>>(),\n childrenMap: new Map<string, Array<NonNullable<CRListStateEntry<T>>>>(),\n }\n if (!snapshot || prototype(snapshot) !== 'record') return crListReplica\n\n /** Hydrate tombstone entries. */\n if (\n Object.hasOwn(snapshot, 'tombstones') &&\n Array.isArray(snapshot.tombstones)\n ) {\n for (const tombstone of snapshot.tombstones) {\n if (crListReplica.tombstones.has(tombstone) || !isUuidV7(tombstone))\n continue\n crListReplica.tombstones.add(tombstone)\n }\n }\n\n /** Hydrate value entries. */\n if (!Object.hasOwn(snapshot, 'values') || !Array.isArray(snapshot.values))\n return crListReplica\n // Build predecessor tree.\n for (const valueEntry of snapshot.values) {\n const linkedListEntry = snapshotValueToLinkedListValue<T>(\n valueEntry,\n crListReplica\n )\n if (!linkedListEntry) continue\n void updateEntryToMaps<T>(crListReplica, linkedListEntry)\n }\n // Flatten tree into a doubly linked list.\n void flattenAndLinkTrustedState<T>(crListReplica)\n // Write live-view indexes.\n void assertListIndices<T>(crListReplica)\n\n return crListReplica\n}\n","import { walkToIndex } from '../../../.helpers/index.js'\nimport { CRListState } from '../../../.types/index.js'\n\n/**\n * Reads the value at an index in the replica live view.\n *\n * The replica cursor is moved as part of the lookup. Successful reads return a\n * detached structured clone of the visible value, so mutating the returned\n * value does not mutate the replica itself. Out-of-bounds and empty list reads\n * resolve to `undefined` instead of throwing.\n *\n * @param targetIndex Index in the live list.\n * @param crListReplica Replica to read from.\n * @returns A detached copy of the value at `targetIndex`, or `undefined` when\n * no value is present.\n *\n * Time complexity: O(d), worst case O(n)\n * - d = distance from cursor to target index\n * - n = list size\n *\n * Space complexity: O(1)\n */\nexport function __read<T>(\n targetIndex: number,\n crListReplica: CRListState<T>\n): T | undefined {\n try {\n void walkToIndex<T>(targetIndex, crListReplica)\n return structuredClone(crListReplica?.cursor?.value)\n } catch {\n return undefined\n }\n}\n","import { CRListError } from '../../../.errors/class.js'\nimport { safeStructuredClone } from '@sovereignbase/utils'\nimport {\n updateEntryToMaps,\n deleteEntryFromMaps,\n walkToIndex,\n moveEntryToPredecessor,\n insertBetween,\n} from '../../../.helpers/index.js'\nimport { v7 as uuidv7 } from 'uuid'\nimport {\n CRListChange,\n CRListDelta,\n CRListState,\n CRListStateEntry,\n} from '../../../.types/index.js'\n/**\n * Applies a local value mutation to the replica live view.\n *\n * The update can replace a range starting at the target entry, insert values\n * before it, or insert values after it. The returned delta is suitable for\n * gossip and the returned change describes the local live-view patch.\n *\n * @param listIndex Target index in the live list.\n * @param listValues Values to insert or overwrite.\n * @param crListReplica Replica to mutate.\n * @param mode Mutation mode relative to `listIndex`.\n * @returns A local change and gossip delta, or `false` if no mutation occurred.\n *\n * Time complexity: O(d + v + r + vk + c), worst case O(vn + c)\n * - d = distance from cursor to target index\n * - v = amount of input values\n * - r = amount of nodes after inserted values whose indexes must be shifted\n * - k = sibling bucket size when predecessor bucket is updated\n * - c = cloned value payload size across all input values\n *\n * Space complexity: O(v + c)\n */\nexport function __update<T>(\n listIndex: number,\n listValues: Array<T>,\n crListReplica: CRListState<T>,\n mode: 'overwrite' | 'before' | 'after'\n): { change: CRListChange<T>; delta: CRListDelta<T> } | false {\n if (listIndex < 0 || listIndex > crListReplica.size)\n throw new CRListError('INDEX_OUT_OF_BOUNDS')\n if (!Array.isArray(listValues))\n throw new CRListError(\n 'UPDATE_EXPECTED_AN_ARRAY',\n '`listValues` must be an Array'\n )\n if (listValues.length === 0) return false\n const change: CRListChange<T> = {}\n const delta: CRListDelta<T> = { values: [], tombstones: [] }\n let shiftCursor: CRListStateEntry<T>\n for (const listValue of listValues) {\n const [cloned, copiedValue] = safeStructuredClone(listValue)\n\n if (!cloned) throw new CRListError('VALUE_NOT_CLONEABLE')\n\n const v7 = uuidv7()\n\n const linkedListEntry: NonNullable<CRListStateEntry<T>> = {\n uuidv7: v7,\n value: copiedValue,\n predecessor: '\\0',\n index: 0,\n next: undefined,\n prev: undefined,\n }\n\n switch (mode) {\n case 'overwrite': {\n if (listIndex === crListReplica.size) {\n if (crListReplica.size === 0) {\n crListReplica.cursor = linkedListEntry\n void updateEntryToMaps<T>(crListReplica, linkedListEntry, delta)\n change[linkedListEntry.index] = linkedListEntry.value\n break\n }\n void walkToIndex<T>(crListReplica.size - 1, crListReplica)\n if (!crListReplica.cursor) return false\n linkedListEntry.index = crListReplica.cursor.index + 1\n linkedListEntry.predecessor = crListReplica.cursor.uuidv7\n insertBetween<T>(crListReplica.cursor, linkedListEntry, undefined)\n void updateEntryToMaps<T>(crListReplica, linkedListEntry, delta)\n crListReplica.cursor = linkedListEntry\n change[linkedListEntry.index] = structuredClone(linkedListEntry.value)\n break\n }\n void walkToIndex<T>(listIndex, crListReplica)\n if (!crListReplica.cursor) return false\n const entryToOverwrite = crListReplica.cursor\n\n linkedListEntry.predecessor = entryToOverwrite.predecessor\n linkedListEntry.index = entryToOverwrite.index\n insertBetween<T>(\n entryToOverwrite.prev,\n linkedListEntry,\n entryToOverwrite.next\n )\n if (entryToOverwrite.next) {\n if (entryToOverwrite.next.predecessor === entryToOverwrite.uuidv7) {\n void moveEntryToPredecessor<T>(\n crListReplica,\n entryToOverwrite.next,\n linkedListEntry.uuidv7,\n delta\n )\n }\n }\n void updateEntryToMaps<T>(crListReplica, linkedListEntry, delta)\n crListReplica.tombstones.add(entryToOverwrite.uuidv7)\n delta.tombstones?.push(entryToOverwrite.uuidv7)\n void deleteEntryFromMaps<T>(crListReplica, entryToOverwrite)\n entryToOverwrite.next = undefined\n entryToOverwrite.prev = undefined\n crListReplica.cursor = linkedListEntry\n change[linkedListEntry.index] = structuredClone(linkedListEntry.value)\n break\n }\n case 'after': {\n if (crListReplica.size === 0 && listIndex === 0) {\n crListReplica.cursor = linkedListEntry\n void updateEntryToMaps<T>(crListReplica, linkedListEntry, delta)\n change[linkedListEntry.index] = structuredClone(linkedListEntry.value)\n break\n }\n if (listIndex === crListReplica.size) {\n void walkToIndex<T>(crListReplica.size - 1, crListReplica)\n } else {\n void walkToIndex<T>(listIndex, crListReplica)\n }\n if (!crListReplica.cursor) return false\n const next =\n listIndex === crListReplica.size\n ? undefined\n : crListReplica.cursor.next\n shiftCursor = next\n linkedListEntry.index = crListReplica.cursor.index + 1\n linkedListEntry.predecessor = crListReplica.cursor.uuidv7\n insertBetween<T>(crListReplica.cursor, linkedListEntry, next)\n if (next) {\n if (next.predecessor === crListReplica.cursor.uuidv7) {\n void moveEntryToPredecessor<T>(\n crListReplica,\n next,\n linkedListEntry.uuidv7,\n delta\n )\n }\n }\n void updateEntryToMaps<T>(crListReplica, linkedListEntry, delta)\n crListReplica.cursor = linkedListEntry\n change[linkedListEntry.index] = structuredClone(linkedListEntry.value)\n break\n }\n case 'before': {\n if (crListReplica.size === 0 && listIndex === 0) {\n crListReplica.cursor = linkedListEntry\n void updateEntryToMaps<T>(crListReplica, linkedListEntry, delta)\n change[linkedListEntry.index] = structuredClone(linkedListEntry.value)\n mode = 'after'\n listIndex = linkedListEntry.index - 1\n break\n }\n void walkToIndex<T>(listIndex, crListReplica)\n if (!crListReplica.cursor) return false\n const prev = crListReplica.cursor.prev\n shiftCursor = crListReplica.cursor\n linkedListEntry.index = crListReplica.cursor.index\n linkedListEntry.predecessor = prev?.uuidv7 ?? '\\0'\n insertBetween<T>(prev, linkedListEntry, crListReplica.cursor)\n if (crListReplica.cursor.predecessor === linkedListEntry.predecessor) {\n void moveEntryToPredecessor<T>(\n crListReplica,\n crListReplica.cursor,\n linkedListEntry.uuidv7,\n delta\n )\n }\n void updateEntryToMaps<T>(crListReplica, linkedListEntry, delta)\n crListReplica.cursor = linkedListEntry\n change[linkedListEntry.index] = structuredClone(linkedListEntry.value)\n mode = 'after'\n listIndex = linkedListEntry.index - 1\n\n break\n }\n }\n crListReplica.size = crListReplica.parentMap.size\n listIndex++\n }\n if (mode !== 'overwrite')\n while (shiftCursor) {\n shiftCursor.index += listValues.length\n shiftCursor = shiftCursor.next\n }\n return { change, delta }\n}\n","import { deleteLinkedEntry, walkToIndex } from '../../../.helpers/index.js'\nimport { CRListError } from '../../../.errors/class.js'\nimport type {\n CRListChange,\n CRListDelta,\n CRListState,\n CRListStateEntry,\n} from '../../../.types/index.js'\n\n/**\n * Deletes a range from the replica live view.\n *\n * With no indexes, the full list is deleted. With only `startIndex`, all entries\n * from `startIndex` onward are deleted. With both indexes, the deleted range is\n * `[startIndex, endIndex)`.\n *\n * @param crListReplica Replica to mutate.\n * @param startIndex Inclusive start index. Defaults to `0`.\n * @param endIndex Exclusive end index. Defaults to the current list size.\n * @returns A local change and gossip delta, or `false` if nothing was deleted.\n *\n * Time complexity: O(d + qk + r), worst case O(n^2)\n * - d = distance from cursor to target index\n * - q = amount of deleted nodes\n * - r = amount of nodes after the deleted range whose indexes must be shifted\n * - k = sibling bucket size when deleted entries are removed from buckets\n *\n * Space complexity: O(q)\n */\nexport function __delete<T>(\n crListReplica: CRListState<T>,\n startIndex?: number,\n endIndex?: number\n): { change: CRListChange<T>; delta: CRListDelta<T> } | false {\n const change: CRListChange<T> = {}\n const delta: CRListDelta<T> = { values: [], tombstones: [] }\n const listIndex = startIndex ?? 0\n const targetEndIndex = endIndex ?? crListReplica.size\n if (\n listIndex < 0 ||\n targetEndIndex < listIndex ||\n listIndex > crListReplica.size\n )\n throw new CRListError('INDEX_OUT_OF_BOUNDS')\n const deleteCount = Math.min(targetEndIndex, crListReplica.size) - listIndex\n if (deleteCount <= 0) return false\n\n void walkToIndex<T>(listIndex, crListReplica)\n if (!crListReplica.cursor) return false\n\n let current: CRListStateEntry<T> = crListReplica.cursor\n let deleted = 0\n\n while (current && deleted < deleteCount) {\n const next: CRListStateEntry<T> = current.next\n change[current.index] = undefined\n void deleteLinkedEntry<T>(crListReplica, current, delta)\n current = next\n deleted++\n }\n\n crListReplica.size = crListReplica.parentMap.size\n\n while (current) {\n current.index -= deleted\n current = current.next\n }\n\n return { change, delta }\n}\n","import type {\n CRListChange,\n CRListDelta,\n CRListState,\n CRListStateEntry,\n} from '../../../.types/index.js'\nimport {\n snapshotValueToLinkedListValue,\n updateEntryToMaps,\n flattenAndLinkTrustedState,\n assertListIndices,\n deleteLinkedEntry,\n moveEntryToPredecessor,\n} from '../../../.helpers/index.js'\nimport { prototype, isUuidV7 } from '@sovereignbase/utils'\n\n/**\n * Merges a remote CRList delta into the local replica.\n *\n * Accepted tombstones update the local live view and accepted values are attached\n * to the predecessor tree. Tail-append deltas are linked incrementally; deltas\n * that can affect ordering fall back to deterministic relinking.\n *\n * @param crListReplica Replica to mutate.\n * @param crListDelta Remote gossip delta.\n * @returns A minimal local change patch, or `false` when the delta is ignored.\n *\n * Time complexity: O(v + t + c) for tail-append deltas; O(n + t + qk) for tombstone-only deletes; otherwise O(n log n + v + t + m*k + c)\n * Worst case: O(n^2 + (v + t)n + c)\n * - n = replica value entry count after merge\n * - v = delta value entry count\n * - t = delta tombstone count\n * - q = amount of live entries deleted by tombstones\n * - m = entries moved between predecessor buckets\n * - k = sibling bucket size when entries are removed from buckets\n * - c = cloned delta value payload size\n *\n * Space complexity: O(n + v + t + c)\n */\nexport function __merge<T>(\n crListReplica: CRListState<T>,\n crListDelta: CRListDelta<T>\n): CRListChange<T> | false {\n if (!crListDelta || prototype(crListDelta) !== 'record') return false\n const newVals: Array<NonNullable<CRListStateEntry<T>>> = []\n const newTombsIndices: Array<number> = []\n const change: CRListChange<T> = {}\n let needsRelink = false\n\n /** Apply tombstone entries. */\n if (\n Object.hasOwn(crListDelta, 'tombstones') &&\n Array.isArray(crListDelta.tombstones)\n ) {\n for (const tombstone of crListDelta.tombstones) {\n if (crListReplica.tombstones.has(tombstone) || !isUuidV7(tombstone))\n continue\n crListReplica.tombstones.add(tombstone)\n const linkedListEntry = crListReplica.parentMap.get(tombstone)\n if (linkedListEntry) {\n void newTombsIndices.push(linkedListEntry.index)\n void deleteLinkedEntry<T>(crListReplica, linkedListEntry)\n needsRelink = true\n }\n }\n }\n\n /** Apply value entries. */\n if (\n !Object.hasOwn(crListDelta, 'values') ||\n !Array.isArray(crListDelta.values)\n ) {\n if (newTombsIndices.length === 0) return false\n void assertListIndices<T>(crListReplica)\n for (const index of newTombsIndices) {\n change[index] = undefined\n }\n return change\n }\n // Attach accepted values to the predecessor tree.\n for (const valueEntry of crListDelta.values) {\n const existingEntry = crListReplica.parentMap.get(valueEntry.uuidv7)\n if (existingEntry) {\n if (\n crListReplica.tombstones.has(valueEntry.uuidv7) ||\n (!isUuidV7(valueEntry.predecessor) && valueEntry.predecessor !== '\\0')\n )\n continue\n if (existingEntry.predecessor >= valueEntry.predecessor) continue\n void moveEntryToPredecessor<T>(\n crListReplica,\n existingEntry,\n valueEntry.predecessor\n )\n needsRelink = true\n void newVals.push(existingEntry)\n continue\n }\n const linkedListEntry = snapshotValueToLinkedListValue<T>(\n valueEntry,\n crListReplica\n )\n if (!linkedListEntry) continue\n const predecessor =\n linkedListEntry.predecessor === '\\0'\n ? undefined\n : crListReplica.parentMap.get(linkedListEntry.predecessor)\n void updateEntryToMaps<T>(crListReplica, linkedListEntry)\n void newVals.push(linkedListEntry)\n if (!needsRelink && linkedListEntry.predecessor === '\\0') {\n if (crListReplica.size === 0) {\n crListReplica.cursor = linkedListEntry\n crListReplica.size = crListReplica.parentMap.size\n } else {\n needsRelink = true\n }\n } else if (!needsRelink && predecessor && !predecessor.next) {\n linkedListEntry.prev = predecessor\n linkedListEntry.index = predecessor.index + 1\n predecessor.next = linkedListEntry\n crListReplica.cursor = linkedListEntry\n crListReplica.size = crListReplica.parentMap.size\n } else {\n needsRelink = true\n }\n }\n if (needsRelink) {\n // Flatten tree into a doubly linked list.\n void flattenAndLinkTrustedState<T>(crListReplica)\n // Write live-view indexes.\n void assertListIndices<T>(crListReplica)\n }\n\n if (newTombsIndices.length === 0 && newVals.length === 0) return false\n\n for (const index of newTombsIndices) {\n change[index] = undefined\n }\n for (const val of newVals) {\n change[val.index] = structuredClone(val.value)\n }\n\n return change\n}\n","import type { CRListAck, CRListState } from '../../../.types/index.js'\n\n/**\n * Returns the replica tombstone acknowledgement frontier.\n *\n * The frontier is the greatest tombstone identifier currently retained by the\n * replica. Peers can use it as input for tombstone garbage collection.\n *\n * @param crListReplica Replica to acknowledge.\n * @returns The acknowledgement frontier, or `false` when there are no tombstones.\n *\n * Time complexity: O(t)\n * - t = replica tombstone count\n *\n * Space complexity: O(1)\n */\nexport function __acknowledge<T>(\n crListReplica: CRListState<T>\n): CRListAck | false {\n let frontier: CRListAck | false = false\n crListReplica.tombstones.forEach((tombstone) => {\n if (frontier === false || frontier < tombstone) frontier = tombstone\n })\n if (typeof frontier === 'string') return frontier\n return false\n}\n","import { CRListAck, CRListState } from '../../../.types/index.js'\n\n/**\n * Removes tombstones acknowledged by all supplied frontiers.\n *\n * The minimum frontier is used as the safe collection boundary. Tombstones less\n * than or equal to that boundary are removed from the local replica.\n *\n * @param frontiers Acknowledgement frontiers received from peers.\n * @param crListReplica Replica whose tombstones will be collected.\n *\n * Time complexity: O(f log f + t)\n * - f = frontier count\n * - t = replica tombstone count\n *\n * Space complexity: O(1)\n */\nexport function __garbageCollect<T>(\n frontiers: Array<CRListAck>,\n crListReplica: CRListState<T>\n): void {\n if (!Array.isArray(frontiers)) return\n const frontier = frontiers.sort().shift()\n if (typeof frontier !== 'string') return\n crListReplica.tombstones.forEach((tombstone, __, tombstones) => {\n if (tombstone <= frontier) {\n tombstones.delete(tombstone)\n }\n })\n}\n","import { CRListError } from '../../../.errors/class.js'\nimport { CRListState, CRListSnapshot } from '../../../.types/index.js'\n\n/**\n * Creates a full serializable CRList snapshot from the current replica state.\n *\n * The snapshot contains every live value entry and all retained tombstones. Value\n * payloads are cloned so callers cannot mutate the replica through the snapshot.\n *\n * @param crListReplica Replica to snapshot.\n * @returns A full snapshot suitable for hydration or transport.\n *\n * Time complexity: O(n + t + c)\n * - n = replica value entry count\n * - t = replica tombstone count\n * - c = cloned value payload size\n *\n * Space complexity: O(n + t + c)\n */\nexport function __snapshot<T>(\n crListReplica: CRListState<T>\n): CRListSnapshot<T> {\n return {\n values: Array.from(crListReplica.parentMap.values()).map(\n (linkedListEntry) => {\n if (!linkedListEntry) throw new CRListError('LIST_INTEGRITY_VIOLATION')\n return {\n uuidv7: linkedListEntry.uuidv7,\n value: structuredClone(linkedListEntry.value),\n predecessor: linkedListEntry.predecessor,\n }\n }\n ),\n tombstones: Array.from(crListReplica.tombstones),\n }\n}\n","import { indexFromPropertyKey } from '../.helpers/index.js'\nimport type {\n CRListState,\n CRListSnapshot,\n CRListEventListenerFor,\n CRListEventMap,\n CRListDelta,\n CRListAck,\n} from '../.types/index.js'\nimport { __create, __read, __update, __delete } from '../core/crud/index.js'\nimport {\n __merge,\n __acknowledge,\n __garbageCollect,\n __snapshot,\n} from '../core/mags/index.js'\n\n/**\n * A convergent replicated list.\n *\n * Numeric property access reads and mutates the live list projection:\n * `list[0]` reads a detached copy of an entry, `list[0] = value` writes an\n * entry, and `delete list[0]` removes one entry. Iteration and `forEach()`\n * likewise expose detached copies rather than mutable references into the\n * replica state. Local mutations emit `delta` and `change` events; remote\n * merges emit `change` events.\n *\n * @typeParam T - The value type stored in the list.\n */\nexport class CRList<T> {\n /**\n * Reads or overwrites an entry in the live list projection by index.\n *\n * Reads return detached copies.\n */\n [index: number]: T\n declare private readonly state: CRListState<T>\n declare private readonly eventTarget: EventTarget\n\n /**\n * Creates a replicated list from an optional serializable snapshot.\n *\n * @param snapshot - A previously emitted CRList snapshot.\n */\n constructor(snapshot?: CRListSnapshot<T>) {\n Object.defineProperties(this, {\n state: {\n value: __create<T>(snapshot),\n enumerable: false,\n configurable: false,\n writable: false,\n },\n eventTarget: {\n value: new EventTarget(),\n enumerable: false,\n configurable: false,\n writable: false,\n },\n })\n\n return new Proxy(this, {\n get(target, index, receiver) {\n const listIndex = indexFromPropertyKey(index)\n // Preserve normal property access for non-index keys.\n if (listIndex === undefined) return Reflect.get(target, index, receiver)\n return __read(listIndex, target.state)\n },\n has(target, index) {\n const listIndex = indexFromPropertyKey(index)\n // Preserve normal property checks for non-index keys.\n if (listIndex === undefined) return Reflect.has(target, index)\n return listIndex >= 0 && listIndex < target.state.size\n },\n set(target, index, value) {\n const listIndex = indexFromPropertyKey(index)\n if (listIndex === undefined) return false\n try {\n const result = __update(listIndex, [value], target.state, 'overwrite')\n if (!result) return false\n const { delta, change } = result\n if (delta)\n void target.eventTarget.dispatchEvent(\n new CustomEvent('delta', { detail: delta })\n )\n if (change)\n void target.eventTarget.dispatchEvent(\n new CustomEvent('change', { detail: change })\n )\n return true\n } catch {\n return false\n }\n },\n deleteProperty(target, index) {\n const listIndex = indexFromPropertyKey(index)\n if (listIndex === undefined) return false\n try {\n const result = __delete(target.state, listIndex, listIndex + 1)\n if (!result) return false\n const { delta, change } = result\n if (delta) {\n void target.eventTarget.dispatchEvent(\n new CustomEvent('delta', { detail: delta })\n )\n }\n if (change) {\n void target.eventTarget.dispatchEvent(\n new CustomEvent('change', { detail: change })\n )\n }\n return true\n } catch {\n return false\n }\n },\n ownKeys(target) {\n return [\n ...Reflect.ownKeys(target),\n ...Array.from({ length: target.size }, (_, index) => String(index)),\n ]\n },\n\n getOwnPropertyDescriptor(target, index) {\n const listIndex = indexFromPropertyKey(index)\n\n if (listIndex !== undefined && listIndex < target.size) {\n return {\n value: __read(listIndex, target.state),\n writable: true,\n enumerable: true,\n configurable: true,\n }\n }\n // Preserve normal property checks for non-index keys.\n return Reflect.getOwnPropertyDescriptor(target, index)\n },\n })\n }\n /**\n * The current number of live entries.\n */\n get size(): number {\n return this.state.size\n }\n /**\n * Inserts a value before an index.\n *\n * If `beforeIndex` is omitted, the value is inserted at the start of the list.\n *\n * @param value - The value to insert.\n * @param beforeIndex - The index to insert before.\n */\n prepend(value: T, beforeIndex?: number): void {\n const result = __update<T>(beforeIndex ?? 0, [value], this.state, 'before')\n if (!result) return\n const { delta, change } = result\n if (delta)\n void this.eventTarget.dispatchEvent(\n new CustomEvent('delta', { detail: delta })\n )\n if (change)\n void this.eventTarget.dispatchEvent(\n new CustomEvent('change', { detail: change })\n )\n }\n /**\n * Inserts a value after an index.\n *\n * If `afterIndex` is omitted, the value is appended at the end of the list.\n *\n * @param value - The value to insert.\n * @param afterIndex - The index to insert after.\n */\n append(value: T, afterIndex?: number): void {\n const result = __update<T>(\n afterIndex ?? this.state.size,\n [value],\n this.state,\n 'after'\n )\n if (!result) return\n const { delta, change } = result\n if (delta)\n void this.eventTarget.dispatchEvent(\n new CustomEvent('delta', { detail: delta })\n )\n if (change)\n void this.eventTarget.dispatchEvent(\n new CustomEvent('change', { detail: change })\n )\n }\n /**\n * Removes the entry at an index.\n *\n * @param index - The index to remove.\n */\n remove(index: number): void {\n const result = __delete(this.state, index, index + 1)\n if (!result) return\n const { delta, change } = result\n if (delta)\n void this.eventTarget.dispatchEvent(\n new CustomEvent('delta', { detail: delta })\n )\n if (change)\n void this.eventTarget.dispatchEvent(\n new CustomEvent('change', { detail: change })\n )\n }\n /**\n * Applies a remote gossip delta to this list.\n *\n * Emits a `change` event when the merge changes the live projection.\n *\n * @param delta - The remote CRList delta to merge.\n */\n merge(delta: CRListDelta<T>): void {\n const change = __merge(this.state, delta)\n if (change)\n void this.eventTarget.dispatchEvent(\n new CustomEvent('change', { detail: change })\n )\n }\n /**\n * Emits an acknowledgement frontier for currently retained tombstones.\n */\n acknowledge(): void {\n const ack = __acknowledge(this.state)\n if (ack)\n void this.eventTarget.dispatchEvent(\n new CustomEvent('ack', { detail: ack })\n )\n }\n /**\n * Garbage-collects tombstones that are covered by acknowledgement frontiers.\n *\n * @param frontiers - Replica acknowledgement frontiers.\n */\n garbageCollect(frontiers: Array<CRListAck>): void {\n void __garbageCollect(frontiers, this.state)\n }\n /**\n * Emits the current serializable list snapshot.\n */\n snapshot(): void {\n const snapshot = __snapshot<T>(this.state)\n if (snapshot)\n void this.eventTarget.dispatchEvent(\n new CustomEvent('snapshot', { detail: snapshot })\n )\n }\n /**\n * Registers an event listener.\n *\n * @param type - The event type to listen for.\n * @param listener - The listener to register.\n * @param options - Listener registration options.\n */\n addEventListener<K extends keyof CRListEventMap<T>>(\n type: K,\n listener: CRListEventListenerFor<T, K> | null,\n options?: boolean | AddEventListenerOptions\n ): void {\n this.eventTarget.addEventListener(\n type,\n listener as EventListenerOrEventListenerObject | null,\n options\n )\n }\n\n /**\n * Removes an event listener.\n *\n * @param type - The event type to stop listening for.\n * @param listener - The listener to remove.\n * @param options - Listener removal options.\n */\n removeEventListener<K extends keyof CRListEventMap<T>>(\n type: K,\n listener: CRListEventListenerFor<T, K> | null,\n options?: boolean | EventListenerOptions\n ): void {\n this.eventTarget.removeEventListener(\n type,\n listener as EventListenerOrEventListenerObject | null,\n options\n )\n }\n /**\n * Returns a serializable snapshot representation of this list.\n *\n * Called automatically by `JSON.stringify`.\n */\n toJSON(): CRListSnapshot<T> {\n return __snapshot<T>(this.state)\n }\n /**\n * Returns this list as a JSON string.\n */\n toString(): string {\n return JSON.stringify(this)\n }\n /**\n * Returns the Node.js console inspection representation.\n */\n [Symbol.for('nodejs.util.inspect.custom')](): CRListSnapshot<T> {\n return this.toJSON()\n }\n /**\n * Returns the Deno console inspection representation.\n */\n [Symbol.for('Deno.customInspect')](): CRListSnapshot<T> {\n return this.toJSON()\n }\n /**\n * Iterates over detached copies of the current live values in index order.\n */\n *[Symbol.iterator](): IterableIterator<T> {\n for (let index = 0; index < this.size; index++) {\n const value = this[index]\n yield value\n }\n }\n /**\n * Calls a function once for each live value copy in index order.\n *\n * Callback values are detached copies, so mutating them does not mutate the\n * list.\n *\n * @param callback - Function to call for each value copy.\n * @param thisArg - Optional `this` value for the callback.\n */\n forEach(\n callback: (value: T, index: number, list: this) => void,\n thisArg?: unknown\n ): void {\n for (let index = 0; index < this.size; index++) {\n callback.call(thisArg, this[index], index, this)\n }\n }\n}\n"],"mappings":"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","names":["isUuidV7","isUuidV7","safeStructuredClone","safeStructuredClone","prototype","isUuidV7"]}
|
|
1
|
+
{"version":3,"sources":["../src/.helpers/assertListIndices/index.ts","../src/.errors/class.ts","../src/.helpers/walkToIndex/index.ts","../src/.helpers/insertBetween/index.ts","../src/.helpers/flattenAndLinkTrustedState/index.ts","../src/.helpers/transformSnapshotEntryToStateEntry/index.ts","../src/.helpers/updateEntryToMaps/index.ts","../src/.helpers/deleteEntryFromMaps/index.ts","../src/.helpers/deleteLinkedEntry/index.ts","../src/.helpers/moveEntryToPredecessor/index.ts","../src/.helpers/indexFromPropertyKey/index.ts","../src/core/crud/create/index.ts","../src/core/crud/read/index.ts","../src/core/crud/update/index.ts","../src/core/crud/delete/index.ts","../src/core/mags/merge/index.ts","../src/core/mags/acknowledge/index.ts","../src/core/mags/garbageCollect/index.ts","../src/core/mags/snapshot/index.ts","../src/CRList/class.ts"],"sourcesContent":["import type { CRListState } from '../../.types/index.js'\n\nexport function assertListIndices<T>(crListReplica: CRListState<T>): void {\n if (!crListReplica.cursor) return\n let index = crListReplica.size\n while (crListReplica.cursor.next)\n crListReplica.cursor = crListReplica.cursor.next\n\n while (index >= 1) {\n index--\n crListReplica.cursor.index = index\n if (crListReplica.cursor.prev === undefined) break\n crListReplica.cursor = crListReplica.cursor.prev\n }\n}\n","/**\n * Error codes thrown by {@link CRList}.\n */\nexport type CRListErrorCode =\n | 'VALUE_NOT_CLONEABLE'\n | 'INDEX_OUT_OF_BOUNDS'\n | 'LIST_EMPTY'\n | 'LIST_INTEGRITY_VIOLATION'\n | 'UPDATE_EXPECTED_AN_ARRAY'\n\n/**\n * Represents a typed CRList runtime error.\n */\nexport class CRListError extends Error {\n /**\n * The semantic error code for the failure.\n */\n readonly code: CRListErrorCode\n\n /**\n * Creates a typed CRList error.\n *\n * @param code - The semantic error code.\n * @param message - An optional human-readable detail message.\n */\n constructor(code: CRListErrorCode, message?: string) {\n const detail = message ?? code\n super(`{@sovereignbase/convergent-replicated-list} ${detail}`)\n this.code = code\n this.name = 'CRListError'\n }\n}\n","import type { CRListState } from '../../.types/index.js'\nimport { CRListError } from '../../.errors/class.js'\n\nexport function walkToIndex<T>(\n targetIndex: number,\n crListReplica: CRListState<T>\n): void {\n if (targetIndex < 0 || targetIndex >= crListReplica.size)\n throw new CRListError('INDEX_OUT_OF_BOUNDS', 'Index out of bounds')\n if (!crListReplica.cursor)\n throw new CRListError('LIST_EMPTY', 'List is empty')\n const direction = crListReplica.cursor.index > targetIndex ? 'prev' : 'next'\n while (crListReplica.cursor && crListReplica.cursor.index !== targetIndex) {\n crListReplica.cursor = crListReplica.cursor[direction]\n }\n}\n","import type { CRListStateEntry } from '../../.types/index.js'\n\nexport function insertBetween<T>(\n prev: CRListStateEntry<T>,\n linkedListEntry: NonNullable<CRListStateEntry<T>>,\n next: CRListStateEntry<T>\n): void {\n linkedListEntry.prev = prev\n linkedListEntry.next = next\n if (prev) prev.next = linkedListEntry\n if (next) next.prev = linkedListEntry\n}\n","import type { CRListState, CRListStateEntry } from '../../.types/index.js'\nimport { insertBetween } from '../insertBetween/index.js'\nexport function flattenAndLinkTrustedState<T>(crListReplica: CRListState<T>) {\n crListReplica.cursor = undefined\n const resolvedSiblingPredecessors = new Set<string>()\n for (const entry of crListReplica.parentMap.values()) {\n if (!entry) continue\n entry.prev = undefined\n entry.next = undefined\n }\n const keys = [...crListReplica.childrenMap.keys()].sort((a, b) =>\n a > b ? 1 : -1\n )\n let hasProgress = true\n while (hasProgress) {\n hasProgress = false\n for (const predecessorIdentifier of keys) {\n if (resolvedSiblingPredecessors.has(predecessorIdentifier)) continue\n const siblings = crListReplica.childrenMap.get(predecessorIdentifier)\n if (!siblings) continue\n\n if (siblings.length > 1)\n siblings.sort((a, b) => (a.uuidv7 > b.uuidv7 ? 1 : -1))\n\n const predecessor =\n predecessorIdentifier === '\\0'\n ? undefined\n : crListReplica.parentMap.get(predecessorIdentifier)\n if (\n predecessor &&\n !predecessor.prev &&\n !predecessor.next &&\n crListReplica.cursor !== predecessor\n )\n continue\n let prev: CRListStateEntry<T> = predecessor ?? crListReplica.cursor\n const predecessorNext = predecessor?.next\n if (siblings.length === 1) {\n const sibling = siblings[0]\n insertBetween<T>(prev, sibling, sibling.next)\n prev = sibling\n if (predecessorNext && predecessorNext !== sibling) {\n prev.next = predecessorNext\n predecessorNext.prev = prev\n } else {\n prev.next = undefined\n }\n if (!predecessorNext) crListReplica.cursor = prev\n resolvedSiblingPredecessors.add(predecessorIdentifier)\n hasProgress = true\n continue\n }\n const siblingSet = new Set(siblings)\n for (let index = 0; index < siblings.length; index++) {\n const sibling = siblings[index]\n const next = siblings[index + 1]\n\n insertBetween<T>(prev, sibling, sibling.next)\n prev = sibling\n\n if (next) {\n prev.next = next\n next.prev = prev\n } else if (predecessorNext && !siblingSet.has(predecessorNext)) {\n prev.next = predecessorNext\n predecessorNext.prev = prev\n } else {\n prev.next = undefined\n }\n }\n if (!predecessorNext) crListReplica.cursor = prev\n resolvedSiblingPredecessors.add(predecessorIdentifier)\n hasProgress = true\n }\n }\n crListReplica.size = crListReplica.parentMap.size\n}\n","import type {\n CRListState,\n CRListSnapshotEntry,\n CRListStateEntry,\n} from '../../.types/index.js'\nimport { isUuidV7, safeStructuredClone } from '@sovereignbase/utils'\nexport function transformSnapshotEntryToStateEntry<T>(\n valueEntry: CRListSnapshotEntry<T>,\n crListReplica: CRListState<T>\n): CRListStateEntry<T> {\n if (valueEntry === null || valueEntry === undefined) return undefined\n if (\n !isUuidV7(valueEntry.uuidv7) ||\n crListReplica.tombstones.has(valueEntry.uuidv7) ||\n crListReplica.parentMap.has(valueEntry.uuidv7) ||\n (!isUuidV7(valueEntry.predecessor) &&\n valueEntry.predecessor !== '\\0' &&\n !crListReplica.tombstones.has(valueEntry.predecessor))\n )\n return undefined\n\n const [cloned, copiedValue] = safeStructuredClone(valueEntry.value)\n\n if (!cloned) return undefined\n return {\n uuidv7: valueEntry.uuidv7,\n value: copiedValue,\n predecessor: valueEntry.predecessor,\n index: 0,\n next: undefined,\n prev: undefined,\n }\n}\n","import type {\n CRListState,\n CRListStateEntry,\n CRListDelta,\n} from '../../.types/index.js'\nexport function updateEntryToMaps<T>(\n crListReplica: CRListState<T>,\n linkedListEntry: NonNullable<CRListStateEntry<T>>,\n deltaBuf?: CRListDelta<T>\n): void {\n crListReplica.parentMap.set(linkedListEntry.uuidv7, linkedListEntry)\n const siblings = crListReplica.childrenMap.get(linkedListEntry.predecessor)\n if (siblings) {\n siblings.push(linkedListEntry)\n } else {\n crListReplica.childrenMap.set(linkedListEntry.predecessor, [\n linkedListEntry,\n ])\n }\n if (deltaBuf && !Array.isArray(deltaBuf.values)) deltaBuf.values = []\n if (deltaBuf?.values)\n deltaBuf.values.push({\n uuidv7: linkedListEntry.uuidv7,\n value: linkedListEntry.value,\n predecessor: linkedListEntry.predecessor,\n })\n}\n","import type { CRListState, CRListStateEntry } from '../../.types/index.js'\nexport function deleteEntryFromMaps<T>(\n crListReplica: CRListState<T>,\n linkedListEntry: NonNullable<CRListStateEntry<T>>\n): void {\n crListReplica.parentMap.delete(linkedListEntry.uuidv7)\n const siblings = crListReplica.childrenMap.get(linkedListEntry.predecessor)\n if (!siblings) return\n const index = siblings.indexOf(linkedListEntry)\n if (index !== -1) siblings.splice(index, 1)\n}\n","import type {\n CRListDelta,\n CRListState,\n CRListStateEntry,\n} from '../../.types/index.js'\nimport { deleteEntryFromMaps } from '../deleteEntryFromMaps/index.js'\n\nexport function deleteLinkedEntry<T>(\n crListReplica: CRListState<T>,\n linkedListEntry: NonNullable<CRListStateEntry<T>>,\n deltaBuf?: CRListDelta<T>\n): void {\n const prev = linkedListEntry.prev\n const next = linkedListEntry.next\n crListReplica.tombstones.add(linkedListEntry.uuidv7)\n if (deltaBuf && !Array.isArray(deltaBuf.tombstones)) deltaBuf.tombstones = []\n deltaBuf?.tombstones?.push(linkedListEntry.uuidv7)\n if (prev) prev.next = next\n if (next) {\n next.prev = prev\n }\n void deleteEntryFromMaps<T>(crListReplica, linkedListEntry)\n if (crListReplica.cursor === linkedListEntry)\n crListReplica.cursor = next ?? prev\n linkedListEntry.prev = undefined\n linkedListEntry.next = undefined\n crListReplica.size = crListReplica.parentMap.size\n}\n","import type {\n CRListDelta,\n CRListState,\n CRListStateEntry,\n} from '../../.types/index.js'\nimport { deleteEntryFromMaps } from '../deleteEntryFromMaps/index.js'\nimport { updateEntryToMaps } from '../updateEntryToMaps/index.js'\n\nexport function moveEntryToPredecessor<T>(\n crListReplica: CRListState<T>,\n linkedListEntry: NonNullable<CRListStateEntry<T>>,\n predecessor: string,\n deltaBuf?: CRListDelta<T>\n): void {\n void deleteEntryFromMaps<T>(crListReplica, linkedListEntry)\n linkedListEntry.predecessor = predecessor\n void updateEntryToMaps<T>(crListReplica, linkedListEntry, deltaBuf)\n}\n","export function indexFromPropertyKey(\n index: string | symbol\n): number | undefined {\n if (typeof index !== 'string' || !/^(0|[1-9]\\d*)$/.test(index))\n return undefined\n const listIndex = Number(index)\n return Number.isSafeInteger(listIndex) ? listIndex : undefined\n}\n","import { isUuidV7, prototype } from '@sovereignbase/utils'\nimport {\n CRListSnapshot,\n CRListState,\n CRListStateEntry,\n} from '../../../.types/index.js'\nimport {\n flattenAndLinkTrustedState,\n assertListIndices,\n transformSnapshotEntryToStateEntry,\n updateEntryToMaps,\n} from '../../../.helpers/index.js'\n\n/**\n * Creates a local CRList replica from an optional snapshot.\n *\n * Invalid snapshot records are ignored. Accepted values are cloned, indexed by\n * UUIDv7, linked through their predecessor buckets, and exposed as a live\n * doubly-linked list.\n *\n * @param snapshot - Optional detached structured-clone-compatible CRList snapshot.\n * @returns - A hydrated CRList replica.\n *\n * Time complexity: O(n log n + t + c), worst case O(n^2 + t + c)\n * - n = snapshot value entry count\n * - t = snapshot tombstone count\n * - c = cloned value payload\n *\n * Space complexity: O(n + t + c)\n */\nexport function __create<T>(snapshot?: CRListSnapshot<T>): CRListState<T> {\n const crListReplica: CRListState<T> = {\n size: 0,\n cursor: undefined,\n tombstones: new Set<string>(),\n parentMap: new Map<string, NonNullable<CRListStateEntry<T>>>(),\n childrenMap: new Map<string, Array<NonNullable<CRListStateEntry<T>>>>(),\n }\n if (!snapshot || prototype(snapshot) !== 'record') return crListReplica\n\n /** Hydrate tombstone entries. */\n if (\n Object.hasOwn(snapshot, 'tombstones') &&\n Array.isArray(snapshot.tombstones)\n ) {\n for (const tombstone of snapshot.tombstones) {\n if (crListReplica.tombstones.has(tombstone) || !isUuidV7(tombstone))\n continue\n crListReplica.tombstones.add(tombstone)\n }\n }\n\n /** Hydrate value entries. */\n if (!Object.hasOwn(snapshot, 'values') || !Array.isArray(snapshot.values))\n return crListReplica\n // Build predecessor tree.\n for (const valueEntry of snapshot.values) {\n const linkedListEntry = transformSnapshotEntryToStateEntry<T>(\n valueEntry,\n crListReplica\n )\n if (!linkedListEntry) continue\n void updateEntryToMaps<T>(crListReplica, linkedListEntry)\n }\n // Flatten tree into a doubly linked list.\n void flattenAndLinkTrustedState<T>(crListReplica)\n // Write live-view indexes.\n void assertListIndices<T>(crListReplica)\n\n return crListReplica\n}\n","import { walkToIndex } from '../../../.helpers/index.js'\nimport { CRListState } from '../../../.types/index.js'\n\n/**\n * Reads the value at an index in the replica live view.\n *\n * The replica cursor is moved as part of the lookup. Successful reads return a\n * detached structured clone of the visible value, so mutating the returned\n * value does not mutate the replica itself. Out-of-bounds and empty list reads\n * resolve to `undefined` instead of throwing.\n *\n * @param targetIndex - Index in the live list.\n * @param crListReplica - Replica to read from.\n * @returns - A detached copy of the value at `targetIndex`, or `undefined` when\n * no value is present.\n *\n * Time complexity: O(d), worst case O(n)\n * - d = distance from cursor to target index\n * - n = list size\n *\n * Space complexity: O(1)\n */\nexport function __read<T>(\n targetIndex: number,\n crListReplica: CRListState<T>\n): T | undefined {\n try {\n void walkToIndex<T>(targetIndex, crListReplica)\n return structuredClone(crListReplica?.cursor?.value)\n } catch {\n return undefined\n }\n}\n","import { CRListError } from '../../../.errors/class.js'\nimport { safeStructuredClone } from '@sovereignbase/utils'\nimport {\n updateEntryToMaps,\n deleteEntryFromMaps,\n walkToIndex,\n moveEntryToPredecessor,\n insertBetween,\n} from '../../../.helpers/index.js'\nimport { v7 as uuidv7 } from 'uuid'\nimport {\n CRListChange,\n CRListDelta,\n CRListState,\n CRListStateEntry,\n} from '../../../.types/index.js'\n/**\n * Applies a local value mutation to the replica live view.\n *\n * The update can replace a range starting at the target entry, insert values\n * before it, or insert values after it. The returned delta is suitable for\n * gossip and the returned change describes the local live-view patch.\n *\n * @param listIndex - Target index in the live list.\n * @param listValues - Values to insert or overwrite.\n * @param crListReplica - Replica to mutate.\n * @param mode - Mutation mode relative to `listIndex`.\n * @returns - A local change and gossip delta, or `false` if no mutation occurred.\n *\n * Time complexity: O(d + v + r + vk + c), worst case O(vn + c)\n * - d = distance from cursor to target index\n * - v = amount of input values\n * - r = amount of nodes after inserted values whose indexes must be shifted\n * - k = sibling bucket size when predecessor bucket is updated\n * - c = cloned value payload size across all input values\n *\n * Space complexity: O(v + c)\n */\nexport function __update<T>(\n listIndex: number,\n listValues: Array<T>,\n crListReplica: CRListState<T>,\n mode: 'overwrite' | 'before' | 'after'\n): { change: CRListChange<T>; delta: CRListDelta<T> } | false {\n if (listIndex < 0 || listIndex > crListReplica.size)\n throw new CRListError('INDEX_OUT_OF_BOUNDS')\n if (!Array.isArray(listValues))\n throw new CRListError(\n 'UPDATE_EXPECTED_AN_ARRAY',\n '`listValues` must be an Array'\n )\n if (listValues.length === 0) return false\n const change: CRListChange<T> = {}\n const delta: CRListDelta<T> = { values: [], tombstones: [] }\n let shiftCursor: CRListStateEntry<T>\n for (const listValue of listValues) {\n const [cloned, copiedValue] = safeStructuredClone(listValue)\n\n if (!cloned) throw new CRListError('VALUE_NOT_CLONEABLE')\n\n const v7 = uuidv7()\n\n const linkedListEntry: NonNullable<CRListStateEntry<T>> = {\n uuidv7: v7,\n value: copiedValue,\n predecessor: '\\0',\n index: 0,\n next: undefined,\n prev: undefined,\n }\n\n switch (mode) {\n case 'overwrite': {\n if (listIndex === crListReplica.size) {\n if (crListReplica.size === 0) {\n crListReplica.cursor = linkedListEntry\n void updateEntryToMaps<T>(crListReplica, linkedListEntry, delta)\n change[linkedListEntry.index] = linkedListEntry.value\n break\n }\n void walkToIndex<T>(crListReplica.size - 1, crListReplica)\n if (!crListReplica.cursor) return false\n linkedListEntry.index = crListReplica.cursor.index + 1\n linkedListEntry.predecessor = crListReplica.cursor.uuidv7\n insertBetween<T>(crListReplica.cursor, linkedListEntry, undefined)\n void updateEntryToMaps<T>(crListReplica, linkedListEntry, delta)\n crListReplica.cursor = linkedListEntry\n change[linkedListEntry.index] = structuredClone(linkedListEntry.value)\n break\n }\n void walkToIndex<T>(listIndex, crListReplica)\n if (!crListReplica.cursor) return false\n const entryToOverwrite = crListReplica.cursor\n\n linkedListEntry.predecessor = entryToOverwrite.predecessor\n linkedListEntry.index = entryToOverwrite.index\n insertBetween<T>(\n entryToOverwrite.prev,\n linkedListEntry,\n entryToOverwrite.next\n )\n if (entryToOverwrite.next) {\n if (entryToOverwrite.next.predecessor === entryToOverwrite.uuidv7) {\n void moveEntryToPredecessor<T>(\n crListReplica,\n entryToOverwrite.next,\n linkedListEntry.uuidv7,\n delta\n )\n }\n }\n void updateEntryToMaps<T>(crListReplica, linkedListEntry, delta)\n crListReplica.tombstones.add(entryToOverwrite.uuidv7)\n delta.tombstones?.push(entryToOverwrite.uuidv7)\n void deleteEntryFromMaps<T>(crListReplica, entryToOverwrite)\n entryToOverwrite.next = undefined\n entryToOverwrite.prev = undefined\n crListReplica.cursor = linkedListEntry\n change[linkedListEntry.index] = structuredClone(linkedListEntry.value)\n break\n }\n case 'after': {\n if (crListReplica.size === 0 && listIndex === 0) {\n crListReplica.cursor = linkedListEntry\n void updateEntryToMaps<T>(crListReplica, linkedListEntry, delta)\n change[linkedListEntry.index] = structuredClone(linkedListEntry.value)\n break\n }\n if (listIndex === crListReplica.size) {\n void walkToIndex<T>(crListReplica.size - 1, crListReplica)\n } else {\n void walkToIndex<T>(listIndex, crListReplica)\n }\n if (!crListReplica.cursor) return false\n const next =\n listIndex === crListReplica.size\n ? undefined\n : crListReplica.cursor.next\n shiftCursor = next\n linkedListEntry.index = crListReplica.cursor.index + 1\n linkedListEntry.predecessor = crListReplica.cursor.uuidv7\n insertBetween<T>(crListReplica.cursor, linkedListEntry, next)\n if (next) {\n if (next.predecessor === crListReplica.cursor.uuidv7) {\n void moveEntryToPredecessor<T>(\n crListReplica,\n next,\n linkedListEntry.uuidv7,\n delta\n )\n }\n }\n void updateEntryToMaps<T>(crListReplica, linkedListEntry, delta)\n crListReplica.cursor = linkedListEntry\n change[linkedListEntry.index] = structuredClone(linkedListEntry.value)\n break\n }\n case 'before': {\n if (crListReplica.size === 0 && listIndex === 0) {\n crListReplica.cursor = linkedListEntry\n void updateEntryToMaps<T>(crListReplica, linkedListEntry, delta)\n change[linkedListEntry.index] = structuredClone(linkedListEntry.value)\n mode = 'after'\n listIndex = linkedListEntry.index - 1\n break\n }\n void walkToIndex<T>(listIndex, crListReplica)\n if (!crListReplica.cursor) return false\n const prev = crListReplica.cursor.prev\n shiftCursor = crListReplica.cursor\n linkedListEntry.index = crListReplica.cursor.index\n linkedListEntry.predecessor = prev?.uuidv7 ?? '\\0'\n insertBetween<T>(prev, linkedListEntry, crListReplica.cursor)\n if (crListReplica.cursor.predecessor === linkedListEntry.predecessor) {\n void moveEntryToPredecessor<T>(\n crListReplica,\n crListReplica.cursor,\n linkedListEntry.uuidv7,\n delta\n )\n }\n void updateEntryToMaps<T>(crListReplica, linkedListEntry, delta)\n crListReplica.cursor = linkedListEntry\n change[linkedListEntry.index] = structuredClone(linkedListEntry.value)\n mode = 'after'\n listIndex = linkedListEntry.index - 1\n\n break\n }\n }\n crListReplica.size = crListReplica.parentMap.size\n listIndex++\n }\n if (mode !== 'overwrite')\n while (shiftCursor) {\n shiftCursor.index += listValues.length\n shiftCursor = shiftCursor.next\n }\n return { change, delta }\n}\n","import { deleteLinkedEntry, walkToIndex } from '../../../.helpers/index.js'\nimport { CRListError } from '../../../.errors/class.js'\nimport type {\n CRListChange,\n CRListDelta,\n CRListState,\n CRListStateEntry,\n} from '../../../.types/index.js'\n\n/**\n * Deletes a range from the replica live view.\n *\n * With no indexes, the full list is deleted. With only `startIndex`, all entries\n * from `startIndex` onward are deleted. With both indexes, the deleted range is\n * `[startIndex, endIndex)`.\n *\n * @param crListReplica - Replica to mutate.\n * @param startIndex - Inclusive start index. Defaults to `0`.\n * @param endIndex - Exclusive end index. Defaults to the current list size.\n * @returns - A local change and gossip delta, or `false` if nothing was deleted.\n *\n * Time complexity: O(d + qk + r), worst case O(n^2)\n * - d = distance from cursor to target index\n * - q = amount of deleted nodes\n * - r = amount of nodes after the deleted range whose indexes must be shifted\n * - k = sibling bucket size when deleted entries are removed from buckets\n *\n * Space complexity: O(q)\n */\nexport function __delete<T>(\n crListReplica: CRListState<T>,\n startIndex?: number,\n endIndex?: number\n): { change: CRListChange<T>; delta: CRListDelta<T> } | false {\n const change: CRListChange<T> = {}\n const delta: CRListDelta<T> = { values: [], tombstones: [] }\n const listIndex = startIndex ?? 0\n const targetEndIndex = endIndex ?? crListReplica.size\n if (\n listIndex < 0 ||\n targetEndIndex < listIndex ||\n listIndex > crListReplica.size\n )\n throw new CRListError('INDEX_OUT_OF_BOUNDS')\n const deleteCount = Math.min(targetEndIndex, crListReplica.size) - listIndex\n if (deleteCount <= 0) return false\n\n void walkToIndex<T>(listIndex, crListReplica)\n if (!crListReplica.cursor) return false\n\n let current: CRListStateEntry<T> = crListReplica.cursor\n let deleted = 0\n\n while (current && deleted < deleteCount) {\n const next: CRListStateEntry<T> = current.next\n change[current.index] = undefined\n void deleteLinkedEntry<T>(crListReplica, current, delta)\n current = next\n deleted++\n }\n\n crListReplica.size = crListReplica.parentMap.size\n\n while (current) {\n current.index -= deleted\n current = current.next\n }\n\n return { change, delta }\n}\n","import type {\n CRListChange,\n CRListDelta,\n CRListState,\n CRListStateEntry,\n} from '../../../.types/index.js'\nimport {\n transformSnapshotEntryToStateEntry,\n updateEntryToMaps,\n flattenAndLinkTrustedState,\n assertListIndices,\n deleteLinkedEntry,\n moveEntryToPredecessor,\n} from '../../../.helpers/index.js'\nimport { prototype, isUuidV7 } from '@sovereignbase/utils'\n\n/**\n * Merges a remote CRList delta into the local replica.\n *\n * Accepted tombstones update the local live view and accepted values are attached\n * to the predecessor tree. Tail-append deltas are linked incrementally; deltas\n * that can affect ordering fall back to deterministic relinking.\n *\n * @param crListReplica - Replica to mutate.\n * @param crListDelta - Remote gossip delta.\n * @returns - A minimal local change patch, or `false` when the delta is ignored.\n *\n * Time complexity: O(v + t + c) for tail-append deltas; O(n + t + qk) for tombstone-only deletes; otherwise O(n log n + v + t + m*k + c)\n * Worst case: O(n^2 + (v + t)n + c)\n * - n = replica value entry count after merge\n * - v = delta value entry count\n * - t = delta tombstone count\n * - q = amount of live entries deleted by tombstones\n * - m = entries moved between predecessor buckets\n * - k = sibling bucket size when entries are removed from buckets\n * - c = cloned delta value payload size\n *\n * Space complexity: O(n + v + t + c)\n */\nexport function __merge<T>(\n crListReplica: CRListState<T>,\n crListDelta: CRListDelta<T>\n): CRListChange<T> | false {\n if (!crListDelta || prototype(crListDelta) !== 'record') return false\n const newVals: Array<NonNullable<CRListStateEntry<T>>> = []\n const newTombsIndices: Array<number> = []\n const change: CRListChange<T> = {}\n let needsRelink = false\n\n /** Apply tombstone entries. */\n if (\n Object.hasOwn(crListDelta, 'tombstones') &&\n Array.isArray(crListDelta.tombstones)\n ) {\n for (const tombstone of crListDelta.tombstones) {\n if (crListReplica.tombstones.has(tombstone) || !isUuidV7(tombstone))\n continue\n crListReplica.tombstones.add(tombstone)\n const linkedListEntry = crListReplica.parentMap.get(tombstone)\n if (linkedListEntry) {\n void newTombsIndices.push(linkedListEntry.index)\n void deleteLinkedEntry<T>(crListReplica, linkedListEntry)\n needsRelink = true\n }\n }\n }\n\n /** Apply value entries. */\n if (\n !Object.hasOwn(crListDelta, 'values') ||\n !Array.isArray(crListDelta.values)\n ) {\n if (newTombsIndices.length === 0) return false\n void assertListIndices<T>(crListReplica)\n for (const index of newTombsIndices) {\n change[index] = undefined\n }\n return change\n }\n // Attach accepted values to the predecessor tree.\n for (const valueEntry of crListDelta.values) {\n if (valueEntry === null || valueEntry === undefined) continue\n const existingEntry = crListReplica.parentMap.get(valueEntry.uuidv7)\n if (existingEntry) {\n if (\n crListReplica.tombstones.has(valueEntry.uuidv7) ||\n (!isUuidV7(valueEntry.predecessor) && valueEntry.predecessor !== '\\0')\n )\n continue\n if (existingEntry.predecessor >= valueEntry.predecessor) continue\n void moveEntryToPredecessor<T>(\n crListReplica,\n existingEntry,\n valueEntry.predecessor\n )\n needsRelink = true\n void newVals.push(existingEntry)\n continue\n }\n const linkedListEntry = transformSnapshotEntryToStateEntry<T>(\n valueEntry,\n crListReplica\n )\n if (!linkedListEntry) continue\n const predecessor =\n linkedListEntry.predecessor === '\\0'\n ? undefined\n : crListReplica.parentMap.get(linkedListEntry.predecessor)\n void updateEntryToMaps<T>(crListReplica, linkedListEntry)\n void newVals.push(linkedListEntry)\n if (!needsRelink && linkedListEntry.predecessor === '\\0') {\n if (crListReplica.size === 0) {\n crListReplica.cursor = linkedListEntry\n crListReplica.size = crListReplica.parentMap.size\n } else {\n needsRelink = true\n }\n } else if (!needsRelink && predecessor && !predecessor.next) {\n linkedListEntry.prev = predecessor\n linkedListEntry.index = predecessor.index + 1\n predecessor.next = linkedListEntry\n crListReplica.cursor = linkedListEntry\n crListReplica.size = crListReplica.parentMap.size\n } else {\n needsRelink = true\n }\n }\n if (needsRelink) {\n // Flatten tree into a doubly linked list.\n void flattenAndLinkTrustedState<T>(crListReplica)\n // Write live-view indexes.\n void assertListIndices<T>(crListReplica)\n }\n\n if (newTombsIndices.length === 0 && newVals.length === 0) return false\n\n for (const index of newTombsIndices) {\n change[index] = undefined\n }\n for (const val of newVals) {\n change[val.index] = structuredClone(val.value)\n }\n\n return change\n}\n","import type { CRListAck, CRListState } from '../../../.types/index.js'\n\n/**\n * Returns the replica tombstone acknowledgement frontier.\n *\n * The frontier is the greatest tombstone identifier currently retained by the\n * replica. Peers can use it as input for tombstone garbage collection.\n *\n * @param crListReplica - Replica to acknowledge.\n * @returns - The acknowledgement frontier, or `false` when there are no tombstones.\n *\n * Time complexity: O(t)\n * - t = replica tombstone count\n *\n * Space complexity: O(1)\n */\nexport function __acknowledge<T>(\n crListReplica: CRListState<T>\n): CRListAck | false {\n let largest: CRListAck | false = false\n crListReplica.tombstones.forEach((tombstone) => {\n if (largest === false || largest < tombstone) largest = tombstone\n })\n if (typeof largest === 'string') return largest\n return false\n}\n","import { isUuidV7 } from '@sovereignbase/utils'\nimport { CRListAck, CRListState } from '../../../.types/index.js'\n\n/**\n * Removes tombstones acknowledged by all supplied frontiers.\n *\n * The minimum frontier is used as the safe collection boundary. Tombstones less\n * than or equal to that boundary are removed from the local replica.\n *\n * @param frontiers - Acknowledgement frontiers received from peers.\n * @param crListReplica - Replica whose tombstones will be collected.\n *\n * Time complexity: O(f log f + t)\n * - f = frontier count\n * - t = replica tombstone count\n *\n * Space complexity: O(1)\n */\nexport function __garbageCollect<T>(\n frontiers: Array<CRListAck>,\n crListReplica: CRListState<T>\n): void {\n if (!Array.isArray(frontiers)) return\n frontiers.sort()\n const smallest = frontiers.find((frontier) => isUuidV7(frontier))\n if (typeof smallest !== 'string') return\n crListReplica.tombstones.forEach((tombstone, __, tombstones) => {\n if (tombstone <= smallest) {\n tombstones.delete(tombstone)\n }\n })\n}\n","import { CRListError } from '../../../.errors/class.js'\nimport { CRListState, CRListSnapshot } from '../../../.types/index.js'\n\n/**\n * Creates a full detached structured-clone-compatible CRList snapshot from the current replica state.\n *\n * The snapshot contains every live value entry and all retained tombstones. Value\n * payloads are cloned so callers cannot mutate the replica through the snapshot.\n *\n * @param crListReplica - Replica to snapshot.\n * @returns - A full snapshot suitable for hydration or transport.\n *\n * Time complexity: O(n + t + c)\n * - n = replica value entry count\n * - t = replica tombstone count\n * - c = cloned value payload size\n *\n * Space complexity: O(n + t + c)\n */\nexport function __snapshot<T>(\n crListReplica: CRListState<T>\n): CRListSnapshot<T> {\n return {\n values: Array.from(crListReplica.parentMap.values()).map(\n (linkedListEntry) => {\n if (!linkedListEntry) throw new CRListError('LIST_INTEGRITY_VIOLATION')\n return {\n uuidv7: linkedListEntry.uuidv7,\n value: structuredClone(linkedListEntry.value),\n predecessor: linkedListEntry.predecessor,\n }\n }\n ),\n tombstones: Array.from(crListReplica.tombstones),\n }\n}\n","import { indexFromPropertyKey } from '../.helpers/index.js'\nimport { CRListError } from '../.errors/class.js'\nimport type {\n CRListState,\n CRListSnapshot,\n CRListEventListenerFor,\n CRListEventMap,\n CRListDelta,\n CRListAck,\n} from '../.types/index.js'\nimport { __create, __read, __update, __delete } from '../core/crud/index.js'\nimport {\n __merge,\n __acknowledge,\n __garbageCollect,\n __snapshot,\n} from '../core/mags/index.js'\n\n/**\n * A convergent replicated list.\n *\n * Numeric property access reads and mutates the live list projection:\n * `list[0]` reads a detached copy of an entry, `list[0] = value` writes an\n * entry, and `delete list[0]` removes one entry. Iteration and `forEach()`\n * likewise expose detached copies rather than mutable references into the\n * replica state. Local mutations emit `delta` and `change` events; remote\n * merges emit `change` events.\n *\n * @typeParam T - The value type stored in the list.\n */\nexport class CRList<T> {\n /**\n * Reads or overwrites an entry in the live list projection by index.\n *\n * Reads return detached copies.\n */\n [index: number]: T\n declare private readonly state: CRListState<T>\n declare private readonly eventTarget: EventTarget\n\n /**\n * Creates a replicated list from an optional detached structured-clone-compatible snapshot.\n *\n * @param snapshot - A previously emitted CRList snapshot.\n */\n constructor(snapshot?: CRListSnapshot<T>) {\n Object.defineProperties(this, {\n state: {\n value: __create<T>(snapshot),\n enumerable: false,\n configurable: false,\n writable: false,\n },\n eventTarget: {\n value: new EventTarget(),\n enumerable: false,\n configurable: false,\n writable: false,\n },\n })\n\n return new Proxy(this, {\n get(target, index, receiver) {\n const listIndex = indexFromPropertyKey(index)\n // Preserve normal property access for non-index keys.\n if (listIndex === undefined) return Reflect.get(target, index, receiver)\n return __read(listIndex, target.state)\n },\n has(target, index) {\n const listIndex = indexFromPropertyKey(index)\n // Preserve normal property checks for non-index keys.\n if (listIndex === undefined) return Reflect.has(target, index)\n return listIndex >= 0 && listIndex < target.state.size\n },\n set(target, index, value) {\n const listIndex = indexFromPropertyKey(index)\n if (listIndex === undefined) return false\n try {\n const result = __update(listIndex, [value], target.state, 'overwrite')\n if (!result) return false\n const { delta, change } = result\n if (delta)\n void target.eventTarget.dispatchEvent(\n new CustomEvent('delta', { detail: delta })\n )\n if (change)\n void target.eventTarget.dispatchEvent(\n new CustomEvent('change', { detail: change })\n )\n return true\n } catch (error) {\n if (error instanceof CRListError) throw error\n return false\n }\n },\n deleteProperty(target, index) {\n const listIndex = indexFromPropertyKey(index)\n if (listIndex === undefined) return false\n try {\n const result = __delete(target.state, listIndex, listIndex + 1)\n if (!result) return false\n const { delta, change } = result\n if (delta) {\n void target.eventTarget.dispatchEvent(\n new CustomEvent('delta', { detail: delta })\n )\n }\n if (change) {\n void target.eventTarget.dispatchEvent(\n new CustomEvent('change', { detail: change })\n )\n }\n return true\n } catch (error) {\n if (error instanceof CRListError) throw error\n return false\n }\n },\n ownKeys(target) {\n return [\n ...Reflect.ownKeys(target),\n ...Array.from({ length: target.size }, (_, index) => String(index)),\n ]\n },\n\n getOwnPropertyDescriptor(target, index) {\n const listIndex = indexFromPropertyKey(index)\n\n if (listIndex !== undefined && listIndex < target.size) {\n return {\n value: __read(listIndex, target.state),\n writable: true,\n enumerable: true,\n configurable: true,\n }\n }\n // Preserve normal property checks for non-index keys.\n return Reflect.getOwnPropertyDescriptor(target, index)\n },\n })\n }\n /**\n * The current number of live entries.\n */\n get size(): number {\n return this.state.size\n }\n /**\n * Inserts a value before an index.\n *\n * If `beforeIndex` is omitted, the value is inserted at the start of the list.\n *\n * @param value - The value to insert.\n * @param beforeIndex - The index to insert before.\n */\n prepend(value: T, beforeIndex?: number): void {\n const result = __update<T>(beforeIndex ?? 0, [value], this.state, 'before')\n if (!result) return\n const { delta, change } = result\n if (delta)\n void this.eventTarget.dispatchEvent(\n new CustomEvent('delta', { detail: delta })\n )\n if (change)\n void this.eventTarget.dispatchEvent(\n new CustomEvent('change', { detail: change })\n )\n }\n /**\n * Inserts a value after an index.\n *\n * If `afterIndex` is omitted, the value is appended at the end of the list.\n *\n * @param value - The value to insert.\n * @param afterIndex - The index to insert after.\n */\n append(value: T, afterIndex?: number): void {\n const result = __update<T>(\n afterIndex ?? this.state.size,\n [value],\n this.state,\n 'after'\n )\n if (!result) return\n const { delta, change } = result\n if (delta)\n void this.eventTarget.dispatchEvent(\n new CustomEvent('delta', { detail: delta })\n )\n if (change)\n void this.eventTarget.dispatchEvent(\n new CustomEvent('change', { detail: change })\n )\n }\n /**\n * Removes the entry at an index.\n *\n * @param index - The index to remove.\n */\n remove(index: number): void {\n const result = __delete(this.state, index, index + 1)\n if (!result) return\n const { delta, change } = result\n if (delta)\n void this.eventTarget.dispatchEvent(\n new CustomEvent('delta', { detail: delta })\n )\n if (change)\n void this.eventTarget.dispatchEvent(\n new CustomEvent('change', { detail: change })\n )\n }\n /**\n * Applies a remote gossip delta to this list.\n *\n * Emits a `change` event when the merge changes the live projection.\n *\n * @param delta - The remote CRList delta to merge.\n */\n merge(delta: CRListDelta<T>): void {\n const change = __merge(this.state, delta)\n if (change)\n void this.eventTarget.dispatchEvent(\n new CustomEvent('change', { detail: change })\n )\n }\n /**\n * Emits an acknowledgement frontier for currently retained tombstones.\n */\n acknowledge(): void {\n const ack = __acknowledge(this.state)\n if (ack)\n void this.eventTarget.dispatchEvent(\n new CustomEvent('ack', { detail: ack })\n )\n }\n /**\n * Garbage-collects tombstones that are covered by acknowledgement frontiers.\n *\n * @param frontiers - Replica acknowledgement frontiers.\n */\n garbageCollect(frontiers: Array<CRListAck>): void {\n void __garbageCollect(frontiers, this.state)\n }\n /**\n * Emits the current detached structured-clone-compatible list snapshot.\n */\n snapshot(): void {\n const snapshot = __snapshot<T>(this.state)\n if (snapshot)\n void this.eventTarget.dispatchEvent(\n new CustomEvent('snapshot', { detail: snapshot })\n )\n }\n /**\n * Registers an event listener.\n *\n * @param type - The event type to listen for.\n * @param listener - The listener to register.\n * @param options - Listener registration options.\n */\n addEventListener<K extends keyof CRListEventMap<T>>(\n type: K,\n listener: CRListEventListenerFor<T, K> | null,\n options?: boolean | AddEventListenerOptions\n ): void {\n this.eventTarget.addEventListener(\n type,\n listener as EventListenerOrEventListenerObject | null,\n options\n )\n }\n\n /**\n * Removes an event listener.\n *\n * @param type - The event type to stop listening for.\n * @param listener - The listener to remove.\n * @param options - Listener removal options.\n */\n removeEventListener<K extends keyof CRListEventMap<T>>(\n type: K,\n listener: CRListEventListenerFor<T, K> | null,\n options?: boolean | EventListenerOptions\n ): void {\n this.eventTarget.removeEventListener(\n type,\n listener as EventListenerOrEventListenerObject | null,\n options\n )\n }\n /**\n * Returns a detached structured-clone-compatible snapshot of this list.\n *\n * Called automatically by `JSON.stringify`.\n */\n toJSON(): CRListSnapshot<T> {\n return __snapshot<T>(this.state)\n }\n /**\n * Attempts to return this list snapshot as a JSON string.\n *\n * This can fail when list values are not JSON-compatible.\n */\n toString(): string {\n return JSON.stringify(this)\n }\n /**\n * Returns the Node.js console inspection representation.\n */\n [Symbol.for('nodejs.util.inspect.custom')](): CRListSnapshot<T> {\n return this.toJSON()\n }\n /**\n * Returns the Deno console inspection representation.\n */\n [Symbol.for('Deno.customInspect')](): CRListSnapshot<T> {\n return this.toJSON()\n }\n /**\n * Iterates over detached copies of the current live values in index order.\n */\n *[Symbol.iterator](): IterableIterator<T> {\n for (let index = 0; index < this.size; index++) {\n const value = this[index]\n yield value\n }\n }\n /**\n * Calls a function once for each live value copy in index order.\n *\n * Callback values are detached copies, so mutating them does not mutate the\n * list.\n *\n * @param callback - Function to call for each value copy.\n * @param thisArg - Optional `this` value for the callback.\n */\n forEach(\n callback: (value: T, index: number, list: this) => void,\n thisArg?: unknown\n ): void {\n for (let index = 0; index < this.size; index++) {\n callback.call(thisArg, this[index], index, this)\n }\n }\n}\n"],"mappings":"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","names":["isUuidV7","isUuidV7","safeStructuredClone","safeStructuredClone","prototype","isUuidV7","isUuidV7"]}
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"type": "module",
|
|
3
3
|
"license": "Apache-2.0",
|
|
4
4
|
"name": "@sovereignbase/convergent-replicated-list",
|
|
5
|
-
"version": "1.0.
|
|
5
|
+
"version": "1.0.6",
|
|
6
6
|
"description": "Convergent Replicated List (CR-List), a delta CRDT for an ordered sequence of entries.",
|
|
7
7
|
"keywords": [
|
|
8
8
|
"crdt",
|