@wraps.dev/cli 2.19.0 → 2.19.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -842,7 +842,7 @@ To remove: wraps destroy --stack ${stackName}`,
842
842
  "The Pulumi stack is locked from a previous run",
843
843
  "STACK_LOCKED",
844
844
  "This happens when a previous deployment was interrupted.\n\nFor local state, run:\n rm -rf ~/.wraps/pulumi/.pulumi/locks\n\nFor S3 state, delete the lock object in your wraps-state-* bucket under .pulumi/locks/\n\nThen try your command again.",
845
- "https://wraps.dev/docs/guides/aws-setup/permissions/troubleshooting"
845
+ "https://wraps.dev/docs/guides/aws-setup/troubleshooting"
846
846
  ),
847
847
  // SMS-specific errors
848
848
  smsNotConfigured: () => new WrapsError(
@@ -958,7 +958,7 @@ View required SES permissions:
958
958
  `SES rejected the message: ${detail}`,
959
959
  "SES_MESSAGE_REJECTED",
960
960
  "Common causes:\n \u2022 Account is in the SES sandbox and the recipient is not a verified address\n \u2022 Sender identity (domain or email) is not verified for sending\n \u2022 The sender domain is verified for receiving but not for sending\n\nCheck status:\n wraps email status\n wraps email doctor\n\nRequest production access (exit sandbox):\n https://docs.aws.amazon.com/ses/latest/dg/request-production-access.html",
961
- "https://wraps.dev/docs/guides/email/troubleshooting"
961
+ "https://wraps.dev/docs/guides/aws-setup/troubleshooting"
962
962
  ),
963
963
  sesMailFromNotVerified: (detail) => new WrapsError(
964
964
  `SES MAIL FROM domain is not verified: ${detail}`,
@@ -1088,25 +1088,25 @@ You may need to merge your existing rules into the wraps rule set.`,
1088
1088
  "wraps/wraps.config.ts not found",
1089
1089
  "WRAPS_CONFIG_NOT_FOUND",
1090
1090
  "Initialize templates first:\n wraps email templates init",
1091
- "https://wraps.dev/docs/templates-as-code"
1091
+ "https://wraps.dev/docs/guides/templates"
1092
1092
  ),
1093
1093
  templateCompilationFailed: (name, error) => new WrapsError(
1094
1094
  `Failed to compile template "${name}": ${error}`,
1095
1095
  "TEMPLATE_COMPILATION_FAILED",
1096
1096
  "Check your template for syntax errors and ensure all imports are valid.",
1097
- "https://wraps.dev/docs/templates-as-code"
1097
+ "https://wraps.dev/docs/guides/templates"
1098
1098
  ),
1099
1099
  notAuthenticated: () => new WrapsError(
1100
1100
  "Not authenticated to Wraps Platform",
1101
1101
  "NOT_AUTHENTICATED",
1102
1102
  "Sign in first:\n wraps auth login\n\nOr provide an API key:\n wraps push --token wraps_...\n WRAPS_API_KEY=wraps_... wraps push",
1103
- "https://wraps.dev/docs/auth"
1103
+ "https://wraps.dev/docs/cli-reference/auth"
1104
1104
  ),
1105
1105
  templatePushFailed: (name, error) => new WrapsError(
1106
1106
  `Failed to push template "${name}": ${error}`,
1107
1107
  "TEMPLATE_PUSH_FAILED",
1108
1108
  "Check your API key and network connection.",
1109
- "https://wraps.dev/docs/templates-as-code"
1109
+ "https://wraps.dev/docs/guides/templates"
1110
1110
  )
1111
1111
  };
1112
1112
  }
