2.0.6 • Published 6 months ago

@env-evolve/utils v2.0.6

Weekly downloads
-
License
MIT
Repository
github
Last release
6 months ago

@env-evolve/utils

A comprehensive environment variable management library for Node.js applications.

Overview

env-evolve is a powerful toolkit for managing environment variables throughout your application's lifecycle. It handles loading, validation, migration, synchronization, and more, making environment configuration seamless across different environments.

Features

  • Load and parse .env files with proper precedence
  • Validate variables against schemas (compatible with Zod)
  • Migrate between different environment schema versions
  • Synchronize template files with actual environment files
  • Apply stage-specific rules (development, production, etc.)
  • Safe modification with automatic backups
  • Analyze your environment against schemas
  • Export variables to process.env with reference expansion
  • Lint environment files with custom rules
  • Mask sensitive values for secure logging

And many more...

Installation

# Install via npm
npm install @env-evolve/utils
# OR clone the repo from github
git clone https://github.com/Massachusetts78/env-utils

Basic Usage

import { loadEnvFilesInOrder, getEnvFiles, exportToProcessEnv } from '@env-evolve/utils';

// Load all env files with proper precedence
const envFiles = getEnvFiles();
const envVars = loadEnvFilesInOrder(envFiles);

// Export to process.env
exportToProcessEnv(envVars);

console.log(`Server running on port ${process.env.PORT}`);

API Reference

Core Functions

Loading Environment Variables

getEnvFiles(options?)

Discovers environment files in the current directory.

const envFiles = getEnvFiles({
  directory: './config',
  patterns: ['.env', '.env.*', '.env.production']
});
loadParsedEnvFile(filePath?)

Loads and parses a single environment file.

const envVars = loadParsedEnvFile('.env.development');
loadEnvFilesInOrder(filePaths)

Loads multiple environment files in order, with later files taking precedence.

const envFiles = ['.env.defaults', '.env', '.env.local'];
const envVars = loadEnvFilesInOrder(envFiles);
exportToProcessEnv(envVariables, options?)

Exports environment variables to process.env.

exportToProcessEnv(envVars, {
  overwrite: true,       // Override existing process.env variables
  expandReferences: true // Expand ${VAR} references in values
});

Environment File Manipulation

syncEnvFiles(sourcePath, targetPath, options?)

Synchronizes variables from a source file to a target file.

// Sync template with actual env file, only adding missing vars
syncEnvFiles('.env.template', '.env', {
  overwrite: false,
  onlyMissing: true
});
addEnvVariable(key, value, filePath, options?)

Adds or updates a single environment variable.

addEnvVariable('API_URL', 'https://api.example.com', '.env', {
  createBackup: true,  // Create backup before modifying
  overwrite: true      // Override if already exists
});
removeEnvVariable(key, filePath, options?)

Removes an environment variable.

removeEnvVariable('DEPRECATED_VAR', '.env', {
  createBackup: true,
  failIfMissing: false // Don't fail if var doesn't exist
});
bulkAddEnvVariables(variables, filePath, options?)

Adds multiple environment variables at once.

bulkAddEnvVariables({
  'SERVER_PORT': '8080',
  'NODE_ENV': 'development',
  'LOG_LEVEL': 'debug'
}, '.env');
bulkRemoveEnvVariables(keys, filePath, options?)

Removes multiple environment variables.

bulkRemoveEnvVariables([
  'OLD_API_KEY',
  'DEPRECATED_URL',
  'UNUSED_SETTING'
], '.env');
writeEnvFile(envVariables, filePath?)

Writes environment variables to a file.

writeEnvFile({
  NODE_ENV: 'production',
  PORT: '3000'
}, '.env.production');
createEnvBackup(filePath)

Creates a backup of an environment file.

const backupPath = createEnvBackup('.env');
console.log(`Backup created at: ${backupPath}`);

Validation & Analysis

validateEnv(schema, envVariables, requiredKeys?)

Validates environment variables against a schema.

import { z } from 'zod';

const schema = {
  PORT: z.string().regex(/^\d+$/),
  NODE_ENV: z.enum(['development', 'production']),
  DATABASE_URL: z.string().url()
};

const validationResult = validateEnv(schema, envVars);
if (validationResult !== true) {
  console.error('Validation failed:', validationResult.errors);
}
lint(envVariables, schema, stageRules, requiredKeys?, lintRules?, migrations?)

Performs comprehensive linting of environment variables.

const lintRules = {
  DATABASE_URL: {
    test: (value) => value.startsWith('postgres://'),
    message: 'DATABASE_URL must be a PostgreSQL connection string'
  }
};

const result = lint(
  envVars,
  schema,
  stageRules,
  ['API_KEY', 'DATABASE_URL'],
  lintRules
);

