hatchkit 0.1.40 → 0.1.42

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 (127) hide show
  1. package/dist/adopt.d.ts.map +1 -1
  2. package/dist/adopt.js +663 -82
  3. package/dist/adopt.js.map +1 -1
  4. package/dist/config.d.ts +32 -10
  5. package/dist/config.d.ts.map +1 -1
  6. package/dist/config.js +91 -38
  7. package/dist/config.js.map +1 -1
  8. package/dist/deploy/coolify-app.d.ts.map +1 -1
  9. package/dist/deploy/coolify-app.js +0 -7
  10. package/dist/deploy/coolify-app.js.map +1 -1
  11. package/dist/deploy/coolify.d.ts.map +1 -1
  12. package/dist/deploy/coolify.js +20 -1
  13. package/dist/deploy/coolify.js.map +1 -1
  14. package/dist/deploy/ghcr.d.ts +4 -2
  15. package/dist/deploy/ghcr.d.ts.map +1 -1
  16. package/dist/deploy/ghcr.js +1 -1
  17. package/dist/deploy/ghcr.js.map +1 -1
  18. package/dist/deploy/github.d.ts +4 -3
  19. package/dist/deploy/github.d.ts.map +1 -1
  20. package/dist/deploy/github.js +5 -2
  21. package/dist/deploy/github.js.map +1 -1
  22. package/dist/deploy/pages.d.ts +41 -0
  23. package/dist/deploy/pages.d.ts.map +1 -1
  24. package/dist/deploy/pages.js +363 -22
  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 +5 -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 +44 -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 +306 -22
  59. package/dist/index.js.map +1 -1
  60. package/dist/inventory.d.ts +37 -0
  61. package/dist/inventory.d.ts.map +1 -1
  62. package/dist/inventory.js +536 -55
  63. package/dist/inventory.js.map +1 -1
  64. package/dist/overview.d.ts +101 -0
  65. package/dist/overview.d.ts.map +1 -0
  66. package/dist/overview.js +880 -0
  67. package/dist/overview.js.map +1 -0
  68. package/dist/prompts.d.ts +27 -0
  69. package/dist/prompts.d.ts.map +1 -1
  70. package/dist/prompts.js +262 -34
  71. package/dist/prompts.js.map +1 -1
  72. package/dist/provision/index.d.ts +20 -1
  73. package/dist/provision/index.d.ts.map +1 -1
  74. package/dist/provision/index.js +115 -0
  75. package/dist/provision/index.js.map +1 -1
  76. package/dist/provision/s3-buckets.js +1 -1
  77. package/dist/provision/s3-buckets.js.map +1 -1
  78. package/dist/scaffold/app.d.ts.map +1 -1
  79. package/dist/scaffold/app.js +15 -7
  80. package/dist/scaffold/app.js.map +1 -1
  81. package/dist/scaffold/build-pipeline.d.ts +16 -0
  82. package/dist/scaffold/build-pipeline.d.ts.map +1 -1
  83. package/dist/scaffold/build-pipeline.js +47 -4
  84. package/dist/scaffold/build-pipeline.js.map +1 -1
  85. package/dist/scaffold/infra.d.ts +4 -5
  86. package/dist/scaffold/infra.d.ts.map +1 -1
  87. package/dist/scaffold/infra.js +18 -57
  88. package/dist/scaffold/infra.js.map +1 -1
  89. package/dist/scaffold/manifest.d.ts +6 -0
  90. package/dist/scaffold/manifest.d.ts.map +1 -1
  91. package/dist/scaffold/manifest.js +2 -0
  92. package/dist/scaffold/manifest.js.map +1 -1
  93. package/dist/scaffold/pages-heuristics.d.ts +17 -0
  94. package/dist/scaffold/pages-heuristics.d.ts.map +1 -0
  95. package/dist/scaffold/pages-heuristics.js +344 -0
  96. package/dist/scaffold/pages-heuristics.js.map +1 -0
  97. package/dist/scaffold/pages-mode.d.ts +10 -0
  98. package/dist/scaffold/pages-mode.d.ts.map +1 -0
  99. package/dist/scaffold/pages-mode.js +107 -0
  100. package/dist/scaffold/pages-mode.js.map +1 -0
  101. package/dist/scaffold/pkg-json.d.ts +4 -0
  102. package/dist/scaffold/pkg-json.d.ts.map +1 -1
  103. package/dist/scaffold/pkg-json.js +17 -0
  104. package/dist/scaffold/pkg-json.js.map +1 -1
  105. package/dist/scaffold/surfaces.d.ts.map +1 -1
  106. package/dist/scaffold/surfaces.js +12 -1
  107. package/dist/scaffold/surfaces.js.map +1 -1
  108. package/dist/scaffold/update.js +1 -1
  109. package/dist/scaffold/update.js.map +1 -1
  110. package/dist/templates/build-pipeline/Dockerfile.nextjs.hbs +103 -0
  111. package/dist/templates/build-pipeline/docker-compose.yml.hbs +23 -6
  112. package/dist/utils/cloudflare-api.d.ts +158 -13
  113. package/dist/utils/cloudflare-api.d.ts.map +1 -1
  114. package/dist/utils/cloudflare-api.js +219 -11
  115. package/dist/utils/cloudflare-api.js.map +1 -1
  116. package/dist/utils/coolify-api.d.ts +9 -0
  117. package/dist/utils/coolify-api.d.ts.map +1 -1
  118. package/dist/utils/coolify-api.js +26 -0
  119. package/dist/utils/coolify-api.js.map +1 -1
  120. package/dist/utils/run-ledger.d.ts +42 -1
  121. package/dist/utils/run-ledger.d.ts.map +1 -1
  122. package/dist/utils/run-ledger.js.map +1 -1
  123. package/dist/utils/s3-admin.d.ts +9 -0
  124. package/dist/utils/s3-admin.d.ts.map +1 -0
  125. package/dist/utils/s3-admin.js +46 -0
  126. package/dist/utils/s3-admin.js.map +1 -0
  127. package/package.json +1 -1