@@ -11812,6 +11812,7 @@ async function createCdnBucket(config2) {
11812
11812
  const corsOrigins = [
11813
11813
  "https://wraps.dev",
11814
11814
  "https://*.wraps.dev",
11815
+ "https://*.wraps.localhost",
11815
11816
  "http://localhost:3000",
11816
11817
  "http://localhost:3001",
11817
11818
  "http://localhost:3002",
@@ -21245,6 +21246,8 @@ async function inboundInit(options) {
21245
21246
  subdomain,
21246
21247
  bucketName: `wraps-inbound-${identity.accountId}-${region}`,
21247
21248
  webhookUrl: webhookUrl || null,
21249
+ webhookSecret: webhookUrl ? webhookSecret : null,
21250
+ webhookHeader: webhookUrl ? "X-Wraps-Inbound-Key" : null,
21248
21251
  dnsAutoCreated,
21249
21252
  region
21250
21253
  });
@@ -21263,6 +21266,27 @@ async function inboundInit(options) {
21263
21266
  if (dnsAutoCreated) {
21264
21267
  console.log(` ${pc24.dim("DNS:")} ${pc24.green("Auto-created")}`);
21265
21268
  }
21269
+ if (webhookUrl) {
21270
+ const setupLines = [
21271
+ `EventBridge will POST every ${pc24.cyan("email.received")} event to:`,
21272
+ ` ${pc24.cyan(webhookUrl)}`,
21273
+ "",
21274
+ "Verify the request by checking this header on every POST:",
21275
+ ` ${pc24.bold("X-Wraps-Inbound-Key")}: ${pc24.yellow(webhookSecret)}`,
21276
+ "",
21277
+ pc24.bold("Save this secret now \u2014 it is only shown once."),
21278
+ `Retrieve it later with: ${pc24.cyan("wraps email inbound status --reveal-secret")}`,
21279
+ "",
21280
+ "Body shape (JSON):",
21281
+ pc24.dim(
21282
+ ' { "emailId", "from", "to", "subject", "html", "text", "attachments", "headers", ... }'
21283
+ ),
21284
+ "",
21285
+ `Docs: ${pc24.cyan("https://wraps.dev/docs/quickstart/email/inbound")}`
21286
+ ].join("\n");
21287
+ console.log();
21288
+ clack22.note(setupLines, "Webhook setup");
21289
+ }
21266
21290
  console.log();
21267
21291
  console.log(pc24.bold("Next steps:"));
21268
21292
  if (dnsAutoCreated) {
@@ -21413,6 +21437,8 @@ Enable it: ${pc24.cyan("wraps email inbound init")}
21413
21437
  bucketName: inbound.bucketName || "",
21414
21438
  region,
21415
21439
  webhookUrl: inbound.webhookUrl || null,
21440
+ webhookHeader: inbound.webhookUrl ? "X-Wraps-Inbound-Key" : null,
21441
+ webhookSecret: options.revealSecret && inbound.webhookUrl ? inbound.webhookSecret || null : null,
21416
21442
  receiptRuleSetActive: activeRuleSet === RULE_SET_NAME,
21417
21443
  retention: inbound.retention || null
21418
21444
  });
@@ -21436,6 +21462,20 @@ Enable it: ${pc24.cyan("wraps email inbound init")}
21436
21462
  console.log(
21437
21463
  ` ${pc24.dim("Webhook URL:")} ${inbound.webhookUrl ? pc24.cyan(inbound.webhookUrl) : pc24.dim("not configured")}`
21438
21464
  );
21465
+ if (inbound.webhookUrl) {
21466
+ console.log(
21467
+ ` ${pc24.dim("Webhook header:")} ${pc24.cyan("X-Wraps-Inbound-Key")}`
21468
+ );
21469
+ if (options.revealSecret) {
21470
+ console.log(
21471
+ ` ${pc24.dim("Webhook secret:")} ${inbound.webhookSecret ? pc24.yellow(inbound.webhookSecret) : pc24.dim("not set")}`
21472
+ );
21473
+ } else {
21474
+ console.log(
21475
+ ` ${pc24.dim("Webhook secret:")} ${pc24.dim("hidden \u2014 pass --reveal-secret to show")}`
21476
+ );
21477
+ }
21478
+ }
21439
21479
  console.log(
21440
21480
  ` ${pc24.dim("Receipt rule set:")} ${activeRuleSet === RULE_SET_NAME ? pc24.green("active") : pc24.yellow("inactive")}`
21441
21481
  );
@@ -21571,7 +21611,7 @@ function mapInboundTestSendError(error, ctx) {
21571
21611
  `Failed to send inbound test email to ${ctx.recipient}`,
21572
21612
  "INBOUND_TEST_SEND_FAILED",
21573
21613
  "An unexpected error occurred while sending the test email.\n\nCheck infrastructure status:\n wraps email status\n wraps email doctor",
21574
- "https://wraps.dev/docs/guides/email/troubleshooting"
21614
+ "https://wraps.dev/docs/guides/aws-setup/troubleshooting"
21575
21615
  );
21576
21616
  }
