@wraps.dev/cli 2.17.5 → 2.17.7

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
@@ -12,9 +12,13 @@ var __export = (target, all6) => {
12
12
  // ../../node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_tsx@4.20.6_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/esm_shims.js
13
13
  import path from "path";
14
14
  import { fileURLToPath } from "url";
15
+ var getFilename, getDirname, __dirname;
15
16
  var init_esm_shims = __esm({
16
17
  "../../node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_tsx@4.20.6_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/esm_shims.js"() {
17
18
  "use strict";
19
+ getFilename = () => fileURLToPath(import.meta.url);
20
+ getDirname = () => path.dirname(getFilename());
21
+ __dirname = /* @__PURE__ */ getDirname();
18
22
  }
19
23
  });
20
24
 
@@ -5327,6 +5331,170 @@ var init_output = __esm({
5327
5331
  }
5328
5332
  });
5329
5333
 
5334
+ // src/utils/shared/pulumi.ts
5335
+ var pulumi_exports = {};
5336
+ __export(pulumi_exports, {
5337
+ checkPulumiInstalled: () => checkPulumiInstalled,
5338
+ clearStackLocks: () => clearStackLocks,
5339
+ ensurePulumiInstalled: () => ensurePulumiInstalled,
5340
+ previewWithResourceChanges: () => previewWithResourceChanges,
5341
+ withLockRetry: () => withLockRetry
5342
+ });
5343
+ import { exec } from "child_process";
5344
+ import { existsSync as existsSync6, readdirSync as readdirSync2 } from "fs";
5345
+ import { homedir as homedir3 } from "os";
5346
+ import { dirname as dirname2, join as join7 } from "path";
5347
+ import { promisify } from "util";
5348
+ import { PulumiCommand } from "@pulumi/pulumi/automation/index.js";
5349
+ function findSdkInstalledPulumi() {
5350
+ const versionsDir = join7(homedir3(), ".pulumi", "versions");
5351
+ if (!existsSync6(versionsDir)) return;
5352
+ const versions = readdirSync2(versionsDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name).sort().reverse();
5353
+ for (const version of versions) {
5354
+ const binPath = join7(versionsDir, version, "bin", "pulumi");
5355
+ if (existsSync6(binPath)) return dirname2(binPath);
5356
+ }
5357
+ return;
5358
+ }
5359
+ async function checkPulumiInstalled() {
5360
+ try {
5361
+ await execAsync("pulumi version");
5362
+ return true;
5363
+ } catch {
5364
+ const binDir = findSdkInstalledPulumi();
5365
+ if (binDir) {
5366
+ process.env.PATH = `${binDir}:${process.env.PATH}`;
5367
+ return true;
5368
+ }
5369
+ return false;
5370
+ }
5371
+ }
5372
+ async function ensurePulumiInstalled() {
5373
+ const isInstalled = await checkPulumiInstalled();
5374
+ if (!isInstalled) {
5375
+ try {
5376
+ const cmd = await PulumiCommand.install();
5377
+ const binDir = dirname2(cmd.command);
5378
+ process.env.PATH = `${binDir}:${process.env.PATH}`;
5379
+ return true;
5380
+ } catch (_error) {
5381
+ throw errors.pulumiNotInstalled();
5382
+ }
5383
+ }
5384
+ return false;
5385
+ }
5386
+ function mapOperationType(op) {
5387
+ switch (op) {
5388
+ case "create":
5389
+ return "create";
5390
+ case "update":
5391
+ return "update";
5392
+ case "delete":
5393
+ return "delete";
5394
+ case "replace":
5395
+ case "create-replacement":
5396
+ case "delete-replaced":
5397
+ return "replace";
5398
+ case "same":
5399
+ case "read":
5400
+ return "same";
5401
+ default:
5402
+ return "same";
5403
+ }
5404
+ }
5405
+ async function previewWithResourceChanges(stack, options) {
5406
+ const resourceChanges = [];
5407
+ const seenResources = /* @__PURE__ */ new Set();
5408
+ const result = await stack.preview({
5409
+ diff: options?.diff ?? true,
5410
+ onEvent: (event) => {
5411
+ if (event.resourcePreEvent) {
5412
+ const metadata = event.resourcePreEvent.metadata;
5413
+ if (metadata) {
5414
+ const resourceKey = `${metadata.type}::${metadata.urn}`;
5415
+ if (seenResources.has(resourceKey)) {
5416
+ return;
5417
+ }
5418
+ seenResources.add(resourceKey);
5419
+ if (metadata.type === "pulumi:pulumi:Stack") {
5420
+ return;
5421
+ }
5422
+ const operation = mapOperationType(metadata.op || "same");
5423
+ const urnParts = metadata.urn?.split("::") || [];
5424
+ const name = urnParts.at(-1) || metadata.urn || "unknown";
5425
+ const diffs = [];
5426
+ if (metadata.diffs && metadata.diffs.length > 0) {
5427
+ for (const diff of metadata.diffs) {
5428
+ diffs.push(diff);
5429
+ }
5430
+ }
5431
+ resourceChanges.push({
5432
+ name,
5433
+ type: metadata.type || "unknown",
5434
+ operation,
5435
+ diffs: diffs.length > 0 ? diffs : void 0
5436
+ });
5437
+ }
5438
+ }
5439
+ }
5440
+ });
5441
+ return {
5442
+ ...result,
5443
+ resourceChanges
5444
+ };
5445
+ }
5446
+ async function clearStackLocks(accountId, region) {
5447
+ const backendUrl = process.env.PULUMI_BACKEND_URL || "";
5448
+ if (backendUrl.startsWith("s3://")) {
5449
+ const { clearS3StackLocks: clearS3StackLocks2 } = await Promise.resolve().then(() => (init_s3_state(), s3_state_exports));
5450
+ return clearS3StackLocks2(accountId, region);
5451
+ }
5452
+ const { clearLocalStackLocks: clearLocalStackLocks2 } = await Promise.resolve().then(() => (init_fs(), fs_exports));
5453
+ return clearLocalStackLocks2();
5454
+ }
5455
+ async function withLockRetry(fn, options) {
5456
+ try {
5457
+ return await fn();
5458
+ } catch (error) {
5459
+ if (!(error instanceof Error)) {
5460
+ throw error;
5461
+ }
5462
+ const parsed = parsePulumiError(error);
5463
+ if (parsed.code !== "STACK_LOCKED") {
5464
+ throw error;
5465
+ }
5466
+ const clack51 = await import("@clack/prompts");
5467
+ const pc54 = (await import("picocolors")).default;
5468
+ if (options.autoConfirm) {
5469
+ clack51.log.warn(
5470
+ "Stack is locked from a previous interrupted run. Auto-clearing..."
5471
+ );
5472
+ } else {
5473
+ const shouldClear = await clack51.confirm({
5474
+ message: `Stack is locked from a previous interrupted run. ${pc54.yellow("Clear the stale lock and retry?")}`,
5475
+ initialValue: true
5476
+ });
5477
+ if (clack51.isCancel(shouldClear) || !shouldClear) {
5478
+ throw errors.stackLocked();
5479
+ }
5480
+ }
5481
+ const cleared = await clearStackLocks(options.accountId, options.region);
5482
+ clack51.log.info(
5483
+ `Cleared ${cleared} lock file${cleared === 1 ? "" : "s"}. Retrying...`
5484
+ );
5485
+ return fn();
5486
+ }
5487
+ }
5488
+ var execAsync;
5489
+ var init_pulumi = __esm({
5490
+ "src/utils/shared/pulumi.ts"() {
5491
+ "use strict";
5492
+ init_esm_shims();
5493
+ init_errors();
5494
+ execAsync = promisify(exec);
5495
+ }
5496
+ });
5497
+
5330
5498
  // src/constants.ts
