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