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

@redenv/client

v1.2.1

Published

A lightweight, caching client for securely fetching secrets from Redenv in any server-side JavaScript or TypeScript application.

Readme

@redenv/client

A lightweight, zero-knowledge client for securely fetching secrets from Redenv in any server-side JavaScript or TypeScript application.

This client is designed for high performance and security. It features an in-memory cache with stale-while-revalidate logic and performs all cryptographic operations locally, ensuring your secrets are never exposed.


Features

  • Zero-Knowledge: All secrets are decrypted on the client side. The backend is treated as an untrusted data store.
  • High-Performance Caching: An in-memory stale-while-revalidate cache serves secrets instantly, providing resilience and low latency.
  • Smart Secrets: Type-safe access with casting (.toInt(), .toBool()), validation (.require()), and scoping (.scope()).
  • Secret Expansion: Automatically resolves references (${VAR}) within secrets.
  • Time Travel: Fetch historical versions of secrets for auditing or rollbacks.
  • Dynamic Updates: Fetch the latest version of secrets without redeploying your application.
  • Secure Write-Back: Allows applications to add or update secrets programmatically.

Installation

Install the package using your preferred package manager:

# With npm
npm install @redenv/client

# With pnpm
pnpm add @redenv/client

# With yarn
yarn add @redenv/client

# With bun
bun add @redenv/client

Usage Guide

1. Instantiation and Initialization

The best practice is to create a single, shared instance of the client and initialize it once when your application starts. This "warms up" the cache for fast access later.

redenv.ts

import { Redenv } from "@redenv/client";

export const redenv = new Redenv({
  // It is highly recommended to load these from environment variables
  project: process.env.REDENV_PROJECT_NAME!,
  tokenId: process.env.REDENV_TOKEN_ID!,
  token: process.env.REDENV_SECRET_TOKEN_KEY!,
  upstash: {
    url: process.env.UPSTASH_REDIS_URL!,
    token: process.env.UPSTASH_REDIS_TOKEN!,
  },
  environment: process.env.NODE_ENV,
});

// Initialize Redenv once as soon as the module is loaded.
// This fetches all secrets and populates the cache for fast access.
// It also performs an initial population of process.env.
await redenv.init();

2. Accessing Secrets

The client returns a powerful Secrets object that provides much more than just key-value access.

Basic & Smart Access

const secrets = await redenv.load();

// 1. Direct Access (Masked in logs)
// Note: Console logging 'secrets' directly will show masked values (********)
const apiKey = secrets.API_KEY;

// 2. Smart Casting (.get)
// Returns a wrapper with helper methods
const port = secrets.get("PORT", 3000).toInt();      // returns number
const isDebug = secrets.get("DEBUG").toBool();       // returns boolean
const config = secrets.get("APP_CONFIG").toJSON();   // returns object

// 3. Validation
// Throws an error immediately if any of these keys are missing
secrets.require("DATABASE_URL", "STRIPE_SECRET_KEY");

// 4. Scoping
// Useful for passing a subset of configuration to a module
// e.g. secrets.scope("AWS_") returns an object where "AWS_KEY" becomes just "KEY"
const awsConfig = secrets.scope("AWS_");

Secret Expansion

Redenv supports referencing other secrets using ${VAR_NAME} syntax. These are automatically resolved.

// If BASE_URL="https://api.example.com" and AUTH_URL="${BASE_URL}/auth"
console.log(secrets.AUTH_URL); // "https://api.example.com/auth"

// Access the raw formula
console.log(secrets.raw.AUTH_URL); // "${BASE_URL}/auth"

Unmasked Access

For security, secrets.toString() and JSON.stringify(secrets) mask values. To get the raw data for debugging or legacy libraries:

const rawObject = secrets.toObject();
console.log(rawObject); // { API_KEY: "actual-secret-value", ... }

3. Time Travel (Version History)

You can fetch historical versions of any secret using getVersion.

// Fetch by absolute version ID
const v10 = await redenv.getVersion("API_KEY", 10);

// Fetch previous version (1 step back)
// Mode "index": 0=Latest, 1=Previous, etc.
const previous = await redenv.getVersion("API_KEY", 1, "index");

// Fetch oldest version
// Negative ID treats as index from the end
const oldest = await redenv.getVersion("API_KEY", -1);

4. Writing Secrets

You can add or update a secret using the .set() method. This requires a Service Token with write permissions. Using this method will automatically clear the client's local cache, ensuring the next read is fresh.

import { redenv } from "./redenv";

// Update the log level dynamically in response to an admin action
await redenv.set("LOG_LEVEL", "debug");

Configuration Options

The Redenv constructor accepts the following options:

| Option | Type | Description | Required | | ------------- | -------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | :------: | | project | string | The name of your Redenv project. | Yes | | tokenId | string | The public ID of your Redenv service token (e.g., stk_...). | Yes | | token | string | The secret key of your Redenv service token (e.g., redenv_sk_...). | Yes | | upstash | { url: string, token: string } | Your Upstash Redis REST credentials (URL and Token). | Yes | | environment | string | The environment within the project to fetch secrets from (e.g., "production", "staging"). Defaults to 'development'. | No | | cache | { ttl?: number, swr?: number } | Caching behavior in seconds. ttl is time-to-live, swr is stale-while-revalidate. Defaults to { ttl: 300, swr: 86400 }. | No | | env | { override?: boolean } | If true (default), overwrites existing environment variables. If false, preserves them. | No | | log | LogPreference | If "none", suppresses informational logs from the client. Defaults to "low". | No |

Caching Behavior

The client uses a powerful stale-while-revalidate caching strategy to ensure your application remains fast and responsive.

  • When you request a secret, it's served instantly from an in-memory cache if available.
  • If the cached data is older than the ttl (time-to-live), it is considered "stale". The client will return the stale data immediately and trigger a non-blocking background fetch to get fresh secrets from Redis.
  • This ensures your application's performance is not impacted by fetching secrets, while also guaranteeing that the secrets are eventually consistent and stay up-to-date.