npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

node-env-resolver-aws

v10.0.0

Published

AWS resolvers for node-env-resolver (Secrets Manager, SSM Parameter Store)

Downloads

263

Readme

node-env-resolver/aws

AWS integration for node-env-resolver with Secrets Manager and SSM Parameter Store support.

npm version

Install

npm install node-env-resolver/aws

Quick start

One-line convenience functions (recommended)

import { resolveSsm, resolveSecrets } from 'node-env-resolver-aws';

// Resolve from SSM Parameter Store
const config = await resolveSsm({
  path: '/myapp/config'
}, {
  API_ENDPOINT: string(),
  TIMEOUT: 30
});

// Resolve from Secrets Manager
const secrets = await resolveSecrets({
  secretId: 'myapp/production/secrets'
}, {
  DATABASE_URL: string(),
  API_KEY: string()
});

Using with resolveAsync() (for combining multiple sources)

import { resolveAsync } from 'node-env-resolver';
import { awsSecrets, awsSsm } from 'node-env-resolver-aws';

const config = await resolveAsync({
  resolvers: [
    [awsSecrets({ secretId: 'myapp/production/secrets' }), {
      DATABASE_URL: postgres(),
      API_KEY: string(),
    }],
    [awsSsm({ path: '/myapp/config' }), {
      TIMEOUT: 30,
    }]
  ]
});

Features

  • One-line convenience functions for quick setup
  • Load secrets from AWS Secrets Manager
  • Load parameters from SSM Parameter Store
  • Safe (non-throwing) versions of all functions
  • Automatic AWS credential detection (environment variables, IAM roles, ~/.aws/credentials)
  • Optional TTL caching
  • Full TypeScript support

Performance and caching

AWS API calls are slow (~100-200ms) and cost money. Caching is essential for production applications.

Without caching (not recommended)

// Every request hits AWS = slow and expensive
export const handler = async (event) => {
  const config = await resolveSecrets({
    secretId: 'myapp/secrets'
  }, {
    DATABASE_URL: postgres(),
    API_KEY: string()
  });
  // 200ms delay on EVERY request + AWS API costs
};

With caching (recommended)

import { resolveAsync, cached, TTL } from 'node-env-resolver';
import { awsSecrets } from 'node-env-resolver-aws';

// Cache AWS calls - call resolveAsync() every time, let cached() make it fast
export const getConfig = async () => {
  return await resolveAsync({
    resolvers: [
      [cached(
        awsSecrets({ secretId: 'myapp/secrets' }),
        {
          ttl: TTL.minutes5,
          maxAge: TTL.hour,
          staleWhileRevalidate: true
        }
      ), {
        DATABASE_URL: postgres(),
        API_KEY: string(),
      }]
    ]
  });
};

// Call in your handler
export const handler = async (event) => {
  const config = await getConfig(); // Fast after first call!
  // Use config...
};

AWS Lambda:

import { resolveAsync, cached, TTL } from 'node-env-resolver';
import { awsSecrets } from 'node-env-resolver-aws';

const getConfig = async () => {
  return await resolveAsync({
    resolvers: [
      [cached(
        awsSecrets({ secretId: 'myapp/lambda' }),
        { ttl: TTL.minutes5, staleWhileRevalidate: true }
      ), {
        DATABASE_URL: postgres(),
      }]
    ]
  });
};

export const handler = async (event) => {
  const config = await getConfig(); // Call every invocation
  // Lambda container reuse = cache persists across invocations
  // = most invocations get instant config
};

Best Practices

  1. Always use cached() wrapper when accessing AWS Secrets Manager or SSM
  2. Call resolveAsync() every time - don't cache the result in a variable
  3. Use staleWhileRevalidate: true for zero-latency updates
  4. Choose appropriate TTL based on how often secrets change:
    • Frequently rotating: TTL.minutes5
    • Rarely changing: TTL.hour or TTL.hours6
  5. Set maxAge as a safety net (default: 1 hour)

AWS Credentials

