@camstack/server 1.1.70 → 1.1.71
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/dist/core/addon/addon-registry.service.js +26 -17
- package/dist/core/server-update/server-update.service.js +10 -10
- package/dist/launcher.js +13 -0
- package/dist/server-root/index.js +436 -416
- package/dist/starter.js +3 -3
- package/package.json +4 -4
- package/dist/core/addon/system-addons-sync.js +0 -121
|
@@ -39,7 +39,6 @@ exports.shouldEmitProviderRegisteredReady = shouldEmitProviderRegisteredReady;
|
|
|
39
39
|
const os = __importStar(require("node:os"));
|
|
40
40
|
const addon_row_manifest_1 = require("./addon-row-manifest");
|
|
41
41
|
const runner_convergence_1 = require("./runner-convergence");
|
|
42
|
-
const system_addons_sync_1 = require("./system-addons-sync");
|
|
43
42
|
const package_dir_utils_1 = require("./package-dir-utils");
|
|
44
43
|
const types_1 = require("@camstack/types");
|
|
45
44
|
const system_1 = require("@camstack/system");
|
|
@@ -435,25 +434,30 @@ class AddonRegistryService {
|
|
|
435
434
|
// launcher). Defaults to `<dataDir>/addons` for dev.
|
|
436
435
|
const dataDir = path.resolve(process.env.CAMSTACK_DATA ?? 'camstack-data');
|
|
437
436
|
const addonsDir = process.env.CAMSTACK_ADDONS_DIR ?? path.resolve(dataDir, 'addons');
|
|
438
|
-
//
|
|
439
|
-
//
|
|
440
|
-
//
|
|
441
|
-
//
|
|
442
|
-
//
|
|
443
|
-
//
|
|
444
|
-
//
|
|
437
|
+
// Single-copy model (2026-07-18 collapse): the framework BUILTINS
|
|
438
|
+
// (`@camstack/system`: device-manager, snapshot, storage, settings, …) load
|
|
439
|
+
// from the ACTIVE CLOSURE the hub itself runs from — resolved via the same
|
|
440
|
+
// walk-up hub-main uses — NOT from a physical `/data/addons/@camstack/system`
|
|
441
|
+
// copy. That copy drifted because no update channel refreshed it (the
|
|
442
|
+
// recurring "+1 restart" / stale-builtin pain); there is now ONE copy and no
|
|
443
|
+
// `syncSystemAddonsCopy` race. Non-framework addons still load from the
|
|
444
|
+
// addons dir unchanged. The addons-dir `@camstack/system` copy (if present,
|
|
445
|
+
// seeded by the image entrypoint) is SKIPPED to avoid a double-load.
|
|
445
446
|
const closureSystemDir = (0, package_dir_utils_1.resolveHubClosurePackageDir)('@camstack/system');
|
|
446
447
|
if (closureSystemDir) {
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
closureSystemDir,
|
|
450
|
-
log: (msg, meta) => this.logger.info(msg, { meta: meta ?? {} }),
|
|
451
|
-
});
|
|
452
|
-
if (outcome === 'failed') {
|
|
453
|
-
this.logger.warn('system addons-copy sync failed — builtins may run stale code');
|
|
448
|
+
try {
|
|
449
|
+
await this.addonLoader.loadFromAddonDir(closureSystemDir);
|
|
454
450
|
}
|
|
451
|
+
catch (err) {
|
|
452
|
+
this.logger.error('Failed to load @camstack/system builtins from the active closure', {
|
|
453
|
+
meta: { closureSystemDir, error: err instanceof Error ? err.message : String(err) },
|
|
454
|
+
});
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
else {
|
|
458
|
+
this.logger.warn('@camstack/system not resolvable from the hub closure — builtins may be missing');
|
|
455
459
|
}
|
|
456
|
-
await this.addonLoader.loadFromDirectory(addonsDir);
|
|
460
|
+
await this.addonLoader.loadFromDirectory(addonsDir, ['@camstack/system']);
|
|
457
461
|
// Hand pre-init load failures (broken package.json, missing
|
|
458
462
|
// dist, import-time errors) to the health monitor so its retry
|
|
459
463
|
// loop and post-grace alerting cover them. Failures during the
|
|
@@ -494,7 +498,12 @@ class AddonRegistryService {
|
|
|
494
498
|
packageDisplayName: registered.packageDisplayName,
|
|
495
499
|
...(registered.bundle !== undefined ? { bundle: registered.bundle } : {}),
|
|
496
500
|
declaredCapabilities: declCaps,
|
|
497
|
-
|
|
501
|
+
// @camstack/system builtins load from the active closure (single-copy
|
|
502
|
+
// model), not the inert addons-dir copy — point their dir there so
|
|
503
|
+
// any dir-derived path (data dir, markers) resolves to the real copy.
|
|
504
|
+
addonDir: registered.packageName === '@camstack/system' && closureSystemDir
|
|
505
|
+
? closureSystemDir
|
|
506
|
+
: path.join(addonsDir, registered.packageName),
|
|
498
507
|
declaration: registered.declaration,
|
|
499
508
|
});
|
|
500
509
|
}
|
|
@@ -38,18 +38,18 @@ exports.ServerUpdateService = void 0;
|
|
|
38
38
|
* ServerUpdateService — hub-side adapter over the SHARED `RootUpdateService`
|
|
39
39
|
* (`@camstack/node-root`, bundled into `dist/server-root/index.js`).
|
|
40
40
|
*
|
|
41
|
-
* The stage/apply
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
* the
|
|
45
|
-
* the
|
|
46
|
-
* the `CAMSTACK_DATA` data-dir default and the running package.json path.
|
|
41
|
+
* The single-copy stage/apply engine — stage a closure into `.staging-*`,
|
|
42
|
+
* arm the pending-root-swap marker, restart — lives in the shared core so the
|
|
43
|
+
* hub and the agent can never drift. This class only binds the hub's
|
|
44
|
+
* parameters: the `@camstack/server` root spec, the `CAMSTACK_SERVER_*` env
|
|
45
|
+
* markers, the `CAMSTACK_DATA` data-dir default and the running package.json.
|
|
47
46
|
*
|
|
48
|
-
* The starter (server/backend/src/starter.ts → shared `runNodeStarter`)
|
|
49
|
-
*
|
|
50
|
-
*
|
|
47
|
+
* The starter (server/backend/src/starter.ts → shared `runNodeStarter`) owns
|
|
48
|
+
* the OTHER half: applying the staged swap of the single `current/` copy at
|
|
49
|
+
* boot + the one-time migration off the legacy multi-copy layout. There is no
|
|
50
|
+
* probation boot / N-1 / auto-rollback (2026-07-18 collapse).
|
|
51
51
|
*
|
|
52
|
-
* Spec: docs/superpowers/specs/2026-07-
|
|
52
|
+
* Spec: docs/superpowers/specs/2026-07-18-single-framework-copy-collapse-design.md
|
|
53
53
|
*/
|
|
54
54
|
const path = __importStar(require("node:path"));
|
|
55
55
|
const index_js_1 = require("../../server-root/index.js");
|
package/dist/launcher.js
CHANGED
|
@@ -254,6 +254,19 @@ async function launch() {
|
|
|
254
254
|
if (fsw.applied)
|
|
255
255
|
console.log(`[launcher] Applied staged framework update (job ${fsw.jobId ?? '?'})`);
|
|
256
256
|
// ── End framework swap ────────────────────────────────────────────────────
|
|
257
|
+
// ── Single-copy framework dir (2026-07-18 collapse) ────────────────────────
|
|
258
|
+
// In data-root mode the ACTIVE single copy (set by the starter as
|
|
259
|
+
// CAMSTACK_SERVER_ACTIVE_ROOT) IS the framework — point the forked
|
|
260
|
+
// addon-runners' resolver + NODE_PATH at it instead of the (now-inert)
|
|
261
|
+
// static /data/framework copy. Forked children inherit this via process.env,
|
|
262
|
+
// and the NODE_PATH extension below reads CAMSTACK_FRAMEWORK_DIR. No-op in
|
|
263
|
+
// baked mode (activeRoot unset → keep the image's /data/framework).
|
|
264
|
+
const activeRoot = process.env['CAMSTACK_SERVER_ACTIVE_ROOT'];
|
|
265
|
+
if (activeRoot && fs.existsSync(path.join(activeRoot, 'node_modules', '@camstack', 'system'))) {
|
|
266
|
+
process.env['CAMSTACK_FRAMEWORK_DIR'] = activeRoot;
|
|
267
|
+
console.log(`[launcher] Single-copy framework dir → ${activeRoot}`);
|
|
268
|
+
}
|
|
269
|
+
// ──────────────────────────────────────────────────────────────────────────
|
|
257
270
|
// Restore must happen first so the snapshot's `addons/` is what the
|
|
258
271
|
// installer + symlink step pick up — otherwise we'd install a stale
|
|
259
272
|
// set and overwrite it a step later.
|