#!/usr/bin/env node import { randomBytes } from "node:crypto"; import { copyFileSync, existsSync, readFileSync, writeFileSync } from "node:fs"; import { join, resolve } from "node:path"; const rootDir = resolve(process.argv[2] || process.cwd()); const envPath = join(rootDir, ".env.local"); const examplePath = join(rootDir, ".env.example"); if (!existsSync(envPath)) { if (!existsSync(examplePath)) { console.error("[deploy] .env.local was not found and .env.example is missing."); process.exit(1); } copyFileSync(examplePath, envPath); console.log("[deploy] Created .env.local from .env.example"); console.log("[deploy] Real generation requires API keys in .env.local. Empty keys keep mock/local flows available."); } let envText = readFileSync(envPath, "utf8"); const token = readEnvValue(envText, "ZHINIAN_INTERNAL_WORKER_TOKEN"); if (!token || token === "change-me-worker-token") { envText = setEnvValue(envText, "ZHINIAN_INTERNAL_WORKER_TOKEN", randomBytes(32).toString("hex")); writeFileSync(envPath, envText); console.log("[deploy] Added ZHINIAN_INTERNAL_WORKER_TOKEN to .env.local"); } function readEnvValue(text, name) { const escaped = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); const match = text.match(new RegExp(`^${escaped}=(.*)$`, "m")); return match?.[1]?.trim().replace(/^['"]|['"]$/g, "") || ""; } function setEnvValue(text, name, value) { const line = `${name}=${value}`; const escaped = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); if (new RegExp(`^${escaped}=`, "m").test(text)) { return text.replace(new RegExp(`^${escaped}=.*$`, "m"), line); } const suffix = text.endsWith("\n") ? "" : "\n"; return `${text}${suffix}${line}\n`; }