hatchkit 0.1.41 → 0.1.43

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 (120) hide show
  1. package/dist/adopt.d.ts +77 -0
  2. package/dist/adopt.d.ts.map +1 -1
  3. package/dist/adopt.js +757 -170
  4. package/dist/adopt.js.map +1 -1
  5. package/dist/config.d.ts +32 -10
  6. package/dist/config.d.ts.map +1 -1
  7. package/dist/config.js +91 -38
  8. package/dist/config.js.map +1 -1
  9. package/dist/deploy/coolify-app.d.ts.map +1 -1
  10. package/dist/deploy/coolify-app.js +0 -7
  11. package/dist/deploy/coolify-app.js.map +1 -1
  12. package/dist/deploy/coolify.d.ts.map +1 -1
  13. package/dist/deploy/coolify.js +20 -1
  14. package/dist/deploy/coolify.js.map +1 -1
  15. package/dist/deploy/ghcr.d.ts +4 -2
  16. package/dist/deploy/ghcr.d.ts.map +1 -1
  17. package/dist/deploy/ghcr.js +1 -1
  18. package/dist/deploy/ghcr.js.map +1 -1
  19. package/dist/deploy/github.d.ts +4 -3
  20. package/dist/deploy/github.d.ts.map +1 -1
  21. package/dist/deploy/github.js +5 -2
  22. package/dist/deploy/github.js.map +1 -1
  23. package/dist/deploy/pages.d.ts.map +1 -1
  24. package/dist/deploy/pages.js +8 -14
  25. package/dist/deploy/pages.js.map +1 -1
  26. package/dist/deploy/regen-infra.d.ts.map +1 -1
  27. package/dist/deploy/regen-infra.js +1 -11
  28. package/dist/deploy/regen-infra.js.map +1 -1
  29. package/dist/deploy/rollback.d.ts.map +1 -1
  30. package/dist/deploy/rollback.js +30 -6
  31. package/dist/deploy/rollback.js.map +1 -1
  32. package/dist/deploy/terraform.d.ts.map +1 -1
  33. package/dist/deploy/terraform.js +20 -37
  34. package/dist/deploy/terraform.js.map +1 -1
  35. package/dist/dns.d.ts.map +1 -1
  36. package/dist/dns.js +4 -5
  37. package/dist/dns.js.map +1 -1
  38. package/dist/doctor.d.ts +15 -0
  39. package/dist/doctor.d.ts.map +1 -1
  40. package/dist/doctor.js +110 -36
  41. package/dist/doctor.js.map +1 -1
  42. package/dist/email/index.d.ts +31 -0
  43. package/dist/email/index.d.ts.map +1 -0
  44. package/dist/email/index.js +251 -0
  45. package/dist/email/index.js.map +1 -0
  46. package/dist/email/presets.d.ts +14 -0
  47. package/dist/email/presets.d.ts.map +1 -0
  48. package/dist/email/presets.js +33 -0
  49. package/dist/email/presets.js.map +1 -0
  50. package/dist/email/setup.d.ts +93 -0
  51. package/dist/email/setup.d.ts.map +1 -0
  52. package/dist/email/setup.js +263 -0
  53. package/dist/email/setup.js.map +1 -0
  54. package/dist/email/spf.d.ts +56 -0
  55. package/dist/email/spf.d.ts.map +1 -0
  56. package/dist/email/spf.js +102 -0
  57. package/dist/email/spf.js.map +1 -0
  58. package/dist/index.js +113 -4
  59. package/dist/index.js.map +1 -1
  60. package/dist/inventory.d.ts.map +1 -1
  61. package/dist/inventory.js +34 -11
  62. package/dist/inventory.js.map +1 -1
  63. package/dist/overview.d.ts.map +1 -1
  64. package/dist/overview.js +43 -15
  65. package/dist/overview.js.map +1 -1
  66. package/dist/prompts.d.ts +5 -0
  67. package/dist/prompts.d.ts.map +1 -1
  68. package/dist/prompts.js +29 -7
  69. package/dist/prompts.js.map +1 -1
  70. package/dist/provision/index.d.ts +20 -1
  71. package/dist/provision/index.d.ts.map +1 -1
  72. package/dist/provision/index.js +115 -0
  73. package/dist/provision/index.js.map +1 -1
  74. package/dist/provision/s3-buckets.d.ts.map +1 -1
  75. package/dist/provision/s3-buckets.js +45 -25
  76. package/dist/provision/s3-buckets.js.map +1 -1
  77. package/dist/provision/write-env.d.ts +6 -0
  78. package/dist/provision/write-env.d.ts.map +1 -1
  79. package/dist/provision/write-env.js +17 -0
  80. package/dist/provision/write-env.js.map +1 -1
  81. package/dist/scaffold/app.d.ts.map +1 -1
  82. package/dist/scaffold/app.js +15 -7
  83. package/dist/scaffold/app.js.map +1 -1
  84. package/dist/scaffold/build-pipeline.d.ts +40 -0
  85. package/dist/scaffold/build-pipeline.d.ts.map +1 -1
  86. package/dist/scaffold/build-pipeline.js +201 -5
  87. package/dist/scaffold/build-pipeline.js.map +1 -1
  88. package/dist/scaffold/infra.d.ts +4 -5
  89. package/dist/scaffold/infra.d.ts.map +1 -1
  90. package/dist/scaffold/infra.js +11 -56
  91. package/dist/scaffold/infra.js.map +1 -1
  92. package/dist/scaffold/manifest.d.ts.map +1 -1
  93. package/dist/scaffold/manifest.js +1 -0
  94. package/dist/scaffold/manifest.js.map +1 -1
  95. package/dist/scaffold/pages-heuristics.d.ts.map +1 -1
  96. package/dist/scaffold/pages-heuristics.js +10 -10
  97. package/dist/scaffold/pages-heuristics.js.map +1 -1
  98. package/dist/scaffold/pages-mode.js +2 -4
  99. package/dist/scaffold/pages-mode.js.map +1 -1
  100. package/dist/scaffold/pkg-json.d.ts +4 -0
  101. package/dist/scaffold/pkg-json.d.ts.map +1 -1
  102. package/dist/scaffold/pkg-json.js +17 -0
  103. package/dist/scaffold/pkg-json.js.map +1 -1
  104. package/dist/scaffold/update.js +1 -1
  105. package/dist/scaffold/update.js.map +1 -1
  106. package/dist/templates/build-pipeline/Dockerfile.nextjs-monorepo.hbs +107 -0
  107. package/dist/templates/build-pipeline/Dockerfile.nextjs.hbs +103 -0
  108. package/dist/templates/build-pipeline/docker-compose.yml.hbs +37 -8
  109. package/dist/utils/cloudflare-api.d.ts +146 -20
  110. package/dist/utils/cloudflare-api.d.ts.map +1 -1
  111. package/dist/utils/cloudflare-api.js +203 -11
  112. package/dist/utils/cloudflare-api.js.map +1 -1
  113. package/dist/utils/run-ledger.d.ts +22 -1
  114. package/dist/utils/run-ledger.d.ts.map +1 -1
  115. package/dist/utils/run-ledger.js.map +1 -1
  116. package/dist/utils/s3-admin.d.ts +9 -0
  117. package/dist/utils/s3-admin.d.ts.map +1 -0
  118. package/dist/utils/s3-admin.js +46 -0
  119. package/dist/utils/s3-admin.js.map +1 -0
  120. package/package.json +1 -1
