@wraps.dev/cli 2.19.1 → 2.19.4

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
@@ -820,6 +820,18 @@ To remove: wraps destroy --stack ${stackName}`,
820
820
  "Use a valid AWS region like: us-east-1, eu-west-1, ap-southeast-1",
821
821
  "https://docs.aws.amazon.com/general/latest/gr/rande.html"
822
822
  ),
823
+ // The accountId parameter is kept in the signature so callers don't
824
+ // have to change, but it is deliberately not included in the output —
825
+ // the user ran the command so they know their own account, and keeping
826
+ // IDs out of error text matches the `sanitizeErrorMessage` posture used
827
+ // elsewhere in the error system.
828
+ regionRequired: (_accountId, savedRegions) => new WrapsError(
829
+ "Region is required and could not be determined",
830
+ "REGION_REQUIRED",
831
+ savedRegions.length > 0 ? `Pass --region or set AWS_REGION.
832
+ Saved regions: ${savedRegions.join(", ")}` : "Pass --region or set AWS_REGION.\nNo saved Wraps deployments found.",
833
+ "https://wraps.dev/docs/cli-reference"
834
+ ),
823
835
  pulumiError: (message) => new WrapsError(
824
836
  `Infrastructure deployment failed: ${message}`,
825
837
  "PULUMI_ERROR",
@@ -1195,8 +1207,8 @@ async function validateAWSCredentialsWithDetails() {
1195
1207
  }
1196
1208
  }
1197
1209
  async function resolveAWSCredentialsToEnv() {
1198
- delete process.env.AWS_PROFILE;
1199
1210
  if (process.env.AWS_ACCESS_KEY_ID && process.env.AWS_SECRET_ACCESS_KEY) {
1211
+ delete process.env.AWS_PROFILE;
1200
1212
  return;
1201
1213
  }
1202
1214
  const sts = new STSClient2({});
@@ -1223,6 +1235,7 @@ async function resolveAWSCredentialsToEnv() {
1223
1235
  if (creds.sessionToken) {
1224
1236
  process.env.AWS_SESSION_TOKEN = creds.sessionToken;
1225
1237
  }
1238
+ delete process.env.AWS_PROFILE;
1226
1239
  }
1227
1240
  async function checkRegion(region) {
1228
1241
  return SES_REGIONS.includes(region);
@@ -1702,8 +1715,8 @@ async function ensurePulumiWorkDir(options) {
1702
1715
  );
1703
1716
  return;
1704
1717
  } catch (error) {
1705
- const clack55 = await import("@clack/prompts");
1706
- clack55.log.warn(
1718
+ const clack56 = await import("@clack/prompts");
1719
+ clack56.log.warn(
1707
1720
  `S3 state backend unavailable (${error instanceof Error ? error.message : error}). Using local state.`
1708
1721
  );
1709
1722
  }
@@ -4423,6 +4436,7 @@ __export(prompts_exports, {
4423
4436
  confirmConnect: () => confirmConnect,
4424
4437
  confirmDeploy: () => confirmDeploy,
4425
4438
  getAvailableFeatures: () => getAvailableFeatures,
4439
+ isInteractive: () => isInteractive,
4426
4440
  promptConfigPreset: () => promptConfigPreset,
4427
4441
  promptConflictResolution: () => promptConflictResolution,
4428
4442
  promptContinueManualDNS: () => promptContinueManualDNS,
@@ -4448,6 +4462,9 @@ __export(prompts_exports, {
4448
4462
  });
4449
4463
  import * as clack6 from "@clack/prompts";
4450
4464
  import pc8 from "picocolors";
4465
+ function isInteractive() {
4466
+ return process.stdin.isTTY === true && process.stdout.isTTY === true && !process.env.CI;
4467
+ }
4451
4468
  async function promptProvider() {
4452
4469
  const provider = await clack6.select({
4453
4470
  message: "Where is your app hosted?",
@@ -6783,23 +6800,23 @@ async function withLockRetry(fn, options) {
6783
6800
  if (parsed.code !== "STACK_LOCKED") {
6784
6801
  throw error;
6785
6802
  }
6786
- const clack55 = await import("@clack/prompts");
6803
+ const clack56 = await import("@clack/prompts");
6787
6804
  const pc60 = (await import("picocolors")).default;
6788
6805
  if (options.autoConfirm) {
6789
- clack55.log.warn(
6806
+ clack56.log.warn(
6790
6807
  "Stack is locked from a previous interrupted run. Auto-clearing..."
6791
6808
  );
6792
6809
  } else {
6793
- const shouldClear = await clack55.confirm({
6810
+ const shouldClear = await clack56.confirm({
6794
6811
  message: `Stack is locked from a previous interrupted run. ${pc60.yellow("Clear the stale lock and retry?")}`,
6795
6812
  initialValue: true
6796
6813
  });
6797
- if (clack55.isCancel(shouldClear) || !shouldClear) {
6814
+ if (clack56.isCancel(shouldClear) || !shouldClear) {
6798
6815
  throw errors.stackLocked();
6799
6816
  }
6800
6817
  }
6801
6818
  const cleared = await clearStackLocks(options.accountId, options.region);
6802
- clack55.log.info(
6819
+ clack56.log.info(
6803
6820
  `Cleared ${cleared} lock file${cleared === 1 ? "" : "s"}. Retrying...`
6804
6821
  );
6805
6822
  return fn();
@@ -6815,26 +6832,11 @@ var init_pulumi = __esm({
6815
6832
  }
6816
6833
  });
6817
6834
 
6818
- // src/constants.ts
6819
- function getDefaultRegion() {
6820
- return process.env.AWS_REGION || DEFAULT_AWS_REGION;
6821
- }
6822
- var DEFAULT_AWS_REGION;
6823
- var init_constants = __esm({
6824
- "src/constants.ts"() {
6825
- "use strict";
6826
- init_esm_shims();
6827
- DEFAULT_AWS_REGION = "us-east-1";
6828
- }
6829
- });
6830
-
6831
6835
  // src/infrastructure/shared/resource-checks.ts
6832
6836
  async function roleExists(roleName) {
6833
6837
  try {
6834
6838
  const { IAMClient: IAMClient5, GetRoleCommand: GetRoleCommand3 } = await import("@aws-sdk/client-iam");
6835
- const iam10 = new IAMClient5({
6836
- region: getDefaultRegion()
6837
- });
6839
+ const iam10 = new IAMClient5({ region: "us-east-1" });
6838
6840
  await iam10.send(new GetRoleCommand3({ RoleName: roleName }));
6839
6841
  return true;
6840
6842
  } catch (error) {
@@ -6845,12 +6847,10 @@ async function roleExists(roleName) {
6845
6847
  return false;
6846
6848
  }
6847
6849
  }
6848
- async function tableExists(tableName) {
6850
+ async function tableExists(tableName, region) {
6849
6851
  try {
6850
6852
  const { DynamoDBClient: DynamoDBClient7, DescribeTableCommand: DescribeTableCommand2 } = await import("@aws-sdk/client-dynamodb");
6851
- const dynamodb3 = new DynamoDBClient7({
6852
- region: getDefaultRegion()
6853
- });
6853
+ const dynamodb3 = new DynamoDBClient7({ region });
6854
6854
  await dynamodb3.send(new DescribeTableCommand2({ TableName: tableName }));
6855
6855
  return true;
6856
6856
  } catch (error) {
@@ -6861,12 +6861,10 @@ async function tableExists(tableName) {
6861
6861
  return false;
6862
6862
  }
6863
6863
  }
6864
- async function sqsQueueExists(queueName) {
6864
+ async function sqsQueueExists(queueName, region) {
6865
6865
  try {
6866
6866
  const { SQSClient, GetQueueUrlCommand } = await import("@aws-sdk/client-sqs");
6867
- const sqs5 = new SQSClient({
6868
- region: getDefaultRegion()
6869
- });
6867
+ const sqs5 = new SQSClient({ region });
6870
6868
  const response = await sqs5.send(
6871
6869
  new GetQueueUrlCommand({ QueueName: queueName })
6872
6870
  );
@@ -6875,12 +6873,10 @@ async function sqsQueueExists(queueName) {
6875
6873
  return null;
6876
6874
  }
6877
6875
  }
6878
- async function snsTopicExists(topicName) {
6876
+ async function snsTopicExists(topicName, region) {
6879
6877
  try {
6880
6878
  const { SNSClient: SNSClient3, ListTopicsCommand: ListTopicsCommand2 } = await import("@aws-sdk/client-sns");
6881
- const sns3 = new SNSClient3({
6882
- region: getDefaultRegion()
6883
- });
6879
+ const sns3 = new SNSClient3({ region });
6884
6880
  let nextToken;
6885
6881
  do {
6886
6882
  const response = await sns3.send(
@@ -6899,12 +6895,10 @@ async function snsTopicExists(topicName) {
6899
6895
  return null;
6900
6896
  }
6901
6897
  }
6902
- async function lambdaFunctionExists(functionName) {
6898
+ async function lambdaFunctionExists(functionName, region) {
6903
6899
  try {
6904
6900
  const { LambdaClient: LambdaClient3, GetFunctionCommand } = await import("@aws-sdk/client-lambda");
6905
- const lambda4 = new LambdaClient3({
6906
- region: getDefaultRegion()
6907
- });
6901
+ const lambda4 = new LambdaClient3({ region });
6908
6902
  await lambda4.send(new GetFunctionCommand({ FunctionName: functionName }));
6909
6903
  return true;
6910
6904
  } catch (error) {
@@ -6919,7 +6913,6 @@ var init_resource_checks = __esm({
6919
6913
  "src/infrastructure/shared/resource-checks.ts"() {
6920
6914
  "use strict";
6921
6915
  init_esm_shims();
6922
- init_constants();
6923
6916
  }
6924
6917
  });
6925
6918
 
@@ -7350,12 +7343,10 @@ function getPackageRoot() {
7350
7343
  }
7351
7344
  throw new Error("Could not find package.json");
7352
7345
  }
7353
- async function findEventSourceMapping(functionName, queueArn) {
7346
+ async function findEventSourceMapping(functionName, queueArn, region) {
7354
7347
  try {
7355
7348
  const { LambdaClient: LambdaClient3, ListEventSourceMappingsCommand } = await import("@aws-sdk/client-lambda");
7356
- const lambda4 = new LambdaClient3({
7357
- region: getDefaultRegion()
7358
- });
7349
+ const lambda4 = new LambdaClient3({ region });
7359
7350
  const response = await lambda4.send(
7360
7351
  new ListEventSourceMappingsCommand({
7361
7352
  FunctionName: functionName,
@@ -7464,7 +7455,7 @@ async function deployLambdaFunctions(config2) {
7464
7455
  )
7465
7456
  });
7466
7457
  const functionName = "wraps-email-event-processor";
7467
- const exists = await lambdaFunctionExists(functionName);
7458
+ const exists = await lambdaFunctionExists(functionName, config2.region);
7468
7459
  const lambdaEnvironment = {
7469
7460
  variables: {
7470
7461
  TABLE_NAME: config2.tableName,
@@ -7512,7 +7503,8 @@ async function deployLambdaFunctions(config2) {
7512
7503
  const queueArnValue = `arn:aws:sqs:${config2.region}:${config2.accountId}:wraps-email-events`;
7513
7504
  const existingMappingUuid = await findEventSourceMapping(
7514
7505
  functionName,
7515
- queueArnValue
7506
+ queueArnValue,
7507
+ config2.region
7516
7508
  );
7517
7509
  const mappingConfig = {
7518
7510
  eventSourceArn: config2.queueArn,
@@ -7545,7 +7537,6 @@ var init_lambda = __esm({
7545
7537
  "src/infrastructure/resources/lambda.ts"() {
7546
7538
  "use strict";
7547
7539
  init_esm_shims();
7548
- init_constants();
7549
7540
  init_resource_checks();
7550
7541
  nodeBuiltins = builtinModules.flatMap((m) => [m, `node:${m}`]);
7551
7542
  }
@@ -7893,7 +7884,7 @@ function retentionToAWSPeriod2(retention) {
7893
7884
  }
7894
7885
  }
7895
7886
  async function createMailManagerArchive(config2) {
7896
- const region = config2.region || getDefaultRegion();
7887
+ const region = config2.region;
7897
7888
  const archiveName = `wraps-${config2.name}-archive`;
7898
7889
  const mailManagerClient = new MailManagerClient({ region });
7899
7890
  const sesClient = new SESv2Client3({ region });
@@ -7977,11 +7968,23 @@ async function createMailManagerArchive(config2) {
7977
7968
  resolve(name);
7978
7969
  });
7979
7970
  });
7971
+ if (!configSetName) {
7972
+ throw new Error(
7973
+ "Failed to resolve SES configuration set name from Pulumi output"
7974
+ );
7975
+ }
7980
7976
  const putArchivingOptionsCommand = new PutConfigurationSetArchivingOptionsCommand({
7981
7977
  ConfigurationSetName: configSetName,
7982
7978
  ArchiveArn: archiveArn
7983
7979
  });
7984
- await sesClient.send(putArchivingOptionsCommand);
7980
+ try {
7981
+ await sesClient.send(putArchivingOptionsCommand);
7982
+ } catch (error) {
7983
+ const detail = error instanceof Error ? error.message : String(error);
7984
+ throw new Error(
7985
+ `Failed to link Mail Manager archive to SES config set '${configSetName}' in ${region}: ${detail}`
7986
+ );
7987
+ }
7985
7988
  if (!(archiveId && archiveArn)) {
7986
7989
  throw new Error("Failed to get archive ID or ARN");
7987
7990
  }
@@ -7995,7 +7998,6 @@ var init_mail_manager = __esm({
7995
7998
  "src/infrastructure/resources/mail-manager.ts"() {
7996
7999
  "use strict";
7997
8000
  init_esm_shims();
7998
- init_constants();
7999
8001
  }
8000
8002
  });
8001
8003
 
@@ -9675,6 +9677,60 @@ var init_test = __esm({
9675
9677
  }
9676
9678
  });
9677
9679
 
9680
+ // src/utils/shared/region-resolver.ts
9681
+ var region_resolver_exports = {};
9682
+ __export(region_resolver_exports, {
9683
+ resolveRegionForCommand: () => resolveRegionForCommand
9684
+ });
9685
+ import * as clack28 from "@clack/prompts";
9686
+ async function resolveRegionForCommand(opts) {
9687
+ const { accountId, optionRegion, service, label = "deployment" } = opts;
9688
+ if (optionRegion) {
9689
+ return optionRegion;
9690
+ }
9691
+ const envRegion = process.env.AWS_REGION || process.env.AWS_DEFAULT_REGION;
9692
+ if (envRegion) {
9693
+ return envRegion;
9694
+ }
9695
+ const connections = (service ? await findConnectionsWithService(accountId, service) : await findConnectionsForAccount(accountId)) ?? [];
9696
+ if (connections.length === 1) {
9697
+ return connections[0].region;
9698
+ }
9699
+ const savedRegions = connections.map((c) => c.region);
9700
+ if (connections.length === 0) {
9701
+ return getAWSRegion();
9702
+ }
9703
+ if (!isInteractive() || isJsonMode()) {
9704
+ throw errors.regionRequired(accountId, savedRegions);
9705
+ }
9706
+ const selected = await clack28.select({
9707
+ message: `Multiple ${label}s found. Which region?`,
9708
+ options: connections.map((conn) => ({
9709
+ value: conn.region,
9710
+ label: conn.region
9711
+ }))
9712
+ });
9713
+ if (clack28.isCancel(selected)) {
9714
+ throw new WrapsError(
9715
+ "Operation cancelled",
9716
+ "OPERATION_CANCELLED",
9717
+ `Pass --region to skip the prompt. Saved regions: ${savedRegions.join(", ")}`
9718
+ );
9719
+ }
9720
+ return selected;
9721
+ }
9722
+ var init_region_resolver = __esm({
9723
+ "src/utils/shared/region-resolver.ts"() {
9724
+ "use strict";
9725
+ init_esm_shims();
9726
+ init_aws();
9727
+ init_errors();
9728
+ init_json_output();
9729
+ init_metadata();
9730
+ init_prompts();
9731
+ }
9732
+ });
9733
+
9678
9734
  // src/utils/dns/caa.ts
9679
9735
  var caa_exports = {};
9680
9736
  __export(caa_exports, {
@@ -10080,7 +10136,7 @@ import { homedir as homedir4, tmpdir as tmpdir2 } from "os";
10080
10136
  import { join as join21 } from "path";
10081
10137
  import { Readable } from "stream";
10082
10138
  import { pipeline } from "stream/promises";
10083
- import { cancel as cancel31, confirm as confirm26, intro as intro51, isCancel as isCancel35, log as log50 } from "@clack/prompts";
10139
+ import { cancel as cancel31, confirm as confirm26, intro as intro51, isCancel as isCancel36, log as log50 } from "@clack/prompts";
10084
10140
  import pc58 from "picocolors";
10085
10141
  function isStandaloneInstall() {
10086
10142
  return process.execPath.includes(".wraps/runtime");
@@ -10142,7 +10198,7 @@ async function update(currentVersion) {
10142
10198
  const shouldUpdate = await confirm26({
10143
10199
  message: `Update to v${latestVersion}?`
10144
10200
  });
10145
- if (isCancel35(shouldUpdate) || !shouldUpdate) {
10201
+ if (isCancel36(shouldUpdate) || !shouldUpdate) {
10146
10202
  cancel31("Update cancelled.");
10147
10203
  return;
10148
10204
  }
@@ -10233,7 +10289,7 @@ init_esm_shims();
10233
10289
  import { readFileSync as readFileSync3 } from "fs";
10234
10290
  import { dirname as dirname5, join as join22 } from "path";
10235
10291
  import { fileURLToPath as fileURLToPath6 } from "url";
10236
- import * as clack54 from "@clack/prompts";
10292
+ import * as clack55 from "@clack/prompts";
10237
10293
  import pc59 from "picocolors";
10238
10294
 
10239
10295
  // src/commands/auth/login.ts
@@ -10648,26 +10704,30 @@ async function runDiagnostics(state) {
10648
10704
  }
10649
10705
  }
10650
10706
  if (state.credentialsConfigured) {
10707
+ const regionUsed = state.region || "us-east-1";
10708
+ const regionNote = state.region ? `Region: ${regionUsed}` : `No AWS_REGION set \u2014 defaulted to ${regionUsed}. Set AWS_REGION if your deployment lives elsewhere.`;
10651
10709
  try {
10652
- const region = state.region || "us-east-1";
10653
- const sandbox = await isSESSandbox(region);
10710
+ const sandbox = await isSESSandbox(regionUsed);
10654
10711
  if (sandbox) {
10655
10712
  results.push({
10656
10713
  status: "warn",
10657
10714
  message: "SES is in sandbox mode",
10658
- details: "You can only send to verified emails. Request production access in AWS console."
10715
+ details: `You can only send to verified emails. Request production access in AWS console.
10716
+ ${regionNote}`
10659
10717
  });
10660
10718
  } else {
10661
10719
  results.push({
10662
10720
  status: "pass",
10663
- message: "SES has production access"
10721
+ message: "SES has production access",
10722
+ details: regionNote
10664
10723
  });
10665
10724
  }
10666
10725
  } catch {
10667
10726
  results.push({
10668
10727
  status: "info",
10669
10728
  message: "Could not check SES status",
10670
- details: "SES may not be enabled in this region"
10729
+ details: `SES may not be enabled in this region.
10730
+ ${regionNote}`
10671
10731
  });
10672
10732
  }
10673
10733
  }
@@ -12202,8 +12262,16 @@ async function createServiceIAMRole(config2) {
12202
12262
 
12203
12263
  // src/infrastructure/vercel-oidc.ts
12204
12264
  init_esm_shims();
12205
- init_constants();
12206
12265
  import * as aws3 from "@pulumi/aws";
12266
+
12267
+ // src/constants.ts
12268
+ init_esm_shims();
12269
+ var DEFAULT_AWS_REGION = "us-east-1";
12270
+ function getDefaultRegion() {
12271
+ return process.env.AWS_REGION || DEFAULT_AWS_REGION;
12272
+ }
12273
+
12274
+ // src/infrastructure/vercel-oidc.ts
12207
12275
  async function getExistingOIDCProviderArn(url) {
12208
12276
  try {
12209
12277
  const { IAMClient: IAMClient5, ListOpenIDConnectProvidersCommand } = await import("@aws-sdk/client-iam");
@@ -17509,9 +17577,9 @@ async function createAlertingResources(config2) {
17509
17577
  init_esm_shims();
17510
17578
  init_resource_checks();
17511
17579
  import * as aws5 from "@pulumi/aws";
17512
- async function createDynamoDBTables(_config) {
17580
+ async function createDynamoDBTables(config2) {
17513
17581
  const tableName = "wraps-email-history";
17514
- const exists = await tableExists(tableName);
17582
+ const exists = await tableExists(tableName, config2.region);
17515
17583
  const emailHistory = exists ? new aws5.dynamodb.Table(
17516
17584
  tableName,
17517
17585
  {
@@ -18049,7 +18117,6 @@ async function createSESResources(config2) {
18049
18117
 
18050
18118
  // src/infrastructure/resources/smtp-credentials.ts
18051
18119
  init_esm_shims();
18052
- init_constants();
18053
18120
  import { createHmac as createHmac3 } from "crypto";
18054
18121
  import * as aws10 from "@pulumi/aws";
18055
18122
  function convertToSMTPPassword2(secretAccessKey, region) {
@@ -18139,11 +18206,11 @@ import * as aws11 from "@pulumi/aws";
18139
18206
  var SQS_TIMEOUTS = {
18140
18207
  customTimeouts: { create: "2m", update: "2m", delete: "2m" }
18141
18208
  };
18142
- async function createSQSResources() {
18209
+ async function createSQSResources(config2) {
18143
18210
  const dlqName = "wraps-email-events-dlq";
18144
18211
  const queueName = "wraps-email-events";
18145
- const dlqUrl = await sqsQueueExists(dlqName);
18146
- const queueUrl = await sqsQueueExists(queueName);
18212
+ const dlqUrl = await sqsQueueExists(dlqName, config2.region);
18213
+ const queueUrl = await sqsQueueExists(queueName, config2.region);
18147
18214
  const dlqConfig = {
18148
18215
  name: dlqName,
18149
18216
  messageRetentionSeconds: 1209600,
@@ -18282,12 +18349,13 @@ async function deployEmailStack(config2) {
18282
18349
  let dynamoTables;
18283
18350
  if (emailConfig.eventTracking?.dynamoDBHistory) {
18284
18351
  dynamoTables = await createDynamoDBTables({
18352
+ region: config2.region,
18285
18353
  retention: emailConfig.eventTracking.archiveRetention
18286
18354
  });
18287
18355
  }
18288
18356
  let sqsResources;
18289
18357
  if (emailConfig.eventTracking?.enabled) {
18290
- sqsResources = await createSQSResources();
18358
+ sqsResources = await createSQSResources({ region: config2.region });
18291
18359
  }
18292
18360
  if (emailConfig.eventTracking?.enabled && sesResources && sqsResources) {
18293
18361
  await createEventBridgeResources({
@@ -23723,7 +23791,8 @@ init_json_output();
23723
23791
  init_metadata();
23724
23792
  init_output();
23725
23793
  init_pulumi();
23726
- import * as clack28 from "@clack/prompts";
23794
+ init_region_resolver();
23795
+ import * as clack29 from "@clack/prompts";
23727
23796
  import * as pulumi21 from "@pulumi/pulumi";
23728
23797
  import pc30 from "picocolors";
23729
23798
  async function restore(options) {
@@ -23736,15 +23805,15 @@ async function restore(options) {
23736
23805
  );
23737
23806
  }
23738
23807
  if (!isJsonMode()) {
23739
- clack28.intro(
23808
+ clack29.intro(
23740
23809
  pc30.bold(
23741
23810
  options.preview ? "Wraps Restore Preview" : "Wraps Restore - Remove Wraps Infrastructure"
23742
23811
  )
23743
23812
  );
23744
- clack28.log.info(
23813
+ clack29.log.info(
23745
23814
  `${pc30.yellow("Note:")} This will remove all Wraps-managed infrastructure.`
23746
23815
  );
23747
- clack28.log.info(
23816
+ clack29.log.info(
23748
23817
  "Your original AWS resources remain untouched (Wraps never modifies them).\n"
23749
23818
  );
23750
23819
  }
@@ -23755,17 +23824,18 @@ async function restore(options) {
23755
23824
  async () => validateAWSCredentials()
23756
23825
  );
23757
23826
  progress.info(`Connected to AWS account: ${pc30.cyan(identity.accountId)}`);
23758
- let region = options.region;
23759
- if (!region) {
23760
- const defaultRegion = await getAWSRegion();
23761
- region = defaultRegion;
23762
- }
23827
+ const region = await resolveRegionForCommand({
23828
+ accountId: identity.accountId,
23829
+ optionRegion: options.region,
23830
+ service: "email",
23831
+ label: "email deployment"
23832
+ });
23763
23833
  const metadata = await loadConnectionMetadata(identity.accountId, region);
23764
23834
  if (!metadata) {
23765
- clack28.log.error(
23835
+ clack29.log.error(
23766
23836
  `No Wraps connection found for account ${pc30.cyan(identity.accountId)} in region ${pc30.cyan(region)}`
23767
23837
  );
23768
- clack28.log.info(
23838
+ clack29.log.info(
23769
23839
  `Use ${pc30.cyan("wraps email init")} or ${pc30.cyan("wraps email connect")} to create a connection first.`
23770
23840
  );
23771
23841
  process.exit(1);
@@ -23790,12 +23860,12 @@ ${pc30.bold("The following Wraps resources will be removed:")}
23790
23860
  console.log(` ${pc30.cyan("\u2713")} IAM Role (wraps-email-role)`);
23791
23861
  console.log("");
23792
23862
  if (!(options.force || options.preview)) {
23793
- const confirmed = await clack28.confirm({
23863
+ const confirmed = await clack29.confirm({
23794
23864
  message: "Proceed with removal? This cannot be undone.",
23795
23865
  initialValue: false
23796
23866
  });
23797
- if (clack28.isCancel(confirmed) || !confirmed) {
23798
- clack28.cancel("Removal cancelled.");
23867
+ if (clack29.isCancel(confirmed) || !confirmed) {
23868
+ clack29.cancel("Removal cancelled.");
23799
23869
  process.exit(0);
23800
23870
  }
23801
23871
  }
@@ -23835,7 +23905,7 @@ ${pc30.bold("The following Wraps resources will be removed:")}
23835
23905
  costEstimate: "Monthly cost after removal: $0.00",
23836
23906
  commandName: "wraps email restore"
23837
23907
  });
23838
- clack28.outro(
23908
+ clack29.outro(
23839
23909
  pc30.green(
23840
23910
  "Preview complete. Run without --preview to remove infrastructure."
23841
23911
  )
@@ -23928,7 +23998,7 @@ init_json_output();
23928
23998
  init_metadata();
23929
23999
  init_output();
23930
24000
  init_pulumi();
23931
- import * as clack29 from "@clack/prompts";
24001
+ import * as clack30 from "@clack/prompts";
23932
24002
  import * as pulumi22 from "@pulumi/pulumi";
23933
24003
  import pc31 from "picocolors";
23934
24004
  async function emailStatus(options) {
@@ -23936,7 +24006,7 @@ async function emailStatus(options) {
23936
24006
  const startTime = Date.now();
23937
24007
  const progress = new DeploymentProgress();
23938
24008
  if (!isJsonMode()) {
23939
- clack29.intro(pc31.bold("Wraps Email Status"));
24009
+ clack30.intro(pc31.bold("Wraps Email Status"));
23940
24010
  }
23941
24011
  const identity = await progress.execute(
23942
24012
  "Loading email infrastructure status",
@@ -23951,15 +24021,15 @@ async function emailStatus(options) {
23951
24021
  if (emailConnections.length === 1) {
23952
24022
  region = emailConnections[0].region;
23953
24023
  } else if (emailConnections.length > 1) {
23954
- const selectedRegion = await clack29.select({
24024
+ const selectedRegion = await clack30.select({
23955
24025
  message: "Multiple email deployments found. Which region?",
23956
24026
  options: emailConnections.map((conn) => ({
23957
24027
  value: conn.region,
23958
24028
  label: conn.region
23959
24029
  }))
23960
24030
  });
23961
- if (clack29.isCancel(selectedRegion)) {
23962
- clack29.cancel("Operation cancelled");
24031
+ if (clack30.isCancel(selectedRegion)) {
24032
+ clack30.cancel("Operation cancelled");
23963
24033
  process.exit(0);
23964
24034
  }
23965
24035
  region = selectedRegion;
@@ -23975,7 +24045,7 @@ async function emailStatus(options) {
23975
24045
  stackOutputs = await stack.outputs();
23976
24046
  } catch (_error) {
23977
24047
  progress.stop();
23978
- clack29.log.error("No email infrastructure found");
24048
+ clack30.log.error("No email infrastructure found");
23979
24049
  console.log(
23980
24050
  `
