void 0.20.0 → 0.20.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.
Files changed (52) hide show
  1. package/dist/{auth-cmd-CYVhSNFy.mjs → auth-cmd-CAH62yDU.mjs} +2 -2
  2. package/dist/{build-cmd-CkVD1uOh.mjs → build-cmd-CJvZvPQO.mjs} +1 -1
  3. package/dist/{cache-QcUfR-ff.mjs → cache-BlNeQjuP.mjs} +1 -1
  4. package/dist/{cancel-deploy-DsvWKFTe.mjs → cancel-deploy-CmlAZ9P6.mjs} +1 -1
  5. package/dist/cli/cli.mjs +164 -33
  6. package/dist/{client-CyCHWSO_.mjs → client-Clirrol3.mjs} +59 -0
  7. package/dist/{cloudflare-auth-DRkGe7-s.mjs → cloudflare-auth-B1QtTO1b.mjs} +51 -4
  8. package/dist/{cloudflare-cmd-D3ME2GAe.mjs → cloudflare-cmd-B6_OZx2V.mjs} +1 -1
  9. package/dist/{cloudflare-connect-BivMefMA.mjs → cloudflare-connect-j5D4hhrG.mjs} +1 -1
  10. package/dist/{connect-D9Yr-T5f.mjs → connect-C04Wdy_h.mjs} +4 -4
  11. package/dist/{create-project-DMV-csEm.mjs → create-project-ChGZ1DFd.mjs} +1 -1
  12. package/dist/{db-BxoUWL0F.mjs → db-D2d_mUsB.mjs} +31 -21
  13. package/dist/{delete-iJOqxBz1.mjs → delete-D8GigDk8.mjs} +1 -1
  14. package/dist/{deploy-CcDoeBIf.mjs → deploy-iXZ3F0N6.mjs} +20 -22
  15. package/dist/{domain-gu_iaHmn.mjs → domain-B1VmoSr0.mjs} +1 -1
  16. package/dist/email-uKyQYUVY.mjs +1016 -0
  17. package/dist/{env-DmU2To0C.mjs → env-BcQzYgoG.mjs} +1 -1
  18. package/dist/{gen-BKw6qHIg.mjs → gen-DI2YwdBM.mjs} +1 -1
  19. package/dist/generate-RTK8_kK1.mjs +47 -0
  20. package/dist/{github-cmd-DJS5Ab-H.mjs → github-cmd-xItS5Zwf.mjs} +1 -1
  21. package/dist/{inbound-CNKxb3FY.mjs → inbound-2d0zi2yS.mjs} +13 -1
  22. package/dist/{inbound-BJ70in1n.d.mts → inbound-afAcWeQ9.d.mts} +9 -0
  23. package/dist/index.mjs +20 -18
  24. package/dist/{init-Dx5cgKqK.mjs → init-BD-9THgn.mjs} +5 -5
  25. package/dist/{link-D_rm5sRH.mjs → link-RMdgjF1v.mjs} +2 -2
  26. package/dist/{list-M8XShti7.mjs → list-3F52R_yO.mjs} +1 -1
  27. package/dist/{local-d1-BE8KBbMy.mjs → local-d1-D2I6Ox5F.mjs} +1 -1
  28. package/dist/{login-C8-UuLnp.mjs → login-pV69H-ZO.mjs} +1 -1
  29. package/dist/{logs-DwFU7dMW.mjs → logs-DFHHD6wE.mjs} +1 -1
  30. package/dist/{node-BkaXcpAc.mjs → node-Dk3H2jmU.mjs} +1 -1
  31. package/dist/{platform-cmd-BEOVv1PN.mjs → platform-cmd-DxJ2FRwR.mjs} +1 -1
  32. package/dist/{platform-domain-BszUfiS8.mjs → platform-domain-ChvbJkdy.mjs} +2 -2
  33. package/dist/{platform-lifecycle-CjSr6xf0.mjs → platform-lifecycle-DN4MzJF_.mjs} +6 -6
  34. package/dist/{platform-management-W30iCaTL.mjs → platform-management-Db2PXw0B.mjs} +1 -1
  35. package/dist/{platform-recovery-pHHv4ZSg.mjs → platform-recovery-C_YO-tIs.mjs} +2 -2
  36. package/dist/{project-cmd-DCpk1cDt.mjs → project-cmd-Mo0V9yKS.mjs} +10 -10
  37. package/dist/{requests-Dn8Vheh1.mjs → requests-BcKOVpRg.mjs} +1 -1
  38. package/dist/{rollback-CtlPXEBi.mjs → rollback-Bx85-0xh.mjs} +1 -1
  39. package/dist/{runner-mysql-CgRFl3s6.mjs → runner-mysql-7BPUNGmL.mjs} +1 -1
  40. package/dist/{runner-pg-DCkWPsWS.mjs → runner-pg-BkEza-dX.mjs} +1 -1
  41. package/dist/runtime/email/testing.d.mts +1 -1
  42. package/dist/runtime/email/testing.mjs +1 -1
  43. package/dist/runtime/email.d.mts +1 -1
  44. package/dist/runtime/email.mjs +1 -1
  45. package/dist/{secret-BqTxGqki.mjs → secret-ByhJ9AMl.mjs} +1 -1
  46. package/dist/sqlite-validation-BzKMWnO4.mjs +25 -0
  47. package/dist/{validate-Bihr8WBi.mjs → validate-tBBN_dXH.mjs} +1 -0
  48. package/package.json +7 -7
  49. package/skills/void/docs/guide/email.md +34 -3
  50. package/skills/void/docs/guide/platform-development.md +29 -0
  51. package/skills/void/docs/reference/cli.md +51 -0
  52. package/dist/email-r6DHJyAB.mjs +0 -262
@@ -1,7 +1,7 @@
1
1
  import { D as log } from "./output-tFQLLj26.mjs";
2
2
  import { c as getToken, p as removeToken } from "./auth-W9WII-mN.mjs";