@@ -0,0 +1,251 @@
1
+ /*
2
+ * `hatchkit email` command surface.
3
+ *
4
+ * Two entry points:
5
+ * · `hatchkit email setup` — full setup or re-run on a given domain.
6
+ * Flag-driven; missing flags get prompted (multi-select for the
7
+ * forwarding addresses, single-input for the destination).
8
+ * · `hatchkit email status` — print the current state of Email Routing
9
+ * for the project's domain. No mutations. Useful inside a project
10
+ * dir or after a setup to confirm verification went through.
11
+ *
12
+ * The same `runEmailSetupForDomain` is reused by the provision
13
+ * orchestrator's `email` service entry, so the setup logic exists in
14
+ * exactly one place — flags and prompts are the only difference.
15
+ */
16
+ import { existsSync } from "node:fs";
17
+ import { join, resolve } from "node:path";
18
+ import { confirm, input } from "@inquirer/prompts";
19
+ import chalk from "chalk";
20
+ import { ensureDefaultForwardingEmail, ensureDns, getDefaultForwardingEmail, getDnsConfig, } from "../config.js";
21
+ import { readManifest } from "../scaffold/manifest.js";
22
+ import { CloudflareApi } from "../utils/cloudflare-api.js";
23
+ import { multiselect } from "../utils/multiselect.js";
24
+ import { DEFAULT_CATCH_ALL, DEFAULT_FORWARD_PRESETS } from "./presets.js";
25
+ import { printEmailSetupSummary, runEmailSetup, } from "./setup.js";
26
+ /** Resolve a domain to set up email for. Precedence:
27
+ * 1. --domain flag
28
+ * 2. .hatchkit.json in cwd
29
+ * 3. interactive prompt
30
+ * Used by both `hatchkit email setup` and the provision-service hook. */
31
+ async function resolveDomain(flagDomain, cwd) {
32
+ if (flagDomain)
33
+ return flagDomain.trim();
34
+ const manifestPath = join(cwd, ".hatchkit.json");
35
+ if (existsSync(manifestPath)) {
36
+ const manifest = readManifest(cwd);
37
+ if (manifest?.domain) {
38
+ console.log(chalk.dim(` Using domain from .hatchkit.json: ${manifest.domain}`));
39
+ return manifest.domain;
40
+ }
41
+ }
42
+ return input({
43
+ message: "Domain to set up email for (e.g. example.com):",
44
+ validate: (v) => /^[a-z0-9][a-z0-9.-]*\.[a-z]{2,}$/i.test(v.trim()) ? true : "Looks malformed.",
45
+ });
46
+ }
47
+ /** Prompt the user for which local parts to forward — or take them
48
+ * straight from the `--addresses` flag. */
49
+ async function resolveAddresses(flags, domain) {
50
+ if (flags.addresses) {
51
+ const list = flags.addresses
52
+ .split(",")
53
+ .map((s) => s.trim().toLowerCase())
54
+ .filter(Boolean);
55
+ return { addresses: list, catchAll: !flags.noCatchAll };
56
+ }
57
+ if (flags.allDefaults) {
58
+ return {
59
+ addresses: DEFAULT_FORWARD_PRESETS.filter((p) => p.defaultChecked).map((p) => p.localPart),
60
+ catchAll: !flags.noCatchAll,
61
+ };
62
+ }
63
+ const picked = await multiselect({
64
+ message: `Which addresses on ${domain} should forward to your inbox?`,
65
+ choices: DEFAULT_FORWARD_PRESETS.map((p) => ({
66
+ name: `${p.localPart}@${domain} — ${p.description}`,
67
+ value: p.localPart,
68
+ checked: p.defaultChecked,
69
+ })),
70
+ required: false,
71
+ });
72
+ const catchAll = flags.noCatchAll
73
+ ? false
74
+ : await confirm({
75
+ message: `Also enable catch-all (*@${domain} → your inbox)?`,
76
+ default: DEFAULT_CATCH_ALL,
77
+ });
78
+ return { addresses: picked, catchAll };
79
+ }
80
+ /** Probe the zone for an existing Resend DKIM record so we can auto-add
81
+ * `_spf.resend.com` to the merged SPF when present. Returns the include
82
+ * list to merge (empty when no Resend in evidence). Cheap one-call probe;
83
+ * if it fails (token lacks read perm, zone not in account), returns []. */
84
+ async function detectExtraSpfIncludes(token, zoneId, domain) {
85
+ try {
86
+ const cf = new CloudflareApi({ token });
87
+ const includes = [];
88
+ // Resend domains add a CNAME at `resend._domainkey.<zone>` — its
89
+ // presence is the cleanest signal that the zone sends via Resend.
90
+ // One name+type lookup is much cheaper than listing the zone.
91
+ const dkim = await cf.findRecordsByName(zoneId, `resend._domainkey.${domain}`, "CNAME");
92
+ if (dkim.length > 0) {
93
+ includes.push("_spf.resend.com");
94
+ }
95
+ return includes;
96
+ }
97
+ catch {
98
+ return [];
99
+ }
100
+ }
101
+ /** Shared setup runner used by both `hatchkit email setup` and the
102
+ * provision-orchestrator "email" service. Resolves DNS config, runs
103
+ * prompts that haven't been answered by flags, executes the setup,
104
+ * and prints the summary. */
105
+ export async function runEmailSetupForDomain(flags, cwd = process.cwd()) {
106
+ // DNS config is needed for the CF Bearer token + accountId. Lazy-prompt
107
+ // when missing — same contract as every other provider in the CLI.
108
+ let dns = await getDnsConfig();
109
+ if (!dns || !dns.apiToken)
110
+ dns = await ensureDns();
111
+ if (!dns?.apiToken) {
112
+ throw new Error("Cloudflare API token not configured. Run `hatchkit config add dns`.");
113
+ }
114
+ const domain = await resolveDomain(flags.domain, cwd);
115
+ const destination = flags.to?.trim() || getDefaultForwardingEmail() || (await ensureDefaultForwardingEmail());
116
+ const { addresses, catchAll } = await resolveAddresses(flags, domain);
117
+ // We need the zone id to detect resend SPF before the main setup runs.
118
+ // The setup orchestrator will look the zone up again — cheap; one API
119
+ // call. Keeping the two lookups separate keeps the orchestrator
120
+ // dependency-free of flag-parsing concerns.
121
+ let extraSpf = [];
122
+ if (!flags.noResendSpf) {
123
+ const cf = new CloudflareApi({ token: dns.apiToken, accountId: dns.accountId });
124
+ const zone = await cf.getZoneByName(domain);
125
+ if (zone) {
126
+ extraSpf = await detectExtraSpfIncludes(dns.apiToken, zone.id, domain);
127
+ }
128
+ }
129
+ const opts = {
130
+ token: dns.apiToken,
131
+ accountId: dns.accountId,
132
+ domain,
133
+ destination,
134
+ addresses,
135
+ catchAll,
136
+ extraSpfIncludes: extraSpf,
137
+ dmarcPolicy: flags.dmarcPolicy ?? "quarantine",
138
+ };
139
+ console.log(chalk.bold(`\n hatchkit email setup`));
140
+ console.log(chalk.dim(` Domain: ${domain}`));
141
+ console.log(chalk.dim(` Destination: ${destination}`));
142
+ console.log(chalk.dim(` Addresses: ${addresses.length > 0 ? addresses.map((a) => `${a}@`).join(", ") : "(none — catch-all only)"}`));
143
+ console.log(chalk.dim(` Catch-all: ${catchAll ? "yes" : "no"}`));
144
+ console.log(chalk.dim(` DMARC: p=${opts.dmarcPolicy}`));
145
+ if (extraSpf.length > 0) {
146
+ console.log(chalk.dim(` SPF merge: ${extraSpf.join(", ")}`));
147
+ }
148
+ const result = await runEmailSetup(opts);
149
+ printEmailSetupSummary(result);
150
+ return result;
151
+ }
152
+ /** `hatchkit email status` — read-only state report for the current
153
+ * project's (or `--domain`-overridden) zone. */
154
+ export async function runEmailStatus(flags, cwd = process.cwd()) {
155
+ const dns = await getDnsConfig();
156
+ if (!dns?.apiToken) {
157
+ console.log(chalk.yellow(" DNS not configured. Run `hatchkit config add dns`."));
158
+ return;
159
+ }
160
+ const domain = await resolveDomain(flags.domain, cwd);
161
+ const cf = new CloudflareApi({ token: dns.apiToken, accountId: dns.accountId });
162
+ const zone = await cf.getZoneByName(domain);
163
+ if (!zone) {
164
+ console.log(chalk.yellow(` No zone for ${domain} in this Cloudflare account.`));
165
+ return;
166
+ }
167
+ const accountId = dns.accountId ?? zone.account?.id;
168
+ const routing = await cf.getEmailRouting(zone.id);
169
+ const rules = routing?.enabled ? await cf.listEmailRoutingRules(zone.id) : [];
170
+ const destinations = accountId ? await cf.listEmailDestinations(accountId) : [];
171
+ const mx = await cf.findRecordsByName(zone.id, domain, "MX");
172
+ const spfAndDmarc = await cf.findRecordsByName(zone.id, domain, "TXT");
173
+ const dmarc = await cf.findRecordsByName(zone.id, `_dmarc.${domain}`, "TXT");
174
+ console.log(chalk.bold(`\n ── Email status: ${domain} ───────────────────────────\n`));
175
+ console.log(` Routing: ${routing?.enabled ? chalk.green("enabled") : chalk.red("disabled")}${routing?.status ? chalk.dim(` (${routing.status})`) : ""}`);
176
+ console.log(` MX records: ${mx.length > 0 ? chalk.green(`${mx.length} (${mx.map((r) => r.content).join(", ")})`) : chalk.red("none")}`);
177
+ const spf = spfAndDmarc.find((r) => /v=spf1/i.test(r.content));
178
+ console.log(` SPF: ${spf ? chalk.green(spf.content) : chalk.red("missing")}`);
179
+ console.log(` DMARC: ${dmarc[0] ? chalk.green(dmarc[0].content) : chalk.red("missing")}`);
180
+ console.log(` Destinations: ${destinations.length} on account`);
181
+ for (const d of destinations) {
182
+ const tag = d.verified === "active" ? chalk.green("✓ verified") : chalk.yellow("· pending");
183
+ console.log(` ${tag} ${d.email}`);
184
+ }
185
+ console.log(` Rules: ${rules.length}`);
186
+ for (const r of rules) {
187
+ const to = r.matchers?.find((m) => m.field === "to")?.value;
188
+ const fwd = r.actions?.[0]?.value?.join(", ");
189
+ console.log(` ${to ?? "?"} → ${fwd ?? "?"}`);
190
+ }
191
+ }
192
+ /** Parse `hatchkit email …` flags from the raw argv slice. Centralised
193
+ * here so the index.ts dispatcher only deals with subcommand routing. */
194
+ export function parseEmailFlags(rest) {
195
+ const flags = {};
196
+ for (let i = 0; i < rest.length; i++) {
197
+ const a = rest[i];
198
+ if (a === "--domain" && rest[i + 1])
199
+ flags.domain = rest[++i];
200
+ else if (a.startsWith("--domain="))
201
+ flags.domain = a.slice("--domain=".length);
202
+ else if (a === "--to" && rest[i + 1])
203
+ flags.to = rest[++i];
204
+ else if (a.startsWith("--to="))
205
+ flags.to = a.slice("--to=".length);
206
+ else if (a === "--addresses" && rest[i + 1])
207
+ flags.addresses = rest[++i];
208
+ else if (a.startsWith("--addresses="))
209
+ flags.addresses = a.slice("--addresses=".length);
210
+ else if (a === "--all-defaults")
211
+ flags.allDefaults = true;
212
+ else if (a === "--no-catch-all")
213
+ flags.noCatchAll = true;
214
+ else if (a === "--dmarc" && rest[i + 1])
215
+ flags.dmarcPolicy = rest[++i];
216
+ else if (a.startsWith("--dmarc="))
217
+ flags.dmarcPolicy = a.slice("--dmarc=".length);
218
+ else if (a === "--no-resend-spf")
219
+ flags.noResendSpf = true;
220
+ }
221
+ return flags;
222
+ }
223
+ /** Top-level `hatchkit email <sub>` dispatcher. */
224
+ export async function handleEmailCommand(rest) {
225
+ const sub = rest[0];
226
+ const flags = parseEmailFlags(rest.slice(1));
227
+ switch (sub) {
228
+ case "setup":
229
+ await runEmailSetupForDomain(flags, resolve("."));
230
+ return;
231
+ case "status":
232
+ await runEmailStatus(flags, resolve("."));
233
+ return;
234
+ default:
235
+ console.log("Usage: hatchkit email <setup|status> [flags]");
236
+ console.log("");
237
+ console.log(" setup Configure Cloudflare Email Routing + DNS for a domain");
238
+ console.log(" status Print the current Email Routing state");
239
+ console.log("");
240
+ console.log("Flags (setup):");
241
+ console.log(" --domain <fqdn> Override the project domain");
242
+ console.log(" --to <email> Forwarding destination");
243
+ console.log(" --addresses <list> Comma-separated local parts (skips prompt)");
244
+ console.log(" --all-defaults Use every default preset; skip prompts");
245
+ console.log(" --no-catch-all Don't set the *@domain catch-all rule");
246
+ console.log(" --dmarc <none|quarantine|reject> DMARC policy (default: quarantine)");
247
+ console.log(" --no-resend-spf Skip auto-merging _spf.resend.com");
248
+ process.exit(1);
249
+ }
250
+ }
251
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/email/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ export interface EmailAddressPreset {
2
+ /** Local part. Joined with `@<domain>` at apply time. */
3
+ localPart: string;
4
+ /** Human-readable description shown in the multi-select prompt. */
5
+ description: string;
6
+ /** Whether this preset is ticked by default in the picker. */
7
+ defaultChecked: boolean;
8
+ }
9
+ export declare const DEFAULT_FORWARD_PRESETS: EmailAddressPreset[];
10
+ /** Whether to enable a catch-all rule (`*@domain` → destination) by
11
+ * default. Catch-all is a safety net for anything not matched by an
12
+ * explicit rule — recommended for personal/operator domains. */
13
+ export declare const DEFAULT_CATCH_ALL = true;
14
+ //# sourceMappingURL=presets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"presets.d.ts","sourceRoot":"","sources":["../../src/email/presets.ts"],"names":[],"mappings":"AAsBA,MAAM,WAAW,kBAAkB;IACjC,yDAAyD;IACzD,SAAS,EAAE,MAAM,CAAC;IAClB,mEAAmE;IACnE,WAAW,EAAE,MAAM,CAAC;IACpB,8DAA8D;IAC9D,cAAc,EAAE,OAAO,CAAC;CACzB;AAED,eAAO,MAAM,uBAAuB,EAAE,kBAAkB,EAMvD,CAAC;AAEF;;iEAEiE;AACjE,eAAO,MAAM,iBAAiB,OAAO,CAAC"}
@@ -0,0 +1,33 @@
1
+ /*
2
+ * Email forwarding presets.
3
+ *
4
+ * Default set of local-parts to offer when configuring Cloudflare Email
5
+ * Routing on a new project's zone. The picker is multi-select so the
6
+ * user can untick anything that doesn't apply, or add custom entries.
7
+ *
8
+ * Curated to cover the common public-facing aliases without bloating
9
+ * the rule list (each rule is a distinct Email Routing entry):
10
+ * · hello@ — generic first-touch contact
11
+ * · rico@ — personal alias (the operator's first name)
12
+ * · admin@ — system / infrastructure correspondence (TLS notices,
13
+ * registrar alerts, dotenvx/Github billing receipts)
14
+ * · support@— customer-facing support inbox
15
+ * · hi@ — short personal alternative to hello@
16
+ *
17
+ * A catch-all rule (`*@domain`) is offered separately because
18
+ * Cloudflare's API treats it differently — it's exactly one rule per
19
+ * zone (PUT semantics), not a list. The default is "enable catch-all"
20
+ * so stray addresses (`careers@`, `dmarc@`, …) still reach the user.
21
+ */
22
+ export const DEFAULT_FORWARD_PRESETS = [
23
+ { localPart: "hello", description: "general first-touch contact", defaultChecked: true },
24
+ { localPart: "rico", description: "personal alias", defaultChecked: true },
25
+ { localPart: "admin", description: "infrastructure / system alerts", defaultChecked: true },
26
+ { localPart: "support", description: "customer-facing support", defaultChecked: true },
27
+ { localPart: "hi", description: "short personal alias", defaultChecked: false },
28
+ ];
29
+ /** Whether to enable a catch-all rule (`*@domain` → destination) by
30
+ * default. Catch-all is a safety net for anything not matched by an
31
+ * explicit rule — recommended for personal/operator domains. */
32
+ export const DEFAULT_CATCH_ALL = true;
33
+ //# sourceMappingURL=presets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"presets.js","sourceRoot":"","sources":["../../src/email/presets.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAWH,MAAM,CAAC,MAAM,uBAAuB,GAAyB;IAC3D,EAAE,SAAS,EAAE,OAAO,EAAE,WAAW,EAAE,6BAA6B,EAAE,cAAc,EAAE,IAAI,EAAE;IACxF,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,gBAAgB,EAAE,cAAc,EAAE,IAAI,EAAE;IAC1E,EAAE,SAAS,EAAE,OAAO,EAAE,WAAW,EAAE,gCAAgC,EAAE,cAAc,EAAE,IAAI,EAAE;IAC3F,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,yBAAyB,EAAE,cAAc,EAAE,IAAI,EAAE;IACtF,EAAE,SAAS,EAAE,IAAI,EAAE,WAAW,EAAE,sBAAsB,EAAE,cAAc,EAAE,KAAK,EAAE;CAChF,CAAC;AAEF;;iEAEiE;AACjE,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,CAAC"}
@@ -0,0 +1,93 @@
1
+ import { type CfEmailDestination } from "../utils/cloudflare-api.js";
2
+ /** Cloudflare-published MX hosts for Email Routing. Verified against
3
+ * what `GET /zones/{id}/email/routing/dns` returns — kept hardcoded
4
+ * so a hatchkit run can describe the records up-front without an
5
+ * extra API call, and because the values have been stable since the
6
+ * Email Routing product launched. The API stays the source of truth
7
+ * in practice: the email module calls `getEmailRoutingDnsRecords()`
8
+ * and uses *those* values, falling back to this list only if CF is
9
+ * unreachable. */
10
+ export declare const CLOUDFLARE_EMAIL_ROUTING_MX: {
11
+ host: string;
12
+ priority: number;
13
+ }[];
14
+ export interface EmailSetupOptions {
15
+ /** Bearer token with Zone:DNS:Edit + Zone:Email Routing Rules:Edit +
16
+ * Account:Email Routing Addresses:Edit. */
17
+ token: string;
18
+ /** Optional Cloudflare account id. Discovered from the zone when
19
+ * absent (since the destinations API is account-scoped, we always
20
+ * need one before the call). */
21
+ accountId?: string;
22
+ /** Apex domain — must match a zone the token can access. */
23
+ domain: string;
24
+ /** Email address that will receive forwarded mail. CF sends a
25
+ * verification email here on first add. */
26
+ destination: string;
27
+ /** Local parts to create forwarding rules for. Each becomes a
28
+ * `<localPart>@<domain>` literal-match rule forwarding to
29
+ * `destination`. Pass an empty list to skip individual rules
30
+ * (still useful with `catchAll: true`). */
31
+ addresses: string[];
32
+ /** Whether to set a catch-all rule (`*@domain` → destination). */
33
+ catchAll: boolean;
34
+ /** SPF includes to merge with Cloudflare's. Use this when the zone
35
+ * already sends via Resend / SES / etc. Pre-existing on-zone
36
+ * records are also auto-merged. */
37
+ extraSpfIncludes?: string[];
38
+ /** DMARC policy. Defaults to "quarantine". */
39
+ dmarcPolicy?: "none" | "quarantine" | "reject";
40
+ /** Aggregate-report destination for DMARC. Defaults to
41
+ * `dmarc@<domain>` (will be caught by the catch-all if enabled).
42
+ * Override when you want CF Email Routing's reports forwarded to
43
+ * a known inbox without relying on catch-all. */
44
+ dmarcRua?: string;
45
+ }
46
+ /** Per-resource report returned by {@link runEmailSetup}. The caller
47
+ * feeds the ledger entries into `RunLedger.record()` for rollback. */
48
+ export interface EmailSetupResult {
49
+ domain: string;
50
+ zoneId: string;
51
+ accountId: string;
52
+ /** True when this run was the one that enabled routing on the zone. */
53
+ routingEnabledThisRun: boolean;
54
+ destination: {
55
+ record: CfEmailDestination;
56
+ /** True when this run created the destination (verification email
57
+ * was just sent). False when it already existed. */
58
+ createdThisRun: boolean;
59
+ /** "active" / "pending" — the user must click the verify link
60
+ * before forwards land. */
61
+ verified: string | null;
62
+ };
63
+ /** DNS records the run created/updated. Each entry's `created` is
64
+ * true when this run added it (use for the rollback ledger). */
65
+ dnsRecords: Array<{
66
+ id: string;
67
+ name: string;
68
+ type: "MX" | "TXT";
69
+ content: string;
70
+ created: boolean;
71
+ updated: boolean;
72
+ }>;
73
+ /** Per-address forwarding rules. */
74
+ rules: Array<{
75
+ address: string;
76
+ id: string;
77
+ created: boolean;
78
+ updated: boolean;
79
+ }>;
80
+ /** Catch-all is a zone-level singleton — toggled, not "created" in
81
+ * the usual sense. `changed` is true when this run flipped its
82
+ * enabled state or forward destination. */
83
+ catchAll?: {
84
+ enabled: boolean;
85
+ changed: boolean;
86
+ };
87
+ }
88
+ export declare function runEmailSetup(opts: EmailSetupOptions): Promise<EmailSetupResult>;
89
+ /** Pretty-print the result for the CLI. Centralised here so both the
90
+ * standalone command and the create/adopt-flow hook print the same
91
+ * status block. */
92
+ export declare function printEmailSetupSummary(result: EmailSetupResult): void;
93
+ //# sourceMappingURL=setup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/email/setup.ts"],"names":[],"mappings":"AA2BA,OAAO,EAEL,KAAK,kBAAkB,EAExB,MAAM,4BAA4B,CAAC;AAGpC;;;;;;;mBAOmB;AACnB,eAAO,MAAM,2BAA2B;;;GAIvC,CAAC;AAEF,MAAM,WAAW,iBAAiB;IAChC;gDAC4C;IAC5C,KAAK,EAAE,MAAM,CAAC;IACd;;qCAEiC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4DAA4D;IAC5D,MAAM,EAAE,MAAM,CAAC;IACf;gDAC4C;IAC5C,WAAW,EAAE,MAAM,CAAC;IACpB;;;gDAG4C;IAC5C,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,kEAAkE;IAClE,QAAQ,EAAE,OAAO,CAAC;IAClB;;wCAEoC;IACpC,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,8CAA8C;IAC9C,WAAW,CAAC,EAAE,MAAM,GAAG,YAAY,GAAG,QAAQ,CAAC;IAC/C;;;sDAGkD;IAClD,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;uEACuE;AACvE,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,uEAAuE;IACvE,qBAAqB,EAAE,OAAO,CAAC;IAC/B,WAAW,EAAE;QACX,MAAM,EAAE,kBAAkB,CAAC;QAC3B;6DACqD;QACrD,cAAc,EAAE,OAAO,CAAC;QACxB;oCAC4B;QAC5B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;KACzB,CAAC;IACF;qEACiE;IACjE,UAAU,EAAE,KAAK,CAAC;QAChB,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,IAAI,GAAG,KAAK,CAAC;QACnB,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,EAAE,OAAO,CAAC;QACjB,OAAO,EAAE,OAAO,CAAC;KAClB,CAAC,CAAC;IACH,oCAAoC;IACpC,KAAK,EAAE,KAAK,CAAC;QACX,OAAO,EAAE,MAAM,CAAC;QAChB,EAAE,EAAE,MAAM,CAAC;QACX,OAAO,EAAE,OAAO,CAAC;QACjB,OAAO,EAAE,OAAO,CAAC;KAClB,CAAC,CAAC;IACH;;gDAE4C;IAC5C,QAAQ,CAAC,EAAE;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;CACnD;AAED,wBAAsB,aAAa,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAiKtF;AAgCD;;oBAEoB;AACpB,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,gBAAgB,GAAG,IAAI,CAqDrE"}