23981
24051
  Run ${pc31.cyan("wraps email init")} to deploy email infrastructure.
@@ -24071,7 +24141,7 @@ init_output();
24071
24141
  import { existsSync as existsSync9 } from "fs";
24072
24142
  import { mkdir as mkdir3, readFile as readFile4, writeFile as writeFile5 } from "fs/promises";
24073
24143
  import { join as join11 } from "path";
24074
- import * as clack30 from "@clack/prompts";
24144
+ import * as clack31 from "@clack/prompts";
24075
24145
  import pc32 from "picocolors";
24076
24146
 
24077
24147
  // src/utils/shared/scaffold-claude.ts
@@ -24518,7 +24588,7 @@ async function templatesInit(options) {
24518
24588
  const cwd = process.cwd();
24519
24589
  const wrapsDir = join11(cwd, "wraps");
24520
24590
  if (!isJsonMode()) {
24521
- clack30.intro(pc32.bold("Templates as Code"));
24591
+ clack31.intro(pc32.bold("Templates as Code"));
24522
24592
  }
24523
24593
  const progress = new DeploymentProgress();
24524
24594
  if (existsSync9(wrapsDir) && !options.force) {
@@ -24535,12 +24605,12 @@ async function templatesInit(options) {
24535
24605
  if (orgs?.length === 1) {
24536
24606
  orgSlug = orgs[0].slug;
24537
24607
  } else if (orgs && orgs.length > 1 && !isJsonMode()) {
24538
- const selected = await clack30.select({
24608
+ const selected = await clack31.select({
24539
24609
  message: "Which organization?",
24540
24610
  options: orgs.map((o) => ({ value: o.slug, label: o.name }))
24541
24611
  });
24542
- if (clack30.isCancel(selected)) {
24543
- clack30.cancel("Operation cancelled.");
24612
+ if (clack31.isCancel(selected)) {
24613
+ clack31.cancel("Operation cancelled.");
24544
24614
  process.exit(0);
24545
24615
  }
24546
24616
  orgSlug = selected;
@@ -24674,7 +24744,7 @@ wraps/.wraps/
24674
24744
  duration_ms: Date.now() - startTime
24675
24745
  });
24676
24746
  console.log();
24677
- clack30.log.success(pc32.green("Templates as Code initialized!"));
24747
+ clack31.log.success(pc32.green("Templates as Code initialized!"));
24678
24748
  console.log();
24679
24749
  console.log(` ${pc32.dim("Directory:")} ${pc32.cyan("wraps/")}`);
24680
24750
  console.log(` ${pc32.dim("Config:")} ${pc32.cyan("wraps/wraps.config.ts")}`);
@@ -24887,7 +24957,7 @@ init_esm_shims();
24887
24957
  init_events();
24888
24958
  import { existsSync as existsSync11, watch } from "fs";
24889
24959
  import { join as join13 } from "path";
24890
- import * as clack31 from "@clack/prompts";
24960
+ import * as clack32 from "@clack/prompts";
24891
24961
  import pc33 from "picocolors";
24892
24962
 
24893
24963
  // src/utils/email/template-compiler.ts
@@ -25012,7 +25082,7 @@ async function templatesPreview(options) {
25012
25082
  if (!existsSync11(configPath)) {
25013
25083
  throw errors.wrapsConfigNotFound();
25014
25084
  }
25015
- clack31.intro(pc33.bold("Preview Templates"));
25085
+ clack32.intro(pc33.bold("Preview Templates"));
25016
25086
  const config2 = await loadWrapsConfig(wrapsDir);
25017
25087
  const templatesDir = join13(wrapsDir, config2.templatesDir || "./templates");
25018
25088
  if (!existsSync11(templatesDir)) {
@@ -25020,7 +25090,7 @@ async function templatesPreview(options) {
25020
25090
  }
25021
25091
  const templateFiles = await discoverTemplates(templatesDir, options.template);
25022
25092
  if (templateFiles.length === 0) {
25023
- clack31.log.info("No templates found.");
25093
+ clack32.log.info("No templates found.");
25024
25094
  return;
25025
25095
  }
25026
25096
  const cache = /* @__PURE__ */ new Map();
@@ -25135,11 +25205,11 @@ async function templatesPreview(options) {
25135
25205
  success: true,
25136
25206
  template_count: templateFiles.length
25137
25207
  });
25138
- clack31.log.success(`Preview server running at ${pc33.cyan(url)}`);
25208
+ clack32.log.success(`Preview server running at ${pc33.cyan(url)}`);
25139
25209
  if (options.template) {
25140
- clack31.log.info(`Previewing: ${pc33.cyan(options.template)}`);
25210
+ clack32.log.info(`Previewing: ${pc33.cyan(options.template)}`);
25141
25211
  } else {
25142
- clack31.log.info(
25212
+ clack32.log.info(
25143
25213
  `${templateFiles.length} template${templateFiles.length === 1 ? "" : "s"} available`
25144
25214
  );
25145
25215
  }
@@ -25339,7 +25409,7 @@ import { createHash } from "crypto";
25339
25409
  import { existsSync as existsSync13 } from "fs";
25340
25410
  import { mkdir as mkdir6, readFile as readFile6, writeFile as writeFile8 } from "fs/promises";
25341
25411
  import { join as join15 } from "path";
25342
- import * as clack32 from "@clack/prompts";
25412
+ import * as clack33 from "@clack/prompts";
25343
25413
  import pc34 from "picocolors";
25344
25414
 
25345
25415
  // src/utils/email/template-render.ts
@@ -25460,7 +25530,7 @@ async function templatesPush(options) {
25460
25530
  throw errors.wrapsConfigNotFound();
25461
25531
  }
25462
25532
  if (!isJsonMode()) {
25463
- clack32.intro(pc34.bold("Push Templates"));
25533
+ clack33.intro(pc34.bold("Push Templates"));
25464
25534
  }
25465
25535
  const progress = new DeploymentProgress();
25466
25536
  progress.start("Loading configuration");
@@ -25473,7 +25543,7 @@ async function templatesPush(options) {
25473
25543
  const templateFiles = await discoverTemplates(templatesDir, options.template);
25474
25544
  if (templateFiles.length === 0) {
25475
25545
  if (!isJsonMode()) {
25476
- clack32.log.info("No templates found to push.");
25546
+ clack33.log.info("No templates found to push.");
25477
25547
  }
25478
25548
  return;
25479
25549
  }
@@ -25519,7 +25589,7 @@ async function templatesPush(options) {
25519
25589
  errors: []
25520
25590
  });
25521
25591
  } else {
25522
- clack32.log.info(
25592
+ clack33.log.info(
25523
25593
  `${unchanged.length} template${unchanged.length === 1 ? "" : "s"} unchanged. Use --force to re-push.`
25524
25594
  );
25525
25595
  }
@@ -25540,7 +25610,7 @@ async function templatesPush(options) {
25540
25610
  });
25541
25611
  } else {
25542
25612
  console.log();
25543
- clack32.log.info(pc34.bold("Dry run \u2014 no changes made"));
25613
+ clack33.log.info(pc34.bold("Dry run \u2014 no changes made"));
25544
25614
  console.log();
25545
25615
  for (const t of compiled) {
25546
25616
  console.log(
@@ -25592,16 +25662,16 @@ async function templatesPush(options) {
25592
25662
  });
25593
25663
  } else {
25594
25664
  console.log();
25595
- clack32.log.success(
25665
+ clack33.log.success(
25596
25666
  pc34.green(
25597
25667
  `${compiled.length} template${compiled.length === 1 ? "" : "s"} pushed`
25598
25668
  )
25599
25669
  );
25600
25670
  if (unchanged.length > 0) {
25601
- clack32.log.info(`${unchanged.length} unchanged (use --force to re-push)`);
25671
+ clack33.log.info(`${unchanged.length} unchanged (use --force to re-push)`);
25602
25672
  }
25603
25673
  if (compileErrors.length > 0) {
25604
- clack32.log.error(`${compileErrors.length} failed to compile`);
25674
+ clack33.log.error(`${compileErrors.length} failed to compile`);
25605
25675
  }
25606
25676
  console.log();
25607
25677
  }
@@ -25736,20 +25806,21 @@ function transformVariablesForSes(content) {
25736
25806
  }
25737
25807
  async function pushToSES(templates, progress) {
25738
25808
  const results = [];
25739
- let hasAWSCredentials = false;
25740
- let region = "us-east-1";
25809
+ const { validateAWSCredentialsWithDetails: validateAWSCredentialsWithDetails2 } = await Promise.resolve().then(() => (init_aws(), aws_exports));
25810
+ let identity;
25741
25811
  try {
25742
- const { validateAWSCredentialsWithDetails: validateAWSCredentialsWithDetails2, getAWSRegion: getAWSRegion2 } = await Promise.resolve().then(() => (init_aws(), aws_exports));
25743
- await validateAWSCredentialsWithDetails2();
25744
- hasAWSCredentials = true;
25745
- region = await getAWSRegion2();
25812
+ const result = await validateAWSCredentialsWithDetails2();
25813
+ identity = result.identity;
25746
25814
  } catch {
25747
25815
  progress.info("No AWS credentials \u2014 skipping SES push");
25748
25816
  return templates.map((t) => ({ slug: t.slug, success: false }));
25749
25817
  }
25750
- if (!hasAWSCredentials) {
25751
- return templates.map((t) => ({ slug: t.slug, success: false }));
25752
- }
25818
+ const { resolveRegionForCommand: resolveRegionForCommand2 } = await Promise.resolve().then(() => (init_region_resolver(), region_resolver_exports));
25819
+ const region = await resolveRegionForCommand2({
25820
+ accountId: identity.accountId,
25821
+ service: "email",
25822
+ label: "email deployment"
25823
+ });
25753
25824
  const {
25754
25825
  SESv2Client: SESv2Client9,
25755
25826
  CreateEmailTemplateCommand,
@@ -25979,7 +26050,7 @@ init_test();
25979
26050
 
25980
26051
  // src/commands/email/upgrade.ts
25981
26052
  init_esm_shims();
25982
- import * as clack33 from "@clack/prompts";
26053
+ import * as clack34 from "@clack/prompts";
25983
26054
  import * as pulumi23 from "@pulumi/pulumi";
25984
26055
  import pc35 from "picocolors";
25985
26056
  init_events();
@@ -25995,11 +26066,12 @@ init_metadata();
25995
26066
  init_output();
25996
26067
  init_prompts();
25997
26068
  init_pulumi();
26069
+ init_region_resolver();
25998
26070
  async function upgrade(options) {
25999
26071
  const startTime = Date.now();
26000
26072
  let upgradeAction = "";
26001
26073
  if (!isJsonMode()) {
26002
- clack33.intro(
26074
+ clack34.intro(
26003
26075
  pc35.bold(
26004
26076
  options.preview ? "Wraps Upgrade Preview" : "Wraps Upgrade - Enhance Your Email Infrastructure"
26005
26077
  )
@@ -26018,17 +26090,18 @@ async function upgrade(options) {
26018
26090
  async () => validateAWSCredentials()
26019
26091
  );
26020
26092
  progress.info(`Connected to AWS account: ${pc35.cyan(identity.accountId)}`);
26021
- let region = options.region;
26022
- if (!region) {
26023
- const defaultRegion = await getAWSRegion();
26024
- region = defaultRegion;
26025
- }
26093
+ const region = await resolveRegionForCommand({
26094
+ accountId: identity.accountId,
26095
+ optionRegion: options.region,
26096
+ service: "email",
26097
+ label: "email deployment"
26098
+ });
26026
26099
  const metadata = await loadConnectionMetadata(identity.accountId, region);
26027
26100
  if (!metadata) {
26028
- clack33.log.error(
26101
+ clack34.log.error(
26029
26102
  `No Wraps connection found for account ${pc35.cyan(identity.accountId)} in region ${pc35.cyan(region)}`
26030
26103
  );
26031
- clack33.log.info(
26104
+ clack34.log.info(
26032
26105
  `Use ${pc35.cyan("wraps email init")} to create new infrastructure or ${pc35.cyan("wraps email connect")} to connect existing.`
26033
26106
  );
26034
26107
  process.exit(1);
@@ -26044,8 +26117,8 @@ ${pc35.bold("Current Configuration:")}
26044
26117
  }
26045
26118
  const config2 = metadata.services.email?.config;
26046
26119
  if (!config2) {
26047
- clack33.log.error("No email configuration found in metadata");
26048
- clack33.log.info(
26120
+ clack34.log.error("No email configuration found in metadata");
26121
+ clack34.log.info(
26049
26122
  `Use ${pc35.cyan("wraps email init")} to create new infrastructure.`
26050
26123
  );
26051
26124
  process.exit(1);
@@ -26198,12 +26271,12 @@ ${pc35.bold("Current Configuration:")}
26198
26271
  if (options.action) {
26199
26272
  upgradeAction = options.action;
26200
26273
  } else {
26201
- upgradeAction = await clack33.select({
26274
+ upgradeAction = await clack34.select({
26202
26275
  message: "What would you like to do?",
26203
26276
  options: upgradeOptions
26204
26277
  });
26205
- if (clack33.isCancel(upgradeAction)) {
26206
- clack33.cancel("Upgrade cancelled.");
26278
+ if (clack34.isCancel(upgradeAction)) {
26279
+ clack34.cancel("Upgrade cancelled.");
26207
26280
  process.exit(0);
26208
26281
  }
26209
26282
  }
@@ -26211,7 +26284,7 @@ ${pc35.bold("Current Configuration:")}
26211
26284
  let newPreset = metadata.services.email?.preset;
26212
26285
  switch (upgradeAction) {
26213
26286
  case "finish-tracking-domain": {
26214
- clack33.log.info(
26287
+ clack34.log.info(
26215
26288
  `Checking certificate status for ${pc35.cyan(config2.tracking?.customRedirectDomain ?? "")}...`
26216
26289
  );
26217
26290
  updatedConfig = { ...config2 };
@@ -26232,19 +26305,19 @@ ${pc35.bold("Current Configuration:")}
26232
26305
  disabled: currentPresetIdx >= 0 && idx <= currentPresetIdx ? "Current or lower tier" : void 0
26233
26306
  })).filter((p) => !p.disabled);
26234
26307
  if (availablePresets.length === 0) {
26235
- clack33.log.warn("Already on highest preset (Enterprise)");
26308
+ clack34.log.warn("Already on highest preset (Enterprise)");
26236
26309
  process.exit(0);
26237
26310
  }
26238
26311
  let selectedPreset;
26239
26312
  if (options.preset) {
26240
26313
  selectedPreset = options.preset;
26241
26314
  } else {
26242
- selectedPreset = await clack33.select({
26315
+ selectedPreset = await clack34.select({
26243
26316
  message: "Select new preset:",
26244
26317
  options: availablePresets
26245
26318
  });
26246
- if (clack33.isCancel(selectedPreset)) {
26247
- clack33.cancel("Upgrade cancelled.");
26319
+ if (clack34.isCancel(selectedPreset)) {
26320
+ clack34.cancel("Upgrade cancelled.");
26248
26321
  process.exit(0);
26249
26322
  }
26250
26323
  }
@@ -26255,7 +26328,7 @@ ${pc35.bold("Current Configuration:")}
26255
26328
  }
26256
26329
  case "archiving": {
26257
26330
  if (config2.emailArchiving?.enabled) {
26258
- const archivingAction = await clack33.select({
26331
+ const archivingAction = await clack34.select({
26259
26332
  message: "What would you like to do with email archiving?",
26260
26333
  options: [
26261
26334
  {
@@ -26270,17 +26343,17 @@ ${pc35.bold("Current Configuration:")}
26270
26343
  }
26271
26344
  ]
26272
26345
  });
26273
- if (clack33.isCancel(archivingAction)) {
26274
- clack33.cancel("Upgrade cancelled.");
26346
+ if (clack34.isCancel(archivingAction)) {
26347
+ clack34.cancel("Upgrade cancelled.");
26275
26348
  process.exit(0);
26276
26349
  }
26277
26350
  if (archivingAction === "disable") {
26278
- const confirmDisable = await clack33.confirm({
26351
+ const confirmDisable = await clack34.confirm({
26279
26352
  message: "Are you sure? Existing archived emails will remain, but new emails won't be archived.",
26280
26353
  initialValue: false
26281
26354
  });
26282
- if (clack33.isCancel(confirmDisable) || !confirmDisable) {
26283
- clack33.cancel("Archiving not disabled.");
26355
+ if (clack34.isCancel(confirmDisable) || !confirmDisable) {
26356
+ clack34.cancel("Archiving not disabled.");
26284
26357
  process.exit(0);
26285
26358
  }
26286
26359
  updatedConfig = {
@@ -26291,7 +26364,7 @@ ${pc35.bold("Current Configuration:")}
26291
26364
  }
26292
26365
  };
26293
26366
  } else {
26294
- const retention = await clack33.select({
26367
+ const retention = await clack34.select({
26295
26368
  message: "Email archive retention period:",
26296
26369
  options: [
26297
26370
  {
@@ -26327,8 +26400,8 @@ ${pc35.bold("Current Configuration:")}
26327
26400
  ],
26328
26401
  initialValue: config2.emailArchiving.retention
26329
26402
  });
26330
- if (clack33.isCancel(retention)) {
26331
- clack33.cancel("Upgrade cancelled.");
26403
+ if (clack34.isCancel(retention)) {
26404
+ clack34.cancel("Upgrade cancelled.");
26332
26405
  process.exit(0);
26333
26406
  }
26334
26407
  updatedConfig = {
@@ -26340,19 +26413,19 @@ ${pc35.bold("Current Configuration:")}
26340
26413
  };
26341
26414
  }
26342
26415
  } else {
26343
- const enableArchiving = await clack33.confirm({
26416
+ const enableArchiving = await clack34.confirm({
26344
26417
  message: "Enable email archiving? (Store full email content with HTML for viewing)",
26345
26418
  initialValue: true
26346
26419
  });
26347
- if (clack33.isCancel(enableArchiving)) {
26348
- clack33.cancel("Upgrade cancelled.");
26420
+ if (clack34.isCancel(enableArchiving)) {
26421
+ clack34.cancel("Upgrade cancelled.");
26349
26422
  process.exit(0);
26350
26423
  }
26351
26424
  if (!enableArchiving) {
26352
- clack33.log.info("Email archiving not enabled.");
26425
+ clack34.log.info("Email archiving not enabled.");
26353
26426
  process.exit(0);
26354
26427
  }
26355
- const retention = await clack33.select({
26428
+ const retention = await clack34.select({
26356
26429
  message: "Email archive retention period:",
26357
26430
  options: [
26358
26431
  {
@@ -26388,16 +26461,16 @@ ${pc35.bold("Current Configuration:")}
26388
26461
  ],
26389
26462
  initialValue: "90days"
26390
26463
  });
26391
- if (clack33.isCancel(retention)) {
26392
- clack33.cancel("Upgrade cancelled.");
26464
+ if (clack34.isCancel(retention)) {
26465
+ clack34.cancel("Upgrade cancelled.");
26393
26466
  process.exit(0);
26394
26467
  }
26395
- clack33.log.info(
26468
+ clack34.log.info(
26396
26469
  pc35.dim(
26397
26470
  "Archiving stores full RFC 822 emails with HTML, attachments, and headers"
26398
26471
  )
26399
26472
  );
26400
- clack33.log.info(
26473
+ clack34.log.info(
26401
26474
  pc35.dim(
26402
26475
  "Cost: $2/GB ingestion + $0.19/GB/month storage (~50KB per email)"
26403
26476
  )
@@ -26415,10 +26488,10 @@ ${pc35.bold("Current Configuration:")}
26415
26488
  }
26416
26489
  case "tracking-domain": {
26417
26490
  if (!config2.domain) {
26418
- clack33.log.error(
26491
+ clack34.log.error(
26419
26492
  "No sending domain configured. You must configure a sending domain before adding a custom tracking domain."
26420
26493
  );
26421
- clack33.log.info(
26494
+ clack34.log.info(
26422
26495
  `Use ${pc35.cyan("wraps email init")} to set up a sending domain first.`
26423
26496
  );
26424
26497
  process.exit(1);
@@ -26430,13 +26503,13 @@ ${pc35.bold("Current Configuration:")}
26430
26503
  );
26431
26504
  const sendingDomain = domains.find((d) => d.domain === config2.domain);
26432
26505
  if (!sendingDomain?.verified) {
26433
- clack33.log.error(
26506
+ clack34.log.error(
26434
26507
  `Sending domain ${pc35.cyan(config2.domain)} is not verified.`
26435
26508
  );
26436
- clack33.log.info(
26509
+ clack34.log.info(
26437
26510
  "You must verify your sending domain before adding a custom tracking domain."
26438
26511
  );
26439
- clack33.log.info(
26512
+ clack34.log.info(
26440
26513
  `Use ${pc35.cyan("wraps email verify")} to check DNS records and complete verification.`
26441
26514
  );
26442
26515
  process.exit(1);
@@ -26444,7 +26517,7 @@ ${pc35.bold("Current Configuration:")}
26444
26517
  progress.info(
26445
26518
  `Sending domain ${pc35.cyan(config2.domain)} is verified ${pc35.green("\u2713")}`
26446
26519
  );
26447
- const trackingDomain = await clack33.text({
26520
+ const trackingDomain = await clack34.text({
26448
26521
  message: "Custom tracking redirect domain:",
26449
26522
  placeholder: "track.yourdomain.com",
26450
26523
  initialValue: config2.tracking?.customRedirectDomain || "",
@@ -26454,25 +26527,25 @@ ${pc35.bold("Current Configuration:")}
26454
26527
  }
26455
26528
  }
26456
26529
  });
26457
- if (clack33.isCancel(trackingDomain)) {
26458
- clack33.cancel("Upgrade cancelled.");
26530
+ if (clack34.isCancel(trackingDomain)) {
26531
+ clack34.cancel("Upgrade cancelled.");
26459
26532
  process.exit(0);
26460
26533
  }
26461
- const enableHttps = await clack33.confirm({
26534
+ const enableHttps = await clack34.confirm({
26462
26535
  message: "Enable HTTPS tracking with CloudFront + SSL certificate?",
26463
26536
  initialValue: true
26464
26537
  });
26465
- if (clack33.isCancel(enableHttps)) {
26466
- clack33.cancel("Upgrade cancelled.");
26538
+ if (clack34.isCancel(enableHttps)) {
26539
+ clack34.cancel("Upgrade cancelled.");
26467
26540
  process.exit(0);
26468
26541
  }
26469
26542
  if (enableHttps) {
26470
- clack33.log.info(
26543
+ clack34.log.info(
26471
26544
  pc35.dim(
26472
26545
  "HTTPS tracking creates a CloudFront distribution with an SSL certificate."
26473
26546
  )
26474
26547
  );
26475
- clack33.log.info(
26548
+ clack34.log.info(
26476
26549
  pc35.dim(
26477
26550
  "This ensures all tracking links use secure HTTPS connections."
26478
26551
  )
@@ -26503,32 +26576,32 @@ ${pc35.bold("Current Configuration:")}
26503
26576
  progress.info(
26504
26577
  `Found ${pc35.cyan(getDNSProviderDisplayName(detectedProvider.provider))} ${pc35.green("\u2713")}`
26505
26578
  );
26506
- clack33.log.info(
26579
+ clack34.log.info(
26507
26580
  pc35.dim(
26508
26581
  "DNS records (SSL certificate validation + CloudFront) will be created automatically."
26509
26582
  )
26510
26583
  );
26511
26584
  } else {
26512
26585
  canAutomateDNS = false;
26513
- clack33.log.warn(
26586
+ clack34.log.warn(
26514
26587
  `No automatic DNS provider detected for ${pc35.cyan(trackingDomain || config2.domain)}`
26515
26588
  );
26516
- clack33.log.info(
26589
+ clack34.log.info(
26517
26590
  pc35.dim(
26518
26591
  "You'll need to manually create DNS records for SSL certificate validation and CloudFront."
26519
26592
  )
26520
26593
  );
26521
- clack33.log.info(
26594
+ clack34.log.info(
26522
26595
  pc35.dim("DNS record details will be shown after deployment.")
26523
26596
  );
26524
26597
  }
26525
26598
  }
26526
- const confirmHttps = await clack33.confirm({
26599
+ const confirmHttps = await clack34.confirm({
26527
26600
  message: canAutomateDNS ? "Proceed with automatic HTTPS setup?" : "Proceed with manual HTTPS setup (requires DNS configuration)?",
26528
26601
  initialValue: true
26529
26602
  });
26530
- if (clack33.isCancel(confirmHttps) || !confirmHttps) {
26531
- clack33.log.info("HTTPS tracking not enabled. Using HTTP tracking.");
26603
+ if (clack34.isCancel(confirmHttps) || !confirmHttps) {
26604
+ clack34.log.info("HTTPS tracking not enabled. Using HTTP tracking.");
26532
26605
  updatedConfig = {
26533
26606
  ...config2,
26534
26607
  tracking: {
@@ -26550,7 +26623,7 @@ ${pc35.bold("Current Configuration:")}
26550
26623
  };
26551
26624
  }
26552
26625
  } else {
26553
- clack33.log.info(
26626
+ clack34.log.info(
26554
26627
  pc35.dim(
26555
26628
  "Using HTTP tracking (standard). Links will use http:// protocol."
26556
26629
  )
@@ -26569,7 +26642,7 @@ ${pc35.bold("Current Configuration:")}
26569
26642
  break;
26570
26643
  }
26571
26644
  case "retention": {
26572
- const retention = await clack33.select({
26645
+ const retention = await clack34.select({
26573
26646
  message: "Email history retention period (event data in DynamoDB):",
26574
26647
  options: [
26575
26648
  { value: "7days", label: "7 days", hint: "Minimal storage cost" },
@@ -26593,16 +26666,16 @@ ${pc35.bold("Current Configuration:")}
26593
26666
  ],
26594
26667
  initialValue: config2.eventTracking?.archiveRetention || "90days"
26595
26668
  });
26596
- if (clack33.isCancel(retention)) {
26597
- clack33.cancel("Upgrade cancelled.");
26669
+ if (clack34.isCancel(retention)) {
26670
+ clack34.cancel("Upgrade cancelled.");
26598
26671
  process.exit(0);
26599
26672
  }
26600
- clack33.log.info(
26673
+ clack34.log.info(
26601
26674
  pc35.dim(
26602
26675
  "Note: This is for event data (sent, delivered, opened, etc.) stored in DynamoDB."
26603
26676
  )
26604
26677
  );
26605
- clack33.log.info(
26678
+ clack34.log.info(
26606
26679
  pc35.dim(
26607
26680
  "For full email content storage, use 'Enable email archiving' option."
26608
26681
  )
@@ -26620,7 +26693,7 @@ ${pc35.bold("Current Configuration:")}
26620
26693
  break;
26621
26694
  }
26622
26695
  case "events": {
26623
- const selectedEvents = await clack33.multiselect({
26696
+ const selectedEvents = await clack34.multiselect({
26624
26697
  message: "Select SES event types to track:",
26625
26698
  options: [
26626
26699
  { value: "SEND", label: "Send", hint: "Email sent to SES" },
@@ -26664,8 +26737,8 @@ ${pc35.bold("Current Configuration:")}
26664
26737
  ],
26665
26738
  required: true
26666
26739
  });
26667
- if (clack33.isCancel(selectedEvents)) {
26668
- clack33.cancel("Upgrade cancelled.");
26740
+ if (clack34.isCancel(selectedEvents)) {
26741
+ clack34.cancel("Upgrade cancelled.");
26669
26742
  process.exit(0);
26670
26743
  }
26671
26744
  updatedConfig = {
@@ -26680,16 +26753,16 @@ ${pc35.bold("Current Configuration:")}
26680
26753
  break;
26681
26754
  }
26682
26755
  case "dedicated-ip": {
26683
- const confirmed = await clack33.confirm({
26756
+ const confirmed = await clack34.confirm({
26684
26757
  message: "Enable dedicated IP? (Requires 100k+ emails/day, adds ~$50-100/mo)",
26685
26758
  initialValue: false
26686
26759
  });
26687
- if (clack33.isCancel(confirmed)) {
26688
- clack33.cancel("Upgrade cancelled.");
26760
+ if (clack34.isCancel(confirmed)) {
26761
+ clack34.cancel("Upgrade cancelled.");
26689
26762
  process.exit(0);
26690
26763
  }
26691
26764
  if (!confirmed) {
26692
- clack33.log.info("Dedicated IP not enabled.");
26765
+ clack34.log.info("Dedicated IP not enabled.");
26693
26766
  process.exit(0);
26694
26767
  }
26695
26768
  updatedConfig = {
@@ -26701,16 +26774,16 @@ ${pc35.bold("Current Configuration:")}
26701
26774
  }
26702
26775
  case "alerts": {
26703
26776
  if (!config2.reputationMetrics) {
26704
- clack33.log.warn("Reputation metrics must be enabled to use alerting.");
26705
- clack33.log.info(
26777
+ clack34.log.warn("Reputation metrics must be enabled to use alerting.");
26778
+ clack34.log.info(
26706
26779
  "This requires the Production or Enterprise preset, or enabling reputation metrics manually."
26707
26780
  );
26708
- const enableReputationMetrics = await clack33.confirm({
26781
+ const enableReputationMetrics = await clack34.confirm({
26709
26782
  message: "Enable reputation metrics now?",
26710
26783
  initialValue: true
26711
26784
  });
26712
- if (clack33.isCancel(enableReputationMetrics) || !enableReputationMetrics) {
26713
- clack33.cancel("Alerting not enabled.");
26785
+ if (clack34.isCancel(enableReputationMetrics) || !enableReputationMetrics) {
26786
+ clack34.cancel("Alerting not enabled.");
26714
26787
  process.exit(0);
26715
26788
  }
26716
26789
  updatedConfig = {
@@ -26719,13 +26792,13 @@ ${pc35.bold("Current Configuration:")}
26719
26792
  };
26720
26793
  }
26721
26794
  if (config2.alerts?.enabled) {
26722
- clack33.log.info(`Alerting is currently ${pc35.green("enabled")}`);
26795
+ clack34.log.info(`Alerting is currently ${pc35.green("enabled")}`);
26723
26796
  if (config2.alerts.notificationEmail) {
26724
- clack33.log.info(
26797
+ clack34.log.info(
26725
26798
  ` Notification email: ${pc35.cyan(config2.alerts.notificationEmail)}`
26726
26799
  );
26727
26800
  }
26728
- const alertsAction = await clack33.select({
26801
+ const alertsAction = await clack34.select({
26729
26802
  message: "What would you like to do?",
26730
26803
  options: [
26731
26804
  {
@@ -26745,17 +26818,17 @@ ${pc35.bold("Current Configuration:")}
26745
26818
  }
26746
26819
  ]
26747
26820
  });
26748
- if (clack33.isCancel(alertsAction)) {
26749
- clack33.cancel("Upgrade cancelled.");
26821
+ if (clack34.isCancel(alertsAction)) {
26822
+ clack34.cancel("Upgrade cancelled.");
26750
26823
  process.exit(0);
26751
26824
  }
26752
26825
  if (alertsAction === "disable") {
26753
- const confirmDisable = await clack33.confirm({
26826
+ const confirmDisable = await clack34.confirm({
26754
26827
  message: "Are you sure? You won't be notified if your reputation degrades.",
26755
26828
  initialValue: false
26756
26829
  });
26757
- if (clack33.isCancel(confirmDisable) || !confirmDisable) {
26758
- clack33.log.info("Alerting not disabled.");
26830
+ if (clack34.isCancel(confirmDisable) || !confirmDisable) {
26831
+ clack34.log.info("Alerting not disabled.");
26759
26832
  process.exit(0);
26760
26833
  }
26761
26834
  updatedConfig = {
@@ -26763,7 +26836,7 @@ ${pc35.bold("Current Configuration:")}
26763
26836
  alerts: { enabled: false }
26764
26837
  };
26765
26838
  } else if (alertsAction === "change-email") {
26766
- const notificationEmail = await clack33.text({
26839
+ const notificationEmail = await clack34.text({
26767
26840
  message: "Notification email address:",
26768
26841
  placeholder: "alerts@yourcompany.com",
26769
26842
  initialValue: config2.alerts.notificationEmail || "",
@@ -26773,8 +26846,8 @@ ${pc35.bold("Current Configuration:")}
26773
26846
  }
26774
26847
  }
26775
26848
  });
26776
- if (clack33.isCancel(notificationEmail)) {
26777
- clack33.cancel("Upgrade cancelled.");
26849
+ if (clack34.isCancel(notificationEmail)) {
26850
+ clack34.cancel("Upgrade cancelled.");
26778
26851
  process.exit(0);
26779
26852
  }
26780
26853
  updatedConfig = {
@@ -26786,14 +26859,14 @@ ${pc35.bold("Current Configuration:")}
26786
26859
  }
26787
26860
  };
26788
26861
  } else if (alertsAction === "change-thresholds") {
26789
- clack33.log.info(`
26862
+ clack34.log.info(`
26790
26863
  ${pc35.bold("Alert Thresholds")}`);
26791
- clack33.log.info(
26864
+ clack34.log.info(
26792
26865
  pc35.dim("These thresholds warn you BEFORE AWS takes action:")
26793
26866
  );
26794
- clack33.log.info(pc35.dim(" AWS warns at 5% bounce, 0.1% complaint"));
26795
- clack33.log.info(pc35.dim(" Gmail blocks at 0.3% complaint rate\n"));
26796
- const thresholdPreset = await clack33.select({
26867
+ clack34.log.info(pc35.dim(" AWS warns at 5% bounce, 0.1% complaint"));
26868
+ clack34.log.info(pc35.dim(" Gmail blocks at 0.3% complaint rate\n"));
26869
+ const thresholdPreset = await clack34.select({
26797
26870
  message: "Choose threshold sensitivity:",
26798
26871
  options: [
26799
26872
  {
@@ -26813,8 +26886,8 @@ ${pc35.bold("Alert Thresholds")}`);
26813
26886
  }
26814
26887
  ]
26815
26888
  });
26816
- if (clack33.isCancel(thresholdPreset)) {
26817
- clack33.cancel("Upgrade cancelled.");
26889
+ if (clack34.isCancel(thresholdPreset)) {
26890
+ clack34.cancel("Upgrade cancelled.");
26818
26891
  process.exit(0);
26819
26892
  }
26820
26893
  const thresholdConfigs = {
@@ -26847,27 +26920,27 @@ ${pc35.bold("Alert Thresholds")}`);
26847
26920
  };
26848
26921
  }
26849
26922
  } else {
26850
- clack33.log.info(`
26923
+ clack34.log.info(`
26851
26924
  ${pc35.bold("Reputation Alerts")}
26852
26925
  `);
26853
- clack33.log.info(
26926
+ clack34.log.info(
26854
26927
  pc35.dim("Get notified when your email reputation is at risk:")
26855
26928
  );
26856
- clack33.log.info(pc35.dim(" - Bounce rate warnings (before AWS review)"));
26857
- clack33.log.info(
26929
+ clack34.log.info(pc35.dim(" - Bounce rate warnings (before AWS review)"));
26930
+ clack34.log.info(
26858
26931
  pc35.dim(" - Complaint rate warnings (before Gmail blocks you)")
26859
26932
  );
26860
- clack33.log.info(pc35.dim(" - DLQ alerts (event processing failures)"));
26861
- clack33.log.info(pc35.dim("\nCost: ~$0.50/mo (5 CloudWatch alarms)\n"));
26862
- const enableAlerts = await clack33.confirm({
26933
+ clack34.log.info(pc35.dim(" - DLQ alerts (event processing failures)"));
26934
+ clack34.log.info(pc35.dim("\nCost: ~$0.50/mo (5 CloudWatch alarms)\n"));
26935
+ const enableAlerts = await clack34.confirm({
26863
26936
  message: "Enable reputation alerts?",
26864
26937
  initialValue: true
26865
26938
  });
26866
- if (clack33.isCancel(enableAlerts) || !enableAlerts) {
26867
- clack33.log.info("Alerting not enabled.");
26939
+ if (clack34.isCancel(enableAlerts) || !enableAlerts) {
26940
+ clack34.log.info("Alerting not enabled.");
26868
26941
  process.exit(0);
26869
26942
  }
26870
- const notificationEmail = await clack33.text({
26943
+ const notificationEmail = await clack34.text({
26871
26944
  message: "Notification email address:",
26872
26945
  placeholder: "alerts@yourcompany.com",
26873
26946
  validate: (value) => {
@@ -26879,11 +26952,11 @@ ${pc35.bold("Reputation Alerts")}
26879
26952
  }
26880
26953
  }
26881
26954
  });
26882
- if (clack33.isCancel(notificationEmail)) {
26883
- clack33.cancel("Upgrade cancelled.");
26955
+ if (clack34.isCancel(notificationEmail)) {
26956
+ clack34.cancel("Upgrade cancelled.");
26884
26957
  process.exit(0);
26885
26958
  }
26886
- clack33.log.info(
26959
+ clack34.log.info(
26887
26960
  pc35.dim("\nYou'll receive an email to confirm your subscription.")
26888
26961
  );
26889
26962
  updatedConfig = {
@@ -26910,18 +26983,18 @@ ${pc35.bold("Reputation Alerts")}
26910
26983
  }
26911
26984
  case "wraps-dashboard": {
26912
26985
  if (!config2.eventTracking?.enabled) {
26913
- clack33.log.warn(
26986
+ clack34.log.warn(
26914
26987
  "Event tracking must be enabled to connect to Wraps Dashboard."
26915
26988
  );
26916
- clack33.log.info(
26989
+ clack34.log.info(
26917
26990
  "Enabling event tracking will allow SES events to be sent to the dashboard."
26918
26991
  );
26919
- const enableEventTracking = await clack33.confirm({
26992
+ const enableEventTracking = await clack34.confirm({
26920
26993
  message: "Enable event tracking now?",
26921
26994
  initialValue: true
26922
26995
  });
26923
- if (clack33.isCancel(enableEventTracking) || !enableEventTracking) {
26924
- clack33.cancel("Dashboard connection cancelled.");
26996
+ if (clack34.isCancel(enableEventTracking) || !enableEventTracking) {
26997
+ clack34.cancel("Dashboard connection cancelled.");
26925
26998
  process.exit(0);
26926
26999
  }
26927
27000
  updatedConfig = {
@@ -26944,10 +27017,10 @@ ${pc35.bold("Reputation Alerts")}
26944
27017
  }
26945
27018
  const existingSecret = metadata.services.email?.webhookSecret;
26946
27019
  if (existingSecret) {
26947
- clack33.log.info(
27020
+ clack34.log.info(
26948
27021
  `Currently connected to Wraps Dashboard (AWS Account: ${pc35.cyan(metadata.accountId)})`
26949
27022
  );
26950
- const action = await clack33.select({
27023
+ const action = await clack34.select({
26951
27024
  message: "What would you like to do?",
26952
27025
  options: [
26953
27026
  {
@@ -26967,17 +27040,17 @@ ${pc35.bold("Reputation Alerts")}
26967
27040
  }
26968
27041
  ]
26969
27042
  });
26970
- if (clack33.isCancel(action) || action === "cancel") {
26971
- clack33.log.info("No changes made.");
27043
+ if (clack34.isCancel(action) || action === "cancel") {
27044
+ clack34.log.info("No changes made.");
26972
27045
  process.exit(0);
26973
27046
  }
26974
27047
  if (action === "disconnect") {
26975
- const confirmDisconnect = await clack33.confirm({
27048
+ const confirmDisconnect = await clack34.confirm({
26976
27049
  message: "Are you sure? Events will no longer be sent to the Wraps Dashboard.",
26977
27050
  initialValue: false
26978
27051
  });
26979
- if (clack33.isCancel(confirmDisconnect) || !confirmDisconnect) {
26980
- clack33.log.info("Disconnect cancelled.");
27052
+ if (clack34.isCancel(confirmDisconnect) || !confirmDisconnect) {
27053
+ clack34.log.info("Disconnect cancelled.");
26981
27054
  process.exit(0);
26982
27055
  }
26983
27056
  if (metadata.services.email) {
@@ -26989,12 +27062,12 @@ ${pc35.bold("Reputation Alerts")}
26989
27062
  }
26990
27063
  }
26991
27064
  const webhookSecret = generateWebhookSecret();
26992
- clack33.log.info(`
27065
+ clack34.log.info(`
26993
27066
  ${pc35.bold("Webhook Configuration:")}`);
26994
- clack33.log.info(
27067
+ clack34.log.info(
26995
27068
  pc35.dim("A secure webhook secret has been generated for authentication.")
26996
27069
  );
26997
- clack33.log.info(
27070
+ clack34.log.info(
26998
27071
  pc35.dim(
26999
27072
  "After deployment, you'll need to register this secret in the dashboard.\n"
27000
27073
  )
@@ -27040,18 +27113,18 @@ ${pc35.bold("Webhook Configuration:")}`);
27040
27113
  }
27041
27114
  };
27042
27115
  if (!config2.eventTracking?.enabled) {
27043
- clack33.log.warn(
27116
+ clack34.log.warn(
27044
27117
  "Event tracking must be enabled to configure a webhook endpoint."
27045
27118
  );
27046
- clack33.log.info(
27119
+ clack34.log.info(
27047
27120
  "Enabling event tracking will allow SES events to be sent to your endpoint."
27048
27121
  );
27049
- const enableEventTracking = await clack33.confirm({
27122
+ const enableEventTracking = await clack34.confirm({
27050
27123
  message: "Enable event tracking now?",
27051
27124
  initialValue: true
27052
27125
  });
27053
- if (clack33.isCancel(enableEventTracking) || !enableEventTracking) {
27054
- clack33.cancel("Webhook configuration cancelled.");
27126
+ if (clack34.isCancel(enableEventTracking) || !enableEventTracking) {
27127
+ clack34.cancel("Webhook configuration cancelled.");
27055
27128
  process.exit(0);
27056
27129
  }
27057
27130
  updatedConfig = {
@@ -27073,10 +27146,10 @@ ${pc35.bold("Webhook Configuration:")}`);
27073
27146
  };
27074
27147
  }
27075
27148
  if (config2.userWebhook?.enabled) {
27076
- clack33.log.info(
27149
+ clack34.log.info(
27077
27150
  `Webhook endpoint currently sending events to: ${pc35.cyan(config2.userWebhook.url)}`
27078
27151
  );
27079
- const action = await clack33.select({
27152
+ const action = await clack34.select({
27080
27153
  message: "What would you like to do?",
27081
27154
  options: [
27082
27155
  {
@@ -27101,17 +27174,17 @@ ${pc35.bold("Webhook Configuration:")}`);
27101
27174
  }
27102
27175
  ]
27103
27176
  });
27104
- if (clack33.isCancel(action) || action === "cancel") {
27105
- clack33.log.info("No changes made.");
27177
+ if (clack34.isCancel(action) || action === "cancel") {
27178
+ clack34.log.info("No changes made.");
27106
27179
  process.exit(0);
27107
27180
  }
27108
27181
  if (action === "disable") {
27109
- const confirmDisable = await clack33.confirm({
27182
+ const confirmDisable = await clack34.confirm({
27110
27183
  message: "Are you sure? Events will no longer be sent to your webhook endpoint.",
27111
27184
  initialValue: false
27112
27185
  });
27113
- if (clack33.isCancel(confirmDisable) || !confirmDisable) {
27114
- clack33.log.info("Webhook not disabled.");
27186
+ if (clack34.isCancel(confirmDisable) || !confirmDisable) {
27187
+ clack34.log.info("Webhook not disabled.");
27115
27188
  process.exit(0);
27116
27189
  }
27117
27190
  updatedConfig = {
@@ -27122,13 +27195,13 @@ ${pc35.bold("Webhook Configuration:")}`);
27122
27195
  break;
27123
27196
  }
27124
27197
  if (action === "change-url") {
27125
- const newUrl = await clack33.text({
27198
+ const newUrl = await clack34.text({
27126
27199
  message: "New webhook URL:",
27127
27200
  placeholder: "https://your-app.com/webhooks/email-events",
27128
27201
  validate: validateWebhookUrl
27129
27202
  });
27130
- if (clack33.isCancel(newUrl)) {
27131
- clack33.cancel("Webhook configuration cancelled.");
27203
+ if (clack34.isCancel(newUrl)) {
27204
+ clack34.cancel("Webhook configuration cancelled.");
27132
27205
  process.exit(0);
27133
27206
  }
27134
27207
  updatedConfig = {
@@ -27156,20 +27229,20 @@ ${pc35.bold("Webhook Configuration:")}`);
27156
27229
  break;
27157
27230
  }
27158
27231
  } else {
27159
- clack33.log.info(`
27232
+ clack34.log.info(`
27160
27233
  ${pc35.bold("Webhook Endpoint")}
27161
27234
  `);
27162
- clack33.log.info(
27235
+ clack34.log.info(
27163
27236
  pc35.dim("Send SES events (send, delivery, open, click, bounce, etc.)")
27164
27237
  );
27165
- clack33.log.info(pc35.dim("to your own HTTP endpoint in real-time.\n"));
27166
- const webhookUrl = await clack33.text({
27238
+ clack34.log.info(pc35.dim("to your own HTTP endpoint in real-time.\n"));
27239
+ const webhookUrl = await clack34.text({
27167
27240
  message: "Webhook URL (must be HTTPS):",
27168
27241
  placeholder: "https://your-app.com/webhooks/email-events",
27169
27242
  validate: validateWebhookUrl
27170
27243
  });
27171
- if (clack33.isCancel(webhookUrl)) {
27172
- clack33.cancel("Webhook configuration cancelled.");
27244
+ if (clack34.isCancel(webhookUrl)) {
27245
+ clack34.cancel("Webhook configuration cancelled.");
27173
27246
  process.exit(0);
27174
27247
  }
27175
27248
  const secret2 = generateWebhookSecret();
@@ -27187,10 +27260,10 @@ ${pc35.bold("Webhook Endpoint")}
27187
27260
  }
27188
27261
  case "smtp-credentials": {
27189
27262
  if (metadata.services.email?.smtpCredentials?.enabled) {
27190
- clack33.log.info(
27263
+ clack34.log.info(
27191
27264
  `SMTP credentials are currently ${pc35.green("enabled")} (created ${metadata.services.email.smtpCredentials.createdAt})`
27192
27265
  );
27193
- const smtpAction = await clack33.select({
27266
+ const smtpAction = await clack34.select({
27194
27267
  message: "What would you like to do?",
27195
27268
  options: [
27196
27269
  {
@@ -27210,17 +27283,17 @@ ${pc35.bold("Webhook Endpoint")}
27210
27283
  }
27211
27284
  ]
27212
27285
  });
27213
- if (clack33.isCancel(smtpAction) || smtpAction === "cancel") {
27214
- clack33.log.info("No changes made.");
27286
+ if (clack34.isCancel(smtpAction) || smtpAction === "cancel") {
27287
+ clack34.log.info("No changes made.");
27215
27288
  process.exit(0);
27216
27289
  }
27217
27290
  if (smtpAction === "disable") {
27218
- const confirmDisable = await clack33.confirm({
27291
+ const confirmDisable = await clack34.confirm({
27219
27292
  message: "Are you sure? Any systems using these credentials will stop working immediately.",
27220
27293
  initialValue: false
27221
27294
  });
27222
- if (clack33.isCancel(confirmDisable) || !confirmDisable) {
27223
- clack33.log.info("SMTP credentials not disabled.");
27295
+ if (clack34.isCancel(confirmDisable) || !confirmDisable) {
27296
+ clack34.log.info("SMTP credentials not disabled.");
27224
27297
  process.exit(0);
27225
27298
  }
27226
27299
  updatedConfig = {
@@ -27233,43 +27306,43 @@ ${pc35.bold("Webhook Endpoint")}
27233
27306
  newPreset = void 0;
27234
27307
  break;
27235
27308
  }
27236
- clack33.log.info(
27309
+ clack34.log.info(
27237
27310
  "\nRotating credentials will invalidate your current SMTP password."
27238
27311
  );
27239
- clack33.log.warn(
27312
+ clack34.log.warn(
27240
27313
  "You will need to update all systems using the old credentials."
27241
27314
  );
27242
- const confirmRotate = await clack33.confirm({
27315
+ const confirmRotate = await clack34.confirm({
27243
27316
  message: "Generate new SMTP credentials?",
27244
27317
  initialValue: false
27245
27318
  });
27246
- if (clack33.isCancel(confirmRotate) || !confirmRotate) {
27247
- clack33.log.info("Credential rotation cancelled.");
27319
+ if (clack34.isCancel(confirmRotate) || !confirmRotate) {
27320
+ clack34.log.info("Credential rotation cancelled.");
27248
27321
  process.exit(0);
27249
27322
  }
27250
27323
  }
27251
- clack33.log.info(`
27324
+ clack34.log.info(`
27252
27325
  ${pc35.bold("SMTP Credentials for Legacy Systems")}
27253
27326
  `);
27254
- clack33.log.info(
27327
+ clack34.log.info(
27255
27328
  pc35.dim("Generate SMTP username/password that works with:")
27256
27329
  );
27257
- clack33.log.info(pc35.dim(" - PHP mail() and PHPMailer"));
27258
- clack33.log.info(pc35.dim(" - WordPress (WP Mail SMTP plugin)"));
27259
- clack33.log.info(pc35.dim(" - Nodemailer and other SMTP libraries"));
27260
- clack33.log.info(pc35.dim(" - Any SMTP-compatible email client"));
27330
+ clack34.log.info(pc35.dim(" - PHP mail() and PHPMailer"));
27331
+ clack34.log.info(pc35.dim(" - WordPress (WP Mail SMTP plugin)"));
27332
+ clack34.log.info(pc35.dim(" - Nodemailer and other SMTP libraries"));
27333
+ clack34.log.info(pc35.dim(" - Any SMTP-compatible email client"));
27261
27334
  console.log("");
27262
- clack33.log.warn(
27335
+ clack34.log.warn(
27263
27336
  "Credentials will be shown ONCE after deployment - save them immediately!"
27264
27337
  );
27265
27338
  console.log("");
27266
27339
  if (!options.yes) {
27267
- const confirmCreate = await clack33.confirm({
27340
+ const confirmCreate = await clack34.confirm({
27268
27341
  message: "Create SMTP credentials?",
27269
27342
  initialValue: true
27270
27343
  });
27271
- if (clack33.isCancel(confirmCreate) || !confirmCreate) {
27272
- clack33.log.info("SMTP credentials not created.");
27344
+ if (clack34.isCancel(confirmCreate) || !confirmCreate) {
27345
+ clack34.log.info("SMTP credentials not created.");
27273
27346
  process.exit(0);
27274
27347
  }
27275
27348
  }
@@ -27284,7 +27357,7 @@ ${pc35.bold("SMTP Credentials for Legacy Systems")}
27284
27357
  break;
27285
27358
  }
27286
27359
  case "hosting-provider": {
27287
- const newProvider = await clack33.select({
27360
+ const newProvider = await clack34.select({
27288
27361
  message: "Where is your app hosted?",
27289
27362
  options: [
27290
27363
  {
@@ -27309,12 +27382,12 @@ ${pc35.bold("SMTP Credentials for Legacy Systems")}
27309
27382
  }
27310
27383
  ]
27311
27384
  });
27312
- if (clack33.isCancel(newProvider)) {
27313
- clack33.cancel("Upgrade cancelled.");
27385
+ if (clack34.isCancel(newProvider)) {
27386
+ clack34.cancel("Upgrade cancelled.");
27314
27387
  process.exit(0);
27315
27388
  }
27316
27389
  if (newProvider === metadata.provider) {
27317
- clack33.log.info("Provider unchanged \u2014 no changes needed.");
27390
+ clack34.log.info("Provider unchanged \u2014 no changes needed.");
27318
27391
  process.exit(0);
27319
27392
  }
27320
27393
  metadata.provider = newProvider;
@@ -27345,12 +27418,12 @@ ${pc35.bold("Cost Impact:")}`);
27345
27418
  }
27346
27419
  console.log("");
27347
27420
  if (!(options.yes || options.preview)) {
27348
- const confirmed = await clack33.confirm({
27421
+ const confirmed = await clack34.confirm({
27349
27422
  message: "Proceed with upgrade?",
27350
27423
  initialValue: true
27351
27424
  });
27352
- if (clack33.isCancel(confirmed) || !confirmed) {
27353
- clack33.cancel("Upgrade cancelled.");
27425
+ if (clack34.isCancel(confirmed) || !confirmed) {
27426
+ clack34.cancel("Upgrade cancelled.");
27354
27427
  process.exit(0);
27355
27428
  }
27356
27429
  }
@@ -27397,15 +27470,15 @@ ${pc35.bold("Cost Impact:")}`);
27397
27470
  );
27398
27471
  await new Promise((resolve) => setTimeout(resolve, 2e3));
27399
27472
  } else if (!caaResult.success) {
27400
- clack33.log.warn(
27473
+ clack34.log.warn(
27401
27474
  `Could not verify CAA records: ${caaResult.error || "Unknown error"}`
27402
27475
  );
27403
- clack33.log.info(
27476
+ clack34.log.info(
27404
27477
  pc35.dim(
27405
27478
  "If certificate issuance fails, you may need to add a CAA record manually:"
27406
27479
  )
27407
27480
  );
27408
- clack33.log.info(pc35.dim(` ${parentDomain} CAA 0 issue "amazon.com"`));
27481
+ clack34.log.info(pc35.dim(` ${parentDomain} CAA 0 issue "amazon.com"`));
27409
27482
  }
27410
27483
  }
27411
27484
  }
@@ -27469,7 +27542,7 @@ ${pc35.bold("Cost Impact:")}`);
27469
27542
  costEstimate: costComparison,
27470
27543
  commandName: "wraps email upgrade"
27471
27544
  });
27472
- clack33.outro(
27545
+ clack34.outro(
27473
27546
  pc35.green("Preview complete. Run without --preview to upgrade.")
27474
27547
  );
27475
27548
  trackServiceUpgrade("email", {
@@ -27647,7 +27720,7 @@ ${pc35.bold("Cost Impact:")}`);
27647
27720
  );
27648
27721
  }
27649
27722
  } else {
27650
- clack33.log.warn(
27723
+ clack34.log.warn(
27651
27724
  credResult.error || `Unable to validate ${getDNSProviderDisplayName(dnsProvider)} credentials`
27652
27725
  );
27653
27726
  }
@@ -27663,7 +27736,7 @@ ${pc35.bold("Cost Impact:")}`);
27663
27736
  };
27664
27737
  const dnsRecords = buildEmailDNSRecords(dnsData);
27665
27738
  console.log();
27666
- clack33.note(
27739
+ clack34.note(
27667
27740
  formatManualDNSInstructions(dnsRecords),
27668
27741
  "DNS Records \u2014 Add these to your DNS provider"
27669
27742
  );
@@ -27973,7 +28046,7 @@ init_output();
27973
28046
  import { existsSync as existsSync14 } from "fs";
27974
28047
  import { mkdir as mkdir7, readFile as readFile7, writeFile as writeFile9 } from "fs/promises";
27975
28048
  import { join as join16 } from "path";
27976
- import * as clack34 from "@clack/prompts";
28049
+ import * as clack35 from "@clack/prompts";
27977
28050
  import pc36 from "picocolors";
27978
28051
 
27979
28052
  // src/commands/email/workflows/claude-content.ts
@@ -28365,7 +28438,7 @@ async function workflowsInit(options) {
28365
28438
  const cwd = process.cwd();
28366
28439
  const workflowsDir = join16(cwd, "wraps", "workflows");
28367
28440
  if (!isJsonMode()) {
28368
- clack34.intro(pc36.bold("Workflows as Code"));
28441
+ clack35.intro(pc36.bold("Workflows as Code"));
28369
28442
  }
28370
28443
  const progress = new DeploymentProgress();
28371
28444
  if (existsSync14(workflowsDir) && !options.force) {
@@ -28375,7 +28448,7 @@ async function workflowsInit(options) {
28375
28448
  (f) => f.endsWith(".ts") && !f.startsWith("_")
28376
28449
  );
28377
28450
  if (tsFiles.length > 0 && !options.force && !isJsonMode()) {
28378
- clack34.log.warn(
28451
+ clack35.log.warn(
28379
28452
  `${pc36.cyan("wraps/workflows/")} already contains ${tsFiles.length} workflow file(s). Use ${pc36.bold("--force")} to overwrite.`
28380
28453
  );
28381
28454
  }
@@ -28442,7 +28515,7 @@ async function workflowsInit(options) {
28442
28515
  return;
28443
28516
  }
28444
28517
  console.log();
28445
- clack34.log.success(pc36.green("Workflows as Code initialized!"));
28518
+ clack35.log.success(pc36.green("Workflows as Code initialized!"));
28446
28519
  console.log();
28447
28520
  console.log(` ${pc36.dim("Directory:")} ${pc36.cyan("wraps/workflows/")}`);
28448
28521
  if (!options.noExample) {
@@ -28485,7 +28558,7 @@ init_esm_shims();
28485
28558
  init_events();
28486
28559
  import { existsSync as existsSync16 } from "fs";
28487
28560
  import { join as join18 } from "path";
28488
- import * as clack35 from "@clack/prompts";
28561
+ import * as clack36 from "@clack/prompts";
28489
28562
  import pc37 from "picocolors";
28490
28563
 
28491
28564
  // src/utils/email/workflow-transform.ts
@@ -29336,7 +29409,7 @@ async function workflowsPush(options) {
29336
29409
  throw errors.wrapsConfigNotFound();
29337
29410
  }
29338
29411
  if (!isJsonMode()) {
29339
- clack35.intro(pc37.bold("Push Workflows"));
29412
+ clack36.intro(pc37.bold("Push Workflows"));
29340
29413
  }
29341
29414
  const progress = new DeploymentProgress();
29342
29415
  progress.start("Loading configuration");
@@ -29351,7 +29424,7 @@ async function workflowsPush(options) {
29351
29424
  errors: []
29352
29425
  });
29353
29426
  } else {
29354
- clack35.log.info("No workflows/ directory found.");
29427
+ clack36.log.info("No workflows/ directory found.");
29355
29428
  }
29356
29429
  return;
29357
29430
  }
@@ -29364,7 +29437,7 @@ async function workflowsPush(options) {
29364
29437
  errors: []
29365
29438
  });
29366
29439
  } else {
29367
- clack35.log.info("No workflows found to push.");
29440
+ clack36.log.info("No workflows found to push.");
29368
29441
  }
29369
29442
  return;
29370
29443
  }
@@ -29433,7 +29506,7 @@ async function workflowsPush(options) {
29433
29506
  });
29434
29507
  } else {
29435
29508
  console.log();
29436
- clack35.log.error(
29509
+ clack36.log.error(
29437
29510
  pc37.red("Cannot push due to validation errors. Fix errors and retry.")
29438
29511
  );
29439
29512
  console.log();
@@ -29448,7 +29521,7 @@ async function workflowsPush(options) {
29448
29521
  errors: []
29449
29522
  });
29450
29523
  } else {
29451
- clack35.log.info(
29524
+ clack36.log.info(
29452
29525
  `${unchanged.length} workflow(s) unchanged. Use --force to re-push.`
29453
29526
  );
29454
29527
  }
@@ -29469,7 +29542,7 @@ async function workflowsPush(options) {
29469
29542
  });
29470
29543
  } else {
29471
29544
  console.log();
29472
- clack35.log.info(pc37.bold("Dry run \u2014 no changes made"));
29545
+ clack36.log.info(pc37.bold("Dry run \u2014 no changes made"));
29473
29546
  console.log();
29474
29547
  for (const w of toProcess) {
29475
29548
  console.log(
@@ -29526,20 +29599,20 @@ async function workflowsPush(options) {
29526
29599
  } else {
29527
29600
  console.log();
29528
29601
  if (enabled.length > 0) {
29529
- clack35.log.success(
29602
+ clack36.log.success(
29530
29603
  pc37.green(`${enabled.length} workflow(s) pushed and enabled`)
29531
29604
  );
29532
29605
  }
29533
29606
  if (drafts.length > 0) {
29534
- clack35.log.success(
29607
+ clack36.log.success(
29535
29608
  pc37.green(`${drafts.length} workflow(s) pushed as draft`)
29536
29609
  );
29537
29610
  }
29538
29611
  if (unchanged.length > 0) {
29539
- clack35.log.info(`${unchanged.length} unchanged (use --force to re-push)`);
29612
+ clack36.log.info(`${unchanged.length} unchanged (use --force to re-push)`);
29540
29613
  }
29541
29614
  if (conflicts.length > 0) {
29542
- clack35.log.error(
29615
+ clack36.log.error(
29543
29616
  `${conflicts.length} workflow(s) skipped due to dashboard edits. Use --force to overwrite.`
29544
29617
  );
29545
29618
  for (const c of conflicts) {
@@ -29703,7 +29776,7 @@ init_esm_shims();
29703
29776
  init_events();
29704
29777
  import { existsSync as existsSync17 } from "fs";
29705
29778
  import { join as join19 } from "path";
29706
- import * as clack36 from "@clack/prompts";
29779
+ import * as clack37 from "@clack/prompts";
29707
29780
  import pc38 from "picocolors";
29708
29781
  init_errors();
29709
29782
  init_json_output();
@@ -29717,7 +29790,7 @@ async function workflowsValidate(options) {
29717
29790
  throw errors.wrapsConfigNotFound();
29718
29791
  }
29719
29792
  if (!isJsonMode()) {
29720
- clack36.intro(pc38.bold("Validate Workflows"));
29793
+ clack37.intro(pc38.bold("Validate Workflows"));
29721
29794
  }
29722
29795
  const progress = new DeploymentProgress();
29723
29796
  progress.start("Loading configuration");
@@ -29728,7 +29801,7 @@ async function workflowsValidate(options) {
29728
29801
  if (isJsonMode()) {
29729
29802
  jsonSuccess("email.workflows.validate", { workflows: [], errors: [] });
29730
29803
  } else {
29731
- clack36.log.info("No workflows/ directory found.");
29804
+ clack37.log.info("No workflows/ directory found.");
29732
29805
  }
29733
29806
  return;
29734
29807
  }
@@ -29737,7 +29810,7 @@ async function workflowsValidate(options) {
29737
29810
  if (isJsonMode()) {
29738
29811
  jsonSuccess("email.workflows.validate", { workflows: [], errors: [] });
29739
29812
  } else {
29740
- clack36.log.info("No workflows found to validate.");
29813
+ clack37.log.info("No workflows found to validate.");
29741
29814
  }
29742
29815
  return;
29743
29816
  }
@@ -29814,18 +29887,18 @@ async function workflowsValidate(options) {
29814
29887
  const invalidCount = validationResults.filter((r) => !r.valid).length;
29815
29888
  const parseErrorCount = parseErrors.length;
29816
29889
  if (parseErrorCount === 0 && invalidCount === 0) {
29817
- clack36.log.success(
29890
+ clack37.log.success(
29818
29891
  pc38.green(`${validCount} workflow(s) validated successfully`)
29819
29892
  );
29820
29893
  } else {
29821
29894
  if (validCount > 0) {
29822
- clack36.log.success(pc38.green(`${validCount} workflow(s) valid`));
29895
+ clack37.log.success(pc38.green(`${validCount} workflow(s) valid`));
29823
29896
  }
29824
29897
  if (invalidCount > 0) {
29825
- clack36.log.error(pc38.red(`${invalidCount} workflow(s) have errors`));
29898
+ clack37.log.error(pc38.red(`${invalidCount} workflow(s) have errors`));
29826
29899
  }
29827
29900
  if (parseErrorCount > 0) {
29828
- clack36.log.error(
29901
+ clack37.log.error(
29829
29902
  pc38.red(`${parseErrorCount} workflow(s) failed to parse`)
29830
29903
  );
29831
29904
  }
@@ -29859,11 +29932,11 @@ async function workflowsValidate(options) {
29859
29932
  // src/commands/news.ts
29860
29933
  init_esm_shims();
29861
29934
  init_events();
29862
- import * as clack37 from "@clack/prompts";
29935
+ import * as clack38 from "@clack/prompts";
29863
29936
  import pc39 from "picocolors";
29864
29937
  async function news() {
29865
29938
  trackCommand("news", { success: true });
29866
- clack37.intro(pc39.bold("What's New in Wraps"));
29939
+ clack38.intro(pc39.bold("What's New in Wraps"));
29867
29940
  console.log();
29868
29941
  console.log(" See the latest updates, features, and improvements:");
29869
29942
  console.log();
@@ -29879,7 +29952,7 @@ async function news() {
29879
29952
  init_esm_shims();
29880
29953
  init_events();
29881
29954
  init_json_output();
29882
- import * as clack38 from "@clack/prompts";
29955
+ import * as clack39 from "@clack/prompts";
29883
29956
  import pc40 from "picocolors";
29884
29957
  function getBaseStatements() {
29885
29958
  return [
@@ -30271,7 +30344,7 @@ function buildPolicy(service, preset) {
30271
30344
  };
30272
30345
  }
30273
30346
  function displaySummary(service, preset) {
30274
- clack38.intro(pc40.bold("Wraps Required AWS Permissions"));
30347
+ clack39.intro(pc40.bold("Wraps Required AWS Permissions"));
30275
30348
  const serviceLabel = service ? service.toUpperCase() : "All Services";
30276
30349
  const presetLabel = preset ? preset.charAt(0).toUpperCase() + preset.slice(1) : "All Features";
30277
30350
  console.log(`
@@ -30365,7 +30438,7 @@ async function permissions(options) {
30365
30438
  console.log("2. Create the policy in AWS Console:");
30366
30439
  console.log(" IAM > Policies > Create Policy > JSON\n");
30367
30440
  console.log("3. Attach to your IAM user/role\n");
30368
- clack38.outro(
30441
+ clack39.outro(
30369
30442
  pc40.green("Run with --json to get the full IAM policy document")
30370
30443
  );
30371
30444
  }
@@ -30383,7 +30456,7 @@ import {
30383
30456
  IAMClient as IAMClient3,
30384
30457
  PutRolePolicyCommand
30385
30458
  } from "@aws-sdk/client-iam";
30386
- import { confirm as confirm18, intro as intro34, isCancel as isCancel24, log as log36, outro as outro20, select as select16 } from "@clack/prompts";
30459
+ import { confirm as confirm18, intro as intro34, isCancel as isCancel25, log as log36, outro as outro20, select as select17 } from "@clack/prompts";
30387
30460
  import * as pulumi24 from "@pulumi/pulumi";
30388
30461
  import pc41 from "picocolors";
30389
30462
  init_events();
@@ -30396,6 +30469,7 @@ init_metadata();
30396
30469
  init_output();
30397
30470
  init_prompts();
30398
30471
  init_pulumi();
30472
+ init_region_resolver();
30399
30473
  function buildConsolePolicyDocument(emailConfig, smsConfig) {
30400
30474
  const statements = [];
30401
30475
  statements.push({
@@ -30572,10 +30646,11 @@ async function validateAndLoadMetadata(options, progress) {
30572
30646
  async () => validateAWSCredentials()
30573
30647
  );
30574
30648
  progress.info(`Connected to AWS account: ${pc41.cyan(identity.accountId)}`);
30575
- let region = options.region;
30576
- if (!region) {
30577
- region = await getAWSRegion();
30578
- }
30649
+ const region = await resolveRegionForCommand({
30650
+ accountId: identity.accountId,
30651
+ optionRegion: options.region,
30652
+ label: "connection"
30653
+ });
30579
30654
  const metadata = await loadConnectionMetadata(identity.accountId, region);
30580
30655
  if (!metadata) {
30581
30656
  progress.stop();
@@ -30734,7 +30809,7 @@ async function resolveOrganization() {
30734
30809
  if (orgs.length === 1) {
30735
30810
  return orgs[0];
30736
30811
  }
30737
- const selected = await select16({
30812
+ const selected = await select17({
30738
30813
  message: "Which organization should this AWS account connect to?",
30739
30814
  options: orgs.map((org) => ({
30740
30815
  value: org.id,
@@ -30742,7 +30817,7 @@ async function resolveOrganization() {
30742
30817
  hint: org.slug
30743
30818
  }))
30744
30819
  });
30745
- if (isCancel24(selected)) {
30820
+ if (isCancel25(selected)) {
30746
30821
  outro20("Operation cancelled");
30747
30822
  process.exit(0);
30748
30823
  }
@@ -30808,7 +30883,7 @@ async function authenticatedConnect(token, options) {
30808
30883
  message: "Enable event tracking now?",
30809
30884
  initialValue: true
30810
30885
  });
30811
- if (isCancel24(enableTracking) || !enableTracking) {
30886
+ if (isCancel25(enableTracking) || !enableTracking) {
30812
30887
  outro20("Platform connection cancelled.");
30813
30888
  process.exit(0);
30814
30889
  }
@@ -30953,10 +31028,11 @@ async function connect3(options) {
30953
31028
  async () => validateAWSCredentials()
30954
31029
  );
30955
31030
  progress.info(`Connected to AWS account: ${pc41.cyan(identity.accountId)}`);
30956
- let region = options.region;
30957
- if (!region) {
30958
- region = await getAWSRegion();
30959
- }
31031
+ const region = await resolveRegionForCommand({
31032
+ accountId: identity.accountId,
31033
+ optionRegion: options.region,
31034
+ label: "connection"
31035
+ });
30960
31036
  const metadata = await loadConnectionMetadata(identity.accountId, region);
30961
31037
  if (!metadata) {
30962
31038
  progress.stop();
@@ -31002,7 +31078,7 @@ Run ${pc41.cyan("wraps email init")} or ${pc41.cyan("wraps sms init")} first.
31002
31078
  message: "Enable event tracking now?",
31003
31079
  initialValue: true
31004
31080
  });
31005
- if (isCancel24(enableEventTracking) || !enableEventTracking) {
31081
+ if (isCancel25(enableEventTracking) || !enableEventTracking) {
31006
31082
  outro20("Platform connection cancelled.");
31007
31083
  process.exit(0);
31008
31084
  }
@@ -31030,7 +31106,7 @@ Run ${pc41.cyan("wraps email init")} or ${pc41.cyan("wraps sms init")} first.
31030
31106
  log36.info(
31031
31107
  `Already connected to Wraps Platform (AWS Account: ${pc41.cyan(metadata.accountId)})`
31032
31108
  );
31033
- const action = await select16({
31109
+ const action = await select17({
31034
31110
  message: "What would you like to do?",
31035
31111
  options: [
31036
31112
  {
@@ -31050,7 +31126,7 @@ Run ${pc41.cyan("wraps email init")} or ${pc41.cyan("wraps sms init")} first.
31050
31126
  }
31051
31127
  ]
31052
31128
  });
31053
- if (isCancel24(action)) {
31129
+ if (isCancel25(action)) {
31054
31130
  outro20("Operation cancelled");
31055
31131
  process.exit(0);
31056
31132
  }
@@ -31061,7 +31137,7 @@ Run ${pc41.cyan("wraps email init")} or ${pc41.cyan("wraps sms init")} first.
31061
31137
  message: "Are you sure? Events will no longer be sent to the Wraps Platform.",
31062
31138
  initialValue: false
31063
31139
  });
31064
- if (isCancel24(confirmDisconnect) || !confirmDisconnect) {
31140
+ if (isCancel25(confirmDisconnect) || !confirmDisconnect) {
31065
31141
  outro20("Disconnect cancelled");
31066
31142
  process.exit(0);
31067
31143
  }
@@ -31211,10 +31287,10 @@ ${pc41.bold("Next Steps:")}`);
31211
31287
 
31212
31288
  // src/commands/platform/index.ts
31213
31289
  init_esm_shims();
31214
- import * as clack39 from "@clack/prompts";
31290
+ import * as clack40 from "@clack/prompts";
31215
31291
  import pc42 from "picocolors";
31216
31292
  async function platform() {
31217
- clack39.intro(pc42.bold("Wraps Platform"));
31293
+ clack40.intro(pc42.bold("Wraps Platform"));
31218
31294
  console.log();
31219
31295
  console.log(
31220
31296
  " The Wraps Platform extends the free CLI with hosted features:"
@@ -31267,12 +31343,13 @@ init_aws();
31267
31343
  init_json_output();
31268
31344
  init_metadata();
31269
31345
  init_output();
31346
+ init_region_resolver();
31270
31347
  import {
31271
31348
  CreateRoleCommand as CreateRoleCommand2,
31272
31349
  GetRoleCommand as GetRoleCommand2,
31273
31350
  IAMClient as IAMClient4
31274
31351
  } from "@aws-sdk/client-iam";
31275
- import { confirm as confirm19, intro as intro36, isCancel as isCancel25, log as log37, outro as outro21 } from "@clack/prompts";
31352
+ import { confirm as confirm19, intro as intro36, isCancel as isCancel26, log as log37, outro as outro21 } from "@clack/prompts";
31276
31353
  import pc43 from "picocolors";
31277
31354
  async function updateRole(options) {
31278
31355
  const startTime = Date.now();
@@ -31284,7 +31361,11 @@ async function updateRole(options) {
31284
31361
  "Validating AWS credentials",
31285
31362
  async () => validateAWSCredentials()
31286
31363
  );
31287
- const region = options.region || await getAWSRegion();
31364
+ const region = await resolveRegionForCommand({
31365
+ accountId: identity.accountId,
31366
+ optionRegion: options.region,
31367
+ label: "connection"
31368
+ });
31288
31369
  const metadata = await loadConnectionMetadata(identity.accountId, region);
31289
31370
  if (!metadata) {
31290
31371
  progress.stop();
@@ -31337,7 +31418,7 @@ Run ${pc43.cyan("wraps email init")} to deploy infrastructure first.
31337
31418
  message: `${actionLabel} IAM role ${pc43.cyan(roleName)} with latest permissions?`,
31338
31419
  initialValue: true
31339
31420
  });
31340
- if (isCancel25(shouldContinue) || !shouldContinue) {
31421
+ if (isCancel26(shouldContinue) || !shouldContinue) {
31341
31422
  outro21(`${actionLabel} cancelled`);
31342
31423
  process.exit(0);
31343
31424
  }
@@ -31656,7 +31737,7 @@ function buildConsolePolicyDocument2(emailConfig, smsConfig) {
31656
31737
 
31657
31738
  // src/commands/shared/dashboard.ts
31658
31739
  init_esm_shims();
31659
- import * as clack40 from "@clack/prompts";
31740
+ import * as clack41 from "@clack/prompts";
31660
31741
  import * as pulumi25 from "@pulumi/pulumi";
31661
31742
  import getPort from "get-port";
31662
31743
  import open2 from "open";
@@ -34307,7 +34388,7 @@ init_output();
34307
34388
  init_pulumi();
34308
34389
  async function dashboard(options) {
34309
34390
  await ensurePulumiInstalled();
34310
- clack40.intro(pc44.bold("Wraps Dashboard"));
34391
+ clack41.intro(pc44.bold("Wraps Dashboard"));
34311
34392
  const progress = new DeploymentProgress();
34312
34393
  const identity = await progress.execute(
34313
34394
  "Validating AWS credentials",
@@ -34348,7 +34429,7 @@ async function dashboard(options) {
34348
34429
  }
34349
34430
  } catch (_error) {
34350
34431
  progress.stop();
34351
- clack40.log.error("No Wraps infrastructure found");
34432
+ clack41.log.error("No Wraps infrastructure found");
34352
34433
  console.log(
34353
34434
  `\\nRun ${pc44.cyan("wraps email init")}, ${pc44.cyan("wraps sms init")}, or ${pc44.cyan("wraps storage init")} to deploy infrastructure first.\\n`
34354
34435
  );
@@ -34392,7 +34473,7 @@ async function dashboard(options) {
34392
34473
  }
34393
34474
  const port = options.port || await getPort({ port: [5555, 5556, 5557, 5558, 5559] });
34394
34475
  progress.stop();
34395
- clack40.log.success("Starting dashboard server...");
34476
+ clack41.log.success("Starting dashboard server...");
34396
34477
  console.log(
34397
34478
  `${pc44.dim("Using current AWS credentials (no role assumption)")}\\n`
34398
34479
  );
@@ -34449,7 +34530,7 @@ init_aws();
34449
34530
  init_errors();
34450
34531
  init_json_output();
34451
34532
  init_metadata();
34452
- import * as clack41 from "@clack/prompts";
34533
+ import * as clack42 from "@clack/prompts";
34453
34534
  import pc45 from "picocolors";
34454
34535
  async function destroy(options) {
34455
34536
  trackCommand("destroy", { success: true });
@@ -34461,9 +34542,9 @@ async function destroy(options) {
34461
34542
  );
34462
34543
  }
34463
34544
  if (!isJsonMode()) {
34464
- clack41.intro(pc45.bold("Wraps Infrastructure Teardown"));
34545
+ clack42.intro(pc45.bold("Wraps Infrastructure Teardown"));
34465
34546
  }
34466
- const spinner10 = clack41.spinner();
34547
+ const spinner10 = clack42.spinner();
34467
34548
  spinner10.start("Validating AWS credentials");
34468
34549
  let identity;
34469
34550
  try {
@@ -34480,7 +34561,7 @@ async function destroy(options) {
34480
34561
  deployedServices.push("email");
34481
34562
  }
34482
34563
  if (deployedServices.length === 0) {
34483
- clack41.log.warn("No Wraps services found in this region");
34564
+ clack42.log.warn("No Wraps services found in this region");
34484
34565
  console.log(
34485
34566
  `
34486
34567
  Run ${pc45.cyan("wraps email init")} to deploy infrastructure.
@@ -34490,7 +34571,7 @@ Run ${pc45.cyan("wraps email init")} to deploy infrastructure.
34490
34571
  }
34491
34572
  if (deployedServices.length === 1) {
34492
34573
  const service = deployedServices[0];
34493
- clack41.log.info(`Found ${pc45.cyan(service)} service deployed`);
34574
+ clack42.log.info(`Found ${pc45.cyan(service)} service deployed`);
34494
34575
  if (service === "email") {
34495
34576
  await emailDestroy(options);
34496
34577
  return;
@@ -34505,7 +34586,7 @@ Run ${pc45.cyan("wraps email init")} to deploy infrastructure.
34505
34586
  jsonSuccess("destroy", { destroyed: true });
34506
34587
  return;
34507
34588
  }
34508
- const serviceToDestroy = await clack41.select({
34589
+ const serviceToDestroy = await clack42.select({
34509
34590
  message: "Which service would you like to destroy?",
34510
34591
  options: [
34511
34592
  ...deployedServices.map((s) => ({
@@ -34520,15 +34601,15 @@ Run ${pc45.cyan("wraps email init")} to deploy infrastructure.
34520
34601
  }
34521
34602
  ]
34522
34603
  });
34523
- if (clack41.isCancel(serviceToDestroy)) {
34524
- clack41.cancel("Operation cancelled.");
34604
+ if (clack42.isCancel(serviceToDestroy)) {
34605
+ clack42.cancel("Operation cancelled.");
34525
34606
  process.exit(0);
34526
34607
  }
34527
34608
  if ((serviceToDestroy === "email" || serviceToDestroy === "all") && deployedServices.includes("email")) {
34528
34609
  await emailDestroy(options);
34529
34610
  }
34530
34611
  if (serviceToDestroy === "all") {
34531
- clack41.outro(pc45.green("All Wraps infrastructure has been removed"));
34612
+ clack42.outro(pc45.green("All Wraps infrastructure has been removed"));
34532
34613
  }
34533
34614
  }
34534
34615
 
@@ -34540,7 +34621,7 @@ init_fs();
34540
34621
  init_json_output();
34541
34622
  init_output();
34542
34623
  init_pulumi();
34543
- import * as clack42 from "@clack/prompts";
34624
+ import * as clack43 from "@clack/prompts";
34544
34625
  import * as pulumi26 from "@pulumi/pulumi";
34545
34626
  import pc46 from "picocolors";
34546
34627
  async function status(_options) {
@@ -34548,7 +34629,7 @@ async function status(_options) {
34548
34629
  const startTime = Date.now();
34549
34630
  const progress = new DeploymentProgress();
34550
34631
  if (!isJsonMode()) {
34551
- clack42.intro(pc46.bold("Wraps Infrastructure Status"));
34632
+ clack43.intro(pc46.bold("Wraps Infrastructure Status"));
34552
34633
  }
34553
34634
  const identity = await progress.execute(
34554
34635
  "Loading infrastructure status",
@@ -34611,7 +34692,7 @@ async function status(_options) {
34611
34692
  return;
34612
34693
  }
34613
34694
  console.log();
34614
- clack42.note(
34695
+ clack43.note(
34615
34696
  services.map((s) => {
34616
34697
  if (s.status === "deployed") {
34617
34698
  const details = s.details ? pc46.dim(` (${s.details})`) : "";
@@ -34650,13 +34731,12 @@ ${pc46.bold("Dashboard:")} ${pc46.blue("https://app.wraps.dev")}`);
34650
34731
 
34651
34732
  // src/commands/sms/destroy.ts
34652
34733
  init_esm_shims();
34653
- import * as clack43 from "@clack/prompts";
34734
+ import * as clack44 from "@clack/prompts";
34654
34735
  import * as pulumi28 from "@pulumi/pulumi";
34655
34736
  import pc47 from "picocolors";
34656
34737
 
34657
34738
  // src/infrastructure/sms-stack.ts
34658
34739
  init_esm_shims();
34659
- init_constants();
34660
34740
  import * as aws20 from "@pulumi/aws";
34661
34741
  import * as pulumi27 from "@pulumi/pulumi";
34662
34742
  init_resource_checks();
@@ -34772,12 +34852,10 @@ function createSMSOptOutList() {
34772
34852
  }
34773
34853
  });
34774
34854
  }
34775
- async function findExistingPhoneNumber(phoneNumberType) {
34855
+ async function findExistingPhoneNumber(phoneNumberType, region) {
34776
34856
  try {
34777
34857
  const { PinpointSMSVoiceV2Client: PinpointSMSVoiceV2Client5, DescribePhoneNumbersCommand: DescribePhoneNumbersCommand2 } = await import("@aws-sdk/client-pinpoint-sms-voice-v2");
34778
- const client = new PinpointSMSVoiceV2Client5({
34779
- region: getDefaultRegion()
34780
- });
34858
+ const client = new PinpointSMSVoiceV2Client5({ region });
34781
34859
  const numberTypeMap = {
34782
34860
  simulator: "SIMULATOR",
34783
34861
  "toll-free": "TOLL_FREE",
@@ -34811,14 +34889,14 @@ async function findExistingPhoneNumber(phoneNumberType) {
34811
34889
  throw error;
34812
34890
  }
34813
34891
  }
34814
- async function createSMSPhoneNumber(phoneNumberType, optOutList) {
34892
+ async function createSMSPhoneNumber(phoneNumberType, optOutList, region) {
34815
34893
  const numberTypeMap = {
34816
34894
  simulator: "SIMULATOR",
34817
34895
  "toll-free": "TOLL_FREE",
34818
34896
  "10dlc": "TEN_DLC",
34819
34897
  "short-code": "SHORT_CODE"
34820
34898
  };
34821
- const existingArn = await findExistingPhoneNumber(phoneNumberType);
34899
+ const existingArn = await findExistingPhoneNumber(phoneNumberType, region);
34822
34900
  const phoneConfig = {
34823
34901
  isoCountryCode: "US",
34824
34902
  messageType: "TRANSACTIONAL",
@@ -34855,11 +34933,11 @@ async function createSMSPhoneNumber(phoneNumberType, optOutList) {
34855
34933
  }
34856
34934
  );
34857
34935
  }
34858
- async function createSMSSQSResources() {
34936
+ async function createSMSSQSResources(config2) {
34859
34937
  const dlqName = "wraps-sms-events-dlq";
34860
34938
  const queueName = "wraps-sms-events";
34861
- const dlqUrl = await sqsQueueExists(dlqName);
34862
- const queueUrl = await sqsQueueExists(queueName);
34939
+ const dlqUrl = await sqsQueueExists(dlqName, config2.region);
34940
+ const queueUrl = await sqsQueueExists(queueName, config2.region);
34863
34941
  const dlqConfig = {
34864
34942
  name: dlqName,
34865
34943
  messageRetentionSeconds: 1209600,
@@ -34906,7 +34984,7 @@ async function createSMSSQSResources() {
34906
34984
  }
34907
34985
  async function createSMSSNSResources(config2) {
34908
34986
  const topicName = "wraps-sms-events";
34909
- const topicArn = await snsTopicExists(topicName);
34987
+ const topicArn = await snsTopicExists(topicName, config2.region);
34910
34988
  const topicConfig = {
34911
34989
  name: topicName,
34912
34990
  tags: {
@@ -34969,9 +35047,9 @@ async function createSMSSNSResources(config2) {
34969
35047
  );
34970
35048
  return { topic, subscription };
34971
35049
  }
34972
- async function createSMSDynamoDBTable() {
35050
+ async function createSMSDynamoDBTable(config2) {
34973
35051
  const tableName = "wraps-sms-history";
34974
- const exists = await tableExists(tableName);
35052
+ const exists = await tableExists(tableName, config2.region);
34975
35053
  const tableConfig = {
34976
35054
  name: tableName,
34977
35055
  billingMode: "PAY_PER_REQUEST",
@@ -35136,23 +35214,25 @@ async function deploySMSStack(config2) {
35136
35214
  if (smsConfig.phoneNumberType) {
35137
35215
  phoneNumber = await createSMSPhoneNumber(
35138
35216
  smsConfig.phoneNumberType,
35139
- optOutList
35217
+ optOutList,
35218
+ config2.region
35140
35219
  );
35141
35220
  }
35142
35221
  let sqsResources;
35143
35222
  if (smsConfig.eventTracking?.enabled) {
35144
- sqsResources = await createSMSSQSResources();
35223
+ sqsResources = await createSMSSQSResources({ region: config2.region });
35145
35224
  }
35146
35225
  let snsResources;
35147
35226
  if (smsConfig.eventTracking?.enabled && sqsResources) {
35148
35227
  snsResources = await createSMSSNSResources({
35149
35228
  queueArn: sqsResources.queue.arn,
35150
- queueUrl: sqsResources.queue.url
35229
+ queueUrl: sqsResources.queue.url,
35230
+ region: config2.region
35151
35231
  });
35152
35232
  }
35153
35233
  let dynamoTable;
35154
35234
  if (smsConfig.eventTracking?.dynamoDBHistory) {
35155
- dynamoTable = await createSMSDynamoDBTable();
35235
+ dynamoTable = await createSMSDynamoDBTable({ region: config2.region });
35156
35236
  }
35157
35237
  let lambdaFunction;
35158
35238
  if (smsConfig.eventTracking?.dynamoDBHistory && dynamoTable && sqsResources) {
@@ -35501,7 +35581,7 @@ async function smsDestroy(options) {
35501
35581
  );
35502
35582
  }
35503
35583
  if (!isJsonMode()) {
35504
- clack43.intro(
35584
+ clack44.intro(
35505
35585
  pc47.bold(
35506
35586
  options.preview ? "SMS Infrastructure Destruction Preview" : "SMS Infrastructure Teardown"
35507
35587
  )
@@ -35528,15 +35608,15 @@ async function smsDestroy(options) {
35528
35608
  `Available regions: ${smsConnections.map((c) => c.region).join(", ")}`
35529
35609
  );
35530
35610
  }
35531
- const selectedRegion = await clack43.select({
35611
+ const selectedRegion = await clack44.select({
35532
35612
  message: "Multiple SMS deployments found. Which region to destroy?",
35533
35613
  options: smsConnections.map((conn) => ({
35534
35614
  value: conn.region,
35535
35615
  label: conn.region
35536
35616
  }))
35537
35617
  });
35538
- if (clack43.isCancel(selectedRegion)) {
35539
- clack43.cancel("Operation cancelled");
35618
+ if (clack44.isCancel(selectedRegion)) {
35619
+ clack44.cancel("Operation cancelled");
35540
35620
  process.exit(0);
35541
35621
  }
35542
35622
  region = selectedRegion;
@@ -35547,18 +35627,18 @@ async function smsDestroy(options) {
35547
35627
  const storedStackName = smsService?.pulumiStackName;
35548
35628
  if (!smsService) {
35549
35629
  progress.stop();
35550
- clack43.log.warn("No SMS infrastructure found");
35630
+ clack44.log.warn("No SMS infrastructure found");
35551
35631
  process.exit(0);
35552
35632
  }
35553
35633
  if (!(options.force || options.preview)) {
35554
- const confirmed = await clack43.confirm({
35634
+ const confirmed = await clack44.confirm({
35555
35635
  message: pc47.red(
35556
35636
  "Are you sure you want to destroy all SMS infrastructure?"
35557
35637
  ),
35558
35638
  initialValue: false
35559
35639
  });
35560
- if (clack43.isCancel(confirmed) || !confirmed) {
35561
- clack43.cancel("Destruction cancelled.");
35640
+ if (clack44.isCancel(confirmed) || !confirmed) {
35641
+ clack44.cancel("Destruction cancelled.");
35562
35642
  process.exit(0);
35563
35643
  }
35564
35644
  }
@@ -35590,7 +35670,7 @@ async function smsDestroy(options) {
35590
35670
  costEstimate: "Monthly cost after destruction: $0.00",
35591
35671
  commandName: "wraps sms destroy"
35592
35672
  });
35593
- clack43.outro(
35673
+ clack44.outro(
35594
35674
  pc47.green("Preview complete. Run without --preview to destroy.")
35595
35675
  );
35596
35676
  trackServiceRemoved("sms", {
@@ -35602,7 +35682,7 @@ async function smsDestroy(options) {
35602
35682
  progress.stop();
35603
35683
  const errorMessage = error instanceof Error ? error.message : String(error);
35604
35684
  if (errorMessage.includes("No SMS infrastructure found")) {
35605
- clack43.log.warn("No SMS infrastructure found to preview");
35685
+ clack44.log.warn("No SMS infrastructure found to preview");
35606
35686
  process.exit(0);
35607
35687
  }
35608
35688
  trackError("PREVIEW_FAILED", "sms destroy", { step: "preview" });
@@ -35651,7 +35731,7 @@ async function smsDestroy(options) {
35651
35731
  progress.stop();
35652
35732
  const errorMessage = error instanceof Error ? error.message : String(error);
35653
35733
  if (errorMessage.includes("No SMS infrastructure found")) {
35654
- clack43.log.warn("No SMS infrastructure found");
35734
+ clack44.log.warn("No SMS infrastructure found");
35655
35735
  if (metadata) {
35656
35736
  removeServiceFromConnection(metadata, "sms");
35657
35737
  await saveConnectionMetadata(metadata);
@@ -35664,7 +35744,7 @@ async function smsDestroy(options) {
35664
35744
  }
35665
35745
  trackError("DESTROY_FAILED", "sms destroy", { step: "destroy" });
35666
35746
  destroyFailed = true;
35667
- clack43.log.warn(
35747
+ clack44.log.warn(
35668
35748
  "Some resources may not have been fully removed. You can re-run this command or clean up manually in the AWS console."
35669
35749
  );
35670
35750
  }
@@ -35687,11 +35767,11 @@ async function smsDestroy(options) {
35687
35767
  return;
35688
35768
  }
35689
35769
  if (destroyFailed) {
35690
- clack43.outro(
35770
+ clack44.outro(
35691
35771
  pc47.yellow("SMS infrastructure partially removed. Metadata cleaned up.")
35692
35772
  );
35693
35773
  } else {
35694
- clack43.outro(pc47.green("SMS infrastructure has been removed"));
35774
+ clack44.outro(pc47.green("SMS infrastructure has been removed"));
35695
35775
  console.log(`
35696
35776
  ${pc47.bold("Cleaned up:")}`);
35697
35777
  console.log(` ${pc47.green("\u2713")} Phone number released`);
@@ -35713,7 +35793,7 @@ Run ${pc47.cyan("wraps sms init")} to deploy infrastructure again.
35713
35793
 
35714
35794
  // src/commands/sms/init.ts
35715
35795
  init_esm_shims();
35716
- import * as clack44 from "@clack/prompts";
35796
+ import * as clack45 from "@clack/prompts";
35717
35797
  import * as pulumi29 from "@pulumi/pulumi";
35718
35798
  import pc48 from "picocolors";
35719
35799
  init_events();
@@ -36134,7 +36214,7 @@ function validateSMSConfig(config2) {
36134
36214
 
36135
36215
  // src/commands/sms/init.ts
36136
36216
  async function promptPhoneNumberType() {
36137
- const result = await clack44.select({
36217
+ const result = await clack45.select({
36138
36218
  message: "Select phone number type:",
36139
36219
  options: [
36140
36220
  {
@@ -36154,14 +36234,14 @@ async function promptPhoneNumberType() {
36154
36234
  }
36155
36235
  ]
36156
36236
  });
36157
- if (clack44.isCancel(result)) {
36158
- clack44.cancel("Operation cancelled.");
36237
+ if (clack45.isCancel(result)) {
36238
+ clack45.cancel("Operation cancelled.");
36159
36239
  process.exit(0);
36160
36240
  }
36161
36241
  return result;
36162
36242
  }
36163
36243
  async function promptSMSPreset() {
36164
- const result = await clack44.select({
36244
+ const result = await clack45.select({
36165
36245
  message: "Choose configuration preset:",
36166
36246
  options: [
36167
36247
  {
@@ -36186,8 +36266,8 @@ async function promptSMSPreset() {
36186
36266
  }
36187
36267
  ]
36188
36268
  });
36189
- if (clack44.isCancel(result)) {
36190
- clack44.cancel("Operation cancelled.");
36269
+ if (clack45.isCancel(result)) {
36270
+ clack45.cancel("Operation cancelled.");
36191
36271
  process.exit(0);
36192
36272
  }
36193
36273
  return result;
@@ -36207,7 +36287,7 @@ var COMMON_COUNTRIES = [
36207
36287
  { code: "IN", name: "India" }
36208
36288
  ];
36209
36289
  async function promptAllowedCountries() {
36210
- const result = await clack44.multiselect({
36290
+ const result = await clack45.multiselect({
36211
36291
  message: "Select countries to allow SMS delivery (blocks all others):",
36212
36292
  options: COMMON_COUNTRIES.map((c) => ({
36213
36293
  value: c.code,
@@ -36216,14 +36296,14 @@ async function promptAllowedCountries() {
36216
36296
  initialValues: ["US"],
36217
36297
  required: true
36218
36298
  });
36219
- if (clack44.isCancel(result)) {
36220
- clack44.cancel("Operation cancelled.");
36299
+ if (clack45.isCancel(result)) {
36300
+ clack45.cancel("Operation cancelled.");
36221
36301
  process.exit(0);
36222
36302
  }
36223
36303
  return result;
36224
36304
  }
36225
36305
  async function promptEstimatedSMSVolume() {
36226
- const result = await clack44.select({
36306
+ const result = await clack45.select({
36227
36307
  message: "Estimated messages per month:",
36228
36308
  options: [
36229
36309
  { value: 100, label: "< 100 (Testing)" },
@@ -36233,8 +36313,8 @@ async function promptEstimatedSMSVolume() {
36233
36313
  { value: 1e5, label: "50,000+" }
36234
36314
  ]
36235
36315
  });
36236
- if (clack44.isCancel(result)) {
36237
- clack44.cancel("Operation cancelled.");
36316
+ if (clack45.isCancel(result)) {
36317
+ clack45.cancel("Operation cancelled.");
36238
36318
  process.exit(0);
36239
36319
  }
36240
36320
  return result;
@@ -36242,7 +36322,7 @@ async function promptEstimatedSMSVolume() {
36242
36322
  async function init3(options) {
36243
36323
  const startTime = Date.now();
36244
36324
  if (!isJsonMode()) {
36245
- clack44.intro(pc48.bold("Wraps SMS Infrastructure Setup"));
36325
+ clack45.intro(pc48.bold("Wraps SMS Infrastructure Setup"));
36246
36326
  }
36247
36327
  const progress = new DeploymentProgress();
36248
36328
  const wasAutoInstalled = await progress.execute(
@@ -36268,10 +36348,10 @@ async function init3(options) {
36268
36348
  region
36269
36349
  );
36270
36350
  if (existingConnection?.services?.sms) {
36271
- clack44.log.warn(
36351
+ clack45.log.warn(
36272
36352
  `SMS already configured for account ${pc48.cyan(identity.accountId)} in region ${pc48.cyan(region)}`
36273
36353
  );
36274
- clack44.log.info(`Use ${pc48.cyan("wraps sms status")} to view current setup`);
36354
+ clack45.log.info(`Use ${pc48.cyan("wraps sms status")} to view current setup`);
36275
36355
  process.exit(0);
36276
36356
  }
36277
36357
  let preset = options.preset;
@@ -36288,12 +36368,12 @@ async function init3(options) {
36288
36368
  optOutManagement: true,
36289
36369
  sendingEnabled: true
36290
36370
  };
36291
- const enableEventTracking = await clack44.confirm({
36371
+ const enableEventTracking = await clack45.confirm({
36292
36372
  message: "Enable event tracking (EventBridge + DynamoDB)?",
36293
36373
  initialValue: false
36294
36374
  });
36295
- if (clack44.isCancel(enableEventTracking)) {
36296
- clack44.cancel("Operation cancelled.");
36375
+ if (clack45.isCancel(enableEventTracking)) {
36376
+ clack45.cancel("Operation cancelled.");
36297
36377
  process.exit(0);
36298
36378
  }
36299
36379
  if (enableEventTracking) {
@@ -36318,12 +36398,12 @@ ${pc48.bold("Fraud Protection")} - Block SMS to countries where you don't do bus
36318
36398
  const allowedCountries = await promptAllowedCountries();
36319
36399
  let aitFiltering = false;
36320
36400
  if (smsConfig.phoneNumberType !== "simulator") {
36321
- const enableAIT = await clack44.confirm({
36401
+ const enableAIT = await clack45.confirm({
36322
36402
  message: "Enable AIT (Artificially Inflated Traffic) filtering? (adds per-message cost)",
36323
36403
  initialValue: false
36324
36404
  });
36325
- if (clack44.isCancel(enableAIT)) {
36326
- clack44.cancel("Operation cancelled.");
36405
+ if (clack45.isCancel(enableAIT)) {
36406
+ clack45.cancel("Operation cancelled.");
36327
36407
  process.exit(0);
36328
36408
  }
36329
36409
  aitFiltering = enableAIT;
@@ -36337,19 +36417,19 @@ ${pc48.bold("Fraud Protection")} - Block SMS to countries where you don't do bus
36337
36417
  progress.info(`
36338
36418
  ${pc48.bold("Cost Estimate:")}`);
36339
36419
  const costSummary = getSMSCostSummary(smsConfig, estimatedVolume);
36340
- clack44.log.info(costSummary);
36420
+ clack45.log.info(costSummary);
36341
36421
  const warnings = validateSMSConfig(smsConfig);
36342
36422
  if (warnings.length > 0) {
36343
36423
  progress.info(`
36344
36424
  ${pc48.yellow(pc48.bold("Important Notes:"))}`);
36345
36425
  for (const warning of warnings) {
36346
- clack44.log.warn(warning);
36426
+ clack45.log.warn(warning);
36347
36427
  }
36348
36428
  }
36349
36429
  if (!options.yes) {
36350
36430
  const confirmed = await confirmDeploy();
36351
36431
  if (!confirmed) {
36352
- clack44.cancel("Deployment cancelled.");
36432
+ clack45.cancel("Deployment cancelled.");
36353
36433
  process.exit(0);
36354
36434
  }
36355
36435
  }
@@ -36425,8 +36505,8 @@ ${pc48.yellow(pc48.bold("Important Notes:"))}`);
36425
36505
  } catch (sdkError) {
36426
36506
  sdkResourceWarning = true;
36427
36507
  const msg = sdkError instanceof Error ? sdkError.message : String(sdkError);
36428
- clack44.log.warn(`Phone pool creation failed: ${msg}`);
36429
- clack44.log.info(
36508
+ clack45.log.warn(`Phone pool creation failed: ${msg}`);
36509
+ clack45.log.info(
36430
36510
  `Run ${pc48.cyan("wraps sms sync")} to retry SDK resource creation.`
36431
36511
  );
36432
36512
  }
@@ -36443,8 +36523,8 @@ ${pc48.yellow(pc48.bold("Important Notes:"))}`);
36443
36523
  } catch (sdkError) {
36444
36524
  sdkResourceWarning = true;
36445
36525
  const msg = sdkError instanceof Error ? sdkError.message : String(sdkError);
36446
- clack44.log.warn(`Event destination creation failed: ${msg}`);
36447
- clack44.log.info(
36526
+ clack45.log.warn(`Event destination creation failed: ${msg}`);
36527
+ clack45.log.info(
36448
36528
  `Run ${pc48.cyan("wraps sms sync")} to retry SDK resource creation.`
36449
36529
  );
36450
36530
  }
@@ -36464,14 +36544,14 @@ ${pc48.yellow(pc48.bold("Important Notes:"))}`);
36464
36544
  } catch (sdkError) {
36465
36545
  sdkResourceWarning = true;
36466
36546
  const msg = sdkError instanceof Error ? sdkError.message : String(sdkError);
36467
- clack44.log.warn(`Protect configuration creation failed: ${msg}`);
36468
- clack44.log.info(
36547
+ clack45.log.warn(`Protect configuration creation failed: ${msg}`);
36548
+ clack45.log.info(
36469
36549
  `Run ${pc48.cyan("wraps sms sync")} to retry SDK resource creation.`
36470
36550
  );
36471
36551
  }
36472
36552
  }
36473
36553
  if (sdkResourceWarning) {
36474
- clack44.log.warn(
36554
+ clack45.log.warn(
36475
36555
  "Some SDK resources failed to create. Core infrastructure is deployed."
36476
36556
  );
36477
36557
  }
@@ -36516,9 +36596,9 @@ ${pc48.yellow(pc48.bold("Important Notes:"))}`);
36516
36596
  return;
36517
36597
  }
36518
36598
  console.log("\n");
36519
- clack44.log.success(pc48.green(pc48.bold("SMS infrastructure deployed!")));
36599
+ clack45.log.success(pc48.green(pc48.bold("SMS infrastructure deployed!")));
36520
36600
  console.log("\n");
36521
- clack44.note(
36601
+ clack45.note(
36522
36602
  [
36523
36603
  `${pc48.bold("Phone Number:")} ${pc48.cyan(outputs.phoneNumber || "Provisioning...")}`,
36524
36604
  `${pc48.bold("Phone Type:")} ${pc48.cyan(smsConfig.phoneNumberType || "simulator")}`,
@@ -36542,12 +36622,12 @@ ${pc48.yellow(pc48.bold("Important Notes:"))}`);
36542
36622
  );
36543
36623
  nextSteps.push(`${pc48.cyan("wraps sms status")} - View SMS configuration`);
36544
36624
  console.log("\n");
36545
- clack44.log.info(pc48.bold("Next steps:"));
36625
+ clack45.log.info(pc48.bold("Next steps:"));
36546
36626
  for (const step of nextSteps) {
36547
36627
  console.log(` ${step}`);
36548
36628
  }
36549
36629
  console.log("\n");
36550
- clack44.log.info(pc48.bold("SDK Usage:"));
36630
+ clack45.log.info(pc48.bold("SDK Usage:"));
36551
36631
  console.log(pc48.dim(" npm install @wraps.dev/sms"));
36552
36632
  console.log("");
36553
36633
  console.log(pc48.dim(" import { Wraps } from '@wraps.dev/sms';"));
@@ -36556,7 +36636,7 @@ ${pc48.yellow(pc48.bold("Important Notes:"))}`);
36556
36636
  console.log(pc48.dim(" to: '+14155551234',"));
36557
36637
  console.log(pc48.dim(" message: 'Your code is 123456',"));
36558
36638
  console.log(pc48.dim(" });"));
36559
- clack44.outro(pc48.green("Setup complete!"));
36639
+ clack45.outro(pc48.green("Setup complete!"));
36560
36640
  const duration = Date.now() - startTime;
36561
36641
  const enabledFeatures = [];
36562
36642
  if (smsConfig.tracking?.enabled) {
@@ -36592,7 +36672,7 @@ init_aws();
36592
36672
  init_json_output();
36593
36673
  init_metadata();
36594
36674
  init_output();
36595
- import * as clack45 from "@clack/prompts";
36675
+ import * as clack46 from "@clack/prompts";
36596
36676
  import pc49 from "picocolors";
36597
36677
  async function getPhoneNumberDetails(region) {
36598
36678
  const { PinpointSMSVoiceV2Client: PinpointSMSVoiceV2Client5, DescribePhoneNumbersCommand: DescribePhoneNumbersCommand2 } = await import("@aws-sdk/client-pinpoint-sms-voice-v2");
@@ -36613,7 +36693,7 @@ async function getPhoneNumberDetails(region) {
36613
36693
  return null;
36614
36694
  } catch (error) {
36615
36695
  const errorMessage = error instanceof Error ? error.message : String(error);
36616
- clack45.log.error(`Error fetching phone number: ${errorMessage}`);
36696
+ clack46.log.error(`Error fetching phone number: ${errorMessage}`);
36617
36697
  return null;
36618
36698
  }
36619
36699
  }
@@ -36634,7 +36714,7 @@ async function getRegistrationStatus(region, registrationId) {
36634
36714
  async function smsRegister(options) {
36635
36715
  const startTime = Date.now();
36636
36716
  if (!isJsonMode()) {
36637
- clack45.intro(pc49.bold("Wraps SMS - Toll-Free Registration"));
36717
+ clack46.intro(pc49.bold("Wraps SMS - Toll-Free Registration"));
36638
36718
  }
36639
36719
  const progress = new DeploymentProgress();
36640
36720
  const identity = await progress.execute(
@@ -36647,8 +36727,8 @@ async function smsRegister(options) {
36647
36727
  }
36648
36728
  const metadata = await loadConnectionMetadata(identity.accountId, region);
36649
36729
  if (!metadata?.services?.sms) {
36650
- clack45.log.error("No SMS infrastructure found.");
36651
- clack45.log.info(`Run ${pc49.cyan("wraps sms init")} first.`);
36730
+ clack46.log.error("No SMS infrastructure found.");
36731
+ clack46.log.info(`Run ${pc49.cyan("wraps sms init")} first.`);
36652
36732
  process.exit(1);
36653
36733
  }
36654
36734
  const phoneDetails = await progress.execute(
@@ -36656,7 +36736,7 @@ async function smsRegister(options) {
36656
36736
  async () => getPhoneNumberDetails(region)
36657
36737
  );
36658
36738
  if (!phoneDetails) {
36659
- clack45.log.error("No phone number found.");
36739
+ clack46.log.error("No phone number found.");
36660
36740
  process.exit(1);
36661
36741
  }
36662
36742
  let registrationStatus = null;
@@ -36693,18 +36773,18 @@ async function smsRegister(options) {
36693
36773
  }
36694
36774
  console.log("");
36695
36775
  if (phoneDetails.status === "ACTIVE") {
36696
- clack45.log.success("Your phone number is already ACTIVE and ready to use!");
36776
+ clack46.log.success("Your phone number is already ACTIVE and ready to use!");
36697
36777
  const { PinpointSMSVoiceV2Client: PinpointSMSVoiceV2Client5, DescribePoolsCommand } = await import("@aws-sdk/client-pinpoint-sms-voice-v2");
36698
36778
  const client = new PinpointSMSVoiceV2Client5({ region });
36699
36779
  const pools = await client.send(new DescribePoolsCommand({}));
36700
36780
  if (!pools.Pools?.length) {
36701
- clack45.log.info("Run `wraps sms sync` to create the phone pool.");
36781
+ clack46.log.info("Run `wraps sms sync` to create the phone pool.");
36702
36782
  }
36703
36783
  process.exit(0);
36704
36784
  }
36705
36785
  if (phoneDetails.type !== "TOLL_FREE") {
36706
- clack45.log.info("Only toll-free numbers require registration.");
36707
- clack45.log.info(`Your ${phoneDetails.type} number should be ready to use.`);
36786
+ clack46.log.info("Only toll-free numbers require registration.");
36787
+ clack46.log.info(`Your ${phoneDetails.type} number should be ready to use.`);
36708
36788
  process.exit(0);
36709
36789
  }
36710
36790
  console.log(pc49.bold("Toll-Free Registration Required"));
@@ -36723,12 +36803,12 @@ async function smsRegister(options) {
36723
36803
  console.log(` ${pc49.dim("\u2022")} How users opt-in to receive messages`);
36724
36804
  console.log(` ${pc49.dim("\u2022")} Expected monthly message volume`);
36725
36805
  console.log("");
36726
- const openConsole = await clack45.confirm({
36806
+ const openConsole = await clack46.confirm({
36727
36807
  message: "Open AWS Console to start registration?",
36728
36808
  initialValue: true
36729
36809
  });
36730
- if (clack45.isCancel(openConsole)) {
36731
- clack45.cancel("Registration cancelled.");
36810
+ if (clack46.isCancel(openConsole)) {
36811
+ clack46.cancel("Registration cancelled.");
36732
36812
  process.exit(0);
36733
36813
  }
36734
36814
  if (openConsole) {
@@ -36738,13 +36818,13 @@ async function smsRegister(options) {
36738
36818
  const execAsync2 = promisify2(exec2);
36739
36819
  try {
36740
36820
  await execAsync2(`open "${consoleUrl}"`);
36741
- clack45.log.success("Opened AWS Console in your browser.");
36821
+ clack46.log.success("Opened AWS Console in your browser.");
36742
36822
  } catch {
36743
36823
  try {
36744
36824
  await execAsync2(`xdg-open "${consoleUrl}"`);
36745
- clack45.log.success("Opened AWS Console in your browser.");
36825
+ clack46.log.success("Opened AWS Console in your browser.");
36746
36826
  } catch {
36747
- clack45.log.info("Open this URL in your browser:");
36827
+ clack46.log.info("Open this URL in your browser:");
36748
36828
  console.log(`
36749
36829
  ${pc49.cyan(consoleUrl)}
36750
36830
  `);
@@ -36772,7 +36852,7 @@ async function smsRegister(options) {
36772
36852
  success: true,
36773
36853
  duration_ms: Date.now() - startTime
36774
36854
  });
36775
- clack45.outro(pc49.dim("Good luck with your registration!"));
36855
+ clack46.outro(pc49.dim("Good luck with your registration!"));
36776
36856
  }
36777
36857
 
36778
36858
  // src/commands/sms/status.ts
@@ -36784,7 +36864,8 @@ init_json_output();
36784
36864
  init_metadata();
36785
36865
  init_output();
36786
36866
  init_pulumi();
36787
- import * as clack46 from "@clack/prompts";
36867
+ init_region_resolver();
36868
+ import * as clack47 from "@clack/prompts";
36788
36869
  import * as pulumi30 from "@pulumi/pulumi";
36789
36870
  import pc50 from "picocolors";
36790
36871
  function displaySMSStatus(options) {
@@ -36824,24 +36905,29 @@ function displaySMSStatus(options) {
36824
36905
  lines.push(pc50.bold("IAM Role"));
36825
36906
  lines.push(` ${pc50.dim(options.roleArn)}`);
36826
36907
  }
36827
- clack46.note(lines.join("\n"), "SMS Status");
36908
+ clack47.note(lines.join("\n"), "SMS Status");
36828
36909
  }
36829
- async function smsStatus(_options) {
36910
+ async function smsStatus(options) {
36830
36911
  await ensurePulumiInstalled();
36831
36912
  const startTime = Date.now();
36832
36913
  const progress = new DeploymentProgress();
36833
36914
  if (!isJsonMode()) {
36834
- clack46.intro(pc50.bold("Wraps SMS Status"));
36915
+ clack47.intro(pc50.bold("Wraps SMS Status"));
36835
36916
  }
36836
36917
  const identity = await progress.execute(
36837
36918
  "Loading SMS infrastructure status",
36838
36919
  async () => validateAWSCredentials()
36839
36920
  );
36840
- const region = await getAWSRegion();
36921
+ const region = await resolveRegionForCommand({
36922
+ accountId: identity.accountId,
36923
+ optionRegion: options.region,
36924
+ service: "sms",
36925
+ label: "SMS deployment"
36926
+ });
36841
36927
  const metadata = await loadConnectionMetadata(identity.accountId, region);
36842
36928
  if (!metadata?.services?.sms) {
36843
36929
  progress.stop();
36844
- clack46.log.error("No SMS infrastructure found");
36930
+ clack47.log.error("No SMS infrastructure found");
36845
36931
  console.log(
36846
36932
  `
36847
36933
  Run ${pc50.cyan("wraps sms init")} to deploy SMS infrastructure.
@@ -36880,7 +36966,7 @@ Run ${pc50.cyan("wraps sms init")} to deploy SMS infrastructure.
36880
36966
  }
36881
36967
  displaySMSStatus(smsStatusData);
36882
36968
  console.log("");
36883
- clack46.log.info(pc50.bold("Commands:"));
36969
+ clack47.log.info(pc50.bold("Commands:"));
36884
36970
  console.log(
36885
36971
  ` ${pc50.cyan("wraps sms test --to +1234567890")} - Send a test message`
36886
36972
  );
@@ -36891,12 +36977,12 @@ Run ${pc50.cyan("wraps sms init")} to deploy SMS infrastructure.
36891
36977
  event_tracking: smsConfig?.eventTracking?.enabled,
36892
36978
  duration_ms: Date.now() - startTime
36893
36979
  });
36894
- clack46.outro(pc50.dim("SMS infrastructure is ready"));
36980
+ clack47.outro(pc50.dim("SMS infrastructure is ready"));
36895
36981
  }
36896
36982
 
36897
36983
  // src/commands/sms/sync.ts
36898
36984
  init_esm_shims();
36899
- import * as clack47 from "@clack/prompts";
36985
+ import * as clack48 from "@clack/prompts";
36900
36986
  import * as pulumi31 from "@pulumi/pulumi";
36901
36987
  import pc51 from "picocolors";
36902
36988
  init_events();
@@ -36911,7 +36997,7 @@ async function smsSync(options) {
36911
36997
  await ensurePulumiInstalled();
36912
36998
  const startTime = Date.now();
36913
36999
  if (!isJsonMode()) {
36914
- clack47.intro(pc51.bold("Wraps SMS Infrastructure Sync"));
37000
+ clack48.intro(pc51.bold("Wraps SMS Infrastructure Sync"));
36915
37001
  }
36916
37002
  const progress = new DeploymentProgress();
36917
37003
  const identity = await progress.execute(
@@ -36923,7 +37009,7 @@ async function smsSync(options) {
36923
37009
  const smsService = metadata?.services?.sms;
36924
37010
  if (!smsService?.config) {
36925
37011
  progress.stop();
36926
- clack47.log.error("No SMS infrastructure found to sync");
37012
+ clack48.log.error("No SMS infrastructure found to sync");
36927
37013
  console.log(
36928
37014
  `
36929
37015
  Run ${pc51.cyan("wraps sms init")} to deploy SMS infrastructure first.
@@ -36941,12 +37027,12 @@ Run ${pc51.cyan("wraps sms init")} to deploy SMS infrastructure first.
36941
37027
  `Event tracking: ${pc51.cyan(smsConfig.eventTracking?.enabled ? "enabled" : "disabled")}`
36942
37028
  );
36943
37029
  if (!options.yes) {
36944
- const confirmed = await clack47.confirm({
37030
+ const confirmed = await clack48.confirm({
36945
37031
  message: "Sync SMS infrastructure? This will update Lambda code and recreate any missing resources.",
36946
37032
  initialValue: true
36947
37033
  });
36948
- if (clack47.isCancel(confirmed) || !confirmed) {
36949
- clack47.cancel("Sync cancelled.");
37034
+ if (clack48.isCancel(confirmed) || !confirmed) {
37035
+ clack48.cancel("Sync cancelled.");
36950
37036
  process.exit(0);
36951
37037
  }
36952
37038
  }
@@ -37051,7 +37137,7 @@ Run ${pc51.cyan("wraps sms init")} to deploy SMS infrastructure first.
37051
37137
  throw errors.stackLocked();
37052
37138
  }
37053
37139
  trackError("SYNC_FAILED", "sms:sync", { step: "sync" });
37054
- clack47.log.error(`SMS sync failed: ${errorMessage}`);
37140
+ clack48.log.error(`SMS sync failed: ${errorMessage}`);
37055
37141
  process.exit(1);
37056
37142
  }
37057
37143
  if (metadata && smsService) {
@@ -37071,7 +37157,7 @@ Run ${pc51.cyan("wraps sms init")} to deploy SMS infrastructure first.
37071
37157
  return;
37072
37158
  }
37073
37159
  console.log("\n");
37074
- clack47.log.success(pc51.green("SMS infrastructure synced successfully!"));
37160
+ clack48.log.success(pc51.green("SMS infrastructure synced successfully!"));
37075
37161
  const changes = [];
37076
37162
  if (outputs.lambdaFunctions?.length) {
37077
37163
  changes.push("Lambda functions updated");
@@ -37085,7 +37171,7 @@ Run ${pc51.cyan("wraps sms init")} to deploy SMS infrastructure first.
37085
37171
  success: true,
37086
37172
  duration_ms: Date.now() - startTime
37087
37173
  });
37088
- clack47.outro(pc51.green("Sync complete!"));
37174
+ clack48.outro(pc51.green("Sync complete!"));
37089
37175
  }
37090
37176
 
37091
37177
  // src/commands/sms/test.ts
@@ -37100,7 +37186,7 @@ import {
37100
37186
  PinpointSMSVoiceV2Client as PinpointSMSVoiceV2Client3,
37101
37187
  SendTextMessageCommand
37102
37188
  } from "@aws-sdk/client-pinpoint-sms-voice-v2";
37103
- import * as clack48 from "@clack/prompts";
37189
+ import * as clack49 from "@clack/prompts";
37104
37190
  import pc52 from "picocolors";
37105
37191
 
37106
37192
  // src/utils/sms/validation.ts
@@ -37124,7 +37210,7 @@ async function smsTest(options) {
37124
37210
  const startTime = Date.now();
37125
37211
  const progress = new DeploymentProgress();
37126
37212
  if (!isJsonMode()) {
37127
- clack48.intro(pc52.bold("Wraps SMS Test"));
37213
+ clack49.intro(pc52.bold("Wraps SMS Test"));
37128
37214
  }
37129
37215
  const identity = await progress.execute(
37130
37216
  "Validating AWS credentials",
@@ -37134,7 +37220,7 @@ async function smsTest(options) {
37134
37220
  const metadata = await loadConnectionMetadata(identity.accountId, region);
37135
37221
  if (!metadata?.services?.sms) {
37136
37222
  progress.stop();
37137
- clack48.log.error("No SMS infrastructure found");
37223
+ clack49.log.error("No SMS infrastructure found");
37138
37224
  console.log(
37139
37225
  `
37140
37226
  Run ${pc52.cyan("wraps sms init")} to deploy SMS infrastructure.
@@ -37151,7 +37237,7 @@ Run ${pc52.cyan("wraps sms init")} to deploy SMS infrastructure.
37151
37237
  );
37152
37238
  }
37153
37239
  if (!toNumber) {
37154
- const destinationType = await clack48.select({
37240
+ const destinationType = await clack49.select({
37155
37241
  message: "Choose destination number:",
37156
37242
  options: [
37157
37243
  {
@@ -37166,25 +37252,25 @@ Run ${pc52.cyan("wraps sms init")} to deploy SMS infrastructure.
37166
37252
  }
37167
37253
  ]
37168
37254
  });
37169
- if (clack48.isCancel(destinationType)) {
37170
- clack48.cancel("Operation cancelled.");
37255
+ if (clack49.isCancel(destinationType)) {
37256
+ clack49.cancel("Operation cancelled.");
37171
37257
  process.exit(0);
37172
37258
  }
37173
37259
  if (destinationType === "simulator") {
37174
- const simResult = await clack48.select({
37260
+ const simResult = await clack49.select({
37175
37261
  message: "Select simulator destination:",
37176
37262
  options: SIMULATOR_DESTINATIONS.map((sim) => ({
37177
37263
  value: sim.number,
37178
37264
  label: `${sim.number} | ${sim.country}`
37179
37265
  }))
37180
37266
  });
37181
- if (clack48.isCancel(simResult)) {
37182
- clack48.cancel("Operation cancelled.");
37267
+ if (clack49.isCancel(simResult)) {
37268
+ clack49.cancel("Operation cancelled.");
37183
37269
  process.exit(0);
37184
37270
  }
37185
37271
  toNumber = simResult;
37186
37272
  } else {
37187
- const result = await clack48.text({
37273
+ const result = await clack49.text({
37188
37274
  message: "Enter destination phone number (E.164 format):",
37189
37275
  placeholder: "+14155551234",
37190
37276
  validate: (value) => {
@@ -37197,22 +37283,22 @@ Run ${pc52.cyan("wraps sms init")} to deploy SMS infrastructure.
37197
37283
  return;
37198
37284
  }
37199
37285
  });
37200
- if (clack48.isCancel(result)) {
37201
- clack48.cancel("Operation cancelled.");
37286
+ if (clack49.isCancel(result)) {
37287
+ clack49.cancel("Operation cancelled.");
37202
37288
  process.exit(0);
37203
37289
  }
37204
37290
  toNumber = result;
37205
37291
  }
37206
37292
  } else if (!isValidPhoneNumber(toNumber)) {
37207
37293
  progress.stop();
37208
- clack48.log.error(
37294
+ clack49.log.error(
37209
37295
  `Invalid phone number format: ${toNumber}. Use E.164 format (e.g., +14155551234)`
37210
37296
  );
37211
37297
  process.exit(1);
37212
37298
  }
37213
37299
  let message = options.message;
37214
37300
  if (!message) {
37215
- const result = await clack48.text({
37301
+ const result = await clack49.text({
37216
37302
  message: "Enter test message:",
37217
37303
  placeholder: "Hello from Wraps SMS!",
37218
37304
  defaultValue: "Hello from Wraps SMS! This is a test message.",
@@ -37226,8 +37312,8 @@ Run ${pc52.cyan("wraps sms init")} to deploy SMS infrastructure.
37226
37312
  return;
37227
37313
  }
37228
37314
  });
37229
- if (clack48.isCancel(result)) {
37230
- clack48.cancel("Operation cancelled.");
37315
+ if (clack49.isCancel(result)) {
37316
+ clack49.cancel("Operation cancelled.");
37231
37317
  process.exit(0);
37232
37318
  }
37233
37319
  message = result;
@@ -37266,9 +37352,9 @@ Run ${pc52.cyan("wraps sms init")} to deploy SMS infrastructure.
37266
37352
  return;
37267
37353
  }
37268
37354
  console.log("\n");
37269
- clack48.log.success(pc52.green("Test SMS sent successfully!"));
37355
+ clack49.log.success(pc52.green("Test SMS sent successfully!"));
37270
37356
  console.log("");
37271
- clack48.note(
37357
+ clack49.note(
37272
37358
  [
37273
37359
  `${pc52.bold("Message ID:")} ${pc52.cyan(messageId || "unknown")}`,
37274
37360
  `${pc52.bold("To:")} ${pc52.cyan(toNumber)}`,
@@ -37283,11 +37369,11 @@ Run ${pc52.cyan("wraps sms init")} to deploy SMS infrastructure.
37283
37369
  );
37284
37370
  if (smsConfig?.eventTracking?.enabled) {
37285
37371
  console.log("");
37286
- clack48.log.info(
37372
+ clack49.log.info(
37287
37373
  pc52.dim("Event tracking is enabled. Check DynamoDB for delivery status.")
37288
37374
  );
37289
37375
  }
37290
- clack48.outro(pc52.green("Test complete!"));
37376
+ clack49.outro(pc52.green("Test complete!"));
37291
37377
  } catch (error) {
37292
37378
  progress.stop();
37293
37379
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -37299,24 +37385,24 @@ Run ${pc52.cyan("wraps sms init")} to deploy SMS infrastructure.
37299
37385
  });
37300
37386
  const errorName = error instanceof Error ? error.name : "";
37301
37387
  if (errorName === "ConflictException" || errorMessage.includes("opt-out")) {
37302
- clack48.log.error("Destination number has opted out of messages");
37388
+ clack49.log.error("Destination number has opted out of messages");
37303
37389
  console.log("\nThe recipient has opted out of receiving SMS messages.\n");
37304
37390
  } else if (errorName === "ThrottlingException" || errorMessage.includes("spending limit")) {
37305
- clack48.log.error("SMS rate or spending limit reached");
37391
+ clack49.log.error("SMS rate or spending limit reached");
37306
37392
  console.log(
37307
37393
  "\nCheck your AWS account SMS spending limits in the console.\n"
37308
37394
  );
37309
37395
  } else if (errorName === "ValidationException") {
37310
- clack48.log.error(`Invalid request: ${errorMessage}`);
37396
+ clack49.log.error(`Invalid request: ${errorMessage}`);
37311
37397
  } else if (errorMessage.includes("not verified") || errorMessage.includes("not registered")) {
37312
- clack48.log.error("Toll-free number registration is not complete");
37398
+ clack49.log.error("Toll-free number registration is not complete");
37313
37399
  console.log(
37314
37400
  `
37315
37401
  Run ${pc52.cyan("wraps sms register")} to check registration status.
37316
37402
  `
37317
37403
  );
37318
37404
  } else if (errorName === "AccessDeniedException") {
37319
- clack48.log.error(
37405
+ clack49.log.error(
37320
37406
  "Permission denied \u2014 IAM role may be missing SMS send permissions"
37321
37407
  );
37322
37408
  console.log(
@@ -37325,7 +37411,7 @@ Run ${pc52.cyan("wraps sms upgrade")} to update IAM policies.
37325
37411
  `
37326
37412
  );
37327
37413
  } else {
37328
- clack48.log.error(`Failed to send SMS: ${errorMessage}`);
37414
+ clack49.log.error(`Failed to send SMS: ${errorMessage}`);
37329
37415
  }
37330
37416
  process.exit(1);
37331
37417
  }
@@ -37333,7 +37419,7 @@ Run ${pc52.cyan("wraps sms upgrade")} to update IAM policies.
37333
37419
 
37334
37420
  // src/commands/sms/upgrade.ts
37335
37421
  init_esm_shims();
37336
- import * as clack49 from "@clack/prompts";
37422
+ import * as clack50 from "@clack/prompts";
37337
37423
  import * as pulumi32 from "@pulumi/pulumi";
37338
37424
  import pc53 from "picocolors";
37339
37425
  init_events();
@@ -37345,11 +37431,12 @@ init_metadata();
37345
37431
  init_output();
37346
37432
  init_prompts();
37347
37433
  init_pulumi();
37434
+ init_region_resolver();
37348
37435
  async function smsUpgrade(options) {
37349
37436
  const startTime = Date.now();
37350
37437
  let upgradeAction = "";
37351
37438
  if (!isJsonMode()) {
37352
- clack49.intro(pc53.bold("Wraps SMS Upgrade - Enhance Your SMS Infrastructure"));
37439
+ clack50.intro(pc53.bold("Wraps SMS Upgrade - Enhance Your SMS Infrastructure"));
37353
37440
  }
37354
37441
  const progress = new DeploymentProgress();
37355
37442
  const wasAutoInstalled = await progress.execute(
@@ -37364,24 +37451,25 @@ async function smsUpgrade(options) {
37364
37451
  async () => validateAWSCredentials()
37365
37452
  );
37366
37453
  progress.info(`Connected to AWS account: ${pc53.cyan(identity.accountId)}`);
37367
- let region = options.region;
37368
- if (!region) {
37369
- const defaultRegion = await getAWSRegion();
37370
- region = defaultRegion;
37371
- }
37454
+ const region = await resolveRegionForCommand({
37455
+ accountId: identity.accountId,
37456
+ optionRegion: options.region,
37457
+ service: "sms",
37458
+ label: "SMS deployment"
37459
+ });
37372
37460
  const metadata = await loadConnectionMetadata(identity.accountId, region);
37373
37461
  if (!metadata) {
37374
- clack49.log.error(
37462
+ clack50.log.error(
37375
37463
  `No Wraps connection found for account ${pc53.cyan(identity.accountId)} in region ${pc53.cyan(region)}`
37376
37464
  );
37377
- clack49.log.info(
37465
+ clack50.log.info(
37378
37466
  `Use ${pc53.cyan("wraps sms init")} to create new infrastructure.`
37379
37467
  );
37380
37468
  process.exit(1);
37381
37469
  }
37382
37470
  if (!metadata.services.sms) {
37383
- clack49.log.error("No SMS infrastructure found");
37384
- clack49.log.info(
37471
+ clack50.log.error("No SMS infrastructure found");
37472
+ clack50.log.info(
37385
37473
  `Use ${pc53.cyan("wraps sms init")} to deploy SMS infrastructure.`
37386
37474
  );
37387
37475
  process.exit(1);
@@ -37397,8 +37485,8 @@ ${pc53.bold("Current Configuration:")}
37397
37485
  }
37398
37486
  const config2 = metadata.services.sms.config;
37399
37487
  if (!config2) {
37400
- clack49.log.error("No SMS configuration found in metadata");
37401
- clack49.log.info(
37488
+ clack50.log.error("No SMS configuration found in metadata");
37489
+ clack50.log.info(
37402
37490
  `Use ${pc53.cyan("wraps sms init")} to create new infrastructure.`
37403
37491
  );
37404
37492
  process.exit(1);
@@ -37458,7 +37546,7 @@ ${pc53.bold("Current Configuration:")}
37458
37546
  "10dlc": "10DLC",
37459
37547
  "short-code": "Short code"
37460
37548
  };
37461
- upgradeAction = await clack49.select({
37549
+ upgradeAction = await clack50.select({
37462
37550
  message: "What would you like to do?",
37463
37551
  options: [
37464
37552
  {
@@ -37498,8 +37586,8 @@ ${pc53.bold("Current Configuration:")}
37498
37586
  }
37499
37587
  ]
37500
37588
  });
37501
- if (clack49.isCancel(upgradeAction)) {
37502
- clack49.cancel("Upgrade cancelled.");
37589
+ if (clack50.isCancel(upgradeAction)) {
37590
+ clack50.cancel("Upgrade cancelled.");
37503
37591
  process.exit(0);
37504
37592
  }
37505
37593
  let updatedConfig = { ...config2 };
@@ -37540,17 +37628,17 @@ ${pc53.bold("Current Configuration:")}
37540
37628
  hint: p.hint
37541
37629
  }));
37542
37630
  if (availableTypes.length === 0) {
37543
- clack49.log.warn(
37631
+ clack50.log.warn(
37544
37632
  "Already on highest phone number tier. Contact AWS for dedicated short codes."
37545
37633
  );
37546
37634
  process.exit(0);
37547
37635
  }
37548
- const selectedType = await clack49.select({
37636
+ const selectedType = await clack50.select({
37549
37637
  message: "Select new phone number type:",
37550
37638
  options: availableTypes
37551
37639
  });
37552
- if (clack49.isCancel(selectedType)) {
37553
- clack49.cancel("Upgrade cancelled.");
37640
+ if (clack50.isCancel(selectedType)) {
37641
+ clack50.cancel("Upgrade cancelled.");
37554
37642
  process.exit(0);
37555
37643
  }
37556
37644
  if (selectedType === "toll-free") {
@@ -37573,12 +37661,12 @@ ${pc53.yellow("\u26A0")} ${pc53.bold("Toll-free Registration Required")}
37573
37661
  console.log(
37574
37662
  pc53.dim("\nUntil verified, sending is limited to low volume.\n")
37575
37663
  );
37576
- const confirmTollFree = await clack49.confirm({
37664
+ const confirmTollFree = await clack50.confirm({
37577
37665
  message: "Continue with toll-free number request?",
37578
37666
  initialValue: true
37579
37667
  });
37580
- if (clack49.isCancel(confirmTollFree) || !confirmTollFree) {
37581
- clack49.cancel("Upgrade cancelled.");
37668
+ if (clack50.isCancel(confirmTollFree) || !confirmTollFree) {
37669
+ clack50.cancel("Upgrade cancelled.");
37582
37670
  process.exit(0);
37583
37671
  }
37584
37672
  }
@@ -37593,12 +37681,12 @@ ${pc53.yellow("\u26A0")} ${pc53.bold("10DLC Campaign Registration Required")}
37593
37681
  console.log(" \u2022 Campaign registration: $15/mo per campaign");
37594
37682
  console.log(" \u2022 Verification takes 1-7 business days");
37595
37683
  console.log("");
37596
- const confirm10DLC = await clack49.confirm({
37684
+ const confirm10DLC = await clack50.confirm({
37597
37685
  message: "Continue with 10DLC number request?",
37598
37686
  initialValue: true
37599
37687
  });
37600
- if (clack49.isCancel(confirm10DLC) || !confirm10DLC) {
37601
- clack49.cancel("Upgrade cancelled.");
37688
+ if (clack50.isCancel(confirm10DLC) || !confirm10DLC) {
37689
+ clack50.cancel("Upgrade cancelled.");
37602
37690
  process.exit(0);
37603
37691
  }
37604
37692
  }
@@ -37623,15 +37711,15 @@ ${pc53.yellow("\u26A0")} ${pc53.bold("10DLC Campaign Registration Required")}
37623
37711
  disabled: currentPresetIdx >= 0 && idx <= currentPresetIdx ? "Current or lower tier" : void 0
37624
37712
  })).filter((p) => !p.disabled && p.value !== "custom");
37625
37713
  if (availablePresets.length === 0) {
37626
- clack49.log.warn("Already on highest preset (Enterprise)");
37714
+ clack50.log.warn("Already on highest preset (Enterprise)");
37627
37715
  process.exit(0);
37628
37716
  }
37629
- const selectedPreset = await clack49.select({
37717
+ const selectedPreset = await clack50.select({
37630
37718
  message: "Select new preset:",
37631
37719
  options: availablePresets
37632
37720
  });
37633
- if (clack49.isCancel(selectedPreset)) {
37634
- clack49.cancel("Upgrade cancelled.");
37721
+ if (clack50.isCancel(selectedPreset)) {
37722
+ clack50.cancel("Upgrade cancelled.");
37635
37723
  process.exit(0);
37636
37724
  }
37637
37725
  const presetConfig = getSMSPreset(selectedPreset);
@@ -37647,7 +37735,7 @@ ${pc53.yellow("\u26A0")} ${pc53.bold("10DLC Campaign Registration Required")}
37647
37735
  }
37648
37736
  case "event-tracking": {
37649
37737
  if (config2.eventTracking?.enabled) {
37650
- const eventAction = await clack49.select({
37738
+ const eventAction = await clack50.select({
37651
37739
  message: "What would you like to do with event tracking?",
37652
37740
  options: [
37653
37741
  {
@@ -37662,17 +37750,17 @@ ${pc53.yellow("\u26A0")} ${pc53.bold("10DLC Campaign Registration Required")}
37662
37750
  }
37663
37751
  ]
37664
37752
  });
37665
- if (clack49.isCancel(eventAction)) {
37666
- clack49.cancel("Upgrade cancelled.");
37753
+ if (clack50.isCancel(eventAction)) {
37754
+ clack50.cancel("Upgrade cancelled.");
37667
37755
  process.exit(0);
37668
37756
  }
37669
37757
  if (eventAction === "disable") {
37670
- const confirmDisable = await clack49.confirm({
37758
+ const confirmDisable = await clack50.confirm({
37671
37759
  message: "Are you sure? Existing history will remain, but new events won't be tracked.",
37672
37760
  initialValue: false
37673
37761
  });
37674
- if (clack49.isCancel(confirmDisable) || !confirmDisable) {
37675
- clack49.cancel("Event tracking not disabled.");
37762
+ if (clack50.isCancel(confirmDisable) || !confirmDisable) {
37763
+ clack50.cancel("Event tracking not disabled.");
37676
37764
  process.exit(0);
37677
37765
  }
37678
37766
  updatedConfig = {
@@ -37682,7 +37770,7 @@ ${pc53.yellow("\u26A0")} ${pc53.bold("10DLC Campaign Registration Required")}
37682
37770
  }
37683
37771
  };
37684
37772
  } else {
37685
- const retention = await clack49.select({
37773
+ const retention = await clack50.select({
37686
37774
  message: "Message history retention period:",
37687
37775
  options: [
37688
37776
  { value: "7days", label: "7 days", hint: "Minimal storage cost" },
@@ -37709,8 +37797,8 @@ ${pc53.yellow("\u26A0")} ${pc53.bold("10DLC Campaign Registration Required")}
37709
37797
  ],
37710
37798
  initialValue: config2.eventTracking.archiveRetention || "90days"
37711
37799
  });
37712
- if (clack49.isCancel(retention)) {
37713
- clack49.cancel("Upgrade cancelled.");
37800
+ if (clack50.isCancel(retention)) {
37801
+ clack50.cancel("Upgrade cancelled.");
37714
37802
  process.exit(0);
37715
37803
  }
37716
37804
  updatedConfig = {
@@ -37722,19 +37810,19 @@ ${pc53.yellow("\u26A0")} ${pc53.bold("10DLC Campaign Registration Required")}
37722
37810
  };
37723
37811
  }
37724
37812
  } else {
37725
- const enableTracking = await clack49.confirm({
37813
+ const enableTracking = await clack50.confirm({
37726
37814
  message: "Enable event tracking? (Track SMS events with history)",
37727
37815
  initialValue: true
37728
37816
  });
37729
- if (clack49.isCancel(enableTracking)) {
37730
- clack49.cancel("Upgrade cancelled.");
37817
+ if (clack50.isCancel(enableTracking)) {
37818
+ clack50.cancel("Upgrade cancelled.");
37731
37819
  process.exit(0);
37732
37820
  }
37733
37821
  if (!enableTracking) {
37734
- clack49.log.info("Event tracking not enabled.");
37822
+ clack50.log.info("Event tracking not enabled.");
37735
37823
  process.exit(0);
37736
37824
  }
37737
- const retention = await clack49.select({
37825
+ const retention = await clack50.select({
37738
37826
  message: "Message history retention period:",
37739
37827
  options: [
37740
37828
  { value: "7days", label: "7 days", hint: "Minimal storage cost" },
@@ -37757,8 +37845,8 @@ ${pc53.yellow("\u26A0")} ${pc53.bold("10DLC Campaign Registration Required")}
37757
37845
  ],
37758
37846
  initialValue: "90days"
37759
37847
  });
37760
- if (clack49.isCancel(retention)) {
37761
- clack49.cancel("Upgrade cancelled.");
37848
+ if (clack50.isCancel(retention)) {
37849
+ clack50.cancel("Upgrade cancelled.");
37762
37850
  process.exit(0);
37763
37851
  }
37764
37852
  updatedConfig = {
@@ -37777,12 +37865,12 @@ ${pc53.yellow("\u26A0")} ${pc53.bold("10DLC Campaign Registration Required")}
37777
37865
  }
37778
37866
  case "retention": {
37779
37867
  if (!config2.eventTracking?.enabled) {
37780
- clack49.log.error(
37868
+ clack50.log.error(
37781
37869
  "Event tracking is not enabled. Enable it first to change retention."
37782
37870
  );
37783
37871
  process.exit(1);
37784
37872
  }
37785
- const retention = await clack49.select({
37873
+ const retention = await clack50.select({
37786
37874
  message: "Message history retention period (event data in DynamoDB):",
37787
37875
  options: [
37788
37876
  { value: "7days", label: "7 days", hint: "Minimal storage cost" },
@@ -37801,8 +37889,8 @@ ${pc53.yellow("\u26A0")} ${pc53.bold("10DLC Campaign Registration Required")}
37801
37889
  ],
37802
37890
  initialValue: config2.eventTracking.archiveRetention || "90days"
37803
37891
  });
37804
- if (clack49.isCancel(retention)) {
37805
- clack49.cancel("Upgrade cancelled.");
37892
+ if (clack50.isCancel(retention)) {
37893
+ clack50.cancel("Upgrade cancelled.");
37806
37894
  process.exit(0);
37807
37895
  }
37808
37896
  updatedConfig = {
@@ -37820,21 +37908,21 @@ ${pc53.yellow("\u26A0")} ${pc53.bold("10DLC Campaign Registration Required")}
37820
37908
  case "link-tracking": {
37821
37909
  const enableLinkTracking = !config2.tracking?.linkTracking;
37822
37910
  if (enableLinkTracking) {
37823
- clack49.log.info(
37911
+ clack50.log.info(
37824
37912
  pc53.dim(
37825
37913
  "Link tracking will track clicks on URLs in your SMS messages."
37826
37914
  )
37827
37915
  );
37828
- clack49.log.info(
37916
+ clack50.log.info(
37829
37917
  pc53.dim("URLs will be rewritten to go through a tracking endpoint.")
37830
37918
  );
37831
37919
  }
37832
- const confirmed = await clack49.confirm({
37920
+ const confirmed = await clack50.confirm({
37833
37921
  message: enableLinkTracking ? "Enable link click tracking?" : "Disable link click tracking?",
37834
37922
  initialValue: enableLinkTracking
37835
37923
  });
37836
- if (clack49.isCancel(confirmed) || !confirmed) {
37837
- clack49.cancel("Upgrade cancelled.");
37924
+ if (clack50.isCancel(confirmed) || !confirmed) {
37925
+ clack50.cancel("Upgrade cancelled.");
37838
37926
  process.exit(0);
37839
37927
  }
37840
37928
  updatedConfig = {
@@ -37851,7 +37939,7 @@ ${pc53.yellow("\u26A0")} ${pc53.bold("10DLC Campaign Registration Required")}
37851
37939
  }
37852
37940
  case "archiving": {
37853
37941
  if (config2.messageArchiving?.enabled) {
37854
- const archivingAction = await clack49.select({
37942
+ const archivingAction = await clack50.select({
37855
37943
  message: "What would you like to do with message archiving?",
37856
37944
  options: [
37857
37945
  {
@@ -37866,17 +37954,17 @@ ${pc53.yellow("\u26A0")} ${pc53.bold("10DLC Campaign Registration Required")}
37866
37954
  }
37867
37955
  ]
37868
37956
  });
37869
- if (clack49.isCancel(archivingAction)) {
37870
- clack49.cancel("Upgrade cancelled.");
37957
+ if (clack50.isCancel(archivingAction)) {
37958
+ clack50.cancel("Upgrade cancelled.");
37871
37959
  process.exit(0);
37872
37960
  }
37873
37961
  if (archivingAction === "disable") {
37874
- const confirmDisable = await clack49.confirm({
37962
+ const confirmDisable = await clack50.confirm({
37875
37963
  message: "Are you sure? Existing archived messages will remain, but new messages won't be archived.",
37876
37964
  initialValue: false
37877
37965
  });
37878
- if (clack49.isCancel(confirmDisable) || !confirmDisable) {
37879
- clack49.cancel("Archiving not disabled.");
37966
+ if (clack50.isCancel(confirmDisable) || !confirmDisable) {
37967
+ clack50.cancel("Archiving not disabled.");
37880
37968
  process.exit(0);
37881
37969
  }
37882
37970
  updatedConfig = {
@@ -37887,7 +37975,7 @@ ${pc53.yellow("\u26A0")} ${pc53.bold("10DLC Campaign Registration Required")}
37887
37975
  }
37888
37976
  };
37889
37977
  } else {
37890
- const retention = await clack49.select({
37978
+ const retention = await clack50.select({
37891
37979
  message: "Message archive retention period:",
37892
37980
  options: [
37893
37981
  {
@@ -37918,8 +38006,8 @@ ${pc53.yellow("\u26A0")} ${pc53.bold("10DLC Campaign Registration Required")}
37918
38006
  ],
37919
38007
  initialValue: config2.messageArchiving.retention
37920
38008
  });
37921
- if (clack49.isCancel(retention)) {
37922
- clack49.cancel("Upgrade cancelled.");
38009
+ if (clack50.isCancel(retention)) {
38010
+ clack50.cancel("Upgrade cancelled.");
37923
38011
  process.exit(0);
37924
38012
  }
37925
38013
  updatedConfig = {
@@ -37931,19 +38019,19 @@ ${pc53.yellow("\u26A0")} ${pc53.bold("10DLC Campaign Registration Required")}
37931
38019
  };
37932
38020
  }
37933
38021
  } else {
37934
- const enableArchiving = await clack49.confirm({
38022
+ const enableArchiving = await clack50.confirm({
37935
38023
  message: "Enable message archiving? (Store full message content for viewing)",
37936
38024
  initialValue: true
37937
38025
  });
37938
- if (clack49.isCancel(enableArchiving)) {
37939
- clack49.cancel("Upgrade cancelled.");
38026
+ if (clack50.isCancel(enableArchiving)) {
38027
+ clack50.cancel("Upgrade cancelled.");
37940
38028
  process.exit(0);
37941
38029
  }
37942
38030
  if (!enableArchiving) {
37943
- clack49.log.info("Message archiving not enabled.");
38031
+ clack50.log.info("Message archiving not enabled.");
37944
38032
  process.exit(0);
37945
38033
  }
37946
- const retention = await clack49.select({
38034
+ const retention = await clack50.select({
37947
38035
  message: "Message archive retention period:",
37948
38036
  options: [
37949
38037
  { value: "7days", label: "7 days", hint: "~$1-2/mo for 10k msgs" },
@@ -37970,8 +38058,8 @@ ${pc53.yellow("\u26A0")} ${pc53.bold("10DLC Campaign Registration Required")}
37970
38058
  ],
37971
38059
  initialValue: "90days"
37972
38060
  });
37973
- if (clack49.isCancel(retention)) {
37974
- clack49.cancel("Upgrade cancelled.");
38061
+ if (clack50.isCancel(retention)) {
38062
+ clack50.cancel("Upgrade cancelled.");
37975
38063
  process.exit(0);
37976
38064
  }
37977
38065
  updatedConfig = {
@@ -38003,7 +38091,7 @@ ${pc53.yellow("\u26A0")} ${pc53.bold("10DLC Campaign Registration Required")}
38003
38091
  const currentAllowed = config2.protectConfiguration?.allowedCountries || [
38004
38092
  "US"
38005
38093
  ];
38006
- const selectedCountries = await clack49.multiselect({
38094
+ const selectedCountries = await clack50.multiselect({
38007
38095
  message: "Select countries to allow SMS delivery (all others blocked):",
38008
38096
  options: commonCountries.map((c) => ({
38009
38097
  value: c.code,
@@ -38012,16 +38100,16 @@ ${pc53.yellow("\u26A0")} ${pc53.bold("10DLC Campaign Registration Required")}
38012
38100
  initialValues: currentAllowed,
38013
38101
  required: true
38014
38102
  });
38015
- if (clack49.isCancel(selectedCountries)) {
38016
- clack49.cancel("Upgrade cancelled.");
38103
+ if (clack50.isCancel(selectedCountries)) {
38104
+ clack50.cancel("Upgrade cancelled.");
38017
38105
  process.exit(0);
38018
38106
  }
38019
- const enableAIT = await clack49.confirm({
38107
+ const enableAIT = await clack50.confirm({
38020
38108
  message: "Enable AIT (Artificially Inflated Traffic) filtering? (adds per-message cost)",
38021
38109
  initialValue: config2.protectConfiguration?.aitFiltering ?? false
38022
38110
  });
38023
- if (clack49.isCancel(enableAIT)) {
38024
- clack49.cancel("Upgrade cancelled.");
38111
+ if (clack50.isCancel(enableAIT)) {
38112
+ clack50.cancel("Upgrade cancelled.");
38025
38113
  process.exit(0);
38026
38114
  }
38027
38115
  updatedConfig = {
@@ -38055,12 +38143,12 @@ ${pc53.bold("Cost Impact:")}`);
38055
38143
  }
38056
38144
  console.log("");
38057
38145
  if (!options.yes) {
38058
- const confirmed = await clack49.confirm({
38146
+ const confirmed = await clack50.confirm({
38059
38147
  message: "Proceed with upgrade?",
38060
38148
  initialValue: true
38061
38149
  });
38062
- if (clack49.isCancel(confirmed) || !confirmed) {
38063
- clack49.cancel("Upgrade cancelled.");
38150
+ if (clack50.isCancel(confirmed) || !confirmed) {
38151
+ clack50.cancel("Upgrade cancelled.");
38064
38152
  process.exit(0);
38065
38153
  }
38066
38154
  }
@@ -38202,9 +38290,9 @@ ${pc53.bold("Cost Impact:")}`);
38202
38290
  }
38203
38291
  progress.info("Connection metadata updated");
38204
38292
  console.log("\n");
38205
- clack49.log.success(pc53.green(pc53.bold("SMS infrastructure upgraded!")));
38293
+ clack50.log.success(pc53.green(pc53.bold("SMS infrastructure upgraded!")));
38206
38294
  console.log("\n");
38207
- clack49.note(
38295
+ clack50.note(
38208
38296
  [
38209
38297
  `${pc53.bold("Phone Number:")} ${pc53.cyan(outputs.phoneNumber || "Provisioning...")}`,
38210
38298
  `${pc53.bold("Phone Type:")} ${pc53.cyan(updatedConfig.phoneNumberType || "simulator")}`,
@@ -38279,7 +38367,7 @@ ${pc53.green("\u2713")} ${pc53.bold("Upgrade complete!")}
38279
38367
  action: typeof upgradeAction === "string" ? upgradeAction : void 0,
38280
38368
  duration_ms: Date.now() - startTime
38281
38369
  });
38282
- clack49.outro(pc53.green("Upgrade complete!"));
38370
+ clack50.outro(pc53.green("Upgrade complete!"));
38283
38371
  }
38284
38372
 
38285
38373
  // src/commands/sms/verify-number.ts
@@ -38298,13 +38386,13 @@ import {
38298
38386
  SendDestinationNumberVerificationCodeCommand,
38299
38387
  VerifyDestinationNumberCommand
38300
38388
  } from "@aws-sdk/client-pinpoint-sms-voice-v2";
38301
- import * as clack50 from "@clack/prompts";
38389
+ import * as clack51 from "@clack/prompts";
38302
38390
  import pc54 from "picocolors";
38303
38391
  async function smsVerifyNumber(options) {
38304
38392
  const startTime = Date.now();
38305
38393
  const progress = new DeploymentProgress();
38306
38394
  if (!isJsonMode()) {
38307
- clack50.intro(pc54.bold("Wraps SMS - Verify Destination Number"));
38395
+ clack51.intro(pc54.bold("Wraps SMS - Verify Destination Number"));
38308
38396
  }
38309
38397
  const identity = await progress.execute(
38310
38398
  "Validating AWS credentials",
@@ -38314,7 +38402,7 @@ async function smsVerifyNumber(options) {
38314
38402
  const metadata = await loadConnectionMetadata(identity.accountId, region);
38315
38403
  if (!metadata?.services?.sms) {
38316
38404
  progress.stop();
38317
- clack50.log.error("No SMS infrastructure found");
38405
+ clack51.log.error("No SMS infrastructure found");
38318
38406
  console.log(
38319
38407
  `
38320
38408
  Run ${pc54.cyan("wraps sms init")} to deploy SMS infrastructure.
@@ -38331,7 +38419,7 @@ Run ${pc54.cyan("wraps sms init")} to deploy SMS infrastructure.
38331
38419
  );
38332
38420
  progress.stop();
38333
38421
  if (!response.VerifiedDestinationNumbers || response.VerifiedDestinationNumbers.length === 0) {
38334
- clack50.log.info("No verified destination numbers found");
38422
+ clack51.log.info("No verified destination numbers found");
38335
38423
  console.log(
38336
38424
  `
38337
38425
  Run ${pc54.cyan("wraps sms verify-number")} to verify a number.
@@ -38339,7 +38427,7 @@ Run ${pc54.cyan("wraps sms verify-number")} to verify a number.
38339
38427
  );
38340
38428
  } else {
38341
38429
  console.log("\n");
38342
- clack50.log.info(pc54.bold("Verified Destination Numbers:"));
38430
+ clack51.log.info(pc54.bold("Verified Destination Numbers:"));
38343
38431
  console.log("");
38344
38432
  for (const num of response.VerifiedDestinationNumbers) {
38345
38433
  const status2 = num.Status === "VERIFIED" ? pc54.green("\u2713 Verified") : pc54.yellow("\u29D6 Pending");
@@ -38361,7 +38449,7 @@ Run ${pc54.cyan("wraps sms verify-number")} to verify a number.
38361
38449
  });
38362
38450
  return;
38363
38451
  }
38364
- clack50.outro(pc54.green("Done!"));
38452
+ clack51.outro(pc54.green("Done!"));
38365
38453
  return;
38366
38454
  } catch (error) {
38367
38455
  progress.stop();
@@ -38369,7 +38457,7 @@ Run ${pc54.cyan("wraps sms verify-number")} to verify a number.
38369
38457
  trackError("SMS_LIST_VERIFIED_FAILED", "sms:verify-number:list", {
38370
38458
  error: errorMessage
38371
38459
  });
38372
- clack50.log.error(`Failed to list verified numbers: ${errorMessage}`);
38460
+ clack51.log.error(`Failed to list verified numbers: ${errorMessage}`);
38373
38461
  process.exit(1);
38374
38462
  }
38375
38463
  }
@@ -38377,7 +38465,7 @@ Run ${pc54.cyan("wraps sms verify-number")} to verify a number.
38377
38465
  const phoneNumber2 = options.phoneNumber;
38378
38466
  if (!phoneNumber2) {
38379
38467
  progress.stop();
38380
- clack50.log.error("Phone number is required for deletion");
38468
+ clack51.log.error("Phone number is required for deletion");
38381
38469
  console.log(
38382
38470
  `
38383
38471
  Usage: ${pc54.cyan("wraps sms verify-number --delete --phone-number +14155551234")}
@@ -38394,7 +38482,7 @@ Usage: ${pc54.cyan("wraps sms verify-number --delete --phone-number +14155551234
38394
38482
  const verifiedNumber = listResponse.VerifiedDestinationNumbers?.[0];
38395
38483
  if (!verifiedNumber?.VerifiedDestinationNumberId) {
38396
38484
  progress.stop();
38397
- clack50.log.error(`Number ${phoneNumber2} is not in verified list`);
38485
+ clack51.log.error(`Number ${phoneNumber2} is not in verified list`);
38398
38486
  process.exit(1);
38399
38487
  }
38400
38488
  await progress.execute(`Removing ${phoneNumber2}`, async () => {
@@ -38405,7 +38493,7 @@ Usage: ${pc54.cyan("wraps sms verify-number --delete --phone-number +14155551234
38405
38493
  );
38406
38494
  });
38407
38495
  progress.stop();
38408
- clack50.log.success(`Removed ${pc54.cyan(phoneNumber2)} from verified list`);
38496
+ clack51.log.success(`Removed ${pc54.cyan(phoneNumber2)} from verified list`);
38409
38497
  trackCommand("sms:verify-number:delete", {
38410
38498
  success: true,
38411
38499
  duration_ms: Date.now() - startTime
@@ -38417,7 +38505,7 @@ Usage: ${pc54.cyan("wraps sms verify-number --delete --phone-number +14155551234
38417
38505
  });
38418
38506
  return;
38419
38507
  }
38420
- clack50.outro(pc54.green("Done!"));
38508
+ clack51.outro(pc54.green("Done!"));
38421
38509
  return;
38422
38510
  } catch (error) {
38423
38511
  progress.stop();
@@ -38425,7 +38513,7 @@ Usage: ${pc54.cyan("wraps sms verify-number --delete --phone-number +14155551234
38425
38513
  trackError("SMS_DELETE_VERIFIED_FAILED", "sms:verify-number:delete", {
38426
38514
  error: errorMessage
38427
38515
  });
38428
- clack50.log.error(`Failed to delete verified number: ${errorMessage}`);
38516
+ clack51.log.error(`Failed to delete verified number: ${errorMessage}`);
38429
38517
  process.exit(1);
38430
38518
  }
38431
38519
  }
@@ -38438,7 +38526,7 @@ Usage: ${pc54.cyan("wraps sms verify-number --delete --phone-number +14155551234
38438
38526
  );
38439
38527
  }
38440
38528
  if (!phoneNumber) {
38441
- const result = await clack50.text({
38529
+ const result = await clack51.text({
38442
38530
  message: "Enter phone number to verify (E.164 format):",
38443
38531
  placeholder: "+14155551234",
38444
38532
  validate: (value) => {
@@ -38451,14 +38539,14 @@ Usage: ${pc54.cyan("wraps sms verify-number --delete --phone-number +14155551234
38451
38539
  return;
38452
38540
  }
38453
38541
  });
38454
- if (clack50.isCancel(result)) {
38455
- clack50.cancel("Operation cancelled.");
38542
+ if (clack51.isCancel(result)) {
38543
+ clack51.cancel("Operation cancelled.");
38456
38544
  process.exit(0);
38457
38545
  }
38458
38546
  phoneNumber = result;
38459
38547
  } else if (!isValidPhoneNumber(phoneNumber)) {
38460
38548
  progress.stop();
38461
- clack50.log.error(
38549
+ clack51.log.error(
38462
38550
  `Invalid phone number format: ${phoneNumber}. Use E.164 format (e.g., +14155551234)`
38463
38551
  );
38464
38552
  process.exit(1);
@@ -38473,7 +38561,7 @@ Usage: ${pc54.cyan("wraps sms verify-number --delete --phone-number +14155551234
38473
38561
  const verifiedNumber = listResponse.VerifiedDestinationNumbers?.[0];
38474
38562
  if (!verifiedNumber?.VerifiedDestinationNumberId) {
38475
38563
  progress.stop();
38476
- clack50.log.error(
38564
+ clack51.log.error(
38477
38565
  `Number ${phoneNumber} not found. Run without --code first.`
38478
38566
  );
38479
38567
  process.exit(1);
@@ -38488,7 +38576,7 @@ Usage: ${pc54.cyan("wraps sms verify-number --delete --phone-number +14155551234
38488
38576
  });
38489
38577
  progress.stop();
38490
38578
  console.log("\n");
38491
- clack50.log.success(
38579
+ clack51.log.success(
38492
38580
  pc54.green(`Phone number ${pc54.cyan(phoneNumber)} verified!`)
38493
38581
  );
38494
38582
  console.log("");
@@ -38506,13 +38594,13 @@ Usage: ${pc54.cyan("wraps sms verify-number --delete --phone-number +14155551234
38506
38594
  });
38507
38595
  return;
38508
38596
  }
38509
- clack50.outro(pc54.green("Verification complete!"));
38597
+ clack51.outro(pc54.green("Verification complete!"));
38510
38598
  return;
38511
38599
  } catch (error) {
38512
38600
  progress.stop();
38513
38601
  const errorMessage = error instanceof Error ? error.message : String(error);
38514
38602
  if (errorMessage.includes("Invalid verification code")) {
38515
- clack50.log.error("Invalid verification code. Please try again.");
38603
+ clack51.log.error("Invalid verification code. Please try again.");
38516
38604
  console.log(
38517
38605
  `
38518
38606
  Run ${pc54.cyan(`wraps sms verify-number --phone-number ${phoneNumber} --resend`)} to get a new code.
@@ -38522,7 +38610,7 @@ Run ${pc54.cyan(`wraps sms verify-number --phone-number ${phoneNumber} --resend`
38522
38610
  trackError("SMS_VERIFY_CODE_FAILED", "sms:verify-number:confirm", {
38523
38611
  error: errorMessage
38524
38612
  });
38525
- clack50.log.error(`Verification failed: ${errorMessage}`);
38613
+ clack51.log.error(`Verification failed: ${errorMessage}`);
38526
38614
  }
38527
38615
  process.exit(1);
38528
38616
  }
@@ -38537,7 +38625,7 @@ Run ${pc54.cyan(`wraps sms verify-number --phone-number ${phoneNumber} --resend`
38537
38625
  const verifiedNumber = listResponse.VerifiedDestinationNumbers?.[0];
38538
38626
  if (!verifiedNumber?.VerifiedDestinationNumberId) {
38539
38627
  progress.stop();
38540
- clack50.log.error(
38628
+ clack51.log.error(
38541
38629
  `Number ${phoneNumber} not found. Run without --resend first.`
38542
38630
  );
38543
38631
  process.exit(1);
@@ -38551,7 +38639,7 @@ Run ${pc54.cyan(`wraps sms verify-number --phone-number ${phoneNumber} --resend`
38551
38639
  );
38552
38640
  });
38553
38641
  progress.stop();
38554
- clack50.log.success(`Verification code resent to ${pc54.cyan(phoneNumber)}`);
38642
+ clack51.log.success(`Verification code resent to ${pc54.cyan(phoneNumber)}`);
38555
38643
  console.log("");
38556
38644
  console.log(
38557
38645
  `Once you receive the code, run:
@@ -38568,7 +38656,7 @@ Run ${pc54.cyan(`wraps sms verify-number --phone-number ${phoneNumber} --resend`
38568
38656
  });
38569
38657
  return;
38570
38658
  }
38571
- clack50.outro(pc54.green("Code sent!"));
38659
+ clack51.outro(pc54.green("Code sent!"));
38572
38660
  return;
38573
38661
  } catch (error) {
38574
38662
  progress.stop();
@@ -38576,7 +38664,7 @@ Run ${pc54.cyan(`wraps sms verify-number --phone-number ${phoneNumber} --resend`
38576
38664
  trackError("SMS_RESEND_CODE_FAILED", "sms:verify-number:resend", {
38577
38665
  error: errorMessage
38578
38666
  });
38579
- clack50.log.error(`Failed to resend code: ${errorMessage}`);
38667
+ clack51.log.error(`Failed to resend code: ${errorMessage}`);
38580
38668
  process.exit(1);
38581
38669
  }
38582
38670
  }
@@ -38596,10 +38684,10 @@ Run ${pc54.cyan(`wraps sms verify-number --phone-number ${phoneNumber} --resend`
38596
38684
  });
38597
38685
  return;
38598
38686
  }
38599
- clack50.log.info(
38687
+ clack51.log.info(
38600
38688
  `Number ${pc54.cyan(phoneNumber)} is already verified and ready to use!`
38601
38689
  );
38602
- clack50.outro(pc54.green("Done!"));
38690
+ clack51.outro(pc54.green("Done!"));
38603
38691
  return;
38604
38692
  }
38605
38693
  if (existingNumber?.Status === "PENDING") {
@@ -38623,7 +38711,7 @@ Run ${pc54.cyan(`wraps sms verify-number --phone-number ${phoneNumber} --resend`
38623
38711
  });
38624
38712
  return;
38625
38713
  }
38626
- clack50.log.info(
38714
+ clack51.log.info(
38627
38715
  `Verification already in progress. New code sent to ${pc54.cyan(phoneNumber)}`
38628
38716
  );
38629
38717
  console.log("");
@@ -38631,7 +38719,7 @@ Run ${pc54.cyan(`wraps sms verify-number --phone-number ${phoneNumber} --resend`
38631
38719
  `Once you receive the code, run:
38632
38720
  ${pc54.cyan(`wraps sms verify-number --phone-number ${phoneNumber} --code YOUR_CODE`)}`
38633
38721
  );
38634
- clack50.outro(pc54.green("Code sent!"));
38722
+ clack51.outro(pc54.green("Code sent!"));
38635
38723
  return;
38636
38724
  }
38637
38725
  const createResponse = await progress.execute(
@@ -38652,11 +38740,11 @@ Run ${pc54.cyan(`wraps sms verify-number --phone-number ${phoneNumber} --resend`
38652
38740
  });
38653
38741
  progress.stop();
38654
38742
  console.log("\n");
38655
- clack50.log.success(
38743
+ clack51.log.success(
38656
38744
  `Verification code sent to ${pc54.cyan(phoneNumber)} via SMS`
38657
38745
  );
38658
38746
  console.log("");
38659
- clack50.note(
38747
+ clack51.note(
38660
38748
  [
38661
38749
  "1. Check your phone for the verification code",
38662
38750
  "",
@@ -38679,12 +38767,12 @@ Run ${pc54.cyan(`wraps sms verify-number --phone-number ${phoneNumber} --resend`
38679
38767
  });
38680
38768
  return;
38681
38769
  }
38682
- clack50.outro(pc54.green("Verification started!"));
38770
+ clack51.outro(pc54.green("Verification started!"));
38683
38771
  } catch (error) {
38684
38772
  progress.stop();
38685
38773
  const errorMessage = error instanceof Error ? error.message : String(error);
38686
38774
  if (errorMessage.includes("already exists")) {
38687
- clack50.log.error("This number is already being verified");
38775
+ clack51.log.error("This number is already being verified");
38688
38776
  console.log(
38689
38777
  `
38690
38778
  Run ${pc54.cyan(`wraps sms verify-number --phone-number ${phoneNumber} --resend`)} to get a new code.
@@ -38694,7 +38782,7 @@ Run ${pc54.cyan(`wraps sms verify-number --phone-number ${phoneNumber} --resend`
38694
38782
  trackError("SMS_CREATE_VERIFIED_FAILED", "sms:verify-number:start", {
38695
38783
  error: errorMessage
38696
38784
  });
38697
- clack50.log.error(`Failed to start verification: ${errorMessage}`);
38785
+ clack51.log.error(`Failed to start verification: ${errorMessage}`);
38698
38786
  }
38699
38787
  process.exit(1);
38700
38788
  }
@@ -38703,11 +38791,11 @@ Run ${pc54.cyan(`wraps sms verify-number --phone-number ${phoneNumber} --resend`
38703
38791
  // src/commands/support.ts
38704
38792
  init_esm_shims();
38705
38793
  init_events();
38706
- import * as clack51 from "@clack/prompts";
38794
+ import * as clack52 from "@clack/prompts";
38707
38795
  import pc55 from "picocolors";
38708
38796
  async function support() {
38709
38797
  trackCommand("support", { success: true });
38710
- clack51.intro(pc55.bold("Get Help with Wraps"));
38798
+ clack52.intro(pc55.bold("Get Help with Wraps"));
38711
38799
  console.log();
38712
38800
  console.log(` ${pc55.bold("Email:")} ${pc55.cyan("hey@wraps.sh")}`);
38713
38801
  console.log(
@@ -38722,20 +38810,20 @@ async function support() {
38722
38810
  // src/commands/telemetry.ts
38723
38811
  init_esm_shims();
38724
38812
  init_client();
38725
- import * as clack52 from "@clack/prompts";
38813
+ import * as clack53 from "@clack/prompts";
38726
38814
  import pc56 from "picocolors";
38727
38815
  async function telemetryEnable() {
38728
38816
  const client = getTelemetryClient();
38729
38817
  const override = client.enable();
38730
38818
  if (override) {
38731
- clack52.log.warn(
38819
+ clack53.log.warn(
38732
38820
  "Telemetry enabled in config, but overridden by environment"
38733
38821
  );
38734
38822
  console.log(` Reason: ${pc56.yellow(override)}`);
38735
38823
  console.log(` Config: ${pc56.dim(client.getConfigPath())}`);
38736
38824
  console.log();
38737
38825
  } else {
38738
- clack52.log.success(pc56.green("Telemetry enabled"));
38826
+ clack53.log.success(pc56.green("Telemetry enabled"));
38739
38827
  console.log(` Config: ${pc56.dim(client.getConfigPath())}`);
38740
38828
  console.log(`
38741
38829
  ${pc56.dim("Thank you for helping improve Wraps!")}
@@ -38745,7 +38833,7 @@ async function telemetryEnable() {
38745
38833
  async function telemetryDisable() {
38746
38834
  const client = getTelemetryClient();
38747
38835
  client.disable();
38748
- clack52.log.success(pc56.green("Telemetry disabled"));
38836
+ clack53.log.success(pc56.green("Telemetry disabled"));
38749
38837
  console.log(` Config: ${pc56.dim(client.getConfigPath())}`);
38750
38838
  console.log(
38751
38839
  `
@@ -38755,7 +38843,7 @@ async function telemetryDisable() {
38755
38843
  }
38756
38844
  async function telemetryStatus() {
38757
38845
  const client = getTelemetryClient();
38758
- clack52.intro(pc56.bold("Telemetry Status"));
38846
+ clack53.intro(pc56.bold("Telemetry Status"));
38759
38847
  const override = client.getEnvOverride();
38760
38848
  const status2 = client.isEnabled() ? pc56.green("Enabled") : pc56.red("Disabled");
38761
38849
  console.log();
@@ -38793,7 +38881,7 @@ async function telemetryStatus() {
38793
38881
  init_esm_shims();
38794
38882
  import { existsSync as existsSync18, mkdirSync as mkdirSync2, writeFileSync } from "fs";
38795
38883
  import { join as join20 } from "path";
38796
- import * as clack53 from "@clack/prompts";
38884
+ import * as clack54 from "@clack/prompts";
38797
38885
  import pc57 from "picocolors";
38798
38886
  var EXAMPLE_CASCADE_WORKFLOW = `import {
38799
38887
  defineWorkflow,
@@ -38889,30 +38977,30 @@ export default defineConfig({
38889
38977
  });
38890
38978
  `;
38891
38979
  async function workflowInit(options = {}) {
38892
- clack53.intro(pc57.bgCyan(pc57.black(" wraps workflow init ")));
38980
+ clack54.intro(pc57.bgCyan(pc57.black(" wraps workflow init ")));
38893
38981
  const wrapsDir = join20(process.cwd(), "wraps");
38894
38982
  const workflowsDir = join20(wrapsDir, "workflows");
38895
38983
  const configPath = join20(wrapsDir, "wraps.config.ts");
38896
38984
  if (existsSync18(workflowsDir)) {
38897
- clack53.log.info(
38985
+ clack54.log.info(
38898
38986
  `Workflows directory already exists at ${pc57.cyan("wraps/workflows/")}`
38899
38987
  );
38900
38988
  const files = existsSync18(join20(workflowsDir, "cart-recovery.ts")) || existsSync18(join20(workflowsDir, "welcome-sequence.ts"));
38901
38989
  if (files && !options.yes) {
38902
- const shouldContinue = await clack53.confirm({
38990
+ const shouldContinue = await clack54.confirm({
38903
38991
  message: "Example files may already exist. Overwrite them?",
38904
38992
  initialValue: false
38905
38993
  });
38906
- if (clack53.isCancel(shouldContinue) || !shouldContinue) {
38907
- clack53.log.info("Skipping file creation.");
38994
+ if (clack54.isCancel(shouldContinue) || !shouldContinue) {
38995
+ clack54.log.info("Skipping file creation.");
38908
38996
  showNextSteps2();
38909
- clack53.outro("Done!");
38997
+ clack54.outro("Done!");
38910
38998
  return;
38911
38999
  }
38912
39000
  }
38913
39001
  }
38914
39002
  try {
38915
- const s = clack53.spinner();
39003
+ const s = clack54.spinner();
38916
39004
  s.start("Creating workflows directory...");
38917
39005
  mkdirSync2(workflowsDir, { recursive: true });
38918
39006
  s.stop("Created wraps/workflows/");
@@ -38930,26 +39018,26 @@ async function workflowInit(options = {}) {
38930
39018
  s.stop("Created 2 example workflows");
38931
39019
  if (!existsSync18(configPath)) {
38932
39020
  writeFileSync(configPath, EXAMPLE_CONFIG, "utf-8");
38933
- clack53.log.info(`Created ${pc57.cyan("wraps/wraps.config.ts")}`);
39021
+ clack54.log.info(`Created ${pc57.cyan("wraps/wraps.config.ts")}`);
38934
39022
  }
38935
- clack53.log.success(
39023
+ clack54.log.success(
38936
39024
  `${pc57.bold("Workflows scaffolded!")} Created:
38937
39025
  ${pc57.cyan("wraps/wraps.config.ts")} \u2014 Project config
38938
39026
  ${pc57.cyan("wraps/workflows/cart-recovery.ts")} \u2014 Cross-channel cascade example
38939
39027
  ${pc57.cyan("wraps/workflows/welcome-sequence.ts")} \u2014 Welcome series example`
38940
39028
  );
38941
39029
  showNextSteps2();
38942
- clack53.outro(pc57.green("Happy orchestrating!"));
39030
+ clack54.outro(pc57.green("Happy orchestrating!"));
38943
39031
  } catch (error) {
38944
- clack53.log.error(
39032
+ clack54.log.error(
38945
39033
  `Failed to scaffold workflows: ${error instanceof Error ? error.message : String(error)}`
38946
39034
  );
38947
- clack53.outro(pc57.red("Scaffolding failed."));
39035
+ clack54.outro(pc57.red("Scaffolding failed."));
38948
39036
  process.exitCode = 1;
38949
39037
  }
38950
39038
  }
38951
39039
  function showNextSteps2() {
38952
- clack53.log.info(
39040
+ clack54.log.info(
38953
39041
  `${pc57.bold("Next steps:")}
38954
39042
 
38955
39043
  1. Edit ${pc57.cyan("wraps/wraps.config.ts")} with your org slug and domain
@@ -39135,7 +39223,7 @@ function showVersion() {
39135
39223
  process.exit(0);
39136
39224
  }
39137
39225
  function showHelp() {
39138
- clack54.intro(pc59.bold(`WRAPS CLI v${VERSION}`));
39226
+ clack55.intro(pc59.bold(`WRAPS CLI v${VERSION}`));
39139
39227
  console.log("Deploy AWS infrastructure to your account\n");
39140
39228
  console.log("Usage: wraps [service] <command> [options]\n");
39141
39229
  console.log("Services:");
@@ -39341,7 +39429,7 @@ if (!primaryCommand) {
39341
39429
  const telemetry = getTelemetryClient();
39342
39430
  if (telemetry.shouldShowNotification()) {
39343
39431
  console.log();
39344
- clack54.log.info(pc59.bold("Anonymous Telemetry"));
39432
+ clack55.log.info(pc59.bold("Anonymous Telemetry"));
39345
39433
  console.log(
39346
39434
  ` Wraps collects ${pc59.cyan("anonymous usage data")} to improve the CLI.`
39347
39435
  );
@@ -39359,9 +39447,9 @@ if (!primaryCommand) {
39359
39447
  telemetry.markNotificationShown();
39360
39448
  }
39361
39449
  trackCommand("interactive:menu", { success: true, duration_ms: 0 });
39362
- clack54.intro(pc59.bold(`WRAPS CLI v${VERSION}`));
39450
+ clack55.intro(pc59.bold(`WRAPS CLI v${VERSION}`));
39363
39451
  console.log(" Deploy AWS infrastructure to your account.\n");
39364
- const action = await clack54.select({
39452
+ const action = await clack55.select({
39365
39453
  message: "What would you like to do?",
39366
39454
  options: [
39367
39455
  {
@@ -39411,13 +39499,13 @@ if (!primaryCommand) {
39411
39499
  }
39412
39500
  ]
39413
39501
  });
39414
- if (clack54.isCancel(action)) {
39502
+ if (clack55.isCancel(action)) {
39415
39503
  trackCommand("interactive:cancel", {
39416
39504
  success: true,
39417
39505
  duration_ms: Date.now() - startTime
39418
39506
  });
39419
39507
  await telemetry.shutdown();
39420
- clack54.cancel("Operation cancelled.");
39508
+ clack55.cancel("Operation cancelled.");
39421
39509
  process.exit(0);
39422
39510
  }
39423
39511
  trackCommand(`interactive:${action}`, {
@@ -39496,7 +39584,7 @@ async function run() {
39496
39584
  const telemetry = getTelemetryClient();
39497
39585
  if (telemetry.shouldShowNotification()) {
39498
39586
  console.log();
39499
- clack54.log.info(pc59.bold("Anonymous Telemetry"));
39587
+ clack55.log.info(pc59.bold("Anonymous Telemetry"));
39500
39588
  console.log(
39501
39589
  ` Wraps collects ${pc59.cyan("anonymous usage data")} to improve the CLI.`
39502
39590
  );
@@ -39593,7 +39681,7 @@ async function run() {
39593
39681
  break;
39594
39682
  case "verify": {
39595
39683
  if (!flags.domain) {
39596
- clack54.log.error("--domain flag is required");
39684
+ clack55.log.error("--domain flag is required");
39597
39685
  console.log(
39598
39686
  `
39599
39687
  Usage: ${pc59.cyan("wraps email verify --domain yourapp.com")}
@@ -39667,7 +39755,7 @@ Usage: ${pc59.cyan("wraps email verify --domain yourapp.com")}
39667
39755
  });
39668
39756
  break;
39669
39757
  default:
39670
- clack54.log.error(
39758
+ clack55.log.error(
39671
39759
  `Unknown inbound command: ${inboundSubCommand || "(none)"}`
39672
39760
  );
39673
39761
  console.log(
@@ -39722,7 +39810,7 @@ Available commands: ${pc59.cyan("init")}, ${pc59.cyan("destroy")}, ${pc59.cyan("
39722
39810
  break;
39723
39811
  }
39724
39812
  default:
39725
- clack54.log.error(
39813
+ clack55.log.error(
39726
39814
  `Unknown reply command: ${replySubCommand || "(none)"}`
39727
39815
  );
39728
39816
  console.log(
@@ -39752,7 +39840,7 @@ Available commands: ${pc59.cyan("init")}, ${pc59.cyan("rotate")}, ${pc59.cyan("s
39752
39840
  break;
39753
39841
  case "verify": {
39754
39842
  if (!flags.domain) {
39755
- clack54.log.error("--domain flag is required");
39843
+ clack55.log.error("--domain flag is required");
39756
39844
  console.log(
39757
39845
  `
39758
39846
  Usage: ${pc59.cyan("wraps email domains verify --domain yourapp.com")}
@@ -39765,7 +39853,7 @@ Usage: ${pc59.cyan("wraps email domains verify --domain yourapp.com")}
39765
39853
  }
39766
39854
  case "get-dkim": {
39767
39855
  if (!flags.domain) {
39768
- clack54.log.error("--domain flag is required");
39856
+ clack55.log.error("--domain flag is required");
39769
39857
  console.log(
39770
39858
  `
39771
39859
  Usage: ${pc59.cyan("wraps email domains get-dkim --domain yourapp.com")}
@@ -39778,7 +39866,7 @@ Usage: ${pc59.cyan("wraps email domains get-dkim --domain yourapp.com")}
39778
39866
  }
39779
39867
  case "remove": {
39780
39868
  if (!flags.domain) {
39781
- clack54.log.error("--domain flag is required");
39869
+ clack55.log.error("--domain flag is required");
39782
39870
  console.log(
39783
39871
  `
39784
39872
  Usage: ${pc59.cyan("wraps email domains remove --domain yourapp.com --force")}
@@ -39793,7 +39881,7 @@ Usage: ${pc59.cyan("wraps email domains remove --domain yourapp.com --force")}
39793
39881
  break;
39794
39882
  }
39795
39883
  default:
39796
- clack54.log.error(
39884
+ clack55.log.error(
39797
39885
  `Unknown domains command: ${domainsSubCommand || "(none)"}`
39798
39886
  );
39799
39887
  console.log(
@@ -39840,7 +39928,7 @@ Available commands: ${pc59.cyan("add")}, ${pc59.cyan("list")}, ${pc59.cyan("veri
39840
39928
  });
39841
39929
  break;
39842
39930
  default:
39843
- clack54.log.error(
39931
+ clack55.log.error(
39844
39932
  `Unknown templates command: ${templatesSubCommand || "(none)"}`
39845
39933
  );
39846
39934
  console.log(
@@ -39884,7 +39972,7 @@ Available commands: ${pc59.cyan("init")}, ${pc59.cyan("push")}, ${pc59.cyan("pre
39884
39972
  });
39885
39973
  break;
39886
39974
  default:
39887
- clack54.log.error(
39975
+ clack55.log.error(
39888
39976
  `Unknown workflows command: ${workflowsSubCommand || "(none)"}`
39889
39977
  );
39890
39978
  console.log(
@@ -39914,7 +40002,7 @@ Available commands: ${pc59.cyan("init")}, ${pc59.cyan("validate")}, ${pc59.cyan(
39914
40002
  });
39915
40003
  break;
39916
40004
  default:
39917
- clack54.log.error(`Unknown email command: ${subCommand}`);
40005
+ clack55.log.error(`Unknown email command: ${subCommand}`);
39918
40006
  console.log(
39919
40007
  `
39920
40008
  Run ${pc59.cyan("wraps --help")} for available commands.
@@ -39992,7 +40080,7 @@ Run ${pc59.cyan("wraps --help")} for available commands.
39992
40080
  });
39993
40081
  break;
39994
40082
  default:
39995
- clack54.log.error(`Unknown sms command: ${subCommand}`);
40083
+ clack55.log.error(`Unknown sms command: ${subCommand}`);
39996
40084
  console.log(
39997
40085
  `
39998
40086
  Run ${pc59.cyan("wraps --help")} for available commands.
@@ -40056,7 +40144,7 @@ Run ${pc59.cyan("wraps --help")} for available commands.
40056
40144
  });
40057
40145
  break;
40058
40146
  default:
40059
- clack54.log.error(`Unknown cdn command: ${subCommand}`);
40147
+ clack55.log.error(`Unknown cdn command: ${subCommand}`);
40060
40148
  console.log(
40061
40149
  `
40062
40150
  Run ${pc59.cyan("wraps --help")} for available commands.
@@ -40081,7 +40169,7 @@ Run ${pc59.cyan("wraps --help")} for available commands.
40081
40169
  });
40082
40170
  break;
40083
40171
  default:
40084
- clack54.log.error(
40172
+ clack55.log.error(
40085
40173
  `Unknown workflow command: ${subCommand || "(none)"}`
40086
40174
  );
40087
40175
  console.log(`
@@ -40129,7 +40217,7 @@ Available commands: ${pc59.cyan("init")}
40129
40217
  });
40130
40218
  break;
40131
40219
  default:
40132
- clack54.log.error(`Unknown platform command: ${subCommand}`);
40220
+ clack55.log.error(`Unknown platform command: ${subCommand}`);
40133
40221
  console.log(
40134
40222
  `
40135
40223
  Available commands: ${pc59.cyan("connect")}, ${pc59.cyan("update-role")}
@@ -40161,7 +40249,7 @@ Available commands: ${pc59.cyan("connect")}, ${pc59.cyan("update-role")}
40161
40249
  await logout();
40162
40250
  break;
40163
40251
  default:
40164
- clack54.log.error(`Unknown auth command: ${subCommand || "(none)"}`);
40252
+ clack55.log.error(`Unknown auth command: ${subCommand || "(none)"}`);
40165
40253
  console.log(
40166
40254
  `
40167
40255
  Available commands: ${pc59.cyan("login")}, ${pc59.cyan("status")}, ${pc59.cyan("logout")}
@@ -40182,7 +40270,7 @@ Available commands: ${pc59.cyan("login")}, ${pc59.cyan("status")}, ${pc59.cyan("
40182
40270
  await doctor();
40183
40271
  break;
40184
40272
  default:
40185
- clack54.log.error(`Unknown aws command: ${subCommand}`);
40273
+ clack55.log.error(`Unknown aws command: ${subCommand}`);
40186
40274
  console.log(
40187
40275
  `
40188
40276
  Available commands: ${pc59.cyan("setup")}, ${pc59.cyan("doctor")}
@@ -40267,7 +40355,7 @@ Available commands: ${pc59.cyan("setup")}, ${pc59.cyan("doctor")}
40267
40355
  await telemetryStatus();
40268
40356
  break;
40269
40357
  default:
40270
- clack54.log.error(`Unknown telemetry command: ${subCommand}`);
40358
+ clack55.log.error(`Unknown telemetry command: ${subCommand}`);
40271
40359
  console.log(
40272
40360
  `
40273
40361
  Available commands: ${pc59.cyan("enable")}, ${pc59.cyan("disable")}, ${pc59.cyan("status")}
@@ -40294,7 +40382,7 @@ Please specify a command for ${primaryCommand} service.
40294
40382
  showHelp();
40295
40383
  break;
40296
40384
  default:
40297
- clack54.log.error(`Unknown command: ${primaryCommand}`);
40385
+ clack55.log.error(`Unknown command: ${primaryCommand}`);
40298
40386
  console.log(
40299
40387
  `
40300
40388
  Run ${pc59.cyan("wraps --help")} for available commands.