hatchkit 0.1.1 → 0.1.3

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 (82) hide show
  1. package/dist/completion.d.ts +2 -0
  2. package/dist/completion.d.ts.map +1 -0
  3. package/dist/completion.js +207 -0
  4. package/dist/completion.js.map +1 -0
  5. package/dist/config.d.ts +33 -1
  6. package/dist/config.d.ts.map +1 -1
  7. package/dist/config.js +455 -117
  8. package/dist/config.js.map +1 -1
  9. package/dist/deploy/keys.d.ts +6 -2
  10. package/dist/deploy/keys.d.ts.map +1 -1
  11. package/dist/deploy/keys.js +16 -2
  12. package/dist/deploy/keys.js.map +1 -1
  13. package/dist/deploy/pages.d.ts +2 -0
  14. package/dist/deploy/pages.d.ts.map +1 -0
  15. package/dist/deploy/pages.js +537 -0
  16. package/dist/deploy/pages.js.map +1 -0
  17. package/dist/deploy/rename-domain.d.ts +55 -0
  18. package/dist/deploy/rename-domain.d.ts.map +1 -0
  19. package/dist/deploy/rename-domain.js +290 -0
  20. package/dist/deploy/rename-domain.js.map +1 -0
  21. package/dist/deploy/terraform.d.ts.map +1 -1
  22. package/dist/deploy/terraform.js +90 -0
  23. package/dist/deploy/terraform.js.map +1 -1
  24. package/dist/dns.d.ts +7 -0
  25. package/dist/dns.d.ts.map +1 -0
  26. package/dist/dns.js +124 -0
  27. package/dist/dns.js.map +1 -0
  28. package/dist/doctor.d.ts +13 -0
  29. package/dist/doctor.d.ts.map +1 -0
  30. package/dist/doctor.js +368 -0
  31. package/dist/doctor.js.map +1 -0
  32. package/dist/explain.d.ts +4 -0
  33. package/dist/explain.d.ts.map +1 -0
  34. package/dist/explain.js +173 -0
  35. package/dist/explain.js.map +1 -0
  36. package/dist/index.js +504 -66
  37. package/dist/index.js.map +1 -1
  38. package/dist/provision/glitchtip.d.ts +3 -0
  39. package/dist/provision/glitchtip.d.ts.map +1 -1
  40. package/dist/provision/glitchtip.js +18 -0
  41. package/dist/provision/glitchtip.js.map +1 -1
  42. package/dist/provision/index.d.ts +26 -0
  43. package/dist/provision/index.d.ts.map +1 -1
  44. package/dist/provision/index.js +435 -60
  45. package/dist/provision/index.js.map +1 -1
  46. package/dist/provision/openpanel.d.ts +7 -0
  47. package/dist/provision/openpanel.d.ts.map +1 -1
  48. package/dist/provision/openpanel.js +113 -48
  49. package/dist/provision/openpanel.js.map +1 -1
  50. package/dist/provision/resend.d.ts +23 -1
  51. package/dist/provision/resend.d.ts.map +1 -1
  52. package/dist/provision/resend.js +62 -1
  53. package/dist/provision/resend.js.map +1 -1
  54. package/dist/provision/write-env.d.ts +31 -0
  55. package/dist/provision/write-env.d.ts.map +1 -0
  56. package/dist/provision/write-env.js +94 -0
  57. package/dist/provision/write-env.js.map +1 -0
  58. package/dist/scaffold/infra.d.ts.map +1 -1
  59. package/dist/scaffold/infra.js +18 -1
  60. package/dist/scaffold/infra.js.map +1 -1
  61. package/dist/status.d.ts +30 -0
  62. package/dist/status.d.ts.map +1 -0
  63. package/dist/status.js +169 -0
  64. package/dist/status.js.map +1 -0
  65. package/dist/templates/addons/analytics/sentry.ts.hbs +6 -0
  66. package/dist/utils/cloudflare-api.d.ts +30 -0
  67. package/dist/utils/cloudflare-api.d.ts.map +1 -0
  68. package/dist/utils/cloudflare-api.js +85 -0
  69. package/dist/utils/cloudflare-api.js.map +1 -0
  70. package/dist/utils/coolify-api.d.ts +3 -1
  71. package/dist/utils/coolify-api.d.ts.map +1 -1
  72. package/dist/utils/coolify-api.js +38 -4
  73. package/dist/utils/coolify-api.js.map +1 -1
  74. package/dist/utils/inwx-api.d.ts +36 -0
  75. package/dist/utils/inwx-api.d.ts.map +1 -0
  76. package/dist/utils/inwx-api.js +105 -0
  77. package/dist/utils/inwx-api.js.map +1 -0
  78. package/dist/utils/secrets.d.ts +8 -1
  79. package/dist/utils/secrets.d.ts.map +1 -1
  80. package/dist/utils/secrets.js +8 -1
  81. package/dist/utils/secrets.js.map +1 -1
  82. package/package.json +2 -2
