@wraps.dev/cli 2.15.1 → 2.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js
CHANGED
|
@@ -65,6 +65,7 @@ var init_ci_detection = __esm({
|
|
|
65
65
|
// src/utils/shared/s3-state.ts
|
|
66
66
|
var s3_state_exports = {};
|
|
67
67
|
__export(s3_state_exports, {
|
|
68
|
+
clearS3StackLocks: () => clearS3StackLocks,
|
|
68
69
|
deleteMetadata: () => deleteMetadata,
|
|
69
70
|
downloadMetadata: () => downloadMetadata,
|
|
70
71
|
ensureStateBucket: () => ensureStateBucket,
|
|
@@ -196,6 +197,27 @@ async function deleteMetadata(bucketName, accountId, region) {
|
|
|
196
197
|
})
|
|
197
198
|
);
|
|
198
199
|
}
|
|
200
|
+
async function clearS3StackLocks(accountId, region) {
|
|
201
|
+
const { S3Client: S3Client2, ListObjectsV2Command: ListObjectsV2Command2, DeleteObjectCommand } = await import("@aws-sdk/client-s3");
|
|
202
|
+
const client = new S3Client2({ region });
|
|
203
|
+
const bucketName = getStateBucketName(accountId, region);
|
|
204
|
+
const prefix = ".pulumi/locks/";
|
|
205
|
+
const response = await client.send(
|
|
206
|
+
new ListObjectsV2Command2({ Bucket: bucketName, Prefix: prefix })
|
|
207
|
+
);
|
|
208
|
+
const lockObjects = response.Contents ?? [];
|
|
209
|
+
if (lockObjects.length === 0) {
|
|
210
|
+
return 0;
|
|
211
|
+
}
|
|
212
|
+
for (const obj of lockObjects) {
|
|
213
|
+
if (obj.Key) {
|
|
214
|
+
await client.send(
|
|
215
|
+
new DeleteObjectCommand({ Bucket: bucketName, Key: obj.Key })
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
return lockObjects.length;
|
|
220
|
+
}
|
|
199
221
|
async function downloadMetadata(bucketName, accountId, region) {
|
|
200
222
|
const { S3Client: S3Client2, GetObjectCommand: GetObjectCommand2 } = await import("@aws-sdk/client-s3");
|
|
201
223
|
const client = new S3Client2({ region });
|
|
@@ -302,8 +324,16 @@ var init_s3_state = __esm({
|
|
|
302
324
|
});
|
|
303
325
|
|
|
304
326
|
// src/utils/shared/fs.ts
|
|
327
|
+
var fs_exports = {};
|
|
328
|
+
__export(fs_exports, {
|
|
329
|
+
clearLocalStackLocks: () => clearLocalStackLocks,
|
|
330
|
+
ensurePulumiWorkDir: () => ensurePulumiWorkDir,
|
|
331
|
+
ensureWrapsDir: () => ensureWrapsDir,
|
|
332
|
+
getPulumiWorkDir: () => getPulumiWorkDir,
|
|
333
|
+
getWrapsDir: () => getWrapsDir
|
|
334
|
+
});
|
|
305
335
|
import { existsSync as existsSync2 } from "fs";
|
|
306
|
-
import { mkdir } from "fs/promises";
|
|
336
|
+
import { mkdir, readdir as readdir2, rm } from "fs/promises";
|
|
307
337
|
import { homedir } from "os";
|
|
308
338
|
import { join as join2 } from "path";
|
|
309
339
|
function getWrapsDir() {
|
|
@@ -318,6 +348,27 @@ async function ensureWrapsDir() {
|
|
|
318
348
|
await mkdir(wrapsDir, { recursive: true });
|
|
319
349
|
}
|
|
320
350
|
}
|
|
351
|
+
async function clearLocalStackLocks() {
|
|
352
|
+
const locksDir = join2(getPulumiWorkDir(), ".pulumi", "locks");
|
|
353
|
+
if (!existsSync2(locksDir)) {
|
|
354
|
+
return 0;
|
|
355
|
+
}
|
|
356
|
+
let count = 0;
|
|
357
|
+
async function walkAndDelete(dir) {
|
|
358
|
+
const entries = await readdir2(dir, { withFileTypes: true });
|
|
359
|
+
for (const entry of entries) {
|
|
360
|
+
const fullPath = join2(dir, entry.name);
|
|
361
|
+
if (entry.isDirectory()) {
|
|
362
|
+
await walkAndDelete(fullPath);
|
|
363
|
+
} else if (entry.name.endsWith(".json")) {
|
|
364
|
+
await rm(fullPath);
|
|
365
|
+
count++;
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
await walkAndDelete(locksDir);
|
|
370
|
+
return count;
|
|
371
|
+
}
|
|
321
372
|
async function ensurePulumiWorkDir(options) {
|
|
322
373
|
await ensureWrapsDir();
|
|
323
374
|
const pulumiDir = getPulumiWorkDir();
|
|
@@ -3383,6 +3434,28 @@ async function promptDNSProvider(domain, availableProviders) {
|
|
|
3383
3434
|
return provider;
|
|
3384
3435
|
}
|
|
3385
3436
|
async function promptInboundSubdomain(domain) {
|
|
3437
|
+
const choice = await clack6.select({
|
|
3438
|
+
message: `Where should ${pc7.cyan(domain)} receive inbound email?`,
|
|
3439
|
+
options: [
|
|
3440
|
+
{
|
|
3441
|
+
value: "",
|
|
3442
|
+
label: `${domain} (root domain)`,
|
|
3443
|
+
hint: `e.g., support@${domain}`
|
|
3444
|
+
},
|
|
3445
|
+
{
|
|
3446
|
+
value: "__subdomain__",
|
|
3447
|
+
label: "Use a subdomain",
|
|
3448
|
+
hint: `e.g., inbound.${domain}`
|
|
3449
|
+
}
|
|
3450
|
+
]
|
|
3451
|
+
});
|
|
3452
|
+
if (clack6.isCancel(choice)) {
|
|
3453
|
+
clack6.cancel("Operation cancelled.");
|
|
3454
|
+
process.exit(0);
|
|
3455
|
+
}
|
|
3456
|
+
if (choice === "") {
|
|
3457
|
+
return "";
|
|
3458
|
+
}
|
|
3386
3459
|
const subdomain = await clack6.text({
|
|
3387
3460
|
message: `Subdomain for receiving emails (e.g., inbound \u2192 inbound.${domain}):`,
|
|
3388
3461
|
placeholder: "inbound",
|
|
@@ -4296,8 +4369,8 @@ async function listConnections() {
|
|
|
4296
4369
|
return [];
|
|
4297
4370
|
}
|
|
4298
4371
|
try {
|
|
4299
|
-
const { readdir:
|
|
4300
|
-
const files = await
|
|
4372
|
+
const { readdir: readdir5 } = await import("fs/promises");
|
|
4373
|
+
const files = await readdir5(connectionsDir);
|
|
4301
4374
|
const connections = [];
|
|
4302
4375
|
for (const file of files) {
|
|
4303
4376
|
if (file.endsWith(".json")) {
|
|
@@ -4614,12 +4687,12 @@ function migrateInboundToMultiDomain(metadata) {
|
|
|
4614
4687
|
return false;
|
|
4615
4688
|
}
|
|
4616
4689
|
const inbound = emailConfig.inbound;
|
|
4617
|
-
const receivingDomain = inbound.receivingDomain || (inbound.subdomain
|
|
4690
|
+
const receivingDomain = inbound.receivingDomain || (inbound.subdomain ? `${inbound.subdomain}.${emailConfig.domain}` : emailConfig.domain || null);
|
|
4618
4691
|
if (!receivingDomain) {
|
|
4619
4692
|
return false;
|
|
4620
4693
|
}
|
|
4621
4694
|
const parentDomain = emailConfig.domain || "";
|
|
4622
|
-
const subdomain = inbound.subdomain
|
|
4695
|
+
const subdomain = inbound.subdomain ?? "";
|
|
4623
4696
|
emailConfig.inboundDomains = [
|
|
4624
4697
|
{
|
|
4625
4698
|
subdomain,
|
|
@@ -10113,6 +10186,48 @@ async function previewWithResourceChanges(stack, options) {
|
|
|
10113
10186
|
resourceChanges
|
|
10114
10187
|
};
|
|
10115
10188
|
}
|
|
10189
|
+
async function clearStackLocks(accountId, region) {
|
|
10190
|
+
const backendUrl = process.env.PULUMI_BACKEND_URL || "";
|
|
10191
|
+
if (backendUrl.startsWith("s3://")) {
|
|
10192
|
+
const { clearS3StackLocks: clearS3StackLocks2 } = await Promise.resolve().then(() => (init_s3_state(), s3_state_exports));
|
|
10193
|
+
return clearS3StackLocks2(accountId, region);
|
|
10194
|
+
}
|
|
10195
|
+
const { clearLocalStackLocks: clearLocalStackLocks2 } = await Promise.resolve().then(() => (init_fs(), fs_exports));
|
|
10196
|
+
return clearLocalStackLocks2();
|
|
10197
|
+
}
|
|
10198
|
+
async function withLockRetry(fn, options) {
|
|
10199
|
+
try {
|
|
10200
|
+
return await fn();
|
|
10201
|
+
} catch (error) {
|
|
10202
|
+
if (!(error instanceof Error)) {
|
|
10203
|
+
throw error;
|
|
10204
|
+
}
|
|
10205
|
+
const parsed = parsePulumiError(error);
|
|
10206
|
+
if (parsed.code !== "STACK_LOCKED") {
|
|
10207
|
+
throw error;
|
|
10208
|
+
}
|
|
10209
|
+
const clack51 = await import("@clack/prompts");
|
|
10210
|
+
const pc54 = (await import("picocolors")).default;
|
|
10211
|
+
if (options.autoConfirm) {
|
|
10212
|
+
clack51.log.warn(
|
|
10213
|
+
"Stack is locked from a previous interrupted run. Auto-clearing..."
|
|
10214
|
+
);
|
|
10215
|
+
} else {
|
|
10216
|
+
const shouldClear = await clack51.confirm({
|
|
10217
|
+
message: `Stack is locked from a previous interrupted run. ${pc54.yellow("Clear the stale lock and retry?")}`,
|
|
10218
|
+
initialValue: true
|
|
10219
|
+
});
|
|
10220
|
+
if (clack51.isCancel(shouldClear) || !shouldClear) {
|
|
10221
|
+
throw errors.stackLocked();
|
|
10222
|
+
}
|
|
10223
|
+
}
|
|
10224
|
+
const cleared = await clearStackLocks(options.accountId, options.region);
|
|
10225
|
+
clack51.log.info(
|
|
10226
|
+
`Cleared ${cleared} lock file${cleared === 1 ? "" : "s"}. Retrying...`
|
|
10227
|
+
);
|
|
10228
|
+
return fn();
|
|
10229
|
+
}
|
|
10230
|
+
}
|
|
10116
10231
|
|
|
10117
10232
|
// src/commands/cdn/destroy.ts
|
|
10118
10233
|
async function cdnDestroy(options) {
|
|
@@ -10303,8 +10418,12 @@ async function cdnDestroy(options) {
|
|
|
10303
10418
|
} catch (_error) {
|
|
10304
10419
|
throw new Error("No CDN infrastructure found to destroy");
|
|
10305
10420
|
}
|
|
10306
|
-
await stack.destroy({ onOutput: () => {
|
|
10307
|
-
} })
|
|
10421
|
+
await withLockRetry(() => stack.destroy({ onOutput: () => {
|
|
10422
|
+
} }), {
|
|
10423
|
+
accountId: identity.accountId,
|
|
10424
|
+
region,
|
|
10425
|
+
autoConfirm: options.force
|
|
10426
|
+
});
|
|
10308
10427
|
await stack.workspace.removeStack(stackName);
|
|
10309
10428
|
}
|
|
10310
10429
|
);
|
|
@@ -10319,10 +10438,6 @@ async function cdnDestroy(options) {
|
|
|
10319
10438
|
}
|
|
10320
10439
|
process.exit(0);
|
|
10321
10440
|
}
|
|
10322
|
-
if (msg.includes("stack is currently locked")) {
|
|
10323
|
-
trackError("STACK_LOCKED", "storage destroy", { step: "destroy" });
|
|
10324
|
-
throw errors.stackLocked();
|
|
10325
|
-
}
|
|
10326
10441
|
trackError("DESTROY_FAILED", "storage destroy", { step: "destroy" });
|
|
10327
10442
|
clack9.log.error("CDN infrastructure destruction failed");
|
|
10328
10443
|
throw error;
|
|
@@ -11712,8 +11827,11 @@ ${pc11.yellow(pc11.bold("Configuration Notes:"))}`);
|
|
|
11712
11827
|
`wraps-cdn-${identity.accountId}-${region}`
|
|
11713
11828
|
);
|
|
11714
11829
|
await stack.setConfig("aws:region", { value: region });
|
|
11715
|
-
const upResult = await
|
|
11716
|
-
|
|
11830
|
+
const upResult = await withLockRetry(
|
|
11831
|
+
() => stack.up({ onOutput: () => {
|
|
11832
|
+
} }),
|
|
11833
|
+
{ accountId: identity.accountId, region, autoConfirm: options.yes }
|
|
11834
|
+
);
|
|
11717
11835
|
const pulumiOutputs = upResult.outputs;
|
|
11718
11836
|
return {
|
|
11719
11837
|
roleArn: pulumiOutputs.roleArn?.value,
|
|
@@ -11739,10 +11857,6 @@ ${pc11.yellow(pc11.bold("Configuration Notes:"))}`);
|
|
|
11739
11857
|
region,
|
|
11740
11858
|
duration_ms: Date.now() - startTime
|
|
11741
11859
|
});
|
|
11742
|
-
if (msg.includes("stack is currently locked")) {
|
|
11743
|
-
trackError("STACK_LOCKED", "storage:init", { step: "deploy" });
|
|
11744
|
-
throw errors.stackLocked();
|
|
11745
|
-
}
|
|
11746
11860
|
trackError("DEPLOYMENT_FAILED", "storage:init", { step: "deploy" });
|
|
11747
11861
|
throw new Error(`Pulumi deployment failed: ${msg}`);
|
|
11748
11862
|
}
|
|
@@ -18190,11 +18304,14 @@ async function emailDestroy(options) {
|
|
|
18190
18304
|
}
|
|
18191
18305
|
await stack.refresh({ onOutput: () => {
|
|
18192
18306
|
} });
|
|
18193
|
-
await
|
|
18194
|
-
|
|
18195
|
-
|
|
18196
|
-
|
|
18197
|
-
|
|
18307
|
+
await withLockRetry(
|
|
18308
|
+
() => withTimeout(
|
|
18309
|
+
stack.destroy({ onOutput: () => {
|
|
18310
|
+
}, continueOnError: true }),
|
|
18311
|
+
DEFAULT_PULUMI_TIMEOUT_MS,
|
|
18312
|
+
"Pulumi destroy"
|
|
18313
|
+
),
|
|
18314
|
+
{ accountId: identity.accountId, region, autoConfirm: options.force }
|
|
18198
18315
|
);
|
|
18199
18316
|
await stack.workspace.removeStack(stackName);
|
|
18200
18317
|
}
|
|
@@ -18207,10 +18324,6 @@ async function emailDestroy(options) {
|
|
|
18207
18324
|
await deleteConnectionMetadata(identity.accountId, region);
|
|
18208
18325
|
process.exit(0);
|
|
18209
18326
|
}
|
|
18210
|
-
if (msg.includes("stack is currently locked")) {
|
|
18211
|
-
trackError("STACK_LOCKED", "email destroy", { step: "destroy" });
|
|
18212
|
-
throw errors.stackLocked();
|
|
18213
|
-
}
|
|
18214
18327
|
trackError("DESTROY_FAILED", "email destroy", { step: "destroy" });
|
|
18215
18328
|
clack18.log.error("Email infrastructure destruction failed");
|
|
18216
18329
|
destroyFailed = true;
|
|
@@ -19460,8 +19573,8 @@ async function inboundInit(options) {
|
|
|
19460
19573
|
if (!domain) {
|
|
19461
19574
|
throw errors.inboundRequiresOutbound();
|
|
19462
19575
|
}
|
|
19463
|
-
const subdomain = options.subdomain
|
|
19464
|
-
const receivingDomain = `${subdomain}.${domain}
|
|
19576
|
+
const subdomain = options.root ? "" : options.subdomain ?? (options.yes ? "inbound" : await promptInboundSubdomain(domain));
|
|
19577
|
+
const receivingDomain = subdomain ? `${subdomain}.${domain}` : domain;
|
|
19465
19578
|
clack20.log.info(`Receiving domain: ${pc21.cyan(receivingDomain)}`);
|
|
19466
19579
|
const webhookUrl = options.webhookUrl || (options.yes ? void 0 : await promptWebhookUrl());
|
|
19467
19580
|
const webhookSecret = randomBytes3(32).toString("hex");
|
|
@@ -19525,22 +19638,25 @@ async function inboundInit(options) {
|
|
|
19525
19638
|
);
|
|
19526
19639
|
await stack.setConfig("aws:region", { value: region });
|
|
19527
19640
|
const pulumiOutput = [];
|
|
19528
|
-
await
|
|
19529
|
-
|
|
19530
|
-
|
|
19531
|
-
|
|
19641
|
+
await withLockRetry(
|
|
19642
|
+
() => withTimeout(
|
|
19643
|
+
stack.up({
|
|
19644
|
+
onOutput: (msg) => {
|
|
19645
|
+
pulumiOutput.push(msg);
|
|
19646
|
+
}
|
|
19647
|
+
}),
|
|
19648
|
+
DEFAULT_PULUMI_TIMEOUT_MS,
|
|
19649
|
+
"Pulumi deployment"
|
|
19650
|
+
).catch((error) => {
|
|
19651
|
+
if (pulumiOutput.length > 0) {
|
|
19652
|
+
const fullOutput = pulumiOutput.join("");
|
|
19653
|
+
clack20.log.error("Pulumi deployment output:");
|
|
19654
|
+
console.error(fullOutput);
|
|
19532
19655
|
}
|
|
19656
|
+
throw error;
|
|
19533
19657
|
}),
|
|
19534
|
-
|
|
19535
|
-
|
|
19536
|
-
).catch((error) => {
|
|
19537
|
-
if (pulumiOutput.length > 0) {
|
|
19538
|
-
const fullOutput = pulumiOutput.join("");
|
|
19539
|
-
clack20.log.error("Pulumi deployment output:");
|
|
19540
|
-
console.error(fullOutput);
|
|
19541
|
-
}
|
|
19542
|
-
throw error;
|
|
19543
|
-
});
|
|
19658
|
+
{ accountId: identity.accountId, region, autoConfirm: options.yes }
|
|
19659
|
+
);
|
|
19544
19660
|
});
|
|
19545
19661
|
await progress.execute("Creating SES receipt rules", async () => {
|
|
19546
19662
|
await createReceiptRuleSet(region);
|
|
@@ -19766,11 +19882,14 @@ Deploy first: ${pc21.cyan("wraps email inbound init")}
|
|
|
19766
19882
|
}
|
|
19767
19883
|
);
|
|
19768
19884
|
await stack.setConfig("aws:region", { value: region });
|
|
19769
|
-
await
|
|
19770
|
-
|
|
19771
|
-
|
|
19772
|
-
|
|
19773
|
-
|
|
19885
|
+
await withLockRetry(
|
|
19886
|
+
() => withTimeout(
|
|
19887
|
+
stack.up({ onOutput: () => {
|
|
19888
|
+
} }),
|
|
19889
|
+
DEFAULT_PULUMI_TIMEOUT_MS,
|
|
19890
|
+
"Pulumi deployment"
|
|
19891
|
+
),
|
|
19892
|
+
{ accountId: identity.accountId, region, autoConfirm: options.force }
|
|
19774
19893
|
);
|
|
19775
19894
|
});
|
|
19776
19895
|
await progress.execute("Saving configuration", async () => {
|
|
@@ -19820,7 +19939,7 @@ Enable it: ${pc21.cyan("wraps email inbound init")}
|
|
|
19820
19939
|
const inboundDomains = emailConfig.inboundDomains ?? [];
|
|
19821
19940
|
const activeRuleSet = await getActiveReceiptRuleSet(region);
|
|
19822
19941
|
const domainList = inboundDomains.length > 0 ? inboundDomains.map((d) => d.receivingDomain) : [
|
|
19823
|
-
inbound.receivingDomain || `${inbound.subdomain}.${emailConfig.domain}`
|
|
19942
|
+
inbound.receivingDomain || (inbound.subdomain ? `${inbound.subdomain}.${emailConfig.domain}` : emailConfig.domain || "")
|
|
19824
19943
|
];
|
|
19825
19944
|
if (isJsonMode()) {
|
|
19826
19945
|
jsonSuccess("email.inbound.status", {
|
|
@@ -19883,7 +20002,7 @@ Enable it: ${pc21.cyan("wraps email inbound init")}
|
|
|
19883
20002
|
const inbound = emailConfig.inbound;
|
|
19884
20003
|
const inboundDomains = emailConfig.inboundDomains ?? [];
|
|
19885
20004
|
const domainList = inboundDomains.length > 0 ? inboundDomains.map((d) => d.receivingDomain) : [
|
|
19886
|
-
inbound.receivingDomain || `${inbound.subdomain}.${emailConfig.domain}`
|
|
20005
|
+
inbound.receivingDomain || (inbound.subdomain ? `${inbound.subdomain}.${emailConfig.domain}` : emailConfig.domain || "")
|
|
19887
20006
|
];
|
|
19888
20007
|
let allPassed = true;
|
|
19889
20008
|
const domainChecks = {};
|
|
@@ -19998,7 +20117,7 @@ Enable it: ${pc21.cyan("wraps email inbound init")}
|
|
|
19998
20117
|
}
|
|
19999
20118
|
const emailConfig = metadata.services.email.config;
|
|
20000
20119
|
const inbound = emailConfig.inbound;
|
|
20001
|
-
const receivingDomain = inbound.receivingDomain || `${inbound.subdomain}.${emailConfig.domain}
|
|
20120
|
+
const receivingDomain = inbound.receivingDomain || (inbound.subdomain ? `${inbound.subdomain}.${emailConfig.domain}` : emailConfig.domain || "");
|
|
20002
20121
|
const bucketName = inbound.bucketName || `wraps-inbound-${identity.accountId}-${region}`;
|
|
20003
20122
|
const testRecipient = `test@${receivingDomain}`;
|
|
20004
20123
|
const testSubject = `Wraps Inbound Test - ${(/* @__PURE__ */ new Date()).toISOString()}`;
|
|
@@ -20176,8 +20295,8 @@ Deploy first: ${pc21.cyan("wraps email inbound init")}
|
|
|
20176
20295
|
parentDomain = selected;
|
|
20177
20296
|
}
|
|
20178
20297
|
}
|
|
20179
|
-
const subdomain = options.subdomain
|
|
20180
|
-
const receivingDomain = `${subdomain}.${parentDomain}
|
|
20298
|
+
const subdomain = options.root ? "" : options.subdomain ?? (options.yes ? "inbound" : await promptInboundSubdomain(parentDomain));
|
|
20299
|
+
const receivingDomain = subdomain ? `${subdomain}.${parentDomain}` : parentDomain;
|
|
20181
20300
|
const existingDomains = emailConfig.inboundDomains ?? [];
|
|
20182
20301
|
if (existingDomains.some((d) => d.receivingDomain === receivingDomain)) {
|
|
20183
20302
|
clack20.log.warn(
|
|
@@ -20828,12 +20947,19 @@ ${pc24.yellow(pc24.bold("Configuration Warnings:"))}`);
|
|
|
20828
20947
|
`wraps-${identity.accountId}-${region}`
|
|
20829
20948
|
);
|
|
20830
20949
|
await stack.setConfig("aws:region", { value: region });
|
|
20831
|
-
const upResult = await
|
|
20832
|
-
|
|
20833
|
-
|
|
20834
|
-
|
|
20835
|
-
|
|
20836
|
-
|
|
20950
|
+
const upResult = await withLockRetry(
|
|
20951
|
+
() => withTimeout(
|
|
20952
|
+
stack.up({ onOutput: () => {
|
|
20953
|
+
} }),
|
|
20954
|
+
// Suppress Pulumi output
|
|
20955
|
+
DEFAULT_PULUMI_TIMEOUT_MS,
|
|
20956
|
+
"Pulumi deployment"
|
|
20957
|
+
),
|
|
20958
|
+
{
|
|
20959
|
+
accountId: identity.accountId,
|
|
20960
|
+
region,
|
|
20961
|
+
autoConfirm: options.yes || options.quick
|
|
20962
|
+
}
|
|
20837
20963
|
);
|
|
20838
20964
|
const pulumiOutputs = upResult.outputs;
|
|
20839
20965
|
return {
|
|
@@ -20860,10 +20986,6 @@ ${pc24.yellow(pc24.bold("Configuration Warnings:"))}`);
|
|
|
20860
20986
|
region,
|
|
20861
20987
|
duration_ms: Date.now() - startTime
|
|
20862
20988
|
});
|
|
20863
|
-
if (msg.includes("stack is currently locked")) {
|
|
20864
|
-
trackError("STACK_LOCKED", "email:init", { step: "deploy" });
|
|
20865
|
-
throw errors.stackLocked();
|
|
20866
|
-
}
|
|
20867
20989
|
if (isPulumiError(error)) {
|
|
20868
20990
|
const { code, iamAction, service } = parsePulumiError(error);
|
|
20869
20991
|
trackError(`PULUMI_${code}`, "email:init", {
|
|
@@ -22028,8 +22150,8 @@ async function templatesInit(options) {
|
|
|
22028
22150
|
const { homedir: homedir3 } = await import("os");
|
|
22029
22151
|
const connectionsDir = join9(homedir3(), ".wraps", "connections");
|
|
22030
22152
|
if (existsSync8(connectionsDir)) {
|
|
22031
|
-
const { readdir:
|
|
22032
|
-
const files = await
|
|
22153
|
+
const { readdir: readdir5 } = await import("fs/promises");
|
|
22154
|
+
const files = await readdir5(connectionsDir);
|
|
22033
22155
|
if (files.length > 0) {
|
|
22034
22156
|
const firstFile = files[0];
|
|
22035
22157
|
const match = firstFile.match(/\d+-(.+)\.json$/);
|
|
@@ -22348,7 +22470,7 @@ import pc28 from "picocolors";
|
|
|
22348
22470
|
// src/utils/email/template-compiler.ts
|
|
22349
22471
|
init_esm_shims();
|
|
22350
22472
|
import { existsSync as existsSync9 } from "fs";
|
|
22351
|
-
import { mkdir as mkdir4, readdir as
|
|
22473
|
+
import { mkdir as mkdir4, readdir as readdir3, writeFile as writeFile6 } from "fs/promises";
|
|
22352
22474
|
import { join as join10 } from "path";
|
|
22353
22475
|
async function loadWrapsConfig(wrapsDir) {
|
|
22354
22476
|
const configPath = join10(wrapsDir, "wraps.config.ts");
|
|
@@ -22383,7 +22505,7 @@ async function loadWrapsConfig(wrapsDir) {
|
|
|
22383
22505
|
return config2;
|
|
22384
22506
|
}
|
|
22385
22507
|
async function discoverTemplates(dir, filter) {
|
|
22386
|
-
const entries = await
|
|
22508
|
+
const entries = await readdir3(dir);
|
|
22387
22509
|
const templates = entries.filter(
|
|
22388
22510
|
(f) => (f.endsWith(".tsx") || f.endsWith(".ts")) && !f.startsWith("_") && !f.endsWith(".d.ts")
|
|
22389
22511
|
);
|
|
@@ -25659,8 +25781,8 @@ async function workflowsInit(options) {
|
|
|
25659
25781
|
}
|
|
25660
25782
|
const progress = new DeploymentProgress();
|
|
25661
25783
|
if (existsSync13(workflowsDir) && !options.force) {
|
|
25662
|
-
const { readdir:
|
|
25663
|
-
const files = await
|
|
25784
|
+
const { readdir: readdir5 } = await import("fs/promises");
|
|
25785
|
+
const files = await readdir5(workflowsDir);
|
|
25664
25786
|
const tsFiles = files.filter(
|
|
25665
25787
|
(f) => f.endsWith(".ts") && !f.startsWith("_")
|
|
25666
25788
|
);
|
|
@@ -25994,13 +26116,13 @@ function assignPositions(steps, transitions) {
|
|
|
25994
26116
|
init_esm_shims();
|
|
25995
26117
|
import { createHash as createHash2 } from "crypto";
|
|
25996
26118
|
import { existsSync as existsSync14 } from "fs";
|
|
25997
|
-
import { mkdir as mkdir8, readdir as
|
|
26119
|
+
import { mkdir as mkdir8, readdir as readdir4, readFile as readFile8, writeFile as writeFile10 } from "fs/promises";
|
|
25998
26120
|
import { basename, join as join15 } from "path";
|
|
25999
26121
|
async function discoverWorkflows(dir, filter) {
|
|
26000
26122
|
if (!existsSync14(dir)) {
|
|
26001
26123
|
return [];
|
|
26002
26124
|
}
|
|
26003
|
-
const entries = await
|
|
26125
|
+
const entries = await readdir4(dir);
|
|
26004
26126
|
const workflows = entries.filter(
|
|
26005
26127
|
(f) => (
|
|
26006
26128
|
// Include .ts files only (not .tsx for workflows)
|
|
@@ -32975,7 +33097,6 @@ import * as pulumi26 from "@pulumi/pulumi";
|
|
|
32975
33097
|
import pc43 from "picocolors";
|
|
32976
33098
|
init_events();
|
|
32977
33099
|
init_aws();
|
|
32978
|
-
init_errors();
|
|
32979
33100
|
init_fs();
|
|
32980
33101
|
init_json_output();
|
|
32981
33102
|
init_metadata();
|
|
@@ -33653,7 +33774,10 @@ ${pc43.yellow(pc43.bold("Important Notes:"))}`);
|
|
|
33653
33774
|
}
|
|
33654
33775
|
);
|
|
33655
33776
|
await stack.setConfig("aws:region", { value: region });
|
|
33656
|
-
const upResult = await
|
|
33777
|
+
const upResult = await withLockRetry(
|
|
33778
|
+
() => stack.up({ onOutput: console.log }),
|
|
33779
|
+
{ accountId: identity.accountId, region, autoConfirm: options.yes }
|
|
33780
|
+
);
|
|
33657
33781
|
const pulumiOutputs = upResult.outputs;
|
|
33658
33782
|
return {
|
|
33659
33783
|
roleArn: pulumiOutputs.roleArn?.value,
|
|
@@ -33736,10 +33860,6 @@ ${pc43.yellow(pc43.bold("Important Notes:"))}`);
|
|
|
33736
33860
|
duration_ms: Date.now() - startTime
|
|
33737
33861
|
});
|
|
33738
33862
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
33739
|
-
if (errorMessage.includes("stack is currently locked")) {
|
|
33740
|
-
trackError("STACK_LOCKED", "sms:init", { step: "deploy" });
|
|
33741
|
-
throw errors.stackLocked();
|
|
33742
|
-
}
|
|
33743
33863
|
trackError("DEPLOYMENT_FAILED", "sms:init", { step: "deploy" });
|
|
33744
33864
|
throw new Error(`SMS deployment failed: ${errorMessage}`);
|
|
33745
33865
|
}
|
|
@@ -36677,6 +36797,11 @@ args.options([
|
|
|
36677
36797
|
name: "subdomain",
|
|
36678
36798
|
description: "Subdomain for inbound email (e.g., inbound, support)",
|
|
36679
36799
|
defaultValue: void 0
|
|
36800
|
+
},
|
|
36801
|
+
{
|
|
36802
|
+
name: "root",
|
|
36803
|
+
description: "Use root domain for inbound email (no subdomain)",
|
|
36804
|
+
defaultValue: false
|
|
36680
36805
|
}
|
|
36681
36806
|
]);
|
|
36682
36807
|
var flags = args.parse(process.argv);
|
|
@@ -36961,6 +37086,7 @@ Usage: ${pc53.cyan("wraps email verify --domain yourapp.com")}
|
|
|
36961
37086
|
region: flags.region,
|
|
36962
37087
|
subdomain: flags.domain,
|
|
36963
37088
|
// reuse --domain flag for subdomain
|
|
37089
|
+
root: flags.root,
|
|
36964
37090
|
yes: flags.yes,
|
|
36965
37091
|
preview: flags.preview,
|
|
36966
37092
|
json: flags.json
|
|
@@ -36995,6 +37121,7 @@ Usage: ${pc53.cyan("wraps email verify --domain yourapp.com")}
|
|
|
36995
37121
|
await inboundAdd({
|
|
36996
37122
|
region: flags.region,
|
|
36997
37123
|
subdomain: flags.subdomain,
|
|
37124
|
+
root: flags.root,
|
|
36998
37125
|
domain: flags.domain,
|
|
36999
37126
|
yes: flags.yes,
|
|
37000
37127
|
json: flags.json
|