@git-stunts/git-warp 11.2.1 → 11.3.3
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/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 +82 -22
- package/package.json +3 -2
- 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 +2 -2
- 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 +11 -11
- 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 +42 -26
- 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 +9 -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 +6 -5
- 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 +14 -12
- 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
|
@@ -6,6 +6,7 @@ import { getRoaringBitmap32 } from '../utils/roaring.js';
|
|
|
6
6
|
import { canonicalStringify } from '../utils/canonicalStringify.js';
|
|
7
7
|
|
|
8
8
|
/** @typedef {import('../../ports/IndexStoragePort.js').default} IndexStoragePort */
|
|
9
|
+
/** @typedef {import('../types/WarpPersistence.js').IndexStorage} IndexStorage */
|
|
9
10
|
/** @typedef {import('../../ports/LoggerPort.js').default} LoggerPort */
|
|
10
11
|
/** @typedef {import('../../ports/CryptoPort.js').default} CryptoPort */
|
|
11
12
|
|
|
@@ -89,11 +90,11 @@ export default class BitmapIndexReader {
|
|
|
89
90
|
* When exceeded, least recently used shards are evicted to free memory.
|
|
90
91
|
* @param {import('../../ports/CryptoPort.js').default} [options.crypto] - CryptoPort instance for checksum verification.
|
|
91
92
|
*/
|
|
92
|
-
constructor({ storage, strict = false, logger = nullLogger, maxCachedShards = DEFAULT_MAX_CACHED_SHARDS, crypto } = /** @type {
|
|
93
|
+
constructor({ storage, strict = false, logger = nullLogger, maxCachedShards = DEFAULT_MAX_CACHED_SHARDS, crypto } = /** @type {{ storage: IndexStoragePort, strict?: boolean, logger?: LoggerPort, maxCachedShards?: number, crypto?: CryptoPort }} */ ({})) {
|
|
93
94
|
if (!storage) {
|
|
94
95
|
throw new Error('BitmapIndexReader requires a storage adapter');
|
|
95
96
|
}
|
|
96
|
-
this.storage = storage;
|
|
97
|
+
this.storage = /** @type {IndexStorage} */ (storage);
|
|
97
98
|
this.strict = strict;
|
|
98
99
|
this.logger = logger;
|
|
99
100
|
this.maxCachedShards = maxCachedShards;
|
|
@@ -144,7 +145,8 @@ export default class BitmapIndexReader {
|
|
|
144
145
|
async lookupId(sha) {
|
|
145
146
|
const prefix = sha.substring(0, 2);
|
|
146
147
|
const path = `meta_${prefix}.json`;
|
|
147
|
-
|
|
148
|
+
// Meta shards always map SHA→numeric ID (built by BitmapIndexBuilder)
|
|
149
|
+
const idMap = /** @type {Record<string, number>} */ (await this._getOrLoadShard(path, 'json'));
|
|
148
150
|
return idMap[sha];
|
|
149
151
|
}
|
|
150
152
|
|
|
@@ -176,7 +178,8 @@ export default class BitmapIndexReader {
|
|
|
176
178
|
async _getEdges(sha, type) {
|
|
177
179
|
const prefix = sha.substring(0, 2);
|
|
178
180
|
const shardPath = `shards_${type}_${prefix}.json`;
|
|
179
|
-
|
|
181
|
+
// Bitmap shards always map SHA→base64-encoded bitmap data
|
|
182
|
+
const shard = /** @type {Record<string, string>} */ (await this._getOrLoadShard(shardPath, 'json'));
|
|
180
183
|
|
|
181
184
|
const encoded = shard[sha];
|
|
182
185
|
if (!encoded) {
|
|
@@ -195,7 +198,7 @@ export default class BitmapIndexReader {
|
|
|
195
198
|
shardPath,
|
|
196
199
|
oid: this.shardOids.get(shardPath),
|
|
197
200
|
reason: 'bitmap_deserialize_error',
|
|
198
|
-
context: { originalError:
|
|
201
|
+
context: { originalError: err instanceof Error ? err.message : String(err) },
|
|
199
202
|
});
|
|
200
203
|
this._handleShardError(corruptionError, {
|
|
201
204
|
path: shardPath,
|
|
@@ -224,7 +227,8 @@ export default class BitmapIndexReader {
|
|
|
224
227
|
|
|
225
228
|
for (const [path] of this.shardOids) {
|
|
226
229
|
if (path.startsWith('meta_') && path.endsWith('.json')) {
|
|
227
|
-
|
|
230
|
+
// Meta shards always map SHA→numeric ID (built by BitmapIndexBuilder)
|
|
231
|
+
const shard = /** @type {Record<string, number>} */ (await this._getOrLoadShard(path, 'json'));
|
|
228
232
|
for (const [sha, id] of Object.entries(shard)) {
|
|
229
233
|
this._idToShaCache[id] = sha;
|
|
230
234
|
}
|
|
@@ -247,10 +251,10 @@ export default class BitmapIndexReader {
|
|
|
247
251
|
/**
|
|
248
252
|
* Validates a shard envelope for version and checksum integrity.
|
|
249
253
|
*
|
|
250
|
-
* @param {{ data?:
|
|
254
|
+
* @param {{ data?: Record<string, string | number>, version?: number, checksum?: string }} envelope - The shard envelope to validate
|
|
251
255
|
* @param {string} path - Shard path (for error context)
|
|
252
256
|
* @param {string} oid - Object ID (for error context)
|
|
253
|
-
* @returns {Promise<
|
|
257
|
+
* @returns {Promise<Record<string, string | number>>} The validated data from the envelope
|
|
254
258
|
* @throws {ShardCorruptionError} If envelope format is invalid
|
|
255
259
|
* @throws {ShardValidationError} If version or checksum validation fails
|
|
256
260
|
* @private
|
|
@@ -299,7 +303,7 @@ export default class BitmapIndexReader {
|
|
|
299
303
|
* @param {string} context.path - Shard path
|
|
300
304
|
* @param {string} context.oid - Object ID
|
|
301
305
|
* @param {string} context.format - 'json' or 'bitmap'
|
|
302
|
-
* @returns {
|
|
306
|
+
* @returns {Record<string, string | number> | import('../utils/roaring.js').RoaringBitmapSubset} Empty shard (non-strict mode only)
|
|
303
307
|
* @throws {ShardCorruptionError|ShardValidationError} In strict mode
|
|
304
308
|
* @private
|
|
305
309
|
*/
|
|
@@ -307,17 +311,21 @@ export default class BitmapIndexReader {
|
|
|
307
311
|
if (this.strict) {
|
|
308
312
|
throw err;
|
|
309
313
|
}
|
|
310
|
-
/** @type {
|
|
311
|
-
const
|
|
314
|
+
/** @type {string|undefined} */
|
|
315
|
+
const field = err instanceof ShardValidationError ? err.field : undefined;
|
|
316
|
+
/** @type {unknown} */
|
|
317
|
+
const expected = err instanceof ShardValidationError ? err.expected : undefined;
|
|
318
|
+
/** @type {unknown} */
|
|
319
|
+
const actual = err instanceof ShardValidationError ? err.actual : undefined;
|
|
312
320
|
this.logger.warn('Shard validation warning', {
|
|
313
321
|
operation: 'loadShard',
|
|
314
322
|
shardPath: path,
|
|
315
323
|
oid,
|
|
316
324
|
error: err.message,
|
|
317
325
|
code: err.code,
|
|
318
|
-
field
|
|
319
|
-
expected
|
|
320
|
-
actual
|
|
326
|
+
field,
|
|
327
|
+
expected,
|
|
328
|
+
actual,
|
|
321
329
|
});
|
|
322
330
|
const emptyShard = format === 'json' ? {} : new (getRoaringBitmap32())();
|
|
323
331
|
this.loadedShards.set(path, emptyShard);
|
|
@@ -329,7 +337,7 @@ export default class BitmapIndexReader {
|
|
|
329
337
|
* @param {Buffer} buffer - Raw shard buffer
|
|
330
338
|
* @param {string} path - Shard path (for error context)
|
|
331
339
|
* @param {string} oid - Object ID (for error context)
|
|
332
|
-
* @returns {Promise<
|
|
340
|
+
* @returns {Promise<Record<string, string | number>>} The validated data from the shard
|
|
333
341
|
* @throws {ShardCorruptionError} If parsing fails or format is invalid
|
|
334
342
|
* @throws {ShardValidationError} If version or checksum validation fails
|
|
335
343
|
* @private
|
|
@@ -349,7 +357,7 @@ export default class BitmapIndexReader {
|
|
|
349
357
|
*/
|
|
350
358
|
async _loadShardBuffer(path, oid) {
|
|
351
359
|
try {
|
|
352
|
-
return await
|
|
360
|
+
return await this.storage.readBlob(oid);
|
|
353
361
|
} catch (cause) {
|
|
354
362
|
throw new ShardLoadError('Failed to load shard from storage', {
|
|
355
363
|
shardPath: path,
|
|
@@ -382,15 +390,16 @@ export default class BitmapIndexReader {
|
|
|
382
390
|
/**
|
|
383
391
|
* Attempts to handle a shard error based on its type.
|
|
384
392
|
* Returns handled result for validation/corruption errors, null otherwise.
|
|
385
|
-
* @param {
|
|
393
|
+
* @param {unknown} err - The error to handle
|
|
386
394
|
* @param {Object} context - Error context
|
|
387
395
|
* @param {string} context.path - Shard path
|
|
388
396
|
* @param {string} context.oid - Object ID
|
|
389
397
|
* @param {string} context.format - 'json' or 'bitmap'
|
|
390
|
-
* @returns {
|
|
398
|
+
* @returns {Record<string, string | number> | import('../utils/roaring.js').RoaringBitmapSubset | null} Handled result or null if error should be re-thrown
|
|
391
399
|
* @private
|
|
392
400
|
*/
|
|
393
401
|
_tryHandleShardError(err, context) {
|
|
402
|
+
if (!(err instanceof Error)) { return null; }
|
|
394
403
|
const wrappedErr = this._wrapParseError(err, context.path, context.oid);
|
|
395
404
|
const isHandleable = wrappedErr instanceof ShardCorruptionError ||
|
|
396
405
|
wrappedErr instanceof ShardValidationError;
|
|
@@ -406,7 +415,7 @@ export default class BitmapIndexReader {
|
|
|
406
415
|
*
|
|
407
416
|
* @param {string} path - Shard path
|
|
408
417
|
* @param {string} format - 'json' or 'bitmap'
|
|
409
|
-
* @returns {Promise<
|
|
418
|
+
* @returns {Promise<Record<string, string | number> | import('../utils/roaring.js').RoaringBitmapSubset>}
|
|
410
419
|
* @throws {ShardLoadError} When storage.readBlob fails
|
|
411
420
|
* @throws {ShardCorruptionError} When shard format is invalid (strict mode only)
|
|
412
421
|
* @throws {ShardValidationError} When version or checksum validation fails (strict mode only)
|
|
@@ -82,7 +82,7 @@ const BTR_VERSION = 1;
|
|
|
82
82
|
* @param {string} fields.h_in - Hash of input state
|
|
83
83
|
* @param {string} fields.h_out - Hash of output state
|
|
84
84
|
* @param {Uint8Array} fields.U_0 - Serialized initial state
|
|
85
|
-
* @param {Array
|
|
85
|
+
* @param {Array<unknown>} fields.P - Serialized provenance payload
|
|
86
86
|
* @param {string} fields.t - ISO timestamp
|
|
87
87
|
* @param {string|Uint8Array} key - HMAC key
|
|
88
88
|
* @param {{ crypto: import('../../ports/CryptoPort.js').default, codec?: import('../../ports/CodecPort.js').default }} deps - Dependencies
|
|
@@ -111,7 +111,7 @@ async function computeHmac(fields, key, { crypto, codec }) {
|
|
|
111
111
|
* @property {string} h_in - Hash of input state (hex SHA-256)
|
|
112
112
|
* @property {string} h_out - Hash of output state (hex SHA-256)
|
|
113
113
|
* @property {Uint8Array} U_0 - Serialized initial state (CBOR)
|
|
114
|
-
* @property {Array
|
|
114
|
+
* @property {Array<unknown>} P - Serialized provenance payload
|
|
115
115
|
* @property {string} t - ISO 8601 timestamp
|
|
116
116
|
* @property {string} kappa - Authentication tag (hex HMAC-SHA256)
|
|
117
117
|
*/
|
|
@@ -189,7 +189,7 @@ const REQUIRED_FIELDS = ['version', 'h_in', 'h_out', 'U_0', 'P', 't', 'kappa'];
|
|
|
189
189
|
/**
|
|
190
190
|
* Validates BTR structure and returns failure reason if invalid.
|
|
191
191
|
*
|
|
192
|
-
* @param {
|
|
192
|
+
* @param {unknown} btr - The BTR object to validate
|
|
193
193
|
* @returns {string|null} Error message if invalid, null if valid
|
|
194
194
|
* @private
|
|
195
195
|
*/
|
|
@@ -197,13 +197,14 @@ function validateBTRStructure(btr) {
|
|
|
197
197
|
if (!btr || typeof btr !== 'object') {
|
|
198
198
|
return 'BTR must be an object';
|
|
199
199
|
}
|
|
200
|
+
const rec = /** @type {Record<string, unknown>} */ (btr);
|
|
200
201
|
for (const field of REQUIRED_FIELDS) {
|
|
201
|
-
if (!(field in
|
|
202
|
+
if (!(field in rec)) {
|
|
202
203
|
return `Missing required field: ${field}`;
|
|
203
204
|
}
|
|
204
205
|
}
|
|
205
|
-
if (
|
|
206
|
-
return `Unsupported BTR version: ${
|
|
206
|
+
if (rec.version !== BTR_VERSION) {
|
|
207
|
+
return `Unsupported BTR version: ${rec.version} (expected ${BTR_VERSION})`;
|
|
207
208
|
}
|
|
208
209
|
return null;
|
|
209
210
|
}
|
|
@@ -250,7 +251,7 @@ async function verifyHmac(btr, key, { crypto, codec }) {
|
|
|
250
251
|
* @returns {Promise<string|null>} Error message if replay mismatch, null if valid
|
|
251
252
|
* @private
|
|
252
253
|
*/
|
|
253
|
-
async function verifyReplayHash(btr, { crypto, codec } =
|
|
254
|
+
async function verifyReplayHash(btr, { crypto, codec } = {}) {
|
|
254
255
|
try {
|
|
255
256
|
const result = await replayBTR(btr, { crypto, codec });
|
|
256
257
|
if (result.h_out !== btr.h_out) {
|
|
@@ -258,7 +259,7 @@ async function verifyReplayHash(btr, { crypto, codec } = /** @type {*} */ ({}))
|
|
|
258
259
|
}
|
|
259
260
|
return null;
|
|
260
261
|
} catch (err) {
|
|
261
|
-
return `Replay failed: ${
|
|
262
|
+
return `Replay failed: ${err instanceof Error ? err.message : String(err)}`;
|
|
262
263
|
}
|
|
263
264
|
}
|
|
264
265
|
|
|
@@ -280,7 +281,7 @@ async function verifyReplayHash(btr, { crypto, codec } = /** @type {*} */ ({}))
|
|
|
280
281
|
* @param {import('../../ports/CodecPort.js').default} [options.codec] - Codec for serialization
|
|
281
282
|
* @returns {Promise<VerificationResult>} Verification result with valid flag and optional reason
|
|
282
283
|
*/
|
|
283
|
-
export async function verifyBTR(btr, key, options =
|
|
284
|
+
export async function verifyBTR(btr, key, options = {}) {
|
|
284
285
|
const { crypto, codec } = options;
|
|
285
286
|
|
|
286
287
|
const structureError = validateBTRStructure(btr);
|
|
@@ -323,13 +324,13 @@ export async function verifyBTR(btr, key, options = /** @type {*} */ ({})) { //
|
|
|
323
324
|
* The final state and its hash
|
|
324
325
|
* @throws {Error} If replay fails
|
|
325
326
|
*/
|
|
326
|
-
export async function replayBTR(btr, { crypto, codec } =
|
|
327
|
+
export async function replayBTR(btr, { crypto, codec } = {}) {
|
|
327
328
|
// Deserialize initial state from U_0
|
|
328
329
|
// Note: U_0 is the full serialized state (via serializeFullStateV5)
|
|
329
330
|
const initialState = deserializeInitialState(btr.U_0, { codec });
|
|
330
331
|
|
|
331
332
|
// Reconstruct payload
|
|
332
|
-
const payload = ProvenancePayload.fromJSON(btr.P);
|
|
333
|
+
const payload = ProvenancePayload.fromJSON(/** @type {import('./ProvenancePayload.js').PatchEntry[]} */ (btr.P));
|
|
333
334
|
|
|
334
335
|
// Replay
|
|
335
336
|
const finalState = payload.replay(initialState);
|
|
@@ -355,7 +356,7 @@ export async function replayBTR(btr, { crypto, codec } = /** @type {*} */ ({}))
|
|
|
355
356
|
* @returns {import('./JoinReducer.js').WarpStateV5} The deserialized state
|
|
356
357
|
* @private
|
|
357
358
|
*/
|
|
358
|
-
function deserializeInitialState(U_0, { codec } =
|
|
359
|
+
function deserializeInitialState(U_0, { codec } = {}) {
|
|
359
360
|
return deserializeFullStateV5(U_0, { codec });
|
|
360
361
|
}
|
|
361
362
|
|
|
@@ -370,7 +371,7 @@ function deserializeInitialState(U_0, { codec } = /** @type {*} */ ({})) { // TO
|
|
|
370
371
|
* @param {import('../../ports/CodecPort.js').default} [options.codec] - Codec for serialization
|
|
371
372
|
* @returns {Uint8Array} CBOR-encoded BTR
|
|
372
373
|
*/
|
|
373
|
-
export function serializeBTR(btr, { codec } =
|
|
374
|
+
export function serializeBTR(btr, { codec } = {}) {
|
|
374
375
|
const c = codec || defaultCodec;
|
|
375
376
|
return c.encode({
|
|
376
377
|
version: btr.version,
|
|
@@ -392,9 +393,9 @@ export function serializeBTR(btr, { codec } = /** @type {*} */ ({})) { // TODO(t
|
|
|
392
393
|
* @returns {BTR} The deserialized BTR
|
|
393
394
|
* @throws {Error} If the bytes are not valid CBOR or missing required fields
|
|
394
395
|
*/
|
|
395
|
-
export function deserializeBTR(bytes, { codec } =
|
|
396
|
+
export function deserializeBTR(bytes, { codec } = {}) {
|
|
396
397
|
const c = codec || defaultCodec;
|
|
397
|
-
const obj = /** @type {Record<string,
|
|
398
|
+
const obj = /** @type {Record<string, unknown>} */ (c.decode(bytes));
|
|
398
399
|
|
|
399
400
|
// Validate structure (reuse module-level constant for consistency with validateBTRStructure)
|
|
400
401
|
for (const field of REQUIRED_FIELDS) {
|
|
@@ -403,7 +404,7 @@ export function deserializeBTR(bytes, { codec } = /** @type {*} */ ({})) { // TO
|
|
|
403
404
|
}
|
|
404
405
|
}
|
|
405
406
|
|
|
406
|
-
return {
|
|
407
|
+
return /** @type {BTR} */ ({
|
|
407
408
|
version: obj.version,
|
|
408
409
|
h_in: obj.h_in,
|
|
409
410
|
h_out: obj.h_out,
|
|
@@ -411,7 +412,7 @@ export function deserializeBTR(bytes, { codec } = /** @type {*} */ ({})) { // TO
|
|
|
411
412
|
P: obj.P,
|
|
412
413
|
t: obj.t,
|
|
413
414
|
kappa: obj.kappa,
|
|
414
|
-
};
|
|
415
|
+
});
|
|
415
416
|
}
|
|
416
417
|
|
|
417
418
|
/**
|
|
@@ -39,7 +39,7 @@ import { createEmptyStateV5 } from './JoinReducer.js';
|
|
|
39
39
|
* @param {import('../../ports/CodecPort.js').default} [options.codec] - Codec for serialization
|
|
40
40
|
* @returns {Buffer|Uint8Array} CBOR-encoded full state
|
|
41
41
|
*/
|
|
42
|
-
export function serializeFullStateV5(state, { codec } =
|
|
42
|
+
export function serializeFullStateV5(state, { codec } = {}) {
|
|
43
43
|
const c = codec || defaultCodec;
|
|
44
44
|
// Serialize ORSets using existing serialization
|
|
45
45
|
const nodeAliveObj = orsetSerialize(state.nodeAlive);
|
|
@@ -90,14 +90,14 @@ export function serializeFullStateV5(state, { codec } = /** @type {*} */ ({})) {
|
|
|
90
90
|
* @returns {import('./JoinReducer.js').WarpStateV5}
|
|
91
91
|
*/
|
|
92
92
|
// eslint-disable-next-line complexity
|
|
93
|
-
export function deserializeFullStateV5(buffer, { codec: codecOpt } =
|
|
93
|
+
export function deserializeFullStateV5(buffer, { codec: codecOpt } = {}) {
|
|
94
94
|
const codec = codecOpt || defaultCodec;
|
|
95
95
|
// Handle null/undefined buffer before attempting decode
|
|
96
96
|
if (buffer === null || buffer === undefined) {
|
|
97
97
|
return createEmptyStateV5();
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
-
const obj = /** @type {Record<string,
|
|
100
|
+
const obj = /** @type {Record<string, unknown>} */ (codec.decode(buffer));
|
|
101
101
|
|
|
102
102
|
// Handle null/undefined decoded result: return empty state
|
|
103
103
|
if (obj === null || obj === undefined) {
|
|
@@ -107,16 +107,17 @@ export function deserializeFullStateV5(buffer, { codec: codecOpt } = /** @type {
|
|
|
107
107
|
// Handle version mismatch: throw with diagnostic info
|
|
108
108
|
// Accept both 'full-v5' and missing version (for backward compatibility with pre-versioned data)
|
|
109
109
|
if (obj.version !== undefined && obj.version !== 'full-v5') {
|
|
110
|
+
const ver = /** @type {string} */ (obj.version);
|
|
110
111
|
throw new Error(
|
|
111
|
-
`Unsupported full state version: expected 'full-v5', got '${
|
|
112
|
+
`Unsupported full state version: expected 'full-v5', got '${ver}'`
|
|
112
113
|
);
|
|
113
114
|
}
|
|
114
115
|
|
|
115
116
|
return {
|
|
116
117
|
nodeAlive: orsetDeserialize(obj.nodeAlive || {}),
|
|
117
118
|
edgeAlive: orsetDeserialize(obj.edgeAlive || {}),
|
|
118
|
-
prop: deserializeProps(obj.prop),
|
|
119
|
-
observedFrontier: vvDeserialize(obj.observedFrontier || {}),
|
|
119
|
+
prop: deserializeProps(/** @type {[string, unknown][]} */ (obj.prop)),
|
|
120
|
+
observedFrontier: vvDeserialize(/** @type {{[x: string]: number}} */ (obj.observedFrontier || {})),
|
|
120
121
|
edgeBirthEvent: /** @type {Map<string, import('../utils/EventId.js').EventId>} */ (deserializeEdgeBirthEvent(obj)),
|
|
121
122
|
};
|
|
122
123
|
}
|
|
@@ -172,7 +173,7 @@ export function computeAppliedVV(state) {
|
|
|
172
173
|
* @param {import('../../ports/CodecPort.js').default} [options.codec] - Codec for serialization
|
|
173
174
|
* @returns {Buffer|Uint8Array} CBOR-encoded version vector
|
|
174
175
|
*/
|
|
175
|
-
export function serializeAppliedVV(vv, { codec } =
|
|
176
|
+
export function serializeAppliedVV(vv, { codec } = {}) {
|
|
176
177
|
const c = codec || defaultCodec;
|
|
177
178
|
const obj = vvSerialize(vv);
|
|
178
179
|
return c.encode(obj);
|
|
@@ -186,7 +187,7 @@ export function serializeAppliedVV(vv, { codec } = /** @type {*} */ ({})) { // T
|
|
|
186
187
|
* @param {import('../../ports/CodecPort.js').default} [options.codec] - Codec for deserialization
|
|
187
188
|
* @returns {Map<string, number>} Version vector
|
|
188
189
|
*/
|
|
189
|
-
export function deserializeAppliedVV(buffer, { codec } =
|
|
190
|
+
export function deserializeAppliedVV(buffer, { codec } = {}) {
|
|
190
191
|
const c = codec || defaultCodec;
|
|
191
192
|
const obj = /** @type {{ [x: string]: number }} */ (c.decode(buffer));
|
|
192
193
|
return vvDeserialize(obj);
|
|
@@ -198,14 +199,14 @@ export function deserializeAppliedVV(buffer, { codec } = /** @type {*} */ ({}))
|
|
|
198
199
|
|
|
199
200
|
/**
|
|
200
201
|
* Deserializes the props array from checkpoint format.
|
|
201
|
-
* @param {Array
|
|
202
|
-
* @returns {Map<string, import('../crdt/LWW.js').LWWRegister
|
|
202
|
+
* @param {Array<[string, unknown]>} propArray - Array of [key, registerObj] pairs
|
|
203
|
+
* @returns {Map<string, import('../crdt/LWW.js').LWWRegister<unknown>>}
|
|
203
204
|
*/
|
|
204
205
|
function deserializeProps(propArray) {
|
|
205
206
|
const prop = new Map();
|
|
206
207
|
if (propArray && Array.isArray(propArray)) {
|
|
207
208
|
for (const [key, registerObj] of propArray) {
|
|
208
|
-
prop.set(key, deserializeLWWRegister(registerObj));
|
|
209
|
+
prop.set(key, deserializeLWWRegister(/** @type {{ eventId: { lamport: number, writerId: string, patchSha: string, opIndex: number }, value: unknown } | null} */ (registerObj)));
|
|
209
210
|
}
|
|
210
211
|
}
|
|
211
212
|
return prop;
|
|
@@ -213,7 +214,7 @@ function deserializeProps(propArray) {
|
|
|
213
214
|
|
|
214
215
|
/**
|
|
215
216
|
* Deserializes edge birth event data, supporting both legacy and current formats.
|
|
216
|
-
* @param {Record<string,
|
|
217
|
+
* @param {Record<string, unknown>} obj - The decoded checkpoint object
|
|
217
218
|
* @returns {Map<string, import('../utils/EventId.js').EventId>}
|
|
218
219
|
*/
|
|
219
220
|
function deserializeEdgeBirthEvent(obj) {
|
|
@@ -240,8 +241,8 @@ function deserializeEdgeBirthEvent(obj) {
|
|
|
240
241
|
* Serializes an LWW register for CBOR encoding.
|
|
241
242
|
* EventId is serialized as a plain object with sorted keys.
|
|
242
243
|
*
|
|
243
|
-
* @param {import('../crdt/LWW.js').LWWRegister
|
|
244
|
-
* @returns {{ eventId: { lamport: number, opIndex: number, patchSha: string, writerId: string }, value:
|
|
244
|
+
* @param {import('../crdt/LWW.js').LWWRegister<unknown>} register
|
|
245
|
+
* @returns {{ eventId: { lamport: number, opIndex: number, patchSha: string, writerId: string }, value: unknown } | null}
|
|
245
246
|
*/
|
|
246
247
|
function serializeLWWRegister(register) {
|
|
247
248
|
if (!register) {
|
|
@@ -262,8 +263,8 @@ function serializeLWWRegister(register) {
|
|
|
262
263
|
/**
|
|
263
264
|
* Deserializes an LWW register from CBOR.
|
|
264
265
|
*
|
|
265
|
-
* @param {{ eventId: { lamport: number, writerId: string, patchSha: string, opIndex: number }, value:
|
|
266
|
-
* @returns {import('../crdt/LWW.js').LWWRegister
|
|
266
|
+
* @param {{ eventId: { lamport: number, writerId: string, patchSha: string, opIndex: number }, value: unknown } | null} obj
|
|
267
|
+
* @returns {import('../crdt/LWW.js').LWWRegister<unknown> | null}
|
|
267
268
|
*/
|
|
268
269
|
function deserializeLWWRegister(obj) {
|
|
269
270
|
if (!obj) {
|
|
@@ -196,7 +196,7 @@ export async function createV5({
|
|
|
196
196
|
* @returns {Promise<{state: import('./JoinReducer.js').WarpStateV5, frontier: import('./Frontier.js').Frontier, stateHash: string, schema: number, appliedVV: Map<string, number>|null, provenanceIndex?: import('./ProvenanceIndex.js').ProvenanceIndex}>} The loaded checkpoint data
|
|
197
197
|
* @throws {Error} If checkpoint is schema:1 (migration required)
|
|
198
198
|
*/
|
|
199
|
-
export async function loadCheckpoint(persistence, checkpointSha, { codec } =
|
|
199
|
+
export async function loadCheckpoint(persistence, checkpointSha, { codec } = {}) {
|
|
200
200
|
// 1. Read commit message and decode
|
|
201
201
|
const message = await persistence.showNode(checkpointSha);
|
|
202
202
|
const decoded = /** @type {{ schema: number, stateHash: string, indexOid: string }} */ (decodeCheckpointMessage(message));
|
|
@@ -327,7 +327,7 @@ export async function materializeIncremental({
|
|
|
327
327
|
* @param {Object} visibleProjection - The checkpoint's visible projection
|
|
328
328
|
* @param {string[]} visibleProjection.nodes - Visible node IDs
|
|
329
329
|
* @param {Array<{from: string, to: string, label: string}>} visibleProjection.edges - Visible edges
|
|
330
|
-
* @param {Array<{node: string, key: string, value:
|
|
330
|
+
* @param {Array<{node: string, key: string, value: unknown}>} visibleProjection.props - Visible properties
|
|
331
331
|
* @returns {import('./JoinReducer.js').WarpStateV5} Reconstructed WarpStateV5
|
|
332
332
|
* @public
|
|
333
333
|
*/
|
|
@@ -39,7 +39,7 @@ export default class CommitDagTraversalService {
|
|
|
39
39
|
* @param {import('./BitmapIndexReader.js').default} options.indexReader - Index reader for O(1) lookups
|
|
40
40
|
* @param {import('../../ports/LoggerPort.js').default} [options.logger] - Logger instance
|
|
41
41
|
*/
|
|
42
|
-
constructor({ indexReader, logger = nullLogger }
|
|
42
|
+
constructor({ indexReader, logger = nullLogger }) {
|
|
43
43
|
if (!indexReader) {
|
|
44
44
|
throw new Error('CommitDagTraversalService requires an indexReader');
|
|
45
45
|
}
|
|
@@ -56,7 +56,7 @@ export default class CommitDagTraversalService {
|
|
|
56
56
|
|
|
57
57
|
/**
|
|
58
58
|
* Breadth-first traversal from a starting node.
|
|
59
|
-
* @param {
|
|
59
|
+
* @param {Parameters<import('./DagTraversal.js').default['bfs']>[0]} options
|
|
60
60
|
* @see DagTraversal#bfs
|
|
61
61
|
*/
|
|
62
62
|
bfs(options) {
|
|
@@ -65,7 +65,7 @@ export default class CommitDagTraversalService {
|
|
|
65
65
|
|
|
66
66
|
/**
|
|
67
67
|
* Depth-first pre-order traversal from a starting node.
|
|
68
|
-
* @param {
|
|
68
|
+
* @param {Parameters<import('./DagTraversal.js').default['dfs']>[0]} options
|
|
69
69
|
* @see DagTraversal#dfs
|
|
70
70
|
*/
|
|
71
71
|
dfs(options) {
|
|
@@ -74,7 +74,7 @@ export default class CommitDagTraversalService {
|
|
|
74
74
|
|
|
75
75
|
/**
|
|
76
76
|
* Yields all ancestors of a node.
|
|
77
|
-
* @param {
|
|
77
|
+
* @param {Parameters<import('./DagTraversal.js').default['ancestors']>[0]} options
|
|
78
78
|
* @see DagTraversal#ancestors
|
|
79
79
|
*/
|
|
80
80
|
ancestors(options) {
|
|
@@ -83,7 +83,7 @@ export default class CommitDagTraversalService {
|
|
|
83
83
|
|
|
84
84
|
/**
|
|
85
85
|
* Yields all descendants of a node.
|
|
86
|
-
* @param {
|
|
86
|
+
* @param {Parameters<import('./DagTraversal.js').default['descendants']>[0]} options
|
|
87
87
|
* @see DagTraversal#descendants
|
|
88
88
|
*/
|
|
89
89
|
descendants(options) {
|
|
@@ -92,7 +92,7 @@ export default class CommitDagTraversalService {
|
|
|
92
92
|
|
|
93
93
|
/**
|
|
94
94
|
* Checks if there is any path from one node to another.
|
|
95
|
-
* @param {
|
|
95
|
+
* @param {Parameters<import('./DagTraversal.js').default['isReachable']>[0]} options
|
|
96
96
|
* @see DagTraversal#isReachable
|
|
97
97
|
*/
|
|
98
98
|
isReachable(options) {
|
|
@@ -103,7 +103,7 @@ export default class CommitDagTraversalService {
|
|
|
103
103
|
|
|
104
104
|
/**
|
|
105
105
|
* Finds ANY path between two nodes using BFS.
|
|
106
|
-
* @param {
|
|
106
|
+
* @param {Parameters<import('./DagPathFinding.js').default['findPath']>[0]} options
|
|
107
107
|
* @see DagPathFinding#findPath
|
|
108
108
|
*/
|
|
109
109
|
findPath(options) {
|
|
@@ -112,7 +112,7 @@ export default class CommitDagTraversalService {
|
|
|
112
112
|
|
|
113
113
|
/**
|
|
114
114
|
* Finds the shortest path using bidirectional BFS.
|
|
115
|
-
* @param {
|
|
115
|
+
* @param {Parameters<import('./DagPathFinding.js').default['shortestPath']>[0]} options
|
|
116
116
|
* @see DagPathFinding#shortestPath
|
|
117
117
|
*/
|
|
118
118
|
shortestPath(options) {
|
|
@@ -121,7 +121,7 @@ export default class CommitDagTraversalService {
|
|
|
121
121
|
|
|
122
122
|
/**
|
|
123
123
|
* Finds shortest path using Dijkstra's algorithm.
|
|
124
|
-
* @param {
|
|
124
|
+
* @param {Parameters<import('./DagPathFinding.js').default['weightedShortestPath']>[0]} options
|
|
125
125
|
* @see DagPathFinding#weightedShortestPath
|
|
126
126
|
*/
|
|
127
127
|
weightedShortestPath(options) {
|
|
@@ -130,7 +130,7 @@ export default class CommitDagTraversalService {
|
|
|
130
130
|
|
|
131
131
|
/**
|
|
132
132
|
* Finds shortest path using A* with heuristic guidance.
|
|
133
|
-
* @param {
|
|
133
|
+
* @param {Parameters<import('./DagPathFinding.js').default['aStarSearch']>[0]} options
|
|
134
134
|
* @see DagPathFinding#aStarSearch
|
|
135
135
|
*/
|
|
136
136
|
aStarSearch(options) {
|
|
@@ -139,7 +139,7 @@ export default class CommitDagTraversalService {
|
|
|
139
139
|
|
|
140
140
|
/**
|
|
141
141
|
* Bi-directional A* search.
|
|
142
|
-
* @param {
|
|
142
|
+
* @param {Parameters<import('./DagPathFinding.js').default['bidirectionalAStar']>[0]} options
|
|
143
143
|
* @see DagPathFinding#bidirectionalAStar
|
|
144
144
|
*/
|
|
145
145
|
bidirectionalAStar(options) {
|
|
@@ -150,7 +150,7 @@ export default class CommitDagTraversalService {
|
|
|
150
150
|
|
|
151
151
|
/**
|
|
152
152
|
* Finds common ancestors of multiple nodes.
|
|
153
|
-
* @param {
|
|
153
|
+
* @param {Parameters<import('./DagTopology.js').default['commonAncestors']>[0]} options
|
|
154
154
|
* @see DagTopology#commonAncestors
|
|
155
155
|
*/
|
|
156
156
|
commonAncestors(options) {
|
|
@@ -159,7 +159,7 @@ export default class CommitDagTraversalService {
|
|
|
159
159
|
|
|
160
160
|
/**
|
|
161
161
|
* Yields nodes in topological order using Kahn's algorithm.
|
|
162
|
-
* @param {
|
|
162
|
+
* @param {Parameters<import('./DagTopology.js').default['topologicalSort']>[0]} options
|
|
163
163
|
* @see DagTopology#topologicalSort
|
|
164
164
|
*/
|
|
165
165
|
topologicalSort(options) {
|
|
@@ -41,7 +41,7 @@ export default class DagPathFinding {
|
|
|
41
41
|
* @param {import('./BitmapIndexReader.js').default} options.indexReader - Index reader for O(1) lookups
|
|
42
42
|
* @param {import('../../ports/LoggerPort.js').default} [options.logger] - Logger instance
|
|
43
43
|
*/
|
|
44
|
-
constructor(/** @type {{ indexReader: import('./BitmapIndexReader.js').default, logger?: import('../../ports/LoggerPort.js').default }} */ { indexReader, logger = nullLogger } = /** @type {
|
|
44
|
+
constructor(/** @type {{ indexReader: import('./BitmapIndexReader.js').default, logger?: import('../../ports/LoggerPort.js').default }} */ { indexReader, logger = nullLogger } = /** @type {{ indexReader: import('./BitmapIndexReader.js').default }} */ ({})) {
|
|
45
45
|
if (!indexReader) {
|
|
46
46
|
throw new Error('DagPathFinding requires an indexReader');
|
|
47
47
|
}
|
|
@@ -228,7 +228,7 @@ export default class DagPathFinding {
|
|
|
228
228
|
checkAborted(signal, 'weightedShortestPath');
|
|
229
229
|
}
|
|
230
230
|
|
|
231
|
-
const current = pq.extractMin();
|
|
231
|
+
const current = /** @type {string} */ (pq.extractMin());
|
|
232
232
|
|
|
233
233
|
if (visited.has(current)) {
|
|
234
234
|
continue;
|
|
@@ -314,7 +314,7 @@ export default class DagPathFinding {
|
|
|
314
314
|
checkAborted(signal, 'aStarSearch');
|
|
315
315
|
}
|
|
316
316
|
|
|
317
|
-
const current = pq.extractMin();
|
|
317
|
+
const current = /** @type {string} */ (pq.extractMin());
|
|
318
318
|
|
|
319
319
|
if (visited.has(current)) {
|
|
320
320
|
continue;
|
|
@@ -463,7 +463,7 @@ export default class DagPathFinding {
|
|
|
463
463
|
* Expands the forward frontier by one node in bidirectional A*.
|
|
464
464
|
*
|
|
465
465
|
* @param {Object} state - Forward expansion state
|
|
466
|
-
* @param {import('../utils/MinHeap.js').default} state.fwdHeap
|
|
466
|
+
* @param {import('../utils/MinHeap.js').default<string>} state.fwdHeap
|
|
467
467
|
* @param {Set<string>} state.fwdVisited
|
|
468
468
|
* @param {Map<string, number>} state.fwdGScore
|
|
469
469
|
* @param {Map<string, string>} state.fwdPrevious
|
|
@@ -483,7 +483,7 @@ export default class DagPathFinding {
|
|
|
483
483
|
weightProvider, forwardHeuristic, to,
|
|
484
484
|
mu: inputMu, meetingPoint: inputMeeting,
|
|
485
485
|
}) {
|
|
486
|
-
const current = fwdHeap.extractMin();
|
|
486
|
+
const current = /** @type {string} */ (fwdHeap.extractMin());
|
|
487
487
|
let explored = 0;
|
|
488
488
|
let bestMu = inputMu;
|
|
489
489
|
let bestMeeting = inputMeeting;
|
|
@@ -536,7 +536,7 @@ export default class DagPathFinding {
|
|
|
536
536
|
* Expands the backward frontier by one node in bidirectional A*.
|
|
537
537
|
*
|
|
538
538
|
* @param {Object} state - Backward expansion state
|
|
539
|
-
* @param {import('../utils/MinHeap.js').default} state.bwdHeap
|
|
539
|
+
* @param {import('../utils/MinHeap.js').default<string>} state.bwdHeap
|
|
540
540
|
* @param {Set<string>} state.bwdVisited
|
|
541
541
|
* @param {Map<string, number>} state.bwdGScore
|
|
542
542
|
* @param {Map<string, string>} state.bwdNext
|
|
@@ -556,7 +556,7 @@ export default class DagPathFinding {
|
|
|
556
556
|
weightProvider, backwardHeuristic, from,
|
|
557
557
|
mu: inputMu, meetingPoint: inputMeeting,
|
|
558
558
|
}) {
|
|
559
|
-
const current = bwdHeap.extractMin();
|
|
559
|
+
const current = /** @type {string} */ (bwdHeap.extractMin());
|
|
560
560
|
let explored = 0;
|
|
561
561
|
let bestMu = inputMu;
|
|
562
562
|
let bestMeeting = inputMeeting;
|
|
@@ -37,7 +37,7 @@ export default class DagTopology {
|
|
|
37
37
|
* @param {import('../../ports/LoggerPort.js').default} [options.logger] - Logger instance
|
|
38
38
|
* @param {import('./DagTraversal.js').default} [options.traversal] - Traversal service for ancestor enumeration
|
|
39
39
|
*/
|
|
40
|
-
constructor(/** @type {{ indexReader: import('./BitmapIndexReader.js').default, logger?: import('../../ports/LoggerPort.js').default, traversal?: import('./DagTraversal.js').default }} */ { indexReader, logger = nullLogger, traversal } = /** @type {
|
|
40
|
+
constructor(/** @type {{ indexReader: import('./BitmapIndexReader.js').default, logger?: import('../../ports/LoggerPort.js').default, traversal?: import('./DagTraversal.js').default }} */ { indexReader, logger = nullLogger, traversal } = /** @type {{ indexReader: import('./BitmapIndexReader.js').default }} */ ({})) {
|
|
41
41
|
if (!indexReader) {
|
|
42
42
|
throw new Error('DagTopology requires an indexReader');
|
|
43
43
|
}
|
|
@@ -43,7 +43,7 @@ export default class DagTraversal {
|
|
|
43
43
|
* @param {import('./BitmapIndexReader.js').default} options.indexReader - Index reader for O(1) lookups
|
|
44
44
|
* @param {import('../../ports/LoggerPort.js').default} [options.logger] - Logger instance
|
|
45
45
|
*/
|
|
46
|
-
constructor(/** @type {{ indexReader: import('./BitmapIndexReader.js').default, logger?: import('../../ports/LoggerPort.js').default }} */ { indexReader, logger = nullLogger } = /** @type {
|
|
46
|
+
constructor(/** @type {{ indexReader: import('./BitmapIndexReader.js').default, logger?: import('../../ports/LoggerPort.js').default }} */ { indexReader, logger = nullLogger } = /** @type {{ indexReader: import('./BitmapIndexReader.js').default }} */ ({})) {
|
|
47
47
|
if (!indexReader) {
|
|
48
48
|
throw new Error('DagTraversal requires an indexReader');
|
|
49
49
|
}
|
|
@@ -191,7 +191,7 @@ export default class HealthCheckService {
|
|
|
191
191
|
} catch (err) {
|
|
192
192
|
this._logger.warn('Repository ping failed', {
|
|
193
193
|
operation: 'checkRepository',
|
|
194
|
-
error:
|
|
194
|
+
error: err instanceof Error ? err.message : String(err),
|
|
195
195
|
});
|
|
196
196
|
return {
|
|
197
197
|
status: /** @type {'healthy'|'unhealthy'} */ (HealthStatus.UNHEALTHY),
|
|
@@ -80,7 +80,7 @@ export class HookInstaller {
|
|
|
80
80
|
* @param {string} deps.templateDir - Directory containing hook templates
|
|
81
81
|
* @param {PathUtils} deps.path - Path utilities (join and resolve)
|
|
82
82
|
*/
|
|
83
|
-
constructor({ fs, execGitConfig, version, templateDir, path }
|
|
83
|
+
constructor({ fs, execGitConfig, version, templateDir, path }) {
|
|
84
84
|
/** @type {FsAdapter} */
|
|
85
85
|
this._fs = fs;
|
|
86
86
|
/** @type {(repoPath: string, key: string) => string|null} */
|