wiki-graph-sdk 0.9.4 → 0.9.5

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.
Files changed (52) hide show
  1. package/dist/archives.cjs +237 -28
  2. package/dist/archives.cjs.map +1 -1
  3. package/dist/archives.d.ts +1 -1
  4. package/dist/archives.js +240 -28
  5. package/dist/archives.js.map +1 -1
  6. package/dist/conversions.cjs +64 -28
  7. package/dist/conversions.cjs.map +1 -1
  8. package/dist/conversions.js +64 -28
  9. package/dist/conversions.js.map +1 -1
  10. package/dist/default-worker.cjs +64 -28
  11. package/dist/default-worker.cjs.map +1 -1
  12. package/dist/default-worker.js +64 -28
  13. package/dist/default-worker.js.map +1 -1
  14. package/dist/embedding.cjs +64 -28
  15. package/dist/embedding.cjs.map +1 -1
  16. package/dist/embedding.js +64 -28
  17. package/dist/embedding.js.map +1 -1
  18. package/dist/gc.cjs +64 -28
  19. package/dist/gc.cjs.map +1 -1
  20. package/dist/gc.js +64 -28
  21. package/dist/gc.js.map +1 -1
  22. package/dist/{index-DQzLAnjf.d.ts → index-4YX4dv6Y.d.ts} +38 -2
  23. package/dist/index.cjs +240 -31
  24. package/dist/index.cjs.map +1 -1
  25. package/dist/index.d.ts +3 -3
  26. package/dist/index.js +243 -31
  27. package/dist/index.js.map +1 -1
  28. package/dist/local-config.cjs +64 -28
  29. package/dist/local-config.cjs.map +1 -1
  30. package/dist/local-config.js +64 -28
  31. package/dist/local-config.js.map +1 -1
  32. package/dist/maintenance.cjs +64 -28
  33. package/dist/maintenance.cjs.map +1 -1
  34. package/dist/maintenance.js +64 -28
  35. package/dist/maintenance.js.map +1 -1
  36. package/dist/node-platform.cjs +64 -28
  37. package/dist/node-platform.cjs.map +1 -1
  38. package/dist/node-platform.js +64 -28
  39. package/dist/node-platform.js.map +1 -1
  40. package/dist/runtime-config.cjs +64 -28
  41. package/dist/runtime-config.cjs.map +1 -1
  42. package/dist/runtime-config.js +64 -28
  43. package/dist/runtime-config.js.map +1 -1
  44. package/dist/stage.cjs +64 -28
  45. package/dist/stage.cjs.map +1 -1
  46. package/dist/stage.js +64 -28
  47. package/dist/stage.js.map +1 -1
  48. package/dist/worker.cjs +64 -28
  49. package/dist/worker.cjs.map +1 -1
  50. package/dist/worker.js +64 -28
  51. package/dist/worker.js.map +1 -1
  52. package/package.json +2 -2
package/dist/archives.cjs CHANGED
@@ -46,6 +46,7 @@ var import_os3 = require("os");
46
46
  var import_path5 = require("path");
47
47
  var import_stream = require("stream");
48
48
  var import_wiki_graph_core7 = require("wiki-graph-core");
49
+ var import_platform2 = require("wiki-graph-core/platform");
49
50
 
50
51
  // src/conversions.ts
51
52
  var import_crypto = require("crypto");
@@ -152,7 +153,7 @@ var NodeFile = class {
152
153
  }
153
154
  path;