5331
5499
  function getDefaultRegion() {
5332
5500
  return process.env.AWS_REGION || DEFAULT_AWS_REGION;
@@ -5458,6 +5626,8 @@ __export(dist_exports, {
5458
5626
  retentionToDays: () => retentionToDays2
5459
5627
  });
5460
5628
  import { createHmac } from "crypto";
5629
+ import { dirname as dirname3, join as join8 } from "path";
5630
+ import { fileURLToPath as fileURLToPath3 } from "url";
5461
5631
  function retentionToDays2(retention) {
5462
5632
  switch (retention) {
5463
5633
  case "7days":
@@ -5577,6 +5747,10 @@ function getSMTPConnectionDetails(region) {
5577
5747
  // Use STARTTLS
5578
5748
  };
5579
5749
  }
5750
+ function resolvePackagePath(relativePath) {
5751
+ const dir = typeof __dirname !== "undefined" ? __dirname : dirname3(fileURLToPath3(import.meta.url));
5752
+ return join8(dir, "..", relativePath);
5753
+ }
5580
5754
  var DEFAULT_EVENT_TYPES, ALL_EVENT_TYPES, DEFAULT_SUPPRESSION_REASONS, DEFAULT_CONFIG_SET_NAME, DEFAULT_MAIL_FROM_SUBDOMAIN, DEFAULT_HISTORY_RETENTION, VERCEL_OIDC_URL, VERCEL_OIDC_THUMBPRINT, RESOURCE_PREFIX, DEFAULT_TAGS, LAMBDA_EVENT_PROCESSOR_PATH, LAMBDA_SMS_EVENT_PROCESSOR_PATH;
5581
5755
  var init_dist = __esm({
5582
5756
  "../core/dist/index.js"() {
@@ -5615,14 +5789,12 @@ var init_dist = __esm({
5615
5789
  DEFAULT_TAGS = {
5616
5790
  ManagedBy: "wraps"
5617
5791
  };
5618
- LAMBDA_EVENT_PROCESSOR_PATH = new URL(
5619
- "../lambda/event-processor",
5620
- import.meta.url
5621
- ).pathname;
5622
- LAMBDA_SMS_EVENT_PROCESSOR_PATH = new URL(
5623
- "../lambda/sms-event-processor",
5624
- import.meta.url
5625
- ).pathname;
5792
+ LAMBDA_EVENT_PROCESSOR_PATH = resolvePackagePath(
5793
+ "lambda/event-processor"
5794
+ );
5795
+ LAMBDA_SMS_EVENT_PROCESSOR_PATH = resolvePackagePath(
5796
+ "lambda/sms-event-processor"
5797
+ );
5626
5798
  }
5627
5799
  });
5628
5800
 
@@ -5731,19 +5903,19 @@ import { randomBytes as randomBytes2 } from "crypto";
5731
5903
  import { existsSync as existsSync7, mkdirSync } from "fs";
5732
5904
  import { builtinModules } from "module";
5733
5905
  import { tmpdir } from "os";
5734
- import { dirname as dirname3, join as join8 } from "path";
5735
- import { fileURLToPath as fileURLToPath3 } from "url";
5906
+ import { dirname as dirname4, join as join9 } from "path";
5907
+ import { fileURLToPath as fileURLToPath4 } from "url";
5736
5908
  import * as aws8 from "@pulumi/aws";
5737
5909
  import * as pulumi11 from "@pulumi/pulumi";
5738
5910
  import { build } from "esbuild";
5739
5911
  function getPackageRoot() {
5740
- const currentFile = fileURLToPath3(import.meta.url);
5741
- let dir = dirname3(currentFile);
5742
- while (dir !== dirname3(dir)) {
5743
- if (existsSync7(join8(dir, "package.json"))) {
5912
+ const currentFile = fileURLToPath4(import.meta.url);
5913
+ let dir = dirname4(currentFile);
5914
+ while (dir !== dirname4(dir)) {
5915
+ if (existsSync7(join9(dir, "package.json"))) {
5744
5916
  return dir;
5745
5917
  }
5746
- dir = dirname3(dir);
5918
+ dir = dirname4(dir);
5747
5919
  }
5748
5920
  throw new Error("Could not find package.json");
5749
5921
  }
@@ -5767,17 +5939,17 @@ async function findEventSourceMapping(functionName, queueArn) {
5767
5939
  }
5768
5940
  async function getLambdaCode(functionName) {
5769
5941
  const packageRoot = getPackageRoot();
5770
- const distLambdaPath = join8(packageRoot, "dist", "lambda", functionName);
5771
- const distBundleMarker = join8(distLambdaPath, ".bundled");
5942
+ const distLambdaPath = join9(packageRoot, "dist", "lambda", functionName);
5943
+ const distBundleMarker = join9(distLambdaPath, ".bundled");
5772
5944
  if (existsSync7(distBundleMarker)) {
5773
5945
  return distLambdaPath;
5774
5946
  }
5775
- const lambdaPath = join8(packageRoot, "lambda", functionName);
5776
- const lambdaBundleMarker = join8(lambdaPath, ".bundled");
5947
+ const lambdaPath = join9(packageRoot, "lambda", functionName);
5948
+ const lambdaBundleMarker = join9(lambdaPath, ".bundled");
5777
5949
  if (existsSync7(lambdaBundleMarker)) {
5778
5950
  return lambdaPath;
5779
5951
  }
5780
- const sourcePath = join8(lambdaPath, "index.ts");
5952
+ const sourcePath = join9(lambdaPath, "index.ts");
5781
5953
  if (!existsSync7(sourcePath)) {
5782
5954
  throw new Error(
5783
5955
  `Lambda source not found: ${sourcePath}
@@ -5786,7 +5958,7 @@ Try running: pnpm build`
5786
5958
  );
5787
5959
  }
5788
5960
  const buildId = randomBytes2(8).toString("hex");
5789
- const outdir = join8(tmpdir(), `wraps-lambda-${buildId}`);
5961
+ const outdir = join9(tmpdir(), `wraps-lambda-${buildId}`);
5790
5962
  if (!existsSync7(outdir)) {
5791
5963
  mkdirSync(outdir, { recursive: true });
5792
5964
  }
@@ -5796,7 +5968,7 @@ Try running: pnpm build`
5796
5968
  platform: "node",
5797
5969
  target: "node24",
5798
5970
  format: "cjs",
5799
- outfile: join8(outdir, "index.js"),
5971
+ outfile: join9(outdir, "index.js"),
5800
5972
  external: ["@aws-sdk/*", ...nodeBuiltins],
5801
5973
  minify: true,
5802
5974
  sourcemap: false
@@ -5877,8 +6049,8 @@ async function deployLambdaFunctions(config2) {
5877
6049
  handler: "index.handler",
5878
6050
  role: lambdaRole.arn,
5879
6051
  code: new pulumi11.asset.FileArchive(eventProcessorCode),
5880
- timeout: 30,
5881
- // Lambda just parses JSON and writes to DynamoDB
6052
+ timeout: 300,
6053
+ // 5 minutes (matches SQS visibility timeout)
5882
6054
  memorySize: 512,
5883
6055
  environment: lambdaEnvironment,
5884
6056
  tags: {
@@ -5897,8 +6069,8 @@ async function deployLambdaFunctions(config2) {
5897
6069
  handler: "index.handler",
5898
6070
  role: lambdaRole.arn,
5899
6071
  code: new pulumi11.asset.FileArchive(eventProcessorCode),
5900
- timeout: 30,
5901
- // Lambda just parses JSON and writes to DynamoDB
6072
+ timeout: 300,
6073
+ // 5 minutes (matches SQS visibility timeout)
5902
6074
  memorySize: 512,
5903
6075
  environment: lambdaEnvironment,
5904
6076
  tags: {
@@ -8938,8 +9110,8 @@ var init_dynamodb_metrics = __esm({
8938
9110
  // src/cli.ts
8939
9111
  init_esm_shims();
8940
9112
  import { readFileSync as readFileSync3 } from "fs";
8941
- import { dirname as dirname4, join as join20 } from "path";
8942
- import { fileURLToPath as fileURLToPath5 } from "url";
9113
+ import { dirname as dirname5, join as join21 } from "path";
9114
+ import { fileURLToPath as fileURLToPath6 } from "url";
8943
9115
  import * as clack50 from "@clack/prompts";
8944
9116
  import args from "args";
8945
9117
  import pc53 from "picocolors";
@@ -10129,161 +10301,10 @@ init_fs();
10129
10301
  init_json_output();
10130
10302
  init_metadata();
10131
10303
  init_output();
10304
+ init_pulumi();
10132
10305
  import * as clack9 from "@clack/prompts";
10133
10306
  import * as pulumi from "@pulumi/pulumi";
10134
10307
  import pc10 from "picocolors";
10135
-
10136
- // src/utils/shared/pulumi.ts
10137
- init_esm_shims();
10138
- init_errors();
10139
- import { exec } from "child_process";
10140
- import { existsSync as existsSync6, readdirSync as readdirSync2 } from "fs";
10141
- import { homedir as homedir3 } from "os";
10142
- import { dirname as dirname2, join as join7 } from "path";
10143
- import { promisify } from "util";
10144
- import { PulumiCommand } from "@pulumi/pulumi/automation/index.js";
10145
- var execAsync = promisify(exec);
10146
- function findSdkInstalledPulumi() {
10147
- const versionsDir = join7(homedir3(), ".pulumi", "versions");
10148
- if (!existsSync6(versionsDir)) return;
10149
- const versions = readdirSync2(versionsDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name).sort().reverse();
10150
- for (const version of versions) {
10151
- const binPath = join7(versionsDir, version, "bin", "pulumi");
10152
- if (existsSync6(binPath)) return dirname2(binPath);
10153
- }
10154
- return;
10155
- }
10156
- async function checkPulumiInstalled() {
10157
- try {
10158
- await execAsync("pulumi version");
10159
- return true;
10160
- } catch {
10161
- const binDir = findSdkInstalledPulumi();
10162
- if (binDir) {
10163
- process.env.PATH = `${binDir}:${process.env.PATH}`;
10164
- return true;
10165
- }
10166
- return false;
10167
- }
10168
- }
10169
- async function ensurePulumiInstalled() {
10170
- const isInstalled = await checkPulumiInstalled();
10171
- if (!isInstalled) {
10172
- try {
10173
- const cmd = await PulumiCommand.install();
10174
- const binDir = dirname2(cmd.command);
10175
- process.env.PATH = `${binDir}:${process.env.PATH}`;
10176
- return true;
10177
- } catch (_error) {
10178
- throw errors.pulumiNotInstalled();
10179
- }
10180
- }
10181
- return false;
10182
- }
10183
- function mapOperationType(op) {
10184
- switch (op) {
10185
- case "create":
10186
- return "create";
10187
- case "update":
10188
- return "update";
10189
- case "delete":
10190
- return "delete";
10191
- case "replace":
10192
- case "create-replacement":
10193
- case "delete-replaced":
10194
- return "replace";
10195
- case "same":
10196
- case "read":
10197
- return "same";
10198
- default:
10199
- return "same";
10200
- }
10201
- }
10202
- async function previewWithResourceChanges(stack, options) {
10203
- const resourceChanges = [];
10204
- const seenResources = /* @__PURE__ */ new Set();
10205
- const result = await stack.preview({
10206
- diff: options?.diff ?? true,
10207
- onEvent: (event) => {
10208
- if (event.resourcePreEvent) {
10209
- const metadata = event.resourcePreEvent.metadata;
10210
- if (metadata) {
10211
- const resourceKey = `${metadata.type}::${metadata.urn}`;
10212
- if (seenResources.has(resourceKey)) {
10213
- return;
10214
- }
10215
- seenResources.add(resourceKey);
10216
- if (metadata.type === "pulumi:pulumi:Stack") {
10217
- return;
10218
- }
10219
- const operation = mapOperationType(metadata.op || "same");
10220
- const urnParts = metadata.urn?.split("::") || [];
10221
- const name = urnParts.at(-1) || metadata.urn || "unknown";
10222
- const diffs = [];
10223
- if (metadata.diffs && metadata.diffs.length > 0) {
10224
- for (const diff of metadata.diffs) {
10225
- diffs.push(diff);
10226
- }
10227
- }
10228
- resourceChanges.push({
10229
- name,
10230
- type: metadata.type || "unknown",
10231
- operation,
10232
- diffs: diffs.length > 0 ? diffs : void 0
10233
- });
10234
- }
10235
- }
10236
- }
10237
- });
10238
- return {
10239
- ...result,
10240
- resourceChanges
10241
- };
10242
- }
10243
- async function clearStackLocks(accountId, region) {
10244
- const backendUrl = process.env.PULUMI_BACKEND_URL || "";
10245
- if (backendUrl.startsWith("s3://")) {
10246
- const { clearS3StackLocks: clearS3StackLocks2 } = await Promise.resolve().then(() => (init_s3_state(), s3_state_exports));
10247
- return clearS3StackLocks2(accountId, region);
10248
- }
10249
- const { clearLocalStackLocks: clearLocalStackLocks2 } = await Promise.resolve().then(() => (init_fs(), fs_exports));
10250
- return clearLocalStackLocks2();
10251
- }
10252
- async function withLockRetry(fn, options) {
10253
- try {
10254
- return await fn();
10255
- } catch (error) {
10256
- if (!(error instanceof Error)) {
10257
- throw error;
10258
- }
10259
- const parsed = parsePulumiError(error);
10260
- if (parsed.code !== "STACK_LOCKED") {
10261
- throw error;
10262
- }
10263
- const clack51 = await import("@clack/prompts");
10264
- const pc54 = (await import("picocolors")).default;
10265
- if (options.autoConfirm) {
10266
- clack51.log.warn(
10267
- "Stack is locked from a previous interrupted run. Auto-clearing..."
10268
- );
10269
- } else {
10270
- const shouldClear = await clack51.confirm({
10271
- message: `Stack is locked from a previous interrupted run. ${pc54.yellow("Clear the stale lock and retry?")}`,
10272
- initialValue: true
10273
- });
10274
- if (clack51.isCancel(shouldClear) || !shouldClear) {
10275
- throw errors.stackLocked();
10276
- }
10277
- }
10278
- const cleared = await clearStackLocks(options.accountId, options.region);
10279
- clack51.log.info(
10280
- `Cleared ${cleared} lock file${cleared === 1 ? "" : "s"}. Retrying...`
10281
- );
10282
- return fn();
10283
- }
10284
- }
10285
-
10286
- // src/commands/cdn/destroy.ts
10287
10308
  async function cdnDestroy(options) {
10288
10309
  await ensurePulumiInstalled();
10289
10310
  const startTime = Date.now();
@@ -11448,6 +11469,7 @@ init_json_output();
11448
11469
  init_metadata();
11449
11470
  init_output();
11450
11471
  init_prompts();
11472
+ init_pulumi();
11451
11473
  async function promptCdnPreset() {
11452
11474
  const starterInfo = getPresetInfo2("starter");
11453
11475
  const productionInfo = getPresetInfo2("production");
@@ -12197,6 +12219,7 @@ init_fs();
12197
12219
  init_json_output();
12198
12220
  init_metadata();
12199
12221
  init_output();
12222
+ init_pulumi();
12200
12223
  import * as clack11 from "@clack/prompts";
12201
12224
  import * as pulumi6 from "@pulumi/pulumi";
12202
12225
  import pc12 from "picocolors";
@@ -12374,6 +12397,7 @@ init_fs();
12374
12397
  init_json_output();
12375
12398
  init_metadata();
12376
12399
  init_output();
12400
+ init_pulumi();
12377
12401
  async function cdnSync(options) {
12378
12402
  await ensurePulumiInstalled();
12379
12403
  const startTime = Date.now();
@@ -12554,6 +12578,7 @@ init_fs();
12554
12578
  init_json_output();
12555
12579
  init_metadata();
12556
12580
  init_output();
12581
+ init_pulumi();
12557
12582
  async function cdnUpgrade(options) {
12558
12583
  await ensurePulumiInstalled();
12559
12584
  const startTime = Date.now();
@@ -12857,6 +12882,7 @@ init_fs();
12857
12882
  init_json_output();
12858
12883
  init_metadata();
12859
12884
  init_output();
12885
+ init_pulumi();
12860
12886
  import * as clack14 from "@clack/prompts";
12861
12887
  import * as pulumi9 from "@pulumi/pulumi";
12862
12888
  import pc15 from "picocolors";
@@ -16962,8 +16988,8 @@ async function createSQSResources() {
16962
16988
  });
16963
16989
  const queue = new aws11.sqs.Queue("wraps-email-events", {
16964
16990
  name: "wraps-email-events",
16965
- visibilityTimeoutSeconds: 60,
16966
- // Must be >= Lambda timeout
16991
+ visibilityTimeoutSeconds: 300,
16992
+ // Must be >= Lambda timeout (5 minutes)
16967
16993
  messageRetentionSeconds: 345600,
16968
16994
  // 4 days
16969
16995
  receiveWaitTimeSeconds: 20,
@@ -17235,6 +17261,7 @@ init_fs();
17235
17261
  init_json_output();
17236
17262
  init_metadata();
17237
17263
  init_output();
17264
+ init_pulumi();
17238
17265
  async function config(options) {
17239
17266
  const startTime = Date.now();
17240
17267
  if (!isJsonMode()) {
@@ -17525,6 +17552,7 @@ init_json_output();
17525
17552
  init_metadata();
17526
17553
  init_output();
17527
17554
  init_prompts();
17555
+ init_pulumi();
17528
17556
 
17529
17557
  // src/utils/shared/scanner.ts
17530
17558
  init_esm_shims();
@@ -18121,6 +18149,7 @@ init_fs();
18121
18149
  init_json_output();
18122
18150
  init_metadata();
18123
18151
  init_output();
18152
+ init_pulumi();
18124
18153
  import * as clack18 from "@clack/prompts";
18125
18154
  import * as pulumi15 from "@pulumi/pulumi";
18126
18155
  import pc19 from "picocolors";
@@ -18193,6 +18222,10 @@ async function emailDestroy(options) {
18193
18222
  );
18194
18223
  }
18195
18224
  const progress = new DeploymentProgress();
18225
+ await progress.execute("Checking Pulumi CLI installation", async () => {
18226
+ const { ensurePulumiInstalled: ensurePulumiInstalled2 } = await Promise.resolve().then(() => (init_pulumi(), pulumi_exports));
18227
+ await ensurePulumiInstalled2();
18228
+ });
18196
18229
  const identity = await progress.execute(
18197
18230
  "Validating AWS credentials",
18198
18231
  async () => validateAWSCredentials()
@@ -19599,6 +19632,7 @@ init_json_output();
19599
19632
  init_metadata();
19600
19633
  init_output();
19601
19634
  init_prompts();
19635
+ init_pulumi();
19602
19636
  async function inboundInit(options) {
19603
19637
  if (!isJsonMode()) {
19604
19638
  clack20.intro(
@@ -20753,6 +20787,7 @@ init_json_output();
20753
20787
  init_metadata();
20754
20788
  init_output();
20755
20789
  init_prompts();
20790
+ init_pulumi();
20756
20791
  async function init2(options) {
20757
20792
  const startTime = Date.now();
20758
20793
  if (!isJsonMode()) {
@@ -21360,6 +21395,7 @@ init_fs();
21360
21395
  init_json_output();
21361
21396
  init_metadata();
21362
21397
  init_output();
21398
+ init_pulumi();
21363
21399
  import * as clack24 from "@clack/prompts";
21364
21400
  import * as pulumi18 from "@pulumi/pulumi";
21365
21401
  import pc25 from "picocolors";
@@ -21564,6 +21600,7 @@ init_fs();
21564
21600
  init_json_output();
21565
21601
  init_metadata();
21566
21602
  init_output();
21603
+ init_pulumi();
21567
21604
  import * as clack25 from "@clack/prompts";
21568
21605
  import * as pulumi19 from "@pulumi/pulumi";
21569
21606
  import pc26 from "picocolors";
@@ -21709,7 +21746,7 @@ init_json_output();
21709
21746
  init_output();
21710
21747
  import { existsSync as existsSync9 } from "fs";
21711
21748
  import { mkdir as mkdir3, readFile as readFile4, writeFile as writeFile5 } from "fs/promises";
21712
- import { join as join10 } from "path";
21749
+ import { join as join11 } from "path";
21713
21750
  import * as clack26 from "@clack/prompts";
21714
21751
  import pc27 from "picocolors";
21715
21752
 
@@ -21717,7 +21754,7 @@ import pc27 from "picocolors";
21717
21754
  init_esm_shims();
21718
21755
  import { existsSync as existsSync8 } from "fs";
21719
21756
  import { mkdir as mkdir2, readFile as readFile3, writeFile as writeFile4 } from "fs/promises";
21720
- import { join as join9 } from "path";
21757
+ import { join as join10 } from "path";
21721
21758
  var CLAUDE_MD_HEADER = `# Wraps
21722
21759
 
21723
21760
  This project uses [Wraps](https://wraps.dev) for email infrastructure.
@@ -21727,8 +21764,8 @@ async function scaffoldClaudeMdSection({
21727
21764
  sectionId,
21728
21765
  sectionContent
21729
21766
  }) {
21730
- const claudeDir = join9(projectDir, ".claude");
21731
- const claudeMdPath = join9(claudeDir, "CLAUDE.md");
21767
+ const claudeDir = join10(projectDir, ".claude");
21768
+ const claudeMdPath = join10(claudeDir, "CLAUDE.md");
21732
21769
  await mkdir2(claudeDir, { recursive: true });
21733
21770
  const startMarker = `<!-- wraps:${sectionId}-start -->`;
21734
21771
  const endMarker = `<!-- wraps:${sectionId}-end -->`;
@@ -21769,8 +21806,8 @@ async function scaffoldClaudeSkill({
21769
21806
  skillName,
21770
21807
  skillContent
21771
21808
  }) {
21772
- const skillDir = join9(projectDir, ".claude", "skills", skillName);
21773
- const skillPath = join9(skillDir, "SKILL.md");
21809
+ const skillDir = join10(projectDir, ".claude", "skills", skillName);
21810
+ const skillPath = join10(skillDir, "SKILL.md");
21774
21811
  await mkdir2(skillDir, { recursive: true });
21775
21812
  await writeFile4(skillPath, `${skillContent.trim()}
21776
21813
  `, "utf-8");
@@ -22155,7 +22192,7 @@ wraps email templates preview # Preview in browser
22155
22192
  async function templatesInit(options) {
22156
22193
  const startTime = Date.now();
22157
22194
  const cwd = process.cwd();
22158
- const wrapsDir = join10(cwd, "wraps");
22195
+ const wrapsDir = join11(cwd, "wraps");
22159
22196
  if (!isJsonMode()) {
22160
22197
  clack26.intro(pc27.bold("Templates as Code"));
22161
22198
  }
@@ -22195,7 +22232,7 @@ async function templatesInit(options) {
22195
22232
  let detectedDomain;
22196
22233
  let detectedRegion;
22197
22234
  try {
22198
- const pkgPath = join10(cwd, "package.json");
22235
+ const pkgPath = join11(cwd, "package.json");
22199
22236
  if (existsSync9(pkgPath)) {
22200
22237
  const pkg = JSON.parse(await readFile4(pkgPath, "utf-8"));
22201
22238
  if (pkg.homepage) {
@@ -22210,7 +22247,7 @@ async function templatesInit(options) {
22210
22247
  }
22211
22248
  try {
22212
22249
  const { homedir: homedir4 } = await import("os");
22213
- const connectionsDir = join10(homedir4(), ".wraps", "connections");
22250
+ const connectionsDir = join11(homedir4(), ".wraps", "connections");
22214
22251
  if (existsSync9(connectionsDir)) {
22215
22252
  const { readdir: readdir5 } = await import("fs/promises");
22216
22253
  const files = await readdir5(connectionsDir);
@@ -22226,33 +22263,33 @@ async function templatesInit(options) {
22226
22263
  }
22227
22264
  progress.start("Creating wraps/ directory structure");
22228
22265
  await mkdir3(wrapsDir, { recursive: true });
22229
- await mkdir3(join10(wrapsDir, "templates"), { recursive: true });
22230
- await mkdir3(join10(wrapsDir, "templates", "_components"), { recursive: true });
22231
- await mkdir3(join10(wrapsDir, "workflows"), { recursive: true });
22232
- await mkdir3(join10(wrapsDir, ".wraps"), { recursive: true });
22266
+ await mkdir3(join11(wrapsDir, "templates"), { recursive: true });
22267
+ await mkdir3(join11(wrapsDir, "templates", "_components"), { recursive: true });
22268
+ await mkdir3(join11(wrapsDir, "workflows"), { recursive: true });
22269
+ await mkdir3(join11(wrapsDir, ".wraps"), { recursive: true });
22233
22270
  const configContent = generateConfigFile(
22234
22271
  orgSlug,
22235
22272
  detectedDomain,
22236
22273
  detectedRegion
22237
22274
  );
22238
- await writeFile5(join10(wrapsDir, "wraps.config.ts"), configContent, "utf-8");
22275
+ await writeFile5(join11(wrapsDir, "wraps.config.ts"), configContent, "utf-8");
22239
22276
  const brandContent = generateBrandFile();
22240
- await writeFile5(join10(wrapsDir, "brand.ts"), brandContent, "utf-8");
22277
+ await writeFile5(join11(wrapsDir, "brand.ts"), brandContent, "utf-8");
22241
22278
  if (!options.noExample) {
22242
22279
  await writeFile5(
22243
- join10(wrapsDir, "templates", "welcome.tsx"),
22280
+ join11(wrapsDir, "templates", "welcome.tsx"),
22244
22281
  generateWelcomeTemplate(),
22245
22282
  "utf-8"
22246
22283
  );
22247
22284
  await writeFile5(
22248
- join10(wrapsDir, "templates", "_components", "footer.tsx"),
22285
+ join11(wrapsDir, "templates", "_components", "footer.tsx"),
22249
22286
  generateFooterComponent(),
22250
22287
  "utf-8"
22251
22288
  );
22252
22289
  }
22253
- const gitignorePath = join10(wrapsDir, ".gitignore");
22290
+ const gitignorePath = join11(wrapsDir, ".gitignore");
22254
22291
  await writeFile5(gitignorePath, ".wraps/\n", "utf-8");
22255
- const rootGitignorePath = join10(cwd, ".gitignore");
22292
+ const rootGitignorePath = join11(cwd, ".gitignore");
22256
22293
  if (existsSync9(rootGitignorePath)) {
22257
22294
  const gitignoreContent = await readFile4(rootGitignorePath, "utf-8");
22258
22295
  if (!gitignoreContent.includes("wraps/.wraps")) {
@@ -22525,7 +22562,7 @@ const unsubscribeLink = {
22525
22562
  init_esm_shims();
22526
22563
  init_events();
22527
22564
  import { existsSync as existsSync11, watch } from "fs";
22528
- import { join as join12 } from "path";
22565
+ import { join as join13 } from "path";
22529
22566
  import * as clack27 from "@clack/prompts";
22530
22567
  import pc28 from "picocolors";
22531
22568
 
@@ -22533,14 +22570,14 @@ import pc28 from "picocolors";
22533
22570
  init_esm_shims();
22534
22571
  import { existsSync as existsSync10 } from "fs";
22535
22572
  import { mkdir as mkdir4, readdir as readdir3, writeFile as writeFile6 } from "fs/promises";
22536
- import { join as join11 } from "path";
22573
+ import { join as join12 } from "path";
22537
22574
  async function loadWrapsConfig(wrapsDir) {
22538
- const configPath = join11(wrapsDir, "wraps.config.ts");
22575
+ const configPath = join12(wrapsDir, "wraps.config.ts");
22539
22576
  const { build: build2 } = await import("esbuild");
22540
- const shimDir = join11(wrapsDir, ".wraps", "_shims");
22577
+ const shimDir = join12(wrapsDir, ".wraps", "_shims");
22541
22578
  await mkdir4(shimDir, { recursive: true });
22542
22579
  await writeFile6(
22543
- join11(shimDir, "wraps-client-shim.mjs"),
22580
+ join12(shimDir, "wraps-client-shim.mjs"),
22544
22581
  "export const defineConfig = (c) => c;\nexport const defineBrand = (b) => b;\n",
22545
22582
  "utf-8"
22546
22583
  );
@@ -22552,11 +22589,11 @@ async function loadWrapsConfig(wrapsDir) {
22552
22589
  platform: "node",
22553
22590
  target: "node20",
22554
22591
  alias: {
22555
- "@wraps.dev/client": join11(shimDir, "wraps-client-shim.mjs")
22592
+ "@wraps.dev/client": join12(shimDir, "wraps-client-shim.mjs")
22556
22593
  }
22557
22594
  });
22558
22595
  const code = result.outputFiles[0].text;
22559
- const tmpPath = join11(wrapsDir, ".wraps", "_config.mjs");
22596
+ const tmpPath = join12(wrapsDir, ".wraps", "_config.mjs");
22560
22597
  await writeFile6(tmpPath, code, "utf-8");
22561
22598
  const mod = await import(tmpPath);
22562
22599
  const config2 = mod.default;
@@ -22581,7 +22618,7 @@ async function findCliNodeModules() {
22581
22618
  const paths = [];
22582
22619
  try {
22583
22620
  const { createRequire } = await import("module");
22584
- const { dirname: dirname5 } = await import("path");
22621
+ const { dirname: dirname6 } = await import("path");
22585
22622
  for (const base of [
22586
22623
  // The current file's location (works when running from source)
22587
22624
  import.meta.url,
@@ -22591,8 +22628,8 @@ async function findCliNodeModules() {
22591
22628
  try {
22592
22629
  const req = createRequire(base);
22593
22630
  const reactPkg = req.resolve("react/package.json");
22594
- const reactNodeModules = join11(dirname5(reactPkg), "..");
22595
- if (existsSync10(join11(reactNodeModules, "react"))) {
22631
+ const reactNodeModules = join12(dirname6(reactPkg), "..");
22632
+ if (existsSync10(join12(reactNodeModules, "react"))) {
22596
22633
  paths.push(reactNodeModules);
22597
22634
  break;
22598
22635
  }
@@ -22620,10 +22657,10 @@ async function compileForPreview(filePath, slug, wrapsDir) {
22620
22657
  }
22621
22658
  });
22622
22659
  const bundledCode = result.outputFiles[0].text;
22623
- const projectRoot = join11(wrapsDir, "..");
22624
- const tmpDir = join11(projectRoot, "node_modules", ".wraps-compiled");
22660
+ const projectRoot = join12(wrapsDir, "..");
22661
+ const tmpDir = join12(projectRoot, "node_modules", ".wraps-compiled");
22625
22662
  await mkdir4(tmpDir, { recursive: true });
22626
- const tmpPath = join11(tmpDir, `${slug}.preview.mjs`);
22663
+ const tmpPath = join12(tmpDir, `${slug}.preview.mjs`);
22627
22664
  await writeFile6(tmpPath, bundledCode, "utf-8");
22628
22665
  const mod = await import(`${tmpPath}?t=${Date.now()}`);
22629
22666
  const Component = mod.default;
@@ -22646,14 +22683,14 @@ async function compileForPreview(filePath, slug, wrapsDir) {
22646
22683
  init_errors();
22647
22684
  async function templatesPreview(options) {
22648
22685
  const cwd = process.cwd();
22649
- const wrapsDir = join12(cwd, "wraps");
22650
- const configPath = join12(wrapsDir, "wraps.config.ts");
22686
+ const wrapsDir = join13(cwd, "wraps");
22687
+ const configPath = join13(wrapsDir, "wraps.config.ts");
22651
22688
  if (!existsSync11(configPath)) {
22652
22689
  throw errors.wrapsConfigNotFound();
22653
22690
  }
22654
22691
  clack27.intro(pc28.bold("Preview Templates"));
22655
22692
  const config2 = await loadWrapsConfig(wrapsDir);
22656
- const templatesDir = join12(wrapsDir, config2.templatesDir || "./templates");
22693
+ const templatesDir = join13(wrapsDir, config2.templatesDir || "./templates");
22657
22694
  if (!existsSync11(templatesDir)) {
22658
22695
  throw errors.wrapsConfigNotFound();
22659
22696
  }
@@ -22673,7 +22710,7 @@ async function templatesPreview(options) {
22673
22710
  throw new Error(`Template not found: ${slug}`);
22674
22711
  }
22675
22712
  const result = await compileForPreview(
22676
- join12(templatesDir, file),
22713
+ join13(templatesDir, file),
22677
22714
  slug,
22678
22715
  wrapsDir
22679
22716
  );
@@ -22977,7 +23014,7 @@ init_events();
22977
23014
  import { createHash } from "crypto";
22978
23015
  import { existsSync as existsSync13 } from "fs";
22979
23016
  import { mkdir as mkdir6, readFile as readFile6, writeFile as writeFile8 } from "fs/promises";
22980
- import { join as join14 } from "path";
23017
+ import { join as join15 } from "path";
22981
23018
  import * as clack28 from "@clack/prompts";
22982
23019
  import pc29 from "picocolors";
22983
23020
  init_config();
@@ -22988,9 +23025,9 @@ init_json_output();
22988
23025
  init_esm_shims();
22989
23026
  import { existsSync as existsSync12 } from "fs";
22990
23027
  import { mkdir as mkdir5, readFile as readFile5, writeFile as writeFile7 } from "fs/promises";
22991
- import { join as join13 } from "path";
23028
+ import { join as join14 } from "path";
22992
23029
  function getLockfilePath(wrapsDir) {
22993
- return join13(wrapsDir, ".wraps", "lockfile.json");
23030
+ return join14(wrapsDir, ".wraps", "lockfile.json");
22994
23031
  }
22995
23032
  async function loadLockfile(wrapsDir) {
22996
23033
  const path3 = getLockfilePath(wrapsDir);
@@ -23013,7 +23050,7 @@ async function loadLockfile(wrapsDir) {
23013
23050
  }
23014
23051
  async function saveLockfile(wrapsDir, lockfile) {
23015
23052
  const path3 = getLockfilePath(wrapsDir);
23016
- const dir = join13(path3, "..");
23053
+ const dir = join14(path3, "..");
23017
23054
  await mkdir5(dir, { recursive: true });
23018
23055
  await writeFile7(path3, JSON.stringify(lockfile, null, 2), "utf-8");
23019
23056
  }
@@ -23023,8 +23060,8 @@ init_output();
23023
23060
  async function templatesPush(options) {
23024
23061
  const startTime = Date.now();
23025
23062
  const cwd = process.cwd();
23026
- const wrapsDir = join14(cwd, "wraps");
23027
- const configPath = join14(wrapsDir, "wraps.config.ts");
23063
+ const wrapsDir = join15(cwd, "wraps");
23064
+ const configPath = join15(wrapsDir, "wraps.config.ts");
23028
23065
  if (!existsSync13(configPath)) {
23029
23066
  throw errors.wrapsConfigNotFound();
23030
23067
  }
@@ -23035,7 +23072,7 @@ async function templatesPush(options) {
23035
23072
  progress.start("Loading configuration");
23036
23073
  const config2 = await loadWrapsConfig(wrapsDir);
23037
23074
  progress.succeed("Configuration loaded");
23038
- const templatesDir = join14(wrapsDir, config2.templatesDir || "./templates");
23075
+ const templatesDir = join15(wrapsDir, config2.templatesDir || "./templates");
23039
23076
  if (!existsSync13(templatesDir)) {
23040
23077
  throw errors.wrapsConfigNotFound();
23041
23078
  }
@@ -23054,7 +23091,7 @@ async function templatesPush(options) {
23054
23091
  const compileErrors = [];
23055
23092
  for (const file of templateFiles) {
23056
23093
  const slug = file.replace(/\.tsx?$/, "");
23057
- const filePath = join14(templatesDir, file);
23094
+ const filePath = join15(templatesDir, file);
23058
23095
  const source = await readFile6(filePath, "utf-8");
23059
23096
  const sourceHash = sha256(source);
23060
23097
  const localHashMatches = lockfile.templates[slug]?.localHash === sourceHash;
@@ -23196,10 +23233,10 @@ async function compileTemplate(filePath, slug, source, sourceHash, wrapsDir) {
23196
23233
  }
23197
23234
  });
23198
23235
  const bundledCode = result.outputFiles[0].text;
23199
- const projectRoot = join14(wrapsDir, "..");
23200
- const tmpDir = join14(projectRoot, "node_modules", ".wraps-compiled");
23236
+ const projectRoot = join15(wrapsDir, "..");
23237
+ const tmpDir = join15(projectRoot, "node_modules", ".wraps-compiled");
23201
23238
  await mkdir6(tmpDir, { recursive: true });
23202
- const tmpPath = join14(tmpDir, `${slug}.mjs`);
23239
+ const tmpPath = join15(tmpDir, `${slug}.mjs`);
23203
23240
  await writeFile8(tmpPath, bundledCode, "utf-8");
23204
23241
  const mod = await import(tmpPath);
23205
23242
  const Component = mod.default;
@@ -23513,6 +23550,7 @@ init_json_output();
23513
23550
  init_metadata();
23514
23551
  init_output();
23515
23552
  init_prompts();
23553
+ init_pulumi();
23516
23554
  async function upgrade(options) {
23517
23555
  const startTime = Date.now();
23518
23556
  let upgradeAction = "";
@@ -23713,13 +23751,17 @@ ${pc30.bold("Current Configuration:")}
23713
23751
  hint: metadata.provider === "vercel" ? `Currently: Vercel (${metadata.vercel?.teamSlug || "configured"})` : `Currently: ${metadata.provider} \u2192 Switch to Vercel OIDC, etc.`
23714
23752
  }
23715
23753
  );
23716
- upgradeAction = await clack29.select({
23717
- message: "What would you like to do?",
23718
- options: upgradeOptions
23719
- });
23720
- if (clack29.isCancel(upgradeAction)) {
23721
- clack29.cancel("Upgrade cancelled.");
23722
- process.exit(0);
23754
+ if (options.action) {
23755
+ upgradeAction = options.action;
23756
+ } else {
23757
+ upgradeAction = await clack29.select({
23758
+ message: "What would you like to do?",
23759
+ options: upgradeOptions
23760
+ });
23761
+ if (clack29.isCancel(upgradeAction)) {
23762
+ clack29.cancel("Upgrade cancelled.");
23763
+ process.exit(0);
23764
+ }
23723
23765
  }
23724
23766
  let updatedConfig = { ...config2 };
23725
23767
  let newPreset = metadata.services.email?.preset;
@@ -23749,13 +23791,18 @@ ${pc30.bold("Current Configuration:")}
23749
23791
  clack29.log.warn("Already on highest preset (Enterprise)");
23750
23792
  process.exit(0);
23751
23793
  }
23752
- const selectedPreset = await clack29.select({
23753
- message: "Select new preset:",
23754
- options: availablePresets
23755
- });
23756
- if (clack29.isCancel(selectedPreset)) {
23757
- clack29.cancel("Upgrade cancelled.");
23758
- process.exit(0);
23794
+ let selectedPreset;
23795
+ if (options.preset) {
23796
+ selectedPreset = options.preset;
23797
+ } else {
23798
+ selectedPreset = await clack29.select({
23799
+ message: "Select new preset:",
23800
+ options: availablePresets
23801
+ });
23802
+ if (clack29.isCancel(selectedPreset)) {
23803
+ clack29.cancel("Upgrade cancelled.");
23804
+ process.exit(0);
23805
+ }
23759
23806
  }
23760
23807
  const presetConfig = getPreset(selectedPreset);
23761
23808
  updatedConfig = applyConfigUpdates(config2, presetConfig);
@@ -24772,13 +24819,15 @@ ${pc30.bold("SMTP Credentials for Legacy Systems")}
24772
24819
  "Credentials will be shown ONCE after deployment - save them immediately!"
24773
24820
  );
24774
24821
  console.log("");
24775
- const confirmCreate = await clack29.confirm({
24776
- message: "Create SMTP credentials?",
24777
- initialValue: true
24778
- });
24779
- if (clack29.isCancel(confirmCreate) || !confirmCreate) {
24780
- clack29.log.info("SMTP credentials not created.");
24781
- process.exit(0);
24822
+ if (!options.yes) {
24823
+ const confirmCreate = await clack29.confirm({
24824
+ message: "Create SMTP credentials?",
24825
+ initialValue: true
24826
+ });
24827
+ if (clack29.isCancel(confirmCreate) || !confirmCreate) {
24828
+ clack29.log.info("SMTP credentials not created.");
24829
+ process.exit(0);
24830
+ }
24782
24831
  }
24783
24832
  updatedConfig = {
24784
24833
  ...config2,
@@ -25091,7 +25140,7 @@ ${pc30.bold("Cost Impact:")}`);
25091
25140
  throw new Error(`Pulumi upgrade failed: ${msg}`);
25092
25141
  }
25093
25142
  let dnsAutoCreated = false;
25094
- if (outputs.domain && outputs.dkimTokens && outputs.dkimTokens.length > 0) {
25143
+ if (!isJsonMode() && outputs.domain && outputs.dkimTokens && outputs.dkimTokens.length > 0) {
25095
25144
  let dnsProvider = metadata.services.email?.dnsProvider;
25096
25145
  if (!dnsProvider) {
25097
25146
  const availableProviders = await progress.execute(
@@ -25493,7 +25542,7 @@ init_json_output();
25493
25542
  init_output();
25494
25543
  import { existsSync as existsSync14 } from "fs";
25495
25544
  import { mkdir as mkdir7, readFile as readFile7, writeFile as writeFile9 } from "fs/promises";
25496
- import { join as join15 } from "path";
25545
+ import { join as join16 } from "path";
25497
25546
  import * as clack30 from "@clack/prompts";
25498
25547
  import pc31 from "picocolors";
25499
25548
 
@@ -25884,7 +25933,7 @@ export default defineWorkflow({
25884
25933
  async function workflowsInit(options) {
25885
25934
  const startTime = Date.now();
25886
25935
  const cwd = process.cwd();
25887
- const workflowsDir = join15(cwd, "wraps", "workflows");
25936
+ const workflowsDir = join16(cwd, "wraps", "workflows");
25888
25937
  if (!isJsonMode()) {
25889
25938
  clack30.intro(pc31.bold("Workflows as Code"));
25890
25939
  }
@@ -25903,7 +25952,7 @@ async function workflowsInit(options) {
25903
25952
  }
25904
25953
  progress.start("Creating wraps/workflows/ directory");
25905
25954
  await mkdir7(workflowsDir, { recursive: true });
25906
- const configPath = join15(cwd, "wraps", "wraps.config.ts");
25955
+ const configPath = join16(cwd, "wraps", "wraps.config.ts");
25907
25956
  if (existsSync14(configPath)) {
25908
25957
  const configContent = await readFile7(configPath, "utf-8");
25909
25958
  if (!configContent.includes("workflowsDir")) {
@@ -25921,7 +25970,7 @@ async function workflowsInit(options) {
25921
25970
  }
25922
25971
  const filesCreated = [];
25923
25972
  if (!options.noExample) {
25924
- const examplePath = join15(workflowsDir, "welcome.ts");
25973
+ const examplePath = join16(workflowsDir, "welcome.ts");
25925
25974
  if (!existsSync14(examplePath) || options.force) {
25926
25975
  await writeFile9(examplePath, EXAMPLE_WORKFLOW, "utf-8");
25927
25976
  filesCreated.push("wraps/workflows/welcome.ts");
@@ -26005,7 +26054,7 @@ export default defineConfig({
26005
26054
  init_esm_shims();
26006
26055
  init_events();
26007
26056
  import { existsSync as existsSync16 } from "fs";
26008
- import { join as join17 } from "path";
26057
+ import { join as join18 } from "path";
26009
26058
  import * as clack31 from "@clack/prompts";
26010
26059
  import pc32 from "picocolors";
26011
26060
 
@@ -26226,7 +26275,7 @@ init_esm_shims();
26226
26275
  import { createHash as createHash2 } from "crypto";
26227
26276
  import { existsSync as existsSync15 } from "fs";
26228
26277
  import { mkdir as mkdir8, readdir as readdir4, readFile as readFile8, writeFile as writeFile10 } from "fs/promises";
26229
- import { basename, join as join16 } from "path";
26278
+ import { basename, join as join17 } from "path";
26230
26279
  async function discoverWorkflows(dir, filter) {
26231
26280
  if (!existsSync15(dir)) {
26232
26281
  return [];
@@ -26251,7 +26300,7 @@ async function parseWorkflowTs(filePath, wrapsDir) {
26251
26300
  const source = await readFile8(filePath, "utf-8");
26252
26301
  const sourceHash = createHash2("sha256").update(source).digest("hex");
26253
26302
  const slug = basename(filePath, ".ts");
26254
- const shimDir = join16(wrapsDir, ".wraps", "_shims");
26303
+ const shimDir = join17(wrapsDir, ".wraps", "_shims");
26255
26304
  await mkdir8(shimDir, { recursive: true });
26256
26305
  const clientShimContent = `
26257
26306
  // Identity functions for workflow definitions
@@ -26480,7 +26529,7 @@ function durationToSeconds(duration) {
26480
26529
  }
26481
26530
  `;
26482
26531
  await writeFile10(
26483
- join16(shimDir, "wraps-client-shim.mjs"),
26532
+ join17(shimDir, "wraps-client-shim.mjs"),
26484
26533
  clientShimContent,
26485
26534
  "utf-8"
26486
26535
  );
@@ -26492,13 +26541,13 @@ function durationToSeconds(duration) {
26492
26541
  platform: "node",
26493
26542
  target: "node20",
26494
26543
  alias: {
26495
- "@wraps.dev/client": join16(shimDir, "wraps-client-shim.mjs")
26544
+ "@wraps.dev/client": join17(shimDir, "wraps-client-shim.mjs")
26496
26545
  }
26497
26546
  });
26498
26547
  const bundledCode = result.outputFiles[0].text;
26499
- const tmpDir = join16(wrapsDir, ".wraps", "_workflows");
26548
+ const tmpDir = join17(wrapsDir, ".wraps", "_workflows");
26500
26549
  await mkdir8(tmpDir, { recursive: true });
26501
- const tmpPath = join16(tmpDir, `${slug}.mjs`);
26550
+ const tmpPath = join17(tmpDir, `${slug}.mjs`);
26502
26551
  await writeFile10(tmpPath, bundledCode, "utf-8");
26503
26552
  const mod = await import(`${tmpPath}?t=${Date.now()}`);
26504
26553
  const definition = mod.default;
@@ -26851,8 +26900,8 @@ init_output();
26851
26900
  async function workflowsPush(options) {
26852
26901
  const startTime = Date.now();
26853
26902
  const cwd = process.cwd();
26854
- const wrapsDir = join17(cwd, "wraps");
26855
- const configPath = join17(wrapsDir, "wraps.config.ts");
26903
+ const wrapsDir = join18(cwd, "wraps");
26904
+ const configPath = join18(wrapsDir, "wraps.config.ts");
26856
26905
  if (!existsSync16(configPath)) {
26857
26906
  throw errors.wrapsConfigNotFound();
26858
26907
  }
@@ -26863,7 +26912,7 @@ async function workflowsPush(options) {
26863
26912
  progress.start("Loading configuration");
26864
26913
  const config2 = await loadWrapsConfig(wrapsDir);
26865
26914
  progress.succeed("Configuration loaded");
26866
- const workflowsDir = join17(wrapsDir, config2.workflowsDir || "./workflows");
26915
+ const workflowsDir = join18(wrapsDir, config2.workflowsDir || "./workflows");
26867
26916
  if (!existsSync16(workflowsDir)) {
26868
26917
  if (isJsonMode()) {
26869
26918
  jsonSuccess("email.workflows.push", {
@@ -26890,7 +26939,7 @@ async function workflowsPush(options) {
26890
26939
  return;
26891
26940
  }
26892
26941
  const lockfile = await loadLockfile(wrapsDir);
26893
- const templatesDir = join17(wrapsDir, config2.templatesDir || "./templates");
26942
+ const templatesDir = join18(wrapsDir, config2.templatesDir || "./templates");
26894
26943
  let localTemplateSlugs;
26895
26944
  if (existsSync16(templatesDir)) {
26896
26945
  const templateFiles = await discoverTemplates(templatesDir);
@@ -26904,7 +26953,7 @@ async function workflowsPush(options) {
26904
26953
  const validationErrors = [];
26905
26954
  for (const file of workflowFiles) {
26906
26955
  const slug = file.replace(/\.ts$/, "");
26907
- const filePath = join17(workflowsDir, file);
26956
+ const filePath = join18(workflowsDir, file);
26908
26957
  progress.start(`Processing ${pc32.cyan(slug)}`);
26909
26958
  try {
26910
26959
  const parsed = await parseWorkflowTs(filePath, wrapsDir);
@@ -27223,7 +27272,7 @@ async function pushToAPI2(workflows, token, progress, options) {
27223
27272
  init_esm_shims();
27224
27273
  init_events();
27225
27274
  import { existsSync as existsSync17 } from "fs";
27226
- import { join as join18 } from "path";
27275
+ import { join as join19 } from "path";
27227
27276
  import * as clack32 from "@clack/prompts";
27228
27277
  import pc33 from "picocolors";
27229
27278
  init_errors();
@@ -27232,8 +27281,8 @@ init_output();
27232
27281
  async function workflowsValidate(options) {
27233
27282
  const startTime = Date.now();
27234
27283
  const cwd = process.cwd();
27235
- const wrapsDir = join18(cwd, "wraps");
27236
- const configPath = join18(wrapsDir, "wraps.config.ts");
27284
+ const wrapsDir = join19(cwd, "wraps");
27285
+ const configPath = join19(wrapsDir, "wraps.config.ts");
27237
27286
  if (!existsSync17(configPath)) {
27238
27287
  throw errors.wrapsConfigNotFound();
27239
27288
  }
@@ -27244,7 +27293,7 @@ async function workflowsValidate(options) {
27244
27293
  progress.start("Loading configuration");
27245
27294
  const config2 = await loadWrapsConfig(wrapsDir);
27246
27295
  progress.succeed("Configuration loaded");
27247
- const workflowsDir = join18(wrapsDir, config2.workflowsDir || "./workflows");
27296
+ const workflowsDir = join19(wrapsDir, config2.workflowsDir || "./workflows");
27248
27297
  if (!existsSync17(workflowsDir)) {
27249
27298
  if (isJsonMode()) {
27250
27299
  jsonSuccess("email.workflows.validate", { workflows: [], errors: [] });
@@ -27262,7 +27311,7 @@ async function workflowsValidate(options) {
27262
27311
  }
27263
27312
  return;
27264
27313
  }
27265
- const templatesDir = join18(wrapsDir, config2.templatesDir || "./templates");
27314
+ const templatesDir = join19(wrapsDir, config2.templatesDir || "./templates");
27266
27315
  let localTemplateSlugs;
27267
27316
  if (existsSync17(templatesDir)) {
27268
27317
  const templateFiles = await discoverTemplates(templatesDir);
@@ -27274,7 +27323,7 @@ async function workflowsValidate(options) {
27274
27323
  const parseErrors = [];
27275
27324
  for (const file of workflowFiles) {
27276
27325
  const slug = file.replace(/\.ts$/, "");
27277
- const filePath = join18(workflowsDir, file);
27326
+ const filePath = join19(workflowsDir, file);
27278
27327
  progress.start(`Validating ${pc33.cyan(slug)}`);
27279
27328
  try {
27280
27329
  const parsed = await parseWorkflowTs(filePath, wrapsDir);
@@ -27915,6 +27964,7 @@ init_json_output();
27915
27964
  init_metadata();
27916
27965
  init_output();
27917
27966
  init_prompts();
27967
+ init_pulumi();
27918
27968
  function buildConsolePolicyDocument(emailConfig, smsConfig) {
27919
27969
  const statements = [];
27920
27970
  statements.push({
@@ -29178,7 +29228,7 @@ import pc39 from "picocolors";
29178
29228
  init_esm_shims();
29179
29229
  import crypto from "crypto";
29180
29230
  import path2 from "path";
29181
- import { fileURLToPath as fileURLToPath4 } from "url";
29231
+ import { fileURLToPath as fileURLToPath5 } from "url";
29182
29232
  import express from "express";
29183
29233
  import { createHttpTerminator } from "http-terminator";
29184
29234
 
@@ -31702,7 +31752,7 @@ function createUserRouter(config2) {
31702
31752
  }
31703
31753
 
31704
31754
  // src/console/server.ts
31705
- var __dirname2 = path2.dirname(fileURLToPath4(import.meta.url));
31755
+ var __dirname2 = path2.dirname(fileURLToPath5(import.meta.url));
31706
31756
  async function startConsoleServer(config2) {
31707
31757
  const app = express();
31708
31758
  const authToken = crypto.randomBytes(32).toString("hex");
@@ -31798,6 +31848,7 @@ init_aws();
31798
31848
  init_fs();
31799
31849
  init_metadata();
31800
31850
  init_output();
31851
+ init_pulumi();
31801
31852
  async function dashboard(options) {
31802
31853
  await ensurePulumiInstalled();
31803
31854
  clack36.intro(pc39.bold("Wraps Dashboard"));
@@ -32032,6 +32083,7 @@ init_aws();
32032
32083
  init_fs();
32033
32084
  init_json_output();
32034
32085
  init_output();
32086
+ init_pulumi();
32035
32087
  import * as clack38 from "@clack/prompts";
32036
32088
  import * as pulumi23 from "@pulumi/pulumi";
32037
32089
  import pc41 from "picocolors";
@@ -32981,6 +33033,7 @@ init_fs();
32981
33033
  init_json_output();
32982
33034
  init_metadata();
32983
33035
  init_output();
33036
+ init_pulumi();
32984
33037
  async function smsDestroy(options) {
32985
33038
  await ensurePulumiInstalled();
32986
33039
  const startTime = Date.now();
@@ -33214,6 +33267,7 @@ init_json_output();
33214
33267
  init_metadata();
33215
33268
  init_output();
33216
33269
  init_prompts();
33270
+ init_pulumi();
33217
33271
 
33218
33272
  // src/utils/sms/costs.ts
33219
33273
  init_esm_shims();
@@ -34273,6 +34327,7 @@ init_fs();
34273
34327
  init_json_output();
34274
34328
  init_metadata();
34275
34329
  init_output();
34330
+ init_pulumi();
34276
34331
  import * as clack42 from "@clack/prompts";
34277
34332
  import * as pulumi27 from "@pulumi/pulumi";
34278
34333
  import pc45 from "picocolors";
@@ -34395,6 +34450,7 @@ init_fs();
34395
34450
  init_json_output();
34396
34451
  init_metadata();
34397
34452
  init_output();
34453
+ init_pulumi();
34398
34454
  async function smsSync(options) {
34399
34455
  await ensurePulumiInstalled();
34400
34456
  const startTime = Date.now();
@@ -34832,6 +34888,7 @@ init_json_output();
34832
34888
  init_metadata();
34833
34889
  init_output();
34834
34890
  init_prompts();
34891
+ init_pulumi();
34835
34892
  async function smsUpgrade(options) {
34836
34893
  const startTime = Date.now();
34837
34894
  let upgradeAction = "";
@@ -36279,7 +36336,7 @@ async function telemetryStatus() {
36279
36336
  // src/commands/workflow/init.ts
36280
36337
  init_esm_shims();
36281
36338
  import { existsSync as existsSync18, mkdirSync as mkdirSync2, writeFileSync } from "fs";
36282
- import { join as join19 } from "path";
36339
+ import { join as join20 } from "path";
36283
36340
  import * as clack49 from "@clack/prompts";
36284
36341
  import pc52 from "picocolors";
36285
36342
  var EXAMPLE_CASCADE_WORKFLOW = `import {
@@ -36377,14 +36434,14 @@ export default defineConfig({
36377
36434
  `;
36378
36435
  async function workflowInit(options = {}) {
36379
36436
  clack49.intro(pc52.bgCyan(pc52.black(" wraps workflow init ")));
36380
- const wrapsDir = join19(process.cwd(), "wraps");
36381
- const workflowsDir = join19(wrapsDir, "workflows");
36382
- const configPath = join19(wrapsDir, "wraps.config.ts");
36437
+ const wrapsDir = join20(process.cwd(), "wraps");
36438
+ const workflowsDir = join20(wrapsDir, "workflows");
36439
+ const configPath = join20(wrapsDir, "wraps.config.ts");
36383
36440
  if (existsSync18(workflowsDir)) {
36384
36441
  clack49.log.info(
36385
36442
  `Workflows directory already exists at ${pc52.cyan("wraps/workflows/")}`
36386
36443
  );
36387
- const files = existsSync18(join19(workflowsDir, "cart-recovery.ts")) || existsSync18(join19(workflowsDir, "welcome-sequence.ts"));
36444
+ const files = existsSync18(join20(workflowsDir, "cart-recovery.ts")) || existsSync18(join20(workflowsDir, "welcome-sequence.ts"));
36388
36445
  if (files && !options.yes) {
36389
36446
  const shouldContinue = await clack49.confirm({
36390
36447
  message: "Example files may already exist. Overwrite them?",
@@ -36405,12 +36462,12 @@ async function workflowInit(options = {}) {
36405
36462
  s.stop("Created wraps/workflows/");
36406
36463
  s.start("Scaffolding example workflows...");
36407
36464
  writeFileSync(
36408
- join19(workflowsDir, "cart-recovery.ts"),
36465
+ join20(workflowsDir, "cart-recovery.ts"),
36409
36466
  EXAMPLE_CASCADE_WORKFLOW,
36410
36467
  "utf-8"
36411
36468
  );
36412
36469
  writeFileSync(
36413
- join19(workflowsDir, "welcome-sequence.ts"),
36470
+ join20(workflowsDir, "welcome-sequence.ts"),
36414
36471
  EXAMPLE_WELCOME_WORKFLOW,
36415
36472
  "utf-8"
36416
36473
  );
@@ -36515,10 +36572,10 @@ if (nodeMajorVersion < 20) {
36515
36572
  console.error("");
36516
36573
  process.exit(1);
36517
36574
  }
36518
- var __filename2 = fileURLToPath5(import.meta.url);
36519
- var __dirname3 = dirname4(__filename2);
36575
+ var __filename2 = fileURLToPath6(import.meta.url);
36576
+ var __dirname3 = dirname5(__filename2);
36520
36577
  var packageJson = JSON.parse(
36521
- readFileSync3(join20(__dirname3, "../package.json"), "utf-8")
36578
+ readFileSync3(join21(__dirname3, "../package.json"), "utf-8")
36522
36579
  );
36523
36580
  var VERSION = packageJson.version;
36524
36581
  setupTabCompletion();
@@ -36806,6 +36863,12 @@ args.options([
36806
36863
  description: "Resend verification code",
36807
36864
  defaultValue: false
36808
36865
  },
36866
+ // Email upgrade options
36867
+ {
36868
+ name: "action",
36869
+ description: "Upgrade action (preset, smtp-credentials, events, archiving, etc.)",
36870
+ defaultValue: void 0
36871
+ },
36809
36872
  // Email test options
36810
36873
  {
36811
36874
  name: "scenario",
@@ -37157,7 +37220,9 @@ async function run() {
37157
37220
  region: flags.region,
37158
37221
  yes: flags.yes,
37159
37222
  preview: flags.preview,
37160
- json: flags.json
37223
+ json: flags.json,
37224
+ action: flags.action,
37225
+ preset: flags.preset
37161
37226
  });
37162
37227
  break;
37163
37228
  case "restore":