#!/usr/bin/env node /** * Cross-platform: run a command with cwd set to a repo-relative directory. * Loads monorepo-root `.env` into the child env (does not override existing vars). * Usage: node scripts/run-in-dir.mjs [args...] */ import { spawn } from "node:child_process"; import fs from "node:fs"; import path from "node:path"; import { fileURLToPath } from "node:url"; const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".."); const [relDir, ...cmd] = process.argv.slice(2); if (!relDir || cmd.length === 0) { console.error("Usage: node scripts/run-in-dir.mjs [args...]"); process.exit(1); } function loadRootEnv(env) { const dotenvPath = process.env.DOTENV_PATH ? path.resolve(process.env.DOTENV_PATH) : path.join(root, ".env"); let text; try { text = fs.readFileSync(dotenvPath, "utf8"); } catch { return env; } const out = { ...env }; for (const raw of text.split(/\r?\n/)) { let line = raw.trim(); if (!line || line.startsWith("#")) continue; if (line.startsWith("export ")) line = line.slice(7).trim(); const eq = line.indexOf("="); if (eq <= 0) continue; const key = line.slice(0, eq).trim(); if (!key || Object.prototype.hasOwnProperty.call(out, key)) continue; let val = line.slice(eq + 1).trim(); if ( (val.startsWith('"') && val.endsWith('"')) || (val.startsWith("'") && val.endsWith("'")) ) { val = val.slice(1, -1); } out[key] = val; } return out; } const cwd = path.join(root, relDir); const [command, ...args] = cmd; const child = spawn(command, args, { cwd, stdio: "inherit", shell: process.platform === "win32", env: loadRootEnv(process.env), }); child.on("exit", (code, signal) => { if (signal) { process.kill(process.pid, signal); return; } process.exit(code ?? 1); });