From d36d69e27554a073d5ea498398579556a9ce2d0c Mon Sep 17 00:00:00 2001 From: Mohd Salauddin Date: Mon, 3 Aug 2026 21:11:14 +0530 Subject: [PATCH] Align CLI dotenv parsing with the runtime --- cli/src/util.ts | 10 ++++++++-- cli/test/util.test.ts | 8 ++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/cli/src/util.ts b/cli/src/util.ts index c4da960f..ca118ab5 100644 --- a/cli/src/util.ts +++ b/cli/src/util.ts @@ -217,12 +217,18 @@ export function readEnvFile(path: string): Map { const out = new Map(); if (!existsSync(path)) return out; for (const raw of readFileSync(path, "utf8").split("\n")) { - const line = raw.trim(); + let line = raw.trim(); if (!line || line.startsWith("#")) continue; + if (line.startsWith("export ")) line = line.slice(7).trimStart(); const eq = line.indexOf("="); if (eq <= 0) continue; const key = line.slice(0, eq).trim(); - if (isEnvVarName(key)) out.set(key, line.slice(eq + 1)); + if (!isEnvVarName(key)) continue; + let val = line.slice(eq + 1).trim(); + if ((val.startsWith('"') && val.endsWith('"')) || (val.startsWith("'") && val.endsWith("'"))) { + val = val.slice(1, -1); + } + out.set(key, val); } return out; } diff --git a/cli/test/util.test.ts b/cli/test/util.test.ts index f4a661ef..a47aed54 100644 --- a/cli/test/util.test.ts +++ b/cli/test/util.test.ts @@ -41,16 +41,20 @@ test("canonicalJson sorts keys and matches JSON.stringify's undefined semantics" } }); -test("readEnvFile preserves hashes in unquoted values", (t) => { +test("readEnvFile preserves hashes in unquoted values and strips export/quotes", (t) => { const dir = mkdtempSync(join(tmpdir(), "qm-env-")); t.after(() => rmSync(dir, { recursive: true, force: true })); const file = join(dir, ".env"); - writeFileSync(file, "# ignored\nTOKEN=abc#def\nURL=https://host/path#fragment\n"); + writeFileSync( + file, + '# ignored\nTOKEN=abc#def\nURL="https://host/path#fragment"\nexport SECRET=\'mysecret\'\n', + ); assert.deepEqual( [...readEnvFile(file)], [ ["TOKEN", "abc#def"], ["URL", "https://host/path#fragment"], + ["SECRET", "mysecret"], ], ); });