smenv is a Node.js library and command-line tool for fetching secrets from AWS Secrets Manager and updating local environment files. It allows you to keep your sensitive information securely in AWS Secrets Manager and easily sync it with your local environment files.
You can install smenv as a dependency in your Node.js project using npm or yarn:
npm install smenvor
yarn add smenvFor easy access across all projects, install smenv globally:
npm install -g smenvThis allows you to use the smenv command from anywhere on your system.
Before using smenv, you need to store your secrets in AWS Secrets Manager with the correct naming convention:
Secrets should be named using the format: packageName/environment
Examples:
- my-app/local- for local development
- my-app/production- for production environment
- my-app/staging- for staging environment
Store your environment variables as a JSON object in the secret value:
{
  "DATABASE_URL": "postgresql://localhost:5432/myapp",
  "API_KEY": "your-api-key-here",
  "REDIS_URL": "redis://localhost:6379"
}You can use smenv as a library in your Node.js code as shown in the following example:
import { smenv } from 'smenv'
import isEmpty from 'lodash.isempty'
  
;(async () => {
  const result = await smenv({
    secretName: 'mySecret', // The name of the secret to fetch from AWS Secrets Manager (optional)
    packageName: 'myApp', // The name of the package (optional, default is value from package.json in current directory)
    environment: 'production', // The environment name (optional, default is NODE_ENV environment variable or 'local')
    isSupportEnvironment: true, // Support environment-specific files like .env.production (optional, default is true)
    isBackupCurrentFile: false, // Create a backup of the current file before updating (optional, default is false)
    awsSettings: {}, // AWS configuration settings (optional, default is {})
    getAwsSecretsFunc: customGetSecrets // Custom function to retrieve secrets (optional, defaults to AWS Secrets Manager)
  })
  if (!result.isDiff) {
    console.log('Local environment file is synced with secrets')
  } else {
    console.log('Differences found between local file and secrets:')
    const { added, deleted, updated } = result.filesDiff
    if (!isEmpty(added)) {
      console.log(
        `Added ${Object.keys(added).length} secrets: ${JSON.stringify(added)}`
      )
    }
    if (!isEmpty(deleted)) {
      console.log(
        `Removed ${Object.keys(deleted).length} secrets: ${JSON.stringify(
          deleted
        )}`
      )
    }
    if (!isEmpty(updated)) {
      console.log(
        `Updated ${Object.keys(updated).length} secrets: ${JSON.stringify(
          updated
        )}`
      )
    }
  }
})()You can provide your own function to retrieve secrets instead of using AWS Secrets Manager. The function must be async and follow this signature:
async function getAwsSecretsFunc(secretName: string, awsSettings: object): Promise<object>Example implementation:
import { smenv } from 'smenv'
// Custom function to get secrets from your own source
// Parameters:
//   - secretName: string - The name of the secret to fetch (e.g., 'my-app-production')
//   - awsSettings: object - Configuration settings passed from smenv options
// Returns: Promise<object> - Object with key-value pairs of environment variables
async function myCustomSecretProvider(secretName, awsSettings) {
  console.log(`Fetching secrets for: ${secretName}`)
  
  // Your custom logic to fetch secrets
  // This could be from a database, API, file system, etc.
  if (secretName === 'my-app-production') {
    return {
      DATABASE_URL: 'postgresql://prod-db:5432/myapp',
      API_KEY: 'prod-api-key-12345',
      REDIS_URL: 'redis://prod-redis:6379'
    }
  }
  
  // Return empty object if secret not found, or throw error
  throw new Error(`Secret '${secretName}' not found`)
}
const result = await smenv({
  secretName: 'my-app-secrets',
  packageName: 'my-app',
  environment: 'production',
  getAwsSecretsFunc: myCustomSecretProvider // Use custom provider
})| Parameter | Type | Default | Description | 
|---|---|---|---|
| secretName | string | undefined | The name of the secret to fetch. If not provided, uses packageName/environment | 
| packageName | string | package.json name | The name of the package/application | 
| environment | string | process.env.NODE_ENV || 'local' | The environment name (e.g., 'local', 'production', 'staging') | 
| isSupportEnvironment | boolean | false | Whether to use environment-specific files (e.g., .env.production) | 
| isBackupCurrentFile | boolean | false | Whether to create a backup before updating the file | 
| awsSettings | object | {} | AWS configuration settings (region, credentials, etc.) | 
| getAwsSecretsFunc | function | getAwsSecrets | Custom function to retrieve secrets. Receives (secretName, awsSettings)and should return an object of key-value pairs | 
The function returns a Promise that resolves to an object with:
| Property | Type | Description | 
|---|---|---|
| isDiff | boolean | Whether differences were found between local and remote secrets | 
| filesDiff | object | Object containing added,deleted, andupdatedproperties | 
| envs | object | The final environment variables after synchronization | 
You can also use smenv as a command-line tool by running the smenv command with the following options:
For the best developer experience, add smenv to your npm scripts to automatically sync secrets before starting your application:
{
  "scripts": {
    "start": "smenv -e local && node server.js",
    "dev": "smenv -e development && npm run dev-server",
    "prod": "smenv -e production && npm start"
  }
}This ensures your environment variables are always up-to-date with the latest secrets from AWS Secrets Manager before your application starts.
Usage: smenv [options]
Options:
      --help                Show help                                  [boolean]
      --version             Show version number                        [boolean]
  -s, --secretName          The name of the secret to fetch from AWS Secrets
                            Manager                                     [string]
  -p, --packageName         The name of the package
                [string] [default: value from package.json in current directory]
  -e, --env                 The environment name
              [string] [default: NODE_ENV environment variable or 'development']
  -f, --fileName            The name of the file to write secrets to
                                                        [string] [default: .env]
      --supportEnvironment  Enable environment-specific files (e.g.,
                            .env.production)           [boolean] [default: false]
  -b, --backup              Create a backup of the current file before updating
                                                                       [boolean]
Examples:
  smenv --secretName mySecret              Fetches the specified secret from
                                            AWS Secrets Manager
  smenv --packageName myApp --env          Specifies custom package name and
  production                                environment
  smenv -s mySecret -p myApp -e            Specifies options with backup
  production --backup                       enabled
  smenv --supportEnvironment               Enables environment-specific files,
                                            uses .env.production instead of .env
  smenv --backup                           Creates a backup of current .env file
                                            before updating
  smenv -b                                 Same as --backup (short form)This project is licensed under the Apache-2.0