This package uses the standard AWS SDK credential provider chain. Credentials are automatically detected from:

  1. Environment variables (recommended for local development)

    export AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE
    export AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
    export AWS_REGION=us-west-2
  2. IAM roles (recommended for production - EC2, Lambda, ECS)

  3. AWS credentials file (~/.aws/credentials)

  4. Explicit options (for special cases):

    await resolveSsm({
      path: '/myapp/config',
      region: 'us-east-1',
      accessKeyId: 'AKIAIOSFODNN7EXAMPLE',
      secretAccessKey: 'wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY'
    }, { API_ENDPOINT: string() });

In most cases, you don't need to pass credentials explicitly - just set the standard AWS environment variables or use IAM roles.

API Functions

Convenience Functions

resolveSsm(ssmOptions, schema, resolveOptions?)

Directly resolve environment variables from SSM Parameter Store.

import { resolveSsm } from 'node-env-resolver-aws';

const config = await resolveSsm({
  path: '/myapp/config',
  region: 'us-east-1',
  recursive: true
}, {
  API_ENDPOINT: string(),
  TIMEOUT: 30
});

safeResolveSsm(ssmOptions, schema, resolveOptions?)

Safe version that returns a result object instead of throwing.

import { safeResolveSsm } from 'node-env-resolver-aws';

const result = await safeResolveSsm({
  path: '/myapp/config'
}, {
  API_ENDPOINT: string()
});

if (result.success) {
  console.log(result.data.API_ENDPOINT);
} else {
  console.error(result.error);
}

resolveSecrets(secretsOptions, schema, resolveOptions?)

Directly resolve environment variables from Secrets Manager.

import { resolveSecrets } from 'node-env-resolver-aws';

const config = await resolveSecrets({
  secretId: 'myapp/production/secrets',
  region: 'us-east-1'
}, {
  DATABASE_URL: string(),
  API_KEY: string()
});

safeResolveSecrets(secretsOptions, schema, resolveOptions?)

Safe version that returns a result object instead of throwing.

import { safeResolveSecrets } from 'node-env-resolver-aws';

const result = await safeResolveSecrets({
  secretId: 'myapp/secrets'
}, {
  DATABASE_URL: string()
});

if (result.success) {
  console.log(result.data.DATABASE_URL);
} else {
  console.error(result.error);
}

Resolver Functions (for use with resolveAsync())

awsSsm(options) and awsSecrets(options)

These return resolver objects for use with resolveAsync() when you need to combine multiple sources.

AWS Secrets Manager

Load JSON secrets from Secrets Manager:

import { resolveAsync } from 'node-env-resolver';
import { awsSecrets } from 'node-env-resolver-aws';

const config = await resolveAsync({
  resolvers: [
    [awsSecrets({ secretId: 'myapp/secrets' }), {
      DATABASE_URL: postgres(),
      API_KEY: string()
    }]
  ]
});

With options:

awsSecrets({
  secretId: 'myapp/production/database',
  region: 'us-east-1',
  parseJson: true  // Default: true
})

SSM Parameter Store

Load parameters from Parameter Store:

import { resolveAsync } from 'node-env-resolver';
import { awsSsm } from 'node-env-resolver-aws';

const config = await resolveAsync({
  resolvers: [
    [awsSsm({ path: '/myapp/config' }), {
      API_ENDPOINT: string(),
      TIMEOUT: 30
    }]
  ]
});

Get all parameters under a path:

awsSsm({
  path: '/myapp/production',
  region: 'us-west-2',
  recursive: true
})

Caching

Add TTL caching to reduce AWS API calls:

import { resolveAsync, cached, TTL } from 'node-env-resolver';
import { awsSecrets } from 'node-env-resolver-aws';

const config = await resolveAsync({
  resolvers: [
    [cached(
      awsSecrets({ secretId: 'myapp/secrets' }),
      {
        ttl: TTL.minutes5,
        maxAge: TTL.hour,
        staleWhileRevalidate: true
      }
    ), {
      DATABASE_URL: postgres()
    }]
  ]
});

AWS Permissions

