@camstack/server 1.1.70 → 1.1.72
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/api/core/cap-providers.js +0 -11
- package/dist/api/core/lifecycle-job-runner.js +0 -2
- package/dist/api/trpc/generated-cap-routers.js +0 -8
- package/dist/api/trpc/trpc.router.js +49 -2
- package/dist/boot/post-boot.service.js +4 -17
- package/dist/boot/reconcile-lifecycle-jobs.js +6 -5
- package/dist/core/addon/addon-package.service.js +17 -388
- 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 +22 -19
- package/dist/manual-boot.js +0 -27
- package/dist/server-root/index.js +444 -398
- package/dist/starter.js +3 -3
- package/package.json +8 -8
- package/dist/boot/resume-framework-swap.js +0 -119
- package/dist/core/addon/system-addons-sync.js +0 -121
- package/dist/launcher-framework-swap.js +0 -408
- package/dist/request-framework-swap.js +0 -41
package/dist/starter.js
CHANGED
|
@@ -41,9 +41,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
41
41
|
*
|
|
42
42
|
* The boot flow lives in the SHARED node-root core (`runNodeStarter`,
|
|
43
43
|
* bundled into `./server-root/index.js` at build time — see the barrel's
|
|
44
|
-
* BUILD NOTE): workspace defer →
|
|
45
|
-
*
|
|
46
|
-
*
|
|
44
|
+
* BUILD NOTE): workspace defer → apply a staged root swap + migrate the legacy
|
|
45
|
+
* layout to the single `current/` copy → host-external resolver hooks → load
|
|
46
|
+
* the single copy (or the baked seed). This file only binds the hub's names:
|
|
47
47
|
* `@camstack/server`, `dist/launcher.js`, the `CAMSTACK_SERVER_*` env
|
|
48
48
|
* markers and the `CAMSTACK_DATA` data dir.
|
|
49
49
|
*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/server",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.72",
|
|
4
4
|
"private": false,
|
|
5
5
|
"files": [
|
|
6
6
|
"dist",
|
|
@@ -23,19 +23,19 @@
|
|
|
23
23
|
"test:watch": "vitest"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@camstack/addon-admin-ui": "1.1.
|
|
26
|
+
"@camstack/addon-admin-ui": "1.1.59",
|
|
27
27
|
"@camstack/addon-advanced-notifier": "1.1.30",
|
|
28
28
|
"@camstack/addon-auth": "1.1.15",
|
|
29
29
|
"@camstack/addon-decoder-nodeav": "1.1.18",
|
|
30
30
|
"@camstack/addon-notifiers": "1.1.30",
|
|
31
|
-
"@camstack/addon-pipeline": "1.1.
|
|
32
|
-
"@camstack/addon-pipeline-orchestrator": "1.1.
|
|
33
|
-
"@camstack/addon-post-analysis": "1.1.
|
|
31
|
+
"@camstack/addon-pipeline": "1.1.65",
|
|
32
|
+
"@camstack/addon-pipeline-orchestrator": "1.1.54",
|
|
33
|
+
"@camstack/addon-post-analysis": "1.1.37",
|
|
34
34
|
"@camstack/sdk": "1.1.30",
|
|
35
35
|
"@camstack/shm-ring": "1.0.29",
|
|
36
|
-
"@camstack/system": "1.1.
|
|
37
|
-
"@camstack/types": "1.1.
|
|
38
|
-
"@camstack/ui-library": "1.1.
|
|
36
|
+
"@camstack/system": "1.1.58",
|
|
37
|
+
"@camstack/types": "1.1.52",
|
|
38
|
+
"@camstack/ui-library": "1.1.43",
|
|
39
39
|
"@fastify/compress": "^9.0.0",
|
|
40
40
|
"@fastify/cookie": "^11.0.2",
|
|
41
41
|
"@fastify/multipart": "^10.0.0",
|
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Boot-time framework-swap job resume + health confirm.
|
|
4
|
-
*
|
|
5
|
-
* After a framework swap reboot, `post-boot.service.ts` calls this once the
|
|
6
|
-
* hub is healthy. It:
|
|
7
|
-
* 1. Reads `.framework-swap-confirm.json` (written by the launcher on apply).
|
|
8
|
-
* 2. Marks the journal task `applied` → `done`, then finalises the job →
|
|
9
|
-
* `completed`.
|
|
10
|
-
* 3. Calls `confirmFrameworkSwapHealthy` to delete the confirm marker +
|
|
11
|
-
* backup dirs (disarms the crash-loop rollback).
|
|
12
|
-
*
|
|
13
|
-
* Best-effort: a missing/corrupt journal is tolerated — `confirmFrameworkSwapHealthy`
|
|
14
|
-
* is still called so the rollback is always disarmed when the hub boots healthy.
|
|
15
|
-
*/
|
|
16
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
17
|
-
if (k2 === undefined) k2 = k;
|
|
18
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
19
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
20
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
21
|
-
}
|
|
22
|
-
Object.defineProperty(o, k2, desc);
|
|
23
|
-
}) : (function(o, m, k, k2) {
|
|
24
|
-
if (k2 === undefined) k2 = k;
|
|
25
|
-
o[k2] = m[k];
|
|
26
|
-
}));
|
|
27
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
28
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
29
|
-
}) : function(o, v) {
|
|
30
|
-
o["default"] = v;
|
|
31
|
-
});
|
|
32
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
33
|
-
var ownKeys = function(o) {
|
|
34
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
35
|
-
var ar = [];
|
|
36
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
37
|
-
return ar;
|
|
38
|
-
};
|
|
39
|
-
return ownKeys(o);
|
|
40
|
-
};
|
|
41
|
-
return function (mod) {
|
|
42
|
-
if (mod && mod.__esModule) return mod;
|
|
43
|
-
var result = {};
|
|
44
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
45
|
-
__setModuleDefault(result, mod);
|
|
46
|
-
return result;
|
|
47
|
-
};
|
|
48
|
-
})();
|
|
49
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
50
|
-
exports.resumeFrameworkSwapJob = resumeFrameworkSwapJob;
|
|
51
|
-
const fs = __importStar(require("node:fs"));
|
|
52
|
-
const path = __importStar(require("node:path"));
|
|
53
|
-
const types_1 = require("@camstack/types");
|
|
54
|
-
const system_1 = require("@camstack/system");
|
|
55
|
-
const launcher_framework_swap_js_1 = require("../launcher-framework-swap.js");
|
|
56
|
-
const lifecycle_journal_path_js_1 = require("../lifecycle-journal-path.js");
|
|
57
|
-
const SWAP_CONFIRM_FILE = '.framework-swap-confirm.json';
|
|
58
|
-
/**
|
|
59
|
-
* Resume a framework-swap journal job to `done`/`completed` and confirm the
|
|
60
|
-
* hub is healthy (deletes the confirm marker + backups).
|
|
61
|
-
*
|
|
62
|
-
* @returns `{ resumed: false }` when no confirm marker exists.
|
|
63
|
-
* `{ resumed: true, jobId }` when the marker was found and processed.
|
|
64
|
-
* Never throws — errors are swallowed to avoid crashing the post-boot path.
|
|
65
|
-
*/
|
|
66
|
-
async function resumeFrameworkSwapJob(dataDir) {
|
|
67
|
-
try {
|
|
68
|
-
const confirmMarker = readConfirmMarker(dataDir);
|
|
69
|
-
if (confirmMarker === null) {
|
|
70
|
-
return { resumed: false };
|
|
71
|
-
}
|
|
72
|
-
const { jobId, taskId } = confirmMarker;
|
|
73
|
-
let journalPatched = false;
|
|
74
|
-
try {
|
|
75
|
-
const journal = new system_1.JobJournal((0, lifecycle_journal_path_js_1.lifecycleJobsDir)(dataDir));
|
|
76
|
-
const job = journal.getJob(jobId);
|
|
77
|
-
if (job !== null) {
|
|
78
|
-
const task = job.tasks.find((t) => t.taskId === taskId);
|
|
79
|
-
if (task !== undefined && task.phase === 'applied') {
|
|
80
|
-
journal.patchTask(jobId, taskId, { phase: 'done', finishedAtMs: Date.now() });
|
|
81
|
-
// Single-task framework job: if all tasks are now terminal and none
|
|
82
|
-
// failed, mark the job completed (mirrors the engine's finalize logic).
|
|
83
|
-
const updatedJob = journal.getJob(jobId);
|
|
84
|
-
if (updatedJob !== null) {
|
|
85
|
-
const allTerminal = updatedJob.tasks.every((t) => t.phase === 'done' || t.phase === 'failed' || t.phase === 'skipped');
|
|
86
|
-
const anyFailed = updatedJob.tasks.some((t) => t.phase === 'failed');
|
|
87
|
-
if (allTerminal && !anyFailed) {
|
|
88
|
-
journal.setJobState(jobId, 'completed');
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
journalPatched = true;
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
catch {
|
|
96
|
-
// Journal is missing or corrupt — still clean up the confirm marker so
|
|
97
|
-
// the rollback is disarmed on a healthy hub boot.
|
|
98
|
-
}
|
|
99
|
-
(0, launcher_framework_swap_js_1.confirmFrameworkSwapHealthy)(dataDir);
|
|
100
|
-
return journalPatched ? { resumed: true, jobId } : { resumed: false };
|
|
101
|
-
}
|
|
102
|
-
catch {
|
|
103
|
-
// Never crash the caller (post-boot service).
|
|
104
|
-
return { resumed: false };
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
/** Read and shape-check the confirm marker. Returns null on any error. */
|
|
108
|
-
function readConfirmMarker(dataDir) {
|
|
109
|
-
try {
|
|
110
|
-
const raw = JSON.parse(fs.readFileSync(path.join(dataDir, SWAP_CONFIRM_FILE), 'utf-8'));
|
|
111
|
-
const parsed = types_1.frameworkSwapConfirmSchema.safeParse(raw);
|
|
112
|
-
if (!parsed.success)
|
|
113
|
-
return null;
|
|
114
|
-
return { jobId: parsed.data.jobId, taskId: parsed.data.taskId };
|
|
115
|
-
}
|
|
116
|
-
catch {
|
|
117
|
-
return null;
|
|
118
|
-
}
|
|
119
|
-
}
|
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.isVersionNewer = isVersionNewer;
|
|
37
|
-
exports.syncSystemAddonsCopy = syncSystemAddonsCopy;
|
|
38
|
-
/**
|
|
39
|
-
* system-addons-sync — reconcile the ADDONS-DIR copy of `@camstack/system`
|
|
40
|
-
* with the hub's own (active server-root closure) copy at boot.
|
|
41
|
-
*
|
|
42
|
-
* Builtins are loaded from `CAMSTACK_ADDONS_DIR/@camstack/system` (the addon
|
|
43
|
-
* loader scans only that dir), but NO update channel refreshes that copy on an
|
|
44
|
-
* image hub: the seed-addons stage excludes framework packages, applyServerUpdate
|
|
45
|
-
* swaps only /data/server-root, and `camstack deploy packages/system` is
|
|
46
|
-
* rejected once a release image runs. Live incident 2026-07-17: the snapshot
|
|
47
|
-
* builtin ran system 1.1.49 (no media endpoint) while the active closure
|
|
48
|
-
* carried 1.1.51 — shipped builtin code silently never executed.
|
|
49
|
-
*
|
|
50
|
-
* The sync copies `dist/` + `package.json` from the closure copy over the
|
|
51
|
-
* addons copy when the closure version is NEWER (semver-wise). The addons
|
|
52
|
-
* copy's own `node_modules/` is preserved: third-party deps also resolve via
|
|
53
|
-
* NODE_PATH (the framework dir), and `@camstack/*` deps are host-provided.
|
|
54
|
-
* Staged copy + rename swap so a crash mid-sync never leaves a gutted dist.
|
|
55
|
-
* An addons copy that is newer or equal (dev live-update flow) is left alone.
|
|
56
|
-
*/
|
|
57
|
-
const fs = __importStar(require("node:fs"));
|
|
58
|
-
const path = __importStar(require("node:path"));
|
|
59
|
-
/** Loose semver compare on dotted numeric parts; non-numeric parts compare 0. */
|
|
60
|
-
function isVersionNewer(candidate, current) {
|
|
61
|
-
const a = candidate.split('.').map((p) => Number.parseInt(p, 10) || 0);
|
|
62
|
-
const b = current.split('.').map((p) => Number.parseInt(p, 10) || 0);
|
|
63
|
-
for (let i = 0; i < Math.max(a.length, b.length); i += 1) {
|
|
64
|
-
const d = (a[i] ?? 0) - (b[i] ?? 0);
|
|
65
|
-
if (d !== 0)
|
|
66
|
-
return d > 0;
|
|
67
|
-
}
|
|
68
|
-
return false;
|
|
69
|
-
}
|
|
70
|
-
function readVersion(pkgDir) {
|
|
71
|
-
try {
|
|
72
|
-
const raw = JSON.parse(fs.readFileSync(path.join(pkgDir, 'package.json'), 'utf-8'));
|
|
73
|
-
return typeof raw.version === 'string' ? raw.version : null;
|
|
74
|
-
}
|
|
75
|
-
catch {
|
|
76
|
-
return null;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
/**
|
|
80
|
-
* Reconcile once. Returns what happened (for the caller's log/telemetry).
|
|
81
|
-
* Never throws — a failed sync leaves the previous copy running (same as
|
|
82
|
-
* before this fix existed) and reports `'failed'`.
|
|
83
|
-
*/
|
|
84
|
-
function syncSystemAddonsCopy(input) {
|
|
85
|
-
const { addonsDir, closureSystemDir, log } = input;
|
|
86
|
-
const addonsCopyDir = path.join(addonsDir, '@camstack', 'system');
|
|
87
|
-
if (!fs.existsSync(path.join(addonsCopyDir, 'package.json')))
|
|
88
|
-
return 'absent';
|
|
89
|
-
const closureVersion = readVersion(closureSystemDir);
|
|
90
|
-
const addonsVersion = readVersion(addonsCopyDir);
|
|
91
|
-
if (closureVersion === null || addonsVersion === null)
|
|
92
|
-
return 'failed';
|
|
93
|
-
if (!isVersionNewer(closureVersion, addonsVersion))
|
|
94
|
-
return 'up-to-date';
|
|
95
|
-
try {
|
|
96
|
-
const srcDist = path.join(closureSystemDir, 'dist');
|
|
97
|
-
const nextDist = path.join(addonsCopyDir, `.dist.next-${process.pid}`);
|
|
98
|
-
const oldDist = path.join(addonsCopyDir, `.dist.old-${process.pid}`);
|
|
99
|
-
fs.rmSync(nextDist, { recursive: true, force: true });
|
|
100
|
-
fs.cpSync(srcDist, nextDist, { recursive: true });
|
|
101
|
-
// Swap: rename-aside then rename-in (metadata ops on the same mount).
|
|
102
|
-
fs.rmSync(oldDist, { recursive: true, force: true });
|
|
103
|
-
if (fs.existsSync(path.join(addonsCopyDir, 'dist'))) {
|
|
104
|
-
fs.renameSync(path.join(addonsCopyDir, 'dist'), oldDist);
|
|
105
|
-
}
|
|
106
|
-
fs.renameSync(nextDist, path.join(addonsCopyDir, 'dist'));
|
|
107
|
-
fs.copyFileSync(path.join(closureSystemDir, 'package.json'), path.join(addonsCopyDir, 'package.json'));
|
|
108
|
-
fs.rmSync(oldDist, { recursive: true, force: true });
|
|
109
|
-
log('addons-dir @camstack/system synced from closure', {
|
|
110
|
-
from: addonsVersion,
|
|
111
|
-
to: closureVersion,
|
|
112
|
-
});
|
|
113
|
-
return 'synced';
|
|
114
|
-
}
|
|
115
|
-
catch (err) {
|
|
116
|
-
log('addons-dir @camstack/system sync FAILED — stale builtins keep running', {
|
|
117
|
-
error: err instanceof Error ? err.message : String(err),
|
|
118
|
-
});
|
|
119
|
-
return 'failed';
|
|
120
|
-
}
|
|
121
|
-
}
|