Fix dev migration prompt and embedded db:migrate
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
#!/usr/bin/env node
|
||||
import { spawn } from "node:child_process";
|
||||
import { createInterface } from "node:readline/promises";
|
||||
import { stdin, stdout } from "node:process";
|
||||
|
||||
const mode = process.argv[2] === "watch" ? "watch" : "dev";
|
||||
const cliArgs = process.argv.slice(3);
|
||||
@@ -43,6 +45,121 @@ if (tailscaleAuth) {
|
||||
}
|
||||
|
||||
const pnpmBin = process.platform === "win32" ? "pnpm.cmd" : "pnpm";
|
||||
|
||||
function formatPendingMigrationSummary(migrations) {
|
||||
if (migrations.length === 0) return "none";
|
||||
return migrations.length > 3
|
||||
? `${migrations.slice(0, 3).join(", ")} (+${migrations.length - 3} more)`
|
||||
: migrations.join(", ");
|
||||
}
|
||||
|
||||
async function runPnpm(args, options = {}) {
|
||||
return await new Promise((resolve, reject) => {
|
||||
const child = spawn(pnpmBin, args, {
|
||||
stdio: options.stdio ?? ["ignore", "pipe", "pipe"],
|
||||
env: options.env ?? process.env,
|
||||
shell: process.platform === "win32",
|
||||
});
|
||||
|
||||
let stdoutBuffer = "";
|
||||
let stderrBuffer = "";
|
||||
|
||||
if (child.stdout) {
|
||||
child.stdout.on("data", (chunk) => {
|
||||
stdoutBuffer += String(chunk);
|
||||
});
|
||||
}
|
||||
if (child.stderr) {
|
||||
child.stderr.on("data", (chunk) => {
|
||||
stderrBuffer += String(chunk);
|
||||
});
|
||||
}
|
||||
|
||||
child.on("error", reject);
|
||||
child.on("exit", (code, signal) => {
|
||||
resolve({
|
||||
code: code ?? 0,
|
||||
signal,
|
||||
stdout: stdoutBuffer,
|
||||
stderr: stderrBuffer,
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function maybePreflightMigrations() {
|
||||
if (mode !== "watch") return;
|
||||
if (process.env.PAPERCLIP_MIGRATION_PROMPT === "never") return;
|
||||
|
||||
const status = await runPnpm(
|
||||
["--filter", "@paperclipai/db", "exec", "tsx", "src/migration-status.ts", "--json"],
|
||||
{ env },
|
||||
);
|
||||
if (status.code !== 0) {
|
||||
process.stderr.write(status.stderr || status.stdout);
|
||||
process.exit(status.code);
|
||||
}
|
||||
|
||||
let payload;
|
||||
try {
|
||||
payload = JSON.parse(status.stdout.trim());
|
||||
} catch (error) {
|
||||
process.stderr.write(status.stderr || status.stdout);
|
||||
throw error;
|
||||
}
|
||||
|
||||
if (payload.status !== "needsMigrations" || payload.pendingMigrations.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const autoApply = process.env.PAPERCLIP_MIGRATION_AUTO_APPLY === "true";
|
||||
let shouldApply = autoApply;
|
||||
|
||||
if (!autoApply) {
|
||||
if (!stdin.isTTY || !stdout.isTTY) {
|
||||
shouldApply = true;
|
||||
} else {
|
||||
const prompt = createInterface({ input: stdin, output: stdout });
|
||||
try {
|
||||
const answer = (
|
||||
await prompt.question(
|
||||
`Apply pending migrations (${formatPendingMigrationSummary(payload.pendingMigrations)}) now? (y/N): `,
|
||||
)
|
||||
)
|
||||
.trim()
|
||||
.toLowerCase();
|
||||
shouldApply = answer === "y" || answer === "yes";
|
||||
} finally {
|
||||
prompt.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!shouldApply) return;
|
||||
|
||||
const migrate = spawn(pnpmBin, ["db:migrate"], {
|
||||
stdio: "inherit",
|
||||
env,
|
||||
shell: process.platform === "win32",
|
||||
});
|
||||
const exit = await new Promise((resolve) => {
|
||||
migrate.on("exit", (code, signal) => resolve({ code: code ?? 0, signal }));
|
||||
});
|
||||
if (exit.signal) {
|
||||
process.kill(process.pid, exit.signal);
|
||||
return;
|
||||
}
|
||||
if (exit.code !== 0) {
|
||||
process.exit(exit.code);
|
||||
}
|
||||
}
|
||||
|
||||
await maybePreflightMigrations();
|
||||
|
||||
if (mode === "watch") {
|
||||
env.PAPERCLIP_MIGRATION_PROMPT = "never";
|
||||
}
|
||||
|
||||
const serverScript = mode === "watch" ? "dev:watch" : "dev";
|
||||
const child = spawn(
|
||||
pnpmBin,
|
||||
@@ -57,4 +174,3 @@ child.on("exit", (code, signal) => {
|
||||
}
|
||||
process.exit(code ?? 0);
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user