@wraps.dev/cli 1.4.0 → 1.4.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 +83 -47
- package/dist/cli.js.map +1 -1
- package/dist/lambda/event-processor/.bundled +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -146,7 +146,7 @@ var require_package = __commonJS({
|
|
|
146
146
|
"package.json"(exports, module) {
|
|
147
147
|
module.exports = {
|
|
148
148
|
name: "@wraps.dev/cli",
|
|
149
|
-
version: "1.4.
|
|
149
|
+
version: "1.4.1",
|
|
150
150
|
description: "CLI for deploying Wraps email infrastructure to your AWS account",
|
|
151
151
|
type: "module",
|
|
152
152
|
main: "./dist/cli.js",
|
|
@@ -546,6 +546,12 @@ To remove: wraps destroy --stack ${stackName}`,
|
|
|
546
546
|
"PULUMI_NOT_INSTALLED",
|
|
547
547
|
"Install Pulumi:\n macOS: brew install pulumi/tap/pulumi\n Linux: curl -fsSL https://get.pulumi.com | sh\n Windows: choco install pulumi\n\nOr download from: https://www.pulumi.com/docs/install/",
|
|
548
548
|
"https://www.pulumi.com/docs/install/"
|
|
549
|
+
),
|
|
550
|
+
stackLocked: () => new WrapsError(
|
|
551
|
+
"The Pulumi stack is locked from a previous run",
|
|
552
|
+
"STACK_LOCKED",
|
|
553
|
+
"This happens when a previous deployment was interrupted.\n\nTo unlock, run:\n rm -rf ~/.wraps/pulumi/.pulumi/locks\n\nThen try your command again.",
|
|
554
|
+
"https://wraps.dev/docs/troubleshooting"
|
|
549
555
|
)
|
|
550
556
|
};
|
|
551
557
|
}
|
|
@@ -3792,7 +3798,7 @@ Try running: pnpm build`
|
|
|
3792
3798
|
entryPoints: [sourcePath],
|
|
3793
3799
|
bundle: true,
|
|
3794
3800
|
platform: "node",
|
|
3795
|
-
target: "
|
|
3801
|
+
target: "node24",
|
|
3796
3802
|
format: "esm",
|
|
3797
3803
|
outfile: join3(outdir, "index.mjs"),
|
|
3798
3804
|
external: ["@aws-sdk/*"],
|
|
@@ -3864,7 +3870,7 @@ async function deployLambdaFunctions(config2) {
|
|
|
3864
3870
|
functionName,
|
|
3865
3871
|
{
|
|
3866
3872
|
name: functionName,
|
|
3867
|
-
runtime:
|
|
3873
|
+
runtime: "nodejs24.x",
|
|
3868
3874
|
handler: "index.handler",
|
|
3869
3875
|
role: lambdaRole.arn,
|
|
3870
3876
|
code: new pulumi3.asset.FileArchive(eventProcessorCode),
|
|
@@ -3888,7 +3894,7 @@ async function deployLambdaFunctions(config2) {
|
|
|
3888
3894
|
}
|
|
3889
3895
|
) : new aws4.lambda.Function(functionName, {
|
|
3890
3896
|
name: functionName,
|
|
3891
|
-
runtime:
|
|
3897
|
+
runtime: "nodejs24.x",
|
|
3892
3898
|
handler: "index.handler",
|
|
3893
3899
|
role: lambdaRole.arn,
|
|
3894
3900
|
code: new pulumi3.asset.FileArchive(eventProcessorCode),
|
|
@@ -3957,6 +3963,28 @@ async function configurationSetExists(configSetName, region) {
|
|
|
3957
3963
|
return false;
|
|
3958
3964
|
}
|
|
3959
3965
|
}
|
|
3966
|
+
async function eventDestinationExists(configSetName, eventDestName, region) {
|
|
3967
|
+
try {
|
|
3968
|
+
const {
|
|
3969
|
+
SESv2Client: SESv2Client5,
|
|
3970
|
+
GetConfigurationSetEventDestinationsCommand
|
|
3971
|
+
} = await import("@aws-sdk/client-sesv2");
|
|
3972
|
+
const ses = new SESv2Client5({ region });
|
|
3973
|
+
const response = await ses.send(
|
|
3974
|
+
new GetConfigurationSetEventDestinationsCommand({
|
|
3975
|
+
ConfigurationSetName: configSetName
|
|
3976
|
+
})
|
|
3977
|
+
);
|
|
3978
|
+
return response.EventDestinations?.some(
|
|
3979
|
+
(dest) => dest.Name === eventDestName
|
|
3980
|
+
) ?? false;
|
|
3981
|
+
} catch (error) {
|
|
3982
|
+
if (error.name === "NotFoundException") {
|
|
3983
|
+
return false;
|
|
3984
|
+
}
|
|
3985
|
+
return false;
|
|
3986
|
+
}
|
|
3987
|
+
}
|
|
3960
3988
|
async function emailIdentityExists(emailIdentity, region) {
|
|
3961
3989
|
try {
|
|
3962
3990
|
const { SESv2Client: SESv2Client5, GetEmailIdentityCommand: GetEmailIdentityCommand4 } = await import("@aws-sdk/client-sesv2");
|
|
@@ -4010,29 +4038,37 @@ async function createSESResources(config2) {
|
|
|
4010
4038
|
});
|
|
4011
4039
|
if (config2.eventTrackingEnabled) {
|
|
4012
4040
|
const eventDestName = "wraps-email-eventbridge";
|
|
4013
|
-
new aws5.sesv2.ConfigurationSetEventDestination(
|
|
4014
|
-
|
|
4015
|
-
|
|
4016
|
-
|
|
4017
|
-
|
|
4018
|
-
|
|
4019
|
-
|
|
4020
|
-
|
|
4021
|
-
|
|
4022
|
-
|
|
4023
|
-
|
|
4024
|
-
|
|
4025
|
-
|
|
4026
|
-
|
|
4027
|
-
|
|
4028
|
-
|
|
4029
|
-
|
|
4030
|
-
|
|
4031
|
-
|
|
4032
|
-
|
|
4041
|
+
new aws5.sesv2.ConfigurationSetEventDestination(
|
|
4042
|
+
"wraps-email-all-events",
|
|
4043
|
+
{
|
|
4044
|
+
configurationSetName: configSet.configurationSetName,
|
|
4045
|
+
eventDestinationName: eventDestName,
|
|
4046
|
+
eventDestination: {
|
|
4047
|
+
enabled: true,
|
|
4048
|
+
matchingEventTypes: [
|
|
4049
|
+
"SEND",
|
|
4050
|
+
"DELIVERY",
|
|
4051
|
+
"OPEN",
|
|
4052
|
+
"CLICK",
|
|
4053
|
+
"BOUNCE",
|
|
4054
|
+
"COMPLAINT",
|
|
4055
|
+
"REJECT",
|
|
4056
|
+
"RENDERING_FAILURE",
|
|
4057
|
+
"DELIVERY_DELAY",
|
|
4058
|
+
"SUBSCRIPTION"
|
|
4059
|
+
],
|
|
4060
|
+
eventBridgeDestination: {
|
|
4061
|
+
// SES requires default bus - cannot use custom bus
|
|
4062
|
+
eventBusArn: defaultEventBus.arn
|
|
4063
|
+
}
|
|
4033
4064
|
}
|
|
4065
|
+
},
|
|
4066
|
+
{
|
|
4067
|
+
// Import existing resource if it already exists in AWS
|
|
4068
|
+
// This prevents AlreadyExistsException when the resource exists but isn't in Pulumi state
|
|
4069
|
+
import: config2.importExistingEventDestination ? `wraps-email-tracking|${eventDestName}` : void 0
|
|
4034
4070
|
}
|
|
4035
|
-
|
|
4071
|
+
);
|
|
4036
4072
|
}
|
|
4037
4073
|
let domainIdentity;
|
|
4038
4074
|
let dkimTokens;
|
|
@@ -4244,6 +4280,11 @@ async function deployEmailStack(config2) {
|
|
|
4244
4280
|
}
|
|
4245
4281
|
let sesResources;
|
|
4246
4282
|
if (emailConfig.tracking?.enabled || emailConfig.eventTracking?.enabled) {
|
|
4283
|
+
const shouldImportEventDest = emailConfig.eventTracking?.enabled && await eventDestinationExists(
|
|
4284
|
+
"wraps-email-tracking",
|
|
4285
|
+
"wraps-email-eventbridge",
|
|
4286
|
+
config2.region
|
|
4287
|
+
);
|
|
4247
4288
|
sesResources = await createSESResources({
|
|
4248
4289
|
domain: emailConfig.domain,
|
|
4249
4290
|
mailFromDomain: emailConfig.mailFromDomain,
|
|
@@ -4252,8 +4293,10 @@ async function deployEmailStack(config2) {
|
|
|
4252
4293
|
eventTypes: emailConfig.eventTracking?.events,
|
|
4253
4294
|
eventTrackingEnabled: emailConfig.eventTracking?.enabled,
|
|
4254
4295
|
// Pass flag to create EventBridge destination
|
|
4255
|
-
tlsRequired: emailConfig.tlsRequired
|
|
4296
|
+
tlsRequired: emailConfig.tlsRequired,
|
|
4256
4297
|
// Require TLS encryption for all emails
|
|
4298
|
+
importExistingEventDestination: shouldImportEventDest
|
|
4299
|
+
// Import if exists to avoid AlreadyExistsException
|
|
4257
4300
|
});
|
|
4258
4301
|
}
|
|
4259
4302
|
let dynamoTables;
|
|
@@ -4318,6 +4361,7 @@ async function deployEmailStack(config2) {
|
|
|
4318
4361
|
|
|
4319
4362
|
// src/commands/email/config.ts
|
|
4320
4363
|
init_aws();
|
|
4364
|
+
init_errors();
|
|
4321
4365
|
|
|
4322
4366
|
// src/utils/shared/pulumi.ts
|
|
4323
4367
|
init_esm_shims();
|
|
@@ -4484,6 +4528,8 @@ ${pc4.bold("Current Configuration:")}
|
|
|
4484
4528
|
metadata.services.email?.pulumiStackName || `wraps-${identity.accountId}-${region}`
|
|
4485
4529
|
);
|
|
4486
4530
|
await stack.setConfig("aws:region", { value: region });
|
|
4531
|
+
await stack.refresh({ onOutput: () => {
|
|
4532
|
+
} });
|
|
4487
4533
|
const upResult = await stack.up({ onOutput: () => {
|
|
4488
4534
|
} });
|
|
4489
4535
|
const pulumiOutputs = upResult.outputs;
|
|
@@ -4500,12 +4546,8 @@ ${pc4.bold("Current Configuration:")}
|
|
|
4500
4546
|
}
|
|
4501
4547
|
);
|
|
4502
4548
|
} catch (error) {
|
|
4503
|
-
clack3.log.error("Infrastructure update failed");
|
|
4504
4549
|
if (error.message?.includes("stack is currently locked")) {
|
|
4505
|
-
|
|
4506
|
-
clack3.log.info("To fix this, run:");
|
|
4507
|
-
clack3.log.info(` ${pc4.cyan("rm -rf ~/.wraps/pulumi/.pulumi/locks")}`);
|
|
4508
|
-
clack3.log.info("\nThen try running wraps update again.");
|
|
4550
|
+
throw errors.stackLocked();
|
|
4509
4551
|
}
|
|
4510
4552
|
throw new Error(`Pulumi update failed: ${error.message}`);
|
|
4511
4553
|
}
|
|
@@ -4546,6 +4588,7 @@ import * as pulumi6 from "@pulumi/pulumi";
|
|
|
4546
4588
|
import pc6 from "picocolors";
|
|
4547
4589
|
init_presets();
|
|
4548
4590
|
init_aws();
|
|
4591
|
+
init_errors();
|
|
4549
4592
|
init_prompts();
|
|
4550
4593
|
|
|
4551
4594
|
// src/utils/shared/scanner.ts
|
|
@@ -4920,12 +4963,8 @@ async function connect(options) {
|
|
|
4920
4963
|
}
|
|
4921
4964
|
);
|
|
4922
4965
|
} catch (error) {
|
|
4923
|
-
clack5.log.error("Infrastructure deployment failed");
|
|
4924
4966
|
if (error.message?.includes("stack is currently locked")) {
|
|
4925
|
-
|
|
4926
|
-
clack5.log.info("To fix this, run:");
|
|
4927
|
-
clack5.log.info(` ${pc6.cyan("rm -rf ~/.wraps/pulumi/.pulumi/locks")}`);
|
|
4928
|
-
clack5.log.info("\nThen try running wraps email connect again.");
|
|
4967
|
+
throw errors.stackLocked();
|
|
4929
4968
|
}
|
|
4930
4969
|
throw new Error(`Pulumi deployment failed: ${error.message}`);
|
|
4931
4970
|
}
|
|
@@ -5423,6 +5462,7 @@ import pc8 from "picocolors";
|
|
|
5423
5462
|
init_costs();
|
|
5424
5463
|
init_presets();
|
|
5425
5464
|
init_aws();
|
|
5465
|
+
init_errors();
|
|
5426
5466
|
init_prompts();
|
|
5427
5467
|
async function init(options) {
|
|
5428
5468
|
clack7.intro(pc8.bold("Wraps Email Infrastructure Setup"));
|
|
@@ -5584,12 +5624,8 @@ ${pc8.yellow(pc8.bold("Configuration Warnings:"))}`);
|
|
|
5584
5624
|
}
|
|
5585
5625
|
);
|
|
5586
5626
|
} catch (error) {
|
|
5587
|
-
clack7.log.error("Infrastructure deployment failed");
|
|
5588
5627
|
if (error.message?.includes("stack is currently locked")) {
|
|
5589
|
-
|
|
5590
|
-
clack7.log.info("To fix this, run:");
|
|
5591
|
-
clack7.log.info(` ${pc8.cyan("rm -rf ~/.wraps/pulumi/.pulumi/locks")}`);
|
|
5592
|
-
clack7.log.info("\nThen try running wraps email init again.");
|
|
5628
|
+
throw errors.stackLocked();
|
|
5593
5629
|
}
|
|
5594
5630
|
throw new Error(`Pulumi deployment failed: ${error.message}`);
|
|
5595
5631
|
}
|
|
@@ -5762,6 +5798,7 @@ import pc10 from "picocolors";
|
|
|
5762
5798
|
init_costs();
|
|
5763
5799
|
init_presets();
|
|
5764
5800
|
init_aws();
|
|
5801
|
+
init_errors();
|
|
5765
5802
|
init_prompts();
|
|
5766
5803
|
async function upgrade(options) {
|
|
5767
5804
|
clack9.intro(pc10.bold("Wraps Upgrade - Enhance Your Email Infrastructure"));
|
|
@@ -6483,12 +6520,8 @@ ${pc10.bold("Cost Impact:")}`);
|
|
|
6483
6520
|
}
|
|
6484
6521
|
);
|
|
6485
6522
|
} catch (error) {
|
|
6486
|
-
clack9.log.error("Infrastructure upgrade failed");
|
|
6487
6523
|
if (error.message?.includes("stack is currently locked")) {
|
|
6488
|
-
|
|
6489
|
-
clack9.log.info("To fix this, run:");
|
|
6490
|
-
clack9.log.info(` ${pc10.cyan("rm -rf ~/.wraps/pulumi/.pulumi/locks")}`);
|
|
6491
|
-
clack9.log.info("\nThen try running wraps upgrade again.");
|
|
6524
|
+
throw errors.stackLocked();
|
|
6492
6525
|
}
|
|
6493
6526
|
throw new Error(`Pulumi upgrade failed: ${error.message}`);
|
|
6494
6527
|
}
|
|
@@ -8142,7 +8175,9 @@ function showHelp() {
|
|
|
8142
8175
|
` ${pc15.cyan("email connect")} Connect to existing AWS SES`
|
|
8143
8176
|
);
|
|
8144
8177
|
console.log(` ${pc15.cyan("email domains verify")} Verify domain DNS records`);
|
|
8145
|
-
console.log(
|
|
8178
|
+
console.log(
|
|
8179
|
+
` ${pc15.cyan("email sync")} Apply CLI updates to infrastructure`
|
|
8180
|
+
);
|
|
8146
8181
|
console.log(` ${pc15.cyan("email upgrade")} Add features`);
|
|
8147
8182
|
console.log(
|
|
8148
8183
|
` ${pc15.cyan("email restore")} Restore original configuration
|
|
@@ -8347,6 +8382,7 @@ async function run() {
|
|
|
8347
8382
|
});
|
|
8348
8383
|
break;
|
|
8349
8384
|
case "config":
|
|
8385
|
+
case "sync":
|
|
8350
8386
|
await config({
|
|
8351
8387
|
region: flags.region,
|
|
8352
8388
|
yes: flags.yes
|