wiki-graph-sdk 0.9.3 → 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 +241 -29
  2. package/dist/archives.cjs.map +1 -1
  3. package/dist/archives.d.ts +1 -1
  4. package/dist/archives.js +245 -29
  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 +244 -32
  24. package/dist/index.cjs.map +1 -1
  25. package/dist/index.d.ts +3 -3
  26. package/dist/index.js +248 -32
  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
@@ -1,4 +1,4 @@
1
- export { h as WikiGraphArchiveChapterInspection, i as WikiGraphArchiveCover, j as WikiGraphArchiveCreateOptions, k as WikiGraphArchiveCreateResult, l as WikiGraphArchiveEvidenceOptions, m as WikiGraphArchiveExistsError, n as WikiGraphArchiveHandle, o as WikiGraphArchiveIndexArtifactInspection, p as WikiGraphArchiveIndexStatus, q as WikiGraphArchiveIndexSyncOptions, r as WikiGraphArchiveInspection, s as WikiGraphArchiveListOptions, W as WikiGraphArchiveManager, t as WikiGraphArchivePageOptions, u as WikiGraphArchiveRelatedOptions, v as WikiGraphArchiveScope, w as WikiGraphArchiveScopeOptions, x as WikiGraphArchiveSearchOptions, y as WikiGraphArchiveWriteOptions, z as WikiGraphChapterArtifactStatus, B as WikiGraphChapterMoveOptions, D as WikiGraphChapterResetStage, E as WikiGraphChapterSourceOptions, F as WikiGraphChapterTreeInput, G as WikiGraphOperationOptions, S as inspectWikiGraphArchive } from './index-DQzLAnjf.js';
1
+ export { h as WikiGraphArchiveChapterData, i as WikiGraphArchiveChapterInspection, j as WikiGraphArchiveCover, k as WikiGraphArchiveCreateOptions, l as WikiGraphArchiveCreateResult, m as WikiGraphArchiveEvidenceOptions, n as WikiGraphArchiveExistsError, o as WikiGraphArchiveExportResult, p as WikiGraphArchiveHandle, q as WikiGraphArchiveIndexArtifactInspection, r as WikiGraphArchiveIndexStatus, s as WikiGraphArchiveIndexSyncOptions, t as WikiGraphArchiveInspection, u as WikiGraphArchiveListOptions, W as WikiGraphArchiveManager, v as WikiGraphArchiveOverview, w as WikiGraphArchivePageOptions, x as WikiGraphArchiveRelatedOptions, y as WikiGraphArchiveSchemaInspection, z as WikiGraphArchiveScope, B as WikiGraphArchiveScopeOptions, D as WikiGraphArchiveSearchOptions, E as WikiGraphArchiveTocFile, F as WikiGraphArchiveTocItem, G as WikiGraphArchiveWriteOptions, H as WikiGraphChapterArtifactStatus, J as WikiGraphChapterMoveOptions, K as WikiGraphChapterResetStage, M as WikiGraphChapterSourceOptions, N as WikiGraphChapterTreeInput, O as WikiGraphOperationOptions, Z as inspectWikiGraphArchive } from './index-4YX4dv6Y.js';
2
2
  export { a as WikiGraphArchiveOwnershipError, W as WikiGraphArchiveTarget } from './target-CZ7elwmj.js';
3
3
  import 'wiki-graph-core';
4
4
  import './jobs-CRK-DZ40.js';
