@wraps.dev/cli 2.18.11 → 2.18.13

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
@@ -461,7 +461,9 @@ function classifyDNSError(error) {
461
461
  return "unknown";
462
462
  }
463
463
  function isAWSNotFoundError(error) {
464
- if (!(error instanceof Error)) return false;
464
+ if (!(error instanceof Error)) {
465
+ return false;
466
+ }
465
467
  const awsError = error;
466
468
  return error.name === "NotFoundException" || error.name === "NoSuchEntityException" || error.name === "NoSuchEntity" || error.name === "ResourceNotFoundException" || awsError.$metadata?.httpStatusCode === 404;
467
469
  }
@@ -3616,7 +3618,9 @@ var init_cloudflare = __esm({
3616
3618
  */
3617
3619
  async getCAARecords() {
3618
3620
  const zoneName = await this.getZoneName();
3619
- if (!zoneName) return [];
3621
+ if (!zoneName) {
3622
+ return [];
3623
+ }
3620
3624
  const result = await this.request(
3621
3625
  "/dns_records?type=CAA"
3622
3626
  );
@@ -3659,7 +3663,9 @@ var init_cloudflare = __esm({
3659
3663
  */
3660
3664
  async addAmazonCAARecord() {
3661
3665
  const zoneName = await this.getZoneName();
3662
- if (!zoneName) return false;
3666
+ if (!zoneName) {
3667
+ return false;
3668
+ }
3663
3669
  const body = {
3664
3670
  name: zoneName,
3665
3671
  type: "CAA",
@@ -4198,6 +4204,7 @@ async function createDNSRecordsForProvider(credentials, data, selectedCategories
4198
4204
  "dkim",
4199
4205
  "spf",
4200
4206
  "dmarc",
4207
+ "tracking",
4201
4208
  "mailfrom_mx",
4202
4209
  "mailfrom_spf",
4203
4210
  "inbound_mx",
@@ -4223,6 +4230,9 @@ async function createDNSRecordsForProvider(credentials, data, selectedCategories
4223
4230
  if (categories.has("dmarc")) {
4224
4231
  recordsCreated += 1;
4225
4232
  }
4233
+ if (data.customTrackingDomain && categories.has("tracking")) {
4234
+ recordsCreated += 1;
4235
+ }
4226
4236
  if (data.mailFromDomain) {
4227
4237
  if (categories.has("mailfrom_mx")) {
4228
4238
  recordsCreated += 1;
@@ -5429,8 +5439,8 @@ async function promptMailFromSubdomain(domain) {
5429
5439
  clack6.cancel("Operation cancelled.");
5430
5440
  process.exit(0);
5431
5441
  }
5432
- const sub = subdomain || "mail";
5433
- return `${sub}.${domain}`;
5442
+ const sub2 = subdomain || "mail";
5443
+ return `${sub2}.${domain}`;
5434
5444
  }
5435
5445
  var DNS_CATEGORY_LABELS, DNS_STATUS_SYMBOLS;
5436
5446
  var init_prompts = __esm({
@@ -6552,7 +6562,9 @@ var init_output = __esm({
6552
6562
  * Start a spinner with a message
6553
6563
  */
6554
6564
  start(message) {
6555
- if (this.silent) return;
6565
+ if (this.silent) {
6566
+ return;
6567
+ }
6556
6568
  if (this.currentSpinner) {
6557
6569
  this.currentSpinner.stop("");
6558
6570
  this.currentSpinner = null;
@@ -6564,7 +6576,9 @@ var init_output = __esm({
6564
6576
  * Mark current step as succeeded
6565
6577
  */
6566
6578
  succeed(message) {
6567
- if (this.silent) return;
6579
+ if (this.silent) {
6580
+ return;
6581
+ }
6568
6582
  if (this.currentSpinner) {
6569
6583
  this.currentSpinner.stop(message);
6570
6584
  }
@@ -6574,7 +6588,9 @@ var init_output = __esm({
6574
6588
  * Mark current step as failed
6575
6589
  */
6576
6590
  fail(message) {
6577
- if (this.silent) return;
6591
+ if (this.silent) {
6592
+ return;
6593
+ }
6578
6594
  if (this.currentSpinner) {
6579
6595
  this.currentSpinner.stop(message);
6580
6596
  }
@@ -6584,14 +6600,18 @@ var init_output = __esm({
6584
6600
  * Show info message
6585
6601
  */
6586
6602
  info(message) {
6587
- if (this.silent) return;
6603
+ if (this.silent) {
6604
+ return;
6605
+ }
6588
6606
  clack8.log.info(message);
6589
6607
  }
6590
6608
  /**
6591
6609
  * Show step message
6592
6610
  */
6593
6611
  step(message) {
6594
- if (this.silent) return;
6612
+ if (this.silent) {
6613
+ return;
6614
+ }
6595
6615
  clack8.log.step(message);
6596
6616
  }
6597
6617
  /**
@@ -6616,7 +6636,9 @@ var init_output = __esm({
6616
6636
  * Stop the spinner
6617
6637
  */
6618
6638
  stop(message) {
6619
- if (this.silent) return;
6639
+ if (this.silent) {
6640
+ return;
6641
+ }
6620
6642
  if (this.currentSpinner) {
6621
6643
  this.currentSpinner.stop(message || "");
6622
6644
  }
@@ -6642,11 +6664,15 @@ import { promisify } from "util";
6642
6664
  import { PulumiCommand } from "@pulumi/pulumi/automation/index.js";
6643
6665
  function findSdkInstalledPulumi() {
6644
6666
  const versionsDir = join7(homedir3(), ".pulumi", "versions");
6645
- if (!existsSync6(versionsDir)) return;
6667
+ if (!existsSync6(versionsDir)) {
6668
+ return;
6669
+ }
6646
6670
  const versions = readdirSync2(versionsDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name).sort().reverse();
6647
6671
  for (const version of versions) {
6648
6672
  const binPath = join7(versionsDir, version, "bin", "pulumi");
6649
- if (existsSync6(binPath)) return dirname2(binPath);
6673
+ if (existsSync6(binPath)) {
6674
+ return dirname2(binPath);
6675
+ }
6650
6676
  }
6651
6677
  return;
6652
6678
  }
@@ -7447,7 +7473,7 @@ async function checkCertificateValidation(domain) {
7447
7473
  return describeResponse.Certificate?.Status === "ISSUED";
7448
7474
  }
7449
7475
  return false;
7450
- } catch (error) {
7476
+ } catch (_error) {
7451
7477
  return false;
7452
7478
  }
7453
7479
  }
@@ -7524,7 +7550,9 @@ async function getCertificateValidationRecords(domain) {
7524
7550
  })
7525
7551
  );
7526
7552
  const options = describeResponse.Certificate?.DomainValidationOptions ?? [];
7527
- return options.filter((opt) => opt.ResourceRecord?.Name && opt.ResourceRecord?.Value).map((opt) => ({
7553
+ return options.filter(
7554
+ (opt) => !!opt.ResourceRecord?.Name && !!opt.ResourceRecord?.Value
7555
+ ).map((opt) => ({
7528
7556
  name: opt.ResourceRecord.Name,
7529
7557
  type: opt.ResourceRecord.Type ?? "CNAME",
7530
7558
  value: opt.ResourceRecord.Value
@@ -8854,11 +8882,21 @@ async function runPreflightScan(region, domain) {
8854
8882
  const existing = checkWrapsResourcesExist(filtered);
8855
8883
  let hasConflicts = false;
8856
8884
  const resourceTypes = [];
8857
- if (existing.hasConfigSet) resourceTypes.push("config set");
8858
- if (existing.hasSNSTopics) resourceTypes.push("SNS topic");
8859
- if (existing.hasDynamoTable) resourceTypes.push("DynamoDB table");
8860
- if (existing.hasLambdaFunctions) resourceTypes.push("Lambda function");
8861
- if (existing.hasIAMRole) resourceTypes.push("IAM role");
8885
+ if (existing.hasConfigSet) {
8886
+ resourceTypes.push("config set");
8887
+ }
8888
+ if (existing.hasSNSTopics) {
8889
+ resourceTypes.push("SNS topic");
8890
+ }
8891
+ if (existing.hasDynamoTable) {
8892
+ resourceTypes.push("DynamoDB table");
8893
+ }
8894
+ if (existing.hasLambdaFunctions) {
8895
+ resourceTypes.push("Lambda function");
8896
+ }
8897
+ if (existing.hasIAMRole) {
8898
+ resourceTypes.push("IAM role");
8899
+ }
8862
8900
  if (resourceTypes.length > 0) {
8863
8901
  hasConflicts = true;
8864
8902
  clack23.log.warn(
@@ -9137,6 +9175,9 @@ Run ${pc27.cyan("wraps email init")} to set up a domain.
9137
9175
  let domain;
9138
9176
  if (trackedDomains.length === 1) {
9139
9177
  domain = trackedDomains[0].domain;
9178
+ } else if (isJsonMode()) {
9179
+ const primaryTrackedDomain = trackedDomains.find((trackedDomain) => trackedDomain.isPrimary) || trackedDomains[0];
9180
+ domain = primaryTrackedDomain.domain;
9140
9181
  } else {
9141
9182
  const selected = await clack25.select({
9142
9183
  message: "Which domain do you want to send from?",
@@ -10019,7 +10060,6 @@ import { readFileSync as readFileSync3 } from "fs";
10019
10060
  import { dirname as dirname5, join as join22 } from "path";
10020
10061
  import { fileURLToPath as fileURLToPath6 } from "url";
10021
10062
  import * as clack53 from "@clack/prompts";
10022
- import args from "args";
10023
10063
  import pc58 from "picocolors";
10024
10064
 
10025
10065
  // src/commands/auth/login.ts
@@ -11881,7 +11921,7 @@ async function createServiceIAMRole(config2) {
11881
11921
  const serviceStatement = JSON.stringify({
11882
11922
  Effect: "Allow",
11883
11923
  Principal: {
11884
- Service: config2.additionalVercelPrincipals.length === 1 ? config2.additionalVercelPrincipals[0] : config2.additionalVercelPrincipals
11924
+ Service: config2.additionalVercelPrincipals?.length === 1 ? config2.additionalVercelPrincipals?.[0] : config2.additionalVercelPrincipals
11885
11925
  },
11886
11926
  Action: "sts:AssumeRole"
11887
11927
  });
@@ -15450,11 +15490,13 @@ function formatX509Name(name) {
15450
15490
  return "";
15451
15491
  }
15452
15492
  const parts = [];
15453
- if (name.O) {
15454
- parts.push(name.O);
15493
+ const o = Array.isArray(name.O) ? name.O[0] : name.O;
15494
+ if (o) {
15495
+ parts.push(o);
15455
15496
  }
15456
- if (name.CN) {
15457
- parts.push(name.CN);
15497
+ const cn = Array.isArray(name.CN) ? name.CN[0] : name.CN;
15498
+ if (cn) {
15499
+ parts.push(cn);
15458
15500
  }
15459
15501
  return parts.join(" - ") || JSON.stringify(name);
15460
15502
  }
@@ -16057,9 +16099,15 @@ function calculateScore(checks) {
16057
16099
  };
16058
16100
  }
16059
16101
  function assessSpf(spf) {
16060
- if (!spf.exists || spf.multipleRecords || !spf.valid) return "missing";
16061
- if (spf.allMechanism === "+all" || spf.hasCircularInclude) return "missing";
16062
- if (spf.allMechanism === "?all") return "weak";
16102
+ if (!spf.exists || spf.multipleRecords || !spf.valid) {
16103
+ return "missing";
16104
+ }
16105
+ if (spf.allMechanism === "+all" || spf.hasCircularInclude) {
16106
+ return "missing";
16107
+ }
16108
+ if (spf.allMechanism === "?all") {
16109
+ return "weak";
16110
+ }
16063
16111
  return "present";
16064
16112
  }
16065
16113
  function assessDkim(checks) {
@@ -16073,17 +16121,25 @@ function assessDkim(checks) {
16073
16121
  return usesAwsSes ? "weak" : "missing";
16074
16122
  }
16075
16123
  function assessDmarc(dmarc) {
16076
- if (!(dmarc.exists && dmarc.valid)) return "missing";
16077
- if (dmarc.policy === "reject" || dmarc.policy === "quarantine") return "good";
16124
+ if (!(dmarc.exists && dmarc.valid)) {
16125
+ return "missing";
16126
+ }
16127
+ if (dmarc.policy === "reject" || dmarc.policy === "quarantine") {
16128
+ return "good";
16129
+ }
16078
16130
  return "present";
16079
16131
  }
16080
16132
  function determineGrade(checks) {
16081
- if (checks.spf.allMechanism === "+all") return "F";
16133
+ if (checks.spf.allMechanism === "+all") {
16134
+ return "F";
16135
+ }
16082
16136
  const hasSpamhausListing = [
16083
16137
  ...checks.blacklist.domainChecks.listed,
16084
16138
  ...checks.blacklist.ipChecks.listed
16085
16139
  ].some((l) => l.zone.includes("spamhaus"));
16086
- if (hasSpamhausListing) return "F";
16140
+ if (hasSpamhausListing) {
16141
+ return "F";
16142
+ }
16087
16143
  const spf = assessSpf(checks.spf);
16088
16144
  const dkim = assessDkim(checks);
16089
16145
  const dmarc = assessDmarc(checks.dmarc);
@@ -16091,9 +16147,15 @@ function determineGrade(checks) {
16091
16147
  if (spf === "present" && (dkim === "present" || dkim === "good") && dmarc === "good") {
16092
16148
  return "A";
16093
16149
  }
16094
- if (presentCount === 3) return "B";
16095
- if (presentCount === 2) return "C";
16096
- if (presentCount === 1) return "D";
16150
+ if (presentCount === 3) {
16151
+ return "B";
16152
+ }
16153
+ if (presentCount === 2) {
16154
+ return "C";
16155
+ }
16156
+ if (presentCount === 1) {
16157
+ return "D";
16158
+ }
16097
16159
  return "F";
16098
16160
  }
16099
16161
  function collectSpfIssues(spf, deductions) {
@@ -20731,6 +20793,9 @@ async function inboundInit(options) {
20731
20793
  let domain;
20732
20794
  if (trackedDomains.length === 1) {
20733
20795
  domain = trackedDomains[0].domain;
20796
+ } else if (options.yes || isJsonMode()) {
20797
+ const primaryTrackedDomain = trackedDomains.find((trackedDomain) => trackedDomain.isPrimary) || trackedDomains[0];
20798
+ domain = primaryTrackedDomain.domain;
20734
20799
  } else {
20735
20800
  const selected = await clack22.select({
20736
20801
  message: "Which domain do you want to receive email on?",
@@ -24198,15 +24263,15 @@ function normalizePlainTextMustaches(text10, canonicalVars) {
24198
24263
  }
24199
24264
  return text10.replace(
24200
24265
  /\{\{([#/]?)([A-Z][A-Z0-9_]*(?:\.[A-Z0-9_]+)*)((?:\s+[A-Z0-9_.]+)*)\s*\}\}/g,
24201
- (match, sigil, name, args2) => {
24266
+ (match, sigil, name, args) => {
24202
24267
  const lower = name.toLowerCase();
24203
24268
  const isHelper = lower === "else" || HANDLEBARS_BLOCK_HELPERS.has(lower);
24204
- const restoredArgs = args2.split(/\s+/).filter(Boolean).map(restoreIdentifier).join(" ");
24269
+ const restoredArgs = args.split(/\s+/).filter(Boolean).map(restoreIdentifier).join(" ");
24205
24270
  if (isHelper) {
24206
24271
  const suffix = restoredArgs ? ` ${restoredArgs}` : "";
24207
24272
  return `{{${sigil}${lower}${suffix}}}`;
24208
24273
  }
24209
- if (!args2 && canonicalByLower.has(lower)) {
24274
+ if (!args && canonicalByLower.has(lower)) {
24210
24275
  return `{{${sigil}${canonicalByLower.get(lower)}}}`;
24211
24276
  }
24212
24277
  return match;
@@ -24970,7 +25035,7 @@ ${pc34.bold("Current Configuration:")}
24970
25035
  upgradeOptions.push({
24971
25036
  value: "finish-tracking-domain",
24972
25037
  label: "Finish setting up custom tracking domain",
24973
- hint: `Complete HTTPS setup for ${config2.tracking.customRedirectDomain}`
25038
+ hint: `Complete HTTPS setup for ${config2.tracking?.customRedirectDomain}`
24974
25039
  });
24975
25040
  }
24976
25041
  upgradeOptions.push(
@@ -25052,7 +25117,7 @@ ${pc34.bold("Current Configuration:")}
25052
25117
  switch (upgradeAction) {
25053
25118
  case "finish-tracking-domain": {
25054
25119
  clack32.log.info(
25055
- `Checking certificate status for ${pc34.cyan(config2.tracking.customRedirectDomain)}...`
25120
+ `Checking certificate status for ${pc34.cyan(config2.tracking?.customRedirectDomain ?? "")}...`
25056
25121
  );
25057
25122
  updatedConfig = { ...config2 };
25058
25123
  newPreset = metadata.services.email?.preset;
@@ -31526,7 +31591,9 @@ function createInboundRouter(config2) {
31526
31591
  })
31527
31592
  );
31528
31593
  const body = await getResponse.Body?.transformToString();
31529
- if (!body) throw new Error("Empty body");
31594
+ if (!body) {
31595
+ throw new Error("Empty body");
31596
+ }
31530
31597
  const parsed = JSON.parse(body);
31531
31598
  return {
31532
31599
  emailId: parsed.emailId,
@@ -31570,7 +31637,9 @@ function createInboundRouter(config2) {
31570
31637
  })
31571
31638
  );
31572
31639
  const body = await getResponse.Body?.transformToString();
31573
- if (!body) throw new Error("Empty body");
31640
+ if (!body) {
31641
+ throw new Error("Empty body");
31642
+ }
31574
31643
  const parsed = JSON.parse(body);
31575
31644
  res.json(parsed);
31576
31645
  } catch (error) {
@@ -37801,6 +37870,100 @@ function showNextSteps2() {
37801
37870
  init_client();
37802
37871
  init_events();
37803
37872
 
37873
+ // src/utils/shared/arg-parser.ts
37874
+ init_esm_shims();
37875
+ import mri from "mri";
37876
+ var STRING_FLAGS = [
37877
+ "provider",
37878
+ "region",
37879
+ "domain",
37880
+ "account",
37881
+ "preset",
37882
+ "port",
37883
+ "to",
37884
+ "message",
37885
+ "phone-number",
37886
+ "code",
37887
+ "action",
37888
+ "scenario",
37889
+ "interval",
37890
+ "token",
37891
+ "dkim-selector",
37892
+ "timeout",
37893
+ "service",
37894
+ "template",
37895
+ "workflow",
37896
+ "org",
37897
+ "subdomain"
37898
+ ];
37899
+ var BOOLEAN_FLAGS = [
37900
+ "yes",
37901
+ "force",
37902
+ "preview",
37903
+ "list",
37904
+ "delete",
37905
+ "resend",
37906
+ "wait",
37907
+ "quick",
37908
+ "json",
37909
+ "verbose",
37910
+ "skip-blacklists",
37911
+ "skip-tls",
37912
+ "dry-run",
37913
+ "draft",
37914
+ "root",
37915
+ "cleanup",
37916
+ "help",
37917
+ "version"
37918
+ ];
37919
+ var NEGATED_BOOLEANS = [
37920
+ { positive: "open", camelKey: "noOpen" },
37921
+ { positive: "example", camelKey: "noExample" },
37922
+ { positive: "claude", camelKey: "noClaude" }
37923
+ ];
37924
+ var ALIAS = {
37925
+ p: "provider",
37926
+ r: "region",
37927
+ d: "domain",
37928
+ y: "yes",
37929
+ f: "force",
37930
+ w: "wait",
37931
+ q: "quick",
37932
+ j: "json",
37933
+ h: "help",
37934
+ v: "version"
37935
+ };
37936
+ var toCamel = (name) => name.replace(/-([a-z])/g, (_, ch) => ch.toUpperCase());
37937
+ function parseCliArgs(argv) {
37938
+ const userArgs = argv.slice(2);
37939
+ const parsed = mri(userArgs, {
37940
+ boolean: [...BOOLEAN_FLAGS, ...NEGATED_BOOLEANS.map((n) => n.positive)],
37941
+ string: [...STRING_FLAGS],
37942
+ alias: ALIAS
37943
+ });
37944
+ const flags2 = {};
37945
+ for (const key of STRING_FLAGS) {
37946
+ const value = parsed[key];
37947
+ if (typeof value === "string" && value.length > 0) {
37948
+ flags2[toCamel(key)] = value;
37949
+ }
37950
+ }
37951
+ for (const key of BOOLEAN_FLAGS) {
37952
+ if (parsed[key] === true) {
37953
+ flags2[toCamel(key)] = true;
37954
+ }
37955
+ }
37956
+ for (const { positive, camelKey } of NEGATED_BOOLEANS) {
37957
+ if (parsed[positive] === false) {
37958
+ flags2[camelKey] = true;
37959
+ }
37960
+ }
37961
+ return {
37962
+ flags: flags2,
37963
+ sub: parsed._
37964
+ };
37965
+ }
37966
+
37804
37967
  // src/utils/shared/completion.ts
37805
37968
  init_esm_shims();
37806
37969
  function setupTabCompletion() {
@@ -38071,220 +38234,11 @@ if (process.argv.includes("--help") || process.argv.includes("-h")) {
38071
38234
  showHelp();
38072
38235
  process.exit(0);
38073
38236
  }
38074
- args.options([
38075
- {
38076
- name: ["p", "provider"],
38077
- description: "Hosting provider (vercel, aws, railway, other)",
38078
- defaultValue: void 0
38079
- },
38080
- {
38081
- name: ["r", "region"],
38082
- description: "AWS region",
38083
- defaultValue: void 0
38084
- },
38085
- {
38086
- name: ["d", "domain"],
38087
- description: "Domain name",
38088
- defaultValue: void 0
38089
- },
38090
- {
38091
- name: "account",
38092
- description: "AWS account ID or alias",
38093
- defaultValue: void 0
38094
- },
38095
- {
38096
- name: "preset",
38097
- description: "Configuration preset (starter, production, enterprise, custom)",
38098
- defaultValue: void 0
38099
- },
38100
- {
38101
- name: ["y", "yes"],
38102
- description: "Skip confirmation prompts (non-destructive operations)",
38103
- defaultValue: false
38104
- },
38105
- {
38106
- name: ["f", "force"],
38107
- description: "Force operation without confirmation (destructive operations)",
38108
- defaultValue: false
38109
- },
38110
- {
38111
- name: "port",
38112
- description: "Port for dashboard server",
38113
- defaultValue: void 0
38114
- },
38115
- {
38116
- name: "noOpen",
38117
- description: "Don't open browser automatically",
38118
- defaultValue: false
38119
- },
38120
- {
38121
- name: "preview",
38122
- description: "Preview changes without deploying",
38123
- defaultValue: false
38124
- },
38125
- // SMS-specific options
38126
- {
38127
- name: "to",
38128
- description: "Destination phone number (E.164 format)",
38129
- defaultValue: void 0
38130
- },
38131
- {
38132
- name: "message",
38133
- description: "SMS message content",
38134
- defaultValue: void 0
38135
- },
38136
- // SMS verify-number options
38137
- {
38138
- name: "phoneNumber",
38139
- description: "Phone number to verify (E.164 format)",
38140
- defaultValue: void 0
38141
- },
38142
- {
38143
- name: "code",
38144
- description: "Verification code received via SMS",
38145
- defaultValue: void 0
38146
- },
38147
- {
38148
- name: "list",
38149
- description: "List all verified destination numbers",
38150
- defaultValue: false
38151
- },
38152
- {
38153
- name: "delete",
38154
- description: "Delete a verified destination number",
38155
- defaultValue: false
38156
- },
38157
- {
38158
- name: "resend",
38159
- description: "Resend verification code",
38160
- defaultValue: false
38161
- },
38162
- // Email upgrade options
38163
- {
38164
- name: "action",
38165
- description: "Upgrade action (preset, smtp-credentials, events, archiving, etc.)",
38166
- defaultValue: void 0
38167
- },
38168
- // Email test options
38169
- {
38170
- name: "scenario",
38171
- description: "Test scenario (success, bounce, complaint, ooto, suppression_list)",
38172
- defaultValue: void 0
38173
- },
38174
- // Email verify options
38175
- {
38176
- name: ["w", "wait"],
38177
- description: "Poll until DNS records are verified",
38178
- defaultValue: false
38179
- },
38180
- {
38181
- name: "interval",
38182
- description: "Polling interval in seconds (default: 30)",
38183
- defaultValue: void 0
38184
- },
38185
- // Email check options
38186
- {
38187
- name: ["q", "quick"],
38188
- description: "Quick mode: fewer DKIM selectors, top blacklists only",
38189
- defaultValue: false
38190
- },
38191
- {
38192
- name: ["j", "json"],
38193
- description: "Output results as JSON",
38194
- defaultValue: false
38195
- },
38196
- {
38197
- name: "token",
38198
- description: "API key or token for authentication",
38199
- defaultValue: void 0
38200
- },
38201
- {
38202
- name: "verbose",
38203
- description: "Show all checks including passing",
38204
- defaultValue: false
38205
- },
38206
- {
38207
- name: "dkimSelector",
38208
- description: "Specific DKIM selector to check",
38209
- defaultValue: void 0
38210
- },
38211
- {
38212
- name: "skipBlacklists",
38213
- description: "Skip blacklist checks",
38214
- defaultValue: false
38215
- },
38216
- {
38217
- name: "skipTls",
38218
- description: "Skip MX TLS checks",
38219
- defaultValue: false
38220
- },
38221
- {
38222
- name: "timeout",
38223
- description: "DNS timeout in milliseconds",
38224
- defaultValue: void 0
38225
- },
38226
- // Permissions command options
38227
- {
38228
- name: "service",
38229
- description: "Service type for permissions (email, sms, cdn)",
38230
- defaultValue: void 0
38231
- },
38232
- // Template-specific options
38233
- {
38234
- name: "template",
38235
- description: "Specific template to push (by name)",
38236
- defaultValue: void 0
38237
- },
38238
- // Workflow-specific options
38239
- {
38240
- name: "workflow",
38241
- description: "Specific workflow to push (by name)",
38242
- defaultValue: void 0
38243
- },
38244
- {
38245
- name: "dryRun",
38246
- description: "Preview changes without pushing",
38247
- defaultValue: false
38248
- },
38249
- {
38250
- name: "draft",
38251
- description: "Push workflow as draft without enabling it",
38252
- defaultValue: false
38253
- },
38254
- {
38255
- name: "noExample",
38256
- description: "Skip creating example template",
38257
- defaultValue: false
38258
- },
38259
- {
38260
- name: "noClaude",
38261
- description: "Skip scaffolding .claude/ context files",
38262
- defaultValue: false
38263
- },
38264
- {
38265
- name: "org",
38266
- description: "Organization slug",
38267
- defaultValue: void 0
38268
- },
38269
- {
38270
- name: "subdomain",
38271
- description: "Subdomain for inbound email (e.g., inbound, support)",
38272
- defaultValue: void 0
38273
- },
38274
- {
38275
- name: "root",
38276
- description: "Use root domain for inbound email (no subdomain)",
38277
- defaultValue: false
38278
- },
38279
- {
38280
- name: "cleanup",
38281
- description: "Delete orphaned resources (used with email doctor)",
38282
- defaultValue: false
38283
- }
38284
- ]);
38285
- var flags = args.parse(process.argv);
38286
- var [primaryCommand, subCommand] = args.sub;
38287
- setJsonMode(flags.json);
38237
+ var parsedCli = parseCliArgs(process.argv);
38238
+ var flags = parsedCli.flags;
38239
+ var { sub } = parsedCli;
38240
+ var [primaryCommand, subCommand] = sub;
38241
+ setJsonMode(flags.json === true);
38288
38242
  if (!primaryCommand) {
38289
38243
  async function interactiveMenu() {
38290
38244
  const startTime = Date.now();
@@ -38488,7 +38442,7 @@ async function run() {
38488
38442
  break;
38489
38443
  case "check":
38490
38444
  await check({
38491
- domain: args.sub[2] || flags.domain,
38445
+ domain: sub[2] || flags.domain,
38492
38446
  quick: flags.quick,
38493
38447
  json: flags.json,
38494
38448
  verbose: flags.verbose,
@@ -38559,7 +38513,7 @@ Usage: ${pc58.cyan("wraps email verify --domain yourapp.com")}
38559
38513
  break;
38560
38514
  }
38561
38515
  case "inbound": {
38562
- const inboundSubCommand = args.sub[2];
38516
+ const inboundSubCommand = sub[2];
38563
38517
  switch (inboundSubCommand) {
38564
38518
  case "init":
38565
38519
  await inboundInit({
@@ -38631,7 +38585,7 @@ Available commands: ${pc58.cyan("init")}, ${pc58.cyan("destroy")}, ${pc58.cyan("
38631
38585
  break;
38632
38586
  }
38633
38587
  case "domains": {
38634
- const domainsSubCommand = args.sub[2];
38588
+ const domainsSubCommand = sub[2];
38635
38589
  switch (domainsSubCommand) {
38636
38590
  case "add": {
38637
38591
  await addDomain({
@@ -38702,7 +38656,7 @@ Available commands: ${pc58.cyan("add")}, ${pc58.cyan("list")}, ${pc58.cyan("veri
38702
38656
  break;
38703
38657
  }
38704
38658
  case "templates": {
38705
- const templatesSubCommand = args.sub[2];
38659
+ const templatesSubCommand = sub[2];
38706
38660
  switch (templatesSubCommand) {
38707
38661
  case "init":
38708
38662
  await templatesInit({
@@ -38716,7 +38670,9 @@ Available commands: ${pc58.cyan("add")}, ${pc58.cyan("list")}, ${pc58.cyan("veri
38716
38670
  break;
38717
38671
  case "push":
38718
38672
  await templatesPush({
38719
- template: flags.template,
38673
+ // Positional slug (e.g. `wraps email templates push my-slug`)
38674
+ // falls back to --template for a nicer UX.
38675
+ template: sub[3] || flags.template,
38720
38676
  dryRun: flags.dryRun,
38721
38677
  force: flags.force,
38722
38678
  yes: flags.yes,
@@ -38747,7 +38703,7 @@ Available commands: ${pc58.cyan("init")}, ${pc58.cyan("push")}, ${pc58.cyan("pre
38747
38703
  break;
38748
38704
  }
38749
38705
  case "workflows": {
38750
- const workflowsSubCommand = args.sub[2];
38706
+ const workflowsSubCommand = sub[2];
38751
38707
  switch (workflowsSubCommand) {
38752
38708
  case "init":
38753
38709
  await workflowsInit({
@@ -39096,7 +39052,8 @@ Available commands: ${pc58.cyan("setup")}, ${pc58.cyan("doctor")}
39096
39052
  // Convenience alias: wraps push → wraps email templates push
39097
39053
  case "push":
39098
39054
  await templatesPush({
39099
- template: flags.template,
39055
+ // `wraps push my-slug` is the same shortcut as above.
39056
+ template: sub[1] || flags.template,
39100
39057
  dryRun: flags.dryRun,
39101
39058
  force: flags.force,
39102
39059
  yes: flags.yes,