Initial commit of Descrybe v2 without local scratch artifacts.
Drop one-shot tmp/axe scripts and agent i18n scratch so the Gitea tree is deployable.
This commit is contained in:
@@ -0,0 +1,122 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* One-shot local bootstrap (any OS):
|
||||
* 1. Copy .env.example → .env if missing
|
||||
* 2. Fill empty TOKEN_SIGNING_SECRET / APP_ENCRYPTION_KEY (local only)
|
||||
* 3. docker compose up -d (Postgres)
|
||||
* 4. wait for healthy DB
|
||||
* 5. goose migrate + sqlc
|
||||
*
|
||||
* Usage: node scripts/setup.mjs
|
||||
* Then: npm install && npm run dev
|
||||
*/
|
||||
import { spawnSync } from "node:child_process";
|
||||
import crypto from "node:crypto";
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import {
|
||||
dotenvPath,
|
||||
parseEnvFile,
|
||||
readRootEnvFile,
|
||||
repoRoot,
|
||||
writeRootEnvFile,
|
||||
} from "./root-env.mjs";
|
||||
|
||||
function requireCmd(bin, hint, versionArgs = ["--version"]) {
|
||||
const r = spawnSync(bin, versionArgs, {
|
||||
encoding: "utf8",
|
||||
shell: process.platform === "win32",
|
||||
});
|
||||
if (r.error || r.status !== 0) {
|
||||
console.error(`[setup] missing prerequisite: ${bin}`);
|
||||
if (hint) console.error(` ${hint}`);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
function runNodeScript(rel) {
|
||||
const script = path.join(repoRoot, rel);
|
||||
const r = spawnSync(process.execPath, [script], {
|
||||
cwd: repoRoot,
|
||||
stdio: "inherit",
|
||||
env: process.env,
|
||||
});
|
||||
if (r.status !== 0) process.exit(r.status ?? 1);
|
||||
}
|
||||
|
||||
function runDockerCompose(args) {
|
||||
const r = spawnSync("docker", ["compose", ...args], {
|
||||
cwd: repoRoot,
|
||||
stdio: "inherit",
|
||||
shell: process.platform === "win32",
|
||||
});
|
||||
if (r.status !== 0) process.exit(r.status ?? 1);
|
||||
}
|
||||
|
||||
function ensureEnvFile() {
|
||||
const dest = dotenvPath();
|
||||
if (fs.existsSync(dest)) {
|
||||
console.log(`[setup] using existing ${path.relative(repoRoot, dest)}`);
|
||||
return;
|
||||
}
|
||||
const example = path.join(repoRoot, ".env.example");
|
||||
if (!fs.existsSync(example)) {
|
||||
console.error("[setup] .env.example missing");
|
||||
process.exit(1);
|
||||
}
|
||||
fs.copyFileSync(example, dest);
|
||||
console.log(`[setup] created ${path.relative(repoRoot, dest)} from .env.example`);
|
||||
}
|
||||
|
||||
function fillEmptySecrets() {
|
||||
const text = readRootEnvFile();
|
||||
if (text == null) return;
|
||||
const parsed = parseEnvFile(text);
|
||||
const need = [];
|
||||
for (const key of ["TOKEN_SIGNING_SECRET", "APP_ENCRYPTION_KEY"]) {
|
||||
if (!parsed[key] || !String(parsed[key]).trim()) need.push(key);
|
||||
}
|
||||
if (need.length === 0) return;
|
||||
|
||||
let next = text;
|
||||
for (const key of need) {
|
||||
const secret = crypto.randomBytes(32).toString("hex");
|
||||
const lineRe = new RegExp(`^(\\s*${key}\\s*=\\s*).*$`, "m");
|
||||
if (lineRe.test(next)) {
|
||||
next = next.replace(lineRe, `$1${secret}`);
|
||||
} else {
|
||||
next = `${next.trimEnd()}\n${key}=${secret}\n`;
|
||||
}
|
||||
console.log(`[setup] generated local ${key} (not committed)`);
|
||||
}
|
||||
writeRootEnvFile(next);
|
||||
}
|
||||
|
||||
console.log("==> Descrybe local setup");
|
||||
requireCmd("node", "Install Node.js 20+ from https://nodejs.org/");
|
||||
// Go uses `go version`, not `go --version`.
|
||||
requireCmd("go", "Install Go 1.25+ from https://go.dev/dl/", ["version"]);
|
||||
requireCmd("docker", "Install Docker Desktop / Docker Engine with Compose v2");
|
||||
|
||||
ensureEnvFile();
|
||||
fillEmptySecrets();
|
||||
|
||||
console.log("==> docker compose up -d (Postgres on host :5433)");
|
||||
runDockerCompose(["up", "-d"]);
|
||||
|
||||
console.log("==> wait for Postgres");
|
||||
runNodeScript("scripts/wait-postgres.mjs");
|
||||
|
||||
console.log("==> migrate");
|
||||
runNodeScript("scripts/migrate.mjs");
|
||||
|
||||
console.log("");
|
||||
console.log("Setup complete.");
|
||||
console.log("Next:");
|
||||
console.log(" npm install");
|
||||
console.log(" npm run dev # API :28471 + web :28472 + worker");
|
||||
console.log(" npm run seed # optional demo login");
|
||||
console.log(" npm run health # /healthz + /readyz (needs worker)");
|
||||
console.log("");
|
||||
console.log("Web: http://localhost:28472");
|
||||
console.log("API: http://localhost:28471");
|
||||
Reference in New Issue
Block a user