hatchkit 0.1.37 → 0.1.39
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.
- package/dist/deploy/coolify.d.ts.map +1 -1
- package/dist/deploy/coolify.js +50 -25
- package/dist/deploy/coolify.js.map +1 -1
- package/dist/deploy/regen-infra.d.ts +12 -0
- package/dist/deploy/regen-infra.d.ts.map +1 -0
- package/dist/deploy/regen-infra.js +194 -0
- package/dist/deploy/regen-infra.js.map +1 -0
- package/dist/index.js +54 -4
- package/dist/index.js.map +1 -1
- package/dist/prompts.d.ts +19 -0
- package/dist/prompts.d.ts.map +1 -1
- package/dist/prompts.js +74 -15
- package/dist/prompts.js.map +1 -1
- package/dist/scaffold/app.d.ts.map +1 -1
- package/dist/scaffold/app.js +26 -2
- package/dist/scaffold/app.js.map +1 -1
- package/dist/scaffold/infra.d.ts.map +1 -1
- package/dist/scaffold/infra.js +13 -5
- package/dist/scaffold/infra.js.map +1 -1
- package/dist/scaffold/manifest.d.ts.map +1 -1
- package/dist/scaffold/manifest.js +1 -0
- package/dist/scaffold/manifest.js.map +1 -1
- package/dist/scaffold/surfaces.d.ts +11 -0
- package/dist/scaffold/surfaces.d.ts.map +1 -0
- package/dist/scaffold/surfaces.js +331 -0
- package/dist/scaffold/surfaces.js.map +1 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"coolify.d.ts","sourceRoot":"","sources":["../../src/deploy/coolify.ts"],"names":[],"mappings":"AA8BA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAGnD,MAAM,WAAW,sBAAsB;IACrC;;sCAEkC;IAClC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;kEAE8D;IAC9D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;uDAEmD;IACnD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,qBAAqB;IACpC;;wDAEoD;IACpD,OAAO,EAAE,MAAM,CAAC;IAChB;;gDAE4C;IAC5C,WAAW,EAAE,MAAM,CAAC;IACpB;;0EAEsE;IACtE,cAAc,EAAE,OAAO,CAAC;IACxB;;yCAEqC;IACrC,UAAU,EAAE,OAAO,CAAC;CACrB;AAED;;oDAEoD;AACpD,wBAAsB,eAAe,CACnC,MAAM,EAAE,aAAa,EACrB,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,qBAAqB,CAAC,
|
|
1
|
+
{"version":3,"file":"coolify.d.ts","sourceRoot":"","sources":["../../src/deploy/coolify.ts"],"names":[],"mappings":"AA8BA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAGnD,MAAM,WAAW,sBAAsB;IACrC;;sCAEkC;IAClC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;kEAE8D;IAC9D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;uDAEmD;IACnD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,qBAAqB;IACpC;;wDAEoD;IACpD,OAAO,EAAE,MAAM,CAAC;IAChB;;gDAE4C;IAC5C,WAAW,EAAE,MAAM,CAAC;IACpB;;0EAEsE;IACtE,cAAc,EAAE,OAAO,CAAC;IACxB;;yCAEqC;IACrC,UAAU,EAAE,OAAO,CAAC;CACrB;AAED;;oDAEoD;AACpD,wBAAsB,eAAe,CACnC,MAAM,EAAE,aAAa,EACrB,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,qBAAqB,CAAC,CA4KhC"}
|
package/dist/deploy/coolify.js
CHANGED
|
@@ -65,16 +65,23 @@ export async function runCoolifySetup(config, options = {}) {
|
|
|
65
65
|
projectCreated = true;
|
|
66
66
|
console.log(chalk.green(` ✓ Project created: ${config.name} (${projectUuid})`));
|
|
67
67
|
}
|
|
68
|
-
// Domain routing
|
|
69
|
-
//
|
|
70
|
-
//
|
|
71
|
-
//
|
|
72
|
-
//
|
|
73
|
-
//
|
|
74
|
-
//
|
|
75
|
-
//
|
|
76
|
-
//
|
|
77
|
-
//
|
|
68
|
+
// Domain routing — surface-aware. Coolify's dockercompose build pack
|
|
69
|
+
// rejects a flat `domains` field (422 — "Use docker_compose_domains
|
|
70
|
+
// instead …") because routing is per-service.
|
|
71
|
+
//
|
|
72
|
+
// · both — `client` gets the bare hostname; `server` gets the
|
|
73
|
+
// api subdomain + the path-based API/WS hosts.
|
|
74
|
+
// · server-only — no client service in the pruned compose, so the
|
|
75
|
+
// bare hostname AND every API/WS host all point at
|
|
76
|
+
// `server`. Browsers hitting `<domain>` reach the
|
|
77
|
+
// Express app directly (which can still serve a 200
|
|
78
|
+
// health page or redirect to the api host).
|
|
79
|
+
// · client-only — only the `client` service exists; nothing public
|
|
80
|
+
// about the API is needed. Currently unreachable
|
|
81
|
+
// from `hatchkit create` (the scaffold step throws
|
|
82
|
+
// before we get here) but the branch is wired so
|
|
83
|
+
// `hatchkit adopt`-driven client-only callers and a
|
|
84
|
+
// future create-side implementation share one path.
|
|
78
85
|
const apiDomain = `api.${config.domain}`;
|
|
79
86
|
const frontendDomain = `https://${config.domain}`;
|
|
80
87
|
const backendDomains = [
|
|
@@ -83,17 +90,29 @@ export async function runCoolifySetup(config, options = {}) {
|
|
|
83
90
|
`https://${config.domain}/api/ws`,
|
|
84
91
|
`https://${apiDomain}/ws`,
|
|
85
92
|
];
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
93
|
+
const surfaces = config.surfaces ?? "both";
|
|
94
|
+
const dockerComposeDomains = surfaces === "client-only"
|
|
95
|
+
? [{ name: "client", domain: frontendDomain }]
|
|
96
|
+
: surfaces === "server-only"
|
|
97
|
+
? [
|
|
98
|
+
{ name: "server", domain: frontendDomain },
|
|
99
|
+
...backendDomains.map((domain) => ({ name: "server", domain })),
|
|
100
|
+
]
|
|
101
|
+
: [
|
|
102
|
+
{ name: "client", domain: frontendDomain },
|
|
103
|
+
...backendDomains.map((domain) => ({ name: "server", domain })),
|
|
104
|
+
];
|
|
94
105
|
console.log(chalk.dim(" Domain routing:"));
|
|
95
|
-
|
|
96
|
-
|
|
106
|
+
if (surfaces === "client-only") {
|
|
107
|
+
console.log(chalk.dim(` Frontend (client): ${frontendDomain}`));
|
|
108
|
+
}
|
|
109
|
+
else if (surfaces === "server-only") {
|
|
110
|
+
console.log(chalk.dim(` All hosts → server: ${[frontendDomain, ...backendDomains].join(", ")}`));
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
console.log(chalk.dim(` Frontend (client): ${frontendDomain}`));
|
|
114
|
+
console.log(chalk.dim(` Backend (server): ${backendDomains.join(", ")}`));
|
|
115
|
+
}
|
|
97
116
|
// Application: reuse-by-name. `findApplicationByName` matches across
|
|
98
117
|
// every project the user can see; first hit wins. Within a single
|
|
99
118
|
// hatchkit-managed Coolify install, project names are unique enough
|
|
@@ -153,11 +172,17 @@ export async function runCoolifySetup(config, options = {}) {
|
|
|
153
172
|
// .env.production and is decrypted at runtime via the dotenvx
|
|
154
173
|
// private key that `hatchkit keys push` puts on Coolify. That keeps
|
|
155
174
|
// prod secrets out of Coolify's UI.
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
175
|
+
//
|
|
176
|
+
// Client-only scaffolds get only NODE_ENV — there's no server to
|
|
177
|
+
// honour PORT (the Next.js standalone server already binds 3000) and
|
|
178
|
+
// FRONTEND_URL is meaningless without a CORS-checking backend.
|
|
179
|
+
const envs = surfaces === "client-only"
|
|
180
|
+
? { NODE_ENV: "production" }
|
|
181
|
+
: {
|
|
182
|
+
NODE_ENV: "production",
|
|
183
|
+
PORT: String(options.serverPort ?? 3000),
|
|
184
|
+
FRONTEND_URL: `https://${config.domain}`,
|
|
185
|
+
};
|
|
161
186
|
await api.setAppEnv(appUuid, envs);
|
|
162
187
|
console.log(chalk.green(` ✓ Set ${Object.keys(envs).length} env vars on application (${Object.keys(envs).join(", ")})`));
|
|
163
188
|
console.log(chalk.green("\n ✓ Coolify app stack created"));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"coolify.js","sourceRoot":"","sources":["../../src/deploy/coolify.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEhD,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAoCrD;;oDAEoD;AACpD,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,MAAqB,EACrB,UAAkC,EAAE;IAEpC,MAAM,GAAG,GAAG,MAAM,gBAAgB,EAAE,CAAC;IACrC,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,MAAM,IAAI,KAAK,CAAC,qEAAqE,CAAC,CAAC;IACzF,CAAC;IAED,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC;IAE/D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,kEAAkE,CAAC,CAAC,CAAC;IAE5F,MAAM,MAAM,GAAG,GAAG,CAAC,4BAA4B,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC;IAClE,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,UAAU,EAAE,CAAC;QACvC,MAAM,CAAC,OAAO,CAAC,yBAAyB,OAAO,EAAE,CAAC,CAAC;IACrD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,CAAC,IAAI,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CAAC,+BAA+B,GAAG,CAAC,GAAG,KAAM,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;IACvF,CAAC;IAED,MAAM,UAAU,GAAG,MAAM,iBAAiB,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IAExD,mEAAmE;IACnE,oEAAoE;IACpE,yBAAyB;IACzB,IAAI,WAAmB,CAAC;IACxB,IAAI,cAAc,GAAG,KAAK,CAAC;IAC3B,MAAM,eAAe,GAAG,MAAM,GAAG,CAAC,iBAAiB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACjE,IAAI,eAAe,EAAE,CAAC;QACpB,WAAW,GAAG,eAAe,CAAC,IAAI,CAAC;QACnC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,oCAAoC,MAAM,CAAC,IAAI,KAAK,WAAW,GAAG,CAAC,CAAC,CAAC;IAC7F,CAAC;SAAM,CAAC;QACN,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACrD,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;QAC3B,cAAc,GAAG,IAAI,CAAC;QACtB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,wBAAwB,MAAM,CAAC,IAAI,KAAK,WAAW,GAAG,CAAC,CAAC,CAAC;IACnF,CAAC;IAED,
|
|
1
|
+
{"version":3,"file":"coolify.js","sourceRoot":"","sources":["../../src/deploy/coolify.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
interface RegenArgs {
|
|
2
|
+
/** Project directory — defaults to cwd. The manifest must live here. */
|
|
3
|
+
projectDir: string;
|
|
4
|
+
/** Repo root for the hatchkit checkout (where the infra/ tree is). */
|
|
5
|
+
monorepoRoot: string;
|
|
6
|
+
/** Show the diff but don't write. */
|
|
7
|
+
dryRun: boolean;
|
|
8
|
+
}
|
|
9
|
+
export declare function runRegenInfraCli(args: string[], monorepoRoot: string): Promise<void>;
|
|
10
|
+
export declare function runRegenInfra(opts: RegenArgs): Promise<void>;
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=regen-infra.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"regen-infra.d.ts","sourceRoot":"","sources":["../../src/deploy/regen-infra.ts"],"names":[],"mappings":"AA8BA,UAAU,SAAS;IACjB,wEAAwE;IACxE,UAAU,EAAE,MAAM,CAAC;IACnB,sEAAsE;IACtE,YAAY,EAAE,MAAM,CAAC;IACrB,qCAAqC;IACrC,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAK1F;AAED,wBAAsB,aAAa,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAgGlE"}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* `hatchkit regen-infra` — regenerate Terraform tfvars + Coolify stack
|
|
3
|
+
* .env for a scaffolded project, in place.
|
|
4
|
+
*
|
|
5
|
+
* Why this exists: `scaffoldInfra` runs once during `create` / `adopt`
|
|
6
|
+
* and bakes the project's choices into static files under
|
|
7
|
+
* `infra/terraform/stacks/.../<name>.tfvars` and `infra/stacks/<name>.env`.
|
|
8
|
+
* When the CLI's tfvars-generation logic changes (e.g. dropping the
|
|
9
|
+
* `api.<sub>` subdomain for client-only surfaces, or flipping
|
|
10
|
+
* `MONGO_ENABLED` based on the surface), existing projects keep their
|
|
11
|
+
* old files until someone re-runs scaffoldInfra. This command does
|
|
12
|
+
* exactly that — re-render from the manifest, preserve the infra-only
|
|
13
|
+
* fields the manifest doesn't carry (target_ipv4/v6 for dns-only,
|
|
14
|
+
* serverType / serverLocation for new-server), diff against what's on
|
|
15
|
+
* disk, and write the new files.
|
|
16
|
+
*
|
|
17
|
+
* Intentionally does NOT run `terraform apply` or touch Coolify. The
|
|
18
|
+
* user runs `terraform apply -var-file=<name>.tfvars` themselves once
|
|
19
|
+
* they've reviewed the plan.
|
|
20
|
+
*/
|
|
21
|
+
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
22
|
+
import { basename, dirname, join, resolve } from "node:path";
|
|
23
|
+
import chalk from "chalk";
|
|
24
|
+
import { getConfig } from "../config.js";
|
|
25
|
+
import { generateCoolifyEnv, generateTfvars, resolveStackDir } from "../scaffold/infra.js";
|
|
26
|
+
import { readManifest } from "../scaffold/manifest.js";
|
|
27
|
+
import { parseDomain } from "../utils/validate.js";
|
|
28
|
+
export async function runRegenInfraCli(args, monorepoRoot) {
|
|
29
|
+
const dryRun = args.includes("--dry-run");
|
|
30
|
+
const dirFlag = args.findIndex((a) => a === "--dir");
|
|
31
|
+
const projectDir = resolve(dirFlag >= 0 ? (args[dirFlag + 1] ?? ".") : ".");
|
|
32
|
+
await runRegenInfra({ projectDir, monorepoRoot, dryRun });
|
|
33
|
+
}
|
|
34
|
+
export async function runRegenInfra(opts) {
|
|
35
|
+
const { projectDir, monorepoRoot, dryRun } = opts;
|
|
36
|
+
const manifest = readManifest(projectDir);
|
|
37
|
+
if (!manifest) {
|
|
38
|
+
throw new Error(`No .hatchkit.json in ${projectDir}. Run from inside a scaffolded project, or pass --dir <project-dir>.`);
|
|
39
|
+
}
|
|
40
|
+
// Locate the existing tfvars file. We try the same three stack dirs
|
|
41
|
+
// `resolveStackDir` knows about and pick the first hit — matches what
|
|
42
|
+
// `rename-domain.ts` does.
|
|
43
|
+
const candidatePaths = [
|
|
44
|
+
join(monorepoRoot, "infra", "terraform", "stacks", "node-realtime", `${manifest.name}.tfvars`),
|
|
45
|
+
join(monorepoRoot, "infra", "terraform", "stacks", "dns-only-cloudflare", `${manifest.name}.tfvars`),
|
|
46
|
+
join(monorepoRoot, "infra", "terraform", "stacks", "dns-only-inwx", `${manifest.name}.tfvars`),
|
|
47
|
+
];
|
|
48
|
+
const existingTfvarsPath = candidatePaths.find((p) => existsSync(p));
|
|
49
|
+
// Reconstruct the bits of ProjectConfig the tfvars/coolify-env
|
|
50
|
+
// generators care about. Manifest carries the safe public-facing
|
|
51
|
+
// fields; everything infra-only (server coords, IPs, S3 creds) we
|
|
52
|
+
// either pull from the existing tfvars (when present) or accept as
|
|
53
|
+
// empty (terraform plan will fail loudly enough if a required value
|
|
54
|
+
// is missing).
|
|
55
|
+
const config = configFromManifestAndTfvars(manifest, existingTfvarsPath);
|
|
56
|
+
const newTfvars = generateTfvars(config);
|
|
57
|
+
const newCoolifyEnv = generateCoolifyEnv(config, {});
|
|
58
|
+
// Existing-content reads — null when the file doesn't yet exist so
|
|
59
|
+
// the diff shows the file as new.
|
|
60
|
+
const oldTfvars = existingTfvarsPath ? readFileSync(existingTfvarsPath, "utf-8") : "";
|
|
61
|
+
const coolifyEnvPath = join(monorepoRoot, "infra", "stacks", `${manifest.name}.env`);
|
|
62
|
+
const oldCoolifyEnv = existsSync(coolifyEnvPath) ? readFileSync(coolifyEnvPath, "utf-8") : "";
|
|
63
|
+
// Decide where the new tfvars should land — same dir as the existing
|
|
64
|
+
// file when we found one, else fall back to `resolveStackDir` so a
|
|
65
|
+
// fresh regen still produces a valid file. resolveStackDir resolves
|
|
66
|
+
// paths relative to the `infra/` root, not the monorepo root, so we
|
|
67
|
+
// join the prefix ourselves.
|
|
68
|
+
let tfvarsTargetPath = existingTfvarsPath;
|
|
69
|
+
if (!tfvarsTargetPath && newTfvars) {
|
|
70
|
+
const cfgDnsProvider = inferDnsProviderFromConfig();
|
|
71
|
+
const stackDir = resolveStackDir(join(monorepoRoot, "infra"), config.deployTarget, cfgDnsProvider);
|
|
72
|
+
if (stackDir)
|
|
73
|
+
tfvarsTargetPath = join(stackDir, `${manifest.name}.tfvars`);
|
|
74
|
+
}
|
|
75
|
+
console.log(chalk.bold(`\n ── regen-infra: ${manifest.name} ─────────────────────────`));
|
|
76
|
+
console.log(chalk.dim(` domain=${manifest.domain} surfaces=${manifest.surfaces ?? "both"} deploy=${manifest.deployTarget}`));
|
|
77
|
+
let touched = 0;
|
|
78
|
+
touched += renderFileChange("tfvars", tfvarsTargetPath, oldTfvars, newTfvars, dryRun);
|
|
79
|
+
touched += renderFileChange("coolify .env", coolifyEnvPath, oldCoolifyEnv, newCoolifyEnv, dryRun);
|
|
80
|
+
if (touched === 0) {
|
|
81
|
+
console.log(chalk.green("\n ✓ Already up to date — no changes."));
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
if (dryRun) {
|
|
85
|
+
console.log(chalk.yellow(`\n [dry-run] ${touched} file(s) would be rewritten.`));
|
|
86
|
+
console.log(chalk.dim(" Re-run without --dry-run to apply."));
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
console.log(chalk.green(`\n ✓ Regenerated ${touched} file(s).`));
|
|
90
|
+
if (tfvarsTargetPath && newTfvars && oldTfvars !== newTfvars) {
|
|
91
|
+
const stackDir = dirname(tfvarsTargetPath);
|
|
92
|
+
console.log(chalk.yellow(`\n Next: terraform -chdir=${stackDir} plan -var-file=${basename(tfvarsTargetPath)}`));
|
|
93
|
+
console.log(chalk.dim(` terraform -chdir=${stackDir} apply -var-file=${basename(tfvarsTargetPath)}`));
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
function renderFileChange(label, path, oldContent, newContent, dryRun) {
|
|
97
|
+
if (!path) {
|
|
98
|
+
console.log(chalk.dim(` ${label}: no target path resolved (manual DNS?) — skipped`));
|
|
99
|
+
return 0;
|
|
100
|
+
}
|
|
101
|
+
if (oldContent === newContent) {
|
|
102
|
+
console.log(chalk.dim(` ${label}: unchanged (${path})`));
|
|
103
|
+
return 0;
|
|
104
|
+
}
|
|
105
|
+
console.log(chalk.bold(`\n ${label}: ${chalk.cyan(path)}`));
|
|
106
|
+
printUnifiedDiff(oldContent, newContent);
|
|
107
|
+
if (!dryRun)
|
|
108
|
+
writeFileSync(path, newContent, "utf-8");
|
|
109
|
+
return 1;
|
|
110
|
+
}
|
|
111
|
+
/** Print a line-level diff between two strings using an LCS table — so
|
|
112
|
+
* removing one line in the middle doesn't make every subsequent line
|
|
113
|
+
* look changed. Files here are small (tens of lines), so the O(n·m)
|
|
114
|
+
* table is fine and we avoid pulling in a dep. */
|
|
115
|
+
function printUnifiedDiff(oldStr, newStr) {
|
|
116
|
+
const a = oldStr.split("\n");
|
|
117
|
+
const b = newStr.split("\n");
|
|
118
|
+
// LCS lengths table.
|
|
119
|
+
const lcs = Array.from({ length: a.length + 1 }, () => new Array(b.length + 1).fill(0));
|
|
120
|
+
for (let i = a.length - 1; i >= 0; i--) {
|
|
121
|
+
for (let j = b.length - 1; j >= 0; j--) {
|
|
122
|
+
lcs[i][j] = a[i] === b[j] ? lcs[i + 1][j + 1] + 1 : Math.max(lcs[i + 1][j], lcs[i][j + 1]);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
// Walk the table emitting -/+/context lines.
|
|
126
|
+
let i = 0;
|
|
127
|
+
let j = 0;
|
|
128
|
+
while (i < a.length && j < b.length) {
|
|
129
|
+
if (a[i] === b[j]) {
|
|
130
|
+
i++;
|
|
131
|
+
j++;
|
|
132
|
+
}
|
|
133
|
+
else if (lcs[i + 1][j] >= lcs[i][j + 1]) {
|
|
134
|
+
console.log(chalk.red(` - ${a[i]}`));
|
|
135
|
+
i++;
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
console.log(chalk.green(` + ${b[j]}`));
|
|
139
|
+
j++;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
while (i < a.length)
|
|
143
|
+
console.log(chalk.red(` - ${a[i++]}`));
|
|
144
|
+
while (j < b.length)
|
|
145
|
+
console.log(chalk.green(` + ${b[j++]}`));
|
|
146
|
+
}
|
|
147
|
+
function configFromManifestAndTfvars(manifest, tfvarsPath) {
|
|
148
|
+
const tfvars = tfvarsPath && existsSync(tfvarsPath) ? readFileSync(tfvarsPath, "utf-8") : "";
|
|
149
|
+
const { baseDomain, subdomain } = parseDomain(manifest.domain);
|
|
150
|
+
return {
|
|
151
|
+
name: manifest.name,
|
|
152
|
+
domain: manifest.domain,
|
|
153
|
+
baseDomain,
|
|
154
|
+
subdomain,
|
|
155
|
+
surfaces: (manifest.surfaces ?? "both"),
|
|
156
|
+
deployTarget: manifest.deployTarget,
|
|
157
|
+
// Infra-only fields — preserved from the existing tfvars so we
|
|
158
|
+
// don't blow away discovered IPs / sizes.
|
|
159
|
+
serverIpv4: extractHcl(tfvars, "target_ipv4") || undefined,
|
|
160
|
+
serverIpv6: extractHcl(tfvars, "target_ipv6") || undefined,
|
|
161
|
+
serverSize: extractHcl(tfvars, "server_type") || undefined,
|
|
162
|
+
serverLocation: extractHcl(tfvars, "server_location") || undefined,
|
|
163
|
+
features: [...manifest.features],
|
|
164
|
+
s3Provider: manifest.s3Provider,
|
|
165
|
+
mlServices: [...manifest.mlServices],
|
|
166
|
+
forceRedeployMl: [],
|
|
167
|
+
gpuPlatforms: manifest.gpuPlatforms,
|
|
168
|
+
customHfModelId: manifest.customHfModelId,
|
|
169
|
+
customHfGpuType: manifest.customHfGpuType,
|
|
170
|
+
scaffoldRepo: false,
|
|
171
|
+
createGithubRepo: false,
|
|
172
|
+
installDeps: false,
|
|
173
|
+
runDeployment: false,
|
|
174
|
+
dryRun: false,
|
|
175
|
+
envValues: {},
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
/** Pull a top-level `key = "value"` line out of an HCL tfvars body.
|
|
179
|
+
* Tolerates leading whitespace; ignores values inside blocks. Returns
|
|
180
|
+
* the unquoted value, or "" when not found. */
|
|
181
|
+
function extractHcl(content, key) {
|
|
182
|
+
if (!content)
|
|
183
|
+
return "";
|
|
184
|
+
const m = content.match(new RegExp(`^\\s*${key}\\s*=\\s*"([^"]*)"`, "m"));
|
|
185
|
+
return m ? m[1] : "";
|
|
186
|
+
}
|
|
187
|
+
/** The DNS provider drives which dns-only stack dir we'd fall back to
|
|
188
|
+
* for a brand-new regen (when there's no existing tfvars to anchor
|
|
189
|
+
* on). Defaults to inwx, which matches `generateTfvars`'s own
|
|
190
|
+
* fallback. */
|
|
191
|
+
function inferDnsProviderFromConfig() {
|
|
192
|
+
return (getConfig().providers.dns?.provider ?? "inwx");
|
|
193
|
+
}
|
|
194
|
+
//# sourceMappingURL=regen-infra.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"regen-infra.js","sourceRoot":"","sources":["../../src/deploy/regen-infra.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -152,6 +152,13 @@ async function main() {
|
|
|
152
152
|
await runSyncCli(args.slice(1));
|
|
153
153
|
break;
|
|
154
154
|
}
|
|
155
|
+
case "regen-infra": {
|
|
156
|
+
if (args.includes("--help"))
|
|
157
|
+
return printHelp("regen-infra");
|
|
158
|
+
const { runRegenInfraCli } = await import("./deploy/regen-infra.js");
|
|
159
|
+
await runRegenInfraCli(args.slice(1), MONOREPO_ROOT);
|
|
160
|
+
break;
|
|
161
|
+
}
|
|
155
162
|
case "doctor": {
|
|
156
163
|
if (args.includes("--help"))
|
|
157
164
|
return printHelp("doctor");
|
|
@@ -914,7 +921,11 @@ async function handleCreate() {
|
|
|
914
921
|
// Auto-provision GlitchTip + write its DSN encrypted into
|
|
915
922
|
// .env.production. The user picked the `analytics` feature; we
|
|
916
923
|
// already verified GlitchTip is configured during pre-flight.
|
|
917
|
-
|
|
924
|
+
// Skipped for client-only — the encrypt target lives in
|
|
925
|
+
// packages/server/, which doesn't exist post-prune. The client
|
|
926
|
+
// side of analytics (OpenPanel via NEXT_PUBLIC_*) still works
|
|
927
|
+
// without any provisioning.
|
|
928
|
+
if (config.features.includes("analytics") && config.surfaces !== "client-only") {
|
|
918
929
|
try {
|
|
919
930
|
const { provisionGlitchtipClient } = await import("./provision/glitchtip.js");
|
|
920
931
|
const { set: dotenvxSet } = await import("@dotenvx/dotenvx");
|
|
@@ -937,8 +948,8 @@ async function handleCreate() {
|
|
|
937
948
|
// · sandbox creds → .env.development (plaintext)
|
|
938
949
|
// · live creds → .env.production (dotenvx-encrypted)
|
|
939
950
|
// Webhook endpoint ids are tracked in keychain so destroy can
|
|
940
|
-
// reach them later.
|
|
941
|
-
if (config.features.includes("stripe")) {
|
|
951
|
+
// reach them later. Skipped for client-only (server-only feature).
|
|
952
|
+
if (config.features.includes("stripe") && config.surfaces !== "client-only") {
|
|
942
953
|
try {
|
|
943
954
|
const { provisionStripeProject, renderStripeEnv, renderStripeSkipComment } = await import("./provision/stripe.js");
|
|
944
955
|
const { appendCommentBlock, parseEnvLines, writeDevEnv, writeProdEnv } = await import("./provision/write-env.js");
|
|
@@ -1203,7 +1214,12 @@ async function handleCreate() {
|
|
|
1203
1214
|
// Final summary
|
|
1204
1215
|
console.log(chalk.bold("\n ── Done! ─────────────────────────────────────────────────\n"));
|
|
1205
1216
|
console.log(` App: ${chalk.cyan(`https://${config.domain}`)}`);
|
|
1206
|
-
|
|
1217
|
+
// Skip the API line for client-only — there's no backend, so showing
|
|
1218
|
+
// a "/api" URL just confuses the user (and falsely implies a service
|
|
1219
|
+
// is listening at that path).
|
|
1220
|
+
if (config.surfaces !== "client-only") {
|
|
1221
|
+
console.log(` API: ${chalk.cyan(`https://${config.domain}/api`)}`);
|
|
1222
|
+
}
|
|
1207
1223
|
console.log(` App dir: ${chalk.dim(appDir)}`);
|
|
1208
1224
|
console.log(` Config: ${chalk.dim(getConfigPath())}`);
|
|
1209
1225
|
if (config.scaffoldRepo) {
|
|
@@ -1800,6 +1816,40 @@ function printHelp(topic) {
|
|
|
1800
1816
|
${chalk.dim(" | jq 'with_entries(select(.key | startswith(\"traefik\")))'")}
|
|
1801
1817
|
A correctly-synced container has 10+ traefik labels (HTTP router,
|
|
1802
1818
|
HTTPS router with letsencrypt, gzip middleware, redirect-to-https).
|
|
1819
|
+
`);
|
|
1820
|
+
return;
|
|
1821
|
+
}
|
|
1822
|
+
if (topic === "regen-infra") {
|
|
1823
|
+
console.log(`
|
|
1824
|
+
${chalk.bold("hatchkit regen-infra")} — rewrite tfvars + Coolify .env from the manifest
|
|
1825
|
+
|
|
1826
|
+
${chalk.bold("Usage:")}
|
|
1827
|
+
cd <project-dir> && hatchkit regen-infra [--dry-run]
|
|
1828
|
+
hatchkit regen-infra --dir <project-dir> [--dry-run]
|
|
1829
|
+
|
|
1830
|
+
${chalk.bold("What it does:")}
|
|
1831
|
+
Reads ${chalk.cyan(".hatchkit.json")}, re-runs the same generators ${chalk.cyan("hatchkit create")}
|
|
1832
|
+
uses (${chalk.dim("generateTfvars")} + ${chalk.dim("generateCoolifyEnv")}), and writes the result
|
|
1833
|
+
back to the existing tfvars + Coolify stack .env paths under
|
|
1834
|
+
${chalk.dim("infra/")}. Infra-only fields the manifest doesn't carry (server IPs,
|
|
1835
|
+
Hetzner type/location) are preserved from the existing tfvars on
|
|
1836
|
+
disk, so a regen never silently blows away discovered values.
|
|
1837
|
+
|
|
1838
|
+
${chalk.bold("When to use:")}
|
|
1839
|
+
· You upgraded the CLI and want existing projects to pick up the
|
|
1840
|
+
new tfvars logic (e.g. dropping the ${chalk.dim("api.<sub>")} subdomain for
|
|
1841
|
+
client-only surfaces).
|
|
1842
|
+
· You edited ${chalk.cyan(".hatchkit.json")} by hand (changed surfaces, added a
|
|
1843
|
+
feature) and want the infra files re-rendered to match.
|
|
1844
|
+
|
|
1845
|
+
${chalk.bold("Out of scope:")}
|
|
1846
|
+
· Does NOT run terraform — review the diff, then
|
|
1847
|
+
${chalk.dim("terraform -chdir=<stack> apply -var-file=<name>.tfvars")} yourself.
|
|
1848
|
+
· Does NOT touch Coolify live state — use ${chalk.cyan("hatchkit sync")} for that.
|
|
1849
|
+
|
|
1850
|
+
${chalk.bold("Options:")}
|
|
1851
|
+
--dir <path> Project root (defaults to cwd).
|
|
1852
|
+
--dry-run Print the unified diff without writing.
|
|
1803
1853
|
`);
|
|
1804
1854
|
return;
|
|
1805
1855
|
}
|