# seniority/dotenv

> Every export of seniority/dotenv, with its signature and doc comment: parse, populate, config, module.exports, dotenv, plus 3 types.

Source: https://seniority.interlace.tools/docs/api/dotenv

<!-- Generated by scripts/api-reference.ts from the built dist/*.d.ts. Do not edit; run `npx tsx scripts/api-reference.ts`. -->

```ts
import dotenv from 'seniority/dotenv';
import { parse, populate, config, … } from 'seniority/dotenv';
```

## Functions

### config

Read, parse and populate. Returns `{ parsed }` or `{ error }` and **never throws for a
missing file** — dotenv is loaded at import time, where a throw takes the program down
before it can say anything useful.

```ts
function config(options?: Partial<ConfigOptions>): ConfigResult;
```

| Parameter | Type |
| :-- | :-- |
| `options` (optional) | `Partial<ConfigOptions>` |

**Returns** `ConfigResult`

### parse

Every `KEY=value` in a `.env`, as an object. Accepts the Buffer `readFileSync` hands back.

```ts
function parse(src: string | Buffer): Record<string, string>;
```

| Parameter | Type |
| :-- | :-- |
| `src` | `string \| Buffer` |

**Returns** `Record<string, string>`

### populate

Copy `parsed` into `target` and return what was actually set. Without `override` a key the
target already holds is left alone — the same rule seniority's own `ORDER` states as
`env > config` (R1), arrived at independently by dotenv and worth noticing.

Two things are dotenv's and not ours. The **`parsed` check** comes first, because that is
the one it makes; the guard on `target` is kept after it, because dotenv reaching
`hasOwnProperty.call(undefined, …)` throws a `TypeError` about converting undefined, which
tells its caller nothing. And `debug` prints through `console.log`, which is what `_debug`
does upstream — not a stream this package owns, and not `process.stdout`, which it may not
name (R11). The text names seniority rather than a dotenv version: the suite asserts that
something was logged, never what.

```ts
function populate(target: Record<string, string | undefined>, parsed: Record<string, string>, options?: PopulateOptions): Record<string, string>;
```

| Parameter | Type |
| :-- | :-- |
| `target` | `Record<string, string \| undefined>` |
| `parsed` | `Record<string, string>` |
| `options` (optional) | `PopulateOptions` |

**Returns** `Record<string, string>`

## Constants

### default

The default export, declared as `dotenv`.

**The default export, and why a drop-in subpath needs one.**

dotenv is CJS: `require('dotenv')` hands back a plain, mutable `module.exports`, and its
own suite depends on that — `test-populate.js` opens with `sinon.stub(dotenv, 'parse')` in
a top-level `beforeEach`. An ES module namespace cannot be stubbed: every property is
non-configurable and the object is not extensible, so sinon refuses with
`ES Modules cannot be stubbed`, the `beforeEach` throws, and **every** case in the file
fails before its first assertion. Measured 2026-09-20: 12 failing entries in the raw TAP
against the control's plan of 6, and not one of them reached a `populate` call.

So the subpath publishes the same shape its incumbent does — one mutable object carrying
the three functions — and the host's import declares `reexportDefault`, which makes the
generated shim re-export it under the `'module.exports'` name Node's `require()` of an ES
module returns whole. That is the mechanism commander's and yargs' CJS fixtures already
run on; dotenv's row simply never declared it. Nothing about seniority changed to make
those cases pass — what changed is that the suite can now reach the functions the way it
reaches dotenv's.

```ts
const dotenv: {
    config: typeof config;
    parse: typeof parse;
    populate: typeof populate;
};
```

### module.exports

**The default export, and why a drop-in subpath needs one.**

dotenv is CJS: `require('dotenv')` hands back a plain, mutable `module.exports`, and its
own suite depends on that — `test-populate.js` opens with `sinon.stub(dotenv, 'parse')` in
a top-level `beforeEach`. An ES module namespace cannot be stubbed: every property is
non-configurable and the object is not extensible, so sinon refuses with
`ES Modules cannot be stubbed`, the `beforeEach` throws, and **every** case in the file
fails before its first assertion. Measured 2026-09-20: 12 failing entries in the raw TAP
against the control's plan of 6, and not one of them reached a `populate` call.

So the subpath publishes the same shape its incumbent does — one mutable object carrying
the three functions — and the host's import declares `reexportDefault`, which makes the
generated shim re-export it under the `'module.exports'` name Node's `require()` of an ES
module returns whole. That is the mechanism commander's and yargs' CJS fixtures already
run on; dotenv's row simply never declared it. Nothing about seniority changed to make
those cases pass — what changed is that the suite can now reach the functions the way it
reaches dotenv's.

```ts
const dotenv: {
    config: typeof config;
    parse: typeof parse;
    populate: typeof populate;
};
```

## Interfaces

### ConfigOptions

```ts
interface ConfigOptions extends Omit<PopulateOptions, 'debug'> {
    /** Log what it does, through `console.log`; a string is read as dotenv reads it (`'false'`, `'0'`, … are false). */
    debug?: boolean | string;
    /** One file or several, highest priority first — an earlier file's key is not overwritten by a later one. `./.env` when omitted; a leading `~` is the home directory; a `URL` is read as one. */
    path: string | URL | readonly (string | URL)[];
    /** The object to populate; the process's own environment when omitted, as dotenv does (D-135). */
    processEnv: Record<string, string | undefined>;
    encoding?: BufferEncoding;
}
```

### ConfigResult

```ts
interface ConfigResult {
    parsed?: Record<string, string>;
    error?: Error;
}
```

### PopulateOptions

```ts
interface PopulateOptions {
    /** Replace a key the target already has. Off by default: the real environment outranks a file. */
    override?: boolean;
    /** Report each key that was already defined, and whether it was overwritten. dotenv's own `_debug`. */
    debug?: boolean;
}
```