21577
21617
  const name = error.name;
@@ -21608,7 +21648,7 @@ Or remove the custom MAIL FROM domain in the SES console and retry.`,
21608
21648
  "Exit the SES sandbox to send to any address:",
21609
21649
  " https://docs.aws.amazon.com/ses/latest/dg/request-production-access.html"
21610
21650
  ].join("\n"),
21611
- "https://wraps.dev/docs/guides/email/troubleshooting"
21651
+ "https://wraps.dev/docs/guides/aws-setup/troubleshooting"
21612
21652
  );
21613
21653
  }
21614
21654
  if (name === "AccountSendingPausedException" || name === "ConfigurationSetSendingPausedException") {
@@ -23049,7 +23089,7 @@ async function replyInitForSingleDomain(params) {
23049
23089
  `The Pulumi deploy completed but the SSM parameter ${ssmParameterName(domain)} was not found. Run:
23050
23090
  wraps email reply status
23051
23091
  to diagnose, or retry the init.`,
23052
- "https://wraps.dev/docs/guides/email/reply-threading"
23092
+ "https://wraps.dev/docs/guides/reply-threading"
23053
23093
  );
23054
23094
  }
23055
23095
  const finalEntry = {
@@ -23162,7 +23202,7 @@ async function replyInit(options) {
23162
23202
  "Reply threading requires inbound email infrastructure",
23163
23203
  "REPLY_REQUIRES_INBOUND",
23164
23204
  "Deploy inbound first:\n wraps email inbound init\n\nThen enable reply threading:\n wraps email reply init --domain yourapp.com",
23165
- "https://wraps.dev/docs/guides/email/reply-threading"
23205
+ "https://wraps.dev/docs/guides/reply-threading"
23166
23206
  );
23167
23207
  }
23168
23208
  const emailService = metadata.services.email;
@@ -23178,7 +23218,7 @@ async function replyInit(options) {
23178
23218
  "No inbound domains configured",
23179
23219
  "REPLY_NO_INBOUND_DOMAINS",
23180
23220
  "Add an inbound domain first:\n wraps email inbound add --domain yourapp.com",
23181
- "https://wraps.dev/docs/guides/email/reply-threading"
23221
+ "https://wraps.dev/docs/guides/reply-threading"
23182
23222
  );
23183
23223
  }
23184
23224
  let targetDomains;
@@ -23207,7 +23247,7 @@ async function replyInit(options) {
23207
23247
  "REPLY_INBOUND_DOMAIN_NOT_FOUND",
23208
23248
  `Add it to inbound first:
23209
23249
  wraps email inbound add ${target}`,
23210
- "https://wraps.dev/docs/guides/email/reply-threading"
23250
+ "https://wraps.dev/docs/guides/reply-threading"
23211
23251
  );
23212
23252
  }
23213
23253
  if (isReplyEnabledFor(metadata, target)) {
@@ -23216,7 +23256,7 @@ async function replyInit(options) {
23216
23256
  "REPLY_ALREADY_ENABLED",
23217
23257
  `To rotate the signing secret, run:
23218
23258
  wraps email reply rotate --domain ${target}`,
23219
- "https://wraps.dev/docs/guides/email/reply-threading"
23259
+ "https://wraps.dev/docs/guides/reply-threading"
23220
23260
  );
23221
23261
  }
23222
23262
  targetDomains = [target];
@@ -23225,7 +23265,7 @@ async function replyInit(options) {
23225
23265
  "Specify a domain or use --all",
23226
23266
  "REPLY_MISSING_DOMAIN",
23227
23267
  "Use one of:\n wraps email reply init --domain yourapp.com\n wraps email reply init --all",
23228
- "https://wraps.dev/docs/guides/email/reply-threading"
23268
+ "https://wraps.dev/docs/guides/reply-threading"
23229
23269
  );
23230
23270
  }
23231
23271
  const stackName = emailService.pulumiStackName || `wraps-${identity.accountId}-${region}`;
@@ -23277,7 +23317,7 @@ async function replyRotate(options) {
23277
23317
  "--domain is required for rotate",
23278
23318
  "REPLY_ROTATE_MISSING_DOMAIN",
23279
23319
  "Usage:\n wraps email reply rotate --domain yourapp.com",
23280
- "https://wraps.dev/docs/guides/email/reply-threading"
23320
+ "https://wraps.dev/docs/guides/reply-threading"
23281
23321
  );
23282
23322
  }
23283
23323
  const identity = await progress.execute(
@@ -23291,7 +23331,7 @@ async function replyRotate(options) {
23291
23331
  "Reply threading is not enabled",
23292
23332
  "REPLY_NOT_ENABLED",
23293
23333
  "Enable it first:\n wraps email reply init --domain yourapp.com",
23294
- "https://wraps.dev/docs/guides/email/reply-threading"
23334
+ "https://wraps.dev/docs/guides/reply-threading"
23295
23335
  );
23296
23336
  }
23297
23337
  const rt = metadata.services.email.config.replyThreading;
@@ -23302,7 +23342,7 @@ async function replyRotate(options) {
23302
23342
  "REPLY_DOMAIN_NOT_ENABLED",
23303
23343
  `Enable it first:
