hatchkit 0.1.47 → 0.2.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 (112) hide show
  1. package/dist/adopt.d.ts +61 -1
  2. package/dist/adopt.d.ts.map +1 -1
  3. package/dist/adopt.js +90 -86
  4. package/dist/adopt.js.map +1 -1
  5. package/dist/completion.d.ts.map +1 -1
  6. package/dist/completion.js +19 -1
  7. package/dist/completion.js.map +1 -1
  8. package/dist/config.d.ts +32 -1
  9. package/dist/config.d.ts.map +1 -1
  10. package/dist/config.js +364 -1
  11. package/dist/config.js.map +1 -1
  12. package/dist/deploy/coolify.d.ts +5 -0
  13. package/dist/deploy/coolify.d.ts.map +1 -1
  14. package/dist/deploy/coolify.js +67 -4
  15. package/dist/deploy/coolify.js.map +1 -1
  16. package/dist/deploy/ghcr.d.ts +1 -0
  17. package/dist/deploy/ghcr.d.ts.map +1 -1
  18. package/dist/deploy/ghcr.js +2 -2
  19. package/dist/deploy/ghcr.js.map +1 -1
  20. package/dist/deploy/github.d.ts.map +1 -1
  21. package/dist/deploy/github.js +3 -2
  22. package/dist/deploy/github.js.map +1 -1
  23. package/dist/deploy/rollback.d.ts.map +1 -1
  24. package/dist/deploy/rollback.js +9 -0
  25. package/dist/deploy/rollback.js.map +1 -1
  26. package/dist/dev-setup.d.ts +10 -4
  27. package/dist/dev-setup.d.ts.map +1 -1
  28. package/dist/dev-setup.js +166 -57
  29. package/dist/dev-setup.js.map +1 -1
  30. package/dist/doctor.d.ts.map +1 -1
  31. package/dist/doctor.js +65 -1
  32. package/dist/doctor.js.map +1 -1
  33. package/dist/email/index.js +5 -5
  34. package/dist/email/index.js.map +1 -1
  35. package/dist/email/setup.d.ts +1 -1
  36. package/dist/email/setup.d.ts.map +1 -1
  37. package/dist/email/setup.js +3 -3
  38. package/dist/email/setup.js.map +1 -1
  39. package/dist/explain.d.ts.map +1 -1
  40. package/dist/explain.js +8 -7
  41. package/dist/explain.js.map +1 -1
  42. package/dist/index.js +277 -60
  43. package/dist/index.js.map +1 -1
  44. package/dist/inventory.d.ts +1 -0
  45. package/dist/inventory.d.ts.map +1 -1
  46. package/dist/inventory.js +2 -0
  47. package/dist/inventory.js.map +1 -1
  48. package/dist/onboarding/plan.d.ts +54 -0
  49. package/dist/onboarding/plan.d.ts.map +1 -0
  50. package/dist/onboarding/plan.js +143 -0
  51. package/dist/onboarding/plan.js.map +1 -0
  52. package/dist/onboarding/review.d.ts +27 -0
  53. package/dist/onboarding/review.d.ts.map +1 -0
  54. package/dist/onboarding/review.js +55 -0
  55. package/dist/onboarding/review.js.map +1 -0
  56. package/dist/prompts.d.ts +13 -0
  57. package/dist/prompts.d.ts.map +1 -1
  58. package/dist/prompts.js +107 -89
  59. package/dist/prompts.js.map +1 -1
  60. package/dist/provision/index.d.ts +21 -3
  61. package/dist/provision/index.d.ts.map +1 -1
  62. package/dist/provision/index.js +112 -5
  63. package/dist/provision/index.js.map +1 -1
  64. package/dist/provision/plausible.d.ts +10 -0
  65. package/dist/provision/plausible.d.ts.map +1 -0
  66. package/dist/provision/plausible.js +103 -0
  67. package/dist/provision/plausible.js.map +1 -0
  68. package/dist/provision/search-console.d.ts +17 -0
  69. package/dist/provision/search-console.d.ts.map +1 -0
  70. package/dist/provision/search-console.js +142 -0
  71. package/dist/provision/search-console.js.map +1 -0
  72. package/dist/scaffold/app.d.ts +1 -0
  73. package/dist/scaffold/app.d.ts.map +1 -1
  74. package/dist/scaffold/app.js +4 -1
  75. package/dist/scaffold/app.js.map +1 -1
  76. package/dist/scaffold/infra.js +2 -0
  77. package/dist/scaffold/infra.js.map +1 -1
  78. package/dist/scaffold/manifest.d.ts +4 -2
  79. package/dist/scaffold/manifest.d.ts.map +1 -1
  80. package/dist/scaffold/manifest.js +7 -1
  81. package/dist/scaffold/manifest.js.map +1 -1
  82. package/dist/scaffold/server-add.d.ts +21 -0
  83. package/dist/scaffold/server-add.d.ts.map +1 -0
  84. package/dist/scaffold/server-add.js +273 -0
  85. package/dist/scaffold/server-add.js.map +1 -0
  86. package/dist/scaffold/update.d.ts +1 -0
  87. package/dist/scaffold/update.d.ts.map +1 -1
  88. package/dist/scaffold/update.js +8 -5
  89. package/dist/scaffold/update.js.map +1 -1
  90. package/dist/status.d.ts.map +1 -1
  91. package/dist/status.js +27 -1
  92. package/dist/status.js.map +1 -1
  93. package/dist/templates/base/env.example.hbs +3 -0
  94. package/dist/utils/cloudflare-api.d.ts +5 -0
  95. package/dist/utils/cloudflare-api.d.ts.map +1 -1
  96. package/dist/utils/cloudflare-api.js +19 -0
  97. package/dist/utils/cloudflare-api.js.map +1 -1
  98. package/dist/utils/coolify-api.d.ts +3 -2
  99. package/dist/utils/coolify-api.d.ts.map +1 -1
  100. package/dist/utils/coolify-api.js +19 -5
  101. package/dist/utils/coolify-api.js.map +1 -1
  102. package/dist/utils/flags.d.ts.map +1 -1
  103. package/dist/utils/flags.js +16 -0
  104. package/dist/utils/flags.js.map +1 -1
  105. package/dist/utils/run-ledger.d.ts +3 -0
  106. package/dist/utils/run-ledger.d.ts.map +1 -1
  107. package/dist/utils/run-ledger.js.map +1 -1
  108. package/dist/utils/secrets.d.ts +5 -0
  109. package/dist/utils/secrets.d.ts.map +1 -1
  110. package/dist/utils/secrets.js +5 -0
  111. package/dist/utils/secrets.js.map +1 -1
  112. package/package.json +24 -3
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAEA,OAAO,IAAI,MAAM,MAAM,CAAC;AAaxB;;;;;;;;;;;;8DAY8D;AAC9D,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAChB,MAAM,GAAG,IAAI,CAaf;AAeD;;;;;;;;;;;gBAWgB;AAChB,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CA0EvE;AAmBD;;sDAEsD;AACtD,wBAAsB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAkBxE;AAMD,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,YAAY,GAAG,cAAc,CAAC;IACtC,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAID,MAAM,WAAW,WAAY,SAAQ,cAAc;IACjD,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAChE;AAED,MAAM,WAAW,WAAY,SAAQ,cAAc;CAAG;AAEtD,MAAM,WAAW,OAAQ,SAAQ,cAAc;IAC7C;;;;yDAIqD;IACrD,QAAQ,EAAE,YAAY,CAAC;IACvB;;;qEAGiE;IACjE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;+EAE2E;IAC3E,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,cAAe,SAAQ,cAAc;IACpD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,eAAgB,SAAQ,cAAc;IACrD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,aAAc,SAAQ,cAAc;IACnD,GAAG,EAAE,MAAM,CAAC;IACZ,uEAAuE;IACvE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;6BACyB;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,aAAc,SAAQ,cAAc;IACnD,iEAAiE;IACjE,GAAG,EAAE,MAAM,CAAC;IACZ;;;sDAGkD;IAClD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;2DACuD;IACvD,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,UAAW,SAAQ,cAAc;IAChD,mFAAmF;IACnF,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,UAAW,SAAQ,cAAc;IAChD;;;mEAG+D;IAC/D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;6CAEyC;IACzC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,QAAS,SAAQ,cAAc;IAC9C;;;;;oEAKgE;IAChE,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAKD,MAAM,WAAW,aAAc,SAAQ,WAAW;IAChD,KAAK,EAAE,MAAM,CAAC;CACf;AACD,MAAM,WAAW,aAAc,SAAQ,WAAW;IAChD,KAAK,EAAE,MAAM,CAAC;CACf;AACD,MAAM,WAAW,SAAU,SAAQ,OAAO;IACxC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;2EACuE;IACvE,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AACD,MAAM,WAAW,gBAAiB,SAAQ,cAAc;IACtD,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AACD,MAAM,WAAW,iBAAkB,SAAQ,eAAe;IACxD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,eAAgB,SAAQ,aAAa;IACpD,KAAK,EAAE,MAAM,CAAC;CACf;AACD,MAAM,WAAW,eAAgB,SAAQ,aAAa;IACpD,oDAAoD;IACpD,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AACD,MAAM,WAAW,YAAa,SAAQ,UAAU;IAC9C,MAAM,EAAE,MAAM,CAAC;CAChB;AACD,MAAM,WAAW,YAAa,SAAQ,UAAU;IAC9C;;kCAE8B;IAC9B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;qBAEiB;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AACD,MAAM,WAAW,UAAW,SAAQ,QAAQ;IAC1C;mEAC+D;IAC/D,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE;QACT,MAAM,EAAE,cAAc,CAAC;QACvB,OAAO,CAAC,EAAE,WAAW,CAAC;QACtB,OAAO,CAAC,EAAE,WAAW,CAAC;QACtB,GAAG,CAAC,EAAE,OAAO,CAAC;QACd,EAAE,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;QACnC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;QACrC,SAAS,CAAC,EAAE,aAAa,CAAC;QAC1B,SAAS,CAAC,EAAE,aAAa,CAAC;QAC1B,MAAM,CAAC,EAAE,UAAU,CAAC;QACpB,MAAM,CAAC,EAAE,UAAU,CAAC;QACpB,IAAI,CAAC,EAAE,QAAQ,CAAC;KACjB,CAAC;IACF,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAC3C;yEACqE;IACrE,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB;;sDAEkD;IAClD,QAAQ,CAAC,EAAE;QACT;;uDAE+C;QAC/C,eAAe,CAAC,EAAE,MAAM,CAAC;KAC1B,CAAC;CACH;AAyDD;;eAEe;AACf,wBAAgB,QAAQ,oBAEvB;AAED,wBAAgB,SAAS,IAAI,SAAS,CAErC;AAED,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED;qDACqD;AACrD,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAGjD;AA4BD,wBAAsB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAqBlD;AAMD,wBAAsB,aAAa,IAAI,OAAO,CAAC,aAAa,CAAC,CAmE5D;AAED;gEACgE;AAChE,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAOtE;AAMD,wBAAsB,aAAa,IAAI,OAAO,CAAC,aAAa,CAAC,CAkC5D;AAED,wBAAsB,eAAe,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAG9D;AAED,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAMtE;AAMD,wBAAsB,SAAS,IAAI,OAAO,CAAC,SAAS,CAAC,CA0FpD;AAMD;;4CAE4C;AAC5C,wBAAgB,yBAAyB,IAAI,MAAM,GAAG,IAAI,CAGzD;AAED,4CAA4C;AAC5C,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAG7D;AAED;;mEAEmE;AACnE,wBAAsB,4BAA4B,IAAI,OAAO,CAAC,MAAM,CAAC,CAmBpE;AAED;;;;;;;;;GASG;AACH,wBAAsB,+BAA+B,IAAI,OAAO,CAAC;IAC/D,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC,CAeD;AAED,wBAAsB,YAAY,IAAI,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAgB9D;AAMD,wBAAsB,QAAQ,CAAC,QAAQ,EAAE,SAAS,GAAG,KAAK,GAAG,IAAI,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA8K5F;AAED,wBAAsB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAqBpF;AAMD,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,OAAO,GAAG,QAAQ,GAAG,IAAI,GAAG,WAAW,GAChD,OAAO,CAAC,iBAAiB,CAAC,CA6C5B;AAED,wBAAsB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAMtF;AAMD,wBAAgB,YAAY,IAAI,MAAM,EAAE,CAEvC;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,CAOlD;AAED;8DAC8D;AAC9D,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,CAIrD;AAMD,wBAAgB,aAAa,IAAI,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAE9D;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,cAAc,GAAG,IAAI,CAE3E;AAMD,wBAAsB,eAAe,IAAI,OAAO,CAAC,eAAe,CAAC,CA+ChE;AAED,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAM1E;AAMD,wBAAsB,eAAe,IAAI,OAAO,CAAC,eAAe,CAAC,CAqFhE;AAED,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAO1E;AAMD,wBAAsB,YAAY,IAAI,OAAO,CAAC,YAAY,CAAC,CAgC1D;AAED,wBAAsB,eAAe,IAAI,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAMpE;AAwGD,wBAAsB,YAAY,IAAI,OAAO,CAAC,YAAY,CAAC,CAwF1D;AAED,wBAAsB,eAAe,IAAI,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAOpE;AAyBD,wBAAsB,UAAU,IAAI,OAAO,CAAC,UAAU,CAAC,CAyDtD;AAED,wBAAsB,aAAa,IAAI,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAMhE;AAMD,wBAAsB,UAAU,IAAI,OAAO,CAAC,OAAO,CAAC,CAGnD;AA0BD,KAAK,sBAAsB,GACvB,SAAS,GACT,SAAS,GACT,KAAK,GACL,WAAW,GACX,WAAW,GACX,QAAQ,GACR,QAAQ,GACR,MAAM,GACN,MAAM,SAAS,GAAG,KAAK,GAAG,IAAI,EAAE,GAChC,OAAO,OAAO,GAAG,QAAQ,GAAG,IAAI,GAAG,WAAW,EAAE,CAAC;AAErD;;2DAE2D;AAC3D,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,sBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC,CAmErF;AAsLD,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAuEnD"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
package/dist/config.js CHANGED
@@ -1,9 +1,12 @@
1
+ import { createHash, randomBytes } from "node:crypto";
2
+ import { createServer } from "node:http";
1
3
  import { Separator, confirm, input, password, select } from "@inquirer/prompts";
