@git-stunts/git-warp 11.2.1 → 11.5.0
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 +24 -1
- package/bin/cli/commands/check.js +2 -2
- package/bin/cli/commands/doctor/checks.js +12 -12
- package/bin/cli/commands/doctor/index.js +2 -2
- package/bin/cli/commands/doctor/types.js +1 -1
- package/bin/cli/commands/history.js +12 -5
- package/bin/cli/commands/install-hooks.js +5 -5
- package/bin/cli/commands/materialize.js +2 -2
- package/bin/cli/commands/patch.js +142 -0
- package/bin/cli/commands/path.js +4 -4
- package/bin/cli/commands/query.js +54 -13
- package/bin/cli/commands/registry.js +4 -0
- package/bin/cli/commands/seek.js +17 -11
- package/bin/cli/commands/tree.js +230 -0
- package/bin/cli/commands/trust.js +3 -3
- package/bin/cli/commands/verify-audit.js +8 -7
- package/bin/cli/commands/view.js +6 -5
- package/bin/cli/infrastructure.js +26 -12
- package/bin/cli/shared.js +2 -2
- package/bin/cli/types.js +19 -8
- package/bin/presenters/index.js +35 -9
- package/bin/presenters/json.js +14 -12
- package/bin/presenters/text.js +155 -33
- package/index.d.ts +118 -22
- package/index.js +2 -0
- package/package.json +5 -3
- package/src/domain/WarpGraph.js +4 -1
- package/src/domain/crdt/ORSet.js +8 -8
- package/src/domain/errors/EmptyMessageError.js +2 -2
- 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/QueryError.js +1 -1
- package/src/domain/errors/SchemaUnsupportedError.js +1 -1
- package/src/domain/errors/ShardCorruptionError.js +2 -2
- package/src/domain/errors/ShardLoadError.js +2 -2
- package/src/domain/errors/ShardValidationError.js +4 -4
- package/src/domain/errors/StorageError.js +2 -2
- 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/WarpError.js +2 -2
- package/src/domain/errors/WormholeError.js +1 -1
- package/src/domain/services/AuditReceiptService.js +6 -6
- package/src/domain/services/AuditVerifierService.js +52 -38
- package/src/domain/services/BitmapIndexBuilder.js +3 -3
- package/src/domain/services/BitmapIndexReader.js +28 -19
- package/src/domain/services/BoundaryTransitionRecord.js +18 -17
- package/src/domain/services/CheckpointSerializerV5.js +17 -16
- package/src/domain/services/CheckpointService.js +22 -3
- package/src/domain/services/CommitDagTraversalService.js +13 -13
- package/src/domain/services/DagPathFinding.js +7 -7
- package/src/domain/services/DagTopology.js +1 -1
- package/src/domain/services/DagTraversal.js +1 -1
- package/src/domain/services/HealthCheckService.js +1 -1
- package/src/domain/services/HookInstaller.js +1 -1
- package/src/domain/services/HttpSyncServer.js +92 -41
- package/src/domain/services/IndexRebuildService.js +7 -7
- package/src/domain/services/IndexStalenessChecker.js +4 -3
- package/src/domain/services/JoinReducer.js +26 -11
- package/src/domain/services/KeyCodec.js +7 -0
- package/src/domain/services/LogicalTraversal.js +1 -1
- package/src/domain/services/MessageCodecInternal.js +1 -1
- package/src/domain/services/MigrationService.js +1 -1
- package/src/domain/services/ObserverView.js +8 -8
- package/src/domain/services/PatchBuilderV2.js +96 -30
- package/src/domain/services/ProvenanceIndex.js +1 -1
- package/src/domain/services/ProvenancePayload.js +1 -1
- package/src/domain/services/QueryBuilder.js +3 -3
- package/src/domain/services/StateDiff.js +14 -11
- package/src/domain/services/StateSerializerV5.js +2 -2
- package/src/domain/services/StreamingBitmapIndexBuilder.js +26 -24
- package/src/domain/services/SyncAuthService.js +3 -2
- package/src/domain/services/SyncProtocol.js +25 -11
- package/src/domain/services/TemporalQuery.js +9 -6
- package/src/domain/services/TranslationCost.js +7 -5
- package/src/domain/services/WormholeService.js +16 -7
- package/src/domain/trust/TrustCanonical.js +3 -3
- package/src/domain/trust/TrustEvaluator.js +18 -3
- package/src/domain/trust/TrustRecordService.js +30 -23
- package/src/domain/trust/TrustStateBuilder.js +21 -8
- package/src/domain/trust/canonical.js +6 -6
- package/src/domain/types/TickReceipt.js +1 -1
- package/src/domain/types/WarpErrors.js +45 -0
- package/src/domain/types/WarpOptions.js +29 -0
- package/src/domain/types/WarpPersistence.js +41 -0
- package/src/domain/types/WarpTypes.js +2 -2
- package/src/domain/types/WarpTypesV2.js +2 -2
- package/src/domain/utils/MinHeap.js +6 -5
- package/src/domain/utils/canonicalStringify.js +5 -4
- package/src/domain/utils/roaring.js +31 -5
- package/src/domain/warp/PatchSession.js +40 -18
- package/src/domain/warp/_wiredMethods.d.ts +199 -45
- package/src/domain/warp/checkpoint.methods.js +5 -1
- package/src/domain/warp/fork.methods.js +2 -2
- package/src/domain/warp/materialize.methods.js +55 -5
- package/src/domain/warp/materializeAdvanced.methods.js +15 -4
- package/src/domain/warp/patch.methods.js +54 -29
- package/src/domain/warp/provenance.methods.js +5 -3
- package/src/domain/warp/query.methods.js +89 -6
- package/src/domain/warp/sync.methods.js +16 -11
- package/src/globals.d.ts +64 -0
- package/src/infrastructure/adapters/BunHttpAdapter.js +14 -9
- package/src/infrastructure/adapters/CasSeekCacheAdapter.js +9 -4
- package/src/infrastructure/adapters/DenoHttpAdapter.js +5 -6
- package/src/infrastructure/adapters/GitGraphAdapter.js +18 -13
- package/src/infrastructure/adapters/NodeHttpAdapter.js +2 -2
- package/src/infrastructure/adapters/WebCryptoAdapter.js +2 -2
- package/src/visualization/layouts/converters.js +2 -2
- package/src/visualization/layouts/elkAdapter.js +1 -1
- package/src/visualization/layouts/elkLayout.js +10 -7
- package/src/visualization/layouts/index.js +1 -1
- package/src/visualization/renderers/ascii/seek.js +16 -6
- package/src/visualization/renderers/svg/index.js +1 -1
package/index.d.ts
CHANGED
|
@@ -566,6 +566,15 @@ export interface GitPlumbing {
|
|
|
566
566
|
*/
|
|
567
567
|
export class InMemoryGraphAdapter extends GraphPersistencePort {
|
|
568
568
|
constructor();
|
|
569
|
+
|
|
570
|
+
get emptyTree(): string;
|
|
571
|
+
commitNode(options: CreateNodeOptions): Promise<string>;
|
|
572
|
+
showNode(sha: string): Promise<string>;
|
|
573
|
+
getNodeInfo(sha: string): Promise<NodeInfo>;
|
|
574
|
+
logNodesStream(options: ListNodesOptions & { format: string }): Promise<AsyncIterable<Uint8Array | string>>;
|
|
575
|
+
logNodes(options: ListNodesOptions & { format: string }): Promise<string>;
|
|
576
|
+
ping(): Promise<PingResult>;
|
|
577
|
+
countNodes(ref: string): Promise<number>;
|
|
569
578
|
}
|
|
570
579
|
|
|
571
580
|
/**
|
|
@@ -1032,7 +1041,7 @@ export class SyncError extends Error {
|
|
|
1032
1041
|
* Base error class for bitmap index operations.
|
|
1033
1042
|
*/
|
|
1034
1043
|
export class IndexError extends Error {
|
|
1035
|
-
readonly name:
|
|
1044
|
+
readonly name: string;
|
|
1036
1045
|
readonly code: string;
|
|
1037
1046
|
readonly context: Record<string, unknown>;
|
|
1038
1047
|
|
|
@@ -1138,6 +1147,12 @@ export function decodeEdgePropKey(encoded: string): { from: string; to: string;
|
|
|
1138
1147
|
*/
|
|
1139
1148
|
export function isEdgePropKey(key: string): boolean;
|
|
1140
1149
|
|
|
1150
|
+
/**
|
|
1151
|
+
* Well-known property key for content attachment.
|
|
1152
|
+
* Stores a content-addressed blob OID as the property value.
|
|
1153
|
+
*/
|
|
1154
|
+
export const CONTENT_PROPERTY_KEY: '_content';
|
|
1155
|
+
|
|
1141
1156
|
/**
|
|
1142
1157
|
* Configuration for an observer view.
|
|
1143
1158
|
*/
|
|
@@ -1293,12 +1308,69 @@ export interface TemporalQuery {
|
|
|
1293
1308
|
): Promise<boolean>;
|
|
1294
1309
|
}
|
|
1295
1310
|
|
|
1311
|
+
// ============================================================================
|
|
1312
|
+
// PatchV2 & PatchBuilderV2
|
|
1313
|
+
// ============================================================================
|
|
1314
|
+
|
|
1315
|
+
/**
|
|
1316
|
+
* WARP V5 patch object (schema 2 or 3).
|
|
1317
|
+
*/
|
|
1318
|
+
export interface PatchV2 {
|
|
1319
|
+
/** Schema version (2 for node/edge ops, 3 if edge properties present) */
|
|
1320
|
+
schema: 2 | 3;
|
|
1321
|
+
/** Writer ID */
|
|
1322
|
+
writer: string;
|
|
1323
|
+
/** Lamport timestamp for ordering */
|
|
1324
|
+
lamport: number;
|
|
1325
|
+
/** Writer's observed frontier (version vector) */
|
|
1326
|
+
context: Record<string, number>;
|
|
1327
|
+
/** Ordered array of operations */
|
|
1328
|
+
ops: unknown[];
|
|
1329
|
+
/** Node/edge IDs read by this patch (provenance tracking) */
|
|
1330
|
+
reads?: string[];
|
|
1331
|
+
/** Node/edge IDs written by this patch (provenance tracking) */
|
|
1332
|
+
writes?: string[];
|
|
1333
|
+
}
|
|
1334
|
+
|
|
1335
|
+
/**
|
|
1336
|
+
* Fluent builder for creating WARP v5 patches with OR-Set semantics.
|
|
1337
|
+
*
|
|
1338
|
+
* Returned by WarpGraph.createPatch(). Chain mutation methods then call
|
|
1339
|
+
* commit() to persist the patch atomically.
|
|
1340
|
+
*/
|
|
1341
|
+
export class PatchBuilderV2 {
|
|
1342
|
+
/** Adds a node to the graph. */
|
|
1343
|
+
addNode(nodeId: string): PatchBuilderV2;
|
|
1344
|
+
/** Removes a node from the graph. */
|
|
1345
|
+
removeNode(nodeId: string): PatchBuilderV2;
|
|
1346
|
+
/** Adds an edge between two nodes. */
|
|
1347
|
+
addEdge(from: string, to: string, label: string): PatchBuilderV2;
|
|
1348
|
+
/** Removes an edge between two nodes. */
|
|
1349
|
+
removeEdge(from: string, to: string, label: string): PatchBuilderV2;
|
|
1350
|
+
/** Sets a property on a node. */
|
|
1351
|
+
setProperty(nodeId: string, key: string, value: unknown): PatchBuilderV2;
|
|
1352
|
+
/** Sets a property on an edge. */
|
|
1353
|
+
setEdgeProperty(from: string, to: string, label: string, key: string, value: unknown): PatchBuilderV2;
|
|
1354
|
+
/** Attaches content to a node (writes blob + sets _content property). */
|
|
1355
|
+
attachContent(nodeId: string, content: Buffer | string): Promise<PatchBuilderV2>;
|
|
1356
|
+
/** Attaches content to an edge (writes blob + sets _content edge property). */
|
|
1357
|
+
attachEdgeContent(from: string, to: string, label: string, content: Buffer | string): Promise<PatchBuilderV2>;
|
|
1358
|
+
/** Builds the PatchV2 object without committing. */
|
|
1359
|
+
build(): PatchV2;
|
|
1360
|
+
/** Commits the patch to the graph and returns the commit SHA. */
|
|
1361
|
+
commit(): Promise<string>;
|
|
1362
|
+
/** Number of operations in this patch. */
|
|
1363
|
+
readonly opCount: number;
|
|
1364
|
+
}
|
|
1365
|
+
|
|
1296
1366
|
// ============================================================================
|
|
1297
1367
|
// Writer & PatchSession
|
|
1298
1368
|
// ============================================================================
|
|
1299
1369
|
|
|
1300
1370
|
/**
|
|
1301
1371
|
* Fluent patch session for building and committing graph mutations.
|
|
1372
|
+
*
|
|
1373
|
+
* Created by Writer.beginPatch(). Wraps a PatchBuilderV2 with CAS protection.
|
|
1302
1374
|
*/
|
|
1303
1375
|
export class PatchSession {
|
|
1304
1376
|
/** Adds a node to the graph. */
|
|
@@ -1313,8 +1385,12 @@ export class PatchSession {
|
|
|
1313
1385
|
setProperty(nodeId: string, key: string, value: unknown): this;
|
|
1314
1386
|
/** Sets a property on an edge. */
|
|
1315
1387
|
setEdgeProperty(from: string, to: string, label: string, key: string, value: unknown): this;
|
|
1316
|
-
/**
|
|
1317
|
-
|
|
1388
|
+
/** Attaches content to a node (writes blob + sets _content property). */
|
|
1389
|
+
attachContent(nodeId: string, content: Buffer | string): Promise<this>;
|
|
1390
|
+
/** Attaches content to an edge (writes blob + sets _content edge property). */
|
|
1391
|
+
attachEdgeContent(from: string, to: string, label: string, content: Buffer | string): Promise<this>;
|
|
1392
|
+
/** Builds the PatchV2 object without committing. */
|
|
1393
|
+
build(): PatchV2;
|
|
1318
1394
|
/** Commits the patch with CAS protection. */
|
|
1319
1395
|
commit(): Promise<string>;
|
|
1320
1396
|
/** Number of operations in this patch. */
|
|
@@ -1527,21 +1603,21 @@ export default class WarpGraph {
|
|
|
1527
1603
|
setSeekCache(cache: SeekCachePort | null): void;
|
|
1528
1604
|
|
|
1529
1605
|
/**
|
|
1530
|
-
* Creates a new
|
|
1606
|
+
* Creates a new PatchBuilderV2 for adding operations.
|
|
1531
1607
|
*/
|
|
1532
|
-
createPatch(): Promise<
|
|
1608
|
+
createPatch(): Promise<PatchBuilderV2>;
|
|
1533
1609
|
|
|
1534
1610
|
/**
|
|
1535
1611
|
* Convenience wrapper: creates a patch, runs the callback, and commits.
|
|
1536
1612
|
*
|
|
1537
|
-
* The callback receives a
|
|
1613
|
+
* The callback receives a PatchBuilderV2 and may be synchronous or
|
|
1538
1614
|
* asynchronous. The commit happens only after the callback resolves.
|
|
1539
1615
|
* If the callback throws or rejects, no commit is attempted.
|
|
1540
1616
|
*
|
|
1541
1617
|
* Not reentrant: calling `graph.patch()` inside a callback throws.
|
|
1542
1618
|
* Use `createPatch()` directly for nested or concurrent patches.
|
|
1543
1619
|
*/
|
|
1544
|
-
patch(build: (patch:
|
|
1620
|
+
patch(build: (patch: PatchBuilderV2) => void | Promise<void>): Promise<string>;
|
|
1545
1621
|
|
|
1546
1622
|
/**
|
|
1547
1623
|
* Returns patches from a writer's ref chain.
|
|
@@ -1549,7 +1625,7 @@ export default class WarpGraph {
|
|
|
1549
1625
|
getWriterPatches(
|
|
1550
1626
|
writerId: string,
|
|
1551
1627
|
stopAtSha?: string | null
|
|
1552
|
-
): Promise<Array<{ patch:
|
|
1628
|
+
): Promise<Array<{ patch: PatchV2; sha: string }>>;
|
|
1553
1629
|
|
|
1554
1630
|
/**
|
|
1555
1631
|
* Gets all visible nodes in the materialized state.
|
|
@@ -1583,6 +1659,28 @@ export default class WarpGraph {
|
|
|
1583
1659
|
*/
|
|
1584
1660
|
getEdgeProps(from: string, to: string, label: string): Promise<Record<string, unknown> | null>;
|
|
1585
1661
|
|
|
1662
|
+
/**
|
|
1663
|
+
* Gets the content blob OID for a node, or null if none is attached.
|
|
1664
|
+
*/
|
|
1665
|
+
getContentOid(nodeId: string): Promise<string | null>;
|
|
1666
|
+
|
|
1667
|
+
/**
|
|
1668
|
+
* Gets the content blob for a node, or null if none is attached.
|
|
1669
|
+
* Returns raw Buffer; call `.toString('utf8')` for text.
|
|
1670
|
+
*/
|
|
1671
|
+
getContent(nodeId: string): Promise<Buffer | null>;
|
|
1672
|
+
|
|
1673
|
+
/**
|
|
1674
|
+
* Gets the content blob OID for an edge, or null if none is attached.
|
|
1675
|
+
*/
|
|
1676
|
+
getEdgeContentOid(from: string, to: string, label: string): Promise<string | null>;
|
|
1677
|
+
|
|
1678
|
+
/**
|
|
1679
|
+
* Gets the content blob for an edge, or null if none is attached.
|
|
1680
|
+
* Returns raw Buffer; call `.toString('utf8')` for text.
|
|
1681
|
+
*/
|
|
1682
|
+
getEdgeContent(from: string, to: string, label: string): Promise<Buffer | null>;
|
|
1683
|
+
|
|
1586
1684
|
/**
|
|
1587
1685
|
* Checks if a node exists in the materialized state.
|
|
1588
1686
|
*/
|
|
@@ -1621,7 +1719,7 @@ export default class WarpGraph {
|
|
|
1621
1719
|
/**
|
|
1622
1720
|
* Materializes graph state from a checkpoint, applying incremental patches.
|
|
1623
1721
|
*/
|
|
1624
|
-
materializeAt(checkpointSha: string): Promise<
|
|
1722
|
+
materializeAt(checkpointSha: string): Promise<WarpStateV5>;
|
|
1625
1723
|
|
|
1626
1724
|
/**
|
|
1627
1725
|
* Logical graph traversal helpers.
|
|
@@ -1654,8 +1752,12 @@ export default class WarpGraph {
|
|
|
1654
1752
|
|
|
1655
1753
|
/**
|
|
1656
1754
|
* Materializes the current graph state from all patches.
|
|
1755
|
+
*
|
|
1756
|
+
* When `options.receipts` is true, returns `{ state, receipts }`.
|
|
1757
|
+
* Otherwise returns the WarpStateV5 directly.
|
|
1657
1758
|
*/
|
|
1658
|
-
materialize(): Promise<
|
|
1759
|
+
materialize(options: { receipts: true; ceiling?: number | null }): Promise<{ state: WarpStateV5; receipts: TickReceipt[] }>;
|
|
1760
|
+
materialize(options?: { receipts?: false; ceiling?: number | null }): Promise<WarpStateV5>;
|
|
1659
1761
|
|
|
1660
1762
|
/**
|
|
1661
1763
|
* Starts a built-in sync server for this graph.
|
|
@@ -1672,6 +1774,8 @@ export default class WarpGraph {
|
|
|
1672
1774
|
|
|
1673
1775
|
/**
|
|
1674
1776
|
* Syncs with a remote peer (HTTP URL or another WarpGraph instance).
|
|
1777
|
+
*
|
|
1778
|
+
* When `options.materialize` is true, the returned object also contains a `state` property.
|
|
1675
1779
|
*/
|
|
1676
1780
|
syncWith(remote: string | WarpGraph, options?: {
|
|
1677
1781
|
path?: string;
|
|
@@ -1688,7 +1792,9 @@ export default class WarpGraph {
|
|
|
1688
1792
|
error?: Error;
|
|
1689
1793
|
}) => void;
|
|
1690
1794
|
auth?: SyncAuthClientOptions;
|
|
1691
|
-
|
|
1795
|
+
/** Auto-materialize after sync; when true, result includes `state` */
|
|
1796
|
+
materialize?: boolean;
|
|
1797
|
+
}): Promise<{ applied: number; attempts: number; state?: WarpStateV5 }>;
|
|
1692
1798
|
|
|
1693
1799
|
/**
|
|
1694
1800
|
* Creates a fork of this graph at a specific point in a writer's history.
|
|
@@ -2113,17 +2219,7 @@ export function migrateV4toV5(v4State: {
|
|
|
2113
2219
|
*/
|
|
2114
2220
|
export interface PatchEntry {
|
|
2115
2221
|
/** The decoded patch object */
|
|
2116
|
-
patch:
|
|
2117
|
-
schema: 2 | 3;
|
|
2118
|
-
writer: string;
|
|
2119
|
-
lamport: number;
|
|
2120
|
-
context: Record<string, number> | Map<string, number>;
|
|
2121
|
-
ops: unknown[];
|
|
2122
|
-
/** Node/edge IDs read by this patch (V2 provenance) */
|
|
2123
|
-
reads?: string[];
|
|
2124
|
-
/** Node/edge IDs written by this patch (V2 provenance) */
|
|
2125
|
-
writes?: string[];
|
|
2126
|
-
};
|
|
2222
|
+
patch: PatchV2;
|
|
2127
2223
|
/** The Git SHA of the patch commit */
|
|
2128
2224
|
sha: string;
|
|
2129
2225
|
}
|
package/index.js
CHANGED
|
@@ -75,6 +75,7 @@ import {
|
|
|
75
75
|
encodeEdgePropKey,
|
|
76
76
|
decodeEdgePropKey,
|
|
77
77
|
isEdgePropKey,
|
|
78
|
+
CONTENT_PROPERTY_KEY,
|
|
78
79
|
} from './src/domain/services/KeyCodec.js';
|
|
79
80
|
import {
|
|
80
81
|
createTickReceipt,
|
|
@@ -173,6 +174,7 @@ export {
|
|
|
173
174
|
encodeEdgePropKey,
|
|
174
175
|
decodeEdgePropKey,
|
|
175
176
|
isEdgePropKey,
|
|
177
|
+
CONTENT_PROPERTY_KEY,
|
|
176
178
|
|
|
177
179
|
// WARP migration
|
|
178
180
|
migrateV4toV5,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@git-stunts/git-warp",
|
|
3
|
-
"version": "11.
|
|
3
|
+
"version": "11.5.0",
|
|
4
4
|
"description": "Deterministic WARP graph over Git: graph-native storage, traversal, and tooling.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -78,7 +78,7 @@
|
|
|
78
78
|
"demo:down": "cd examples && docker compose down -v",
|
|
79
79
|
"setup:hooks": "node scripts/setup-hooks.js",
|
|
80
80
|
"prepare": "patch-package && node scripts/setup-hooks.js",
|
|
81
|
-
"prepack": "npm run lint && npm run test:local",
|
|
81
|
+
"prepack": "npm run lint && npm run test:local && npm run typecheck:consumer",
|
|
82
82
|
"install:git-warp": "bash scripts/install-git-warp.sh",
|
|
83
83
|
"uninstall:git-warp": "bash scripts/uninstall-git-warp.sh",
|
|
84
84
|
"test:node20": "docker compose -f docker-compose.test.yml --profile node20 run --build --rm test-node20",
|
|
@@ -89,7 +89,9 @@
|
|
|
89
89
|
"typecheck": "tsc --noEmit",
|
|
90
90
|
"typecheck:src": "tsc --noEmit -p tsconfig.src.json",
|
|
91
91
|
"typecheck:test": "tsc --noEmit -p tsconfig.test.json",
|
|
92
|
-
"typecheck:
|
|
92
|
+
"typecheck:consumer": "tsc --noEmit -p test/type-check/tsconfig.json",
|
|
93
|
+
"typecheck:policy": "node scripts/ts-policy-check.js",
|
|
94
|
+
"typecheck:surface": "node scripts/check-dts-surface.js"
|
|
93
95
|
},
|
|
94
96
|
"dependencies": {
|
|
95
97
|
"@git-stunts/alfred": "^0.4.0",
|
package/src/domain/WarpGraph.js
CHANGED
|
@@ -95,6 +95,9 @@ export default class WarpGraph {
|
|
|
95
95
|
/** @type {number} */
|
|
96
96
|
this._patchesSinceCheckpoint = 0;
|
|
97
97
|
|
|
98
|
+
/** @type {number} */
|
|
99
|
+
this._maxObservedLamport = 0;
|
|
100
|
+
|
|
98
101
|
/** @type {{every: number}|null} */
|
|
99
102
|
this._checkpointPolicy = checkpointPolicy || null;
|
|
100
103
|
|
|
@@ -285,7 +288,7 @@ export default class WarpGraph {
|
|
|
285
288
|
// Initialize audit service if enabled
|
|
286
289
|
if (graph._audit) {
|
|
287
290
|
graph._auditService = new AuditReceiptService({
|
|
288
|
-
persistence: /** @type {
|
|
291
|
+
persistence: /** @type {import('./types/WarpPersistence.js').CorePersistence} */ (persistence),
|
|
289
292
|
graphName,
|
|
290
293
|
writerId,
|
|
291
294
|
codec: graph._codec,
|
package/src/domain/crdt/ORSet.js
CHANGED
|
@@ -91,7 +91,7 @@ import { vvContains } from './VersionVector.js';
|
|
|
91
91
|
* An element is present if it has at least one non-tombstoned dot.
|
|
92
92
|
*
|
|
93
93
|
* @typedef {Object} ORSet
|
|
94
|
-
* @property {Map
|
|
94
|
+
* @property {Map<string, Set<string>>} entries - element -> dots that added it
|
|
95
95
|
* @property {Set<string>} tombstones - global tombstones
|
|
96
96
|
*/
|
|
97
97
|
|
|
@@ -112,7 +112,7 @@ export function createORSet() {
|
|
|
112
112
|
* Mutates the set.
|
|
113
113
|
*
|
|
114
114
|
* @param {ORSet} set - The ORSet to mutate
|
|
115
|
-
* @param {
|
|
115
|
+
* @param {string} element - The element to add
|
|
116
116
|
* @param {import('./Dot.js').Dot} dot - The dot representing this add operation
|
|
117
117
|
*/
|
|
118
118
|
export function orsetAdd(set, element, dot) {
|
|
@@ -145,7 +145,7 @@ export function orsetRemove(set, observedDots) {
|
|
|
145
145
|
* An element is present if it has at least one non-tombstoned dot.
|
|
146
146
|
*
|
|
147
147
|
* @param {ORSet} set - The ORSet to check
|
|
148
|
-
* @param {
|
|
148
|
+
* @param {string} element - The element to check
|
|
149
149
|
* @returns {boolean}
|
|
150
150
|
*/
|
|
151
151
|
export function orsetContains(set, element) {
|
|
@@ -168,7 +168,7 @@ export function orsetContains(set, element) {
|
|
|
168
168
|
* Only returns elements that have at least one non-tombstoned dot.
|
|
169
169
|
*
|
|
170
170
|
* @param {ORSet} set - The ORSet
|
|
171
|
-
* @returns {
|
|
171
|
+
* @returns {string[]} Array of present elements
|
|
172
172
|
*/
|
|
173
173
|
export function orsetElements(set) {
|
|
174
174
|
const result = [];
|
|
@@ -186,7 +186,7 @@ export function orsetElements(set) {
|
|
|
186
186
|
* Returns the non-tombstoned dots for an element.
|
|
187
187
|
*
|
|
188
188
|
* @param {ORSet} set - The ORSet
|
|
189
|
-
* @param {
|
|
189
|
+
* @param {string} element - The element
|
|
190
190
|
* @returns {Set<string>} Set of encoded dots that are not tombstoned
|
|
191
191
|
*/
|
|
192
192
|
export function orsetGetDots(set, element) {
|
|
@@ -311,11 +311,11 @@ export function orsetCompact(set, includedVV) {
|
|
|
311
311
|
* Tombstones are sorted.
|
|
312
312
|
*
|
|
313
313
|
* @param {ORSet} set
|
|
314
|
-
* @returns {{entries: Array<[
|
|
314
|
+
* @returns {{entries: Array<[string, string[]]>, tombstones: string[]}}
|
|
315
315
|
*/
|
|
316
316
|
export function orsetSerialize(set) {
|
|
317
317
|
// Serialize entries: convert Map to array of [element, sortedDots]
|
|
318
|
-
/** @type {Array<[
|
|
318
|
+
/** @type {Array<[string, string[]]>} */
|
|
319
319
|
const entriesArray = [];
|
|
320
320
|
for (const [element, dots] of set.entries) {
|
|
321
321
|
const sortedDots = [...dots].sort((a, b) => {
|
|
@@ -349,7 +349,7 @@ export function orsetSerialize(set) {
|
|
|
349
349
|
/**
|
|
350
350
|
* Deserializes a plain object back to an ORSet.
|
|
351
351
|
*
|
|
352
|
-
* @param {{entries?: Array<[
|
|
352
|
+
* @param {{entries?: Array<[string, string[]]>, tombstones?: string[]}} obj
|
|
353
353
|
* @returns {ORSet}
|
|
354
354
|
*/
|
|
355
355
|
export function orsetDeserialize(obj) {
|
|
@@ -12,7 +12,7 @@ import IndexError from './IndexError.js';
|
|
|
12
12
|
* @property {string} name - The error name ('EmptyMessageError')
|
|
13
13
|
* @property {string} code - Error code ('EMPTY_MESSAGE')
|
|
14
14
|
* @property {string} operation - The operation that failed due to empty message
|
|
15
|
-
* @property {Record<string,
|
|
15
|
+
* @property {Record<string, unknown>} context - Serializable context object for debugging
|
|
16
16
|
*
|
|
17
17
|
* @example
|
|
18
18
|
* if (!message || message.trim() === '') {
|
|
@@ -27,7 +27,7 @@ export default class EmptyMessageError extends IndexError {
|
|
|
27
27
|
* Creates a new EmptyMessageError.
|
|
28
28
|
*
|
|
29
29
|
* @param {string} message - Human-readable error message
|
|
30
|
-
* @param {{ operation?: string, context?: Record<string,
|
|
30
|
+
* @param {{ operation?: string, context?: Record<string, unknown> }} [options={}] - Error options
|
|
31
31
|
*/
|
|
32
32
|
constructor(message, options = {}) {
|
|
33
33
|
const context = {
|
|
@@ -26,7 +26,7 @@ import WarpError from './WarpError.js';
|
|
|
26
26
|
export default class ForkError extends WarpError {
|
|
27
27
|
/**
|
|
28
28
|
* @param {string} message
|
|
29
|
-
* @param {{ code?: string, context?:
|
|
29
|
+
* @param {{ code?: string, context?: Record<string, unknown> }} [options={}]
|
|
30
30
|
*/
|
|
31
31
|
constructor(message, options = {}) {
|
|
32
32
|
super(message, 'FORK_ERROR', options);
|
|
@@ -19,7 +19,7 @@ import WarpError from './WarpError.js';
|
|
|
19
19
|
export default class IndexError extends WarpError {
|
|
20
20
|
/**
|
|
21
21
|
* @param {string} message
|
|
22
|
-
* @param {{ code?: string, context?:
|
|
22
|
+
* @param {{ code?: string, context?: Record<string, unknown> }} [options={}]
|
|
23
23
|
*/
|
|
24
24
|
constructor(message, options = {}) {
|
|
25
25
|
super(message, 'INDEX_ERROR', options);
|
|
@@ -15,7 +15,7 @@ import WarpError from './WarpError.js';
|
|
|
15
15
|
export default class OperationAbortedError extends WarpError {
|
|
16
16
|
/**
|
|
17
17
|
* @param {string} operation
|
|
18
|
-
* @param {{ code?: string, context?:
|
|
18
|
+
* @param {{ code?: string, context?: Record<string, unknown>, reason?: string }} [options={}]
|
|
19
19
|
*/
|
|
20
20
|
constructor(operation, options = {}) {
|
|
21
21
|
const reason = options.reason || 'Operation was aborted';
|
|
@@ -35,7 +35,7 @@ import WarpError from './WarpError.js';
|
|
|
35
35
|
export default class QueryError extends WarpError {
|
|
36
36
|
/**
|
|
37
37
|
* @param {string} message
|
|
38
|
-
* @param {{ code?: string, context?:
|
|
38
|
+
* @param {{ code?: string, context?: Record<string, unknown> }} [options={}]
|
|
39
39
|
*/
|
|
40
40
|
constructor(message, options = {}) {
|
|
41
41
|
super(message, 'QUERY_ERROR', options);
|
|
@@ -13,7 +13,7 @@ import WarpError from './WarpError.js';
|
|
|
13
13
|
export default class SchemaUnsupportedError extends WarpError {
|
|
14
14
|
/**
|
|
15
15
|
* @param {string} message
|
|
16
|
-
* @param {{ code?: string, context?:
|
|
16
|
+
* @param {{ code?: string, context?: Record<string, unknown> }} [options={}]
|
|
17
17
|
*/
|
|
18
18
|
constructor(message, options = {}) {
|
|
19
19
|
super(message, 'E_SCHEMA_UNSUPPORTED', options);
|
|
@@ -14,7 +14,7 @@ import IndexError from './IndexError.js';
|
|
|
14
14
|
* @property {string} shardPath - Path to the corrupted shard file
|
|
15
15
|
* @property {string} oid - Object ID associated with the shard
|
|
16
16
|
* @property {string} reason - Reason for corruption (e.g., 'invalid_checksum', 'invalid_version', 'parse_error')
|
|
17
|
-
* @property {Record<string,
|
|
17
|
+
* @property {Record<string, unknown>} context - Serializable context object for debugging
|
|
18
18
|
*
|
|
19
19
|
* @example
|
|
20
20
|
* if (!validateChecksum(data)) {
|
|
@@ -30,7 +30,7 @@ export default class ShardCorruptionError extends IndexError {
|
|
|
30
30
|
* Creates a new ShardCorruptionError.
|
|
31
31
|
*
|
|
32
32
|
* @param {string} message - Human-readable error message
|
|
33
|
-
* @param {{ shardPath?: string, oid?: string, reason?: string, context?: Record<string,
|
|
33
|
+
* @param {{ shardPath?: string, oid?: string, reason?: string, context?: Record<string, unknown> }} [options={}] - Error options
|
|
34
34
|
*/
|
|
35
35
|
constructor(message, options = {}) {
|
|
36
36
|
const context = {
|
|
@@ -14,7 +14,7 @@ import IndexError from './IndexError.js';
|
|
|
14
14
|
* @property {string} shardPath - Path to the shard file that failed to load
|
|
15
15
|
* @property {string} oid - Object ID associated with the shard
|
|
16
16
|
* @property {Error} cause - The original error that caused the load failure
|
|
17
|
-
* @property {Record<string,
|
|
17
|
+
* @property {Record<string, unknown>} context - Serializable context object for debugging
|
|
18
18
|
*
|
|
19
19
|
* @example
|
|
20
20
|
* try {
|
|
@@ -32,7 +32,7 @@ export default class ShardLoadError extends IndexError {
|
|
|
32
32
|
* Creates a new ShardLoadError.
|
|
33
33
|
*
|
|
34
34
|
* @param {string} message - Human-readable error message
|
|
35
|
-
* @param {{ shardPath?: string, oid?: string, cause?: Error, context?: Record<string,
|
|
35
|
+
* @param {{ shardPath?: string, oid?: string, cause?: Error, context?: Record<string, unknown> }} [options={}] - Error options
|
|
36
36
|
*/
|
|
37
37
|
constructor(message, options = {}) {
|
|
38
38
|
const context = {
|
|
@@ -12,10 +12,10 @@ import IndexError from './IndexError.js';
|
|
|
12
12
|
* @property {string} name - The error name ('ShardValidationError')
|
|
13
13
|
* @property {string} code - Error code ('SHARD_VALIDATION_ERROR')
|
|
14
14
|
* @property {string} shardPath - Path to the shard file that failed validation
|
|
15
|
-
* @property {
|
|
16
|
-
* @property {
|
|
15
|
+
* @property {unknown} expected - The expected value for the field
|
|
16
|
+
* @property {unknown} actual - The actual value found in the shard
|
|
17
17
|
* @property {string} field - The field that failed validation (e.g., 'checksum', 'version')
|
|
18
|
-
* @property {Record<string,
|
|
18
|
+
* @property {Record<string, unknown>} context - Serializable context object for debugging
|
|
19
19
|
*
|
|
20
20
|
* @example
|
|
21
21
|
* if (shard.version !== EXPECTED_VERSION) {
|
|
@@ -32,7 +32,7 @@ export default class ShardValidationError extends IndexError {
|
|
|
32
32
|
* Creates a new ShardValidationError.
|
|
33
33
|
*
|
|
34
34
|
* @param {string} message - Human-readable error message
|
|
35
|
-
* @param {{ shardPath?: string, expected?:
|
|
35
|
+
* @param {{ shardPath?: string, expected?: unknown, actual?: unknown, field?: string, context?: Record<string, unknown> }} [options={}] - Error options
|
|
36
36
|
*/
|
|
37
37
|
constructor(message, options = {}) {
|
|
38
38
|
const context = {
|
|
@@ -14,7 +14,7 @@ import IndexError from './IndexError.js';
|
|
|
14
14
|
* @property {string} operation - The operation that failed ('read' or 'write')
|
|
15
15
|
* @property {string} oid - Object ID associated with the operation
|
|
16
16
|
* @property {Error} cause - The original error that caused the failure
|
|
17
|
-
* @property {Record<string,
|
|
17
|
+
* @property {Record<string, unknown>} context - Serializable context object for debugging
|
|
18
18
|
*
|
|
19
19
|
* @example
|
|
20
20
|
* try {
|
|
@@ -32,7 +32,7 @@ export default class StorageError extends IndexError {
|
|
|
32
32
|
* Creates a new StorageError.
|
|
33
33
|
*
|
|
34
34
|
* @param {string} message - Human-readable error message
|
|
35
|
-
* @param {{ operation?: string, oid?: string, cause?: Error, context?: Record<string,
|
|
35
|
+
* @param {{ operation?: string, oid?: string, cause?: Error, context?: Record<string, unknown> }} [options={}] - Error options
|
|
36
36
|
*/
|
|
37
37
|
constructor(message, options = {}) {
|
|
38
38
|
const context = {
|
|
@@ -26,7 +26,7 @@ import WarpError from './WarpError.js';
|
|
|
26
26
|
export default class SyncError extends WarpError {
|
|
27
27
|
/**
|
|
28
28
|
* @param {string} message
|
|
29
|
-
* @param {{ code?: string, context?:
|
|
29
|
+
* @param {{ code?: string, context?: Record<string, unknown> }} [options={}]
|
|
30
30
|
*/
|
|
31
31
|
constructor(message, options = {}) {
|
|
32
32
|
super(message, 'SYNC_ERROR', options);
|
|
@@ -19,7 +19,7 @@ import WarpError from './WarpError.js';
|
|
|
19
19
|
export default class TraversalError extends WarpError {
|
|
20
20
|
/**
|
|
21
21
|
* @param {string} message
|
|
22
|
-
* @param {{ code?: string, context?:
|
|
22
|
+
* @param {{ code?: string, context?: Record<string, unknown> }} [options={}]
|
|
23
23
|
*/
|
|
24
24
|
constructor(message, options = {}) {
|
|
25
25
|
super(message, 'TRAVERSAL_ERROR', options);
|
|
@@ -21,7 +21,7 @@ import WarpError from './WarpError.js';
|
|
|
21
21
|
export default class TrustError extends WarpError {
|
|
22
22
|
/**
|
|
23
23
|
* @param {string} message
|
|
24
|
-
* @param {{ code?: string, context?:
|
|
24
|
+
* @param {{ code?: string, context?: Record<string, unknown> }} [options={}]
|
|
25
25
|
*/
|
|
26
26
|
constructor(message, options = {}) {
|
|
27
27
|
super(message, 'TRUST_ERROR', options);
|
|
@@ -10,13 +10,13 @@
|
|
|
10
10
|
*
|
|
11
11
|
* @property {string} name - Error name (set from constructor.name)
|
|
12
12
|
* @property {string} code - Machine-readable error code
|
|
13
|
-
* @property {Record<string,
|
|
13
|
+
* @property {Record<string, unknown>} context - Serializable context for debugging
|
|
14
14
|
*/
|
|
15
15
|
export default class WarpError extends Error {
|
|
16
16
|
/**
|
|
17
17
|
* @param {string} message - Human-readable error message
|
|
18
18
|
* @param {string} defaultCode - Default error code if not overridden by options
|
|
19
|
-
* @param {{ code?: string, context?: Record<string,
|
|
19
|
+
* @param {{ code?: string, context?: Record<string, unknown> }} [options={}] - Error options
|
|
20
20
|
*/
|
|
21
21
|
constructor(message, defaultCode, options = {}) {
|
|
22
22
|
super(message);
|
|
@@ -24,7 +24,7 @@ import WarpError from './WarpError.js';
|
|
|
24
24
|
export default class WormholeError extends WarpError {
|
|
25
25
|
/**
|
|
26
26
|
* @param {string} message
|
|
27
|
-
* @param {{ code?: string, context?:
|
|
27
|
+
* @param {{ code?: string, context?: Record<string, unknown> }} [options={}]
|
|
28
28
|
*/
|
|
29
29
|
constructor(message, options = {}) {
|
|
30
30
|
super(message, 'WORMHOLE_ERROR', options);
|
|
@@ -290,12 +290,12 @@ export class AuditReceiptService {
|
|
|
290
290
|
|
|
291
291
|
try {
|
|
292
292
|
return await this._commitInner(tickReceipt);
|
|
293
|
-
} catch (
|
|
293
|
+
} catch (err) {
|
|
294
294
|
this._failed++;
|
|
295
295
|
this._logger?.warn('[warp:audit]', {
|
|
296
296
|
code: 'AUDIT_COMMIT_FAILED',
|
|
297
297
|
writerId: this._writerId,
|
|
298
|
-
error: err
|
|
298
|
+
error: err instanceof Error ? err.message : String(err),
|
|
299
299
|
});
|
|
300
300
|
return null;
|
|
301
301
|
}
|
|
@@ -366,11 +366,11 @@ export class AuditReceiptService {
|
|
|
366
366
|
let blobOid;
|
|
367
367
|
try {
|
|
368
368
|
blobOid = await this._persistence.writeBlob(Buffer.from(cborBytes));
|
|
369
|
-
} catch (
|
|
369
|
+
} catch (err) {
|
|
370
370
|
this._logger?.warn('[warp:audit]', {
|
|
371
371
|
code: 'AUDIT_WRITE_BLOB_FAILED',
|
|
372
372
|
writerId: this._writerId,
|
|
373
|
-
error: err
|
|
373
|
+
error: err instanceof Error ? err.message : String(err),
|
|
374
374
|
});
|
|
375
375
|
throw err;
|
|
376
376
|
}
|
|
@@ -381,11 +381,11 @@ export class AuditReceiptService {
|
|
|
381
381
|
treeOid = await this._persistence.writeTree([
|
|
382
382
|
`100644 blob ${blobOid}\treceipt.cbor`,
|
|
383
383
|
]);
|
|
384
|
-
} catch (
|
|
384
|
+
} catch (err) {
|
|
385
385
|
this._logger?.warn('[warp:audit]', {
|
|
386
386
|
code: 'AUDIT_WRITE_TREE_FAILED',
|
|
387
387
|
writerId: this._writerId,
|
|
388
|
-
error: err
|
|
388
|
+
error: err instanceof Error ? err.message : String(err),
|
|
389
389
|
});
|
|
390
390
|
throw err;
|
|
391
391
|
}
|