3
- import { n as PlatformClient } from "./client-CyCHWSO_.mjs";
4
- import { n as runLoginCommand } from "./login-C8-UuLnp.mjs";
3
+ import { n as PlatformClient } from "./client-Clirrol3.mjs";
4
+ import { n as runLoginCommand } from "./login-pV69H-ZO.mjs";
5
5
  import { execSync } from "node:child_process";
6
6
  //#region src/cli/auth-cmd.ts
7
7
  async function runAuthCommand(root, args) {
@@ -1,6 +1,6 @@
1
1
  import { D as log, E as intro, a as dim, c as import_picocolors, k as outro, r as cliTitle } from "./output-tFQLLj26.mjs";
2
2
  import { c as getToken, x as readProjectConfig } from "./auth-W9WII-mN.mjs";
3
- import { n as PlatformClient, t as PlatformApiError } from "./client-CyCHWSO_.mjs";
3
+ import { n as PlatformClient, t as PlatformApiError } from "./client-Clirrol3.mjs";
4
4
  import { r as resolveProjectBySlug, t as getRequestedProjectSlug } from "./resolve-project--Vxawf7z.mjs";
5
5
  import { appendFileSync, writeFileSync } from "node:fs";
6
6
  //#region src/cli/build-cmd.ts
@@ -1,6 +1,6 @@
1
1
  import { D as log, E as intro, a as dim, i as createSpinner, k as outro, r as cliTitle } from "./output-tFQLLj26.mjs";
2
2
  import { c as getToken, x as readProjectConfig } from "./auth-W9WII-mN.mjs";
3
- import { n as PlatformClient } from "./client-CyCHWSO_.mjs";
3
+ import { n as PlatformClient } from "./client-Clirrol3.mjs";
4
4
  import { r as resolveProjectBySlug, t as getRequestedProjectSlug } from "./resolve-project--Vxawf7z.mjs";
5
5
  //#region src/cli/cache.ts
6
6
  async function runPurgeCacheCommand(root, projectSlug) {
@@ -1,6 +1,6 @@
1
1
  import { D as log, E as intro, F as isCancel, k as outro, r as cliTitle, w as confirm } from "./output-tFQLLj26.mjs";
2
2
  import { c as getToken, x as readProjectConfig } from "./auth-W9WII-mN.mjs";
3
- import { n as PlatformClient } from "./client-CyCHWSO_.mjs";
3
+ import { n as PlatformClient } from "./client-Clirrol3.mjs";
4
4
  //#region src/cli/cancel-deploy.ts
5
5
  const ACTIVE_STATUSES = /* @__PURE__ */ new Set([
6
6
  "pending",
package/dist/cli/cli.mjs CHANGED
@@ -490,6 +490,11 @@ const emailSubcommands = [
490
490
  arg: "<address>",
491
491
  description: "Remove a verified recipient"
492
492
  },
493
+ {
494
+ name: "domain",
495
+ arg: "<add|status|list|sync|remove>",
496
+ description: "Send and receive at your own domain on a Cloudflare zone"
497
+ },
493
498
  {
494
499
  name: "status",
495
500
  description: "Show the email setup state and address map",
@@ -507,9 +512,17 @@ const EMAIL_SUBCOMMANDS = [
507
512
  "destinations",
508
513
  "allow",
509
514
  "disallow",
515
+ "domain",
510
516
  "status",
511
517
  "setup"
512
518
  ];
519
+ const EMAIL_DOMAIN_VERBS = [
520
+ "add",
521
+ "status",
522
+ "list",
523
+ "sync",
524
+ "remove"
525
+ ];
513
526
  /**
514
527
  * Read a value-taking flag in its `--flag value` or `--flag=value` form. Returns the
515
528
  * raw value, or `undefined` when the flag is the last token or is followed by another
@@ -534,11 +547,13 @@ function readFlagValue(rest, i, flag) {
534
547
  }
535
548
  function parseEmailArgs(args) {
536
549
  const subcommand = args[0];
537
- if (!subcommand || !EMAIL_SUBCOMMANDS.includes(subcommand)) throw new Error("email: Usage: void email <usage|logs|destinations|allow|disallow|status|setup> [args] [--project <name>] [--limit <n>] [--platform cloudflare].");
550
+ if (!subcommand || !EMAIL_SUBCOMMANDS.includes(subcommand)) throw new Error("email: Usage: void email <usage|logs|destinations|allow|disallow|domain|status|setup> [args] [--project <name>] [--limit <n>] [--platform cloudflare].");
538
551
  let limit;
539
552
  const projectValues = [];
540
553
  const platformValues = [];
541
554
  const backendValues = [];
555
+ const subdomainValues = [];
556
+ let forceCount = 0;
542
557
  const positional = [];
543
558
  const rest = args.slice(1);
544
559
  for (let i = 0; i < rest.length; i++) if (rest[i] === "--project" || rest[i]?.startsWith("--project=")) {
@@ -563,7 +578,17 @@ function parseEmailArgs(args) {
563
578
  if (value === void 0) throw new Error("email: --backend requires a value ('cloudflare').");
564
579
  backendValues.push(value);
565
580
  i = next;
581
+ } else if (rest[i] === "--subdomain" || rest[i]?.startsWith("--subdomain=")) {
582
+ const { value, next } = readFlagValue(rest, i, "--subdomain");
583
+ if (value === void 0 || value.trim() === "") throw new Error("email: --subdomain requires a value (a subdomain label or host).");
584
+ subdomainValues.push(value);
585
+ i = next;
586
+ } else if (rest[i] === "--force" || rest[i]?.startsWith("--force=")) {
587
+ if (rest[i] !== "--force") throw new Error("email: --force takes no value.");
588
+ forceCount++;
566
589
  } else positional.push(rest[i]);
590
+ if (forceCount > 1) throw new Error("email: --force can only be specified once.");
591
+ const force = forceCount > 0 ? true : void 0;
567
592
  if (projectValues.length > 1) throw new Error("email: --project can only be specified once.");
568
593
  const projectSlug = projectValues[0];
569
594
  if (backendValues.length > 1) throw new Error("email: --backend can only be specified once.");
@@ -580,6 +605,20 @@ function parseEmailArgs(args) {
580
605
  if (backendValue !== "cloudflare") throw new Error("email: --backend must be 'cloudflare'.");
581
606
  platform = "cloudflare";
582
607
  }
608
+ if (subdomainValues.length > 1) throw new Error("email: --subdomain can only be specified once.");
609
+ const subdomain = subdomainValues[0];
610
+ if (subcommand === "domain") {
611
+ if (platform === "cloudflare") throw new Error("email: --platform cloudflare applies to `void email status` and `void email setup` only (`domain` is a Void platform command).");
612
+ return parseEmailDomainArgs(positional, {
613
+ projectSlug,
614
+ limit,
615
+ platform,
616
+ subdomain,
617
+ force
618
+ });
619
+ }
620
+ if (subdomain !== void 0) throw new Error("email: --subdomain applies to `void email domain add` only.");
621
+ if (force !== void 0) throw new Error("email: --force applies to `void email domain remove` only.");
583
622
  if (positional.length > 1) throw new Error(`email: \`void email ${subcommand}\` takes exactly one positional argument (got ${positional.length}: ${positional.map((p) => JSON.stringify(p)).join(", ")}).`);
584
623
  const address = positional[0];
585
624
  if ((subcommand === "allow" || subcommand === "disallow") && !address) throw new Error(`email: Usage: void email ${subcommand} <address> [--project <name>].`);
@@ -596,6 +635,34 @@ function parseEmailArgs(args) {
596
635
  platform
597
636
  };
598
637
  }
638
+ /**
639
+ * The nested `void email domain <verb> [<domain>]` group. positional[0] is the
640
+ * verb, positional[1] the domain — `list` takes no domain, every other verb
641
+ * requires exactly one. Shape validation of the domain itself is the command's
642
+ * job (and ultimately the api's — its regex is authoritative); the parser only
643
+ * counts positionals, exactly as it does for `allow <address>`.
644
+ */
645
+ function parseEmailDomainArgs(positional, flags) {
646
+ const verb = positional[0];
647
+ if (!verb || !EMAIL_DOMAIN_VERBS.includes(verb)) throw new Error("email: Usage: void email domain <add|status|list|sync|remove> [<domain>] [--project <name>].");
648
+ if (flags.subdomain !== void 0 && verb !== "add") throw new Error("email: --subdomain applies to `void email domain add` only.");
649
+ if (flags.force !== void 0 && verb !== "remove") throw new Error("email: --force applies to `void email domain remove` only.");
650
+ const domain = positional[1];
651
+ if (verb === "list") {
652
+ if (domain !== void 0) throw new Error("email: `void email domain list` takes no domain argument.");
653
+ } else if (domain === void 0) throw new Error(`email: Usage: void email domain ${verb} <domain> [--project <name>].`);
654
+ if (positional.length > 2) throw new Error(`email: \`void email domain ${verb}\` takes exactly one domain argument (got ${positional.length - 1}: ${positional.slice(1).map((p) => JSON.stringify(p)).join(", ")}).`);
655
+ return {
656
+ subcommand: "domain",
657
+ domainVerb: verb,
658
+ domain,
659
+ subdomain: flags.subdomain,
660
+ force: flags.force,
661
+ projectSlug: flags.projectSlug,
662
+ limit: flags.limit,
663
+ platform: flags.platform
664
+ };
665
+ }
599
666
  //#endregion
600
667
  //#region src/cli/env-args.ts
601
668
  const envSubcommands = [{
@@ -2175,7 +2242,7 @@ const HELP_TREE = {
2175
2242
  }
2176
2243
  },
2177
2244
  email: {
2178
- summary: "Inspect email activity and manage verified recipients.",
2245
+ summary: "Inspect email activity, manage verified recipients, and send and receive at your own domain.",
2179
2246
  usage: ["void email <command>"],
2180
2247
  commands: [
2181
2248
  {
@@ -2198,6 +2265,10 @@ const HELP_TREE = {
2198
2265
  command: "disallow <address>",
2199
2266
  description: "Remove a recipient from the allowlist"
2200
2267
  },
2268
+ {
2269
+ command: "domain <add|status|list|sync|remove>",
2270
+ description: "Send and receive at your own domain on a Cloudflare zone"
2271
+ },
2201
2272
  {
2202
2273
  command: "status --platform cloudflare",
2203
2274
  description: "Show the email setup state and address map on your own account"
@@ -2223,6 +2294,66 @@ const HELP_TREE = {
2223
2294
  destinations: withProjectOption("List verified recipient addresses.", "void email destinations [options]"),
2224
2295
  allow: withProjectOption("Add a recipient and trigger a Cloudflare verification email.", "void email allow <address> [options]"),
2225
2296
  disallow: withProjectOption("Remove a recipient from the verified allowlist.", "void email disallow <address> [options]"),
2297
+ domain: {
2298
+ summary: "Send and receive at your own domain on a Cloudflare zone.",
2299
+ usage: ["void email domain <verb> [<domain>] [options]"],
2300
+ commands: [
2301
+ {
2302
+ command: "add <domain>",
2303
+ description: "Register the domain (OAuth grant, or a scoped API token)"
2304
+ },
2305
+ {
2306
+ command: "status <domain>",
2307
+ description: "Show state; re-probes the credential and relay, polls a pending row"
2308
+ },
2309
+ {
2310
+ command: "list",
2311
+ description: "List registered email domains"
2312
+ },
2313
+ {
2314
+ command: "sync <domain>",
2315
+ description: "Redeploy the relay at the current version and rotate its secret"
2316
+ },
2317
+ {
2318
+ command: "remove <domain>",
2319
+ description: "Delete the registration, stored credential, and relay secret"
2320
+ }
2321
+ ],
2322
+ options: [{
2323
+ command: "--subdomain <label|host>",
2324
+ description: "On add: register this subdomain instead of the proposed mail.<domain>"
2325
+ }, {
2326
+ command: "--project <name>",
2327
+ description: "Project name override"
2328
+ }],
2329
+ children: {
2330
+ add: {
2331
+ summary: "Register a domain on a Cloudflare zone you own for sending and receiving. Proposes mail.<domain> when the apex already carries MX.",
2332
+ usage: ["void email domain add <domain> [options]"],
2333
+ options: [{
2334
+ command: "--subdomain <label|host>",
2335
+ description: "Register this subdomain instead of the proposed mail.<domain>"
2336
+ }, {
2337
+ command: "--project <name>",
2338
+ description: "Project name override"
2339
+ }]
2340
+ },
2341
+ status: withProjectOption("Show a registered domain, re-probing its credential and relay.", "void email domain status <domain> [options]"),
2342
+ list: withProjectOption("List registered email domains.", "void email domain list [options]"),
2343
+ sync: withProjectOption("Redeploy the relay at the current version and rotate its secret.", "void email domain sync <domain> [options]"),
2344
+ remove: {
2345
+ summary: "Delete the registration, stored credential, and relay secret.",
2346
+ usage: ["void email domain remove <domain> [options]"],
2347
+ options: [{
2348
+ command: "--force",
2349
+ description: "Drop the row even when Cloudflare-side cleanup fails"
2350
+ }, {
2351
+ command: "--project <name>",
2352
+ description: "Project name override"
2353
+ }]
2354
+ }
2355
+ }
2356
+ },
2226
2357
  status: {
2227
2358
  summary: "Show the email setup state and address map. Exit 1 when not ready.",
2228
2359
  usage: ["void email status --platform cloudflare"],
@@ -3488,7 +3619,7 @@ if (helpPath) {
3488
3619
  log.error(formatCloudflareUserMessage(err instanceof Error ? err.message : String(err)));
3489
3620
  process.exit(1);
3490
3621
  }
3491
- import("../deploy-CcDoeBIf.mjs").then((n) => n.n).then(({ runDeploy }) => {
3622
+ import("../deploy-iXZ3F0N6.mjs").then((n) => n.n).then(({ runDeploy }) => {
3492
3623
  runDeploy(root, {
3493
3624
  projectSlug: deployArgs.projectSlug,
3494
3625
  dir: deployArgs.dir,
@@ -3506,24 +3637,24 @@ if (helpPath) {
3506
3637
  });
3507
3638
  } else if (command === "connect") (async () => {
3508
3639
  const parsed = parseConnectArgs(args.slice(1));
3509
- const { runConnectCommand } = await import("../connect-D9Yr-T5f.mjs");
3640
+ const { runConnectCommand } = await import("../connect-C04Wdy_h.mjs");
3510
3641
  await runConnectCommand(process.cwd(), parsed);
3511
3642
  })().catch((err) => {
3512
3643
  log.error(formatCloudflareUserMessage(err instanceof Error ? err.message : String(err)));
3513
3644
  process.exit(1);
3514
3645
  });
3515
- else if (command === "auth") runSubcommandGroup("auth", authSubcommands, parseAuthArgs, (root, parsed) => import("../auth-cmd-CYVhSNFy.mjs").then(({ runAuthCommand }) => runAuthCommand(root, parsed)));
3516
- else if (command === "platform") runSubcommandGroup("platform", platformSubcommands, parsePlatformArgs, (root, parsed) => import("../platform-cmd-BEOVv1PN.mjs").then(({ runPlatformCommand }) => runPlatformCommand(root, parsed)));
3517
- else if (command === "cloudflare") runSubcommandGroup("cloudflare", cloudflareSubcommands, parseCloudflareArgs, (root, parsed) => import("../cloudflare-cmd-D3ME2GAe.mjs").then(({ runCloudflareCommand }) => runCloudflareCommand(root, parsed)));
3518
- else if (command === "project") runSubcommandGroup("project", projectSubcommands, parseProjectArgs, (root, parsed) => import("../project-cmd-DCpk1cDt.mjs").then(({ runProjectCommand }) => runProjectCommand(root, parsed)));
3519
- else if (command === "secret") runSubcommandGroup("secret", secretSubcommands, parseSecretArgs, (root, parsed) => import("../secret-BqTxGqki.mjs").then(({ runSecretCommand }) => runSecretCommand(root, parsed)));
3520
- else if (command === "domain") runSubcommandGroup("domain", domainSubcommands, parseDomainArgs, (root, parsed) => import("../domain-gu_iaHmn.mjs").then(({ runDomainCommand }) => runDomainCommand(root, parsed)));
3521
- else if (command === "email") runSubcommandGroup("email", emailSubcommands, parseEmailArgs, (root, parsed) => import("../email-r6DHJyAB.mjs").then(({ runEmailCommand }) => runEmailCommand(root, parsed)));
3522
- else if (command === "db") runSubcommandGroup("db", dbSubcommands, parseDbArgs, (root, parsed) => import("../db-BxoUWL0F.mjs").then(({ runDbCommand }) => runDbCommand(root, parsed)));
3523
- else if (command === "env") runSubcommandGroup("env", envSubcommands, parseEnvArgs, (root, parsed) => import("../env-DmU2To0C.mjs").then(({ runEnvCommand }) => runEnvCommand(root, parsed)));
3524
- else if (command === "gen") runSubcommandGroup("gen", genSubcommands, parseGenArgs, (root, parsed) => import("../gen-BKw6qHIg.mjs").then(({ runGenCommand }) => runGenCommand(root, parsed)));
3525
- else if (command === "github") runSubcommandGroup("github", githubSubcommands, parseGithubArgs, (root, parsed) => import("../github-cmd-DJS5Ab-H.mjs").then(({ runGithubCommand }) => runGithubCommand(root, parsed)));
3526
- else if (command === "build") runSubcommandGroup("build", buildSubcommands, parseBuildArgs, (root, parsed) => import("../build-cmd-CkVD1uOh.mjs").then(({ runBuildCommand }) => runBuildCommand(root, parsed)));
3646
+ else if (command === "auth") runSubcommandGroup("auth", authSubcommands, parseAuthArgs, (root, parsed) => import("../auth-cmd-CAH62yDU.mjs").then(({ runAuthCommand }) => runAuthCommand(root, parsed)));
3647
+ else if (command === "platform") runSubcommandGroup("platform", platformSubcommands, parsePlatformArgs, (root, parsed) => import("../platform-cmd-DxJ2FRwR.mjs").then(({ runPlatformCommand }) => runPlatformCommand(root, parsed)));
3648
+ else if (command === "cloudflare") runSubcommandGroup("cloudflare", cloudflareSubcommands, parseCloudflareArgs, (root, parsed) => import("../cloudflare-cmd-B6_OZx2V.mjs").then(({ runCloudflareCommand }) => runCloudflareCommand(root, parsed)));
3649
+ else if (command === "project") runSubcommandGroup("project", projectSubcommands, parseProjectArgs, (root, parsed) => import("../project-cmd-Mo0V9yKS.mjs").then(({ runProjectCommand }) => runProjectCommand(root, parsed)));
3650
+ else if (command === "secret") runSubcommandGroup("secret", secretSubcommands, parseSecretArgs, (root, parsed) => import("../secret-ByhJ9AMl.mjs").then(({ runSecretCommand }) => runSecretCommand(root, parsed)));
3651
+ else if (command === "domain") runSubcommandGroup("domain", domainSubcommands, parseDomainArgs, (root, parsed) => import("../domain-B1VmoSr0.mjs").then(({ runDomainCommand }) => runDomainCommand(root, parsed)));
3652
+ else if (command === "email") runSubcommandGroup("email", emailSubcommands, parseEmailArgs, (root, parsed) => import("../email-uKyQYUVY.mjs").then(({ runEmailCommand }) => runEmailCommand(root, parsed)));
3653
+ else if (command === "db") runSubcommandGroup("db", dbSubcommands, parseDbArgs, (root, parsed) => import("../db-D2d_mUsB.mjs").then(({ runDbCommand }) => runDbCommand(root, parsed)));
3654
+ else if (command === "env") runSubcommandGroup("env", envSubcommands, parseEnvArgs, (root, parsed) => import("../env-BcQzYgoG.mjs").then(({ runEnvCommand }) => runEnvCommand(root, parsed)));
3655
+ else if (command === "gen") runSubcommandGroup("gen", genSubcommands, parseGenArgs, (root, parsed) => import("../gen-DI2YwdBM.mjs").then(({ runGenCommand }) => runGenCommand(root, parsed)));
3656
+ else if (command === "github") runSubcommandGroup("github", githubSubcommands, parseGithubArgs, (root, parsed) => import("../github-cmd-xItS5Zwf.mjs").then(({ runGithubCommand }) => runGithubCommand(root, parsed)));
3657
+ else if (command === "build") runSubcommandGroup("build", buildSubcommands, parseBuildArgs, (root, parsed) => import("../build-cmd-CJvZvPQO.mjs").then(({ runBuildCommand }) => runBuildCommand(root, parsed)));
3527
3658
  else if (command === "prepare") {
3528
3659
  const root = process.cwd();
3529
3660
  let prepareArgs;
@@ -3541,7 +3672,7 @@ else if (command === "prepare") {
3541
3672
  });
3542
3673
  } else if (command === "init") {
3543
3674
  const root = process.cwd();
3544
- import("../init-Dx5cgKqK.mjs").then(({ runInitCommand, parseInitArgs }) => {
3675
+ import("../init-BD-9THgn.mjs").then(({ runInitCommand, parseInitArgs }) => {
3545
3676
  let initArgs;
3546
3677
  try {
3547
3678
  initArgs = parseInitArgs(args.slice(1));
@@ -3607,7 +3738,7 @@ else if (command === "prepare") {
3607
3738
  },
3608
3739
  {
3609
3740
  name: "email",
3610
- hint: "usage | logs | destinations | allow | disallow | status | setup",
3741
+ hint: "usage | logs | destinations | allow | disallow | domain | status | setup",
3611
3742
  description: "Inspect email activity and manage verified recipients"
3612
3743
  },
3613
3744
  {
@@ -3653,32 +3784,32 @@ else if (command === "prepare") {
3653
3784
  const root = process.cwd();
3654
3785
  switch (cmd) {
3655
3786
  case "connect": {
3656
- const { runConnectCommand } = await import("../connect-D9Yr-T5f.mjs");
3787
+ const { runConnectCommand } = await import("../connect-C04Wdy_h.mjs");
3657
3788
  await runConnectCommand(root, parseConnectArgs([]));
3658
3789
  return;
3659
3790
  }
3660
3791
  case "init": {
3661
- const { runInitCommand, parseInitArgs } = await import("../init-Dx5cgKqK.mjs");
3792
+ const { runInitCommand, parseInitArgs } = await import("../init-BD-9THgn.mjs");
3662
3793
  await runInitCommand(root, parseInitArgs([]));
3663
3794
  return;
3664
3795
  }
3665
3796
  case "deploy": {
3666
- const { runDeploy } = await import("../deploy-CcDoeBIf.mjs").then((n) => n.n);
3797
+ const { runDeploy } = await import("../deploy-iXZ3F0N6.mjs").then((n) => n.n);
3667
3798
  await runDeploy(root);
3668
3799
  return;
3669
3800
  }
3670
- case "auth": return runSubcommandGroup("auth", authSubcommands, parseAuthArgs, (r, p) => import("../auth-cmd-CYVhSNFy.mjs").then(({ runAuthCommand }) => runAuthCommand(r, p)));
3671
- case "platform": return runSubcommandGroup("platform", platformSubcommands, parsePlatformArgs, (r, p) => import("../platform-cmd-BEOVv1PN.mjs").then(({ runPlatformCommand }) => runPlatformCommand(r, p)));
3672
- case "cloudflare": return runSubcommandGroup("cloudflare", cloudflareSubcommands, parseCloudflareArgs, (r, p) => import("../cloudflare-cmd-D3ME2GAe.mjs").then(({ runCloudflareCommand }) => runCloudflareCommand(r, p)));
3673
- case "project": return runSubcommandGroup("project", projectSubcommands, parseProjectArgs, (r, p) => import("../project-cmd-DCpk1cDt.mjs").then(({ runProjectCommand }) => runProjectCommand(r, p)));
3674
- case "secret": return runSubcommandGroup("secret", secretSubcommands, parseSecretArgs, (r, p) => import("../secret-BqTxGqki.mjs").then(({ runSecretCommand }) => runSecretCommand(r, p)));
3675
- case "domain": return runSubcommandGroup("domain", domainSubcommands, parseDomainArgs, (r, p) => import("../domain-gu_iaHmn.mjs").then(({ runDomainCommand }) => runDomainCommand(r, p)));
3676
- case "github": return runSubcommandGroup("github", githubSubcommands, parseGithubArgs, (r, p) => import("../github-cmd-DJS5Ab-H.mjs").then(({ runGithubCommand }) => runGithubCommand(r, p)));
3677
- case "build": return runSubcommandGroup("build", buildSubcommands, parseBuildArgs, (r, p) => import("../build-cmd-CkVD1uOh.mjs").then(({ runBuildCommand }) => runBuildCommand(r, p)));
3678
- case "email": return runSubcommandGroup("email", emailSubcommands, parseEmailArgs, (r, p) => import("../email-r6DHJyAB.mjs").then(({ runEmailCommand }) => runEmailCommand(r, p)));
3679
- case "db": return runSubcommandGroup("db", dbSubcommands, parseDbArgs, (r, p) => import("../db-BxoUWL0F.mjs").then(({ runDbCommand }) => runDbCommand(r, p)));
3680
- case "env": return runSubcommandGroup("env", envSubcommands, parseEnvArgs, (r, p) => import("../env-DmU2To0C.mjs").then(({ runEnvCommand }) => runEnvCommand(r, p)));
3681
- case "gen": return runSubcommandGroup("gen", genSubcommands, parseGenArgs, (r, p) => import("../gen-BKw6qHIg.mjs").then(({ runGenCommand }) => runGenCommand(r, p)));
3801
+ case "auth": return runSubcommandGroup("auth", authSubcommands, parseAuthArgs, (r, p) => import("../auth-cmd-CAH62yDU.mjs").then(({ runAuthCommand }) => runAuthCommand(r, p)));
3802
+ case "platform": return runSubcommandGroup("platform", platformSubcommands, parsePlatformArgs, (r, p) => import("../platform-cmd-DxJ2FRwR.mjs").then(({ runPlatformCommand }) => runPlatformCommand(r, p)));
3803
+ case "cloudflare": return runSubcommandGroup("cloudflare", cloudflareSubcommands, parseCloudflareArgs, (r, p) => import("../cloudflare-cmd-B6_OZx2V.mjs").then(({ runCloudflareCommand }) => runCloudflareCommand(r, p)));
3804
+ case "project": return runSubcommandGroup("project", projectSubcommands, parseProjectArgs, (r, p) => import("../project-cmd-Mo0V9yKS.mjs").then(({ runProjectCommand }) => runProjectCommand(r, p)));
3805
+ case "secret": return runSubcommandGroup("secret", secretSubcommands, parseSecretArgs, (r, p) => import("../secret-ByhJ9AMl.mjs").then(({ runSecretCommand }) => runSecretCommand(r, p)));
3806
+ case "domain": return runSubcommandGroup("domain", domainSubcommands, parseDomainArgs, (r, p) => import("../domain-B1VmoSr0.mjs").then(({ runDomainCommand }) => runDomainCommand(r, p)));
3807
+ case "github": return runSubcommandGroup("github", githubSubcommands, parseGithubArgs, (r, p) => import("../github-cmd-xItS5Zwf.mjs").then(({ runGithubCommand }) => runGithubCommand(r, p)));
3808
+ case "build": return runSubcommandGroup("build", buildSubcommands, parseBuildArgs, (r, p) => import("../build-cmd-CJvZvPQO.mjs").then(({ runBuildCommand }) => runBuildCommand(r, p)));
3809
+ case "email": return runSubcommandGroup("email", emailSubcommands, parseEmailArgs, (r, p) => import("../email-uKyQYUVY.mjs").then(({ runEmailCommand }) => runEmailCommand(r, p)));
3810
+ case "db": return runSubcommandGroup("db", dbSubcommands, parseDbArgs, (r, p) => import("../db-D2d_mUsB.mjs").then(({ runDbCommand }) => runDbCommand(r, p)));
3811
+ case "env": return runSubcommandGroup("env", envSubcommands, parseEnvArgs, (r, p) => import("../env-BcQzYgoG.mjs").then(({ runEnvCommand }) => runEnvCommand(r, p)));
3812
+ case "gen": return runSubcommandGroup("gen", genSubcommands, parseGenArgs, (r, p) => import("../gen-DI2YwdBM.mjs").then(({ runGenCommand }) => runGenCommand(r, p)));
3682
3813
  case "prepare": {
3683
3814
  const { runPrepareCommand } = await import("../prepare-BfJvFUtJ.mjs");
3684
3815
  await runPrepareCommand(root, parsePrepareArgs([]));
@@ -641,6 +641,65 @@ var PlatformClient = class {
641
641
  if (!res.ok) await throwPlatformApiError("Failed to remove email destination", res);
642
642
  return res.json();
643
643
  }
644
+ async listEmailDomains(projectId) {
645
+ const res = await fetch(`${this.baseUrl}/projects/${projectId}/email/domains`, { headers: { ...this.authHeaders } });
646
+ if (!res.ok) await throwPlatformApiError("Failed to list email domains", res);
647
+ return res.json();
648
+ }
649
+ /**
650
+ * `domain add` sends the credential exactly once — the OAuth grant's
651
+ * refresh token xor a pasted API token (the api enforces exactly one). It
652
+ * is the only call that ever carries it: the platform stores it encrypted
653
+ * per project, and every later step (`status`, `sync`, `remove`) addresses
654
+ * the row by domain. The caller must not log the input.
655
+ */
656
+ async addEmailDomain(projectId, input) {
657
+ const res = await fetch(`${this.baseUrl}/projects/${projectId}/email/domains`, {
658
+ method: "POST",
659
+ headers: {
660
+ "Content-Type": "application/json",
661
+ ...this.authHeaders
662
+ },
663
+ body: JSON.stringify({
664
+ domain: input.domain,
665
+ ...input.refreshToken !== void 0 ? { refreshToken: input.refreshToken } : {},
666
+ ...input.apiToken !== void 0 ? { apiToken: input.apiToken } : {},
667
+ ...input.attemptId !== void 0 ? { attemptId: input.attemptId } : {}
668
+ })
669
+ });
670
+ if (!res.ok) await throwPlatformApiError("Failed to add email domain", res);
671
+ return res.json();
672
+ }
673
+ async getEmailDomain(projectId, domain) {
674
+ const res = await fetch(`${this.baseUrl}/projects/${projectId}/email/domains/${encodeURIComponent(domain)}`, { headers: { ...this.authHeaders } });
675
+ if (!res.ok) await throwPlatformApiError("Failed to fetch email domain status", res);
676
+ return res.json();
677
+ }
678
+ /** Redeploys the relay at the current version and rotates its secret (0078, `sync`). */
679
+ async syncEmailDomain(projectId, domain) {
680
+ const res = await fetch(`${this.baseUrl}/projects/${projectId}/email/domains/${encodeURIComponent(domain)}/sync`, {
681
+ method: "POST",
682
+ headers: { ...this.authHeaders }
683
+ });
684
+ if (!res.ok) await throwPlatformApiError("Failed to sync email domain", res);
685
+ return res.json();
686
+ }
687
+ /**
688
+ * `force` appends `?force=1`: the api drops the row even when a
689
+ * Cloudflare-side cleanup step fails (and answers `forced: true` +
690
+ * `failed_steps`). Without it a CF-side failure keeps the row for retry
691
+ * (`removed: false`).
692
+ */
693
+ async removeEmailDomain(projectId, domain, force) {
694
+ const url = new URL(`${this.baseUrl}/projects/${projectId}/email/domains/${encodeURIComponent(domain)}`);
695
+ if (force) url.searchParams.set("force", "1");
696
+ const res = await fetch(url, {
697
+ method: "DELETE",
698
+ headers: { ...this.authHeaders }
699
+ });
700
+ if (!res.ok) await throwPlatformApiError("Failed to remove email domain", res);
701
+ return res.json();
702
+ }
644
703
  };
645
704
  //#endregion
646
705
  export { isExpiredTokenError as a, isCliOutdatedError as i, PlatformClient as n, parsePlatformErrorBody as o, client_exports as r, PlatformApiError as t };
@@ -1,6 +1,6 @@
1
1
  import { D as log } from "./output-tFQLLj26.mjs";
2
2
  import { o as resolveWranglerArgv } from "./preset-lAy0B0BQ.mjs";
3
- import { execFile, spawnSync } from "node:child_process";
3
+ import { execFile, spawn, spawnSync } from "node:child_process";
4
4
  //#region src/cli/cloudflare-auth.ts
5
5
  var CloudflareAuthenticationError = class extends Error {
6
6
  name = "CloudflareAuthenticationError";
@@ -102,7 +102,11 @@ function createBundledCloudflareAuthRunner(root) {
102
102
  env,
103
103
  maxBuffer: 10485760,
104
104
  shell: false,
105
- stdio: capture ? [
105
+ stdio: cloudflareKeyringNeedsTerminal(args) ? [
106
+ "inherit",
107
+ "inherit",
108
+ "ignore"
109
+ ] : capture ? [
106
110
  "ignore",
107
111
  "pipe",
108
112
  "pipe"
@@ -122,6 +126,37 @@ function createBundledCloudflareAuthRunner(root) {
122
126
  /** Run a captured auth command without blocking terminal input or exposing credentials. */
123
127
  function runCloudflareAuthCommand(root, args, signal) {
124
128
  const [command, ...prefix] = resolveWranglerArgv(root);
129
+ if (cloudflareKeyringNeedsTerminal(args)) return new Promise((resolve) => {
130
+ const child = spawn(command, [...prefix, ...args], {
131
+ cwd: root,
132
+ env: cloudflareAuthCommandEnvironment(args),
133
+ shell: false,
134
+ signal,
135
+ stdio: [
136
+ "inherit",
137
+ "inherit",
138
+ "ignore"
139
+ ],
140
+ timeout: 6e5,
141
+ windowsHide: true
142
+ });
143
+ child.once("error", (error) => {
144
+ resolve({
145
+ status: null,
146
+ stdout: "",
147
+ stderr: "",
148
+ error: error.message
149
+ });
150
+ });
151
+ child.once("close", (status, signal) => {
152
+ resolve({
153
+ status,
154
+ signal,
155
+ stdout: "",
156
+ stderr: ""
157
+ });
158
+ });
159
+ });
125
160
  return new Promise((resolve) => {
126
161
  execFile(command, [...prefix, ...args], {
127
162
  cwd: root,
@@ -145,9 +180,21 @@ function runCloudflareAuthCommand(root, args, signal) {
145
180
  }
146
181
  function cloudflareAuthCommandEnvironment(args, source = process.env) {
147
182
  const env = cloudflareAuthEnvironment(source);
148
- if (args[0] === "login" || args[0] === "logout") env.WRANGLER_LOG = "none";
183
+ if (args[0] === "login" || args[0] === "logout" || isCloudflareKeyringEnable(args)) env.WRANGLER_LOG = "none";
149
184
  return env;
150
185
  }
186
+ function isCloudflareKeyringEnable(args) {
187
+ return args.length === 3 && args[0] === "auth" && args[1] === "keyring" && args[2] === "enable";
188
+ }
189
+ /**
190
+ * Wrangler installs its Windows keyring backend only when stdin AND stdout are
191
+ * terminals. Capturing `auth keyring enable` makes first-time setup fail even
192
+ * inside PowerShell. This command only configures storage; it never reads or
193
+ * prints a credential. Keep every other auth command captured.
194
+ */
195
+ function cloudflareKeyringNeedsTerminal(args) {
196
+ return process.platform === "win32" && process.stdin.isTTY === true && process.stdout.isTTY === true && isCloudflareKeyringEnable(args);
197
+ }
151
198
  function cloudflareAuthEnvironment(source = process.env) {
152
199
  const env = { ...source };
153
200
  const scrubbedWranglerKeys = /* @__PURE__ */ new Set([
@@ -167,4 +214,4 @@ function announceCloudflareLogin() {
167
214
  log.info("Opening Cloudflare login in your browser. Press Ctrl+C to cancel.");
168
215
  }
169
216
  //#endregion
170
- export { enableCloudflareKeyring as a, runCloudflareAuthCommand as c, createBundledCloudflareAuthRunner as i, announceCloudflareLogin as n, ensureCloudflareAuthentication as o, cloudflareCredentialOverrides as r, parseCloudflareAuthSession as s, CloudflareAuthenticationError as t };
217
+ export { createBundledCloudflareAuthRunner as a, parseCloudflareAuthSession as c, cloudflareKeyringNeedsTerminal as i, runCloudflareAuthCommand as l, announceCloudflareLogin as n, enableCloudflareKeyring as o, cloudflareCredentialOverrides as r, ensureCloudflareAuthentication as s, CloudflareAuthenticationError as t };
@@ -1,7 +1,7 @@
1
1
  import { t as basename } from "./dist-BrsS7cai.mjs";
2
2
  import { D as log } from "./output-tFQLLj26.mjs";
3
3
  import { v as readRootWranglerConfig } from "./wrangler--imS8n0d.mjs";
4
- import { a as enableCloudflareKeyring, i as createBundledCloudflareAuthRunner, o as ensureCloudflareAuthentication, r as cloudflareCredentialOverrides, s as parseCloudflareAuthSession } from "./cloudflare-auth-DRkGe7-s.mjs";
4
+ import { a as createBundledCloudflareAuthRunner, c as parseCloudflareAuthSession, o as enableCloudflareKeyring, r as cloudflareCredentialOverrides, s as ensureCloudflareAuthentication } from "./cloudflare-auth-B1QtTO1b.mjs";
5
5
  //#region src/cli/cloudflare-cmd.ts
6
6
  async function runCloudflareCommand(root, args) {
7
7
  const runWrangler = createBundledCloudflareAuthRunner(root);
@@ -1,7 +1,7 @@
1
1
  import { o as join, t as basename } from "./dist-BrsS7cai.mjs";
2
2
  import { D as log, F as isCancel, j as select } from "./output-tFQLLj26.mjs";
3
3
  import { i as LATEST_KNOWN_COMPAT_DATE, k as writeProvisionedWranglerConfig, v as readRootWranglerConfig } from "./wrangler--imS8n0d.mjs";
4
- import { i as createBundledCloudflareAuthRunner, o as ensureCloudflareAuthentication } from "./cloudflare-auth-DRkGe7-s.mjs";
4
+ import { a as createBundledCloudflareAuthRunner, s as ensureCloudflareAuthentication } from "./cloudflare-auth-B1QtTO1b.mjs";
5
5
  import { existsSync } from "node:fs";
6
6
  //#region src/cli/cloudflare-connect.ts
7
7
  async function connectCloudflare(root, interactive = Boolean(process.stdin.isTTY)) {
@@ -1,9 +1,9 @@
1
1
  import { D as log, F as isCancel, G as normalizePlatformApiUrl, W as listPlatformConnections, j as select } from "./output-tFQLLj26.mjs";
2
2
  import { C as writeDeploymentPlatform, b as readDeploymentPlatform, f as readPlatformToken, w as writePlatformSelection } from "./auth-W9WII-mN.mjs";
3
- import { a as isExpiredTokenError, n as PlatformClient } from "./client-CyCHWSO_.mjs";
4
- import { t as promptForLoginToken } from "./login-C8-UuLnp.mjs";
5
- import { t as connectCloudflare } from "./cloudflare-connect-BivMefMA.mjs";
6
- import { discoverPlatform, promptPlatformUrl, saveDiscoveredPlatform } from "./platform-cmd-BEOVv1PN.mjs";
3
+ import { a as isExpiredTokenError, n as PlatformClient } from "./client-Clirrol3.mjs";
4
+ import { t as promptForLoginToken } from "./login-pV69H-ZO.mjs";
5
+ import { t as connectCloudflare } from "./cloudflare-connect-j5D4hhrG.mjs";
6
+ import { discoverPlatform, promptPlatformUrl, saveDiscoveredPlatform } from "./platform-cmd-DxJ2FRwR.mjs";
7
7
  //#region src/cli/connect.ts
8
8
  async function selectVoidPlatform(interactive) {
9
9
  if (!interactive) throw new Error("connect: Supply a Void platform URL in non-interactive mode.");
@@ -1,7 +1,7 @@
1
1
  import { n as __exportAll } from "./rolldown-runtime-rQ84J-ij.mjs";
2
2
  import { C as cancel, D as log, F as isCancel, N as text, c as import_picocolors, j as select, w as confirm } from "./output-tFQLLj26.mjs";
3
3
  import { T as writeProjectConfig, s as getSiteDomain, v as attachSelectedPlatform } from "./auth-W9WII-mN.mjs";
4
- import { t as PlatformApiError } from "./client-CyCHWSO_.mjs";
4
+ import { t as PlatformApiError } from "./client-Clirrol3.mjs";
5
5
  import { n as inferDefaultSlug } from "./resolve-project--Vxawf7z.mjs";
6
6
  //#region src/cli/project-slug.ts
7
7
  var project_slug_exports = /* @__PURE__ */ __exportAll({