@camstack/server 1.1.42 → 1.1.44

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,1124 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
9
+ var __commonJS = (cb, mod) => function __require() {
10
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
11
+ };
12
+ var __export = (target, all) => {
13
+ for (var name in all)
14
+ __defProp(target, name, { get: all[name], enumerable: true });
15
+ };
16
+ var __copyProps = (to, from, except, desc) => {
17
+ if (from && typeof from === "object" || typeof from === "function") {
18
+ for (let key of __getOwnPropNames(from))
19
+ if (!__hasOwnProp.call(to, key) && key !== except)
20
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
21
+ }
22
+ return to;
23
+ };
24
+ var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
25
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
26
+ // If the importer is in node compatibility mode or this is not an ESM
27
+ // file that has been converted to a CommonJS file using a Babel-
28
+ // compatible transform (i.e. "__esModule" has not been set), then set
29
+ // "default" to the CommonJS "module.exports" for node compatibility.
30
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
31
+ mod
32
+ ));
33
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
34
+
35
+ // ../../packages/node-root/dist/index.js
36
+ var require_dist = __commonJS({
37
+ "../../packages/node-root/dist/index.js"(exports2, module2) {
38
+ "use strict";
39
+ var __create2 = Object.create;
40
+ var __defProp2 = Object.defineProperty;
41
+ var __getOwnPropDesc2 = Object.getOwnPropertyDescriptor;
42
+ var __getOwnPropNames2 = Object.getOwnPropertyNames;
43
+ var __getProtoOf2 = Object.getPrototypeOf;
44
+ var __hasOwnProp2 = Object.prototype.hasOwnProperty;
45
+ var __export2 = /* @__PURE__ */ __name((target, all) => {
46
+ for (var name in all) __defProp2(target, name, {
47
+ get: all[name],
48
+ enumerable: true
49
+ });
50
+ }, "__export");
51
+ var __copyProps2 = /* @__PURE__ */ __name((to, from, except, desc) => {
52
+ if (from && typeof from === "object" || typeof from === "function") {
53
+ for (let key of __getOwnPropNames2(from)) if (!__hasOwnProp2.call(to, key) && key !== except) __defProp2(to, key, {
54
+ get: /* @__PURE__ */ __name(() => from[key], "get"),
55
+ enumerable: !(desc = __getOwnPropDesc2(from, key)) || desc.enumerable
56
+ });
57
+ }
58
+ return to;
59
+ }, "__copyProps");
60
+ var __toESM2 = /* @__PURE__ */ __name((mod, isNodeMode, target) => (target = mod != null ? __create2(__getProtoOf2(mod)) : {}, __copyProps2(
61
+ // If the importer is in node compatibility mode or this is not an ESM
62
+ // file that has been converted to a CommonJS file using a Babel-
63
+ // compatible transform (i.e. "__esModule" has not been set), then set
64
+ // "default" to the CommonJS "module.exports" for node compatibility.
65
+ isNodeMode || !mod || !mod.__esModule ? __defProp2(target, "default", {
66
+ value: mod,
67
+ enumerable: true
68
+ }) : target,
69
+ mod
70
+ )), "__toESM");
71
+ var __toCommonJS2 = /* @__PURE__ */ __name((mod) => __copyProps2(__defProp2({}, "__esModule", {
72
+ value: true
73
+ }), mod), "__toCommonJS");
74
+ var src_exports = {};
75
+ __export2(src_exports, {
76
+ AGENT_ROOT_SPEC: /* @__PURE__ */ __name(() => AGENT_ROOT_SPEC, "AGENT_ROOT_SPEC"),
77
+ HOST_EXTERNAL_SPECIFIERS: /* @__PURE__ */ __name(() => HOST_EXTERNAL_SPECIFIERS, "HOST_EXTERNAL_SPECIFIERS"),
78
+ HUB_ROOT_SPEC: /* @__PURE__ */ __name(() => HUB_ROOT_SPEC2, "HUB_ROOT_SPEC"),
79
+ RESTART_INTENT_FILE: /* @__PURE__ */ __name(() => RESTART_INTENT_FILE, "RESTART_INTENT_FILE"),
80
+ RootUpdateService: /* @__PURE__ */ __name(() => RootUpdateService, "RootUpdateService"),
81
+ SERVER_ROOT_DIRNAME: /* @__PURE__ */ __name(() => SERVER_ROOT_DIRNAME, "SERVER_ROOT_DIRNAME"),
82
+ SERVER_ROOT_STATE_FILE: /* @__PURE__ */ __name(() => SERVER_ROOT_STATE_FILE, "SERVER_ROOT_STATE_FILE"),
83
+ clearRestartIntentMarker: /* @__PURE__ */ __name(() => clearRestartIntentMarker, "clearRestartIntentMarker"),
84
+ compareSemver: /* @__PURE__ */ __name(() => compareSemver, "compareSemver"),
85
+ detectWorkspaceRoot: /* @__PURE__ */ __name(() => detectWorkspaceRoot, "detectWorkspaceRoot"),
86
+ emptyServerRootState: /* @__PURE__ */ __name(() => emptyServerRootState, "emptyServerRootState"),
87
+ isHostExternal: /* @__PURE__ */ __name(() => isHostExternal, "isHostExternal"),
88
+ isServerRootState: /* @__PURE__ */ __name(() => isServerRootState, "isServerRootState"),
89
+ minNodeMajorOf: /* @__PURE__ */ __name(() => minNodeMajorOf, "minNodeMajorOf"),
90
+ planBoot: /* @__PURE__ */ __name(() => planBoot, "planBoot"),
91
+ readRestartIntentMarker: /* @__PURE__ */ __name(() => readRestartIntentMarker, "readRestartIntentMarker"),
92
+ readServerRootState: /* @__PURE__ */ __name(() => readServerRootState, "readServerRootState"),
93
+ registerActiveRootResolver: /* @__PURE__ */ __name(() => registerActiveRootResolver, "registerActiveRootResolver"),
94
+ restartIntentMarkerPath: /* @__PURE__ */ __name(() => restartIntentMarkerPath, "restartIntentMarkerPath"),
95
+ rootEntryPath: /* @__PURE__ */ __name(() => rootEntryPath2, "rootEntryPath"),
96
+ rootPackageDir: /* @__PURE__ */ __name(() => rootPackageDir2, "rootPackageDir"),
97
+ runNodeStarter: /* @__PURE__ */ __name(() => runNodeStarter, "runNodeStarter"),
98
+ serverRootDir: /* @__PURE__ */ __name(() => serverRootDir, "serverRootDir"),
99
+ stateFilePath: /* @__PURE__ */ __name(() => stateFilePath, "stateFilePath"),
100
+ validateVersionDir: /* @__PURE__ */ __name(() => validateVersionDir, "validateVersionDir"),
101
+ versionDir: /* @__PURE__ */ __name(() => versionDir, "versionDir"),
102
+ versionsDir: /* @__PURE__ */ __name(() => versionsDir, "versionsDir"),
103
+ writeRestartIntentMarker: /* @__PURE__ */ __name(() => writeRestartIntentMarker, "writeRestartIntentMarker"),
104
+ writeServerRootState: /* @__PURE__ */ __name(() => writeServerRootState, "writeServerRootState")
105
+ });
106
+ module2.exports = __toCommonJS2(src_exports);
107
+ var HUB_ROOT_SPEC2 = {
108
+ packageName: "@camstack/server",
109
+ entryRelPath: [
110
+ "dist",
111
+ "launcher.js"
112
+ ]
113
+ };
114
+ var AGENT_ROOT_SPEC = {
115
+ packageName: "@camstack/agent",
116
+ entryRelPath: [
117
+ "dist",
118
+ "cli.js"
119
+ ]
120
+ };
121
+ var fs = __toESM2(require("fs"));
122
+ var path = __toESM2(require("path"));
123
+ var SERVER_ROOT_DIRNAME = "server-root";
124
+ var SERVER_ROOT_STATE_FILE = "state.json";
125
+ var RESTART_INTENT_FILE = ".restart-intent";
126
+ function emptyServerRootState() {
127
+ return {
128
+ schemaVersion: 1,
129
+ currentVersion: null,
130
+ previousVersion: null,
131
+ pendingBoot: null,
132
+ rolledBack: null
133
+ };
134
+ }
135
+ __name(emptyServerRootState, "emptyServerRootState");
136
+ function serverRootDir(dataDir) {
137
+ return path.join(dataDir, SERVER_ROOT_DIRNAME);
138
+ }
139
+ __name(serverRootDir, "serverRootDir");
140
+ function versionsDir(rootDir) {
141
+ return path.join(rootDir, "versions");
142
+ }
143
+ __name(versionsDir, "versionsDir");
144
+ function versionDir(rootDir, version) {
145
+ return path.join(versionsDir(rootDir), version);
146
+ }
147
+ __name(versionDir, "versionDir");
148
+ function rootPackageDir2(versionDirPath, spec) {
149
+ return path.join(versionDirPath, "node_modules", ...spec.packageName.split("/"));
150
+ }
151
+ __name(rootPackageDir2, "rootPackageDir");
152
+ function rootEntryPath2(versionDirPath, spec) {
153
+ return path.join(rootPackageDir2(versionDirPath, spec), ...spec.entryRelPath);
154
+ }
155
+ __name(rootEntryPath2, "rootEntryPath");
156
+ function stateFilePath(rootDir) {
157
+ return path.join(rootDir, SERVER_ROOT_STATE_FILE);
158
+ }
159
+ __name(stateFilePath, "stateFilePath");
160
+ function isNullableString(v) {
161
+ return v === null || typeof v === "string";
162
+ }
163
+ __name(isNullableString, "isNullableString");
164
+ function isPendingBoot(v) {
165
+ if (typeof v !== "object" || v === null) return false;
166
+ const p = v;
167
+ return typeof p["version"] === "string" && isNullableString(p["fromVersion"]) && typeof p["requestedAtMs"] === "number" && typeof p["bootAttempts"] === "number";
168
+ }
169
+ __name(isPendingBoot, "isPendingBoot");
170
+ function isRollbackInfo(v) {
171
+ if (typeof v !== "object" || v === null) return false;
172
+ const r = v;
173
+ return typeof r["fromVersion"] === "string" && isNullableString(r["toVersion"]) && typeof r["atMs"] === "number" && typeof r["reason"] === "string";
174
+ }
175
+ __name(isRollbackInfo, "isRollbackInfo");
176
+ function isServerRootState(v) {
177
+ if (typeof v !== "object" || v === null) return false;
178
+ const s = v;
179
+ if (s["schemaVersion"] !== 1) return false;
180
+ if (!isNullableString(s["currentVersion"])) return false;
181
+ if (!isNullableString(s["previousVersion"])) return false;
182
+ if (s["pendingBoot"] !== null && !isPendingBoot(s["pendingBoot"])) return false;
183
+ if (s["rolledBack"] !== null && !isRollbackInfo(s["rolledBack"])) return false;
184
+ return true;
185
+ }
186
+ __name(isServerRootState, "isServerRootState");
187
+ function readServerRootState(rootDir) {
188
+ try {
189
+ const raw = JSON.parse(fs.readFileSync(stateFilePath(rootDir), "utf-8"));
190
+ return isServerRootState(raw) ? raw : null;
191
+ } catch {
192
+ return null;
193
+ }
194
+ }
195
+ __name(readServerRootState, "readServerRootState");
196
+ function writeServerRootState(rootDir, state) {
197
+ fs.mkdirSync(rootDir, {
198
+ recursive: true
199
+ });
200
+ const target = stateFilePath(rootDir);
201
+ const tmp = `${target}.tmp`;
202
+ fs.writeFileSync(tmp, JSON.stringify(state, null, 2), "utf-8");
203
+ fs.renameSync(tmp, target);
204
+ }
205
+ __name(writeServerRootState, "writeServerRootState");
206
+ function restartIntentMarkerPath(rootDir) {
207
+ return path.join(rootDir, RESTART_INTENT_FILE);
208
+ }
209
+ __name(restartIntentMarkerPath, "restartIntentMarkerPath");
210
+ function isRestartIntentMarker(v) {
211
+ if (typeof v !== "object" || v === null) return false;
212
+ const m = v;
213
+ return typeof m["requestedAtMs"] === "number" && typeof m["reason"] === "string";
214
+ }
215
+ __name(isRestartIntentMarker, "isRestartIntentMarker");
216
+ function writeRestartIntentMarker(rootDir, marker) {
217
+ fs.mkdirSync(rootDir, {
218
+ recursive: true
219
+ });
220
+ const target = restartIntentMarkerPath(rootDir);
221
+ const tmp = `${target}.tmp`;
222
+ fs.writeFileSync(tmp, JSON.stringify(marker, null, 2), "utf-8");
223
+ fs.renameSync(tmp, target);
224
+ }
225
+ __name(writeRestartIntentMarker, "writeRestartIntentMarker");
226
+ function readRestartIntentMarker(rootDir) {
227
+ try {
228
+ const raw = JSON.parse(fs.readFileSync(restartIntentMarkerPath(rootDir), "utf-8"));
229
+ return isRestartIntentMarker(raw) ? raw : null;
230
+ } catch {
231
+ return null;
232
+ }
233
+ }
234
+ __name(readRestartIntentMarker, "readRestartIntentMarker");
235
+ function clearRestartIntentMarker(rootDir) {
236
+ try {
237
+ fs.rmSync(restartIntentMarkerPath(rootDir), {
238
+ force: true
239
+ });
240
+ } catch {
241
+ }
242
+ }
243
+ __name(clearRestartIntentMarker, "clearRestartIntentMarker");
244
+ function minNodeMajorOf(enginesNode) {
245
+ const match = /(\d+)/.exec(enginesNode);
246
+ if (match === null) return null;
247
+ const major = Number.parseInt(match[1] ?? "", 10);
248
+ return Number.isNaN(major) ? null : major;
249
+ }
250
+ __name(minNodeMajorOf, "minNodeMajorOf");
251
+ function validateVersionDir(rootDir, version, nodeMajor, spec) {
252
+ const vDir = versionDir(rootDir, version);
253
+ const entry = rootEntryPath2(vDir, spec);
254
+ if (!fs.existsSync(entry)) {
255
+ return `root entry missing: ${entry}`;
256
+ }
257
+ const pkgJsonPath = path.join(rootPackageDir2(vDir, spec), "package.json");
258
+ let pkg;
259
+ try {
260
+ const raw = JSON.parse(fs.readFileSync(pkgJsonPath, "utf-8"));
261
+ if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
262
+ return `package.json malformed: ${pkgJsonPath}`;
263
+ }
264
+ pkg = raw;
265
+ } catch {
266
+ return `package.json unreadable: ${pkgJsonPath}`;
267
+ }
268
+ if (pkg["name"] !== spec.packageName) {
269
+ return `package name mismatch: expected ${spec.packageName}, got ${String(pkg["name"])}`;
270
+ }
271
+ if (pkg["version"] !== version) {
272
+ return `package version mismatch: dir says ${version}, package.json says ${String(pkg["version"])}`;
273
+ }
274
+ const engines = pkg["engines"];
275
+ if (typeof engines === "object" && engines !== null) {
276
+ const enginesNode = engines["node"];
277
+ if (typeof enginesNode === "string") {
278
+ const minMajor = minNodeMajorOf(enginesNode);
279
+ if (minMajor !== null && nodeMajor < minMajor) {
280
+ return `engines.node "${enginesNode}" requires Node >= ${minMajor}, runtime is ${nodeMajor}`;
281
+ }
282
+ }
283
+ }
284
+ return null;
285
+ }
286
+ __name(validateVersionDir, "validateVersionDir");
287
+ function planBoot(state, isValidVersion, now) {
288
+ if (state === null) {
289
+ return {
290
+ kind: "baked",
291
+ reason: "no server-root state",
292
+ stateToWrite: null
293
+ };
294
+ }
295
+ let next = state;
296
+ let changed = false;
297
+ if (next.pendingBoot !== null) {
298
+ const pending = next.pendingBoot;
299
+ if (pending.bootAttempts >= 1) {
300
+ next = {
301
+ ...next,
302
+ pendingBoot: null,
303
+ rolledBack: {
304
+ fromVersion: pending.version,
305
+ toVersion: next.currentVersion,
306
+ atMs: now(),
307
+ reason: "probation boot did not reach ready \u2014 rolled back"
308
+ }
309
+ };
310
+ changed = true;
311
+ } else if (!isValidVersion(pending.version)) {
312
+ next = {
313
+ ...next,
314
+ pendingBoot: null,
315
+ rolledBack: {
316
+ fromVersion: pending.version,
317
+ toVersion: next.currentVersion,
318
+ atMs: now(),
319
+ reason: "staged version failed validation"
320
+ }
321
+ };
322
+ changed = true;
323
+ } else {
324
+ return {
325
+ kind: "data-root",
326
+ version: pending.version,
327
+ probation: true,
328
+ stateToWrite: {
329
+ ...next,
330
+ pendingBoot: {
331
+ ...pending,
332
+ bootAttempts: pending.bootAttempts + 1
333
+ }
334
+ }
335
+ };
336
+ }
337
+ }
338
+ if (next.currentVersion !== null) {
339
+ if (isValidVersion(next.currentVersion)) {
340
+ return {
341
+ kind: "data-root",
342
+ version: next.currentVersion,
343
+ probation: false,
344
+ stateToWrite: changed ? next : null
345
+ };
346
+ }
347
+ const broken = next.currentVersion;
348
+ if (next.previousVersion !== null && isValidVersion(next.previousVersion)) {
349
+ const fallback = next.previousVersion;
350
+ return {
351
+ kind: "data-root",
352
+ version: fallback,
353
+ probation: false,
354
+ stateToWrite: {
355
+ ...next,
356
+ currentVersion: fallback,
357
+ previousVersion: null,
358
+ rolledBack: {
359
+ fromVersion: broken,
360
+ toVersion: fallback,
361
+ atMs: now(),
362
+ reason: "active version failed validation"
363
+ }
364
+ }
365
+ };
366
+ }
367
+ return {
368
+ kind: "baked",
369
+ reason: `active version ${broken} failed validation and no valid previous version exists`,
370
+ stateToWrite: {
371
+ ...next,
372
+ currentVersion: null,
373
+ rolledBack: {
374
+ fromVersion: broken,
375
+ toVersion: null,
376
+ atMs: now(),
377
+ reason: "active version failed validation"
378
+ }
379
+ }
380
+ };
381
+ }
382
+ return {
383
+ kind: "baked",
384
+ reason: "no active data-root version",
385
+ stateToWrite: changed ? next : null
386
+ };
387
+ }
388
+ __name(planBoot, "planBoot");
389
+ function parse(version) {
390
+ const dashIdx = version.indexOf("-");
391
+ const base = dashIdx === -1 ? version : version.slice(0, dashIdx);
392
+ const prerelease = dashIdx === -1 ? null : version.slice(dashIdx + 1);
393
+ const nums = base.split(".").map((seg) => {
394
+ const n = Number.parseInt(seg, 10);
395
+ return Number.isNaN(n) ? 0 : n;
396
+ });
397
+ return {
398
+ nums,
399
+ prerelease
400
+ };
401
+ }
402
+ __name(parse, "parse");
403
+ function compareSemver(a, b) {
404
+ const pa = parse(a);
405
+ const pb = parse(b);
406
+ const len = Math.max(pa.nums.length, pb.nums.length);
407
+ for (let i = 0; i < len; i++) {
408
+ const na = pa.nums[i] ?? 0;
409
+ const nb = pb.nums[i] ?? 0;
410
+ if (na < nb) return -1;
411
+ if (na > nb) return 1;
412
+ }
413
+ if (pa.prerelease === null && pb.prerelease === null) return 0;
414
+ if (pa.prerelease === null) return 1;
415
+ if (pb.prerelease === null) return -1;
416
+ if (pa.prerelease < pb.prerelease) return -1;
417
+ if (pa.prerelease > pb.prerelease) return 1;
418
+ return 0;
419
+ }
420
+ __name(compareSemver, "compareSemver");
421
+ var fs2 = __toESM2(require("fs"));
422
+ var path2 = __toESM2(require("path"));
423
+ function detectWorkspaceRoot(fromDir) {
424
+ let dir = path2.resolve(fromDir);
425
+ for (; ; ) {
426
+ const pkgPath = path2.join(dir, "package.json");
427
+ try {
428
+ const raw = JSON.parse(fs2.readFileSync(pkgPath, "utf-8"));
429
+ if (typeof raw === "object" && raw !== null && raw["workspaces"] !== void 0) {
430
+ return dir;
431
+ }
432
+ } catch {
433
+ }
434
+ const parent = path2.dirname(dir);
435
+ if (parent === dir) return null;
436
+ dir = parent;
437
+ }
438
+ }
439
+ __name(detectWorkspaceRoot, "detectWorkspaceRoot");
440
+ var path3 = __toESM2(require("path"));
441
+ var import_node_url = require("url");
442
+ var HOST_EXTERNAL_SPECIFIERS = [
443
+ "@camstack/system",
444
+ "@camstack/shm-ring",
445
+ "@camstack/types",
446
+ "@camstack/sdk",
447
+ "zod",
448
+ "@trpc/server",
449
+ "@trpc/client",
450
+ "sharp",
451
+ "node-av"
452
+ ];
453
+ function isHostExternal(specifier) {
454
+ return HOST_EXTERNAL_SPECIFIERS.some((name) => specifier === name || specifier.startsWith(`${name}/`));
455
+ }
456
+ __name(isHostExternal, "isHostExternal");
457
+ function registerActiveRootResolver(activeRootDir) {
458
+ const moduleApi = require("module");
459
+ const registerHooks = moduleApi["registerHooks"];
460
+ if (typeof registerHooks !== "function") {
461
+ console.warn("[starter] module.registerHooks unavailable (Node < 22.15) \u2014 host-external redirect skipped");
462
+ return;
463
+ }
464
+ const anchorURL = (0, import_node_url.pathToFileURL)(path3.join(activeRootDir, "node_modules", "__camstack_starter_anchor__.js")).href;
465
+ const hooks = {
466
+ resolve: /* @__PURE__ */ __name((specifier, context, nextResolve) => {
467
+ if (isHostExternal(specifier)) {
468
+ try {
469
+ return nextResolve(specifier, {
470
+ ...context,
471
+ parentURL: anchorURL
472
+ });
473
+ } catch {
474
+ }
475
+ }
476
+ return nextResolve(specifier, context);
477
+ }, "resolve")
478
+ };
479
+ registerHooks(hooks);
480
+ }
481
+ __name(registerActiveRootResolver, "registerActiveRootResolver");
482
+ function runNodeStarter(options) {
483
+ const env = options.env ?? process.env;
484
+ const now = options.now ?? Date.now;
485
+ const registerResolver = options.registerResolver ?? registerActiveRootResolver;
486
+ const disabled = env[options.envNames.killSwitch] === "off";
487
+ const workspaceRoot = detectWorkspaceRoot(options.starterDir);
488
+ if (workspaceRoot !== null) {
489
+ console.log(`[starter] workspace checkout detected at ${workspaceRoot} \u2014 using plain resolution`);
490
+ env[options.envNames.bootMode] = "workspace";
491
+ options.loadEntry(options.seedEntry);
492
+ return;
493
+ }
494
+ if (disabled) {
495
+ console.log(`[starter] ${options.envNames.killSwitch}=off \u2014 booting the baked seed closure`);
496
+ env[options.envNames.bootMode] = "baked";
497
+ options.loadEntry(options.seedEntry);
498
+ return;
499
+ }
500
+ const rootDir = serverRootDir(options.dataDir);
501
+ const state = readServerRootState(rootDir);
502
+ const nodeMajor = options.nodeMajor ?? Number.parseInt(process.versions.node.split(".")[0] ?? "0", 10);
503
+ const isValidVersion = /* @__PURE__ */ __name((version) => {
504
+ const reason = validateVersionDir(rootDir, version, nodeMajor, options.spec);
505
+ if (reason !== null) console.warn(`[starter] version ${version} invalid: ${reason}`);
506
+ return reason === null;
507
+ }, "isValidVersion");
508
+ const plan = planBoot(state, isValidVersion, now);
509
+ if (plan.stateToWrite !== null) {
510
+ try {
511
+ writeServerRootState(rootDir, plan.stateToWrite);
512
+ } catch (err) {
513
+ console.error("[starter] FAILED to persist server-root state \u2014 booting baked seed:", err);
514
+ env[options.envNames.bootMode] = "baked";
515
+ options.loadEntry(options.seedEntry);
516
+ return;
517
+ }
518
+ if (plan.stateToWrite.rolledBack !== null && (state?.rolledBack ?? null) !== plan.stateToWrite.rolledBack) {
519
+ const rb = plan.stateToWrite.rolledBack;
520
+ console.warn(`[starter] ROLLED BACK ${rb.fromVersion} -> ${rb.toVersion ?? "baked seed"}: ${rb.reason}`);
521
+ }
522
+ }
523
+ if (plan.kind === "data-root") {
524
+ const activeRootDir = versionDir(rootDir, plan.version);
525
+ const entry = rootEntryPath2(activeRootDir, options.spec);
526
+ console.log(`[starter] booting ${options.spec.packageName}@${plan.version} from ${activeRootDir}` + (plan.probation ? " (probation boot \u2014 health-check armed)" : ""));
527
+ env[options.envNames.bootMode] = "data-root";
528
+ env[options.envNames.activeRoot] = activeRootDir;
529
+ env[options.envNames.activeVersion] = plan.version;
530
+ registerResolver(activeRootDir);
531
+ options.loadEntry(entry);
532
+ return;
533
+ }
534
+ console.log(`[starter] booting baked seed closure (${plan.reason})`);
535
+ env[options.envNames.bootMode] = "baked";
536
+ options.loadEntry(options.seedEntry);
537
+ }
538
+ __name(runNodeStarter, "runNodeStarter");
539
+ var import_node_child_process = require("child_process");
540
+ var fs3 = __toESM2(require("fs"));
541
+ var path4 = __toESM2(require("path"));
542
+ var import_node_util = require("util");
543
+ var execFileAsync = (0, import_node_util.promisify)(import_node_child_process.execFile);
544
+ function buildNpmRegistryArgs(registry) {
545
+ if (registry === void 0 || registry.length === 0) return [];
546
+ return [
547
+ "--registry",
548
+ registry,
549
+ `--@camstack:registry=${registry}`
550
+ ];
551
+ }
552
+ __name(buildNpmRegistryArgs, "buildNpmRegistryArgs");
553
+ var NPM_VIEW_TIMEOUT_MS = 2e4;
554
+ var NPM_INSTALL_TIMEOUT_MS = 15 * 6e4;
555
+ var RESTART_REASON_PREFIX = "server-update";
556
+ function readPackageVersion(pkgJsonPath) {
557
+ try {
558
+ const raw = JSON.parse(fs3.readFileSync(pkgJsonPath, "utf-8"));
559
+ if (typeof raw === "object" && raw !== null) {
560
+ const version = raw["version"];
561
+ if (typeof version === "string") return version;
562
+ }
563
+ } catch {
564
+ }
565
+ return null;
566
+ }
567
+ __name(readPackageVersion, "readPackageVersion");
568
+ var RootUpdateService = class _RootUpdateService {
569
+ static {
570
+ __name(this, "_RootUpdateService");
571
+ }
572
+ spec;
573
+ envNames;
574
+ logger;
575
+ restartServerFn;
576
+ dataDir;
577
+ execNpm;
578
+ env;
579
+ now;
580
+ runningPackageJsonPath;
581
+ workspaceProbeDir;
582
+ checkCache = null;
583
+ inFlight = "idle";
584
+ constructor(options) {
585
+ this.spec = options.spec;
586
+ this.envNames = options.envNames;
587
+ this.logger = options.logger;
588
+ this.restartServerFn = options.restartServer;
589
+ this.dataDir = path4.resolve(options.dataDir);
590
+ this.execNpm = options.execNpm ?? (async (args, opts) => {
591
+ const { stdout } = await execFileAsync("npm", [
592
+ ...args
593
+ ], {
594
+ cwd: opts.cwd,
595
+ timeout: opts.timeoutMs
596
+ });
597
+ return {
598
+ stdout
599
+ };
600
+ });
601
+ this.env = options.env ?? process.env;
602
+ this.now = options.now ?? Date.now;
603
+ this.runningPackageJsonPath = options.runningPackageJsonPath;
604
+ this.workspaceProbeDir = options.workspaceProbeDir;
605
+ }
606
+ // ── Status ────────────────────────────────────────────────────────────
607
+ resolveBootMode() {
608
+ const raw = this.env[this.envNames.bootMode];
609
+ if (raw === "workspace" || raw === "baked" || raw === "data-root") return raw;
610
+ return detectWorkspaceRoot(this.workspaceProbeDir) !== null ? "workspace" : "baked";
611
+ }
612
+ runningVersion() {
613
+ return readPackageVersion(this.runningPackageJsonPath);
614
+ }
615
+ /** The running root package's identity — feeds registerNode / topology rows. */
616
+ getRunningRootPackage() {
617
+ return {
618
+ name: this.spec.packageName,
619
+ version: this.runningVersion()
620
+ };
621
+ }
622
+ seedVersion() {
623
+ const seedDir = this.env[this.envNames.seedDir];
624
+ if (seedDir === void 0 || seedDir.length === 0) return null;
625
+ return readPackageVersion(path4.join(seedDir, "package.json"));
626
+ }
627
+ rootDir() {
628
+ return serverRootDir(this.dataDir);
629
+ }
630
+ readState() {
631
+ return readServerRootState(this.rootDir()) ?? emptyServerRootState();
632
+ }
633
+ /**
634
+ * Like `readState`, but distinguishes "state.json missing" (normal on a
635
+ * fresh node) from "state.json present but corrupt" — in the corrupt case
636
+ * the starter booted the baked seed while installed data-dir versions are
637
+ * silently ignored, which the status surface must make visible.
638
+ */
639
+ readStateInfo() {
640
+ const rootDir = this.rootDir();
641
+ const raw = readServerRootState(rootDir);
642
+ if (raw !== null) return {
643
+ state: raw,
644
+ corrupt: false
645
+ };
646
+ return {
647
+ state: emptyServerRootState(),
648
+ corrupt: fs3.existsSync(stateFilePath(rootDir))
649
+ };
650
+ }
651
+ updateState(state) {
652
+ if (this.inFlight === "checking") return "checking";
653
+ if (this.inFlight === "staging") return "staging";
654
+ if (state.pendingBoot !== null) {
655
+ const activeVersion = this.env[this.envNames.activeVersion] ?? null;
656
+ if (activeVersion !== null && activeVersion === state.pendingBoot.version) {
657
+ return "awaiting-confirmation";
658
+ }
659
+ return "pending-restart";
660
+ }
661
+ return "idle";
662
+ }
663
+ async getServerPackageStatus() {
664
+ const { state, corrupt } = this.readStateInfo();
665
+ const runningVersion = this.runningVersion();
666
+ const latestVersion = this.checkCache?.latestVersion ?? null;
667
+ const updateAvailable = latestVersion !== null && runningVersion !== null && compareSemver(latestVersion, runningVersion) > 0;
668
+ return {
669
+ packageName: this.spec.packageName,
670
+ runningVersion,
671
+ nodeRuntimeVersion: process.versions.node,
672
+ activeVersion: this.env[this.envNames.activeVersion] ?? state.currentVersion,
673
+ previousVersion: state.previousVersion,
674
+ seedVersion: this.seedVersion(),
675
+ latestVersion,
676
+ updateAvailable,
677
+ bootMode: this.resolveBootMode(),
678
+ updateState: this.updateState(state),
679
+ pendingVersion: state.pendingBoot?.version ?? null,
680
+ rolledBack: state.rolledBack,
681
+ stateFileCorrupt: corrupt,
682
+ lastCheckedAtMs: this.checkCache?.checkedAtMs ?? null
683
+ };
684
+ }
685
+ // ── Check ─────────────────────────────────────────────────────────────
686
+ async checkServerUpdate() {
687
+ const runningVersion = this.runningVersion();
688
+ if (this.inFlight !== "idle") {
689
+ return {
690
+ packageName: this.spec.packageName,
691
+ runningVersion,
692
+ latestVersion: this.checkCache?.latestVersion ?? null,
693
+ updateAvailable: false,
694
+ checkedAtMs: this.checkCache?.checkedAtMs ?? this.now(),
695
+ error: `busy: ${this.inFlight}`
696
+ };
697
+ }
698
+ this.inFlight = "checking";
699
+ try {
700
+ const registry = this.env["CAMSTACK_NPM_REGISTRY"];
701
+ const args = [
702
+ "view",
703
+ `${this.spec.packageName}@latest`,
704
+ "version",
705
+ ...buildNpmRegistryArgs(registry)
706
+ ];
707
+ const { stdout } = await this.execNpm(args, {
708
+ timeoutMs: NPM_VIEW_TIMEOUT_MS
709
+ });
710
+ const latestVersion = stdout.trim().length > 0 ? stdout.trim() : null;
711
+ this.checkCache = {
712
+ latestVersion,
713
+ checkedAtMs: this.now(),
714
+ error: null
715
+ };
716
+ const updateAvailable = latestVersion !== null && runningVersion !== null && compareSemver(latestVersion, runningVersion) > 0;
717
+ return {
718
+ packageName: this.spec.packageName,
719
+ runningVersion,
720
+ latestVersion,
721
+ updateAvailable,
722
+ checkedAtMs: this.checkCache.checkedAtMs,
723
+ error: null
724
+ };
725
+ } catch (err) {
726
+ const message = err instanceof Error ? err.message : String(err);
727
+ this.checkCache = {
728
+ latestVersion: this.checkCache?.latestVersion ?? null,
729
+ checkedAtMs: this.now(),
730
+ error: message
731
+ };
732
+ this.logger.warn("root package update check failed", {
733
+ meta: {
734
+ error: message
735
+ }
736
+ });
737
+ return {
738
+ packageName: this.spec.packageName,
739
+ runningVersion,
740
+ latestVersion: this.checkCache.latestVersion,
741
+ updateAvailable: false,
742
+ checkedAtMs: this.checkCache.checkedAtMs,
743
+ error: message
744
+ };
745
+ } finally {
746
+ this.inFlight = "idle";
747
+ }
748
+ }
749
+ // ── Apply ─────────────────────────────────────────────────────────────
750
+ async applyServerUpdate(input) {
751
+ const bootMode = this.resolveBootMode();
752
+ if (bootMode === "workspace") {
753
+ return {
754
+ accepted: false,
755
+ targetVersion: input.version ?? null,
756
+ restarting: false,
757
+ message: "Refused: running from a workspace checkout \u2014 the dev loop resolves code from the workspace, a data-root update would never be loaded."
758
+ };
759
+ }
760
+ if (this.inFlight !== "idle") {
761
+ return {
762
+ accepted: false,
763
+ targetVersion: input.version ?? null,
764
+ restarting: false,
765
+ message: `Refused: another operation is in flight (${this.inFlight}).`
766
+ };
767
+ }
768
+ const stateBefore = this.readState();
769
+ if (stateBefore.pendingBoot !== null) {
770
+ return {
771
+ accepted: false,
772
+ targetVersion: input.version ?? null,
773
+ restarting: false,
774
+ message: `Refused: version ${stateBefore.pendingBoot.version} is already staged and awaiting restart.`
775
+ };
776
+ }
777
+ let target = input.version ?? null;
778
+ if (target === null) {
779
+ const check = await this.checkServerUpdate();
780
+ if (check.error !== null || check.latestVersion === null) {
781
+ return {
782
+ accepted: false,
783
+ targetVersion: null,
784
+ restarting: false,
785
+ message: `Refused: could not resolve the latest version (${check.error ?? "no version returned"}).`
786
+ };
787
+ }
788
+ target = check.latestVersion;
789
+ }
790
+ const runningVersion = this.runningVersion();
791
+ if (target === runningVersion) {
792
+ return {
793
+ accepted: false,
794
+ targetVersion: target,
795
+ restarting: false,
796
+ message: `Refused: ${this.spec.packageName}@${target} is already running.`
797
+ };
798
+ }
799
+ this.inFlight = "staging";
800
+ try {
801
+ await this.stageAndActivate(target);
802
+ } catch (err) {
803
+ const message = err instanceof Error ? err.message : String(err);
804
+ this.logger.error("root package update staging failed", {
805
+ meta: {
806
+ targetVersion: target,
807
+ error: message
808
+ }
809
+ });
810
+ return {
811
+ accepted: false,
812
+ targetVersion: target,
813
+ restarting: false,
814
+ message: `Staging failed: ${message}`
815
+ };
816
+ } finally {
817
+ this.inFlight = "idle";
818
+ }
819
+ const state = this.readState();
820
+ writeServerRootState(this.rootDir(), {
821
+ ...state,
822
+ pendingBoot: {
823
+ version: target,
824
+ fromVersion: state.currentVersion,
825
+ requestedAtMs: this.now(),
826
+ bootAttempts: 0
827
+ },
828
+ rolledBack: null
829
+ });
830
+ this.logger.info("root package update staged \u2014 restarting to apply", {
831
+ meta: {
832
+ targetVersion: target,
833
+ fromVersion: state.currentVersion
834
+ }
835
+ });
836
+ this.restartServerFn(`${RESTART_REASON_PREFIX}: ${this.spec.packageName}@${target}`);
837
+ return {
838
+ accepted: true,
839
+ targetVersion: target,
840
+ restarting: true,
841
+ message: `Staged ${this.spec.packageName}@${target} \u2014 restarting to apply (probation boot with auto-rollback).`
842
+ };
843
+ }
844
+ /**
845
+ * npm-install the target closure into a SAME-FS staging dir inside
846
+ * `versions/`, validate it, then atomically rename it into place.
847
+ */
848
+ async stageAndActivate(target) {
849
+ const rootDir = this.rootDir();
850
+ const vDir = versionsDir(rootDir);
851
+ fs3.mkdirSync(vDir, {
852
+ recursive: true
853
+ });
854
+ const stagingDir = path4.join(vDir, `.staging-${target}-${process.pid}-${this.now()}`);
855
+ fs3.mkdirSync(stagingDir, {
856
+ recursive: true
857
+ });
858
+ try {
859
+ fs3.writeFileSync(path4.join(stagingDir, "package.json"), JSON.stringify({
860
+ name: "camstack-node-root",
861
+ private: true
862
+ }, null, 2), "utf-8");
863
+ const registry = this.env["CAMSTACK_NPM_REGISTRY"];
864
+ await this.execNpm([
865
+ "install",
866
+ "--omit=dev",
867
+ "--no-audit",
868
+ "--no-fund",
869
+ "--loglevel=error",
870
+ `${this.spec.packageName}@${target}`,
871
+ ...buildNpmRegistryArgs(registry)
872
+ ], {
873
+ cwd: stagingDir,
874
+ timeoutMs: NPM_INSTALL_TIMEOUT_MS
875
+ });
876
+ const entry = rootEntryPath2(stagingDir, this.spec);
877
+ if (!fs3.existsSync(entry)) {
878
+ throw new Error(`staged closure is missing the root entry (${entry})`);
879
+ }
880
+ const stagedVersion = readPackageVersion(path4.join(rootPackageDir2(stagingDir, this.spec), "package.json"));
881
+ if (stagedVersion !== target) {
882
+ throw new Error(`staged closure version mismatch: expected ${target}, got ${stagedVersion ?? "unknown"}`);
883
+ }
884
+ const dest = versionDir(rootDir, target);
885
+ if (fs3.existsSync(dest)) {
886
+ const aside = `${dest}.evicted-${this.now()}`;
887
+ await fs3.promises.rename(dest, aside);
888
+ await fs3.promises.rm(aside, {
889
+ recursive: true,
890
+ force: true
891
+ }).catch(() => void 0);
892
+ }
893
+ await fs3.promises.rename(stagingDir, dest);
894
+ } catch (err) {
895
+ await fs3.promises.rm(stagingDir, {
896
+ recursive: true,
897
+ force: true
898
+ }).catch(() => void 0);
899
+ throw err;
900
+ }
901
+ }
902
+ // ── Rollback ──────────────────────────────────────────────────────────
903
+ async rollbackServerUpdate() {
904
+ if (this.inFlight !== "idle") {
905
+ return {
906
+ accepted: false,
907
+ targetVersion: null,
908
+ restarting: false,
909
+ message: `Refused: another operation is in flight (${this.inFlight}).`
910
+ };
911
+ }
912
+ const state = this.readState();
913
+ if (state.pendingBoot !== null) {
914
+ return {
915
+ accepted: false,
916
+ targetVersion: null,
917
+ restarting: false,
918
+ message: `Refused: version ${state.pendingBoot.version} is already staged and awaiting restart.`
919
+ };
920
+ }
921
+ if (state.currentVersion === null || state.previousVersion === null) {
922
+ return {
923
+ accepted: false,
924
+ targetVersion: state.previousVersion,
925
+ restarting: false,
926
+ message: "Refused: no previous version available to roll back to."
927
+ };
928
+ }
929
+ const nodeMajor = Number.parseInt(process.versions.node.split(".")[0] ?? "0", 10);
930
+ const invalidReason = validateVersionDir(this.rootDir(), state.previousVersion, nodeMajor, this.spec);
931
+ if (invalidReason !== null) {
932
+ return {
933
+ accepted: false,
934
+ targetVersion: state.previousVersion,
935
+ restarting: false,
936
+ message: `Refused: previous version ${state.previousVersion} is not loadable (${invalidReason}).`
937
+ };
938
+ }
939
+ writeServerRootState(this.rootDir(), {
940
+ ...state,
941
+ pendingBoot: {
942
+ version: state.previousVersion,
943
+ fromVersion: state.currentVersion,
944
+ requestedAtMs: this.now(),
945
+ bootAttempts: 0
946
+ }
947
+ });
948
+ this.logger.info("root package rollback requested \u2014 restarting", {
949
+ meta: {
950
+ fromVersion: state.currentVersion,
951
+ toVersion: state.previousVersion
952
+ }
953
+ });
954
+ this.restartServerFn(`${RESTART_REASON_PREFIX}: rollback to ${this.spec.packageName}@${state.previousVersion}`);
955
+ return {
956
+ accepted: true,
957
+ targetVersion: state.previousVersion,
958
+ restarting: true,
959
+ message: `Rolling back to ${this.spec.packageName}@${state.previousVersion} \u2014 restarting.`
960
+ };
961
+ }
962
+ // ── Plain restart ─────────────────────────────────────────────────────
963
+ /**
964
+ * Plain process restart — no version change. Backs the `restartServer` cap
965
+ * method. Guards mirror apply/rollback: refuse while a stage is in flight
966
+ * (a concurrent npm install must not be interrupted) or while a version is
967
+ * already staged awaiting restart (a naive bounce would boot the OLD version
968
+ * and orphan the pending one — the operator should apply/rollback instead).
969
+ */
970
+ restartNode() {
971
+ const runningVersion = this.runningVersion();
972
+ if (this.inFlight !== "idle") {
973
+ return {
974
+ accepted: false,
975
+ targetVersion: runningVersion,
976
+ restarting: false,
977
+ message: `Refused: another operation is in flight (${this.inFlight}).`
978
+ };
979
+ }
980
+ const state = this.readState();
981
+ if (state.pendingBoot !== null) {
982
+ return {
983
+ accepted: false,
984
+ targetVersion: runningVersion,
985
+ restarting: false,
986
+ message: `Refused: version ${state.pendingBoot.version} is staged and awaiting restart \u2014 apply or roll it back instead of a plain restart.`
987
+ };
988
+ }
989
+ this.logger.info("plain node restart requested", {
990
+ meta: {
991
+ runningVersion
992
+ }
993
+ });
994
+ this.restartServerFn(`${RESTART_REASON_PREFIX}: manual restart`);
995
+ return {
996
+ accepted: true,
997
+ targetVersion: runningVersion,
998
+ restarting: true,
999
+ message: "Restarting the node \u2014 the supervisor relaunches it on the same version."
1000
+ };
1001
+ }
1002
+ // ── Boot health confirmation ──────────────────────────────────────────
1003
+ /**
1004
+ * Called by the post-boot path once the node is READY (hub: post-boot
1005
+ * pipeline; agent: first acked `$hub.registerNode`). When THIS process is
1006
+ * the probation boot of a pending version, promote it: `currentVersion` ←
1007
+ * pending, `previousVersion` ← the version it replaced (N-1 retained for
1008
+ * rollback), clear `pendingBoot` + `rolledBack`, and prune every version
1009
+ * dir beyond {current, previous}. No-op otherwise.
1010
+ */
1011
+ confirmBootHealthy() {
1012
+ const state = readServerRootState(this.rootDir());
1013
+ if (state === null || state.pendingBoot === null) return {
1014
+ promoted: null
1015
+ };
1016
+ const activeVersion = this.env[this.envNames.activeVersion] ?? null;
1017
+ if (activeVersion !== state.pendingBoot.version) {
1018
+ return {
1019
+ promoted: null
1020
+ };
1021
+ }
1022
+ const promoted = {
1023
+ ...state,
1024
+ currentVersion: state.pendingBoot.version,
1025
+ previousVersion: state.pendingBoot.fromVersion,
1026
+ pendingBoot: null,
1027
+ rolledBack: null
1028
+ };
1029
+ writeServerRootState(this.rootDir(), promoted);
1030
+ this.pruneVersions([
1031
+ promoted.currentVersion,
1032
+ promoted.previousVersion
1033
+ ].filter((v) => typeof v === "string"));
1034
+ this.logger.info("root package update confirmed healthy", {
1035
+ meta: {
1036
+ version: promoted.currentVersion,
1037
+ previousVersion: promoted.previousVersion
1038
+ }
1039
+ });
1040
+ return {
1041
+ promoted: promoted.currentVersion
1042
+ };
1043
+ }
1044
+ /**
1045
+ * Remove version dirs under `versions/` not in `keep`.
1046
+ *
1047
+ * Transient dot-entries (`.staging-*` / `.evicted-*`) are NOT pruned unless
1048
+ * older than {@link RootUpdateService.STALE_TRANSIENT_MS}: the API starts
1049
+ * serving BEFORE the post-boot `confirmBootHealthy()` runs, so a concurrent
1050
+ * `applyServerUpdate` can be mid-npm-install into a fresh `.staging-*` dir
1051
+ * when this prune fires — deleting it would corrupt that install. Fresh
1052
+ * transient dirs are owned by their in-flight operation (which cleans up on
1053
+ * failure); the staleness sweep only collects dirs orphaned by a crash.
1054
+ */
1055
+ pruneVersions(keep) {
1056
+ const vDir = versionsDir(this.rootDir());
1057
+ let entries;
1058
+ try {
1059
+ entries = fs3.readdirSync(vDir);
1060
+ } catch {
1061
+ return;
1062
+ }
1063
+ for (const entry of entries) {
1064
+ if (keep.includes(entry)) continue;
1065
+ const full = path4.join(vDir, entry);
1066
+ if (entry.startsWith(".")) {
1067
+ try {
1068
+ const ageMs = this.now() - fs3.statSync(full).mtimeMs;
1069
+ if (ageMs < _RootUpdateService.STALE_TRANSIENT_MS) continue;
1070
+ } catch {
1071
+ continue;
1072
+ }
1073
+ }
1074
+ try {
1075
+ fs3.rmSync(full, {
1076
+ recursive: true,
1077
+ force: true
1078
+ });
1079
+ this.logger.debug("pruned server-root version dir", {
1080
+ meta: {
1081
+ entry
1082
+ }
1083
+ });
1084
+ } catch (err) {
1085
+ this.logger.warn("failed to prune server-root version dir", {
1086
+ meta: {
1087
+ entry,
1088
+ error: err instanceof Error ? err.message : String(err)
1089
+ }
1090
+ });
1091
+ }
1092
+ }
1093
+ }
1094
+ /** Transient (.staging- / .evicted-) dirs younger than this are never pruned. */
1095
+ static STALE_TRANSIENT_MS = 24 * 60 * 60 * 1e3;
1096
+ };
1097
+ }
1098
+ });
1099
+
1100
+ // src/server-root/index.ts
1101
+ var server_root_exports = {};
1102
+ __export(server_root_exports, {
1103
+ SERVER_ROOT_PACKAGE_NAME: () => SERVER_ROOT_PACKAGE_NAME,
1104
+ serverEntryPath: () => serverEntryPath,
1105
+ serverPackageDir: () => serverPackageDir
1106
+ });
1107
+ module.exports = __toCommonJS(server_root_exports);
1108
+ var import_node_root = __toESM(require_dist());
1109
+ __reExport(server_root_exports, __toESM(require_dist()), module.exports);
1110
+ var SERVER_ROOT_PACKAGE_NAME = import_node_root.HUB_ROOT_SPEC.packageName;
1111
+ function serverPackageDir(versionDirPath) {
1112
+ return (0, import_node_root.rootPackageDir)(versionDirPath, import_node_root.HUB_ROOT_SPEC);
1113
+ }
1114
+ __name(serverPackageDir, "serverPackageDir");
1115
+ function serverEntryPath(versionDirPath) {
1116
+ return (0, import_node_root.rootEntryPath)(versionDirPath, import_node_root.HUB_ROOT_SPEC);
1117
+ }
1118
+ __name(serverEntryPath, "serverEntryPath");
1119
+ // Annotate the CommonJS export names for ESM import in node:
1120
+ 0 && (module.exports = {
1121
+ SERVER_ROOT_PACKAGE_NAME,
1122
+ serverEntryPath,
1123
+ serverPackageDir
1124
+ });