wiki-graph-sdk 0.7.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/LICENSE +201 -0
- package/README.md +32 -0
- package/dist/archives.cjs +2799 -0
- package/dist/archives.cjs.map +1 -0
- package/dist/archives.d.ts +249 -0
- package/dist/archives.js +2814 -0
- package/dist/archives.js.map +1 -0
- package/dist/conversions.cjs +1332 -0
- package/dist/conversions.cjs.map +1 -0
- package/dist/conversions.d.ts +37 -0
- package/dist/conversions.js +1308 -0
- package/dist/conversions.js.map +1 -0
- package/dist/data/editor/clue_reviewer.jinja +410 -0
- package/dist/data/editor/clue_reviewer_generator.jinja +428 -0
- package/dist/data/editor/revision_feedback.jinja +5 -0
- package/dist/data/editor/text_compressor.jinja +131 -0
- package/dist/data/guaranteed/response_intent_classifier.jinja +8 -0
- package/dist/data/output/epub/cover.xhtml.jinja +13 -0
- package/dist/data/output/epub/nav.xhtml.jinja +12 -0
- package/dist/data/output/epub/package.opf.xml.jinja +39 -0
- package/dist/data/output/epub/section.xhtml.jinja +12 -0
- package/dist/data/topologization/book_coherence_extraction.jinja +223 -0
- package/dist/data/topologization/chunk_extraction.jinja +233 -0
- package/dist/data/topologization/evidence_choice.jinja +38 -0
- package/dist/data/topologization/translate_chunks.jinja +138 -0
- package/dist/data/topologization/user_focused_extraction.jinja +378 -0
- package/dist/default-worker.cjs +1709 -0
- package/dist/default-worker.cjs.map +1 -0
- package/dist/default-worker.d.ts +10 -0
- package/dist/default-worker.js +1705 -0
- package/dist/default-worker.js.map +1 -0
- package/dist/embedding.cjs +1091 -0
- package/dist/embedding.cjs.map +1 -0
- package/dist/embedding.d.ts +26 -0
- package/dist/embedding.js +1062 -0
- package/dist/embedding.js.map +1 -0
- package/dist/entry-context.cjs +91 -0
- package/dist/entry-context.cjs.map +1 -0
- package/dist/entry-context.d.ts +20 -0
- package/dist/entry-context.js +68 -0
- package/dist/entry-context.js.map +1 -0
- package/dist/gc.cjs +731 -0
- package/dist/gc.cjs.map +1 -0
- package/dist/gc.d.ts +14 -0
- package/dist/gc.js +707 -0
- package/dist/gc.js.map +1 -0
- package/dist/index.cjs +4760 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +213 -0
- package/dist/index.js +4808 -0
- package/dist/index.js.map +1 -0
- package/dist/jobs-Dd5PMSId.d.ts +98 -0
- package/dist/llm.cjs +101 -0
- package/dist/llm.cjs.map +1 -0
- package/dist/llm.d.ts +7 -0
- package/dist/llm.js +79 -0
- package/dist/llm.js.map +1 -0
- package/dist/local-config.cjs +1024 -0
- package/dist/local-config.cjs.map +1 -0
- package/dist/local-config.d.ts +14 -0
- package/dist/local-config.js +989 -0
- package/dist/local-config.js.map +1 -0
- package/dist/maintenance.cjs +800 -0
- package/dist/maintenance.cjs.map +1 -0
- package/dist/maintenance.d.ts +24 -0
- package/dist/maintenance.js +778 -0
- package/dist/maintenance.js.map +1 -0
- package/dist/node-platform.cjs +758 -0
- package/dist/node-platform.cjs.map +1 -0
- package/dist/node-platform.d.ts +49 -0
- package/dist/node-platform.js +723 -0
- package/dist/node-platform.js.map +1 -0
- package/dist/planning.cjs +164 -0
- package/dist/planning.cjs.map +1 -0
- package/dist/planning.d.ts +43 -0
- package/dist/planning.js +137 -0
- package/dist/planning.js.map +1 -0
- package/dist/runtime-config.cjs +1155 -0
- package/dist/runtime-config.cjs.map +1 -0
- package/dist/runtime-config.d.ts +50 -0
- package/dist/runtime-config.js +1127 -0
- package/dist/runtime-config.js.map +1 -0
- package/dist/stage.cjs +1265 -0
- package/dist/stage.cjs.map +1 -0
- package/dist/stage.d.ts +16 -0
- package/dist/stage.js +1239 -0
- package/dist/stage.js.map +1 -0
- package/dist/wikispine.cjs +85 -0
- package/dist/wikispine.cjs.map +1 -0
- package/dist/wikispine.d.ts +6 -0
- package/dist/wikispine.js +63 -0
- package/dist/wikispine.js.map +1 -0
- package/dist/worker.cjs +738 -0
- package/dist/worker.cjs.map +1 -0
- package/dist/worker.d.ts +157 -0
- package/dist/worker.js +715 -0
- package/dist/worker.js.map +1 -0
- package/package.json +151 -0
package/dist/worker.js
ADDED
|
@@ -0,0 +1,715 @@
|
|
|
1
|
+
import { fileURLToPath as __WIKIGRAPH_FILE_URL_TO_PATH__ } from "url";
|
|
2
|
+
import { resolve as __WIKIGRAPH_RESOLVE__ } from "path";
|
|
3
|
+
globalThis.__WIKIGRAPH_DATA_DIR__ ??= __WIKIGRAPH_RESOLVE__(__WIKIGRAPH_FILE_URL_TO_PATH__(new URL("./data", import.meta.url)));
|
|
4
|
+
|
|
5
|
+
// src/worker.ts
|
|
6
|
+
import {
|
|
7
|
+
runBuildJobWorker as runCoreBuildJobWorker
|
|
8
|
+
} from "wiki-graph-core/worker";
|
|
9
|
+
|
|
10
|
+
// src/node-platform.ts
|
|
11
|
+
import * as asyncHooks from "async_hooks";
|
|
12
|
+
import * as crypto from "crypto";
|
|
13
|
+
import * as fs from "fs";
|
|
14
|
+
import * as fsPromises from "fs/promises";
|
|
15
|
+
import * as os from "os";
|
|
16
|
+
import * as pathModule from "path";
|
|
17
|
+
import * as process from "process";
|
|
18
|
+
import { Readable, Writable } from "stream";
|
|
19
|
+
import { pipeline } from "stream/promises";
|
|
20
|
+
import * as sqlite3 from "sqlite3";
|
|
21
|
+
import * as yauzl from "yauzl";
|
|
22
|
+
import * as yazl from "yazl";
|
|
23
|
+
import { Environment, Loader } from "nunjucks";
|
|
24
|
+
import {
|
|
25
|
+
getWikiGraphStorage,
|
|
26
|
+
installWikiGraphPlatform,
|
|
27
|
+
installWikiGraphStorage,
|
|
28
|
+
withWikiGraphStorage,
|
|
29
|
+
normalizeTemplateName
|
|
30
|
+
} from "wiki-graph-core/platform";
|
|
31
|
+
var nodeProcess = process.default ?? process;
|
|
32
|
+
var nodeSqlite3 = sqlite3.default ?? sqlite3;
|
|
33
|
+
var NODE_RESOURCE_KIND = /* @__PURE__ */ Symbol.for("wiki-graph-sdk.node-resource.v1");
|
|
34
|
+
var NodeFile = class {
|
|
35
|
+
constructor(path, name = pathModule.basename(path)) {
|
|
36
|
+
this.path = path;
|
|
37
|
+
this.identity = encodeNodeResourceIdentity("file", path);
|
|
38
|
+
this.name = name;
|
|
39
|
+
}
|
|
40
|
+
path;
|
|
41
|
+
kind = "file";
|
|
42
|
+
[NODE_RESOURCE_KIND] = "file";
|
|
43
|
+
identity;
|
|
44
|
+
name;
|
|
45
|
+
async openReader() {
|
|
46
|
+
const handle = await fsPromises.open(this.path, "r");
|
|
47
|
+
let closed = false;
|
|
48
|
+
try {
|
|
49
|
+
const stats = await handle.stat();
|
|
50
|
+
if (!stats.isFile())
|
|
51
|
+
throw new Error("File reader requires a regular file");
|
|
52
|
+
const { size } = stats;
|
|
53
|
+
return {
|
|
54
|
+
size,
|
|
55
|
+
close: async () => {
|
|
56
|
+
if (!closed) await handle.close();
|
|
57
|
+
closed = true;
|
|
58
|
+
},
|
|
59
|
+
read: async (offset, length) => {
|
|
60
|
+
if (closed) throw new Error("Cannot read from a closed FileReader");
|
|
61
|
+
assertFileRange(offset, length, size);
|
|
62
|
+
const buffer = Buffer.allocUnsafe(length);
|
|
63
|
+
let bytesRead = 0;
|
|
64
|
+
while (bytesRead < length) {
|
|
65
|
+
const result = await handle.read(
|
|
66
|
+
buffer,
|
|
67
|
+
bytesRead,
|
|
68
|
+
length - bytesRead,
|
|
69
|
+
offset + bytesRead
|
|
70
|
+
);
|
|
71
|
+
if (result.bytesRead === 0) {
|
|
72
|
+
throw new Error("File changed while reading its byte range");
|
|
73
|
+
}
|
|
74
|
+
bytesRead += result.bytesRead;
|
|
75
|
+
}
|
|
76
|
+
return new Uint8Array(buffer.buffer, buffer.byteOffset, bytesRead);
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
} catch (error) {
|
|
80
|
+
await handle.close();
|
|
81
|
+
throw error;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
async getLastModified() {
|
|
85
|
+
try {
|
|
86
|
+
return (await fsPromises.stat(this.path)).mtimeMs;
|
|
87
|
+
} catch (error) {
|
|
88
|
+
if (typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT") {
|
|
89
|
+
return void 0;
|
|
90
|
+
}
|
|
91
|
+
throw error;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
async openWriter() {
|
|
95
|
+
await fsPromises.mkdir(pathModule.dirname(this.path), { recursive: true });
|
|
96
|
+
const temporary = `${this.path}.tmp-${crypto.randomUUID()}`;
|
|
97
|
+
const handle = await fsPromises.open(temporary, "wx");
|
|
98
|
+
let closed = false;
|
|
99
|
+
return {
|
|
100
|
+
write: async (data) => {
|
|
101
|
+
if (closed) throw new Error("Cannot write to a closed FileWriter");
|
|
102
|
+
await writeNodeFileHandle(handle, data);
|
|
103
|
+
},
|
|
104
|
+
writeAt: async (offset, data) => {
|
|
105
|
+
if (closed) throw new Error("Cannot write to a closed FileWriter");
|
|
106
|
+
assertFileOffset(offset);
|
|
107
|
+
await writeNodeFileHandle(handle, data, offset);
|
|
108
|
+
},
|
|
109
|
+
commit: async () => {
|
|
110
|
+
if (!closed) {
|
|
111
|
+
await handle.close();
|
|
112
|
+
await fsPromises.rename(temporary, this.path);
|
|
113
|
+
}
|
|
114
|
+
closed = true;
|
|
115
|
+
},
|
|
116
|
+
abort: async () => {
|
|
117
|
+
if (!closed) {
|
|
118
|
+
await handle.close();
|
|
119
|
+
await fsPromises.rm(temporary, { force: true });
|
|
120
|
+
}
|
|
121
|
+
closed = true;
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
async function writeNodeFileHandle(handle, data, position) {
|
|
127
|
+
const buffer = Buffer.from(data);
|
|
128
|
+
let written = 0;
|
|
129
|
+
while (written < buffer.byteLength) {
|
|
130
|
+
const result = await handle.write(
|
|
131
|
+
buffer,
|
|
132
|
+
written,
|
|
133
|
+
buffer.byteLength - written,
|
|
134
|
+
position === void 0 ? null : position + written
|
|
135
|
+
);
|
|
136
|
+
if (result.bytesWritten === 0) {
|
|
137
|
+
throw new Error("File writer made no progress");
|
|
138
|
+
}
|
|
139
|
+
written += result.bytesWritten;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
function assertFileRange(offset, length, size) {
|
|
143
|
+
assertFileOffset(offset);
|
|
144
|
+
if (!Number.isSafeInteger(length) || length < 0) {
|
|
145
|
+
throw new RangeError(
|
|
146
|
+
"File read length must be a non-negative safe integer"
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
if (offset > size || length > size - offset) {
|
|
150
|
+
throw new RangeError("File read range exceeds the file size");
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
function assertFileOffset(offset) {
|
|
154
|
+
if (!Number.isSafeInteger(offset) || offset < 0) {
|
|
155
|
+
throw new RangeError("File offset must be a non-negative safe integer");
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
var NodeDirectory = class _NodeDirectory {
|
|
159
|
+
constructor(path) {
|
|
160
|
+
this.path = path;
|
|
161
|
+
this.identity = encodeNodeResourceIdentity("directory", path);
|
|
162
|
+
this.name = pathModule.basename(path);
|
|
163
|
+
}
|
|
164
|
+
path;
|
|
165
|
+
kind = "directory";
|
|
166
|
+
[NODE_RESOURCE_KIND] = "directory";
|
|
167
|
+
identity;
|
|
168
|
+
name;
|
|
169
|
+
async getFile(name) {
|
|
170
|
+
assertChildName(name);
|
|
171
|
+
const file = new NodeFile(pathModule.join(this.path, name));
|
|
172
|
+
try {
|
|
173
|
+
return (await fsPromises.stat(file.path)).isFile() ? file : void 0;
|
|
174
|
+
} catch {
|
|
175
|
+
return void 0;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
async getLastModified() {
|
|
179
|
+
try {
|
|
180
|
+
return (await fsPromises.stat(this.path)).mtimeMs;
|
|
181
|
+
} catch (error) {
|
|
182
|
+
if (typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT") {
|
|
183
|
+
return void 0;
|
|
184
|
+
}
|
|
185
|
+
throw error;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
async getDirectory(name) {
|
|
189
|
+
assertChildName(name);
|
|
190
|
+
const directory = new _NodeDirectory(pathModule.join(this.path, name));
|
|
191
|
+
try {
|
|
192
|
+
return (await fsPromises.stat(directory.path)).isDirectory() ? directory : void 0;
|
|
193
|
+
} catch {
|
|
194
|
+
return void 0;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
async list() {
|
|
198
|
+
const entries = await fsPromises.readdir(this.path, {
|
|
199
|
+
withFileTypes: true
|
|
200
|
+
});
|
|
201
|
+
return entries.map(
|
|
202
|
+
(entry) => entry.isDirectory() ? new _NodeDirectory(pathModule.join(this.path, entry.name)) : new NodeFile(pathModule.join(this.path, entry.name), entry.name)
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
async createFile(name) {
|
|
206
|
+
assertChildName(name);
|
|
207
|
+
await fsPromises.mkdir(this.path, { recursive: true });
|
|
208
|
+
const file = new NodeFile(pathModule.join(this.path, name));
|
|
209
|
+
await fsPromises.writeFile(file.path, "", { flag: "wx" });
|
|
210
|
+
return file;
|
|
211
|
+
}
|
|
212
|
+
async createDirectory(name) {
|
|
213
|
+
assertChildName(name);
|
|
214
|
+
await fsPromises.mkdir(this.path, { recursive: true });
|
|
215
|
+
const directory = new _NodeDirectory(pathModule.join(this.path, name));
|
|
216
|
+
await fsPromises.mkdir(directory.path);
|
|
217
|
+
return directory;
|
|
218
|
+
}
|
|
219
|
+
async remove(name, options) {
|
|
220
|
+
assertChildName(name);
|
|
221
|
+
await fsPromises.rm(pathModule.join(this.path, name), {
|
|
222
|
+
force: true,
|
|
223
|
+
recursive: options?.recursive === true
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
};
|
|
227
|
+
function encodeNodeResourceIdentity(kind, path) {
|
|
228
|
+
return `node-${kind}:${Buffer.from(pathModule.resolve(path), "utf8").toString("base64url")}`;
|
|
229
|
+
}
|
|
230
|
+
function decodeNodeResourceIdentity(identity, kind) {
|
|
231
|
+
const prefix = `node-${kind}:`;
|
|
232
|
+
if (!identity.startsWith(prefix)) {
|
|
233
|
+
return pathModule.isAbsolute(identity) ? identity : void 0;
|
|
234
|
+
}
|
|
235
|
+
try {
|
|
236
|
+
return Buffer.from(identity.slice(prefix.length), "base64url").toString(
|
|
237
|
+
"utf8"
|
|
238
|
+
);
|
|
239
|
+
} catch {
|
|
240
|
+
return void 0;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
function assertChildName(name) {
|
|
244
|
+
if (name.length === 0 || name === "." || name === ".." || pathModule.isAbsolute(name) || name.includes("/") || name.includes("\\")) {
|
|
245
|
+
throw new TypeError(`Directory child must be a relative name: ${name}`);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
var NodeDatabaseConnection = class {
|
|
249
|
+
constructor(database) {
|
|
250
|
+
this.database = database;
|
|
251
|
+
}
|
|
252
|
+
database;
|
|
253
|
+
async close() {
|
|
254
|
+
await new Promise((resolve2, reject) => {
|
|
255
|
+
this.database.close((error) => {
|
|
256
|
+
if (error) reject(error);
|
|
257
|
+
else resolve2();
|
|
258
|
+
});
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
async execute(sql) {
|
|
262
|
+
await new Promise((resolve2, reject) => {
|
|
263
|
+
this.database.exec(sql, (error) => {
|
|
264
|
+
if (error) reject(error);
|
|
265
|
+
else resolve2();
|
|
266
|
+
});
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
async queryAll(sql, params = []) {
|
|
270
|
+
return await new Promise((resolve2, reject) => {
|
|
271
|
+
this.database.all(sql, [...params], (error, rows) => {
|
|
272
|
+
if (error) reject(error);
|
|
273
|
+
else resolve2(rows);
|
|
274
|
+
});
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
async queryOne(sql, params = []) {
|
|
278
|
+
return await new Promise((resolve2, reject) => {
|
|
279
|
+
this.database.get(sql, [...params], (error, row) => {
|
|
280
|
+
if (error) reject(error);
|
|
281
|
+
else resolve2(row);
|
|
282
|
+
});
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
async run(sql, params = []) {
|
|
286
|
+
await new Promise((resolve2, reject) => {
|
|
287
|
+
this.database.run(sql, [...params], (error) => {
|
|
288
|
+
if (error) reject(error);
|
|
289
|
+
else resolve2();
|
|
290
|
+
});
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
};
|
|
294
|
+
async function openNodeDatabase(file, options) {
|
|
295
|
+
const flags = (options.mode === "readonly" ? nodeSqlite3.OPEN_READONLY : nodeSqlite3.OPEN_READWRITE | (options.create ? nodeSqlite3.OPEN_CREATE : 0)) | nodeSqlite3.OPEN_FULLMUTEX;
|
|
296
|
+
return new NodeDatabaseConnection(await openNativeNodeDatabase(file, flags));
|
|
297
|
+
}
|
|
298
|
+
async function openNativeNodeDatabase(file, flags) {
|
|
299
|
+
const path = getBrandedNodeResourcePath(file, "file");
|
|
300
|
+
if (path === void 0) {
|
|
301
|
+
throw new TypeError("The Node database adapter requires a NodeFile");
|
|
302
|
+
}
|
|
303
|
+
return await new Promise((resolve2, reject) => {
|
|
304
|
+
const database = new nodeSqlite3.Database(path, flags, (error) => {
|
|
305
|
+
if (error) reject(error);
|
|
306
|
+
else resolve2(database);
|
|
307
|
+
});
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
async function openNodeZip(file) {
|
|
311
|
+
const path = getBrandedNodeResourcePath(file, "file");
|
|
312
|
+
if (path === void 0) {
|
|
313
|
+
throw new TypeError("The Node ZIP adapter requires a NodeFile");
|
|
314
|
+
}
|
|
315
|
+
const zipFile = await new Promise((resolve2, reject) => {
|
|
316
|
+
yauzl.open(
|
|
317
|
+
path,
|
|
318
|
+
{ autoClose: false, lazyEntries: true },
|
|
319
|
+
(error, opened) => {
|
|
320
|
+
if (error || opened === void 0)
|
|
321
|
+
reject(error ?? new Error("Cannot open ZIP"));
|
|
322
|
+
else resolve2(opened);
|
|
323
|
+
}
|
|
324
|
+
);
|
|
325
|
+
});
|
|
326
|
+
const entries = await new Promise(
|
|
327
|
+
(resolve2, reject) => {
|
|
328
|
+
const discovered = /* @__PURE__ */ new Map();
|
|
329
|
+
const rejectAndClose = (error) => {
|
|
330
|
+
zipFile.close();
|
|
331
|
+
reject(
|
|
332
|
+
error instanceof Error ? error : new Error("Cannot scan ZIP central directory")
|
|
333
|
+
);
|
|
334
|
+
};
|
|
335
|
+
const resolveEntries = () => {
|
|
336
|
+
zipFile.off("error", rejectAndClose);
|
|
337
|
+
resolve2(discovered);
|
|
338
|
+
};
|
|
339
|
+
zipFile.on("entry", (entry) => {
|
|
340
|
+
if (!entry.fileName.endsWith("/")) {
|
|
341
|
+
discovered.set(entry.fileName, entry);
|
|
342
|
+
}
|
|
343
|
+
zipFile.readEntry();
|
|
344
|
+
});
|
|
345
|
+
zipFile.once("error", rejectAndClose);
|
|
346
|
+
zipFile.once("end", resolveEntries);
|
|
347
|
+
zipFile.readEntry();
|
|
348
|
+
}
|
|
349
|
+
);
|
|
350
|
+
let closed = false;
|
|
351
|
+
return {
|
|
352
|
+
close: () => {
|
|
353
|
+
if (!closed) zipFile.close();
|
|
354
|
+
closed = true;
|
|
355
|
+
return Promise.resolve();
|
|
356
|
+
},
|
|
357
|
+
copyEntry: async (name, target) => {
|
|
358
|
+
if (closed) throw new Error("Cannot read a closed ZIP archive");
|
|
359
|
+
const entry = entries.get(name);
|
|
360
|
+
if (entry === void 0) return false;
|
|
361
|
+
await copyNodeZipEntry(zipFile, entry, target);
|
|
362
|
+
return true;
|
|
363
|
+
},
|
|
364
|
+
getEntrySize: (name) => {
|
|
365
|
+
if (closed) throw new Error("Cannot read a closed ZIP archive");
|
|
366
|
+
return Promise.resolve(entries.get(name)?.uncompressedSize);
|
|
367
|
+
},
|
|
368
|
+
listEntries: () => Promise.resolve([...entries.keys()]),
|
|
369
|
+
readEntryRange: async (name, offset, length) => {
|
|
370
|
+
if (closed) throw new Error("Cannot read a closed ZIP archive");
|
|
371
|
+
const entry = entries.get(name);
|
|
372
|
+
if (entry === void 0) return void 0;
|
|
373
|
+
return await readNodeZipEntryRange(zipFile, entry, offset, length);
|
|
374
|
+
},
|
|
375
|
+
readEntry: async (name) => {
|
|
376
|
+
if (closed) throw new Error("Cannot read a closed ZIP archive");
|
|
377
|
+
const entry = entries.get(name);
|
|
378
|
+
if (entry === void 0) return void 0;
|
|
379
|
+
return await readNodeZipEntry(zipFile, entry);
|
|
380
|
+
}
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
async function copyNodeZipEntry(zipFile, entry, target) {
|
|
384
|
+
const writer = await target.openWriter();
|
|
385
|
+
try {
|
|
386
|
+
const stream = await openNodeZipEntryStream(zipFile, entry);
|
|
387
|
+
await writeNodeStream(stream, writer);
|
|
388
|
+
await writer.commit();
|
|
389
|
+
} catch (error) {
|
|
390
|
+
await writer.abort().catch(() => void 0);
|
|
391
|
+
throw error;
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
async function readNodeZipEntry(zipFile, entry) {
|
|
395
|
+
return await collectNodeStream(await openNodeZipEntryStream(zipFile, entry));
|
|
396
|
+
}
|
|
397
|
+
async function readNodeZipEntryRange(zipFile, entry, offset, length) {
|
|
398
|
+
assertFileRange(offset, length, entry.uncompressedSize);
|
|
399
|
+
if (length === 0) return new Uint8Array();
|
|
400
|
+
if (entry.compressionMethod !== 0) {
|
|
401
|
+
const content2 = await collectDecodedNodeStreamRange(
|
|
402
|
+
await openNodeZipEntryStream(zipFile, entry),
|
|
403
|
+
offset,
|
|
404
|
+
length
|
|
405
|
+
);
|
|
406
|
+
return new Uint8Array(
|
|
407
|
+
content2.buffer,
|
|
408
|
+
content2.byteOffset,
|
|
409
|
+
content2.byteLength
|
|
410
|
+
);
|
|
411
|
+
}
|
|
412
|
+
const content = await collectNodeStream(
|
|
413
|
+
await openNodeZipEntryStream(zipFile, entry, {
|
|
414
|
+
decompress: null,
|
|
415
|
+
decrypt: null,
|
|
416
|
+
end: offset + length,
|
|
417
|
+
start: offset
|
|
418
|
+
})
|
|
419
|
+
);
|
|
420
|
+
return new Uint8Array(content.buffer, content.byteOffset, content.byteLength);
|
|
421
|
+
}
|
|
422
|
+
async function collectDecodedNodeStreamRange(input, offset, length) {
|
|
423
|
+
const chunks = [];
|
|
424
|
+
const end = offset + length;
|
|
425
|
+
let position = 0;
|
|
426
|
+
let collected = 0;
|
|
427
|
+
for await (const value of input) {
|
|
428
|
+
const chunk = Buffer.isBuffer(value) ? value : Buffer.from(value);
|
|
429
|
+
const chunkEnd = position + chunk.byteLength;
|
|
430
|
+
if (chunkEnd > offset && position < end) {
|
|
431
|
+
const selected = chunk.subarray(
|
|
432
|
+
Math.max(0, offset - position),
|
|
433
|
+
Math.min(chunk.byteLength, end - position)
|
|
434
|
+
);
|
|
435
|
+
chunks.push(selected);
|
|
436
|
+
collected += selected.byteLength;
|
|
437
|
+
}
|
|
438
|
+
position = chunkEnd;
|
|
439
|
+
if (position >= end) break;
|
|
440
|
+
}
|
|
441
|
+
if (collected !== length) {
|
|
442
|
+
throw new Error("ZIP entry changed while reading its byte range");
|
|
443
|
+
}
|
|
444
|
+
return Buffer.concat(chunks, collected);
|
|
445
|
+
}
|
|
446
|
+
async function openNodeZipEntryStream(zipFile, entry, options) {
|
|
447
|
+
return await new Promise((resolve2, reject) => {
|
|
448
|
+
const callback = (error, opened) => {
|
|
449
|
+
if (error || opened === void 0) {
|
|
450
|
+
reject(error ?? new Error(`Cannot read ZIP entry: ${entry.fileName}`));
|
|
451
|
+
} else {
|
|
452
|
+
resolve2(opened);
|
|
453
|
+
}
|
|
454
|
+
};
|
|
455
|
+
if (options === void 0) zipFile.openReadStream(entry, callback);
|
|
456
|
+
else zipFile.openReadStream(entry, options, callback);
|
|
457
|
+
});
|
|
458
|
+
}
|
|
459
|
+
async function writeNodeZip(file, entries) {
|
|
460
|
+
const zipFile = new yazl.ZipFile();
|
|
461
|
+
const writer = await file.openWriter();
|
|
462
|
+
const outputStream = zipFile.outputStream;
|
|
463
|
+
const outputDone = writeNodeStream(outputStream, writer);
|
|
464
|
+
const entryState = { cancelled: false, complete: false };
|
|
465
|
+
let iterator;
|
|
466
|
+
try {
|
|
467
|
+
iterator = getNodeZipEntryIterator(entries);
|
|
468
|
+
const entriesDone = addNodeZipEntries(zipFile, iterator, entryState);
|
|
469
|
+
await Promise.race([entriesDone, outputDone]);
|
|
470
|
+
if (!entryState.complete) {
|
|
471
|
+
throw new Error("ZIP output ended before entry production completed");
|
|
472
|
+
}
|
|
473
|
+
zipFile.end();
|
|
474
|
+
await outputDone;
|
|
475
|
+
await writer.commit();
|
|
476
|
+
} catch (error) {
|
|
477
|
+
entryState.cancelled = true;
|
|
478
|
+
if (!entryState.complete && iterator !== void 0) {
|
|
479
|
+
closeNodeZipEntryIterator(iterator);
|
|
480
|
+
}
|
|
481
|
+
if (!outputStream.destroyed) {
|
|
482
|
+
outputStream.destroy(
|
|
483
|
+
error instanceof Error ? error : new Error("Cannot write ZIP archive")
|
|
484
|
+
);
|
|
485
|
+
}
|
|
486
|
+
await outputDone.catch(() => void 0);
|
|
487
|
+
await writer.abort().catch(() => void 0);
|
|
488
|
+
throw error;
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
async function addNodeZipEntries(zipFile, iterator, state) {
|
|
492
|
+
while (!state.cancelled) {
|
|
493
|
+
const result = await iterator.next();
|
|
494
|
+
if (state.cancelled) return;
|
|
495
|
+
if (result.done) {
|
|
496
|
+
state.complete = true;
|
|
497
|
+
return;
|
|
498
|
+
}
|
|
499
|
+
if ("file" in result.value) {
|
|
500
|
+
zipFile.addReadStream(
|
|
501
|
+
createNodeFileReadStream(result.value.file),
|
|
502
|
+
result.value.name,
|
|
503
|
+
{ compress: false }
|
|
504
|
+
);
|
|
505
|
+
} else if ("data" in result.value) {
|
|
506
|
+
zipFile.addBuffer(Buffer.from(result.value.data), result.value.name, {
|
|
507
|
+
compress: false
|
|
508
|
+
});
|
|
509
|
+
} else {
|
|
510
|
+
zipFile.addReadStream(
|
|
511
|
+
createNodeRangeReadStream(result.value),
|
|
512
|
+
result.value.name,
|
|
513
|
+
{ compress: false, size: result.value.size }
|
|
514
|
+
);
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
function createNodeFileReadStream(file) {
|
|
519
|
+
return Readable.from(
|
|
520
|
+
(async function* () {
|
|
521
|
+
const reader = await file.openReader();
|
|
522
|
+
try {
|
|
523
|
+
for (let offset = 0; offset < reader.size; ) {
|
|
524
|
+
const chunk = await reader.read(
|
|
525
|
+
offset,
|
|
526
|
+
Math.min(64 * 1024, reader.size - offset)
|
|
527
|
+
);
|
|
528
|
+
offset += chunk.byteLength;
|
|
529
|
+
yield chunk;
|
|
530
|
+
}
|
|
531
|
+
} finally {
|
|
532
|
+
await reader.close();
|
|
533
|
+
}
|
|
534
|
+
})()
|
|
535
|
+
);
|
|
536
|
+
}
|
|
537
|
+
function getBrandedNodeResourcePath(resource, kind) {
|
|
538
|
+
if (typeof resource !== "object" || resource === null) return void 0;
|
|
539
|
+
const candidate = resource;
|
|
540
|
+
return candidate[NODE_RESOURCE_KIND] === kind && typeof candidate.path === "string" ? candidate.path : void 0;
|
|
541
|
+
}
|
|
542
|
+
function createNodeRangeReadStream(entry) {
|
|
543
|
+
return Readable.from(
|
|
544
|
+
(async function* () {
|
|
545
|
+
for (let offset = 0; offset < entry.size; ) {
|
|
546
|
+
const chunk = await entry.read(
|
|
547
|
+
offset,
|
|
548
|
+
Math.min(64 * 1024, entry.size - offset)
|
|
549
|
+
);
|
|
550
|
+
offset += chunk.byteLength;
|
|
551
|
+
yield chunk;
|
|
552
|
+
}
|
|
553
|
+
})()
|
|
554
|
+
);
|
|
555
|
+
}
|
|
556
|
+
function getNodeZipEntryIterator(entries) {
|
|
557
|
+
const asyncIterator = entries[Symbol.asyncIterator];
|
|
558
|
+
return asyncIterator === void 0 ? entries[Symbol.iterator]() : asyncIterator.call(entries);
|
|
559
|
+
}
|
|
560
|
+
function closeNodeZipEntryIterator(iterator) {
|
|
561
|
+
if (iterator.return === void 0) return;
|
|
562
|
+
try {
|
|
563
|
+
void Promise.resolve(iterator.return()).catch(() => void 0);
|
|
564
|
+
} catch {
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
async function writeNodeStream(input, writer) {
|
|
568
|
+
await pipeline(
|
|
569
|
+
input,
|
|
570
|
+
new Writable({
|
|
571
|
+
write: (chunk, _encoding, callback) => {
|
|
572
|
+
void writer.write(chunk).then(
|
|
573
|
+
() => callback(),
|
|
574
|
+
(error) => callback(
|
|
575
|
+
error instanceof Error ? error : new Error("Cannot stream ZIP archive")
|
|
576
|
+
)
|
|
577
|
+
);
|
|
578
|
+
}
|
|
579
|
+
})
|
|
580
|
+
);
|
|
581
|
+
}
|
|
582
|
+
async function collectNodeStream(input) {
|
|
583
|
+
return await new Promise((resolve2, reject) => {
|
|
584
|
+
const chunks = [];
|
|
585
|
+
input.on("data", (chunk) => chunks.push(chunk));
|
|
586
|
+
input.once("error", reject);
|
|
587
|
+
input.once("end", () => resolve2(Buffer.concat(chunks)));
|
|
588
|
+
});
|
|
589
|
+
}
|
|
590
|
+
var nodeWikiGraphPlatform = {
|
|
591
|
+
asyncContext: {
|
|
592
|
+
create: () => new asyncHooks.AsyncLocalStorage()
|
|
593
|
+
},
|
|
594
|
+
database: { open: openNodeDatabase },
|
|
595
|
+
lifecycle: {
|
|
596
|
+
instanceId: `node-process:${nodeProcess.pid}`,
|
|
597
|
+
isInstanceAlive: (instanceId) => {
|
|
598
|
+
const match = /^node-process:(\d+)$/u.exec(instanceId);
|
|
599
|
+
if (match === null) return Promise.resolve(void 0);
|
|
600
|
+
try {
|
|
601
|
+
nodeProcess.kill(Number(match[1]), 0);
|
|
602
|
+
return Promise.resolve(true);
|
|
603
|
+
} catch (error) {
|
|
604
|
+
if (typeof error === "object" && error !== null && "code" in error && error.code === "ESRCH") {
|
|
605
|
+
return Promise.resolve(false);
|
|
606
|
+
}
|
|
607
|
+
return Promise.resolve(true);
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
},
|
|
611
|
+
resources: {
|
|
612
|
+
getDirectory: (identity) => {
|
|
613
|
+
const path = decodeNodeResourceIdentity(identity, "directory");
|
|
614
|
+
return Promise.resolve(
|
|
615
|
+
path === void 0 ? void 0 : new NodeDirectory(path)
|
|
616
|
+
);
|
|
617
|
+
},
|
|
618
|
+
getFile: (identity) => {
|
|
619
|
+
const path = decodeNodeResourceIdentity(identity, "file");
|
|
620
|
+
return Promise.resolve(
|
|
621
|
+
path === void 0 ? void 0 : new NodeFile(path)
|
|
622
|
+
);
|
|
623
|
+
},
|
|
624
|
+
resolveLegacyDirectory: (reference) => {
|
|
625
|
+
const path = decodeNodeResourceIdentity(reference, "directory");
|
|
626
|
+
return Promise.resolve(
|
|
627
|
+
path === void 0 ? void 0 : new NodeDirectory(path)
|
|
628
|
+
);
|
|
629
|
+
}
|
|
630
|
+
},
|
|
631
|
+
templates: {
|
|
632
|
+
createEnvironment: (options) => new Environment(new NodeTemplateLoader(), options)
|
|
633
|
+
},
|
|
634
|
+
zip: {
|
|
635
|
+
open: openNodeZip,
|
|
636
|
+
write: writeNodeZip
|
|
637
|
+
}
|
|
638
|
+
};
|
|
639
|
+
var NodeTemplateLoader = class extends Loader {
|
|
640
|
+
#dataDirectory;
|
|
641
|
+
constructor(dataDirectory) {
|
|
642
|
+
super();
|
|
643
|
+
this.#dataDirectory = dataDirectory;
|
|
644
|
+
}
|
|
645
|
+
getSource(templateName) {
|
|
646
|
+
const name = normalizeTemplateName(templateName);
|
|
647
|
+
const filePath = pathModule.join(
|
|
648
|
+
this.#dataDirectory ?? resolveNodeDataDirectory(),
|
|
649
|
+
name
|
|
650
|
+
);
|
|
651
|
+
return {
|
|
652
|
+
noCache: false,
|
|
653
|
+
path: name,
|
|
654
|
+
src: fs.readFileSync(filePath, "utf8")
|
|
655
|
+
};
|
|
656
|
+
}
|
|
657
|
+
};
|
|
658
|
+
function resolveNodeDataDirectory() {
|
|
659
|
+
const injected = globalThis.__WIKIGRAPH_DATA_DIR__;
|
|
660
|
+
if (typeof injected === "string" && injected !== "") return injected;
|
|
661
|
+
let directory = nodeProcess.cwd();
|
|
662
|
+
while (true) {
|
|
663
|
+
for (const candidate of [
|
|
664
|
+
pathModule.join(directory, "data"),
|
|
665
|
+
pathModule.join(directory, "packages", "core", "data")
|
|
666
|
+
]) {
|
|
667
|
+
try {
|
|
668
|
+
if (fs.statSync(candidate).isDirectory()) return candidate;
|
|
669
|
+
} catch {
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
const parent = pathModule.dirname(directory);
|
|
673
|
+
if (parent === directory)
|
|
674
|
+
throw new Error("Could not locate data directory");
|
|
675
|
+
directory = parent;
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
function createNodeWikiGraphStorage(stateRoot = pathModule.join(os.homedir(), ".wikigraph")) {
|
|
679
|
+
return {
|
|
680
|
+
library: new NodeDirectory(stateRoot),
|
|
681
|
+
documentStore: new NodeDirectory(pathModule.join(stateRoot, "documents"))
|
|
682
|
+
};
|
|
683
|
+
}
|
|
684
|
+
function installNodeWikiGraphPlatform(stateRoot) {
|
|
685
|
+
installWikiGraphPlatform(nodeWikiGraphPlatform);
|
|
686
|
+
installWikiGraphStorage(createNodeWikiGraphStorage(stateRoot));
|
|
687
|
+
}
|
|
688
|
+
async function withNodeWikiGraphStorage(stateRoot, operation) {
|
|
689
|
+
return await withWikiGraphStorage(
|
|
690
|
+
stateRoot === void 0 ? void 0 : createNodeWikiGraphStorage(stateRoot),
|
|
691
|
+
operation
|
|
692
|
+
);
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
// src/worker.ts
|
|
696
|
+
import {
|
|
697
|
+
applyChapterJobArtifactFile,
|
|
698
|
+
createLocalChapterJobFileExecutor,
|
|
699
|
+
writeChapterJobInputFile
|
|
700
|
+
} from "wiki-graph-core/worker";
|
|
701
|
+
async function runBuildJobWorker(options) {
|
|
702
|
+
installNodeWikiGraphPlatform();
|
|
703
|
+
const { stateDir, ...coreOptions } = options;
|
|
704
|
+
await withNodeWikiGraphStorage(
|
|
705
|
+
stateDir,
|
|
706
|
+
async () => await runCoreBuildJobWorker(coreOptions)
|
|
707
|
+
);
|
|
708
|
+
}
|
|
709
|
+
export {
|
|
710
|
+
applyChapterJobArtifactFile,
|
|
711
|
+
createLocalChapterJobFileExecutor,
|
|
712
|
+
runBuildJobWorker,
|
|
713
|
+
writeChapterJobInputFile
|
|
714
|
+
};
|
|
715
|
+
//# sourceMappingURL=worker.js.map
|