Skip to content

Commit eaba496

Browse files
committed
feat(angular): use builder configuration (#67)
1 parent f2878ab commit eaba496

File tree

13 files changed

+260
-16
lines changed

13 files changed

+260
-16
lines changed

.github/workflows/release.yml

-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ jobs:
2121
pnpm i
2222
pnpm build
2323
pnpm build:docs
24-
cp README.md packages/cli/README.md
2524
- name: Publish @dotenv-run packages
2625
id: changesets
2726
uses: changesets/action@v1

examples/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
"e2e:all": "nx run-many --target=e2e --all --parallel"
99
},
1010
"devDependencies": {
11-
"@dotenv-run/cli": "^1.3.0",
11+
"@dotenv-run/cli": "^1.3.1",
1212
"@dotenv-run/load": "^1.3.0",
1313
"@dotenv-run/webpack": "^1.3.0",
1414
"@dotenv-run/rollup": "^1.3.0",

packages/angular/src/builders/application/index.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import {
22
BuilderContext,
33
createBuilder,
44
fromAsyncIterable,
5+
targetFromTargetString,
56
} from "@angular-devkit/architect";
67
import {
78
ApplicationBuilderOptions,
@@ -14,6 +15,7 @@ import { indexHtml } from "../utils/esbuild-index-html";
1415
import { getProjectCwd } from "../utils/project";
1516
import { NgxEnvSchema } from "../ngx-env/ngx-env-schema";
1617
import { join } from "path";
18+
import { getEnvironment } from "../utils/get-environment";
1719

1820
export const buildWithPlugin = (
1921
options: ApplicationBuilderOptions & NgxEnvSchema,
@@ -22,7 +24,11 @@ export const buildWithPlugin = (
2224
const dotEnvOptions: DotenvRunOptions = options.ngxEnv;
2325
return from(getProjectCwd(context)).pipe(
2426
switchMap((cwd) => {
25-
const { full, raw } = env({ ...dotEnvOptions, cwd });
27+
const { full, raw } = env({
28+
...dotEnvOptions,
29+
cwd,
30+
environment: getEnvironment(context.target.configuration),
31+
});
2632
return fromAsyncIterable(
2733
buildApplication(options, context, [dotenvRunDefine(full)])
2834
).pipe(

packages/angular/src/builders/browser/index.ts

+8-3
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@ import {
33
BrowserBuilderOptions,
44
executeBrowserBuilder,
55
} from "@angular-devkit/build-angular";
6-
import { NgxEnvSchema } from "../ngx-env/ngx-env-schema";
7-
import { plugin } from "../utils/webpack-plugin";
86
import { from, switchMap } from "rxjs";
7+
import { NgxEnvSchema } from "../ngx-env/ngx-env-schema";
8+
import { getEnvironment } from "../utils/get-environment";
99
import { getProjectCwd } from "../utils/project";
10+
import { plugin } from "../utils/webpack-plugin";
1011

1112
export const buildWithPlugin = (
1213
options: BrowserBuilderOptions & NgxEnvSchema,
@@ -17,7 +18,11 @@ export const buildWithPlugin = (
1718
executeBrowserBuilder(
1819
options,
1920
context,
20-
plugin({ ...options.ngxEnv, cwd })
21+
plugin({
22+
...options.ngxEnv,
23+
cwd,
24+
environment: getEnvironment(context.target.configuration),
25+
})
2126
)
2227
)
2328
);

packages/angular/src/builders/dev-server/index.ts

+7-3
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,17 @@ import {
88
DevServerBuilderOutput,
99
executeDevServerBuilder,
1010
} from "@angular-devkit/build-angular";
11+
import { env } from "@dotenv-run/core";
1112
import {
1213
DotenvRunOptions,
1314
dotenvRunDefine as esbuildPlugin,
1415
} from "@dotenv-run/esbuild";
1516
import { Observable, combineLatest, switchMap } from "rxjs";
17+
import { NgxEnvSchema } from "../ngx-env/ngx-env-schema";
1618
import { devServerIndexHtml } from "../utils/esbuild-index-html";
19+
import { getEnvironment } from "../utils/get-environment";
1720
import { getProjectCwd } from "../utils/project";
18-
import { NgxEnvSchema } from "../ngx-env/ngx-env-schema";
1921
import { plugin as webpackPlugin } from "../utils/webpack-plugin";
20-
import { env } from "@dotenv-run/core";
2122

2223
export const buildWithPlugin = (
2324
options: DevServerBuilderOptions & NgxEnvSchema,
@@ -43,7 +44,10 @@ export const buildWithPlugin = (
4344
};
4445
if (builderName === "@ngx-env/builder:application") {
4546
options.forceEsbuild = true;
46-
const { full, raw } = env(ngxEnvOptions);
47+
const { full, raw } = env({
48+
...ngxEnvOptions,
49+
environment: getEnvironment(buildTarget.configuration),
50+
});
4751
return executeDevServerBuilder(
4852
options,
4953
context,

packages/angular/src/builders/extract-i18n/index.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
import { getProjectCwd } from "../utils/project";
77
import { NgxEnvSchema } from "../ngx-env/ngx-env-schema";
88
import { plugin } from "../utils/webpack-plugin";
9+
import { getEnvironment } from "../utils/get-environment";
910

1011
export const buildWithPlugin = (
1112
options: ExtractI18nBuilderOptions & NgxEnvSchema,
@@ -15,7 +16,11 @@ export const buildWithPlugin = (
1516
executeExtractI18nBuilder(
1617
options,
1718
context,
18-
plugin({ ...options.ngxEnv, cwd })
19+
plugin({
20+
...options.ngxEnv,
21+
cwd,
22+
environment: getEnvironment(context.target.configuration),
23+
})
1924
)
2025
);
2126
};

packages/angular/src/builders/karma/index.ts

+10-1
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,23 @@ import { NgxEnvSchema } from "../ngx-env/ngx-env-schema";
77
import { plugin } from "../utils/webpack-plugin";
88
import { from, switchMap } from "rxjs";
99
import { getProjectCwd } from "../utils/project";
10+
import { getEnvironment } from "../utils/get-environment";
1011

1112
export const buildWithPlugin = (
1213
options: KarmaBuilderOptions & NgxEnvSchema,
1314
context: BuilderContext
1415
): ReturnType<typeof executeKarmaBuilder> => {
1516
return from(getProjectCwd(context)).pipe(
1617
switchMap((cwd: string) =>
17-
executeKarmaBuilder(options, context, plugin({ ...options.ngxEnv, cwd }))
18+
executeKarmaBuilder(
19+
options,
20+
context,
21+
plugin({
22+
...options.ngxEnv,
23+
cwd,
24+
environment: getEnvironment(context.target.configuration),
25+
})
26+
)
1827
)
1928
);
2029
};

packages/angular/src/builders/server/index.ts

+12-3
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,28 @@ import { NgxEnvSchema } from "../ngx-env/ngx-env-schema";
77
import { plugin } from "../utils/webpack-plugin";
88
import { from, switchMap } from "rxjs";
99
import { getProjectCwd } from "../utils/project";
10+
import { getEnvironment } from "../utils/get-environment";
1011

1112
export const buildWithPlugin = (
1213
options: ServerBuilderOptions & NgxEnvSchema,
1314
context: BuilderContext
14-
): ReturnType<typeof executeServerBuilder> =>
15-
from(getProjectCwd(context)).pipe(
15+
): ReturnType<typeof executeServerBuilder> => {
16+
return from(getProjectCwd(context)).pipe(
1617
switchMap((cwd: string) =>
1718
executeServerBuilder(
1819
options,
1920
context,
20-
plugin({ ...options.ngxEnv, cwd }, true)
21+
plugin(
22+
{
23+
...options.ngxEnv,
24+
cwd,
25+
environment: getEnvironment(context.target.configuration),
26+
},
27+
true
28+
)
2129
)
2230
)
2331
);
32+
};
2433

2534
export default createBuilder<ServerBuilderOptions>(buildWithPlugin);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export function getEnvironment(configuration: string) {
2+
return (
3+
process.env.NG_APP_ENV || // @deprecated
4+
process.env.NODE_ENV || // default in @dotenv-run/core
5+
configuration // default in @angular-devkit/build-angular
6+
);
7+
}

packages/cli/CHANGELOG.md

+6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# @dotenv-run/cli
22

3+
## 1.3.1
4+
5+
### Patch Changes
6+
7+
- docs: add README.md
8+
39
## 1.3.0
410

511
### Minor Changes

packages/cli/README.md

+194
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
<h1>@dotenv-run/cli</h1>
2+
3+
A CLI tool to load command line and .env environment variables with monorepo support.
4+
5+
- ✅ Loading environment variables from the command line `API_BASE=/v1/ dotenv-run -- npm start`
6+
- ✅ Load environment variables from `.env` files
7+
- ✅ Expand environment variables `API_URL=$API_BASE/users`
8+
- ✅ Define environment variables for a specific (e.g. `.env.production`)
9+
- ✅ Load priorities of `.env.*` files (e.g. `.env.production` > `.env`)
10+
- ✅ Supports hierarchical cascading configuration in monorepo projects ([Nx](https://nx.dev), [Turbo](https://turbo.build/), etc.)
11+
`apps/next-app/.env` > `apps/.env` > `.env`
12+
- ✅ Supports all platforms and languages (Node.js, Python...) `dotenv-run -- python main.py`
13+
14+
# Quick Start
15+
16+
## Installation
17+
18+
```sh
19+
npm add -D @dotenv-run/cli
20+
```
21+
22+
## Prompt
23+
24+
```sh
25+
$> dotenv-run -h
26+
27+
Usage: dotenv-run [options] -- <command>
28+
29+
Options:
30+
31+
-h, --help output usage information
32+
-e, --env environment name (e.g. dev, prod)
33+
-s, --silent do not print .env file paths
34+
-r, --root root directory to search for .env files
35+
36+
Examples:
37+
38+
dotenv-run -- npm start
39+
dotenv-run -r ../.. -- npm start
40+
dotenv-run -e prod -- npm start
41+
```
42+
43+
## Usage
44+
45+
In addition to loading environment variables, **@dotenv-run/cli** supports monorepo projects with multiple applications.
46+
47+
In a monorepo configuration, `.env.*` files can be defined in the root workspace and overriden by each application.
48+
49+
**Root workspace**
50+
51+
`dotenv-run` will search and load `.env.*` files located in the root workspace down to the current working directory.
52+
53+
If no root workspace is found, `dotenv-run` will load environment files within the current working directory.
54+
55+
You can specify a root workspace with the `-r` option.
56+
57+
**Example**
58+
59+
Given the following files:
60+
61+
```sh
62+
platform
63+
├── apps
64+
│ ├── frontend1
65+
│ │ ├── .env.local # API_USERS=http://localhost:3001/users
66+
│ │ └── vite.config.js
67+
│ └── frontend2
68+
│ ├── package.json
69+
│ └── webapp.config.mjs
70+
├── .env.dev # API_BASE=https://dotenv-run.dev
71+
├── .env.prod # API_BASE=https://dotenv-run.app
72+
├── .env # API_USERS=$API_BASE/api/v1/users API_AUTH=https://$API_BASE/auth
73+
├── nx.json
74+
└── package.json
75+
```
76+
77+
```sh
78+
$> cd /platform
79+
$> dotenv-run -e prod -- bash -c 'echo "✨ $API_USERS"'
80+
✔ /platform/.env.prod
81+
✔ /platform/.env
82+
✨ https://dotenv-run.app/api/v1/users
83+
```
84+
85+
```sh
86+
$> cd /platform/apps/frontend1
87+
$> dotenv-run -e dev -- bash -c 'printf "✨ API_USERS $API_USERS\n✨ API_AUTH $API_AUTH"'
88+
✔ /platform/apps/frontend1/.env.local
89+
✔ /platform/.env.dev
90+
✔ /platform/.env
91+
✨ API_USERS http://localhost:3001/users
92+
✨ API_AUTH https://dotenv-run.dev/api/v1/auth
93+
```
94+
95+
```sh
96+
$> cd /platform/apps/frontend2
97+
$> API_BASE=$CI_CONTAINER_API dotenv-run -- bash -c 'echo "✨ $API_USERS"'
98+
✔ /platform/.env
99+
✨ https://XAE221D1DE-ci-provider.cloud/api/v1/users
100+
101+
# CI_CONTAINER_API could be an environment variable provided by some CI provider
102+
```
103+
104+
**-r option**
105+
106+
```sh
107+
$> cd /platform/apps/frontend1
108+
$> dotenv-run -r . -- bash -c 'echo "✨ $API_USERS"'
109+
✔ /platform/apps/frontend1/.env.local
110+
✨ http://localhost:3001/users
111+
```
112+
113+
Paths to the root workspace can be relative or absolute, the following are all valid :
114+
115+
- ` -r ../..`
116+
- ` -r ../...env`
117+
- ` -r /platform`
118+
- ` -r /platform/.env`
119+
120+
## Loading Priorities
121+
122+
`@dotenv-run/cli` uses [dotenv](https://github.com/motdotla/dotenv) to support loading environment variables from `.env` files.
123+
124+
`@dotenv-run/cli` loads `.env` files with these specific names for the following `-e ENV` value, files on the top have less priority than files on the bottom.
125+
126+
An env file for a specific mode (e.g. .env.production) will take higher priority than a generic one (e.g. .env).
127+
128+
| valid `.env` filenames | `ENV=*` | `ENV=test` |
129+
| ---------------------- | ------- | ---------- |
130+
| `.env` | ✔️ | ✔️ |
131+
| `.env.local` | ✔️ | ✖️ |
132+
| `.env.${ENV}` | ✔️ | ✔️ |
133+
| `.env.${ENV}.local` | ✔️ | ✔️ |
134+
135+
In addition, environment variables that already exist when the CLI is executed have the highest priority and will not be overwritten by .env files. For example, when running `SOME_KEY=123 dotenv-run`.
136+
137+
## Expanding `.env`
138+
139+
You can expand variables already available on your machine for use in your `.env`
140+
141+
For example:
142+
143+
```shell
144+
VERSION=$npm_package_version
145+
HOSTNAME=$HOSTNAME
146+
```
147+
148+
Or expand variables local to the current `.env` file:
149+
150+
```shell
151+
DOMAIN=www.example.com
152+
FOO=$DOMAIN/foo
153+
BAR=$DOMAIN/bar
154+
```
155+
156+
## Command Line
157+
158+
Defining environment variables can vary between OSes. It’s also important to know that this manner is temporary for the life of the shell session.
159+
160+
### Windows (cmd.exe)
161+
162+
```cmd
163+
set "API_URL=abcdef" && dotenv-run -- npm start
164+
```
165+
166+
(Note: Quotes around the variable assignment are required to avoid a trailing whitespace.)
167+
168+
### Windows (Powershell)
169+
170+
```Powershell
171+
($env:API_URL = "abcdef") -and (dotenv-run -- npm start)
172+
```
173+
174+
### Linux, macOS (Bash)
175+
176+
```sh
177+
API_URL=abcdef dotenv-run -- npm start
178+
```
179+
180+
# In the browser
181+
182+
In order to consume environment variables in your webapps, you need to expose them to the browser. The bundler you use will need to support replacing the environment variables at build time.
183+
184+
**React, Vue.js...**
185+
186+
Use [Vite](https://vitejs.dev/guide/env-and-mode.html)
187+
188+
**Angular**
189+
190+
Use [@ngx-env/builder](https://www.npmjs.com/package/@ngx-env/builder)
191+
192+
# License
193+
194+
MIT © [Chihab Otmani](https://twitter.com/chihabotmani)

0 commit comments

Comments
 (0)