@mostra/worker 0.0.0-placeholder → 0.1.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.
@@ -0,0 +1,557 @@
1
+ import { n as createSharedState, r as sharedViews, t as SECRET_SLOT } from "./shared-BH5iNWqJ.js";
2
+ import { isBuiltin, registerHooks } from "node:module";
3
+ import { pathToFileURL } from "node:url";
4
+ import { readdirSync, realpathSync, statSync, watch } from "node:fs";
5
+ import { readFile } from "node:fs/promises";
6
+ import { join, matchesGlob, relative, resolve, sep } from "node:path";
7
+ import { Worker } from "node:worker_threads";
8
+ import { RpcError, RpcPeer, SerializationError, ValueWriter, WORKER_CHANNEL_REVISION, WORKER_METHODS, WorkerCallParams, WorkerStartParams, createDiagnostic, deserializeAll, encodeLine, serializeAll, wireError } from "@mostra/protocol";
9
+ import { currentCall, installServerHost, liveSourceOptions, parseDuration, runWithContext } from "@mostra/server/host";
10
+ //#region src/worker.ts
11
+ /**
12
+ * The worker's main thread (ARCHITECTURE §7, D124): loads one artifact version's server bundle and
13
+ * runs its server functions and live producers, each call inside the request context of
14
+ * `@mostra/server` (D19 seam 3). It speaks the worker channel (`@mostra/protocol`'s `worker.ts`)
15
+ * through its channel thread, never sees a cookie, a token or a raw browser request, and gets
16
+ * secrets only by asking for them by name.
17
+ */
18
+ /** The longest wait for a secret: the host port's 30 s and a margin. */
19
+ const SECRET_WAIT_MS = 4e4;
20
+ /** How often the event loop proves it turns, for the watchdog (D62). */
21
+ const BEAT_MS = 100;
22
+ const ownExtension = import.meta.url.endsWith(".ts") ? ".ts" : ".js";
23
+ /** Whether `specifier` names a package (`react`, `@scope/name/sub`), not a path, URL or built-in. */
24
+ function isPackageSpecifier(specifier) {
25
+ if (specifier.startsWith(".") || specifier.startsWith("/") || specifier.startsWith("#")) return false;
26
+ if (/^[a-z][a-z0-9+.-]*:/i.test(specifier)) return false;
27
+ return !isBuiltin(specifier);
28
+ }
29
+ /**
30
+ * Resolves the version's imports (D135): `@mostra/server` is this worker's own copy, so they share
31
+ * context; every other package the server bundle imports resolves from `modules`, the layout the
32
+ * version was built against, as though the bundle sat beside it. Imports inside packages resolve
33
+ * as Node resolves them, from the packages' own directories.
34
+ */
35
+ function resolveVersionImports(versionDir, modules) {
36
+ const entries = {
37
+ "@mostra/server": import.meta.resolve("@mostra/server"),
38
+ "@mostra/server/host": import.meta.resolve("@mostra/server/host")
39
+ };
40
+ const versionUrls = [resolve(versionDir), realpathSync(versionDir)].map((dir) => `${pathToFileURL(dir).href}/`);
41
+ const layoutParent = modules === void 0 ? void 0 : pathToFileURL(join(modules, "..", "mostra-server.mjs")).href;
42
+ registerHooks({ resolve(specifier, context, next) {
43
+ const url = entries[specifier];
44
+ if (url) return {
45
+ url,
46
+ shortCircuit: true
47
+ };
48
+ if (layoutParent !== void 0 && versionUrls.some((url) => context.parentURL?.startsWith(url) === true) && isPackageSpecifier(specifier)) return next(specifier, {
49
+ ...context,
50
+ parentURL: layoutParent
51
+ });
52
+ return next(specifier, context);
53
+ } });
54
+ }
55
+ /** Runs a worker until its channel closes. */
56
+ async function runWorker(options) {
57
+ resolveVersionImports(options.versionDir, options.modules);
58
+ const shared = createSharedState();
59
+ const views = sharedViews(shared);
60
+ const thread = new Worker(new URL(`./channel-thread${ownExtension}`, import.meta.url), { workerData: {
61
+ channel: options.channel,
62
+ shared
63
+ } });
64
+ thread.unref();
65
+ const beat = () => {
66
+ Atomics.store(views.beat, 0, BigInt(Date.now()));
67
+ Atomics.store(views.beat, 1, BigInt(process.memoryUsage().heapUsed));
68
+ };
69
+ beat();
70
+ setInterval(beat, BEAT_MS);
71
+ const calls = /* @__PURE__ */ new Map();
72
+ const functions = /* @__PURE__ */ new Map();
73
+ const ids = /* @__PURE__ */ new Map();
74
+ const producers = /* @__PURE__ */ new Map();
75
+ const sources = /* @__PURE__ */ new Map();
76
+ const shutdown = (code) => {
77
+ for (const producer of producers.values()) producer.stop();
78
+ try {
79
+ process.kill(-process.pid, "SIGTERM");
80
+ } catch {}
81
+ process.exit(code);
82
+ };
83
+ const peer = new RpcPeer({
84
+ send(message) {
85
+ thread.postMessage({
86
+ type: "line",
87
+ line: encodeLine(message)
88
+ });
89
+ },
90
+ onRequest(method, params) {
91
+ switch (method) {
92
+ case WORKER_METHODS.start: return start(params);
93
+ case WORKER_METHODS.call: return call(params);
94
+ case WORKER_METHODS.liveStart: return liveStart(params);
95
+ case WORKER_METHODS.liveStop: {
96
+ const key = String(params.key);
97
+ producers.get(key)?.stop();
98
+ producers.delete(key);
99
+ return {};
100
+ }
101
+ case WORKER_METHODS.stop:
102
+ setImmediate(() => shutdown(0));
103
+ return {};
104
+ default: throw new RpcError(createDiagnostic("MOSTRA_HOST_METHOD_UNKNOWN", { message: `The worker serves no method ${method}.` }));
105
+ }
106
+ },
107
+ onNotification(method, params) {
108
+ if (method === WORKER_METHODS.cancel) {
109
+ const { callId, reason } = params;
110
+ const entry = callId === void 0 ? void 0 : calls.get(callId);
111
+ if (entry) {
112
+ const error = new Error(reason ?? "The run was cancelled.");
113
+ error.code = "MOSTRA_ACTION_CANCELLED";
114
+ error.name = "AbortError";
115
+ entry.controller.abort(error);
116
+ }
117
+ } else if (method === WORKER_METHODS.liveRefresh) producers.get(String(params.key))?.refresh();
118
+ },
119
+ onInternalError(error) {
120
+ process.stderr.write(`mostra worker: ${error?.stack ?? String(error)}\n`);
121
+ }
122
+ });
123
+ thread.on("message", (message) => {
124
+ if (message.type === "line" && message.line !== void 0) peer.receiveLine(message.line);
125
+ else if (message.type === "closed") shutdown(0);
126
+ });
127
+ thread.on("error", (error) => {
128
+ process.stderr.write(`mostra worker: the channel failed: ${error.message}\n`);
129
+ shutdown(1);
130
+ });
131
+ thread.on("exit", () => shutdown(0));
132
+ const track = (callId, promise) => {
133
+ const entry = callId === void 0 ? void 0 : calls.get(callId);
134
+ const settled = promise.catch((error) => {
135
+ const line = `${error?.message ?? String(error)}`;
136
+ peer.notify(WORKER_METHODS.log, {
137
+ ...callId === void 0 ? {} : { callId },
138
+ line: `Mostra couldn't record it: ${line}`
139
+ });
140
+ });
141
+ if (entry) {
142
+ entry.pending.add(settled);
143
+ settled.finally(() => entry.pending.delete(settled));
144
+ }
145
+ };
146
+ installServerHost({
147
+ secret(name) {
148
+ Atomics.store(views.control, SECRET_SLOT.state, 1);
149
+ thread.postMessage({
150
+ type: "secret",
151
+ name
152
+ });
153
+ const outcome = Atomics.wait(views.control, SECRET_SLOT.state, 1, SECRET_WAIT_MS);
154
+ const length = Atomics.load(views.control, SECRET_SLOT.length);
155
+ const status = Atomics.load(views.control, SECRET_SLOT.status);
156
+ const text = new TextDecoder().decode(views.secretBytes.slice(0, length));
157
+ Atomics.store(views.control, SECRET_SLOT.state, 0);
158
+ if (outcome === "timed-out") throw Object.assign(/* @__PURE__ */ new Error(`Reading the secret ${name} timed out.`), { code: "MOSTRA_SECRET_MISSING" });
159
+ if (status !== 0) {
160
+ const failure = JSON.parse(text);
161
+ throw Object.assign(new Error(failure.message), { code: failure.code });
162
+ }
163
+ return text;
164
+ },
165
+ progress(callId, p) {
166
+ peer.notify(WORKER_METHODS.progress, {
167
+ callId,
168
+ ...p
169
+ });
170
+ },
171
+ log(callId, line) {
172
+ peer.notify(WORKER_METHODS.log, {
173
+ ...callId === void 0 ? {} : { callId },
174
+ line
175
+ });
176
+ },
177
+ signal(callId, name, payload) {
178
+ track(callId, peer.request(WORKER_METHODS.signal, {
179
+ ...callId === void 0 ? {} : { callId },
180
+ name,
181
+ ...payload === void 0 ? {} : { payload }
182
+ }));
183
+ },
184
+ emit(callId, type, payload) {
185
+ track(callId, peer.request(WORKER_METHODS.emit, {
186
+ ...callId === void 0 ? {} : { callId },
187
+ type,
188
+ ...payload === void 0 ? {} : { payload }
189
+ }));
190
+ },
191
+ async stateGet(stateIds) {
192
+ return await peer.request(WORKER_METHODS.stateGet, { ...stateIds === void 0 ? {} : { ids: [...stateIds] } });
193
+ },
194
+ async statePatch(callId, ops, writeOptions) {
195
+ return await peer.request(WORKER_METHODS.statePatch, {
196
+ ...callId === void 0 ? {} : { callId },
197
+ ops: [...ops],
198
+ ...writeOptions
199
+ });
200
+ }
201
+ });
202
+ for (const level of [
203
+ "log",
204
+ "info",
205
+ "warn",
206
+ "error",
207
+ "debug"
208
+ ]) {
209
+ const original = console[level].bind(console);
210
+ console[level] = (...args) => {
211
+ original(...args);
212
+ const active = currentCall();
213
+ if (active) {
214
+ const line = args.map((arg) => typeof arg === "string" ? arg : inspectLine(arg)).join(" ");
215
+ peer.notify(WORKER_METHODS.log, {
216
+ callId: active.callId,
217
+ line
218
+ });
219
+ }
220
+ };
221
+ }
222
+ async function start(raw) {
223
+ const params = WorkerStartParams.parse(raw);
224
+ if (JSON.parse(await readFile(join(options.versionDir, "manifest.json"), "utf8")).outputDigest !== params.version.outputDigest) throw new RpcError(createDiagnostic("MOSTRA_HOME_INTEGRITY", { message: `The version directory doesn't hold ${params.version.versionId}: its output digest differs.` }));
225
+ const entry = resolve(options.versionDir, params.entry);
226
+ if (!entry.startsWith(`${resolve(options.versionDir)}${sep}`)) throw new RpcError(createDiagnostic("MOSTRA_HOME_INTEGRITY", { message: "The server entry leaves the version." }));
227
+ const bundle = await import(pathToFileURL(entry).href);
228
+ for (const [id, fn] of Object.entries(bundle.functions ?? {})) {
229
+ if (typeof fn !== "function") continue;
230
+ functions.set(id, fn);
231
+ ids.set(fn, id);
232
+ }
233
+ const live = [];
234
+ for (const [key, value] of Object.entries(bundle.live ?? {})) {
235
+ const source = liveSourceOptions(value);
236
+ if (!source) continue;
237
+ sources.set(key, source);
238
+ live.push(describeSource(key, source));
239
+ }
240
+ return {
241
+ revision: WORKER_CHANNEL_REVISION,
242
+ functions: [...functions.keys()],
243
+ live
244
+ };
245
+ }
246
+ async function call(raw) {
247
+ const params = WorkerCallParams.parse(raw);
248
+ const fn = functions.get(params.fnId);
249
+ if (!fn) return {
250
+ status: "failed",
251
+ error: {
252
+ code: "MOSTRA_ACTION_UNKNOWN_FUNCTION",
253
+ message: `This version has no server function ${params.fnId}.`
254
+ }
255
+ };
256
+ const entry = {
257
+ controller: new AbortController(),
258
+ pending: /* @__PURE__ */ new Set()
259
+ };
260
+ calls.set(params.callId, entry);
261
+ try {
262
+ let args;
263
+ try {
264
+ args = await deserializeAll(params.args, {
265
+ mode: "argument",
266
+ serverFunction: (id) => serverFunction(id)
267
+ });
268
+ } catch (error) {
269
+ return {
270
+ status: "failed",
271
+ error: errorOf(error, "MOSTRA_ACTION_UNSERIALIZABLE")
272
+ };
273
+ }
274
+ if (!Array.isArray(args)) return {
275
+ status: "failed",
276
+ error: {
277
+ code: "MOSTRA_ACTION_UNSERIALIZABLE",
278
+ message: "The arguments aren't a list."
279
+ }
280
+ };
281
+ const context = {
282
+ kind: params.context.kind,
283
+ callId: params.callId,
284
+ dryRun: params.context.dryRun,
285
+ signal: entry.controller.signal,
286
+ ...params.context.runId === void 0 ? {} : { runId: params.context.runId },
287
+ ...params.context.viewer === void 0 ? {} : { viewer: params.context.viewer }
288
+ };
289
+ let result;
290
+ try {
291
+ result = await runWithContext(context, () => fn(...args));
292
+ } catch (error) {
293
+ await settlePending(entry);
294
+ if (entry.controller.signal.aborted && isAbort(error, entry.controller.signal)) return { status: "cancelled" };
295
+ return {
296
+ status: "failed",
297
+ error: errorOf(error, "MOSTRA_ACTION_THREW")
298
+ };
299
+ }
300
+ const writer = new ValueWriter({
301
+ mode: "result",
302
+ serverFunctionId: (candidate) => ids.get(candidate),
303
+ onBatch: (batch) => peer.notify(WORKER_METHODS.batch, {
304
+ callId: params.callId,
305
+ batch
306
+ })
307
+ });
308
+ entry.writer = writer;
309
+ const stop = () => writer.abort();
310
+ try {
311
+ await runWithContext(context, async () => {
312
+ await writer.write(result);
313
+ if (entry.controller.signal.aborted) writer.abort();
314
+ else entry.controller.signal.addEventListener("abort", stop, { once: true });
315
+ await writer.done;
316
+ });
317
+ } catch (error) {
318
+ await settlePending(entry);
319
+ return {
320
+ status: "failed",
321
+ error: errorOf(error, error instanceof SerializationError ? error.code : "MOSTRA_ACTION_THREW")
322
+ };
323
+ }
324
+ await settlePending(entry);
325
+ return { status: writer.cutShort ? "cancelled" : "succeeded" };
326
+ } finally {
327
+ calls.delete(params.callId);
328
+ }
329
+ }
330
+ async function settlePending(entry) {
331
+ while (entry.pending.size > 0) await Promise.all([...entry.pending]);
332
+ }
333
+ function serverFunction(id) {
334
+ const fn = functions.get(id);
335
+ if (!fn) throw new SerializationError(`names no server function of this version (${id}).`);
336
+ return fn;
337
+ }
338
+ function liveStart(raw) {
339
+ const key = String(raw.key);
340
+ if (producers.has(key)) return {};
341
+ const source = sources.get(key);
342
+ if (!source) throw new RpcError(createDiagnostic("MOSTRA_LIVE_SOURCE_FAILED", { message: `live.ts defines no live source ${key}.` }));
343
+ const producer = new Producer(key, source, options.sourceDir, peer);
344
+ producers.set(key, producer);
345
+ producer.start();
346
+ return {};
347
+ }
348
+ await new Promise(() => {});
349
+ }
350
+ function inspectLine(value) {
351
+ try {
352
+ return typeof value === "object" ? JSON.stringify(value) : String(value);
353
+ } catch {
354
+ return String(value);
355
+ }
356
+ }
357
+ function isAbort(error, signal) {
358
+ return error === signal.reason || error?.name === "AbortError";
359
+ }
360
+ function errorOf(error, fallback) {
361
+ const code = error?.code;
362
+ const message = error instanceof Error ? error.message : String(error);
363
+ const stack = error instanceof Error ? error.stack : void 0;
364
+ return {
365
+ code: typeof code === "string" && /^MOSTRA_[A-Z]+_[A-Z0-9_]+$/.test(code) ? code : fallback,
366
+ message,
367
+ ...stack === void 0 ? {} : { stack }
368
+ };
369
+ }
370
+ function describeSource(key, source) {
371
+ const watch = source.watch === void 0 ? void 0 : typeof source.watch === "string" ? [source.watch] : [...source.watch];
372
+ return {
373
+ key,
374
+ load: typeof source.load === "function",
375
+ stream: typeof source.stream === "function",
376
+ always: source.always === true,
377
+ ...source.refresh === void 0 ? {} : { refreshMs: parseDuration(source.refresh) },
378
+ ...watch === void 0 ? {} : { watch },
379
+ ...source.ring === void 0 ? {} : { ring: source.ring }
380
+ };
381
+ }
382
+ /** How often watched files are compared, besides file events. */
383
+ const WATCH_POLL_MS = 2e3;
384
+ /** Directories a watch never descends into. */
385
+ const UNWATCHED = /* @__PURE__ */ new Set([
386
+ "node_modules",
387
+ ".git",
388
+ ".mostra"
389
+ ]);
390
+ /** The sizes and change times of the files under `dir` that `matches`, as one string. */
391
+ function fingerprintOf(dir, matches) {
392
+ const parts = [];
393
+ const walk = (relativeDir, depth) => {
394
+ if (depth > 16) return;
395
+ let entries;
396
+ try {
397
+ entries = readdirSync(join(dir, relativeDir), { withFileTypes: true });
398
+ } catch {
399
+ return;
400
+ }
401
+ for (const entry of entries) {
402
+ const path = relativeDir ? `${relativeDir}/${entry.name}` : entry.name;
403
+ if (entry.isDirectory()) {
404
+ if (!UNWATCHED.has(entry.name)) walk(path, depth + 1);
405
+ } else if (matches(path)) try {
406
+ const stats = statSync(join(dir, path));
407
+ parts.push(`${path}:${stats.size}:${stats.mtimeMs}`);
408
+ } catch {}
409
+ }
410
+ };
411
+ walk("", 0);
412
+ return parts.sort().join("|");
413
+ }
414
+ /** One running live source: its loads, refreshes, file watching and stream (D56). */
415
+ var Producer = class {
416
+ #key;
417
+ #source;
418
+ #sourceDir;
419
+ #peer;
420
+ #controller;
421
+ #timer;
422
+ #watcher;
423
+ #poll;
424
+ #debounce;
425
+ #loading = false;
426
+ #again = false;
427
+ constructor(key, source, sourceDir, peer) {
428
+ this.#key = key;
429
+ this.#source = source;
430
+ this.#sourceDir = sourceDir;
431
+ this.#peer = peer;
432
+ }
433
+ start() {
434
+ if (this.#controller) return;
435
+ const controller = new AbortController();
436
+ this.#controller = controller;
437
+ if (this.#source.load) {
438
+ this.refresh();
439
+ if (this.#source.refresh) this.#timer = setInterval(() => this.refresh(), parseDuration(this.#source.refresh));
440
+ if (this.#source.watch !== void 0) this.#watch();
441
+ }
442
+ if (this.#source.stream) this.#stream(controller.signal);
443
+ }
444
+ stop() {
445
+ this.#controller?.abort();
446
+ this.#controller = void 0;
447
+ if (this.#timer !== void 0) clearInterval(this.#timer);
448
+ this.#timer = void 0;
449
+ if (this.#debounce !== void 0) clearTimeout(this.#debounce);
450
+ this.#watcher?.close();
451
+ this.#watcher = void 0;
452
+ if (this.#poll !== void 0) clearInterval(this.#poll);
453
+ this.#poll = void 0;
454
+ }
455
+ /** Loads again now; a load already running is followed by one more. */
456
+ refresh() {
457
+ const load = this.#source.load;
458
+ if (!load || !this.#controller) return;
459
+ if (this.#loading) {
460
+ this.#again = true;
461
+ return;
462
+ }
463
+ this.#loading = true;
464
+ (async () => {
465
+ try {
466
+ do {
467
+ this.#again = false;
468
+ try {
469
+ await this.#publish(await load());
470
+ } catch (error) {
471
+ this.#fail(error);
472
+ }
473
+ } while (this.#again && this.#controller);
474
+ } finally {
475
+ this.#loading = false;
476
+ }
477
+ })();
478
+ }
479
+ #watch() {
480
+ const globs = typeof this.#source.watch === "string" ? [this.#source.watch] : [...this.#source.watch ?? []];
481
+ const dir = this.#sourceDir;
482
+ if (!dir) {
483
+ this.#fail(Object.assign(/* @__PURE__ */ new Error(`The live source ${this.#key} watches files, but its artifact's source directory is gone.`), { code: "MOSTRA_LIVE_SOURCE_FAILED" }));
484
+ return;
485
+ }
486
+ const patterns = globs.map((glob) => glob.replace(/^\.\//, ""));
487
+ const matches = (path) => patterns.some((pattern) => matchesGlob(path, pattern));
488
+ const changed = () => {
489
+ if (this.#debounce !== void 0) clearTimeout(this.#debounce);
490
+ this.#debounce = setTimeout(() => this.refresh(), 100);
491
+ };
492
+ try {
493
+ this.#watcher = watch(dir, { recursive: true }, (_event, name) => {
494
+ if (name === null) return;
495
+ const path = relative(dir, resolve(dir, name.toString())).split(sep).join("/");
496
+ if (matches(path)) changed();
497
+ });
498
+ } catch (error) {
499
+ this.#fail(error);
500
+ return;
501
+ }
502
+ let fingerprint = fingerprintOf(dir, matches);
503
+ this.#poll = setInterval(() => {
504
+ const next = fingerprintOf(dir, matches);
505
+ if (next !== fingerprint) {
506
+ fingerprint = next;
507
+ changed();
508
+ }
509
+ }, WATCH_POLL_MS);
510
+ }
511
+ async #stream(signal) {
512
+ const stream = this.#source.stream;
513
+ if (!stream) return;
514
+ let backoff = 1e3;
515
+ while (!signal.aborted) try {
516
+ for await (const value of stream(signal)) {
517
+ if (signal.aborted) return;
518
+ await this.#publish(value);
519
+ backoff = 1e3;
520
+ }
521
+ return;
522
+ } catch (error) {
523
+ if (signal.aborted) return;
524
+ this.#fail(error);
525
+ await new Promise((resolve) => setTimeout(resolve, backoff));
526
+ backoff = Math.min(backoff * 2, 6e4);
527
+ }
528
+ }
529
+ async #publish(value) {
530
+ if (!this.#controller) return;
531
+ let batches;
532
+ try {
533
+ batches = await serializeAll(value, { mode: "argument" });
534
+ } catch (error) {
535
+ this.#fail(error);
536
+ return;
537
+ }
538
+ this.#peer.notify(WORKER_METHODS.liveValue, {
539
+ key: this.#key,
540
+ value: batches
541
+ });
542
+ }
543
+ #fail(error) {
544
+ const failure = wireError(error);
545
+ this.#peer.notify(WORKER_METHODS.liveValue, {
546
+ key: this.#key,
547
+ error: {
548
+ message: failure.message,
549
+ code: failure.code && /^MOSTRA_/.test(failure.code) ? failure.code : "MOSTRA_LIVE_SOURCE_FAILED"
550
+ }
551
+ });
552
+ }
553
+ };
554
+ //#endregion
555
+ export { runWorker as t };
556
+
557
+ //# sourceMappingURL=worker-qog0hvgA.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker-qog0hvgA.js","names":["watchFiles"],"sources":["../src/worker.ts"],"sourcesContent":["/**\n * The worker's main thread (ARCHITECTURE §7, D124): loads one artifact version's server bundle and\n * runs its server functions and live producers, each call inside the request context of\n * `@mostra/server` (D19 seam 3). It speaks the worker channel (`@mostra/protocol`'s `worker.ts`)\n * through its channel thread, never sees a cookie, a token or a raw browser request, and gets\n * secrets only by asking for them by name.\n */\nimport {\n type Dirent,\n type FSWatcher,\n readdirSync,\n realpathSync,\n statSync,\n watch as watchFiles,\n} from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport { isBuiltin, registerHooks } from \"node:module\";\nimport { join, matchesGlob, relative, resolve, sep } from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport { Worker } from \"node:worker_threads\";\nimport {\n type Batches,\n createDiagnostic,\n deserializeAll,\n encodeLine,\n type Frame,\n type LiveSourceInfo,\n RpcError,\n RpcPeer,\n SerializationError,\n serializeAll,\n ValueWriter,\n WORKER_CHANNEL_REVISION,\n WORKER_METHODS,\n type WorkerCallOutcome,\n WorkerCallParams,\n WorkerStartParams,\n type WorkerStartResult,\n wireError,\n} from \"@mostra/protocol\";\nimport {\n currentCall,\n installServerHost,\n type LiveSourceOptions,\n liveSourceOptions,\n parseDuration,\n runWithContext,\n type StateSnapshot,\n} from \"@mostra/server/host\";\nimport { createSharedState, SECRET_SLOT, sharedViews } from \"./shared.ts\";\n\n/** How the worker is started. */\nexport interface WorkerOptions {\n /** `fd:<n>` (a pipe the launcher passed) or `unix:<path>` (a socket to connect to). */\n readonly channel: string;\n /** The version's directory, which the launcher resolved from the version reference. */\n readonly versionDir: string;\n /** The artifact's source directory, when it still exists: `watch` globs are relative to it. */\n readonly sourceDir?: string;\n /**\n * The `node_modules` the version's packages resolve from (D135): the layout of the version's\n * lockfile, or the warm set's. The server bundle keeps every package import external, so the\n * packages run from their own directories: native addons load, and files a package reads\n * beside itself are there.\n */\n readonly modules?: string;\n}\n\ntype AnyFunction = (...args: unknown[]) => unknown;\n\n/** The longest wait for a secret: the host port's 30 s and a margin. */\nconst SECRET_WAIT_MS = 40_000;\n\n/** How often the event loop proves it turns, for the watchdog (D62). */\nconst BEAT_MS = 100;\n\nconst ownExtension = import.meta.url.endsWith(\".ts\") ? \".ts\" : \".js\";\n\n/** Whether `specifier` names a package (`react`, `@scope/name/sub`), not a path, URL or built-in. */\nfunction isPackageSpecifier(specifier: string): boolean {\n if (specifier.startsWith(\".\") || specifier.startsWith(\"/\") || specifier.startsWith(\"#\")) {\n return false;\n }\n if (/^[a-z][a-z0-9+.-]*:/i.test(specifier)) return false; // node:, file:, data:, https:\n return !isBuiltin(specifier);\n}\n\n/**\n * Resolves the version's imports (D135): `@mostra/server` is this worker's own copy, so they share\n * context; every other package the server bundle imports resolves from `modules`, the layout the\n * version was built against, as though the bundle sat beside it. Imports inside packages resolve\n * as Node resolves them, from the packages' own directories.\n */\nfunction resolveVersionImports(versionDir: string, modules: string | undefined): void {\n const entries = {\n \"@mostra/server\": import.meta.resolve(\"@mostra/server\"),\n \"@mostra/server/host\": import.meta.resolve(\"@mostra/server/host\"),\n } as Record<string, string>;\n // The bundle's imports name it by its real path (Node resolves symlinks), the launcher's\n // argument perhaps through one (macOS's /tmp): either form is the version.\n const versionUrls = [resolve(versionDir), realpathSync(versionDir)].map(\n (dir) => `${pathToFileURL(dir).href}/`,\n );\n const layoutParent =\n modules === undefined\n ? undefined\n : pathToFileURL(join(modules, \"..\", \"mostra-server.mjs\")).href;\n registerHooks({\n resolve(specifier, context, next) {\n const url = entries[specifier];\n if (url) return { url, shortCircuit: true };\n if (\n layoutParent !== undefined &&\n versionUrls.some((url) => context.parentURL?.startsWith(url) === true) &&\n isPackageSpecifier(specifier)\n ) {\n return next(specifier, { ...context, parentURL: layoutParent });\n }\n return next(specifier, context);\n },\n });\n}\n\ninterface Call {\n readonly controller: AbortController;\n readonly pending: Set<Promise<unknown>>;\n writer?: ValueWriter;\n}\n\n/** Runs a worker until its channel closes. */\nexport async function runWorker(options: WorkerOptions): Promise<void> {\n resolveVersionImports(options.versionDir, options.modules);\n const shared = createSharedState();\n const views = sharedViews(shared);\n const thread = new Worker(new URL(`./channel-thread${ownExtension}`, import.meta.url), {\n workerData: { channel: options.channel, shared },\n });\n thread.unref();\n\n const beat = (): void => {\n Atomics.store(views.beat, 0, BigInt(Date.now()));\n Atomics.store(views.beat, 1, BigInt(process.memoryUsage().heapUsed));\n };\n beat();\n setInterval(beat, BEAT_MS);\n\n const calls = new Map<string, Call>();\n const functions = new Map<string, AnyFunction>();\n const ids = new Map<AnyFunction, string>();\n const producers = new Map<string, Producer>();\n const sources = new Map<string, LiveSourceOptions<unknown>>();\n\n const shutdown = (code: number): never => {\n for (const producer of producers.values()) producer.stop();\n try {\n // Children of server code die with the worker (it leads its own process group).\n process.kill(-process.pid, \"SIGTERM\");\n } catch {\n // Not a group leader (a launcher that runs the worker elsewhere): only this process ends.\n }\n process.exit(code);\n };\n\n const peer: RpcPeer = new RpcPeer({\n send(message) {\n thread.postMessage({ type: \"line\", line: encodeLine(message) });\n },\n onRequest(method, params) {\n switch (method) {\n case WORKER_METHODS.start:\n return start(params);\n case WORKER_METHODS.call:\n return call(params);\n case WORKER_METHODS.liveStart:\n return liveStart(params);\n case WORKER_METHODS.liveStop: {\n const key = String((params as { key?: unknown }).key);\n producers.get(key)?.stop();\n producers.delete(key);\n return {};\n }\n case WORKER_METHODS.stop:\n setImmediate(() => shutdown(0));\n return {};\n default:\n throw new RpcError(\n createDiagnostic(\"MOSTRA_HOST_METHOD_UNKNOWN\", {\n message: `The worker serves no method ${method}.`,\n }),\n );\n }\n },\n onNotification(method, params) {\n if (method === WORKER_METHODS.cancel) {\n const { callId, reason } = params as { callId?: string; reason?: string };\n const entry = callId === undefined ? undefined : calls.get(callId);\n if (entry) {\n const error = new Error(reason ?? \"The run was cancelled.\");\n (error as Error & { code: string }).code = \"MOSTRA_ACTION_CANCELLED\";\n error.name = \"AbortError\";\n entry.controller.abort(error);\n }\n } else if (method === WORKER_METHODS.liveRefresh) {\n producers.get(String((params as { key?: unknown }).key))?.refresh();\n }\n },\n onInternalError(error) {\n process.stderr.write(`mostra worker: ${(error as Error)?.stack ?? String(error)}\\n`);\n },\n });\n\n thread.on(\"message\", (message: { type: string; line?: string }) => {\n if (message.type === \"line\" && message.line !== undefined) peer.receiveLine(message.line);\n else if (message.type === \"closed\") shutdown(0);\n });\n thread.on(\"error\", (error) => {\n process.stderr.write(`mostra worker: the channel failed: ${error.message}\\n`);\n shutdown(1);\n });\n thread.on(\"exit\", () => shutdown(0));\n\n // ── @mostra/server's host ────────────────────────────────────────────────────────────────\n\n const track = (callId: string | undefined, promise: Promise<unknown>): void => {\n const entry = callId === undefined ? undefined : calls.get(callId);\n const settled = promise.catch((error: unknown) => {\n const line = `${(error as Error)?.message ?? String(error)}`;\n peer.notify(WORKER_METHODS.log, {\n ...(callId === undefined ? {} : { callId }),\n line: `Mostra couldn't record it: ${line}`,\n });\n });\n if (entry) {\n entry.pending.add(settled);\n void settled.finally(() => entry.pending.delete(settled));\n }\n };\n\n installServerHost({\n secret(name) {\n Atomics.store(views.control, SECRET_SLOT.state, 1);\n thread.postMessage({ type: \"secret\", name });\n const outcome = Atomics.wait(views.control, SECRET_SLOT.state, 1, SECRET_WAIT_MS);\n const length = Atomics.load(views.control, SECRET_SLOT.length);\n const status = Atomics.load(views.control, SECRET_SLOT.status);\n const text = new TextDecoder().decode(views.secretBytes.slice(0, length));\n Atomics.store(views.control, SECRET_SLOT.state, 0);\n if (outcome === \"timed-out\") {\n throw Object.assign(new Error(`Reading the secret ${name} timed out.`), {\n code: \"MOSTRA_SECRET_MISSING\",\n });\n }\n if (status !== 0) {\n const failure = JSON.parse(text) as { code: string; message: string };\n throw Object.assign(new Error(failure.message), { code: failure.code });\n }\n return text;\n },\n progress(callId, p) {\n peer.notify(WORKER_METHODS.progress, { callId, ...p });\n },\n log(callId, line) {\n peer.notify(WORKER_METHODS.log, { ...(callId === undefined ? {} : { callId }), line });\n },\n signal(callId, name, payload) {\n track(\n callId,\n peer.request(WORKER_METHODS.signal, {\n ...(callId === undefined ? {} : { callId }),\n name,\n ...(payload === undefined ? {} : { payload }),\n }),\n );\n },\n emit(callId, type, payload) {\n track(\n callId,\n peer.request(WORKER_METHODS.emit, {\n ...(callId === undefined ? {} : { callId }),\n type,\n ...(payload === undefined ? {} : { payload }),\n }),\n );\n },\n async stateGet(stateIds) {\n return (await peer.request(WORKER_METHODS.stateGet, {\n ...(stateIds === undefined ? {} : { ids: [...stateIds] }),\n })) as StateSnapshot;\n },\n async statePatch(callId, ops, writeOptions) {\n return (await peer.request(WORKER_METHODS.statePatch, {\n ...(callId === undefined ? {} : { callId }),\n ops: [...ops],\n ...writeOptions,\n })) as never;\n },\n });\n\n // Console output inside a call also goes to its run's log.\n for (const level of [\"log\", \"info\", \"warn\", \"error\", \"debug\"] as const) {\n const original = console[level].bind(console);\n console[level] = (...args: unknown[]) => {\n original(...args);\n const active = currentCall();\n if (active) {\n const line = args\n .map((arg) => (typeof arg === \"string\" ? arg : inspectLine(arg)))\n .join(\" \");\n peer.notify(WORKER_METHODS.log, { callId: active.callId, line });\n }\n };\n }\n\n // ── Requests ─────────────────────────────────────────────────────────────────────────────\n\n async function start(raw: unknown): Promise<WorkerStartResult> {\n const params = WorkerStartParams.parse(raw);\n const manifest = JSON.parse(\n await readFile(join(options.versionDir, \"manifest.json\"), \"utf8\"),\n ) as { outputDigest?: string };\n if (manifest.outputDigest !== params.version.outputDigest) {\n throw new RpcError(\n createDiagnostic(\"MOSTRA_HOME_INTEGRITY\", {\n message: `The version directory doesn't hold ${params.version.versionId}: its output digest differs.`,\n }),\n );\n }\n const entry = resolve(options.versionDir, params.entry);\n if (!entry.startsWith(`${resolve(options.versionDir)}${sep}`)) {\n throw new RpcError(\n createDiagnostic(\"MOSTRA_HOME_INTEGRITY\", {\n message: \"The server entry leaves the version.\",\n }),\n );\n }\n const bundle = (await import(pathToFileURL(entry).href)) as {\n functions?: Record<string, unknown>;\n live?: Record<string, unknown>;\n };\n for (const [id, fn] of Object.entries(bundle.functions ?? {})) {\n if (typeof fn !== \"function\") continue;\n functions.set(id, fn as AnyFunction);\n ids.set(fn as AnyFunction, id);\n }\n const live: LiveSourceInfo[] = [];\n for (const [key, value] of Object.entries(bundle.live ?? {})) {\n const source = liveSourceOptions(value);\n if (!source) continue;\n sources.set(key, source);\n live.push(describeSource(key, source));\n }\n return { revision: WORKER_CHANNEL_REVISION, functions: [...functions.keys()], live };\n }\n\n async function call(raw: unknown): Promise<WorkerCallOutcome> {\n const params = WorkerCallParams.parse(raw);\n const fn = functions.get(params.fnId);\n if (!fn) {\n return {\n status: \"failed\",\n error: {\n code: \"MOSTRA_ACTION_UNKNOWN_FUNCTION\",\n message: `This version has no server function ${params.fnId}.`,\n },\n };\n }\n const entry: Call = { controller: new AbortController(), pending: new Set() };\n calls.set(params.callId, entry);\n try {\n let args: unknown;\n try {\n // A page's arguments arrive whole and are read in argument mode: no symbols or\n // iterables, bounded bigints, and every promise in them settled (Opus review 1, 13).\n args = await deserializeAll(params.args, {\n mode: \"argument\",\n serverFunction: (id) => serverFunction(id),\n });\n } catch (error) {\n return { status: \"failed\", error: errorOf(error, \"MOSTRA_ACTION_UNSERIALIZABLE\") };\n }\n if (!Array.isArray(args)) {\n return {\n status: \"failed\",\n error: { code: \"MOSTRA_ACTION_UNSERIALIZABLE\", message: \"The arguments aren't a list.\" },\n };\n }\n const context = {\n kind: params.context.kind,\n callId: params.callId,\n dryRun: params.context.dryRun,\n signal: entry.controller.signal,\n ...(params.context.runId === undefined ? {} : { runId: params.context.runId }),\n ...(params.context.viewer === undefined ? {} : { viewer: params.context.viewer }),\n } satisfies Parameters<typeof runWithContext>[0];\n let result: unknown;\n try {\n result = await runWithContext(context, () => fn(...(args as unknown[])));\n } catch (error) {\n await settlePending(entry);\n if (entry.controller.signal.aborted && isAbort(error, entry.controller.signal)) {\n return { status: \"cancelled\" };\n }\n return { status: \"failed\", error: errorOf(error, \"MOSTRA_ACTION_THREW\") };\n }\n const writer = new ValueWriter({\n mode: \"result\",\n serverFunctionId: (candidate) => ids.get(candidate as AnyFunction),\n onBatch: (batch) =>\n peer.notify(WORKER_METHODS.batch, { callId: params.callId, batch: batch as Frame[] }),\n });\n entry.writer = writer;\n const stop = (): void => writer.abort();\n try {\n await runWithContext(context, async () => {\n await writer.write(result);\n // The action returned, so it ran to its end (FAILURE_MODEL §6, AC-04): a cancel from\n // here on stops only the parts of the result still streaming, and the run is\n // `cancelled` only if it cut one short.\n if (entry.controller.signal.aborted) writer.abort();\n else entry.controller.signal.addEventListener(\"abort\", stop, { once: true });\n await writer.done;\n });\n } catch (error) {\n await settlePending(entry);\n return {\n status: \"failed\",\n error: errorOf(\n error,\n error instanceof SerializationError ? error.code : \"MOSTRA_ACTION_THREW\",\n ),\n };\n }\n await settlePending(entry);\n return { status: writer.cutShort ? \"cancelled\" : \"succeeded\" };\n } finally {\n calls.delete(params.callId);\n }\n }\n\n async function settlePending(entry: Call): Promise<void> {\n while (entry.pending.size > 0) await Promise.all([...entry.pending]);\n }\n\n function serverFunction(id: string): AnyFunction {\n const fn = functions.get(id);\n if (!fn) throw new SerializationError(`names no server function of this version (${id}).`);\n return fn;\n }\n\n function liveStart(raw: unknown): Record<string, never> {\n const key = String((raw as { key?: unknown }).key);\n if (producers.has(key)) return {};\n const source = sources.get(key);\n if (!source) {\n throw new RpcError(\n createDiagnostic(\"MOSTRA_LIVE_SOURCE_FAILED\", {\n message: `live.ts defines no live source ${key}.`,\n }),\n );\n }\n const producer = new Producer(key, source, options.sourceDir, peer);\n producers.set(key, producer);\n producer.start();\n return {};\n }\n\n // The worker lives until its channel closes (`shutdown`).\n await new Promise<never>(() => {});\n}\n\nfunction inspectLine(value: unknown): string {\n try {\n return typeof value === \"object\" ? JSON.stringify(value) : String(value);\n } catch {\n return String(value);\n }\n}\n\nfunction isAbort(error: unknown, signal: AbortSignal): boolean {\n return error === signal.reason || (error as Error)?.name === \"AbortError\";\n}\n\nfunction errorOf(\n error: unknown,\n fallback: string,\n): { code: string; message: string; stack?: string } {\n const code = (error as { code?: unknown })?.code;\n const message = error instanceof Error ? error.message : String(error);\n const stack = error instanceof Error ? error.stack : undefined;\n return {\n code: typeof code === \"string\" && /^MOSTRA_[A-Z]+_[A-Z0-9_]+$/.test(code) ? code : fallback,\n message,\n ...(stack === undefined ? {} : { stack }),\n };\n}\n\nfunction describeSource(key: string, source: LiveSourceOptions<unknown>): LiveSourceInfo {\n const watch =\n source.watch === undefined\n ? undefined\n : typeof source.watch === \"string\"\n ? [source.watch]\n : [...source.watch];\n return {\n key,\n load: typeof source.load === \"function\",\n stream: typeof source.stream === \"function\",\n always: source.always === true,\n ...(source.refresh === undefined ? {} : { refreshMs: parseDuration(source.refresh) }),\n ...(watch === undefined ? {} : { watch }),\n ...(source.ring === undefined ? {} : { ring: source.ring }),\n };\n}\n\n/** How often watched files are compared, besides file events. */\nconst WATCH_POLL_MS = 2000;\n\n/** Directories a watch never descends into. */\nconst UNWATCHED = new Set([\"node_modules\", \".git\", \".mostra\"]);\n\n/** The sizes and change times of the files under `dir` that `matches`, as one string. */\nfunction fingerprintOf(dir: string, matches: (path: string) => boolean): string {\n const parts: string[] = [];\n const walk = (relativeDir: string, depth: number): void => {\n if (depth > 16) return;\n let entries: Dirent[];\n try {\n entries = readdirSync(join(dir, relativeDir), { withFileTypes: true });\n } catch {\n return;\n }\n for (const entry of entries) {\n const path = relativeDir ? `${relativeDir}/${entry.name}` : entry.name;\n if (entry.isDirectory()) {\n if (!UNWATCHED.has(entry.name)) walk(path, depth + 1);\n } else if (matches(path)) {\n try {\n const stats = statSync(join(dir, path));\n parts.push(`${path}:${stats.size}:${stats.mtimeMs}`);\n } catch {\n // Removed while walking: the next comparison sees it.\n }\n }\n }\n };\n walk(\"\", 0);\n return parts.sort().join(\"|\");\n}\n\n/** One running live source: its loads, refreshes, file watching and stream (D56). */\nclass Producer {\n readonly #key: string;\n readonly #source: LiveSourceOptions<unknown>;\n readonly #sourceDir: string | undefined;\n readonly #peer: RpcPeer;\n #controller: AbortController | undefined;\n #timer: ReturnType<typeof setInterval> | undefined;\n #watcher: FSWatcher | undefined;\n #poll: ReturnType<typeof setInterval> | undefined;\n #debounce: ReturnType<typeof setTimeout> | undefined;\n #loading = false;\n #again = false;\n\n constructor(\n key: string,\n source: LiveSourceOptions<unknown>,\n sourceDir: string | undefined,\n peer: RpcPeer,\n ) {\n this.#key = key;\n this.#source = source;\n this.#sourceDir = sourceDir;\n this.#peer = peer;\n }\n\n start(): void {\n if (this.#controller) return;\n const controller = new AbortController();\n this.#controller = controller;\n if (this.#source.load) {\n this.refresh();\n if (this.#source.refresh) {\n this.#timer = setInterval(() => this.refresh(), parseDuration(this.#source.refresh));\n }\n if (this.#source.watch !== undefined) this.#watch();\n }\n if (this.#source.stream) void this.#stream(controller.signal);\n }\n\n stop(): void {\n this.#controller?.abort();\n this.#controller = undefined;\n if (this.#timer !== undefined) clearInterval(this.#timer);\n this.#timer = undefined;\n if (this.#debounce !== undefined) clearTimeout(this.#debounce);\n this.#watcher?.close();\n this.#watcher = undefined;\n if (this.#poll !== undefined) clearInterval(this.#poll);\n this.#poll = undefined;\n }\n\n /** Loads again now; a load already running is followed by one more. */\n refresh(): void {\n const load = this.#source.load;\n if (!load || !this.#controller) return;\n if (this.#loading) {\n this.#again = true;\n return;\n }\n this.#loading = true;\n void (async () => {\n try {\n do {\n this.#again = false;\n try {\n await this.#publish(await load());\n } catch (error) {\n this.#fail(error);\n }\n } while (this.#again && this.#controller);\n } finally {\n this.#loading = false;\n }\n })();\n }\n\n #watch(): void {\n const globs =\n typeof this.#source.watch === \"string\"\n ? [this.#source.watch]\n : [...(this.#source.watch ?? [])];\n const dir = this.#sourceDir;\n if (!dir) {\n this.#fail(\n Object.assign(\n new Error(\n `The live source ${this.#key} watches files, but its artifact's source directory is gone.`,\n ),\n { code: \"MOSTRA_LIVE_SOURCE_FAILED\" },\n ),\n );\n return;\n }\n const patterns = globs.map((glob) => glob.replace(/^\\.\\//, \"\"));\n const matches = (path: string): boolean =>\n patterns.some((pattern) => matchesGlob(path, pattern));\n const changed = (): void => {\n if (this.#debounce !== undefined) clearTimeout(this.#debounce);\n this.#debounce = setTimeout(() => this.refresh(), 100);\n };\n try {\n this.#watcher = watchFiles(dir, { recursive: true }, (_event, name) => {\n if (name === null) return;\n const path = relative(dir, resolve(dir, name.toString())).split(sep).join(\"/\");\n if (matches(path)) changed();\n });\n } catch (error) {\n this.#fail(error);\n return;\n }\n // File events can be dropped (macOS coalesces and delays them), so the matching files'\n // sizes and times are also compared every two seconds: a change is never missed for long.\n let fingerprint = fingerprintOf(dir, matches);\n this.#poll = setInterval(() => {\n const next = fingerprintOf(dir, matches);\n if (next !== fingerprint) {\n fingerprint = next;\n changed();\n }\n }, WATCH_POLL_MS);\n }\n\n async #stream(signal: AbortSignal): Promise<void> {\n const stream = this.#source.stream;\n if (!stream) return;\n let backoff = 1_000;\n while (!signal.aborted) {\n try {\n for await (const value of stream(signal)) {\n if (signal.aborted) return;\n await this.#publish(value);\n backoff = 1_000;\n }\n return;\n } catch (error) {\n if (signal.aborted) return;\n this.#fail(error);\n await new Promise((resolve) => setTimeout(resolve, backoff));\n backoff = Math.min(backoff * 2, 60_000);\n }\n }\n }\n\n async #publish(value: unknown): Promise<void> {\n if (!this.#controller) return;\n let batches: Batches;\n try {\n batches = await serializeAll(value, { mode: \"argument\" });\n } catch (error) {\n this.#fail(error);\n return;\n }\n this.#peer.notify(WORKER_METHODS.liveValue, {\n key: this.#key,\n value: batches as unknown as Batches,\n } as never);\n }\n\n #fail(error: unknown): void {\n const failure = wireError(error);\n this.#peer.notify(WORKER_METHODS.liveValue, {\n key: this.#key,\n error: {\n message: failure.message,\n code:\n failure.code && /^MOSTRA_/.test(failure.code)\n ? failure.code\n : \"MOSTRA_LIVE_SOURCE_FAILED\",\n },\n });\n }\n}\n"],"mappings":"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"}