package/dist/status.js ADDED
@@ -0,0 +1,169 @@
1
+ /*
2
+ * Shared status collection — what's configured, what's blocked, what's
3
+ * next. Used by the top-level menu, `hatchkit status`, `hatchkit doctor`,
4
+ * and the MCP server.
5
+ *
6
+ * Returns structured data (no chalk, no side-effects). The caller picks
7
+ * a renderer (human/json).
8
+ */
9
+ import chalk from "chalk";
10
+ import { getConfig, getConfigPath, getMlServices } from "./config.js";
11
+ import { getCliVersion } from "./utils/version.js";
12
+ export function collectStatus() {
13
+ const config = getConfig();
14
+ const providers = [];
15
+ providers.push({
16
+ key: "github",
17
+ label: "GitHub (gh CLI)",
18
+ configured: config.providers.github.status === "configured",
19
+ configureCommand: "hatchkit setup",
20
+ });
21
+ providers.push({
22
+ key: "coolify",
23
+ label: "Coolify",
24
+ configured: config.providers.coolify?.status === "configured",
25
+ detail: config.providers.coolify?.url,
26
+ configureCommand: "hatchkit config add coolify",
27
+ });
28
+ providers.push({
29
+ key: "hetzner",
30
+ label: "Hetzner Cloud",
31
+ configured: config.providers.hetzner?.status === "configured",
32
+ configureCommand: "hatchkit config add hetzner",
33
+ });
34
+ providers.push({
35
+ key: "dns",
36
+ label: "DNS",
37
+ configured: config.providers.dns?.status === "configured",
38
+ detail: config.providers.dns?.provider,
39
+ configureCommand: "hatchkit config add dns",
40
+ });
41
+ const s3Providers = Object.keys(config.providers.s3);
42
+ providers.push({
43
+ key: "s3",
44
+ label: "S3",
45
+ configured: s3Providers.length > 0,
46
+ detail: s3Providers.length > 0 ? s3Providers.join(", ") : undefined,
47
+ configureCommand: "hatchkit config add s3",
48
+ });
49
+ const gpuProviders = Object.keys(config.providers.gpu);
50
+ providers.push({
51
+ key: "gpu",
52
+ label: "GPU",
53
+ configured: gpuProviders.length > 0,
54
+ detail: gpuProviders.length > 0 ? gpuProviders.join(", ") : undefined,
55
+ configureCommand: "hatchkit config add gpu",
56
+ });
57
+ providers.push({
58
+ key: "glitchtip",
59
+ label: "GlitchTip (errors)",
60
+ configured: !!config.providers.glitchtip && config.providers.glitchtip.status === "configured",
61
+ configureCommand: "hatchkit config add glitchtip",
62
+ });
63
+ providers.push({
64
+ key: "openpanel",
65
+ label: "OpenPanel (analytics)",
66
+ configured: !!config.providers.openpanel && config.providers.openpanel.status === "configured",
67
+ configureCommand: "hatchkit config add openpanel",
68
+ });
69
+ providers.push({
70
+ key: "resend",
71
+ label: "Resend (email)",
72
+ configured: !!config.providers.resend && config.providers.resend.status === "configured",
73
+ configureCommand: "hatchkit config add resend",
74
+ });
75
+ const services = getMlServices();
76
+ const mlServiceList = Object.entries(services).map(([name, entry]) => ({
77
+ name,
78
+ endpoint: entry.endpoint,
79
+ platform: entry.platform,
80
+ }));
81
+ const nextStep = computeNextStep(providers);
82
+ const suggestions = computeSuggestions(providers);
83
+ return {
84
+ version: getCliVersion(),
85
+ configPath: getConfigPath(),
86
+ providers,
87
+ mlServiceCount: mlServiceList.length,
88
+ mlServices: mlServiceList,
89
+ nextStep,
90
+ suggestions,
91
+ };
92
+ }
93
+ function computeNextStep(providers) {
94
+ const required = ["github", "coolify", "hetzner", "dns"];
95
+ const firstMissing = providers.find((p) => required.includes(p.key) && !p.configured);
96
+ if (firstMissing) {
97
+ return `Run \`${firstMissing.configureCommand}\` — ${firstMissing.label} is required for full scaffolds.`;
98
+ }
99
+ return "You're set up. Try `hatchkit create` to scaffold a new project.";
100
+ }
101
+ function computeSuggestions(providers) {
102
+ const out = [];
103
+ const has = (k) => providers.find((p) => p.key === k)?.configured;
104
+ if (!has("github") || !has("coolify") || !has("hetzner") || !has("dns")) {
105
+ out.push({
106
+ command: "hatchkit setup",
107
+ why: "first-time onboarding wires up GitHub + Coolify + Hetzner + DNS at once",
108
+ });
109
+ }
110
+ if (has("coolify") && has("hetzner") && has("dns")) {
111
+ out.push({ command: "hatchkit create", why: "scaffold and (optionally) deploy a new project" });
112
+ }
113
+ out.push({
114
+ command: "hatchkit doctor",
115
+ why: "health-check every configured provider with contextual fix hints",
116
+ });
117
+ out.push({
118
+ command: "hatchkit add <project>",
119
+ why: "add per-project GlitchTip / OpenPanel / Resend clients",
120
+ });
121
+ out.push({
122
+ command: "hatchkit explain",
123
+ why: "one-page mental model of how the pieces fit together",
124
+ });
125
+ return out;
126
+ }
127
+ // ---------------------------------------------------------------------------
128
+ // Renderers
129
+ // ---------------------------------------------------------------------------
130
+ export function renderStatusHuman(s) {
131
+ const lines = [];
132
+ lines.push(chalk.bold(" Provider Status:"));
133
+ lines.push("");
134
+ for (const p of s.providers) {
135
+ const icon = p.configured ? chalk.green("✓") : chalk.dim("·");
136
+ const detail = p.detail ? chalk.dim(` (${p.detail})`) : "";
137
+ const hint = p.configured ? "" : chalk.dim(` — ${p.configureCommand ?? "not configured"}`);
138
+ lines.push(` ${icon} ${p.label.padEnd(24)}${detail}${hint}`);
139
+ }
140
+ lines.push("");
141
+ lines.push(` ML Services: ${s.mlServiceCount > 0 ? chalk.green(`${s.mlServiceCount} registered`) : chalk.dim("none")}`);
142
+ for (const m of s.mlServices) {
143
+ lines.push(chalk.dim(` ${m.name}: ${m.endpoint} (${m.platform})`));
144
+ }
145
+ lines.push("");
146
+ lines.push(` ${chalk.bold("Next:")} ${s.nextStep}`);
147
+ lines.push(chalk.dim(` Config: ${s.configPath}`));
148
+ lines.push("");
149
+ return lines.join("\n");
150
+ }
151
+ export function renderMenu(s) {
152
+ const lines = [];
153
+ const configured = s.providers.filter((p) => p.configured).length;
154
+ const total = s.providers.length;
155
+ lines.push(` ${chalk.bold("Hatchkit")} — scaffold, deploy, and provision full-stack projects`);
156
+ lines.push(` ${chalk.dim(`${configured}/${total} providers configured`)} ${chalk.dim("·")} ${chalk.dim(s.version ? `v${s.version}` : "")}`);
157
+ lines.push("");
158
+ lines.push(` ${chalk.bold("Next:")} ${s.nextStep}`);
159
+ lines.push("");
160
+ lines.push(chalk.bold(" Suggested commands:"));
161
+ for (const sug of s.suggestions) {
162
+ lines.push(` ${chalk.cyan(sug.command.padEnd(28))} ${chalk.dim(sug.why)}`);
163
+ }
164
+ lines.push("");
165
+ lines.push(chalk.dim(" Run `hatchkit help <command>` for detail, or `hatchkit explain` for the mental model."));
166
+ lines.push("");
167
+ return lines.join("\n");
168
+ }
169
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../src/status.ts"],"names":[],"mappings":"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"}
@@ -3,10 +3,16 @@ import type { Express } from "express";
3
3
  import { config } from "../config.js";
