camstack 1.2.15 → 1.2.17
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/{chunk-EA6763XQ.js → chunk-BQIVUGZ6.js} +15358 -13544
- package/dist/chunk-LMMQX4CK.js +49 -0
- package/dist/chunk-RA674VWL.js +2785 -0
- package/dist/cli.js +72 -24
- package/dist/{discover-UMBUCPOL.js → discover-I7QQOQNW.js} +2 -2
- package/dist/{discover-addons-MHWUAAMX.js → discover-addons-3N32LTH7.js} +1 -1
- package/dist/dist-RV3V7TEU.js +902 -0
- package/dist/launcher-6P52TSCL.js +392885 -0
- package/dist/main-IM5JIKX5.js +2302 -0
- package/package.json +1 -1
- package/dist/chunk-K3NQKI34.js +0 -10
package/dist/cli.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
runDiscover
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import "./chunk-
|
|
4
|
+
} from "./chunk-BQIVUGZ6.js";
|
|
5
|
+
import "./chunk-LMMQX4CK.js";
|
|
6
6
|
|
|
7
7
|
// src/cli.ts
|
|
8
8
|
import { createRequire } from "module";
|
|
@@ -15,7 +15,9 @@ import { parseArgs as parseArgs7 } from "util";
|
|
|
15
15
|
import { parseArgs } from "util";
|
|
16
16
|
function buildServeEnv(opts) {
|
|
17
17
|
const env = {
|
|
18
|
-
CAMSTACK_MODE
|
|
18
|
+
// `CAMSTACK_ROLE`, not `CAMSTACK_MODE` — see agent.ts. This one worked
|
|
19
|
+
// only because an empty role DEFAULTS to hub, i.e. by accident.
|
|
20
|
+
CAMSTACK_ROLE: "hub"
|
|
19
21
|
};
|
|
20
22
|
if (opts.port) env.PORT = opts.port;
|
|
21
23
|
if (opts.data) env.CAMSTACK_DATA = opts.data;
|
|
@@ -36,7 +38,7 @@ async function runServe(args) {
|
|
|
36
38
|
...typeof values.data === "string" ? { data: values.data } : {}
|
|
37
39
|
};
|
|
38
40
|
Object.assign(process.env, buildServeEnv(opts));
|
|
39
|
-
await import("
|
|
41
|
+
await import("./launcher-6P52TSCL.js");
|
|
40
42
|
}
|
|
41
43
|
|
|
42
44
|
// src/commands/agent.ts
|
|
@@ -46,7 +48,11 @@ function buildAgentEnv(opts) {
|
|
|
46
48
|
const hubPort = opts.port ?? "4443";
|
|
47
49
|
const agentName = opts.name ?? `${os.hostname()}-${os.arch()}`;
|
|
48
50
|
return {
|
|
49
|
-
CAMSTACK_MODE
|
|
51
|
+
// `CAMSTACK_ROLE`, not `CAMSTACK_MODE`. Nothing in server/backend has ever
|
|
52
|
+
// read `CAMSTACK_MODE` — the role switch is `resolveNodeRole`
|
|
53
|
+
// (server/backend/src/node-role.ts), which returns 'hub' for an EMPTY
|
|
54
|
+
// value. So `camstack agent` set a variable no one reads and booted a HUB.
|
|
55
|
+
CAMSTACK_ROLE: "agent",
|
|
50
56
|
CAMSTACK_HUB_URL: `ws://${opts.hub}:${hubPort}/agent`,
|
|
51
57
|
CAMSTACK_HUB_TOKEN: opts.token,
|
|
52
58
|
CAMSTACK_AGENT_NAME: agentName
|
|
@@ -77,7 +83,7 @@ async function runAgent(args) {
|
|
|
77
83
|
...typeof values.port === "string" ? { port: values.port } : {}
|
|
78
84
|
};
|
|
79
85
|
Object.assign(process.env, buildAgentEnv(opts));
|
|
80
|
-
await import("
|
|
86
|
+
await import("./launcher-6P52TSCL.js");
|
|
81
87
|
}
|
|
82
88
|
|
|
83
89
|
// src/commands/setup.ts
|
|
@@ -238,9 +244,39 @@ function toDeployResult(value) {
|
|
|
238
244
|
target: typeof value["target"] === "string" ? value["target"] : void 0,
|
|
239
245
|
addonId: typeof value["addonId"] === "string" ? value["addonId"] : void 0,
|
|
240
246
|
capabilities: Array.isArray(value["capabilities"]) ? value["capabilities"].filter((c) => typeof c === "string") : void 0,
|
|
247
|
+
reloaded: Array.isArray(value["reloaded"]) ? value["reloaded"].filter((c) => typeof c === "string") : void 0,
|
|
248
|
+
verifiedSha256: typeof value["verifiedSha256"] === "string" ? value["verifiedSha256"] : void 0,
|
|
241
249
|
error: typeof value["error"] === "string" ? value["error"] : void 0
|
|
242
250
|
};
|
|
243
251
|
}
|
|
252
|
+
function checkDeployTarget(result, requestedNodeId) {
|
|
253
|
+
const actual = result.target;
|
|
254
|
+
if (actual === void 0) return null;
|
|
255
|
+
const expected = requestedNodeId ?? "hub";
|
|
256
|
+
if (actual === expected) return null;
|
|
257
|
+
return `the hub installed this on "${actual}", NOT on "${expected}" \u2014 the target was ignored. Nothing was deployed to the node you named.`;
|
|
258
|
+
}
|
|
259
|
+
function describeDeployOutcome(result, isAgentTarget) {
|
|
260
|
+
const id = result.packageName ?? result.addonId ?? "?";
|
|
261
|
+
const version = result.version ? `@${result.version}` : "";
|
|
262
|
+
const reloaded = result.reloaded;
|
|
263
|
+
const suffix = reloaded === void 0 ? "" : ` (reloaded: ${reloaded.join(", ") || "none"})`;
|
|
264
|
+
const detail = `${id}${version}${suffix}`;
|
|
265
|
+
if (!isAgentTarget) return { detail, warning: null };
|
|
266
|
+
if (reloaded === void 0) {
|
|
267
|
+
return {
|
|
268
|
+
detail,
|
|
269
|
+
warning: "node did not report what it reloaded \u2014 its hub runtime predates deploy verification, so nothing confirms the new code is running"
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
if (reloaded.length === 0) {
|
|
273
|
+
return {
|
|
274
|
+
detail,
|
|
275
|
+
warning: "bundle landed but the node reloaded NOTHING \u2014 it is probably still running the previous code. Check the node, or restart the addon."
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
return { detail, warning: null };
|
|
279
|
+
}
|
|
244
280
|
function toPackFilenames(raw) {
|
|
245
281
|
try {
|
|
246
282
|
const parsed = JSON.parse(raw);
|
|
@@ -278,13 +314,13 @@ async function resolveAddonPathInteractive(arg) {
|
|
|
278
314
|
}
|
|
279
315
|
const cwdAbs = path2.resolve(".");
|
|
280
316
|
if (fs2.existsSync(path2.join(cwdAbs, "package.json"))) {
|
|
281
|
-
const { discoverAddonsInCwd: discoverAddonsInCwd2 } = await import("./discover-addons-
|
|
317
|
+
const { discoverAddonsInCwd: discoverAddonsInCwd2 } = await import("./discover-addons-3N32LTH7.js");
|
|
282
318
|
const direct = discoverAddonsInCwd2(cwdAbs, 0);
|
|
283
319
|
if (direct.length > 0 && direct[0].path === cwdAbs) {
|
|
284
320
|
return cwdAbs;
|
|
285
321
|
}
|
|
286
322
|
}
|
|
287
|
-
const { discoverAddonsInCwd } = await import("./discover-addons-
|
|
323
|
+
const { discoverAddonsInCwd } = await import("./discover-addons-3N32LTH7.js");
|
|
288
324
|
const candidates = discoverAddonsInCwd(cwdAbs, 5);
|
|
289
325
|
if (candidates.length === 0) {
|
|
290
326
|
throw new Error(
|
|
@@ -376,7 +412,7 @@ function packAddon(addonDir) {
|
|
|
376
412
|
};
|
|
377
413
|
}
|
|
378
414
|
async function fetchOnlineAgents(serverUrl, token) {
|
|
379
|
-
const url = `${serverUrl}/trpc/nodes.topology?input=${encodeURIComponent('{"json":
|
|
415
|
+
const url = `${serverUrl}/trpc/nodes.topology?input=${encodeURIComponent('{"json":{}}')}`;
|
|
380
416
|
const res = await hubRequest(url, {
|
|
381
417
|
headers: { Authorization: `Bearer ${token}` }
|
|
382
418
|
});
|
|
@@ -386,7 +422,15 @@ async function fetchOnlineAgents(serverUrl, token) {
|
|
|
386
422
|
);
|
|
387
423
|
}
|
|
388
424
|
const body = await res.json();
|
|
389
|
-
|
|
425
|
+
if (body.error) {
|
|
426
|
+
throw new Error(`nodes.topology failed: ${body.error.json?.message ?? "unknown error"}`);
|
|
427
|
+
}
|
|
428
|
+
const nodes = body.result?.data?.json;
|
|
429
|
+
if (!Array.isArray(nodes)) {
|
|
430
|
+
throw new Error(
|
|
431
|
+
"nodes.topology returned no node list \u2014 refusing to assume the cluster is empty"
|
|
432
|
+
);
|
|
433
|
+
}
|
|
390
434
|
return nodes.filter((n) => n.isOnline && !n.isHub);
|
|
391
435
|
}
|
|
392
436
|
async function uploadToTarget(args) {
|
|
@@ -394,13 +438,7 @@ async function uploadToTarget(args) {
|
|
|
394
438
|
const fileBuffer = fs2.readFileSync(tgzPath);
|
|
395
439
|
const boundary = `----camstackcli${randomBytes(16).toString("hex")}`;
|
|
396
440
|
const CRLF = "\r\n";
|
|
397
|
-
const parts = [
|
|
398
|
-
Buffer.from(
|
|
399
|
-
`--${boundary}${CRLF}Content-Disposition: form-data; name="file"; filename="${path2.basename(tgzPath)}"${CRLF}Content-Type: application/gzip${CRLF}${CRLF}`
|
|
400
|
-
),
|
|
401
|
-
fileBuffer,
|
|
402
|
-
Buffer.from(CRLF)
|
|
403
|
-
];
|
|
441
|
+
const parts = [];
|
|
404
442
|
const appendField = (name, value) => {
|
|
405
443
|
parts.push(
|
|
406
444
|
Buffer.from(
|
|
@@ -410,6 +448,13 @@ async function uploadToTarget(args) {
|
|
|
410
448
|
};
|
|
411
449
|
if (nodeId) appendField("nodeId", nodeId);
|
|
412
450
|
if (addonId) appendField("addonId", addonId);
|
|
451
|
+
parts.push(
|
|
452
|
+
Buffer.from(
|
|
453
|
+
`--${boundary}${CRLF}Content-Disposition: form-data; name="file"; filename="${path2.basename(tgzPath)}"${CRLF}Content-Type: application/gzip${CRLF}${CRLF}`
|
|
454
|
+
),
|
|
455
|
+
fileBuffer,
|
|
456
|
+
Buffer.from(CRLF)
|
|
457
|
+
);
|
|
413
458
|
parts.push(Buffer.from(`--${boundary}--${CRLF}`));
|
|
414
459
|
const body = Buffer.concat(parts);
|
|
415
460
|
const response = await hubRequest(`${serverUrl}/api/addons/upload`, {
|
|
@@ -478,8 +523,8 @@ async function deployAddon(addonPath, opts) {
|
|
|
478
523
|
}
|
|
479
524
|
} catch (err) {
|
|
480
525
|
const msg = err instanceof Error ? err.message : String(err);
|
|
481
|
-
|
|
482
|
-
|
|
526
|
+
throw new Error(
|
|
527
|
+
`--cluster: cannot enumerate agents, refusing a partial cluster deploy (${msg}). Deploy per node with -n <nodeId> if this is intentional.`
|
|
483
528
|
);
|
|
484
529
|
}
|
|
485
530
|
} else {
|
|
@@ -503,11 +548,14 @@ async function deployAddon(addonPath, opts) {
|
|
|
503
548
|
)
|
|
504
549
|
}
|
|
505
550
|
);
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
551
|
+
const misrouted = result.success ? checkDeployTarget(result, t.nodeId) : null;
|
|
552
|
+
if (misrouted) {
|
|
553
|
+
console.error(`[camstack] \u2717 ${t.label}: ${misrouted}`);
|
|
554
|
+
outcomes.push({ target: t.label, ok: false, detail: misrouted });
|
|
555
|
+
} else if (result.success) {
|
|
556
|
+
const { detail, warning } = describeDeployOutcome(result, t.nodeId !== void 0);
|
|
510
557
|
console.log(`[camstack] \u2713 ${t.label}: ${detail}`);
|
|
558
|
+
if (warning) console.warn(`[camstack] \u26A0 ${t.label}: ${warning}`);
|
|
511
559
|
outcomes.push({ target: t.label, ok: true, detail });
|
|
512
560
|
} else {
|
|
513
561
|
const detail = result.error ?? "unknown";
|
|
@@ -1079,7 +1127,7 @@ function isUnknown(_value) {
|
|
|
1079
1127
|
return true;
|
|
1080
1128
|
}
|
|
1081
1129
|
async function resolveServerInteractive(presetNamespace) {
|
|
1082
|
-
const { discoverNodes, resolveHubFromDiscovered, filterHubNodes, DEFAULT_HUB_HTTPS_PORT } = await import("./discover-
|
|
1130
|
+
const { discoverNodes, resolveHubFromDiscovered, filterHubNodes, DEFAULT_HUB_HTTPS_PORT } = await import("./discover-I7QQOQNW.js");
|
|
1083
1131
|
if (presetNamespace) {
|
|
1084
1132
|
const spinner4 = clack.spinner();
|
|
1085
1133
|
spinner4.start(`Discovering hub on LAN (namespace "${presetNamespace}")`);
|