@wraps.dev/cli 3.3.0 → 3.4.0

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
@@ -778,13 +778,13 @@ function handleCLIError(error, command6) {
778
778
  docsUrl = wrapsErr.docsUrl;
779
779
  } else {
780
780
  trackError("UNHANDLED_ERROR", cmdContext, {
781
- errorType: error instanceof Error ? error.constructor.name : typeof error,
782
- message: sanitizeErrorMessage(error)
781
+ errorType: error instanceof Error ? error.constructor.name : typeof error
783
782
  });
784
783
  message = error instanceof Error ? error.message : String(error || message);
785
784
  }
786
785
  jsonError(cmdContext, { code, message, suggestion, docsUrl });
787
- process.exit(1);
786
+ process.exitCode = 1;
787
+ return;
788
788
  }
789
789
  console.error("");
790
790
  if (error instanceof WrapsError) {
@@ -804,7 +804,8 @@ ${pc.yellow("Suggestion:")}`);
804
804
  console.log(` ${pc.blue(error.docsUrl)}
805
805
  `);
806
806
  }
807
- process.exit(1);
807
+ process.exitCode = 1;
808
+ return;
808
809
  }
809
810
  if (isAWSError(error)) {
810
811
  const { code, action } = parseAWSError(error);
@@ -830,7 +831,8 @@ ${pc.yellow("Suggestion:")}`);
830
831
  console.log(` ${pc.blue(wrapsError.docsUrl)}
831
832
  `);
832
833
  }
833
- process.exit(1);
834
+ process.exitCode = 1;
835
+ return;
834
836
  }
835
837
  if (isPulumiError(error)) {
836
838
  const { code, iamAction, service, resourceName, resourceType } = parsePulumiError(error);
@@ -862,11 +864,11 @@ ${pc.yellow("Suggestion:")}`);
862
864
  console.log(` ${pc.blue(wrapsError.docsUrl)}
863
865
  `);
864
866
  }
865
- process.exit(1);
867
+ process.exitCode = 1;
868
+ return;
866
869
  }
867
870
  trackError("UNHANDLED_ERROR", cmdContext, {
868
- errorType: error instanceof Error ? error.constructor.name : typeof error,
869
- message: sanitizeErrorMessage(error)
871
+ errorType: error instanceof Error ? error.constructor.name : typeof error
870
872
  });
871
873
  clack.log.error("An unexpected error occurred");
872
874
  if (error instanceof Error) {
@@ -878,7 +880,7 @@ ${pc.yellow("Suggestion:")}`);
878
880
  ${pc.dim("If this persists, please report at:")}`);
879
881
  console.log(` ${pc.blue("https://github.com/wraps-team/wraps/issues")}
880
882
  `);
881
- process.exit(1);
883
+ process.exitCode = 1;
882
884
  }
883
885
  function awsErrorToWrapsError(code, action, originalError, isAgentContext = false) {
884
886
  const originalName = originalError instanceof Error ? originalError.name : "";
@@ -1035,6 +1037,37 @@ Saved regions: ${savedRegions.join(", ")}` : "Pass --region or set AWS_REGION.\n
1035
1037
  `Pass ${flagHint} (or run in an interactive terminal).`,
1036
1038
  "https://wraps.dev/docs/reference/json-output"
1037
1039
  ),
