From abc06e438cc79cf1900f4b964e50476f0531b1cd Mon Sep 17 00:00:00 2001 From: openhands Date: Tue, 11 Aug 2026 17:08:23 +0200 Subject: [PATCH] fix: load .env in standalone tsx scripts --- scripts/apply-migrations.ts | 1 + scripts/jobs-worker.ts | 1 + scripts/load-env.ts | 19 +++++++++++++++++++ 3 files changed, 21 insertions(+) create mode 100644 scripts/load-env.ts diff --git a/scripts/apply-migrations.ts b/scripts/apply-migrations.ts index f4bcc18e..9f2484ba 100644 --- a/scripts/apply-migrations.ts +++ b/scripts/apply-migrations.ts @@ -1,3 +1,4 @@ +import "./load-env"; import { readdirSync, readFileSync } from "node:fs"; import { dirname, resolve } from "node:path"; import { fileURLToPath } from "node:url"; diff --git a/scripts/jobs-worker.ts b/scripts/jobs-worker.ts index 9567d797..c89d137d 100644 --- a/scripts/jobs-worker.ts +++ b/scripts/jobs-worker.ts @@ -1,3 +1,4 @@ +import "./load-env"; import { Cron } from "croner"; import { lt, sql } from "drizzle-orm"; import { env } from "../src/env"; diff --git a/scripts/load-env.ts b/scripts/load-env.ts new file mode 100644 index 00000000..99740d85 --- /dev/null +++ b/scripts/load-env.ts @@ -0,0 +1,19 @@ +import { existsSync } from "node:fs"; +import { dirname, resolve } from "node:path"; +import { fileURLToPath } from "node:url"; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const ROOT = resolve(__dirname, ".."); + +// Standalone scripts (tsx) don't auto-load .env like Next.js does, so the +// deploy step symlinks ${LIVE}/.env into the stage but nothing ever read it. +// Node's loadEnvFile() never overrides already-set variables, so real shell +// env wins; we load .env.local first so it takes precedence over .env. +function loadEnvFile(): void { + for (const name of [".env.local", ".env"]) { + const file = resolve(ROOT, name); + if (existsSync(file)) process.loadEnvFile(file); + } +} + +loadEnvFile();