A robust and lightweight TypeScript library for securely loading, validating, and managing environment variables, preventing unintended access by third-party dependencies.
In modern applications, especially those with a large number of dependencies, there's a significant risk of sensitive environment variables (like API keys, database credentials, etc.) being inadvertently accessed or logged by "shady" or compromised third-party packages. The traditional approach of loading all .env
variables directly into process.env
exposes your entire configuration to every part of your application's dependency tree.
process-venv
addresses this by providing a "virtual environment" for your application's configuration. It ensures that:
- Isolation: Only explicitly "shared" environment variables are exposed to
process.env
. All other variables are kept in memory within thecreateEnv
instance, accessible only through its properties. - Validation: All environment variables are rigorously validated against a Standard Schema compliant schema at application startup, catching missing or malformed configurations early. While the examples use Zod,
process-venv
is designed to work with any Standard Schema compliant validator (e.g., Valibot, ArkType). - Immutability: The environment variables are immutable after creation, enhancing predictability and preventing accidental runtime modifications.
This approach significantly enhances the security and reliability of your application's environment management.
- Secure Isolation: Prevents unintended access to sensitive environment variables by third-party dependencies.
- Standard Schema Validation: Enforces strict schema validation for all environment variables at runtime, allowing you to use any compliant validator (e.g., Zod, Valibot, ArkType).
- Flexible Loading: Load from
.env
files or directly from an existing object (e.g., from a secret vault). - Immutability: Environment variables are immutable after creation.
- Lightweight: Minimal footprint with zero runtime dependencies beyond
dotenv
(optional) and your chosen Standard Schema compliant validator. - TypeScript First: Written entirely in TypeScript with strong type safety.
pnpm install process-venv
It is recommended to define your environment schema and initialize createEnv
in a dedicated file (e.g., src/env.ts
) and then import the venv
instance where needed.
// -- src/env.ts
import { createEnv } from 'process-venv';
import * as z from 'zod';
export const venv = createEnv({
schema: {
NODE_ENV: z
.enum(['development', 'production', 'test'])
.default('development'),
PORT: z.coerce.number().default(3000),
DATABASE_URL: z.string().url(),
API_KEY: z.string(), // This will be private by default
SHARED_SECRET: z.string(), // This will be shared
},
shared: ['NODE_ENV', 'PORT', 'SHARED_SECRET'],
// Optional dotenv options:
// path: ['.env.local', '.env'],
});
Then, in your application's entry point (e.g., src/index.ts
):
// -- src/index.ts
import { venv } from './env';
// Access shared variables via process.env (e.g., for frameworks)
console.log('NODE_ENV from process.env:', process.env.NODE_ENV);
// Access all variables securely via the venv instance
console.log('API_KEY from venv:', venv.API_KEY);
console.log('PORT from venv:', venv.PORT);
// process.env.API_KEY will be undefined
console.log('API_KEY from process.env:', process.env.API_KEY);
Similarly, for loading from an external object, you can define and initialize your venv
instance in src/env.ts
:
// -- src/env.ts
import { createEnv } from 'process-venv';
import { z } from 'zod';
const myExternalConfig = {
NODE_ENV: 'production',
PORT: '8080',
DATABASE_URL: 'postgresql://user:pass@host:port/db',
API_KEY: 'my-super-secret-key-from-vault',
};
export const venv = createEnv(
{
schema: {
NODE_ENV: z.enum(['development', 'production', 'test']),
PORT: z.coerce.number(),
DATABASE_URL: z.string().url(),
API_KEY: z.string(),
},
shared: ['NODE_ENV', 'PORT'],
},
myExternalConfig
);
And then use it in src/index.ts
:
// -- src/index.ts
import { venv } from './env';
console.log('API_KEY from venv:', venv.API_KEY);
console.log('NODE_ENV from process.env:', process.env.NODE_ENV);
For all configuration options, please see the API docs.
Want to contribute? Awesome! To show your support is to star the project, or to raise issues on GitHub
Thanks again for your support, it is much appreciated! π
MIT Β© Shahrad Elahi and contributors.