154
155
  async getPhysicalIdentity() {
155
- const value = await fsPromises.stat(this.path).catch((error) => {
156
+ const value = await fsPromises.stat(toNodeFilesystemPath(this.path)).catch((error) => {
156
157
  if (typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT")
157
158
  return void 0;
158
159
  throw error;
@@ -165,7 +166,7 @@ var NodeFile = class {
165
166
  identity;
166
167
  name;
167
168
  async openReader() {
168
- const handle = await fsPromises.open(this.path, "r");
169
+ const handle = await fsPromises.open(toNodeFilesystemPath(this.path), "r");
169
170
  let closed = false;
170
171
  try {
171
172
  const stats = await handle.stat();
@@ -205,7 +206,7 @@ var NodeFile = class {
205
206
  }
206
207
  async getLastModified() {
207
208
  try {
208
- return (await fsPromises.stat(this.path)).mtimeMs;
209
+ return (await fsPromises.stat(toNodeFilesystemPath(this.path))).mtimeMs;
209
210
  } catch (error) {
210
211
  if (typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT") {
211
212
  return void 0;
@@ -214,9 +215,14 @@ var NodeFile = class {
214
215
  }
215
216
  }
216
217
  async openWriter() {
217
- await fsPromises.mkdir(pathModule.dirname(this.path), { recursive: true });
218
+ await fsPromises.mkdir(
219
+ toNodeFilesystemPath(pathModule.dirname(this.path)),
220
+ {
221
+ recursive: true
222
+ }
223
+ );
218
224
  const temporary = `${this.path}.tmp-${crypto.randomUUID()}`;
219
- const handle = await fsPromises.open(temporary, "wx");
225
+ const handle = await fsPromises.open(toNodeFilesystemPath(temporary), "wx");
220
226
  let closed = false;
221
227
  return {
222
228
  write: async (data) => {
@@ -231,14 +237,17 @@ var NodeFile = class {
231
237
  commit: async () => {
232
238
  if (!closed) {
233
239
  await handle.close();
234
- await fsPromises.rename(temporary, this.path);
240
+ await fsPromises.rename(
241
+ toNodeFilesystemPath(temporary),
242
+ toNodeFilesystemPath(this.path)
243
+ );
235
244
  }
236
245
  closed = true;
237
246
  },
238
247
  abort: async () => {
239
248
  if (!closed) {
240
249
  await handle.close();
241
- await fsPromises.rm(temporary, { force: true });
250
+ await fsPromises.rm(toNodeFilesystemPath(temporary), { force: true });
242
251
  }
243
252
  closed = true;
244
253
  }
@@ -285,7 +294,7 @@ var NodeDirectory = class _NodeDirectory {
285
294
  }
286
295
  path;
287
296
  async getPhysicalIdentity() {
288
- const value = await fsPromises.stat(this.path).catch((error) => {
297
+ const value = await fsPromises.stat(toNodeFilesystemPath(this.path)).catch((error) => {
289
298
  if (typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT")
290
299
  return void 0;
291
300
  throw error;
@@ -301,7 +310,7 @@ var NodeDirectory = class _NodeDirectory {
301
310
  assertChildName(name);
302
311
  const file = new NodeFile(pathModule.join(this.path, name));
303
312
  try {
304
- return (await fsPromises.stat(file.path)).isFile() ? file : void 0;
313
+ return (await fsPromises.stat(toNodeFilesystemPath(file.path))).isFile() ? file : void 0;
305
314
  } catch (error) {
306
315
  if (typeof error === "object" && error !== null && "code" in error && (error.code === "ENOENT" || error.code === "ENOTDIR"))
307
316
  return void 0;
@@ -310,7 +319,7 @@ var NodeDirectory = class _NodeDirectory {
310
319
  }
311
320
  async getLastModified() {
312
321
  try {
313
- return (await fsPromises.stat(this.path)).mtimeMs;
322
+ return (await fsPromises.stat(toNodeFilesystemPath(this.path))).mtimeMs;
314
323
  } catch (error) {
315
324
  if (typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT") {
316
325
  return void 0;
@@ -322,7 +331,7 @@ var NodeDirectory = class _NodeDirectory {
322
331
  assertChildName(name);
323
332
  const directory = new _NodeDirectory(pathModule.join(this.path, name));
324
333
  try {
325
- return (await fsPromises.stat(directory.path)).isDirectory() ? directory : void 0;
334
+ return (await fsPromises.stat(toNodeFilesystemPath(directory.path))).isDirectory() ? directory : void 0;
326
335
  } catch (error) {
327
336
  if (typeof error === "object" && error !== null && "code" in error && (error.code === "ENOENT" || error.code === "ENOTDIR"))
328
337
  return void 0;
@@ -330,7 +339,7 @@ var NodeDirectory = class _NodeDirectory {
330
339
  }
331
340
  }
332
341
  async list() {
333
- const entries = await fsPromises.readdir(this.path, {
342
+ const entries = await fsPromises.readdir(toNodeFilesystemPath(this.path), {
334
343
  withFileTypes: true
335
344
  });
336
345
  return entries.map(
@@ -339,26 +348,45 @@ var NodeDirectory = class _NodeDirectory {
339
348
  }
340
349
  async createFile(name) {
341
350
  assertChildName(name);
342
- await fsPromises.mkdir(this.path, { recursive: true });
351
+ await fsPromises.mkdir(toNodeFilesystemPath(this.path), {
352
+ recursive: true
353
+ });
343
354
  const file = new NodeFile(pathModule.join(this.path, name));
344
- await fsPromises.writeFile(file.path, "", { flag: "wx" });
355
+ await fsPromises.writeFile(toNodeFilesystemPath(file.path), "", {
356
+ flag: "wx"
357
+ });
345
358
  return file;
346
359
  }
347
360
  async createDirectory(name) {
348
361
  assertChildName(name);
349
- await fsPromises.mkdir(this.path, { recursive: true });
362
+ await fsPromises.mkdir(toNodeFilesystemPath(this.path), {
363
+ recursive: true
364
+ });
350
365
  const directory = new _NodeDirectory(pathModule.join(this.path, name));
351
- await fsPromises.mkdir(directory.path);
366
+ await fsPromises.mkdir(toNodeFilesystemPath(directory.path));
352
367
  return directory;
353
368
  }
354
369
  async remove(name, options) {
355
370
  assertChildName(name);
356
- await fsPromises.rm(pathModule.join(this.path, name), {
357
- force: true,
358
- recursive: options?.recursive === true
359
- });
371
+ await fsPromises.rm(
372
+ toNodeFilesystemPath(pathModule.join(this.path, name)),
373
+ {
374
+ force: true,
375
+ recursive: options?.recursive === true
376
+ }
377
+ );
360
378
  }
361
379
  };
380
+ function toNodeFilesystemPath(path) {
381
+ if (nodeProcess.platform !== "win32" || path.startsWith("\\\\?\\")) {
382
+ return path;
383
+ }
384
+ const absolute = pathModule.resolve(path);
385
+ if (absolute.startsWith("\\\\")) {
386
+ return `\\\\?\\UNC\\${absolute.slice(2)}`;
387
+ }
388
+ return `\\\\?\\${absolute}`;
389
+ }
362
390
  function encodeNodeResourceIdentity(kind, path) {
363
391
  return `node-${kind}:${Buffer.from(pathModule.resolve(path), "utf8").toString("base64url")}`;
364
392
  }
@@ -444,10 +472,14 @@ async function openNativeNodeDatabase(file, flags) {
444
472
  throw new TypeError("The Node database adapter requires a NodeFile");
445
473
  }
446
474
  return await new Promise((resolve4, reject) => {
447
- const database = new nodeSqlite3.Database(path, flags, (error) => {
448
- if (error) reject(error);
449
- else resolve4(database);
450
- });
475
+ const database = new nodeSqlite3.Database(
476
+ toNodeFilesystemPath(path),
477
+ flags,
478
+ (error) => {
479
+ if (error) reject(error);
480
+ else resolve4(database);
481
+ }
482
+ );
451
483
  });
452
484
  }
453
485
  async function openNodeZip(file, options = {}) {
@@ -455,7 +487,7 @@ async function openNodeZip(file, options = {}) {
455
487
  if (path === void 0) {
456
488
  throw new TypeError("The Node ZIP adapter requires a NodeFile");
457
489
  }
458
- const handle = await fsPromises.open(path, "r");
490
+ const handle = await fsPromises.open(toNodeFilesystemPath(path), "r");
459
491
  let size;
460
492
  try {
461
493
  size = (await handle.stat()).size;
@@ -770,6 +802,11 @@ async function writeNodeZip(file, entries) {
770
802
  }
771
803
  }
772
804
  async function addNodeZipEntries(zipFile, iterator, state) {
805
+ const stableZipOptions = {
806
+ compress: false,
807
+ forceDosTimestamp: true,
808
+ mtime: new Date(1980, 0, 2)
809
+ };
773
810
  while (!state.cancelled) {
774
811
  const result = await iterator.next();
775
812
  if (state.cancelled) return;
@@ -781,17 +818,17 @@ async function addNodeZipEntries(zipFile, iterator, state) {
781
818
  zipFile.addReadStream(
782
819
  createNodeFileReadStream(result.value.file),
783
820
  result.value.name,
784
- { compress: false }
821
+ stableZipOptions
785
822
  );
786
823
  } else if ("data" in result.value) {
787
824
  zipFile.addBuffer(Buffer.from(result.value.data), result.value.name, {
788
- compress: false
825
+ ...stableZipOptions
789
826
  });
790
827
  } else {
791
828
  zipFile.addReadStream(
792
829
  createNodeRangeReadStream(result.value),
793
830
  result.value.name,
794
- { compress: false, size: result.value.size }
831
+ { ...stableZipOptions, size: result.value.size }
795
832
  );
796
833
  }
797
834
  }
@@ -2390,6 +2427,18 @@ var WikiGraphArchiveManager = class {
2390
2427
  }, options.signal);
2391
2428
  return new WikiGraphArchiveHandle(this.#runtime, location);
2392
2429
  }
2430
+ async inspectSchema(target, options = {}) {
2431
+ return await this.#runtime.run(
2432
+ async () => ({
2433
+ schemaVersion: await (0, import_wiki_graph_core7.readWikiGraphArchiveSchemaVersion)(
2434
+ await resolveWikiGraphArchiveLocation(target).then(
2435
+ (location) => location.archiveFile
2436
+ )
2437
+ )
2438
+ }),
2439
+ options.signal
2440
+ );
2441
+ }
2393
2442
  };
2394
2443
  var WikiGraphArchiveHandle = class {
2395
2444
  #runtime;
@@ -2416,6 +2465,19 @@ var WikiGraphArchiveHandle = class {
2416
2465
  get target() {
2417
2466
  return this.#location.target;
2418
2467
  }
2468
+ /** Export this archive through the SDK without exposing core file adapters. */
2469
+ async export(path) {
2470
+ return await this.#runtime.run(async () => {
2471
+ const outputPath = await assertStandaloneWikiGraphArchivePath(path);
2472
+ const output = new NodeFile(outputPath);
2473
+ if (this.#location.archiveFile.kind === "directory") {
2474
+ await (0, import_wiki_graph_core7.writeWikgArchive)(this.#location.archiveFile, output);
2475
+ } else {
2476
+ await (0, import_platform2.copyFileContent)(this.#location.archiveFile, output);
2477
+ }
2478
+ return { path: outputPath };
2479
+ });
2480
+ }
2419
2481
  async #persistCursor(cursor) {
2420
2482
  return await this.#runtime.run(
2421
2483
  async () => await (0, import_wiki_graph_core7.createContinuationCursor)(cursor)
@@ -2948,6 +3010,38 @@ var WikiGraphArchiveHandle = class {
2948
3010
  options
2949
3011
  );
2950
3012
  }
3013
+ /** Read archive-level data without exposing the underlying Core reader. */
3014
+ async readOverview(options = {}) {
3015
+ return await this.#readDocument(async (document) => {
3016
+ const [metadata, cover, toc] = await Promise.all([
3017
+ document.readBookMeta(),
3018
+ document.readCover(),
3019
+ document.readToc()
3020
+ ]);
3021
+ const serials = toc === void 0 ? [] : await collectArchiveSerials(document, toc.items);
3022
+ return {
3023
+ ...metadata === void 0 ? {} : { metadata },
3024
+ ...cover === void 0 ? {} : { cover },
3025
+ ...toc === void 0 ? {} : { toc },
3026
+ serials
3027
+ };
3028
+ }, options);
3029
+ }
3030
+ /** Read a chapter and expose its graph as the stable WikgObject stream. */
3031
+ async readChapterData(serialId, options = {}) {
3032
+ const result = await this.#readDocument(async (document) => {
3033
+ const [chapter, summary] = await Promise.all([
3034
+ (0, import_wiki_graph_core7.getChapterDetails)(document, serialId),
3035
+ document.readSummary(serialId)
3036
+ ]);
3037
+ return { chapter, summary };
3038
+ }, options);
3039
+ return {
3040
+ chapter: result.chapter,
3041
+ ...result.summary === void 0 ? {} : { summary: result.summary },
3042
+ objects: this.#readChapterObjects(serialId, options)
3043
+ };
3044
+ }
2951
3045
  async replaceBookMeta(meta, options = {}) {
2952
3046
  return await this.#writeDocument(async (document) => {
2953
3047
  await document.replaceBookMeta(meta);
@@ -3035,6 +3129,33 @@ var WikiGraphArchiveHandle = class {
3035
3129
  (error) => rethrowArchiveSchemaError(error, this.#location.target)
3036
3130
  );
3037
3131
  }
3132
+ async *#readChapterObjects(serialId, options) {
3133
+ const queue = createAsyncValueQueue();
3134
+ const producer = this.#readDocument(async (document) => {
3135
+ try {
3136
+ for await (const object of (0, import_wiki_graph_core7.createChapterReadingGraphObjectStream)({
3137
+ chapterId: serialId,
3138
+ document
3139
+ })) {
3140
+ if (!await queue.push(object)) break;
3141
+ }
3142
+ queue.end();
3143
+ } catch (error) {
3144
+ queue.fail(error);
3145
+ throw error;
3146
+ }
3147
+ }, options).catch((error) => {
3148
+ queue.fail(error);
3149
+ throw error;
3150
+ });
3151
+ try {
3152
+ for await (const object of queue) yield object;
3153
+ await producer;
3154
+ } finally {
3155
+ queue.cancel();
3156
+ await producer.catch(() => void 0);
3157
+ }
3158
+ }
3038
3159
  async #writeDocument(operation, options = {}) {
3039
3160
  return await this.#runtime.run(async () => {
3040
3161
  return await writeWikiGraphArchiveLocation(this.#location, operation, {
@@ -3229,6 +3350,94 @@ function requireChapter(chapters, chapterId) {
3229
3350
  function asTextStream(text) {
3230
3351
  return import_stream.Readable.from([text]);
3231
3352
  }
3353
+ async function collectArchiveSerials(document, items, ancestorTitles = []) {
3354
+ const entries = [];
3355
+ for (const item of items) {
3356
+ const title = item.title?.trim() || `Chapter ${item.serialId ?? "group"}`;
3357
+ const tocPath = [...ancestorTitles, title];
3358
+ if (item.serialId !== void 0) {
3359
+ entries.push({
3360
+ fragmentCount: (await document.getSerialFragments(item.serialId).listFragmentIds()).length,
3361
+ serialId: item.serialId,
3362
+ title,
3363
+ tocPath
3364
+ });
3365
+ }
3366
+ entries.push(
3367
+ ...await collectArchiveSerials(document, item.children, tocPath)
3368
+ );
3369
+ }
3370
+ return entries;
3371
+ }
3372
+ function createAsyncValueQueue() {
3373
+ const values = [];
3374
+ const readers = [];
3375
+ const writers = [];
3376
+ let cancelled = false;
3377
+ let ended = false;
3378
+ let failure;
3379
+ const settleReaders = () => {
3380
+ while (readers.length > 0) {
3381
+ const reader = readers.shift();
3382
+ if (failure !== void 0) reader.reject(failure);
3383
+ else if (values.length > 0) {
3384
+ reader.resolve({ done: false, value: values.shift() });
3385
+ writers.shift()?.();
3386
+ } else if (ended) reader.resolve({ done: true, value: void 0 });
3387
+ else {
3388
+ readers.unshift(reader);
3389
+ return;
3390
+ }
3391
+ }
3392
+ };
3393
+ return {
3394
+ [Symbol.asyncIterator]: () => ({
3395
+ next: async () => {
3396
+ if (failure !== void 0) throw failure;
3397
+ if (values.length > 0) {
3398
+ const value = values.shift();
3399
+ writers.shift()?.();
3400
+ return { done: false, value };
3401
+ }
3402
+ if (ended) return { done: true, value: void 0 };
3403
+ return await new Promise((resolve4, reject) => {
3404
+ readers.push({ reject, resolve: resolve4 });
3405
+ });
3406
+ }
3407
+ }),
3408
+ cancel: () => {
3409
+ cancelled = true;
3410
+ ended = true;
3411
+ values.length = 0;
3412
+ while (writers.length > 0) writers.shift()();
3413
+ settleReaders();
3414
+ },
3415
+ end: () => {
3416
+ ended = true;
3417
+ settleReaders();
3418
+ },
3419
+ fail: (error) => {
3420
+ failure = error instanceof Error ? error : new Error(String(error));
3421
+ ended = true;
3422
+ values.length = 0;
3423
+ while (writers.length > 0) writers.shift()();
3424
+ settleReaders();
3425
+ },
3426
+ push: async (value) => {
3427
+ if (cancelled || ended || failure !== void 0) return false;
3428
+ if (readers.length > 0) {
3429
+ readers.shift().resolve({ done: false, value });
3430
+ return true;
3431
+ }
3432
+ if (values.length > 0) {
3433
+ await new Promise((resolve4) => writers.push(resolve4));
3434
+ if (cancelled || ended || failure !== void 0) return false;
3435
+ }
3436
+ values.push(value);
3437
+ return true;
3438
+ }
3439
+ };
3440
+ }
3232
3441
  async function assertChapterResetAllowed(archive, chapterId, stage) {
3233
3442
  if (stage === "planned") {
3234
3443
  await (0, import_wiki_graph_core7.assertNoActiveBuildJobs)({