@wraps.dev/cli 2.4.0 → 2.5.0
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
|
@@ -5735,7 +5735,7 @@ import { dirname as dirname2, join as join5 } from "path";
|
|
|
5735
5735
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
5736
5736
|
import * as clack37 from "@clack/prompts";
|
|
5737
5737
|
import args from "args";
|
|
5738
|
-
import
|
|
5738
|
+
import pc40 from "picocolors";
|
|
5739
5739
|
|
|
5740
5740
|
// src/commands/aws/doctor.ts
|
|
5741
5741
|
init_esm_shims();
|
|
@@ -7862,8 +7862,8 @@ init_esm_shims();
|
|
|
7862
7862
|
import * as aws2 from "@pulumi/aws";
|
|
7863
7863
|
async function getExistingOIDCProviderArn(url) {
|
|
7864
7864
|
try {
|
|
7865
|
-
const { IAMClient:
|
|
7866
|
-
const iam8 = new
|
|
7865
|
+
const { IAMClient: IAMClient4, ListOpenIDConnectProvidersCommand } = await import("@aws-sdk/client-iam");
|
|
7866
|
+
const iam8 = new IAMClient4({
|
|
7867
7867
|
region: process.env.AWS_REGION || "us-east-1"
|
|
7868
7868
|
});
|
|
7869
7869
|
const response = await iam8.send(new ListOpenIDConnectProvidersCommand({}));
|
|
@@ -7920,11 +7920,11 @@ async function createVercelOIDC(config2) {
|
|
|
7920
7920
|
// src/infrastructure/cdn-stack.ts
|
|
7921
7921
|
async function roleExists(roleName) {
|
|
7922
7922
|
try {
|
|
7923
|
-
const { IAMClient:
|
|
7924
|
-
const iam8 = new
|
|
7923
|
+
const { IAMClient: IAMClient4, GetRoleCommand: GetRoleCommand3 } = await import("@aws-sdk/client-iam");
|
|
7924
|
+
const iam8 = new IAMClient4({
|
|
7925
7925
|
region: process.env.AWS_REGION || "us-east-1"
|
|
7926
7926
|
});
|
|
7927
|
-
await iam8.send(new
|
|
7927
|
+
await iam8.send(new GetRoleCommand3({ RoleName: roleName }));
|
|
7928
7928
|
return true;
|
|
7929
7929
|
} catch (error) {
|
|
7930
7930
|
if (error.name === "NoSuchEntityException" || error.Code === "NoSuchEntity" || error.Error?.Code === "NoSuchEntity") {
|
|
@@ -13277,11 +13277,11 @@ import * as aws7 from "@pulumi/aws";
|
|
|
13277
13277
|
import * as pulumi10 from "@pulumi/pulumi";
|
|
13278
13278
|
async function roleExists2(roleName) {
|
|
13279
13279
|
try {
|
|
13280
|
-
const { IAMClient:
|
|
13281
|
-
const iam8 = new
|
|
13280
|
+
const { IAMClient: IAMClient4, GetRoleCommand: GetRoleCommand3 } = await import("@aws-sdk/client-iam");
|
|
13281
|
+
const iam8 = new IAMClient4({
|
|
13282
13282
|
region: process.env.AWS_REGION || "us-east-1"
|
|
13283
13283
|
});
|
|
13284
|
-
await iam8.send(new
|
|
13284
|
+
await iam8.send(new GetRoleCommand3({ RoleName: roleName }));
|
|
13285
13285
|
return true;
|
|
13286
13286
|
} catch (error) {
|
|
13287
13287
|
if (error.name === "NoSuchEntityException" || error.Code === "NoSuchEntity" || error.Error?.Code === "NoSuchEntity") {
|
|
@@ -13666,8 +13666,8 @@ function convertToSMTPPassword2(secretAccessKey, region) {
|
|
|
13666
13666
|
}
|
|
13667
13667
|
async function userExists(userName) {
|
|
13668
13668
|
try {
|
|
13669
|
-
const { IAMClient:
|
|
13670
|
-
const iam8 = new
|
|
13669
|
+
const { IAMClient: IAMClient4, GetUserCommand } = await import("@aws-sdk/client-iam");
|
|
13670
|
+
const iam8 = new IAMClient4({
|
|
13671
13671
|
region: process.env.AWS_REGION || "us-east-1"
|
|
13672
13672
|
});
|
|
13673
13673
|
await iam8.send(new GetUserCommand({ UserName: userName }));
|
|
@@ -15562,8 +15562,8 @@ function getRequiredActions(config2) {
|
|
|
15562
15562
|
}
|
|
15563
15563
|
async function checkIAMPermissions(userArn, actions, region) {
|
|
15564
15564
|
try {
|
|
15565
|
-
const { IAMClient:
|
|
15566
|
-
const client = new
|
|
15565
|
+
const { IAMClient: IAMClient4, SimulatePrincipalPolicyCommand } = await import("@aws-sdk/client-iam");
|
|
15566
|
+
const client = new IAMClient4({ region });
|
|
15567
15567
|
const batchSize = 100;
|
|
15568
15568
|
const batches = [];
|
|
15569
15569
|
for (let i = 0; i < actions.length; i += batchSize) {
|
|
@@ -18501,51 +18501,502 @@ async function permissions(options) {
|
|
|
18501
18501
|
});
|
|
18502
18502
|
}
|
|
18503
18503
|
|
|
18504
|
+
// src/commands/platform/connect.ts
|
|
18505
|
+
init_esm_shims();
|
|
18506
|
+
import {
|
|
18507
|
+
GetRoleCommand,
|
|
18508
|
+
IAMClient as IAMClient2,
|
|
18509
|
+
PutRolePolicyCommand
|
|
18510
|
+
} from "@aws-sdk/client-iam";
|
|
18511
|
+
import { confirm as confirm11, intro as intro21, isCancel as isCancel16, log as log21, outro as outro18, select as select12 } from "@clack/prompts";
|
|
18512
|
+
import * as pulumi19 from "@pulumi/pulumi";
|
|
18513
|
+
import pc24 from "picocolors";
|
|
18514
|
+
init_events();
|
|
18515
|
+
init_aws();
|
|
18516
|
+
init_fs();
|
|
18517
|
+
init_metadata();
|
|
18518
|
+
init_prompts();
|
|
18519
|
+
function buildConsolePolicyDocument(emailConfig, smsConfig) {
|
|
18520
|
+
const statements = [];
|
|
18521
|
+
statements.push({
|
|
18522
|
+
Effect: "Allow",
|
|
18523
|
+
Action: [
|
|
18524
|
+
"ses:GetAccount",
|
|
18525
|
+
"ses:GetSendStatistics",
|
|
18526
|
+
"ses:ListIdentities",
|
|
18527
|
+
"ses:GetIdentityVerificationAttributes",
|
|
18528
|
+
"ses:ListEmailIdentities",
|
|
18529
|
+
"ses:GetEmailIdentity",
|
|
18530
|
+
"ses:GetConfigurationSet",
|
|
18531
|
+
"ses:GetConfigurationSetEventDestinations",
|
|
18532
|
+
"cloudwatch:GetMetricData",
|
|
18533
|
+
"cloudwatch:GetMetricStatistics"
|
|
18534
|
+
],
|
|
18535
|
+
Resource: "*"
|
|
18536
|
+
});
|
|
18537
|
+
statements.push({
|
|
18538
|
+
Effect: "Allow",
|
|
18539
|
+
Action: [
|
|
18540
|
+
"ses:GetTemplate",
|
|
18541
|
+
"ses:ListTemplates",
|
|
18542
|
+
"ses:CreateTemplate",
|
|
18543
|
+
"ses:UpdateTemplate",
|
|
18544
|
+
"ses:DeleteTemplate",
|
|
18545
|
+
"ses:TestRenderTemplate"
|
|
18546
|
+
],
|
|
18547
|
+
Resource: "*"
|
|
18548
|
+
});
|
|
18549
|
+
const sendingEnabled = !emailConfig || emailConfig.sendingEnabled !== false;
|
|
18550
|
+
if (sendingEnabled) {
|
|
18551
|
+
statements.push({
|
|
18552
|
+
Effect: "Allow",
|
|
18553
|
+
Action: [
|
|
18554
|
+
"ses:SendEmail",
|
|
18555
|
+
"ses:SendRawEmail",
|
|
18556
|
+
"ses:SendTemplatedEmail",
|
|
18557
|
+
"ses:SendBulkTemplatedEmail",
|
|
18558
|
+
"ses:SendBulkEmail"
|
|
18559
|
+
],
|
|
18560
|
+
Resource: "*"
|
|
18561
|
+
});
|
|
18562
|
+
}
|
|
18563
|
+
const eventTracking = emailConfig?.eventTracking;
|
|
18564
|
+
if (eventTracking?.dynamoDBHistory) {
|
|
18565
|
+
statements.push({
|
|
18566
|
+
Effect: "Allow",
|
|
18567
|
+
Action: [
|
|
18568
|
+
"dynamodb:PutItem",
|
|
18569
|
+
"dynamodb:GetItem",
|
|
18570
|
+
"dynamodb:Query",
|
|
18571
|
+
"dynamodb:Scan",
|
|
18572
|
+
"dynamodb:BatchGetItem",
|
|
18573
|
+
"dynamodb:DescribeTable"
|
|
18574
|
+
],
|
|
18575
|
+
Resource: [
|
|
18576
|
+
"arn:aws:dynamodb:*:*:table/wraps-email-*",
|
|
18577
|
+
"arn:aws:dynamodb:*:*:table/wraps-email-*/index/*"
|
|
18578
|
+
]
|
|
18579
|
+
});
|
|
18580
|
+
}
|
|
18581
|
+
if (eventTracking?.enabled) {
|
|
18582
|
+
statements.push({
|
|
18583
|
+
Effect: "Allow",
|
|
18584
|
+
Action: ["events:PutEvents", "events:DescribeEventBus"],
|
|
18585
|
+
Resource: "arn:aws:events:*:*:event-bus/wraps-email-*"
|
|
18586
|
+
});
|
|
18587
|
+
}
|
|
18588
|
+
if (eventTracking?.enabled) {
|
|
18589
|
+
statements.push({
|
|
18590
|
+
Effect: "Allow",
|
|
18591
|
+
Action: [
|
|
18592
|
+
"sqs:SendMessage",
|
|
18593
|
+
"sqs:ReceiveMessage",
|
|
18594
|
+
"sqs:DeleteMessage",
|
|
18595
|
+
"sqs:GetQueueAttributes"
|
|
18596
|
+
],
|
|
18597
|
+
Resource: "arn:aws:sqs:*:*:wraps-email-*"
|
|
18598
|
+
});
|
|
18599
|
+
}
|
|
18600
|
+
const emailArchiving = emailConfig?.emailArchiving;
|
|
18601
|
+
if (emailArchiving?.enabled) {
|
|
18602
|
+
statements.push({
|
|
18603
|
+
Effect: "Allow",
|
|
18604
|
+
Action: [
|
|
18605
|
+
"ses:StartArchiveSearch",
|
|
18606
|
+
"ses:GetArchiveSearchResults",
|
|
18607
|
+
"ses:GetArchiveMessage",
|
|
18608
|
+
"ses:GetArchiveMessageContent",
|
|
18609
|
+
"ses:GetArchive",
|
|
18610
|
+
"ses:ListArchives",
|
|
18611
|
+
"ses:StartArchiveExport",
|
|
18612
|
+
"ses:GetArchiveExport"
|
|
18613
|
+
],
|
|
18614
|
+
Resource: "arn:aws:ses:*:*:mailmanager-archive/*"
|
|
18615
|
+
});
|
|
18616
|
+
}
|
|
18617
|
+
if (smsConfig) {
|
|
18618
|
+
statements.push({
|
|
18619
|
+
Effect: "Allow",
|
|
18620
|
+
Action: [
|
|
18621
|
+
"sms-voice:DescribeAccountAttributes",
|
|
18622
|
+
"sms-voice:DescribeSpendLimits",
|
|
18623
|
+
"sms-voice:DescribeConfigurationSets",
|
|
18624
|
+
"sms-voice:DescribeOptOutLists",
|
|
18625
|
+
"sms-voice:DescribeOptedOutNumbers",
|
|
18626
|
+
"sms-voice:DescribePools",
|
|
18627
|
+
"sms-voice:DescribePhoneNumbers",
|
|
18628
|
+
"sms-voice:DescribeProtectConfigurations",
|
|
18629
|
+
"sms-voice:DescribeRegistrations",
|
|
18630
|
+
"sms-voice:DescribeRegistrationAttachments",
|
|
18631
|
+
"sms-voice:DescribeRegistrationFieldDefinitions",
|
|
18632
|
+
"sms-voice:DescribeRegistrationFieldValues",
|
|
18633
|
+
"sms-voice:DescribeRegistrationSectionDefinitions",
|
|
18634
|
+
"sms-voice:DescribeRegistrationVersions"
|
|
18635
|
+
],
|
|
18636
|
+
Resource: "*"
|
|
18637
|
+
});
|
|
18638
|
+
const smsSendingEnabled = smsConfig.sendingEnabled !== false;
|
|
18639
|
+
if (smsSendingEnabled) {
|
|
18640
|
+
statements.push({
|
|
18641
|
+
Effect: "Allow",
|
|
18642
|
+
Action: ["sms-voice:SendTextMessage", "sms-voice:SendMediaMessage"],
|
|
18643
|
+
Resource: "*"
|
|
18644
|
+
});
|
|
18645
|
+
}
|
|
18646
|
+
const smsEventTracking = smsConfig.eventTracking;
|
|
18647
|
+
if (smsEventTracking?.dynamoDBHistory) {
|
|
18648
|
+
statements.push({
|
|
18649
|
+
Effect: "Allow",
|
|
18650
|
+
Action: [
|
|
18651
|
+
"dynamodb:GetItem",
|
|
18652
|
+
"dynamodb:Query",
|
|
18653
|
+
"dynamodb:Scan",
|
|
18654
|
+
"dynamodb:BatchGetItem",
|
|
18655
|
+
"dynamodb:DescribeTable"
|
|
18656
|
+
],
|
|
18657
|
+
Resource: [
|
|
18658
|
+
"arn:aws:dynamodb:*:*:table/wraps-sms-*",
|
|
18659
|
+
"arn:aws:dynamodb:*:*:table/wraps-sms-*/index/*"
|
|
18660
|
+
]
|
|
18661
|
+
});
|
|
18662
|
+
}
|
|
18663
|
+
if (smsEventTracking?.enabled) {
|
|
18664
|
+
statements.push({
|
|
18665
|
+
Effect: "Allow",
|
|
18666
|
+
Action: ["sns:GetTopicAttributes", "sns:ListSubscriptionsByTopic"],
|
|
18667
|
+
Resource: "arn:aws:sns:*:*:wraps-sms-*"
|
|
18668
|
+
});
|
|
18669
|
+
}
|
|
18670
|
+
}
|
|
18671
|
+
return {
|
|
18672
|
+
Version: "2012-10-17",
|
|
18673
|
+
Statement: statements
|
|
18674
|
+
};
|
|
18675
|
+
}
|
|
18676
|
+
async function connect3(options) {
|
|
18677
|
+
const startTime = Date.now();
|
|
18678
|
+
intro21(pc24.bold("Connect to Wraps Platform"));
|
|
18679
|
+
const progress = new DeploymentProgress();
|
|
18680
|
+
try {
|
|
18681
|
+
const wasAutoInstalled = await progress.execute(
|
|
18682
|
+
"Checking Pulumi CLI installation",
|
|
18683
|
+
async () => await ensurePulumiInstalled()
|
|
18684
|
+
);
|
|
18685
|
+
if (wasAutoInstalled) {
|
|
18686
|
+
progress.info("Pulumi CLI was automatically installed");
|
|
18687
|
+
}
|
|
18688
|
+
const identity = await progress.execute(
|
|
18689
|
+
"Validating AWS credentials",
|
|
18690
|
+
async () => validateAWSCredentials()
|
|
18691
|
+
);
|
|
18692
|
+
progress.info(`Connected to AWS account: ${pc24.cyan(identity.accountId)}`);
|
|
18693
|
+
let region = options.region;
|
|
18694
|
+
if (!region) {
|
|
18695
|
+
region = await getAWSRegion();
|
|
18696
|
+
}
|
|
18697
|
+
const metadata = await loadConnectionMetadata(identity.accountId, region);
|
|
18698
|
+
if (!metadata) {
|
|
18699
|
+
progress.stop();
|
|
18700
|
+
log21.error(
|
|
18701
|
+
`No Wraps deployment found for account ${pc24.cyan(identity.accountId)} in region ${pc24.cyan(region)}`
|
|
18702
|
+
);
|
|
18703
|
+
console.log(
|
|
18704
|
+
`
|
|
18705
|
+
Run ${pc24.cyan("wraps email init")} to deploy infrastructure first.
|
|
18706
|
+
`
|
|
18707
|
+
);
|
|
18708
|
+
process.exit(1);
|
|
18709
|
+
}
|
|
18710
|
+
const hasEmail = !!metadata.services.email?.config;
|
|
18711
|
+
const hasSms = !!metadata.services.sms?.config;
|
|
18712
|
+
if (!(hasEmail || hasSms)) {
|
|
18713
|
+
progress.stop();
|
|
18714
|
+
log21.error("No services deployed in this region.");
|
|
18715
|
+
console.log(
|
|
18716
|
+
`
|
|
18717
|
+
Run ${pc24.cyan("wraps email init")} or ${pc24.cyan("wraps sms init")} first.
|
|
18718
|
+
`
|
|
18719
|
+
);
|
|
18720
|
+
process.exit(1);
|
|
18721
|
+
}
|
|
18722
|
+
progress.info(
|
|
18723
|
+
`Found services: ${[hasEmail && "email", hasSms && "sms"].filter(Boolean).join(", ")}`
|
|
18724
|
+
);
|
|
18725
|
+
let webhookSecret;
|
|
18726
|
+
let needsDeployment = false;
|
|
18727
|
+
if (hasEmail) {
|
|
18728
|
+
const emailConfig = metadata.services.email.config;
|
|
18729
|
+
const existingSecret = metadata.services.email.webhookSecret;
|
|
18730
|
+
if (!emailConfig.eventTracking?.enabled) {
|
|
18731
|
+
progress.stop();
|
|
18732
|
+
log21.warn(
|
|
18733
|
+
"Event tracking must be enabled to connect to the Wraps Platform."
|
|
18734
|
+
);
|
|
18735
|
+
log21.info(
|
|
18736
|
+
"Enabling event tracking will allow SES events to be streamed to the dashboard."
|
|
18737
|
+
);
|
|
18738
|
+
const enableEventTracking = await confirm11({
|
|
18739
|
+
message: "Enable event tracking now?",
|
|
18740
|
+
initialValue: true
|
|
18741
|
+
});
|
|
18742
|
+
if (isCancel16(enableEventTracking) || !enableEventTracking) {
|
|
18743
|
+
outro18("Platform connection cancelled.");
|
|
18744
|
+
process.exit(0);
|
|
18745
|
+
}
|
|
18746
|
+
metadata.services.email.config = {
|
|
18747
|
+
...emailConfig,
|
|
18748
|
+
eventTracking: {
|
|
18749
|
+
enabled: true,
|
|
18750
|
+
eventBridge: true,
|
|
18751
|
+
events: [
|
|
18752
|
+
"SEND",
|
|
18753
|
+
"DELIVERY",
|
|
18754
|
+
"OPEN",
|
|
18755
|
+
"CLICK",
|
|
18756
|
+
"BOUNCE",
|
|
18757
|
+
"COMPLAINT"
|
|
18758
|
+
],
|
|
18759
|
+
dynamoDBHistory: emailConfig.eventTracking?.dynamoDBHistory ?? false,
|
|
18760
|
+
archiveRetention: emailConfig.eventTracking?.archiveRetention ?? "90days"
|
|
18761
|
+
}
|
|
18762
|
+
};
|
|
18763
|
+
needsDeployment = true;
|
|
18764
|
+
}
|
|
18765
|
+
if (existingSecret) {
|
|
18766
|
+
progress.stop();
|
|
18767
|
+
log21.info(
|
|
18768
|
+
`Already connected to Wraps Platform (AWS Account: ${pc24.cyan(metadata.accountId)})`
|
|
18769
|
+
);
|
|
18770
|
+
const action = await select12({
|
|
18771
|
+
message: "What would you like to do?",
|
|
18772
|
+
options: [
|
|
18773
|
+
{
|
|
18774
|
+
value: "keep",
|
|
18775
|
+
label: "Keep current connection",
|
|
18776
|
+
hint: "Continue with existing webhook secret"
|
|
18777
|
+
},
|
|
18778
|
+
{
|
|
18779
|
+
value: "regenerate",
|
|
18780
|
+
label: "Regenerate webhook secret",
|
|
18781
|
+
hint: "Create new secret (requires update in dashboard)"
|
|
18782
|
+
},
|
|
18783
|
+
{
|
|
18784
|
+
value: "disconnect",
|
|
18785
|
+
label: "Disconnect from platform",
|
|
18786
|
+
hint: "Stop sending events to Wraps"
|
|
18787
|
+
}
|
|
18788
|
+
]
|
|
18789
|
+
});
|
|
18790
|
+
if (isCancel16(action)) {
|
|
18791
|
+
outro18("Operation cancelled");
|
|
18792
|
+
process.exit(0);
|
|
18793
|
+
}
|
|
18794
|
+
if (action === "keep") {
|
|
18795
|
+
webhookSecret = existingSecret;
|
|
18796
|
+
} else if (action === "disconnect") {
|
|
18797
|
+
const confirmDisconnect = await confirm11({
|
|
18798
|
+
message: "Are you sure? Events will no longer be sent to the Wraps Platform.",
|
|
18799
|
+
initialValue: false
|
|
18800
|
+
});
|
|
18801
|
+
if (isCancel16(confirmDisconnect) || !confirmDisconnect) {
|
|
18802
|
+
outro18("Disconnect cancelled");
|
|
18803
|
+
process.exit(0);
|
|
18804
|
+
}
|
|
18805
|
+
metadata.services.email.webhookSecret = void 0;
|
|
18806
|
+
needsDeployment = true;
|
|
18807
|
+
webhookSecret = void 0;
|
|
18808
|
+
} else {
|
|
18809
|
+
webhookSecret = generateWebhookSecret();
|
|
18810
|
+
metadata.services.email.webhookSecret = webhookSecret;
|
|
18811
|
+
needsDeployment = true;
|
|
18812
|
+
}
|
|
18813
|
+
} else {
|
|
18814
|
+
webhookSecret = generateWebhookSecret();
|
|
18815
|
+
metadata.services.email.webhookSecret = webhookSecret;
|
|
18816
|
+
needsDeployment = true;
|
|
18817
|
+
}
|
|
18818
|
+
}
|
|
18819
|
+
if (needsDeployment && hasEmail) {
|
|
18820
|
+
let vercelConfig;
|
|
18821
|
+
if (metadata.provider === "vercel" && !metadata.vercel) {
|
|
18822
|
+
progress.stop();
|
|
18823
|
+
vercelConfig = await promptVercelConfig();
|
|
18824
|
+
} else if (metadata.provider === "vercel") {
|
|
18825
|
+
vercelConfig = metadata.vercel;
|
|
18826
|
+
}
|
|
18827
|
+
const stackConfig = {
|
|
18828
|
+
provider: metadata.provider,
|
|
18829
|
+
region,
|
|
18830
|
+
vercel: vercelConfig,
|
|
18831
|
+
emailConfig: metadata.services.email.config,
|
|
18832
|
+
webhook: webhookSecret ? {
|
|
18833
|
+
awsAccountNumber: metadata.accountId,
|
|
18834
|
+
webhookSecret
|
|
18835
|
+
} : void 0
|
|
18836
|
+
};
|
|
18837
|
+
await progress.execute("Configuring event streaming", async () => {
|
|
18838
|
+
await ensurePulumiWorkDir();
|
|
18839
|
+
const stack = await pulumi19.automation.LocalWorkspace.createOrSelectStack(
|
|
18840
|
+
{
|
|
18841
|
+
stackName: metadata.services.email?.pulumiStackName || `wraps-${identity.accountId}-${region}`,
|
|
18842
|
+
projectName: "wraps-email",
|
|
18843
|
+
program: async () => {
|
|
18844
|
+
const result = await deployEmailStack(stackConfig);
|
|
18845
|
+
return {
|
|
18846
|
+
roleArn: result.roleArn,
|
|
18847
|
+
configSetName: result.configSetName,
|
|
18848
|
+
tableName: result.tableName,
|
|
18849
|
+
region: result.region
|
|
18850
|
+
};
|
|
18851
|
+
}
|
|
18852
|
+
},
|
|
18853
|
+
{
|
|
18854
|
+
workDir: getPulumiWorkDir(),
|
|
18855
|
+
envVars: {
|
|
18856
|
+
PULUMI_CONFIG_PASSPHRASE: "",
|
|
18857
|
+
AWS_REGION: region
|
|
18858
|
+
},
|
|
18859
|
+
secretsProvider: "passphrase"
|
|
18860
|
+
}
|
|
18861
|
+
);
|
|
18862
|
+
await stack.setConfig("aws:region", { value: region });
|
|
18863
|
+
await stack.refresh({ onOutput: () => {
|
|
18864
|
+
} });
|
|
18865
|
+
await stack.up({ onOutput: () => {
|
|
18866
|
+
} });
|
|
18867
|
+
});
|
|
18868
|
+
progress.succeed("Event streaming configured");
|
|
18869
|
+
} else if (!needsDeployment && hasEmail && webhookSecret) {
|
|
18870
|
+
progress.succeed("Event streaming already configured");
|
|
18871
|
+
}
|
|
18872
|
+
const roleName = "wraps-console-access-role";
|
|
18873
|
+
const iam8 = new IAMClient2({ region: "us-east-1" });
|
|
18874
|
+
let roleExists4 = false;
|
|
18875
|
+
try {
|
|
18876
|
+
await iam8.send(new GetRoleCommand({ RoleName: roleName }));
|
|
18877
|
+
roleExists4 = true;
|
|
18878
|
+
} catch (error) {
|
|
18879
|
+
if (error && typeof error === "object" && "name" in error && error.name !== "NoSuchEntity") {
|
|
18880
|
+
throw error;
|
|
18881
|
+
}
|
|
18882
|
+
}
|
|
18883
|
+
if (roleExists4) {
|
|
18884
|
+
const emailConfig = metadata.services.email?.config;
|
|
18885
|
+
const smsConfig = metadata.services.sms?.config;
|
|
18886
|
+
const policy = buildConsolePolicyDocument(emailConfig, smsConfig);
|
|
18887
|
+
await progress.execute("Updating platform access role", async () => {
|
|
18888
|
+
await iam8.send(
|
|
18889
|
+
new PutRolePolicyCommand({
|
|
18890
|
+
RoleName: roleName,
|
|
18891
|
+
PolicyName: "wraps-console-access-policy",
|
|
18892
|
+
PolicyDocument: JSON.stringify(policy, null, 2)
|
|
18893
|
+
})
|
|
18894
|
+
);
|
|
18895
|
+
});
|
|
18896
|
+
progress.succeed("Platform access role updated");
|
|
18897
|
+
} else {
|
|
18898
|
+
progress.info(
|
|
18899
|
+
`IAM role ${pc24.cyan(roleName)} will be created when you add your AWS account in the dashboard`
|
|
18900
|
+
);
|
|
18901
|
+
}
|
|
18902
|
+
await saveConnectionMetadata(metadata);
|
|
18903
|
+
progress.stop();
|
|
18904
|
+
outro18(pc24.green("Platform connection complete!"));
|
|
18905
|
+
if (webhookSecret && needsDeployment) {
|
|
18906
|
+
console.log(`
|
|
18907
|
+
${pc24.bold("Webhook Secret")} ${pc24.dim("(save this!)")}`);
|
|
18908
|
+
console.log(pc24.dim("\u2500".repeat(60)));
|
|
18909
|
+
console.log(` ${pc24.cyan(webhookSecret)}`);
|
|
18910
|
+
console.log(pc24.dim("\u2500".repeat(60)));
|
|
18911
|
+
} else if (metadata.services.email?.webhookSecret && !needsDeployment) {
|
|
18912
|
+
console.log(`
|
|
18913
|
+
${pc24.bold("Existing Webhook Secret:")}`);
|
|
18914
|
+
console.log(pc24.dim("\u2500".repeat(60)));
|
|
18915
|
+
console.log(` ${pc24.cyan(metadata.services.email.webhookSecret)}`);
|
|
18916
|
+
console.log(pc24.dim("\u2500".repeat(60)));
|
|
18917
|
+
}
|
|
18918
|
+
console.log(`
|
|
18919
|
+
${pc24.bold("Next Steps:")}`);
|
|
18920
|
+
console.log(` 1. Go to ${pc24.cyan("https://app.wraps.dev/settings/aws")}`);
|
|
18921
|
+
console.log(` 2. Add your AWS account: ${pc24.cyan(identity.accountId)}`);
|
|
18922
|
+
if (webhookSecret) {
|
|
18923
|
+
console.log(" 3. Paste the webhook secret shown above");
|
|
18924
|
+
}
|
|
18925
|
+
console.log();
|
|
18926
|
+
console.log(
|
|
18927
|
+
pc24.dim(
|
|
18928
|
+
"Events from your AWS infrastructure will stream to the dashboard."
|
|
18929
|
+
)
|
|
18930
|
+
);
|
|
18931
|
+
console.log();
|
|
18932
|
+
const duration = Date.now() - startTime;
|
|
18933
|
+
trackCommand("platform:connect", {
|
|
18934
|
+
success: true,
|
|
18935
|
+
duration_ms: duration
|
|
18936
|
+
});
|
|
18937
|
+
} catch (error) {
|
|
18938
|
+
progress.stop();
|
|
18939
|
+
const duration = Date.now() - startTime;
|
|
18940
|
+
const errorCode = error instanceof Error ? error.name : "UNKNOWN_ERROR";
|
|
18941
|
+
trackError(errorCode, "platform:connect", {
|
|
18942
|
+
message: error instanceof Error ? error.message : String(error)
|
|
18943
|
+
});
|
|
18944
|
+
trackCommand("platform:connect", {
|
|
18945
|
+
success: false,
|
|
18946
|
+
duration_ms: duration
|
|
18947
|
+
});
|
|
18948
|
+
throw error;
|
|
18949
|
+
}
|
|
18950
|
+
}
|
|
18951
|
+
|
|
18504
18952
|
// src/commands/platform/index.ts
|
|
18505
18953
|
init_esm_shims();
|
|
18506
18954
|
import * as clack23 from "@clack/prompts";
|
|
18507
|
-
import
|
|
18955
|
+
import pc25 from "picocolors";
|
|
18508
18956
|
async function platform() {
|
|
18509
|
-
clack23.intro(
|
|
18957
|
+
clack23.intro(pc25.bold("Wraps Platform"));
|
|
18510
18958
|
console.log();
|
|
18511
18959
|
console.log(
|
|
18512
18960
|
" The Wraps Platform extends the free CLI with hosted features:"
|
|
18513
18961
|
);
|
|
18514
18962
|
console.log();
|
|
18515
|
-
console.log(` ${
|
|
18516
|
-
console.log(` ${
|
|
18517
|
-
console.log(` ${
|
|
18518
|
-
console.log(` ${
|
|
18519
|
-
console.log(` ${
|
|
18520
|
-
console.log(` ${
|
|
18521
|
-
console.log(` ${
|
|
18963
|
+
console.log(` ${pc25.bold("Features:")}`);
|
|
18964
|
+
console.log(` ${pc25.green("\u2713")} Visual email template editor`);
|
|
18965
|
+
console.log(` ${pc25.green("\u2713")} Broadcast campaigns & scheduling`);
|
|
18966
|
+
console.log(` ${pc25.green("\u2713")} Contact management & segments`);
|
|
18967
|
+
console.log(` ${pc25.green("\u2713")} Workflow automations`);
|
|
18968
|
+
console.log(` ${pc25.green("\u2713")} Analytics dashboard`);
|
|
18969
|
+
console.log(` ${pc25.green("\u2713")} Team collaboration`);
|
|
18522
18970
|
console.log();
|
|
18523
|
-
console.log(` ${
|
|
18524
|
-
console.log(` ${
|
|
18525
|
-
console.log(` ${
|
|
18526
|
-
console.log(` ${
|
|
18527
|
-
console.log(` ${
|
|
18971
|
+
console.log(` ${pc25.bold("Pricing:")}`);
|
|
18972
|
+
console.log(` ${pc25.cyan("Starter")} $10/mo 5,000 contacts`);
|
|
18973
|
+
console.log(` ${pc25.cyan("Growth")} $25/mo 25,000 contacts`);
|
|
18974
|
+
console.log(` ${pc25.cyan("Scale")} $50/mo 100,000 contacts`);
|
|
18975
|
+
console.log(` ${pc25.cyan("Enterprise")} Custom Unlimited contacts`);
|
|
18528
18976
|
console.log();
|
|
18529
18977
|
console.log(
|
|
18530
|
-
|
|
18978
|
+
pc25.dim(" + AWS costs at $0.10 per 1,000 emails (paid directly to AWS)")
|
|
18531
18979
|
);
|
|
18532
18980
|
console.log();
|
|
18533
18981
|
console.log(
|
|
18534
|
-
` ${
|
|
18982
|
+
` ${pc25.bold("Learn more:")} ${pc25.cyan("https://wraps.dev/platform")}`
|
|
18535
18983
|
);
|
|
18536
18984
|
console.log();
|
|
18537
|
-
console.log(
|
|
18985
|
+
console.log(pc25.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
18538
18986
|
console.log();
|
|
18539
|
-
console.log(` ${
|
|
18987
|
+
console.log(` ${pc25.bold("Platform Commands:")}`);
|
|
18540
18988
|
console.log();
|
|
18541
18989
|
console.log(
|
|
18542
|
-
` ${
|
|
18990
|
+
` ${pc25.cyan("wraps platform connect")} Connect infrastructure to Wraps Platform`
|
|
18991
|
+
);
|
|
18992
|
+
console.log(
|
|
18993
|
+
` ${pc25.cyan("wraps platform update-role")} Update IAM permissions for dashboard`
|
|
18543
18994
|
);
|
|
18544
18995
|
console.log();
|
|
18545
18996
|
console.log(
|
|
18546
|
-
|
|
18997
|
+
pc25.dim(" The connect command sets up event streaming and IAM permissions")
|
|
18547
18998
|
);
|
|
18548
|
-
console.log(
|
|
18999
|
+
console.log(pc25.dim(" in one step. Run it after deploying infrastructure."));
|
|
18549
19000
|
console.log();
|
|
18550
19001
|
}
|
|
18551
19002
|
|
|
@@ -18553,11 +19004,11 @@ async function platform() {
|
|
|
18553
19004
|
init_esm_shims();
|
|
18554
19005
|
init_aws();
|
|
18555
19006
|
init_metadata();
|
|
18556
|
-
import { GetRoleCommand, IAMClient as
|
|
18557
|
-
import { confirm as
|
|
18558
|
-
import
|
|
19007
|
+
import { GetRoleCommand as GetRoleCommand2, IAMClient as IAMClient3 } from "@aws-sdk/client-iam";
|
|
19008
|
+
import { confirm as confirm12, intro as intro23, isCancel as isCancel17, log as log22, outro as outro19 } from "@clack/prompts";
|
|
19009
|
+
import pc26 from "picocolors";
|
|
18559
19010
|
async function updateRole(options) {
|
|
18560
|
-
|
|
19011
|
+
intro23(pc26.bold("Update Platform Access Role"));
|
|
18561
19012
|
const progress = new DeploymentProgress();
|
|
18562
19013
|
const identity = await progress.execute(
|
|
18563
19014
|
"Validating AWS credentials",
|
|
@@ -18567,21 +19018,21 @@ async function updateRole(options) {
|
|
|
18567
19018
|
const metadata = await loadConnectionMetadata(identity.accountId, region);
|
|
18568
19019
|
if (!metadata) {
|
|
18569
19020
|
progress.stop();
|
|
18570
|
-
|
|
18571
|
-
`No Wraps deployment found for account ${
|
|
19021
|
+
log22.error(
|
|
19022
|
+
`No Wraps deployment found for account ${pc26.cyan(identity.accountId)} in region ${pc26.cyan(region)}`
|
|
18572
19023
|
);
|
|
18573
19024
|
console.log(
|
|
18574
19025
|
`
|
|
18575
|
-
Run ${
|
|
19026
|
+
Run ${pc26.cyan("wraps email init")} to deploy infrastructure first.
|
|
18576
19027
|
`
|
|
18577
19028
|
);
|
|
18578
19029
|
process.exit(1);
|
|
18579
19030
|
}
|
|
18580
19031
|
const roleName = "wraps-console-access-role";
|
|
18581
|
-
const iam8 = new
|
|
19032
|
+
const iam8 = new IAMClient3({ region: "us-east-1" });
|
|
18582
19033
|
let roleExists4 = false;
|
|
18583
19034
|
try {
|
|
18584
|
-
await iam8.send(new
|
|
19035
|
+
await iam8.send(new GetRoleCommand2({ RoleName: roleName }));
|
|
18585
19036
|
roleExists4 = true;
|
|
18586
19037
|
} catch (error) {
|
|
18587
19038
|
if (error && typeof error === "object" && "name" in error && error.name !== "NoSuchEntity") {
|
|
@@ -18590,7 +19041,7 @@ Run ${pc25.cyan("wraps email init")} to deploy infrastructure first.
|
|
|
18590
19041
|
}
|
|
18591
19042
|
if (!roleExists4) {
|
|
18592
19043
|
progress.stop();
|
|
18593
|
-
|
|
19044
|
+
log22.warn(`IAM role ${pc26.cyan(roleName)} does not exist`);
|
|
18594
19045
|
console.log(
|
|
18595
19046
|
"\nThis role is created when you connect AWS accounts through the Wraps Platform."
|
|
18596
19047
|
);
|
|
@@ -18599,21 +19050,21 @@ Run ${pc25.cyan("wraps email init")} to deploy infrastructure first.
|
|
|
18599
19050
|
);
|
|
18600
19051
|
process.exit(0);
|
|
18601
19052
|
}
|
|
18602
|
-
progress.info(`Found IAM role: ${
|
|
19053
|
+
progress.info(`Found IAM role: ${pc26.cyan(roleName)}`);
|
|
18603
19054
|
if (!options.force) {
|
|
18604
19055
|
progress.stop();
|
|
18605
|
-
const shouldContinue = await
|
|
18606
|
-
message: `Update IAM role ${
|
|
19056
|
+
const shouldContinue = await confirm12({
|
|
19057
|
+
message: `Update IAM role ${pc26.cyan(roleName)} with latest permissions?`,
|
|
18607
19058
|
initialValue: true
|
|
18608
19059
|
});
|
|
18609
|
-
if (
|
|
18610
|
-
|
|
19060
|
+
if (isCancel17(shouldContinue) || !shouldContinue) {
|
|
19061
|
+
outro19("Update cancelled");
|
|
18611
19062
|
process.exit(0);
|
|
18612
19063
|
}
|
|
18613
19064
|
}
|
|
18614
19065
|
const emailConfig = metadata.services.email?.config;
|
|
18615
19066
|
const smsConfig = metadata.services.sms?.config;
|
|
18616
|
-
const policy =
|
|
19067
|
+
const policy = buildConsolePolicyDocument2(emailConfig, smsConfig);
|
|
18617
19068
|
const sendingEnabled = !emailConfig || emailConfig.sendingEnabled !== false;
|
|
18618
19069
|
const eventTracking = emailConfig?.eventTracking;
|
|
18619
19070
|
const emailArchiving = emailConfig?.emailArchiving;
|
|
@@ -18621,9 +19072,9 @@ Run ${pc25.cyan("wraps email init")} to deploy infrastructure first.
|
|
|
18621
19072
|
const smsSendingEnabled = smsConfig && smsConfig.sendingEnabled !== false;
|
|
18622
19073
|
const smsEventTracking = smsConfig?.eventTracking;
|
|
18623
19074
|
await progress.execute("Updating IAM role permissions", async () => {
|
|
18624
|
-
const { PutRolePolicyCommand } = await import("@aws-sdk/client-iam");
|
|
19075
|
+
const { PutRolePolicyCommand: PutRolePolicyCommand2 } = await import("@aws-sdk/client-iam");
|
|
18625
19076
|
await iam8.send(
|
|
18626
|
-
new
|
|
19077
|
+
new PutRolePolicyCommand2({
|
|
18627
19078
|
RoleName: roleName,
|
|
18628
19079
|
PolicyName: "wraps-console-access-policy",
|
|
18629
19080
|
PolicyDocument: JSON.stringify(policy, null, 2)
|
|
@@ -18631,52 +19082,52 @@ Run ${pc25.cyan("wraps email init")} to deploy infrastructure first.
|
|
|
18631
19082
|
);
|
|
18632
19083
|
});
|
|
18633
19084
|
progress.stop();
|
|
18634
|
-
|
|
19085
|
+
outro19(pc26.green("\u2713 Platform access role updated successfully"));
|
|
18635
19086
|
console.log(`
|
|
18636
|
-
${
|
|
19087
|
+
${pc26.bold("Updated Permissions:")}`);
|
|
18637
19088
|
console.log(`
|
|
18638
|
-
${
|
|
19089
|
+
${pc26.bold(pc26.cyan("Email:"))}`);
|
|
18639
19090
|
console.log(
|
|
18640
|
-
` ${
|
|
19091
|
+
` ${pc26.green("\u2713")} SES metrics and identity verification (always enabled)`
|
|
18641
19092
|
);
|
|
18642
|
-
console.log(` ${
|
|
19093
|
+
console.log(` ${pc26.green("\u2713")} SES template management (always enabled)`);
|
|
18643
19094
|
if (sendingEnabled) {
|
|
18644
|
-
console.log(` ${
|
|
19095
|
+
console.log(` ${pc26.green("\u2713")} Email sending via SES`);
|
|
18645
19096
|
}
|
|
18646
19097
|
if (eventTracking?.dynamoDBHistory) {
|
|
18647
19098
|
console.log(
|
|
18648
|
-
` ${
|
|
19099
|
+
` ${pc26.green("\u2713")} DynamoDB read access (including DescribeTable)`
|
|
18649
19100
|
);
|
|
18650
19101
|
}
|
|
18651
19102
|
if (eventTracking?.enabled) {
|
|
18652
|
-
console.log(` ${
|
|
19103
|
+
console.log(` ${pc26.green("\u2713")} EventBridge and SQS access`);
|
|
18653
19104
|
}
|
|
18654
19105
|
if (emailArchiving?.enabled) {
|
|
18655
|
-
console.log(` ${
|
|
19106
|
+
console.log(` ${pc26.green("\u2713")} Mail Manager Archive access`);
|
|
18656
19107
|
}
|
|
18657
19108
|
if (smsEnabled) {
|
|
18658
19109
|
console.log(`
|
|
18659
|
-
${
|
|
19110
|
+
${pc26.bold(pc26.cyan("SMS:"))}`);
|
|
18660
19111
|
console.log(
|
|
18661
|
-
` ${
|
|
19112
|
+
` ${pc26.green("\u2713")} SMS Voice V2 read access (phone numbers, config, registrations)`
|
|
18662
19113
|
);
|
|
18663
19114
|
if (smsSendingEnabled) {
|
|
18664
|
-
console.log(` ${
|
|
19115
|
+
console.log(` ${pc26.green("\u2713")} SMS sending via SMS Voice V2`);
|
|
18665
19116
|
}
|
|
18666
19117
|
if (smsEventTracking?.dynamoDBHistory) {
|
|
18667
|
-
console.log(` ${
|
|
19118
|
+
console.log(` ${pc26.green("\u2713")} DynamoDB read access for SMS history`);
|
|
18668
19119
|
}
|
|
18669
19120
|
if (smsEventTracking?.enabled) {
|
|
18670
|
-
console.log(` ${
|
|
19121
|
+
console.log(` ${pc26.green("\u2713")} SNS topic access for SMS events`);
|
|
18671
19122
|
}
|
|
18672
19123
|
}
|
|
18673
19124
|
console.log(
|
|
18674
19125
|
`
|
|
18675
|
-
${
|
|
19126
|
+
${pc26.dim("The Wraps Platform will now have updated permissions for feature detection.")}
|
|
18676
19127
|
`
|
|
18677
19128
|
);
|
|
18678
19129
|
}
|
|
18679
|
-
function
|
|
19130
|
+
function buildConsolePolicyDocument2(emailConfig, smsConfig) {
|
|
18680
19131
|
const statements = [];
|
|
18681
19132
|
statements.push({
|
|
18682
19133
|
Effect: "Allow",
|
|
@@ -18841,10 +19292,10 @@ function buildConsolePolicyDocument(emailConfig, smsConfig) {
|
|
|
18841
19292
|
// src/commands/shared/dashboard.ts
|
|
18842
19293
|
init_esm_shims();
|
|
18843
19294
|
import * as clack24 from "@clack/prompts";
|
|
18844
|
-
import * as
|
|
19295
|
+
import * as pulumi20 from "@pulumi/pulumi";
|
|
18845
19296
|
import getPort from "get-port";
|
|
18846
19297
|
import open from "open";
|
|
18847
|
-
import
|
|
19298
|
+
import pc27 from "picocolors";
|
|
18848
19299
|
|
|
18849
19300
|
// src/console/server.ts
|
|
18850
19301
|
init_esm_shims();
|
|
@@ -19933,13 +20384,13 @@ function createMetricsRouter(config2) {
|
|
|
19933
20384
|
const router = createRouter4();
|
|
19934
20385
|
router.get("/stream", async (req, res) => {
|
|
19935
20386
|
const connectionId = randomUUID().slice(0, 8);
|
|
19936
|
-
const
|
|
20387
|
+
const log35 = (msg, data) => {
|
|
19937
20388
|
console.log(JSON.stringify({ connectionId, msg, ...data }));
|
|
19938
20389
|
};
|
|
19939
20390
|
res.setHeader("Content-Type", "text/event-stream");
|
|
19940
20391
|
res.setHeader("Cache-Control", "no-cache");
|
|
19941
20392
|
res.setHeader("Connection", "keep-alive");
|
|
19942
|
-
|
|
20393
|
+
log35("SSE connected");
|
|
19943
20394
|
res.write('data: {"type":"connected"}\n\n');
|
|
19944
20395
|
const { startTime, endTime } = req.query;
|
|
19945
20396
|
const getTimeRange = () => ({
|
|
@@ -19949,7 +20400,7 @@ function createMetricsRouter(config2) {
|
|
|
19949
20400
|
const sendMetrics = async () => {
|
|
19950
20401
|
try {
|
|
19951
20402
|
const timeRange = getTimeRange();
|
|
19952
|
-
|
|
20403
|
+
log35("Fetching metrics", {
|
|
19953
20404
|
start: timeRange.start.toISOString(),
|
|
19954
20405
|
end: timeRange.end.toISOString()
|
|
19955
20406
|
});
|
|
@@ -19962,7 +20413,7 @@ function createMetricsRouter(config2) {
|
|
|
19962
20413
|
),
|
|
19963
20414
|
fetchSendQuota(config2.roleArn, config2.region)
|
|
19964
20415
|
]);
|
|
19965
|
-
|
|
20416
|
+
log35("Metrics fetched successfully");
|
|
19966
20417
|
const data = {
|
|
19967
20418
|
type: "metrics",
|
|
19968
20419
|
timestamp: Date.now(),
|
|
@@ -19992,7 +20443,7 @@ function createMetricsRouter(config2) {
|
|
|
19992
20443
|
const interval = setInterval(sendMetrics, 6e4);
|
|
19993
20444
|
req.on("close", () => {
|
|
19994
20445
|
clearInterval(interval);
|
|
19995
|
-
|
|
20446
|
+
log35("SSE disconnected");
|
|
19996
20447
|
});
|
|
19997
20448
|
});
|
|
19998
20449
|
router.get("/snapshot", async (_req, res) => {
|
|
@@ -21234,9 +21685,9 @@ function createUserRouter(config2) {
|
|
|
21234
21685
|
if (config2.roleArn) {
|
|
21235
21686
|
console.log("[User API] Attempting to fetch account alias via IAM");
|
|
21236
21687
|
const { assumeRole: assumeRole2 } = await Promise.resolve().then(() => (init_assume_role(), assume_role_exports));
|
|
21237
|
-
const { IAMClient:
|
|
21688
|
+
const { IAMClient: IAMClient4, ListAccountAliasesCommand } = await import("@aws-sdk/client-iam");
|
|
21238
21689
|
const credentials = await assumeRole2(config2.roleArn, region);
|
|
21239
|
-
const iamClient = new
|
|
21690
|
+
const iamClient = new IAMClient4({ region, credentials });
|
|
21240
21691
|
const response = await iamClient.send(
|
|
21241
21692
|
new ListAccountAliasesCommand({})
|
|
21242
21693
|
);
|
|
@@ -21364,7 +21815,7 @@ init_aws();
|
|
|
21364
21815
|
init_fs();
|
|
21365
21816
|
init_metadata();
|
|
21366
21817
|
async function dashboard(options) {
|
|
21367
|
-
clack24.intro(
|
|
21818
|
+
clack24.intro(pc27.bold("Wraps Dashboard"));
|
|
21368
21819
|
const progress = new DeploymentProgress();
|
|
21369
21820
|
const identity = await progress.execute(
|
|
21370
21821
|
"Validating AWS credentials",
|
|
@@ -21377,7 +21828,7 @@ async function dashboard(options) {
|
|
|
21377
21828
|
try {
|
|
21378
21829
|
await ensurePulumiWorkDir();
|
|
21379
21830
|
try {
|
|
21380
|
-
const emailStack = await
|
|
21831
|
+
const emailStack = await pulumi20.automation.LocalWorkspace.selectStack({
|
|
21381
21832
|
stackName: `wraps-${identity.accountId}-${region}`,
|
|
21382
21833
|
workDir: getPulumiWorkDir()
|
|
21383
21834
|
});
|
|
@@ -21385,7 +21836,7 @@ async function dashboard(options) {
|
|
|
21385
21836
|
} catch (_emailError) {
|
|
21386
21837
|
}
|
|
21387
21838
|
try {
|
|
21388
|
-
const smsStack = await
|
|
21839
|
+
const smsStack = await pulumi20.automation.LocalWorkspace.selectStack({
|
|
21389
21840
|
stackName: `wraps-sms-${identity.accountId}-${region}`,
|
|
21390
21841
|
workDir: getPulumiWorkDir()
|
|
21391
21842
|
});
|
|
@@ -21393,7 +21844,7 @@ async function dashboard(options) {
|
|
|
21393
21844
|
} catch (_smsError) {
|
|
21394
21845
|
}
|
|
21395
21846
|
try {
|
|
21396
|
-
const cdnStack = await
|
|
21847
|
+
const cdnStack = await pulumi20.automation.LocalWorkspace.selectStack({
|
|
21397
21848
|
stackName: `wraps-cdn-${identity.accountId}-${region}`,
|
|
21398
21849
|
workDir: getPulumiWorkDir()
|
|
21399
21850
|
});
|
|
@@ -21407,7 +21858,7 @@ async function dashboard(options) {
|
|
|
21407
21858
|
progress.stop();
|
|
21408
21859
|
clack24.log.error("No Wraps infrastructure found");
|
|
21409
21860
|
console.log(
|
|
21410
|
-
`\\nRun ${
|
|
21861
|
+
`\\nRun ${pc27.cyan("wraps email init")}, ${pc27.cyan("wraps sms init")}, or ${pc27.cyan("wraps storage init")} to deploy infrastructure first.\\n`
|
|
21411
21862
|
);
|
|
21412
21863
|
process.exit(1);
|
|
21413
21864
|
}
|
|
@@ -21450,7 +21901,7 @@ async function dashboard(options) {
|
|
|
21450
21901
|
progress.stop();
|
|
21451
21902
|
clack24.log.success("Starting dashboard server...");
|
|
21452
21903
|
console.log(
|
|
21453
|
-
`${
|
|
21904
|
+
`${pc27.dim("Using current AWS credentials (no role assumption)")}\\n`
|
|
21454
21905
|
);
|
|
21455
21906
|
const { url } = await startConsoleServer({
|
|
21456
21907
|
port,
|
|
@@ -21481,8 +21932,8 @@ async function dashboard(options) {
|
|
|
21481
21932
|
cdnCustomDomain,
|
|
21482
21933
|
cdnCertificateArn
|
|
21483
21934
|
});
|
|
21484
|
-
console.log(`\\n${
|
|
21485
|
-
console.log(`${
|
|
21935
|
+
console.log(`\\n${pc27.bold("Dashboard:")} ${pc27.cyan(url)}`);
|
|
21936
|
+
console.log(`${pc27.dim("Press Ctrl+C to stop")}\\n`);
|
|
21486
21937
|
getTelemetryClient().showFooterOnce();
|
|
21487
21938
|
if (!options.noOpen) {
|
|
21488
21939
|
await open(url);
|
|
@@ -21501,9 +21952,9 @@ init_esm_shims();
|
|
|
21501
21952
|
init_aws();
|
|
21502
21953
|
init_metadata();
|
|
21503
21954
|
import * as clack25 from "@clack/prompts";
|
|
21504
|
-
import
|
|
21955
|
+
import pc28 from "picocolors";
|
|
21505
21956
|
async function destroy(options) {
|
|
21506
|
-
clack25.intro(
|
|
21957
|
+
clack25.intro(pc28.bold("Wraps Infrastructure Teardown"));
|
|
21507
21958
|
const spinner6 = clack25.spinner();
|
|
21508
21959
|
spinner6.start("Validating AWS credentials");
|
|
21509
21960
|
let identity;
|
|
@@ -21524,14 +21975,14 @@ async function destroy(options) {
|
|
|
21524
21975
|
clack25.log.warn("No Wraps services found in this region");
|
|
21525
21976
|
console.log(
|
|
21526
21977
|
`
|
|
21527
|
-
Run ${
|
|
21978
|
+
Run ${pc28.cyan("wraps email init")} to deploy infrastructure.
|
|
21528
21979
|
`
|
|
21529
21980
|
);
|
|
21530
21981
|
process.exit(0);
|
|
21531
21982
|
}
|
|
21532
21983
|
if (deployedServices.length === 1) {
|
|
21533
21984
|
const service = deployedServices[0];
|
|
21534
|
-
clack25.log.info(`Found ${
|
|
21985
|
+
clack25.log.info(`Found ${pc28.cyan(service)} service deployed`);
|
|
21535
21986
|
if (service === "email") {
|
|
21536
21987
|
await emailDestroy(options);
|
|
21537
21988
|
return;
|
|
@@ -21560,7 +22011,7 @@ Run ${pc27.cyan("wraps email init")} to deploy infrastructure.
|
|
|
21560
22011
|
await emailDestroy(options);
|
|
21561
22012
|
}
|
|
21562
22013
|
if (serviceToDestroy === "all") {
|
|
21563
|
-
clack25.outro(
|
|
22014
|
+
clack25.outro(pc28.green("All Wraps infrastructure has been removed"));
|
|
21564
22015
|
}
|
|
21565
22016
|
}
|
|
21566
22017
|
|
|
@@ -21570,23 +22021,23 @@ init_events();
|
|
|
21570
22021
|
init_aws();
|
|
21571
22022
|
init_fs();
|
|
21572
22023
|
import * as clack26 from "@clack/prompts";
|
|
21573
|
-
import * as
|
|
21574
|
-
import
|
|
22024
|
+
import * as pulumi21 from "@pulumi/pulumi";
|
|
22025
|
+
import pc29 from "picocolors";
|
|
21575
22026
|
async function status(_options) {
|
|
21576
22027
|
const startTime = Date.now();
|
|
21577
22028
|
const progress = new DeploymentProgress();
|
|
21578
|
-
clack26.intro(
|
|
22029
|
+
clack26.intro(pc29.bold("Wraps Infrastructure Status"));
|
|
21579
22030
|
const identity = await progress.execute(
|
|
21580
22031
|
"Loading infrastructure status",
|
|
21581
22032
|
async () => validateAWSCredentials()
|
|
21582
22033
|
);
|
|
21583
|
-
progress.info(`AWS Account: ${
|
|
22034
|
+
progress.info(`AWS Account: ${pc29.cyan(identity.accountId)}`);
|
|
21584
22035
|
const region = await getAWSRegion();
|
|
21585
|
-
progress.info(`Region: ${
|
|
22036
|
+
progress.info(`Region: ${pc29.cyan(region)}`);
|
|
21586
22037
|
const services = [];
|
|
21587
22038
|
try {
|
|
21588
22039
|
await ensurePulumiWorkDir();
|
|
21589
|
-
const emailStack = await
|
|
22040
|
+
const emailStack = await pulumi21.automation.LocalWorkspace.selectStack({
|
|
21590
22041
|
stackName: `wraps-${identity.accountId}-${region}`,
|
|
21591
22042
|
workDir: getPulumiWorkDir()
|
|
21592
22043
|
});
|
|
@@ -21605,7 +22056,7 @@ async function status(_options) {
|
|
|
21605
22056
|
services.push({ name: "Email", status: "not_deployed" });
|
|
21606
22057
|
}
|
|
21607
22058
|
try {
|
|
21608
|
-
const smsStack = await
|
|
22059
|
+
const smsStack = await pulumi21.automation.LocalWorkspace.selectStack({
|
|
21609
22060
|
stackName: `wraps-sms-${identity.accountId}-${region}`,
|
|
21610
22061
|
workDir: getPulumiWorkDir()
|
|
21611
22062
|
});
|
|
@@ -21628,32 +22079,32 @@ async function status(_options) {
|
|
|
21628
22079
|
clack26.note(
|
|
21629
22080
|
services.map((s) => {
|
|
21630
22081
|
if (s.status === "deployed") {
|
|
21631
|
-
const details = s.details ?
|
|
21632
|
-
return ` ${
|
|
22082
|
+
const details = s.details ? pc29.dim(` (${s.details})`) : "";
|
|
22083
|
+
return ` ${pc29.green("\u2713")} ${s.name}${details}`;
|
|
21633
22084
|
}
|
|
21634
|
-
return ` ${
|
|
22085
|
+
return ` ${pc29.dim("\u25CB")} ${s.name} ${pc29.dim("(not deployed)")}`;
|
|
21635
22086
|
}).join("\n"),
|
|
21636
22087
|
"Services"
|
|
21637
22088
|
);
|
|
21638
22089
|
const hasDeployedServices = services.some((s) => s.status === "deployed");
|
|
21639
22090
|
if (hasDeployedServices) {
|
|
21640
22091
|
console.log(`
|
|
21641
|
-
${
|
|
22092
|
+
${pc29.bold("Details:")}`);
|
|
21642
22093
|
if (services.find((s) => s.name === "Email")?.status === "deployed") {
|
|
21643
|
-
console.log(` ${
|
|
22094
|
+
console.log(` ${pc29.dim("Email:")} ${pc29.cyan("wraps email status")}`);
|
|
21644
22095
|
}
|
|
21645
22096
|
if (services.find((s) => s.name === "SMS")?.status === "deployed") {
|
|
21646
|
-
console.log(` ${
|
|
22097
|
+
console.log(` ${pc29.dim("SMS:")} ${pc29.cyan("wraps sms status")}`);
|
|
21647
22098
|
}
|
|
21648
22099
|
} else {
|
|
21649
22100
|
console.log(`
|
|
21650
|
-
${
|
|
21651
|
-
console.log(` ${
|
|
21652
|
-
console.log(` ${
|
|
22101
|
+
${pc29.bold("Get started:")}`);
|
|
22102
|
+
console.log(` ${pc29.dim("Deploy email:")} ${pc29.cyan("wraps email init")}`);
|
|
22103
|
+
console.log(` ${pc29.dim("Deploy SMS:")} ${pc29.cyan("wraps sms init")}`);
|
|
21653
22104
|
}
|
|
21654
22105
|
console.log(`
|
|
21655
|
-
${
|
|
21656
|
-
console.log(`${
|
|
22106
|
+
${pc29.bold("Dashboard:")} ${pc29.blue("https://app.wraps.dev")}`);
|
|
22107
|
+
console.log(`${pc29.bold("Docs:")} ${pc29.blue("https://wraps.dev/docs")}
|
|
21657
22108
|
`);
|
|
21658
22109
|
trackCommand("status", {
|
|
21659
22110
|
success: true,
|
|
@@ -21665,20 +22116,20 @@ ${pc28.bold("Dashboard:")} ${pc28.blue("https://app.wraps.dev")}`);
|
|
|
21665
22116
|
// src/commands/sms/destroy.ts
|
|
21666
22117
|
init_esm_shims();
|
|
21667
22118
|
import * as clack27 from "@clack/prompts";
|
|
21668
|
-
import * as
|
|
21669
|
-
import
|
|
22119
|
+
import * as pulumi23 from "@pulumi/pulumi";
|
|
22120
|
+
import pc30 from "picocolors";
|
|
21670
22121
|
|
|
21671
22122
|
// src/infrastructure/sms-stack.ts
|
|
21672
22123
|
init_esm_shims();
|
|
21673
22124
|
import * as aws15 from "@pulumi/aws";
|
|
21674
|
-
import * as
|
|
22125
|
+
import * as pulumi22 from "@pulumi/pulumi";
|
|
21675
22126
|
async function roleExists3(roleName) {
|
|
21676
22127
|
try {
|
|
21677
|
-
const { IAMClient:
|
|
21678
|
-
const iam8 = new
|
|
22128
|
+
const { IAMClient: IAMClient4, GetRoleCommand: GetRoleCommand3 } = await import("@aws-sdk/client-iam");
|
|
22129
|
+
const iam8 = new IAMClient4({
|
|
21679
22130
|
region: process.env.AWS_REGION || "us-east-1"
|
|
21680
22131
|
});
|
|
21681
|
-
await iam8.send(new
|
|
22132
|
+
await iam8.send(new GetRoleCommand3({ RoleName: roleName }));
|
|
21682
22133
|
return true;
|
|
21683
22134
|
} catch (error) {
|
|
21684
22135
|
if (error.name === "NoSuchEntityException" || error.Code === "NoSuchEntity" || error.Error?.Code === "NoSuchEntity") {
|
|
@@ -21705,7 +22156,7 @@ async function tableExists2(tableName) {
|
|
|
21705
22156
|
async function createSMSIAMRole(config2) {
|
|
21706
22157
|
let assumeRolePolicy;
|
|
21707
22158
|
if (config2.provider === "vercel" && config2.oidcProvider) {
|
|
21708
|
-
assumeRolePolicy =
|
|
22159
|
+
assumeRolePolicy = pulumi22.interpolate`{
|
|
21709
22160
|
"Version": "2012-10-17",
|
|
21710
22161
|
"Statement": [
|
|
21711
22162
|
{
|
|
@@ -21733,7 +22184,7 @@ async function createSMSIAMRole(config2) {
|
|
|
21733
22184
|
]
|
|
21734
22185
|
}`;
|
|
21735
22186
|
} else if (config2.provider === "aws") {
|
|
21736
|
-
assumeRolePolicy =
|
|
22187
|
+
assumeRolePolicy = pulumi22.output(`{
|
|
21737
22188
|
"Version": "2012-10-17",
|
|
21738
22189
|
"Statement": [{
|
|
21739
22190
|
"Effect": "Allow",
|
|
@@ -22088,7 +22539,7 @@ async function createSMSSNSResources(config2) {
|
|
|
22088
22539
|
});
|
|
22089
22540
|
new aws15.sqs.QueuePolicy("wraps-sms-events-queue-policy", {
|
|
22090
22541
|
queueUrl: config2.queueUrl,
|
|
22091
|
-
policy:
|
|
22542
|
+
policy: pulumi22.all([config2.queueArn, topic.arn]).apply(
|
|
22092
22543
|
([queueArn, topicArn2]) => JSON.stringify({
|
|
22093
22544
|
Version: "2012-10-17",
|
|
22094
22545
|
Statement: [
|
|
@@ -22187,7 +22638,7 @@ async function deploySMSLambdaFunction(config2) {
|
|
|
22187
22638
|
});
|
|
22188
22639
|
new aws15.iam.RolePolicy("wraps-sms-lambda-policy", {
|
|
22189
22640
|
role: lambdaRole.name,
|
|
22190
|
-
policy:
|
|
22641
|
+
policy: pulumi22.all([config2.tableName, config2.queueArn]).apply(
|
|
22191
22642
|
([tableName, queueArn]) => JSON.stringify({
|
|
22192
22643
|
Version: "2012-10-17",
|
|
22193
22644
|
Statement: [
|
|
@@ -22224,7 +22675,7 @@ async function deploySMSLambdaFunction(config2) {
|
|
|
22224
22675
|
runtime: "nodejs20.x",
|
|
22225
22676
|
handler: "index.handler",
|
|
22226
22677
|
role: lambdaRole.arn,
|
|
22227
|
-
code: new
|
|
22678
|
+
code: new pulumi22.asset.FileArchive(codeDir),
|
|
22228
22679
|
timeout: 300,
|
|
22229
22680
|
// 5 minutes
|
|
22230
22681
|
memorySize: 512,
|
|
@@ -22464,18 +22915,18 @@ async function createSMSProtectConfigurationWithSDK(configurationSetName, region
|
|
|
22464
22915
|
const existing = await client.send(
|
|
22465
22916
|
new DescribeProtectConfigurationsCommand({})
|
|
22466
22917
|
);
|
|
22467
|
-
for (const
|
|
22468
|
-
if (!(
|
|
22918
|
+
for (const pc41 of existing.ProtectConfigurations || []) {
|
|
22919
|
+
if (!(pc41.ProtectConfigurationArn && pc41.ProtectConfigurationId)) {
|
|
22469
22920
|
continue;
|
|
22470
22921
|
}
|
|
22471
22922
|
const tagsResponse = await client.send(
|
|
22472
22923
|
new ListTagsForResourceCommand({
|
|
22473
|
-
ResourceArn:
|
|
22924
|
+
ResourceArn: pc41.ProtectConfigurationArn
|
|
22474
22925
|
})
|
|
22475
22926
|
);
|
|
22476
22927
|
const nameTag = tagsResponse.Tags?.find((t) => t.Key === "Name");
|
|
22477
22928
|
if (nameTag?.Value === protectConfigName) {
|
|
22478
|
-
existingProtectConfigId =
|
|
22929
|
+
existingProtectConfigId = pc41.ProtectConfigurationId;
|
|
22479
22930
|
break;
|
|
22480
22931
|
}
|
|
22481
22932
|
}
|
|
@@ -22562,13 +23013,13 @@ async function deleteSMSProtectConfigurationWithSDK(region) {
|
|
|
22562
23013
|
new DescribeProtectConfigurationsCommand({})
|
|
22563
23014
|
);
|
|
22564
23015
|
if (existing.ProtectConfigurations) {
|
|
22565
|
-
for (const
|
|
22566
|
-
if (!(
|
|
23016
|
+
for (const pc41 of existing.ProtectConfigurations) {
|
|
23017
|
+
if (!(pc41.ProtectConfigurationArn && pc41.ProtectConfigurationId)) {
|
|
22567
23018
|
continue;
|
|
22568
23019
|
}
|
|
22569
23020
|
const tagsResponse = await client.send(
|
|
22570
23021
|
new ListTagsForResourceCommand({
|
|
22571
|
-
ResourceArn:
|
|
23022
|
+
ResourceArn: pc41.ProtectConfigurationArn
|
|
22572
23023
|
})
|
|
22573
23024
|
);
|
|
22574
23025
|
const isWrapsManaged = tagsResponse.Tags?.some(
|
|
@@ -22577,7 +23028,7 @@ async function deleteSMSProtectConfigurationWithSDK(region) {
|
|
|
22577
23028
|
if (isWrapsManaged) {
|
|
22578
23029
|
await client.send(
|
|
22579
23030
|
new DeleteProtectConfigurationCommand({
|
|
22580
|
-
ProtectConfigurationId:
|
|
23031
|
+
ProtectConfigurationId: pc41.ProtectConfigurationId
|
|
22581
23032
|
})
|
|
22582
23033
|
);
|
|
22583
23034
|
}
|
|
@@ -22596,7 +23047,7 @@ init_metadata();
|
|
|
22596
23047
|
async function smsDestroy(options) {
|
|
22597
23048
|
const startTime = Date.now();
|
|
22598
23049
|
clack27.intro(
|
|
22599
|
-
|
|
23050
|
+
pc30.bold(
|
|
22600
23051
|
options.preview ? "SMS Infrastructure Destruction Preview" : "SMS Infrastructure Teardown"
|
|
22601
23052
|
)
|
|
22602
23053
|
);
|
|
@@ -22616,7 +23067,7 @@ async function smsDestroy(options) {
|
|
|
22616
23067
|
}
|
|
22617
23068
|
if (!(options.force || options.preview)) {
|
|
22618
23069
|
const confirmed = await clack27.confirm({
|
|
22619
|
-
message:
|
|
23070
|
+
message: pc30.red(
|
|
22620
23071
|
"Are you sure you want to destroy all SMS infrastructure?"
|
|
22621
23072
|
),
|
|
22622
23073
|
initialValue: false
|
|
@@ -22635,7 +23086,7 @@ async function smsDestroy(options) {
|
|
|
22635
23086
|
const stackName = storedStackName || `wraps-sms-${identity.accountId}-${region}`;
|
|
22636
23087
|
let stack;
|
|
22637
23088
|
try {
|
|
22638
|
-
stack = await
|
|
23089
|
+
stack = await pulumi23.automation.LocalWorkspace.selectStack({
|
|
22639
23090
|
stackName,
|
|
22640
23091
|
workDir: getPulumiWorkDir()
|
|
22641
23092
|
});
|
|
@@ -22655,7 +23106,7 @@ async function smsDestroy(options) {
|
|
|
22655
23106
|
commandName: "wraps sms destroy"
|
|
22656
23107
|
});
|
|
22657
23108
|
clack27.outro(
|
|
22658
|
-
|
|
23109
|
+
pc30.green("Preview complete. Run without --preview to destroy.")
|
|
22659
23110
|
);
|
|
22660
23111
|
trackServiceRemoved("sms", {
|
|
22661
23112
|
preview: true,
|
|
@@ -22692,7 +23143,7 @@ async function smsDestroy(options) {
|
|
|
22692
23143
|
const stackName = storedStackName || `wraps-sms-${identity.accountId}-${region}`;
|
|
22693
23144
|
let stack;
|
|
22694
23145
|
try {
|
|
22695
|
-
stack = await
|
|
23146
|
+
stack = await pulumi23.automation.LocalWorkspace.selectStack({
|
|
22696
23147
|
stackName,
|
|
22697
23148
|
workDir: getPulumiWorkDir()
|
|
22698
23149
|
});
|
|
@@ -22728,16 +23179,16 @@ async function smsDestroy(options) {
|
|
|
22728
23179
|
await saveConnectionMetadata(metadata);
|
|
22729
23180
|
}
|
|
22730
23181
|
progress.stop();
|
|
22731
|
-
clack27.outro(
|
|
23182
|
+
clack27.outro(pc30.green("SMS infrastructure has been removed"));
|
|
22732
23183
|
console.log(`
|
|
22733
|
-
${
|
|
22734
|
-
console.log(` ${
|
|
22735
|
-
console.log(` ${
|
|
22736
|
-
console.log(` ${
|
|
22737
|
-
console.log(` ${
|
|
23184
|
+
${pc30.bold("Cleaned up:")}`);
|
|
23185
|
+
console.log(` ${pc30.green("\u2713")} Phone number released`);
|
|
23186
|
+
console.log(` ${pc30.green("\u2713")} Configuration set deleted`);
|
|
23187
|
+
console.log(` ${pc30.green("\u2713")} Event processing infrastructure removed`);
|
|
23188
|
+
console.log(` ${pc30.green("\u2713")} IAM role deleted`);
|
|
22738
23189
|
console.log(
|
|
22739
23190
|
`
|
|
22740
|
-
Run ${
|
|
23191
|
+
Run ${pc30.cyan("wraps sms init")} to deploy infrastructure again.
|
|
22741
23192
|
`
|
|
22742
23193
|
);
|
|
22743
23194
|
trackServiceRemoved("sms", {
|
|
@@ -22749,8 +23200,8 @@ Run ${pc29.cyan("wraps sms init")} to deploy infrastructure again.
|
|
|
22749
23200
|
// src/commands/sms/init.ts
|
|
22750
23201
|
init_esm_shims();
|
|
22751
23202
|
import * as clack28 from "@clack/prompts";
|
|
22752
|
-
import * as
|
|
22753
|
-
import
|
|
23203
|
+
import * as pulumi24 from "@pulumi/pulumi";
|
|
23204
|
+
import pc31 from "picocolors";
|
|
22754
23205
|
init_events();
|
|
22755
23206
|
init_aws();
|
|
22756
23207
|
init_errors();
|
|
@@ -23274,7 +23725,7 @@ async function promptEstimatedSMSVolume() {
|
|
|
23274
23725
|
}
|
|
23275
23726
|
async function init3(options) {
|
|
23276
23727
|
const startTime = Date.now();
|
|
23277
|
-
clack28.intro(
|
|
23728
|
+
clack28.intro(pc31.bold("Wraps SMS Infrastructure Setup"));
|
|
23278
23729
|
const progress = new DeploymentProgress();
|
|
23279
23730
|
const wasAutoInstalled = await progress.execute(
|
|
23280
23731
|
"Checking Pulumi CLI installation",
|
|
@@ -23287,7 +23738,7 @@ async function init3(options) {
|
|
|
23287
23738
|
"Validating AWS credentials",
|
|
23288
23739
|
async () => validateAWSCredentials()
|
|
23289
23740
|
);
|
|
23290
|
-
progress.info(`Connected to AWS account: ${
|
|
23741
|
+
progress.info(`Connected to AWS account: ${pc31.cyan(identity.accountId)}`);
|
|
23291
23742
|
const provider = options.provider || await promptProvider();
|
|
23292
23743
|
const region = options.region || await promptRegion(await getAWSRegion());
|
|
23293
23744
|
let vercelConfig;
|
|
@@ -23300,9 +23751,9 @@ async function init3(options) {
|
|
|
23300
23751
|
);
|
|
23301
23752
|
if (existingConnection?.services?.sms) {
|
|
23302
23753
|
clack28.log.warn(
|
|
23303
|
-
`SMS already configured for account ${
|
|
23754
|
+
`SMS already configured for account ${pc31.cyan(identity.accountId)} in region ${pc31.cyan(region)}`
|
|
23304
23755
|
);
|
|
23305
|
-
clack28.log.info(`Use ${
|
|
23756
|
+
clack28.log.info(`Use ${pc31.cyan("wraps sms status")} to view current setup`);
|
|
23306
23757
|
process.exit(0);
|
|
23307
23758
|
}
|
|
23308
23759
|
let preset = options.preset;
|
|
@@ -23344,7 +23795,7 @@ async function init3(options) {
|
|
|
23344
23795
|
}
|
|
23345
23796
|
progress.info(
|
|
23346
23797
|
`
|
|
23347
|
-
${
|
|
23798
|
+
${pc31.bold("Fraud Protection")} - Block SMS to countries where you don't do business`
|
|
23348
23799
|
);
|
|
23349
23800
|
const allowedCountries = await promptAllowedCountries();
|
|
23350
23801
|
let aitFiltering = false;
|
|
@@ -23366,13 +23817,13 @@ ${pc30.bold("Fraud Protection")} - Block SMS to countries where you don't do bus
|
|
|
23366
23817
|
};
|
|
23367
23818
|
const estimatedVolume = await promptEstimatedSMSVolume();
|
|
23368
23819
|
progress.info(`
|
|
23369
|
-
${
|
|
23820
|
+
${pc31.bold("Cost Estimate:")}`);
|
|
23370
23821
|
const costSummary = getSMSCostSummary(smsConfig, estimatedVolume);
|
|
23371
23822
|
clack28.log.info(costSummary);
|
|
23372
23823
|
const warnings = validateSMSConfig(smsConfig);
|
|
23373
23824
|
if (warnings.length > 0) {
|
|
23374
23825
|
progress.info(`
|
|
23375
|
-
${
|
|
23826
|
+
${pc31.yellow(pc31.bold("Important Notes:"))}`);
|
|
23376
23827
|
for (const warning of warnings) {
|
|
23377
23828
|
clack28.log.warn(warning);
|
|
23378
23829
|
}
|
|
@@ -23396,7 +23847,7 @@ ${pc30.yellow(pc30.bold("Important Notes:"))}`);
|
|
|
23396
23847
|
"Deploying SMS infrastructure (this may take 2-3 minutes)",
|
|
23397
23848
|
async () => {
|
|
23398
23849
|
await ensurePulumiWorkDir();
|
|
23399
|
-
const stack = await
|
|
23850
|
+
const stack = await pulumi24.automation.LocalWorkspace.createOrSelectStack(
|
|
23400
23851
|
{
|
|
23401
23852
|
stackName: `wraps-sms-${identity.accountId}-${region}`,
|
|
23402
23853
|
projectName: "wraps-sms",
|
|
@@ -23502,47 +23953,47 @@ ${pc30.yellow(pc30.bold("Important Notes:"))}`);
|
|
|
23502
23953
|
await saveConnectionMetadata(metadata);
|
|
23503
23954
|
progress.info("Connection metadata saved");
|
|
23504
23955
|
console.log("\n");
|
|
23505
|
-
clack28.log.success(
|
|
23956
|
+
clack28.log.success(pc31.green(pc31.bold("SMS infrastructure deployed!")));
|
|
23506
23957
|
console.log("\n");
|
|
23507
23958
|
clack28.note(
|
|
23508
23959
|
[
|
|
23509
|
-
`${
|
|
23510
|
-
`${
|
|
23511
|
-
`${
|
|
23512
|
-
`${
|
|
23513
|
-
outputs.tableName ? `${
|
|
23960
|
+
`${pc31.bold("Phone Number:")} ${pc31.cyan(outputs.phoneNumber || "Provisioning...")}`,
|
|
23961
|
+
`${pc31.bold("Phone Type:")} ${pc31.cyan(smsConfig.phoneNumberType || "simulator")}`,
|
|
23962
|
+
`${pc31.bold("Config Set:")} ${pc31.cyan(outputs.configSetName || "wraps-sms-config")}`,
|
|
23963
|
+
`${pc31.bold("Region:")} ${pc31.cyan(outputs.region)}`,
|
|
23964
|
+
outputs.tableName ? `${pc31.bold("History Table:")} ${pc31.cyan(outputs.tableName)}` : "",
|
|
23514
23965
|
"",
|
|
23515
|
-
|
|
23516
|
-
|
|
23966
|
+
pc31.dim("IAM Role:"),
|
|
23967
|
+
pc31.dim(` ${outputs.roleArn}`)
|
|
23517
23968
|
].filter(Boolean).join("\n"),
|
|
23518
23969
|
"SMS Infrastructure"
|
|
23519
23970
|
);
|
|
23520
23971
|
const nextSteps = [];
|
|
23521
23972
|
if (smsConfig.phoneNumberType === "toll-free") {
|
|
23522
23973
|
nextSteps.push(
|
|
23523
|
-
`${
|
|
23974
|
+
`${pc31.cyan("wraps sms register")} - Submit toll-free registration (required before sending)`
|
|
23524
23975
|
);
|
|
23525
23976
|
}
|
|
23526
23977
|
nextSteps.push(
|
|
23527
|
-
`${
|
|
23978
|
+
`${pc31.cyan("wraps sms test --to +1234567890")} - Send a test message`
|
|
23528
23979
|
);
|
|
23529
|
-
nextSteps.push(`${
|
|
23980
|
+
nextSteps.push(`${pc31.cyan("wraps sms status")} - View SMS configuration`);
|
|
23530
23981
|
console.log("\n");
|
|
23531
|
-
clack28.log.info(
|
|
23982
|
+
clack28.log.info(pc31.bold("Next steps:"));
|
|
23532
23983
|
for (const step of nextSteps) {
|
|
23533
23984
|
console.log(` ${step}`);
|
|
23534
23985
|
}
|
|
23535
23986
|
console.log("\n");
|
|
23536
|
-
clack28.log.info(
|
|
23537
|
-
console.log(
|
|
23987
|
+
clack28.log.info(pc31.bold("SDK Usage:"));
|
|
23988
|
+
console.log(pc31.dim(" npm install @wraps.dev/sms"));
|
|
23538
23989
|
console.log("");
|
|
23539
|
-
console.log(
|
|
23540
|
-
console.log(
|
|
23541
|
-
console.log(
|
|
23542
|
-
console.log(
|
|
23543
|
-
console.log(
|
|
23544
|
-
console.log(
|
|
23545
|
-
clack28.outro(
|
|
23990
|
+
console.log(pc31.dim(" import { Wraps } from '@wraps.dev/sms';"));
|
|
23991
|
+
console.log(pc31.dim(" const wraps = new Wraps();"));
|
|
23992
|
+
console.log(pc31.dim(" await wraps.sms.send({"));
|
|
23993
|
+
console.log(pc31.dim(" to: '+14155551234',"));
|
|
23994
|
+
console.log(pc31.dim(" message: 'Your code is 123456',"));
|
|
23995
|
+
console.log(pc31.dim(" });"));
|
|
23996
|
+
clack28.outro(pc31.green("Setup complete!"));
|
|
23546
23997
|
const duration = Date.now() - startTime;
|
|
23547
23998
|
const enabledFeatures = [];
|
|
23548
23999
|
if (smsConfig.tracking?.enabled) {
|
|
@@ -23576,7 +24027,7 @@ init_esm_shims();
|
|
|
23576
24027
|
init_aws();
|
|
23577
24028
|
init_metadata();
|
|
23578
24029
|
import * as clack29 from "@clack/prompts";
|
|
23579
|
-
import
|
|
24030
|
+
import pc32 from "picocolors";
|
|
23580
24031
|
async function getPhoneNumberDetails(region) {
|
|
23581
24032
|
const { PinpointSMSVoiceV2Client: PinpointSMSVoiceV2Client5, DescribePhoneNumbersCommand: DescribePhoneNumbersCommand2 } = await import("@aws-sdk/client-pinpoint-sms-voice-v2");
|
|
23582
24033
|
const client = new PinpointSMSVoiceV2Client5({ region });
|
|
@@ -23614,7 +24065,7 @@ async function getRegistrationStatus(region, registrationId) {
|
|
|
23614
24065
|
}
|
|
23615
24066
|
}
|
|
23616
24067
|
async function smsRegister(options) {
|
|
23617
|
-
clack29.intro(
|
|
24068
|
+
clack29.intro(pc32.bold("Wraps SMS - Toll-Free Registration"));
|
|
23618
24069
|
const progress = new DeploymentProgress();
|
|
23619
24070
|
const identity = await progress.execute(
|
|
23620
24071
|
"Validating AWS credentials",
|
|
@@ -23627,7 +24078,7 @@ async function smsRegister(options) {
|
|
|
23627
24078
|
const metadata = await loadConnectionMetadata(identity.accountId, region);
|
|
23628
24079
|
if (!metadata?.services?.sms) {
|
|
23629
24080
|
clack29.log.error("No SMS infrastructure found.");
|
|
23630
|
-
clack29.log.info(`Run ${
|
|
24081
|
+
clack29.log.info(`Run ${pc32.cyan("wraps sms init")} first.`);
|
|
23631
24082
|
process.exit(1);
|
|
23632
24083
|
}
|
|
23633
24084
|
const phoneDetails = await progress.execute(
|
|
@@ -23640,11 +24091,11 @@ async function smsRegister(options) {
|
|
|
23640
24091
|
}
|
|
23641
24092
|
console.log("");
|
|
23642
24093
|
console.log(
|
|
23643
|
-
`${
|
|
24094
|
+
`${pc32.bold("Phone Number:")} ${pc32.cyan(phoneDetails.phoneNumber)}`
|
|
23644
24095
|
);
|
|
23645
|
-
console.log(`${
|
|
24096
|
+
console.log(`${pc32.bold("Type:")} ${pc32.cyan(phoneDetails.type)}`);
|
|
23646
24097
|
console.log(
|
|
23647
|
-
`${
|
|
24098
|
+
`${pc32.bold("Status:")} ${phoneDetails.status === "ACTIVE" ? pc32.green(phoneDetails.status) : pc32.yellow(phoneDetails.status)}`
|
|
23648
24099
|
);
|
|
23649
24100
|
if (phoneDetails.registrationId) {
|
|
23650
24101
|
const regStatus = await getRegistrationStatus(
|
|
@@ -23652,7 +24103,7 @@ async function smsRegister(options) {
|
|
|
23652
24103
|
phoneDetails.registrationId
|
|
23653
24104
|
);
|
|
23654
24105
|
if (regStatus) {
|
|
23655
|
-
console.log(`${
|
|
24106
|
+
console.log(`${pc32.bold("Registration:")} ${pc32.cyan(regStatus)}`);
|
|
23656
24107
|
}
|
|
23657
24108
|
}
|
|
23658
24109
|
console.log("");
|
|
@@ -23671,21 +24122,21 @@ async function smsRegister(options) {
|
|
|
23671
24122
|
clack29.log.info(`Your ${phoneDetails.type} number should be ready to use.`);
|
|
23672
24123
|
process.exit(0);
|
|
23673
24124
|
}
|
|
23674
|
-
console.log(
|
|
24125
|
+
console.log(pc32.bold("Toll-Free Registration Required"));
|
|
23675
24126
|
console.log("");
|
|
23676
24127
|
console.log(
|
|
23677
|
-
|
|
24128
|
+
pc32.dim("To send SMS at scale, you must register your toll-free number.")
|
|
23678
24129
|
);
|
|
23679
|
-
console.log(
|
|
24130
|
+
console.log(pc32.dim("This process typically takes 1-15 business days."));
|
|
23680
24131
|
console.log("");
|
|
23681
|
-
console.log(
|
|
23682
|
-
console.log(` ${
|
|
24132
|
+
console.log(pc32.bold("You'll need to provide:"));
|
|
24133
|
+
console.log(` ${pc32.dim("\u2022")} Business name and address`);
|
|
23683
24134
|
console.log(
|
|
23684
|
-
` ${
|
|
24135
|
+
` ${pc32.dim("\u2022")} Use case description (what messages you're sending)`
|
|
23685
24136
|
);
|
|
23686
|
-
console.log(` ${
|
|
23687
|
-
console.log(` ${
|
|
23688
|
-
console.log(` ${
|
|
24137
|
+
console.log(` ${pc32.dim("\u2022")} Sample messages (2-3 examples)`);
|
|
24138
|
+
console.log(` ${pc32.dim("\u2022")} How users opt-in to receive messages`);
|
|
24139
|
+
console.log(` ${pc32.dim("\u2022")} Expected monthly message volume`);
|
|
23689
24140
|
console.log("");
|
|
23690
24141
|
const openConsole = await clack29.confirm({
|
|
23691
24142
|
message: "Open AWS Console to start registration?",
|
|
@@ -23710,29 +24161,29 @@ async function smsRegister(options) {
|
|
|
23710
24161
|
} catch {
|
|
23711
24162
|
clack29.log.info("Open this URL in your browser:");
|
|
23712
24163
|
console.log(`
|
|
23713
|
-
${
|
|
24164
|
+
${pc32.cyan(consoleUrl)}
|
|
23714
24165
|
`);
|
|
23715
24166
|
}
|
|
23716
24167
|
}
|
|
23717
24168
|
console.log("");
|
|
23718
|
-
console.log(
|
|
24169
|
+
console.log(pc32.bold("Next Steps:"));
|
|
23719
24170
|
console.log(
|
|
23720
|
-
` 1. Click ${
|
|
24171
|
+
` 1. Click ${pc32.cyan("Create registration")} in the AWS Console`
|
|
23721
24172
|
);
|
|
23722
|
-
console.log(` 2. Select ${
|
|
24173
|
+
console.log(` 2. Select ${pc32.cyan("Toll-free number registration")}`);
|
|
23723
24174
|
console.log(" 3. Fill out the business information form");
|
|
23724
24175
|
console.log(" 4. Submit and wait for approval (1-15 business days)");
|
|
23725
24176
|
console.log("");
|
|
23726
24177
|
console.log(
|
|
23727
|
-
|
|
24178
|
+
pc32.dim("Once approved, run `wraps sms sync` to complete setup.")
|
|
23728
24179
|
);
|
|
23729
24180
|
} else {
|
|
23730
24181
|
const consoleUrl = `https://${region}.console.aws.amazon.com/sms-voice/home?region=${region}#/registrations`;
|
|
23731
24182
|
console.log("");
|
|
23732
24183
|
console.log("When you're ready, go to:");
|
|
23733
|
-
console.log(` ${
|
|
24184
|
+
console.log(` ${pc32.cyan(consoleUrl)}`);
|
|
23734
24185
|
}
|
|
23735
|
-
clack29.outro(
|
|
24186
|
+
clack29.outro(pc32.dim("Good luck with your registration!"));
|
|
23736
24187
|
}
|
|
23737
24188
|
|
|
23738
24189
|
// src/commands/sms/status.ts
|
|
@@ -23742,51 +24193,51 @@ init_aws();
|
|
|
23742
24193
|
init_fs();
|
|
23743
24194
|
init_metadata();
|
|
23744
24195
|
import * as clack30 from "@clack/prompts";
|
|
23745
|
-
import * as
|
|
23746
|
-
import
|
|
24196
|
+
import * as pulumi25 from "@pulumi/pulumi";
|
|
24197
|
+
import pc33 from "picocolors";
|
|
23747
24198
|
function displaySMSStatus(options) {
|
|
23748
24199
|
const lines = [];
|
|
23749
|
-
lines.push(
|
|
24200
|
+
lines.push(pc33.bold(pc33.green("SMS Infrastructure Active")));
|
|
23750
24201
|
lines.push("");
|
|
23751
|
-
lines.push(
|
|
24202
|
+
lines.push(pc33.bold("Phone Number"));
|
|
23752
24203
|
if (options.phoneNumber) {
|
|
23753
|
-
lines.push(` Number: ${
|
|
24204
|
+
lines.push(` Number: ${pc33.cyan(options.phoneNumber)}`);
|
|
23754
24205
|
} else {
|
|
23755
|
-
lines.push(` Number: ${
|
|
24206
|
+
lines.push(` Number: ${pc33.yellow("Provisioning...")}`);
|
|
23756
24207
|
}
|
|
23757
|
-
lines.push(` Type: ${
|
|
24208
|
+
lines.push(` Type: ${pc33.cyan(options.phoneNumberType || "simulator")}`);
|
|
23758
24209
|
lines.push("");
|
|
23759
|
-
lines.push(
|
|
23760
|
-
lines.push(` Region: ${
|
|
24210
|
+
lines.push(pc33.bold("Configuration"));
|
|
24211
|
+
lines.push(` Region: ${pc33.cyan(options.region)}`);
|
|
23761
24212
|
if (options.preset) {
|
|
23762
|
-
lines.push(` Preset: ${
|
|
24213
|
+
lines.push(` Preset: ${pc33.cyan(options.preset)}`);
|
|
23763
24214
|
}
|
|
23764
24215
|
if (options.configSetName) {
|
|
23765
|
-
lines.push(` Config Set: ${
|
|
24216
|
+
lines.push(` Config Set: ${pc33.cyan(options.configSetName)}`);
|
|
23766
24217
|
}
|
|
23767
24218
|
lines.push("");
|
|
23768
|
-
lines.push(
|
|
24219
|
+
lines.push(pc33.bold("Features"));
|
|
23769
24220
|
lines.push(
|
|
23770
|
-
` Event Tracking: ${options.eventTracking ?
|
|
24221
|
+
` Event Tracking: ${options.eventTracking ? pc33.green("Enabled") : pc33.dim("Disabled")}`
|
|
23771
24222
|
);
|
|
23772
24223
|
if (options.tableName) {
|
|
23773
|
-
lines.push(` Message History: ${
|
|
23774
|
-
lines.push(` Table: ${
|
|
24224
|
+
lines.push(` Message History: ${pc33.green("Enabled")}`);
|
|
24225
|
+
lines.push(` Table: ${pc33.dim(options.tableName)}`);
|
|
23775
24226
|
}
|
|
23776
24227
|
if (options.queueUrl) {
|
|
23777
|
-
lines.push(` Event Queue: ${
|
|
24228
|
+
lines.push(` Event Queue: ${pc33.green("Enabled")}`);
|
|
23778
24229
|
}
|
|
23779
24230
|
lines.push("");
|
|
23780
24231
|
if (options.roleArn) {
|
|
23781
|
-
lines.push(
|
|
23782
|
-
lines.push(` ${
|
|
24232
|
+
lines.push(pc33.bold("IAM Role"));
|
|
24233
|
+
lines.push(` ${pc33.dim(options.roleArn)}`);
|
|
23783
24234
|
}
|
|
23784
24235
|
clack30.note(lines.join("\n"), "SMS Status");
|
|
23785
24236
|
}
|
|
23786
24237
|
async function smsStatus(_options) {
|
|
23787
24238
|
const startTime = Date.now();
|
|
23788
24239
|
const progress = new DeploymentProgress();
|
|
23789
|
-
clack30.intro(
|
|
24240
|
+
clack30.intro(pc33.bold("Wraps SMS Status"));
|
|
23790
24241
|
const identity = await progress.execute(
|
|
23791
24242
|
"Loading SMS infrastructure status",
|
|
23792
24243
|
async () => validateAWSCredentials()
|
|
@@ -23798,7 +24249,7 @@ async function smsStatus(_options) {
|
|
|
23798
24249
|
clack30.log.error("No SMS infrastructure found");
|
|
23799
24250
|
console.log(
|
|
23800
24251
|
`
|
|
23801
|
-
Run ${
|
|
24252
|
+
Run ${pc33.cyan("wraps sms init")} to deploy SMS infrastructure.
|
|
23802
24253
|
`
|
|
23803
24254
|
);
|
|
23804
24255
|
process.exit(1);
|
|
@@ -23807,7 +24258,7 @@ Run ${pc32.cyan("wraps sms init")} to deploy SMS infrastructure.
|
|
|
23807
24258
|
try {
|
|
23808
24259
|
await ensurePulumiWorkDir();
|
|
23809
24260
|
const stackName = metadata.services.sms.pulumiStackName || `wraps-sms-${identity.accountId}-${region}`;
|
|
23810
|
-
const stack = await
|
|
24261
|
+
const stack = await pulumi25.automation.LocalWorkspace.selectStack({
|
|
23811
24262
|
stackName,
|
|
23812
24263
|
workDir: getPulumiWorkDir()
|
|
23813
24264
|
});
|
|
@@ -23829,25 +24280,25 @@ Run ${pc32.cyan("wraps sms init")} to deploy SMS infrastructure.
|
|
|
23829
24280
|
preset: metadata.services.sms.preset
|
|
23830
24281
|
});
|
|
23831
24282
|
console.log("");
|
|
23832
|
-
clack30.log.info(
|
|
24283
|
+
clack30.log.info(pc33.bold("Commands:"));
|
|
23833
24284
|
console.log(
|
|
23834
|
-
` ${
|
|
24285
|
+
` ${pc33.cyan("wraps sms test --to +1234567890")} - Send a test message`
|
|
23835
24286
|
);
|
|
23836
|
-
console.log(` ${
|
|
24287
|
+
console.log(` ${pc33.cyan("wraps sms destroy")} - Remove SMS infrastructure`);
|
|
23837
24288
|
trackCommand("sms:status", {
|
|
23838
24289
|
success: true,
|
|
23839
24290
|
phone_type: smsConfig?.phoneNumberType,
|
|
23840
24291
|
event_tracking: smsConfig?.eventTracking?.enabled,
|
|
23841
24292
|
duration_ms: Date.now() - startTime
|
|
23842
24293
|
});
|
|
23843
|
-
clack30.outro(
|
|
24294
|
+
clack30.outro(pc33.dim("SMS infrastructure is ready"));
|
|
23844
24295
|
}
|
|
23845
24296
|
|
|
23846
24297
|
// src/commands/sms/sync.ts
|
|
23847
24298
|
init_esm_shims();
|
|
23848
24299
|
import * as clack31 from "@clack/prompts";
|
|
23849
|
-
import * as
|
|
23850
|
-
import
|
|
24300
|
+
import * as pulumi26 from "@pulumi/pulumi";
|
|
24301
|
+
import pc34 from "picocolors";
|
|
23851
24302
|
init_events();
|
|
23852
24303
|
init_aws();
|
|
23853
24304
|
init_errors();
|
|
@@ -23855,7 +24306,7 @@ init_fs();
|
|
|
23855
24306
|
init_metadata();
|
|
23856
24307
|
async function smsSync(options) {
|
|
23857
24308
|
const startTime = Date.now();
|
|
23858
|
-
clack31.intro(
|
|
24309
|
+
clack31.intro(pc34.bold("Wraps SMS Infrastructure Sync"));
|
|
23859
24310
|
const progress = new DeploymentProgress();
|
|
23860
24311
|
const identity = await progress.execute(
|
|
23861
24312
|
"Validating AWS credentials",
|
|
@@ -23869,7 +24320,7 @@ async function smsSync(options) {
|
|
|
23869
24320
|
clack31.log.error("No SMS infrastructure found to sync");
|
|
23870
24321
|
console.log(
|
|
23871
24322
|
`
|
|
23872
|
-
Run ${
|
|
24323
|
+
Run ${pc34.cyan("wraps sms init")} to deploy SMS infrastructure first.
|
|
23873
24324
|
`
|
|
23874
24325
|
);
|
|
23875
24326
|
process.exit(1);
|
|
@@ -23878,10 +24329,10 @@ Run ${pc33.cyan("wraps sms init")} to deploy SMS infrastructure first.
|
|
|
23878
24329
|
const storedStackName = smsService.pulumiStackName;
|
|
23879
24330
|
progress.info("Found existing SMS configuration");
|
|
23880
24331
|
progress.info(
|
|
23881
|
-
`Phone type: ${
|
|
24332
|
+
`Phone type: ${pc34.cyan(smsConfig.phoneNumberType || "simulator")}`
|
|
23882
24333
|
);
|
|
23883
24334
|
progress.info(
|
|
23884
|
-
`Event tracking: ${
|
|
24335
|
+
`Event tracking: ${pc34.cyan(smsConfig.eventTracking?.enabled ? "enabled" : "disabled")}`
|
|
23885
24336
|
);
|
|
23886
24337
|
if (!options.yes) {
|
|
23887
24338
|
const confirmed = await clack31.confirm({
|
|
@@ -23904,7 +24355,7 @@ Run ${pc33.cyan("wraps sms init")} to deploy SMS infrastructure first.
|
|
|
23904
24355
|
outputs = await progress.execute("Syncing SMS infrastructure", async () => {
|
|
23905
24356
|
await ensurePulumiWorkDir();
|
|
23906
24357
|
const stackName = storedStackName || `wraps-sms-${identity.accountId}-${region}`;
|
|
23907
|
-
const stack = await
|
|
24358
|
+
const stack = await pulumi26.automation.LocalWorkspace.createOrSelectStack(
|
|
23908
24359
|
{
|
|
23909
24360
|
stackName,
|
|
23910
24361
|
projectName: "wraps-sms",
|
|
@@ -24003,7 +24454,7 @@ Run ${pc33.cyan("wraps sms init")} to deploy SMS infrastructure first.
|
|
|
24003
24454
|
}
|
|
24004
24455
|
progress.stop();
|
|
24005
24456
|
console.log("\n");
|
|
24006
|
-
clack31.log.success(
|
|
24457
|
+
clack31.log.success(pc34.green("SMS infrastructure synced successfully!"));
|
|
24007
24458
|
const changes = [];
|
|
24008
24459
|
if (outputs.lambdaFunctions?.length) {
|
|
24009
24460
|
changes.push("Lambda functions updated");
|
|
@@ -24011,13 +24462,13 @@ Run ${pc33.cyan("wraps sms init")} to deploy SMS infrastructure first.
|
|
|
24011
24462
|
changes.push("SDK resources verified");
|
|
24012
24463
|
console.log("");
|
|
24013
24464
|
for (const change of changes) {
|
|
24014
|
-
console.log(` ${
|
|
24465
|
+
console.log(` ${pc34.green("\u2713")} ${change}`);
|
|
24015
24466
|
}
|
|
24016
24467
|
trackCommand("sms:sync", {
|
|
24017
24468
|
success: true,
|
|
24018
24469
|
duration_ms: Date.now() - startTime
|
|
24019
24470
|
});
|
|
24020
|
-
clack31.outro(
|
|
24471
|
+
clack31.outro(pc34.green("Sync complete!"));
|
|
24021
24472
|
}
|
|
24022
24473
|
|
|
24023
24474
|
// src/commands/sms/test.ts
|
|
@@ -24030,7 +24481,7 @@ import {
|
|
|
24030
24481
|
SendTextMessageCommand
|
|
24031
24482
|
} from "@aws-sdk/client-pinpoint-sms-voice-v2";
|
|
24032
24483
|
import * as clack32 from "@clack/prompts";
|
|
24033
|
-
import
|
|
24484
|
+
import pc35 from "picocolors";
|
|
24034
24485
|
function isValidPhoneNumber(phone) {
|
|
24035
24486
|
return /^\+[1-9]\d{1,14}$/.test(phone);
|
|
24036
24487
|
}
|
|
@@ -24047,7 +24498,7 @@ var SIMULATOR_DESTINATIONS = [
|
|
|
24047
24498
|
async function smsTest(options) {
|
|
24048
24499
|
const startTime = Date.now();
|
|
24049
24500
|
const progress = new DeploymentProgress();
|
|
24050
|
-
clack32.intro(
|
|
24501
|
+
clack32.intro(pc35.bold("Wraps SMS Test"));
|
|
24051
24502
|
const identity = await progress.execute(
|
|
24052
24503
|
"Validating AWS credentials",
|
|
24053
24504
|
async () => validateAWSCredentials()
|
|
@@ -24059,7 +24510,7 @@ async function smsTest(options) {
|
|
|
24059
24510
|
clack32.log.error("No SMS infrastructure found");
|
|
24060
24511
|
console.log(
|
|
24061
24512
|
`
|
|
24062
|
-
Run ${
|
|
24513
|
+
Run ${pc35.cyan("wraps sms init")} to deploy SMS infrastructure.
|
|
24063
24514
|
`
|
|
24064
24515
|
);
|
|
24065
24516
|
process.exit(1);
|
|
@@ -24166,16 +24617,16 @@ Run ${pc34.cyan("wraps sms init")} to deploy SMS infrastructure.
|
|
|
24166
24617
|
);
|
|
24167
24618
|
progress.stop();
|
|
24168
24619
|
console.log("\n");
|
|
24169
|
-
clack32.log.success(
|
|
24620
|
+
clack32.log.success(pc35.green("Test SMS sent successfully!"));
|
|
24170
24621
|
console.log("");
|
|
24171
24622
|
clack32.note(
|
|
24172
24623
|
[
|
|
24173
|
-
`${
|
|
24174
|
-
`${
|
|
24175
|
-
`${
|
|
24176
|
-
`${
|
|
24624
|
+
`${pc35.bold("Message ID:")} ${pc35.cyan(messageId || "unknown")}`,
|
|
24625
|
+
`${pc35.bold("To:")} ${pc35.cyan(toNumber)}`,
|
|
24626
|
+
`${pc35.bold("Message:")} ${message}`,
|
|
24627
|
+
`${pc35.bold("Type:")} ${pc35.cyan(smsConfig?.phoneNumberType || "simulator")}`,
|
|
24177
24628
|
"",
|
|
24178
|
-
|
|
24629
|
+
pc35.dim(
|
|
24179
24630
|
smsConfig?.phoneNumberType === "simulator" ? "Note: Simulator messages are not actually delivered" : "Check your phone for the message!"
|
|
24180
24631
|
)
|
|
24181
24632
|
].join("\n"),
|
|
@@ -24184,7 +24635,7 @@ Run ${pc34.cyan("wraps sms init")} to deploy SMS infrastructure.
|
|
|
24184
24635
|
if (smsConfig?.eventTracking?.enabled) {
|
|
24185
24636
|
console.log("");
|
|
24186
24637
|
clack32.log.info(
|
|
24187
|
-
|
|
24638
|
+
pc35.dim("Event tracking is enabled. Check DynamoDB for delivery status.")
|
|
24188
24639
|
);
|
|
24189
24640
|
}
|
|
24190
24641
|
trackCommand("sms:test", {
|
|
@@ -24193,7 +24644,7 @@ Run ${pc34.cyan("wraps sms init")} to deploy SMS infrastructure.
|
|
|
24193
24644
|
message_length: message?.length,
|
|
24194
24645
|
duration_ms: Date.now() - startTime
|
|
24195
24646
|
});
|
|
24196
|
-
clack32.outro(
|
|
24647
|
+
clack32.outro(pc35.green("Test complete!"));
|
|
24197
24648
|
} catch (error) {
|
|
24198
24649
|
progress.stop();
|
|
24199
24650
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
@@ -24207,7 +24658,7 @@ Run ${pc34.cyan("wraps sms init")} to deploy SMS infrastructure.
|
|
|
24207
24658
|
clack32.log.error("Toll-free number registration is not complete");
|
|
24208
24659
|
console.log(
|
|
24209
24660
|
`
|
|
24210
|
-
Run ${
|
|
24661
|
+
Run ${pc35.cyan("wraps sms register")} to complete registration.
|
|
24211
24662
|
`
|
|
24212
24663
|
);
|
|
24213
24664
|
} else if (errorMessage.includes("opt-out")) {
|
|
@@ -24225,8 +24676,8 @@ Run ${pc34.cyan("wraps sms register")} to complete registration.
|
|
|
24225
24676
|
// src/commands/sms/upgrade.ts
|
|
24226
24677
|
init_esm_shims();
|
|
24227
24678
|
import * as clack33 from "@clack/prompts";
|
|
24228
|
-
import * as
|
|
24229
|
-
import
|
|
24679
|
+
import * as pulumi27 from "@pulumi/pulumi";
|
|
24680
|
+
import pc36 from "picocolors";
|
|
24230
24681
|
init_events();
|
|
24231
24682
|
init_aws();
|
|
24232
24683
|
init_errors();
|
|
@@ -24236,7 +24687,7 @@ init_prompts();
|
|
|
24236
24687
|
async function smsUpgrade(options) {
|
|
24237
24688
|
const startTime = Date.now();
|
|
24238
24689
|
let upgradeAction = "";
|
|
24239
|
-
clack33.intro(
|
|
24690
|
+
clack33.intro(pc36.bold("Wraps SMS Upgrade - Enhance Your SMS Infrastructure"));
|
|
24240
24691
|
const progress = new DeploymentProgress();
|
|
24241
24692
|
const wasAutoInstalled = await progress.execute(
|
|
24242
24693
|
"Checking Pulumi CLI installation",
|
|
@@ -24249,7 +24700,7 @@ async function smsUpgrade(options) {
|
|
|
24249
24700
|
"Validating AWS credentials",
|
|
24250
24701
|
async () => validateAWSCredentials()
|
|
24251
24702
|
);
|
|
24252
|
-
progress.info(`Connected to AWS account: ${
|
|
24703
|
+
progress.info(`Connected to AWS account: ${pc36.cyan(identity.accountId)}`);
|
|
24253
24704
|
let region = options.region;
|
|
24254
24705
|
if (!region) {
|
|
24255
24706
|
const defaultRegion = await getAWSRegion();
|
|
@@ -24258,34 +24709,34 @@ async function smsUpgrade(options) {
|
|
|
24258
24709
|
const metadata = await loadConnectionMetadata(identity.accountId, region);
|
|
24259
24710
|
if (!metadata) {
|
|
24260
24711
|
clack33.log.error(
|
|
24261
|
-
`No Wraps connection found for account ${
|
|
24712
|
+
`No Wraps connection found for account ${pc36.cyan(identity.accountId)} in region ${pc36.cyan(region)}`
|
|
24262
24713
|
);
|
|
24263
24714
|
clack33.log.info(
|
|
24264
|
-
`Use ${
|
|
24715
|
+
`Use ${pc36.cyan("wraps sms init")} to create new infrastructure.`
|
|
24265
24716
|
);
|
|
24266
24717
|
process.exit(1);
|
|
24267
24718
|
}
|
|
24268
24719
|
if (!metadata.services.sms) {
|
|
24269
24720
|
clack33.log.error("No SMS infrastructure found");
|
|
24270
24721
|
clack33.log.info(
|
|
24271
|
-
`Use ${
|
|
24722
|
+
`Use ${pc36.cyan("wraps sms init")} to deploy SMS infrastructure.`
|
|
24272
24723
|
);
|
|
24273
24724
|
process.exit(1);
|
|
24274
24725
|
}
|
|
24275
24726
|
progress.info(`Found existing connection created: ${metadata.timestamp}`);
|
|
24276
24727
|
console.log(`
|
|
24277
|
-
${
|
|
24728
|
+
${pc36.bold("Current Configuration:")}
|
|
24278
24729
|
`);
|
|
24279
24730
|
if (metadata.services.sms.preset) {
|
|
24280
|
-
console.log(` Preset: ${
|
|
24731
|
+
console.log(` Preset: ${pc36.cyan(metadata.services.sms.preset)}`);
|
|
24281
24732
|
} else {
|
|
24282
|
-
console.log(` Preset: ${
|
|
24733
|
+
console.log(` Preset: ${pc36.cyan("custom")}`);
|
|
24283
24734
|
}
|
|
24284
24735
|
const config2 = metadata.services.sms.config;
|
|
24285
24736
|
if (!config2) {
|
|
24286
24737
|
clack33.log.error("No SMS configuration found in metadata");
|
|
24287
24738
|
clack33.log.info(
|
|
24288
|
-
`Use ${
|
|
24739
|
+
`Use ${pc36.cyan("wraps sms init")} to create new infrastructure.`
|
|
24289
24740
|
);
|
|
24290
24741
|
process.exit(1);
|
|
24291
24742
|
}
|
|
@@ -24297,45 +24748,45 @@ ${pc35.bold("Current Configuration:")}
|
|
|
24297
24748
|
"short-code": "Short code ($995+/mo, 100+ MPS)"
|
|
24298
24749
|
};
|
|
24299
24750
|
console.log(
|
|
24300
|
-
` Phone Type: ${
|
|
24751
|
+
` Phone Type: ${pc36.cyan(phoneTypeLabels2[config2.phoneNumberType] || config2.phoneNumberType)}`
|
|
24301
24752
|
);
|
|
24302
24753
|
}
|
|
24303
24754
|
if (config2.tracking?.enabled) {
|
|
24304
|
-
console.log(` ${
|
|
24755
|
+
console.log(` ${pc36.green("\u2713")} Delivery Tracking`);
|
|
24305
24756
|
if (config2.tracking.linkTracking) {
|
|
24306
|
-
console.log(` ${
|
|
24757
|
+
console.log(` ${pc36.dim("\u2514\u2500")} Link click tracking enabled`);
|
|
24307
24758
|
}
|
|
24308
24759
|
}
|
|
24309
24760
|
if (config2.eventTracking?.enabled) {
|
|
24310
|
-
console.log(` ${
|
|
24761
|
+
console.log(` ${pc36.green("\u2713")} Event Tracking (SNS)`);
|
|
24311
24762
|
if (config2.eventTracking.dynamoDBHistory) {
|
|
24312
24763
|
console.log(
|
|
24313
|
-
` ${
|
|
24764
|
+
` ${pc36.dim("\u2514\u2500")} Message History: ${pc36.cyan(config2.eventTracking.archiveRetention || "90days")}`
|
|
24314
24765
|
);
|
|
24315
24766
|
}
|
|
24316
24767
|
}
|
|
24317
24768
|
if (config2.messageArchiving?.enabled) {
|
|
24318
24769
|
console.log(
|
|
24319
|
-
` ${
|
|
24770
|
+
` ${pc36.green("\u2713")} Message Archiving (${config2.messageArchiving.retention})`
|
|
24320
24771
|
);
|
|
24321
24772
|
}
|
|
24322
24773
|
if (config2.optOutManagement) {
|
|
24323
|
-
console.log(` ${
|
|
24774
|
+
console.log(` ${pc36.green("\u2713")} Opt-out Management`);
|
|
24324
24775
|
}
|
|
24325
24776
|
if (config2.protectConfiguration?.enabled) {
|
|
24326
24777
|
const countries = config2.protectConfiguration.allowedCountries?.join(", ") || "US";
|
|
24327
|
-
console.log(` ${
|
|
24328
|
-
console.log(` ${
|
|
24778
|
+
console.log(` ${pc36.green("\u2713")} Fraud Protection`);
|
|
24779
|
+
console.log(` ${pc36.dim("\u2514\u2500")} Allowed countries: ${pc36.cyan(countries)}`);
|
|
24329
24780
|
if (config2.protectConfiguration.aitFiltering) {
|
|
24330
|
-
console.log(` ${
|
|
24781
|
+
console.log(` ${pc36.dim("\u2514\u2500")} AIT filtering: ${pc36.cyan("enabled")}`);
|
|
24331
24782
|
}
|
|
24332
24783
|
} else {
|
|
24333
|
-
console.log(` ${
|
|
24784
|
+
console.log(` ${pc36.dim("\u25CB")} Fraud Protection (not configured)`);
|
|
24334
24785
|
}
|
|
24335
24786
|
const currentCostData = calculateSMSCosts(config2, 1e4);
|
|
24336
24787
|
console.log(
|
|
24337
24788
|
`
|
|
24338
|
-
Estimated Cost: ${
|
|
24789
|
+
Estimated Cost: ${pc36.cyan(`~${formatCost3(currentCostData.total.monthly)}/mo`)}`
|
|
24339
24790
|
);
|
|
24340
24791
|
console.log("");
|
|
24341
24792
|
const phoneTypeLabels = {
|
|
@@ -24442,22 +24893,22 @@ ${pc35.bold("Current Configuration:")}
|
|
|
24442
24893
|
if (selectedType === "toll-free") {
|
|
24443
24894
|
console.log(
|
|
24444
24895
|
`
|
|
24445
|
-
${
|
|
24896
|
+
${pc36.yellow("\u26A0")} ${pc36.bold("Toll-free Registration Required")}
|
|
24446
24897
|
`
|
|
24447
24898
|
);
|
|
24448
24899
|
console.log(
|
|
24449
|
-
|
|
24900
|
+
pc36.dim("Toll-free numbers require carrier registration before")
|
|
24450
24901
|
);
|
|
24451
24902
|
console.log(
|
|
24452
|
-
|
|
24903
|
+
pc36.dim("they can send messages at scale. After deployment:\n")
|
|
24453
24904
|
);
|
|
24454
24905
|
console.log(
|
|
24455
|
-
` 1. Run ${
|
|
24906
|
+
` 1. Run ${pc36.cyan("wraps sms register")} to start registration`
|
|
24456
24907
|
);
|
|
24457
24908
|
console.log(" 2. Submit your business use case information");
|
|
24458
24909
|
console.log(" 3. Wait for carrier verification (1-5 business days)");
|
|
24459
24910
|
console.log(
|
|
24460
|
-
|
|
24911
|
+
pc36.dim("\nUntil verified, sending is limited to low volume.\n")
|
|
24461
24912
|
);
|
|
24462
24913
|
const confirmTollFree = await clack33.confirm({
|
|
24463
24914
|
message: "Continue with toll-free number request?",
|
|
@@ -24471,10 +24922,10 @@ ${pc35.yellow("\u26A0")} ${pc35.bold("Toll-free Registration Required")}
|
|
|
24471
24922
|
if (selectedType === "10dlc") {
|
|
24472
24923
|
console.log(
|
|
24473
24924
|
`
|
|
24474
|
-
${
|
|
24925
|
+
${pc36.yellow("\u26A0")} ${pc36.bold("10DLC Campaign Registration Required")}
|
|
24475
24926
|
`
|
|
24476
24927
|
);
|
|
24477
|
-
console.log(
|
|
24928
|
+
console.log(pc36.dim("10DLC requires brand and campaign registration:"));
|
|
24478
24929
|
console.log(" \u2022 Brand registration: one-time $4 fee");
|
|
24479
24930
|
console.log(" \u2022 Campaign registration: $15/mo per campaign");
|
|
24480
24931
|
console.log(" \u2022 Verification takes 1-7 business days");
|
|
@@ -24707,12 +25158,12 @@ ${pc35.yellow("\u26A0")} ${pc35.bold("10DLC Campaign Registration Required")}
|
|
|
24707
25158
|
const enableLinkTracking = !config2.tracking?.linkTracking;
|
|
24708
25159
|
if (enableLinkTracking) {
|
|
24709
25160
|
clack33.log.info(
|
|
24710
|
-
|
|
25161
|
+
pc36.dim(
|
|
24711
25162
|
"Link tracking will track clicks on URLs in your SMS messages."
|
|
24712
25163
|
)
|
|
24713
25164
|
);
|
|
24714
25165
|
clack33.log.info(
|
|
24715
|
-
|
|
25166
|
+
pc36.dim("URLs will be rewritten to go through a tracking endpoint.")
|
|
24716
25167
|
);
|
|
24717
25168
|
}
|
|
24718
25169
|
const confirmed = await clack33.confirm({
|
|
@@ -24925,18 +25376,18 @@ ${pc35.yellow("\u26A0")} ${pc35.bold("10DLC Campaign Registration Required")}
|
|
|
24925
25376
|
const newCostData = calculateSMSCosts(updatedConfig, 1e4);
|
|
24926
25377
|
const costDiff = newCostData.total.monthly - currentCostData.total.monthly;
|
|
24927
25378
|
console.log(`
|
|
24928
|
-
${
|
|
25379
|
+
${pc36.bold("Cost Impact:")}`);
|
|
24929
25380
|
console.log(
|
|
24930
|
-
` Current: ${
|
|
25381
|
+
` Current: ${pc36.cyan(`${formatCost3(currentCostData.total.monthly)}/mo`)}`
|
|
24931
25382
|
);
|
|
24932
25383
|
console.log(
|
|
24933
|
-
` New: ${
|
|
25384
|
+
` New: ${pc36.cyan(`${formatCost3(newCostData.total.monthly)}/mo`)}`
|
|
24934
25385
|
);
|
|
24935
25386
|
if (costDiff > 0) {
|
|
24936
|
-
console.log(` Change: ${
|
|
25387
|
+
console.log(` Change: ${pc36.yellow(`+${formatCost3(costDiff)}/mo`)}`);
|
|
24937
25388
|
} else if (costDiff < 0) {
|
|
24938
25389
|
console.log(
|
|
24939
|
-
` Change: ${
|
|
25390
|
+
` Change: ${pc36.green(`-${formatCost3(Math.abs(costDiff))}/mo`)}`
|
|
24940
25391
|
);
|
|
24941
25392
|
}
|
|
24942
25393
|
console.log("");
|
|
@@ -24968,7 +25419,7 @@ ${pc35.bold("Cost Impact:")}`);
|
|
|
24968
25419
|
"Updating SMS infrastructure (this may take 2-3 minutes)",
|
|
24969
25420
|
async () => {
|
|
24970
25421
|
await ensurePulumiWorkDir();
|
|
24971
|
-
const stack = await
|
|
25422
|
+
const stack = await pulumi27.automation.LocalWorkspace.createOrSelectStack(
|
|
24972
25423
|
{
|
|
24973
25424
|
stackName: metadata.services.sms?.pulumiStackName || `wraps-sms-${identity.accountId}-${region}`,
|
|
24974
25425
|
projectName: "wraps-sms",
|
|
@@ -25069,43 +25520,43 @@ ${pc35.bold("Cost Impact:")}`);
|
|
|
25069
25520
|
await saveConnectionMetadata(metadata);
|
|
25070
25521
|
progress.info("Connection metadata updated");
|
|
25071
25522
|
console.log("\n");
|
|
25072
|
-
clack33.log.success(
|
|
25523
|
+
clack33.log.success(pc36.green(pc36.bold("SMS infrastructure upgraded!")));
|
|
25073
25524
|
console.log("\n");
|
|
25074
25525
|
clack33.note(
|
|
25075
25526
|
[
|
|
25076
|
-
`${
|
|
25077
|
-
`${
|
|
25078
|
-
`${
|
|
25079
|
-
`${
|
|
25080
|
-
outputs.tableName ? `${
|
|
25527
|
+
`${pc36.bold("Phone Number:")} ${pc36.cyan(outputs.phoneNumber || "Provisioning...")}`,
|
|
25528
|
+
`${pc36.bold("Phone Type:")} ${pc36.cyan(updatedConfig.phoneNumberType || "simulator")}`,
|
|
25529
|
+
`${pc36.bold("Config Set:")} ${pc36.cyan(outputs.configSetName || "wraps-sms-config")}`,
|
|
25530
|
+
`${pc36.bold("Region:")} ${pc36.cyan(outputs.region)}`,
|
|
25531
|
+
outputs.tableName ? `${pc36.bold("History Table:")} ${pc36.cyan(outputs.tableName)}` : "",
|
|
25081
25532
|
"",
|
|
25082
|
-
|
|
25083
|
-
|
|
25533
|
+
pc36.dim("IAM Role:"),
|
|
25534
|
+
pc36.dim(` ${outputs.roleArn}`)
|
|
25084
25535
|
].filter(Boolean).join("\n"),
|
|
25085
25536
|
"SMS Infrastructure"
|
|
25086
25537
|
);
|
|
25087
25538
|
console.log(`
|
|
25088
|
-
${
|
|
25539
|
+
${pc36.green("\u2713")} ${pc36.bold("Upgrade complete!")}
|
|
25089
25540
|
`);
|
|
25090
25541
|
if (upgradeAction === "phone-number") {
|
|
25091
25542
|
console.log(
|
|
25092
|
-
`Upgraded to ${
|
|
25543
|
+
`Upgraded to ${pc36.cyan(updatedConfig.phoneNumberType)} number (${pc36.green(`${formatCost3(newCostData.total.monthly)}/mo`)})
|
|
25093
25544
|
`
|
|
25094
25545
|
);
|
|
25095
25546
|
if (updatedConfig.phoneNumberType === "toll-free") {
|
|
25096
|
-
console.log(`${
|
|
25547
|
+
console.log(`${pc36.bold("Next Steps:")}`);
|
|
25097
25548
|
console.log(
|
|
25098
|
-
` 1. Run ${
|
|
25549
|
+
` 1. Run ${pc36.cyan("wraps sms register")} to start toll-free registration`
|
|
25099
25550
|
);
|
|
25100
25551
|
console.log(" 2. Submit your business information and use case");
|
|
25101
25552
|
console.log(" 3. Wait for carrier verification (1-5 business days)");
|
|
25102
25553
|
console.log("");
|
|
25103
25554
|
console.log(
|
|
25104
|
-
|
|
25555
|
+
pc36.dim("Until verified, your number can only send limited messages.")
|
|
25105
25556
|
);
|
|
25106
25557
|
console.log("");
|
|
25107
25558
|
} else if (updatedConfig.phoneNumberType === "10dlc") {
|
|
25108
|
-
console.log(`${
|
|
25559
|
+
console.log(`${pc36.bold("Next Steps:")}`);
|
|
25109
25560
|
console.log(" 1. Register your brand in the AWS Console");
|
|
25110
25561
|
console.log(" 2. Create a 10DLC campaign for your use case");
|
|
25111
25562
|
console.log(" 3. Wait for campaign approval (1-7 business days)");
|
|
@@ -25113,16 +25564,16 @@ ${pc35.green("\u2713")} ${pc35.bold("Upgrade complete!")}
|
|
|
25113
25564
|
}
|
|
25114
25565
|
} else if (upgradeAction === "preset" && newPreset) {
|
|
25115
25566
|
console.log(
|
|
25116
|
-
`Upgraded to ${
|
|
25567
|
+
`Upgraded to ${pc36.cyan(newPreset)} preset (${pc36.green(`${formatCost3(newCostData.total.monthly)}/mo`)})
|
|
25117
25568
|
`
|
|
25118
25569
|
);
|
|
25119
25570
|
} else {
|
|
25120
25571
|
console.log(
|
|
25121
|
-
`Updated configuration (${
|
|
25572
|
+
`Updated configuration (${pc36.green(`${formatCost3(newCostData.total.monthly)}/mo`)})
|
|
25122
25573
|
`
|
|
25123
25574
|
);
|
|
25124
25575
|
}
|
|
25125
|
-
console.log(
|
|
25576
|
+
console.log(pc36.dim(getSMSCostSummary(updatedConfig, 1e4)));
|
|
25126
25577
|
const enabledFeatures = [];
|
|
25127
25578
|
if (updatedConfig.tracking?.enabled) {
|
|
25128
25579
|
enabledFeatures.push("tracking");
|
|
@@ -25146,7 +25597,7 @@ ${pc35.green("\u2713")} ${pc35.bold("Upgrade complete!")}
|
|
|
25146
25597
|
action: typeof upgradeAction === "string" ? upgradeAction : void 0,
|
|
25147
25598
|
duration_ms: Date.now() - startTime
|
|
25148
25599
|
});
|
|
25149
|
-
clack33.outro(
|
|
25600
|
+
clack33.outro(pc36.green("Upgrade complete!"));
|
|
25150
25601
|
}
|
|
25151
25602
|
|
|
25152
25603
|
// src/commands/sms/verify-number.ts
|
|
@@ -25163,14 +25614,14 @@ import {
|
|
|
25163
25614
|
VerifyDestinationNumberCommand
|
|
25164
25615
|
} from "@aws-sdk/client-pinpoint-sms-voice-v2";
|
|
25165
25616
|
import * as clack34 from "@clack/prompts";
|
|
25166
|
-
import
|
|
25617
|
+
import pc37 from "picocolors";
|
|
25167
25618
|
function isValidPhoneNumber2(phone) {
|
|
25168
25619
|
return /^\+[1-9]\d{1,14}$/.test(phone);
|
|
25169
25620
|
}
|
|
25170
25621
|
async function smsVerifyNumber(options) {
|
|
25171
25622
|
const startTime = Date.now();
|
|
25172
25623
|
const progress = new DeploymentProgress();
|
|
25173
|
-
clack34.intro(
|
|
25624
|
+
clack34.intro(pc37.bold("Wraps SMS - Verify Destination Number"));
|
|
25174
25625
|
const identity = await progress.execute(
|
|
25175
25626
|
"Validating AWS credentials",
|
|
25176
25627
|
async () => validateAWSCredentials()
|
|
@@ -25182,7 +25633,7 @@ async function smsVerifyNumber(options) {
|
|
|
25182
25633
|
clack34.log.error("No SMS infrastructure found");
|
|
25183
25634
|
console.log(
|
|
25184
25635
|
`
|
|
25185
|
-
Run ${
|
|
25636
|
+
Run ${pc37.cyan("wraps sms init")} to deploy SMS infrastructure.
|
|
25186
25637
|
`
|
|
25187
25638
|
);
|
|
25188
25639
|
process.exit(1);
|
|
@@ -25199,16 +25650,16 @@ Run ${pc36.cyan("wraps sms init")} to deploy SMS infrastructure.
|
|
|
25199
25650
|
clack34.log.info("No verified destination numbers found");
|
|
25200
25651
|
console.log(
|
|
25201
25652
|
`
|
|
25202
|
-
Run ${
|
|
25653
|
+
Run ${pc37.cyan("wraps sms verify-number")} to verify a number.
|
|
25203
25654
|
`
|
|
25204
25655
|
);
|
|
25205
25656
|
} else {
|
|
25206
25657
|
console.log("\n");
|
|
25207
|
-
clack34.log.info(
|
|
25658
|
+
clack34.log.info(pc37.bold("Verified Destination Numbers:"));
|
|
25208
25659
|
console.log("");
|
|
25209
25660
|
for (const num of response.VerifiedDestinationNumbers) {
|
|
25210
|
-
const status2 = num.Status === "VERIFIED" ?
|
|
25211
|
-
console.log(` ${
|
|
25661
|
+
const status2 = num.Status === "VERIFIED" ? pc37.green("\u2713 Verified") : pc37.yellow("\u29D6 Pending");
|
|
25662
|
+
console.log(` ${pc37.cyan(num.DestinationPhoneNumber)} - ${status2}`);
|
|
25212
25663
|
}
|
|
25213
25664
|
console.log("");
|
|
25214
25665
|
}
|
|
@@ -25217,7 +25668,7 @@ Run ${pc36.cyan("wraps sms verify-number")} to verify a number.
|
|
|
25217
25668
|
count: response.VerifiedDestinationNumbers?.length || 0,
|
|
25218
25669
|
duration_ms: Date.now() - startTime
|
|
25219
25670
|
});
|
|
25220
|
-
clack34.outro(
|
|
25671
|
+
clack34.outro(pc37.green("Done!"));
|
|
25221
25672
|
return;
|
|
25222
25673
|
} catch (error) {
|
|
25223
25674
|
progress.stop();
|
|
@@ -25236,7 +25687,7 @@ Run ${pc36.cyan("wraps sms verify-number")} to verify a number.
|
|
|
25236
25687
|
clack34.log.error("Phone number is required for deletion");
|
|
25237
25688
|
console.log(
|
|
25238
25689
|
`
|
|
25239
|
-
Usage: ${
|
|
25690
|
+
Usage: ${pc37.cyan("wraps sms verify-number --delete --phone-number +14155551234")}
|
|
25240
25691
|
`
|
|
25241
25692
|
);
|
|
25242
25693
|
process.exit(1);
|
|
@@ -25261,12 +25712,12 @@ Usage: ${pc36.cyan("wraps sms verify-number --delete --phone-number +14155551234
|
|
|
25261
25712
|
);
|
|
25262
25713
|
});
|
|
25263
25714
|
progress.stop();
|
|
25264
|
-
clack34.log.success(`Removed ${
|
|
25715
|
+
clack34.log.success(`Removed ${pc37.cyan(phoneNumber2)} from verified list`);
|
|
25265
25716
|
trackCommand("sms:verify-number:delete", {
|
|
25266
25717
|
success: true,
|
|
25267
25718
|
duration_ms: Date.now() - startTime
|
|
25268
25719
|
});
|
|
25269
|
-
clack34.outro(
|
|
25720
|
+
clack34.outro(pc37.green("Done!"));
|
|
25270
25721
|
return;
|
|
25271
25722
|
} catch (error) {
|
|
25272
25723
|
progress.stop();
|
|
@@ -25331,17 +25782,17 @@ Usage: ${pc36.cyan("wraps sms verify-number --delete --phone-number +14155551234
|
|
|
25331
25782
|
progress.stop();
|
|
25332
25783
|
console.log("\n");
|
|
25333
25784
|
clack34.log.success(
|
|
25334
|
-
|
|
25785
|
+
pc37.green(`Phone number ${pc37.cyan(phoneNumber)} verified!`)
|
|
25335
25786
|
);
|
|
25336
25787
|
console.log("");
|
|
25337
25788
|
console.log(
|
|
25338
|
-
`You can now send test messages to this number with ${
|
|
25789
|
+
`You can now send test messages to this number with ${pc37.cyan("wraps sms test")}`
|
|
25339
25790
|
);
|
|
25340
25791
|
trackCommand("sms:verify-number:confirm", {
|
|
25341
25792
|
success: true,
|
|
25342
25793
|
duration_ms: Date.now() - startTime
|
|
25343
25794
|
});
|
|
25344
|
-
clack34.outro(
|
|
25795
|
+
clack34.outro(pc37.green("Verification complete!"));
|
|
25345
25796
|
return;
|
|
25346
25797
|
} catch (error) {
|
|
25347
25798
|
progress.stop();
|
|
@@ -25350,7 +25801,7 @@ Usage: ${pc36.cyan("wraps sms verify-number --delete --phone-number +14155551234
|
|
|
25350
25801
|
clack34.log.error("Invalid verification code. Please try again.");
|
|
25351
25802
|
console.log(
|
|
25352
25803
|
`
|
|
25353
|
-
Run ${
|
|
25804
|
+
Run ${pc37.cyan(`wraps sms verify-number --phone-number ${phoneNumber} --resend`)} to get a new code.
|
|
25354
25805
|
`
|
|
25355
25806
|
);
|
|
25356
25807
|
} else {
|
|
@@ -25386,17 +25837,17 @@ Run ${pc36.cyan(`wraps sms verify-number --phone-number ${phoneNumber} --resend`
|
|
|
25386
25837
|
);
|
|
25387
25838
|
});
|
|
25388
25839
|
progress.stop();
|
|
25389
|
-
clack34.log.success(`Verification code resent to ${
|
|
25840
|
+
clack34.log.success(`Verification code resent to ${pc37.cyan(phoneNumber)}`);
|
|
25390
25841
|
console.log("");
|
|
25391
25842
|
console.log(
|
|
25392
25843
|
`Once you receive the code, run:
|
|
25393
|
-
${
|
|
25844
|
+
${pc37.cyan(`wraps sms verify-number --phone-number ${phoneNumber} --code YOUR_CODE`)}`
|
|
25394
25845
|
);
|
|
25395
25846
|
trackCommand("sms:verify-number:resend", {
|
|
25396
25847
|
success: true,
|
|
25397
25848
|
duration_ms: Date.now() - startTime
|
|
25398
25849
|
});
|
|
25399
|
-
clack34.outro(
|
|
25850
|
+
clack34.outro(pc37.green("Code sent!"));
|
|
25400
25851
|
return;
|
|
25401
25852
|
} catch (error) {
|
|
25402
25853
|
progress.stop();
|
|
@@ -25418,9 +25869,9 @@ Run ${pc36.cyan(`wraps sms verify-number --phone-number ${phoneNumber} --resend`
|
|
|
25418
25869
|
if (existingNumber?.Status === "VERIFIED") {
|
|
25419
25870
|
progress.stop();
|
|
25420
25871
|
clack34.log.info(
|
|
25421
|
-
`Number ${
|
|
25872
|
+
`Number ${pc37.cyan(phoneNumber)} is already verified and ready to use!`
|
|
25422
25873
|
);
|
|
25423
|
-
clack34.outro(
|
|
25874
|
+
clack34.outro(pc37.green("Done!"));
|
|
25424
25875
|
return;
|
|
25425
25876
|
}
|
|
25426
25877
|
if (existingNumber?.Status === "PENDING") {
|
|
@@ -25437,14 +25888,14 @@ Run ${pc36.cyan(`wraps sms verify-number --phone-number ${phoneNumber} --resend`
|
|
|
25437
25888
|
);
|
|
25438
25889
|
progress.stop();
|
|
25439
25890
|
clack34.log.info(
|
|
25440
|
-
`Verification already in progress. New code sent to ${
|
|
25891
|
+
`Verification already in progress. New code sent to ${pc37.cyan(phoneNumber)}`
|
|
25441
25892
|
);
|
|
25442
25893
|
console.log("");
|
|
25443
25894
|
console.log(
|
|
25444
25895
|
`Once you receive the code, run:
|
|
25445
|
-
${
|
|
25896
|
+
${pc37.cyan(`wraps sms verify-number --phone-number ${phoneNumber} --code YOUR_CODE`)}`
|
|
25446
25897
|
);
|
|
25447
|
-
clack34.outro(
|
|
25898
|
+
clack34.outro(pc37.green("Code sent!"));
|
|
25448
25899
|
return;
|
|
25449
25900
|
}
|
|
25450
25901
|
const createResponse = await progress.execute(
|
|
@@ -25466,7 +25917,7 @@ Run ${pc36.cyan(`wraps sms verify-number --phone-number ${phoneNumber} --resend`
|
|
|
25466
25917
|
progress.stop();
|
|
25467
25918
|
console.log("\n");
|
|
25468
25919
|
clack34.log.success(
|
|
25469
|
-
`Verification code sent to ${
|
|
25920
|
+
`Verification code sent to ${pc37.cyan(phoneNumber)} via SMS`
|
|
25470
25921
|
);
|
|
25471
25922
|
console.log("");
|
|
25472
25923
|
clack34.note(
|
|
@@ -25474,9 +25925,9 @@ Run ${pc36.cyan(`wraps sms verify-number --phone-number ${phoneNumber} --resend`
|
|
|
25474
25925
|
"1. Check your phone for the verification code",
|
|
25475
25926
|
"",
|
|
25476
25927
|
"2. Complete verification with:",
|
|
25477
|
-
` ${
|
|
25928
|
+
` ${pc37.cyan(`wraps sms verify-number --phone-number ${phoneNumber} --code YOUR_CODE`)}`,
|
|
25478
25929
|
"",
|
|
25479
|
-
|
|
25930
|
+
pc37.dim("The code expires in 24 hours")
|
|
25480
25931
|
].join("\n"),
|
|
25481
25932
|
"Next Steps"
|
|
25482
25933
|
);
|
|
@@ -25484,7 +25935,7 @@ Run ${pc36.cyan(`wraps sms verify-number --phone-number ${phoneNumber} --resend`
|
|
|
25484
25935
|
success: true,
|
|
25485
25936
|
duration_ms: Date.now() - startTime
|
|
25486
25937
|
});
|
|
25487
|
-
clack34.outro(
|
|
25938
|
+
clack34.outro(pc37.green("Verification started!"));
|
|
25488
25939
|
} catch (error) {
|
|
25489
25940
|
progress.stop();
|
|
25490
25941
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
@@ -25492,7 +25943,7 @@ Run ${pc36.cyan(`wraps sms verify-number --phone-number ${phoneNumber} --resend`
|
|
|
25492
25943
|
clack34.log.error("This number is already being verified");
|
|
25493
25944
|
console.log(
|
|
25494
25945
|
`
|
|
25495
|
-
Run ${
|
|
25946
|
+
Run ${pc37.cyan(`wraps sms verify-number --phone-number ${phoneNumber} --resend`)} to get a new code.
|
|
25496
25947
|
`
|
|
25497
25948
|
);
|
|
25498
25949
|
} else {
|
|
@@ -25508,17 +25959,17 @@ Run ${pc36.cyan(`wraps sms verify-number --phone-number ${phoneNumber} --resend`
|
|
|
25508
25959
|
// src/commands/support.ts
|
|
25509
25960
|
init_esm_shims();
|
|
25510
25961
|
import * as clack35 from "@clack/prompts";
|
|
25511
|
-
import
|
|
25962
|
+
import pc38 from "picocolors";
|
|
25512
25963
|
async function support() {
|
|
25513
|
-
clack35.intro(
|
|
25964
|
+
clack35.intro(pc38.bold("Get Help with Wraps"));
|
|
25514
25965
|
console.log();
|
|
25515
|
-
console.log(` ${
|
|
25966
|
+
console.log(` ${pc38.bold("Email:")} ${pc38.cyan("hey@wraps.sh")}`);
|
|
25516
25967
|
console.log(
|
|
25517
|
-
` ${
|
|
25968
|
+
` ${pc38.bold("GitHub:")} ${pc38.cyan("https://github.com/wraps-dev/wraps/issues")}`
|
|
25518
25969
|
);
|
|
25519
|
-
console.log(` ${
|
|
25970
|
+
console.log(` ${pc38.bold("Docs:")} ${pc38.cyan("https://wraps.dev/docs")}`);
|
|
25520
25971
|
console.log();
|
|
25521
|
-
console.log(
|
|
25972
|
+
console.log(pc38.dim(" Response time: Usually within 24 hours"));
|
|
25522
25973
|
console.log();
|
|
25523
25974
|
}
|
|
25524
25975
|
|
|
@@ -25526,55 +25977,55 @@ async function support() {
|
|
|
25526
25977
|
init_esm_shims();
|
|
25527
25978
|
init_client();
|
|
25528
25979
|
import * as clack36 from "@clack/prompts";
|
|
25529
|
-
import
|
|
25980
|
+
import pc39 from "picocolors";
|
|
25530
25981
|
async function telemetryEnable() {
|
|
25531
25982
|
const client = getTelemetryClient();
|
|
25532
25983
|
client.enable();
|
|
25533
|
-
clack36.log.success(
|
|
25534
|
-
console.log(` Config: ${
|
|
25984
|
+
clack36.log.success(pc39.green("Telemetry enabled"));
|
|
25985
|
+
console.log(` Config: ${pc39.dim(client.getConfigPath())}`);
|
|
25535
25986
|
console.log(`
|
|
25536
|
-
${
|
|
25987
|
+
${pc39.dim("Thank you for helping improve Wraps!")}
|
|
25537
25988
|
`);
|
|
25538
25989
|
}
|
|
25539
25990
|
async function telemetryDisable() {
|
|
25540
25991
|
const client = getTelemetryClient();
|
|
25541
25992
|
client.disable();
|
|
25542
|
-
clack36.log.success(
|
|
25543
|
-
console.log(` Config: ${
|
|
25993
|
+
clack36.log.success(pc39.green("Telemetry disabled"));
|
|
25994
|
+
console.log(` Config: ${pc39.dim(client.getConfigPath())}`);
|
|
25544
25995
|
console.log(
|
|
25545
25996
|
`
|
|
25546
|
-
${
|
|
25997
|
+
${pc39.dim("You can re-enable with:")} wraps telemetry enable
|
|
25547
25998
|
`
|
|
25548
25999
|
);
|
|
25549
26000
|
}
|
|
25550
26001
|
async function telemetryStatus() {
|
|
25551
26002
|
const client = getTelemetryClient();
|
|
25552
|
-
clack36.intro(
|
|
25553
|
-
const status2 = client.isEnabled() ?
|
|
26003
|
+
clack36.intro(pc39.bold("Telemetry Status"));
|
|
26004
|
+
const status2 = client.isEnabled() ? pc39.green("Enabled") : pc39.red("Disabled");
|
|
25554
26005
|
console.log();
|
|
25555
|
-
console.log(` ${
|
|
25556
|
-
console.log(` ${
|
|
26006
|
+
console.log(` ${pc39.bold("Status:")} ${status2}`);
|
|
26007
|
+
console.log(` ${pc39.bold("Config file:")} ${pc39.dim(client.getConfigPath())}`);
|
|
25557
26008
|
if (client.isEnabled()) {
|
|
25558
26009
|
console.log();
|
|
25559
|
-
console.log(
|
|
25560
|
-
console.log(` ${
|
|
26010
|
+
console.log(pc39.bold(" How to opt-out:"));
|
|
26011
|
+
console.log(` ${pc39.cyan("wraps telemetry disable")}`);
|
|
25561
26012
|
console.log(
|
|
25562
|
-
` ${
|
|
26013
|
+
` ${pc39.dim("Or set:")} ${pc39.cyan("WRAPS_TELEMETRY_DISABLED=1")}`
|
|
25563
26014
|
);
|
|
25564
|
-
console.log(` ${
|
|
26015
|
+
console.log(` ${pc39.dim("Or set:")} ${pc39.cyan("DO_NOT_TRACK=1")}`);
|
|
25565
26016
|
} else {
|
|
25566
26017
|
console.log();
|
|
25567
|
-
console.log(
|
|
25568
|
-
console.log(` ${
|
|
26018
|
+
console.log(pc39.bold(" How to opt-in:"));
|
|
26019
|
+
console.log(` ${pc39.cyan("wraps telemetry enable")}`);
|
|
25569
26020
|
}
|
|
25570
26021
|
console.log();
|
|
25571
|
-
console.log(
|
|
26022
|
+
console.log(pc39.bold(" Debug mode:"));
|
|
25572
26023
|
console.log(
|
|
25573
|
-
` ${
|
|
26024
|
+
` ${pc39.dim("See what would be sent:")} ${pc39.cyan("WRAPS_TELEMETRY_DEBUG=1 wraps <command>")}`
|
|
25574
26025
|
);
|
|
25575
26026
|
console.log();
|
|
25576
26027
|
console.log(
|
|
25577
|
-
` ${
|
|
26028
|
+
` ${pc39.dim("Learn more:")} ${pc39.cyan("https://wraps.dev/docs/telemetry")}`
|
|
25578
26029
|
);
|
|
25579
26030
|
console.log();
|
|
25580
26031
|
}
|
|
@@ -25659,135 +26110,138 @@ function showVersion() {
|
|
|
25659
26110
|
process.exit(0);
|
|
25660
26111
|
}
|
|
25661
26112
|
function showHelp() {
|
|
25662
|
-
clack37.intro(
|
|
26113
|
+
clack37.intro(pc40.bold(`WRAPS CLI v${VERSION}`));
|
|
25663
26114
|
console.log("Deploy AWS infrastructure to your account\n");
|
|
25664
26115
|
console.log("Usage: wraps [service] <command> [options]\n");
|
|
25665
26116
|
console.log("Services:");
|
|
25666
|
-
console.log(` ${
|
|
26117
|
+
console.log(` ${pc40.cyan("email")} Email infrastructure (AWS SES)`);
|
|
25667
26118
|
console.log(
|
|
25668
|
-
` ${
|
|
26119
|
+
` ${pc40.cyan("sms")} SMS infrastructure (AWS End User Messaging)`
|
|
25669
26120
|
);
|
|
25670
26121
|
console.log(
|
|
25671
|
-
` ${
|
|
26122
|
+
` ${pc40.cyan("cdn")} CDN infrastructure (AWS S3 + CloudFront)
|
|
25672
26123
|
`
|
|
25673
26124
|
);
|
|
25674
26125
|
console.log("Email Commands:");
|
|
25675
26126
|
console.log(
|
|
25676
|
-
` ${
|
|
26127
|
+
` ${pc40.cyan("email init")} Deploy new email infrastructure`
|
|
25677
26128
|
);
|
|
25678
26129
|
console.log(
|
|
25679
|
-
` ${
|
|
26130
|
+
` ${pc40.cyan("email check")} Check email deliverability for a domain`
|
|
25680
26131
|
);
|
|
25681
26132
|
console.log(
|
|
25682
|
-
` ${
|
|
26133
|
+
` ${pc40.cyan("email connect")} Connect to existing AWS SES`
|
|
25683
26134
|
);
|
|
25684
26135
|
console.log(
|
|
25685
|
-
` ${
|
|
26136
|
+
` ${pc40.cyan("email status")} Show email infrastructure details`
|
|
25686
26137
|
);
|
|
25687
|
-
console.log(` ${
|
|
26138
|
+
console.log(` ${pc40.cyan("email verify")} Verify domain DNS records`);
|
|
25688
26139
|
console.log(
|
|
25689
|
-
` ${
|
|
26140
|
+
` ${pc40.cyan("email sync")} Apply CLI updates to infrastructure`
|
|
25690
26141
|
);
|
|
25691
|
-
console.log(` ${
|
|
26142
|
+
console.log(` ${pc40.cyan("email upgrade")} Add features`);
|
|
25692
26143
|
console.log(
|
|
25693
|
-
` ${
|
|
26144
|
+
` ${pc40.cyan("email restore")} Restore original configuration`
|
|
25694
26145
|
);
|
|
25695
26146
|
console.log(
|
|
25696
|
-
` ${
|
|
26147
|
+
` ${pc40.cyan("email destroy")} Remove email infrastructure`
|
|
25697
26148
|
);
|
|
25698
|
-
console.log(` ${
|
|
25699
|
-
console.log(` ${
|
|
25700
|
-
console.log(` ${
|
|
26149
|
+
console.log(` ${pc40.cyan("email domains add")} Add a domain to SES`);
|
|
26150
|
+
console.log(` ${pc40.cyan("email domains list")} List all domains`);
|
|
26151
|
+
console.log(` ${pc40.cyan("email domains remove")} Remove a domain
|
|
25701
26152
|
`);
|
|
25702
26153
|
console.log("SMS Commands:");
|
|
25703
|
-
console.log(` ${
|
|
26154
|
+
console.log(` ${pc40.cyan("sms init")} Deploy SMS infrastructure`);
|
|
25704
26155
|
console.log(
|
|
25705
|
-
` ${
|
|
26156
|
+
` ${pc40.cyan("sms status")} Show SMS infrastructure details`
|
|
25706
26157
|
);
|
|
25707
|
-
console.log(` ${
|
|
26158
|
+
console.log(` ${pc40.cyan("sms test")} Send a test SMS message`);
|
|
25708
26159
|
console.log(
|
|
25709
|
-
` ${
|
|
26160
|
+
` ${pc40.cyan("sms verify-number")} Verify a destination phone number`
|
|
25710
26161
|
);
|
|
25711
26162
|
console.log(
|
|
25712
|
-
` ${
|
|
26163
|
+
` ${pc40.cyan("sms sync")} Sync infrastructure (update Lambda, etc.)`
|
|
25713
26164
|
);
|
|
25714
|
-
console.log(` ${
|
|
25715
|
-
console.log(` ${
|
|
26165
|
+
console.log(` ${pc40.cyan("sms upgrade")} Upgrade SMS features`);
|
|
26166
|
+
console.log(` ${pc40.cyan("sms register")} Register toll-free number`);
|
|
25716
26167
|
console.log(
|
|
25717
|
-
` ${
|
|
26168
|
+
` ${pc40.cyan("sms destroy")} Remove SMS infrastructure
|
|
25718
26169
|
`
|
|
25719
26170
|
);
|
|
25720
26171
|
console.log("CDN Commands:");
|
|
25721
26172
|
console.log(
|
|
25722
|
-
` ${
|
|
26173
|
+
` ${pc40.cyan("cdn init")} Deploy CDN infrastructure (S3 + CloudFront)`
|
|
25723
26174
|
);
|
|
25724
26175
|
console.log(
|
|
25725
|
-
` ${
|
|
26176
|
+
` ${pc40.cyan("cdn status")} Show CDN infrastructure details`
|
|
25726
26177
|
);
|
|
25727
26178
|
console.log(
|
|
25728
|
-
` ${
|
|
26179
|
+
` ${pc40.cyan("cdn verify")} Check DNS and certificate status`
|
|
25729
26180
|
);
|
|
25730
26181
|
console.log(
|
|
25731
|
-
` ${
|
|
26182
|
+
` ${pc40.cyan("cdn upgrade")} Add custom domain after cert validation`
|
|
25732
26183
|
);
|
|
25733
26184
|
console.log(
|
|
25734
|
-
` ${
|
|
26185
|
+
` ${pc40.cyan("cdn sync")} Sync infrastructure with current config`
|
|
25735
26186
|
);
|
|
25736
26187
|
console.log(
|
|
25737
|
-
` ${
|
|
26188
|
+
` ${pc40.cyan("cdn destroy")} Remove CDN infrastructure
|
|
25738
26189
|
`
|
|
25739
26190
|
);
|
|
25740
26191
|
console.log("Local Development:");
|
|
25741
26192
|
console.log(
|
|
25742
|
-
` ${
|
|
26193
|
+
` ${pc40.cyan("console")} Start local web console
|
|
25743
26194
|
`
|
|
25744
26195
|
);
|
|
25745
26196
|
console.log("Platform:");
|
|
25746
26197
|
console.log(
|
|
25747
|
-
` ${
|
|
26198
|
+
` ${pc40.cyan("platform")} Show platform info and pricing`
|
|
26199
|
+
);
|
|
26200
|
+
console.log(
|
|
26201
|
+
` ${pc40.cyan("platform connect")} Connect to Wraps Platform (events + IAM)`
|
|
25748
26202
|
);
|
|
25749
26203
|
console.log(
|
|
25750
|
-
` ${
|
|
26204
|
+
` ${pc40.cyan("platform update-role")} Update platform IAM permissions
|
|
25751
26205
|
`
|
|
25752
26206
|
);
|
|
25753
26207
|
console.log("AWS Setup:");
|
|
25754
26208
|
console.log(
|
|
25755
|
-
` ${
|
|
26209
|
+
` ${pc40.cyan("aws setup")} Interactive AWS setup wizard`
|
|
25756
26210
|
);
|
|
25757
26211
|
console.log(
|
|
25758
|
-
` ${
|
|
26212
|
+
` ${pc40.cyan("aws doctor")} Diagnose AWS configuration issues
|
|
25759
26213
|
`
|
|
25760
26214
|
);
|
|
25761
26215
|
console.log("Global Commands:");
|
|
25762
|
-
console.log(` ${
|
|
25763
|
-
console.log(` ${
|
|
25764
|
-
console.log(` ${
|
|
25765
|
-
console.log(` ${
|
|
26216
|
+
console.log(` ${pc40.cyan("status")} Show overview of all services`);
|
|
26217
|
+
console.log(` ${pc40.cyan("destroy")} Remove deployed infrastructure`);
|
|
26218
|
+
console.log(` ${pc40.cyan("permissions")} Show required AWS IAM permissions`);
|
|
26219
|
+
console.log(` ${pc40.cyan("completion")} Generate shell completion script`);
|
|
25766
26220
|
console.log(
|
|
25767
|
-
` ${
|
|
26221
|
+
` ${pc40.cyan("telemetry")} Manage anonymous telemetry settings`
|
|
25768
26222
|
);
|
|
25769
|
-
console.log(` ${
|
|
26223
|
+
console.log(` ${pc40.cyan("news")} Show recent Wraps updates`);
|
|
25770
26224
|
console.log(
|
|
25771
|
-
` ${
|
|
26225
|
+
` ${pc40.cyan("support")} Get help and support contact info
|
|
25772
26226
|
`
|
|
25773
26227
|
);
|
|
25774
26228
|
console.log("Options:");
|
|
25775
26229
|
console.log(
|
|
25776
|
-
` ${
|
|
26230
|
+
` ${pc40.dim("-p, --provider")} Hosting provider (vercel, aws, railway, other)`
|
|
25777
26231
|
);
|
|
25778
|
-
console.log(` ${
|
|
25779
|
-
console.log(` ${
|
|
25780
|
-
console.log(` ${
|
|
25781
|
-
console.log(` ${
|
|
25782
|
-
console.log(` ${
|
|
25783
|
-
console.log(` ${
|
|
26232
|
+
console.log(` ${pc40.dim("-r, --region")} AWS region`);
|
|
26233
|
+
console.log(` ${pc40.dim("-d, --domain")} Domain name`);
|
|
26234
|
+
console.log(` ${pc40.dim("--account")} AWS account ID or alias`);
|
|
26235
|
+
console.log(` ${pc40.dim("--preset")} Configuration preset`);
|
|
26236
|
+
console.log(` ${pc40.dim("-y, --yes")} Skip confirmation prompts`);
|
|
26237
|
+
console.log(` ${pc40.dim("-f, --force")} Force destructive operations`);
|
|
25784
26238
|
console.log(
|
|
25785
|
-
` ${
|
|
26239
|
+
` ${pc40.dim("--preview")} Preview changes without deploying`
|
|
25786
26240
|
);
|
|
25787
|
-
console.log(` ${
|
|
26241
|
+
console.log(` ${pc40.dim("-v, --version")} Show version number
|
|
25788
26242
|
`);
|
|
25789
26243
|
console.log(
|
|
25790
|
-
`Run ${
|
|
26244
|
+
`Run ${pc40.cyan("wraps <service> <command> --help")} for more information.
|
|
25791
26245
|
`
|
|
25792
26246
|
);
|
|
25793
26247
|
process.exit(0);
|
|
@@ -25933,7 +26387,7 @@ var flags = args.parse(process.argv);
|
|
|
25933
26387
|
var [primaryCommand, subCommand] = args.sub;
|
|
25934
26388
|
if (!primaryCommand) {
|
|
25935
26389
|
async function interactiveMenu() {
|
|
25936
|
-
clack37.intro(
|
|
26390
|
+
clack37.intro(pc40.bold(`WRAPS CLI v${VERSION}`));
|
|
25937
26391
|
console.log(" Deploy AWS infrastructure to your account.\n");
|
|
25938
26392
|
const action = await clack37.select({
|
|
25939
26393
|
message: "What would you like to do?",
|
|
@@ -26047,20 +26501,20 @@ async function run() {
|
|
|
26047
26501
|
const telemetry = getTelemetryClient();
|
|
26048
26502
|
if (telemetry.shouldShowNotification()) {
|
|
26049
26503
|
console.log();
|
|
26050
|
-
clack37.log.info(
|
|
26504
|
+
clack37.log.info(pc40.bold("Anonymous Telemetry"));
|
|
26051
26505
|
console.log(
|
|
26052
|
-
` Wraps collects ${
|
|
26506
|
+
` Wraps collects ${pc40.cyan("anonymous usage data")} to improve the CLI.`
|
|
26053
26507
|
);
|
|
26054
26508
|
console.log(
|
|
26055
|
-
` We ${
|
|
26509
|
+
` We ${pc40.bold("never")} collect: domains, AWS credentials, email content, or PII.`
|
|
26056
26510
|
);
|
|
26057
26511
|
console.log(
|
|
26058
|
-
` We ${
|
|
26512
|
+
` We ${pc40.bold("only")} collect: command names, success/failure, CLI version, OS.`
|
|
26059
26513
|
);
|
|
26060
26514
|
console.log();
|
|
26061
|
-
console.log(` Opt-out anytime: ${
|
|
26062
|
-
console.log(` Or set: ${
|
|
26063
|
-
console.log(` Learn more: ${
|
|
26515
|
+
console.log(` Opt-out anytime: ${pc40.cyan("wraps telemetry disable")}`);
|
|
26516
|
+
console.log(` Or set: ${pc40.cyan("WRAPS_TELEMETRY_DISABLED=1")}`);
|
|
26517
|
+
console.log(` Learn more: ${pc40.cyan("https://wraps.dev/docs")}`);
|
|
26064
26518
|
console.log();
|
|
26065
26519
|
telemetry.markNotificationShown();
|
|
26066
26520
|
}
|
|
@@ -26130,7 +26584,7 @@ async function run() {
|
|
|
26130
26584
|
clack37.log.error("--domain flag is required");
|
|
26131
26585
|
console.log(
|
|
26132
26586
|
`
|
|
26133
|
-
Usage: ${
|
|
26587
|
+
Usage: ${pc40.cyan("wraps email verify --domain yourapp.com")}
|
|
26134
26588
|
`
|
|
26135
26589
|
);
|
|
26136
26590
|
process.exit(1);
|
|
@@ -26146,7 +26600,7 @@ Usage: ${pc39.cyan("wraps email verify --domain yourapp.com")}
|
|
|
26146
26600
|
clack37.log.error("--domain flag is required");
|
|
26147
26601
|
console.log(
|
|
26148
26602
|
`
|
|
26149
|
-
Usage: ${
|
|
26603
|
+
Usage: ${pc40.cyan("wraps email domains add --domain yourapp.com")}
|
|
26150
26604
|
`
|
|
26151
26605
|
);
|
|
26152
26606
|
process.exit(1);
|
|
@@ -26162,7 +26616,7 @@ Usage: ${pc39.cyan("wraps email domains add --domain yourapp.com")}
|
|
|
26162
26616
|
clack37.log.error("--domain flag is required");
|
|
26163
26617
|
console.log(
|
|
26164
26618
|
`
|
|
26165
|
-
Usage: ${
|
|
26619
|
+
Usage: ${pc40.cyan("wraps email domains verify --domain yourapp.com")}
|
|
26166
26620
|
`
|
|
26167
26621
|
);
|
|
26168
26622
|
process.exit(1);
|
|
@@ -26175,7 +26629,7 @@ Usage: ${pc39.cyan("wraps email domains verify --domain yourapp.com")}
|
|
|
26175
26629
|
clack37.log.error("--domain flag is required");
|
|
26176
26630
|
console.log(
|
|
26177
26631
|
`
|
|
26178
|
-
Usage: ${
|
|
26632
|
+
Usage: ${pc40.cyan("wraps email domains get-dkim --domain yourapp.com")}
|
|
26179
26633
|
`
|
|
26180
26634
|
);
|
|
26181
26635
|
process.exit(1);
|
|
@@ -26188,7 +26642,7 @@ Usage: ${pc39.cyan("wraps email domains get-dkim --domain yourapp.com")}
|
|
|
26188
26642
|
clack37.log.error("--domain flag is required");
|
|
26189
26643
|
console.log(
|
|
26190
26644
|
`
|
|
26191
|
-
Usage: ${
|
|
26645
|
+
Usage: ${pc40.cyan("wraps email domains remove --domain yourapp.com --force")}
|
|
26192
26646
|
`
|
|
26193
26647
|
);
|
|
26194
26648
|
process.exit(1);
|
|
@@ -26205,7 +26659,7 @@ Usage: ${pc39.cyan("wraps email domains remove --domain yourapp.com --force")}
|
|
|
26205
26659
|
);
|
|
26206
26660
|
console.log(
|
|
26207
26661
|
`
|
|
26208
|
-
Available commands: ${
|
|
26662
|
+
Available commands: ${pc40.cyan("add")}, ${pc40.cyan("list")}, ${pc40.cyan("verify")}, ${pc40.cyan("get-dkim")}, ${pc40.cyan("remove")}
|
|
26209
26663
|
`
|
|
26210
26664
|
);
|
|
26211
26665
|
process.exit(1);
|
|
@@ -26223,7 +26677,7 @@ Available commands: ${pc39.cyan("add")}, ${pc39.cyan("list")}, ${pc39.cyan("veri
|
|
|
26223
26677
|
clack37.log.error(`Unknown email command: ${subCommand}`);
|
|
26224
26678
|
console.log(
|
|
26225
26679
|
`
|
|
26226
|
-
Run ${
|
|
26680
|
+
Run ${pc40.cyan("wraps --help")} for available commands.
|
|
26227
26681
|
`
|
|
26228
26682
|
);
|
|
26229
26683
|
process.exit(1);
|
|
@@ -26294,7 +26748,7 @@ Run ${pc39.cyan("wraps --help")} for available commands.
|
|
|
26294
26748
|
clack37.log.error(`Unknown sms command: ${subCommand}`);
|
|
26295
26749
|
console.log(
|
|
26296
26750
|
`
|
|
26297
|
-
Run ${
|
|
26751
|
+
Run ${pc40.cyan("wraps --help")} for available commands.
|
|
26298
26752
|
`
|
|
26299
26753
|
);
|
|
26300
26754
|
process.exit(1);
|
|
@@ -26353,7 +26807,7 @@ Run ${pc39.cyan("wraps --help")} for available commands.
|
|
|
26353
26807
|
clack37.log.error(`Unknown cdn command: ${subCommand}`);
|
|
26354
26808
|
console.log(
|
|
26355
26809
|
`
|
|
26356
|
-
Run ${
|
|
26810
|
+
Run ${pc40.cyan("wraps --help")} for available commands.
|
|
26357
26811
|
`
|
|
26358
26812
|
);
|
|
26359
26813
|
process.exit(1);
|
|
@@ -26378,6 +26832,13 @@ Run ${pc39.cyan("wraps --help")} for available commands.
|
|
|
26378
26832
|
return;
|
|
26379
26833
|
}
|
|
26380
26834
|
switch (subCommand) {
|
|
26835
|
+
case "connect":
|
|
26836
|
+
await connect3({
|
|
26837
|
+
region: flags.region,
|
|
26838
|
+
force: flags.force,
|
|
26839
|
+
yes: flags.yes
|
|
26840
|
+
});
|
|
26841
|
+
break;
|
|
26381
26842
|
case "update-role":
|
|
26382
26843
|
await updateRole({
|
|
26383
26844
|
region: flags.region,
|
|
@@ -26386,11 +26847,13 @@ Run ${pc39.cyan("wraps --help")} for available commands.
|
|
|
26386
26847
|
break;
|
|
26387
26848
|
default:
|
|
26388
26849
|
clack37.log.error(`Unknown platform command: ${subCommand}`);
|
|
26389
|
-
console.log(`
|
|
26390
|
-
Available commands: ${pc39.cyan("update-role")}
|
|
26391
|
-
`);
|
|
26392
26850
|
console.log(
|
|
26393
|
-
`
|
|
26851
|
+
`
|
|
26852
|
+
Available commands: ${pc40.cyan("connect")}, ${pc40.cyan("update-role")}
|
|
26853
|
+
`
|
|
26854
|
+
);
|
|
26855
|
+
console.log(
|
|
26856
|
+
`Run ${pc40.cyan("wraps platform")} for more information.
|
|
26394
26857
|
`
|
|
26395
26858
|
);
|
|
26396
26859
|
process.exit(1);
|
|
@@ -26417,10 +26880,10 @@ Available commands: ${pc39.cyan("update-role")}
|
|
|
26417
26880
|
clack37.log.error(`Unknown aws command: ${subCommand}`);
|
|
26418
26881
|
console.log(
|
|
26419
26882
|
`
|
|
26420
|
-
Available commands: ${
|
|
26883
|
+
Available commands: ${pc40.cyan("setup")}, ${pc40.cyan("doctor")}
|
|
26421
26884
|
`
|
|
26422
26885
|
);
|
|
26423
|
-
console.log(`Run ${
|
|
26886
|
+
console.log(`Run ${pc40.cyan("wraps --help")} for more information.
|
|
26424
26887
|
`);
|
|
26425
26888
|
process.exit(1);
|
|
26426
26889
|
}
|
|
@@ -26483,7 +26946,7 @@ Available commands: ${pc39.cyan("setup")}, ${pc39.cyan("doctor")}
|
|
|
26483
26946
|
clack37.log.error(`Unknown telemetry command: ${subCommand}`);
|
|
26484
26947
|
console.log(
|
|
26485
26948
|
`
|
|
26486
|
-
Available commands: ${
|
|
26949
|
+
Available commands: ${pc40.cyan("enable")}, ${pc40.cyan("disable")}, ${pc40.cyan("status")}
|
|
26487
26950
|
`
|
|
26488
26951
|
);
|
|
26489
26952
|
process.exit(1);
|
|
@@ -26506,7 +26969,7 @@ Please specify a command for ${primaryCommand} service.
|
|
|
26506
26969
|
clack37.log.error(`Unknown command: ${primaryCommand}`);
|
|
26507
26970
|
console.log(
|
|
26508
26971
|
`
|
|
26509
|
-
Run ${
|
|
26972
|
+
Run ${pc40.cyan("wraps --help")} for available commands.
|
|
26510
26973
|
`
|
|
26511
26974
|
);
|
|
26512
26975
|
process.exit(1);
|