#!/usr/bin/env node const fs = require('node:fs') const path = require('node:path') const { spawn } = require('node:child_process') function parseEnvFile(content) { const env = {} for (const rawLine of content.split(/\r?\n/)) { const line = rawLine.trim() if (!line || line.startsWith('#')) continue const normalized = line.startsWith('export ') ? line.slice(7).trim() : line const separatorIndex = normalized.indexOf('=') if (separatorIndex === -1) continue const key = normalized.slice(0, separatorIndex).trim() if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key)) continue let value = normalized.slice(separatorIndex + 1) if ( (value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'")) ) { const quote = value[0] value = value.slice(1, -1) if (quote === '"') { value = value .replace(/\\n/g, '\n') .replace(/\\r/g, '\r') .replace(/\\t/g, '\t') .replace(/\\"/g, '"') .replace(/\\\\/g, '\\') } } env[key] = value } return env } const [, , envFileArg, commandArg, ...commandArgs] = process.argv if (!envFileArg || !commandArg) { console.error('Usage: node run-with-env-file.cjs [args...]') process.exit(1) } const envFilePath = path.resolve(process.cwd(), envFileArg) const commandPath = path.resolve(process.cwd(), commandArg) const fileContent = fs.readFileSync(envFilePath, 'utf8') const parsedEnv = parseEnvFile(fileContent) const child = spawn(commandPath, commandArgs, { stdio: 'inherit', env: { ...process.env, ...parsedEnv, }, }) child.on('exit', (code, signal) => { if (signal) { process.kill(process.pid, signal) return } process.exit(code ?? 0) }) child.on('error', (error) => { console.error(error.message) process.exit(1) })