wiki-graph-sdk 0.8.4 → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/archives.cjs +345 -152
- package/dist/archives.cjs.map +1 -1
- package/dist/archives.js +356 -157
- package/dist/archives.js.map +1 -1
- package/dist/conversions.cjs +269 -99
- package/dist/conversions.cjs.map +1 -1
- package/dist/conversions.js +275 -103
- package/dist/conversions.js.map +1 -1
- package/dist/default-worker.cjs +278 -108
- package/dist/default-worker.cjs.map +1 -1
- package/dist/default-worker.js +285 -112
- package/dist/default-worker.js.map +1 -1
- package/dist/embedding.cjs +214 -54
- package/dist/embedding.cjs.map +1 -1
- package/dist/embedding.js +214 -54
- package/dist/embedding.js.map +1 -1
- package/dist/gc.cjs +214 -54
- package/dist/gc.cjs.map +1 -1
- package/dist/gc.js +214 -54
- package/dist/gc.js.map +1 -1
- package/dist/index.cjs +442 -226
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +461 -236
- package/dist/index.js.map +1 -1
- package/dist/local-config.cjs +214 -54
- package/dist/local-config.cjs.map +1 -1
- package/dist/local-config.js +214 -54
- package/dist/local-config.js.map +1 -1
- package/dist/maintenance.cjs +265 -97
- package/dist/maintenance.cjs.map +1 -1
- package/dist/maintenance.js +271 -101
- package/dist/maintenance.js.map +1 -1
- package/dist/node-platform.cjs +214 -54
- package/dist/node-platform.cjs.map +1 -1
- package/dist/node-platform.d.ts +2 -0
- package/dist/node-platform.js +214 -54
- package/dist/node-platform.js.map +1 -1
- package/dist/runtime-config.cjs +214 -54
- package/dist/runtime-config.cjs.map +1 -1
- package/dist/runtime-config.js +214 -54
- package/dist/runtime-config.js.map +1 -1
- package/dist/stage.cjs +214 -54
- package/dist/stage.cjs.map +1 -1
- package/dist/stage.js +214 -54
- package/dist/stage.js.map +1 -1
- package/dist/worker.cjs +277 -103
- package/dist/worker.cjs.map +1 -1
- package/dist/worker.js +284 -107
- package/dist/worker.js.map +1 -1
- package/package.json +2 -2
package/dist/archives.js
CHANGED
|
@@ -11,7 +11,9 @@ import { Readable as Readable2 } from "stream";
|
|
|
11
11
|
import {
|
|
12
12
|
addChapter,
|
|
13
13
|
applyChapterTree,
|
|
14
|
-
|
|
14
|
+
assertArchiveQueryReady,
|
|
15
|
+
resolveIndexedArchiveChapterScope,
|
|
16
|
+
ensureWikiGraphArchiveSchemaCurrent,
|
|
15
17
|
assertNoActiveBuildJobConflicts,
|
|
16
18
|
assertNoActiveBuildJobs,
|
|
17
19
|
deleteArchiveSearchSessions,
|
|
@@ -43,6 +45,7 @@ import {
|
|
|
43
45
|
getChapterTree,
|
|
44
46
|
WikiGraph as WikiGraph2,
|
|
45
47
|
WikiGraphArchiveFile as WikiGraphArchiveFile2,
|
|
48
|
+
WikiGraphDirectoryFile as WikiGraphDirectoryFile2,
|
|
46
49
|
TOC_FILE_VERSION,
|
|
47
50
|
writeWikgArchive,
|
|
48
51
|
ObjectMetadataKind
|
|
@@ -161,6 +164,15 @@ var NodeFile = class {
|
|
|
161
164
|
this.name = name;
|
|
162
165
|
}
|
|
163
166
|
path;
|
|
167
|
+
async getPhysicalIdentity() {
|
|
168
|
+
const value = await fsPromises.stat(this.path).catch((error) => {
|
|
169
|
+
if (typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT")
|
|
170
|
+
return void 0;
|
|
171
|
+
throw error;
|
|
172
|
+
});
|
|
173
|
+
if (value === void 0) return void 0;
|
|
174
|
+
return `${value.dev}:${value.ino}`;
|
|
175
|
+
}
|
|
164
176
|
kind = "file";
|
|
165
177
|
[NODE_RESOURCE_KIND] = "file";
|
|
166
178
|
identity;
|
|
@@ -285,6 +297,15 @@ var NodeDirectory = class _NodeDirectory {
|
|
|
285
297
|
this.name = pathModule.basename(path);
|
|
286
298
|
}
|
|
287
299
|
path;
|
|
300
|
+
async getPhysicalIdentity() {
|
|
301
|
+
const value = await fsPromises.stat(this.path).catch((error) => {
|
|
302
|
+
if (typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT")
|
|
303
|
+
return void 0;
|
|
304
|
+
throw error;
|
|
305
|
+
});
|
|
306
|
+
if (value === void 0) return void 0;
|
|
307
|
+
return `${value.dev}:${value.ino}`;
|
|
308
|
+
}
|
|
288
309
|
kind = "directory";
|
|
289
310
|
[NODE_RESOURCE_KIND] = "directory";
|
|
290
311
|
identity;
|
|
@@ -294,8 +315,10 @@ var NodeDirectory = class _NodeDirectory {
|
|
|
294
315
|
const file = new NodeFile(pathModule.join(this.path, name));
|
|
295
316
|
try {
|
|
296
317
|
return (await fsPromises.stat(file.path)).isFile() ? file : void 0;
|
|
297
|
-
} catch {
|
|
298
|
-
|
|
318
|
+
} catch (error) {
|
|
319
|
+
if (typeof error === "object" && error !== null && "code" in error && (error.code === "ENOENT" || error.code === "ENOTDIR"))
|
|
320
|
+
return void 0;
|
|
321
|
+
throw error;
|
|
299
322
|
}
|
|
300
323
|
}
|
|
301
324
|
async getLastModified() {
|
|
@@ -313,8 +336,10 @@ var NodeDirectory = class _NodeDirectory {
|
|
|
313
336
|
const directory = new _NodeDirectory(pathModule.join(this.path, name));
|
|
314
337
|
try {
|
|
315
338
|
return (await fsPromises.stat(directory.path)).isDirectory() ? directory : void 0;
|
|
316
|
-
} catch {
|
|
317
|
-
|
|
339
|
+
} catch (error) {
|
|
340
|
+
if (typeof error === "object" && error !== null && "code" in error && (error.code === "ENOENT" || error.code === "ENOTDIR"))
|
|
341
|
+
return void 0;
|
|
342
|
+
throw error;
|
|
318
343
|
}
|
|
319
344
|
}
|
|
320
345
|
async list() {
|
|
@@ -438,14 +463,23 @@ async function openNativeNodeDatabase(file, flags) {
|
|
|
438
463
|
});
|
|
439
464
|
});
|
|
440
465
|
}
|
|
441
|
-
async function openNodeZip(file) {
|
|
466
|
+
async function openNodeZip(file, options = {}) {
|
|
442
467
|
const path = getBrandedNodeResourcePath(file, "file");
|
|
443
468
|
if (path === void 0) {
|
|
444
469
|
throw new TypeError("The Node ZIP adapter requires a NodeFile");
|
|
445
470
|
}
|
|
446
|
-
const
|
|
447
|
-
|
|
448
|
-
|
|
471
|
+
const handle = await fsPromises.open(path, "r");
|
|
472
|
+
let size;
|
|
473
|
+
try {
|
|
474
|
+
size = (await handle.stat()).size;
|
|
475
|
+
} catch (error) {
|
|
476
|
+
await handle.close();
|
|
477
|
+
throw error;
|
|
478
|
+
}
|
|
479
|
+
const open2 = () => new Promise((resolve4, reject) => {
|
|
480
|
+
yauzl.fromRandomAccessReader(
|
|
481
|
+
new NodeZipSource(handle),
|
|
482
|
+
size,
|
|
449
483
|
{ autoClose: false, lazyEntries: true },
|
|
450
484
|
(error, opened) => {
|
|
451
485
|
if (error || opened === void 0)
|
|
@@ -454,63 +488,192 @@ async function openNodeZip(file) {
|
|
|
454
488
|
}
|
|
455
489
|
);
|
|
456
490
|
});
|
|
457
|
-
|
|
458
|
-
(
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
error instanceof Error ? error : new Error("Cannot scan ZIP central directory")
|
|
464
|
-
);
|
|
465
|
-
};
|
|
466
|
-
const resolveEntries = () => {
|
|
467
|
-
zipFile.off("error", rejectAndClose);
|
|
468
|
-
resolve4(discovered);
|
|
469
|
-
};
|
|
470
|
-
zipFile.on("entry", (entry) => {
|
|
471
|
-
if (!entry.fileName.endsWith("/")) {
|
|
472
|
-
discovered.set(entry.fileName, entry);
|
|
473
|
-
}
|
|
474
|
-
zipFile.readEntry();
|
|
475
|
-
});
|
|
476
|
-
zipFile.once("error", rejectAndClose);
|
|
477
|
-
zipFile.once("end", resolveEntries);
|
|
478
|
-
zipFile.readEntry();
|
|
479
|
-
}
|
|
480
|
-
);
|
|
491
|
+
try {
|
|
492
|
+
(await open2()).close();
|
|
493
|
+
} catch (error) {
|
|
494
|
+
await handle.close();
|
|
495
|
+
throw error;
|
|
496
|
+
}
|
|
481
497
|
let closed = false;
|
|
498
|
+
let pending = Promise.resolve();
|
|
499
|
+
let closing;
|
|
500
|
+
const run = (operation) => {
|
|
501
|
+
if (closed)
|
|
502
|
+
return Promise.reject(new Error("Cannot read a closed ZIP archive"));
|
|
503
|
+
const result = pending.then(async () => {
|
|
504
|
+
const zip = await open2();
|
|
505
|
+
try {
|
|
506
|
+
return await operation(zip);
|
|
507
|
+
} finally {
|
|
508
|
+
zip.close();
|
|
509
|
+
}
|
|
510
|
+
});
|
|
511
|
+
pending = result.then(
|
|
512
|
+
() => void 0,
|
|
513
|
+
() => void 0
|
|
514
|
+
);
|
|
515
|
+
return result;
|
|
516
|
+
};
|
|
517
|
+
const withEntry = (name, operation) => run(async (zip) => {
|
|
518
|
+
let exact;
|
|
519
|
+
let alias;
|
|
520
|
+
let aliasCollision = false;
|
|
521
|
+
await scanNodeZip(zip, (entry) => {
|
|
522
|
+
if (entry.fileName === name) exact = entry;
|
|
523
|
+
if (normalizeNodeZipName(entry.fileName) === name) {
|
|
524
|
+
if (alias !== void 0 && alias.fileName !== entry.fileName)
|
|
525
|
+
aliasCollision = true;
|
|
526
|
+
alias = entry;
|
|
527
|
+
}
|
|
528
|
+
});
|
|
529
|
+
if ((exact === void 0 || options.entryNameMode === "normalized") && aliasCollision) {
|
|
530
|
+
let bestPosition = -1;
|
|
531
|
+
const candidates = await open2();
|
|
532
|
+
try {
|
|
533
|
+
await scanNodeZip(candidates, async (entry) => {
|
|
534
|
+
if (normalizeNodeZipName(entry.fileName) !== name) return;
|
|
535
|
+
const probe = await open2();
|
|
536
|
+
let position = 0;
|
|
537
|
+
try {
|
|
538
|
+
await scanNodeZip(probe, (candidate) => {
|
|
539
|
+
if (candidate.fileName === entry.fileName) return false;
|
|
540
|
+
position++;
|
|
541
|
+
});
|
|
542
|
+
} finally {
|
|
543
|
+
probe.close();
|
|
544
|
+
}
|
|
545
|
+
if (position >= bestPosition) {
|
|
546
|
+
bestPosition = position;
|
|
547
|
+
alias = entry;
|
|
548
|
+
}
|
|
549
|
+
});
|
|
550
|
+
return await operation(candidates, alias);
|
|
551
|
+
} finally {
|
|
552
|
+
candidates.close();
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
return await operation(
|
|
556
|
+
zip,
|
|
557
|
+
options.entryNameMode === "normalized" ? alias : exact ?? alias
|
|
558
|
+
);
|
|
559
|
+
});
|
|
482
560
|
return {
|
|
483
561
|
close: () => {
|
|
484
|
-
if (!closed) zipFile.close();
|
|
485
562
|
closed = true;
|
|
486
|
-
|
|
563
|
+
closing ??= pending.then(() => handle.close());
|
|
564
|
+
return closing;
|
|
487
565
|
},
|
|
488
|
-
copyEntry:
|
|
489
|
-
if (closed) throw new Error("Cannot read a closed ZIP archive");
|
|
490
|
-
const entry = entries.get(name);
|
|
566
|
+
copyEntry: (name, target) => withEntry(name, async (zip, entry) => {
|
|
491
567
|
if (entry === void 0) return false;
|
|
492
|
-
await copyNodeZipEntry(
|
|
568
|
+
await copyNodeZipEntry(zip, entry, target);
|
|
493
569
|
return true;
|
|
494
|
-
},
|
|
495
|
-
getEntrySize: (name) =>
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
listEntries: () =>
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
570
|
+
}),
|
|
571
|
+
getEntrySize: (name) => withEntry(
|
|
572
|
+
name,
|
|
573
|
+
(_zip, entry) => Promise.resolve(entry?.uncompressedSize)
|
|
574
|
+
),
|
|
575
|
+
listEntries: () => run(async (zip) => {
|
|
576
|
+
const names = /* @__PURE__ */ new Set();
|
|
577
|
+
await scanNodeZip(zip, (entry) => {
|
|
578
|
+
names.add(entry.fileName);
|
|
579
|
+
});
|
|
580
|
+
return [...names];
|
|
581
|
+
}),
|
|
582
|
+
readEntryRange: (name, offset, length) => withEntry(name, async (zip, entry) => {
|
|
503
583
|
if (entry === void 0) return void 0;
|
|
504
|
-
return await readNodeZipEntryRange(
|
|
505
|
-
},
|
|
506
|
-
readEntry: async (
|
|
507
|
-
if (closed) throw new Error("Cannot read a closed ZIP archive");
|
|
508
|
-
const entry = entries.get(name);
|
|
584
|
+
return await readNodeZipEntryRange(zip, entry, offset, length);
|
|
585
|
+
}),
|
|
586
|
+
readEntry: (name) => withEntry(name, async (zip, entry) => {
|
|
509
587
|
if (entry === void 0) return void 0;
|
|
510
|
-
return await readNodeZipEntry(
|
|
511
|
-
}
|
|
588
|
+
return await readNodeZipEntry(zip, entry);
|
|
589
|
+
})
|
|
512
590
|
};
|
|
513
591
|
}
|
|
592
|
+
var NodeZipSource = class extends yauzl.RandomAccessReader {
|
|
593
|
+
constructor(handle) {
|
|
594
|
+
super();
|
|
595
|
+
this.handle = handle;
|
|
596
|
+
}
|
|
597
|
+
handle;
|
|
598
|
+
read(buffer, offset, length, position, callback) {
|
|
599
|
+
const read2 = (written) => {
|
|
600
|
+
if (written === length) {
|
|
601
|
+
callback(null);
|
|
602
|
+
return;
|
|
603
|
+
}
|
|
604
|
+
fs.read(
|
|
605
|
+
this.handle.fd,
|
|
606
|
+
buffer,
|
|
607
|
+
offset + written,
|
|
608
|
+
length - written,
|
|
609
|
+
position + written,
|
|
610
|
+
(error, bytesRead) => {
|
|
611
|
+
if (error) callback(error);
|
|
612
|
+
else if (bytesRead === 0)
|
|
613
|
+
callback(new Error("Unexpected end of ZIP file"));
|
|
614
|
+
else read2(written + bytesRead);
|
|
615
|
+
}
|
|
616
|
+
);
|
|
617
|
+
};
|
|
618
|
+
read2(0);
|
|
619
|
+
}
|
|
620
|
+
_readStreamForRange(start, end) {
|
|
621
|
+
const handle = this.handle;
|
|
622
|
+
return Readable.from(
|
|
623
|
+
(async function* () {
|
|
624
|
+
for (let position = start; position < end; ) {
|
|
625
|
+
const buffer = Buffer.allocUnsafe(
|
|
626
|
+
Math.min(64 * 1024, end - position)
|
|
627
|
+
);
|
|
628
|
+
const { bytesRead } = await handle.read(
|
|
629
|
+
buffer,
|
|
630
|
+
0,
|
|
631
|
+
buffer.length,
|
|
632
|
+
position
|
|
633
|
+
);
|
|
634
|
+
if (bytesRead === 0) return;
|
|
635
|
+
position += bytesRead;
|
|
636
|
+
yield buffer.subarray(0, bytesRead);
|
|
637
|
+
}
|
|
638
|
+
})()
|
|
639
|
+
);
|
|
640
|
+
}
|
|
641
|
+
};
|
|
642
|
+
function normalizeNodeZipName(name) {
|
|
643
|
+
const normalized = name.replaceAll("\\", "/").trim().split("/").filter((part) => part !== "" && part !== ".").join("/");
|
|
644
|
+
return normalized.split("/").includes("..") ? void 0 : normalized;
|
|
645
|
+
}
|
|
646
|
+
async function scanNodeZip(zip, visit) {
|
|
647
|
+
await new Promise((resolve4, reject) => {
|
|
648
|
+
const cleanup = () => {
|
|
649
|
+
zip.off("entry", onEntry);
|
|
650
|
+
zip.off("end", onEnd);
|
|
651
|
+
zip.off("error", onError);
|
|
652
|
+
};
|
|
653
|
+
const onError = (error) => {
|
|
654
|
+
cleanup();
|
|
655
|
+
reject(error);
|
|
656
|
+
};
|
|
657
|
+
const onEnd = () => {
|
|
658
|
+
cleanup();
|
|
659
|
+
resolve4();
|
|
660
|
+
};
|
|
661
|
+
const onEntry = (entry) => {
|
|
662
|
+
void Promise.resolve().then(() => entry.fileName.endsWith("/") ? void 0 : visit(entry)).then((keepReading) => {
|
|
663
|
+
if (keepReading === false) onEnd();
|
|
664
|
+
else zip.readEntry();
|
|
665
|
+
}).catch(
|
|
666
|
+
(error) => onError(
|
|
667
|
+
error instanceof Error ? error : new Error("Cannot scan ZIP", { cause: error })
|
|
668
|
+
)
|
|
669
|
+
);
|
|
670
|
+
};
|
|
671
|
+
zip.on("entry", onEntry);
|
|
672
|
+
zip.once("end", onEnd);
|
|
673
|
+
zip.once("error", onError);
|
|
674
|
+
zip.readEntry();
|
|
675
|
+
});
|
|
676
|
+
}
|
|
514
677
|
async function copyNodeZipEntry(zipFile, entry, target) {
|
|
515
678
|
const writer = await target.openWriter();
|
|
516
679
|
try {
|
|
@@ -1281,17 +1444,32 @@ function resolveWikiGraphRuntimePath(path) {
|
|
|
1281
1444
|
|
|
1282
1445
|
// src/archive/target.ts
|
|
1283
1446
|
import { realpath, stat as stat2 } from "fs/promises";
|
|
1284
|
-
import { basename as basename2, dirname as dirname2,
|
|
1447
|
+
import { basename as basename2, dirname as dirname2, join as join3, resolve as resolve3 } from "path";
|
|
1285
1448
|
import {
|
|
1286
1449
|
formatLocatedWikiGraphUri,
|
|
1287
1450
|
formatWikiGraphLibraryUri,
|
|
1288
|
-
|
|
1289
|
-
|
|
1451
|
+
findWikiGraphLibraryByPhysicalIdentity,
|
|
1452
|
+
findWikiGraphLibraryArchivePhysicalAliases,
|
|
1290
1453
|
parseLocatedWikiGraphUri,
|
|
1291
1454
|
parseWikiGraphLibraryUri,
|
|
1292
1455
|
resolveWikiGraphLibrary,
|
|
1293
|
-
resolveWikiGraphLibraryArchiveFile
|
|
1456
|
+
resolveWikiGraphLibraryArchiveFile,
|
|
1457
|
+
isWikiGraphSchemaVersionError,
|
|
1458
|
+
WikiGraphSchemaVersionError
|
|
1294
1459
|
} from "wiki-graph-core";
|
|
1460
|
+
function rethrowArchiveSchemaError(error, target) {
|
|
1461
|
+
if (isWikiGraphSchemaVersionError(error) && error.target.kind === "archive") {
|
|
1462
|
+
throw new WikiGraphSchemaVersionError(
|
|
1463
|
+
target.kind === "standalone" ? { kind: "archive", path: resolveWikiGraphRuntimePath(target.path) } : { kind: "library", uri: target.uri.split("/arc/")[0] },
|
|
1464
|
+
error.actualVersion,
|
|
1465
|
+
error.supportedVersion
|
|
1466
|
+
);
|
|
1467
|
+
}
|
|
1468
|
+
throw error;
|
|
1469
|
+
}
|
|
1470
|
+
function requireWikiGraphArchiveFile(location) {
|
|
1471
|
+
return location.archiveFile;
|
|
1472
|
+
}
|
|
1295
1473
|
var WikiGraphArchiveOwnershipError = class extends Error {
|
|
1296
1474
|
code = "WIKI_GRAPH_ARCHIVE_OWNERSHIP_MISMATCH";
|
|
1297
1475
|
constructor(message) {
|
|
@@ -1309,12 +1487,7 @@ async function assertStandaloneWikiGraphArchivePath(inputPath) {
|
|
|
1309
1487
|
const path = resolveWikiGraphRuntimePath(inputPath);
|
|
1310
1488
|
const candidate = await canonicalPath(path);
|
|
1311
1489
|
const candidateIdentity = await readFileIdentity(path);
|
|
1312
|
-
const
|
|
1313
|
-
const matches = await findMatchingMembers(
|
|
1314
|
-
libraries,
|
|
1315
|
-
candidate,
|
|
1316
|
-
candidateIdentity
|
|
1317
|
-
);
|
|
1490
|
+
const matches = await findMatchingMembers(candidate, candidateIdentity);
|
|
1318
1491
|
if (matches.length > 0) {
|
|
1319
1492
|
const match = requireUnambiguousManagedMatch(path, matches);
|
|
1320
1493
|
throw new WikiGraphArchiveOwnershipError(
|
|
@@ -1323,15 +1496,26 @@ async function assertStandaloneWikiGraphArchivePath(inputPath) {
|
|
|
1323
1496
|
)}: ${path}. Use the library UUID URI ${match.archive.uri} instead.`
|
|
1324
1497
|
);
|
|
1325
1498
|
}
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1499
|
+
const ancestors = /* @__PURE__ */ new Set();
|
|
1500
|
+
for (const start of [candidate, resolve3(path)]) {
|
|
1501
|
+
for (let parent = dirname2(start); ; parent = dirname2(parent)) {
|
|
1502
|
+
ancestors.add(parent);
|
|
1503
|
+
if (dirname2(parent) === parent) break;
|
|
1504
|
+
}
|
|
1505
|
+
}
|
|
1506
|
+
for (const parent of ancestors) {
|
|
1507
|
+
const identity = await readFileIdentity(parent);
|
|
1508
|
+
const library = await findWikiGraphLibraryByPhysicalIdentity(
|
|
1509
|
+
identity,
|
|
1510
|
+
new NodeDirectory(parent).identity
|
|
1334
1511
|
);
|
|
1512
|
+
if (library !== void 0) {
|
|
1513
|
+
throw new WikiGraphArchiveOwnershipError(
|
|
1514
|
+
`Standalone archive path belongs to registered library ${formatWikiGraphLibraryUri(
|
|
1515
|
+
library.isDefault ? void 0 : library.publicId
|
|
1516
|
+
)}: ${path}. Scan the library, then address the archive by its library UUID URI.`
|
|
1517
|
+
);
|
|
1518
|
+
}
|
|
1335
1519
|
}
|
|
1336
1520
|
return path;
|
|
1337
1521
|
}
|
|
@@ -1389,47 +1573,35 @@ async function resolveLibraryLocation(target) {
|
|
|
1389
1573
|
async function canonicalPath(path) {
|
|
1390
1574
|
try {
|
|
1391
1575
|
return await realpath(path);
|
|
1392
|
-
} catch {
|
|
1576
|
+
} catch (error) {
|
|
1577
|
+
if (!(typeof error === "object" && error !== null && "code" in error && (error.code === "ENOENT" || error.code === "ENOTDIR")))
|
|
1578
|
+
throw error;
|
|
1393
1579
|
const absolute = resolve3(path);
|
|
1394
1580
|
const parent = dirname2(absolute);
|
|
1395
1581
|
return parent === absolute ? absolute : join3(await canonicalPath(parent), basename2(absolute));
|
|
1396
1582
|
}
|
|
1397
1583
|
}
|
|
1398
|
-
function
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
}
|
|
1402
|
-
async function findMatchingMembers(libraries, candidate, candidateIdentity) {
|
|
1584
|
+
async function findMatchingMembers(candidate, candidateIdentity) {
|
|
1585
|
+
if (candidateIdentity === void 0) return [];
|
|
1586
|
+
const archives = await findWikiGraphLibraryArchivePhysicalAliases(candidateIdentity);
|
|
1403
1587
|
const members = [];
|
|
1404
|
-
for (const
|
|
1405
|
-
const
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
});
|
|
1410
|
-
for (const archive of archives) {
|
|
1411
|
-
if (archive.file === void 0) continue;
|
|
1588
|
+
for (const archive of archives) {
|
|
1589
|
+
const parsed = parseWikiGraphLibraryUri(archive.libraryUri);
|
|
1590
|
+
const library = await resolveWikiGraphLibrary(parsed);
|
|
1591
|
+
const physical = archive.file ?? archive.directory;
|
|
1592
|
+
if (library !== void 0 && physical !== void 0)
|
|
1412
1593
|
members.push({
|
|
1413
1594
|
archive,
|
|
1414
1595
|
library,
|
|
1415
|
-
memberPath: getNodeResourcePath(
|
|
1596
|
+
memberPath: getNodeResourcePath(physical)
|
|
1416
1597
|
});
|
|
1417
|
-
}
|
|
1418
1598
|
}
|
|
1419
1599
|
const exact = [];
|
|
1420
1600
|
for (const member of members) {
|
|
1421
|
-
if (await canonicalPath(member.memberPath) === candidate)
|
|
1601
|
+
if (await canonicalPath(member.memberPath) === candidate)
|
|
1422
1602
|
exact.push(member);
|
|
1423
|
-
}
|
|
1424
|
-
}
|
|
1425
|
-
if (exact.length > 0 || candidateIdentity === void 0) return exact;
|
|
1426
|
-
const identityMatches = [];
|
|
1427
|
-
for (const member of members) {
|
|
1428
|
-
if (await readFileIdentity(member.memberPath) === candidateIdentity) {
|
|
1429
|
-
identityMatches.push(member);
|
|
1430
|
-
}
|
|
1431
1603
|
}
|
|
1432
|
-
return
|
|
1604
|
+
return exact.length > 0 ? exact : members;
|
|
1433
1605
|
}
|
|
1434
1606
|
function requireUnambiguousManagedMatch(path, matches) {
|
|
1435
1607
|
if (matches.length === 1) return matches[0];
|
|
@@ -1441,8 +1613,10 @@ async function readFileIdentity(path) {
|
|
|
1441
1613
|
try {
|
|
1442
1614
|
const value = await stat2(path);
|
|
1443
1615
|
return `${value.dev}:${value.ino}`;
|
|
1444
|
-
} catch {
|
|
1445
|
-
|
|
1616
|
+
} catch (error) {
|
|
1617
|
+
if (typeof error === "object" && error !== null && "code" in error && (error.code === "ENOENT" || error.code === "ENOTDIR"))
|
|
1618
|
+
return void 0;
|
|
1619
|
+
throw error;
|
|
1446
1620
|
}
|
|
1447
1621
|
}
|
|
1448
1622
|
|
|
@@ -1504,11 +1678,15 @@ var WikiGraphConversionManager = class {
|
|
|
1504
1678
|
if (!("path" in options.input)) {
|
|
1505
1679
|
throw new Error("wikg input requires a file path.");
|
|
1506
1680
|
}
|
|
1681
|
+
const inputPath = options.input.path;
|
|
1507
1682
|
await app.openSession(
|
|
1508
|
-
new NodeFile(
|
|
1509
|
-
await assertStandaloneWikiGraphArchivePath(options.input.path)
|
|
1510
|
-
),
|
|
1683
|
+
new NodeFile(await assertStandaloneWikiGraphArchivePath(inputPath)),
|
|
1511
1684
|
write
|
|
1685
|
+
).catch(
|
|
1686
|
+
(error) => rethrowArchiveSchemaError(error, {
|
|
1687
|
+
kind: "standalone",
|
|
1688
|
+
path: inputPath
|
|
1689
|
+
})
|
|
1512
1690
|
);
|
|
1513
1691
|
} else if ("stream" in options.input) {
|
|
1514
1692
|
await app.digestTextStreamSession(
|
|
@@ -1902,17 +2080,36 @@ function formatLocatedChapterUri(archiveUri, chapter) {
|
|
|
1902
2080
|
// src/archive/write.ts
|
|
1903
2081
|
import {
|
|
1904
2082
|
WikiGraphArchiveFile,
|
|
2083
|
+
WikiGraphDirectoryFile,
|
|
1905
2084
|
writeWikiGraphLibraryArchive
|
|
1906
2085
|
} from "wiki-graph-core";
|
|
1907
2086
|
async function writeWikiGraphArchiveLocation(location, operation, options = {}) {
|
|
1908
2087
|
const cacheOnly = options.searchIndexWritebackPolicy === "cache";
|
|
1909
|
-
const write = async (archiveFile = location.archiveFile) =>
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
2088
|
+
const write = async (archiveFile = location.archiveFile) => {
|
|
2089
|
+
if (cacheOnly) {
|
|
2090
|
+
return await new WikiGraphArchiveFile(archiveFile).readDocument(
|
|
2091
|
+
operation,
|
|
2092
|
+
{ searchIndexWritebackPolicy: "cache" }
|
|
2093
|
+
);
|
|
2094
|
+
}
|
|
2095
|
+
const writeOptions = {
|
|
2096
|
+
...cacheOnly ? {} : { derivedStateKeys: [location.archiveKey, location.archivePath] },
|
|
2097
|
+
...options.invalidateContinuationCursors === void 0 ? {} : {
|
|
2098
|
+
invalidateContinuationCursors: options.invalidateContinuationCursors
|
|
2099
|
+
},
|
|
2100
|
+
...options.searchIndexWritebackPolicy === void 0 ? {} : { searchIndexWritebackPolicy: options.searchIndexWritebackPolicy }
|
|
2101
|
+
};
|
|
2102
|
+
if (archiveFile.kind === "directory") {
|
|
2103
|
+
return await new WikiGraphDirectoryFile(archiveFile).write(
|
|
2104
|
+
operation,
|
|
2105
|
+
writeOptions
|
|
2106
|
+
);
|
|
2107
|
+
}
|
|
2108
|
+
return await new WikiGraphArchiveFile(archiveFile).write(
|
|
2109
|
+
operation,
|
|
2110
|
+
writeOptions
|
|
2111
|
+
);
|
|
2112
|
+
};
|
|
1916
2113
|
if (location.libraryArchiveTarget === void 0 || cacheOnly || options.refreshLibraryIndex === false) {
|
|
1917
2114
|
return await write();
|
|
1918
2115
|
}
|
|
@@ -2212,10 +2409,15 @@ var WikiGraphArchiveManager = class {
|
|
|
2212
2409
|
}, options.signal);
|
|
2213
2410
|
}
|
|
2214
2411
|
async open(target, options = {}) {
|
|
2215
|
-
const location = await this.#runtime.run(
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2412
|
+
const location = await this.#runtime.run(async () => {
|
|
2413
|
+
const location2 = await resolveWikiGraphArchiveLocation(target);
|
|
2414
|
+
try {
|
|
2415
|
+
await ensureWikiGraphArchiveSchemaCurrent(location2.archiveFile);
|
|
2416
|
+
} catch (error) {
|
|
2417
|
+
rethrowArchiveSchemaError(error, target);
|
|
2418
|
+
}
|
|
2419
|
+
return location2;
|
|
2420
|
+
}, options.signal);
|
|
2219
2421
|
return new WikiGraphArchiveHandle(this.#runtime, location);
|
|
2220
2422
|
}
|
|
2221
2423
|
};
|
|
@@ -2266,15 +2468,11 @@ var WikiGraphArchiveHandle = class {
|
|
|
2266
2468
|
options.queryMode,
|
|
2267
2469
|
options.signal
|
|
2268
2470
|
);
|
|
2269
|
-
const result = await this.#
|
|
2471
|
+
const result = await this.#readDocument(
|
|
2270
2472
|
async (document) => {
|
|
2271
2473
|
const chapters = await this.#resolveQueryChapters(document, options, {
|
|
2272
2474
|
embeddingProvider
|
|
2273
2475
|
});
|
|
2274
|
-
await ensureArchiveSearchIndex(document, {
|
|
2275
|
-
...chapters === void 0 ? {} : { chapters },
|
|
2276
|
-
...embeddingProvider === void 0 ? {} : { embeddingProvider }
|
|
2277
|
-
});
|
|
2278
2476
|
return await findArchiveObjects(document, query, {
|
|
2279
2477
|
...withoutOperationAndScope(options),
|
|
2280
2478
|
archiveKey: this.archiveKey,
|
|
@@ -2283,7 +2481,6 @@ var WikiGraphArchiveHandle = class {
|
|
|
2283
2481
|
});
|
|
2284
2482
|
},
|
|
2285
2483
|
{
|
|
2286
|
-
searchIndexWritebackPolicy: "cache",
|
|
2287
2484
|
...options.signal === void 0 ? {} : { signal: options.signal }
|
|
2288
2485
|
}
|
|
2289
2486
|
);
|
|
@@ -2388,6 +2585,7 @@ var WikiGraphArchiveHandle = class {
|
|
|
2388
2585
|
async (document) => {
|
|
2389
2586
|
const chapters = await this.#resolveScope(document, options);
|
|
2390
2587
|
await ensureArchiveSearchIndex(document, {
|
|
2588
|
+
rebuild: true,
|
|
2391
2589
|
...chapters === void 0 ? {} : { chapters },
|
|
2392
2590
|
...embeddingProvider === void 0 ? {} : { embeddingProvider }
|
|
2393
2591
|
});
|
|
@@ -2566,7 +2764,7 @@ var WikiGraphArchiveHandle = class {
|
|
|
2566
2764
|
return await this.#writeDocument(async (document) => {
|
|
2567
2765
|
const chapterId = await resolveChapterPathReadonly(document, path);
|
|
2568
2766
|
await assertChapterResetAllowed(
|
|
2569
|
-
this.#location
|
|
2767
|
+
requireWikiGraphArchiveFile(this.#location),
|
|
2570
2768
|
chapterId,
|
|
2571
2769
|
stage
|
|
2572
2770
|
);
|
|
@@ -2677,15 +2875,11 @@ var WikiGraphArchiveHandle = class {
|
|
|
2677
2875
|
options.queryMode,
|
|
2678
2876
|
options.signal
|
|
2679
2877
|
);
|
|
2680
|
-
const result = await this.#
|
|
2878
|
+
const result = await this.#readDocument(
|
|
2681
2879
|
async (document) => {
|
|
2682
2880
|
const chapters = await this.#resolveQueryChapters(document, options, {
|
|
2683
2881
|
embeddingProvider
|
|
2684
2882
|
});
|
|
2685
|
-
await ensureArchiveSearchIndex(document, {
|
|
2686
|
-
...chapters === void 0 ? {} : { chapters },
|
|
2687
|
-
...embeddingProvider === void 0 ? {} : { embeddingProvider }
|
|
2688
|
-
});
|
|
2689
2883
|
return await listRelatedArchiveObjects(document, objectUri, {
|
|
2690
2884
|
...withoutOperation(options),
|
|
2691
2885
|
...embeddingProvider === void 0 ? {} : { embeddingProvider },
|
|
@@ -2693,7 +2887,6 @@ var WikiGraphArchiveHandle = class {
|
|
|
2693
2887
|
});
|
|
2694
2888
|
},
|
|
2695
2889
|
{
|
|
2696
|
-
searchIndexWritebackPolicy: "cache",
|
|
2697
2890
|
...options.signal === void 0 ? {} : { signal: options.signal }
|
|
2698
2891
|
}
|
|
2699
2892
|
);
|
|
@@ -2737,15 +2930,11 @@ var WikiGraphArchiveHandle = class {
|
|
|
2737
2930
|
options.queryMode,
|
|
2738
2931
|
options.signal
|
|
2739
2932
|
);
|
|
2740
|
-
const result = await this.#
|
|
2933
|
+
const result = await this.#readDocument(
|
|
2741
2934
|
async (document) => {
|
|
2742
2935
|
const chapters = await this.#resolveQueryChapters(document, options, {
|
|
2743
2936
|
embeddingProvider
|
|
2744
2937
|
});
|
|
2745
|
-
await ensureArchiveSearchIndex(document, {
|
|
2746
|
-
...chapters === void 0 ? {} : { chapters },
|
|
2747
|
-
...embeddingProvider === void 0 ? {} : { embeddingProvider }
|
|
2748
|
-
});
|
|
2749
2938
|
return await listArchiveEvidence(document, objectUri, {
|
|
2750
2939
|
...withoutOperation(options),
|
|
2751
2940
|
...embeddingProvider === void 0 ? {} : { embeddingProvider },
|
|
@@ -2753,7 +2942,6 @@ var WikiGraphArchiveHandle = class {
|
|
|
2753
2942
|
});
|
|
2754
2943
|
},
|
|
2755
2944
|
{
|
|
2756
|
-
searchIndexWritebackPolicy: "cache",
|
|
2757
2945
|
...options.signal === void 0 ? {} : { signal: options.signal }
|
|
2758
2946
|
}
|
|
2759
2947
|
);
|
|
@@ -2812,14 +3000,18 @@ var WikiGraphArchiveHandle = class {
|
|
|
2812
3000
|
}, options);
|
|
2813
3001
|
}
|
|
2814
3002
|
async readCover(options = {}) {
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
-
|
|
3003
|
+
return await this.#runtime.run(async () => {
|
|
3004
|
+
if (this.#location.archiveFile.kind === "directory") {
|
|
3005
|
+
return await this.#readDocument(
|
|
3006
|
+
async (document) => await document.readCover()
|
|
3007
|
+
);
|
|
3008
|
+
}
|
|
3009
|
+
const app = new WikiGraph2({});
|
|
3010
|
+
return await app.openSession(
|
|
2818
3011
|
this.#location.archiveFile,
|
|
2819
3012
|
async (archive) => await archive.readCover()
|
|
2820
|
-
)
|
|
2821
|
-
|
|
2822
|
-
);
|
|
3013
|
+
);
|
|
3014
|
+
}, options.signal);
|
|
2823
3015
|
}
|
|
2824
3016
|
async replaceMetadata(objectPath, value, options = {}) {
|
|
2825
3017
|
return await this.#writeDocument(async (document) => {
|
|
@@ -2860,10 +3052,14 @@ var WikiGraphArchiveHandle = class {
|
|
|
2860
3052
|
}
|
|
2861
3053
|
async #readDocument(operation, options = {}) {
|
|
2862
3054
|
return await this.#runtime.run(
|
|
2863
|
-
async () =>
|
|
2864
|
-
|
|
2865
|
-
)
|
|
3055
|
+
async () => this.#location.archiveFile.kind === "directory" ? await new WikiGraphDirectoryFile2(
|
|
3056
|
+
this.#location.archiveFile
|
|
3057
|
+
).readDocument(operation) : await new WikiGraphArchiveFile2(
|
|
3058
|
+
this.#location.archiveFile
|
|
3059
|
+
).readDocument(operation),
|
|
2866
3060
|
options.signal
|
|
3061
|
+
).catch(
|
|
3062
|
+
(error) => rethrowArchiveSchemaError(error, this.#location.target)
|
|
2867
3063
|
);
|
|
2868
3064
|
}
|
|
2869
3065
|
async #writeDocument(operation, options = {}) {
|
|
@@ -2875,33 +3071,32 @@ var WikiGraphArchiveHandle = class {
|
|
|
2875
3071
|
searchIndexWritebackPolicy: options.searchIndexWritebackPolicy
|
|
2876
3072
|
}
|
|
2877
3073
|
});
|
|
2878
|
-
}, options.signal)
|
|
3074
|
+
}, options.signal).catch(
|
|
3075
|
+
(error) => rethrowArchiveSchemaError(error, this.#location.target)
|
|
3076
|
+
);
|
|
2879
3077
|
}
|
|
2880
3078
|
async #resolveScope(document, options) {
|
|
2881
3079
|
if (options.chapters !== void 0) return options.chapters;
|
|
2882
3080
|
return (await resolveArchiveScope(document, this.objectUri, options.depth))?.chapterIds;
|
|
2883
3081
|
}
|
|
2884
3082
|
async #resolveQueryChapters(document, options, capabilities) {
|
|
2885
|
-
const
|
|
3083
|
+
const parsed = parseChapterScopePath(this.objectUri);
|
|
3084
|
+
const chapters = options.chapters ?? (parsed === void 0 || parsed.kind === "collection" && options.depth === void 0 ? void 0 : await resolveIndexedArchiveChapterScope(
|
|
3085
|
+
document,
|
|
3086
|
+
parsed.kind === "chapter" ? parsed.chapterPath : void 0,
|
|
3087
|
+
options.depth
|
|
3088
|
+
));
|
|
2886
3089
|
const coverageOptions = {
|
|
2887
3090
|
...chapters === void 0 ? {} : { chapters },
|
|
2888
3091
|
...capabilities.embeddingProvider === void 0 ? {} : { embeddingProvider: capabilities.embeddingProvider },
|
|
2889
3092
|
requireEmbeddingProvider: true,
|
|
2890
3093
|
...options.queryMode === void 0 ? {} : { queryMode: options.queryMode }
|
|
2891
3094
|
};
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
}
|
|
2896
|
-
const queryable = await listArchiveQueryableChapterIds(document, {
|
|
2897
|
-
...coverageOptions
|
|
3095
|
+
await assertArchiveQueryReady(document, {
|
|
3096
|
+
...coverageOptions,
|
|
3097
|
+
...options.skipUnindexed === void 0 ? {} : { skipUnindexed: options.skipUnindexed }
|
|
2898
3098
|
});
|
|
2899
|
-
|
|
2900
|
-
throw new Error(
|
|
2901
|
-
"Wiki Graph query is not ready. No chapters in this scope have a current FTS artifact or source embedding artifact."
|
|
2902
|
-
);
|
|
2903
|
-
}
|
|
2904
|
-
return queryable;
|
|
3099
|
+
return chapters;
|
|
2905
3100
|
}
|
|
2906
3101
|
async #resolveQueryEmbeddingProvider(queryMode, signal) {
|
|
2907
3102
|
if (queryMode === "fts") return void 0;
|
|
@@ -2920,6 +3115,10 @@ var WikiGraphArchiveHandle = class {
|
|
|
2920
3115
|
async function ensureArchiveSearchIndex(document, options = {}) {
|
|
2921
3116
|
const scope = options.chapters === void 0 ? {} : { chapters: options.chapters };
|
|
2922
3117
|
if (await isArchiveSearchIndexCurrent2(document, scope)) return;
|
|
3118
|
+
if (options.rebuild !== true)
|
|
3119
|
+
throw new Error(
|
|
3120
|
+
"Archive search index is missing or dirty. Run `wg <archive-uri>/index sync` explicitly before querying."
|
|
3121
|
+
);
|
|
2923
3122
|
await rebuildArchiveSearchIndex(document, void 0, {
|
|
2924
3123
|
...scope,
|
|
2925
3124
|
...options.embeddingProvider === void 0 ? {} : { embeddingProvider: options.embeddingProvider }
|