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

envista

v0.1.0

Published

Cascading .env loader built on Node's own parser. Zero dependencies.

Readme

envista

Cascading .env loader built on Node's own parser. Zero dependencies.

pnpm add envista
import { loadEnvFiles } from "envista";

loadEnvFiles();

Why this exists

Node already parses .env files: util.parseEnv went stable in 22.21 and 24.10, and process.loadEnvFile copies one file into process.env. What it leaves to you is picking which files to read. envista adds only that:

  • Cascades by mode, in Vite's order: .env, .env.local, .env.<mode>, .env.<mode>.local
  • Searches upward, so a package in a monorepo reads its own .env and falls back to the repository root for the rest
  • No dependencies, and no bundled parser to drift from the runtime's

Precedence

When two files declare the same key, highest precedence first:

  1. Whatever is already in process.env. A shell export outranks every file
  2. Files in the nearest directory
  3. Files in each directory above it, nearest first

Within one directory: .env.<mode>.local, then .env.<mode>, then .env.local, then .env.

The directory rule outranks the file rule, so a package's plain .env still wins over the root's .env.<mode>.local. The nearest file decides, and the root fills the gaps.

Want files to override what your shell set? Pass override: true.

API

loadEnvFiles(options?)

Reads every file that applies into process.env, the way process.loadEnvFile does for one file. Call it once, before anything reads a variable.

loadEnvFiles({ mode: "production" });

Returns everything the files held, including values process.env kept.

readEnvFiles(options?)

The same read, with process.env left alone. Use it when you want the variables as data, not a side effect.

resolveEnvFiles(options?)

Returns the absolute paths that apply, lowest precedence first, without reading them. Good for showing what a directory resolves to.

Options

| Option | Default | What it does | | ---------- | ---------------------- | ------------------------------------------------------------------------------------------------------ | | cwd | process.cwd() | Where the upward search starts. | | mode | process.env.NODE_ENV | Picks the .env.<mode> files. Without a mode, only .env and .env.local are read. | | stopAt | file system root | Where the search stops, inclusive. Point it at your repository root to keep a stray .env in ~ out. | | override | false | loadEnvFiles only. Lets files replace variables already set. |

Format

envista parses what util.parseEnv parses, which is close to dotenv but not identical. src/parse.test.ts pins down every case, and every disagreement with dotenv, Node, or the POSIX-shell dotenv-spec carries a note saying why.

Files written on Windows are fine. CRLF endings stay out of your values, and a byte order mark stays out of your first key, where Node would leave it and hand you a name you cannot type.

Two quirks bite:

  • \r stays literal inside double quotes. dotenv expands it, Node does not
  • A="he\"llo" ends the value at the escaped quote and drops the rest of the line. Single quote it instead: A='he"llo'

envista does not expand ${VAR} references. Values arrive as written, since expansion means a second parser, the one thing this package exists to avoid.

Requirements

Node ^22.21.0 || >=24.10.0, the releases where util.parseEnv stopped being experimental.

Credit

The cascade order and the named-pipe handling come from Vite's env.ts, MIT licensed. envista adds the upward search, and drops the last dependency by leaving variable references alone.

License

MIT