From 8f747ef62d9df573981bebd11e11a05c5d921c35 Mon Sep 17 00:00:00 2001 From: cyphercodes Date: Thu, 8 Oct 2026 07:27:43 +0300 Subject: [PATCH] fix: resolve dotenv forward references --- .../src/internal-utils/__tests__/env.test.ts | 24 ++++++++++++++++--- .../internal-utils/__tests__/fixtures/.env | 4 ++++ .../__tests__/fixtures/.env.local | 2 ++ packages/wxt/src/internal-utils/env-utils.ts | 11 ++++++--- 4 files changed, 35 insertions(+), 6 deletions(-) create mode 100644 packages/wxt/src/internal-utils/__tests__/fixtures/.env.local diff --git a/packages/wxt/src/internal-utils/__tests__/env.test.ts b/packages/wxt/src/internal-utils/__tests__/env.test.ts index c1e3289e1..a21216c19 100644 --- a/packages/wxt/src/internal-utils/__tests__/env.test.ts +++ b/packages/wxt/src/internal-utils/__tests__/env.test.ts @@ -8,6 +8,11 @@ describe('Env Utils', () => { if (process.cwd() !== cwd) process.chdir(cwd); delete process.env.TEST_VAR; delete process.env.EXPANDED; + delete process.env.LOCAL_VAR; + delete process.env.EXPANDED_FROM_LOCAL; + delete process.env.OVERRIDDEN; + delete process.env.EXPANDED_OVERRIDE; + delete process.env.UNRESOLVED; }); describe('isCI', () => { @@ -53,11 +58,24 @@ describe('Env Utils', () => { expect(process.env.TEST_VAR).toEqual('non-blank'); }); - // Node doesn't return vars in the same order as they're defined: - // https://github.com/nodejs/node/issues/62736 - it.skip('should expand env vars into the real `process.env`', () => { + it('should expand env vars into the real `process.env`', () => { loadEnv('testing', 'chrome'); expect(process.env.EXPANDED).toEqual('expected expanded'); }); + + it('should expand env vars defined in more specific files', () => { + loadEnv('testing', 'chrome'); + expect(process.env.EXPANDED_FROM_LOCAL).toEqual('local expanded'); + }); + + it('should expand the value from the most specific file', () => { + loadEnv('testing', 'chrome'); + expect(process.env.EXPANDED_OVERRIDE).toEqual('local expanded'); + }); + + it('should expand unresolved env vars to empty strings', () => { + loadEnv('testing', 'chrome'); + expect(process.env.UNRESOLVED).toEqual(' unresolved'); + }); }); }); diff --git a/packages/wxt/src/internal-utils/__tests__/fixtures/.env b/packages/wxt/src/internal-utils/__tests__/fixtures/.env index a6fd32b1f..2a087fa14 100644 --- a/packages/wxt/src/internal-utils/__tests__/fixtures/.env +++ b/packages/wxt/src/internal-utils/__tests__/fixtures/.env @@ -1,2 +1,6 @@ TEST_VAR="expected" EXPANDED="$TEST_VAR expanded" +EXPANDED_FROM_LOCAL="$LOCAL_VAR expanded" +OVERRIDDEN="general" +EXPANDED_OVERRIDE="$OVERRIDDEN expanded" +UNRESOLVED="$MISSING unresolved" diff --git a/packages/wxt/src/internal-utils/__tests__/fixtures/.env.local b/packages/wxt/src/internal-utils/__tests__/fixtures/.env.local new file mode 100644 index 000000000..457af6b3f --- /dev/null +++ b/packages/wxt/src/internal-utils/__tests__/fixtures/.env.local @@ -0,0 +1,2 @@ +LOCAL_VAR="local" +OVERRIDDEN="local" diff --git a/packages/wxt/src/internal-utils/env-utils.ts b/packages/wxt/src/internal-utils/env-utils.ts index 1fa799d89..94bdb4abb 100644 --- a/packages/wxt/src/internal-utils/env-utils.ts +++ b/packages/wxt/src/internal-utils/env-utils.ts @@ -37,9 +37,14 @@ export function loadEnv(mode: string, browser: TargetBrowser) { }), ); - expand({ - parsed, - }); + // Expand against the complete parsed set so references are independent of + // parseEnv's key order. Existing non-empty process.env values still win. + const processEnv = { ...parsed }; + for (const [key, value] of Object.entries(process.env)) { + if (value) processEnv[key] = value; + } + expand({ parsed, processEnv }); + Object.assign(process.env, parsed); return parsed; }