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