@wraps.dev/cli 2.19.1 → 2.19.2

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 });
@@ -7995,7 +7986,6 @@ var init_mail_manager = __esm({
7995
7986
  "src/infrastructure/resources/mail-manager.ts"() {
7996
7987
  "use strict";
7997
7988
  init_esm_shims();
7998
- init_constants();
7999
7989
  }
8000
7990
  });
8001
7991
 
@@ -9675,6 +9665,60 @@ var init_test = __esm({
9675
9665
  }
9676
9666
  });
9677
9667
 
9668
+ // src/utils/shared/region-resolver.ts
9669
+ var region_resolver_exports = {};
9670
+ __export(region_resolver_exports, {
9671
+ resolveRegionForCommand: () => resolveRegionForCommand
9672
+ });
9673
+ import * as clack28 from "@clack/prompts";
9674
+ async function resolveRegionForCommand(opts) {
9675
+ const { accountId, optionRegion, service, label = "deployment" } = opts;
9676
+ if (optionRegion) {
9677
+ return optionRegion;
9678
+ }
9679
+ const envRegion = process.env.AWS_REGION || process.env.AWS_DEFAULT_REGION;
9680
+ if (envRegion) {
9681
+ return envRegion;
9682
+ }
9683
+ const connections = (service ? await findConnectionsWithService(accountId, service) : await findConnectionsForAccount(accountId)) ?? [];
9684
+ if (connections.length === 1) {
9685
+ return connections[0].region;
9686
+ }
9687
+ const savedRegions = connections.map((c) => c.region);
9688
+ if (connections.length === 0) {
9689
+ return getAWSRegion();
9690
+ }
9691
+ if (!isInteractive() || isJsonMode()) {
9692
+ throw errors.regionRequired(accountId, savedRegions);
9693
+ }
9694
+ const selected = await clack28.select({
9695
+ message: `Multiple ${label}s found. Which region?`,
9696
+ options: connections.map((conn) => ({
9697
+ value: conn.region,
9698
+ label: conn.region
9699
+ }))
9700
+ });
9701
+ if (clack28.isCancel(selected)) {
9702
+ throw new WrapsError(
9703
+ "Operation cancelled",
9704
+ "OPERATION_CANCELLED",
9705
+ `Pass --region to skip the prompt. Saved regions: ${savedRegions.join(", ")}`
9706
+ );
9707
+ }
9708
+ return selected;
9709
+ }
9710
+ var init_region_resolver = __esm({
9711
+ "src/utils/shared/region-resolver.ts"() {
9712
+ "use strict";
9713
+ init_esm_shims();
9714
+ init_aws();
9715
+ init_errors();
9716
+ init_json_output();
9717
+ init_metadata();
9718
+ init_prompts();
9719
+ }
9720
+ });
9721
+
9678
9722
  // src/utils/dns/caa.ts
9679
9723
  var caa_exports = {};