2
4
  import chalk from "chalk";
3
5
  import Conf from "conf";
4
6
  import ora from "ora";
5
7
  import { verifyCoolify } from "./utils/coolify-api.js";
6
8
  import { execOk } from "./utils/exec.js";
9
+ import { pickPort } from "./utils/ports.js";
7
10
  import { SECRET_KEYS, clearAllSecrets, deleteSecret, getSecret, setSecret, } from "./utils/secrets.js";
8
11
  import { validateRequired, validateUrl } from "./utils/validate.js";
9
12
  /** Sanity-check an S3 access/secret pair against shape rules. Returns
@@ -925,6 +928,55 @@ export async function getOpenpanelConfig() {
925
928
  return { ...meta, rootClientId, rootClientSecret };
926
929
  }
927
930
  // ---------------------------------------------------------------------------
931
+ // Provider: Plausible (privacy-friendly web analytics)
932
+ // ---------------------------------------------------------------------------
933
+ export async function ensurePlausible() {
934
+ const existing = store.get("providers.plausible");
935
+ const existingKey = await getSecret(SECRET_KEYS.plausibleApiKey);
936
+ if (existing?.status === "configured" && existingKey) {
937
+ return { ...existing, apiKey: existingKey };
938
+ }
939
+ console.log(chalk.yellow("\n Plausible is not configured yet. Let's set it up."));
940
+ const url = (await input({
941
+ message: "Plausible base URL:",
942
+ default: existing?.url ?? "https://plausible.io",
943
+ validate: (v) => validateUrl(v.trim()),
944
+ }))
945
+ .trim()
946
+ .replace(/\/$/, "");
947
+ tokenHint(`${url}/settings`, "Sites API key (can list/create/delete sites; Plausible Cloud requires a Sites API-enabled plan)");
948
+ const apiKey = await confirmPastedSecret("Plausible Sites API key");
949
+ const teamId = (await input({
950
+ message: "Plausible team id (optional):",
951
+ default: existing?.teamId ?? "",
952
+ })).trim();
953
+ const timezone = (await input({
954
+ message: "Default site timezone:",
955
+ default: existing?.timezone ?? "Etc/UTC",
956
+ validate: validateRequired,
957
+ })).trim();
958
+ const meta = {
959
+ status: "configured",
960
+ url,
961
+ teamId: teamId || undefined,
962
+ timezone,
963
+ lastVerified: new Date().toISOString(),
964
+ };
965
+ store.set("providers.plausible", meta);
966
+ await setSecret(SECRET_KEYS.plausibleApiKey, apiKey);
967
+ console.log(chalk.green(" ✓ Plausible configured"));
968
+ return { ...meta, apiKey };
969
+ }
970
+ export async function getPlausibleConfig() {
971
+ const meta = store.get("providers.plausible");
972
+ if (!meta || meta.status !== "configured")
973
+ return null;
974
+ const apiKey = await getSecret(SECRET_KEYS.plausibleApiKey);
975
+ if (!apiKey)
976
+ return null;
977
+ return { ...meta, apiKey };
978
+ }
979
+ // ---------------------------------------------------------------------------
928
980
  // Provider: Resend (transactional email SaaS)
929
981
  // ---------------------------------------------------------------------------
930
982
  export async function ensureResend() {
@@ -968,6 +1020,279 @@ export async function getResendConfig() {
968
1020
  return { ...meta, apiKey };
969
1021
  }
970
1022
  // ---------------------------------------------------------------------------
1023
+ // Provider: Google Search Console
1024
+ // ---------------------------------------------------------------------------
1025
+ const GOOGLE_SEARCH_CONSOLE_SCOPES = [
1026
+ "https://www.googleapis.com/auth/webmasters",
1027
+ "https://www.googleapis.com/auth/siteverification.verify_only",
1028
+ ];
1029
+ // Public Desktop OAuth client id for Hatchkit's own Google Cloud project.
1030
+ // Desktop/installed clients are public clients, so this value is safe to ship.
1031
+ // Until the Hatchkit project is verified, dev builds can set
1032
+ // HATCHKIT_GOOGLE_SEARCH_CONSOLE_CLIENT_ID to exercise the packaged PKCE path.
1033
+ const PACKAGED_GOOGLE_SEARCH_CONSOLE_CLIENT_ID = "932614455438-s0ih891al5pkeo4aeafekf01t6pbqd21.apps.googleusercontent.com";
1034
+ function hatchkitGoogleSearchConsoleClientId() {
1035
+ const configured = process.env.HATCHKIT_GOOGLE_SEARCH_CONSOLE_CLIENT_ID?.trim() ||
1036
+ PACKAGED_GOOGLE_SEARCH_CONSOLE_CLIENT_ID.trim();
1037
+ return configured || null;
1038
+ }
1039
+ const GOOGLE_SEARCH_CONSOLE_SCOPE_REQUIREMENTS = [
1040
+ {
1041
+ label: "Search Console read/write",
1042
+ scopes: ["https://www.googleapis.com/auth/webmasters"],
1043
+ },
1044
+ {
1045
+ label: "Site Verification verify-only",
1046
+ scopes: [
1047
+ "https://www.googleapis.com/auth/siteverification.verify_only",
1048
+ "https://www.googleapis.com/auth/siteverification",
1049
+ ],
1050
+ },
1051
+ ];
1052
+ function assertGoogleSearchConsoleScopes(scopes) {
1053
+ const granted = new Set(scopes);
1054
+ const missing = GOOGLE_SEARCH_CONSOLE_SCOPE_REQUIREMENTS.filter((req) => !req.scopes.some((scope) => granted.has(scope)));
1055
+ if (missing.length === 0)
1056
+ return;
1057
+ throw new Error("Google OAuth did not grant every scope Hatchkit needs. " +
1058
+ `Missing: ${missing.map((m) => m.label).join(", ")}. ` +
1059
+ "Re-run setup and approve both Search Console and Site Verification access.");
1060
+ }
1061
+ function base64Url(input) {
1062
+ return input.toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
1063
+ }
1064
+ function createPkcePair() {
1065
+ const verifier = base64Url(randomBytes(64));
1066
+ const challenge = base64Url(createHash("sha256").update(verifier).digest());
1067
+ return { verifier, challenge };
1068
+ }
1069
+ async function exchangeGoogleCode(args) {
1070
+ const body = new URLSearchParams({
1071
+ client_id: args.clientId,
1072
+ code: args.code,
1073
+ grant_type: "authorization_code",
1074
+ redirect_uri: args.redirectUri,
1075
+ });
1076
+ if (args.clientSecret)
1077
+ body.set("client_secret", args.clientSecret);
1078
+ if (args.codeVerifier)
1079
+ body.set("code_verifier", args.codeVerifier);
1080
+ const res = await fetch("https://oauth2.googleapis.com/token", {
1081
+ method: "POST",
1082
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
1083
+ body,
1084
+ });
1085
+ const json = (await res.json().catch(() => null));
1086
+ if (!res.ok || !json?.access_token) {
1087
+ const msg = json?.error_description ?? json?.error ?? `HTTP ${res.status}`;
1088
+ throw new Error(`Google OAuth token exchange failed: ${msg}`);
1089
+ }
1090
+ return {
1091
+ access_token: json.access_token,
1092
+ refresh_token: json.refresh_token,
1093
+ scope: json.scope,
1094
+ };
1095
+ }
1096
+ async function runGoogleOAuthLoopback(args) {
1097
+ const port = await pickPort(49152, 65535, new Set());
1098
+ const state = randomBytes(18).toString("hex");
1099
+ const pkce = args.clientSecret ? null : createPkcePair();
1100
+ const redirectUri = `http://127.0.0.1:${port}/oauth/google/callback`;
1101
+ let settled = false;
1102
+ let resolveCode = () => { };
1103
+ let rejectCode = () => { };
1104
+ const codePromise = new Promise((resolve, reject) => {
1105
+ resolveCode = resolve;
1106
+ rejectCode = reject;
1107
+ });
1108
+ const server = createServer((req, res) => {
1109
+ const url = new URL(req.url ?? "/", redirectUri);
1110
+ if (url.pathname !== "/oauth/google/callback") {
1111
+ res.writeHead(404, { "Content-Type": "text/plain" });
1112
+ res.end("Not found");
1113
+ return;
1114
+ }
1115
+ const gotState = url.searchParams.get("state");
1116
+ const code = url.searchParams.get("code");
1117
+ const error = url.searchParams.get("error");
1118
+ if (gotState !== state) {
1119
+ res.writeHead(400, { "Content-Type": "text/plain" });
1120
+ res.end("State mismatch. Return to the terminal and retry setup.");
1121
+ if (!settled) {
1122
+ settled = true;
1123
+ rejectCode(new Error("Google OAuth state mismatch."));
1124
+ }
1125
+ return;
1126
+ }
1127
+ if (error || !code) {
1128
+ res.writeHead(400, { "Content-Type": "text/plain" });
1129
+ res.end("Google authorization failed. Return to the terminal and retry setup.");
1130
+ if (!settled) {
1131
+ settled = true;
1132
+ rejectCode(new Error(`Google OAuth failed: ${error ?? "missing code"}`));
1133
+ }
1134
+ return;
1135
+ }
1136
+ res.writeHead(200, { "Content-Type": "text/plain" });
1137
+ res.end("Google Search Console authorization complete. You can close this tab.");
1138
+ if (!settled) {
1139
+ settled = true;
1140
+ resolveCode(code);
1141
+ }
1142
+ });
1143
+ await new Promise((resolve, reject) => {
1144
+ server.once("error", reject);
1145
+ server.listen(port, "127.0.0.1", () => resolve());
1146
+ });
1147
+ const authUrl = new URL("https://accounts.google.com/o/oauth2/v2/auth");
1148
+ authUrl.searchParams.set("client_id", args.clientId);
1149
+ authUrl.searchParams.set("redirect_uri", redirectUri);
1150
+ authUrl.searchParams.set("response_type", "code");
1151
+ authUrl.searchParams.set("scope", GOOGLE_SEARCH_CONSOLE_SCOPES.join(" "));
1152
+ authUrl.searchParams.set("access_type", "offline");
1153
+ authUrl.searchParams.set("prompt", "consent");
1154
+ authUrl.searchParams.set("state", state);
1155
+ if (pkce) {
1156
+ authUrl.searchParams.set("code_challenge", pkce.challenge);
1157
+ authUrl.searchParams.set("code_challenge_method", "S256");
1158
+ }
1159
+ console.log(chalk.dim("\n Open this URL in your browser, approve access, then return here:"));
1160
+ console.log(chalk.cyan(` ${authUrl.toString()}\n`));
1161
+ try {
1162
+ const code = await codePromise;
1163
+ const token = await exchangeGoogleCode({
1164
+ clientId: args.clientId,
1165
+ clientSecret: args.clientSecret,
1166
+ code,
1167
+ redirectUri,
1168
+ codeVerifier: pkce?.verifier,
1169
+ });
1170
+ if (!token.refresh_token) {
1171
+ throw new Error("Google did not return a refresh token. Re-run setup and keep `prompt=consent`, or revoke the app at https://myaccount.google.com/permissions and try again.");
1172
+ }
1173
+ const scopes = token.scope?.split(/\s+/).filter(Boolean) ?? GOOGLE_SEARCH_CONSOLE_SCOPES;
1174
+ assertGoogleSearchConsoleScopes(scopes);
1175
+ return {
1176
+ refreshToken: token.refresh_token,
1177
+ scopes,
1178
+ };
1179
+ }
1180
+ finally {
1181
+ await new Promise((resolve) => server.close(() => resolve()));
1182
+ }
1183
+ }
1184
+ export async function refreshGoogleSearchConsoleAccessToken(cfg) {
1185
+ const body = new URLSearchParams({
1186
+ client_id: cfg.clientId,
1187
+ refresh_token: cfg.refreshToken,
1188
+ grant_type: "refresh_token",
1189
+ });
1190
+ if (cfg.clientSecret)
1191
+ body.set("client_secret", cfg.clientSecret);
1192
+ const res = await fetch("https://oauth2.googleapis.com/token", {
1193
+ method: "POST",
1194
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
1195
+ body,
1196
+ });
1197
+ const json = (await res.json().catch(() => null));
1198
+ if (!res.ok || !json?.access_token) {
1199
+ const msg = json?.error_description ?? json?.error ?? `HTTP ${res.status}`;
1200
+ throw new Error(`Google refresh token failed: ${msg}`);
1201
+ }
1202
+ return json.access_token;
1203
+ }
1204
+ export async function ensureGoogleSearchConsole() {
1205
+ const existing = store.get("providers.googleSearchConsole");
1206
+ const existingClientId = await getSecret(SECRET_KEYS.googleSearchConsoleClientId);
1207
+ const existingClientSecret = await getSecret(SECRET_KEYS.googleSearchConsoleClientSecret);
1208
+ const existingRefreshToken = await getSecret(SECRET_KEYS.googleSearchConsoleRefreshToken);
1209
+ const hatchkitClientId = hatchkitGoogleSearchConsoleClientId();
1210
+ const existingMode = existing?.oauthMode ?? (existingClientSecret ? "byo-client" : "hatchkit-pkce");
1211
+ if (existing?.status === "configured" && existingRefreshToken) {
1212
+ if (existingMode === "hatchkit-pkce" && hatchkitClientId) {
1213
+ return {
1214
+ ...existing,
1215
+ oauthMode: "hatchkit-pkce",
1216
+ clientId: hatchkitClientId,
1217
+ refreshToken: existingRefreshToken,
1218
+ };
1219
+ }
1220
+ if (existingClientId && existingClientSecret) {
1221
+ return {
1222
+ ...existing,
1223
+ oauthMode: "byo-client",
1224
+ clientId: existingClientId,
1225
+ clientSecret: existingClientSecret,
1226
+ refreshToken: existingRefreshToken,
1227
+ };
1228
+ }
1229
+ }
1230
+ console.log(chalk.yellow("\n Google Search Console is not configured yet. Let's set it up."));
1231
+ console.log(chalk.dim(" Hatchkit uses Google OAuth for Search Console and Site Verification.\n" +
1232
+ " You sign in with your own Google account; Hatchkit stores only that\n" +
1233
+ " account's refresh token in your OS keychain on this machine.\n"));
1234
+ let clientId;
1235
+ let clientSecret;
1236
+ let oauthMode;
1237
+ if (hatchkitClientId) {
1238
+ clientId = hatchkitClientId;
1239
+ oauthMode = "hatchkit-pkce";
1240
+ console.log(chalk.dim(" Using Hatchkit's shipped Google OAuth client with PKCE. No Google Cloud setup or client secret is needed."));
1241
+ }
1242
+ else {
1243
+ oauthMode = "byo-client";
1244
+ console.log(chalk.dim(" No packaged Hatchkit Google OAuth client id is configured in this build.\n" +
1245
+ " Falling back to the legacy BYO Google Cloud OAuth client setup.\n"));
1246
+ tokenHint("https://console.cloud.google.com/apis/credentials", "OAuth client (Desktop app) with Search Console API + Site Verification API enabled", `Scopes: ${GOOGLE_SEARCH_CONSOLE_SCOPES.join(", ")}`);
1247
+ clientId = (await input({
1248
+ message: "Google OAuth client ID:",
1249
+ default: existingClientId ?? undefined,
1250
+ validate: validateRequired,
1251
+ })).trim();
1252
+ clientSecret = await confirmPastedSecret("Google OAuth client secret");
1253
+ }
1254
+ const oauth = await runGoogleOAuthLoopback({ clientId, clientSecret });
1255
+ const meta = {
1256
+ status: "configured",
1257
+ scopes: oauth.scopes,
1258
+ oauthMode,
1259
+ lastVerified: new Date().toISOString(),
1260
+ };
1261
+ store.set("providers.googleSearchConsole", meta);
1262
+ if (oauthMode === "byo-client") {
1263
+ await setSecret(SECRET_KEYS.googleSearchConsoleClientId, clientId);
1264
+ if (clientSecret)
1265
+ await setSecret(SECRET_KEYS.googleSearchConsoleClientSecret, clientSecret);
1266
+ }
1267
+ else {
1268
+ await deleteSecret(SECRET_KEYS.googleSearchConsoleClientId);
1269
+ await deleteSecret(SECRET_KEYS.googleSearchConsoleClientSecret);
1270
+ }
1271
+ await setSecret(SECRET_KEYS.googleSearchConsoleRefreshToken, oauth.refreshToken);
1272
+ console.log(chalk.green(" ✓ Google Search Console configured"));
1273
+ return { ...meta, clientId, clientSecret, refreshToken: oauth.refreshToken };
1274
+ }
1275
+ export async function getGoogleSearchConsoleConfig() {
1276
+ const meta = store.get("providers.googleSearchConsole");
1277
+ if (!meta || meta.status !== "configured")
1278
+ return null;
1279
+ const oauthMode = meta.oauthMode ?? "byo-client";
1280
+ const clientId = await getSecret(SECRET_KEYS.googleSearchConsoleClientId);
1281
+ const clientSecret = await getSecret(SECRET_KEYS.googleSearchConsoleClientSecret);
1282
+ const refreshToken = await getSecret(SECRET_KEYS.googleSearchConsoleRefreshToken);
1283
+ if (!refreshToken)
1284
+ return null;
1285
+ if (oauthMode === "hatchkit-pkce") {
1286
+ const hatchkitClientId = hatchkitGoogleSearchConsoleClientId();
1287
+ if (!hatchkitClientId)
1288
+ return null;
1289
+ return { ...meta, oauthMode, clientId: hatchkitClientId, refreshToken };
1290
+ }
1291
+ if (!clientId || !clientSecret)
1292
+ return null;
1293
+ return { ...meta, oauthMode: "byo-client", clientId, clientSecret, refreshToken };
1294
+ }
1295
+ // ---------------------------------------------------------------------------
971
1296
  // Provider: Stripe (payments)
972
1297
  // ---------------------------------------------------------------------------
973
1298
  //
@@ -1250,10 +1575,22 @@ export async function reconfigureProvider(name) {
1250
1575
  ]);
1251
1576
  await ensureOpenpanel();
1252
1577
  }
1578
+ else if (name === "plausible") {
1579
+ await wipeProvider("providers.plausible", [SECRET_KEYS.plausibleApiKey]);
1580
+ await ensurePlausible();
1581
+ }
1253
1582
  else if (name === "resend") {
1254
1583
  await wipeProvider("providers.resend", [SECRET_KEYS.resendApiKey]);
1255
1584
  await ensureResend();
1256
1585
  }
1586
+ else if (name === "search-console") {
1587
+ await wipeProvider("providers.googleSearchConsole", [
1588
+ SECRET_KEYS.googleSearchConsoleClientId,
1589
+ SECRET_KEYS.googleSearchConsoleClientSecret,
1590
+ SECRET_KEYS.googleSearchConsoleRefreshToken,
1591
+ ]);
1592
+ await ensureGoogleSearchConsole();
1593
+ }
1257
1594
  else if (name === "stripe") {
1258
1595
  // NB: per-project Stripe entries (`stripe:project:<name>:*`) are
1259
1596
  // intentionally NOT swept here — those belong to individual scaffolded
@@ -1397,6 +1734,15 @@ function buildSetupGroups() {
1397
1734
  },
1398
1735
  run: () => reconfigureProvider("openpanel"),
1399
1736
  },
1737
+ {
1738
+ key: "plausible",
1739
+ label: "Plausible (web analytics)",
1740
+ status: () => {
1741
+ const m = store.get("providers.plausible");
1742
+ return { configured: m?.status === "configured", summary: m?.url };
1743
+ },
1744
+ run: () => reconfigureProvider("plausible"),
1745
+ },
1400
1746
  {
1401
1747
  key: "resend",
1402
1748
  label: "Resend (transactional email)",
@@ -1406,6 +1752,23 @@ function buildSetupGroups() {
1406
1752
  },
1407
1753
  run: () => reconfigureProvider("resend"),
1408
1754
  },
1755
+ {
1756
+ key: "search-console",
1757
+ label: "Google Search Console",
1758
+ status: () => {
1759
+ const m = store.get("providers.googleSearchConsole");
1760
+ return {
1761
+ configured: m?.status === "configured",
1762
+ summary: [
1763
+ m?.oauthMode === "hatchkit-pkce" ? "Hatchkit OAuth" : m ? "BYO OAuth" : null,
1764
+ m?.scopes?.length ? `${m.scopes.length} scopes` : null,
1765
+ ]
1766
+ .filter(Boolean)
1767
+ .join(", "),
1768
+ };
1769
+ },
1770
+ run: () => reconfigureProvider("search-console"),
1771
+ },
1409
1772
  {
1410
1773
  key: "defaultForwardingEmail",
1411
1774
  label: "Default forwarding email",
@@ -1513,7 +1876,7 @@ export async function runOnboarding() {
1513
1876
  console.log();
1514
1877
  }
1515
1878
  // Summary — show both what's configured and what's still missing so
1516
- // the user notices optional-but-important steps (GlitchTip / OpenPanel
1879
+ // the user notices optional-but-important steps (GlitchTip / OpenPanel / Plausible
1517
1880
  // / Resend) they may have skipped.
1518
1881
  const configured = allSteps.filter((s) => s.status().configured);
1519
1882
  const unconfigured = allSteps.filter((s) => !s.status().configured);