4
4
 
5
5
  export function initSentry(app: Express): void {
6
+ // No DSN = no init. `hatchkit add` writes GLITCHTIP_DSN to
7
+ // .env.production by default; dev doesn't get one (dev error noise
8
+ // pollutes real metrics). Pass `--enable-dev-obs` to opt in.
6
9
  if (!config.GLITCHTIP_DSN) return;
7
10
 
8
11
  Sentry.init({
9
12
  dsn: config.GLITCHTIP_DSN,
13
+ // `environment` drives GlitchTip's UI filter. DEPLOY_ENV wins so
14
+ // staging deploys tag correctly even when NODE_ENV is "production".
15
+ environment: process.env.DEPLOY_ENV || process.env.NODE_ENV || "development",
10
16
  integrations: [
11
17
  Sentry.httpIntegration(),
12
18
  Sentry.expressIntegration({ app }),
@@ -0,0 +1,30 @@
1
+ export interface CloudflareZone {
2
+ id: string;
3
+ name: string;
4
+ name_servers: string[];
5
+ status: string;
6
+ }
7
+ export interface CloudflareApiOptions {
8
+ token: string;
9
+ /** Optional: filter to one account. Useful if the token spans multiple. */
10
+ accountId?: string;
11
+ }
12
+ /** Cloudflare REST API client. */
13
+ export declare class CloudflareApi {
14
+ private token;
15
+ private accountId?;
16
+ constructor(options: CloudflareApiOptions);
17
+ private request;
18
+ /** Verify the token. "active" means it works. */
19
+ verifyToken(): Promise<string>;
20
+ /**
21
+ * List all zones accessible with this token, optionally filtered to one
22
+ * account. Paginates through the whole result set (CF caps per_page at
23
+ * 50). Safety valve: hard stop at 20 pages (= 1000 zones) to avoid
24
+ * runaway loops if the API misbehaves.
25
+ */
26
+ listZones(): Promise<CloudflareZone[]>;
27
+ /** Look up a single zone by name. Returns null if not found. */
28
+ getZoneByName(name: string): Promise<CloudflareZone | null>;
29
+ }
30
+ //# sourceMappingURL=cloudflare-api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloudflare-api.d.ts","sourceRoot":"","sources":["../../src/utils/cloudflare-api.ts"],"names":[],"mappings":"AAYA,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,2EAA2E;IAC3E,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAiBD,kCAAkC;AAClC,qBAAa,aAAa;IACxB,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,SAAS,CAAC,CAAS;gBAEf,OAAO,EAAE,oBAAoB;YAK3B,OAAO;IAoBrB,iDAAiD;IAC3C,WAAW,IAAI,OAAO,CAAC,MAAM,CAAC;IAKpC;;;;;OAKG;IACG,SAAS,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;IA2B5C,gEAAgE;IAC1D,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;CAMlE"}
@@ -0,0 +1,85 @@
1
+ // Cloudflare REST API client.
2
+ //
3
+ // Minimal wrapper used by the `hatchkit dns link-to-cloudflare` command
4
+ // to verify a token and list the zones in an account so we can
5
+ // cross-reference them against domains registered at INWX. The DNS record
6
+ // creation itself goes through Terraform (modules/cloudflare-dns) during
7
+ // a normal `hatchkit create` flow — this client is for the standalone
8
+ // migration / reconciliation command.
9
+ //
10
+ // NB: `hatchkit gh-pages` has its own inline Cloudflare DNS helper for
11
+ // record CRUD. That path is separate and doesn't share this class.
12
+ const API_BASE = "https://api.cloudflare.com/client/v4";
13
+ /** Cloudflare REST API client. */
14
+ export class CloudflareApi {
15
+ token;
16
+ accountId;
17
+ constructor(options) {
18
+ this.token = options.token;
19
+ this.accountId = options.accountId;
20
+ }
21
+ async request(method, path, body) {
22
+ const res = await fetch(`${API_BASE}${path}`, {
23
+ method,
24
+ headers: {
25
+ Authorization: `Bearer ${this.token}`,
26
+ "Content-Type": "application/json",
27
+ Accept: "application/json",
28
+ },
29
+ body: body ? JSON.stringify(body) : undefined,
30
+ });
31
+ const json = (await res.json().catch(() => null));
32
+ if (!res.ok || !json || !json.success) {
33
+ const errMsg = json?.errors?.map((e) => `${e.code}: ${e.message}`).join("; ") ?? res.statusText;
34
+ throw new Error(`Cloudflare ${method} ${path} failed: ${errMsg}`);
35
+ }
36
+ return json.result;
37
+ }
38
+ /** Verify the token. "active" means it works. */
39
+ async verifyToken() {
40
+ const data = await this.request("GET", "/user/tokens/verify");
41
+ return data.status;
42
+ }
43
+ /**
44
+ * List all zones accessible with this token, optionally filtered to one
45
+ * account. Paginates through the whole result set (CF caps per_page at
46
+ * 50). Safety valve: hard stop at 20 pages (= 1000 zones) to avoid
47
+ * runaway loops if the API misbehaves.
48
+ */
49
+ async listZones() {
50
+ const all = [];
51
+ let page = 1;
52
+ while (page <= 20) {
53
+ const query = new URLSearchParams({ per_page: "50", page: String(page) });
54
+ if (this.accountId)
55
+ query.set("account.id", this.accountId);
56
+ const path = `/zones?${query.toString()}`;
57
+ const res = await fetch(`${API_BASE}${path}`, {
58
+ headers: {
59
+ Authorization: `Bearer ${this.token}`,
60
+ Accept: "application/json",
61
+ },
62
+ });
63
+ const json = (await res.json());
64
+ if (!res.ok || !json.success) {
65
+ const errMsg = json?.errors?.map((e) => `${e.code}: ${e.message}`).join("; ") ?? res.statusText;
66
+ throw new Error(`Cloudflare GET /zones failed: ${errMsg}`);
67
+ }
68
+ all.push(...json.result);
69
+ const totalPages = json.result_info?.total_pages ?? 1;
70
+ if (page >= totalPages)
71
+ break;
72
+ page += 1;
73
+ }
74
+ return all;
75
+ }
76
+ /** Look up a single zone by name. Returns null if not found. */
77
+ async getZoneByName(name) {
78
+ const query = new URLSearchParams({ name });
79
+ if (this.accountId)
80
+ query.set("account.id", this.accountId);
81
+ const data = await this.request("GET", `/zones?${query.toString()}`);
82
+ return data[0] ?? null;
83
+ }
84
+ }
85
+ //# sourceMappingURL=cloudflare-api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloudflare-api.js","sourceRoot":"","sources":["../../src/utils/cloudflare-api.ts"],"names":[],"mappings":"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"}
@@ -14,7 +14,9 @@ export declare class CoolifyApi {
14
14
  private token;
15
15
  constructor(options: CoolifyApiOptions);
16
16
  private request;
17
- /** Test connection and get Coolify version. */
17
+ /** Test connection and get Coolify version. The endpoint returns a
18
+ * plain-text version string on modern Coolify, but older builds
19
+ * wrap it as `{ version: "..." }` — accept either. */
18
20
  getVersion(): Promise<string>;
19
21
  /** List all servers. */
20
22
  listServers(): Promise<CoolifyServer[]>;
@@ -1 +1 @@
1
- {"version":3,"file":"coolify-api.d.ts","sourceRoot":"","sources":["../../src/utils/coolify-api.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;CACf;AAED,+BAA+B;AAC/B,qBAAa,UAAU;IACrB,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,KAAK,CAAS;gBAEV,OAAO,EAAE,iBAAiB;YAKxB,OAAO;IAqBrB,+CAA+C;IACzC,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC;IAKnC,wBAAwB;IAClB,WAAW,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;IAkB7C,yBAAyB;IACnB,YAAY,IAAI,OAAO,CAAC,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAIlE,4BAA4B;IACtB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAIxE,wEAAwE;IAClE,gBAAgB,IAAI,OAAO,CAAC,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAI9F;mEAC+D;IACzD,SAAS,CACb,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,OAAO,GAAE;QAAE,SAAS,CAAC,EAAE,OAAO,CAAA;KAAO,GACpC,OAAO,CAAC,IAAI,CAAC;CAYjB;AAED,mEAAmE;AACnE,wBAAsB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAG/E"}
1
+ {"version":3,"file":"coolify-api.d.ts","sourceRoot":"","sources":["../../src/utils/coolify-api.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;CACf;AAED,+BAA+B;AAC/B,qBAAa,UAAU;IACrB,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,KAAK,CAAS;gBAEV,OAAO,EAAE,iBAAiB;YAKxB,OAAO;IAiCrB;;2DAEuD;IACjD,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC;IA0BnC,wBAAwB;IAClB,WAAW,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;IAkB7C,yBAAyB;IACnB,YAAY,IAAI,OAAO,CAAC,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAIlE,4BAA4B;IACtB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAIxE,wEAAwE;IAClE,gBAAgB,IAAI,OAAO,CAAC,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAI9F;mEAC+D;IACzD,SAAS,CACb,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,OAAO,GAAE;QAAE,SAAS,CAAC,EAAE,OAAO,CAAA;KAAO,GACpC,OAAO,CAAC,IAAI,CAAC;CAYjB;AAED,mEAAmE;AACnE,wBAAsB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAG/E"}
@@ -20,12 +20,46 @@ export class CoolifyApi {
20
20
  const text = await res.text().catch(() => "");
21
21
  throw new Error(`Coolify API ${method} ${path} failed: ${res.status} ${res.statusText}${text ? ` — ${text}` : ""}`);
22
22
  }
23
- return res.json();
23
+ const text = await res.text();
24
+ try {
25
+ return JSON.parse(text);
26
+ }
27
+ catch {
28
+ const ct = res.headers.get("content-type") ?? "unknown";
29
+ const snippet = text.slice(0, 200).replace(/\s+/g, " ").trim();
30
+ const hint = text.trimStart().startsWith("<")
31
+ ? " (got HTML — token may be invalid or URL points to a login page)"
32
+ : "";
33
+ throw new Error(`Coolify API ${method} ${path}: response is not JSON${hint}\n content-type: ${ct}\n body: ${snippet || "(empty)"}`);
34
+ }
24
35
  }
25
- /** Test connection and get Coolify version. */
36
+ /** Test connection and get Coolify version. The endpoint returns a
37
+ * plain-text version string on modern Coolify, but older builds
38
+ * wrap it as `{ version: "..." }` — accept either. */
26
39
  async getVersion() {
27
- const data = await this.request("GET", "/version");
28
- return data.version;
40
+ const res = await fetch(`${this.url}/api/v1/version`, {
41
+ headers: {
42
+ Authorization: `Bearer ${this.token}`,
43
+ Accept: "application/json, text/plain;q=0.9",
44
+ },
45
+ });
46
+ if (!res.ok) {
47
+ const text = await res.text().catch(() => "");
48
+ throw new Error(`Coolify API GET /version failed: ${res.status} ${res.statusText}${text ? ` — ${text}` : ""}`);
49
+ }
50
+ const text = (await res.text()).trim();
51
+ try {
52
+ const parsed = JSON.parse(text);
53
+ if (typeof parsed === "string")
54
+ return parsed;
55
+ if (parsed && typeof parsed === "object" && typeof parsed.version === "string") {
56
+ return parsed.version;
57
+ }
58
+ }
59
+ catch {
60
+ // Fall through: plain-text version string (e.g. "4.0.0-beta.432")
61
+ }
62
+ return text;
29
63
  }
30
64
  /** List all servers. */
31
65
  async listServers() {
@@ -1 +1 @@
1
- {"version":3,"file":"coolify-api.js","sourceRoot":"","sources":["../../src/utils/coolify-api.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"coolify-api.js","sourceRoot":"","sources":["../../src/utils/coolify-api.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ export interface InwxApiOptions {
2
+ username: string;
3
+ password: string;
4
+ /** Use the OTE sandbox instead of production. Set via INWX_SANDBOX=1. */
5
+ sandbox?: boolean;
6
+ }
7
+ /** INWX JSON-RPC API client. */
8
+ export declare class InwxApi {
9
+ private url;
10
+ private username;
11
+ private password;
12
+ private cookie;
13
+ constructor(options: InwxApiOptions);
14
+ private request;
15
+ /** Log in and capture the session cookie. Must be called before any
16
+ * other method. Idempotent — safe to call twice. */
17
+ login(): Promise<void>;
18
+ /** Log out and drop the session cookie. */
19
+ logout(): Promise<void>;
20
+ /** Look up a single domain. Returns the record including current
21
+ * nameservers. Throws if the domain isn't registered on this account. */
22
+ getDomainInfo(domain: string): Promise<{
23
+ domain: string;
24
+ ns: string[];
25
+ }>;
26
+ /**
27
+ * Update the nameservers delegated at the registrar for `domain`.
28
+ * Replaces the full list — pass all the NS you want, not a diff.
29
+ *
30
+ * INWX's `domain.update` also accepts many other fields (contacts,
31
+ * transferLock, authinfo, ...). We only touch `ns` here so we never
32
+ * accidentally clobber contact info set via the web UI.
33
+ */
34
+ setDomainNameservers(domain: string, nameservers: string[]): Promise<void>;
35
+ }
36
+ //# sourceMappingURL=inwx-api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inwx-api.d.ts","sourceRoot":"","sources":["../../src/utils/inwx-api.ts"],"names":[],"mappings":"AAmBA,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,yEAAyE;IACzE,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAQD,gCAAgC;AAChC,qBAAa,OAAO;IAClB,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,MAAM,CAAuB;gBAEzB,OAAO,EAAE,cAAc;YAMrB,OAAO;IAsCrB;yDACqD;IAC/C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAU5B,2CAA2C;IACrC,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ7B;8EAC0E;IACpE,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAK9E;;;;;;;OAOG;IACG,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CAQjF"}
@@ -0,0 +1,105 @@
1
+ // INWX JSON-RPC API client.
2
+ //
3
+ // The INWX Terraform provider can create DNS records inside a zone, but it
4
+ // can't change the nameservers that the TLD delegates a domain to. That's
5
+ // a "domain object" operation (domain.update), not a "nameserver object"
6
+ // operation — different part of the INWX API. This client handles the
7
+ // domain-level call so hatchkit can automatically point an INWX-registered
8
+ // domain at Cloudflare's nameservers after the CF zone is ready.
9
+ //
10
+ // API docs: https://www.inwx.com/en/help/apidoc
11
+ // Endpoints: https://api.domrobot.com/jsonrpc/ (OTE sandbox on api.ote)
12
+ //
13
+ // The API is JSON-RPC 2.0 over HTTPS, session-cookie authenticated. Call
14
+ // `account.login` once, capture the PHPSESSID cookie, include it on every
15
+ // follow-up request.
16
+ const PROD_URL = "https://api.domrobot.com/jsonrpc/";
17
+ const OTE_URL = "https://api.ote.domrobot.com/jsonrpc/";
18
+ /** INWX JSON-RPC API client. */
19
+ export class InwxApi {
20
+ url;
21
+ username;
22
+ password;
23
+ cookie = null;
24
+ constructor(options) {
25
+ this.url = options.sandbox ? OTE_URL : PROD_URL;
26
+ this.username = options.username;
27
+ this.password = options.password;
28
+ }
29
+ async request(method, params) {
30
+ const headers = {
31
+ "Content-Type": "application/json",
32
+ Accept: "application/json",
33
+ };
34
+ if (this.cookie)
35
+ headers.Cookie = this.cookie;
36
+ const res = await fetch(this.url, {
37
+ method: "POST",
38
+ headers,
39
+ body: JSON.stringify({ method, params }),
40
+ });
41
+ if (!res.ok) {
42
+ throw new Error(`INWX API ${method} failed: HTTP ${res.status} ${res.statusText}`);
43
+ }
44
+ // Capture the session cookie from the response on login. INWX sets
45
+ // PHPSESSID; we pass it back on every subsequent call.
46
+ const setCookie = res.headers.get("set-cookie");
47
+ if (setCookie) {
48
+ const match = setCookie.match(/(PHPSESSID=[^;]+)/);
49
+ if (match)
50
+ this.cookie = match[1];
51
+ }
52
+ const json = (await res.json());
53
+ // INWX returns HTTP 200 with an error code in the body. 1000 = success,
54
+ // anything else is a failure. The `msg` field is the human-readable
55
+ // error — surface it verbatim so callers can see what went wrong
56
+ // (e.g. "Authentication error" vs "Object does not exist").
57
+ if (json.code !== 1000) {
58
+ throw new Error(`INWX ${method} failed: ${json.code} ${json.msg}`);
59
+ }
60
+ return json.resData;
61
+ }
62
+ /** Log in and capture the session cookie. Must be called before any
63
+ * other method. Idempotent — safe to call twice. */
64
+ async login() {
65
+ await this.request("account.login", {
66
+ user: this.username,
67
+ pass: this.password,
68
+ });
69
+ if (!this.cookie) {
70
+ throw new Error("INWX login succeeded but no session cookie was set");
71
+ }
72
+ }
73
+ /** Log out and drop the session cookie. */
74
+ async logout() {
75
+ try {
76
+ await this.request("account.logout", {});
77
+ }
78
+ finally {
79
+ this.cookie = null;
80
+ }
81
+ }
82
+ /** Look up a single domain. Returns the record including current
83
+ * nameservers. Throws if the domain isn't registered on this account. */
84
+ async getDomainInfo(domain) {
85
+ const data = await this.request("domain.info", { domain });
86
+ return data;
87
+ }
88
+ /**
89
+ * Update the nameservers delegated at the registrar for `domain`.
90
+ * Replaces the full list — pass all the NS you want, not a diff.
91
+ *
92
+ * INWX's `domain.update` also accepts many other fields (contacts,
93
+ * transferLock, authinfo, ...). We only touch `ns` here so we never
94
+ * accidentally clobber contact info set via the web UI.
95
+ */
96
+ async setDomainNameservers(domain, nameservers) {
97
+ if (nameservers.length < 2) {
98
+ // Most registries require ≥2 NS records. Fail loud rather than
99
+ // letting the TLD registry reject it with a less obvious error.
100
+ throw new Error(`At least 2 nameservers required, got ${nameservers.length}`);
101
+ }
102
+ await this.request("domain.update", { domain, ns: nameservers });
103
+ }
104
+ }
105
+ //# sourceMappingURL=inwx-api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inwx-api.js","sourceRoot":"","sources":["../../src/utils/inwx-api.ts"],"names":[],"mappings":"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"}
@@ -5,11 +5,18 @@ export declare const SECRET_KEYS: {
5
5
  readonly hetznerToken: "hetzner:token";
6
6
  readonly dnsInwxPassword: "dns:inwx:password";
7
7
  readonly dnsCloudflareToken: "dns:cloudflare:token";
8
+ /** Registrar password when DNS is on Cloudflare but the domain is
9
+ * registered at INWX. Used by the post-apply NS flip in deploy/terraform
10
+ * and by `hatchkit dns link-to-cloudflare`. */
11
+ readonly dnsInwxRegistrarPassword: "dns:inwx-registrar:password";
8
12
  readonly s3AccessKey: (provider: string) => string;
9
13
  readonly s3SecretKey: (provider: string) => string;
10
14
  readonly gpuApiKey: (platform: string) => string;
11
15
  readonly glitchtipToken: "glitchtip:auth-token";
12
- readonly openpanelToken: "openpanel:personal-access-token";
16
+ /** Root-mode OpenPanel client used by the Management API to auto-create
17
+ * per-project clients. Created once in the OpenPanel dashboard. */
18
+ readonly openpanelRootClientId: "openpanel:root-client-id";
19
+ readonly openpanelRootClientSecret: "openpanel:root-client-secret";
13
20
  readonly openpanelClientSecret: (name: string) => string;
14
21
  readonly resendApiKey: "resend:api-key";
15
22
  /** Per-scaffolded-project dotenvx private key for .env.production.
@@ -1 +1 @@
1
- {"version":3,"file":"secrets.d.ts","sourceRoot":"","sources":["../../src/utils/secrets.ts"],"names":[],"mappings":"AAoBA;mEACmE;AACnE,eAAO,MAAM,WAAW;;;;;qCAKE,MAAM;qCACN,MAAM;mCACR,MAAM;;;2CAGE,MAAM;;IAEpC;;+DAE2D;8CAC1B,MAAM;CAC/B,CAAC;AAEX,wBAAsB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAEnE;AAED,wBAAsB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAEzE;AAED,wBAAsB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAEhE;AAED,iEAAiE;AACjE,wBAAsB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CAGrD"}
1
+ {"version":3,"file":"secrets.d.ts","sourceRoot":"","sources":["../../src/utils/secrets.ts"],"names":[],"mappings":"AAoBA;mEACmE;AACnE,eAAO,MAAM,WAAW;;;;;IAKtB;;oDAEgD;;qCAExB,MAAM;qCACN,MAAM;mCACR,MAAM;;IAE5B;wEACoE;;;2CAGtC,MAAM;;IAEpC;;+DAE2D;8CAC1B,MAAM;CAC/B,CAAC;AAEX,wBAAsB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAEnE;AAED,wBAAsB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAEzE;AAED,wBAAsB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAEhE;AAED,iEAAiE;AACjE,wBAAsB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CAGrD"}
@@ -22,11 +22,18 @@ export const SECRET_KEYS = {
22
22
  hetznerToken: "hetzner:token",
23
23
  dnsInwxPassword: "dns:inwx:password",
24
24
  dnsCloudflareToken: "dns:cloudflare:token",
25
+ /** Registrar password when DNS is on Cloudflare but the domain is
26
+ * registered at INWX. Used by the post-apply NS flip in deploy/terraform
27
+ * and by `hatchkit dns link-to-cloudflare`. */
28
+ dnsInwxRegistrarPassword: "dns:inwx-registrar:password",
25
29
  s3AccessKey: (provider) => `s3:${provider}:access-key`,
26
30
  s3SecretKey: (provider) => `s3:${provider}:secret-key`,
27
31
  gpuApiKey: (platform) => `gpu:${platform}:api-key`,
28
32
  glitchtipToken: "glitchtip:auth-token",
29
- openpanelToken: "openpanel:personal-access-token",
33
+ /** Root-mode OpenPanel client used by the Management API to auto-create
34
+ * per-project clients. Created once in the OpenPanel dashboard. */
35
+ openpanelRootClientId: "openpanel:root-client-id",
36
+ openpanelRootClientSecret: "openpanel:root-client-secret",
30
37
  openpanelClientSecret: (name) => `openpanel:${name}:client-secret`,
31
38
  resendApiKey: "resend:api-key",
32
39
  /** Per-scaffolded-project dotenvx private key for .env.production.
@@ -1 +1 @@
1
- {"version":3,"file":"secrets.js","sourceRoot":"","sources":["../../src/utils/secrets.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,MAAM,MAAM,QAAQ,CAAC;AAE5B,iEAAiE;AACjE,uEAAuE;AACvE,sEAAsE;AACtE,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,uBAAuB,IAAI,UAAU,CAAC;AAElE;mEACmE;AACnE,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,YAAY,EAAE,eAAe;IAC7B,YAAY,EAAE,eAAe;IAC7B,eAAe,EAAE,mBAAmB;IACpC,kBAAkB,EAAE,sBAAsB;IAC1C,WAAW,EAAE,CAAC,QAAgB,EAAE,EAAE,CAAC,MAAM,QAAQ,aAAa;IAC9D,WAAW,EAAE,CAAC,QAAgB,EAAE,EAAE,CAAC,MAAM,QAAQ,aAAa;IAC9D,SAAS,EAAE,CAAC,QAAgB,EAAE,EAAE,CAAC,OAAO,QAAQ,UAAU;IAC1D,cAAc,EAAE,sBAAsB;IACtC,cAAc,EAAE,iCAAiC;IACjD,qBAAqB,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,aAAa,IAAI,gBAAgB;IAC1E,YAAY,EAAE,gBAAgB;IAC9B;;+DAE2D;IAC3D,iBAAiB,EAAE,CAAC,WAAmB,EAAE,EAAE,CAAC,WAAW,WAAW,yBAAyB;CACnF,CAAC;AAEX,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,GAAW;IACzC,OAAO,MAAM,CAAC,WAAW,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;AAC1C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,GAAW,EAAE,KAAa;IACxD,MAAM,MAAM,CAAC,WAAW,CAAC,OAAO,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,GAAW;IAC5C,OAAO,MAAM,CAAC,cAAc,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;AAC7C,CAAC;AAED,iEAAiE;AACjE,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;IACtD,MAAM,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AACnF,CAAC"}
1
+ {"version":3,"file":"secrets.js","sourceRoot":"","sources":["../../src/utils/secrets.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,MAAM,MAAM,QAAQ,CAAC;AAE5B,iEAAiE;AACjE,uEAAuE;AACvE,sEAAsE;AACtE,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,uBAAuB,IAAI,UAAU,CAAC;AAElE;mEACmE;AACnE,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,YAAY,EAAE,eAAe;IAC7B,YAAY,EAAE,eAAe;IAC7B,eAAe,EAAE,mBAAmB;IACpC,kBAAkB,EAAE,sBAAsB;IAC1C;;oDAEgD;IAChD,wBAAwB,EAAE,6BAA6B;IACvD,WAAW,EAAE,CAAC,QAAgB,EAAE,EAAE,CAAC,MAAM,QAAQ,aAAa;IAC9D,WAAW,EAAE,CAAC,QAAgB,EAAE,EAAE,CAAC,MAAM,QAAQ,aAAa;IAC9D,SAAS,EAAE,CAAC,QAAgB,EAAE,EAAE,CAAC,OAAO,QAAQ,UAAU;IAC1D,cAAc,EAAE,sBAAsB;IACtC;wEACoE;IACpE,qBAAqB,EAAE,0BAA0B;IACjD,yBAAyB,EAAE,8BAA8B;IACzD,qBAAqB,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,aAAa,IAAI,gBAAgB;IAC1E,YAAY,EAAE,gBAAgB;IAC9B;;+DAE2D;IAC3D,iBAAiB,EAAE,CAAC,WAAmB,EAAE,EAAE,CAAC,WAAW,WAAW,yBAAyB;CACnF,CAAC;AAEX,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,GAAW;IACzC,OAAO,MAAM,CAAC,WAAW,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;AAC1C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,GAAW,EAAE,KAAa;IACxD,MAAM,MAAM,CAAC,WAAW,CAAC,OAAO,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,GAAW;IAC5C,OAAO,MAAM,CAAC,cAAc,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;AAC7C,CAAC;AAED,iEAAiE;AACjE,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;IACtD,MAAM,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AACnF,CAAC"}