1040
+ // ── User-input rejections ──────────────────────────────────────────────────
1041
+ // "The user gave us bad input and this message says exactly what was wrong."
1042
+ // These are WrapsErrors on purpose: handleCLIError's WrapsError branch
1043
+ // (errors.ts:424 human, :369 JSON) already renders the exact target shape —
1044
+ // a specific telemetry code, the message, the suggestion, exit non-zero —
1045
+ // whereas a bare `throw new Error(...)` falls through to the generic tail,
1046
+ // which prints "An unexpected error occurred" plus a GitHub-issue link and
1047
+ // reports the user's typo as UNHANDLED_ERROR.
1048
+ //
1049
+ // Callers throw these INSTEAD of printing their own clack.log.error and
1050
+ // usage line. That is not tidiness: an unguarded clack.log.error writes to
1051
+ // stdout ahead of the JSON envelope, so `--json` consumers were parsing the
1052
+ // human text and the envelope out of one stream.
1053
+ unknownCommand: (what, typed, suggestion) => new WrapsError(
1054
+ `Unknown ${what}: ${typed || "(none)"}`,
1055
+ "UNKNOWN_COMMAND",
1056
+ suggestion,
1057
+ "https://wraps.dev/docs/cli-reference"
1058
+ ),
1059
+ // Code deliberately reuses MISSING_REQUIRED_FLAG rather than minting a new one:
1060
+ // four commands already emit it inline (commands/sms/verify-number.ts:193,
1061
+ // commands/sms/test.ts:71, commands/email/config-domain.ts:208,
1062
+ // commands/email/test.ts:108), it is already on the errors reference page (:583),
1063
+ // and domains.test.ts:1251 already asserts it. A second code for one condition is
1064
+ // exactly the machine-readable inconsistency this feature exists to remove.
1065
+ missingInput: (what, usage) => new WrapsError(
1066
+ `${what} is required`,
1067
+ "MISSING_REQUIRED_FLAG",
1068
+ `Usage: ${usage}`,
1069
+ "https://wraps.dev/docs/cli-reference"
1070
+ ),
1038
1071
  pulumiError: (message) => new WrapsError(
1039
1072
  `Infrastructure deployment failed: ${message}`,
1040
1073
  "PULUMI_ERROR",
@@ -32427,7 +32460,7 @@ function collectRemediations(findings) {
32427
32460
  // src/commands/aws/doctor.ts
32428
32461
  init_json_output();
32429
32462
  var CATEGORY = "AWS Setup";
32430
- async function runDiagnostics(state2) {
32463
+ async function runDiagnostics(state2, regionOverride) {
32431
32464
  const results = [];
32432
32465
  if (state2.cliInstalled) {
32433
32466
  results.push({
@@ -32613,6 +32646,8 @@ async function runDiagnostics(state2) {
32613
32646
  }
32614
32647
  return results;
32615
32648
  }
32649
+ const configuredRegion = state2.region || "us-east-1";
32650
+ const effectiveRegion = regionOverride || state2.region;
32616
32651
  if (state2.region) {
32617
32652
  results.push({
32618
32653
  status: "pass",
@@ -32628,6 +32663,14 @@ async function runDiagnostics(state2) {
32628
32663
  remediation: remediations.setAwsRegion()
32629
32664
  });
32630
32665
  }
32666
+ if (regionOverride && regionOverride !== configuredRegion) {
32667
+ results.push({
32668
+ status: "info",
32669
+ category: CATEGORY,
32670
+ name: `Checked region: ${regionOverride}`,
32671
+ details: state2.region ? `Overrides the configured region ${state2.region}. The SES check below is about ${regionOverride}.` : `The SES check below is about ${regionOverride}, not the us-east-1 default.`
32672
+ });
32673
+ }
32631
32674
  if (!state2.sso.configured) {
32632
32675
  const profiles = getConfiguredProfiles();
32633
32676
  if (profiles.length > 1) {
@@ -32640,11 +32683,19 @@ async function runDiagnostics(state2) {
32640
32683
  }
32641
32684
  }
32642
32685
  if (state2.credentialsConfigured) {
32643
- const regionUsed = state2.region || "us-east-1";
32644
- const regionNote = state2.region ? `Region: ${regionUsed}` : `No AWS_REGION set \u2014 defaulted to ${regionUsed}. Set AWS_REGION if your deployment lives elsewhere.`;
32686
+ const regionUsed = effectiveRegion || "us-east-1";
32687
+ const regionNote = effectiveRegion ? `Region: ${regionUsed}` : `No AWS_REGION set \u2014 defaulted to ${regionUsed}. Set AWS_REGION if your deployment lives elsewhere.`;
32645
32688
  try {
32646
- const sandbox = await isSESSandbox(regionUsed);
32647
- if (sandbox) {
32689
+ const ses = await getSESAccountStatus(regionUsed);
32690
+ if (ses.sandboxUncertain) {
32691
+ results.push({
32692
+ status: "info",
32693
+ category: CATEGORY,
32694
+ name: "Could not confirm SES account status",
32695
+ details: `SES may not be enabled in this region, or the account may lack ses:GetAccount.
32696
+ ${regionNote}`
32697
+ });
32698
+ } else if (ses.isSandbox) {
32648
32699
  results.push({
32649
32700
  status: "warn",
32650
32701
  category: CATEGORY,
@@ -32665,7 +32716,7 @@ ${regionNote}`,
32665
32716
  results.push({
32666
32717
  status: "info",
32667
32718
  category: CATEGORY,
32668
- name: "Could not check SES status",
32719
+ name: "Could not confirm SES account status",
32669
32720
  details: `SES may not be enabled in this region.
32670
32721
  ${regionNote}`
32671
32722
  });
@@ -32731,22 +32782,32 @@ function suggestionsFor(results) {
32731
32782
  results.filter((r6) => r6.status === "fail" || r6.status === "warn")
32732
32783
  ).map(formatRemediation);
32733
32784
  }
32734
- async function collectAwsFindings() {
32735
- const state2 = await detectAWSState();
32736
- return { findings: await runDiagnostics(state2), state: state2 };
32785
+ async function collectAwsFindings(options = {}) {
32786
+ const state2 = options.state ?? await detectAWSState();
32787
+ return { findings: await runDiagnostics(state2, options.region), state: state2 };
32737
32788
  }
32738
- async function doctor() {
32789
+ async function doctor(options = {}) {
32739
32790
  const startTime = Date.now();
32740
32791
  if (!isJsonMode()) {
32741
32792
  clack5.intro(pc6.bold("AWS Setup Diagnostics"));
32742
32793
  }
32743
32794
  const spinner11 = isJsonMode() ? null : clack5.spinner();
32744
32795
  spinner11?.start("Running diagnostics...");
32745
- const { findings: results } = await collectAwsFindings();
32796
+ const { findings: results, state: state2 } = await collectAwsFindings({
32797
+ region: options.region
32798
+ });
32746
32799
  spinner11?.stop("Diagnostics complete");
32747
32800
  const failCount = results.filter((r6) => r6.status === "fail").length;
32748
32801
  const warnCount = results.filter((r6) => r6.status === "warn").length;
32749
32802
  const passCount = results.filter((r6) => r6.status === "pass").length;
32803
+ trackCommand("aws:doctor", {
32804
+ success: true,
32805
+ duration_ms: Date.now() - startTime,
32806
+ region: options.region || state2.region || "us-east-1",
32807
+ pass_count: passCount,
32808
+ fail_count: failCount,
32809
+ warn_count: warnCount
32810
+ });
32750
32811
  if (isJsonMode()) {
32751
32812
  jsonSuccess("aws.doctor", {
32752
32813
  checks: results.map((r6) => ({
@@ -32778,13 +32839,6 @@ async function doctor() {
32778
32839
  console.log(` ${pc6.dim("-")} ${suggestion}`);
32779
32840
  }
32780
32841
  }
32781
- trackCommand("aws:doctor", {
32782
- success: true,
32783
- duration_ms: Date.now() - startTime,
32784
- pass_count: passCount,
32785
- fail_count: failCount,
32786
- warn_count: warnCount
32787
- });
32788
32842
  console.log();
32789
32843
  clack5.outro(
32790
32844
  pc6.dim(failCount > 0 ? "See suggested fixes above" : "Ready to deploy")
@@ -36269,6 +36323,7 @@ ${pc16.dim("Tip:")} Run ${pc16.cyan("wraps cdn sync")} to update infrastructure
36269
36323
  init_esm_shims();
36270
36324
  init_events();
36271
36325
  init_aws();
36326
+ init_aws_detection();
36272
36327
  import * as clack16 from "@clack/prompts";
36273
36328
  import pc18 from "picocolors";
36274
36329
  init_json_output();
@@ -37256,19 +37311,23 @@ async function wrapsDoctor(options) {
37256
37311
  clack16.intro(pc18.bold("Wraps Doctor"));
37257
37312
  }
37258
37313
  const progress = new DeploymentProgress();
37259
- const { findings: awsFindings, state: state2 } = await progress.execute(
37260
- "Checking AWS setup",
37261
- async () => collectAwsFindings()
37314
+ const state2 = await progress.execute(
37315
+ "Detecting AWS setup",
37316
+ async () => detectAWSState()
37262
37317
  );
37263
- const findings = [...awsFindings];
37264
37318
  const emailConnections = state2.credentialsConfigured && state2.accountId ? await findConnectionsWithService(state2.accountId, "email") : [];
37265
37319
  const regionExplicit = Boolean(
37266
37320
  options.region || process.env.AWS_REGION || process.env.AWS_DEFAULT_REGION
37267
37321
  );
37268
- let region = options.region || await getAWSRegion();
37322
+ let region = options.region || state2.region || await getAWSRegion();
37269
37323
  if (!regionExplicit && emailConnections.length > 0) {
37270
37324
  region = emailConnections[0].region;
37271
37325
  }
37326
+ const { findings: awsFindings } = await progress.execute(
37327
+ "Checking AWS setup",
37328
+ async () => collectAwsFindings({ region, state: state2 })
37329
+ );
37330
+ const findings = [...awsFindings];
37272
37331
  if (state2.credentialsConfigured && state2.accountId) {
37273
37332
  if (!regionExplicit && emailConnections.length > 1) {
37274
37333
  findings.push({
@@ -53345,10 +53404,7 @@ ${pc40.bold("Cost Impact:")}`);
53345
53404
  trackError("STACK_LOCKED", "email:upgrade", { step: "deploy" });
53346
53405
  throw errors.stackLocked();
53347
53406
  }
53348
- trackError("UPGRADE_FAILED", "email:upgrade", {
53349
- step: "deploy",
53350
- error_detail: redactSensitiveValues(msg).slice(0, 3e3)
53351
- });
53407
+ trackError("UPGRADE_FAILED", "email:upgrade", { step: "deploy" });
53352
53408
  throw new Error(`Pulumi upgrade failed: ${extractPulumiErrorSummary(msg)}`);
53353
53409
  }
53354
53410
  let dnsAutoCreated = false;
@@ -56296,7 +56352,6 @@ import pc47 from "picocolors";
56296
56352
  init_events();
56297
56353
  init_aws();
56298
56354
  init_config();
56299
- init_errors();
56300
56355
  init_fs();
56301
56356
  init_json_output();
56302
56357
  init_metadata();
@@ -56960,9 +57015,7 @@ You can try the manual flow: ${pc47.cyan("wraps auth logout")} then ${pc47.cyan(
56960
57015
  progress.stop();
56961
57016
  const duration = Date.now() - startTime;
56962
57017
  const errorCode = error instanceof Error ? error.name : "UNKNOWN_ERROR";
56963
- trackError(errorCode, "platform:connect", {
56964
- message: sanitizeErrorMessage(error)
56965
- });
57018
+ trackError(errorCode, "platform:connect", { step: "authenticated" });
56966
57019
  trackCommand("platform:connect", {
56967
57020
  success: false,
56968
57021
  duration_ms: duration,
@@ -57243,9 +57296,7 @@ ${pc47.bold("Next Steps:")}`);
57243
57296
  progress.stop();
57244
57297
  const duration = Date.now() - startTime;
57245
57298
  const errorCode = error instanceof Error ? error.name : "UNKNOWN_ERROR";
57246
- trackError(errorCode, "platform:connect", {
57247
- message: sanitizeErrorMessage(error)
57248
- });
57299
+ trackError(errorCode, "platform:connect", { step: "unauthenticated" });
57249
57300
  trackCommand("platform:connect", {
57250
57301
  success: false,
57251
57302
  duration_ms: duration
@@ -66389,6 +66440,90 @@ function showNextSteps2() {
66389
66440
 
66390
66441
  // src/cli.ts
66391
66442
  init_client();
66443
+
66444
+ // src/telemetry/command-name.ts
66445
+ init_esm_shims();
66446
+
66447
+ // src/utils/shared/did-you-mean.ts
66448
+ init_esm_shims();
66449
+ var TOP_LEVEL_COMMANDS = [
66450
+ "auth",
66451
+ "aws",
66452
+ "cdn",
66453
+ "completion",
66454
+ "console",
66455
+ "destroy",
66456
+ "doctor",
66457
+ "email",
66458
+ "help",
66459
+ "license",
66460
+ "news",
66461
+ "permissions",
66462
+ "platform",
66463
+ "push",
66464
+ "selfhost",
66465
+ "sms",
66466
+ "status",
66467
+ "support",
66468
+ "telemetry",
66469
+ "update",
66470
+ "workflow"
66471
+ ];
66472
+ function distance(a6, b6) {
66473
+ let previous = Array.from({ length: b6.length + 1 }, (_, i6) => i6);
66474
+ for (let i6 = 1; i6 <= a6.length; i6++) {
66475
+ const current = [i6];
66476
+ for (let j6 = 1; j6 <= b6.length; j6++) {
66477
+ const substitution = previous[j6 - 1] + (a6[i6 - 1] === b6[j6 - 1] ? 0 : 1);
66478
+ current[j6] = Math.min(current[j6 - 1] + 1, previous[j6] + 1, substitution);
66479
+ }
66480
+ previous = current;
66481
+ }
66482
+ return previous[b6.length];
66483
+ }
66484
+ var MAX_DISTANCE = 2;
66485
+ function suggestCommand(input, known = TOP_LEVEL_COMMANDS) {
66486
+ const needle = input.toLowerCase();
66487
+ if (needle === "") {
66488
+ return null;
66489
+ }
66490
+ const candidates = known.filter((candidate) => candidate !== needle);
66491
+ let prefixMatch = null;
66492
+ for (const candidate of candidates) {
66493
+ if (candidate.startsWith(needle) && (prefixMatch === null || candidate.length < prefixMatch.length)) {
66494
+ prefixMatch = candidate;
66495
+ }
66496
+ }
66497
+ if (prefixMatch) {
66498
+ return prefixMatch;
66499
+ }
66500
+ let best = null;
66501
+ let bestDistance = Number.POSITIVE_INFINITY;
66502
+ for (const candidate of candidates) {
66503
+ const candidateDistance = distance(needle, candidate);
66504
+ if (candidateDistance < bestDistance) {
66505
+ best = candidate;
66506
+ bestDistance = candidateDistance;
66507
+ }
66508
+ }
66509
+ return bestDistance <= MAX_DISTANCE ? best : null;
66510
+ }
66511
+
66512
+ // src/telemetry/command-name.ts
66513
+ var UNKNOWN = "unknown";
66514
+ var COMMAND_WORD = /^[a-z][a-z0-9-]{0,31}$/;
66515
+ var COMMANDS_WITH_DATA_SECOND_POSITIONAL = ["push"];
66516
+ function telemetryCommandName(primaryCommand2, subCommand2) {
66517
+ if (!(primaryCommand2 && TOP_LEVEL_COMMANDS.includes(primaryCommand2))) {
66518
+ return UNKNOWN;
66519
+ }
66520
+ if (!subCommand2 || COMMANDS_WITH_DATA_SECOND_POSITIONAL.includes(primaryCommand2)) {
66521
+ return primaryCommand2;
66522
+ }
66523
+ return COMMAND_WORD.test(subCommand2) ? `${primaryCommand2}:${subCommand2}` : `${primaryCommand2}:${UNKNOWN}`;
66524
+ }
66525
+
66526
+ // src/cli.ts
66392
66527
  init_events();
66393
66528
 
66394
66529
  // src/utils/shared/arg-parser.ts
@@ -66562,71 +66697,6 @@ function printCompletionScript() {
66562
66697
  console.log("# --preview : Preview changes without deploying\n");
66563
66698
  }
66564
66699
 
66565
- // src/utils/shared/did-you-mean.ts
66566
- init_esm_shims();
66567
- var TOP_LEVEL_COMMANDS = [
66568
- "auth",
66569
- "aws",
66570
- "cdn",
66571
- "completion",
66572
- "console",
66573
- "destroy",
66574
- "doctor",
66575
- "email",
66576
- "help",
66577
- "license",
66578
- "news",
66579
- "permissions",
66580
- "platform",
66581
- "push",
66582
- "selfhost",
66583
- "sms",
66584
- "status",
66585
- "support",
66586
- "telemetry",
66587
- "update",
66588
- "workflow"
66589
- ];
66590
- function distance(a6, b6) {
66591
- let previous = Array.from({ length: b6.length + 1 }, (_, i6) => i6);
66592
- for (let i6 = 1; i6 <= a6.length; i6++) {
66593
- const current = [i6];
66594
- for (let j6 = 1; j6 <= b6.length; j6++) {
66595
- const substitution = previous[j6 - 1] + (a6[i6 - 1] === b6[j6 - 1] ? 0 : 1);
66596
- current[j6] = Math.min(current[j6 - 1] + 1, previous[j6] + 1, substitution);
66597
- }
66598
- previous = current;
66599
- }
66600
- return previous[b6.length];
66601
- }
66602
- var MAX_DISTANCE = 2;
66603
- function suggestCommand(input, known = TOP_LEVEL_COMMANDS) {
66604
- const needle = input.toLowerCase();
66605
- if (needle === "") {
66606
- return null;
66607
- }
66608
- const candidates = known.filter((candidate) => candidate !== needle);
66609
- let prefixMatch = null;
66610
- for (const candidate of candidates) {
66611
- if (candidate.startsWith(needle) && (prefixMatch === null || candidate.length < prefixMatch.length)) {
66612
- prefixMatch = candidate;
66613
- }
66614
- }
66615
- if (prefixMatch) {
66616
- return prefixMatch;
66617
- }
66618
- let best = null;
66619
- let bestDistance = Number.POSITIVE_INFINITY;
66620
- for (const candidate of candidates) {
66621
- const candidateDistance = distance(needle, candidate);
66622
- if (candidateDistance < bestDistance) {
66623
- best = candidate;
66624
- bestDistance = candidateDistance;
66625
- }
66626
- }
66627
- return bestDistance <= MAX_DISTANCE ? best : null;
66628
- }
66629
-
66630
66700
  // src/cli.ts
66631
66701
  init_errors();
66632
66702
  init_json_output();
@@ -67055,8 +67125,9 @@ if (!primaryCommand) {
67055
67125
  await telemetry.shutdown();
67056
67126
  }
67057
67127
  }
67058
- interactiveMenu().then(() => process.exit(0)).catch((err) => {
67128
+ interactiveMenu().then(() => process.exit(0)).catch(async (err) => {
67059
67129
  handleCLIError(err);
67130
+ await getTelemetryClient().shutdown();
67060
67131
  process.exit(1);
67061
67132
  });
67062
67133
  }
@@ -67173,13 +67244,10 @@ async function run() {
67173
67244
  break;
67174
67245
  case "verify": {
67175
67246
  if (!flags.domain) {
67176
- clack66.log.error("--domain flag is required");
67177
- console.log(
67178
- `
67179
- Usage: ${pc71.cyan("wraps email verify --domain yourapp.com")}
67180
- `
67247
+ throw errors.missingInput(
67248
+ "--domain",
67249
+ "wraps email verify --domain yourapp.com"
67181
67250
  );
67182
- throw new Error("Missing required flag: --domain");
67183
67251
  }
67184
67252
  await verifyDomain({
67185
67253
  domain: flags.domain,
@@ -67248,16 +67316,10 @@ Usage: ${pc71.cyan("wraps email verify --domain yourapp.com")}
67248
67316
  });
67249
67317
  break;
67250
67318
  default:
67251
- clack66.log.error(
67252
- `Unknown inbound command: ${inboundSubCommand || "(none)"}`
67253
- );
67254
- console.log(
67255
- `
67256
- Available commands: ${pc71.cyan("init")}, ${pc71.cyan("destroy")}, ${pc71.cyan("status")}, ${pc71.cyan("verify")}, ${pc71.cyan("test")}, ${pc71.cyan("add")}, ${pc71.cyan("remove")}
67257
- `
67258
- );
67259
- throw new Error(
67260
- `Unknown inbound command: ${inboundSubCommand || "(none)"}`
67319
+ throw errors.unknownCommand(
67320
+ "inbound command",
67321
+ inboundSubCommand,
67322
+ "Available commands: init, destroy, status, verify, test, add, remove"
67261
67323
  );
67262
67324
  }
67263
67325
  break;
@@ -67290,16 +67352,10 @@ Available commands: ${pc71.cyan("init")}, ${pc71.cyan("destroy")}, ${pc71.cyan("
67290
67352
  });
67291
67353
  break;
67292
67354
  default:
67293
- clack66.log.error(
67294
- `Unknown agent command: ${agentSubCommand || "(none)"}`
67295
- );
67296
- console.log(
67297
- `
67298
- Available commands: ${pc71.cyan("create")}, ${pc71.cyan("list")}, ${pc71.cyan("kill")}
67299
- `
67300
- );
67301
- throw new Error(
67302
- `Unknown agent command: ${agentSubCommand || "(none)"}`
67355
+ throw errors.unknownCommand(
67356
+ "agent command",
67357
+ agentSubCommand,
67358
+ "Available commands: create, list, kill"
67303
67359
  );
67304
67360
  }
67305
67361
  break;
@@ -67347,16 +67403,10 @@ Available commands: ${pc71.cyan("create")}, ${pc71.cyan("list")}, ${pc71.cyan("k
67347
67403
  break;
67348
67404
  }
67349
67405
  default:
67350
- clack66.log.error(
67351
- `Unknown reply command: ${replySubCommand || "(none)"}`
67352
- );
67353
- console.log(
67354
- `
67355
- Available commands: ${pc71.cyan("init")}, ${pc71.cyan("rotate")}, ${pc71.cyan("status")}, ${pc71.cyan("destroy")}, ${pc71.cyan("decode")}
67356
- `
67357
- );
67358
- throw new Error(
67359
- `Unknown reply command: ${replySubCommand || "(none)"}`
67406
+ throw errors.unknownCommand(
67407
+ "reply command",
67408
+ replySubCommand,
67409
+ "Available commands: init, rotate, status, destroy, decode"
67360
67410
  );
67361
67411
  }
67362
67412
  break;
@@ -67377,39 +67427,30 @@ Available commands: ${pc71.cyan("init")}, ${pc71.cyan("rotate")}, ${pc71.cyan("s
67377
67427
  break;
67378
67428
  case "verify": {
67379
67429
  if (!flags.domain) {
67380
- clack66.log.error("--domain flag is required");
67381
- console.log(
67382
- `
67383
- Usage: ${pc71.cyan("wraps email domains verify --domain yourapp.com")}
67384
- `
67430
+ throw errors.missingInput(
67431
+ "--domain",
67432
+ "wraps email domains verify --domain yourapp.com"
67385
67433
  );
67386
- throw new Error("Missing required flag: --domain");
67387
67434
  }
67388
67435
  await verifyDomain({ domain: flags.domain });
67389
67436
  break;
67390
67437
  }
67391
67438
  case "get-dkim": {
67392
67439
  if (!flags.domain) {
67393
- clack66.log.error("--domain flag is required");
67394
- console.log(
67395
- `
67396
- Usage: ${pc71.cyan("wraps email domains get-dkim --domain yourapp.com")}
67397
- `
67440
+ throw errors.missingInput(
67441
+ "--domain",
67442
+ "wraps email domains get-dkim --domain yourapp.com"
67398
67443
  );
67399
- throw new Error("Missing required flag: --domain");
67400
67444
  }
67401
67445
  await getDkim({ domain: flags.domain });
67402
67446
  break;
67403
67447
  }
67404
67448
  case "remove": {
67405
67449
  if (!flags.domain) {
67406
- clack66.log.error("--domain flag is required");
67407
- console.log(
67408
- `
67409
- Usage: ${pc71.cyan("wraps email domains remove --domain yourapp.com --force")}
67410
- `
67450
+ throw errors.missingInput(
67451
+ "--domain",
67452
+ "wraps email domains remove --domain yourapp.com --force"
67411
67453
  );
67412
- throw new Error("Missing required flag: --domain");
67413
67454
  }
67414
67455
  await removeDomain({
67415
67456
  domain: flags.domain,
@@ -67436,16 +67477,10 @@ Usage: ${pc71.cyan("wraps email domains remove --domain yourapp.com --force")}
67436
67477
  break;
67437
67478
  }
67438
67479
  default:
67439
- clack66.log.error(
67440
- `Unknown domains command: ${domainsSubCommand || "(none)"}`
67441
- );
67442
- console.log(
67443
- `
67444
- Available commands: ${pc71.cyan("add")}, ${pc71.cyan("list")}, ${pc71.cyan("verify")}, ${pc71.cyan("get-dkim")}, ${pc71.cyan("remove")}, ${pc71.cyan("config")}
67445
- `
67446
- );
67447
- throw new Error(
67448
- `Unknown domains command: ${domainsSubCommand || "(none)"}`
67480
+ throw errors.unknownCommand(
67481
+ "domains command",
67482
+ domainsSubCommand,
67483
+ "Available commands: add, list, verify, get-dkim, remove, config"
67449
67484
  );
67450
67485
  }
67451
67486
  break;
@@ -67483,16 +67518,10 @@ Available commands: ${pc71.cyan("add")}, ${pc71.cyan("list")}, ${pc71.cyan("veri
67483
67518
  });
67484
67519
  break;
67485
67520
  default:
67486
- clack66.log.error(
67487
- `Unknown templates command: ${templatesSubCommand || "(none)"}`
67488
- );
67489
- console.log(
67490
- `
67491
- Available commands: ${pc71.cyan("init")}, ${pc71.cyan("push")}, ${pc71.cyan("preview")}
67492
- `
67493
- );
67494
- throw new Error(
67495
- `Unknown templates command: ${templatesSubCommand || "(none)"}`
67521
+ throw errors.unknownCommand(
67522
+ "templates command",
67523
+ templatesSubCommand,
67524
+ "Available commands: init, push, preview"
67496
67525
  );
67497
67526
  }
67498
67527
  break;
@@ -67527,16 +67556,10 @@ Available commands: ${pc71.cyan("init")}, ${pc71.cyan("push")}, ${pc71.cyan("pre
67527
67556
  });
67528
67557
  break;
67529
67558
  default:
67530
- clack66.log.error(
67531
- `Unknown workflows command: ${workflowsSubCommand || "(none)"}`
67532
- );
67533
- console.log(
67534
- `
67535
- Available commands: ${pc71.cyan("init")}, ${pc71.cyan("validate")}, ${pc71.cyan("push")}
67536
- `
67537
- );
67538
- throw new Error(
67539
- `Unknown workflows command: ${workflowsSubCommand || "(none)"}`
67559
+ throw errors.unknownCommand(
67560
+ "workflows command",
67561
+ workflowsSubCommand,
67562
+ "Available commands: init, validate, push"
67540
67563
  );
67541
67564
  }
67542
67565
  break;
@@ -67557,8 +67580,10 @@ Available commands: ${pc71.cyan("init")}, ${pc71.cyan("validate")}, ${pc71.cyan(
67557
67580
  case "get": {
67558
67581
  const messageId = sub[3];
67559
67582
  if (!messageId) {
67560
- clack66.log.error("Usage: wraps email logs get <message-id>");
67561
- throw new Error("Missing required argument: <message-id>");
67583
+ throw errors.missingInput(
67584
+ "<message-id>",
67585
+ "wraps email logs get <message-id>"
67586
+ );
67562
67587
  }
67563
67588
  await emailLogsGet({
67564
67589
  messageId,
@@ -67569,16 +67594,10 @@ Available commands: ${pc71.cyan("init")}, ${pc71.cyan("validate")}, ${pc71.cyan(
67569
67594
  break;
67570
67595
  }
67571
67596
  default:
67572
- clack66.log.error(
67573
- `Unknown logs command: ${logsSubCommand || "(none)"}`
67574
- );
67575
- console.log(
67576
- `
67577
- Available commands: ${pc71.cyan("list")}, ${pc71.cyan("get <message-id>")}
67578
- `
67579
- );
67580
- throw new Error(
67581
- `Unknown logs command: ${logsSubCommand || "(none)"}`
67597
+ throw errors.unknownCommand(
67598
+ "logs command",
67599
+ logsSubCommand,
67600
+ "Available commands: list, get <message-id>"
67582
67601
  );
67583
67602
  }
67584
67603
  break;
@@ -67599,13 +67618,11 @@ Available commands: ${pc71.cyan("list")}, ${pc71.cyan("get <message-id>")}
67599
67618
  });
67600
67619
  break;
67601
67620
  default:
67602
- clack66.log.error(`Unknown email command: ${subCommand}`);
67603
- console.log(
67604
- `
67605
- Run ${pc71.cyan("wraps --help")} for available commands.
67606
- `
67621
+ throw errors.unknownCommand(
67622
+ "email command",
67623
+ subCommand,
67624
+ "Run wraps --help for available commands."
67607
67625
  );
67608
- throw new Error(`Unknown email command: ${subCommand}`);
67609
67626
  }
67610
67627
  const emailDuration = Date.now() - startTime;
67611
67628
  const emailCommandName = `email:${subCommand}`;
@@ -67627,13 +67644,11 @@ Run ${pc71.cyan("wraps --help")} for available commands.
67627
67644
  });
67628
67645
  break;
67629
67646
  default:
67630
- clack66.log.error(`Unknown license command: ${subCommand}`);
67631
- console.log(
67632
- `
67633
- Run ${pc71.cyan("wraps --help")} for available commands.
67634
- `
67647
+ throw errors.unknownCommand(
67648
+ "license command",
67649
+ subCommand,
67650
+ "Run wraps --help for available commands."
67635
67651
  );
67636
- throw new Error(`Unknown license command: ${subCommand}`);
67637
67652
  }
67638
67653
  trackCommand(`license:${subCommand}`, {
67639
67654
  success: true,
@@ -67701,13 +67716,11 @@ Run ${pc71.cyan("wraps --help")} for available commands.
67701
67716
  });
67702
67717
  break;
67703
67718
  default:
67704
- clack66.log.error(`Unknown selfhost command: ${subCommand}`);
67705
- console.log(
67706
- `
67707
- Run ${pc71.cyan("wraps --help")} for available commands.
67708
- `
67719
+ throw errors.unknownCommand(
67720
+ "selfhost command",
67721
+ subCommand,
67722
+ "Run wraps --help for available commands."
67709
67723
  );
67710
- throw new Error(`Unknown selfhost command: ${subCommand}`);
67711
67724
  }
67712
67725
  const selfhostDuration = Date.now() - startTime;
67713
67726
  const selfhostCommandName = `selfhost:${subCommand}`;
@@ -67787,13 +67800,11 @@ Run ${pc71.cyan("wraps --help")} for available commands.
67787
67800
  });
67788
67801
  break;
67789
67802
  default:
67790
- clack66.log.error(`Unknown sms command: ${subCommand}`);
67791
- console.log(
67792
- `
67793
- Run ${pc71.cyan("wraps --help")} for available commands.
67794
- `
67803
+ throw errors.unknownCommand(
67804
+ "sms command",
67805
+ subCommand,
67806
+ "Run wraps --help for available commands."
67795
67807
  );
67796
- throw new Error(`Unknown sms command: ${subCommand}`);
67797
67808
  }
67798
67809
  const smsDuration = Date.now() - startTime;
67799
67810
  const smsCommandName = `sms:${subCommand}`;
@@ -67851,13 +67862,11 @@ Run ${pc71.cyan("wraps --help")} for available commands.
67851
67862
  });
67852
67863
  break;
67853
67864
  default:
67854
- clack66.log.error(`Unknown cdn command: ${subCommand}`);
67855
- console.log(
67856
- `
67857
- Run ${pc71.cyan("wraps --help")} for available commands.
67858
- `
67865
+ throw errors.unknownCommand(
67866
+ "cdn command",
67867
+ subCommand,
67868
+ "Run wraps --help for available commands."
67859
67869
  );
67860
- throw new Error(`Unknown cdn command: ${subCommand}`);
67861
67870
  }
67862
67871
  const cdnDuration = Date.now() - startTime;
67863
67872
  const cdnCommandName = `cdn:${subCommand}`;
@@ -67876,16 +67885,10 @@ Run ${pc71.cyan("wraps --help")} for available commands.
67876
67885
  });
67877
67886
  break;
67878
67887
  default:
67879
- clack66.log.error(
67880
- `Unknown workflow command: ${subCommand || "(none)"}`
67881
- );
67882
- console.log(`
67883
- Available commands: ${pc71.cyan("init")}
67884
- `);
67885
- console.log(`Run ${pc71.cyan("wraps --help")} for more information.
67886
- `);
67887
- throw new Error(
67888
- `Unknown workflow command: ${subCommand || "(none)"}`
67888
+ throw errors.unknownCommand(
67889
+ "workflow command",
67890
+ subCommand,
67891
+ "Available commands: init\n\nRun wraps --help for more information."
67889
67892
  );
67890
67893
  }
67891
67894
  const workflowDuration = Date.now() - startTime;
@@ -67924,17 +67927,11 @@ Available commands: ${pc71.cyan("init")}
67924
67927
  });
67925
67928
  break;
67926
67929
  default:
67927
- clack66.log.error(`Unknown platform command: ${subCommand}`);
67928
- console.log(
67929
- `
67930
- Available commands: ${pc71.cyan("connect")}, ${pc71.cyan("update-role")}
67931
- `
67930
+ throw errors.unknownCommand(
67931
+ "platform command",
67932
+ subCommand,
67933
+ "Available commands: connect, update-role\n\nRun wraps platform for more information."
67932
67934
  );
67933
- console.log(
67934
- `Run ${pc71.cyan("wraps platform")} for more information.
67935
- `
67936
- );
67937
- throw new Error(`Unknown platform command: ${subCommand}`);
67938
67935
  }
67939
67936
  const platformDuration = Date.now() - startTime;
67940
67937
  const platformCommandName = `platform:${subCommand}`;
@@ -67956,13 +67953,11 @@ Available commands: ${pc71.cyan("connect")}, ${pc71.cyan("update-role")}
67956
67953
  await logout();
67957
67954
  break;
67958
67955
  default:
67959
- clack66.log.error(`Unknown auth command: ${subCommand || "(none)"}`);
67960
- console.log(
67961
- `
67962
- Available commands: ${pc71.cyan("login")}, ${pc71.cyan("status")}, ${pc71.cyan("logout")}
67963
- `
67956
+ throw errors.unknownCommand(
67957
+ "auth command",
67958
+ subCommand,
67959
+ "Available commands: login, status, logout"
67964
67960
  );
67965
- throw new Error(`Unknown auth command: ${subCommand || "(none)"}`);
67966
67961
  }
67967
67962
  return;
67968
67963
  }
@@ -67972,18 +67967,14 @@ Available commands: ${pc71.cyan("login")}, ${pc71.cyan("status")}, ${pc71.cyan("
67972
67967
  await setup({});
67973
67968
  break;
67974
67969
  case "doctor":
67975
- await doctor();
67970
+ await doctor({ region: flags.region, json: flags.json });
67976
67971
  break;
67977
67972
  default:
67978
- clack66.log.error(`Unknown aws command: ${subCommand}`);
67979
- console.log(
67980
- `
67981
- Available commands: ${pc71.cyan("setup")}, ${pc71.cyan("doctor")}
67982
- `
67973
+ throw errors.unknownCommand(
67974
+ "aws command",
67975
+ subCommand,
67976
+ "Available commands: setup, doctor\n\nRun wraps --help for more information."
67983
67977
  );
67984
- console.log(`Run ${pc71.cyan("wraps --help")} for more information.
67985
- `);
67986
- throw new Error(`Unknown aws command: ${subCommand}`);
67987
67978
  }
67988
67979
  const awsDuration = Date.now() - startTime;
67989
67980
  const awsCommandName = `aws:${subCommand}`;
@@ -68068,13 +68059,11 @@ Available commands: ${pc71.cyan("setup")}, ${pc71.cyan("doctor")}
68068
68059
  await telemetryStatus();
68069
68060
  break;
68070
68061
  default:
68071
- clack66.log.error(`Unknown telemetry command: ${subCommand}`);
68072
- console.log(
68073
- `
68074
- Available commands: ${pc71.cyan("enable")}, ${pc71.cyan("disable")}, ${pc71.cyan("status")}
68075
- `
68062
+ throw errors.unknownCommand(
68063
+ "telemetry command",
68064
+ subCommand,
68065
+ "Available commands: enable, disable, status"
68076
68066
  );
68077
- throw new Error(`Unknown telemetry command: ${subCommand}`);
68078
68067
  }
68079
68068
  break;
68080
68069
  }
@@ -68095,29 +68084,22 @@ Please specify a command for ${primaryCommand} service.
68095
68084
  showHelp();
68096
68085
  break;
68097
68086
  default: {
68098
- clack66.log.error(`Unknown command: ${primaryCommand}`);
68099
- const suggestion = suggestCommand(primaryCommand);
68100
- if (suggestion) {
68101
- console.log(`
68102
- Did you mean ${pc71.cyan(`wraps ${suggestion}`)}?`);
68103
- }
68104
- console.log(
68105
- `
68106
- Run ${pc71.cyan("wraps --help")} for available commands.
68107
- `
68108
- );
68109
- throw new Error(`Unknown command: ${primaryCommand}`);
68087
+ const didYouMean = suggestCommand(primaryCommand);
68088
+ const hint = didYouMean ? `Did you mean: wraps ${didYouMean}
68089
+
68090
+ Run wraps --help for available commands.` : "Run wraps --help for available commands.";
68091
+ throw errors.unknownCommand("command", primaryCommand, hint);
68110
68092
  }
68111
68093
  }
68112
68094
  const duration = Date.now() - startTime;
68113
- const commandName = subCommand ? `${primaryCommand}:${subCommand}` : primaryCommand;
68095
+ const commandName = telemetryCommandName(primaryCommand, subCommand);
68114
68096
  trackCommand(commandName, {
68115
68097
  success: true,
68116
68098
  duration_ms: duration
68117
68099
  });
68118
68100
  } catch (error) {
68119
68101
  const duration = Date.now() - startTime;
68120
- const commandName = subCommand ? `${primaryCommand}:${subCommand}` : primaryCommand;
68102
+ const commandName = telemetryCommandName(primaryCommand, subCommand);
68121
68103
  trackCommand(commandName, {
68122
68104
  success: false,
68123
68105
  duration_ms: duration
@@ -68125,6 +68107,9 @@ Run ${pc71.cyan("wraps --help")} for available commands.
68125
68107
  handleCLIError(error, commandName);
68126
68108
  } finally {
68127
68109
  await telemetry.shutdown();
68110
+ if (process.exitCode) {
68111
+ process.exit(process.exitCode);
68112
+ }
68128
68113
  }
68129
68114
  }
68130
68115
  if (primaryCommand) {