camstack 1.2.179 → 1.2.181
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
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
FFMPEG_PATH_ENV,
|
|
4
4
|
runDiscover
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-4MQR56VQ.js";
|
|
6
6
|
import "./chunk-LMMQX4CK.js";
|
|
7
7
|
|
|
8
8
|
// src/cli.ts
|
|
@@ -39,7 +39,7 @@ async function runServe(args) {
|
|
|
39
39
|
...typeof values.data === "string" ? { data: values.data } : {}
|
|
40
40
|
};
|
|
41
41
|
Object.assign(process.env, buildServeEnv(opts));
|
|
42
|
-
await import("./launcher-
|
|
42
|
+
await import("./launcher-TUOJ3PCS.js");
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
// src/commands/agent.ts
|
|
@@ -84,7 +84,7 @@ async function runAgent(args) {
|
|
|
84
84
|
...typeof values.port === "string" ? { port: values.port } : {}
|
|
85
85
|
};
|
|
86
86
|
Object.assign(process.env, buildAgentEnv(opts));
|
|
87
|
-
await import("./launcher-
|
|
87
|
+
await import("./launcher-TUOJ3PCS.js");
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
// src/commands/setup.ts
|
|
@@ -100,8 +100,6 @@ function describeFfmpegProvisioning(env) {
|
|
|
100
100
|
return "ffmpeg: the pinned build is downloaded by each node on first start \u2014 nothing to install";
|
|
101
101
|
}
|
|
102
102
|
function getDefaultDataPath() {
|
|
103
|
-
const root = process.env.CAMSTACK_ROOT;
|
|
104
|
-
if (root) return path.join(root, "data");
|
|
105
103
|
return path.join(process.cwd(), "camstack-data");
|
|
106
104
|
}
|
|
107
105
|
function runSetup(args) {
|
|
@@ -138,7 +136,7 @@ function runSetup(args) {
|
|
|
138
136
|
// src/commands/deploy.ts
|
|
139
137
|
import { execSync } from "child_process";
|
|
140
138
|
import { randomBytes } from "crypto";
|
|
141
|
-
import * as
|
|
139
|
+
import * as fs3 from "fs";
|
|
142
140
|
import * as path2 from "path";
|
|
143
141
|
|
|
144
142
|
// src/http/hub-http.ts
|
|
@@ -189,6 +187,95 @@ function hubRequest(url, opts = {}) {
|
|
|
189
187
|
});
|
|
190
188
|
}
|
|
191
189
|
|
|
190
|
+
// src/commands/credentials.ts
|
|
191
|
+
import * as fs2 from "fs";
|
|
192
|
+
var MissingCredentialsError = class extends Error {
|
|
193
|
+
constructor(server) {
|
|
194
|
+
super(
|
|
195
|
+
[
|
|
196
|
+
`Not logged in to ${server ?? "any hub"}.`,
|
|
197
|
+
" Run `camstack login`: it caches a token in ~/.camstack/<host>.json that every",
|
|
198
|
+
" command reuses automatically. For scripts/CI, pass --token-file <path> with a",
|
|
199
|
+
" token issued on Identity \u2192 Tokens (or a copied ~/.camstack session file)."
|
|
200
|
+
].join("\n")
|
|
201
|
+
);
|
|
202
|
+
this.name = "MissingCredentialsError";
|
|
203
|
+
}
|
|
204
|
+
};
|
|
205
|
+
var GROUP_OR_OTHER_BITS = 63;
|
|
206
|
+
function readTokenFile(filePath) {
|
|
207
|
+
let raw;
|
|
208
|
+
let mode;
|
|
209
|
+
try {
|
|
210
|
+
raw = fs2.readFileSync(filePath, "utf8");
|
|
211
|
+
mode = fs2.statSync(filePath).mode;
|
|
212
|
+
} catch (err) {
|
|
213
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
214
|
+
throw new Error(`Cannot read token file ${filePath}: ${reason}`, { cause: err });
|
|
215
|
+
}
|
|
216
|
+
const warning = process.platform !== "win32" && (mode & GROUP_OR_OTHER_BITS) !== 0 ? `Token file ${filePath} is readable by other users \u2014 run \`chmod 600 ${filePath}\`.` : void 0;
|
|
217
|
+
const parsed = parseTokenFile(raw.trim(), filePath);
|
|
218
|
+
return warning ? { ...parsed, warning } : parsed;
|
|
219
|
+
}
|
|
220
|
+
function parseTokenFile(content, filePath) {
|
|
221
|
+
if (content.length === 0) throw new Error(`Token file ${filePath} is empty.`);
|
|
222
|
+
if (content.startsWith("{")) return parseSessionJson(content, filePath);
|
|
223
|
+
if (/\s/.test(content)) {
|
|
224
|
+
throw new Error(`Token file ${filePath} must hold exactly one token (found several lines).`);
|
|
225
|
+
}
|
|
226
|
+
return { token: content };
|
|
227
|
+
}
|
|
228
|
+
function parseSessionJson(content, filePath) {
|
|
229
|
+
let json;
|
|
230
|
+
try {
|
|
231
|
+
json = JSON.parse(content);
|
|
232
|
+
} catch {
|
|
233
|
+
throw new Error(`Token file ${filePath} looks like JSON but does not parse.`);
|
|
234
|
+
}
|
|
235
|
+
if (json === null || typeof json !== "object") {
|
|
236
|
+
throw new Error(`Token file ${filePath}: expected a JSON object with a "token" field.`);
|
|
237
|
+
}
|
|
238
|
+
const token = Reflect.get(json, "token");
|
|
239
|
+
const server = Reflect.get(json, "server");
|
|
240
|
+
if (typeof token !== "string" || token.length === 0) {
|
|
241
|
+
throw new Error(`Token file ${filePath}: the JSON has no string "token" field.`);
|
|
242
|
+
}
|
|
243
|
+
return typeof server === "string" && server.length > 0 ? { token, server } : { token };
|
|
244
|
+
}
|
|
245
|
+
function resolveCredentials(inputs) {
|
|
246
|
+
const env = inputs.env ?? process.env;
|
|
247
|
+
const file = inputs.tokenFile ? readTokenFile(inputs.tokenFile) : null;
|
|
248
|
+
const targeted = inputs.server ?? env["CAMSTACK_SERVER"] ?? file?.server;
|
|
249
|
+
const session = inputs.loadSession(targeted);
|
|
250
|
+
const server = targeted ?? session?.server;
|
|
251
|
+
const picked = pickToken(inputs.token, file, env["CAMSTACK_TOKEN"], session);
|
|
252
|
+
if (!picked) throw new MissingCredentialsError(server);
|
|
253
|
+
const warning = file?.warning;
|
|
254
|
+
return warning ? { server, ...picked, warning } : { server, ...picked };
|
|
255
|
+
}
|
|
256
|
+
function pickToken(flag, file, envToken, session) {
|
|
257
|
+
if (flag) return { token: flag, source: "flag" };
|
|
258
|
+
if (file) return { token: file.token, source: "token-file" };
|
|
259
|
+
if (envToken) return { token: envToken, source: "env" };
|
|
260
|
+
if (session) return { token: session.token, source: "session" };
|
|
261
|
+
return null;
|
|
262
|
+
}
|
|
263
|
+
var REJECTION_ADVICE = {
|
|
264
|
+
session: "The hub rejected the cached session token (revoked or expired). Run `camstack login` again.",
|
|
265
|
+
"token-file": "The hub rejected the token from the token file (revoked, expired or lacking scope) \u2014 ask the operator who issued it for a new one.",
|
|
266
|
+
env: "The hub rejected $CAMSTACK_TOKEN (revoked, expired or lacking scope).",
|
|
267
|
+
flag: "The hub rejected the --token value (revoked, expired or lacking scope)."
|
|
268
|
+
};
|
|
269
|
+
function authRejectedHint(status, source) {
|
|
270
|
+
if (status !== 401 && status !== 403) return null;
|
|
271
|
+
return REJECTION_ADVICE[source];
|
|
272
|
+
}
|
|
273
|
+
function withAuthHint(message, status, source) {
|
|
274
|
+
const hint = source ? authRejectedHint(status, source) : null;
|
|
275
|
+
return hint ? `${message}
|
|
276
|
+
${hint}` : message;
|
|
277
|
+
}
|
|
278
|
+
|
|
192
279
|
// src/commands/deploy.ts
|
|
193
280
|
function isRecord(value) {
|
|
194
281
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
@@ -285,12 +372,12 @@ function toPackFilenames(raw) {
|
|
|
285
372
|
}
|
|
286
373
|
function resolveAddonPath(arg) {
|
|
287
374
|
const absolute = path2.resolve(arg);
|
|
288
|
-
if (
|
|
375
|
+
if (fs3.existsSync(absolute)) return absolute;
|
|
289
376
|
for (const candidate of [
|
|
290
377
|
path2.resolve("packages", `addon-${arg}`),
|
|
291
378
|
path2.resolve("packages", arg)
|
|
292
379
|
]) {
|
|
293
|
-
if (
|
|
380
|
+
if (fs3.existsSync(candidate) && fs3.existsSync(path2.join(candidate, "package.json"))) {
|
|
294
381
|
return candidate;
|
|
295
382
|
}
|
|
296
383
|
}
|
|
@@ -307,7 +394,7 @@ async function resolveAddonPathInteractive(arg) {
|
|
|
307
394
|
return resolved;
|
|
308
395
|
}
|
|
309
396
|
const cwdAbs = path2.resolve(".");
|
|
310
|
-
if (
|
|
397
|
+
if (fs3.existsSync(path2.join(cwdAbs, "package.json"))) {
|
|
311
398
|
const { discoverAddonsInCwd: discoverAddonsInCwd2 } = await import("./discover-addons-3N32LTH7.js");
|
|
312
399
|
const direct = discoverAddonsInCwd2(cwdAbs, 0);
|
|
313
400
|
if (direct.length > 0 && direct[0].path === cwdAbs) {
|
|
@@ -345,9 +432,9 @@ async function resolveAddonPathInteractive(arg) {
|
|
|
345
432
|
}
|
|
346
433
|
function readBuildScript(addonDir, scriptName) {
|
|
347
434
|
const pkgJsonPath = path2.join(addonDir, "package.json");
|
|
348
|
-
if (!
|
|
435
|
+
if (!fs3.existsSync(pkgJsonPath)) return null;
|
|
349
436
|
try {
|
|
350
|
-
const parsed = JSON.parse(
|
|
437
|
+
const parsed = JSON.parse(fs3.readFileSync(pkgJsonPath, "utf8"));
|
|
351
438
|
if (!parsed || typeof parsed !== "object") return null;
|
|
352
439
|
const scripts = parsed.scripts;
|
|
353
440
|
if (!scripts || typeof scripts !== "object") return null;
|
|
@@ -372,7 +459,7 @@ function buildAddon(addonDir, scriptName) {
|
|
|
372
459
|
}
|
|
373
460
|
function packAddon(addonDir) {
|
|
374
461
|
const pkgJsonPath = path2.join(addonDir, "package.json");
|
|
375
|
-
if (!
|
|
462
|
+
if (!fs3.existsSync(pkgJsonPath)) {
|
|
376
463
|
throw new Error(`No package.json found in: ${addonDir}`);
|
|
377
464
|
}
|
|
378
465
|
console.log(`[camstack] Packing addon from ${addonDir}...`);
|
|
@@ -391,7 +478,7 @@ function packAddon(addonDir) {
|
|
|
391
478
|
}
|
|
392
479
|
if (!tgzFilename) throw new Error("npm pack did not produce a .tgz file");
|
|
393
480
|
const tgzPath = path2.join(addonDir, tgzFilename);
|
|
394
|
-
if (!
|
|
481
|
+
if (!fs3.existsSync(tgzPath)) {
|
|
395
482
|
throw new Error(`Expected tgz file not found: ${tgzPath}`);
|
|
396
483
|
}
|
|
397
484
|
console.log(`[camstack] Packed: ${tgzFilename}`);
|
|
@@ -399,7 +486,7 @@ function packAddon(addonDir) {
|
|
|
399
486
|
tgzPath,
|
|
400
487
|
cleanup: () => {
|
|
401
488
|
try {
|
|
402
|
-
if (
|
|
489
|
+
if (fs3.existsSync(tgzPath)) fs3.unlinkSync(tgzPath);
|
|
403
490
|
} catch {
|
|
404
491
|
}
|
|
405
492
|
}
|
|
@@ -429,7 +516,7 @@ async function fetchOnlineAgents(serverUrl, token) {
|
|
|
429
516
|
}
|
|
430
517
|
async function uploadToTarget(args) {
|
|
431
518
|
const { serverUrl, token, tgzPath, nodeId, addonId } = args;
|
|
432
|
-
const fileBuffer =
|
|
519
|
+
const fileBuffer = fs3.readFileSync(tgzPath);
|
|
433
520
|
const boundary = `----camstackcli${randomBytes(16).toString("hex")}`;
|
|
434
521
|
const CRLF = "\r\n";
|
|
435
522
|
const parts = [];
|
|
@@ -466,17 +553,21 @@ async function uploadToTarget(args) {
|
|
|
466
553
|
if (!response.ok) {
|
|
467
554
|
return {
|
|
468
555
|
success: false,
|
|
469
|
-
error:
|
|
556
|
+
error: withAuthHint(
|
|
557
|
+
result.error ?? `Server returned ${response.status} ${response.statusText}`,
|
|
558
|
+
response.status,
|
|
559
|
+
args.authSource
|
|
560
|
+
)
|
|
470
561
|
};
|
|
471
562
|
}
|
|
472
563
|
return result;
|
|
473
564
|
}
|
|
474
565
|
async function deployAddon(addonPath, opts) {
|
|
475
|
-
const resolvedPath = path2.isAbsolute(addonPath) &&
|
|
566
|
+
const resolvedPath = path2.isAbsolute(addonPath) && fs3.existsSync(addonPath) ? addonPath : await resolveAddonPathInteractive(addonPath);
|
|
476
567
|
let tgzPath;
|
|
477
568
|
let cleanup = null;
|
|
478
569
|
if (resolvedPath.endsWith(".tgz") || resolvedPath.endsWith(".tar.gz")) {
|
|
479
|
-
if (!
|
|
570
|
+
if (!fs3.existsSync(resolvedPath)) throw new Error(`File not found: ${resolvedPath}`);
|
|
480
571
|
tgzPath = resolvedPath;
|
|
481
572
|
} else {
|
|
482
573
|
const buildMode = opts.buildMode ?? "auto";
|
|
@@ -533,7 +624,8 @@ async function deployAddon(addonPath, opts) {
|
|
|
533
624
|
serverUrl: opts.serverUrl,
|
|
534
625
|
token: opts.token,
|
|
535
626
|
tgzPath,
|
|
536
|
-
...t.nodeId ? { nodeId: t.nodeId } : {}
|
|
627
|
+
...t.nodeId ? { nodeId: t.nodeId } : {},
|
|
628
|
+
...opts.authSource ? { authSource: opts.authSource } : {}
|
|
537
629
|
}),
|
|
538
630
|
{
|
|
539
631
|
attempts: 5,
|
|
@@ -593,12 +685,12 @@ async function deployAddon(addonPath, opts) {
|
|
|
593
685
|
// src/commands/deploy-server.ts
|
|
594
686
|
import { execSync as execSync2 } from "child_process";
|
|
595
687
|
import { randomBytes as randomBytes2 } from "crypto";
|
|
596
|
-
import * as
|
|
688
|
+
import * as fs5 from "fs";
|
|
597
689
|
import * as os2 from "os";
|
|
598
690
|
import * as path4 from "path";
|
|
599
691
|
|
|
600
692
|
// src/commands/server-closure.ts
|
|
601
|
-
import * as
|
|
693
|
+
import * as fs4 from "fs";
|
|
602
694
|
import * as path3 from "path";
|
|
603
695
|
var CAMSTACK_SCOPE_PREFIX = "@camstack/";
|
|
604
696
|
function computeDevVersion(base, epochSeconds) {
|
|
@@ -607,7 +699,7 @@ function computeDevVersion(base, epochSeconds) {
|
|
|
607
699
|
function readPackageManifest(dir) {
|
|
608
700
|
const pkgJsonPath = path3.join(dir, "package.json");
|
|
609
701
|
try {
|
|
610
|
-
const parsed = JSON.parse(
|
|
702
|
+
const parsed = JSON.parse(fs4.readFileSync(pkgJsonPath, "utf-8"));
|
|
611
703
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) return null;
|
|
612
704
|
const raw = parsed;
|
|
613
705
|
if (typeof raw["name"] !== "string") return null;
|
|
@@ -633,7 +725,7 @@ function loadWorkspacePackages(workspaceRoot) {
|
|
|
633
725
|
const base = path3.join(workspaceRoot, pattern.slice(0, -2));
|
|
634
726
|
let entries;
|
|
635
727
|
try {
|
|
636
|
-
entries =
|
|
728
|
+
entries = fs4.readdirSync(base, { withFileTypes: true });
|
|
637
729
|
} catch {
|
|
638
730
|
continue;
|
|
639
731
|
}
|
|
@@ -707,7 +799,7 @@ function discoverServerClosure(workspaceRoot) {
|
|
|
707
799
|
}
|
|
708
800
|
function withDevVersionPackageJson(pkgDir, devVersion, intraSetNames, fn) {
|
|
709
801
|
const pkgJsonPath = path3.join(pkgDir, "package.json");
|
|
710
|
-
const originalBytes =
|
|
802
|
+
const originalBytes = fs4.readFileSync(pkgJsonPath);
|
|
711
803
|
const parsed = JSON.parse(originalBytes.toString("utf-8"));
|
|
712
804
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
713
805
|
throw new Error(`Malformed package.json: ${pkgJsonPath}`);
|
|
@@ -725,12 +817,12 @@ function withDevVersionPackageJson(pkgDir, devVersion, intraSetNames, fn) {
|
|
|
725
817
|
}
|
|
726
818
|
manifest[field] = rewritten;
|
|
727
819
|
}
|
|
728
|
-
|
|
820
|
+
fs4.writeFileSync(pkgJsonPath, `${JSON.stringify(manifest, null, 2)}
|
|
729
821
|
`, "utf-8");
|
|
730
822
|
try {
|
|
731
823
|
return fn();
|
|
732
824
|
} finally {
|
|
733
|
-
|
|
825
|
+
fs4.writeFileSync(pkgJsonPath, originalBytes);
|
|
734
826
|
}
|
|
735
827
|
}
|
|
736
828
|
|
|
@@ -753,7 +845,7 @@ function hasBuildScript(pkgDir) {
|
|
|
753
845
|
}
|
|
754
846
|
function readJson(filePath) {
|
|
755
847
|
try {
|
|
756
|
-
return JSON.parse(
|
|
848
|
+
return JSON.parse(fs5.readFileSync(filePath, "utf-8"));
|
|
757
849
|
} catch {
|
|
758
850
|
return null;
|
|
759
851
|
}
|
|
@@ -801,7 +893,7 @@ function packPackage(pkg, devVersion, intraSetNames, outDir) {
|
|
|
801
893
|
throw new Error(`npm pack produced no tarball for ${pkg.name}`);
|
|
802
894
|
}
|
|
803
895
|
const tgzPath = path4.join(outDir, path4.basename(filename));
|
|
804
|
-
if (!
|
|
896
|
+
if (!fs5.existsSync(tgzPath)) {
|
|
805
897
|
throw new Error(`Expected tarball not found after pack: ${tgzPath}`);
|
|
806
898
|
}
|
|
807
899
|
return { name: pkg.name, tgzPath };
|
|
@@ -819,7 +911,7 @@ async function uploadClosure(args) {
|
|
|
819
911
|
Buffer.from(
|
|
820
912
|
`--${boundary}${CRLF}Content-Disposition: form-data; name="file"; filename="${path4.basename(tarball.tgzPath)}"${CRLF}Content-Type: application/gzip${CRLF}${CRLF}`
|
|
821
913
|
),
|
|
822
|
-
|
|
914
|
+
fs5.readFileSync(tarball.tgzPath),
|
|
823
915
|
Buffer.from(CRLF)
|
|
824
916
|
);
|
|
825
917
|
}
|
|
@@ -838,7 +930,9 @@ async function uploadClosure(args) {
|
|
|
838
930
|
const payload = await response.json().catch(() => ({}));
|
|
839
931
|
if (!response.ok || !isRecord2(payload) || payload["success"] !== true) {
|
|
840
932
|
const detail = isRecord2(payload) && typeof payload["error"] === "string" ? payload["error"] : `${response.status} ${response.statusText}`;
|
|
841
|
-
throw new Error(
|
|
933
|
+
throw new Error(
|
|
934
|
+
withAuthHint(`Server upload rejected: ${detail}`, response.status, args.authSource)
|
|
935
|
+
);
|
|
842
936
|
}
|
|
843
937
|
}
|
|
844
938
|
function toApplyResult(value) {
|
|
@@ -874,7 +968,13 @@ async function applyServerUpdate(args) {
|
|
|
874
968
|
);
|
|
875
969
|
const body = await res.json().catch(() => null);
|
|
876
970
|
if (!res.ok) {
|
|
877
|
-
throw new Error(
|
|
971
|
+
throw new Error(
|
|
972
|
+
withAuthHint(
|
|
973
|
+
`applyServerUpdate returned ${res.status} ${res.statusText}`,
|
|
974
|
+
res.status,
|
|
975
|
+
args.authSource
|
|
976
|
+
)
|
|
977
|
+
);
|
|
878
978
|
}
|
|
879
979
|
const result = toApplyResult(unwrapTrpcJson(body));
|
|
880
980
|
if (result === null) {
|
|
@@ -952,7 +1052,7 @@ async function deployServer(opts) {
|
|
|
952
1052
|
console.log(`[camstack] Building ${closure.buildSet.length} packages (dependency order)...`);
|
|
953
1053
|
for (const pkg of closure.buildSet) buildPackage(pkg);
|
|
954
1054
|
const intraSetNames = new Set(closure.packSet.map((p) => p.name));
|
|
955
|
-
const outDir =
|
|
1055
|
+
const outDir = fs5.mkdtempSync(path4.join(os2.tmpdir(), "camstack-deploy-server-"));
|
|
956
1056
|
try {
|
|
957
1057
|
console.log(`[camstack] Packing ${closure.packSet.length} packages at ${devVersion}...`);
|
|
958
1058
|
const tarballs = [];
|
|
@@ -966,14 +1066,16 @@ async function deployServer(opts) {
|
|
|
966
1066
|
serverUrl: opts.serverUrl,
|
|
967
1067
|
token: opts.token,
|
|
968
1068
|
version: devVersion,
|
|
969
|
-
tarballs
|
|
1069
|
+
tarballs,
|
|
1070
|
+
...opts.authSource ? { authSource: opts.authSource } : {}
|
|
970
1071
|
});
|
|
971
1072
|
console.log("[camstack] \u2713 Upload accepted");
|
|
972
1073
|
console.log(`[camstack] Applying server update to ${devVersion}...`);
|
|
973
1074
|
const apply = await applyServerUpdate({
|
|
974
1075
|
serverUrl: opts.serverUrl,
|
|
975
1076
|
token: opts.token,
|
|
976
|
-
version: devVersion
|
|
1077
|
+
version: devVersion,
|
|
1078
|
+
...opts.authSource ? { authSource: opts.authSource } : {}
|
|
977
1079
|
});
|
|
978
1080
|
if (!apply.accepted) {
|
|
979
1081
|
console.error(`[camstack] \u2717 applyServerUpdate refused: ${apply.message}`);
|
|
@@ -988,12 +1090,12 @@ async function deployServer(opts) {
|
|
|
988
1090
|
await pollUntilPromoted({ serverUrl: opts.serverUrl, token: opts.token, version: devVersion });
|
|
989
1091
|
console.log(`[camstack] \u2713 ${devVersion} promoted \u2014 the hub is running the dev closure`);
|
|
990
1092
|
} finally {
|
|
991
|
-
|
|
1093
|
+
fs5.rmSync(outDir, { recursive: true, force: true });
|
|
992
1094
|
}
|
|
993
1095
|
}
|
|
994
1096
|
|
|
995
1097
|
// src/commands/auth.ts
|
|
996
|
-
import * as
|
|
1098
|
+
import * as fs6 from "fs";
|
|
997
1099
|
import * as path5 from "path";
|
|
998
1100
|
import * as os3 from "os";
|
|
999
1101
|
import * as clack from "@clack/prompts";
|
|
@@ -1005,12 +1107,12 @@ function sessionFileForServer(serverUrl) {
|
|
|
1005
1107
|
function resolveSessionFile(serverUrl) {
|
|
1006
1108
|
if (serverUrl) {
|
|
1007
1109
|
const p = sessionFileForServer(serverUrl);
|
|
1008
|
-
return
|
|
1110
|
+
return fs6.existsSync(p) ? p : null;
|
|
1009
1111
|
}
|
|
1010
|
-
if (!
|
|
1011
|
-
const files =
|
|
1112
|
+
if (!fs6.existsSync(SESSION_DIR)) return null;
|
|
1113
|
+
const files = fs6.readdirSync(SESSION_DIR).filter((f) => f.endsWith(".json")).map((f) => path5.join(SESSION_DIR, f));
|
|
1012
1114
|
if (files.length === 0) return null;
|
|
1013
|
-
return files.map((f) => ({ f, mtime:
|
|
1115
|
+
return files.map((f) => ({ f, mtime: fs6.statSync(f).mtimeMs })).toSorted((a, b) => b.mtime - a.mtime)[0].f;
|
|
1014
1116
|
}
|
|
1015
1117
|
function isSessionFile(value) {
|
|
1016
1118
|
if (value === null || typeof value !== "object") return false;
|
|
@@ -1027,24 +1129,24 @@ function loadSession(serverUrl) {
|
|
|
1027
1129
|
const file = resolveSessionFile(serverUrl);
|
|
1028
1130
|
if (!file) return null;
|
|
1029
1131
|
try {
|
|
1030
|
-
const parsed = JSON.parse(
|
|
1132
|
+
const parsed = JSON.parse(fs6.readFileSync(file, "utf8"));
|
|
1031
1133
|
return isSessionFile(parsed) ? parsed : null;
|
|
1032
1134
|
} catch {
|
|
1033
1135
|
return null;
|
|
1034
1136
|
}
|
|
1035
1137
|
}
|
|
1036
1138
|
function saveSession(session) {
|
|
1037
|
-
if (!
|
|
1038
|
-
|
|
1139
|
+
if (!fs6.existsSync(SESSION_DIR)) {
|
|
1140
|
+
fs6.mkdirSync(SESSION_DIR, { recursive: true, mode: 448 });
|
|
1039
1141
|
}
|
|
1040
1142
|
const file = sessionFileForServer(session.server);
|
|
1041
|
-
|
|
1143
|
+
fs6.writeFileSync(file, JSON.stringify(session, null, 2), { mode: 384 });
|
|
1042
1144
|
return file;
|
|
1043
1145
|
}
|
|
1044
1146
|
function clearSession(serverUrl) {
|
|
1045
1147
|
const file = sessionFileForServer(serverUrl);
|
|
1046
|
-
if (
|
|
1047
|
-
|
|
1148
|
+
if (fs6.existsSync(file)) {
|
|
1149
|
+
fs6.unlinkSync(file);
|
|
1048
1150
|
return true;
|
|
1049
1151
|
}
|
|
1050
1152
|
return false;
|
|
@@ -1134,7 +1236,7 @@ function isUnknown(_value) {
|
|
|
1134
1236
|
return true;
|
|
1135
1237
|
}
|
|
1136
1238
|
async function resolveServerInteractive(presetNamespace) {
|
|
1137
|
-
const { discoverNodes, resolveHubFromDiscovered, filterHubNodes, DEFAULT_HUB_HTTPS_PORT } = await import("./discover-
|
|
1239
|
+
const { discoverNodes, resolveHubFromDiscovered, filterHubNodes, DEFAULT_HUB_HTTPS_PORT } = await import("./discover-LW74552N.js");
|
|
1138
1240
|
if (presetNamespace) {
|
|
1139
1241
|
const spinner4 = clack.spinner();
|
|
1140
1242
|
spinner4.start(`Discovering hub on LAN (namespace "${presetNamespace}")`);
|
|
@@ -1383,7 +1485,7 @@ import { spawn } from "child_process";
|
|
|
1383
1485
|
import * as clack2 from "@clack/prompts";
|
|
1384
1486
|
|
|
1385
1487
|
// src/update-notifier.ts
|
|
1386
|
-
import * as
|
|
1488
|
+
import * as fs7 from "fs";
|
|
1387
1489
|
import * as path6 from "path";
|
|
1388
1490
|
import * as os4 from "os";
|
|
1389
1491
|
var CACHE_DIR = path6.join(os4.homedir(), ".camstack");
|
|
@@ -1393,8 +1495,8 @@ var REGISTRY_BASE = "https://registry.npmjs.org";
|
|
|
1393
1495
|
var FETCH_TIMEOUT_MS = 2500;
|
|
1394
1496
|
function readCache() {
|
|
1395
1497
|
try {
|
|
1396
|
-
if (!
|
|
1397
|
-
const parsed = JSON.parse(
|
|
1498
|
+
if (!fs7.existsSync(CACHE_FILE)) return null;
|
|
1499
|
+
const parsed = JSON.parse(fs7.readFileSync(CACHE_FILE, "utf8"));
|
|
1398
1500
|
if (!parsed || typeof parsed !== "object") return null;
|
|
1399
1501
|
const c = parsed;
|
|
1400
1502
|
if (typeof c.lastCheckAt !== "number") return null;
|
|
@@ -1409,8 +1511,8 @@ function readCache() {
|
|
|
1409
1511
|
}
|
|
1410
1512
|
function writeCache(c) {
|
|
1411
1513
|
try {
|
|
1412
|
-
if (!
|
|
1413
|
-
|
|
1514
|
+
if (!fs7.existsSync(CACHE_DIR)) fs7.mkdirSync(CACHE_DIR, { recursive: true, mode: 448 });
|
|
1515
|
+
fs7.writeFileSync(CACHE_FILE, JSON.stringify(c, null, 2));
|
|
1414
1516
|
} catch {
|
|
1415
1517
|
}
|
|
1416
1518
|
}
|
|
@@ -1569,7 +1671,7 @@ async function runUpdate(args) {
|
|
|
1569
1671
|
}
|
|
1570
1672
|
|
|
1571
1673
|
// src/commands/dev.ts
|
|
1572
|
-
import * as
|
|
1674
|
+
import * as fs8 from "fs";
|
|
1573
1675
|
import * as path7 from "path";
|
|
1574
1676
|
import { parseArgs as parseArgs5 } from "util";
|
|
1575
1677
|
import * as clack3 from "@clack/prompts";
|
|
@@ -1580,14 +1682,14 @@ function resolveAddonDir(arg) {
|
|
|
1580
1682
|
throw new Error("`dev` requires a source directory, not a tarball (nothing to watch).");
|
|
1581
1683
|
}
|
|
1582
1684
|
const absolute = path7.resolve(arg);
|
|
1583
|
-
if (
|
|
1685
|
+
if (fs8.existsSync(absolute) && fs8.statSync(absolute).isDirectory()) {
|
|
1584
1686
|
return absolute;
|
|
1585
1687
|
}
|
|
1586
1688
|
for (const candidate of [
|
|
1587
1689
|
path7.resolve("packages", `addon-${arg}`),
|
|
1588
1690
|
path7.resolve("packages", arg)
|
|
1589
1691
|
]) {
|
|
1590
|
-
if (
|
|
1692
|
+
if (fs8.existsSync(candidate) && fs8.statSync(candidate).isDirectory()) {
|
|
1591
1693
|
return candidate;
|
|
1592
1694
|
}
|
|
1593
1695
|
}
|
|
@@ -1597,10 +1699,10 @@ function resolveAddonDir(arg) {
|
|
|
1597
1699
|
}
|
|
1598
1700
|
function watchRecursive(target, onEvent) {
|
|
1599
1701
|
try {
|
|
1600
|
-
const w =
|
|
1702
|
+
const w = fs8.watch(target, { recursive: true }, onEvent);
|
|
1601
1703
|
return { close: () => w.close(), recursive: true };
|
|
1602
1704
|
} catch {
|
|
1603
|
-
const w =
|
|
1705
|
+
const w = fs8.watch(target, onEvent);
|
|
1604
1706
|
return { close: () => w.close(), recursive: false };
|
|
1605
1707
|
}
|
|
1606
1708
|
}
|
|
@@ -1624,6 +1726,7 @@ async function runDev(args) {
|
|
|
1624
1726
|
options: {
|
|
1625
1727
|
server: { type: "string", short: "s" },
|
|
1626
1728
|
token: { type: "string", short: "t" },
|
|
1729
|
+
"token-file": { type: "string" },
|
|
1627
1730
|
node: { type: "string", short: "n" },
|
|
1628
1731
|
cluster: { type: "boolean", short: "c" },
|
|
1629
1732
|
"watch-path": { type: "string", short: "w" },
|
|
@@ -1637,27 +1740,32 @@ async function runDev(args) {
|
|
|
1637
1740
|
});
|
|
1638
1741
|
const addonArg = positionals[0] ?? ".";
|
|
1639
1742
|
const addonDir = resolveAddonDir(addonArg);
|
|
1640
|
-
const
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1743
|
+
const creds = resolveCredentials({
|
|
1744
|
+
...typeof values.server === "string" ? { server: values.server } : {},
|
|
1745
|
+
...typeof values.token === "string" ? { token: values.token } : {},
|
|
1746
|
+
...typeof values["token-file"] === "string" ? { tokenFile: values["token-file"] } : {},
|
|
1747
|
+
loadSession
|
|
1748
|
+
});
|
|
1749
|
+
if (creds.warning) console.error(`[camstack dev] Warning: ${creds.warning}`);
|
|
1750
|
+
const serverUrl = creds.server;
|
|
1751
|
+
const token = creds.token;
|
|
1752
|
+
if (!serverUrl) {
|
|
1753
|
+
throw new Error("No hub server known. Pass --server, or run `camstack login` first.");
|
|
1647
1754
|
}
|
|
1648
1755
|
const nodeId = typeof values.node === "string" ? values.node : void 0;
|
|
1649
1756
|
const cluster = values.cluster === true;
|
|
1650
1757
|
const deployOpts = {
|
|
1651
1758
|
serverUrl,
|
|
1652
1759
|
token,
|
|
1760
|
+
authSource: creds.source,
|
|
1653
1761
|
...nodeId ? { nodeId } : {},
|
|
1654
1762
|
...cluster ? { cluster: true } : {},
|
|
1655
1763
|
buildMode: values["no-build"] === true ? "skip" : "auto",
|
|
1656
1764
|
...typeof values["build-script"] === "string" ? { buildScript: values["build-script"] } : {}
|
|
1657
1765
|
};
|
|
1658
1766
|
const watchOverride = typeof values["watch-path"] === "string" ? values["watch-path"] : void 0;
|
|
1659
|
-
const watchTarget = watchOverride ? path7.resolve(addonDir, watchOverride) :
|
|
1660
|
-
if (!
|
|
1767
|
+
const watchTarget = watchOverride ? path7.resolve(addonDir, watchOverride) : fs8.existsSync(path7.join(addonDir, DEFAULT_WATCH_SUBDIR)) ? path7.join(addonDir, DEFAULT_WATCH_SUBDIR) : addonDir;
|
|
1768
|
+
if (!fs8.existsSync(watchTarget)) {
|
|
1661
1769
|
throw new Error(`Watch path does not exist: ${watchTarget}`);
|
|
1662
1770
|
}
|
|
1663
1771
|
const debounceMs = typeof values.debounce === "string" ? parseInt(values.debounce, 10) : DEFAULT_DEBOUNCE_MS;
|
|
@@ -1745,13 +1853,15 @@ function printLine(e, addonId) {
|
|
|
1745
1853
|
`
|
|
1746
1854
|
);
|
|
1747
1855
|
}
|
|
1748
|
-
async function fetchLogs(server, token, addonId, limit) {
|
|
1856
|
+
async function fetchLogs(server, token, addonId, limit, authSource) {
|
|
1749
1857
|
const input = encodeURIComponent(JSON.stringify({ json: { addonId, limit } }));
|
|
1750
1858
|
const url = `${server}/trpc/addons.getLogs?input=${input}`;
|
|
1751
1859
|
const res = await hubRequest(url, { headers: { Authorization: `Bearer ${token}` } });
|
|
1752
1860
|
if (!res.ok) {
|
|
1753
1861
|
const text2 = await res.text().catch(() => "");
|
|
1754
|
-
throw new Error(
|
|
1862
|
+
throw new Error(
|
|
1863
|
+
withAuthHint(`getLogs HTTP ${res.status}: ${text2.slice(0, 200)}`, res.status, authSource)
|
|
1864
|
+
);
|
|
1755
1865
|
}
|
|
1756
1866
|
const body = await res.json();
|
|
1757
1867
|
return body.result?.data?.json ?? [];
|
|
@@ -1762,6 +1872,7 @@ async function runWatch(args) {
|
|
|
1762
1872
|
options: {
|
|
1763
1873
|
server: { type: "string", short: "s" },
|
|
1764
1874
|
token: { type: "string", short: "t" },
|
|
1875
|
+
"token-file": { type: "string" },
|
|
1765
1876
|
node: { type: "string", short: "n" },
|
|
1766
1877
|
cluster: { type: "boolean", short: "c" },
|
|
1767
1878
|
"no-build": { type: "boolean" },
|
|
@@ -1773,17 +1884,24 @@ async function runWatch(args) {
|
|
|
1773
1884
|
allowPositionals: true
|
|
1774
1885
|
});
|
|
1775
1886
|
const addonArg = positionals[0] ?? ".";
|
|
1776
|
-
const
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1887
|
+
const creds = resolveCredentials({
|
|
1888
|
+
...typeof values.server === "string" ? { server: values.server } : {},
|
|
1889
|
+
...typeof values.token === "string" ? { token: values.token } : {},
|
|
1890
|
+
...typeof values["token-file"] === "string" ? { tokenFile: values["token-file"] } : {},
|
|
1891
|
+
loadSession
|
|
1892
|
+
});
|
|
1893
|
+
if (creds.warning) console.error(`[camstack watch] Warning: ${creds.warning}`);
|
|
1894
|
+
const serverUrl = creds.server;
|
|
1895
|
+
const token = creds.token;
|
|
1896
|
+
if (!serverUrl) {
|
|
1897
|
+
throw new Error("No hub server known. Pass --server, or run `camstack login` first.");
|
|
1781
1898
|
}
|
|
1782
1899
|
const nodeId = typeof values.node === "string" ? values.node : void 0;
|
|
1783
1900
|
const cluster = values.cluster === true;
|
|
1784
1901
|
const deployOpts = {
|
|
1785
1902
|
serverUrl,
|
|
1786
1903
|
token,
|
|
1904
|
+
authSource: creds.source,
|
|
1787
1905
|
...nodeId ? { nodeId } : {},
|
|
1788
1906
|
...cluster ? { cluster: true } : {},
|
|
1789
1907
|
buildMode: values["no-build"] === true ? "skip" : "auto",
|
|
@@ -1809,7 +1927,7 @@ async function runWatch(args) {
|
|
|
1809
1927
|
process.on("SIGTERM", shutdown);
|
|
1810
1928
|
while (!stop) {
|
|
1811
1929
|
try {
|
|
1812
|
-
const entries = await fetchLogs(serverUrl, token, addonId, LOG_BATCH_LIMIT);
|
|
1930
|
+
const entries = await fetchLogs(serverUrl, token, addonId, LOG_BATCH_LIMIT, creds.source);
|
|
1813
1931
|
const sorted = [...entries].toSorted((a, b) => {
|
|
1814
1932
|
const ta = typeof a.timestamp === "number" ? a.timestamp : new Date(a.timestamp).getTime();
|
|
1815
1933
|
const tb = typeof b.timestamp === "number" ? b.timestamp : new Date(b.timestamp).getTime();
|
|
@@ -2212,6 +2330,10 @@ function printGlobalHelp(commands) {
|
|
|
2212
2330
|
lines.push(" -h, --help Show this help, or per-command help with `camstack <cmd> --help`");
|
|
2213
2331
|
console.log(lines.join("\n"));
|
|
2214
2332
|
}
|
|
2333
|
+
var TOKEN_RESOLUTION_HELP = [
|
|
2334
|
+
"Token resolution (first hit wins): --token, --token-file, $CAMSTACK_TOKEN,",
|
|
2335
|
+
" then the session cached by `camstack login` for the target server."
|
|
2336
|
+
].join("\n");
|
|
2215
2337
|
function buildCommands() {
|
|
2216
2338
|
return [
|
|
2217
2339
|
{
|
|
@@ -2333,10 +2455,13 @@ function buildCommands() {
|
|
|
2333
2455
|
" --no-verify Skip the post-deploy hub /health gate",
|
|
2334
2456
|
"",
|
|
2335
2457
|
"Target options:",
|
|
2336
|
-
" -s, --server <url> Server URL (default:
|
|
2337
|
-
" -t, --token <token> Auth token override
|
|
2458
|
+
" -s, --server <url> Server URL (default: $CAMSTACK_SERVER, then the cached session)",
|
|
2459
|
+
" -t, --token <token> Auth token override",
|
|
2460
|
+
" --token-file <path> Read the token from a file (bare token or a ~/.camstack session file)",
|
|
2338
2461
|
" -n, --node <id> Push to a specific node. Mutually exclusive with --cluster",
|
|
2339
|
-
" -c, --cluster Push to hub + every online agent (requires admin token)"
|
|
2462
|
+
" -c, --cluster Push to hub + every online agent (requires admin token)",
|
|
2463
|
+
"",
|
|
2464
|
+
TOKEN_RESOLUTION_HELP
|
|
2340
2465
|
].join("\n")
|
|
2341
2466
|
},
|
|
2342
2467
|
{
|
|
@@ -2354,9 +2479,12 @@ function buildCommands() {
|
|
|
2354
2479
|
" and waits for the probation boot to promote.",
|
|
2355
2480
|
"",
|
|
2356
2481
|
"Options:",
|
|
2357
|
-
" -s, --server <url> Server URL (default:
|
|
2358
|
-
" -t, --token <token> Auth token override
|
|
2359
|
-
" --
|
|
2482
|
+
" -s, --server <url> Server URL (default: $CAMSTACK_SERVER, then the cached session)",
|
|
2483
|
+
" -t, --token <token> Auth token override",
|
|
2484
|
+
" --token-file <path> Read the token from a file (bare token or a ~/.camstack session file)",
|
|
2485
|
+
" --no-verify Do not wait for promotion after applyServerUpdate is accepted",
|
|
2486
|
+
"",
|
|
2487
|
+
TOKEN_RESOLUTION_HELP
|
|
2360
2488
|
].join("\n")
|
|
2361
2489
|
},
|
|
2362
2490
|
{
|
|
@@ -2372,6 +2500,7 @@ function buildCommands() {
|
|
|
2372
2500
|
"Options:",
|
|
2373
2501
|
" -s, --server <url> Server URL (default: cached session)",
|
|
2374
2502
|
" -t, --token <token> Auth token override",
|
|
2503
|
+
" --token-file <path> Read the token from a file",
|
|
2375
2504
|
" -n, --node <id> Push to a specific node",
|
|
2376
2505
|
" -c, --cluster Push to hub + every online agent",
|
|
2377
2506
|
" --no-build Skip `npm run build`",
|
|
@@ -2380,7 +2509,9 @@ function buildCommands() {
|
|
|
2380
2509
|
" --no-initial-deploy Skip initial deploy \u2014 only tail existing addon",
|
|
2381
2510
|
"",
|
|
2382
2511
|
"Each round polls the last 100 entries; new entries (by timestamp+content)",
|
|
2383
|
-
"are printed. Ctrl-C to stop."
|
|
2512
|
+
"are printed. Ctrl-C to stop.",
|
|
2513
|
+
"",
|
|
2514
|
+
TOKEN_RESOLUTION_HELP
|
|
2384
2515
|
].join("\n")
|
|
2385
2516
|
},
|
|
2386
2517
|
{
|
|
@@ -2405,11 +2536,14 @@ function buildCommands() {
|
|
|
2405
2536
|
"Target options:",
|
|
2406
2537
|
" -s, --server <url> Server URL (default: cached session)",
|
|
2407
2538
|
" -t, --token <token> Auth token override",
|
|
2539
|
+
" --token-file <path> Read the token from a file",
|
|
2408
2540
|
" -n, --node <id> Push to a specific node",
|
|
2409
2541
|
" -c, --cluster Push to hub + every online agent",
|
|
2410
2542
|
"",
|
|
2411
2543
|
"Stop with Ctrl-C. Each cycle is sequential \u2014 concurrent changes during",
|
|
2412
|
-
"a push are coalesced into the next cycle."
|
|
2544
|
+
"a push are coalesced into the next cycle.",
|
|
2545
|
+
"",
|
|
2546
|
+
TOKEN_RESOLUTION_HELP
|
|
2413
2547
|
].join("\n")
|
|
2414
2548
|
},
|
|
2415
2549
|
{
|
|
@@ -2530,6 +2664,7 @@ async function runDeploy(args) {
|
|
|
2530
2664
|
{
|
|
2531
2665
|
server: { type: "string", short: "s" },
|
|
2532
2666
|
token: { type: "string", short: "t" },
|
|
2667
|
+
"token-file": { type: "string" },
|
|
2533
2668
|
node: { type: "string", short: "n" },
|
|
2534
2669
|
cluster: { type: "boolean", short: "c" },
|
|
2535
2670
|
build: { type: "string", short: "b" },
|
|
@@ -2544,15 +2679,9 @@ async function runDeploy(args) {
|
|
|
2544
2679
|
return;
|
|
2545
2680
|
}
|
|
2546
2681
|
const addonPath = parsed.positionals[0] ?? ".";
|
|
2547
|
-
const
|
|
2548
|
-
const server =
|
|
2549
|
-
const token =
|
|
2550
|
-
if (!token) {
|
|
2551
|
-
console.error(
|
|
2552
|
-
"[camstack] Error: No token. Run `camstack login` first, pass --token, or set CAMSTACK_TOKEN."
|
|
2553
|
-
);
|
|
2554
|
-
process.exit(1);
|
|
2555
|
-
}
|
|
2682
|
+
const creds = resolveCommandCredentials(parsed.values);
|
|
2683
|
+
const server = creds.server ?? DEFAULT_SERVER_URL;
|
|
2684
|
+
const token = creds.token;
|
|
2556
2685
|
const nodeId = stringOpt(parsed.values, "node");
|
|
2557
2686
|
const cluster = boolOpt(parsed.values, "cluster");
|
|
2558
2687
|
if (nodeId && cluster) {
|
|
@@ -2574,6 +2703,7 @@ async function runDeploy(args) {
|
|
|
2574
2703
|
await deployAddon(addonPath, {
|
|
2575
2704
|
serverUrl: server,
|
|
2576
2705
|
token,
|
|
2706
|
+
authSource: creds.source,
|
|
2577
2707
|
...nodeId ? { nodeId } : {},
|
|
2578
2708
|
...cluster ? { cluster: true } : {},
|
|
2579
2709
|
buildMode,
|
|
@@ -2587,6 +2717,7 @@ async function runDeployServer(args) {
|
|
|
2587
2717
|
{
|
|
2588
2718
|
server: { type: "string", short: "s" },
|
|
2589
2719
|
token: { type: "string", short: "t" },
|
|
2720
|
+
"token-file": { type: "string" },
|
|
2590
2721
|
"no-verify": { type: "boolean" }
|
|
2591
2722
|
},
|
|
2592
2723
|
false
|
|
@@ -2595,21 +2726,36 @@ async function runDeployServer(args) {
|
|
|
2595
2726
|
console.log(commandHelp("deploy-server"));
|
|
2596
2727
|
return;
|
|
2597
2728
|
}
|
|
2598
|
-
const
|
|
2599
|
-
const server = stringOpt(parsed.values, "server") ?? process.env.CAMSTACK_SERVER ?? session?.server ?? "https://localhost:4443";
|
|
2600
|
-
const token = stringOpt(parsed.values, "token") ?? process.env.CAMSTACK_TOKEN ?? session?.token;
|
|
2601
|
-
if (!token) {
|
|
2602
|
-
console.error(
|
|
2603
|
-
"[camstack] Error: No token. Run `camstack login` first, pass --token, or set CAMSTACK_TOKEN."
|
|
2604
|
-
);
|
|
2605
|
-
process.exit(1);
|
|
2606
|
-
}
|
|
2729
|
+
const creds = resolveCommandCredentials(parsed.values);
|
|
2607
2730
|
await deployServer({
|
|
2608
|
-
serverUrl: server,
|
|
2609
|
-
token,
|
|
2731
|
+
serverUrl: creds.server ?? DEFAULT_SERVER_URL,
|
|
2732
|
+
token: creds.token,
|
|
2733
|
+
authSource: creds.source,
|
|
2610
2734
|
verify: !boolOpt(parsed.values, "no-verify")
|
|
2611
2735
|
});
|
|
2612
2736
|
}
|
|
2737
|
+
var DEFAULT_SERVER_URL = "https://localhost:4443";
|
|
2738
|
+
function resolveCommandCredentials(values) {
|
|
2739
|
+
const server = stringOpt(values, "server");
|
|
2740
|
+
const token = stringOpt(values, "token");
|
|
2741
|
+
const tokenFile = stringOpt(values, "token-file");
|
|
2742
|
+
try {
|
|
2743
|
+
const creds = resolveCredentials({
|
|
2744
|
+
...server ? { server } : {},
|
|
2745
|
+
...token ? { token } : {},
|
|
2746
|
+
...tokenFile ? { tokenFile } : {},
|
|
2747
|
+
loadSession
|
|
2748
|
+
});
|
|
2749
|
+
if (creds.warning) console.error(`[camstack] Warning: ${creds.warning}`);
|
|
2750
|
+
return creds;
|
|
2751
|
+
} catch (err) {
|
|
2752
|
+
if (err instanceof MissingCredentialsError) {
|
|
2753
|
+
console.error(`[camstack] ${err.message}`);
|
|
2754
|
+
process.exit(1);
|
|
2755
|
+
}
|
|
2756
|
+
throw err;
|
|
2757
|
+
}
|
|
2758
|
+
}
|
|
2613
2759
|
function commandHelp(name) {
|
|
2614
2760
|
const cmd = buildCommands().find((c) => c.name === name);
|
|
2615
2761
|
return cmd ? cmd.help() : "";
|