@git-stunts/git-warp 12.3.0 → 12.4.1
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 +5 -6
- package/bin/cli/commands/info.js +1 -5
- package/bin/cli/infrastructure.js +6 -9
- package/bin/cli/shared.js +8 -0
- package/bin/warp-graph.js +6 -6
- package/package.json +1 -1
- package/src/domain/WarpGraph.js +5 -35
- package/src/domain/crdt/VersionVector.js +1 -1
- package/src/domain/entities/GraphNode.js +1 -6
- package/src/domain/errors/ForkError.js +1 -1
- package/src/domain/errors/IndexError.js +1 -1
- package/src/domain/errors/OperationAbortedError.js +1 -1
- package/src/domain/errors/PatchError.js +1 -1
- package/src/domain/errors/PersistenceError.js +45 -0
- package/src/domain/errors/QueryError.js +1 -1
- package/src/domain/errors/SchemaUnsupportedError.js +1 -1
- package/src/domain/errors/SyncError.js +1 -1
- package/src/domain/errors/TraversalError.js +1 -1
- package/src/domain/errors/TrustError.js +1 -1
- package/src/domain/errors/WormholeError.js +1 -1
- package/src/domain/errors/index.js +1 -0
- package/src/domain/services/AdjacencyNeighborProvider.js +1 -4
- package/src/domain/services/AnchorMessageCodec.js +1 -3
- package/src/domain/services/AuditMessageCodec.js +1 -5
- package/src/domain/services/AuditReceiptService.js +2 -17
- package/src/domain/services/AuditVerifierService.js +2 -7
- package/src/domain/services/BitmapIndexBuilder.js +6 -12
- package/src/domain/services/BitmapIndexReader.js +7 -20
- package/src/domain/services/BitmapNeighborProvider.js +1 -3
- package/src/domain/services/BoundaryTransitionRecord.js +6 -23
- package/src/domain/services/CheckpointMessageCodec.js +1 -6
- package/src/domain/services/CheckpointSerializerV5.js +8 -12
- package/src/domain/services/CheckpointService.js +9 -39
- package/src/domain/services/CommitDagTraversalService.js +1 -3
- package/src/domain/services/DagPathFinding.js +9 -59
- package/src/domain/services/DagTopology.js +4 -16
- package/src/domain/services/DagTraversal.js +7 -31
- package/src/domain/services/Frontier.js +4 -6
- package/src/domain/services/GitLogParser.js +1 -2
- package/src/domain/services/GraphTraversal.js +14 -114
- package/src/domain/services/HealthCheckService.js +3 -9
- package/src/domain/services/HookInstaller.js +2 -8
- package/src/domain/services/HttpSyncServer.js +24 -25
- package/src/domain/services/IncrementalIndexUpdater.js +4 -6
- package/src/domain/services/IndexRebuildService.js +6 -52
- package/src/domain/services/IndexStalenessChecker.js +2 -3
- package/src/domain/services/JoinReducer.js +39 -65
- package/src/domain/services/LogicalBitmapIndexBuilder.js +1 -2
- package/src/domain/services/LogicalIndexBuildService.js +2 -6
- package/src/domain/services/LogicalIndexReader.js +1 -2
- package/src/domain/services/LogicalTraversal.js +13 -64
- package/src/domain/services/MaterializedViewService.js +4 -18
- package/src/domain/services/MigrationService.js +1 -4
- package/src/domain/services/ObserverView.js +1 -7
- package/src/domain/services/PatchBuilderV2.js +6 -18
- package/src/domain/services/PatchMessageCodec.js +1 -6
- package/src/domain/services/PropertyIndexBuilder.js +1 -2
- package/src/domain/services/PropertyIndexReader.js +1 -4
- package/src/domain/services/ProvenanceIndex.js +5 -7
- package/src/domain/services/ProvenancePayload.js +1 -1
- package/src/domain/services/QueryBuilder.js +3 -16
- package/src/domain/services/StateDiff.js +3 -9
- package/src/domain/services/StateSerializerV5.js +10 -10
- package/src/domain/services/StreamingBitmapIndexBuilder.js +13 -41
- package/src/domain/services/SyncAuthService.js +5 -32
- package/src/domain/services/SyncController.js +5 -25
- package/src/domain/services/SyncProtocol.js +4 -8
- package/src/domain/services/SyncTrustGate.js +4 -9
- package/src/domain/services/TemporalQuery.js +9 -27
- package/src/domain/services/TranslationCost.js +2 -8
- package/src/domain/services/WarpStateIndexBuilder.js +2 -4
- package/src/domain/services/WormholeService.js +9 -25
- package/src/domain/trust/TrustCrypto.js +1 -5
- package/src/domain/trust/TrustEvaluator.js +1 -8
- package/src/domain/trust/TrustRecordService.js +5 -10
- package/src/domain/types/TickReceipt.js +3 -7
- package/src/domain/types/WarpTypes.js +1 -5
- package/src/domain/types/WarpTypesV2.js +1 -8
- package/src/domain/utils/CachedValue.js +1 -4
- package/src/domain/utils/MinHeap.js +3 -3
- package/src/domain/utils/RefLayout.js +26 -0
- package/src/domain/utils/WriterId.js +2 -7
- package/src/domain/utils/canonicalCbor.js +1 -1
- package/src/domain/utils/defaultCodec.js +1 -1
- package/src/domain/utils/parseCursorBlob.js +4 -4
- package/src/domain/warp/PatchSession.js +3 -8
- package/src/domain/warp/Writer.js +3 -12
- package/src/domain/warp/_wire.js +2 -2
- package/src/domain/warp/_wiredMethods.d.ts +5 -7
- package/src/domain/warp/checkpoint.methods.js +1 -1
- package/src/domain/warp/fork.methods.js +1 -5
- package/src/domain/warp/materializeAdvanced.methods.js +3 -3
- package/src/domain/warp/patch.methods.js +6 -8
- package/src/domain/warp/provenance.methods.js +5 -5
- package/src/domain/warp/query.methods.js +9 -18
- package/src/domain/warp/subscribe.methods.js +2 -8
- package/src/globals.d.ts +7 -0
- package/src/infrastructure/adapters/BunHttpAdapter.js +14 -18
- package/src/infrastructure/adapters/ConsoleLogger.js +2 -9
- package/src/infrastructure/adapters/DenoHttpAdapter.js +15 -15
- package/src/infrastructure/adapters/GitGraphAdapter.js +234 -58
- package/src/infrastructure/adapters/InMemoryGraphAdapter.js +9 -2
- package/src/infrastructure/adapters/NodeHttpAdapter.js +14 -14
- package/src/infrastructure/adapters/WebCryptoAdapter.js +1 -2
- package/src/ports/BlobPort.js +2 -2
- package/src/ports/HttpServerPort.js +24 -2
- package/src/ports/RefPort.js +2 -1
- package/src/visualization/renderers/ascii/box.js +1 -1
- package/src/visualization/renderers/ascii/check.js +1 -5
- package/src/visualization/renderers/ascii/history.js +1 -6
- package/src/visualization/renderers/ascii/path.js +4 -22
- package/src/visualization/renderers/ascii/progress.js +1 -4
- package/src/visualization/renderers/ascii/seek.js +1 -5
- package/src/visualization/renderers/ascii/table.js +1 -3
|
@@ -44,6 +44,28 @@ export { normalizeRawOp, lowerCanonicalOp } from './OpNormalizer.js';
|
|
|
44
44
|
* always produces an empty Map for them.
|
|
45
45
|
*/
|
|
46
46
|
|
|
47
|
+
/**
|
|
48
|
+
* @typedef {Object} OpLike
|
|
49
|
+
* @property {string} type - Operation type discriminator
|
|
50
|
+
* @property {string} [node] - Node ID (for NodeAdd, NodeRemove, PropSet)
|
|
51
|
+
* @property {import('../crdt/Dot.js').Dot} [dot] - Dot identifier (for NodeAdd, EdgeAdd)
|
|
52
|
+
* @property {string[]} [observedDots] - Encoded dots to remove (for NodeRemove, EdgeRemove)
|
|
53
|
+
* @property {string} [from] - Source node ID (for EdgeAdd, EdgeRemove)
|
|
54
|
+
* @property {string} [to] - Target node ID (for EdgeAdd, EdgeRemove)
|
|
55
|
+
* @property {string} [label] - Edge label (for EdgeAdd, EdgeRemove)
|
|
56
|
+
* @property {string} [key] - Property key (for PropSet)
|
|
57
|
+
* @property {unknown} [value] - Property value (for PropSet)
|
|
58
|
+
* @property {string} [oid] - Blob object ID (for BlobValue)
|
|
59
|
+
*/
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* @typedef {Object} PatchLike
|
|
63
|
+
* @property {string} writer - Writer ID who created this patch
|
|
64
|
+
* @property {number} lamport - Lamport timestamp of this patch
|
|
65
|
+
* @property {OpLike[]} ops - Ordered array of operations
|
|
66
|
+
* @property {Map<string, number>|Record<string, number>} context - Version vector context
|
|
67
|
+
*/
|
|
68
|
+
|
|
47
69
|
/**
|
|
48
70
|
* Creates an empty V5 state with all CRDT structures initialized.
|
|
49
71
|
*
|
|
@@ -82,16 +104,7 @@ export function createEmptyStateV5() {
|
|
|
82
104
|
* clone the state first using `cloneStateV5()`.
|
|
83
105
|
*
|
|
84
106
|
* @param {WarpStateV5} state - The state to mutate. Modified in place.
|
|
85
|
-
* @param {
|
|
86
|
-
* @param {string} op.type - One of: 'NodeAdd', 'NodeRemove', 'EdgeAdd', 'EdgeRemove', 'PropSet', 'BlobValue'
|
|
87
|
-
* @param {string} [op.node] - Node ID (for NodeAdd, NodeRemove, PropSet)
|
|
88
|
-
* @param {import('../crdt/Dot.js').Dot} [op.dot] - Dot identifier (for NodeAdd, EdgeAdd)
|
|
89
|
-
* @param {string[]} [op.observedDots] - Encoded dots to remove (for NodeRemove, EdgeRemove)
|
|
90
|
-
* @param {string} [op.from] - Source node ID (for EdgeAdd, EdgeRemove)
|
|
91
|
-
* @param {string} [op.to] - Target node ID (for EdgeAdd, EdgeRemove)
|
|
92
|
-
* @param {string} [op.label] - Edge label (for EdgeAdd, EdgeRemove)
|
|
93
|
-
* @param {string} [op.key] - Property key (for PropSet)
|
|
94
|
-
* @param {unknown} [op.value] - Property value (for PropSet)
|
|
107
|
+
* @param {OpLike} op - The operation to apply
|
|
95
108
|
* @param {import('../utils/EventId.js').EventId} eventId - Event ID for causality tracking
|
|
96
109
|
* @returns {void}
|
|
97
110
|
*/
|
|
@@ -349,7 +362,7 @@ export function applyOpV2(state, op, eventId) {
|
|
|
349
362
|
* - EdgeRemove -> EdgeTombstone (CRDT tombstone semantics)
|
|
350
363
|
* - All others pass through unchanged
|
|
351
364
|
*
|
|
352
|
-
* @const {
|
|
365
|
+
* @const {Record<string, string>}
|
|
353
366
|
*/
|
|
354
367
|
const RECEIPT_OP_TYPE = {
|
|
355
368
|
NodeAdd: 'NodeAdd',
|
|
@@ -376,9 +389,7 @@ const VALID_RECEIPT_OPS = new Set(OP_TYPES);
|
|
|
376
389
|
* this add operation is effective or redundant (idempotent re-delivery).
|
|
377
390
|
*
|
|
378
391
|
* @param {import('../crdt/ORSet.js').ORSet} orset - The node OR-Set containing alive nodes
|
|
379
|
-
* @param {
|
|
380
|
-
* @param {string} op.node - The node ID being added
|
|
381
|
-
* @param {import('../crdt/Dot.js').Dot} op.dot - The dot uniquely identifying this add event
|
|
392
|
+
* @param {{node: string, dot: import('../crdt/Dot.js').Dot}} op - The NodeAdd operation
|
|
382
393
|
* @returns {{target: string, result: 'applied'|'redundant'}} Outcome with node ID as target
|
|
383
394
|
*/
|
|
384
395
|
function nodeAddOutcome(orset, op) {
|
|
@@ -399,9 +410,7 @@ function nodeAddOutcome(orset, op) {
|
|
|
399
410
|
* observed at the time the remove was issued.
|
|
400
411
|
*
|
|
401
412
|
* @param {import('../crdt/ORSet.js').ORSet} orset - The node OR-Set containing alive nodes
|
|
402
|
-
* @param {
|
|
403
|
-
* @param {string} [op.node] - The node ID being removed (may be absent for dot-only removes)
|
|
404
|
-
* @param {string[]} op.observedDots - Array of encoded dots that were observed when the remove was issued
|
|
413
|
+
* @param {{node?: string, observedDots: string[] | Set<string>}} op - The NodeRemove operation
|
|
405
414
|
* @returns {{target: string, result: 'applied'|'redundant'}} Outcome with node ID (or '*') as target
|
|
406
415
|
*/
|
|
407
416
|
function nodeRemoveOutcome(orset, op) {
|
|
@@ -431,11 +440,7 @@ function nodeRemoveOutcome(orset, op) {
|
|
|
431
440
|
* Unlike nodes, edges are keyed by the composite (from, to, label) tuple.
|
|
432
441
|
*
|
|
433
442
|
* @param {import('../crdt/ORSet.js').ORSet} orset - The edge OR-Set containing alive edges
|
|
434
|
-
* @param {
|
|
435
|
-
* @param {string} op.from - Source node ID
|
|
436
|
-
* @param {string} op.to - Target node ID
|
|
437
|
-
* @param {string} op.label - Edge label
|
|
438
|
-
* @param {import('../crdt/Dot.js').Dot} op.dot - The dot uniquely identifying this add event
|
|
443
|
+
* @param {{from: string, to: string, label: string, dot: import('../crdt/Dot.js').Dot}} op - The EdgeAdd operation
|
|
439
444
|
* @param {string} edgeKey - Pre-encoded edge key (from\0to\0label format)
|
|
440
445
|
* @returns {{target: string, result: 'applied'|'redundant'}} Outcome with encoded edge key as target
|
|
441
446
|
*/
|
|
@@ -460,11 +465,7 @@ function edgeAddOutcome(orset, op, edgeKey) {
|
|
|
460
465
|
* otherwise falls back to '*' for wildcard/unknown targets.
|
|
461
466
|
*
|
|
462
467
|
* @param {import('../crdt/ORSet.js').ORSet} orset - The edge OR-Set containing alive edges
|
|
463
|
-
* @param {
|
|
464
|
-
* @param {string} [op.from] - Source node ID (optional for computing target)
|
|
465
|
-
* @param {string} [op.to] - Target node ID (optional for computing target)
|
|
466
|
-
* @param {string} [op.label] - Edge label (optional for computing target)
|
|
467
|
-
* @param {string[]} op.observedDots - Array of encoded dots that were observed when the remove was issued
|
|
468
|
+
* @param {{from?: string, to?: string, label?: string, observedDots: string[] | Set<string>}} op - The EdgeRemove operation
|
|
468
469
|
* @returns {{target: string, result: 'applied'|'redundant'}} Outcome with encoded edge key (or '*') as target
|
|
469
470
|
*/
|
|
470
471
|
function edgeRemoveOutcome(orset, op) {
|
|
@@ -535,9 +536,7 @@ function propOutcomeForKey(propMap, key, eventId) {
|
|
|
535
536
|
* Determines the receipt outcome for a PropSet/NodePropSet operation.
|
|
536
537
|
*
|
|
537
538
|
* @param {Map<string, import('../crdt/LWW.js').LWWRegister<unknown>>} propMap
|
|
538
|
-
* @param {
|
|
539
|
-
* @param {string} op.node - Node ID owning the property
|
|
540
|
-
* @param {string} op.key - Property key/name
|
|
539
|
+
* @param {{node: string, key: string}} op - The PropSet or NodePropSet operation
|
|
541
540
|
* @param {import('../utils/EventId.js').EventId} eventId
|
|
542
541
|
* @returns {{target: string, result: 'applied'|'superseded'|'redundant', reason?: string}}
|
|
543
542
|
*/
|
|
@@ -549,11 +548,7 @@ function propSetOutcome(propMap, op, eventId) {
|
|
|
549
548
|
* Determines the receipt outcome for an EdgePropSet operation.
|
|
550
549
|
*
|
|
551
550
|
* @param {Map<string, import('../crdt/LWW.js').LWWRegister<unknown>>} propMap
|
|
552
|
-
* @param {
|
|
553
|
-
* @param {string} op.from
|
|
554
|
-
* @param {string} op.to
|
|
555
|
-
* @param {string} op.label
|
|
556
|
-
* @param {string} op.key
|
|
551
|
+
* @param {{from: string, to: string, label: string, key: string}} op - The EdgePropSet operation
|
|
557
552
|
* @param {import('../utils/EventId.js').EventId} eventId
|
|
558
553
|
* @returns {{target: string, result: 'applied'|'superseded'|'redundant', reason?: string}}
|
|
559
554
|
*/
|
|
@@ -577,10 +572,7 @@ function foldPatchDot(frontier, writer, lamport) {
|
|
|
577
572
|
/**
|
|
578
573
|
* Merges a patch's context into state and folds the patch dot.
|
|
579
574
|
* @param {WarpStateV5} state
|
|
580
|
-
* @param {
|
|
581
|
-
* @param {string} patch.writer
|
|
582
|
-
* @param {number} patch.lamport
|
|
583
|
-
* @param {Map<string, number>|{[x: string]: number}} patch.context
|
|
575
|
+
* @param {{writer: string, lamport: number, context: Map<string, number>|Record<string, number>}} patch
|
|
584
576
|
*/
|
|
585
577
|
function updateFrontierFromPatch(state, patch) {
|
|
586
578
|
const contextVV = patch.context instanceof Map
|
|
@@ -594,11 +586,7 @@ function updateFrontierFromPatch(state, patch) {
|
|
|
594
586
|
* Applies a patch to state without receipt collection (zero overhead).
|
|
595
587
|
*
|
|
596
588
|
* @param {WarpStateV5} state - The state to mutate in place
|
|
597
|
-
* @param {
|
|
598
|
-
* @param {string} patch.writer
|
|
599
|
-
* @param {number} patch.lamport
|
|
600
|
-
* @param {Array<{type: string, node?: string, dot?: import('../crdt/Dot.js').Dot, observedDots?: string[], from?: string, to?: string, label?: string, key?: string, value?: unknown, oid?: string}>} patch.ops
|
|
601
|
-
* @param {Map<string, number>|{[x: string]: number}} patch.context
|
|
589
|
+
* @param {PatchLike} patch - The patch to apply
|
|
602
590
|
* @param {string} patchSha - Git SHA of the patch commit
|
|
603
591
|
* @returns {WarpStateV5} The mutated state
|
|
604
592
|
*/
|
|
@@ -819,11 +807,7 @@ function collectEdgeRemovals(diff, state, before) {
|
|
|
819
807
|
* winner changes. Redundant ops produce no diff entries.
|
|
820
808
|
*
|
|
821
809
|
* @param {WarpStateV5} state - The state to mutate in place
|
|
822
|
-
* @param {
|
|
823
|
-
* @param {string} patch.writer
|
|
824
|
-
* @param {number} patch.lamport
|
|
825
|
-
* @param {Array<import('../types/WarpTypesV2.js').OpV2 | {type: string}>} patch.ops
|
|
826
|
-
* @param {Map<string, number>|{[x: string]: number}} patch.context
|
|
810
|
+
* @param {PatchLike} patch - The patch to apply
|
|
827
811
|
* @param {string} patchSha - Git SHA of the patch commit
|
|
828
812
|
* @returns {{state: WarpStateV5, diff: import('../types/PatchDiff.js').PatchDiff}}
|
|
829
813
|
*/
|
|
@@ -847,11 +831,7 @@ export function applyWithDiff(state, patch, patchSha) {
|
|
|
847
831
|
* Applies a patch to state with receipt collection for provenance tracking.
|
|
848
832
|
*
|
|
849
833
|
* @param {WarpStateV5} state - The state to mutate in place
|
|
850
|
-
* @param {
|
|
851
|
-
* @param {string} patch.writer
|
|
852
|
-
* @param {number} patch.lamport
|
|
853
|
-
* @param {Array<{type: string, node?: string, dot?: import('../crdt/Dot.js').Dot, observedDots?: string[], from?: string, to?: string, label?: string, key?: string, value?: unknown, oid?: string}>} patch.ops
|
|
854
|
-
* @param {Map<string, number>|{[x: string]: number}} patch.context
|
|
834
|
+
* @param {PatchLike} patch - The patch to apply
|
|
855
835
|
* @param {string} patchSha - Git SHA of the patch commit
|
|
856
836
|
* @returns {{state: WarpStateV5, receipt: import('../types/TickReceipt.js').TickReceipt}}
|
|
857
837
|
*/
|
|
@@ -883,10 +863,10 @@ export function applyWithReceipt(state, patch, patchSha) {
|
|
|
883
863
|
break;
|
|
884
864
|
case 'PropSet':
|
|
885
865
|
case 'NodePropSet':
|
|
886
|
-
outcome = propSetOutcome(state.prop, /** @type {{node: string, key: string, value:
|
|
866
|
+
outcome = propSetOutcome(state.prop, /** @type {{node: string, key: string, value: unknown}} */ (canonOp), eventId);
|
|
887
867
|
break;
|
|
888
868
|
case 'EdgePropSet':
|
|
889
|
-
outcome = edgePropSetOutcome(state.prop, /** @type {{from: string, to: string, label: string, key: string, value:
|
|
869
|
+
outcome = edgePropSetOutcome(state.prop, /** @type {{from: string, to: string, label: string, key: string, value: unknown}} */ (canonOp), eventId);
|
|
890
870
|
break;
|
|
891
871
|
default: {
|
|
892
872
|
// Unknown or BlobValue — always applied
|
|
@@ -940,11 +920,7 @@ export function applyWithReceipt(state, patch, patchSha) {
|
|
|
940
920
|
* clone the state first using `cloneStateV5()`.
|
|
941
921
|
*
|
|
942
922
|
* @param {WarpStateV5} state - The state to mutate. Modified in place.
|
|
943
|
-
* @param {
|
|
944
|
-
* @param {string} patch.writer - Writer ID who created this patch
|
|
945
|
-
* @param {number} patch.lamport - Lamport timestamp of this patch
|
|
946
|
-
* @param {Array<{type: string, node?: string, dot?: import('../crdt/Dot.js').Dot, observedDots?: string[], from?: string, to?: string, label?: string, key?: string, value?: unknown, oid?: string}>} patch.ops - Array of operations to apply
|
|
947
|
-
* @param {Map<string, number>|{[x: string]: number}} patch.context - Version vector context (Map or serialized form)
|
|
923
|
+
* @param {PatchLike} patch - The patch to apply
|
|
948
924
|
* @param {string} patchSha - The Git SHA of the patch commit (used for EventId creation)
|
|
949
925
|
* @param {boolean} [collectReceipts=false] - When true, computes and returns receipt data
|
|
950
926
|
* @returns {WarpStateV5|{state: WarpStateV5, receipt: import('../types/TickReceipt.js').TickReceipt}}
|
|
@@ -1053,11 +1029,9 @@ function mergeEdgeBirthEvent(a, b) {
|
|
|
1053
1029
|
* - When `options.receipts` is true, returns a TickReceipt per patch for
|
|
1054
1030
|
* provenance tracking and debugging.
|
|
1055
1031
|
*
|
|
1056
|
-
* @param {Array<{patch:
|
|
1032
|
+
* @param {Array<{patch: PatchLike, sha: string}>} patches - Array of patch objects with their Git SHAs
|
|
1057
1033
|
* @param {WarpStateV5} [initialState] - Optional starting state (for incremental materialization from checkpoint)
|
|
1058
|
-
* @param {
|
|
1059
|
-
* @param {boolean} [options.receipts=false] - When true, collect and return TickReceipts
|
|
1060
|
-
* @param {boolean} [options.trackDiff=false] - When true, collect and return PatchDiff
|
|
1034
|
+
* @param {{receipts?: boolean, trackDiff?: boolean}} [options] - Optional configuration
|
|
1061
1035
|
* @returns {WarpStateV5|{state: WarpStateV5, receipts: import('../types/TickReceipt.js').TickReceipt[]}|{state: WarpStateV5, diff: import('../types/PatchDiff.js').PatchDiff}}
|
|
1062
1036
|
* Returns state directly when no options;
|
|
1063
1037
|
* returns {state, receipts} when receipts is true;
|
|
@@ -24,8 +24,7 @@ const MAX_LOCAL_ID = 1 << 24;
|
|
|
24
24
|
|
|
25
25
|
export default class LogicalBitmapIndexBuilder {
|
|
26
26
|
/**
|
|
27
|
-
* @param {
|
|
28
|
-
* @param {import('../../ports/CodecPort.js').default} [options.codec]
|
|
27
|
+
* @param {{ codec?: import('../../ports/CodecPort.js').default }} [options]
|
|
29
28
|
*/
|
|
30
29
|
constructor({ codec } = {}) {
|
|
31
30
|
this._codec = codec || defaultCodec;
|
|
@@ -17,9 +17,7 @@ import { nodeVisibleV5, edgeVisibleV5 } from './StateSerializerV5.js';
|
|
|
17
17
|
|
|
18
18
|
export default class LogicalIndexBuildService {
|
|
19
19
|
/**
|
|
20
|
-
* @param {
|
|
21
|
-
* @param {import('../../ports/CodecPort.js').default} [options.codec]
|
|
22
|
-
* @param {import('../../ports/LoggerPort.js').default} [options.logger]
|
|
20
|
+
* @param {{ codec?: import('../../ports/CodecPort.js').default, logger?: import('../../ports/LoggerPort.js').default }} [options]
|
|
23
21
|
*/
|
|
24
22
|
constructor({ codec, logger } = {}) {
|
|
25
23
|
this._codec = codec || defaultCodec;
|
|
@@ -30,9 +28,7 @@ export default class LogicalIndexBuildService {
|
|
|
30
28
|
* Builds a complete logical index from materialized state.
|
|
31
29
|
*
|
|
32
30
|
* @param {import('./JoinReducer.js').WarpStateV5} state
|
|
33
|
-
* @param {
|
|
34
|
-
* @param {Record<string, { nodeToGlobal: Record<string, number>, nextLocalId: number }>} [options.existingMeta] - Prior meta shards for ID stability
|
|
35
|
-
* @param {Record<string, number>|Array<[string, number]>} [options.existingLabels] - Prior label registry for append-only stability
|
|
31
|
+
* @param {{ existingMeta?: Record<string, { nodeToGlobal: Record<string, number>, nextLocalId: number }>, existingLabels?: Record<string, number>|Array<[string, number]> }} [options]
|
|
36
32
|
* @returns {{ tree: Record<string, Uint8Array>, receipt: Record<string, unknown> }}
|
|
37
33
|
*/
|
|
38
34
|
build(state, options = {}) {
|
|
@@ -89,8 +89,7 @@ function classifyShards(items) {
|
|
|
89
89
|
|
|
90
90
|
export default class LogicalIndexReader {
|
|
91
91
|
/**
|
|
92
|
-
* @param {
|
|
93
|
-
* @param {import('../../ports/CodecPort.js').default} [options.codec]
|
|
92
|
+
* @param {{ codec?: import('../../ports/CodecPort.js').default }} [options]
|
|
94
93
|
*/
|
|
95
94
|
constructor({ codec } = {}) {
|
|
96
95
|
this._codec = codec || defaultCodec;
|
|
@@ -83,10 +83,7 @@ export default class LogicalTraversal {
|
|
|
83
83
|
* multiple starts or no start at all (topologicalSort, commonAncestors).
|
|
84
84
|
*
|
|
85
85
|
* @private
|
|
86
|
-
* @param {
|
|
87
|
-
* @param {'out'|'in'|'both'} [opts.dir] - Edge direction to follow
|
|
88
|
-
* @param {string|string[]} [opts.labelFilter] - Edge label(s) to include
|
|
89
|
-
* @param {number} [opts.maxDepth] - Maximum depth to traverse
|
|
86
|
+
* @param {{ dir?: 'out'|'in'|'both', labelFilter?: string|string[], maxDepth?: number }} opts - The traversal options
|
|
90
87
|
* @returns {Promise<{engine: GraphTraversal, direction: 'out'|'in'|'both', options: {labels?: Set<string>}|undefined, depthLimit: number}>}
|
|
91
88
|
* @throws {TraversalError} If the direction is invalid (INVALID_DIRECTION)
|
|
92
89
|
* @throws {TraversalError} If the labelFilter is invalid (INVALID_LABEL_FILTER)
|
|
@@ -120,10 +117,7 @@ export default class LogicalTraversal {
|
|
|
120
117
|
*
|
|
121
118
|
* @private
|
|
122
119
|
* @param {string} start - The starting node ID for traversal
|
|
123
|
-
* @param {
|
|
124
|
-
* @param {'out'|'in'|'both'} [opts.dir] - Edge direction to follow
|
|
125
|
-
* @param {string|string[]} [opts.labelFilter] - Edge label(s) to include
|
|
126
|
-
* @param {number} [opts.maxDepth] - Maximum depth to traverse
|
|
120
|
+
* @param {{ dir?: 'out'|'in'|'both', labelFilter?: string|string[], maxDepth?: number }} opts - The traversal options
|
|
127
121
|
* @returns {Promise<{engine: GraphTraversal, direction: 'out'|'in'|'both', options: {labels?: Set<string>}|undefined, depthLimit: number}>}
|
|
128
122
|
* @throws {TraversalError} If the start node is not found (NODE_NOT_FOUND)
|
|
129
123
|
* @throws {TraversalError} If the direction is invalid (INVALID_DIRECTION)
|
|
@@ -146,10 +140,7 @@ export default class LogicalTraversal {
|
|
|
146
140
|
* Breadth-first traversal.
|
|
147
141
|
*
|
|
148
142
|
* @param {string} start - Starting node ID
|
|
149
|
-
* @param {
|
|
150
|
-
* @param {number} [options.maxDepth] - Maximum depth to traverse
|
|
151
|
-
* @param {'out'|'in'|'both'} [options.dir] - Edge direction to follow
|
|
152
|
-
* @param {string|string[]} [options.labelFilter] - Edge label(s) to include
|
|
143
|
+
* @param {{ maxDepth?: number, dir?: 'out'|'in'|'both', labelFilter?: string|string[] }} [options] - Traversal options
|
|
153
144
|
* @returns {Promise<string[]>} Node IDs in visit order
|
|
154
145
|
* @throws {TraversalError} If the start node is not found or direction is invalid
|
|
155
146
|
*/
|
|
@@ -169,10 +160,7 @@ export default class LogicalTraversal {
|
|
|
169
160
|
* Depth-first traversal (pre-order).
|
|
170
161
|
*
|
|
171
162
|
* @param {string} start - Starting node ID
|
|
172
|
-
* @param {
|
|
173
|
-
* @param {number} [options.maxDepth] - Maximum depth to traverse
|
|
174
|
-
* @param {'out'|'in'|'both'} [options.dir] - Edge direction to follow
|
|
175
|
-
* @param {string|string[]} [options.labelFilter] - Edge label(s) to include
|
|
163
|
+
* @param {{ maxDepth?: number, dir?: 'out'|'in'|'both', labelFilter?: string|string[] }} [options] - Traversal options
|
|
176
164
|
* @returns {Promise<string[]>} Node IDs in visit order
|
|
177
165
|
* @throws {TraversalError} If the start node is not found or direction is invalid
|
|
178
166
|
*/
|
|
@@ -193,10 +181,7 @@ export default class LogicalTraversal {
|
|
|
193
181
|
*
|
|
194
182
|
* @param {string} from - Source node ID
|
|
195
183
|
* @param {string} to - Target node ID
|
|
196
|
-
* @param {
|
|
197
|
-
* @param {number} [options.maxDepth] - Maximum search depth
|
|
198
|
-
* @param {'out'|'in'|'both'} [options.dir] - Edge direction to follow
|
|
199
|
-
* @param {string|string[]} [options.labelFilter] - Edge label(s) to include
|
|
184
|
+
* @param {{ maxDepth?: number, dir?: 'out'|'in'|'both', labelFilter?: string|string[] }} [options] - Traversal options
|
|
200
185
|
* @returns {Promise<{found: boolean, path: string[], length: number}>}
|
|
201
186
|
* When `found` is true, `path` contains the node IDs from `from` to `to` and
|
|
202
187
|
* `length` is the hop count. When `found` is false, `path` is empty and `length` is -1.
|
|
@@ -219,9 +204,7 @@ export default class LogicalTraversal {
|
|
|
219
204
|
* Connected component (undirected by default).
|
|
220
205
|
*
|
|
221
206
|
* @param {string} start - Starting node ID
|
|
222
|
-
* @param {
|
|
223
|
-
* @param {number} [options.maxDepth] - Maximum depth to traverse (default: 1000)
|
|
224
|
-
* @param {string|string[]} [options.labelFilter] - Edge label(s) to include
|
|
207
|
+
* @param {{ maxDepth?: number, labelFilter?: string|string[] }} [options] - Traversal options
|
|
225
208
|
* @returns {Promise<string[]>} Node IDs in visit order
|
|
226
209
|
* @throws {TraversalError} If the start node is not found
|
|
227
210
|
*/
|
|
@@ -236,11 +219,7 @@ export default class LogicalTraversal {
|
|
|
236
219
|
*
|
|
237
220
|
* @param {string} from - Source node ID
|
|
238
221
|
* @param {string} to - Target node ID
|
|
239
|
-
* @param {
|
|
240
|
-
* @param {number} [options.maxDepth] - Maximum search depth
|
|
241
|
-
* @param {'out'|'in'|'both'} [options.dir] - Edge direction to follow
|
|
242
|
-
* @param {string|string[]} [options.labelFilter] - Edge label(s) to include
|
|
243
|
-
* @param {AbortSignal} [options.signal] - Abort signal
|
|
222
|
+
* @param {{ maxDepth?: number, dir?: 'out'|'in'|'both', labelFilter?: string|string[], signal?: AbortSignal }} [options] - Traversal options
|
|
244
223
|
* @returns {Promise<{reachable: boolean}>}
|
|
245
224
|
*/
|
|
246
225
|
async isReachable(from, to, options = {}) {
|
|
@@ -262,12 +241,7 @@ export default class LogicalTraversal {
|
|
|
262
241
|
*
|
|
263
242
|
* @param {string} from - Source node ID
|
|
264
243
|
* @param {string} to - Target node ID
|
|
265
|
-
* @param {
|
|
266
|
-
* @param {'out'|'in'|'both'} [options.dir] - Edge direction to follow
|
|
267
|
-
* @param {string|string[]} [options.labelFilter] - Edge label(s) to include
|
|
268
|
-
* @param {(from: string, to: string, label: string) => number | Promise<number>} [options.weightFn] - Edge weight function
|
|
269
|
-
* @param {(nodeId: string) => number | Promise<number>} [options.nodeWeightFn] - Node weight function (mutually exclusive with weightFn)
|
|
270
|
-
* @param {AbortSignal} [options.signal] - Abort signal
|
|
244
|
+
* @param {{ dir?: 'out'|'in'|'both', labelFilter?: string|string[], weightFn?: (from: string, to: string, label: string) => number | Promise<number>, nodeWeightFn?: (nodeId: string) => number | Promise<number>, signal?: AbortSignal }} [options] - Traversal options
|
|
271
245
|
* @returns {Promise<{path: string[], totalCost: number}>}
|
|
272
246
|
* @throws {TraversalError} code 'NO_PATH' if unreachable
|
|
273
247
|
* @throws {TraversalError} code 'E_WEIGHT_FN_CONFLICT' if both weightFn and nodeWeightFn provided
|
|
@@ -292,13 +266,7 @@ export default class LogicalTraversal {
|
|
|
292
266
|
*
|
|
293
267
|
* @param {string} from - Source node ID
|
|
294
268
|
* @param {string} to - Target node ID
|
|
295
|
-
* @param {
|
|
296
|
-
* @param {'out'|'in'|'both'} [options.dir] - Edge direction to follow
|
|
297
|
-
* @param {string|string[]} [options.labelFilter] - Edge label(s) to include
|
|
298
|
-
* @param {(from: string, to: string, label: string) => number | Promise<number>} [options.weightFn] - Edge weight function
|
|
299
|
-
* @param {(nodeId: string) => number | Promise<number>} [options.nodeWeightFn] - Node weight function (mutually exclusive with weightFn)
|
|
300
|
-
* @param {(nodeId: string, goalId: string) => number} [options.heuristicFn] - Heuristic function
|
|
301
|
-
* @param {AbortSignal} [options.signal] - Abort signal
|
|
269
|
+
* @param {{ dir?: 'out'|'in'|'both', labelFilter?: string|string[], weightFn?: (from: string, to: string, label: string) => number | Promise<number>, nodeWeightFn?: (nodeId: string) => number | Promise<number>, heuristicFn?: (nodeId: string, goalId: string) => number, signal?: AbortSignal }} [options] - Traversal options
|
|
302
270
|
* @returns {Promise<{path: string[], totalCost: number, nodesExplored: number}>}
|
|
303
271
|
* @throws {TraversalError} code 'NO_PATH' if unreachable
|
|
304
272
|
* @throws {TraversalError} code 'E_WEIGHT_FN_CONFLICT' if both weightFn and nodeWeightFn provided
|
|
@@ -326,13 +294,7 @@ export default class LogicalTraversal {
|
|
|
326
294
|
*
|
|
327
295
|
* @param {string} from - Source node ID
|
|
328
296
|
* @param {string} to - Target node ID
|
|
329
|
-
* @param {
|
|
330
|
-
* @param {string|string[]} [options.labelFilter] - Edge label(s) to include
|
|
331
|
-
* @param {(from: string, to: string, label: string) => number | Promise<number>} [options.weightFn] - Edge weight function
|
|
332
|
-
* @param {(nodeId: string) => number | Promise<number>} [options.nodeWeightFn] - Node weight function (mutually exclusive with weightFn)
|
|
333
|
-
* @param {(nodeId: string, goalId: string) => number} [options.forwardHeuristic] - Forward heuristic
|
|
334
|
-
* @param {(nodeId: string, goalId: string) => number} [options.backwardHeuristic] - Backward heuristic
|
|
335
|
-
* @param {AbortSignal} [options.signal] - Abort signal
|
|
297
|
+
* @param {{ labelFilter?: string|string[], weightFn?: (from: string, to: string, label: string) => number | Promise<number>, nodeWeightFn?: (nodeId: string) => number | Promise<number>, forwardHeuristic?: (nodeId: string, goalId: string) => number, backwardHeuristic?: (nodeId: string, goalId: string) => number, signal?: AbortSignal }} [options] - Traversal options
|
|
336
298
|
* @returns {Promise<{path: string[], totalCost: number, nodesExplored: number}>}
|
|
337
299
|
* @throws {TraversalError} code 'NO_PATH' if unreachable
|
|
338
300
|
* @throws {TraversalError} code 'E_WEIGHT_FN_CONFLICT' if both weightFn and nodeWeightFn provided
|
|
@@ -365,11 +327,7 @@ export default class LogicalTraversal {
|
|
|
365
327
|
* Topological sort (Kahn's algorithm).
|
|
366
328
|
*
|
|
367
329
|
* @param {string|string[]} start - One or more start nodes
|
|
368
|
-
* @param {
|
|
369
|
-
* @param {'out'|'in'|'both'} [options.dir] - Edge direction to follow
|
|
370
|
-
* @param {string|string[]} [options.labelFilter] - Edge label(s) to include
|
|
371
|
-
* @param {boolean} [options.throwOnCycle] - Whether to throw on cycle detection
|
|
372
|
-
* @param {AbortSignal} [options.signal] - Abort signal
|
|
330
|
+
* @param {{ dir?: 'out'|'in'|'both', labelFilter?: string|string[], throwOnCycle?: boolean, signal?: AbortSignal }} [options] - Traversal options
|
|
373
331
|
* @returns {Promise<{sorted: string[], hasCycle: boolean}>}
|
|
374
332
|
* @throws {TraversalError} code 'ERR_GRAPH_HAS_CYCLES' if throwOnCycle and cycle found
|
|
375
333
|
* @throws {TraversalError} code 'NODE_NOT_FOUND' if a start node does not exist
|
|
@@ -405,11 +363,7 @@ export default class LogicalTraversal {
|
|
|
405
363
|
* Direction is fixed to 'in' (backward BFS).
|
|
406
364
|
*
|
|
407
365
|
* @param {string[]} nodes - Nodes to find common ancestors of
|
|
408
|
-
* @param {
|
|
409
|
-
* @param {number} [options.maxDepth] - Maximum search depth
|
|
410
|
-
* @param {string|string[]} [options.labelFilter] - Edge label(s) to include
|
|
411
|
-
* @param {number} [options.maxResults] - Maximum number of results
|
|
412
|
-
* @param {AbortSignal} [options.signal] - Abort signal
|
|
366
|
+
* @param {{ maxDepth?: number, labelFilter?: string|string[], maxResults?: number, signal?: AbortSignal }} [options] - Traversal options
|
|
413
367
|
* @returns {Promise<{ancestors: string[]}>}
|
|
414
368
|
* @throws {TraversalError} code 'NODE_NOT_FOUND' if a node does not exist
|
|
415
369
|
*/
|
|
@@ -443,12 +397,7 @@ export default class LogicalTraversal {
|
|
|
443
397
|
*
|
|
444
398
|
* @param {string} from - Source node ID
|
|
445
399
|
* @param {string} to - Target node ID
|
|
446
|
-
* @param {
|
|
447
|
-
* @param {'out'|'in'|'both'} [options.dir] - Edge direction to follow
|
|
448
|
-
* @param {string|string[]} [options.labelFilter] - Edge label(s) to include
|
|
449
|
-
* @param {(from: string, to: string, label: string) => number | Promise<number>} [options.weightFn] - Edge weight function
|
|
450
|
-
* @param {(nodeId: string) => number | Promise<number>} [options.nodeWeightFn] - Node weight function (mutually exclusive with weightFn)
|
|
451
|
-
* @param {AbortSignal} [options.signal] - Abort signal
|
|
400
|
+
* @param {{ dir?: 'out'|'in'|'both', labelFilter?: string|string[], weightFn?: (from: string, to: string, label: string) => number | Promise<number>, nodeWeightFn?: (nodeId: string) => number | Promise<number>, signal?: AbortSignal }} [options] - Traversal options
|
|
452
401
|
* @returns {Promise<{path: string[], totalCost: number}>}
|
|
453
402
|
* @throws {TraversalError} code 'ERR_GRAPH_HAS_CYCLES' if graph has cycles
|
|
454
403
|
* @throws {TraversalError} code 'NO_PATH' if unreachable
|
|
@@ -207,11 +207,7 @@ function canonicalizeNeighborSignatures(edges) {
|
|
|
207
207
|
/**
|
|
208
208
|
* Compares bitmap index neighbors against ground-truth adjacency for one node.
|
|
209
209
|
*
|
|
210
|
-
* @param {
|
|
211
|
-
* @param {string} params.nodeId
|
|
212
|
-
* @param {string} params.direction
|
|
213
|
-
* @param {LogicalIndex} params.logicalIndex
|
|
214
|
-
* @param {Map<string, Array<{neighborId: string, label: string}>>} params.truthMap
|
|
210
|
+
* @param {{ nodeId: string, direction: string, logicalIndex: LogicalIndex, truthMap: Map<string, Array<{neighborId: string, label: string}>> }} params
|
|
215
211
|
* @returns {VerifyError|null}
|
|
216
212
|
*/
|
|
217
213
|
function compareNodeDirection({ nodeId, direction, logicalIndex, truthMap }) {
|
|
@@ -232,9 +228,7 @@ function compareNodeDirection({ nodeId, direction, logicalIndex, truthMap }) {
|
|
|
232
228
|
|
|
233
229
|
export default class MaterializedViewService {
|
|
234
230
|
/**
|
|
235
|
-
* @param {
|
|
236
|
-
* @param {import('../../ports/CodecPort.js').default} [options.codec]
|
|
237
|
-
* @param {import('../../ports/LoggerPort.js').default} [options.logger]
|
|
231
|
+
* @param {{ codec?: import('../../ports/CodecPort.js').default, logger?: import('../../ports/LoggerPort.js').default }} [options]
|
|
238
232
|
*/
|
|
239
233
|
constructor({ codec, logger } = {}) {
|
|
240
234
|
this._codec = codec || defaultCodec;
|
|
@@ -308,10 +302,7 @@ export default class MaterializedViewService {
|
|
|
308
302
|
/**
|
|
309
303
|
* Applies a PatchDiff incrementally to an existing index tree.
|
|
310
304
|
*
|
|
311
|
-
* @param {
|
|
312
|
-
* @param {Record<string, Uint8Array>} params.existingTree
|
|
313
|
-
* @param {import('../types/PatchDiff.js').PatchDiff} params.diff
|
|
314
|
-
* @param {import('./JoinReducer.js').WarpStateV5} params.state
|
|
305
|
+
* @param {{ existingTree: Record<string, Uint8Array>, diff: import('../types/PatchDiff.js').PatchDiff, state: import('./JoinReducer.js').WarpStateV5 }} params
|
|
315
306
|
* @returns {BuildResult}
|
|
316
307
|
*/
|
|
317
308
|
applyDiff({ existingTree, diff, state }) {
|
|
@@ -345,12 +336,7 @@ export default class MaterializedViewService {
|
|
|
345
336
|
* Verifies index integrity by sampling alive nodes and comparing
|
|
346
337
|
* bitmap neighbor queries against adjacency-based ground truth.
|
|
347
338
|
*
|
|
348
|
-
* @param {
|
|
349
|
-
* @param {import('./JoinReducer.js').WarpStateV5} params.state
|
|
350
|
-
* @param {LogicalIndex} params.logicalIndex
|
|
351
|
-
* @param {Object} [params.options]
|
|
352
|
-
* @param {number} [params.options.seed] - PRNG seed for reproducible sampling
|
|
353
|
-
* @param {number} [params.options.sampleRate] - Fraction of nodes to check (>0 and <=1, default 0.1)
|
|
339
|
+
* @param {{ state: import('./JoinReducer.js').WarpStateV5, logicalIndex: LogicalIndex, options?: { seed?: number, sampleRate?: number } }} params
|
|
354
340
|
* @returns {VerifyResult}
|
|
355
341
|
*/
|
|
356
342
|
verifyIndex({ state, logicalIndex, options = {} }) {
|
|
@@ -13,10 +13,7 @@ import { createVersionVector, vvIncrement } from '../crdt/VersionVector.js';
|
|
|
13
13
|
* writer, rebuilds the ORSet structures, and copies only properties belonging
|
|
14
14
|
* to visible nodes (dropping dangling props from deleted nodes).
|
|
15
15
|
*
|
|
16
|
-
* @param {
|
|
17
|
-
* @param {Map<string, {value: boolean}>} v4State.nodeAlive - V4 node alive map
|
|
18
|
-
* @param {Map<string, {value: boolean}>} v4State.edgeAlive - V4 edge alive map
|
|
19
|
-
* @param {Map<string, import('../crdt/LWW.js').LWWRegister<unknown>>} v4State.prop - V4 property map
|
|
16
|
+
* @param {{ nodeAlive: Map<string, {value: boolean}>, edgeAlive: Map<string, {value: boolean}>, prop: Map<string, import('../crdt/LWW.js').LWWRegister<unknown>> }} v4State - The V4 materialized state (visible projection)
|
|
20
17
|
* @param {string} migrationWriterId - Writer ID to use for synthetic dots
|
|
21
18
|
* @returns {import('./JoinReducer.js').WarpStateV5} The migrated V5 state
|
|
22
19
|
*/
|
|
@@ -156,13 +156,7 @@ export default class ObserverView {
|
|
|
156
156
|
/**
|
|
157
157
|
* Creates a new ObserverView.
|
|
158
158
|
*
|
|
159
|
-
* @param {
|
|
160
|
-
* @param {string} options.name - Observer name
|
|
161
|
-
* @param {Object} options.config - Observer configuration
|
|
162
|
-
* @param {string|string[]} options.config.match - Glob pattern(s) for visible nodes
|
|
163
|
-
* @param {string[]} [options.config.expose] - Property keys to include
|
|
164
|
-
* @param {string[]} [options.config.redact] - Property keys to exclude (takes precedence over expose)
|
|
165
|
-
* @param {import('../WarpGraph.js').default} options.graph - The source WarpGraph instance
|
|
159
|
+
* @param {{ name: string, config: { match: string|string[], expose?: string[], redact?: string[] }, graph: import('../WarpGraph.js').default }} options
|
|
166
160
|
*/
|
|
167
161
|
constructor({ name, config, graph }) {
|
|
168
162
|
/** @type {string} */
|
|
@@ -99,19 +99,7 @@ export class PatchBuilderV2 {
|
|
|
99
99
|
/**
|
|
100
100
|
* Creates a new PatchBuilderV2.
|
|
101
101
|
*
|
|
102
|
-
* @param {
|
|
103
|
-
* @param {import('../../ports/GraphPersistencePort.js').default} options.persistence - Git adapter
|
|
104
|
-
* (uses CommitPort + RefPort + BlobPort + TreePort methods)
|
|
105
|
-
* @param {string} options.graphName - Graph namespace
|
|
106
|
-
* @param {string} options.writerId - This writer's ID
|
|
107
|
-
* @param {number} options.lamport - Lamport timestamp for this patch
|
|
108
|
-
* @param {import('../crdt/VersionVector.js').VersionVector} options.versionVector - Current version vector
|
|
109
|
-
* @param {Function} options.getCurrentState - Function that returns the current materialized state
|
|
110
|
-
* @param {string|null} [options.expectedParentSha] - Expected parent SHA for race detection
|
|
111
|
-
* @param {Function|null} [options.onCommitSuccess] - Callback invoked after successful commit
|
|
112
|
-
* @param {'reject'|'cascade'|'warn'} [options.onDeleteWithData='warn'] - Policy when deleting a node with attached data
|
|
113
|
-
* @param {import('../../ports/CodecPort.js').default} [options.codec] - Codec for serialization
|
|
114
|
-
* @param {import('../../ports/LoggerPort.js').default} [options.logger] - Logger for non-fatal warnings
|
|
102
|
+
* @param {{ persistence: import('../../ports/GraphPersistencePort.js').default, graphName: string, writerId: string, lamport: number, versionVector: import('../crdt/VersionVector.js').VersionVector, getCurrentState: () => import('../services/JoinReducer.js').WarpStateV5 | null, expectedParentSha?: string|null, onCommitSuccess?: ((result: {patch: import('../types/WarpTypesV2.js').PatchV2, sha: string}) => void | Promise<void>)|null, onDeleteWithData?: 'reject'|'cascade'|'warn', codec?: import('../../ports/CodecPort.js').default, logger?: import('../../ports/LoggerPort.js').default }} options
|
|
115
103
|
*/
|
|
116
104
|
constructor({ persistence, graphName, writerId, lamport, versionVector, getCurrentState, expectedParentSha = null, onCommitSuccess = null, onDeleteWithData = 'warn', codec, logger }) {
|
|
117
105
|
/** @type {import('../../ports/GraphPersistencePort.js').default & import('../../ports/RefPort.js').default & import('../../ports/CommitPort.js').default & import('../../ports/BlobPort.js').default & import('../../ports/TreePort.js').default} */
|
|
@@ -129,8 +117,8 @@ export class PatchBuilderV2 {
|
|
|
129
117
|
/** @type {import('../crdt/VersionVector.js').VersionVector} */
|
|
130
118
|
this._vv = vvClone(versionVector); // Clone to track local increments
|
|
131
119
|
|
|
132
|
-
/** @type {
|
|
133
|
-
this._getCurrentState = getCurrentState;
|
|
120
|
+
/** @type {() => import('../services/JoinReducer.js').WarpStateV5 | null} */
|
|
121
|
+
this._getCurrentState = getCurrentState;
|
|
134
122
|
|
|
135
123
|
/**
|
|
136
124
|
* Snapshot of state captured at construction time (C4).
|
|
@@ -540,7 +528,7 @@ export class PatchBuilderV2 {
|
|
|
540
528
|
* only sets the `_content` property — it does not create the node.
|
|
541
529
|
*
|
|
542
530
|
* @param {string} nodeId - The node ID to attach content to
|
|
543
|
-
* @param {
|
|
531
|
+
* @param {Uint8Array|string} content - The content to attach
|
|
544
532
|
* @returns {Promise<PatchBuilderV2>} This builder instance for method chaining
|
|
545
533
|
*/
|
|
546
534
|
async attachContent(nodeId, content) {
|
|
@@ -561,7 +549,7 @@ export class PatchBuilderV2 {
|
|
|
561
549
|
* @param {string} from - Source node ID
|
|
562
550
|
* @param {string} to - Target node ID
|
|
563
551
|
* @param {string} label - Edge label
|
|
564
|
-
* @param {
|
|
552
|
+
* @param {Uint8Array|string} content - The content to attach
|
|
565
553
|
* @returns {Promise<PatchBuilderV2>} This builder instance for method chaining
|
|
566
554
|
*/
|
|
567
555
|
async attachEdgeContent(from, to, label, content) {
|
|
@@ -732,7 +720,7 @@ export class PatchBuilderV2 {
|
|
|
732
720
|
|
|
733
721
|
// 6. Encode patch as CBOR and write as a Git blob
|
|
734
722
|
const patchCbor = this._codec.encode(patch);
|
|
735
|
-
const patchBlobOid = await this._persistence.writeBlob(
|
|
723
|
+
const patchBlobOid = await this._persistence.writeBlob(patchCbor);
|
|
736
724
|
|
|
737
725
|
// 7. Create tree with the patch blob + any content blobs (deduplicated)
|
|
738
726
|
// Format for mktree: "mode type oid\tpath"
|
|
@@ -25,12 +25,7 @@ import {
|
|
|
25
25
|
/**
|
|
26
26
|
* Encodes a patch commit message.
|
|
27
27
|
*
|
|
28
|
-
* @param {
|
|
29
|
-
* @param {string} options.graph - The graph name
|
|
30
|
-
* @param {string} options.writer - The writer ID
|
|
31
|
-
* @param {number} options.lamport - The Lamport timestamp (must be a positive integer)
|
|
32
|
-
* @param {string} options.patchOid - The OID of the patch blob
|
|
33
|
-
* @param {number} [options.schema=2] - The schema version (defaults to 2 for new messages)
|
|
28
|
+
* @param {{ graph: string, writer: string, lamport: number, patchOid: string, schema?: number }} options - The patch message options
|
|
34
29
|
* @returns {string} The encoded commit message
|
|
35
30
|
* @throws {Error} If any validation fails
|
|
36
31
|
*
|
|
@@ -12,8 +12,7 @@ import computeShardKey from '../utils/shardKey.js';
|
|
|
12
12
|
|
|
13
13
|
export default class PropertyIndexBuilder {
|
|
14
14
|
/**
|
|
15
|
-
* @param {
|
|
16
|
-
* @param {import('../../ports/CodecPort.js').default} [options.codec]
|
|
15
|
+
* @param {{ codec?: import('../../ports/CodecPort.js').default }} [options]
|
|
17
16
|
*/
|
|
18
17
|
constructor({ codec } = {}) {
|
|
19
18
|
this._codec = codec || defaultCodec;
|
|
@@ -12,10 +12,7 @@ import LRUCache from '../utils/LRUCache.js';
|
|
|
12
12
|
|
|
13
13
|
export default class PropertyIndexReader {
|
|
14
14
|
/**
|
|
15
|
-
* @param {
|
|
16
|
-
* @param {import('../../ports/IndexStoragePort.js').default} [options.storage]
|
|
17
|
-
* @param {import('../../ports/CodecPort.js').default} [options.codec]
|
|
18
|
-
* @param {number} [options.maxCachedShards=64]
|
|
15
|
+
* @param {{ storage?: import('../../ports/IndexStoragePort.js').default, codec?: import('../../ports/CodecPort.js').default, maxCachedShards?: number }} [options]
|
|
19
16
|
*/
|
|
20
17
|
constructor({ storage, codec, maxCachedShards = 64 } = /** @type {{ storage?: import('../../ports/IndexStoragePort.js').default, codec?: import('../../ports/CodecPort.js').default, maxCachedShards?: number }} */ ({})) {
|
|
21
18
|
this._storage = storage;
|
|
@@ -242,9 +242,8 @@ class ProvenanceIndex {
|
|
|
242
242
|
* The serialized format is a sorted array of [entityId, sortedShas[]] pairs
|
|
243
243
|
* for deterministic output.
|
|
244
244
|
*
|
|
245
|
-
* @param {
|
|
246
|
-
* @
|
|
247
|
-
* @returns {Buffer|Uint8Array} CBOR-encoded index
|
|
245
|
+
* @param {{ codec?: import('../../ports/CodecPort.js').default }} [options]
|
|
246
|
+
* @returns {Uint8Array} CBOR-encoded index
|
|
248
247
|
*/
|
|
249
248
|
serialize({ codec } = {}) {
|
|
250
249
|
const c = codec || defaultCodec;
|
|
@@ -268,9 +267,8 @@ class ProvenanceIndex {
|
|
|
268
267
|
/**
|
|
269
268
|
* Deserializes an index from CBOR format.
|
|
270
269
|
*
|
|
271
|
-
* @param {
|
|
272
|
-
* @param {
|
|
273
|
-
* @param {import('../../ports/CodecPort.js').default} [options.codec] - Codec for deserialization
|
|
270
|
+
* @param {Uint8Array} buffer - CBOR-encoded index
|
|
271
|
+
* @param {{ codec?: import('../../ports/CodecPort.js').default }} [options]
|
|
274
272
|
* @returns {ProvenanceIndex} The deserialized index
|
|
275
273
|
* @throws {Error} If the buffer contains an unsupported version
|
|
276
274
|
*/
|
|
@@ -293,7 +291,7 @@ class ProvenanceIndex {
|
|
|
293
291
|
/**
|
|
294
292
|
* Returns a JSON-serializable representation of this index.
|
|
295
293
|
*
|
|
296
|
-
* @returns {
|
|
294
|
+
* @returns {{version: number, entries: Array<[string, string[]]>}} Object with version and entries array
|
|
297
295
|
*/
|
|
298
296
|
toJSON() {
|
|
299
297
|
return { version: 1, entries: this.#sortedEntries() };
|