#!/usr/bin/env node import { spawn } from 'node:child_process' import fs from 'node:fs' import path from 'node:path' import { fileURLToPath } from 'node:url' const __filename = fileURLToPath(import.meta.url) const __dirname = path.dirname(__filename) const projectRoot = path.resolve(__dirname, '..') const envFile = path.join(projectRoot, '.env.development.local') const args = process.argv.slice(2) function parseEnvFile(filePath) { const values = {} const raw = fs.readFileSync(filePath, 'utf8') for (const line of raw.split(/\r?\n/)) { const trimmed = line.trim() if (!trimmed || trimmed.startsWith('#')) continue const normalized = trimmed.startsWith('export ') ? trimmed.slice(7).trim() : trimmed const eqIndex = normalized.indexOf('=') if (eqIndex <= 0) continue const key = normalized.slice(0, eqIndex).trim() let value = normalized.slice(eqIndex + 1).trim() if ( (value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'")) ) { value = value.slice(1, -1) } values[key] = value } return values } function describeDatabase(url) { try { const parsed = new URL(url) const port = parsed.port ? `:${parsed.port}` : '' const database = parsed.pathname && parsed.pathname !== '/' ? parsed.pathname.slice(1) : '(default)' return { host: parsed.hostname, label: `${parsed.hostname}${port}/${database}`, } } catch { return { host: '', label: '(invalid DATABASE_URL)', } } } function isLocalDatabaseHost(host) { const normalized = host.toLowerCase() return [ 'localhost', '127.0.0.1', '::1', '[::1]', 'host.docker.internal', ].includes(normalized) } if (args.length === 0) { console.error('Usage: npm run prisma:dev -- ') console.error('Example: npm run prisma:dev -- migrate status') process.exit(1) } if (!fs.existsSync(envFile)) { console.error('[prisma-local-dev] Missing .env.development.local.') console.error('[prisma-local-dev] Refusing to guess a database target from .env or .env.local.') process.exit(1) } const localEnv = parseEnvFile(envFile) const databaseUrl = localEnv.DATABASE_URL if (!databaseUrl) { console.error('[prisma-local-dev] .env.development.local does not define DATABASE_URL.') process.exit(1) } const database = describeDatabase(databaseUrl) if (!isLocalDatabaseHost(database.host) && process.env.ALLOW_NONLOCAL_PRISMA_DEV_DB !== '1') { console.error(`[prisma-local-dev] Refusing non-local DATABASE_URL host: ${database.host || '(unknown)'}`) console.error('[prisma-local-dev] Set ALLOW_NONLOCAL_PRISMA_DEV_DB=1 only when you intentionally need this.') process.exit(1) } const childEnv = { ...process.env, ...localEnv, } console.log(`[prisma-local-dev] Using .env.development.local -> ${database.label}`) const prismaCli = path.join(projectRoot, 'node_modules', 'prisma', 'build', 'index.js') if (!fs.existsSync(prismaCli)) { console.error('[prisma-local-dev] Prisma CLI is missing. Run npm install first.') process.exit(1) } const child = spawn(process.execPath, [prismaCli, ...args], { cwd: projectRoot, env: childEnv, stdio: 'inherit', }) child.on('exit', (code, signal) => { if (signal) { process.kill(process.pid, signal) return } process.exit(code ?? 1) })