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