@@ -3,8 +3,10 @@ export interface GhcrSetupOptions {
3
3
  /** Owner/repo slug, e.g. `trebeljahr/extinction-protocol`. */
4
4
  repoSlug: string;
5
5
  /** Maximum time to wait for the first Actions push to create the
6
- * package in GHCR. Default 5 minutes — enough headroom for cold
7
- * builds without keeping the user staring at a spinner forever. */
6
+ * package in GHCR. Default 10 minutes — the starter's verify + e2e
7
+ * + build-server/client pipeline routinely takes 5–8 min on a cold
8
+ * GHA runner, so 5 was right at the boundary and timed out
9
+ * intermittently. */
8
10
  waitTimeoutMs?: number;
9
11
  /** How often to recheck whether the package exists. Default 8s —
10
12
  * matches GHCR's typical sync delay after a push. */
@@ -1 +1 @@
1
- {"version":3,"file":"ghcr.d.ts","sourceRoot":"","sources":["../../src/deploy/ghcr.ts"],"names":[],"mappings":"AAkCA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAG1D,MAAM,WAAW,gBAAgB;IAC/B,8DAA8D;IAC9D,QAAQ,EAAE,MAAM,CAAC;IACjB;;wEAEoE;IACpE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;0DACsD;IACtD,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;oBAGoB;AACpB,MAAM,MAAM,eAAe,GACvB;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,UAAU,EAAE,QAAQ,CAAA;CAAE,GAC5C;IAAE,IAAI,EAAE,oBAAoB,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GACpD;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAE,GACvD;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC;AAE3D;;;;;;;;GAQG;AACH,wBAAsB,qBAAqB,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC,CAiE/F;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,4BAA4B,CAChD,OAAO,EAAE,gBAAgB,GAAG;IAC1B,GAAG,EAAE,UAAU,CAAC;IAChB;+DAC2D;IAC3D,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B;;6CAEyC;IACzC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;CAC9B,GACA,OAAO,CAAC,eAAe,CAAC,CA2C1B"}
1
+ {"version":3,"file":"ghcr.d.ts","sourceRoot":"","sources":["../../src/deploy/ghcr.ts"],"names":[],"mappings":"AAkCA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAG1D,MAAM,WAAW,gBAAgB;IAC/B,8DAA8D;IAC9D,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;0BAIsB;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;0DACsD;IACtD,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;oBAGoB;AACpB,MAAM,MAAM,eAAe,GACvB;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,UAAU,EAAE,QAAQ,CAAA;CAAE,GAC5C;IAAE,IAAI,EAAE,oBAAoB,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GACpD;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAE,GACvD;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC;AAE3D;;;;;;;;GAQG;AACH,wBAAsB,qBAAqB,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC,CAiE/F;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,4BAA4B,CAChD,OAAO,EAAE,gBAAgB,GAAG;IAC1B,GAAG,EAAE,UAAU,CAAC;IAChB;+DAC2D;IAC3D,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B;;6CAEyC;IACzC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;CAC9B,GACA,OAAO,CAAC,eAAe,CAAC,CA2C1B"}
@@ -42,7 +42,7 @@ import { exec, execOk } from "../utils/exec.js";
42
42
  * the user isn't stuck if Actions failed for an unrelated reason.
43
43
  */
44
44
  export async function makeGhcrPackagePublic(options) {
45
- const { repoSlug, waitTimeoutMs = 5 * 60_000, pollIntervalMs = 8_000 } = options;
45
+ const { repoSlug, waitTimeoutMs = 10 * 60_000, pollIntervalMs = 8_000 } = options;
46
46
  const [owner, name] = splitSlug(repoSlug);
47
47
  // Cheap upfront check — bail before the wait if `gh` can't possibly
48
48
  // succeed at the PATCH step. Saves 5 minutes of false hope.
@@ -1 +1 @@
1
- {"version":3,"file":"ghcr.js","sourceRoot":"","sources":["../../src/deploy/ghcr.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ghcr.js","sourceRoot":"","sources":["../../src/deploy/ghcr.ts"],"names":[],"mappings":"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"}
@@ -7,7 +7,8 @@ import type { ProjectConfig } from "../prompts.js";
7
7
  export declare function setupGitHub(config: ProjectConfig, appDir: string): Promise<string | null>;
8
8
  /** Push the working branch to `origin`. Run AFTER Coolify wiring +
9
9
  * GH Actions secrets are in place so the workflow's first run can
10
- * hit the redeploy webhook successfully. Best-effort failures
11
- * print a copy-pasteable manual command rather than throwing. */
12
- export declare function pushInitialBranch(projectDir: string): Promise<void>;
10
+ * hit the redeploy webhook successfully. Returns true on a clean
11
+ * push, false otherwise the caller uses this to gate the GHCR
12
+ * visibility flip (no push = no Actions run = no image to wait for). */
13
+ export declare function pushInitialBranch(projectDir: string): Promise<boolean>;
13
14
  //# sourceMappingURL=github.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"github.d.ts","sourceRoot":"","sources":["../../src/deploy/github.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAGnD;;;;eAIe;AACf,wBAAsB,WAAW,CAAC,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAmD/F;AAED;;;kEAGkE;AAClE,wBAAsB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAsBzE"}
1
+ {"version":3,"file":"github.d.ts","sourceRoot":"","sources":["../../src/deploy/github.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAGnD;;;;eAIe;AACf,wBAAsB,WAAW,CAAC,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAmD/F;AAED;;;;yEAIyE;AACzE,wBAAsB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAwB5E"}
@@ -44,8 +44,9 @@ export async function setupGitHub(config, appDir) {
44
44
  }
45
45
  /** Push the working branch to `origin`. Run AFTER Coolify wiring +
46
46
  * GH Actions secrets are in place so the workflow's first run can
47
- * hit the redeploy webhook successfully. Best-effort failures
48
- * print a copy-pasteable manual command rather than throwing. */
47
+ * hit the redeploy webhook successfully. Returns true on a clean
48
+ * push, false otherwise the caller uses this to gate the GHCR
49
+ * visibility flip (no push = no Actions run = no image to wait for). */
49
50
  export async function pushInitialBranch(projectDir) {
50
51
  // `git symbolic-ref --short HEAD` is more reliable than rev-parse
51
52
  // for the brand-new `git init` case where HEAD points at an unborn
@@ -63,6 +64,8 @@ export async function pushInitialBranch(projectDir) {
63
64
  console.log(chalk.yellow(` Couldn't push ${branch} to origin — push manually:\n` +
64
65
  ` cd ${projectDir}\n` +
65
66
  ` git push -u origin ${branch}`));
67
+ return false;
66
68
  }
69
+ return true;
67
70
  }
68
71
  //# sourceMappingURL=github.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"github.js","sourceRoot":"","sources":["../../src/deploy/github.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"github.js","sourceRoot":"","sources":["../../src/deploy/github.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAExC;;;;eAIe;AACf,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,MAAqB,EAAE,MAAc;IACrE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,kEAAkE,CAAC,CAAC,CAAC;IAE5F,WAAW;IACX,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC,MAAM,CAAC,EAAE;QAC1B,GAAG,EAAE,MAAM;QACX,OAAO,EAAE,0BAA0B;KACpC,CAAC,CAAC;IAEH,iBAAiB;IACjB,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,IAAI,CAAC,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC;IAClD,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC,QAAQ,EAAE,IAAI,EAAE,kBAAkB,CAAC,EAAE;QACtD,GAAG,EAAE,MAAM;QACX,OAAO,EAAE,4BAA4B;KACtC,CAAC,CAAC;IAEH,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE,CAAC;QAC7B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAC,CAAC;QAC5D,OAAO,IAAI,CAAC;IACd,CAAC;IAED,+DAA+D;IAC/D,iEAAiE;IACjE,6CAA6C;IAC7C,MAAM,YAAY,GAAG,MAAM,IAAI,CAC7B,IAAI,EACJ,CAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,IAAI,EAAE,WAAW,EAAE,YAAY,CAAC,EAC1D,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,yBAAyB,MAAM,CAAC,IAAI,KAAK,EAAE,CACpE,CAAC;IAEF,IAAI,YAAY,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;QAChC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,+DAA+D,CAAC,CAAC,CAAC;QAC3F,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,4CAA4C,CAAC,CAAC,CAAC;QACxE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,MAAM,EAAE,CAAC,CAAC,CAAC;QAC3C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,sBAAsB,MAAM,CAAC,IAAI,8BAA8B,CAAC,CAAC,CAAC;QACxF,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,MAAM,CACV,iFAAiF,CAClF,CACF,CAAC;QACF,OAAO,IAAI,CAAC;IACd,CAAC;IAED,mBAAmB;IACnB,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,CAAC,EAAE;QAClF,GAAG,EAAE,MAAM;KACZ,CAAC,CAAC;IAEH,MAAM,OAAO,GAAG,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IACxC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,oBAAoB,OAAO,EAAE,CAAC,CAAC,CAAC;IACxD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;yEAIyE;AACzE,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,UAAkB;IACxD,kEAAkE;IAClE,mEAAmE;IACnE,iDAAiD;IACjD,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC,cAAc,EAAE,SAAS,EAAE,MAAM,CAAC,EAAE;QACrE,GAAG,EAAE,UAAU;QACf,MAAM,EAAE,IAAI;KACb,CAAC,CAAC;IACH,MAAM,MAAM,GAAG,OAAO,CAAC,QAAQ,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;IACvE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE;QAC/D,GAAG,EAAE,UAAU;QACf,OAAO,EAAE,WAAW,MAAM,eAAe;KAC1C,CAAC,CAAC;IACH,IAAI,IAAI,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,MAAM,CACV,mBAAmB,MAAM,+BAA+B;YACtD,UAAU,UAAU,IAAI;YACxB,0BAA0B,MAAM,EAAE,CACrC,CACF,CAAC;QACF,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -1,2 +1,43 @@
1
+ /** What kind of site lives in a folder — determines the build workflow. */
2
+ export type SiteKind = "static" | "node-build" | "docusaurus" | "jekyll";
3
+ export interface Detected {
4
+ kind: SiteKind;
5
+ /** Folder uploaded to Pages. Relative to repo root. */
6
+ publishDir: string;
7
+ /** Package manager for node-build sites. */
8
+ packageManager?: "pnpm" | "npm" | "yarn" | "bun";
9
+ /** npm script name used for the build (usually "build"). */
10
+ buildScript?: string;
11
+ /** Working directory for the build. Empty string = repo root. */
12
+ workDir: string;
13
+ }
1
14
  export declare function runPagesSetup(cwd: string): Promise<void>;
15
+ /** Programmatic entrypoint for the create/adopt flows.
16
+ *
17
+ * Takes already-resolved values (detected site shape, optional
18
+ * custom domain) and runs the same enable / workflow / DNS / cert
19
+ * pipeline as the interactive flow. Skips the pickSite + promptDomain
20
+ * steps so it's safe to call from within a larger non-interactive
21
+ * scaffold.
22
+ *
23
+ * Returns the public URL the site will be served from so callers
24
+ * can include it in their summary. */
25
+ export declare function runPagesSetupProgrammatic(cwd: string, opts: {
26
+ detected: Detected;
27
+ domain: string | null;
28
+ }): Promise<{
29
+ pageUrl: string;
30
+ }>;
31
+ interface UndoOptions {
32
+ dryRun: boolean;
33
+ yes: boolean;
34
+ }
35
+ /**
36
+ * Reverse what `hatchkit gh-pages` did: disables Pages, deletes the
37
+ * Cloudflare records it created, removes the workflow file, removes any
38
+ * CNAME files matching the registered domain. Idempotent — safe to run
39
+ * even if some pieces are already gone.
40
+ */
41
+ export declare function runPagesUndo(cwd: string, opts: UndoOptions): Promise<void>;
42
+ export {};
2
43
  //# sourceMappingURL=pages.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"pages.d.ts","sourceRoot":"","sources":["../../src/deploy/pages.ts"],"names":[],"mappings":"AAsDA,wBAAsB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAuC9D"}
1
+ {"version":3,"file":"pages.d.ts","sourceRoot":"","sources":["../../src/deploy/pages.ts"],"names":[],"mappings":"AAuBA,2EAA2E;AAC3E,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG,YAAY,GAAG,YAAY,GAAG,QAAQ,CAAC;AAEzE,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,QAAQ,CAAC;IACf,uDAAuD;IACvD,UAAU,EAAE,MAAM,CAAC;IACnB,4CAA4C;IAC5C,cAAc,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,CAAC;IACjD,4DAA4D;IAC5D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iEAAiE;IACjE,OAAO,EAAE,MAAM,CAAC;CACjB;AA4BD,wBAAsB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAgB9D;AAED;;;;;;;;;uCASuC;AACvC,wBAAsB,yBAAyB,CAC7C,GAAG,EAAE,MAAM,EACX,IAAI,EAAE;IAAE,QAAQ,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAClD,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAS9B;AA8yBD,UAAU,WAAW;IACnB,MAAM,EAAE,OAAO,CAAC;IAChB,GAAG,EAAE,OAAO,CAAC;CACd;AAgBD;;;;;GAKG;AACH,wBAAsB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CA0ChF"}
@@ -1,7 +1,10 @@
1
- import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
1
+ import { resolve4 } from "node:dns/promises";
2
+ import { existsSync, mkdirSync, readFileSync, readdirSync, unlinkSync, writeFileSync, } from "node:fs";
2
3
  import { join } from "node:path";
4
+ import { setTimeout as sleep } from "node:timers/promises";
3
5
  import { confirm, input, select } from "@inquirer/prompts";
4
6
  import chalk from "chalk";
7
+ import ora from "ora";
5
8
  import { ensureDns, getDnsConfig } from "../config.js";
6
9
  import { CloudflareApi } from "../utils/cloudflare-api.js";
7
10
  import { exec } from "../utils/exec.js";
@@ -18,16 +21,47 @@ export async function runPagesSetup(cwd) {
18
21
  console.log(chalk.bold("\n ── hatchkit gh-pages ──────────────────────────────────────\n"));
19
22
  // 1. Repo — must be a git repo with an `origin` pointing at GitHub.
20
23
  const repo = await detectRepo(cwd);
21
- console.log(chalk.dim(` Repo: ${repo.fullName} (${repo.private ? "private" : "public"})`));
22
- if (repo.private) {
23
- console.log(chalk.yellow(" ⚠ Private repos need a paid GitHub plan (Pro/Team/Enterprise) for Pages.\n Continuing anyway — will fail at API call if unsupported."));
24
- }
24
+ printRepoHeader(repo);
25
25
  // 2. Pick a site. Auto-confirm when there's one obvious candidate;
26
26
  // ask when zero or many. Also let the user override the detected
27
27
  // publish folder before we commit to writing anything.
28
28
  const confirmed = await pickSite(cwd);
29
29
  // 3. Custom domain (optional).
30
30
  const domain = await promptDomain();
31
+ await executePagesSetup(cwd, repo, confirmed, domain);
32
+ }
33
+ /** Programmatic entrypoint for the create/adopt flows.
34
+ *
35
+ * Takes already-resolved values (detected site shape, optional
36
+ * custom domain) and runs the same enable / workflow / DNS / cert
37
+ * pipeline as the interactive flow. Skips the pickSite + promptDomain
38
+ * steps so it's safe to call from within a larger non-interactive
39
+ * scaffold.
40
+ *
41
+ * Returns the public URL the site will be served from so callers
42
+ * can include it in their summary. */
43
+ export async function runPagesSetupProgrammatic(cwd, opts) {
44
+ const repo = await detectRepo(cwd);
45
+ printRepoHeader(repo);
46
+ await executePagesSetup(cwd, repo, opts.detected, opts.domain);
47
+ return {
48
+ pageUrl: opts.domain
49
+ ? `https://${opts.domain}`
50
+ : `https://${repo.owner}.github.io/${repo.repo}/`,
51
+ };
52
+ }
53
+ function printRepoHeader(repo) {
54
+ console.log(chalk.dim(` Repo: ${repo.fullName} (${repo.private ? "private" : "public"})`));
55
+ if (repo.private) {
56
+ console.log(chalk.yellow(" ⚠ Private repos need a paid GitHub plan (Pro/Team/Enterprise) for Pages.\n Continuing anyway — will fail at API call if unsupported."));
57
+ }
58
+ }
59
+ /** The shared execution pipeline used by both the interactive
60
+ * `runPagesSetup` and the programmatic `runPagesSetupProgrammatic`.
61
+ * Everything from "we know what to deploy and where" onwards lives
62
+ * here — anything *before* that (site detection, domain prompt) is
63
+ * caller-specific. */
64
+ async function executePagesSetup(cwd, repo, confirmed, domain) {
31
65
  // 4. Enable Pages via GitHub API.
32
66
  await enablePages(repo);
33
67
  // 5. Write the workflow — unless the repo already has a Pages-deploying
@@ -36,10 +70,23 @@ export async function runPagesSetup(cwd) {
36
70
  // 6. CNAME file — only when a custom domain is chosen.
37
71
  if (domain)
38
72
  writeCnameFile(cwd, confirmed, domain);
39
- // 7. Pages CNAME + DNS wiring.
73
+ // 7. DNS + Pages CNAME + HTTPS.
74
+ //
75
+ // Order matters: GitHub validates the cname by resolving DNS the moment
76
+ // we PUT it. If DNS isn't in place yet, validation fails silently, cert
77
+ // provisioning is never kicked off, and GitHub doesn't retry. So:
78
+ // a. Wire DNS first.
79
+ // b. Wait for DNS to actually resolve (only when we wrote it ourselves).
80
+ // c. Then tell GitHub the cname — bouncing it first if a prior run
81
+ // left it stuck without a cert.
82
+ // d. Wait for the Let's Encrypt cert to be issued, then flip
83
+ // `https_enforced` so http:// redirects to https://.
40
84
  if (domain) {
85
+ const { wired } = await configureDns(domain);
86
+ if (wired)
87
+ await waitForDnsResolves(domain);
41
88
  await setPagesCname(repo, domain);
42
- await configureDns(domain);
89
+ await provisionHttps(repo, wired);
43
90
  }
44
91
  printSummary(repo, confirmed, domain);
45
92
  }
@@ -280,12 +327,121 @@ async function enablePages(repo) {
280
327
  throw new Error(`Couldn't enable Pages: ${res.stderr.trim() || res.stdout.trim()}`);
281
328
  }
282
329
  async function setPagesCname(repo, domain) {
330
+ // If the cname is already correct but no cert exists, GitHub is stuck
331
+ // (most often because an earlier run set the cname before DNS was live,
332
+ // so the validation+cert flow ran against missing DNS and never retried).
333
+ // Bounce the cname — clear, then re-set — to force a fresh validation
334
+ // pass now that DNS is in place. Idempotent on the happy path: if a cert
335
+ // is already issued we skip the bounce entirely.
336
+ const current = await getPagesInfo(repo);
337
+ const stuck = current?.cname === domain && !current?.https_certificate;
338
+ if (stuck) {
339
+ await exec("gh", ["api", "-X", "PUT", `repos/${repo.fullName}/pages`, "-f", "cname="], {
340
+ silent: true,
341
+ spinner: "Resetting Pages CNAME to retry cert provisioning...",
342
+ });
343
+ await sleep(2000);
344
+ }
283
345
  const res = await exec("gh", ["api", "-X", "PUT", `repos/${repo.fullName}/pages`, "-f", `cname=${domain}`], { silent: true, spinner: `Registering ${domain} with Pages...` });
284
346
  if (res.exitCode !== 0) {
285
- // Non-fatal: DNS might not be in place yet.
347
+ // Non-fatal: DNS might still not be visible to GitHub yet.
286
348
  console.log(chalk.yellow(` ⚠ Couldn't set Pages CNAME to ${domain} (${res.stderr.trim()}).\n Set it manually in Settings → Pages once DNS resolves.`));
287
349
  }
288
350
  }
351
+ async function getPagesInfo(repo) {
352
+ const res = await exec("gh", ["api", `repos/${repo.fullName}/pages`], { silent: true });
353
+ if (res.exitCode !== 0)
354
+ return null;
355
+ try {
356
+ return JSON.parse(res.stdout);
357
+ }
358
+ catch {
359
+ return null;
360
+ }
361
+ }
362
+ // ---------------------------------------------------------------------------
363
+ // HTTPS provisioning
364
+ // ---------------------------------------------------------------------------
365
+ /**
366
+ * Wait for `domain` to resolve to one of GitHub's Pages IPs. Important when
367
+ * we just wrote DNS records via API — GitHub validates the cname by hitting
368
+ * authoritative DNS, and Cloudflare propagation is usually a few seconds
369
+ * but can briefly lag. Bounded wait; on timeout we proceed anyway.
370
+ */
371
+ async function waitForDnsResolves(domain, timeoutMs = 60_000) {
372
+ const githubIps = new Set(GITHUB_APEX_A);
373
+ const spinner = ora(`Waiting for DNS for ${domain} to resolve to GitHub...`).start();
374
+ const start = Date.now();
375
+ while (Date.now() - start < timeoutMs) {
376
+ try {
377
+ const ips = await resolve4(domain);
378
+ if (ips.some((ip) => githubIps.has(ip))) {
379
+ spinner.succeed(`DNS resolves: ${domain} → ${ips[0]}`);
380
+ return true;
381
+ }
382
+ }
383
+ catch {
384
+ // ENOTFOUND / SERVFAIL — keep polling.
385
+ }
386
+ await sleep(3000);
387
+ }
388
+ spinner.warn(`DNS for ${domain} hasn't propagated yet — continuing anyway`);
389
+ return false;
390
+ }
391
+ /**
392
+ * Drive GitHub's HTTPS state machine to completion: poll until the Let's
393
+ * Encrypt cert is `issued`, then flip `https_enforced=true` so http://
394
+ * redirects to https://. Pre-existing fully-configured sites short-circuit
395
+ * on the first poll.
396
+ *
397
+ * If the user added DNS records manually we don't know when they'll land,
398
+ * so we skip the wait and print the finishing commands instead of blocking
399
+ * the CLI for what could be hours.
400
+ */
401
+ async function provisionHttps(repo, autoDns) {
402
+ if (!autoDns) {
403
+ console.log(chalk.dim(`\n Once your DNS records resolve, GitHub will provision an HTTPS cert (usually <5 min).`));
404
+ console.log(chalk.dim(` Check: gh api repos/${repo.fullName}/pages | jq .https_certificate`));
405
+ console.log(chalk.dim(` Enforce: gh api -X PUT repos/${repo.fullName}/pages -F https_enforced=true`));
406
+ return;
407
+ }
408
+ const issued = await waitForCertIssued(repo);
409
+ if (!issued) {
410
+ console.log(chalk.yellow(`\n ⚠ HTTPS cert wasn't issued within the wait window — leaving https_enforced off.`));
411
+ console.log(chalk.dim(` Check: gh api repos/${repo.fullName}/pages | jq .https_certificate`));
412
+ console.log(chalk.dim(` Enforce: gh api -X PUT repos/${repo.fullName}/pages -F https_enforced=true`));
413
+ return;
414
+ }
415
+ const info = await getPagesInfo(repo);
416
+ if (info?.https_enforced) {
417
+ console.log(chalk.dim(" HTTPS already enforced."));
418
+ return;
419
+ }
420
+ const res = await exec("gh", ["api", "-X", "PUT", `repos/${repo.fullName}/pages`, "-F", "https_enforced=true"], { silent: true, spinner: "Enabling Enforce HTTPS..." });
421
+ if (res.exitCode !== 0) {
422
+ console.log(chalk.yellow(` ⚠ Couldn't enable HTTPS enforcement: ${res.stderr.trim() || res.stdout.trim()}`));
423
+ console.log(chalk.dim(` Run later: gh api -X PUT repos/${repo.fullName}/pages -F https_enforced=true`));
424
+ }
425
+ }
426
+ async function waitForCertIssued(repo, timeoutMs = 5 * 60_000) {
427
+ const spinner = ora("Waiting for GitHub to provision the HTTPS certificate...").start();
428
+ const start = Date.now();
429
+ let lastState = "pending";
430
+ while (Date.now() - start < timeoutMs) {
431
+ const info = await getPagesInfo(repo);
432
+ const state = info?.https_certificate?.state;
433
+ if (state)
434
+ lastState = state;
435
+ if (state === "issued" || state === "approved") {
436
+ spinner.succeed(`HTTPS certificate ${state}`);
437
+ return true;
438
+ }
439
+ spinner.text = `Waiting for HTTPS certificate (state: ${lastState})...`;
440
+ await sleep(15_000);
441
+ }
442
+ spinner.warn(`HTTPS cert not ready after ${Math.round(timeoutMs / 1000)}s (last: ${lastState})`);
443
+ return false;
444
+ }
289
445
  // ---------------------------------------------------------------------------
290
446
  // Workflow + CNAME file
291
447
  // ---------------------------------------------------------------------------
@@ -472,22 +628,16 @@ async function configureDns(domain) {
472
628
  if (wantConfigure)
473
629
  dns = await ensureDns();
474
630
  }
475
- if (!dns || dns.provider === "manual") {
631
+ if (!dns) {
476
632
  printManualDnsRecords(baseDomain, subdomain, target, isApex);
477
- return;
633
+ return { wired: false };
478
634
  }
479
- if (dns.provider === "cloudflare") {
480
- if (!dns.apiToken) {
481
- console.log(chalk.yellow(" ⚠ Cloudflare token missing from keychain."));
482
- printManualDnsRecords(baseDomain, subdomain, target, isApex);
483
- return;
484
- }
485
- await configureCloudflareDns(dns.apiToken, baseDomain, subdomain, target, isApex);
486
- return;
635
+ if (!dns.apiToken) {
636
+ console.log(chalk.yellow(" ⚠ Cloudflare token missing from keychain."));
637
+ printManualDnsRecords(baseDomain, subdomain, target, isApex);
638
+ return { wired: false };
487
639
  }
488
- // INWX auto-wiring isn't implemented — XML-RPC + rarely used for Pages.
489
- console.log(chalk.dim(" INWX auto-configure isn't implemented for Pages — showing manual records:"));
490
- printManualDnsRecords(baseDomain, subdomain, target, isApex);
640
+ return configureCloudflareDns(dns.apiToken, baseDomain, subdomain, target, isApex);
491
641
  }
492
642
  async function getGitHubUser() {
493
643
  const res = await exec("gh", ["api", "user", "--jq", ".login"], { silent: true });
@@ -514,7 +664,7 @@ async function configureCloudflareDns(token, baseDomain, subdomain, target, isAp
514
664
  if (!zone) {
515
665
  console.log(chalk.yellow(` ⚠ No Cloudflare zone found for ${baseDomain}. Falling back to manual records.`));
516
666
  printManualDnsRecords(baseDomain, subdomain, target, isApex);
517
- return;
667
+ return { wired: false };
518
668
  }
519
669
  const recordName = isApex ? baseDomain : `${subdomain}.${baseDomain}`;
520
670
  // GitHub Pages apex needs A records for all four IPs (round-robin
@@ -535,6 +685,7 @@ async function configureCloudflareDns(token, baseDomain, subdomain, target, isAp
535
685
  const line = ` ${rec.type} ${recordName} → ${rec.content} (${status})`;
536
686
  console.log(result.created || result.updated ? chalk.green(`✓ ${line.trimStart()}`) : chalk.dim(line));
537
687
  }
688
+ return { wired: true };
538
689
  }
539
690
  // ---------------------------------------------------------------------------
540
691
  // Summary
@@ -554,4 +705,194 @@ function printSummary(repo, d, domain) {
554
705
  }
555
706
  console.log(chalk.yellow(`\n Next: commit & push the new workflow (and CNAME file) to ${repo.defaultBranch}.\n`));
556
707
  }
708
+ /**
709
+ * Reverse what `hatchkit gh-pages` did: disables Pages, deletes the
710
+ * Cloudflare records it created, removes the workflow file, removes any
711
+ * CNAME files matching the registered domain. Idempotent — safe to run
712
+ * even if some pieces are already gone.
713
+ */
714
+ export async function runPagesUndo(cwd, opts) {
715
+ console.log(chalk.bold("\n ── hatchkit gh-pages --undo ───────────────────────────────\n"));
716
+ const repo = await detectRepo(cwd);
717
+ console.log(chalk.dim(` Repo: ${repo.fullName}`));
718
+ const plan = await buildUndoPlan(cwd, repo);
719
+ if (!isAnythingToUndo(plan)) {
720
+ console.log(chalk.dim("\n Nothing to undo — no Pages config, workflow, or CNAME files found.\n"));
721
+ return;
722
+ }
723
+ printUndoPlan(plan);
724
+ if (opts.dryRun) {
725
+ console.log(chalk.dim("\n --dry-run set, nothing changed.\n"));
726
+ return;
727
+ }
728
+ if (!opts.yes) {
729
+ const ok = await confirm({
730
+ message: "Proceed with the steps above?",
731
+ default: false,
732
+ });
733
+ if (!ok) {
734
+ console.log(chalk.dim("\n Aborted — nothing changed.\n"));
735
+ return;
736
+ }
737
+ }
738
+ await executeUndo(repo, plan);
739
+ console.log(chalk.bold("\n ── Done ───────────────────────────────────────────────────\n"));
740
+ if (plan.cname) {
741
+ console.log(chalk.dim(` DNS at other providers (registrar caches, AAAA records, etc.) may need manual cleanup.\n`));
742
+ }
743
+ }
744
+ async function buildUndoPlan(cwd, repo) {
745
+ const info = await getPagesInfo(repo);
746
+ const cname = info?.cname ?? null;
747
+ // Workflow: only the one we write. Hand-written Pages workflows
748
+ // (e.g. docs.yml) belong to the user — don't touch them.
749
+ const wfPath = join(cwd, ".github", "workflows", WORKFLOW_FILENAME);
750
+ const workflowPath = existsSync(wfPath) ? wfPath : null;
751
+ // CNAME files: scan the spots `writeCnameFile` could have written.
752
+ // Only flag files whose content matches the registered cname so we
753
+ // never delete a CNAME the user wrote for some other purpose.
754
+ const cnamePaths = cname ? findCnameFiles(cwd, cname) : [];
755
+ // Cloudflare records: present only if a cname was registered AND
756
+ // we have a Cloudflare token AND the zone is in this account.
757
+ const cloudflare = { available: false, records: [] };
758
+ if (cname) {
759
+ const dns = await getDnsConfig();
760
+ if (dns?.apiToken) {
761
+ const { baseDomain, subdomain } = parseDomain(cname);
762
+ const recordName = subdomain === "" ? baseDomain : `${subdomain}.${baseDomain}`;
763
+ const api = new CloudflareApi({ token: dns.apiToken });
764
+ const zone = await api.getZoneByName(baseDomain);
765
+ if (zone) {
766
+ const ghUser = await getGitHubUser().catch(() => "");
767
+ const target = ghUser ? `${ghUser}.github.io` : "";
768
+ const all = await api.findRecordsByName(zone.id, recordName);
769
+ // Only delete records that match what hatchkit could plausibly
770
+ // have written: A records pointing at GitHub's Pages IPs, or a
771
+ // CNAME pointing at <user>.github.io. Anything else stays.
772
+ const records = all.filter((r) => (r.type === "A" && GITHUB_APEX_A.includes(r.content)) ||
773
+ (r.type === "CNAME" && target && r.content === target));
774
+ cloudflare.available = true;
775
+ cloudflare.zoneId = zone.id;
776
+ cloudflare.baseDomain = baseDomain;
777
+ cloudflare.records = records.map((r) => ({
778
+ id: r.id,
779
+ type: r.type,
780
+ name: r.name,
781
+ content: r.content,
782
+ }));
783
+ }
784
+ }
785
+ }
786
+ return {
787
+ pagesEnabled: info !== null,
788
+ cname,
789
+ workflowPath,
790
+ cnamePaths,
791
+ cloudflare,
792
+ };
793
+ }
794
+ function isAnythingToUndo(plan) {
795
+ return (plan.pagesEnabled ||
796
+ plan.workflowPath !== null ||
797
+ plan.cnamePaths.length > 0 ||
798
+ plan.cloudflare.records.length > 0);
799
+ }
800
+ function printUndoPlan(plan) {
801
+ console.log(chalk.bold("\n Will undo:\n"));
802
+ if (plan.pagesEnabled) {
803
+ const suffix = plan.cname ? ` (cname: ${plan.cname})` : "";
804
+ console.log(chalk.yellow(` • Disable GitHub Pages${suffix}`));
805
+ }
806
+ for (const rec of plan.cloudflare.records) {
807
+ console.log(chalk.yellow(` • Delete Cloudflare ${rec.type} ${rec.name} → ${rec.content}`));
808
+ }
809
+ if (plan.workflowPath) {
810
+ console.log(chalk.yellow(` • Delete ${relPath(plan.workflowPath)}`));
811
+ }
812
+ for (const p of plan.cnamePaths) {
813
+ console.log(chalk.yellow(` • Delete ${relPath(p)}`));
814
+ }
815
+ if (plan.cname && !plan.cloudflare.available) {
816
+ console.log(chalk.dim(`\n (Cloudflare records for ${plan.cname} can't be auto-deleted — no token / zone not in this account.\n Remove them manually at your DNS provider.)`));
817
+ }
818
+ }
819
+ async function executeUndo(repo, plan) {
820
+ if (plan.pagesEnabled) {
821
+ const res = await exec("gh", ["api", "-X", "DELETE", `repos/${repo.fullName}/pages`], {
822
+ silent: true,
823
+ spinner: "Disabling GitHub Pages...",
824
+ });
825
+ if (res.exitCode !== 0) {
826
+ console.log(chalk.yellow(` ⚠ Couldn't disable Pages: ${res.stderr.trim() || res.stdout.trim()}`));
827
+ }
828
+ }
829
+ if (plan.cloudflare.records.length > 0 && plan.cloudflare.zoneId) {
830
+ const dns = await getDnsConfig();
831
+ if (dns?.apiToken) {
832
+ const api = new CloudflareApi({ token: dns.apiToken });
833
+ for (const rec of plan.cloudflare.records) {
834
+ const result = await api.deleteRecord(plan.cloudflare.zoneId, rec.id);
835
+ const tag = result === "deleted" ? chalk.green("✓") : chalk.dim("—");
836
+ console.log(` ${tag} Cloudflare ${rec.type} ${rec.name} → ${rec.content} (${result})`);
837
+ }
838
+ }
839
+ }
840
+ if (plan.workflowPath) {
841
+ try {
842
+ unlinkSync(plan.workflowPath);
843
+ console.log(chalk.green(` ✓ Removed ${relPath(plan.workflowPath)}`));
844
+ }
845
+ catch (err) {
846
+ console.log(chalk.yellow(` ⚠ Couldn't remove ${relPath(plan.workflowPath)}: ${err.message}`));
847
+ }
848
+ }
849
+ for (const p of plan.cnamePaths) {
850
+ try {
851
+ unlinkSync(p);
852
+ console.log(chalk.green(` ✓ Removed ${relPath(p)}`));
853
+ }
854
+ catch (err) {
855
+ console.log(chalk.yellow(` ⚠ Couldn't remove ${relPath(p)}: ${err.message}`));
856
+ }
857
+ }
858
+ }
859
+ /**
860
+ * Look for `CNAME` files in the places `writeCnameFile` could have put
861
+ * one, in the current working dir and each candidate scan dir. Only
862
+ * returns files whose content matches `expected` (trimmed, case-insensitive)
863
+ * so we never delete an unrelated CNAME file.
864
+ */
865
+ function findCnameFiles(cwd, expected) {
866
+ const target = expected.trim().toLowerCase();
867
+ const out = [];
868
+ const seen = new Set();
869
+ const bases = ["", ...SCAN_DIRS.filter((d) => d !== "")];
870
+ for (const base of bases) {
871
+ const baseAbs = base ? join(cwd, base) : cwd;
872
+ if (base && !existsSync(baseAbs))
873
+ continue;
874
+ for (const sub of ["", "public", "static"]) {
875
+ const subAbs = sub ? join(baseAbs, sub) : baseAbs;
876
+ const candidate = join(subAbs, "CNAME");
877
+ if (seen.has(candidate))
878
+ continue;
879
+ seen.add(candidate);
880
+ if (!existsSync(candidate))
881
+ continue;
882
+ try {
883
+ const content = readFileSync(candidate, "utf8").trim().toLowerCase();
884
+ if (content === target)
885
+ out.push(candidate);
886
+ }
887
+ catch {
888
+ // unreadable — skip
889
+ }
890
+ }
891
+ }
892
+ return out;
893
+ }
894
+ function relPath(p) {
895
+ const cwd = process.cwd();
896
+ return p.startsWith(cwd) ? p.slice(cwd.length + 1) : p;
897
+ }
557
898
  //# sourceMappingURL=pages.js.map