@wraps.dev/cli 1.5.4 → 1.5.5
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
|
@@ -147,7 +147,7 @@ var require_package = __commonJS({
|
|
|
147
147
|
"package.json"(exports, module) {
|
|
148
148
|
module.exports = {
|
|
149
149
|
name: "@wraps.dev/cli",
|
|
150
|
-
version: "1.5.
|
|
150
|
+
version: "1.5.5",
|
|
151
151
|
description: "CLI for deploying Wraps email infrastructure to your AWS account",
|
|
152
152
|
type: "module",
|
|
153
153
|
main: "./dist/cli.js",
|
|
@@ -4184,34 +4184,139 @@ ${pc2.bold("Dashboard:")} ${pc2.blue("https://app.wraps.dev")}`);
|
|
|
4184
4184
|
console.log(`${pc2.bold("Docs:")} ${pc2.blue("https://wraps.dev/docs")}
|
|
4185
4185
|
`);
|
|
4186
4186
|
}
|
|
4187
|
-
function
|
|
4188
|
-
|
|
4189
|
-
|
|
4190
|
-
|
|
4191
|
-
|
|
4192
|
-
|
|
4193
|
-
|
|
4194
|
-
|
|
4195
|
-
|
|
4196
|
-
|
|
4197
|
-
|
|
4198
|
-
|
|
4199
|
-
|
|
4200
|
-
|
|
4201
|
-
|
|
4187
|
+
function formatResourceType(type) {
|
|
4188
|
+
const typeMap = {
|
|
4189
|
+
"aws:iam/role:Role": "IAM Role",
|
|
4190
|
+
"aws:iam/policy:Policy": "IAM Policy",
|
|
4191
|
+
"aws:iam/rolePolicyAttachment:RolePolicyAttachment": "IAM Policy Attachment",
|
|
4192
|
+
"aws:iam/openIdConnectProvider:OpenIdConnectProvider": "OIDC Provider",
|
|
4193
|
+
"aws:ses/configurationSet:ConfigurationSet": "SES Configuration Set",
|
|
4194
|
+
"aws:ses/emailIdentity:EmailIdentity": "SES Email Identity",
|
|
4195
|
+
"aws:ses/eventDestination:EventDestination": "SES Event Destination",
|
|
4196
|
+
"aws:sesv2/configurationSetEventDestination:ConfigurationSetEventDestination": "SES Event Destination",
|
|
4197
|
+
"aws:dynamodb/table:Table": "DynamoDB Table",
|
|
4198
|
+
"aws:lambda/function:Function": "Lambda Function",
|
|
4199
|
+
"aws:lambda/eventSourceMapping:EventSourceMapping": "Lambda Event Source",
|
|
4200
|
+
"aws:sqs/queue:Queue": "SQS Queue",
|
|
4201
|
+
"aws:cloudwatch/eventRule:EventRule": "EventBridge Rule",
|
|
4202
|
+
"aws:cloudwatch/eventTarget:EventTarget": "EventBridge Target",
|
|
4203
|
+
"aws:sns/topic:Topic": "SNS Topic",
|
|
4204
|
+
"aws:sns/topicSubscription:TopicSubscription": "SNS Subscription",
|
|
4205
|
+
"aws:s3/bucket:Bucket": "S3 Bucket",
|
|
4206
|
+
"aws:s3/bucketPolicy:BucketPolicy": "S3 Bucket Policy",
|
|
4207
|
+
"aws:cloudfront/distribution:Distribution": "CloudFront Distribution",
|
|
4208
|
+
"aws:acm/certificate:Certificate": "ACM Certificate",
|
|
4209
|
+
"aws:acm/certificateValidation:CertificateValidation": "ACM Validation",
|
|
4210
|
+
"aws:route53/record:Record": "Route53 Record",
|
|
4211
|
+
"pulumi:pulumi:Stack": "Pulumi Stack"
|
|
4212
|
+
};
|
|
4213
|
+
return typeMap[type] || type.split(":").pop() || type;
|
|
4214
|
+
}
|
|
4215
|
+
function getOperationIcon(operation) {
|
|
4216
|
+
switch (operation) {
|
|
4217
|
+
case "create":
|
|
4218
|
+
return pc2.green("+");
|
|
4219
|
+
case "update":
|
|
4220
|
+
return pc2.yellow("~");
|
|
4221
|
+
case "delete":
|
|
4222
|
+
return pc2.red("-");
|
|
4223
|
+
case "replace":
|
|
4224
|
+
return pc2.magenta("\xB1");
|
|
4225
|
+
case "same":
|
|
4226
|
+
return pc2.dim("=");
|
|
4227
|
+
default:
|
|
4228
|
+
return " ";
|
|
4202
4229
|
}
|
|
4203
|
-
|
|
4204
|
-
|
|
4230
|
+
}
|
|
4231
|
+
function getOperationLabel(operation) {
|
|
4232
|
+
switch (operation) {
|
|
4233
|
+
case "create":
|
|
4234
|
+
return pc2.green("CREATE");
|
|
4235
|
+
case "update":
|
|
4236
|
+
return pc2.yellow("UPDATE");
|
|
4237
|
+
case "delete":
|
|
4238
|
+
return pc2.red("DELETE");
|
|
4239
|
+
case "replace":
|
|
4240
|
+
return pc2.magenta("REPLACE");
|
|
4241
|
+
case "same":
|
|
4242
|
+
return pc2.dim("UNCHANGED");
|
|
4205
4243
|
}
|
|
4206
|
-
|
|
4207
|
-
|
|
4244
|
+
}
|
|
4245
|
+
function displayPreview(outputs) {
|
|
4246
|
+
console.log(pc2.yellow("\n\u2501\u2501\u2501 PREVIEW MODE (no changes will be made) \u2501\u2501\u2501\n"));
|
|
4247
|
+
if (outputs.resourceChanges && outputs.resourceChanges.length > 0) {
|
|
4248
|
+
const grouped = /* @__PURE__ */ new Map();
|
|
4249
|
+
for (const resource of outputs.resourceChanges) {
|
|
4250
|
+
const existing = grouped.get(resource.operation) || [];
|
|
4251
|
+
existing.push(resource);
|
|
4252
|
+
grouped.set(resource.operation, existing);
|
|
4253
|
+
}
|
|
4254
|
+
const operationOrder = [
|
|
4255
|
+
"create",
|
|
4256
|
+
"update",
|
|
4257
|
+
"replace",
|
|
4258
|
+
"delete",
|
|
4259
|
+
"same"
|
|
4260
|
+
];
|
|
4261
|
+
const sections = [];
|
|
4262
|
+
for (const operation of operationOrder) {
|
|
4263
|
+
const resources = grouped.get(operation);
|
|
4264
|
+
if (!resources || resources.length === 0) continue;
|
|
4265
|
+
if (operation === "same" && outputs.resourceChanges.length > 10) {
|
|
4266
|
+
sections.push(
|
|
4267
|
+
`${getOperationLabel(operation)} ${pc2.dim(`(${resources.length} resources)`)}`
|
|
4268
|
+
);
|
|
4269
|
+
continue;
|
|
4270
|
+
}
|
|
4271
|
+
const resourceLines = resources.map((r) => {
|
|
4272
|
+
const icon = getOperationIcon(operation);
|
|
4273
|
+
const typeLabel = pc2.dim(`(${formatResourceType(r.type)})`);
|
|
4274
|
+
let line = ` ${icon} ${r.name} ${typeLabel}`;
|
|
4275
|
+
if (r.diffs && r.diffs.length > 0 && operation === "update") {
|
|
4276
|
+
const diffStr = r.diffs.slice(0, 3).join(", ");
|
|
4277
|
+
const more = r.diffs.length > 3 ? ` +${r.diffs.length - 3} more` : "";
|
|
4278
|
+
line += `
|
|
4279
|
+
${pc2.dim(`changed: ${diffStr}${more}`)}`;
|
|
4280
|
+
}
|
|
4281
|
+
return line;
|
|
4282
|
+
}).join("\n");
|
|
4283
|
+
sections.push(
|
|
4284
|
+
`${getOperationLabel(operation)} ${pc2.dim(`(${resources.length})`)}
|
|
4285
|
+
${resourceLines}`
|
|
4286
|
+
);
|
|
4287
|
+
}
|
|
4288
|
+
if (sections.length > 0) {
|
|
4289
|
+
console.log(sections.join("\n\n"));
|
|
4290
|
+
console.log();
|
|
4291
|
+
}
|
|
4208
4292
|
} else {
|
|
4209
|
-
|
|
4293
|
+
const changes = outputs.changeSummary;
|
|
4294
|
+
const summaryLines = [];
|
|
4295
|
+
if (changes.create && changes.create > 0) {
|
|
4296
|
+
summaryLines.push(` ${pc2.green("+")} ${changes.create} to create`);
|
|
4297
|
+
}
|
|
4298
|
+
if (changes.update && changes.update > 0) {
|
|
4299
|
+
summaryLines.push(` ${pc2.yellow("~")} ${changes.update} to update`);
|
|
4300
|
+
}
|
|
4301
|
+
if (changes.delete && changes.delete > 0) {
|
|
4302
|
+
summaryLines.push(` ${pc2.red("-")} ${changes.delete} to destroy`);
|
|
4303
|
+
}
|
|
4304
|
+
if (changes.same && changes.same > 0) {
|
|
4305
|
+
summaryLines.push(` ${pc2.dim("=")} ${changes.same} unchanged`);
|
|
4306
|
+
}
|
|
4307
|
+
if (changes.replace && changes.replace > 0) {
|
|
4308
|
+
summaryLines.push(` ${pc2.magenta("\xB1")} ${changes.replace} to replace`);
|
|
4309
|
+
}
|
|
4310
|
+
if (summaryLines.length > 0) {
|
|
4311
|
+
clack2.note(summaryLines.join("\n"), "Resource Changes");
|
|
4312
|
+
} else {
|
|
4313
|
+
clack2.note("No changes detected", "Resource Changes");
|
|
4314
|
+
}
|
|
4210
4315
|
}
|
|
4211
4316
|
if (outputs.costEstimate) {
|
|
4212
4317
|
clack2.note(outputs.costEstimate, "Estimated Monthly Cost");
|
|
4213
4318
|
}
|
|
4214
|
-
console.log(pc2.yellow("\
|
|
4319
|
+
console.log(pc2.yellow("\u2501\u2501\u2501 END PREVIEW (no changes were made) \u2501\u2501\u2501\n"));
|
|
4215
4320
|
}
|
|
4216
4321
|
|
|
4217
4322
|
// src/commands/dashboard/update-role.ts
|
|
@@ -4649,7 +4754,7 @@ async function roleExists(roleName) {
|
|
|
4649
4754
|
await iam5.send(new GetRoleCommand2({ RoleName: roleName }));
|
|
4650
4755
|
return true;
|
|
4651
4756
|
} catch (error) {
|
|
4652
|
-
if (error.name === "NoSuchEntityException") {
|
|
4757
|
+
if (error.name === "NoSuchEntityException" || error.Code === "NoSuchEntity" || error.Error?.Code === "NoSuchEntity") {
|
|
4653
4758
|
return false;
|
|
4654
4759
|
}
|
|
4655
4760
|
console.error("Error checking for existing IAM role:", error);
|
|
@@ -5257,6 +5362,66 @@ async function ensurePulumiInstalled() {
|
|
|
5257
5362
|
}
|
|
5258
5363
|
return false;
|
|
5259
5364
|
}
|
|
5365
|
+
function mapOperationType(op) {
|
|
5366
|
+
switch (op) {
|
|
5367
|
+
case "create":
|
|
5368
|
+
return "create";
|
|
5369
|
+
case "update":
|
|
5370
|
+
return "update";
|
|
5371
|
+
case "delete":
|
|
5372
|
+
return "delete";
|
|
5373
|
+
case "replace":
|
|
5374
|
+
case "create-replacement":
|
|
5375
|
+
case "delete-replaced":
|
|
5376
|
+
return "replace";
|
|
5377
|
+
case "same":
|
|
5378
|
+
case "read":
|
|
5379
|
+
return "same";
|
|
5380
|
+
default:
|
|
5381
|
+
return "same";
|
|
5382
|
+
}
|
|
5383
|
+
}
|
|
5384
|
+
async function previewWithResourceChanges(stack, options) {
|
|
5385
|
+
const resourceChanges = [];
|
|
5386
|
+
const seenResources = /* @__PURE__ */ new Set();
|
|
5387
|
+
const result = await stack.preview({
|
|
5388
|
+
diff: options?.diff ?? true,
|
|
5389
|
+
onEvent: (event) => {
|
|
5390
|
+
if (event.resourcePreEvent) {
|
|
5391
|
+
const metadata = event.resourcePreEvent.metadata;
|
|
5392
|
+
if (metadata) {
|
|
5393
|
+
const resourceKey = `${metadata.type}::${metadata.urn}`;
|
|
5394
|
+
if (seenResources.has(resourceKey)) {
|
|
5395
|
+
return;
|
|
5396
|
+
}
|
|
5397
|
+
seenResources.add(resourceKey);
|
|
5398
|
+
if (metadata.type === "pulumi:pulumi:Stack") {
|
|
5399
|
+
return;
|
|
5400
|
+
}
|
|
5401
|
+
const operation = mapOperationType(metadata.op || "same");
|
|
5402
|
+
const urnParts = metadata.urn?.split("::") || [];
|
|
5403
|
+
const name = urnParts[urnParts.length - 1] || metadata.urn || "unknown";
|
|
5404
|
+
const diffs = [];
|
|
5405
|
+
if (metadata.diffs && metadata.diffs.length > 0) {
|
|
5406
|
+
for (const diff of metadata.diffs) {
|
|
5407
|
+
diffs.push(diff);
|
|
5408
|
+
}
|
|
5409
|
+
}
|
|
5410
|
+
resourceChanges.push({
|
|
5411
|
+
name,
|
|
5412
|
+
type: metadata.type || "unknown",
|
|
5413
|
+
operation,
|
|
5414
|
+
diffs: diffs.length > 0 ? diffs : void 0
|
|
5415
|
+
});
|
|
5416
|
+
}
|
|
5417
|
+
}
|
|
5418
|
+
}
|
|
5419
|
+
});
|
|
5420
|
+
return {
|
|
5421
|
+
...result,
|
|
5422
|
+
resourceChanges
|
|
5423
|
+
};
|
|
5424
|
+
}
|
|
5260
5425
|
|
|
5261
5426
|
// src/commands/email/config.ts
|
|
5262
5427
|
async function config(options) {
|
|
@@ -5398,12 +5563,13 @@ ${pc4.bold("Current Configuration:")}
|
|
|
5398
5563
|
await stack.setConfig("aws:region", { value: region });
|
|
5399
5564
|
await stack.refresh({ onOutput: () => {
|
|
5400
5565
|
} });
|
|
5401
|
-
const result = await stack
|
|
5566
|
+
const result = await previewWithResourceChanges(stack, { diff: true });
|
|
5402
5567
|
return result;
|
|
5403
5568
|
}
|
|
5404
5569
|
);
|
|
5405
5570
|
displayPreview({
|
|
5406
5571
|
changeSummary: previewResult.changeSummary,
|
|
5572
|
+
resourceChanges: previewResult.resourceChanges,
|
|
5407
5573
|
commandName: "wraps email config"
|
|
5408
5574
|
});
|
|
5409
5575
|
clack3.outro(
|
|
@@ -5892,12 +6058,13 @@ async function connect(options) {
|
|
|
5892
6058
|
}
|
|
5893
6059
|
);
|
|
5894
6060
|
await stack.setConfig("aws:region", { value: region });
|
|
5895
|
-
const result = await stack
|
|
6061
|
+
const result = await previewWithResourceChanges(stack, { diff: true });
|
|
5896
6062
|
return result;
|
|
5897
6063
|
}
|
|
5898
6064
|
);
|
|
5899
6065
|
displayPreview({
|
|
5900
6066
|
changeSummary: previewResult.changeSummary,
|
|
6067
|
+
resourceChanges: previewResult.resourceChanges,
|
|
5901
6068
|
commandName: "wraps email connect"
|
|
5902
6069
|
});
|
|
5903
6070
|
clack5.outro(
|
|
@@ -6190,12 +6357,13 @@ async function emailDestroy(options) {
|
|
|
6190
6357
|
} catch (_error) {
|
|
6191
6358
|
throw new Error("No email infrastructure found to preview");
|
|
6192
6359
|
}
|
|
6193
|
-
const result = await stack
|
|
6360
|
+
const result = await previewWithResourceChanges(stack, { diff: true });
|
|
6194
6361
|
return result;
|
|
6195
6362
|
}
|
|
6196
6363
|
);
|
|
6197
6364
|
displayPreview({
|
|
6198
6365
|
changeSummary: previewResult.changeSummary,
|
|
6366
|
+
resourceChanges: previewResult.resourceChanges,
|
|
6199
6367
|
costEstimate: "Monthly cost after destruction: $0.00",
|
|
6200
6368
|
commandName: "wraps email destroy"
|
|
6201
6369
|
});
|
|
@@ -6909,12 +7077,13 @@ ${pc9.yellow(pc9.bold("Configuration Warnings:"))}`);
|
|
|
6909
7077
|
}
|
|
6910
7078
|
);
|
|
6911
7079
|
await stack.setConfig("aws:region", { value: region });
|
|
6912
|
-
const result = await stack
|
|
7080
|
+
const result = await previewWithResourceChanges(stack, { diff: true });
|
|
6913
7081
|
return result;
|
|
6914
7082
|
}
|
|
6915
7083
|
);
|
|
6916
7084
|
displayPreview({
|
|
6917
7085
|
changeSummary: previewResult.changeSummary,
|
|
7086
|
+
resourceChanges: previewResult.resourceChanges,
|
|
6918
7087
|
costEstimate: costSummary,
|
|
6919
7088
|
commandName: "wraps email init"
|
|
6920
7089
|
});
|
|
@@ -7213,12 +7382,13 @@ ${pc10.bold("The following Wraps resources will be removed:")}
|
|
|
7213
7382
|
secretsProvider: "passphrase"
|
|
7214
7383
|
}
|
|
7215
7384
|
);
|
|
7216
|
-
const result = await stack
|
|
7385
|
+
const result = await previewWithResourceChanges(stack, { diff: true });
|
|
7217
7386
|
return result;
|
|
7218
7387
|
}
|
|
7219
7388
|
);
|
|
7220
7389
|
displayPreview({
|
|
7221
7390
|
changeSummary: previewResult.changeSummary,
|
|
7391
|
+
resourceChanges: previewResult.resourceChanges,
|
|
7222
7392
|
costEstimate: "Monthly cost after removal: $0.00",
|
|
7223
7393
|
commandName: "wraps email restore"
|
|
7224
7394
|
});
|
|
@@ -8117,7 +8287,7 @@ ${pc12.bold("Cost Impact:")}`);
|
|
|
8117
8287
|
await stack.setConfig("aws:region", { value: region });
|
|
8118
8288
|
await stack.refresh({ onOutput: () => {
|
|
8119
8289
|
} });
|
|
8120
|
-
const result = await stack
|
|
8290
|
+
const result = await previewWithResourceChanges(stack, { diff: true });
|
|
8121
8291
|
return result;
|
|
8122
8292
|
}
|
|
8123
8293
|
);
|
|
@@ -8128,6 +8298,7 @@ ${pc12.bold("Cost Impact:")}`);
|
|
|
8128
8298
|
].join("\n");
|
|
8129
8299
|
displayPreview({
|
|
8130
8300
|
changeSummary: previewResult.changeSummary,
|
|
8301
|
+
resourceChanges: previewResult.resourceChanges,
|
|
8131
8302
|
costEstimate: costComparison,
|
|
8132
8303
|
commandName: "wraps email upgrade"
|
|
8133
8304
|
});
|
|
@@ -10662,7 +10833,7 @@ async function roleExists2(roleName) {
|
|
|
10662
10833
|
await iam5.send(new GetRoleCommand2({ RoleName: roleName }));
|
|
10663
10834
|
return true;
|
|
10664
10835
|
} catch (error) {
|
|
10665
|
-
if (error
|
|
10836
|
+
if (error.name === "NoSuchEntityException" || error.Code === "NoSuchEntity" || error.Error?.Code === "NoSuchEntity") {
|
|
10666
10837
|
return false;
|
|
10667
10838
|
}
|
|
10668
10839
|
return false;
|
|
@@ -11610,12 +11781,13 @@ async function smsDestroy(options) {
|
|
|
11610
11781
|
} catch (_error) {
|
|
11611
11782
|
throw new Error("No SMS infrastructure found to preview");
|
|
11612
11783
|
}
|
|
11613
|
-
const result = await stack
|
|
11784
|
+
const result = await previewWithResourceChanges(stack, { diff: true });
|
|
11614
11785
|
return result;
|
|
11615
11786
|
}
|
|
11616
11787
|
);
|
|
11617
11788
|
displayPreview({
|
|
11618
11789
|
changeSummary: previewResult.changeSummary,
|
|
11790
|
+
resourceChanges: previewResult.resourceChanges,
|
|
11619
11791
|
costEstimate: "Monthly cost after destruction: $0.00",
|
|
11620
11792
|
commandName: "wraps sms destroy"
|
|
11621
11793
|
});
|