@wraps.dev/cli 2.18.2 → 2.18.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js
CHANGED
|
@@ -5979,8 +5979,15 @@ function displaySuccess(outputs) {
|
|
|
5979
5979
|
clack8.outro(pc10.green("Email infrastructure deployed successfully!"));
|
|
5980
5980
|
console.log(lines.join("\n"));
|
|
5981
5981
|
if (outputs.dnsAutoCreated && outputs.domain) {
|
|
5982
|
+
const providerNames = {
|
|
5983
|
+
route53: "AWS Route53",
|
|
5984
|
+
vercel: "Vercel DNS",
|
|
5985
|
+
cloudflare: "Cloudflare",
|
|
5986
|
+
manual: "Manual"
|
|
5987
|
+
};
|
|
5988
|
+
const providerDisplay = providerNames[outputs.dnsProvider ?? "route53"] ?? "your DNS provider";
|
|
5982
5989
|
clack8.note(
|
|
5983
|
-
`DNS records (DKIM, SPF, DMARC) were automatically created in
|
|
5990
|
+
`DNS records (DKIM, SPF, DMARC) were automatically created in ${providerDisplay} for ${pc10.cyan(
|
|
5984
5991
|
outputs.domain
|
|
5985
5992
|
)}.
|
|
5986
5993
|
|
|
@@ -8971,9 +8978,8 @@ Run ${pc27.cyan("wraps email init")} to deploy email infrastructure.
|
|
|
8971
8978
|
process.exit(1);
|
|
8972
8979
|
return;
|
|
8973
8980
|
}
|
|
8974
|
-
const
|
|
8975
|
-
|
|
8976
|
-
if (!domain) {
|
|
8981
|
+
const trackedDomains = getAllTrackedDomains(metadata);
|
|
8982
|
+
if (trackedDomains.length === 0) {
|
|
8977
8983
|
progress.stop();
|
|
8978
8984
|
clack25.log.error("No domain configured in email infrastructure");
|
|
8979
8985
|
console.log(`
|
|
@@ -8982,6 +8988,24 @@ Run ${pc27.cyan("wraps email init")} to set up a domain.
|
|
|
8982
8988
|
process.exit(1);
|
|
8983
8989
|
return;
|
|
8984
8990
|
}
|
|
8991
|
+
let domain;
|
|
8992
|
+
if (trackedDomains.length === 1) {
|
|
8993
|
+
domain = trackedDomains[0].domain;
|
|
8994
|
+
} else {
|
|
8995
|
+
const selected = await clack25.select({
|
|
8996
|
+
message: "Which domain do you want to send from?",
|
|
8997
|
+
options: trackedDomains.map((d) => ({
|
|
8998
|
+
value: d.domain,
|
|
8999
|
+
label: d.domain,
|
|
9000
|
+
hint: d.isPrimary ? "primary" : d.purpose
|
|
9001
|
+
}))
|
|
9002
|
+
});
|
|
9003
|
+
if (clack25.isCancel(selected)) {
|
|
9004
|
+
clack25.cancel("Operation cancelled.");
|
|
9005
|
+
process.exit(0);
|
|
9006
|
+
}
|
|
9007
|
+
domain = selected;
|
|
9008
|
+
}
|
|
8985
9009
|
let toEmail = options.to;
|
|
8986
9010
|
if (!toEmail) {
|
|
8987
9011
|
if (isJsonMode() && !options.scenario) {
|
|
@@ -17707,12 +17731,7 @@ async function createSMTPCredentials(config2) {
|
|
|
17707
17731
|
{
|
|
17708
17732
|
Effect: "Allow",
|
|
17709
17733
|
Action: "ses:SendRawEmail",
|
|
17710
|
-
Resource: "*"
|
|
17711
|
-
Condition: {
|
|
17712
|
-
StringEquals: {
|
|
17713
|
-
"ses:ConfigurationSetName": config2.configSetName
|
|
17714
|
-
}
|
|
17715
|
-
}
|
|
17734
|
+
Resource: "*"
|
|
17716
17735
|
}
|
|
17717
17736
|
]
|
|
17718
17737
|
})
|
|
@@ -19742,18 +19761,17 @@ Run ${pc23.cyan("wraps email init")} first to deploy email infrastructure.
|
|
|
19742
19761
|
}
|
|
19743
19762
|
clack21.log.step(`Adding ${pc23.cyan(domain)}`);
|
|
19744
19763
|
const sesClient = new SESv2Client4({ region });
|
|
19764
|
+
let domainAlreadyExists = false;
|
|
19765
|
+
let dkimTokens = [];
|
|
19745
19766
|
try {
|
|
19746
|
-
await sesClient.send(
|
|
19767
|
+
const existing = await sesClient.send(
|
|
19747
19768
|
new GetEmailIdentityCommand2({ EmailIdentity: domain })
|
|
19748
19769
|
);
|
|
19749
|
-
|
|
19750
|
-
|
|
19751
|
-
|
|
19752
|
-
`
|
|
19753
|
-
Run ${pc23.cyan(`wraps email domains verify --domain ${domain}`)} to check verification status.
|
|
19754
|
-
`
|
|
19770
|
+
domainAlreadyExists = true;
|
|
19771
|
+
dkimTokens = existing.DkimAttributes?.Tokens || [];
|
|
19772
|
+
clack21.log.info(
|
|
19773
|
+
`Domain ${pc23.cyan(domain)} already exists in SES \u2014 adopting into Wraps`
|
|
19755
19774
|
);
|
|
19756
|
-
return;
|
|
19757
19775
|
} catch (error) {
|
|
19758
19776
|
if (!isAWSNotFoundError(error)) {
|
|
19759
19777
|
throw error;
|
|
@@ -19763,22 +19781,34 @@ Run ${pc23.cyan(`wraps email domains verify --domain ${domain}`)} to check verif
|
|
|
19763
19781
|
if (!options.yes) {
|
|
19764
19782
|
purpose = await promptDomainPurpose();
|
|
19765
19783
|
}
|
|
19766
|
-
|
|
19767
|
-
|
|
19768
|
-
await
|
|
19769
|
-
|
|
19770
|
-
|
|
19771
|
-
|
|
19772
|
-
|
|
19773
|
-
|
|
19774
|
-
|
|
19775
|
-
|
|
19784
|
+
if (domainAlreadyExists) {
|
|
19785
|
+
const { PutEmailIdentityConfigurationSetAttributesCommand } = await import("@aws-sdk/client-sesv2");
|
|
19786
|
+
await progress.execute("Associating tracking configuration", async () => {
|
|
19787
|
+
await sesClient.send(
|
|
19788
|
+
new PutEmailIdentityConfigurationSetAttributesCommand({
|
|
19789
|
+
EmailIdentity: domain,
|
|
19790
|
+
ConfigurationSetName: "wraps-email-tracking"
|
|
19791
|
+
})
|
|
19792
|
+
);
|
|
19793
|
+
});
|
|
19794
|
+
} else {
|
|
19795
|
+
const { CreateEmailIdentityCommand } = await import("@aws-sdk/client-sesv2");
|
|
19796
|
+
await progress.execute("Creating SES identity", async () => {
|
|
19797
|
+
await sesClient.send(
|
|
19798
|
+
new CreateEmailIdentityCommand({
|
|
19799
|
+
EmailIdentity: domain,
|
|
19800
|
+
ConfigurationSetName: "wraps-email-tracking",
|
|
19801
|
+
DkimSigningAttributes: {
|
|
19802
|
+
NextSigningKeyLength: "RSA_2048_BIT"
|
|
19803
|
+
}
|
|
19804
|
+
})
|
|
19805
|
+
);
|
|
19806
|
+
});
|
|
19807
|
+
const sesIdentity = await sesClient.send(
|
|
19808
|
+
new GetEmailIdentityCommand2({ EmailIdentity: domain })
|
|
19776
19809
|
);
|
|
19777
|
-
|
|
19778
|
-
|
|
19779
|
-
new GetEmailIdentityCommand2({ EmailIdentity: domain })
|
|
19780
|
-
);
|
|
19781
|
-
const dkimTokens = sesIdentity.DkimAttributes?.Tokens || [];
|
|
19810
|
+
dkimTokens = sesIdentity.DkimAttributes?.Tokens || [];
|
|
19811
|
+
}
|
|
19782
19812
|
let mailFromDomain;
|
|
19783
19813
|
if (options.yes) {
|
|
19784
19814
|
mailFromDomain = `mail.${domain}`;
|
|
@@ -20470,12 +20500,30 @@ async function inboundInit(options) {
|
|
|
20470
20500
|
if (!metadata?.services?.email) {
|
|
20471
20501
|
throw errors.inboundRequiresOutbound();
|
|
20472
20502
|
}
|
|
20473
|
-
const
|
|
20474
|
-
|
|
20475
|
-
const domain = emailConfig.domain;
|
|
20476
|
-
if (!domain) {
|
|
20503
|
+
const trackedDomains = getAllTrackedDomains(metadata);
|
|
20504
|
+
if (trackedDomains.length === 0) {
|
|
20477
20505
|
throw errors.inboundRequiresOutbound();
|
|
20478
20506
|
}
|
|
20507
|
+
let domain;
|
|
20508
|
+
if (trackedDomains.length === 1) {
|
|
20509
|
+
domain = trackedDomains[0].domain;
|
|
20510
|
+
} else {
|
|
20511
|
+
const selected = await clack22.select({
|
|
20512
|
+
message: "Which domain do you want to receive email on?",
|
|
20513
|
+
options: trackedDomains.map((d) => ({
|
|
20514
|
+
value: d.domain,
|
|
20515
|
+
label: d.domain,
|
|
20516
|
+
hint: d.isPrimary ? "primary" : d.purpose
|
|
20517
|
+
}))
|
|
20518
|
+
});
|
|
20519
|
+
if (clack22.isCancel(selected)) {
|
|
20520
|
+
clack22.cancel("Operation cancelled.");
|
|
20521
|
+
process.exit(0);
|
|
20522
|
+
}
|
|
20523
|
+
domain = selected;
|
|
20524
|
+
}
|
|
20525
|
+
const emailService = metadata.services.email;
|
|
20526
|
+
const emailConfig = emailService.config;
|
|
20479
20527
|
const subdomain = options.root ? "" : options.subdomain ?? (options.yes ? "inbound" : await promptInboundSubdomain(domain));
|
|
20480
20528
|
const receivingDomain = subdomain ? `${subdomain}.${domain}` : domain;
|
|
20481
20529
|
clack22.log.info(`Receiving domain: ${pc24.cyan(receivingDomain)}`);
|
|
@@ -21651,6 +21699,21 @@ async function init2(options) {
|
|
|
21651
21699
|
if (domain) {
|
|
21652
21700
|
emailConfig.domain = domain;
|
|
21653
21701
|
}
|
|
21702
|
+
if (domain && !options.quick && preset !== "custom") {
|
|
21703
|
+
const wantsMailFrom = await clack26.confirm({
|
|
21704
|
+
message: `Configure MAIL FROM for ${pc28.cyan(domain)}? ${pc28.dim("(improves DMARC alignment)")}`,
|
|
21705
|
+
initialValue: true
|
|
21706
|
+
});
|
|
21707
|
+
if (clack26.isCancel(wantsMailFrom)) {
|
|
21708
|
+
clack26.cancel("Operation cancelled.");
|
|
21709
|
+
process.exit(0);
|
|
21710
|
+
}
|
|
21711
|
+
if (wantsMailFrom) {
|
|
21712
|
+
const mailFromFull = await promptMailFromSubdomain(domain);
|
|
21713
|
+
const suffix = `.${domain}`;
|
|
21714
|
+
emailConfig.mailFromSubdomain = mailFromFull.endsWith(suffix) ? mailFromFull.slice(0, -suffix.length) || "mail" : "mail";
|
|
21715
|
+
}
|
|
21716
|
+
}
|
|
21654
21717
|
let costSummary;
|
|
21655
21718
|
if (!options.quick) {
|
|
21656
21719
|
const estimatedVolume = await promptEstimatedVolume();
|
|
@@ -22099,6 +22162,7 @@ ${pc28.yellow(pc28.bold("Configuration Warnings:"))}`);
|
|
|
22099
22162
|
tableName: outputs.tableName,
|
|
22100
22163
|
dnsRecords: void 0,
|
|
22101
22164
|
dnsAutoCreated,
|
|
22165
|
+
dnsProvider,
|
|
22102
22166
|
domain: outputs.domain,
|
|
22103
22167
|
mailFromDomain: outputs.mailFromDomain
|
|
22104
22168
|
});
|