create-op-node 0.10.3 → 0.10.5

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
@@ -28,7 +28,10 @@ async function get(token, path, fetchImpl = fetch) {
28
28
  function shortError(body) {
29
29
  if (typeof body === "object" && body !== null && "errors" in body && Array.isArray(body.errors)) {
30
30
  const errs = body.errors;
31
- return errs.map((e) => `${e.code ? `CF ${e.code}: ` : ""}${e.message ?? "unknown"}`).join("; ");
31
+ return errs.map((e) => {
32
+ const prefix = e.code ? `CF ${e.code}: ` : "";
33
+ return `${prefix}${e.message ?? "unknown"}`;
34
+ }).join("; ");
32
35
  }
33
36
  return "no error message returned";
34
37
  }
@@ -484,7 +487,7 @@ function generatePgsodiumRootKey() {
484
487
  }
485
488
  function base64url(input) {
486
489
  const buf = typeof input === "string" ? Buffer.from(input) : input;
487
- return buf.toString("base64").replace(/=+$/, "").replace(/\+/g, "-").replace(/\//g, "_");
490
+ return buf.toString("base64").replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
488
491
  }
489
492
  function generatePostgresPassword() {
490
493
  return base64url(randomBytes(32));
@@ -710,12 +713,13 @@ var initCommand = new Command("init").description(
710
713
  const kcNote = keychain.available ? `\u2713 macOS Keychain available \u2014 pgsodium key + Tunnel token will be saved to your login keychain.
711
714
  ` + pc2.dim("Note: items don't sync to iCloud Keychain via the security CLI.\n") + pc2.dim("On the Studio, bootstrap will read locally and prompt you to paste if missing.") : `\u26A0 ${keychain.reason ?? "Keychain unavailable"}. Secrets will be printed for manual stash.`;
712
715
  p3.note(kcNote, "Secret store");
716
+ const orgWriteAccess = pc2.dim(`required for ${owner}`);
713
717
  p3.note(
714
718
  opts.localOnly ? [
715
719
  `Region label: ${pc2.cyan(region)}`,
716
720
  `New node repo: ${pc2.cyan(newRepoFull)}`,
717
721
  `Template: ${pc2.dim(opts.template ?? "OpusPopuli/opuspopuli-node")}`,
718
- `GH org write access: ${pc2.dim(`required for ${owner}`)}`,
722
+ `GH org write access: ${orgWriteAccess}`,
719
723
  ``,
720
724
  `Will create the repo from template (private, no Cloudflare),`,
721
725
  `and store a fresh pgsodium key in Keychain. That's it \u2014 no PR,`,
@@ -727,7 +731,7 @@ var initCommand = new Command("init").description(
727
731
  `New node repo: ${pc2.cyan(newRepoFull)}`,
728
732
  `Template: ${pc2.dim(opts.template ?? "OpusPopuli/opuspopuli-node")}`,
729
733
  `TFC organization: ${pc2.cyan(publicConfig?.tfOrg ?? "")}`,
730
- `GH org write access: ${pc2.dim(`required for ${owner}`)}`,
734
+ `GH org write access: ${orgWriteAccess}`,
731
735
  ``,
732
736
  `Will create the repo, seed 5 secrets, write prod.tfvars on a branch,`,
733
737
  `open a PR, generate a fresh pgsodium key, and (after you merge) wait`,
@@ -1010,7 +1014,10 @@ async function collectPublicConfig(opts) {
1010
1014
  await p3.text({
1011
1015
  message: "Domain registered in Cloudflare?",
1012
1016
  placeholder: "example.org",
1013
- validate: (v) => !v ? "Required" : v.includes(".") ? void 0 : "Missing a TLD?"
1017
+ validate: (v) => {
1018
+ if (!v) return "Required";
1019
+ return v.includes(".") ? void 0 : "Missing a TLD?";
1020
+ }
1014
1021
  })
1015
1022
  );
1016
1023
  const cfToken = await collectSecret(
@@ -1054,9 +1061,10 @@ async function collectPublicConfig(opts) {
1054
1061
  p3.cancel("Fix the token / org, then re-run.");
1055
1062
  process.exit(1);
1056
1063
  }
1064
+ const asUser = tfProbe.userName ? ` (as ${tfProbe.userName})` : "";
1057
1065
  tfSpin.stop(
1058
1066
  pc2.green(
1059
- `\u2713 TFC token valid${tfProbe.userName ? ` (as ${tfProbe.userName})` : ""}, org "${tfOrg}" reachable.`
1067
+ `\u2713 TFC token valid${asUser}, org "${tfOrg}" reachable.`
1060
1068
  )
1061
1069
  );
1062
1070
  return { domain, cfToken, cfAccount, cfZone, tfToken, tfOrg };
@@ -2297,7 +2305,10 @@ var bootstrapCommand = new Command("bootstrap").description(
2297
2305
  validate: (v) => URL_SAFE_PASSWORD_RE.test(v) ? void 0 : "must be base64url chars only (no + / =)"
2298
2306
  });
2299
2307
  }
2300
- const promptServiceUrl = nodeType === "region-with-prompts" ? "http://opuspopuli-prompts:3210" : opts.promptServiceUrl ?? "https://prompts.opuspopuli.org";
2308
+ const promptServiceUrl = nodeType === "region-with-prompts" ? (
2309
+ // eslint-disable-next-line sonarjs/no-clear-text-protocols -- in-network (docker) prompt-service URL is legitimately plaintext http; no TLS on the internal bridge
2310
+ "http://opuspopuli-prompts:3210"
2311
+ ) : opts.promptServiceUrl ?? "https://prompts.opuspopuli.org";
2301
2312
  if (!SAFE_URL_RE.test(promptServiceUrl)) {
2302
2313
  p3.cancel(
2303
2314
  `--prompt-service-url ${JSON.stringify(promptServiceUrl)} contains characters outside the allowed URL set`
@@ -2314,7 +2325,10 @@ var bootstrapCommand = new Command("bootstrap").description(
2314
2325
  await p3.text({
2315
2326
  message: "Public-facing Supabase URL (what browsers + microservices use to reach kong)?",
2316
2327
  placeholder: "https://supabase.civicfeed.tx",
2317
- validate: (v) => !v ? "required" : SAFE_URL_RE.test(v) ? void 0 : "contains characters outside the allowed URL set"
2328
+ validate: (v) => {
2329
+ if (!v) return "required";
2330
+ return SAFE_URL_RE.test(v) ? void 0 : "contains characters outside the allowed URL set";
2331
+ }
2318
2332
  })
2319
2333
  );
2320
2334
  }
@@ -2587,8 +2601,8 @@ async function selectLlmModel(opts) {
2587
2601
  );
2588
2602
  }
2589
2603
  function estimatedPullTime(model) {
2590
- if (/\d+x\d+b/i.test(model)) return "~60+ min for frontier MoE";
2591
- const match = /(\d+)b\b/i.exec(model);
2604
+ if (/\d{1,3}x\d{1,3}b/i.test(model)) return "~60+ min for frontier MoE";
2605
+ const match = /(\d{1,4})b\b/i.exec(model);
2592
2606
  if (!match) return "time depends on model size";
2593
2607
  const size = Number.parseInt(match[1], 10);
2594
2608
  if (size <= 13) return "~3\u20135 min for \u2264 13B-class";
@@ -2940,11 +2954,19 @@ var resetCommand = new Command("reset").description(
2940
2954
  ...opts.envFile ? { envFile: opts.envFile } : {}
2941
2955
  });
2942
2956
  }
2957
+ let runningContainersLabel;
2958
+ if (runningContainers === null) {
2959
+ runningContainersLabel = pc2.dim("unknown");
2960
+ } else if (runningContainers.length === 0) {
2961
+ runningContainersLabel = pc2.dim("none");
2962
+ } else {
2963
+ runningContainersLabel = pc2.cyan(`${runningContainers.length} listed by compose ps`);
2964
+ }
2943
2965
  p3.note(
2944
2966
  [
2945
2967
  `Region: ${pc2.cyan(region)}`,
2946
2968
  `Repo path: ${repoPath ? pc2.cyan(repoPath) : pc2.dim(`not used (${stackSkipReason ?? "no repo path resolved"})`)}`,
2947
- `Running containers: ${runningContainers === null ? pc2.dim("unknown") : runningContainers.length === 0 ? pc2.dim("none") : pc2.cyan(`${runningContainers.length} listed by compose ps`)}`,
2969
+ `Running containers: ${runningContainersLabel}`,
2948
2970
  `LaunchAgent plist: ${plistExists ? pc2.cyan(launchAgentPaths.plistFile) : pc2.dim("not present")}`,
2949
2971
  `pgsodium key file: ${keyFileExists ? pc2.cyan(launchAgentPaths.keyFile) : pc2.dim("not present")}`,
2950
2972
  `Registry to log out: ${pc2.cyan(opts.registry ?? GHCR_REGISTRY)}`,
@@ -3400,7 +3422,7 @@ var verifyCommand = new Command("verify").description(
3400
3422
  );
3401
3423
  activeSpin?.stop("Done.");
3402
3424
  const visible = opts.showSkipped ?? false ? report.phases : report.phases.filter((ph) => ph.status !== "skipped");
3403
- const lines = visible.map((ph, i) => {
3425
+ const lines = visible.map((ph) => {
3404
3426
  const idx = report.phases.indexOf(ph) + 1;
3405
3427
  return `${phaseIcon2(ph)} [${idx}/${totalPhases}] ${ph.name}: ${pc2.dim(ph.detail)}`;
3406
3428
  });
@@ -3411,9 +3433,11 @@ var verifyCommand = new Command("verify").description(
3411
3433
  p3.note(lines.join("\n"), "Summary");
3412
3434
  const summary = summarize(report);
3413
3435
  if (summary.ok) {
3414
- p3.outro(
3415
- summary.warned === 0 ? pc2.green("All checks passed.") : pc2.yellow(`Passed with ${summary.warned} warning${summary.warned === 1 ? "" : "s"}.`)
3416
- );
3436
+ if (summary.warned === 0) {
3437
+ p3.outro(pc2.green("All checks passed."));
3438
+ } else {
3439
+ p3.outro(pc2.yellow(`Passed with ${summary.warned} warning${summary.warned === 1 ? "" : "s"}.`));
3440
+ }
3417
3441
  } else {
3418
3442
  p3.outro(pc2.red(`${summary.failed} check${summary.failed === 1 ? "" : "s"} failed.`));
3419
3443
  process.exit(1);
@@ -3431,9 +3455,21 @@ function phaseIcon2(ph) {
3431
3455
  return pc2.red("\u2717");
3432
3456
  }
3433
3457
  }
3458
+ function phaseColor(status) {
3459
+ switch (status) {
3460
+ case "ok":
3461
+ return pc2.green;
3462
+ case "warn":
3463
+ return pc2.yellow;
3464
+ case "skipped":
3465
+ return pc2.dim;
3466
+ case "fail":
3467
+ return pc2.red;
3468
+ }
3469
+ }
3434
3470
  function formatPhaseLine(prefix, ph) {
3435
3471
  const icon = phaseIcon2(ph);
3436
- const colorize = ph.status === "ok" ? pc2.green : ph.status === "warn" ? pc2.yellow : ph.status === "skipped" ? pc2.dim : pc2.red;
3472
+ const colorize = phaseColor(ph.status);
3437
3473
  return colorize(`${icon} ${prefix}: ${ph.detail}`);
3438
3474
  }
3439
3475
 
@@ -4096,7 +4132,7 @@ var SOURCE_TYPES = [
4096
4132
  var SLUG_RE = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
4097
4133
  var STATE_CODE_RE = /^[A-Z]{2}$/;
4098
4134
  function slugify(input) {
4099
- return input.normalize("NFKD").replace(/[̀-ͯ]/g, "").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
4135
+ return input.normalize("NFKD").replace(/[̀-ͯ]/g, "").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
4100
4136
  }
4101
4137
  function isValidSlug(v) {
4102
4138
  return SLUG_RE.test(v);
@@ -4318,7 +4354,11 @@ var regionCommand = new Command("region").description(
4318
4354
  await p3.text({
4319
4355
  message: level === "county" ? "County FIPS (5 digits)?" : "State FIPS (2 digits)?",
4320
4356
  placeholder: level === "county" ? "06001" : "06",
4321
- validate: (v) => isValidFips(v ?? "", level) ? void 0 : `Expected ${level === "county" ? "5" : "2"} digits`
4357
+ validate: (v) => {
4358
+ if (isValidFips(v ?? "", level)) return void 0;
4359
+ const expectedDigits = level === "county" ? "5" : "2";
4360
+ return `Expected ${expectedDigits} digits`;
4361
+ }
4322
4362
  })
4323
4363
  );
4324
4364
  if (!isValidFips(fipsCode, level)) {
@@ -4452,7 +4492,7 @@ async function looksLikeRegionsRepo(dir) {
4452
4492
  }
4453
4493
 
4454
4494
  // src/cli.ts
4455
- var VERSION = "0.10.3";
4495
+ var VERSION = "0.10.5";
4456
4496
  var program = new Command();
4457
4497
  program.name("create-op-node").description(
4458
4498
  "Interactive bootstrap for an Opus Populi federation node.\nCloudflare infrastructure \u2192 Mac Studio \u2192 live public API."