Secrets Manager

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["secretsmanager:GetSecretValue"],
      "Resource": ["arn:aws:secretsmanager:region:account:secret:myapp/secrets-*"]
    }
  ]
}

SSM Parameter Store

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "ssm:GetParameter",
        "ssm:GetParameters",
        "ssm:GetParametersByPath"
      ],
      "Resource": ["arn:aws:ssm:region:account:parameter/myapp/*"]
    }
  ]
}

Configuration

awsSecrets options

interface AwsSecretsOptions {
  secretId: string;              // Secret ID or ARN
  region?: string;               // AWS region (overrides profile/env defaults)
  accessKeyId?: string;          // AWS access key (optional)
  secretAccessKey?: string;      // AWS secret key (optional)
  parseJson?: boolean;           // Parse JSON secrets (default: true)
}

awsSsm options

interface AwsSsmOptions {
  path: string;                  // Parameter path
  region?: string;               // AWS region (overrides profile/env defaults)
  accessKeyId?: string;          // AWS access key (optional)
  secretAccessKey?: string;      // AWS secret key (optional)
  recursive?: boolean;           // Get all parameters under path (default: false)
}

Examples

Production app with one-line functions

import { resolveSecrets, resolveSsm } from 'node-env-resolver-aws';

// Load secrets from Secrets Manager
const secrets = await resolveSecrets({
  secretId: 'myapp/production/secrets'
}, {
  DATABASE_URL: postgres(),
  JWT_SECRET: string(),
});

// Load config from SSM
const config = await resolveSsm({
  path: '/myapp/production/config',
  recursive: true
}, {
  NODE_ENV: ['development', 'production'] as const,
  PORT: 3000,
});

Production app with resolveAsync() (combining sources)

import { resolveAsync, processEnv } from 'node-env-resolver';
import { awsSecrets, awsSsm } from 'node-env-resolver-aws';

const config = await resolveAsync({
  resolvers: [
    [processEnv(), {
      NODE_ENV: ['development', 'production'] as const,
      PORT: 3000,
    }],
    [awsSecrets({ secretId: 'myapp/production/secrets' }), {
      DATABASE_URL: postgres(),
      JWT_SECRET: string(),
    }],
    [awsSsm({ path: '/myapp/production/config' }), {
      TIMEOUT: 30,
    }]
  ]
});

Lambda function

import { resolveSecrets } from 'node-env-resolver-aws';

const config = await resolveSecrets({
  secretId: 'lambda/secrets'
}, {
  API_ENDPOINT: string(),
  TIMEOUT: 30,
});

export const handler = async (event) => {
  // Use config
};

Safe error handling

import { safeResolveSecrets } from 'node-env-resolver-aws';

const result = await safeResolveSecrets({
  secretId: 'myapp/production/secrets'
}, {
  DATABASE_URL: string(),
  API_KEY: string()
});

if (result.success) {
  // Use result.data with full type safety
  await connectDatabase(result.data.DATABASE_URL);
} else {
  // Handle error gracefully
  console.error('Failed to load secrets:', result.error);
  process.exit(1);
}

Error handling

With safe functions (recommended)

import { safeResolveSecrets } from 'node-env-resolver-aws';

const result = await safeResolveSecrets({
  secretId: 'myapp/secrets'
}, {
  DATABASE_URL: string()
});

if (!result.success) {
  console.error('Failed to load secrets:', result.error);
  process.exit(1);
}

// Use result.data safely
console.log(result.data.DATABASE_URL);

With try-catch

import { resolveSecrets } from 'node-env-resolver-aws';

try {
  const config = await resolveSecrets({
    secretId: 'myapp/secrets'
  }, {
    DATABASE_URL: string()
  });
} catch (error) {
  console.error('Failed to load secrets from AWS:', error);
}

Troubleshooting

Permission denied

  • Check IAM permissions match examples above
  • Verify resource ARNs are correct

Secret not found

  • Verify secret ID or path exists
  • Check region matches where secret is stored

Network timeout

  • Check VPC/security group configuration
  • Verify internet/NAT gateway access

Licence

MIT