Files
WRNexusJS/packages/cli/src/docker.ts
T
Clintchiz 2c960fc1dc
Quality / quality (ubuntu-latest) (push) Failing after 9m49s
Quality / quality (windows-latest) (push) Canceled after 0s
refactor: migrate legacy wire namespace to wrn
2026-08-12 18:51:15 +05:30

94 lines
2.5 KiB
TypeScript

/**
* `wrnexus generate docker` — scaffold containerization for a WrNexus app:
* a multi-stage Dockerfile (build with Bun → slim runtime), a .dockerignore,
* and a docker-compose.yml (app + Postgres). Uses the app's `/healthz` endpoint
* for the container health check.
*/
import { existsSync, writeFileSync } from "node:fs";
import { join, resolve } from "node:path";
const DOCKERFILE = `# syntax=docker/dockerfile:1
# --- build stage: install deps + produce dist/server.js ---
FROM oven/bun:1 AS build
WORKDIR /app
COPY package.json bun.lock* bun.lockb* ./
RUN bun install
COPY . .
RUN bun run build
# --- runtime stage: slim image with only the built server + migrations ---
FROM oven/bun:1-slim AS runtime
WORKDIR /app
ENV NODE_ENV=production
ENV PORT=3000
COPY --from=build /app/dist ./dist
COPY --from=build /app/app/db/migrations ./app/db/migrations
EXPOSE 3000
HEALTHCHECK --interval=30s --timeout=3s --retries=3 \\
CMD bun -e "fetch('http://localhost:'+(process.env.PORT||3000)+'/healthz').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"
CMD ["bun", "dist/server.js"]
`;
const DOCKERIGNORE = `node_modules
dist
**/.wrnexus
.git
*.log
*.db
*.db-shm
*.db-wal
.DS_Store
`;
const COMPOSE = `services:
app:
build: .
ports:
- "3000:3000"
environment:
NODE_ENV: production
PORT: "3000"
DATABASE_URL: postgres://wrn:wrn@db:5432/app
depends_on:
db:
condition: service_healthy
restart: unless-stopped
db:
image: postgres:16-alpine
environment:
POSTGRES_USER: wrn
POSTGRES_PASSWORD: wrn
POSTGRES_DB: app
healthcheck:
test: ["CMD-SHELL", "pg_isready -U wrn -d app"]
interval: 3s
timeout: 3s
retries: 20
volumes:
- pgdata:/var/lib/postgresql/data
volumes:
pgdata:
`;
function writeIfAbsent(path: string, content: string, name: string): void {
if (existsSync(path)) {
console.warn(` • ${name} already exists — skipped`);
return;
}
writeFileSync(path, content, "utf8");
console.log(` ✓ ${name}`);
}
/** Scaffold Dockerfile, .dockerignore, and docker-compose.yml into `appRoot`. */
export function generateDocker(appRoot: string): void {
const root = resolve(appRoot);
console.log("Scaffolding containerization:");
writeIfAbsent(join(root, "Dockerfile"), DOCKERFILE, "Dockerfile");
writeIfAbsent(join(root, ".dockerignore"), DOCKERIGNORE, ".dockerignore");
writeIfAbsent(join(root, "docker-compose.yml"), COMPOSE, "docker-compose.yml");
console.log("\nBuild + run: docker compose up --build");
}