if (!result.success) {
  console.error('Linting failed:', result.errors);
}
checkRequiredEnvVars(requiredKeys, envVariables)

Checks if all required variables are present.

const { valid, errors } = checkRequiredEnvVars(
  ['API_KEY', 'DATABASE_URL', 'PORT'],
  envVars
);

if (!valid) {
  console.error('Missing required variables:', errors);
}
analyzeEnvAgainstSchema(schema, envVariables)

Analyzes environment variables against a schema.

const analysis = analyzeEnvAgainstSchema(schema, envVars);
console.log('Missing variables:', analysis.missing);
console.log('Unexpected variables:', analysis.unexpected);
console.log('Deprecated variables:', analysis.deprecated);

Migration & Versioning

applyEnvMigrations(envVariables, migrations)

Applies migrations to environment variables.

const migrations = {
  1: { 'DB_HOST': 'DATABASE_HOST', 'DB_PORT': 'DATABASE_PORT' },
  2: { 'API_KEY': 'SERVICE_API_KEY' }
};

const migratedVars = applyEnvMigrations(envVars, migrations);
determineEnvVersion(envVariables)

Determines the schema version of environment variables.

const version = determineEnvVersion(envVars);
console.log(`Current environment schema version: ${version}`);
validateMigration(envVariables)

Validates environment variables before migration.

if (validateMigration(envVars)) {
  const migratedVars = applyEnvMigrations(envVars, migrations);
  writeEnvFile(migratedVars, '.env');
}

Environment Transformation

applyStageRules(envVariables, stageRules)

Applies stage-specific rules to environment variables.

const stageRules = {
  development: {
    forcedValues: { DEBUG: 'true', LOG_LEVEL: 'debug' }
  },
  production: {
    forbiddenVars: ['DEBUG'],
    forcedValues: { LOG_LEVEL: 'error' }
  }
};

const processedVars = applyStageRules(envVars, stageRules);
expandEnvReferences(envVariables)

Expands references in environment variable values.

const vars = {
  BASE_URL: 'https://api.example.com',
  API_ENDPOINT: '${BASE_URL}/v1'
};

const expanded = expandEnvReferences(vars);
// expanded.API_ENDPOINT === 'https://api.example.com/v1'
pruneUnknownVariables(schema, envVariables)

Removes variables not defined in the schema.

const prunedVars = pruneUnknownVariables(schema, envVars);
maskSensitiveValues(envVariables)

Masks sensitive values for logging.

const maskedVars = maskSensitiveValues(envVars);
console.log('Safe to log:', maskedVars);

Template Generation

generateEnvTemplate(schema, outputPath, defaults?)

Generates a template file from a schema.

generateEnvTemplate(schema, '.env.template', {
  PORT: '3000',
  NODE_ENV: 'development'
});

Utility Functions

compareEnvFiles(file1Path, file2Path)

Compares two environment files.

const changes = compareEnvFiles('.env.staging', '.env.production');
console.log('Added variables:', changes.added);
console.log('Removed variables:', changes.removed);
console.log('Modified variables:', changes.modified);
mergeEnvObjects(...envObjects)

Merges multiple environment objects.

const merged = mergeEnvObjects(defaultEnv, userEnv, overrideEnv);
ensureEnvSetup(schema, envPath?, options?)

Ensures environment setup with validation and defaults.

const envVars = ensureEnvSetup(schema, '.env', {
  createIfMissing: true,
  populateDefaults: true,
  validateOnLoad: true
});

Configuration

ENV-EVOLVE can be configured using an env-evolve.config.js file in your project root:

import { z } from 'zod';

const config = {
  main: '.env',
  schema: {
    NODE_ENV: z.enum(['development', 'staging', 'production']),
    PORT: z.string().regex(/^\d+$/),
    DATABASE_URL: z.string().url()
  },
  requiredKeys: ['NODE_ENV', 'DATABASE_URL'],
  migrations: {
    1: { 'DB_URL': 'DATABASE_URL' },
    2: { 'API_SECRET': 'API_KEY' }
  },
  stageRules: {
    development: {
      forcedValues: { DEBUG: 'true', LOG_LEVEL: 'debug' }
    },
    production: {
      forbiddenVars: ['DEBUG'],
      forcedValues: { LOG_LEVEL: 'error' }
    }
  }
};
export default config;

Best Practices

  1. Version your environment schema using ENV_SCHEMA_VERSION
  2. Keep a template file (e.g., .env.template) in version control
  3. Exclude actual .env files from version control
  4. Validate on application startup to catch issues early
  5. Use stage rules to enforce environment-specific configurations
  6. Always create backups before modifying environment files

License

MIT

2.0.6

6 months ago

2.0.5

6 months ago

2.0.0

6 months ago

1.0.0

6 months ago

0.0.5

6 months ago

0.0.2

6 months ago

0.0.1

6 months ago