diff --git a/e2e/nx-misc/src/extras.test.ts b/e2e/nx-misc/src/extras.test.ts index 1297adbf6985e..5949da61785af 100644 --- a/e2e/nx-misc/src/extras.test.ts +++ b/e2e/nx-misc/src/extras.test.ts @@ -273,4 +273,51 @@ describe('Extra Nx Misc Tests', () => { expect(output).not.toContain('Installed'); }); }); + + describe('Env File', () => { + it('should have the right env', () => { + const appName = uniq('app'); + runCLI( + `generate @nx/react:app ${appName} --style=css --bundler=webpack --no-interactive` + ); + updateFile( + '.env', + `FIRSTNAME="firstname" + LASTNAME="lastname" + NX_USERNAME=$FIRSTNAME $LASTNAME` + ); + updateFile( + `apps/${appName}/src/app/app.tsx`, + ` + import NxWelcome from './nx-welcome'; + + export function App() { + return ( + <> + + + ); + } + + export default App; + ` + ); + updateFile( + `apps/${appName}/src/app/app.spec.tsx`, + `import { render } from '@testing-library/react'; + + import App from './app'; + + describe('App', () => { + it('should have a greeting as the title', () => { + const { getByText } = render(); + expect(getByText(/Welcome firstname lastname/gi)).toBeTruthy(); + }); + }); + ` + ); + const unitTestsOutput = runCLI(`test ${appName}`); + expect(unitTestsOutput).toContain('Successfully ran target test'); + }); + }); }); diff --git a/package.json b/package.json index 2dd062390260a..0a921f1c800d6 100644 --- a/package.json +++ b/package.json @@ -158,6 +158,7 @@ "czg": "^1.4.0", "detect-port": "^1.5.1", "dotenv": "~16.3.1", + "dotenv-expand": "^10.0.0", "ejs": "^3.1.7", "enhanced-resolve": "^5.8.3", "esbuild": "^0.17.5", diff --git a/packages/nx/bin/nx.ts b/packages/nx/bin/nx.ts index 6851730d816cf..8755ad02ae3b1 100644 --- a/packages/nx/bin/nx.ts +++ b/packages/nx/bin/nx.ts @@ -5,6 +5,7 @@ import { } from '../src/utils/find-workspace-root'; import * as chalk from 'chalk'; import { config as loadDotEnvFile } from 'dotenv'; +import { expand } from 'dotenv-expand'; import { initLocal } from './init-local'; import { output } from '../src/utils/output'; import { @@ -109,9 +110,10 @@ function main() { */ function loadDotEnvFiles() { for (const file of ['.local.env', '.env.local', '.env']) { - loadDotEnvFile({ + const myEnv = loadDotEnvFile({ path: file, }); + expand(myEnv); } } diff --git a/packages/nx/package.json b/packages/nx/package.json index ba3402bc61d3d..df38a9d3d9862 100644 --- a/packages/nx/package.json +++ b/packages/nx/package.json @@ -42,6 +42,7 @@ "cli-spinners": "2.6.1", "cliui": "^7.0.2", "dotenv": "~16.3.1", + "dotenv-expand": "~10.0.0", "enquirer": "~2.3.6", "fast-glob": "3.2.7", "figures": "3.2.0", diff --git a/packages/nx/src/tasks-runner/forked-process-task-runner.ts b/packages/nx/src/tasks-runner/forked-process-task-runner.ts index f91a0631fe790..22a90dab04907 100644 --- a/packages/nx/src/tasks-runner/forked-process-task-runner.ts +++ b/packages/nx/src/tasks-runner/forked-process-task-runner.ts @@ -1,5 +1,6 @@ import { readFileSync, writeFileSync } from 'fs'; import { config as loadDotEnvFile } from 'dotenv'; +import { expand } from 'dotenv-expand'; import { ChildProcess, fork, Serializable } from 'child_process'; import * as chalk from 'chalk'; import * as logTransformer from 'strong-log-transformer'; @@ -443,12 +444,19 @@ export class ForkedProcessTaskRunner { ]; for (const file of dotEnvFiles) { - loadDotEnvFile({ + const myEnv = loadDotEnvFile({ path: file, processEnv: environmentVariables, // Do not override existing env variables as we load override: false, }); + environmentVariables = { + ...expand({ + ...myEnv, + ignoreProcessEnv: true, // Do not override existing env variables as we load + }).parsed, + ...environmentVariables, + }; } return environmentVariables; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c2d5bd34c08b1..f376b8ceae722 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -549,6 +549,9 @@ devDependencies: dotenv: specifier: ~16.3.1 version: 16.3.1 + dotenv-expand: + specifier: ^10.0.0 + version: 10.0.0 ejs: specifier: ^3.1.7 version: 3.1.8 diff --git a/tools/documentation/create-embeddings/src/main.mts b/tools/documentation/create-embeddings/src/main.mts index 6b91be01c0b9b..f4e379ac17dbc 100644 --- a/tools/documentation/create-embeddings/src/main.mts +++ b/tools/documentation/create-embeddings/src/main.mts @@ -2,7 +2,8 @@ // https://github.com/supabase-community/nextjs-openai-doc-search/blob/main/lib/generate-embeddings.ts import { createClient } from '@supabase/supabase-js'; -import * as dotenv from 'dotenv'; +import { config as loadDotEnvFile } from 'dotenv'; +import { expand } from 'dotenv-expand'; import { readFile } from 'fs/promises'; import 'openai'; import { Configuration, OpenAIApi } from 'openai'; @@ -24,7 +25,8 @@ import manifestsTags from '../../../../docs/generated/manifests/tags.json' asser let identityMap = {}; -dotenv.config(); +const myEnv = loadDotEnvFile(); +expand(myEnv); type ProcessedMdx = { checksum: string;