Gathering detailed insights and metrics for monoenv
Gathering detailed insights and metrics for monoenv
better handling of multiple applications dotenv files in monorepos
npm install monoenv
Typescript
Module System
Node Version
NPM Version
70.3
Supply Chain
99.3
Quality
75.1
Maintenance
100
Vulnerability
99.6
License
TypeScript (95.63%)
JavaScript (4.37%)
Total Downloads
2,306
Last Day
4
Last Week
19
Last Month
119
Last Year
897
19 Stars
15 Commits
2 Watching
2 Branches
1 Contributors
Minified
Minified + Gzipped
Latest Version
1.0.3
Package Id
monoenv@1.0.3
Unpacked Size
19.84 kB
Size
6.37 kB
File Count
22
NPM Version
9.3.1
Node Version
18.14.0
Publised On
29 Mar 2023
Cumulative downloads
Total Downloads
Last day
-20%
4
Compared to previous day
Last week
-29.6%
19
Compared to previous week
Last month
-8.5%
119
Compared to previous month
Last year
-36.3%
897
Compared to previous year
4
Better handling of multiple applications dotenv files in monorepos.
Monoenv is a tool that helps you manage multiple dotenv files in a monorepo with ease in both development and production environments, with the goal of having a single source of truth yaml file that contains all of your environment variables for all of your projects that you can either combibne them under single .env
file (usually for development) or have a multiple per-application .env
file (usually for production).
Package is depending on dotenv
because you will need it to manage your generated .env
file/s.
On your monorepo root, run:
1npm i -D monoenv
Handling dotenv files in monorepos for me is a bit of pain especaially whe it comes to deployment. Since at least for turborepo you're expected to have a single .env
file that is shared between all of your projects, while this is fine for development, i didn't want to have this while deploying and building my projects' docker images.
I wanted to have a single .env
file per project, that i could feed to my docker build or docker run commands.
I would have a shared .env
file at the root of my application that contains all environement variables for my 3 services and 1 frontend application, during deployment i would have to pass the .env
file to frontend image build command and to my running services too.
1version: "3.2" 2 3services: 4 frontend: 5 container_name: frontend 6 image: frontend 7 build: 8 context: . 9 dockerfile: ./apps/frontend/Dockerfile 10 args: 11 - VITE_API_URL=${VITE_API_URL} 12 env_file: ./.env # ---- here 13 restart: always 14 15 server: 16 container_name: server 17 image: server 18 build: 19 context: . 20 dockerfile: ./apps/api/Dockerfile 21 env_file: ./.env # ---- here 22 restart: always 23 24 uploader: 25 container_name: uploader 26 image: uploader 27 build: 28 context: . 29 dockerfile: ./apps/uploader/Dockerfile 30 env_file: ./.env # ---- here 31 restart: always
Notice how i'm using the same .env
file for all of my services.
Separation of concerns is a good thing. Now i have a single .env
file for each project and can be easilly fed to docker
1version: "3.2" 2 3services: 4 frontend: 5 container_name: frontend 6 image: frontend 7 build: 8 context: . 9 dockerfile: ./apps/frontend/Dockerfile 10 args: 11 - VITE_API_URL=${VITE_API_URL} 12 restart: always 13 env_file: ./.frontend.env # ---- here 14 15 server: 16 container_name: server 17 image: server 18 build: 19 context: . 20 dockerfile: ./apps/api/Dockerfile 21 env_file: ./.server.env # ---- here 22 restart: always 23 24 uploader: 25 container_name: uploader 26 image: uploader 27 build: 28 context: . 29 dockerfile: ./apps/uploader/Dockerfile 30 env_file: ./.uploader.env # ---- here 31 restart: always
So the reason i created this so i don't worry more about .env
files no more, i just have a single .monoenv.yaml
file that i keep maintaining and do not care anymore about my environment since monoenv
will take care of generating all the files needed and i have to prepare my deployment scripts and applications accordingly.
Create a .monoenv.yaml
file in your project root directory:
1shared: true # set true if you want to combine all the environment variables in a single `.env` file 2overwrite: false # set true if you want to overwrite any existing `.env` file/s 3postfix: '.env' # set the postfix for the generated application environment file 4prefix: '.' # set the prefix for the generated application environment file 5output: '.env' # set the output file for the generated application environment file, this works only with 'shared' option set to true 6 7apps: 8 api: 9 - NODE_ENV="production" 10 - API_PORT="3000" 11 - HOST="0.0.0.0" 12 - LOG_LEVEL="info" 13 - JWT_SECRET="test" 14 - DATABASE_URL="postgres://postgres:postgres@localhost:5432/test" 15 16 uploader: 17 - NODE_ENV="production" 18 19 web: 20 - NODE_ENV="production" 21 - VITE_API_URL=localhost:3000
now you can use monoenv in by calling it in your before running your development script in package.json
:
1"scripts": { 2 "dev": "monoenv && dotenv -- turbo run dev --parallel" 3 ... 4}
Make sure you setup your monorepo to load your environment variables (e.g. on turborepo) and that have dotenv
package installed in your applications, since dev
script will generate a .env
file on the parent directory that will look like this:
NODE_ENV="production"
API_PORT="3000"
HOST="0.0.0.0"
LOG_LEVEL="info"
JWT_SECRET="test"
DATABASE_URL="postgres://postgres:postgres@localhost:5432/test"
NODE_ENV="production"
NODE_ENV="production"
VITE_API_URL="localhost:3000"
You can always use different name for your monoenv config file, then you can supply that config file as such:
1monoenv --config project.production.yaml
Although not really recommended and is not its purpose, just like you're calling dotenv.config()
as early as possible in your application, you can call monoenv.loadEnv
or monoenv.loadEnvFromConfigFile
before calling dotenv.config
to parse and create the needed dotenv files.
1import monoenv from "monoenv"; 2import * as dotenv from "dotenv"; 3monoenv.loadEnvFromConfigFile(".monoenv.yaml"); 4// monoenv.loadEnv(); // To load .monoenv.yaml|yml file by default 5dotenv.config();
Let's say you're woring on turborepo and you want to have a separate environment file for each application on production since this is the recommended way to do it. You have 3 applications api, image-uploader, and web
Now on the root of your monorepo you have a .monoenv.dev.yaml
file that looks like this:
1shared: true 2overwrite: true 3output: '.env' 4 5apps: 6 api: 7 - NODE_ENV="development" 8 - API_PORT="5000" 9 - HOST="localhost" 10 - LOG_LEVEL="debug" 11 - JWT_SECRET="supersecret" 12 - DATABASE_URL="postgres://postgres:postgres@localhost:5432/test" 13 14 uploader: 15 - NODE_ENV="development" 16 - API_URL="http://localhost:5000" 17 18 web: 19 - NODE_ENV="development" 20 - VITE_API_URL=localhost:5000
And in your package.json
file you will have:
1"scripts": { 2 "dev": "monoenv -c .monoenv.dev.yaml && dotenv -- turbo run dev --parallel", 3 ... 4}
once you run npm run dev
you'll find a new .env
file in your root directory that will be fed by dotenv-cli
to your applications.
However this is for your development environment, so for production you will need to have a separate .env
file for each application. And the way to do is by having another .monoenv.prod.yaml
file that looks like this:
1shared: false 2overwrite: false 3postfix: '.env' 4prefix: '.' 5 6apps: 7 api: 8 - NODE_ENV="production" 9 - API_PORT="3000" 10 - HOST="0.0.0.0" 11 - LOG_LEVEL="info" 12 - JWT_SECRET="productionsecret" 13 - DATABASE_URL="postgres://postgres:postgres@localhost:5432/prod" 14 15 uploader: 16 - NODE_ENV="production" 17 18 web: 19 - NODE_ENV="production" 20 - VITE_API_URL=localhost:3000
Then in your deployment process and before building your applications or docker images, you can run:
1npx monoenv -c .monoenv.prod.yaml
You'll notice 3 new files created with these names:
You can now feed these env files to your applications in whatever way you'd like.
No vulnerabilities found.
No security vulnerabilities found.