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/cli.js CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  runDiscover
4
- } from "./chunk-EA6763XQ.js";
5
- import "./chunk-K3NQKI34.js";
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: "hub"
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("@camstack/server/main.js");
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: "agent",
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("@camstack/server/main.js");
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-MHWUAAMX.js");
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-MHWUAAMX.js");
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":null}')}`;
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
- const nodes = body.result?.data?.json ?? [];
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
- console.error(
482
- `[camstack] --cluster: failed to enumerate agents \u2014 falling back to hub only (${msg})`
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
- if (result.success) {
507
- const id = result.packageName ?? result.addonId ?? "?";
508
- const ver = result.version ? `@${result.version}` : "";
509
- const detail = `${id}${ver}`;
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-UMBUCPOL.js");
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}")`);
@@ -5,8 +5,8 @@ import {
5
5
  filterHubNodes,
6
6
  resolveHubFromDiscovered,
7
7
  runDiscover
8
- } from "./chunk-EA6763XQ.js";
9
- import "./chunk-K3NQKI34.js";
8
+ } from "./chunk-BQIVUGZ6.js";
9
+ import "./chunk-LMMQX4CK.js";
10
10
  export {
11
11
  DEFAULT_HUB_HTTPS_PORT,
12
12
  discoverNodes,
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import "./chunk-K3NQKI34.js";
2
+ import "./chunk-LMMQX4CK.js";
3
3
 
4
4
  // src/commands/discover-addons.ts
5
5
  import * as fs from "fs";