@gmickel/gno 1.34.6 → 1.35.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 +12 -1
- package/browser-extension/artifacts/{gno-browser-clipper-v1.34.6.zip → gno-browser-clipper-v1.35.0.zip} +0 -0
- package/browser-extension/artifacts/gno-browser-clipper-v1.35.0.zip.sha256 +1 -0
- package/browser-extension/dist/manifest.json +1 -1
- package/package.json +1 -1
- package/spec/cli.md +37 -0
- package/spec/output-schemas/mcp-job-status.schema.json +6 -2
- package/src/config/index.ts +4 -0
- package/src/config/types.ts +14 -0
- package/src/core/path-rules.ts +34 -0
- package/src/ingestion/index.ts +21 -0
- package/src/ingestion/record-container.ts +23 -1
- package/src/ingestion/source-availability/darwin-io.ts +295 -0
- package/src/ingestion/source-availability/darwin-path.ts +58 -0
- package/src/ingestion/source-availability/directory.ts +402 -0
- package/src/ingestion/source-availability/index.ts +74 -0
- package/src/ingestion/source-availability/readers.ts +360 -0
- package/src/ingestion/source-availability/resolve.ts +28 -0
- package/src/ingestion/source-availability/types.ts +170 -0
- package/src/ingestion/sync.ts +197 -24
- package/src/ingestion/types.ts +45 -3
- package/src/ingestion/walker.ts +263 -5
- package/src/serve/public/globals.built.css +1 -1
- package/src/serve/watch-reconciliation-fallback-disk.ts +239 -100
- package/src/serve/watch-reconciliation-fallback.ts +35 -5
- package/src/serve/watch-reconciliation-shared.ts +8 -3
- package/src/serve/watch-reconciliation.ts +7 -0
- package/src/serve/watch-service-flush.ts +10 -0
- package/src/serve/watch-service-lifecycle.ts +2 -0
- package/src/serve/watch-service-snapshot.ts +27 -3
- package/src/serve/watch-service.ts +1 -0
- package/src/serve/watch-snapshot-availability.ts +51 -0
- package/src/serve/watch-snapshot-handles.ts +117 -37
- package/src/serve/watch-snapshot-libc.ts +141 -22
- package/src/serve/watch-snapshot-ops.ts +151 -9
- package/src/serve/watch-snapshot-scan.ts +3 -0
- package/src/serve/watch-snapshot-types.ts +45 -3
- package/browser-extension/artifacts/gno-browser-clipper-v1.34.6.zip.sha256 +0 -1
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* @module src/serve/watch-snapshot-ops
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
+
import type { DirectoryAvailabilityPort } from "../ingestion/source-availability";
|
|
8
9
|
import type {
|
|
9
10
|
DiffWorkResult,
|
|
10
11
|
SnapshotEntryFingerprint,
|
|
@@ -15,12 +16,15 @@ import type {
|
|
|
15
16
|
WatcherSnapshotOptions,
|
|
16
17
|
} from "./watch-snapshot-types";
|
|
17
18
|
|
|
19
|
+
import {
|
|
20
|
+
directoryAllowsDescent,
|
|
21
|
+
readAvailableDirectory,
|
|
22
|
+
} from "./watch-snapshot-availability";
|
|
18
23
|
import {
|
|
19
24
|
cloneDirectoryMaps,
|
|
20
25
|
defaultClock,
|
|
21
26
|
defaultFs,
|
|
22
27
|
freezeSnapshot,
|
|
23
|
-
readDirectChildren,
|
|
24
28
|
removeSubtreeFromMaps,
|
|
25
29
|
setDirectoryEntries,
|
|
26
30
|
type MutableSnapshotMaps,
|
|
@@ -46,11 +50,25 @@ export async function buildWatcherSnapshot(
|
|
|
46
50
|
const fs = options.fs ?? defaultFs;
|
|
47
51
|
const clock = options.clock ?? defaultClock;
|
|
48
52
|
const ceiling = options.entryCeiling ?? WATCHER_SNAPSHOT_ENTRY_CEILING;
|
|
53
|
+
const directoryAvailability = options.directoryAvailability;
|
|
49
54
|
const started = clock.nowMs();
|
|
50
55
|
|
|
56
|
+
if (!(await directoryAllowsDescent(rootAbs, "", directoryAvailability))) {
|
|
57
|
+
// Root itself is unproven — fail closed without claiming an empty tree.
|
|
58
|
+
return {
|
|
59
|
+
status: "fallback",
|
|
60
|
+
reason: "scan_failed",
|
|
61
|
+
durationMs: clock.nowMs() - started,
|
|
62
|
+
cause: new Error(
|
|
63
|
+
"Collection root availability is unproven; refusing snapshot descent"
|
|
64
|
+
),
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
51
68
|
const state: MutableSnapshotMaps = {
|
|
52
69
|
directories: new Map(),
|
|
53
70
|
entryCount: 0,
|
|
71
|
+
unprovenSubtrees: new Set(),
|
|
54
72
|
};
|
|
55
73
|
// Cursor-index queue avoids O(n) shift on large directory sets.
|
|
56
74
|
const queue: string[] = [""];
|
|
@@ -68,7 +86,27 @@ export async function buildWatcherSnapshot(
|
|
|
68
86
|
durationMs: clock.nowMs() - started,
|
|
69
87
|
};
|
|
70
88
|
}
|
|
71
|
-
const scanned = await
|
|
89
|
+
const scanned = await readAvailableDirectory(
|
|
90
|
+
rootAbs,
|
|
91
|
+
dirRel,
|
|
92
|
+
fs,
|
|
93
|
+
remaining,
|
|
94
|
+
directoryAvailability
|
|
95
|
+
);
|
|
96
|
+
if (scanned.status === "unproven") {
|
|
97
|
+
if (dirRel === "") {
|
|
98
|
+
return {
|
|
99
|
+
status: "fallback",
|
|
100
|
+
reason: "scan_failed",
|
|
101
|
+
durationMs: clock.nowMs() - started,
|
|
102
|
+
cause: new Error(
|
|
103
|
+
"Collection root availability changed before snapshot enumeration"
|
|
104
|
+
),
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
state.unprovenSubtrees.add(dirRel);
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
72
110
|
if (scanned.status === "missing") {
|
|
73
111
|
if (dirRel === "") {
|
|
74
112
|
return {
|
|
@@ -107,7 +145,19 @@ export async function buildWatcherSnapshot(
|
|
|
107
145
|
for (const [name, fingerprint] of scanned.entries) {
|
|
108
146
|
// No-follow: never recurse through symlinks (even if they point inside root).
|
|
109
147
|
if (fingerprint.kind === "directory") {
|
|
110
|
-
|
|
148
|
+
const childRel = joinWatcherRelPath(dirRel, name);
|
|
149
|
+
if (
|
|
150
|
+
!(await directoryAllowsDescent(
|
|
151
|
+
rootAbs,
|
|
152
|
+
childRel,
|
|
153
|
+
directoryAvailability
|
|
154
|
+
))
|
|
155
|
+
) {
|
|
156
|
+
// Refuse descent/enumeration; leave subtree absent from this build.
|
|
157
|
+
state.unprovenSubtrees.add(childRel);
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
160
|
+
queue.push(childRel);
|
|
111
161
|
}
|
|
112
162
|
}
|
|
113
163
|
}
|
|
@@ -138,6 +188,7 @@ export async function diffWatcherSnapshot(
|
|
|
138
188
|
const clock = options.clock ?? defaultClock;
|
|
139
189
|
const ceiling = options.entryCeiling ?? WATCHER_SNAPSHOT_ENTRY_CEILING;
|
|
140
190
|
const mapHooks = options.mapHooks;
|
|
191
|
+
const directoryAvailability = options.directoryAvailability;
|
|
141
192
|
const started = clock.nowMs();
|
|
142
193
|
|
|
143
194
|
const normalizedDirs: string[] = [];
|
|
@@ -179,19 +230,45 @@ export async function diffWatcherSnapshot(
|
|
|
179
230
|
}
|
|
180
231
|
};
|
|
181
232
|
|
|
233
|
+
const subtreeInventoryIsUnproven = (dirRel: string): boolean => {
|
|
234
|
+
const prefix = `${dirRel}/`;
|
|
235
|
+
for (const unproven of nextState.unprovenSubtrees) {
|
|
236
|
+
if (unproven === dirRel || unproven.startsWith(prefix)) {
|
|
237
|
+
return true;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
return false;
|
|
241
|
+
};
|
|
242
|
+
|
|
182
243
|
const diffDirectory = async (dirRel: string): Promise<DiffWorkResult> => {
|
|
183
244
|
if (visited.has(dirRel)) {
|
|
184
245
|
return { status: "ok" };
|
|
185
246
|
}
|
|
186
247
|
visited.add(dirRel);
|
|
187
248
|
|
|
249
|
+
if (
|
|
250
|
+
!(await directoryAllowsDescent(rootAbs, dirRel, directoryAvailability))
|
|
251
|
+
) {
|
|
252
|
+
// Dirty target is unproven — keep prior subtree, prove nothing.
|
|
253
|
+
return { status: "ok" };
|
|
254
|
+
}
|
|
255
|
+
|
|
188
256
|
// Replacement frees prior slots for this directory map before the new scan.
|
|
189
257
|
const previousSize = nextState.directories.get(dirRel)?.size ?? 0;
|
|
190
258
|
const remaining = ceiling - nextState.entryCount + previousSize;
|
|
191
259
|
if (remaining < 0) {
|
|
192
260
|
return { status: "overflow" };
|
|
193
261
|
}
|
|
194
|
-
const scanned = await
|
|
262
|
+
const scanned = await readAvailableDirectory(
|
|
263
|
+
rootAbs,
|
|
264
|
+
dirRel,
|
|
265
|
+
fs,
|
|
266
|
+
remaining,
|
|
267
|
+
directoryAvailability
|
|
268
|
+
);
|
|
269
|
+
if (scanned.status === "unproven") {
|
|
270
|
+
return { status: "ok" };
|
|
271
|
+
}
|
|
195
272
|
if (scanned.status === "missing") {
|
|
196
273
|
// Open-time ENOENT/ENOTDIR is never directory-deletion proof.
|
|
197
274
|
// A nested dirty target may have raced into a file/symlink/other after
|
|
@@ -217,6 +294,7 @@ export async function diffWatcherSnapshot(
|
|
|
217
294
|
new Map<string, SnapshotEntryFingerprint>();
|
|
218
295
|
const newEntries = scanned.entries;
|
|
219
296
|
setDirectoryEntries(nextState, dirRel, new Map(newEntries));
|
|
297
|
+
nextState.unprovenSubtrees.delete(dirRel);
|
|
220
298
|
|
|
221
299
|
if (nextState.entryCount > ceiling) {
|
|
222
300
|
return { status: "overflow" };
|
|
@@ -232,6 +310,9 @@ export async function diffWatcherSnapshot(
|
|
|
232
310
|
// Removed entry: expand prior subtree for directories; files/symlinks directly.
|
|
233
311
|
// `other` was never an indexable source — drop fingerprint only.
|
|
234
312
|
if (oldFp.kind === "directory") {
|
|
313
|
+
if (subtreeInventoryIsUnproven(childRel)) {
|
|
314
|
+
return { status: "unproven_subtree" };
|
|
315
|
+
}
|
|
235
316
|
recordSubtreeRemovals(childRel);
|
|
236
317
|
} else if (isWatcherSourceKind(oldFp.kind)) {
|
|
237
318
|
removals.add(childRel);
|
|
@@ -242,13 +323,24 @@ export async function diffWatcherSnapshot(
|
|
|
242
323
|
if (newFp && !oldFp) {
|
|
243
324
|
// Added entry. Candidates are file/symlink only — ignore new FIFO/etc.
|
|
244
325
|
if (newFp.kind === "directory") {
|
|
326
|
+
if (
|
|
327
|
+
!(await directoryAllowsDescent(
|
|
328
|
+
rootAbs,
|
|
329
|
+
childRel,
|
|
330
|
+
directoryAvailability
|
|
331
|
+
))
|
|
332
|
+
) {
|
|
333
|
+
// Unproven new directory: keep fingerprint, do not enumerate.
|
|
334
|
+
continue;
|
|
335
|
+
}
|
|
245
336
|
const built = await scanNewSubtree(
|
|
246
337
|
rootAbs,
|
|
247
338
|
childRel,
|
|
248
339
|
fs,
|
|
249
340
|
nextState,
|
|
250
341
|
candidates,
|
|
251
|
-
ceiling
|
|
342
|
+
ceiling,
|
|
343
|
+
directoryAvailability
|
|
252
344
|
);
|
|
253
345
|
if (built.status !== "ok") {
|
|
254
346
|
return built;
|
|
@@ -264,6 +356,9 @@ export async function diffWatcherSnapshot(
|
|
|
264
356
|
// Changed entry — handle kind transitions with the other-kind contract.
|
|
265
357
|
if (oldFp.kind === "directory" && newFp.kind !== "directory") {
|
|
266
358
|
// Directory → file/symlink/other: expand nested indexable removals.
|
|
359
|
+
if (subtreeInventoryIsUnproven(childRel)) {
|
|
360
|
+
return { status: "unproven_subtree" };
|
|
361
|
+
}
|
|
267
362
|
recordSubtreeRemovals(childRel);
|
|
268
363
|
if (isWatcherSourceKind(newFp.kind)) {
|
|
269
364
|
candidates.add(childRel);
|
|
@@ -278,13 +373,23 @@ export async function diffWatcherSnapshot(
|
|
|
278
373
|
if (isWatcherSourceKind(oldFp.kind)) {
|
|
279
374
|
removals.add(childRel);
|
|
280
375
|
}
|
|
376
|
+
if (
|
|
377
|
+
!(await directoryAllowsDescent(
|
|
378
|
+
rootAbs,
|
|
379
|
+
childRel,
|
|
380
|
+
directoryAvailability
|
|
381
|
+
))
|
|
382
|
+
) {
|
|
383
|
+
continue;
|
|
384
|
+
}
|
|
281
385
|
const built = await scanNewSubtree(
|
|
282
386
|
rootAbs,
|
|
283
387
|
childRel,
|
|
284
388
|
fs,
|
|
285
389
|
nextState,
|
|
286
390
|
candidates,
|
|
287
|
-
ceiling
|
|
391
|
+
ceiling,
|
|
392
|
+
directoryAvailability
|
|
288
393
|
);
|
|
289
394
|
if (built.status !== "ok") {
|
|
290
395
|
return built;
|
|
@@ -293,7 +398,17 @@ export async function diffWatcherSnapshot(
|
|
|
293
398
|
}
|
|
294
399
|
|
|
295
400
|
if (newFp.kind === "directory") {
|
|
296
|
-
// Directory → directory (metadata change): recurse.
|
|
401
|
+
// Directory → directory (metadata change): recurse only when available.
|
|
402
|
+
if (
|
|
403
|
+
!(await directoryAllowsDescent(
|
|
404
|
+
rootAbs,
|
|
405
|
+
childRel,
|
|
406
|
+
directoryAvailability
|
|
407
|
+
))
|
|
408
|
+
) {
|
|
409
|
+
// Preserve prior subtree under unproven directory — do not re-scan.
|
|
410
|
+
continue;
|
|
411
|
+
}
|
|
297
412
|
const nested = await diffDirectory(childRel);
|
|
298
413
|
if (nested.status !== "ok") {
|
|
299
414
|
return nested;
|
|
@@ -358,8 +473,14 @@ async function scanNewSubtree(
|
|
|
358
473
|
fs: WatcherSnapshotFs,
|
|
359
474
|
state: MutableSnapshotMaps,
|
|
360
475
|
candidates: Set<string>,
|
|
361
|
-
ceiling: number
|
|
476
|
+
ceiling: number,
|
|
477
|
+
directoryAvailability?: DirectoryAvailabilityPort
|
|
362
478
|
): Promise<DiffWorkResult> {
|
|
479
|
+
if (!(await directoryAllowsDescent(rootAbs, dirRel, directoryAvailability))) {
|
|
480
|
+
// Keep the directory fingerprint from the parent listing; do not enumerate.
|
|
481
|
+
state.unprovenSubtrees.add(dirRel);
|
|
482
|
+
return { status: "ok" };
|
|
483
|
+
}
|
|
363
484
|
const queue = [dirRel];
|
|
364
485
|
let head = 0;
|
|
365
486
|
while (head < queue.length) {
|
|
@@ -370,7 +491,17 @@ async function scanNewSubtree(
|
|
|
370
491
|
if (remaining < 0) {
|
|
371
492
|
return { status: "overflow" };
|
|
372
493
|
}
|
|
373
|
-
const scanned = await
|
|
494
|
+
const scanned = await readAvailableDirectory(
|
|
495
|
+
rootAbs,
|
|
496
|
+
current,
|
|
497
|
+
fs,
|
|
498
|
+
remaining,
|
|
499
|
+
directoryAvailability
|
|
500
|
+
);
|
|
501
|
+
if (scanned.status === "unproven") {
|
|
502
|
+
state.unprovenSubtrees.add(current);
|
|
503
|
+
continue;
|
|
504
|
+
}
|
|
374
505
|
if (scanned.status === "missing") {
|
|
375
506
|
// New directory vanished while scanning — fail closed.
|
|
376
507
|
return {
|
|
@@ -382,12 +513,23 @@ async function scanNewSubtree(
|
|
|
382
513
|
return scanned;
|
|
383
514
|
}
|
|
384
515
|
setDirectoryEntries(state, current, new Map(scanned.entries));
|
|
516
|
+
state.unprovenSubtrees.delete(current);
|
|
385
517
|
if (state.entryCount > ceiling) {
|
|
386
518
|
return { status: "overflow" };
|
|
387
519
|
}
|
|
388
520
|
for (const [name, fingerprint] of scanned.entries) {
|
|
389
521
|
const childRel = joinWatcherRelPath(current, name);
|
|
390
522
|
if (fingerprint.kind === "directory") {
|
|
523
|
+
if (
|
|
524
|
+
!(await directoryAllowsDescent(
|
|
525
|
+
rootAbs,
|
|
526
|
+
childRel,
|
|
527
|
+
directoryAvailability
|
|
528
|
+
))
|
|
529
|
+
) {
|
|
530
|
+
state.unprovenSubtrees.add(childRel);
|
|
531
|
+
continue;
|
|
532
|
+
}
|
|
391
533
|
queue.push(childRel);
|
|
392
534
|
} else if (isWatcherSourceKind(fingerprint.kind)) {
|
|
393
535
|
candidates.add(childRel);
|
|
@@ -35,6 +35,7 @@ export const defaultFs: WatcherSnapshotFs = createDefaultWatcherFs();
|
|
|
35
35
|
export interface MutableSnapshotMaps {
|
|
36
36
|
directories: Map<string, Map<string, SnapshotEntryFingerprint>>;
|
|
37
37
|
entryCount: number;
|
|
38
|
+
unprovenSubtrees: Set<string>;
|
|
38
39
|
}
|
|
39
40
|
|
|
40
41
|
export function cloneDirectoryMaps(
|
|
@@ -47,6 +48,7 @@ export function cloneDirectoryMaps(
|
|
|
47
48
|
return {
|
|
48
49
|
directories,
|
|
49
50
|
entryCount: source.entryCount,
|
|
51
|
+
unprovenSubtrees: new Set(source.unprovenSubtrees ?? []),
|
|
50
52
|
};
|
|
51
53
|
}
|
|
52
54
|
|
|
@@ -61,6 +63,7 @@ export function freezeSnapshot(state: MutableSnapshotMaps): WatcherSnapshot {
|
|
|
61
63
|
return {
|
|
62
64
|
directories: frozen,
|
|
63
65
|
entryCount: state.entryCount,
|
|
66
|
+
unprovenSubtrees: new Set(state.unprovenSubtrees),
|
|
64
67
|
};
|
|
65
68
|
}
|
|
66
69
|
|
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
// node:path — Bun has no path utilities
|
|
8
8
|
import { isAbsolute } from "node:path";
|
|
9
9
|
|
|
10
|
+
import type { DirectoryAvailabilityPort } from "../ingestion/source-availability";
|
|
11
|
+
|
|
10
12
|
/** Fixed service-wide maximum entries retained in one collection snapshot. */
|
|
11
13
|
export const WATCHER_SNAPSHOT_ENTRY_CEILING = 100_000;
|
|
12
14
|
|
|
@@ -44,6 +46,12 @@ export interface WatcherSnapshot {
|
|
|
44
46
|
>;
|
|
45
47
|
/** Total no-follow entries across every directory map. */
|
|
46
48
|
readonly entryCount: number;
|
|
49
|
+
/**
|
|
50
|
+
* Directory roots observed in a parent listing but not enumerated because
|
|
51
|
+
* source availability was unproven. Their stored descendant inventory is
|
|
52
|
+
* incomplete, so a later proven removal requires full reconciliation.
|
|
53
|
+
*/
|
|
54
|
+
readonly unprovenSubtrees?: ReadonlySet<string>;
|
|
47
55
|
}
|
|
48
56
|
|
|
49
57
|
/** Injectable lstat view. `unreliable` forces the correctness-preserving fallback. */
|
|
@@ -120,6 +128,26 @@ export interface WatcherSnapshotFs {
|
|
|
120
128
|
|
|
121
129
|
/** Deterministic close; safe to call once per open. */
|
|
122
130
|
closeDir(handle: WatcherDirHandle): Promise<void>;
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Optional production-grade synchronous scan used only while a process-wide
|
|
134
|
+
* no-materialization policy is active. Missing support fails local mode closed.
|
|
135
|
+
*/
|
|
136
|
+
readDirectChildrenSync?: (
|
|
137
|
+
rootAbs: string,
|
|
138
|
+
dirRel: string,
|
|
139
|
+
maxEntries: number
|
|
140
|
+
) =>
|
|
141
|
+
| { status: "present"; entries: Map<string, SnapshotEntryFingerprint> }
|
|
142
|
+
| { status: "missing" }
|
|
143
|
+
| ScanFailure;
|
|
144
|
+
|
|
145
|
+
/** Synchronous anchored child lstat for guarded local-mode presence checks. */
|
|
146
|
+
lstatChildByRelSync?: (
|
|
147
|
+
rootAbs: string,
|
|
148
|
+
parentRel: string,
|
|
149
|
+
name: string
|
|
150
|
+
) => WatcherSnapshotStat;
|
|
123
151
|
}
|
|
124
152
|
|
|
125
153
|
export interface WatcherSnapshotClock {
|
|
@@ -135,7 +163,8 @@ export interface SnapshotMapHooks {
|
|
|
135
163
|
export type SnapshotFallbackReason =
|
|
136
164
|
| "overflow"
|
|
137
165
|
| "scan_failed"
|
|
138
|
-
| "unreliable_metadata"
|
|
166
|
+
| "unreliable_metadata"
|
|
167
|
+
| "unproven_subtree";
|
|
139
168
|
|
|
140
169
|
export type WatcherSnapshotBuildResult =
|
|
141
170
|
| {
|
|
@@ -191,6 +220,12 @@ export interface WatcherSnapshotOptions {
|
|
|
191
220
|
entryCeiling?: number;
|
|
192
221
|
/** Map-visit instrumentation (tests / complexity regression). */
|
|
193
222
|
mapHooks?: SnapshotMapHooks;
|
|
223
|
+
/**
|
|
224
|
+
* Optional directory-availability classifier for local-mode collections.
|
|
225
|
+
* When set, dataless / availability-unknown directories are not descended;
|
|
226
|
+
* previously observed subtrees are preserved rather than proven removed.
|
|
227
|
+
*/
|
|
228
|
+
directoryAvailability?: DirectoryAvailabilityPort;
|
|
194
229
|
}
|
|
195
230
|
|
|
196
231
|
export type ScanFailure =
|
|
@@ -198,7 +233,10 @@ export type ScanFailure =
|
|
|
198
233
|
| { status: "scan_failed"; cause: unknown }
|
|
199
234
|
| { status: "unreliable_metadata" };
|
|
200
235
|
|
|
201
|
-
export type DiffWorkResult =
|
|
236
|
+
export type DiffWorkResult =
|
|
237
|
+
| { status: "ok" }
|
|
238
|
+
| ScanFailure
|
|
239
|
+
| { status: "unproven_subtree" };
|
|
202
240
|
|
|
203
241
|
export function toBigInt(value: number | bigint | undefined): bigint | null {
|
|
204
242
|
if (value === undefined) {
|
|
@@ -332,7 +370,11 @@ export function joinWatcherRelPath(dir: string, name: string): string {
|
|
|
332
370
|
}
|
|
333
371
|
|
|
334
372
|
export function createEmptyWatcherSnapshot(): WatcherSnapshot {
|
|
335
|
-
return {
|
|
373
|
+
return {
|
|
374
|
+
directories: new Map(),
|
|
375
|
+
entryCount: 0,
|
|
376
|
+
unprovenSubtrees: new Set(),
|
|
377
|
+
};
|
|
336
378
|
}
|
|
337
379
|
|
|
338
380
|
export function isMissingFsError(error: unknown): boolean {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
76e1e560efa69f780e5e61130008e863cf8288a8ffe5cd82e16b48608c6c8578 gno-browser-clipper-v1.34.6.zip
|