23304
23344
  wraps email reply init --domain ${options.domain}`,
23305
- "https://wraps.dev/docs/guides/email/reply-threading"
23345
+ "https://wraps.dev/docs/guides/reply-threading"
23306
23346
  );
23307
23347
  }
23308
23348
  const parameterName = entry.parameterName || ssmParameterName(options.domain);
@@ -23327,7 +23367,7 @@ async function replyRotate(options) {
23327
23367
  "REPLY_SECRET_PARAMETER_MISSING",
23328
23368
  `The signing secret for ${options.domain} has not been created yet. Run:
23329
23369
  wraps email reply init --domain ${options.domain}`,
23330
- "https://wraps.dev/docs/guides/email/reply-threading"
23370
+ "https://wraps.dev/docs/guides/reply-threading"
23331
23371
  );
23332
23372
  }
23333
23373
  throw error;
@@ -23567,7 +23607,7 @@ async function replyDestroy(options) {
23567
23607
  "Specify a domain or use --all",
23568
23608
  "REPLY_DESTROY_MISSING_DOMAIN",
23569
23609
  "Usage:\n wraps email reply destroy --domain yourapp.com\n wraps email reply destroy --all",
23570
- "https://wraps.dev/docs/guides/email/reply-threading"
23610
+ "https://wraps.dev/docs/guides/reply-threading"
23571
23611
  );
23572
23612
  }
23573
23613
  if (!(options.force || isJsonMode())) {
@@ -23622,7 +23662,7 @@ async function replyDecode(addressInput, options) {
23622
23662
  "Usage: wraps email reply decode <token>@r.mail.yourapp.com",
23623
23663
  "REPLY_DECODE_MISSING_ADDRESS",
23624
23664
  "Provide a signed reply address like:\n wraps email reply decode abcDEF123@r.mail.yourapp.com",
23625
- "https://wraps.dev/docs/guides/email/reply-threading"
23665
+ "https://wraps.dev/docs/guides/reply-threading"
23626
23666
  );
23627
23667
  }
23628
23668
  const at = addressInput.lastIndexOf("@");
@@ -23632,7 +23672,7 @@ async function replyDecode(addressInput, options) {
23632
23672
  "Address must be in the form <token>@r.mail.example.com",
23633
23673
  "REPLY_DECODE_MALFORMED_ADDRESS",
23634
23674
  "Pass a full signed reply address:\n wraps email reply decode abcDEF123@r.mail.yourapp.com",
23635
- "https://wraps.dev/docs/guides/email/reply-threading"
23675
+ "https://wraps.dev/docs/guides/reply-threading"
23636
23676
  );
23637
23677
  }
23638
23678
  const local = addressInput.slice(0, at);
@@ -38968,6 +39008,7 @@ var BOOLEAN_FLAGS = [
38968
39008
  "draft",
38969
39009
  "root",
38970
39010
  "cleanup",
39011
+ "reveal-secret",
38971
39012
  "help",
38972
39013
  "version"
38973
39014
  ];
@@ -39591,7 +39632,8 @@ Usage: ${pc59.cyan("wraps email verify --domain yourapp.com")}
39591
39632
  case "status":
39592
39633
  await inboundStatus({
39593
39634
  region: flags.region,
39594
- json: flags.json
39635
+ json: flags.json,
39636
+ revealSecret: flags.revealSecret
39595
39637
  });
39596
39638
  break;
39597
39639
  case "verify":