9680
9724
  __export(caa_exports, {
@@ -10080,7 +10124,7 @@ import { homedir as homedir4, tmpdir as tmpdir2 } from "os";
10080
10124
  import { join as join21 } from "path";
10081
10125
  import { Readable } from "stream";
10082
10126
  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";
10127
+ import { cancel as cancel31, confirm as confirm26, intro as intro51, isCancel as isCancel36, log as log50 } from "@clack/prompts";
10084
10128
  import pc58 from "picocolors";
10085
10129
  function isStandaloneInstall() {
10086
10130
  return process.execPath.includes(".wraps/runtime");
@@ -10142,7 +10186,7 @@ async function update(currentVersion) {
10142
10186
  const shouldUpdate = await confirm26({
10143
10187
  message: `Update to v${latestVersion}?`
10144
10188
  });
10145
- if (isCancel35(shouldUpdate) || !shouldUpdate) {
10189
+ if (isCancel36(shouldUpdate) || !shouldUpdate) {
10146
10190
  cancel31("Update cancelled.");
10147
10191
  return;
10148
10192
  }
@@ -10233,7 +10277,7 @@ init_esm_shims();
10233
10277
  import { readFileSync as readFileSync3 } from "fs";
10234
10278
  import { dirname as dirname5, join as join22 } from "path";
10235
10279
  import { fileURLToPath as fileURLToPath6 } from "url";
10236
- import * as clack54 from "@clack/prompts";
10280
+ import * as clack55 from "@clack/prompts";
10237
10281
  import pc59 from "picocolors";
10238
10282
 
10239
10283
  // src/commands/auth/login.ts
@@ -10648,26 +10692,30 @@ async function runDiagnostics(state) {
10648
10692
  }
10649
10693
  }
10650
10694
  if (state.credentialsConfigured) {
10695
+ const regionUsed = state.region || "us-east-1";
10696
+ const regionNote = state.region ? `Region: ${regionUsed}` : `No AWS_REGION set \u2014 defaulted to ${regionUsed}. Set AWS_REGION if your deployment lives elsewhere.`;
10651
10697
  try {
10652
- const region = state.region || "us-east-1";
10653
- const sandbox = await isSESSandbox(region);
10698
+ const sandbox = await isSESSandbox(regionUsed);
10654
10699
  if (sandbox) {
10655
10700
  results.push({
10656
10701
  status: "warn",
10657
10702
  message: "SES is in sandbox mode",
10658
- details: "You can only send to verified emails. Request production access in AWS console."
10703
+ details: `You can only send to verified emails. Request production access in AWS console.
10704
+ ${regionNote}`
10659
10705
  });
10660
10706
  } else {
10661
10707
  results.push({
10662
10708
  status: "pass",
10663
- message: "SES has production access"
10709
+ message: "SES has production access",
10710
+ details: regionNote
10664
10711
  });
10665
10712
  }
10666
10713
  } catch {
10667
10714
  results.push({
10668
10715
  status: "info",
10669
10716
  message: "Could not check SES status",
10670
- details: "SES may not be enabled in this region"
10717
+ details: `SES may not be enabled in this region.
10718
+ ${regionNote}`
10671
10719
  });
10672
10720
  }
10673
10721
  }
@@ -12202,8 +12250,16 @@ async function createServiceIAMRole(config2) {
12202
12250
 
12203
12251
  // src/infrastructure/vercel-oidc.ts
12204
12252
  init_esm_shims();
12205
- init_constants();
12206
12253
  import * as aws3 from "@pulumi/aws";
12254
+
12255
+ // src/constants.ts
12256
+ init_esm_shims();
12257
+ var DEFAULT_AWS_REGION = "us-east-1";
12258
+ function getDefaultRegion() {
12259
+ return process.env.AWS_REGION || DEFAULT_AWS_REGION;
12260
+ }
12261
+
12262
+ // src/infrastructure/vercel-oidc.ts
12207
12263
  async function getExistingOIDCProviderArn(url) {
12208
12264
  try {
12209
12265
  const { IAMClient: IAMClient5, ListOpenIDConnectProvidersCommand } = await import("@aws-sdk/client-iam");
@@ -17509,9 +17565,9 @@ async function createAlertingResources(config2) {
17509
17565
  init_esm_shims();
17510
17566
  init_resource_checks();
17511
17567
  import * as aws5 from "@pulumi/aws";
17512
- async function createDynamoDBTables(_config) {
17568
+ async function createDynamoDBTables(config2) {
17513
17569
  const tableName = "wraps-email-history";
17514
- const exists = await tableExists(tableName);
17570
+ const exists = await tableExists(tableName, config2.region);
17515
17571
  const emailHistory = exists ? new aws5.dynamodb.Table(
17516
17572
  tableName,
17517
17573
  {
@@ -18049,7 +18105,6 @@ async function createSESResources(config2) {
18049
18105
 
18050
18106
  // src/infrastructure/resources/smtp-credentials.ts
18051
18107
  init_esm_shims();
18052
- init_constants();
18053
18108
  import { createHmac as createHmac3 } from "crypto";
18054
18109
  import * as aws10 from "@pulumi/aws";
18055
18110
  function convertToSMTPPassword2(secretAccessKey, region) {
@@ -18139,11 +18194,11 @@ import * as aws11 from "@pulumi/aws";
18139
18194
  var SQS_TIMEOUTS = {
18140
18195
  customTimeouts: { create: "2m", update: "2m", delete: "2m" }
18141
18196
  };
18142
- async function createSQSResources() {
18197
+ async function createSQSResources(config2) {
18143
18198
  const dlqName = "wraps-email-events-dlq";
18144
18199
  const queueName = "wraps-email-events";
18145
- const dlqUrl = await sqsQueueExists(dlqName);
18146
- const queueUrl = await sqsQueueExists(queueName);
18200
+ const dlqUrl = await sqsQueueExists(dlqName, config2.region);
18201
+ const queueUrl = await sqsQueueExists(queueName, config2.region);
18147
18202
  const dlqConfig = {
18148
18203
  name: dlqName,
18149
18204
  messageRetentionSeconds: 1209600,
@@ -18282,12 +18337,13 @@ async function deployEmailStack(config2) {
18282
18337
  let dynamoTables;
18283
18338
  if (emailConfig.eventTracking?.dynamoDBHistory) {
18284
18339
  dynamoTables = await createDynamoDBTables({
18340
+ region: config2.region,
18285
18341
  retention: emailConfig.eventTracking.archiveRetention
18286
18342
  });
18287
18343
  }
18288
18344
  let sqsResources;
18289
18345
  if (emailConfig.eventTracking?.enabled) {
18290
- sqsResources = await createSQSResources();
18346
+ sqsResources = await createSQSResources({ region: config2.region });
18291
18347
  }
18292
18348
  if (emailConfig.eventTracking?.enabled && sesResources && sqsResources) {
18293
18349
  await createEventBridgeResources({
@@ -23723,7 +23779,8 @@ init_json_output();
23723
23779
  init_metadata();
23724
23780
  init_output();
23725
23781
  init_pulumi();
23726
- import * as clack28 from "@clack/prompts";
23782
+ init_region_resolver();
23783
+ import * as clack29 from "@clack/prompts";
23727
23784
  import * as pulumi21 from "@pulumi/pulumi";
23728
23785
  import pc30 from "picocolors";
23729
23786
  async function restore(options) {
@@ -23736,15 +23793,15 @@ async function restore(options) {
23736
23793
  );
23737
23794
  }
23738
23795
  if (!isJsonMode()) {
23739
- clack28.intro(
23796
+ clack29.intro(
23740
23797
  pc30.bold(
23741
23798
  options.preview ? "Wraps Restore Preview" : "Wraps Restore - Remove Wraps Infrastructure"
23742
23799
  )
23743
23800
  );
23744
- clack28.log.info(
23801
+ clack29.log.info(
23745
23802
  `${pc30.yellow("Note:")} This will remove all Wraps-managed infrastructure.`
23746
23803
  );
23747
- clack28.log.info(
23804
+ clack29.log.info(
23748
23805
  "Your original AWS resources remain untouched (Wraps never modifies them).\n"
23749
23806
  );
23750
23807
  }
@@ -23755,17 +23812,18 @@ async function restore(options) {
23755
23812
  async () => validateAWSCredentials()
23756
23813
  );
23757
23814
  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
- }
23815
+ const region = await resolveRegionForCommand({
23816
+ accountId: identity.accountId,
23817
+ optionRegion: options.region,
23818
+ service: "email",
23819
+ label: "email deployment"
23820
+ });
23763
23821
  const metadata = await loadConnectionMetadata(identity.accountId, region);
23764
23822
  if (!metadata) {
23765
- clack28.log.error(
23823
+ clack29.log.error(
23766
23824
  `No Wraps connection found for account ${pc30.cyan(identity.accountId)} in region ${pc30.cyan(region)}`
23767
23825
  );
23768
- clack28.log.info(
23826
+ clack29.log.info(
23769
23827
  `Use ${pc30.cyan("wraps email init")} or ${pc30.cyan("wraps email connect")} to create a connection first.`
23770
23828
  );
23771
23829
  process.exit(1);
@@ -23790,12 +23848,12 @@ ${pc30.bold("The following Wraps resources will be removed:")}
23790
23848
  console.log(` ${pc30.cyan("\u2713")} IAM Role (wraps-email-role)`);
23791
23849
  console.log("");
23792
23850
  if (!(options.force || options.preview)) {
23793
- const confirmed = await clack28.confirm({
23851
+ const confirmed = await clack29.confirm({
23794
23852
  message: "Proceed with removal? This cannot be undone.",
23795
23853
  initialValue: false
23796
23854
  });
23797
- if (clack28.isCancel(confirmed) || !confirmed) {
23798
- clack28.cancel("Removal cancelled.");
23855
+ if (clack29.isCancel(confirmed) || !confirmed) {
23856
+ clack29.cancel("Removal cancelled.");
23799
23857
  process.exit(0);
23800
23858
  }
23801
23859
  }
@@ -23835,7 +23893,7 @@ ${pc30.bold("The following Wraps resources will be removed:")}
23835
23893
  costEstimate: "Monthly cost after removal: $0.00",
23836
23894
  commandName: "wraps email restore"
23837
23895
  });
23838
- clack28.outro(
23896
+ clack29.outro(
23839
23897
  pc30.green(
23840
23898
  "Preview complete. Run without --preview to remove infrastructure."
23841
23899
  )
@@ -23928,7 +23986,7 @@ init_json_output();
23928
23986
  init_metadata();
23929
23987
  init_output();
23930
23988
  init_pulumi();
23931
- import * as clack29 from "@clack/prompts";
23989
+ import * as clack30 from "@clack/prompts";
23932
23990
  import * as pulumi22 from "@pulumi/pulumi";
23933
23991
  import pc31 from "picocolors";
23934
23992
  async function emailStatus(options) {
@@ -23936,7 +23994,7 @@ async function emailStatus(options) {
23936
23994
  const startTime = Date.now();
23937
23995
  const progress = new DeploymentProgress();
23938
23996
  if (!isJsonMode()) {
23939
- clack29.intro(pc31.bold("Wraps Email Status"));
23997
+ clack30.intro(pc31.bold("Wraps Email Status"));
23940
23998
  }
23941
23999
  const identity = await progress.execute(
23942
24000
  "Loading email infrastructure status",
@@ -23951,15 +24009,15 @@ async function emailStatus(options) {
23951
24009
  if (emailConnections.length === 1) {
23952
24010
  region = emailConnections[0].region;
23953
24011
  } else if (emailConnections.length > 1) {
23954
- const selectedRegion = await clack29.select({
24012
+ const selectedRegion = await clack30.select({
23955
24013
  message: "Multiple email deployments found. Which region?",
23956
24014
  options: emailConnections.map((conn) => ({
23957
24015
  value: conn.region,
23958
24016
  label: conn.region
23959
24017
  }))
23960
24018
  });
23961
- if (clack29.isCancel(selectedRegion)) {
23962
- clack29.cancel("Operation cancelled");
24019
+ if (clack30.isCancel(selectedRegion)) {
24020
+ clack30.cancel("Operation cancelled");
23963
24021
  process.exit(0);
23964
24022
  }
23965
24023
  region = selectedRegion;
@@ -23975,7 +24033,7 @@ async function emailStatus(options) {
23975
24033
  stackOutputs = await stack.outputs();
23976
24034
  } catch (_error) {
23977
24035
  progress.stop();
23978
- clack29.log.error("No email infrastructure found");
24036
+ clack30.log.error("No email infrastructure found");
23979
24037
  console.log(
23980
24038
  `
23981
24039
  Run ${pc31.cyan("wraps email init")} to deploy email infrastructure.
@@ -24071,7 +24129,7 @@ init_output();
24071
24129
  import { existsSync as existsSync9 } from "fs";
24072
24130
  import { mkdir as mkdir3, readFile as readFile4, writeFile as writeFile5 } from "fs/promises";
24073
24131
  import { join as join11 } from "path";
24074
- import * as clack30 from "@clack/prompts";
24132
+ import * as clack31 from "@clack/prompts";
24075
24133
  import pc32 from "picocolors";
24076
24134
 
24077
24135
  // src/utils/shared/scaffold-claude.ts
@@ -24518,7 +24576,7 @@ async function templatesInit(options) {
24518
24576
  const cwd = process.cwd();
24519
24577
  const wrapsDir = join11(cwd, "wraps");
24520
24578
  if (!isJsonMode()) {
24521
- clack30.intro(pc32.bold("Templates as Code"));
24579
+ clack31.intro(pc32.bold("Templates as Code"));
24522
24580
  }
24523
24581
  const progress = new DeploymentProgress();
24524
24582
  if (existsSync9(wrapsDir) && !options.force) {
@@ -24535,12 +24593,12 @@ async function templatesInit(options) {
24535
24593
  if (orgs?.length === 1) {
24536
24594
  orgSlug = orgs[0].slug;
24537
24595
  } else if (orgs && orgs.length > 1 && !isJsonMode()) {
24538
- const selected = await clack30.select({
24596
+ const selected = await clack31.select({
24539
24597
  message: "Which organization?",
24540
24598
  options: orgs.map((o) => ({ value: o.slug, label: o.name }))
24541
24599
  });
24542
- if (clack30.isCancel(selected)) {
24543
- clack30.cancel("Operation cancelled.");
24600
+ if (clack31.isCancel(selected)) {
24601
+ clack31.cancel("Operation cancelled.");
24544
24602
  process.exit(0);
24545
24603
  }
24546
24604
  orgSlug = selected;
@@ -24674,7 +24732,7 @@ wraps/.wraps/
24674
24732
  duration_ms: Date.now() - startTime
24675
24733
  });
24676
24734
  console.log();
24677
- clack30.log.success(pc32.green("Templates as Code initialized!"));
24735
+ clack31.log.success(pc32.green("Templates as Code initialized!"));
24678
24736
  console.log();
24679
24737
  console.log(` ${pc32.dim("Directory:")} ${pc32.cyan("wraps/")}`);
24680
24738
  console.log(` ${pc32.dim("Config:")} ${pc32.cyan("wraps/wraps.config.ts")}`);
@@ -24887,7 +24945,7 @@ init_esm_shims();
24887
24945
  init_events();
24888
24946
  import { existsSync as existsSync11, watch } from "fs";
24889
24947
  import { join as join13 } from "path";
24890
- import * as clack31 from "@clack/prompts";
24948
+ import * as clack32 from "@clack/prompts";
24891
24949
  import pc33 from "picocolors";
24892
24950
 
24893
24951
  // src/utils/email/template-compiler.ts
@@ -25012,7 +25070,7 @@ async function templatesPreview(options) {
25012
25070
  if (!existsSync11(configPath)) {
25013
25071
  throw errors.wrapsConfigNotFound();
25014
25072
  }
25015
- clack31.intro(pc33.bold("Preview Templates"));
25073
+ clack32.intro(pc33.bold("Preview Templates"));
25016
25074
  const config2 = await loadWrapsConfig(wrapsDir);
25017
25075
  const templatesDir = join13(wrapsDir, config2.templatesDir || "./templates");
25018
25076
  if (!existsSync11(templatesDir)) {
@@ -25020,7 +25078,7 @@ async function templatesPreview(options) {
25020
25078
  }
25021
25079
  const templateFiles = await discoverTemplates(templatesDir, options.template);
25022
25080
  if (templateFiles.length === 0) {
25023
- clack31.log.info("No templates found.");
25081
+ clack32.log.info("No templates found.");
25024
25082
  return;
25025
25083
  }
25026
25084
  const cache = /* @__PURE__ */ new Map();
@@ -25135,11 +25193,11 @@ async function templatesPreview(options) {
25135
25193
  success: true,
25136
25194
  template_count: templateFiles.length
25137
25195
  });
25138
- clack31.log.success(`Preview server running at ${pc33.cyan(url)}`);
25196
+ clack32.log.success(`Preview server running at ${pc33.cyan(url)}`);
25139
25197
  if (options.template) {
25140
- clack31.log.info(`Previewing: ${pc33.cyan(options.template)}`);
25198
+ clack32.log.info(`Previewing: ${pc33.cyan(options.template)}`);
25141
25199
  } else {
25142
- clack31.log.info(
25200
+ clack32.log.info(
25143
25201
  `${templateFiles.length} template${templateFiles.length === 1 ? "" : "s"} available`
25144
25202
  );
25145
25203
  }
@@ -25339,7 +25397,7 @@ import { createHash } from "crypto";
25339
25397
  import { existsSync as existsSync13 } from "fs";
25340
25398
  import { mkdir as mkdir6, readFile as readFile6, writeFile as writeFile8 } from "fs/promises";
25341
25399
  import { join as join15 } from "path";
25342
- import * as clack32 from "@clack/prompts";
25400
+ import * as clack33 from "@clack/prompts";
25343
25401
  import pc34 from "picocolors";
25344
25402
 
25345
25403
  // src/utils/email/template-render.ts
@@ -25460,7 +25518,7 @@ async function templatesPush(options) {
25460
25518
  throw errors.wrapsConfigNotFound();
25461
25519
  }
25462
25520
  if (!isJsonMode()) {
25463
- clack32.intro(pc34.bold("Push Templates"));
25521
+ clack33.intro(pc34.bold("Push Templates"));
25464
25522
  }
25465
25523
  const progress = new DeploymentProgress();
25466
25524
  progress.start("Loading configuration");
@@ -25473,7 +25531,7 @@ async function templatesPush(options) {
25473
25531
  const templateFiles = await discoverTemplates(templatesDir, options.template);
25474
25532
  if (templateFiles.length === 0) {
25475
25533
  if (!isJsonMode()) {
25476
- clack32.log.info("No templates found to push.");
25534
+ clack33.log.info("No templates found to push.");
25477
25535
  }
25478
25536
  return;
25479
25537
  }
@@ -25519,7 +25577,7 @@ async function templatesPush(options) {
25519
25577
  errors: []
25520
25578
  });
25521
25579
  } else {
25522
- clack32.log.info(
25580
+ clack33.log.info(
25523
25581
  `${unchanged.length} template${unchanged.length === 1 ? "" : "s"} unchanged. Use --force to re-push.`
25524
25582
  );
25525
25583
  }
@@ -25540,7 +25598,7 @@ async function templatesPush(options) {
25540
25598
  });
25541
25599
  } else {
25542
25600
  console.log();
25543
- clack32.log.info(pc34.bold("Dry run \u2014 no changes made"));
25601
+ clack33.log.info(pc34.bold("Dry run \u2014 no changes made"));
25544
25602
  console.log();
25545
25603
  for (const t of compiled) {
25546
25604
  console.log(
@@ -25592,16 +25650,16 @@ async function templatesPush(options) {
25592
25650
  });
25593
25651
  } else {
25594
25652
  console.log();
25595
- clack32.log.success(
25653
+ clack33.log.success(
25596
25654
  pc34.green(
25597
25655
  `${compiled.length} template${compiled.length === 1 ? "" : "s"} pushed`
25598
25656
  )
25599
25657
  );
25600
25658
  if (unchanged.length > 0) {
25601
- clack32.log.info(`${unchanged.length} unchanged (use --force to re-push)`);
25659
+ clack33.log.info(`${unchanged.length} unchanged (use --force to re-push)`);
25602
25660
  }
25603
25661
  if (compileErrors.length > 0) {
25604
- clack32.log.error(`${compileErrors.length} failed to compile`);
25662
+ clack33.log.error(`${compileErrors.length} failed to compile`);
25605
25663
  }
25606
25664
  console.log();
25607
25665
  }
@@ -25736,20 +25794,21 @@ function transformVariablesForSes(content) {
25736
25794
  }
25737
25795
  async function pushToSES(templates, progress) {
25738
25796
  const results = [];
25739
- let hasAWSCredentials = false;
25740
- let region = "us-east-1";
25797
+ const { validateAWSCredentialsWithDetails: validateAWSCredentialsWithDetails2 } = await Promise.resolve().then(() => (init_aws(), aws_exports));
25798
+ let identity;
25741
25799
  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();
25800
+ const result = await validateAWSCredentialsWithDetails2();
25801
+ identity = result.identity;
25746
25802
  } catch {
25747
25803
  progress.info("No AWS credentials \u2014 skipping SES push");
25748
25804
  return templates.map((t) => ({ slug: t.slug, success: false }));
25749
25805
  }
25750
- if (!hasAWSCredentials) {
25751
- return templates.map((t) => ({ slug: t.slug, success: false }));
25752
- }
25806
+ const { resolveRegionForCommand: resolveRegionForCommand2 } = await Promise.resolve().then(() => (init_region_resolver(), region_resolver_exports));
25807
+ const region = await resolveRegionForCommand2({
25808
+ accountId: identity.accountId,
25809
+ service: "email",
25810
+ label: "email deployment"
25811
+ });
25753
25812
  const {
25754
25813
  SESv2Client: SESv2Client9,
25755
25814
  CreateEmailTemplateCommand,
@@ -25979,7 +26038,7 @@ init_test();
25979
26038
 
25980
26039
  // src/commands/email/upgrade.ts
25981
26040
  init_esm_shims();
25982
- import * as clack33 from "@clack/prompts";
26041
+ import * as clack34 from "@clack/prompts";
25983
26042
  import * as pulumi23 from "@pulumi/pulumi";
25984
26043
  import pc35 from "picocolors";
25985
26044
  init_events();
@@ -25995,11 +26054,12 @@ init_metadata();
25995
26054
  init_output();
25996
26055
  init_prompts();
25997
26056
  init_pulumi();
26057
+ init_region_resolver();
25998
26058
  async function upgrade(options) {
25999
26059
  const startTime = Date.now();
26000
26060
  let upgradeAction = "";
26001
26061
  if (!isJsonMode()) {
26002
- clack33.intro(
26062
+ clack34.intro(
26003
26063
  pc35.bold(
26004
26064
  options.preview ? "Wraps Upgrade Preview" : "Wraps Upgrade - Enhance Your Email Infrastructure"
26005
26065
  )
@@ -26018,17 +26078,18 @@ async function upgrade(options) {
26018
26078
  async () => validateAWSCredentials()
26019
26079
  );
26020
26080
  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
- }
26081
+ const region = await resolveRegionForCommand({
26082
+ accountId: identity.accountId,
26083
+ optionRegion: options.region,
26084
+ service: "email",
26085
+ label: "email deployment"
26086
+ });
26026
26087
  const metadata = await loadConnectionMetadata(identity.accountId, region);
26027
26088
  if (!metadata) {
26028
- clack33.log.error(
26089
+ clack34.log.error(
26029
26090
  `No Wraps connection found for account ${pc35.cyan(identity.accountId)} in region ${pc35.cyan(region)}`
26030
26091
  );
26031
- clack33.log.info(
26092
+ clack34.log.info(
26032
26093
  `Use ${pc35.cyan("wraps email init")} to create new infrastructure or ${pc35.cyan("wraps email connect")} to connect existing.`
26033
26094
  );
26034
26095
  process.exit(1);
@@ -26044,8 +26105,8 @@ ${pc35.bold("Current Configuration:")}
26044
26105
  }
26045
26106
  const config2 = metadata.services.email?.config;
26046
26107
  if (!config2) {
26047
- clack33.log.error("No email configuration found in metadata");
26048
- clack33.log.info(
26108
+ clack34.log.error("No email configuration found in metadata");
26109
+ clack34.log.info(
26049
26110
  `Use ${pc35.cyan("wraps email init")} to create new infrastructure.`
26050
26111
  );
26051
26112
  process.exit(1);
@@ -26198,12 +26259,12 @@ ${pc35.bold("Current Configuration:")}
26198
26259
  if (options.action) {
26199
26260
  upgradeAction = options.action;
26200
26261
  } else {
26201
- upgradeAction = await clack33.select({
26262
+ upgradeAction = await clack34.select({
26202
26263
  message: "What would you like to do?",
26203
26264
  options: upgradeOptions
26204
26265
  });
26205
- if (clack33.isCancel(upgradeAction)) {
26206
- clack33.cancel("Upgrade cancelled.");
26266
+ if (clack34.isCancel(upgradeAction)) {
26267
+ clack34.cancel("Upgrade cancelled.");
26207
26268
  process.exit(0);
26208
26269
  }
26209
26270
  }
@@ -26211,7 +26272,7 @@ ${pc35.bold("Current Configuration:")}
26211
26272
  let newPreset = metadata.services.email?.preset;
26212
26273
  switch (upgradeAction) {
26213
26274
  case "finish-tracking-domain": {
26214
- clack33.log.info(
26275
+ clack34.log.info(
26215
26276
  `Checking certificate status for ${pc35.cyan(config2.tracking?.customRedirectDomain ?? "")}...`
26216
26277
  );
26217
26278
  updatedConfig = { ...config2 };
@@ -26232,19 +26293,19 @@ ${pc35.bold("Current Configuration:")}
26232
26293
  disabled: currentPresetIdx >= 0 && idx <= currentPresetIdx ? "Current or lower tier" : void 0
26233
26294
  })).filter((p) => !p.disabled);
26234
26295
  if (availablePresets.length === 0) {
26235
- clack33.log.warn("Already on highest preset (Enterprise)");
26296
+ clack34.log.warn("Already on highest preset (Enterprise)");
26236
26297
  process.exit(0);
26237
26298
  }
26238
26299
  let selectedPreset;
26239
26300
  if (options.preset) {
26240
26301
  selectedPreset = options.preset;
26241
26302
  } else {
26242
- selectedPreset = await clack33.select({
26303
+ selectedPreset = await clack34.select({
26243
26304
  message: "Select new preset:",
26244
26305
  options: availablePresets
26245
26306
  });
26246
- if (clack33.isCancel(selectedPreset)) {
26247
- clack33.cancel("Upgrade cancelled.");
26307
+ if (clack34.isCancel(selectedPreset)) {
26308
+ clack34.cancel("Upgrade cancelled.");
26248
26309
  process.exit(0);
26249
26310
  }
26250
26311
  }
@@ -26255,7 +26316,7 @@ ${pc35.bold("Current Configuration:")}
26255
26316
  }
26256
26317
  case "archiving": {
26257
26318
  if (config2.emailArchiving?.enabled) {
26258
- const archivingAction = await clack33.select({
26319
+ const archivingAction = await clack34.select({
26259
26320
  message: "What would you like to do with email archiving?",
26260
26321
  options: [
26261
26322
  {
@@ -26270,17 +26331,17 @@ ${pc35.bold("Current Configuration:")}
26270
26331
  }
26271
26332
  ]
26272
26333
  });
26273
- if (clack33.isCancel(archivingAction)) {
26274
- clack33.cancel("Upgrade cancelled.");
26334
+ if (clack34.isCancel(archivingAction)) {
26335
+ clack34.cancel("Upgrade cancelled.");
26275
26336
  process.exit(0);
26276
26337
  }
26277
26338
  if (archivingAction === "disable") {
26278
- const confirmDisable = await clack33.confirm({
26339
+ const confirmDisable = await clack34.confirm({
26279
26340
  message: "Are you sure? Existing archived emails will remain, but new emails won't be archived.",
26280
26341
  initialValue: false
26281
26342
  });
26282
- if (clack33.isCancel(confirmDisable) || !confirmDisable) {
26283
- clack33.cancel("Archiving not disabled.");
26343
+ if (clack34.isCancel(confirmDisable) || !confirmDisable) {
26344
+ clack34.cancel("Archiving not disabled.");
26284
26345
  process.exit(0);
26285
26346
  }
26286
26347
  updatedConfig = {
@@ -26291,7 +26352,7 @@ ${pc35.bold("Current Configuration:")}
26291
26352
  }
26292
26353
  };
26293
26354
  } else {
26294
- const retention = await clack33.select({
26355
+ const retention = await clack34.select({
26295
26356
  message: "Email archive retention period:",
26296
26357
  options: [
26297
26358
  {
@@ -26327,8 +26388,8 @@ ${pc35.bold("Current Configuration:")}
26327
26388
  ],
26328
26389
  initialValue: config2.emailArchiving.retention
26329
26390
  });
26330
- if (clack33.isCancel(retention)) {
26331
- clack33.cancel("Upgrade cancelled.");
26391
+ if (clack34.isCancel(retention)) {
26392
+ clack34.cancel("Upgrade cancelled.");
26332
26393
  process.exit(0);
26333
26394
  }
26334
26395
  updatedConfig = {
@@ -26340,19 +26401,19 @@ ${pc35.bold("Current Configuration:")}
26340
26401
  };
26341
26402
  }
26342
26403
  } else {
26343
- const enableArchiving = await clack33.confirm({
26404
+ const enableArchiving = await clack34.confirm({
26344
26405
  message: "Enable email archiving? (Store full email content with HTML for viewing)",
26345
26406
  initialValue: true
26346
26407
  });
26347
- if (clack33.isCancel(enableArchiving)) {
26348
- clack33.cancel("Upgrade cancelled.");
26408
+ if (clack34.isCancel(enableArchiving)) {
26409
+ clack34.cancel("Upgrade cancelled.");
26349
26410
  process.exit(0);
26350
26411
  }
26351
26412
  if (!enableArchiving) {
26352
- clack33.log.info("Email archiving not enabled.");
26413
+ clack34.log.info("Email archiving not enabled.");
26353
26414
  process.exit(0);
26354
26415
  }
26355
- const retention = await clack33.select({
26416
+ const retention = await clack34.select({
26356
26417
  message: "Email archive retention period:",
26357
26418
  options: [
26358
26419
  {
@@ -26388,16 +26449,16 @@ ${pc35.bold("Current Configuration:")}
26388
26449
  ],
26389
26450
  initialValue: "90days"
26390
26451
  });
26391
- if (clack33.isCancel(retention)) {
26392
- clack33.cancel("Upgrade cancelled.");
26452
+ if (clack34.isCancel(retention)) {
26453
+ clack34.cancel("Upgrade cancelled.");
26393
26454
  process.exit(0);
26394
26455
  }
26395
- clack33.log.info(
26456
+ clack34.log.info(
26396
26457
  pc35.dim(
26397
26458
  "Archiving stores full RFC 822 emails with HTML, attachments, and headers"
26398
26459
  )
26399
26460
  );
26400
- clack33.log.info(
26461
+ clack34.log.info(
26401
26462
  pc35.dim(
26402
26463
  "Cost: $2/GB ingestion + $0.19/GB/month storage (~50KB per email)"
26403
26464
  )
@@ -26415,10 +26476,10 @@ ${pc35.bold("Current Configuration:")}
26415
26476
  }
26416
26477
  case "tracking-domain": {
26417
26478
  if (!config2.domain) {
26418
- clack33.log.error(
26479
+ clack34.log.error(
26419
26480
  "No sending domain configured. You must configure a sending domain before adding a custom tracking domain."
26420
26481
  );
26421
- clack33.log.info(
26482
+ clack34.log.info(
26422
26483
  `Use ${pc35.cyan("wraps email init")} to set up a sending domain first.`
26423
26484
  );
26424
26485
  process.exit(1);
@@ -26430,13 +26491,13 @@ ${pc35.bold("Current Configuration:")}
26430
26491
  );
26431
26492
  const sendingDomain = domains.find((d) => d.domain === config2.domain);
26432
26493
  if (!sendingDomain?.verified) {
26433
- clack33.log.error(
26494
+ clack34.log.error(
26434
26495
  `Sending domain ${pc35.cyan(config2.domain)} is not verified.`
26435
26496
  );
26436
- clack33.log.info(
26497
+ clack34.log.info(
26437
26498
  "You must verify your sending domain before adding a custom tracking domain."
26438
26499
  );
26439
- clack33.log.info(
26500
+ clack34.log.info(
26440
26501
  `Use ${pc35.cyan("wraps email verify")} to check DNS records and complete verification.`
26441
26502
  );
26442
26503
  process.exit(1);
@@ -26444,7 +26505,7 @@ ${pc35.bold("Current Configuration:")}
26444
26505
  progress.info(
26445
26506
  `Sending domain ${pc35.cyan(config2.domain)} is verified ${pc35.green("\u2713")}`
26446
26507
  );
26447
- const trackingDomain = await clack33.text({
26508
+ const trackingDomain = await clack34.text({
26448
26509
  message: "Custom tracking redirect domain:",
26449
26510
  placeholder: "track.yourdomain.com",
26450
26511
  initialValue: config2.tracking?.customRedirectDomain || "",
@@ -26454,25 +26515,25 @@ ${pc35.bold("Current Configuration:")}
26454
26515
  }
26455
26516
  }
26456
26517
  });
26457
- if (clack33.isCancel(trackingDomain)) {
26458
- clack33.cancel("Upgrade cancelled.");
26518
+ if (clack34.isCancel(trackingDomain)) {
26519
+ clack34.cancel("Upgrade cancelled.");
26459
26520
  process.exit(0);
26460
26521
  }
26461
- const enableHttps = await clack33.confirm({
26522
+ const enableHttps = await clack34.confirm({
26462
26523
  message: "Enable HTTPS tracking with CloudFront + SSL certificate?",
26463
26524
  initialValue: true
26464
26525
  });
26465
- if (clack33.isCancel(enableHttps)) {
26466
- clack33.cancel("Upgrade cancelled.");
26526
+ if (clack34.isCancel(enableHttps)) {
26527
+ clack34.cancel("Upgrade cancelled.");
26467
26528
  process.exit(0);
26468
26529
  }
26469
26530
  if (enableHttps) {
26470
- clack33.log.info(
26531
+ clack34.log.info(
26471
26532
  pc35.dim(
26472
26533
  "HTTPS tracking creates a CloudFront distribution with an SSL certificate."
26473
26534
  )
26474
26535
  );
26475
- clack33.log.info(
26536
+ clack34.log.info(
26476
26537
  pc35.dim(
26477
26538
  "This ensures all tracking links use secure HTTPS connections."
26478
26539
  )
@@ -26503,32 +26564,32 @@ ${pc35.bold("Current Configuration:")}
26503
26564
  progress.info(
26504
26565
  `Found ${pc35.cyan(getDNSProviderDisplayName(detectedProvider.provider))} ${pc35.green("\u2713")}`
26505
26566
  );
26506
- clack33.log.info(
26567
+ clack34.log.info(
26507
26568
  pc35.dim(
26508
26569
  "DNS records (SSL certificate validation + CloudFront) will be created automatically."
26509
26570
  )
26510
26571
  );
26511
26572
  } else {
26512
26573
  canAutomateDNS = false;
26513
- clack33.log.warn(
26574
+ clack34.log.warn(
26514
26575
  `No automatic DNS provider detected for ${pc35.cyan(trackingDomain || config2.domain)}`
26515
26576
  );
26516
- clack33.log.info(
26577
+ clack34.log.info(
26517
26578
  pc35.dim(
26518
26579
  "You'll need to manually create DNS records for SSL certificate validation and CloudFront."
26519
26580
  )
26520
26581
  );
26521
- clack33.log.info(
26582
+ clack34.log.info(
26522
26583
  pc35.dim("DNS record details will be shown after deployment.")
26523
26584
  );
26524
26585
  }
26525
26586
  }
26526
- const confirmHttps = await clack33.confirm({
26587
+ const confirmHttps = await clack34.confirm({
26527
26588
  message: canAutomateDNS ? "Proceed with automatic HTTPS setup?" : "Proceed with manual HTTPS setup (requires DNS configuration)?",
26528
26589
  initialValue: true
26529
26590
  });
26530
- if (clack33.isCancel(confirmHttps) || !confirmHttps) {
26531
- clack33.log.info("HTTPS tracking not enabled. Using HTTP tracking.");
26591
+ if (clack34.isCancel(confirmHttps) || !confirmHttps) {
26592
+ clack34.log.info("HTTPS tracking not enabled. Using HTTP tracking.");
26532
26593
  updatedConfig = {
26533
26594
  ...config2,
26534
26595
  tracking: {
@@ -26550,7 +26611,7 @@ ${pc35.bold("Current Configuration:")}
26550
26611
  };
26551
26612
  }
26552
26613
  } else {
26553
- clack33.log.info(
26614
+ clack34.log.info(
26554
26615
  pc35.dim(
26555
26616
  "Using HTTP tracking (standard). Links will use http:// protocol."
26556
26617
  )
@@ -26569,7 +26630,7 @@ ${pc35.bold("Current Configuration:")}
26569
26630
  break;
26570
26631
  }
26571
26632
  case "retention": {
26572
- const retention = await clack33.select({
26633
+ const retention = await clack34.select({
26573
26634
  message: "Email history retention period (event data in DynamoDB):",
26574
26635
  options: [
26575
26636
  { value: "7days", label: "7 days", hint: "Minimal storage cost" },
@@ -26593,16 +26654,16 @@ ${pc35.bold("Current Configuration:")}
26593
26654
  ],
26594
26655
  initialValue: config2.eventTracking?.archiveRetention || "90days"
26595
26656
  });
26596
- if (clack33.isCancel(retention)) {
26597
- clack33.cancel("Upgrade cancelled.");
26657
+ if (clack34.isCancel(retention)) {
26658
+ clack34.cancel("Upgrade cancelled.");
26598
26659
  process.exit(0);
26599
26660
  }
26600
- clack33.log.info(
26661
+ clack34.log.info(
26601
26662
  pc35.dim(
26602
26663
  "Note: This is for event data (sent, delivered, opened, etc.) stored in DynamoDB."
26603
26664
  )
26604
26665
  );
26605
- clack33.log.info(
26666
+ clack34.log.info(
26606
26667
  pc35.dim(
26607
26668
  "For full email content storage, use 'Enable email archiving' option."
26608
26669
  )
@@ -26620,7 +26681,7 @@ ${pc35.bold("Current Configuration:")}
26620
26681
  break;
26621
26682
  }
26622
26683
  case "events": {
26623
- const selectedEvents = await clack33.multiselect({
26684
+ const selectedEvents = await clack34.multiselect({
26624
26685
  message: "Select SES event types to track:",
26625
26686
  options: [
26626
26687
  { value: "SEND", label: "Send", hint: "Email sent to SES" },
@@ -26664,8 +26725,8 @@ ${pc35.bold("Current Configuration:")}
26664
26725
  ],
26665
26726
  required: true
26666
26727
  });
26667
- if (clack33.isCancel(selectedEvents)) {
26668
- clack33.cancel("Upgrade cancelled.");
26728
+ if (clack34.isCancel(selectedEvents)) {
26729
+ clack34.cancel("Upgrade cancelled.");
26669
26730
  process.exit(0);
26670
26731
  }
26671
26732
  updatedConfig = {
@@ -26680,16 +26741,16 @@ ${pc35.bold("Current Configuration:")}
26680
26741
  break;
26681
26742
  }
26682
26743
  case "dedicated-ip": {
26683
- const confirmed = await clack33.confirm({
26744
+ const confirmed = await clack34.confirm({
26684
26745
  message: "Enable dedicated IP? (Requires 100k+ emails/day, adds ~$50-100/mo)",
26685
26746
  initialValue: false
26686
26747
  });
26687
- if (clack33.isCancel(confirmed)) {
26688
- clack33.cancel("Upgrade cancelled.");
26748
+ if (clack34.isCancel(confirmed)) {
26749
+ clack34.cancel("Upgrade cancelled.");
26689
26750
  process.exit(0);
26690
26751
  }
26691
26752
  if (!confirmed) {
26692
- clack33.log.info("Dedicated IP not enabled.");
26753
+ clack34.log.info("Dedicated IP not enabled.");
26693
26754
  process.exit(0);
26694
26755
  }
26695
26756
  updatedConfig = {
@@ -26701,16 +26762,16 @@ ${pc35.bold("Current Configuration:")}
26701
26762
  }
26702
26763
  case "alerts": {
26703
26764
  if (!config2.reputationMetrics) {
26704
- clack33.log.warn("Reputation metrics must be enabled to use alerting.");
26705
- clack33.log.info(
26765
+ clack34.log.warn("Reputation metrics must be enabled to use alerting.");
26766
+ clack34.log.info(
26706
26767
  "This requires the Production or Enterprise preset, or enabling reputation metrics manually."
26707
26768
  );
26708
- const enableReputationMetrics = await clack33.confirm({
26769
+ const enableReputationMetrics = await clack34.confirm({
26709
26770
  message: "Enable reputation metrics now?",
26710
26771
  initialValue: true
26711
26772
  });
26712
- if (clack33.isCancel(enableReputationMetrics) || !enableReputationMetrics) {
26713
- clack33.cancel("Alerting not enabled.");
26773
+ if (clack34.isCancel(enableReputationMetrics) || !enableReputationMetrics) {
26774
+ clack34.cancel("Alerting not enabled.");
26714
26775
  process.exit(0);
26715
26776
  }
26716
26777
  updatedConfig = {
@@ -26719,13 +26780,13 @@ ${pc35.bold("Current Configuration:")}
26719
26780
  };
26720
26781
  }
26721
26782
  if (config2.alerts?.enabled) {
26722
- clack33.log.info(`Alerting is currently ${pc35.green("enabled")}`);
26783
+ clack34.log.info(`Alerting is currently ${pc35.green("enabled")}`);
26723
26784
  if (config2.alerts.notificationEmail) {
26724
- clack33.log.info(
26785
+ clack34.log.info(
26725
26786
  ` Notification email: ${pc35.cyan(config2.alerts.notificationEmail)}`
26726
26787
  );
26727
26788
  }
26728
- const alertsAction = await clack33.select({
26789
+ const alertsAction = await clack34.select({
26729
26790
  message: "What would you like to do?",
26730
26791
  options: [
26731
26792
  {
@@ -26745,17 +26806,17 @@ ${pc35.bold("Current Configuration:")}
26745
26806
  }
26746
26807
  ]
26747
26808
  });
26748
- if (clack33.isCancel(alertsAction)) {
26749
- clack33.cancel("Upgrade cancelled.");
26809
+ if (clack34.isCancel(alertsAction)) {
26810
+ clack34.cancel("Upgrade cancelled.");
26750
26811
  process.exit(0);
26751
26812
  }
26752
26813
  if (alertsAction === "disable") {
26753
- const confirmDisable = await clack33.confirm({
26814
+ const confirmDisable = await clack34.confirm({
26754
26815
  message: "Are you sure? You won't be notified if your reputation degrades.",
26755
26816
  initialValue: false
26756
26817
  });
26757
- if (clack33.isCancel(confirmDisable) || !confirmDisable) {
26758
- clack33.log.info("Alerting not disabled.");
26818
+ if (clack34.isCancel(confirmDisable) || !confirmDisable) {
26819
+ clack34.log.info("Alerting not disabled.");
26759
26820
  process.exit(0);
26760
26821
  }
26761
26822
  updatedConfig = {
@@ -26763,7 +26824,7 @@ ${pc35.bold("Current Configuration:")}
26763
26824
  alerts: { enabled: false }
26764
26825
  };
26765
26826
  } else if (alertsAction === "change-email") {
26766
- const notificationEmail = await clack33.text({
26827
+ const notificationEmail = await clack34.text({
26767
26828
  message: "Notification email address:",
26768
26829
  placeholder: "alerts@yourcompany.com",
26769
26830
  initialValue: config2.alerts.notificationEmail || "",
@@ -26773,8 +26834,8 @@ ${pc35.bold("Current Configuration:")}
26773
26834
  }
26774
26835
  }
26775
26836
  });
26776
- if (clack33.isCancel(notificationEmail)) {
26777
- clack33.cancel("Upgrade cancelled.");
26837
+ if (clack34.isCancel(notificationEmail)) {
26838
+ clack34.cancel("Upgrade cancelled.");
26778
26839
  process.exit(0);
26779
26840
  }
26780
26841
  updatedConfig = {
@@ -26786,14 +26847,14 @@ ${pc35.bold("Current Configuration:")}
26786
26847
  }
26787
26848
  };
26788
26849
  } else if (alertsAction === "change-thresholds") {
26789
- clack33.log.info(`
26850
+ clack34.log.info(`
26790
26851
  ${pc35.bold("Alert Thresholds")}`);
26791
- clack33.log.info(
26852
+ clack34.log.info(
26792
26853
  pc35.dim("These thresholds warn you BEFORE AWS takes action:")
26793
26854
  );
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({
26855
+ clack34.log.info(pc35.dim(" AWS warns at 5% bounce, 0.1% complaint"));
26856
+ clack34.log.info(pc35.dim(" Gmail blocks at 0.3% complaint rate\n"));
26857
+ const thresholdPreset = await clack34.select({
26797
26858
  message: "Choose threshold sensitivity:",
26798
26859
  options: [
26799
26860
  {
@@ -26813,8 +26874,8 @@ ${pc35.bold("Alert Thresholds")}`);
26813
26874
  }
26814
26875
  ]
26815
26876
  });
26816
- if (clack33.isCancel(thresholdPreset)) {
26817
- clack33.cancel("Upgrade cancelled.");
26877
+ if (clack34.isCancel(thresholdPreset)) {
26878
+ clack34.cancel("Upgrade cancelled.");
26818
26879
  process.exit(0);
26819
26880
  }
26820
26881
  const thresholdConfigs = {
@@ -26847,27 +26908,27 @@ ${pc35.bold("Alert Thresholds")}`);
26847
26908
  };
26848
26909
  }
26849
26910
  } else {
26850
- clack33.log.info(`
26911
+ clack34.log.info(`
26851
26912
  ${pc35.bold("Reputation Alerts")}
26852
26913
  `);
26853
- clack33.log.info(
26914
+ clack34.log.info(
26854
26915
  pc35.dim("Get notified when your email reputation is at risk:")
26855
26916
  );
26856
- clack33.log.info(pc35.dim(" - Bounce rate warnings (before AWS review)"));
26857
- clack33.log.info(
26917
+ clack34.log.info(pc35.dim(" - Bounce rate warnings (before AWS review)"));
26918
+ clack34.log.info(
26858
26919
  pc35.dim(" - Complaint rate warnings (before Gmail blocks you)")
26859
26920
  );
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({
26921
+ clack34.log.info(pc35.dim(" - DLQ alerts (event processing failures)"));
26922
+ clack34.log.info(pc35.dim("\nCost: ~$0.50/mo (5 CloudWatch alarms)\n"));
26923
+ const enableAlerts = await clack34.confirm({
26863
26924
  message: "Enable reputation alerts?",
26864
26925
  initialValue: true
26865
26926
  });
26866
- if (clack33.isCancel(enableAlerts) || !enableAlerts) {
26867
- clack33.log.info("Alerting not enabled.");
26927
+ if (clack34.isCancel(enableAlerts) || !enableAlerts) {
26928
+ clack34.log.info("Alerting not enabled.");
26868
26929
  process.exit(0);
26869
26930
  }
26870
- const notificationEmail = await clack33.text({
26931
+ const notificationEmail = await clack34.text({
26871
26932
  message: "Notification email address:",
26872
26933
  placeholder: "alerts@yourcompany.com",
26873
26934
  validate: (value) => {
@@ -26879,11 +26940,11 @@ ${pc35.bold("Reputation Alerts")}
26879
26940
  }
26880
26941
  }
26881
26942
  });
26882
- if (clack33.isCancel(notificationEmail)) {
26883
- clack33.cancel("Upgrade cancelled.");
26943
+ if (clack34.isCancel(notificationEmail)) {
26944
+ clack34.cancel("Upgrade cancelled.");
26884
26945
  process.exit(0);
26885
26946
  }
26886
- clack33.log.info(
26947
+ clack34.log.info(
26887
26948
  pc35.dim("\nYou'll receive an email to confirm your subscription.")
26888
26949
  );
26889
26950
  updatedConfig = {
@@ -26910,18 +26971,18 @@ ${pc35.bold("Reputation Alerts")}
26910
26971
  }
26911
26972
  case "wraps-dashboard": {
26912
26973
  if (!config2.eventTracking?.enabled) {
26913
- clack33.log.warn(
26974
+ clack34.log.warn(
26914
26975
  "Event tracking must be enabled to connect to Wraps Dashboard."
26915
26976
  );
26916
- clack33.log.info(
26977
+ clack34.log.info(
26917
26978
  "Enabling event tracking will allow SES events to be sent to the dashboard."
26918
26979
  );
26919
- const enableEventTracking = await clack33.confirm({
26980
+ const enableEventTracking = await clack34.confirm({
26920
26981
  message: "Enable event tracking now?",
26921
26982
  initialValue: true
26922
26983
  });
26923
- if (clack33.isCancel(enableEventTracking) || !enableEventTracking) {
26924
- clack33.cancel("Dashboard connection cancelled.");
26984
+ if (clack34.isCancel(enableEventTracking) || !enableEventTracking) {
26985
+ clack34.cancel("Dashboard connection cancelled.");
26925
26986
  process.exit(0);
26926
26987
  }
26927
26988
  updatedConfig = {
@@ -26944,10 +27005,10 @@ ${pc35.bold("Reputation Alerts")}
26944
27005
  }
26945
27006
  const existingSecret = metadata.services.email?.webhookSecret;
26946
27007
  if (existingSecret) {
26947
- clack33.log.info(
27008
+ clack34.log.info(
26948
27009
  `Currently connected to Wraps Dashboard (AWS Account: ${pc35.cyan(metadata.accountId)})`
26949
27010
  );
26950
- const action = await clack33.select({
27011
+ const action = await clack34.select({
26951
27012
  message: "What would you like to do?",
26952
27013
  options: [
26953
27014
  {
@@ -26967,17 +27028,17 @@ ${pc35.bold("Reputation Alerts")}
26967
27028
  }
26968
27029
  ]
26969
27030
  });
26970
- if (clack33.isCancel(action) || action === "cancel") {
26971
- clack33.log.info("No changes made.");
27031
+ if (clack34.isCancel(action) || action === "cancel") {
27032
+ clack34.log.info("No changes made.");
26972
27033
  process.exit(0);
26973
27034
  }
26974
27035
  if (action === "disconnect") {
26975
- const confirmDisconnect = await clack33.confirm({
27036
+ const confirmDisconnect = await clack34.confirm({
26976
27037
  message: "Are you sure? Events will no longer be sent to the Wraps Dashboard.",
26977
27038
  initialValue: false
26978
27039
  });
26979
- if (clack33.isCancel(confirmDisconnect) || !confirmDisconnect) {
26980
- clack33.log.info("Disconnect cancelled.");
27040
+ if (clack34.isCancel(confirmDisconnect) || !confirmDisconnect) {
27041
+ clack34.log.info("Disconnect cancelled.");
26981
27042
  process.exit(0);
26982
27043
  }
26983
27044
  if (metadata.services.email) {
@@ -26989,12 +27050,12 @@ ${pc35.bold("Reputation Alerts")}
26989
27050
  }
26990
27051
  }
26991
27052
  const webhookSecret = generateWebhookSecret();
26992
- clack33.log.info(`
27053
+ clack34.log.info(`
26993
27054
  ${pc35.bold("Webhook Configuration:")}`);
26994
- clack33.log.info(
27055
+ clack34.log.info(
26995
27056
  pc35.dim("A secure webhook secret has been generated for authentication.")
26996
27057
  );
26997
- clack33.log.info(
27058
+ clack34.log.info(
26998
27059
  pc35.dim(
26999
27060
  "After deployment, you'll need to register this secret in the dashboard.\n"
27000
27061
  )
@@ -27040,18 +27101,18 @@ ${pc35.bold("Webhook Configuration:")}`);
27040
27101
  }
27041
27102
  };
27042
27103
  if (!config2.eventTracking?.enabled) {
27043
- clack33.log.warn(
27104
+ clack34.log.warn(
27044
27105
  "Event tracking must be enabled to configure a webhook endpoint."
27045
27106
  );
27046
- clack33.log.info(
27107
+ clack34.log.info(
27047
27108
  "Enabling event tracking will allow SES events to be sent to your endpoint."
27048
27109
  );
27049
- const enableEventTracking = await clack33.confirm({
27110
+ const enableEventTracking = await clack34.confirm({
27050
27111
  message: "Enable event tracking now?",
27051
27112
  initialValue: true
27052
27113
  });
27053
- if (clack33.isCancel(enableEventTracking) || !enableEventTracking) {
27054
- clack33.cancel("Webhook configuration cancelled.");
27114
+ if (clack34.isCancel(enableEventTracking) || !enableEventTracking) {
27115
+ clack34.cancel("Webhook configuration cancelled.");
27055
27116
  process.exit(0);
27056
27117
  }
27057
27118
  updatedConfig = {
@@ -27073,10 +27134,10 @@ ${pc35.bold("Webhook Configuration:")}`);
27073
27134
  };
27074
27135
  }
27075
27136
  if (config2.userWebhook?.enabled) {
27076
- clack33.log.info(
27137
+ clack34.log.info(
27077
27138
  `Webhook endpoint currently sending events to: ${pc35.cyan(config2.userWebhook.url)}`
27078
27139
  );
27079
- const action = await clack33.select({
27140
+ const action = await clack34.select({
27080
27141
  message: "What would you like to do?",
27081
27142
  options: [
27082
27143
  {
@@ -27101,17 +27162,17 @@ ${pc35.bold("Webhook Configuration:")}`);
27101
27162
  }
27102
27163
  ]
27103
27164
  });
27104
- if (clack33.isCancel(action) || action === "cancel") {
27105
- clack33.log.info("No changes made.");
27165
+ if (clack34.isCancel(action) || action === "cancel") {
27166
+ clack34.log.info("No changes made.");
27106
27167
  process.exit(0);
27107
27168
  }
27108
27169
  if (action === "disable") {
27109
- const confirmDisable = await clack33.confirm({
27170
+ const confirmDisable = await clack34.confirm({
27110
27171
  message: "Are you sure? Events will no longer be sent to your webhook endpoint.",
27111
27172
  initialValue: false
27112
27173
  });
27113
- if (clack33.isCancel(confirmDisable) || !confirmDisable) {
27114
- clack33.log.info("Webhook not disabled.");
27174
+ if (clack34.isCancel(confirmDisable) || !confirmDisable) {
27175
+ clack34.log.info("Webhook not disabled.");
27115
27176
  process.exit(0);
27116
27177
  }
27117
27178
  updatedConfig = {
@@ -27122,13 +27183,13 @@ ${pc35.bold("Webhook Configuration:")}`);
27122
27183
  break;
27123
27184
  }
27124
27185
  if (action === "change-url") {
27125
- const newUrl = await clack33.text({
27186
+ const newUrl = await clack34.text({
27126
27187
  message: "New webhook URL:",
27127
27188
  placeholder: "https://your-app.com/webhooks/email-events",
27128
27189
  validate: validateWebhookUrl
27129
27190
  });
27130
- if (clack33.isCancel(newUrl)) {
27131
- clack33.cancel("Webhook configuration cancelled.");
27191
+ if (clack34.isCancel(newUrl)) {
27192
+ clack34.cancel("Webhook configuration cancelled.");
27132
27193
  process.exit(0);
27133
27194
  }
27134
27195
  updatedConfig = {
@@ -27156,20 +27217,20 @@ ${pc35.bold("Webhook Configuration:")}`);
27156
27217
  break;
27157
27218
  }
27158
27219
  } else {
27159
- clack33.log.info(`
27220
+ clack34.log.info(`
27160
27221
  ${pc35.bold("Webhook Endpoint")}
27161
27222
  `);
27162
- clack33.log.info(
27223
+ clack34.log.info(
27163
27224
  pc35.dim("Send SES events (send, delivery, open, click, bounce, etc.)")
27164
27225
  );
27165
- clack33.log.info(pc35.dim("to your own HTTP endpoint in real-time.\n"));
27166
- const webhookUrl = await clack33.text({
27226
+ clack34.log.info(pc35.dim("to your own HTTP endpoint in real-time.\n"));
27227
+ const webhookUrl = await clack34.text({
27167
27228
  message: "Webhook URL (must be HTTPS):",
27168
27229
  placeholder: "https://your-app.com/webhooks/email-events",
27169
27230
  validate: validateWebhookUrl
27170
27231
  });
27171
- if (clack33.isCancel(webhookUrl)) {
27172
- clack33.cancel("Webhook configuration cancelled.");
27232
+ if (clack34.isCancel(webhookUrl)) {
27233
+ clack34.cancel("Webhook configuration cancelled.");
27173
27234
  process.exit(0);
27174
27235
  }
27175
27236
  const secret2 = generateWebhookSecret();
@@ -27187,10 +27248,10 @@ ${pc35.bold("Webhook Endpoint")}
27187
27248
  }
27188
27249
  case "smtp-credentials": {
27189
27250
  if (metadata.services.email?.smtpCredentials?.enabled) {
27190
- clack33.log.info(
27251
+ clack34.log.info(
27191
27252
  `SMTP credentials are currently ${pc35.green("enabled")} (created ${metadata.services.email.smtpCredentials.createdAt})`
27192
27253
  );
27193
- const smtpAction = await clack33.select({
27254
+ const smtpAction = await clack34.select({
27194
27255
  message: "What would you like to do?",
27195
27256
  options: [
27196
27257
  {
@@ -27210,17 +27271,17 @@ ${pc35.bold("Webhook Endpoint")}
27210
27271
  }
27211
27272
  ]
27212
27273
  });
27213
- if (clack33.isCancel(smtpAction) || smtpAction === "cancel") {
27214
- clack33.log.info("No changes made.");
27274
+ if (clack34.isCancel(smtpAction) || smtpAction === "cancel") {
27275
+ clack34.log.info("No changes made.");
27215
27276
  process.exit(0);
27216
27277
  }
27217
27278
  if (smtpAction === "disable") {
27218
- const confirmDisable = await clack33.confirm({
27279
+ const confirmDisable = await clack34.confirm({
27219
27280
  message: "Are you sure? Any systems using these credentials will stop working immediately.",
27220
27281
  initialValue: false
27221
27282
  });
27222
- if (clack33.isCancel(confirmDisable) || !confirmDisable) {
27223
- clack33.log.info("SMTP credentials not disabled.");
27283
+ if (clack34.isCancel(confirmDisable) || !confirmDisable) {
27284
+ clack34.log.info("SMTP credentials not disabled.");
27224
27285
  process.exit(0);
27225
27286
  }
27226
27287
  updatedConfig = {
@@ -27233,43 +27294,43 @@ ${pc35.bold("Webhook Endpoint")}
27233
27294
  newPreset = void 0;
27234
27295
  break;
27235
27296
  }
27236
- clack33.log.info(
27297
+ clack34.log.info(
27237
27298
  "\nRotating credentials will invalidate your current SMTP password."
27238
27299
  );
27239
- clack33.log.warn(
27300
+ clack34.log.warn(
27240
27301
  "You will need to update all systems using the old credentials."
27241
27302
  );
27242
- const confirmRotate = await clack33.confirm({
27303
+ const confirmRotate = await clack34.confirm({
27243
27304
  message: "Generate new SMTP credentials?",
27244
27305
  initialValue: false
27245
27306
  });
27246
- if (clack33.isCancel(confirmRotate) || !confirmRotate) {
27247
- clack33.log.info("Credential rotation cancelled.");
27307
+ if (clack34.isCancel(confirmRotate) || !confirmRotate) {
27308
+ clack34.log.info("Credential rotation cancelled.");
27248
27309
  process.exit(0);
27249
27310
  }
27250
27311
  }
27251
- clack33.log.info(`
27312
+ clack34.log.info(`
27252
27313
  ${pc35.bold("SMTP Credentials for Legacy Systems")}
27253
27314
  `);
27254
- clack33.log.info(
27315
+ clack34.log.info(
27255
27316
  pc35.dim("Generate SMTP username/password that works with:")
27256
27317
  );
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"));
27318
+ clack34.log.info(pc35.dim(" - PHP mail() and PHPMailer"));
27319
+ clack34.log.info(pc35.dim(" - WordPress (WP Mail SMTP plugin)"));
27320
+ clack34.log.info(pc35.dim(" - Nodemailer and other SMTP libraries"));
27321
+ clack34.log.info(pc35.dim(" - Any SMTP-compatible email client"));
27261
27322
  console.log("");
27262
- clack33.log.warn(
27323
+ clack34.log.warn(
27263
27324
  "Credentials will be shown ONCE after deployment - save them immediately!"
27264
27325
  );
27265
27326
  console.log("");
27266
27327
  if (!options.yes) {
27267
- const confirmCreate = await clack33.confirm({
27328
+ const confirmCreate = await clack34.confirm({
27268
27329
  message: "Create SMTP credentials?",
27269
27330
  initialValue: true
27270
27331
  });
27271
- if (clack33.isCancel(confirmCreate) || !confirmCreate) {
27272
- clack33.log.info("SMTP credentials not created.");
27332
+ if (clack34.isCancel(confirmCreate) || !confirmCreate) {
27333
+ clack34.log.info("SMTP credentials not created.");
27273
27334
  process.exit(0);
27274
27335
  }
27275
27336
  }
@@ -27284,7 +27345,7 @@ ${pc35.bold("SMTP Credentials for Legacy Systems")}
27284
27345
  break;
27285
27346
  }
27286
27347
  case "hosting-provider": {
27287
- const newProvider = await clack33.select({
27348
+ const newProvider = await clack34.select({
27288
27349
  message: "Where is your app hosted?",
27289
27350
  options: [
27290
27351
  {
@@ -27309,12 +27370,12 @@ ${pc35.bold("SMTP Credentials for Legacy Systems")}
27309
27370
  }
27310
27371
  ]
27311
27372
  });
27312
- if (clack33.isCancel(newProvider)) {
27313
- clack33.cancel("Upgrade cancelled.");
27373
+ if (clack34.isCancel(newProvider)) {
27374
+ clack34.cancel("Upgrade cancelled.");
27314
27375
  process.exit(0);
27315
27376
  }
27316
27377
  if (newProvider === metadata.provider) {
27317
- clack33.log.info("Provider unchanged \u2014 no changes needed.");
27378
+ clack34.log.info("Provider unchanged \u2014 no changes needed.");
27318
27379
  process.exit(0);
27319
27380
  }
27320
27381
  metadata.provider = newProvider;
@@ -27345,12 +27406,12 @@ ${pc35.bold("Cost Impact:")}`);
27345
27406
  }
27346
27407
  console.log("");
27347
27408
  if (!(options.yes || options.preview)) {
27348
- const confirmed = await clack33.confirm({
27409
+ const confirmed = await clack34.confirm({
27349
27410
  message: "Proceed with upgrade?",
27350
27411
  initialValue: true
27351
27412
  });
27352
- if (clack33.isCancel(confirmed) || !confirmed) {
27353
- clack33.cancel("Upgrade cancelled.");
27413
+ if (clack34.isCancel(confirmed) || !confirmed) {
27414
+ clack34.cancel("Upgrade cancelled.");
27354
27415
  process.exit(0);
27355
27416
  }
27356
27417
  }
@@ -27397,15 +27458,15 @@ ${pc35.bold("Cost Impact:")}`);
27397
27458
  );
27398
27459
  await new Promise((resolve) => setTimeout(resolve, 2e3));
27399
27460
  } else if (!caaResult.success) {
27400
- clack33.log.warn(
27461
+ clack34.log.warn(
27401
27462
  `Could not verify CAA records: ${caaResult.error || "Unknown error"}`
27402
27463
  );
27403
- clack33.log.info(
27464
+ clack34.log.info(
27404
27465
  pc35.dim(
27405
27466
  "If certificate issuance fails, you may need to add a CAA record manually:"
27406
27467
  )
27407
27468
  );
27408
- clack33.log.info(pc35.dim(` ${parentDomain} CAA 0 issue "amazon.com"`));
27469
+ clack34.log.info(pc35.dim(` ${parentDomain} CAA 0 issue "amazon.com"`));
27409
27470
  }
27410
27471
  }
27411
27472
  }
@@ -27469,7 +27530,7 @@ ${pc35.bold("Cost Impact:")}`);
27469
27530
  costEstimate: costComparison,
27470
27531
  commandName: "wraps email upgrade"
27471
27532
  });
27472
- clack33.outro(
27533
+ clack34.outro(
27473
27534
  pc35.green("Preview complete. Run without --preview to upgrade.")
27474
27535
  );
27475
27536
  trackServiceUpgrade("email", {
@@ -27647,7 +27708,7 @@ ${pc35.bold("Cost Impact:")}`);
27647
27708
  );
27648
27709
  }
27649
27710
  } else {
27650
- clack33.log.warn(
27711
+ clack34.log.warn(
27651
27712
  credResult.error || `Unable to validate ${getDNSProviderDisplayName(dnsProvider)} credentials`
27652
27713
  );
27653
27714
  }
@@ -27663,7 +27724,7 @@ ${pc35.bold("Cost Impact:")}`);
27663
27724
  };
27664
27725
  const dnsRecords = buildEmailDNSRecords(dnsData);
27665
27726
  console.log();
27666
- clack33.note(
27727
+ clack34.note(
27667
27728
  formatManualDNSInstructions(dnsRecords),
27668
27729
  "DNS Records \u2014 Add these to your DNS provider"
27669
27730
  );
@@ -27973,7 +28034,7 @@ init_output();
27973
28034
  import { existsSync as existsSync14 } from "fs";
27974
28035
  import { mkdir as mkdir7, readFile as readFile7, writeFile as writeFile9 } from "fs/promises";
27975
28036
  import { join as join16 } from "path";
27976
- import * as clack34 from "@clack/prompts";
28037
+ import * as clack35 from "@clack/prompts";
27977
28038
  import pc36 from "picocolors";
27978
28039
 
27979
28040
  // src/commands/email/workflows/claude-content.ts
@@ -28365,7 +28426,7 @@ async function workflowsInit(options) {
28365
28426
  const cwd = process.cwd();
28366
28427
  const workflowsDir = join16(cwd, "wraps", "workflows");
28367
28428
  if (!isJsonMode()) {
28368
- clack34.intro(pc36.bold("Workflows as Code"));
28429
+ clack35.intro(pc36.bold("Workflows as Code"));
28369
28430
  }
28370
28431
  const progress = new DeploymentProgress();
28371
28432
  if (existsSync14(workflowsDir) && !options.force) {
@@ -28375,7 +28436,7 @@ async function workflowsInit(options) {
28375
28436
  (f) => f.endsWith(".ts") && !f.startsWith("_")
28376
28437
  );
28377
28438
  if (tsFiles.length > 0 && !options.force && !isJsonMode()) {
28378
- clack34.log.warn(
28439
+ clack35.log.warn(
28379
28440
  `${pc36.cyan("wraps/workflows/")} already contains ${tsFiles.length} workflow file(s). Use ${pc36.bold("--force")} to overwrite.`
28380
28441
  );
28381
28442
  }
@@ -28442,7 +28503,7 @@ async function workflowsInit(options) {
28442
28503
  return;
28443
28504
  }
28444
28505
  console.log();
28445
- clack34.log.success(pc36.green("Workflows as Code initialized!"));
28506
+ clack35.log.success(pc36.green("Workflows as Code initialized!"));
28446
28507
  console.log();
28447
28508
  console.log(` ${pc36.dim("Directory:")} ${pc36.cyan("wraps/workflows/")}`);
28448
28509
  if (!options.noExample) {
@@ -28485,7 +28546,7 @@ init_esm_shims();
28485
28546
  init_events();
28486
28547
  import { existsSync as existsSync16 } from "fs";
28487
28548
  import { join as join18 } from "path";
28488
- import * as clack35 from "@clack/prompts";
28549
+ import * as clack36 from "@clack/prompts";
28489
28550
  import pc37 from "picocolors";
28490
28551
 
28491
28552
  // src/utils/email/workflow-transform.ts
@@ -29336,7 +29397,7 @@ async function workflowsPush(options) {
29336
29397
  throw errors.wrapsConfigNotFound();
29337
29398
  }
29338
29399
  if (!isJsonMode()) {
29339
- clack35.intro(pc37.bold("Push Workflows"));
29400
+ clack36.intro(pc37.bold("Push Workflows"));
29340
29401
  }
29341
29402
  const progress = new DeploymentProgress();
29342
29403
  progress.start("Loading configuration");
@@ -29351,7 +29412,7 @@ async function workflowsPush(options) {
29351
29412
  errors: []
29352
29413
  });
29353
29414
  } else {
29354
- clack35.log.info("No workflows/ directory found.");
29415
+ clack36.log.info("No workflows/ directory found.");
29355
29416
  }
29356
29417
  return;
29357
29418
  }
@@ -29364,7 +29425,7 @@ async function workflowsPush(options) {
29364
29425
  errors: []
29365
29426
  });
29366
29427
  } else {
29367
- clack35.log.info("No workflows found to push.");
29428
+ clack36.log.info("No workflows found to push.");
29368
29429
  }
29369
29430
  return;
29370
29431
  }
@@ -29433,7 +29494,7 @@ async function workflowsPush(options) {
29433
29494
  });
29434
29495
  } else {
29435
29496
  console.log();
29436
- clack35.log.error(
29497
+ clack36.log.error(
29437
29498
  pc37.red("Cannot push due to validation errors. Fix errors and retry.")
29438
29499
  );
29439
29500
  console.log();
@@ -29448,7 +29509,7 @@ async function workflowsPush(options) {
29448
29509
  errors: []
29449
29510
  });
29450
29511
  } else {
29451
- clack35.log.info(
29512
+ clack36.log.info(
29452
29513
  `${unchanged.length} workflow(s) unchanged. Use --force to re-push.`
29453
29514
  );
29454
29515
  }
@@ -29469,7 +29530,7 @@ async function workflowsPush(options) {
29469
29530
  });
29470
29531
  } else {
29471
29532
  console.log();
29472
- clack35.log.info(pc37.bold("Dry run \u2014 no changes made"));
29533
+ clack36.log.info(pc37.bold("Dry run \u2014 no changes made"));
29473
29534
  console.log();
29474
29535
  for (const w of toProcess) {
29475
29536
  console.log(
@@ -29526,20 +29587,20 @@ async function workflowsPush(options) {
29526
29587
  } else {
29527
29588
  console.log();
29528
29589
  if (enabled.length > 0) {
29529
- clack35.log.success(
29590
+ clack36.log.success(
29530
29591
  pc37.green(`${enabled.length} workflow(s) pushed and enabled`)
29531
29592
  );
29532
29593
  }
29533
29594
  if (drafts.length > 0) {
29534
- clack35.log.success(
29595
+ clack36.log.success(
29535
29596
  pc37.green(`${drafts.length} workflow(s) pushed as draft`)
29536
29597
  );
29537
29598
  }
29538
29599
  if (unchanged.length > 0) {
29539
- clack35.log.info(`${unchanged.length} unchanged (use --force to re-push)`);
29600
+ clack36.log.info(`${unchanged.length} unchanged (use --force to re-push)`);
29540
29601
  }
29541
29602
  if (conflicts.length > 0) {
29542
- clack35.log.error(
29603
+ clack36.log.error(
29543
29604
  `${conflicts.length} workflow(s) skipped due to dashboard edits. Use --force to overwrite.`
29544
29605
  );
29545
29606
  for (const c of conflicts) {
@@ -29703,7 +29764,7 @@ init_esm_shims();
29703
29764
  init_events();
29704
29765
  import { existsSync as existsSync17 } from "fs";
29705
29766
  import { join as join19 } from "path";
29706
- import * as clack36 from "@clack/prompts";
29767
+ import * as clack37 from "@clack/prompts";
29707
29768
  import pc38 from "picocolors";
29708
29769
  init_errors();
29709
29770
  init_json_output();
@@ -29717,7 +29778,7 @@ async function workflowsValidate(options) {
29717
29778
  throw errors.wrapsConfigNotFound();
29718
29779
  }
29719
29780
  if (!isJsonMode()) {
29720
- clack36.intro(pc38.bold("Validate Workflows"));
29781
+ clack37.intro(pc38.bold("Validate Workflows"));
29721
29782
  }
29722
29783
  const progress = new DeploymentProgress();
29723
29784
  progress.start("Loading configuration");
@@ -29728,7 +29789,7 @@ async function workflowsValidate(options) {
29728
29789
  if (isJsonMode()) {
29729
29790
  jsonSuccess("email.workflows.validate", { workflows: [], errors: [] });
29730
29791
  } else {
29731
- clack36.log.info("No workflows/ directory found.");
29792
+ clack37.log.info("No workflows/ directory found.");
29732
29793
  }
29733
29794
  return;
29734
29795
  }
@@ -29737,7 +29798,7 @@ async function workflowsValidate(options) {
29737
29798
  if (isJsonMode()) {
29738
29799
  jsonSuccess("email.workflows.validate", { workflows: [], errors: [] });
29739
29800
  } else {
29740
- clack36.log.info("No workflows found to validate.");
29801
+ clack37.log.info("No workflows found to validate.");
29741
29802
  }
29742
29803
  return;
29743
29804
  }
@@ -29814,18 +29875,18 @@ async function workflowsValidate(options) {
29814
29875
  const invalidCount = validationResults.filter((r) => !r.valid).length;
29815
29876
  const parseErrorCount = parseErrors.length;
29816
29877
  if (parseErrorCount === 0 && invalidCount === 0) {
29817
- clack36.log.success(
29878
+ clack37.log.success(
29818
29879
  pc38.green(`${validCount} workflow(s) validated successfully`)
29819
29880
  );
29820
29881
  } else {
29821
29882
  if (validCount > 0) {
29822
- clack36.log.success(pc38.green(`${validCount} workflow(s) valid`));
29883
+ clack37.log.success(pc38.green(`${validCount} workflow(s) valid`));
29823
29884
  }
29824
29885
  if (invalidCount > 0) {
29825
- clack36.log.error(pc38.red(`${invalidCount} workflow(s) have errors`));
29886
+ clack37.log.error(pc38.red(`${invalidCount} workflow(s) have errors`));
29826
29887
  }
29827
29888
  if (parseErrorCount > 0) {
29828
- clack36.log.error(
29889
+ clack37.log.error(
29829
29890
  pc38.red(`${parseErrorCount} workflow(s) failed to parse`)
29830
29891
  );
29831
29892
  }
@@ -29859,11 +29920,11 @@ async function workflowsValidate(options) {
29859
29920
  // src/commands/news.ts
29860
29921
  init_esm_shims();
29861
29922
  init_events();
29862
- import * as clack37 from "@clack/prompts";
29923
+ import * as clack38 from "@clack/prompts";
29863
29924
  import pc39 from "picocolors";
29864
29925
  async function news() {
29865
29926
  trackCommand("news", { success: true });
29866
- clack37.intro(pc39.bold("What's New in Wraps"));
29927
+ clack38.intro(pc39.bold("What's New in Wraps"));
29867
29928
  console.log();
29868
29929
  console.log(" See the latest updates, features, and improvements:");
29869
29930
  console.log();
@@ -29879,7 +29940,7 @@ async function news() {
29879
29940
  init_esm_shims();
29880
29941
  init_events();
29881
29942
  init_json_output();
29882
- import * as clack38 from "@clack/prompts";
29943
+ import * as clack39 from "@clack/prompts";
29883
29944
  import pc40 from "picocolors";
29884
29945
  function getBaseStatements() {
29885
29946
  return [
@@ -30271,7 +30332,7 @@ function buildPolicy(service, preset) {
30271
30332
  };
30272
30333
  }
30273
30334
  function displaySummary(service, preset) {
30274
- clack38.intro(pc40.bold("Wraps Required AWS Permissions"));
30335
+ clack39.intro(pc40.bold("Wraps Required AWS Permissions"));
30275
30336
  const serviceLabel = service ? service.toUpperCase() : "All Services";
30276
30337
  const presetLabel = preset ? preset.charAt(0).toUpperCase() + preset.slice(1) : "All Features";
30277
30338
  console.log(`
@@ -30365,7 +30426,7 @@ async function permissions(options) {
30365
30426
  console.log("2. Create the policy in AWS Console:");
30366
30427
  console.log(" IAM > Policies > Create Policy > JSON\n");
30367
30428
  console.log("3. Attach to your IAM user/role\n");
30368
- clack38.outro(
30429
+ clack39.outro(
30369
30430
  pc40.green("Run with --json to get the full IAM policy document")
30370
30431
  );
30371
30432
  }
@@ -30383,7 +30444,7 @@ import {
30383
30444
  IAMClient as IAMClient3,
30384
30445
  PutRolePolicyCommand
30385
30446
  } 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";
30447
+ import { confirm as confirm18, intro as intro34, isCancel as isCancel25, log as log36, outro as outro20, select as select17 } from "@clack/prompts";
30387
30448
  import * as pulumi24 from "@pulumi/pulumi";
30388
30449
  import pc41 from "picocolors";
30389
30450
  init_events();
@@ -30396,6 +30457,7 @@ init_metadata();
30396
30457
  init_output();
30397
30458
  init_prompts();
30398
30459
  init_pulumi();
30460
+ init_region_resolver();
30399
30461
  function buildConsolePolicyDocument(emailConfig, smsConfig) {
30400
30462
  const statements = [];
30401
30463
  statements.push({
@@ -30572,10 +30634,11 @@ async function validateAndLoadMetadata(options, progress) {
30572
30634
  async () => validateAWSCredentials()
30573
30635
  );
30574
30636
  progress.info(`Connected to AWS account: ${pc41.cyan(identity.accountId)}`);
30575
- let region = options.region;
30576
- if (!region) {
30577
- region = await getAWSRegion();
30578
- }
30637
+ const region = await resolveRegionForCommand({
30638
+ accountId: identity.accountId,
30639
+ optionRegion: options.region,
30640
+ label: "connection"
30641
+ });
30579
30642
  const metadata = await loadConnectionMetadata(identity.accountId, region);
30580
30643
  if (!metadata) {
30581
30644
  progress.stop();
@@ -30734,7 +30797,7 @@ async function resolveOrganization() {
30734
30797
  if (orgs.length === 1) {
30735
30798
  return orgs[0];
30736
30799
  }
30737
- const selected = await select16({
30800
+ const selected = await select17({
30738
30801
  message: "Which organization should this AWS account connect to?",
30739
30802
  options: orgs.map((org) => ({
30740
30803
  value: org.id,
@@ -30742,7 +30805,7 @@ async function resolveOrganization() {
30742
30805
  hint: org.slug
30743
30806
  }))
30744
30807
  });
30745
- if (isCancel24(selected)) {
30808
+ if (isCancel25(selected)) {
30746
30809
  outro20("Operation cancelled");
30747
30810
  process.exit(0);
30748
30811
  }
@@ -30808,7 +30871,7 @@ async function authenticatedConnect(token, options) {
30808
30871
  message: "Enable event tracking now?",
30809
30872
  initialValue: true
30810
30873
  });
30811
- if (isCancel24(enableTracking) || !enableTracking) {
30874
+ if (isCancel25(enableTracking) || !enableTracking) {
30812
30875
  outro20("Platform connection cancelled.");
30813
30876
  process.exit(0);
30814
30877
  }
@@ -30953,10 +31016,11 @@ async function connect3(options) {
30953
31016
  async () => validateAWSCredentials()
30954
31017
  );
30955
31018
  progress.info(`Connected to AWS account: ${pc41.cyan(identity.accountId)}`);
30956
- let region = options.region;
30957
- if (!region) {
30958
- region = await getAWSRegion();
30959
- }
31019
+ const region = await resolveRegionForCommand({
31020
+ accountId: identity.accountId,
31021
+ optionRegion: options.region,
31022
+ label: "connection"
31023
+ });
30960
31024
  const metadata = await loadConnectionMetadata(identity.accountId, region);
30961
31025
  if (!metadata) {
30962
31026
  progress.stop();
@@ -31002,7 +31066,7 @@ Run ${pc41.cyan("wraps email init")} or ${pc41.cyan("wraps sms init")} first.
31002
31066
  message: "Enable event tracking now?",
31003
31067
  initialValue: true
31004
31068
  });
31005
- if (isCancel24(enableEventTracking) || !enableEventTracking) {
31069
+ if (isCancel25(enableEventTracking) || !enableEventTracking) {
31006
31070
  outro20("Platform connection cancelled.");
31007
31071
  process.exit(0);
31008
31072
  }
@@ -31030,7 +31094,7 @@ Run ${pc41.cyan("wraps email init")} or ${pc41.cyan("wraps sms init")} first.
31030
31094
  log36.info(
31031
31095
  `Already connected to Wraps Platform (AWS Account: ${pc41.cyan(metadata.accountId)})`
31032
31096
  );
31033
- const action = await select16({
31097
+ const action = await select17({
31034
31098
  message: "What would you like to do?",
31035
31099
  options: [
31036
31100
  {
@@ -31050,7 +31114,7 @@ Run ${pc41.cyan("wraps email init")} or ${pc41.cyan("wraps sms init")} first.
31050
31114
  }
31051
31115
  ]
31052
31116
  });
31053
- if (isCancel24(action)) {
31117
+ if (isCancel25(action)) {
31054
31118
  outro20("Operation cancelled");
31055
31119
  process.exit(0);
31056
31120
  }
@@ -31061,7 +31125,7 @@ Run ${pc41.cyan("wraps email init")} or ${pc41.cyan("wraps sms init")} first.
31061
31125
  message: "Are you sure? Events will no longer be sent to the Wraps Platform.",
31062
31126
  initialValue: false
31063
31127
  });
31064
- if (isCancel24(confirmDisconnect) || !confirmDisconnect) {
31128
+ if (isCancel25(confirmDisconnect) || !confirmDisconnect) {
31065
31129
  outro20("Disconnect cancelled");
31066
31130
  process.exit(0);
31067
31131
  }
@@ -31211,10 +31275,10 @@ ${pc41.bold("Next Steps:")}`);
31211
31275
 
31212
31276
  // src/commands/platform/index.ts
31213
31277
  init_esm_shims();
31214
- import * as clack39 from "@clack/prompts";
31278
+ import * as clack40 from "@clack/prompts";
31215
31279
  import pc42 from "picocolors";
31216
31280
  async function platform() {
31217
- clack39.intro(pc42.bold("Wraps Platform"));
31281
+ clack40.intro(pc42.bold("Wraps Platform"));
31218
31282
  console.log();
31219
31283
  console.log(
31220
31284
  " The Wraps Platform extends the free CLI with hosted features:"
@@ -31267,12 +31331,13 @@ init_aws();
31267
31331
  init_json_output();
31268
31332
  init_metadata();
31269
31333
  init_output();
31334
+ init_region_resolver();
31270
31335
  import {
31271
31336
  CreateRoleCommand as CreateRoleCommand2,
31272
31337
  GetRoleCommand as GetRoleCommand2,
31273
31338
  IAMClient as IAMClient4
31274
31339
  } 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";
31340
+ import { confirm as confirm19, intro as intro36, isCancel as isCancel26, log as log37, outro as outro21 } from "@clack/prompts";
31276
31341
  import pc43 from "picocolors";
31277
31342
  async function updateRole(options) {
31278
31343
  const startTime = Date.now();
@@ -31284,7 +31349,11 @@ async function updateRole(options) {
31284
31349
  "Validating AWS credentials",
31285
31350
  async () => validateAWSCredentials()
31286
31351
  );
31287
- const region = options.region || await getAWSRegion();
31352
+ const region = await resolveRegionForCommand({
31353
+ accountId: identity.accountId,
31354
+ optionRegion: options.region,
31355
+ label: "connection"
31356
+ });
31288
31357
  const metadata = await loadConnectionMetadata(identity.accountId, region);
31289
31358
  if (!metadata) {
31290
31359
  progress.stop();
@@ -31337,7 +31406,7 @@ Run ${pc43.cyan("wraps email init")} to deploy infrastructure first.
31337
31406
  message: `${actionLabel} IAM role ${pc43.cyan(roleName)} with latest permissions?`,
31338
31407
  initialValue: true
31339
31408
  });
31340
- if (isCancel25(shouldContinue) || !shouldContinue) {
31409
+ if (isCancel26(shouldContinue) || !shouldContinue) {
31341
31410
  outro21(`${actionLabel} cancelled`);
31342
31411
  process.exit(0);
31343
31412
  }
@@ -31656,7 +31725,7 @@ function buildConsolePolicyDocument2(emailConfig, smsConfig) {
31656
31725
 
31657
31726
  // src/commands/shared/dashboard.ts
31658
31727
  init_esm_shims();
31659
- import * as clack40 from "@clack/prompts";
31728
+ import * as clack41 from "@clack/prompts";
31660
31729
  import * as pulumi25 from "@pulumi/pulumi";
31661
31730
  import getPort from "get-port";
31662
31731
  import open2 from "open";
@@ -34307,7 +34376,7 @@ init_output();
34307
34376
  init_pulumi();
34308
34377
  async function dashboard(options) {
34309
34378
  await ensurePulumiInstalled();
34310
- clack40.intro(pc44.bold("Wraps Dashboard"));
34379
+ clack41.intro(pc44.bold("Wraps Dashboard"));
34311
34380
  const progress = new DeploymentProgress();
34312
34381
  const identity = await progress.execute(
34313
34382
  "Validating AWS credentials",
@@ -34348,7 +34417,7 @@ async function dashboard(options) {
34348
34417
  }
34349
34418
  } catch (_error) {
34350
34419
  progress.stop();
34351
- clack40.log.error("No Wraps infrastructure found");
34420
+ clack41.log.error("No Wraps infrastructure found");
34352
34421
  console.log(
34353
34422
  `\\nRun ${pc44.cyan("wraps email init")}, ${pc44.cyan("wraps sms init")}, or ${pc44.cyan("wraps storage init")} to deploy infrastructure first.\\n`
34354
34423
  );
@@ -34392,7 +34461,7 @@ async function dashboard(options) {
34392
34461
  }
34393
34462
  const port = options.port || await getPort({ port: [5555, 5556, 5557, 5558, 5559] });
34394
34463
  progress.stop();
34395
- clack40.log.success("Starting dashboard server...");
34464
+ clack41.log.success("Starting dashboard server...");
34396
34465
  console.log(
34397
34466
  `${pc44.dim("Using current AWS credentials (no role assumption)")}\\n`
34398
34467
  );
@@ -34449,7 +34518,7 @@ init_aws();
34449
34518
  init_errors();
34450
34519
  init_json_output();
34451
34520
  init_metadata();
34452
- import * as clack41 from "@clack/prompts";
34521
+ import * as clack42 from "@clack/prompts";
34453
34522
  import pc45 from "picocolors";
34454
34523
  async function destroy(options) {
34455
34524
  trackCommand("destroy", { success: true });
@@ -34461,9 +34530,9 @@ async function destroy(options) {
34461
34530
  );
34462
34531
  }
34463
34532
  if (!isJsonMode()) {
34464
- clack41.intro(pc45.bold("Wraps Infrastructure Teardown"));
34533
+ clack42.intro(pc45.bold("Wraps Infrastructure Teardown"));
34465
34534
  }
34466
- const spinner10 = clack41.spinner();
34535
+ const spinner10 = clack42.spinner();
34467
34536
  spinner10.start("Validating AWS credentials");
34468
34537
  let identity;
34469
34538
  try {
@@ -34480,7 +34549,7 @@ async function destroy(options) {
34480
34549
  deployedServices.push("email");
34481
34550
  }
34482
34551
  if (deployedServices.length === 0) {
34483
- clack41.log.warn("No Wraps services found in this region");
34552
+ clack42.log.warn("No Wraps services found in this region");
34484
34553
  console.log(
34485
34554
  `
34486
34555
  Run ${pc45.cyan("wraps email init")} to deploy infrastructure.
@@ -34490,7 +34559,7 @@ Run ${pc45.cyan("wraps email init")} to deploy infrastructure.
34490
34559
  }
34491
34560
  if (deployedServices.length === 1) {
34492
34561
  const service = deployedServices[0];
34493
- clack41.log.info(`Found ${pc45.cyan(service)} service deployed`);
34562
+ clack42.log.info(`Found ${pc45.cyan(service)} service deployed`);
34494
34563
  if (service === "email") {
34495
34564
  await emailDestroy(options);
34496
34565
  return;
@@ -34505,7 +34574,7 @@ Run ${pc45.cyan("wraps email init")} to deploy infrastructure.
34505
34574
  jsonSuccess("destroy", { destroyed: true });
34506
34575
  return;
34507
34576
  }
34508
- const serviceToDestroy = await clack41.select({
34577
+ const serviceToDestroy = await clack42.select({
34509
34578
  message: "Which service would you like to destroy?",
34510
34579
  options: [
34511
34580
  ...deployedServices.map((s) => ({
@@ -34520,15 +34589,15 @@ Run ${pc45.cyan("wraps email init")} to deploy infrastructure.
34520
34589
  }
34521
34590
  ]
34522
34591
  });
34523
- if (clack41.isCancel(serviceToDestroy)) {
34524
- clack41.cancel("Operation cancelled.");
34592
+ if (clack42.isCancel(serviceToDestroy)) {
34593
+ clack42.cancel("Operation cancelled.");
34525
34594
  process.exit(0);
34526
34595
  }
34527
34596
  if ((serviceToDestroy === "email" || serviceToDestroy === "all") && deployedServices.includes("email")) {
34528
34597
  await emailDestroy(options);
34529
34598
  }
34530
34599
  if (serviceToDestroy === "all") {
34531
- clack41.outro(pc45.green("All Wraps infrastructure has been removed"));
34600
+ clack42.outro(pc45.green("All Wraps infrastructure has been removed"));
34532
34601
  }
34533
34602
  }
34534
34603
 
@@ -34540,7 +34609,7 @@ init_fs();
34540
34609
  init_json_output();
34541
34610
  init_output();
34542
34611
  init_pulumi();
34543
- import * as clack42 from "@clack/prompts";
34612
+ import * as clack43 from "@clack/prompts";
34544
34613
  import * as pulumi26 from "@pulumi/pulumi";
34545
34614
  import pc46 from "picocolors";
34546
34615
  async function status(_options) {
@@ -34548,7 +34617,7 @@ async function status(_options) {
34548
34617
  const startTime = Date.now();
34549
34618
  const progress = new DeploymentProgress();
34550
34619
  if (!isJsonMode()) {
34551
- clack42.intro(pc46.bold("Wraps Infrastructure Status"));
34620
+ clack43.intro(pc46.bold("Wraps Infrastructure Status"));
34552
34621
  }
34553
34622
  const identity = await progress.execute(
34554
34623
  "Loading infrastructure status",
@@ -34611,7 +34680,7 @@ async function status(_options) {
34611
34680
  return;
34612
34681
  }
34613
34682
  console.log();
34614
- clack42.note(
34683
+ clack43.note(
34615
34684
  services.map((s) => {
34616
34685
  if (s.status === "deployed") {
34617
34686
  const details = s.details ? pc46.dim(` (${s.details})`) : "";
@@ -34650,13 +34719,12 @@ ${pc46.bold("Dashboard:")} ${pc46.blue("https://app.wraps.dev")}`);
34650
34719
 
34651
34720
  // src/commands/sms/destroy.ts
34652
34721
  init_esm_shims();
34653
- import * as clack43 from "@clack/prompts";
34722
+ import * as clack44 from "@clack/prompts";
34654
34723
  import * as pulumi28 from "@pulumi/pulumi";
34655
34724
  import pc47 from "picocolors";
34656
34725
 
34657
34726
  // src/infrastructure/sms-stack.ts
34658
34727
  init_esm_shims();
34659
- init_constants();
34660
34728
  import * as aws20 from "@pulumi/aws";
34661
34729
  import * as pulumi27 from "@pulumi/pulumi";
34662
34730
  init_resource_checks();
@@ -34772,12 +34840,10 @@ function createSMSOptOutList() {
34772
34840
  }
34773
34841
  });
34774
34842
  }
34775
- async function findExistingPhoneNumber(phoneNumberType) {
34843
+ async function findExistingPhoneNumber(phoneNumberType, region) {
34776
34844
  try {
34777
34845
  const { PinpointSMSVoiceV2Client: PinpointSMSVoiceV2Client5, DescribePhoneNumbersCommand: DescribePhoneNumbersCommand2 } = await import("@aws-sdk/client-pinpoint-sms-voice-v2");
34778
- const client = new PinpointSMSVoiceV2Client5({
34779
- region: getDefaultRegion()
34780
- });
34846
+ const client = new PinpointSMSVoiceV2Client5({ region });
34781
34847
  const numberTypeMap = {
34782
34848
  simulator: "SIMULATOR",
34783
34849
  "toll-free": "TOLL_FREE",
@@ -34811,14 +34877,14 @@ async function findExistingPhoneNumber(phoneNumberType) {
34811
34877
  throw error;
34812
34878
  }
34813
34879
  }
34814
- async function createSMSPhoneNumber(phoneNumberType, optOutList) {
34880
+ async function createSMSPhoneNumber(phoneNumberType, optOutList, region) {
34815
34881
  const numberTypeMap = {
34816
34882
  simulator: "SIMULATOR",
34817
34883
  "toll-free": "TOLL_FREE",
34818
34884
  "10dlc": "TEN_DLC",
34819
34885
  "short-code": "SHORT_CODE"
34820
34886
  };
34821
- const existingArn = await findExistingPhoneNumber(phoneNumberType);
34887
+ const existingArn = await findExistingPhoneNumber(phoneNumberType, region);
34822
34888
  const phoneConfig = {
34823
34889
  isoCountryCode: "US",
34824
34890
  messageType: "TRANSACTIONAL",
@@ -34855,11 +34921,11 @@ async function createSMSPhoneNumber(phoneNumberType, optOutList) {
34855
34921
  }
34856
34922
  );
34857
34923
  }
34858
- async function createSMSSQSResources() {
34924
+ async function createSMSSQSResources(config2) {
34859
34925
  const dlqName = "wraps-sms-events-dlq";
34860
34926
  const queueName = "wraps-sms-events";
34861
- const dlqUrl = await sqsQueueExists(dlqName);
34862
- const queueUrl = await sqsQueueExists(queueName);
34927
+ const dlqUrl = await sqsQueueExists(dlqName, config2.region);
34928
+ const queueUrl = await sqsQueueExists(queueName, config2.region);
34863
34929
  const dlqConfig = {
34864
34930
  name: dlqName,
34865
34931
  messageRetentionSeconds: 1209600,
@@ -34906,7 +34972,7 @@ async function createSMSSQSResources() {
34906
34972
  }
34907
34973
  async function createSMSSNSResources(config2) {
34908
34974
  const topicName = "wraps-sms-events";
34909
- const topicArn = await snsTopicExists(topicName);
34975
+ const topicArn = await snsTopicExists(topicName, config2.region);
34910
34976
  const topicConfig = {
34911
34977
  name: topicName,
34912
34978
  tags: {
@@ -34969,9 +35035,9 @@ async function createSMSSNSResources(config2) {
34969
35035
  );
34970
35036
  return { topic, subscription };
34971
35037
  }
34972
- async function createSMSDynamoDBTable() {
35038
+ async function createSMSDynamoDBTable(config2) {
34973
35039
  const tableName = "wraps-sms-history";
34974
- const exists = await tableExists(tableName);
35040
+ const exists = await tableExists(tableName, config2.region);
34975
35041
  const tableConfig = {
34976
35042
  name: tableName,
34977
35043
  billingMode: "PAY_PER_REQUEST",
@@ -35136,23 +35202,25 @@ async function deploySMSStack(config2) {
35136
35202
  if (smsConfig.phoneNumberType) {
35137
35203
  phoneNumber = await createSMSPhoneNumber(
35138
35204
  smsConfig.phoneNumberType,
35139
- optOutList
35205
+ optOutList,
35206
+ config2.region
35140
35207
  );
35141
35208
  }
35142
35209
  let sqsResources;
35143
35210
  if (smsConfig.eventTracking?.enabled) {
35144
- sqsResources = await createSMSSQSResources();
35211
+ sqsResources = await createSMSSQSResources({ region: config2.region });
35145
35212
  }
35146
35213
  let snsResources;
35147
35214
  if (smsConfig.eventTracking?.enabled && sqsResources) {
35148
35215
  snsResources = await createSMSSNSResources({
35149
35216
  queueArn: sqsResources.queue.arn,
35150
- queueUrl: sqsResources.queue.url
35217
+ queueUrl: sqsResources.queue.url,
35218
+ region: config2.region
35151
35219
  });
35152
35220
  }
35153
35221
  let dynamoTable;
35154
35222
  if (smsConfig.eventTracking?.dynamoDBHistory) {
35155
- dynamoTable = await createSMSDynamoDBTable();
35223
+ dynamoTable = await createSMSDynamoDBTable({ region: config2.region });
35156
35224
  }
35157
35225
  let lambdaFunction;
35158
35226
  if (smsConfig.eventTracking?.dynamoDBHistory && dynamoTable && sqsResources) {
@@ -35501,7 +35569,7 @@ async function smsDestroy(options) {
35501
35569
  );
35502
35570
  }
35503
35571
  if (!isJsonMode()) {
35504
- clack43.intro(
35572
+ clack44.intro(
35505
35573
  pc47.bold(
35506
35574
  options.preview ? "SMS Infrastructure Destruction Preview" : "SMS Infrastructure Teardown"
35507
35575
  )
@@ -35528,15 +35596,15 @@ async function smsDestroy(options) {
35528
35596
  `Available regions: ${smsConnections.map((c) => c.region).join(", ")}`
35529
35597
  );
35530
35598
  }
35531
- const selectedRegion = await clack43.select({
35599
+ const selectedRegion = await clack44.select({
35532
35600
  message: "Multiple SMS deployments found. Which region to destroy?",
35533
35601
  options: smsConnections.map((conn) => ({
35534
35602
  value: conn.region,
35535
35603
  label: conn.region
35536
35604
  }))
35537
35605
  });
35538
- if (clack43.isCancel(selectedRegion)) {
35539
- clack43.cancel("Operation cancelled");
35606
+ if (clack44.isCancel(selectedRegion)) {
35607
+ clack44.cancel("Operation cancelled");
35540
35608
  process.exit(0);
35541
35609
  }
35542
35610
  region = selectedRegion;
@@ -35547,18 +35615,18 @@ async function smsDestroy(options) {
35547
35615
  const storedStackName = smsService?.pulumiStackName;
35548
35616
  if (!smsService) {
35549
35617
  progress.stop();
35550
- clack43.log.warn("No SMS infrastructure found");
35618
+ clack44.log.warn("No SMS infrastructure found");
35551
35619
  process.exit(0);
35552
35620
  }
35553
35621
  if (!(options.force || options.preview)) {
35554
- const confirmed = await clack43.confirm({
35622
+ const confirmed = await clack44.confirm({
35555
35623
  message: pc47.red(
35556
35624
  "Are you sure you want to destroy all SMS infrastructure?"
35557
35625
  ),
35558
35626
  initialValue: false
35559
35627
  });
35560
- if (clack43.isCancel(confirmed) || !confirmed) {
35561
- clack43.cancel("Destruction cancelled.");
35628
+ if (clack44.isCancel(confirmed) || !confirmed) {
35629
+ clack44.cancel("Destruction cancelled.");
35562
35630
  process.exit(0);
35563
35631
  }
35564
35632
  }
@@ -35590,7 +35658,7 @@ async function smsDestroy(options) {
35590
35658
  costEstimate: "Monthly cost after destruction: $0.00",
35591
35659
  commandName: "wraps sms destroy"
35592
35660
  });
35593
- clack43.outro(
35661
+ clack44.outro(
35594
35662
  pc47.green("Preview complete. Run without --preview to destroy.")
35595
35663
  );
35596
35664
  trackServiceRemoved("sms", {
@@ -35602,7 +35670,7 @@ async function smsDestroy(options) {
35602
35670
  progress.stop();
35603
35671
  const errorMessage = error instanceof Error ? error.message : String(error);
35604
35672
  if (errorMessage.includes("No SMS infrastructure found")) {
35605
- clack43.log.warn("No SMS infrastructure found to preview");
35673
+ clack44.log.warn("No SMS infrastructure found to preview");
35606
35674
  process.exit(0);
35607
35675
  }
35608
35676
  trackError("PREVIEW_FAILED", "sms destroy", { step: "preview" });
@@ -35651,7 +35719,7 @@ async function smsDestroy(options) {
35651
35719
  progress.stop();
35652
35720
  const errorMessage = error instanceof Error ? error.message : String(error);
35653
35721
  if (errorMessage.includes("No SMS infrastructure found")) {
35654
- clack43.log.warn("No SMS infrastructure found");
35722
+ clack44.log.warn("No SMS infrastructure found");
35655
35723
  if (metadata) {
35656
35724
  removeServiceFromConnection(metadata, "sms");
35657
35725
  await saveConnectionMetadata(metadata);
@@ -35664,7 +35732,7 @@ async function smsDestroy(options) {
35664
35732
  }
35665
35733
  trackError("DESTROY_FAILED", "sms destroy", { step: "destroy" });
35666
35734
  destroyFailed = true;
35667
- clack43.log.warn(
35735
+ clack44.log.warn(
35668
35736
  "Some resources may not have been fully removed. You can re-run this command or clean up manually in the AWS console."
35669
35737
  );
35670
35738
  }
@@ -35687,11 +35755,11 @@ async function smsDestroy(options) {
35687
35755
  return;
35688
35756
  }
35689
35757
  if (destroyFailed) {
35690
- clack43.outro(
35758
+ clack44.outro(
35691
35759
  pc47.yellow("SMS infrastructure partially removed. Metadata cleaned up.")
35692
35760
  );
35693
35761
  } else {
35694
- clack43.outro(pc47.green("SMS infrastructure has been removed"));
35762
+ clack44.outro(pc47.green("SMS infrastructure has been removed"));
35695
35763
  console.log(`
35696
35764
  ${pc47.bold("Cleaned up:")}`);
35697
35765
  console.log(` ${pc47.green("\u2713")} Phone number released`);
@@ -35713,7 +35781,7 @@ Run ${pc47.cyan("wraps sms init")} to deploy infrastructure again.
35713
35781
 
35714
35782
  // src/commands/sms/init.ts
35715
35783
  init_esm_shims();
35716
- import * as clack44 from "@clack/prompts";
35784
+ import * as clack45 from "@clack/prompts";
35717
35785
  import * as pulumi29 from "@pulumi/pulumi";
35718
35786
  import pc48 from "picocolors";
35719
35787
  init_events();
@@ -36134,7 +36202,7 @@ function validateSMSConfig(config2) {
36134
36202
 
36135
36203
  // src/commands/sms/init.ts
36136
36204
  async function promptPhoneNumberType() {
36137
- const result = await clack44.select({
36205
+ const result = await clack45.select({
36138
36206
  message: "Select phone number type:",
36139
36207
  options: [
36140
36208
  {
@@ -36154,14 +36222,14 @@ async function promptPhoneNumberType() {
36154
36222
  }
36155
36223
  ]
36156
36224
  });
36157
- if (clack44.isCancel(result)) {
36158
- clack44.cancel("Operation cancelled.");
36225
+ if (clack45.isCancel(result)) {
36226
+ clack45.cancel("Operation cancelled.");
36159
36227
  process.exit(0);
36160
36228
  }
36161
36229
  return result;
36162
36230
  }
36163
36231
  async function promptSMSPreset() {
36164
- const result = await clack44.select({
36232
+ const result = await clack45.select({
36165
36233
  message: "Choose configuration preset:",
36166
36234
  options: [
36167
36235
  {
@@ -36186,8 +36254,8 @@ async function promptSMSPreset() {
36186
36254
  }
36187
36255
  ]
36188
36256
  });
36189
- if (clack44.isCancel(result)) {
36190
- clack44.cancel("Operation cancelled.");
36257
+ if (clack45.isCancel(result)) {
36258
+ clack45.cancel("Operation cancelled.");
36191
36259
  process.exit(0);
36192
36260
  }
36193
36261
  return result;
@@ -36207,7 +36275,7 @@ var COMMON_COUNTRIES = [
36207
36275
  { code: "IN", name: "India" }
36208
36276
  ];
36209
36277
  async function promptAllowedCountries() {
36210
- const result = await clack44.multiselect({
36278
+ const result = await clack45.multiselect({
36211
36279
  message: "Select countries to allow SMS delivery (blocks all others):",
36212
36280
  options: COMMON_COUNTRIES.map((c) => ({
36213
36281
  value: c.code,
@@ -36216,14 +36284,14 @@ async function promptAllowedCountries() {
36216
36284
  initialValues: ["US"],
36217
36285
  required: true
36218
36286
  });
36219
- if (clack44.isCancel(result)) {
36220
- clack44.cancel("Operation cancelled.");
36287
+ if (clack45.isCancel(result)) {
36288
+ clack45.cancel("Operation cancelled.");
36221
36289
  process.exit(0);
36222
36290
  }
36223
36291
  return result;
36224
36292
  }
36225
36293
  async function promptEstimatedSMSVolume() {
36226
- const result = await clack44.select({
36294
+ const result = await clack45.select({
36227
36295
  message: "Estimated messages per month:",
36228
36296
  options: [
36229
36297
  { value: 100, label: "< 100 (Testing)" },
@@ -36233,8 +36301,8 @@ async function promptEstimatedSMSVolume() {
36233
36301
  { value: 1e5, label: "50,000+" }
36234
36302
  ]
36235
36303
  });
36236
- if (clack44.isCancel(result)) {
36237
- clack44.cancel("Operation cancelled.");
36304
+ if (clack45.isCancel(result)) {
36305
+ clack45.cancel("Operation cancelled.");
36238
36306
  process.exit(0);
36239
36307
  }
36240
36308
  return result;
@@ -36242,7 +36310,7 @@ async function promptEstimatedSMSVolume() {
36242
36310
  async function init3(options) {
36243
36311
  const startTime = Date.now();
36244
36312
  if (!isJsonMode()) {
36245
- clack44.intro(pc48.bold("Wraps SMS Infrastructure Setup"));
36313
+ clack45.intro(pc48.bold("Wraps SMS Infrastructure Setup"));
36246
36314
  }
36247
36315
  const progress = new DeploymentProgress();
36248
36316
  const wasAutoInstalled = await progress.execute(
@@ -36268,10 +36336,10 @@ async function init3(options) {
36268
36336
  region
36269
36337
  );
36270
36338
  if (existingConnection?.services?.sms) {
36271
- clack44.log.warn(
36339
+ clack45.log.warn(
36272
36340
  `SMS already configured for account ${pc48.cyan(identity.accountId)} in region ${pc48.cyan(region)}`
36273
36341
  );
36274
- clack44.log.info(`Use ${pc48.cyan("wraps sms status")} to view current setup`);
36342
+ clack45.log.info(`Use ${pc48.cyan("wraps sms status")} to view current setup`);
36275
36343
  process.exit(0);
36276
36344
  }
36277
36345
  let preset = options.preset;
@@ -36288,12 +36356,12 @@ async function init3(options) {
36288
36356
  optOutManagement: true,
36289
36357
  sendingEnabled: true
36290
36358
  };
36291
- const enableEventTracking = await clack44.confirm({
36359
+ const enableEventTracking = await clack45.confirm({
36292
36360
  message: "Enable event tracking (EventBridge + DynamoDB)?",
36293
36361
  initialValue: false
36294
36362
  });
36295
- if (clack44.isCancel(enableEventTracking)) {
36296
- clack44.cancel("Operation cancelled.");
36363
+ if (clack45.isCancel(enableEventTracking)) {
36364
+ clack45.cancel("Operation cancelled.");
36297
36365
  process.exit(0);
36298
36366
  }
36299
36367
  if (enableEventTracking) {
@@ -36318,12 +36386,12 @@ ${pc48.bold("Fraud Protection")} - Block SMS to countries where you don't do bus
36318
36386
  const allowedCountries = await promptAllowedCountries();
36319
36387
  let aitFiltering = false;
36320
36388
  if (smsConfig.phoneNumberType !== "simulator") {
36321
- const enableAIT = await clack44.confirm({
36389
+ const enableAIT = await clack45.confirm({
36322
36390
  message: "Enable AIT (Artificially Inflated Traffic) filtering? (adds per-message cost)",
36323
36391
  initialValue: false
36324
36392
  });
36325
- if (clack44.isCancel(enableAIT)) {
36326
- clack44.cancel("Operation cancelled.");
36393
+ if (clack45.isCancel(enableAIT)) {
36394
+ clack45.cancel("Operation cancelled.");
36327
36395
  process.exit(0);
36328
36396
  }
36329
36397
  aitFiltering = enableAIT;
@@ -36337,19 +36405,19 @@ ${pc48.bold("Fraud Protection")} - Block SMS to countries where you don't do bus
36337
36405
  progress.info(`
36338
36406
  ${pc48.bold("Cost Estimate:")}`);
36339
36407
  const costSummary = getSMSCostSummary(smsConfig, estimatedVolume);
36340
- clack44.log.info(costSummary);
36408
+ clack45.log.info(costSummary);
36341
36409
  const warnings = validateSMSConfig(smsConfig);
36342
36410
  if (warnings.length > 0) {
36343
36411
  progress.info(`
36344
36412
  ${pc48.yellow(pc48.bold("Important Notes:"))}`);
36345
36413
  for (const warning of warnings) {
36346
- clack44.log.warn(warning);
36414
+ clack45.log.warn(warning);
36347
36415
  }
36348
36416
  }
36349
36417
  if (!options.yes) {
36350
36418
  const confirmed = await confirmDeploy();
36351
36419
  if (!confirmed) {
36352
- clack44.cancel("Deployment cancelled.");
36420
+ clack45.cancel("Deployment cancelled.");
36353
36421
  process.exit(0);
36354
36422
  }
36355
36423
  }
@@ -36425,8 +36493,8 @@ ${pc48.yellow(pc48.bold("Important Notes:"))}`);
36425
36493
  } catch (sdkError) {
36426
36494
  sdkResourceWarning = true;
36427
36495
  const msg = sdkError instanceof Error ? sdkError.message : String(sdkError);
36428
- clack44.log.warn(`Phone pool creation failed: ${msg}`);
36429
- clack44.log.info(
36496
+ clack45.log.warn(`Phone pool creation failed: ${msg}`);
36497
+ clack45.log.info(
36430
36498
  `Run ${pc48.cyan("wraps sms sync")} to retry SDK resource creation.`
36431
36499
  );
36432
36500
  }
@@ -36443,8 +36511,8 @@ ${pc48.yellow(pc48.bold("Important Notes:"))}`);
36443
36511
  } catch (sdkError) {
36444
36512
  sdkResourceWarning = true;
36445
36513
  const msg = sdkError instanceof Error ? sdkError.message : String(sdkError);
36446
- clack44.log.warn(`Event destination creation failed: ${msg}`);
36447
- clack44.log.info(
36514
+ clack45.log.warn(`Event destination creation failed: ${msg}`);
36515
+ clack45.log.info(
36448
36516
  `Run ${pc48.cyan("wraps sms sync")} to retry SDK resource creation.`
36449
36517
  );
36450
36518
  }
@@ -36464,14 +36532,14 @@ ${pc48.yellow(pc48.bold("Important Notes:"))}`);
36464
36532
  } catch (sdkError) {
36465
36533
  sdkResourceWarning = true;
36466
36534
  const msg = sdkError instanceof Error ? sdkError.message : String(sdkError);
36467
- clack44.log.warn(`Protect configuration creation failed: ${msg}`);
36468
- clack44.log.info(
36535
+ clack45.log.warn(`Protect configuration creation failed: ${msg}`);
36536
+ clack45.log.info(
36469
36537
  `Run ${pc48.cyan("wraps sms sync")} to retry SDK resource creation.`
36470
36538
  );
36471
36539
  }
36472
36540
  }
36473
36541
  if (sdkResourceWarning) {
36474
- clack44.log.warn(
36542
+ clack45.log.warn(
36475
36543
  "Some SDK resources failed to create. Core infrastructure is deployed."
36476
36544
  );
36477
36545
  }
@@ -36516,9 +36584,9 @@ ${pc48.yellow(pc48.bold("Important Notes:"))}`);
36516
36584
  return;
36517
36585
  }
36518
36586
  console.log("\n");
36519
- clack44.log.success(pc48.green(pc48.bold("SMS infrastructure deployed!")));
36587
+ clack45.log.success(pc48.green(pc48.bold("SMS infrastructure deployed!")));
36520
36588
  console.log("\n");
36521
- clack44.note(
36589
+ clack45.note(
36522
36590
  [
36523
36591
  `${pc48.bold("Phone Number:")} ${pc48.cyan(outputs.phoneNumber || "Provisioning...")}`,
36524
36592
  `${pc48.bold("Phone Type:")} ${pc48.cyan(smsConfig.phoneNumberType || "simulator")}`,
@@ -36542,12 +36610,12 @@ ${pc48.yellow(pc48.bold("Important Notes:"))}`);
36542
36610
  );
36543
36611
  nextSteps.push(`${pc48.cyan("wraps sms status")} - View SMS configuration`);
36544
36612
  console.log("\n");
36545
- clack44.log.info(pc48.bold("Next steps:"));
36613
+ clack45.log.info(pc48.bold("Next steps:"));
36546
36614
  for (const step of nextSteps) {
36547
36615
  console.log(` ${step}`);
36548
36616
  }
36549
36617
  console.log("\n");
36550
- clack44.log.info(pc48.bold("SDK Usage:"));
36618
+ clack45.log.info(pc48.bold("SDK Usage:"));
36551
36619
  console.log(pc48.dim(" npm install @wraps.dev/sms"));
36552
36620
  console.log("");
36553
36621
  console.log(pc48.dim(" import { Wraps } from '@wraps.dev/sms';"));
@@ -36556,7 +36624,7 @@ ${pc48.yellow(pc48.bold("Important Notes:"))}`);
36556
36624
  console.log(pc48.dim(" to: '+14155551234',"));
36557
36625
  console.log(pc48.dim(" message: 'Your code is 123456',"));
36558
36626
  console.log(pc48.dim(" });"));
36559
- clack44.outro(pc48.green("Setup complete!"));
36627
+ clack45.outro(pc48.green("Setup complete!"));
36560
36628
  const duration = Date.now() - startTime;
36561
36629
  const enabledFeatures = [];
36562
36630
  if (smsConfig.tracking?.enabled) {
@@ -36592,7 +36660,7 @@ init_aws();
36592
36660
  init_json_output();
36593
36661
  init_metadata();
36594
36662
  init_output();
36595
- import * as clack45 from "@clack/prompts";
36663
+ import * as clack46 from "@clack/prompts";
36596
36664
  import pc49 from "picocolors";
36597
36665
  async function getPhoneNumberDetails(region) {
36598
36666
  const { PinpointSMSVoiceV2Client: PinpointSMSVoiceV2Client5, DescribePhoneNumbersCommand: DescribePhoneNumbersCommand2 } = await import("@aws-sdk/client-pinpoint-sms-voice-v2");
@@ -36613,7 +36681,7 @@ async function getPhoneNumberDetails(region) {
36613
36681
  return null;
36614
36682
  } catch (error) {
36615
36683
  const errorMessage = error instanceof Error ? error.message : String(error);
36616
- clack45.log.error(`Error fetching phone number: ${errorMessage}`);
36684
+ clack46.log.error(`Error fetching phone number: ${errorMessage}`);
36617
36685
  return null;
36618
36686
  }
36619
36687
  }
@@ -36634,7 +36702,7 @@ async function getRegistrationStatus(region, registrationId) {
36634
36702
  async function smsRegister(options) {
36635
36703
  const startTime = Date.now();
36636
36704
  if (!isJsonMode()) {
36637
- clack45.intro(pc49.bold("Wraps SMS - Toll-Free Registration"));
36705
+ clack46.intro(pc49.bold("Wraps SMS - Toll-Free Registration"));
36638
36706
  }
36639
36707
  const progress = new DeploymentProgress();
36640
36708
  const identity = await progress.execute(
@@ -36647,8 +36715,8 @@ async function smsRegister(options) {
36647
36715
  }
36648
36716
  const metadata = await loadConnectionMetadata(identity.accountId, region);
36649
36717
  if (!metadata?.services?.sms) {
36650
- clack45.log.error("No SMS infrastructure found.");
36651
- clack45.log.info(`Run ${pc49.cyan("wraps sms init")} first.`);
36718
+ clack46.log.error("No SMS infrastructure found.");
36719
+ clack46.log.info(`Run ${pc49.cyan("wraps sms init")} first.`);
36652
36720
  process.exit(1);
36653
36721
  }
36654
36722
  const phoneDetails = await progress.execute(
@@ -36656,7 +36724,7 @@ async function smsRegister(options) {
36656
36724
  async () => getPhoneNumberDetails(region)
36657
36725
  );
36658
36726
  if (!phoneDetails) {
36659
- clack45.log.error("No phone number found.");
36727
+ clack46.log.error("No phone number found.");
36660
36728
  process.exit(1);
36661
36729
  }
36662
36730
  let registrationStatus = null;
@@ -36693,18 +36761,18 @@ async function smsRegister(options) {
36693
36761
  }
36694
36762
  console.log("");
36695
36763
  if (phoneDetails.status === "ACTIVE") {
36696
- clack45.log.success("Your phone number is already ACTIVE and ready to use!");
36764
+ clack46.log.success("Your phone number is already ACTIVE and ready to use!");
36697
36765
  const { PinpointSMSVoiceV2Client: PinpointSMSVoiceV2Client5, DescribePoolsCommand } = await import("@aws-sdk/client-pinpoint-sms-voice-v2");
36698
36766
  const client = new PinpointSMSVoiceV2Client5({ region });
36699
36767
  const pools = await client.send(new DescribePoolsCommand({}));
36700
36768
  if (!pools.Pools?.length) {
36701
- clack45.log.info("Run `wraps sms sync` to create the phone pool.");
36769
+ clack46.log.info("Run `wraps sms sync` to create the phone pool.");
36702
36770
  }
36703
36771
  process.exit(0);
36704
36772
  }
36705
36773
  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.`);
36774
+ clack46.log.info("Only toll-free numbers require registration.");
36775
+ clack46.log.info(`Your ${phoneDetails.type} number should be ready to use.`);
36708
36776
  process.exit(0);
36709
36777
  }
36710
36778
  console.log(pc49.bold("Toll-Free Registration Required"));
@@ -36723,12 +36791,12 @@ async function smsRegister(options) {
36723
36791
  console.log(` ${pc49.dim("\u2022")} How users opt-in to receive messages`);
36724
36792
  console.log(` ${pc49.dim("\u2022")} Expected monthly message volume`);
36725
36793
  console.log("");
36726
- const openConsole = await clack45.confirm({
36794
+ const openConsole = await clack46.confirm({
36727
36795
  message: "Open AWS Console to start registration?",
36728
36796
  initialValue: true
36729
36797
  });
36730
- if (clack45.isCancel(openConsole)) {
36731
- clack45.cancel("Registration cancelled.");
36798
+ if (clack46.isCancel(openConsole)) {
36799
+ clack46.cancel("Registration cancelled.");
36732
36800
  process.exit(0);
36733
36801
  }
36734
36802
  if (openConsole) {
@@ -36738,13 +36806,13 @@ async function smsRegister(options) {
36738
36806
  const execAsync2 = promisify2(exec2);
36739
36807
  try {
36740
36808
  await execAsync2(`open "${consoleUrl}"`);
36741
- clack45.log.success("Opened AWS Console in your browser.");
36809
+ clack46.log.success("Opened AWS Console in your browser.");
36742
36810
  } catch {
36743
36811
  try {
36744
36812
  await execAsync2(`xdg-open "${consoleUrl}"`);
36745
- clack45.log.success("Opened AWS Console in your browser.");
36813
+ clack46.log.success("Opened AWS Console in your browser.");
36746
36814
  } catch {
36747
- clack45.log.info("Open this URL in your browser:");
36815
+ clack46.log.info("Open this URL in your browser:");
36748
36816
  console.log(`
36749
36817
  ${pc49.cyan(consoleUrl)}
36750
36818
  `);
@@ -36772,7 +36840,7 @@ async function smsRegister(options) {
36772
36840
  success: true,
36773
36841
  duration_ms: Date.now() - startTime
36774
36842
  });
36775
- clack45.outro(pc49.dim("Good luck with your registration!"));
36843
+ clack46.outro(pc49.dim("Good luck with your registration!"));
36776
36844
  }
36777
36845
 
36778
36846
  // src/commands/sms/status.ts
@@ -36784,7 +36852,8 @@ init_json_output();
36784
36852
  init_metadata();
36785
36853
  init_output();
36786
36854
  init_pulumi();
36787
- import * as clack46 from "@clack/prompts";
36855
+ init_region_resolver();
36856
+ import * as clack47 from "@clack/prompts";
36788
36857
  import * as pulumi30 from "@pulumi/pulumi";
36789
36858
  import pc50 from "picocolors";
36790
36859
  function displaySMSStatus(options) {
@@ -36824,24 +36893,29 @@ function displaySMSStatus(options) {
36824
36893
  lines.push(pc50.bold("IAM Role"));
36825
36894
  lines.push(` ${pc50.dim(options.roleArn)}`);
36826
36895
  }
36827
- clack46.note(lines.join("\n"), "SMS Status");
36896
+ clack47.note(lines.join("\n"), "SMS Status");
36828
36897
  }
36829
- async function smsStatus(_options) {
36898
+ async function smsStatus(options) {
36830
36899
  await ensurePulumiInstalled();
36831
36900
  const startTime = Date.now();
36832
36901
  const progress = new DeploymentProgress();
36833
36902
  if (!isJsonMode()) {
36834
- clack46.intro(pc50.bold("Wraps SMS Status"));
36903
+ clack47.intro(pc50.bold("Wraps SMS Status"));
36835
36904
  }
36836
36905
  const identity = await progress.execute(
36837
36906
  "Loading SMS infrastructure status",
36838
36907
  async () => validateAWSCredentials()
36839
36908
  );
36840
- const region = await getAWSRegion();
36909
+ const region = await resolveRegionForCommand({
36910
+ accountId: identity.accountId,
36911
+ optionRegion: options.region,
36912
+ service: "sms",
36913
+ label: "SMS deployment"
36914
+ });
36841
36915
  const metadata = await loadConnectionMetadata(identity.accountId, region);
36842
36916
  if (!metadata?.services?.sms) {
36843
36917
  progress.stop();
36844
- clack46.log.error("No SMS infrastructure found");
36918
+ clack47.log.error("No SMS infrastructure found");
36845
36919
  console.log(
36846
36920
  `
36847
36921
  Run ${pc50.cyan("wraps sms init")} to deploy SMS infrastructure.
@@ -36880,7 +36954,7 @@ Run ${pc50.cyan("wraps sms init")} to deploy SMS infrastructure.
36880
36954
  }
36881
36955
  displaySMSStatus(smsStatusData);
36882
36956
  console.log("");
36883
- clack46.log.info(pc50.bold("Commands:"));
36957
+ clack47.log.info(pc50.bold("Commands:"));
36884
36958
  console.log(
36885
36959
  ` ${pc50.cyan("wraps sms test --to +1234567890")} - Send a test message`
36886
36960
  );
@@ -36891,12 +36965,12 @@ Run ${pc50.cyan("wraps sms init")} to deploy SMS infrastructure.
36891
36965
  event_tracking: smsConfig?.eventTracking?.enabled,
36892
36966
  duration_ms: Date.now() - startTime
36893
36967
  });
36894
- clack46.outro(pc50.dim("SMS infrastructure is ready"));
36968
+ clack47.outro(pc50.dim("SMS infrastructure is ready"));
36895
36969
  }
36896
36970
 
36897
36971
  // src/commands/sms/sync.ts
36898
36972
  init_esm_shims();
36899
- import * as clack47 from "@clack/prompts";
36973
+ import * as clack48 from "@clack/prompts";
36900
36974
  import * as pulumi31 from "@pulumi/pulumi";
36901
36975
  import pc51 from "picocolors";
36902
36976
  init_events();
@@ -36911,7 +36985,7 @@ async function smsSync(options) {
36911
36985
  await ensurePulumiInstalled();
36912
36986
  const startTime = Date.now();
36913
36987
  if (!isJsonMode()) {
36914
- clack47.intro(pc51.bold("Wraps SMS Infrastructure Sync"));
36988
+ clack48.intro(pc51.bold("Wraps SMS Infrastructure Sync"));
36915
36989
  }
36916
36990
  const progress = new DeploymentProgress();
36917
36991
  const identity = await progress.execute(
@@ -36923,7 +36997,7 @@ async function smsSync(options) {
36923
36997
  const smsService = metadata?.services?.sms;
36924
36998
  if (!smsService?.config) {
36925
36999
  progress.stop();
36926
- clack47.log.error("No SMS infrastructure found to sync");
37000
+ clack48.log.error("No SMS infrastructure found to sync");
36927
37001
  console.log(
36928
37002
  `
36929
37003
  Run ${pc51.cyan("wraps sms init")} to deploy SMS infrastructure first.
@@ -36941,12 +37015,12 @@ Run ${pc51.cyan("wraps sms init")} to deploy SMS infrastructure first.
36941
37015
  `Event tracking: ${pc51.cyan(smsConfig.eventTracking?.enabled ? "enabled" : "disabled")}`
36942
37016
  );
36943
37017
  if (!options.yes) {
36944
- const confirmed = await clack47.confirm({
37018
+ const confirmed = await clack48.confirm({
36945
37019
  message: "Sync SMS infrastructure? This will update Lambda code and recreate any missing resources.",
36946
37020
  initialValue: true
36947
37021
  });
36948
- if (clack47.isCancel(confirmed) || !confirmed) {
36949
- clack47.cancel("Sync cancelled.");
37022
+ if (clack48.isCancel(confirmed) || !confirmed) {
37023
+ clack48.cancel("Sync cancelled.");
36950
37024
  process.exit(0);
36951
37025
  }
36952
37026
  }
@@ -37051,7 +37125,7 @@ Run ${pc51.cyan("wraps sms init")} to deploy SMS infrastructure first.
37051
37125
  throw errors.stackLocked();
37052
37126
  }
37053
37127
  trackError("SYNC_FAILED", "sms:sync", { step: "sync" });
37054
- clack47.log.error(`SMS sync failed: ${errorMessage}`);
37128
+ clack48.log.error(`SMS sync failed: ${errorMessage}`);
37055
37129
  process.exit(1);
37056
37130
  }
37057
37131
  if (metadata && smsService) {
@@ -37071,7 +37145,7 @@ Run ${pc51.cyan("wraps sms init")} to deploy SMS infrastructure first.
37071
37145
  return;
37072
37146
  }
37073
37147
  console.log("\n");
37074
- clack47.log.success(pc51.green("SMS infrastructure synced successfully!"));
37148
+ clack48.log.success(pc51.green("SMS infrastructure synced successfully!"));
37075
37149
  const changes = [];
37076
37150
  if (outputs.lambdaFunctions?.length) {
37077
37151
  changes.push("Lambda functions updated");
@@ -37085,7 +37159,7 @@ Run ${pc51.cyan("wraps sms init")} to deploy SMS infrastructure first.
37085
37159
  success: true,
37086
37160
  duration_ms: Date.now() - startTime
37087
37161
  });
37088
- clack47.outro(pc51.green("Sync complete!"));
37162
+ clack48.outro(pc51.green("Sync complete!"));
37089
37163
  }
37090
37164
 
37091
37165
  // src/commands/sms/test.ts
@@ -37100,7 +37174,7 @@ import {
37100
37174
  PinpointSMSVoiceV2Client as PinpointSMSVoiceV2Client3,
37101
37175
  SendTextMessageCommand
37102
37176
  } from "@aws-sdk/client-pinpoint-sms-voice-v2";
37103
- import * as clack48 from "@clack/prompts";
37177
+ import * as clack49 from "@clack/prompts";
37104
37178
  import pc52 from "picocolors";
37105
37179
 
37106
37180
  // src/utils/sms/validation.ts
@@ -37124,7 +37198,7 @@ async function smsTest(options) {
37124
37198
  const startTime = Date.now();
37125
37199
  const progress = new DeploymentProgress();
37126
37200
  if (!isJsonMode()) {
37127
- clack48.intro(pc52.bold("Wraps SMS Test"));
37201
+ clack49.intro(pc52.bold("Wraps SMS Test"));
37128
37202
  }
37129
37203
  const identity = await progress.execute(
37130
37204
  "Validating AWS credentials",
@@ -37134,7 +37208,7 @@ async function smsTest(options) {
37134
37208
  const metadata = await loadConnectionMetadata(identity.accountId, region);
37135
37209
  if (!metadata?.services?.sms) {
37136
37210
  progress.stop();
37137
- clack48.log.error("No SMS infrastructure found");
37211
+ clack49.log.error("No SMS infrastructure found");
37138
37212
  console.log(
37139
37213
  `
37140
37214
  Run ${pc52.cyan("wraps sms init")} to deploy SMS infrastructure.
@@ -37151,7 +37225,7 @@ Run ${pc52.cyan("wraps sms init")} to deploy SMS infrastructure.
37151
37225
  );
37152
37226
  }
37153
37227
  if (!toNumber) {
37154
- const destinationType = await clack48.select({
37228
+ const destinationType = await clack49.select({
37155
37229
  message: "Choose destination number:",
37156
37230
  options: [
37157
37231
  {
@@ -37166,25 +37240,25 @@ Run ${pc52.cyan("wraps sms init")} to deploy SMS infrastructure.
37166
37240
  }
37167
37241
  ]
37168
37242
  });
37169
- if (clack48.isCancel(destinationType)) {
37170
- clack48.cancel("Operation cancelled.");
37243
+ if (clack49.isCancel(destinationType)) {
37244
+ clack49.cancel("Operation cancelled.");
37171
37245
  process.exit(0);
37172
37246
  }
37173
37247
  if (destinationType === "simulator") {
37174
- const simResult = await clack48.select({
37248
+ const simResult = await clack49.select({
37175
37249
  message: "Select simulator destination:",
37176
37250
  options: SIMULATOR_DESTINATIONS.map((sim) => ({
37177
37251
  value: sim.number,
37178
37252
  label: `${sim.number} | ${sim.country}`
37179
37253
  }))
37180
37254
  });
37181
- if (clack48.isCancel(simResult)) {
37182
- clack48.cancel("Operation cancelled.");
37255
+ if (clack49.isCancel(simResult)) {
37256
+ clack49.cancel("Operation cancelled.");
37183
37257
  process.exit(0);
37184
37258
  }
37185
37259
  toNumber = simResult;
37186
37260
  } else {
37187
- const result = await clack48.text({
37261
+ const result = await clack49.text({
37188
37262
  message: "Enter destination phone number (E.164 format):",
37189
37263
  placeholder: "+14155551234",
37190
37264
  validate: (value) => {
@@ -37197,22 +37271,22 @@ Run ${pc52.cyan("wraps sms init")} to deploy SMS infrastructure.
37197
37271
  return;
37198
37272
  }
37199
37273
  });
37200
- if (clack48.isCancel(result)) {
37201
- clack48.cancel("Operation cancelled.");
37274
+ if (clack49.isCancel(result)) {
37275
+ clack49.cancel("Operation cancelled.");
37202
37276
  process.exit(0);
37203
37277
  }
37204
37278
  toNumber = result;
37205
37279
  }
37206
37280
  } else if (!isValidPhoneNumber(toNumber)) {
37207
37281
  progress.stop();
37208
- clack48.log.error(
37282
+ clack49.log.error(
37209
37283
  `Invalid phone number format: ${toNumber}. Use E.164 format (e.g., +14155551234)`
37210
37284
  );
37211
37285
  process.exit(1);
37212
37286
  }
37213
37287
  let message = options.message;
37214
37288
  if (!message) {
37215
- const result = await clack48.text({
37289
+ const result = await clack49.text({
37216
37290
  message: "Enter test message:",
37217
37291
  placeholder: "Hello from Wraps SMS!",
37218
37292
  defaultValue: "Hello from Wraps SMS! This is a test message.",
@@ -37226,8 +37300,8 @@ Run ${pc52.cyan("wraps sms init")} to deploy SMS infrastructure.
37226
37300
  return;
37227
37301
  }
37228
37302
  });
37229
- if (clack48.isCancel(result)) {
37230
- clack48.cancel("Operation cancelled.");
37303
+ if (clack49.isCancel(result)) {
37304
+ clack49.cancel("Operation cancelled.");
37231
37305
  process.exit(0);
37232
37306
  }
37233
37307
  message = result;
@@ -37266,9 +37340,9 @@ Run ${pc52.cyan("wraps sms init")} to deploy SMS infrastructure.
37266
37340
  return;
37267
37341
  }
37268
37342
  console.log("\n");
37269
- clack48.log.success(pc52.green("Test SMS sent successfully!"));
37343
+ clack49.log.success(pc52.green("Test SMS sent successfully!"));
37270
37344
  console.log("");
37271
- clack48.note(
37345
+ clack49.note(
37272
37346
  [
37273
37347
  `${pc52.bold("Message ID:")} ${pc52.cyan(messageId || "unknown")}`,
37274
37348
  `${pc52.bold("To:")} ${pc52.cyan(toNumber)}`,
@@ -37283,11 +37357,11 @@ Run ${pc52.cyan("wraps sms init")} to deploy SMS infrastructure.
37283
37357
  );
37284
37358
  if (smsConfig?.eventTracking?.enabled) {
37285
37359
  console.log("");
37286
- clack48.log.info(
37360
+ clack49.log.info(
37287
37361
  pc52.dim("Event tracking is enabled. Check DynamoDB for delivery status.")
37288
37362
  );
37289
37363
  }
37290
- clack48.outro(pc52.green("Test complete!"));
37364
+ clack49.outro(pc52.green("Test complete!"));
37291
37365
  } catch (error) {
37292
37366
  progress.stop();
37293
37367
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -37299,24 +37373,24 @@ Run ${pc52.cyan("wraps sms init")} to deploy SMS infrastructure.
37299
37373
  });
37300
37374
  const errorName = error instanceof Error ? error.name : "";
37301
37375
  if (errorName === "ConflictException" || errorMessage.includes("opt-out")) {
37302
- clack48.log.error("Destination number has opted out of messages");
37376
+ clack49.log.error("Destination number has opted out of messages");
37303
37377
  console.log("\nThe recipient has opted out of receiving SMS messages.\n");
37304
37378
  } else if (errorName === "ThrottlingException" || errorMessage.includes("spending limit")) {
37305
- clack48.log.error("SMS rate or spending limit reached");
37379
+ clack49.log.error("SMS rate or spending limit reached");
37306
37380
  console.log(
37307
37381
  "\nCheck your AWS account SMS spending limits in the console.\n"
37308
37382
  );
37309
37383
  } else if (errorName === "ValidationException") {
37310
- clack48.log.error(`Invalid request: ${errorMessage}`);
37384
+ clack49.log.error(`Invalid request: ${errorMessage}`);
37311
37385
  } else if (errorMessage.includes("not verified") || errorMessage.includes("not registered")) {
37312
- clack48.log.error("Toll-free number registration is not complete");
37386
+ clack49.log.error("Toll-free number registration is not complete");
37313
37387
  console.log(
37314
37388
  `
37315
37389
  Run ${pc52.cyan("wraps sms register")} to check registration status.
37316
37390
  `
37317
37391
  );
37318
37392
  } else if (errorName === "AccessDeniedException") {
37319
- clack48.log.error(
37393
+ clack49.log.error(
37320
37394
  "Permission denied \u2014 IAM role may be missing SMS send permissions"
37321
37395
  );
37322
37396
  console.log(
@@ -37325,7 +37399,7 @@ Run ${pc52.cyan("wraps sms upgrade")} to update IAM policies.
37325
37399
  `
37326
37400
  );
37327
37401
  } else {
37328
- clack48.log.error(`Failed to send SMS: ${errorMessage}`);
37402
+ clack49.log.error(`Failed to send SMS: ${errorMessage}`);
37329
37403
  }
37330
37404
  process.exit(1);
37331
37405
  }
@@ -37333,7 +37407,7 @@ Run ${pc52.cyan("wraps sms upgrade")} to update IAM policies.
37333
37407
 
37334
37408
  // src/commands/sms/upgrade.ts
37335
37409
  init_esm_shims();
37336
- import * as clack49 from "@clack/prompts";
37410
+ import * as clack50 from "@clack/prompts";
37337
37411
  import * as pulumi32 from "@pulumi/pulumi";
37338
37412
  import pc53 from "picocolors";
37339
37413
  init_events();
@@ -37345,11 +37419,12 @@ init_metadata();
37345
37419
  init_output();
37346
37420
  init_prompts();
37347
37421
  init_pulumi();
37422
+ init_region_resolver();
37348
37423
  async function smsUpgrade(options) {
37349
37424
  const startTime = Date.now();
37350
37425
  let upgradeAction = "";
37351
37426
  if (!isJsonMode()) {
37352
- clack49.intro(pc53.bold("Wraps SMS Upgrade - Enhance Your SMS Infrastructure"));
37427
+ clack50.intro(pc53.bold("Wraps SMS Upgrade - Enhance Your SMS Infrastructure"));
37353
37428
  }
37354
37429
  const progress = new DeploymentProgress();
37355
37430
  const wasAutoInstalled = await progress.execute(
@@ -37364,24 +37439,25 @@ async function smsUpgrade(options) {
37364
37439
  async () => validateAWSCredentials()
37365
37440
  );
37366
37441
  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
- }
37442
+ const region = await resolveRegionForCommand({
37443
+ accountId: identity.accountId,
37444
+ optionRegion: options.region,
37445
+ service: "sms",
37446
+ label: "SMS deployment"
37447
+ });
37372
37448
  const metadata = await loadConnectionMetadata(identity.accountId, region);
37373
37449
  if (!metadata) {
37374
- clack49.log.error(
37450
+ clack50.log.error(
37375
37451
  `No Wraps connection found for account ${pc53.cyan(identity.accountId)} in region ${pc53.cyan(region)}`
37376
37452
  );
37377
- clack49.log.info(
37453
+ clack50.log.info(
37378
37454
  `Use ${pc53.cyan("wraps sms init")} to create new infrastructure.`
37379
37455
  );
37380
37456
  process.exit(1);
37381
37457
  }
37382
37458
  if (!metadata.services.sms) {
37383
- clack49.log.error("No SMS infrastructure found");
37384
- clack49.log.info(
37459
+ clack50.log.error("No SMS infrastructure found");
37460
+ clack50.log.info(
37385
37461
  `Use ${pc53.cyan("wraps sms init")} to deploy SMS infrastructure.`
37386
37462
  );
37387
37463
  process.exit(1);
@@ -37397,8 +37473,8 @@ ${pc53.bold("Current Configuration:")}
37397
37473
  }
37398
37474
  const config2 = metadata.services.sms.config;
37399
37475
  if (!config2) {
37400
- clack49.log.error("No SMS configuration found in metadata");
37401
- clack49.log.info(
37476
+ clack50.log.error("No SMS configuration found in metadata");
37477
+ clack50.log.info(
37402
37478
  `Use ${pc53.cyan("wraps sms init")} to create new infrastructure.`
37403
37479
  );
37404
37480
  process.exit(1);
@@ -37458,7 +37534,7 @@ ${pc53.bold("Current Configuration:")}
37458
37534
  "10dlc": "10DLC",
37459
37535
  "short-code": "Short code"
37460
37536
  };
37461
- upgradeAction = await clack49.select({
37537
+ upgradeAction = await clack50.select({
37462
37538
  message: "What would you like to do?",
37463
37539
  options: [
37464
37540
  {
@@ -37498,8 +37574,8 @@ ${pc53.bold("Current Configuration:")}
37498
37574
  }
37499
37575
  ]
37500
37576
  });
37501
- if (clack49.isCancel(upgradeAction)) {
37502
- clack49.cancel("Upgrade cancelled.");
37577
+ if (clack50.isCancel(upgradeAction)) {
37578
+ clack50.cancel("Upgrade cancelled.");
37503
37579
  process.exit(0);
37504
37580
  }
37505
37581
  let updatedConfig = { ...config2 };
@@ -37540,17 +37616,17 @@ ${pc53.bold("Current Configuration:")}
37540
37616
  hint: p.hint
37541
37617
  }));
37542
37618
  if (availableTypes.length === 0) {
37543
- clack49.log.warn(
37619
+ clack50.log.warn(
37544
37620
  "Already on highest phone number tier. Contact AWS for dedicated short codes."
37545
37621
  );
37546
37622
  process.exit(0);
37547
37623
  }
37548
- const selectedType = await clack49.select({
37624
+ const selectedType = await clack50.select({
37549
37625
  message: "Select new phone number type:",
37550
37626
  options: availableTypes
37551
37627
  });
37552
- if (clack49.isCancel(selectedType)) {
37553
- clack49.cancel("Upgrade cancelled.");
37628
+ if (clack50.isCancel(selectedType)) {
37629
+ clack50.cancel("Upgrade cancelled.");
37554
37630
  process.exit(0);
37555
37631
  }
37556
37632
  if (selectedType === "toll-free") {
@@ -37573,12 +37649,12 @@ ${pc53.yellow("\u26A0")} ${pc53.bold("Toll-free Registration Required")}
37573
37649
  console.log(
37574
37650
  pc53.dim("\nUntil verified, sending is limited to low volume.\n")
37575
37651
  );
37576
- const confirmTollFree = await clack49.confirm({
37652
+ const confirmTollFree = await clack50.confirm({
37577
37653
  message: "Continue with toll-free number request?",
37578
37654
  initialValue: true
37579
37655
  });
37580
- if (clack49.isCancel(confirmTollFree) || !confirmTollFree) {
37581
- clack49.cancel("Upgrade cancelled.");
37656
+ if (clack50.isCancel(confirmTollFree) || !confirmTollFree) {
37657
+ clack50.cancel("Upgrade cancelled.");
37582
37658
  process.exit(0);
37583
37659
  }
37584
37660
  }
@@ -37593,12 +37669,12 @@ ${pc53.yellow("\u26A0")} ${pc53.bold("10DLC Campaign Registration Required")}
37593
37669
  console.log(" \u2022 Campaign registration: $15/mo per campaign");
37594
37670
  console.log(" \u2022 Verification takes 1-7 business days");
37595
37671
  console.log("");
37596
- const confirm10DLC = await clack49.confirm({
37672
+ const confirm10DLC = await clack50.confirm({
37597
37673
  message: "Continue with 10DLC number request?",
37598
37674
  initialValue: true
37599
37675
  });
37600
- if (clack49.isCancel(confirm10DLC) || !confirm10DLC) {
37601
- clack49.cancel("Upgrade cancelled.");
37676
+ if (clack50.isCancel(confirm10DLC) || !confirm10DLC) {
37677
+ clack50.cancel("Upgrade cancelled.");
37602
37678
  process.exit(0);
37603
37679
  }
37604
37680
  }
@@ -37623,15 +37699,15 @@ ${pc53.yellow("\u26A0")} ${pc53.bold("10DLC Campaign Registration Required")}
37623
37699
  disabled: currentPresetIdx >= 0 && idx <= currentPresetIdx ? "Current or lower tier" : void 0
37624
37700
  })).filter((p) => !p.disabled && p.value !== "custom");
37625
37701
  if (availablePresets.length === 0) {
37626
- clack49.log.warn("Already on highest preset (Enterprise)");
37702
+ clack50.log.warn("Already on highest preset (Enterprise)");
37627
37703
  process.exit(0);
37628
37704
  }
37629
- const selectedPreset = await clack49.select({
37705
+ const selectedPreset = await clack50.select({
37630
37706
  message: "Select new preset:",
37631
37707
  options: availablePresets
37632
37708
  });
37633
- if (clack49.isCancel(selectedPreset)) {
37634
- clack49.cancel("Upgrade cancelled.");
37709
+ if (clack50.isCancel(selectedPreset)) {
37710
+ clack50.cancel("Upgrade cancelled.");
37635
37711
  process.exit(0);
37636
37712
  }
37637
37713
  const presetConfig = getSMSPreset(selectedPreset);
@@ -37647,7 +37723,7 @@ ${pc53.yellow("\u26A0")} ${pc53.bold("10DLC Campaign Registration Required")}
37647
37723
  }
37648
37724
  case "event-tracking": {
37649
37725
  if (config2.eventTracking?.enabled) {
37650
- const eventAction = await clack49.select({
37726
+ const eventAction = await clack50.select({
37651
37727
  message: "What would you like to do with event tracking?",
37652
37728
  options: [
37653
37729
  {
@@ -37662,17 +37738,17 @@ ${pc53.yellow("\u26A0")} ${pc53.bold("10DLC Campaign Registration Required")}
37662
37738
  }
37663
37739
  ]
37664
37740
  });
37665
- if (clack49.isCancel(eventAction)) {
37666
- clack49.cancel("Upgrade cancelled.");
37741
+ if (clack50.isCancel(eventAction)) {
37742
+ clack50.cancel("Upgrade cancelled.");
37667
37743
  process.exit(0);
37668
37744
  }
37669
37745
  if (eventAction === "disable") {
37670
- const confirmDisable = await clack49.confirm({
37746
+ const confirmDisable = await clack50.confirm({
37671
37747
  message: "Are you sure? Existing history will remain, but new events won't be tracked.",
37672
37748
  initialValue: false
37673
37749
  });
37674
- if (clack49.isCancel(confirmDisable) || !confirmDisable) {
37675
- clack49.cancel("Event tracking not disabled.");
37750
+ if (clack50.isCancel(confirmDisable) || !confirmDisable) {
37751
+ clack50.cancel("Event tracking not disabled.");
37676
37752
  process.exit(0);
37677
37753
  }
37678
37754
  updatedConfig = {
@@ -37682,7 +37758,7 @@ ${pc53.yellow("\u26A0")} ${pc53.bold("10DLC Campaign Registration Required")}
37682
37758
  }
37683
37759
  };
37684
37760
  } else {
37685
- const retention = await clack49.select({
37761
+ const retention = await clack50.select({
37686
37762
  message: "Message history retention period:",
37687
37763
  options: [
37688
37764
  { value: "7days", label: "7 days", hint: "Minimal storage cost" },
@@ -37709,8 +37785,8 @@ ${pc53.yellow("\u26A0")} ${pc53.bold("10DLC Campaign Registration Required")}
37709
37785
  ],
37710
37786
  initialValue: config2.eventTracking.archiveRetention || "90days"
37711
37787
  });
37712
- if (clack49.isCancel(retention)) {
37713
- clack49.cancel("Upgrade cancelled.");
37788
+ if (clack50.isCancel(retention)) {
37789
+ clack50.cancel("Upgrade cancelled.");
37714
37790
  process.exit(0);
37715
37791
  }
37716
37792
  updatedConfig = {
@@ -37722,19 +37798,19 @@ ${pc53.yellow("\u26A0")} ${pc53.bold("10DLC Campaign Registration Required")}
37722
37798
  };
37723
37799
  }
37724
37800
  } else {
37725
- const enableTracking = await clack49.confirm({
37801
+ const enableTracking = await clack50.confirm({
37726
37802
  message: "Enable event tracking? (Track SMS events with history)",
37727
37803
  initialValue: true
37728
37804
  });
37729
- if (clack49.isCancel(enableTracking)) {
37730
- clack49.cancel("Upgrade cancelled.");
37805
+ if (clack50.isCancel(enableTracking)) {
37806
+ clack50.cancel("Upgrade cancelled.");
37731
37807
  process.exit(0);
37732
37808
  }
37733
37809
  if (!enableTracking) {
37734
- clack49.log.info("Event tracking not enabled.");
37810
+ clack50.log.info("Event tracking not enabled.");
37735
37811
  process.exit(0);
37736
37812
  }
37737
- const retention = await clack49.select({
37813
+ const retention = await clack50.select({
37738
37814
  message: "Message history retention period:",
37739
37815
  options: [
37740
37816
  { value: "7days", label: "7 days", hint: "Minimal storage cost" },
@@ -37757,8 +37833,8 @@ ${pc53.yellow("\u26A0")} ${pc53.bold("10DLC Campaign Registration Required")}
37757
37833
  ],
37758
37834
  initialValue: "90days"
37759
37835
  });
37760
- if (clack49.isCancel(retention)) {
37761
- clack49.cancel("Upgrade cancelled.");
37836
+ if (clack50.isCancel(retention)) {
37837
+ clack50.cancel("Upgrade cancelled.");
37762
37838
  process.exit(0);
37763
37839
  }
37764
37840
  updatedConfig = {
@@ -37777,12 +37853,12 @@ ${pc53.yellow("\u26A0")} ${pc53.bold("10DLC Campaign Registration Required")}
37777
37853
  }
37778
37854
  case "retention": {
37779
37855
  if (!config2.eventTracking?.enabled) {
37780
- clack49.log.error(
37856
+ clack50.log.error(
37781
37857
  "Event tracking is not enabled. Enable it first to change retention."
37782
37858
  );
37783
37859
  process.exit(1);
37784
37860
  }
37785
- const retention = await clack49.select({
37861
+ const retention = await clack50.select({
37786
37862
  message: "Message history retention period (event data in DynamoDB):",
37787
37863
  options: [
37788
37864
  { value: "7days", label: "7 days", hint: "Minimal storage cost" },
@@ -37801,8 +37877,8 @@ ${pc53.yellow("\u26A0")} ${pc53.bold("10DLC Campaign Registration Required")}
37801
37877
  ],
37802
37878
  initialValue: config2.eventTracking.archiveRetention || "90days"
37803
37879
  });
37804
- if (clack49.isCancel(retention)) {
37805
- clack49.cancel("Upgrade cancelled.");
37880
+ if (clack50.isCancel(retention)) {
37881
+ clack50.cancel("Upgrade cancelled.");
37806
37882
  process.exit(0);
37807
37883
  }
37808
37884
  updatedConfig = {
@@ -37820,21 +37896,21 @@ ${pc53.yellow("\u26A0")} ${pc53.bold("10DLC Campaign Registration Required")}
37820
37896
  case "link-tracking": {
37821
37897
  const enableLinkTracking = !config2.tracking?.linkTracking;
37822
37898
  if (enableLinkTracking) {
37823
- clack49.log.info(
37899
+ clack50.log.info(
37824
37900
  pc53.dim(
37825
37901
  "Link tracking will track clicks on URLs in your SMS messages."
37826
37902
  )
37827
37903
  );
37828
- clack49.log.info(
37904
+ clack50.log.info(
37829
37905
  pc53.dim("URLs will be rewritten to go through a tracking endpoint.")
37830
37906
  );
37831
37907
  }
37832
- const confirmed = await clack49.confirm({
37908
+ const confirmed = await clack50.confirm({
37833
37909
  message: enableLinkTracking ? "Enable link click tracking?" : "Disable link click tracking?",
37834
37910
  initialValue: enableLinkTracking
37835
37911
  });
37836
- if (clack49.isCancel(confirmed) || !confirmed) {
37837
- clack49.cancel("Upgrade cancelled.");
37912
+ if (clack50.isCancel(confirmed) || !confirmed) {
37913
+ clack50.cancel("Upgrade cancelled.");
37838
37914
  process.exit(0);
37839
37915
  }
37840
37916
  updatedConfig = {
@@ -37851,7 +37927,7 @@ ${pc53.yellow("\u26A0")} ${pc53.bold("10DLC Campaign Registration Required")}
37851
37927
  }
37852
37928
  case "archiving": {
37853
37929
  if (config2.messageArchiving?.enabled) {
37854
- const archivingAction = await clack49.select({
37930
+ const archivingAction = await clack50.select({
37855
37931
  message: "What would you like to do with message archiving?",
37856
37932
  options: [
37857
37933
  {
@@ -37866,17 +37942,17 @@ ${pc53.yellow("\u26A0")} ${pc53.bold("10DLC Campaign Registration Required")}
37866
37942
  }
37867
37943
  ]
37868
37944
  });
37869
- if (clack49.isCancel(archivingAction)) {
37870
- clack49.cancel("Upgrade cancelled.");
37945
+ if (clack50.isCancel(archivingAction)) {
37946
+ clack50.cancel("Upgrade cancelled.");
37871
37947
  process.exit(0);
37872
37948
  }
37873
37949
  if (archivingAction === "disable") {
37874
- const confirmDisable = await clack49.confirm({
37950
+ const confirmDisable = await clack50.confirm({
37875
37951
  message: "Are you sure? Existing archived messages will remain, but new messages won't be archived.",
37876
37952
  initialValue: false
37877
37953
  });
37878
- if (clack49.isCancel(confirmDisable) || !confirmDisable) {
37879
- clack49.cancel("Archiving not disabled.");
37954
+ if (clack50.isCancel(confirmDisable) || !confirmDisable) {
37955
+ clack50.cancel("Archiving not disabled.");
37880
37956
  process.exit(0);
37881
37957
  }
37882
37958
  updatedConfig = {
@@ -37887,7 +37963,7 @@ ${pc53.yellow("\u26A0")} ${pc53.bold("10DLC Campaign Registration Required")}
37887
37963
  }
37888
37964
  };
37889
37965
  } else {
37890
- const retention = await clack49.select({
37966
+ const retention = await clack50.select({
37891
37967
  message: "Message archive retention period:",
37892
37968
  options: [
37893
37969
  {
@@ -37918,8 +37994,8 @@ ${pc53.yellow("\u26A0")} ${pc53.bold("10DLC Campaign Registration Required")}
37918
37994
  ],
37919
37995
  initialValue: config2.messageArchiving.retention
37920
37996
  });
37921
- if (clack49.isCancel(retention)) {
37922
- clack49.cancel("Upgrade cancelled.");
37997
+ if (clack50.isCancel(retention)) {
37998
+ clack50.cancel("Upgrade cancelled.");
37923
37999
  process.exit(0);
37924
38000
  }
37925
38001
  updatedConfig = {
@@ -37931,19 +38007,19 @@ ${pc53.yellow("\u26A0")} ${pc53.bold("10DLC Campaign Registration Required")}
37931
38007
  };
37932
38008
  }
37933
38009
  } else {
37934
- const enableArchiving = await clack49.confirm({
38010
+ const enableArchiving = await clack50.confirm({
37935
38011
  message: "Enable message archiving? (Store full message content for viewing)",
37936
38012
  initialValue: true
37937
38013
  });
37938
- if (clack49.isCancel(enableArchiving)) {
37939
- clack49.cancel("Upgrade cancelled.");
38014
+ if (clack50.isCancel(enableArchiving)) {
38015
+ clack50.cancel("Upgrade cancelled.");
37940
38016
  process.exit(0);
37941
38017
  }
37942
38018
  if (!enableArchiving) {
37943
- clack49.log.info("Message archiving not enabled.");
38019
+ clack50.log.info("Message archiving not enabled.");
37944
38020
  process.exit(0);
37945
38021
  }
37946
- const retention = await clack49.select({
38022
+ const retention = await clack50.select({
37947
38023
  message: "Message archive retention period:",
37948
38024
  options: [
37949
38025
  { value: "7days", label: "7 days", hint: "~$1-2/mo for 10k msgs" },
@@ -37970,8 +38046,8 @@ ${pc53.yellow("\u26A0")} ${pc53.bold("10DLC Campaign Registration Required")}
37970
38046
  ],
37971
38047
  initialValue: "90days"
37972
38048
  });
37973
- if (clack49.isCancel(retention)) {
37974
- clack49.cancel("Upgrade cancelled.");
38049
+ if (clack50.isCancel(retention)) {
38050
+ clack50.cancel("Upgrade cancelled.");
37975
38051
  process.exit(0);
37976
38052
  }
37977
38053
  updatedConfig = {
@@ -38003,7 +38079,7 @@ ${pc53.yellow("\u26A0")} ${pc53.bold("10DLC Campaign Registration Required")}
38003
38079
  const currentAllowed = config2.protectConfiguration?.allowedCountries || [
38004
38080
  "US"
38005
38081
  ];
38006
- const selectedCountries = await clack49.multiselect({
38082
+ const selectedCountries = await clack50.multiselect({
38007
38083
  message: "Select countries to allow SMS delivery (all others blocked):",
38008
38084
  options: commonCountries.map((c) => ({
38009
38085
  value: c.code,
@@ -38012,16 +38088,16 @@ ${pc53.yellow("\u26A0")} ${pc53.bold("10DLC Campaign Registration Required")}
38012
38088
  initialValues: currentAllowed,
38013
38089
  required: true
38014
38090
  });
38015
- if (clack49.isCancel(selectedCountries)) {
38016
- clack49.cancel("Upgrade cancelled.");
38091
+ if (clack50.isCancel(selectedCountries)) {
38092
+ clack50.cancel("Upgrade cancelled.");
38017
38093
  process.exit(0);
38018
38094
  }
38019
- const enableAIT = await clack49.confirm({
38095
+ const enableAIT = await clack50.confirm({
38020
38096
  message: "Enable AIT (Artificially Inflated Traffic) filtering? (adds per-message cost)",
38021
38097
  initialValue: config2.protectConfiguration?.aitFiltering ?? false
38022
38098
  });
38023
- if (clack49.isCancel(enableAIT)) {
38024
- clack49.cancel("Upgrade cancelled.");
38099
+ if (clack50.isCancel(enableAIT)) {
38100
+ clack50.cancel("Upgrade cancelled.");
38025
38101
  process.exit(0);
38026
38102
  }
38027
38103
  updatedConfig = {
@@ -38055,12 +38131,12 @@ ${pc53.bold("Cost Impact:")}`);
38055
38131
  }
38056
38132
  console.log("");
38057
38133
  if (!options.yes) {
38058
- const confirmed = await clack49.confirm({
38134
+ const confirmed = await clack50.confirm({
38059
38135
  message: "Proceed with upgrade?",
38060
38136
  initialValue: true
38061
38137
  });
38062
- if (clack49.isCancel(confirmed) || !confirmed) {
38063
- clack49.cancel("Upgrade cancelled.");
38138
+ if (clack50.isCancel(confirmed) || !confirmed) {
38139
+ clack50.cancel("Upgrade cancelled.");
38064
38140
  process.exit(0);
38065
38141
  }
38066
38142
  }
@@ -38202,9 +38278,9 @@ ${pc53.bold("Cost Impact:")}`);
38202
38278
  }
38203
38279
  progress.info("Connection metadata updated");
38204
38280
  console.log("\n");
38205
- clack49.log.success(pc53.green(pc53.bold("SMS infrastructure upgraded!")));
38281
+ clack50.log.success(pc53.green(pc53.bold("SMS infrastructure upgraded!")));
38206
38282
  console.log("\n");
38207
- clack49.note(
38283
+ clack50.note(
38208
38284
  [
38209
38285
  `${pc53.bold("Phone Number:")} ${pc53.cyan(outputs.phoneNumber || "Provisioning...")}`,
38210
38286
  `${pc53.bold("Phone Type:")} ${pc53.cyan(updatedConfig.phoneNumberType || "simulator")}`,
@@ -38279,7 +38355,7 @@ ${pc53.green("\u2713")} ${pc53.bold("Upgrade complete!")}
38279
38355
  action: typeof upgradeAction === "string" ? upgradeAction : void 0,
38280
38356
  duration_ms: Date.now() - startTime
38281
38357
  });
38282
- clack49.outro(pc53.green("Upgrade complete!"));
38358
+ clack50.outro(pc53.green("Upgrade complete!"));
38283
38359
  }
38284
38360
 
38285
38361
  // src/commands/sms/verify-number.ts
@@ -38298,13 +38374,13 @@ import {
38298
38374
  SendDestinationNumberVerificationCodeCommand,
38299
38375
  VerifyDestinationNumberCommand
38300
38376
  } from "@aws-sdk/client-pinpoint-sms-voice-v2";
38301
- import * as clack50 from "@clack/prompts";
38377
+ import * as clack51 from "@clack/prompts";
38302
38378
  import pc54 from "picocolors";
38303
38379
  async function smsVerifyNumber(options) {
38304
38380
  const startTime = Date.now();
38305
38381
  const progress = new DeploymentProgress();
38306
38382
  if (!isJsonMode()) {
38307
- clack50.intro(pc54.bold("Wraps SMS - Verify Destination Number"));
38383
+ clack51.intro(pc54.bold("Wraps SMS - Verify Destination Number"));
38308
38384
  }
38309
38385
  const identity = await progress.execute(
38310
38386
  "Validating AWS credentials",
@@ -38314,7 +38390,7 @@ async function smsVerifyNumber(options) {
38314
38390
  const metadata = await loadConnectionMetadata(identity.accountId, region);
38315
38391
  if (!metadata?.services?.sms) {
38316
38392
  progress.stop();
38317
- clack50.log.error("No SMS infrastructure found");
38393
+ clack51.log.error("No SMS infrastructure found");
38318
38394
  console.log(
38319
38395
  `
38320
38396
  Run ${pc54.cyan("wraps sms init")} to deploy SMS infrastructure.
@@ -38331,7 +38407,7 @@ Run ${pc54.cyan("wraps sms init")} to deploy SMS infrastructure.
38331
38407
  );
38332
38408
  progress.stop();
38333
38409
  if (!response.VerifiedDestinationNumbers || response.VerifiedDestinationNumbers.length === 0) {
38334
- clack50.log.info("No verified destination numbers found");
38410
+ clack51.log.info("No verified destination numbers found");
38335
38411
  console.log(
38336
38412
  `
38337
38413
  Run ${pc54.cyan("wraps sms verify-number")} to verify a number.
@@ -38339,7 +38415,7 @@ Run ${pc54.cyan("wraps sms verify-number")} to verify a number.
38339
38415
  );
38340
38416
  } else {
38341
38417
  console.log("\n");
38342
- clack50.log.info(pc54.bold("Verified Destination Numbers:"));
38418
+ clack51.log.info(pc54.bold("Verified Destination Numbers:"));
38343
38419
  console.log("");
38344
38420
  for (const num of response.VerifiedDestinationNumbers) {
38345
38421
  const status2 = num.Status === "VERIFIED" ? pc54.green("\u2713 Verified") : pc54.yellow("\u29D6 Pending");
@@ -38361,7 +38437,7 @@ Run ${pc54.cyan("wraps sms verify-number")} to verify a number.
38361
38437
  });
38362
38438
  return;
38363
38439
  }
38364
- clack50.outro(pc54.green("Done!"));
38440
+ clack51.outro(pc54.green("Done!"));
38365
38441
  return;
38366
38442
  } catch (error) {
38367
38443
  progress.stop();
@@ -38369,7 +38445,7 @@ Run ${pc54.cyan("wraps sms verify-number")} to verify a number.
38369
38445
  trackError("SMS_LIST_VERIFIED_FAILED", "sms:verify-number:list", {
38370
38446
  error: errorMessage
38371
38447
  });
38372
- clack50.log.error(`Failed to list verified numbers: ${errorMessage}`);
38448
+ clack51.log.error(`Failed to list verified numbers: ${errorMessage}`);
38373
38449
  process.exit(1);
38374
38450
  }
38375
38451
  }
@@ -38377,7 +38453,7 @@ Run ${pc54.cyan("wraps sms verify-number")} to verify a number.
38377
38453
  const phoneNumber2 = options.phoneNumber;
38378
38454
  if (!phoneNumber2) {
38379
38455
  progress.stop();
38380
- clack50.log.error("Phone number is required for deletion");
38456
+ clack51.log.error("Phone number is required for deletion");
38381
38457
  console.log(
38382
38458
  `
38383
38459
  Usage: ${pc54.cyan("wraps sms verify-number --delete --phone-number +14155551234")}
@@ -38394,7 +38470,7 @@ Usage: ${pc54.cyan("wraps sms verify-number --delete --phone-number +14155551234
38394
38470
  const verifiedNumber = listResponse.VerifiedDestinationNumbers?.[0];
38395
38471
  if (!verifiedNumber?.VerifiedDestinationNumberId) {
38396
38472
  progress.stop();
38397
- clack50.log.error(`Number ${phoneNumber2} is not in verified list`);
38473
+ clack51.log.error(`Number ${phoneNumber2} is not in verified list`);
38398
38474
  process.exit(1);
38399
38475
  }
38400
38476
  await progress.execute(`Removing ${phoneNumber2}`, async () => {
@@ -38405,7 +38481,7 @@ Usage: ${pc54.cyan("wraps sms verify-number --delete --phone-number +14155551234
38405
38481
  );
38406
38482
  });
38407
38483
  progress.stop();
38408
- clack50.log.success(`Removed ${pc54.cyan(phoneNumber2)} from verified list`);
38484
+ clack51.log.success(`Removed ${pc54.cyan(phoneNumber2)} from verified list`);
38409
38485
  trackCommand("sms:verify-number:delete", {
38410
38486
  success: true,
38411
38487
  duration_ms: Date.now() - startTime
@@ -38417,7 +38493,7 @@ Usage: ${pc54.cyan("wraps sms verify-number --delete --phone-number +14155551234
38417
38493
  });
38418
38494
  return;
38419
38495
  }
38420
- clack50.outro(pc54.green("Done!"));
38496
+ clack51.outro(pc54.green("Done!"));
38421
38497
  return;
38422
38498
  } catch (error) {
38423
38499
  progress.stop();
@@ -38425,7 +38501,7 @@ Usage: ${pc54.cyan("wraps sms verify-number --delete --phone-number +14155551234
38425
38501
  trackError("SMS_DELETE_VERIFIED_FAILED", "sms:verify-number:delete", {
38426
38502
  error: errorMessage
38427
38503
  });
38428
- clack50.log.error(`Failed to delete verified number: ${errorMessage}`);
38504
+ clack51.log.error(`Failed to delete verified number: ${errorMessage}`);
38429
38505
  process.exit(1);
38430
38506
  }
38431
38507
  }
@@ -38438,7 +38514,7 @@ Usage: ${pc54.cyan("wraps sms verify-number --delete --phone-number +14155551234
38438
38514
  );
38439
38515
  }
38440
38516
  if (!phoneNumber) {
38441
- const result = await clack50.text({
38517
+ const result = await clack51.text({
38442
38518
  message: "Enter phone number to verify (E.164 format):",
38443
38519
  placeholder: "+14155551234",
38444
38520
  validate: (value) => {
@@ -38451,14 +38527,14 @@ Usage: ${pc54.cyan("wraps sms verify-number --delete --phone-number +14155551234
38451
38527
  return;
38452
38528
  }
38453
38529
  });
38454
- if (clack50.isCancel(result)) {
38455
- clack50.cancel("Operation cancelled.");
38530
+ if (clack51.isCancel(result)) {
38531
+ clack51.cancel("Operation cancelled.");
38456
38532
  process.exit(0);
38457
38533
  }
38458
38534
  phoneNumber = result;
38459
38535
  } else if (!isValidPhoneNumber(phoneNumber)) {
38460
38536
  progress.stop();
38461
- clack50.log.error(
38537
+ clack51.log.error(
38462
38538
  `Invalid phone number format: ${phoneNumber}. Use E.164 format (e.g., +14155551234)`
38463
38539
  );
38464
38540
  process.exit(1);
@@ -38473,7 +38549,7 @@ Usage: ${pc54.cyan("wraps sms verify-number --delete --phone-number +14155551234
38473
38549
  const verifiedNumber = listResponse.VerifiedDestinationNumbers?.[0];
38474
38550
  if (!verifiedNumber?.VerifiedDestinationNumberId) {
38475
38551
  progress.stop();
38476
- clack50.log.error(
38552
+ clack51.log.error(
38477
38553
  `Number ${phoneNumber} not found. Run without --code first.`
38478
38554
  );
38479
38555
  process.exit(1);
@@ -38488,7 +38564,7 @@ Usage: ${pc54.cyan("wraps sms verify-number --delete --phone-number +14155551234
38488
38564
  });
38489
38565
  progress.stop();
38490
38566
  console.log("\n");
38491
- clack50.log.success(
38567
+ clack51.log.success(
38492
38568
  pc54.green(`Phone number ${pc54.cyan(phoneNumber)} verified!`)
38493
38569
  );
38494
38570
  console.log("");
@@ -38506,13 +38582,13 @@ Usage: ${pc54.cyan("wraps sms verify-number --delete --phone-number +14155551234
38506
38582
  });
38507
38583
  return;
38508
38584
  }
38509
- clack50.outro(pc54.green("Verification complete!"));
38585
+ clack51.outro(pc54.green("Verification complete!"));
38510
38586
  return;
38511
38587
  } catch (error) {
38512
38588
  progress.stop();
38513
38589
  const errorMessage = error instanceof Error ? error.message : String(error);
38514
38590
  if (errorMessage.includes("Invalid verification code")) {
38515
- clack50.log.error("Invalid verification code. Please try again.");
38591
+ clack51.log.error("Invalid verification code. Please try again.");
38516
38592
  console.log(
38517
38593
  `
38518
38594
  Run ${pc54.cyan(`wraps sms verify-number --phone-number ${phoneNumber} --resend`)} to get a new code.
@@ -38522,7 +38598,7 @@ Run ${pc54.cyan(`wraps sms verify-number --phone-number ${phoneNumber} --resend`
38522
38598
  trackError("SMS_VERIFY_CODE_FAILED", "sms:verify-number:confirm", {
38523
38599
  error: errorMessage
38524
38600
  });
38525
- clack50.log.error(`Verification failed: ${errorMessage}`);
38601
+ clack51.log.error(`Verification failed: ${errorMessage}`);
38526
38602
  }
38527
38603
  process.exit(1);
38528
38604
  }
@@ -38537,7 +38613,7 @@ Run ${pc54.cyan(`wraps sms verify-number --phone-number ${phoneNumber} --resend`
38537
38613
  const verifiedNumber = listResponse.VerifiedDestinationNumbers?.[0];
38538
38614
  if (!verifiedNumber?.VerifiedDestinationNumberId) {
38539
38615
  progress.stop();
38540
- clack50.log.error(
38616
+ clack51.log.error(
38541
38617
  `Number ${phoneNumber} not found. Run without --resend first.`
38542
38618
  );
38543
38619
  process.exit(1);
@@ -38551,7 +38627,7 @@ Run ${pc54.cyan(`wraps sms verify-number --phone-number ${phoneNumber} --resend`
38551
38627
  );
38552
38628
  });
38553
38629
  progress.stop();
38554
- clack50.log.success(`Verification code resent to ${pc54.cyan(phoneNumber)}`);
38630
+ clack51.log.success(`Verification code resent to ${pc54.cyan(phoneNumber)}`);
38555
38631
  console.log("");
38556
38632
  console.log(
38557
38633
  `Once you receive the code, run:
@@ -38568,7 +38644,7 @@ Run ${pc54.cyan(`wraps sms verify-number --phone-number ${phoneNumber} --resend`
38568
38644
  });
38569
38645
  return;
38570
38646
  }
38571
- clack50.outro(pc54.green("Code sent!"));
38647
+ clack51.outro(pc54.green("Code sent!"));
38572
38648
  return;
38573
38649
  } catch (error) {
38574
38650
  progress.stop();
@@ -38576,7 +38652,7 @@ Run ${pc54.cyan(`wraps sms verify-number --phone-number ${phoneNumber} --resend`
38576
38652
  trackError("SMS_RESEND_CODE_FAILED", "sms:verify-number:resend", {
38577
38653
  error: errorMessage
38578
38654
  });
38579
- clack50.log.error(`Failed to resend code: ${errorMessage}`);
38655
+ clack51.log.error(`Failed to resend code: ${errorMessage}`);
38580
38656
  process.exit(1);
38581
38657
  }
38582
38658
  }
@@ -38596,10 +38672,10 @@ Run ${pc54.cyan(`wraps sms verify-number --phone-number ${phoneNumber} --resend`
38596
38672
  });
38597
38673
  return;
38598
38674
  }
38599
- clack50.log.info(
38675
+ clack51.log.info(
38600
38676
  `Number ${pc54.cyan(phoneNumber)} is already verified and ready to use!`
38601
38677
  );
38602
- clack50.outro(pc54.green("Done!"));
38678
+ clack51.outro(pc54.green("Done!"));
38603
38679
  return;
38604
38680
  }
38605
38681
  if (existingNumber?.Status === "PENDING") {
@@ -38623,7 +38699,7 @@ Run ${pc54.cyan(`wraps sms verify-number --phone-number ${phoneNumber} --resend`
38623
38699
  });
38624
38700
  return;
38625
38701
  }
38626
- clack50.log.info(
38702
+ clack51.log.info(
38627
38703
  `Verification already in progress. New code sent to ${pc54.cyan(phoneNumber)}`
38628
38704
  );
38629
38705
  console.log("");
@@ -38631,7 +38707,7 @@ Run ${pc54.cyan(`wraps sms verify-number --phone-number ${phoneNumber} --resend`
38631
38707
  `Once you receive the code, run:
38632
38708
  ${pc54.cyan(`wraps sms verify-number --phone-number ${phoneNumber} --code YOUR_CODE`)}`
38633
38709
  );
38634
- clack50.outro(pc54.green("Code sent!"));
38710
+ clack51.outro(pc54.green("Code sent!"));
38635
38711
  return;
38636
38712
  }
38637
38713
  const createResponse = await progress.execute(
@@ -38652,11 +38728,11 @@ Run ${pc54.cyan(`wraps sms verify-number --phone-number ${phoneNumber} --resend`
38652
38728
  });
38653
38729
  progress.stop();
38654
38730
  console.log("\n");
38655
- clack50.log.success(
38731
+ clack51.log.success(
38656
38732
  `Verification code sent to ${pc54.cyan(phoneNumber)} via SMS`
38657
38733
  );
38658
38734
  console.log("");
38659
- clack50.note(
38735
+ clack51.note(
38660
38736
  [
38661
38737
  "1. Check your phone for the verification code",
38662
38738
  "",
@@ -38679,12 +38755,12 @@ Run ${pc54.cyan(`wraps sms verify-number --phone-number ${phoneNumber} --resend`
38679
38755
  });
38680
38756
  return;
38681
38757
  }
38682
- clack50.outro(pc54.green("Verification started!"));
38758
+ clack51.outro(pc54.green("Verification started!"));
38683
38759
  } catch (error) {
38684
38760
  progress.stop();
38685
38761
  const errorMessage = error instanceof Error ? error.message : String(error);
38686
38762
  if (errorMessage.includes("already exists")) {
38687
- clack50.log.error("This number is already being verified");
38763
+ clack51.log.error("This number is already being verified");
38688
38764
  console.log(
38689
38765
  `
38690
38766
  Run ${pc54.cyan(`wraps sms verify-number --phone-number ${phoneNumber} --resend`)} to get a new code.
@@ -38694,7 +38770,7 @@ Run ${pc54.cyan(`wraps sms verify-number --phone-number ${phoneNumber} --resend`
38694
38770
  trackError("SMS_CREATE_VERIFIED_FAILED", "sms:verify-number:start", {
38695
38771
  error: errorMessage
38696
38772
  });
38697
- clack50.log.error(`Failed to start verification: ${errorMessage}`);
38773
+ clack51.log.error(`Failed to start verification: ${errorMessage}`);
38698
38774
  }
38699
38775
  process.exit(1);
38700
38776
  }
@@ -38703,11 +38779,11 @@ Run ${pc54.cyan(`wraps sms verify-number --phone-number ${phoneNumber} --resend`
38703
38779
  // src/commands/support.ts
38704
38780
  init_esm_shims();
38705
38781
  init_events();
38706
- import * as clack51 from "@clack/prompts";
38782
+ import * as clack52 from "@clack/prompts";
38707
38783
  import pc55 from "picocolors";
38708
38784
  async function support() {
38709
38785
  trackCommand("support", { success: true });
38710
- clack51.intro(pc55.bold("Get Help with Wraps"));
38786
+ clack52.intro(pc55.bold("Get Help with Wraps"));
38711
38787
  console.log();
38712
38788
  console.log(` ${pc55.bold("Email:")} ${pc55.cyan("hey@wraps.sh")}`);
38713
38789
  console.log(
@@ -38722,20 +38798,20 @@ async function support() {
38722
38798
  // src/commands/telemetry.ts
38723
38799
  init_esm_shims();
38724
38800
  init_client();
38725
- import * as clack52 from "@clack/prompts";
38801
+ import * as clack53 from "@clack/prompts";
38726
38802
  import pc56 from "picocolors";
38727
38803
  async function telemetryEnable() {
38728
38804
  const client = getTelemetryClient();
38729
38805
  const override = client.enable();
38730
38806
  if (override) {
38731
- clack52.log.warn(
38807
+ clack53.log.warn(
38732
38808
  "Telemetry enabled in config, but overridden by environment"
38733
38809
  );
38734
38810
  console.log(` Reason: ${pc56.yellow(override)}`);
38735
38811
  console.log(` Config: ${pc56.dim(client.getConfigPath())}`);
38736
38812
  console.log();
38737
38813
  } else {
38738
- clack52.log.success(pc56.green("Telemetry enabled"));
38814
+ clack53.log.success(pc56.green("Telemetry enabled"));
38739
38815
  console.log(` Config: ${pc56.dim(client.getConfigPath())}`);
38740
38816
  console.log(`
38741
38817
  ${pc56.dim("Thank you for helping improve Wraps!")}
@@ -38745,7 +38821,7 @@ async function telemetryEnable() {
38745
38821
  async function telemetryDisable() {
38746
38822
  const client = getTelemetryClient();
38747
38823
  client.disable();
38748
- clack52.log.success(pc56.green("Telemetry disabled"));
38824
+ clack53.log.success(pc56.green("Telemetry disabled"));
38749
38825
  console.log(` Config: ${pc56.dim(client.getConfigPath())}`);
38750
38826
  console.log(
38751
38827
  `
@@ -38755,7 +38831,7 @@ async function telemetryDisable() {
38755
38831
  }
38756
38832
  async function telemetryStatus() {
38757
38833
  const client = getTelemetryClient();
38758
- clack52.intro(pc56.bold("Telemetry Status"));
38834
+ clack53.intro(pc56.bold("Telemetry Status"));
38759
38835
  const override = client.getEnvOverride();
38760
38836
  const status2 = client.isEnabled() ? pc56.green("Enabled") : pc56.red("Disabled");
38761
38837
  console.log();
@@ -38793,7 +38869,7 @@ async function telemetryStatus() {
38793
38869
  init_esm_shims();
38794
38870
  import { existsSync as existsSync18, mkdirSync as mkdirSync2, writeFileSync } from "fs";
38795
38871
  import { join as join20 } from "path";
38796
- import * as clack53 from "@clack/prompts";
38872
+ import * as clack54 from "@clack/prompts";
38797
38873
  import pc57 from "picocolors";
38798
38874
  var EXAMPLE_CASCADE_WORKFLOW = `import {
38799
38875
  defineWorkflow,
@@ -38889,30 +38965,30 @@ export default defineConfig({
38889
38965
  });
38890
38966
  `;
38891
38967
  async function workflowInit(options = {}) {
38892
- clack53.intro(pc57.bgCyan(pc57.black(" wraps workflow init ")));
38968
+ clack54.intro(pc57.bgCyan(pc57.black(" wraps workflow init ")));
38893
38969
  const wrapsDir = join20(process.cwd(), "wraps");
38894
38970
  const workflowsDir = join20(wrapsDir, "workflows");
38895
38971
  const configPath = join20(wrapsDir, "wraps.config.ts");
38896
38972
  if (existsSync18(workflowsDir)) {
38897
- clack53.log.info(
38973
+ clack54.log.info(
38898
38974
  `Workflows directory already exists at ${pc57.cyan("wraps/workflows/")}`
38899
38975
  );
38900
38976
  const files = existsSync18(join20(workflowsDir, "cart-recovery.ts")) || existsSync18(join20(workflowsDir, "welcome-sequence.ts"));
38901
38977
  if (files && !options.yes) {
38902
- const shouldContinue = await clack53.confirm({
38978
+ const shouldContinue = await clack54.confirm({
38903
38979
  message: "Example files may already exist. Overwrite them?",
38904
38980
  initialValue: false
38905
38981
  });
38906
- if (clack53.isCancel(shouldContinue) || !shouldContinue) {
38907
- clack53.log.info("Skipping file creation.");
38982
+ if (clack54.isCancel(shouldContinue) || !shouldContinue) {
38983
+ clack54.log.info("Skipping file creation.");
38908
38984
  showNextSteps2();
38909
- clack53.outro("Done!");
38985
+ clack54.outro("Done!");
38910
38986
  return;
38911
38987
  }
38912
38988
  }
38913
38989
  }
38914
38990
  try {
38915
- const s = clack53.spinner();
38991
+ const s = clack54.spinner();
38916
38992
  s.start("Creating workflows directory...");
38917
38993
  mkdirSync2(workflowsDir, { recursive: true });
38918
38994
  s.stop("Created wraps/workflows/");
@@ -38930,26 +39006,26 @@ async function workflowInit(options = {}) {
38930
39006
  s.stop("Created 2 example workflows");
38931
39007
  if (!existsSync18(configPath)) {
38932
39008
  writeFileSync(configPath, EXAMPLE_CONFIG, "utf-8");
38933
- clack53.log.info(`Created ${pc57.cyan("wraps/wraps.config.ts")}`);
39009
+ clack54.log.info(`Created ${pc57.cyan("wraps/wraps.config.ts")}`);
38934
39010
  }
38935
- clack53.log.success(
39011
+ clack54.log.success(
38936
39012
  `${pc57.bold("Workflows scaffolded!")} Created:
38937
39013
  ${pc57.cyan("wraps/wraps.config.ts")} \u2014 Project config
38938
39014
  ${pc57.cyan("wraps/workflows/cart-recovery.ts")} \u2014 Cross-channel cascade example
38939
39015
  ${pc57.cyan("wraps/workflows/welcome-sequence.ts")} \u2014 Welcome series example`
38940
39016
  );
38941
39017
  showNextSteps2();
38942
- clack53.outro(pc57.green("Happy orchestrating!"));
39018
+ clack54.outro(pc57.green("Happy orchestrating!"));
38943
39019
  } catch (error) {
38944
- clack53.log.error(
39020
+ clack54.log.error(
38945
39021
  `Failed to scaffold workflows: ${error instanceof Error ? error.message : String(error)}`
38946
39022
  );
38947
- clack53.outro(pc57.red("Scaffolding failed."));
39023
+ clack54.outro(pc57.red("Scaffolding failed."));
38948
39024
  process.exitCode = 1;
38949
39025
  }
38950
39026
  }
38951
39027
  function showNextSteps2() {
38952
- clack53.log.info(
39028
+ clack54.log.info(
38953
39029
  `${pc57.bold("Next steps:")}
38954
39030
 
38955
39031
  1. Edit ${pc57.cyan("wraps/wraps.config.ts")} with your org slug and domain
@@ -39135,7 +39211,7 @@ function showVersion() {
39135
39211
  process.exit(0);
39136
39212
  }
39137
39213
  function showHelp() {
39138
- clack54.intro(pc59.bold(`WRAPS CLI v${VERSION}`));
39214
+ clack55.intro(pc59.bold(`WRAPS CLI v${VERSION}`));
39139
39215
  console.log("Deploy AWS infrastructure to your account\n");
39140
39216
  console.log("Usage: wraps [service] <command> [options]\n");
39141
39217
  console.log("Services:");
@@ -39341,7 +39417,7 @@ if (!primaryCommand) {
39341
39417
  const telemetry = getTelemetryClient();
39342
39418
  if (telemetry.shouldShowNotification()) {
39343
39419
  console.log();
39344
- clack54.log.info(pc59.bold("Anonymous Telemetry"));
39420
+ clack55.log.info(pc59.bold("Anonymous Telemetry"));
39345
39421
  console.log(
39346
39422
  ` Wraps collects ${pc59.cyan("anonymous usage data")} to improve the CLI.`
39347
39423
  );
@@ -39359,9 +39435,9 @@ if (!primaryCommand) {
39359
39435
  telemetry.markNotificationShown();
39360
39436
  }
39361
39437
  trackCommand("interactive:menu", { success: true, duration_ms: 0 });
39362
- clack54.intro(pc59.bold(`WRAPS CLI v${VERSION}`));
39438
+ clack55.intro(pc59.bold(`WRAPS CLI v${VERSION}`));
39363
39439
  console.log(" Deploy AWS infrastructure to your account.\n");
39364
- const action = await clack54.select({
39440
+ const action = await clack55.select({
39365
39441
  message: "What would you like to do?",
39366
39442
  options: [
39367
39443
  {
@@ -39411,13 +39487,13 @@ if (!primaryCommand) {
39411
39487
  }
39412
39488
  ]
39413
39489
  });
39414
- if (clack54.isCancel(action)) {
39490
+ if (clack55.isCancel(action)) {
39415
39491
  trackCommand("interactive:cancel", {
39416
39492
  success: true,
39417
39493
  duration_ms: Date.now() - startTime
39418
39494
  });
39419
39495
  await telemetry.shutdown();
39420
- clack54.cancel("Operation cancelled.");
39496
+ clack55.cancel("Operation cancelled.");
39421
39497
  process.exit(0);
39422
39498
  }
39423
39499
  trackCommand(`interactive:${action}`, {
@@ -39496,7 +39572,7 @@ async function run() {
39496
39572
  const telemetry = getTelemetryClient();
39497
39573
  if (telemetry.shouldShowNotification()) {
39498
39574
  console.log();
39499
- clack54.log.info(pc59.bold("Anonymous Telemetry"));
39575
+ clack55.log.info(pc59.bold("Anonymous Telemetry"));
39500
39576
  console.log(
39501
39577
  ` Wraps collects ${pc59.cyan("anonymous usage data")} to improve the CLI.`
39502
39578
  );
@@ -39593,7 +39669,7 @@ async function run() {
39593
39669
  break;
39594
39670
  case "verify": {
39595
39671
  if (!flags.domain) {
39596
- clack54.log.error("--domain flag is required");
39672
+ clack55.log.error("--domain flag is required");
39597
39673
  console.log(
39598
39674
  `
39599
39675
  Usage: ${pc59.cyan("wraps email verify --domain yourapp.com")}
@@ -39667,7 +39743,7 @@ Usage: ${pc59.cyan("wraps email verify --domain yourapp.com")}
39667
39743
  });
39668
39744
  break;
39669
39745
  default:
39670
- clack54.log.error(
39746
+ clack55.log.error(
39671
39747
  `Unknown inbound command: ${inboundSubCommand || "(none)"}`
39672
39748
  );
39673
39749
  console.log(
@@ -39722,7 +39798,7 @@ Available commands: ${pc59.cyan("init")}, ${pc59.cyan("destroy")}, ${pc59.cyan("
39722
39798
  break;
39723
39799
  }
39724
39800
  default:
39725
- clack54.log.error(
39801
+ clack55.log.error(
39726
39802
  `Unknown reply command: ${replySubCommand || "(none)"}`
39727
39803
  );
39728
39804
  console.log(
@@ -39752,7 +39828,7 @@ Available commands: ${pc59.cyan("init")}, ${pc59.cyan("rotate")}, ${pc59.cyan("s
39752
39828
  break;
39753
39829
  case "verify": {
39754
39830
  if (!flags.domain) {
39755
- clack54.log.error("--domain flag is required");
39831
+ clack55.log.error("--domain flag is required");
39756
39832
  console.log(
39757
39833
  `
39758
39834
  Usage: ${pc59.cyan("wraps email domains verify --domain yourapp.com")}
@@ -39765,7 +39841,7 @@ Usage: ${pc59.cyan("wraps email domains verify --domain yourapp.com")}
39765
39841
  }
39766
39842
  case "get-dkim": {
39767
39843
  if (!flags.domain) {
39768
- clack54.log.error("--domain flag is required");
39844
+ clack55.log.error("--domain flag is required");
39769
39845
  console.log(
39770
39846
  `
39771
39847
  Usage: ${pc59.cyan("wraps email domains get-dkim --domain yourapp.com")}
@@ -39778,7 +39854,7 @@ Usage: ${pc59.cyan("wraps email domains get-dkim --domain yourapp.com")}
39778
39854
  }
39779
39855
  case "remove": {
39780
39856
  if (!flags.domain) {
39781
- clack54.log.error("--domain flag is required");
39857
+ clack55.log.error("--domain flag is required");
39782
39858
  console.log(
39783
39859
  `
39784
39860
  Usage: ${pc59.cyan("wraps email domains remove --domain yourapp.com --force")}
@@ -39793,7 +39869,7 @@ Usage: ${pc59.cyan("wraps email domains remove --domain yourapp.com --force")}
39793
39869
  break;
39794
39870
  }
39795
39871
  default:
39796
- clack54.log.error(
39872
+ clack55.log.error(
39797
39873
  `Unknown domains command: ${domainsSubCommand || "(none)"}`
39798
39874
  );
39799
39875
  console.log(
@@ -39840,7 +39916,7 @@ Available commands: ${pc59.cyan("add")}, ${pc59.cyan("list")}, ${pc59.cyan("veri
39840
39916
  });
39841
39917
  break;
39842
39918
  default:
39843
- clack54.log.error(
39919
+ clack55.log.error(
39844
39920
  `Unknown templates command: ${templatesSubCommand || "(none)"}`
39845
39921
  );
39846
39922
  console.log(
@@ -39884,7 +39960,7 @@ Available commands: ${pc59.cyan("init")}, ${pc59.cyan("push")}, ${pc59.cyan("pre
39884
39960
  });
39885
39961
  break;
39886
39962
  default:
39887
- clack54.log.error(
39963
+ clack55.log.error(
39888
39964
  `Unknown workflows command: ${workflowsSubCommand || "(none)"}`
39889
39965
  );
39890
39966
  console.log(
@@ -39914,7 +39990,7 @@ Available commands: ${pc59.cyan("init")}, ${pc59.cyan("validate")}, ${pc59.cyan(
39914
39990
  });
39915
39991
  break;
39916
39992
  default:
39917
- clack54.log.error(`Unknown email command: ${subCommand}`);
39993
+ clack55.log.error(`Unknown email command: ${subCommand}`);
39918
39994
  console.log(
39919
39995
  `
39920
39996
  Run ${pc59.cyan("wraps --help")} for available commands.
@@ -39992,7 +40068,7 @@ Run ${pc59.cyan("wraps --help")} for available commands.
39992
40068
  });
39993
40069
  break;
39994
40070
  default:
39995
- clack54.log.error(`Unknown sms command: ${subCommand}`);
40071
+ clack55.log.error(`Unknown sms command: ${subCommand}`);
39996
40072
  console.log(
39997
40073
  `
39998
40074
  Run ${pc59.cyan("wraps --help")} for available commands.
@@ -40056,7 +40132,7 @@ Run ${pc59.cyan("wraps --help")} for available commands.
40056
40132
  });
40057
40133
  break;
40058
40134
  default:
40059
- clack54.log.error(`Unknown cdn command: ${subCommand}`);
40135
+ clack55.log.error(`Unknown cdn command: ${subCommand}`);
40060
40136
  console.log(
40061
40137
  `
40062
40138
  Run ${pc59.cyan("wraps --help")} for available commands.
@@ -40081,7 +40157,7 @@ Run ${pc59.cyan("wraps --help")} for available commands.
40081
40157
  });
40082
40158
  break;
40083
40159
  default:
40084
- clack54.log.error(
40160
+ clack55.log.error(
40085
40161
  `Unknown workflow command: ${subCommand || "(none)"}`
40086
40162
  );
40087
40163
  console.log(`
@@ -40129,7 +40205,7 @@ Available commands: ${pc59.cyan("init")}
40129
40205
  });
40130
40206
  break;
40131
40207
  default:
40132
- clack54.log.error(`Unknown platform command: ${subCommand}`);
40208
+ clack55.log.error(`Unknown platform command: ${subCommand}`);
40133
40209
  console.log(
40134
40210
  `
40135
40211
  Available commands: ${pc59.cyan("connect")}, ${pc59.cyan("update-role")}
@@ -40161,7 +40237,7 @@ Available commands: ${pc59.cyan("connect")}, ${pc59.cyan("update-role")}
40161
40237
  await logout();
40162
40238
  break;
40163
40239
  default:
40164
- clack54.log.error(`Unknown auth command: ${subCommand || "(none)"}`);
40240
+ clack55.log.error(`Unknown auth command: ${subCommand || "(none)"}`);
40165
40241
  console.log(
40166
40242
  `
40167
40243
  Available commands: ${pc59.cyan("login")}, ${pc59.cyan("status")}, ${pc59.cyan("logout")}
@@ -40182,7 +40258,7 @@ Available commands: ${pc59.cyan("login")}, ${pc59.cyan("status")}, ${pc59.cyan("
40182
40258
  await doctor();
40183
40259
  break;
40184
40260
  default:
40185
- clack54.log.error(`Unknown aws command: ${subCommand}`);
40261
+ clack55.log.error(`Unknown aws command: ${subCommand}`);
40186
40262
  console.log(
40187
40263
  `
40188
40264
  Available commands: ${pc59.cyan("setup")}, ${pc59.cyan("doctor")}
@@ -40267,7 +40343,7 @@ Available commands: ${pc59.cyan("setup")}, ${pc59.cyan("doctor")}
40267
40343
  await telemetryStatus();
40268
40344
  break;
40269
40345
  default:
40270
- clack54.log.error(`Unknown telemetry command: ${subCommand}`);
40346
+ clack55.log.error(`Unknown telemetry command: ${subCommand}`);
40271
40347
  console.log(
40272
40348
  `
40273
40349
  Available commands: ${pc59.cyan("enable")}, ${pc59.cyan("disable")}, ${pc59.cyan("status")}
@@ -40294,7 +40370,7 @@ Please specify a command for ${primaryCommand} service.
40294
40370
  showHelp();
40295
40371
  break;
40296
40372
  default:
40297
- clack54.log.error(`Unknown command: ${primaryCommand}`);
40373
+ clack55.log.error(`Unknown command: ${primaryCommand}`);
40298
40374
  console.log(
40299
40375
  `
40300
40376
  Run ${pc59.cyan("wraps --help")} for available commands.