package/dist/archives.js CHANGED
@@ -14,10 +14,12 @@ import {
14
14
  assertArchiveQueryReady,
15
15
  resolveIndexedArchiveChapterScope,
16
16
  ensureWikiGraphArchiveSchemaCurrent,
17
+ readWikiGraphArchiveSchemaVersion,
17
18
  assertNoActiveBuildJobConflicts,
18
19
  assertNoActiveBuildJobs,
19
20
  deleteArchiveSearchSessions,
20
21
  createContinuationCursor,
22
+ createChapterReadingGraphObjectStream,
21
23
  deleteContinuationCursor,
22
24
  DirectoryDocument,
23
25
  findArchiveObjects,
@@ -43,13 +45,16 @@ import {
43
45
  setChapterSummary,
44
46
  setChapterTitle,
45
47
  getChapterTree,
48
+ getChapterDetails,
46
49
  WikiGraph as WikiGraph2,
47
50
  WikiGraphArchiveFile as WikiGraphArchiveFile2,
48
51
  WikiGraphDirectoryFile as WikiGraphDirectoryFile2,
52
+ WikgCoordinator,
49
53
  TOC_FILE_VERSION,
50
54
  writeWikgArchive,
51
55
  ObjectMetadataKind
52
56
  } from "wiki-graph-core";
57
+ import { copyFileContent } from "wiki-graph-core/platform";
53
58
 
54
59
  // src/conversions.ts
55
60
  import { createHash } from "crypto";
@@ -165,7 +170,7 @@ var NodeFile = class {
165
170
  }
166
171
  path;
167
172
  async getPhysicalIdentity() {
168
- const value = await fsPromises.stat(this.path).catch((error) => {
173
+ const value = await fsPromises.stat(toNodeFilesystemPath(this.path)).catch((error) => {
169
174
  if (typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT")
170
175
  return void 0;
171
176
  throw error;
@@ -178,7 +183,7 @@ var NodeFile = class {
178
183
  identity;
179
184
  name;
180
185
  async openReader() {
181
- const handle = await fsPromises.open(this.path, "r");
186
+ const handle = await fsPromises.open(toNodeFilesystemPath(this.path), "r");
182
187
  let closed = false;
183
188
  try {
184
189
  const stats = await handle.stat();
@@ -218,7 +223,7 @@ var NodeFile = class {
218
223
  }
219
224
  async getLastModified() {
220
225
  try {
221
- return (await fsPromises.stat(this.path)).mtimeMs;
226
+ return (await fsPromises.stat(toNodeFilesystemPath(this.path))).mtimeMs;
222
227
  } catch (error) {
223
228
  if (typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT") {
224
229
  return void 0;
@@ -227,9 +232,14 @@ var NodeFile = class {
227
232
  }
228
233
  }
229
234
  async openWriter() {
230
- await fsPromises.mkdir(pathModule.dirname(this.path), { recursive: true });
235
+ await fsPromises.mkdir(
236
+ toNodeFilesystemPath(pathModule.dirname(this.path)),
237
+ {
238
+ recursive: true
239
+ }
240
+ );
231
241
  const temporary = `${this.path}.tmp-${crypto.randomUUID()}`;
232
- const handle = await fsPromises.open(temporary, "wx");
242
+ const handle = await fsPromises.open(toNodeFilesystemPath(temporary), "wx");
233
243
  let closed = false;
234
244
  return {
235
245
  write: async (data) => {
@@ -244,14 +254,17 @@ var NodeFile = class {
244
254
  commit: async () => {
245
255
  if (!closed) {
246
256
  await handle.close();
247
- await fsPromises.rename(temporary, this.path);
257
+ await fsPromises.rename(
258
+ toNodeFilesystemPath(temporary),
259
+ toNodeFilesystemPath(this.path)
260
+ );
248
261
  }
249
262
  closed = true;
250
263
  },
251
264
  abort: async () => {
252
265
  if (!closed) {
253
266
  await handle.close();
254
- await fsPromises.rm(temporary, { force: true });
267
+ await fsPromises.rm(toNodeFilesystemPath(temporary), { force: true });
255
268
  }
256
269
  closed = true;
257
270
  }
@@ -298,7 +311,7 @@ var NodeDirectory = class _NodeDirectory {
298
311
  }
299
312
  path;
300
313
  async getPhysicalIdentity() {
301
- const value = await fsPromises.stat(this.path).catch((error) => {
314
+ const value = await fsPromises.stat(toNodeFilesystemPath(this.path)).catch((error) => {
302
315
  if (typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT")
303
316
  return void 0;
304
317
  throw error;
@@ -314,7 +327,7 @@ var NodeDirectory = class _NodeDirectory {
314
327
  assertChildName(name);
315
328
  const file = new NodeFile(pathModule.join(this.path, name));
316
329
  try {
317
- return (await fsPromises.stat(file.path)).isFile() ? file : void 0;
330
+ return (await fsPromises.stat(toNodeFilesystemPath(file.path))).isFile() ? file : void 0;
318
331
  } catch (error) {
319
332
  if (typeof error === "object" && error !== null && "code" in error && (error.code === "ENOENT" || error.code === "ENOTDIR"))
320
333
  return void 0;
@@ -323,7 +336,7 @@ var NodeDirectory = class _NodeDirectory {
323
336
  }
324
337
  async getLastModified() {
325
338
  try {
326
- return (await fsPromises.stat(this.path)).mtimeMs;
339
+ return (await fsPromises.stat(toNodeFilesystemPath(this.path))).mtimeMs;
327
340
  } catch (error) {
328
341
  if (typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT") {
329
342
  return void 0;
@@ -335,7 +348,7 @@ var NodeDirectory = class _NodeDirectory {
335
348
  assertChildName(name);
336
349
  const directory = new _NodeDirectory(pathModule.join(this.path, name));
337
350
  try {
338
- return (await fsPromises.stat(directory.path)).isDirectory() ? directory : void 0;
351
+ return (await fsPromises.stat(toNodeFilesystemPath(directory.path))).isDirectory() ? directory : void 0;
339
352
  } catch (error) {
340
353
  if (typeof error === "object" && error !== null && "code" in error && (error.code === "ENOENT" || error.code === "ENOTDIR"))
341
354
  return void 0;
@@ -343,7 +356,7 @@ var NodeDirectory = class _NodeDirectory {
343
356
  }
344
357
  }
345
358
  async list() {
346
- const entries = await fsPromises.readdir(this.path, {
359
+ const entries = await fsPromises.readdir(toNodeFilesystemPath(this.path), {
347
360
  withFileTypes: true
348
361
  });
349
362
  return entries.map(
@@ -352,26 +365,45 @@ var NodeDirectory = class _NodeDirectory {
352
365
  }
353
366
  async createFile(name) {
354
367
  assertChildName(name);
355
- await fsPromises.mkdir(this.path, { recursive: true });
368
+ await fsPromises.mkdir(toNodeFilesystemPath(this.path), {
369
+ recursive: true
370
+ });
356
371
  const file = new NodeFile(pathModule.join(this.path, name));
357
- await fsPromises.writeFile(file.path, "", { flag: "wx" });
372
+ await fsPromises.writeFile(toNodeFilesystemPath(file.path), "", {
373
+ flag: "wx"
374
+ });
358
375
  return file;
359
376
  }
360
377
  async createDirectory(name) {
361
378
  assertChildName(name);
362
- await fsPromises.mkdir(this.path, { recursive: true });
379
+ await fsPromises.mkdir(toNodeFilesystemPath(this.path), {
380
+ recursive: true
381
+ });
363
382
  const directory = new _NodeDirectory(pathModule.join(this.path, name));
364
- await fsPromises.mkdir(directory.path);
383
+ await fsPromises.mkdir(toNodeFilesystemPath(directory.path));
365
384
  return directory;
366
385
  }
367
386
  async remove(name, options) {
368
387
  assertChildName(name);
369
- await fsPromises.rm(pathModule.join(this.path, name), {
370
- force: true,
371
- recursive: options?.recursive === true
372
- });
388
+ await fsPromises.rm(
389
+ toNodeFilesystemPath(pathModule.join(this.path, name)),
390
+ {
391
+ force: true,
392
+ recursive: options?.recursive === true
393
+ }
394
+ );
373
395
  }
374
396
  };
397
+ function toNodeFilesystemPath(path) {
398
+ if (nodeProcess.platform !== "win32" || path.startsWith("\\\\?\\")) {
399
+ return path;
400
+ }
401
+ const absolute = pathModule.resolve(path);
402
+ if (absolute.startsWith("\\\\")) {
403
+ return `\\\\?\\UNC\\${absolute.slice(2)}`;
404
+ }
405
+ return `\\\\?\\${absolute}`;
406
+ }
375
407
  function encodeNodeResourceIdentity(kind, path) {
376
408
  return `node-${kind}:${Buffer.from(pathModule.resolve(path), "utf8").toString("base64url")}`;
377
409
  }
@@ -457,10 +489,14 @@ async function openNativeNodeDatabase(file, flags) {
457
489
  throw new TypeError("The Node database adapter requires a NodeFile");
458
490
  }
459
491
  return await new Promise((resolve4, reject) => {
460
- const database = new nodeSqlite3.Database(path, flags, (error) => {
461
- if (error) reject(error);
462
- else resolve4(database);
463
- });
492
+ const database = new nodeSqlite3.Database(
493
+ toNodeFilesystemPath(path),
494
+ flags,
495
+ (error) => {
496
+ if (error) reject(error);
497
+ else resolve4(database);
498
+ }
499
+ );
464
500
  });
465
501
  }
466
502
  async function openNodeZip(file, options = {}) {
@@ -468,7 +504,7 @@ async function openNodeZip(file, options = {}) {
468
504
  if (path === void 0) {
469
505
  throw new TypeError("The Node ZIP adapter requires a NodeFile");
470
506
  }
471
- const handle = await fsPromises.open(path, "r");
507
+ const handle = await fsPromises.open(toNodeFilesystemPath(path), "r");
472
508
  let size;
473
509
  try {
474
510
  size = (await handle.stat()).size;
@@ -783,6 +819,11 @@ async function writeNodeZip(file, entries) {
783
819
  }
784
820
  }
785
821
  async function addNodeZipEntries(zipFile, iterator, state) {
822
+ const stableZipOptions = {
823
+ compress: false,
824
+ forceDosTimestamp: true,
825
+ mtime: new Date(1980, 0, 2)
826
+ };
786
827
  while (!state.cancelled) {
787
828
  const result = await iterator.next();
788
829
  if (state.cancelled) return;
@@ -794,17 +835,17 @@ async function addNodeZipEntries(zipFile, iterator, state) {
794
835
  zipFile.addReadStream(
795
836
  createNodeFileReadStream(result.value.file),
796
837
  result.value.name,
797
- { compress: false }
838
+ stableZipOptions
798
839
  );
799
840
  } else if ("data" in result.value) {
800
841
  zipFile.addBuffer(Buffer.from(result.value.data), result.value.name, {
801
- compress: false
842
+ ...stableZipOptions
802
843
  });
803
844
  } else {
804
845
  zipFile.addReadStream(
805
846
  createNodeRangeReadStream(result.value),
806
847
  result.value.name,
807
- { compress: false, size: result.value.size }
848
+ { ...stableZipOptions, size: result.value.size }
808
849
  );
809
850
  }
810
851
  }
@@ -2391,7 +2432,10 @@ var WikiGraphArchiveManager = class {
2391
2432
  });
2392
2433
  }
2393
2434
  if (options.replace === true) {
2394
- await rename2(outputPath, path);
2435
+ await new WikgCoordinator().withExclusiveArchiveReplacement(
2436
+ new NodeFile(path),
2437
+ async () => await rename2(outputPath, path)
2438
+ );
2395
2439
  } else {
2396
2440
  try {
2397
2441
  await link(outputPath, path);
@@ -2420,6 +2464,18 @@ var WikiGraphArchiveManager = class {
2420
2464
  }, options.signal);
2421
2465
  return new WikiGraphArchiveHandle(this.#runtime, location);
2422
2466
  }
2467
+ async inspectSchema(target, options = {}) {
2468
+ return await this.#runtime.run(
2469
+ async () => ({
2470
+ schemaVersion: await readWikiGraphArchiveSchemaVersion(
2471
+ await resolveWikiGraphArchiveLocation(target).then(
2472
+ (location) => location.archiveFile
2473
+ )
2474
+ )
2475
+ }),
2476
+ options.signal
2477
+ );
2478
+ }
2423
2479
  };
2424
2480
  var WikiGraphArchiveHandle = class {
2425
2481
  #runtime;
@@ -2446,6 +2502,19 @@ var WikiGraphArchiveHandle = class {
2446
2502
  get target() {
2447
2503
  return this.#location.target;
2448
2504
  }
2505
+ /** Export this archive through the SDK without exposing core file adapters. */
2506
+ async export(path) {
2507
+ return await this.#runtime.run(async () => {
2508
+ const outputPath = await assertStandaloneWikiGraphArchivePath(path);
2509
+ const output = new NodeFile(outputPath);
2510
+ if (this.#location.archiveFile.kind === "directory") {
2511
+ await writeWikgArchive(this.#location.archiveFile, output);
2512
+ } else {
2513
+ await copyFileContent(this.#location.archiveFile, output);
2514
+ }
2515
+ return { path: outputPath };
2516
+ });
2517
+ }
2449
2518
  async #persistCursor(cursor) {
2450
2519
  return await this.#runtime.run(
2451
2520
  async () => await createContinuationCursor(cursor)
@@ -2978,6 +3047,38 @@ var WikiGraphArchiveHandle = class {
2978
3047
  options
2979
3048
  );
2980
3049
  }
3050
+ /** Read archive-level data without exposing the underlying Core reader. */
3051
+ async readOverview(options = {}) {
3052
+ return await this.#readDocument(async (document) => {
3053
+ const [metadata, cover, toc] = await Promise.all([
3054
+ document.readBookMeta(),
3055
+ document.readCover(),
3056
+ document.readToc()
3057
+ ]);
3058
+ const serials = toc === void 0 ? [] : await collectArchiveSerials(document, toc.items);
3059
+ return {
3060
+ ...metadata === void 0 ? {} : { metadata },
3061
+ ...cover === void 0 ? {} : { cover },
3062
+ ...toc === void 0 ? {} : { toc },
3063
+ serials
3064
+ };
3065
+ }, options);
3066
+ }
3067
+ /** Read a chapter and expose its graph as the stable WikgObject stream. */
3068
+ async readChapterData(serialId, options = {}) {
3069
+ const result = await this.#readDocument(async (document) => {
3070
+ const [chapter, summary] = await Promise.all([
3071
+ getChapterDetails(document, serialId),
3072
+ document.readSummary(serialId)
3073
+ ]);
3074
+ return { chapter, summary };
3075
+ }, options);
3076
+ return {
3077
+ chapter: result.chapter,
3078
+ ...result.summary === void 0 ? {} : { summary: result.summary },
3079
+ objects: this.#readChapterObjects(serialId, options)
3080
+ };
3081
+ }
2981
3082
  async replaceBookMeta(meta, options = {}) {
2982
3083
  return await this.#writeDocument(async (document) => {
2983
3084
  await document.replaceBookMeta(meta);
@@ -3065,6 +3166,33 @@ var WikiGraphArchiveHandle = class {
3065
3166
  (error) => rethrowArchiveSchemaError(error, this.#location.target)
3066
3167
  );
3067
3168
  }
3169
+ async *#readChapterObjects(serialId, options) {
3170
+ const queue = createAsyncValueQueue();
3171
+ const producer = this.#readDocument(async (document) => {
3172
+ try {
3173
+ for await (const object of createChapterReadingGraphObjectStream({
3174
+ chapterId: serialId,
3175
+ document
3176
+ })) {
3177
+ if (!await queue.push(object)) break;
3178
+ }
3179
+ queue.end();
3180
+ } catch (error) {
3181
+ queue.fail(error);
3182
+ throw error;
3183
+ }
3184
+ }, options).catch((error) => {
3185
+ queue.fail(error);
3186
+ throw error;
3187
+ });
3188
+ try {
3189
+ for await (const object of queue) yield object;
3190
+ await producer;
3191
+ } finally {
3192
+ queue.cancel();
3193
+ await producer.catch(() => void 0);
3194
+ }
3195
+ }
3068
3196
  async #writeDocument(operation, options = {}) {
3069
3197
  return await this.#runtime.run(async () => {
3070
3198
  return await writeWikiGraphArchiveLocation(this.#location, operation, {
@@ -3259,6 +3387,94 @@ function requireChapter(chapters, chapterId) {
3259
3387
  function asTextStream(text) {
3260
3388
  return Readable2.from([text]);
3261
3389
  }
3390
+ async function collectArchiveSerials(document, items, ancestorTitles = []) {
3391
+ const entries = [];
3392
+ for (const item of items) {
3393
+ const title = item.title?.trim() || `Chapter ${item.serialId ?? "group"}`;
3394
+ const tocPath = [...ancestorTitles, title];
3395
+ if (item.serialId !== void 0) {
3396
+ entries.push({
3397
+ fragmentCount: (await document.getSerialFragments(item.serialId).listFragmentIds()).length,
3398
+ serialId: item.serialId,
3399
+ title,
3400
+ tocPath
3401
+ });
3402
+ }
3403
+ entries.push(
3404
+ ...await collectArchiveSerials(document, item.children, tocPath)
3405
+ );
3406
+ }
3407
+ return entries;
3408
+ }
3409
+ function createAsyncValueQueue() {
3410
+ const values = [];
3411
+ const readers = [];
3412
+ const writers = [];
3413
+ let cancelled = false;
3414
+ let ended = false;
3415
+ let failure;
3416
+ const settleReaders = () => {
3417
+ while (readers.length > 0) {
3418
+ const reader = readers.shift();
3419
+ if (failure !== void 0) reader.reject(failure);
3420
+ else if (values.length > 0) {
3421
+ reader.resolve({ done: false, value: values.shift() });
3422
+ writers.shift()?.();
3423
+ } else if (ended) reader.resolve({ done: true, value: void 0 });
3424
+ else {
3425
+ readers.unshift(reader);
3426
+ return;
3427
+ }
3428
+ }
3429
+ };
3430
+ return {
3431
+ [Symbol.asyncIterator]: () => ({
3432
+ next: async () => {
3433
+ if (failure !== void 0) throw failure;
3434
+ if (values.length > 0) {
3435
+ const value = values.shift();
3436
+ writers.shift()?.();
3437
+ return { done: false, value };
3438
+ }
3439
+ if (ended) return { done: true, value: void 0 };
3440
+ return await new Promise((resolve4, reject) => {
3441
+ readers.push({ reject, resolve: resolve4 });
3442
+ });
3443
+ }
3444
+ }),
3445
+ cancel: () => {
3446
+ cancelled = true;
3447
+ ended = true;
3448
+ values.length = 0;
3449
+ while (writers.length > 0) writers.shift()();
3450
+ settleReaders();
3451
+ },
3452
+ end: () => {
3453
+ ended = true;
3454
+ settleReaders();
3455
+ },
3456
+ fail: (error) => {
3457
+ failure = error instanceof Error ? error : new Error(String(error));
3458
+ ended = true;
3459
+ values.length = 0;
3460
+ while (writers.length > 0) writers.shift()();
3461
+ settleReaders();
3462
+ },
3463
+ push: async (value) => {
3464
+ if (cancelled || ended || failure !== void 0) return false;
3465
+ if (readers.length > 0) {
3466
+ readers.shift().resolve({ done: false, value });
3467
+ return true;
3468
+ }
3469
+ if (values.length > 0) {
3470
+ await new Promise((resolve4) => writers.push(resolve4));
3471
+ if (cancelled || ended || failure !== void 0) return false;
3472
+ }
3473
+ values.push(value);
3474
+ return true;
3475
+ }
3476
+ };
3477
+ }
3262
3478
  async function assertChapterResetAllowed(archive, chapterId, stage) {
3263
3479
  if (stage === "planned") {
3264
3480
  await assertNoActiveBuildJobs({