Files
suaveplan/packages/foundation/core/env
2026-05-27 23:47:53 +01:00
..
2026-05-27 23:47:53 +01:00
2026-05-27 23:47:53 +01:00
2026-05-27 23:47:53 +01:00
2026-05-27 23:47:53 +01:00
2026-05-27 23:47:53 +01:00
2026-05-27 23:47:53 +01:00
2026-05-27 23:47:53 +01:00

@suaveplan/env - Type-safe environment variable loading: schema-first validation, field types, dotenv loader, presets, structured errors.

Summary

Type-safe, schema-first environment variable loading for Node.js and edge runtimes. Define a schema of typed field builders, point it at your sources, and receive a frozen record with TypeScript types inferred at compile time — no manual type annotations required.

Documentation tree

- [create-env](./src/core/create-env/create-env.md) — _(no submodules)_- [field](./src/core/field/field.md) — _(no submodules)_- [field](./src/core/field/field.md) — _(no submodules)_- [validator](./src/core/validator/validator.md) — _(no submodules)_- [validator](./src/core/validator/validator.md) — _(no submodules)_- [env-error](./src/errors/env-error.md) — Provides the complete error class hierarchy and a value-object factory for `@suaveplan/env`. All classes extend `Suavep…

Features

  • Nine field builders: str, num, bool, enums, url, email, port, json, array
  • Fluent builder chains: constraints, defaults, sensitive marking, and descriptions per field
  • Pluggable loaders: dotenv file, object (process.env), or custom loaders with priority ordering
  • Three error modes: throw (default), collect (partial data), warn (log and continue)
  • Full-error accumulation: reports every broken field in a single run, not just the first
  • Sensitive value redaction: maskSensitive replaces secret values with **** before logging
  • Preset libraries: commonFields and serverFields for the most frequent env variables
  • Zod runtime schemas: for validation at serialisation boundaries
  • 100% Istanbul coverage: foundation-grade reliability

Installation

bun add @suaveplan/env

Quick Start

import { createEnv, str, num, bool } from '@suaveplan/env';

const env = createEnv({
    schema: {
        HOST: str().default('localhost'),
        PORT: num().default(3000),
        DEBUG: bool().default(false),
        API_KEY: str().nonempty().sensitive(),
    },
    source: process.env,
});

// Full TypeScript types — no manual annotation needed
console.log(env.HOST);   // string
console.log(env.PORT);   // number
console.log(env.DEBUG);  // boolean
console.log(env.API_KEY); // string

Field Builders

Factory Output type Key methods
str() string trim, lowercase, uppercase, minLength, maxLength, pattern, nonempty, startsWith, endsWith, includes
num() number min, max, integer, positive, nonNegative
bool() boolean truthy(values), falsy(values)
enums(values) "a" | "b" | … caseInsensitive, getAllowedValues
url() string protocols(list), noTrailingSlash
email() string normalise, pattern(regex)
port() number min(n), max(n)
json<T>() T (default unknown) validator(fn)
array(itemField) T[] separator, noTrim, keepEmpty, minItems, maxItems

All builders share: optional(), default(value), sensitive(), describe(text), addRule(options).

Loaders

import { createEnv, str } from '@suaveplan/env';
import { dotenvLoader, objectLoader } from '@suaveplan/env/loaders';

const env = createEnv({
    schema: { DB_URL: str().sensitive() },
    loaders: [
        dotenvLoader({ path: '.env' }),        // from file
        objectLoader({ source: process.env }), // from process.env (wins)
    ],
});

Later loaders override earlier ones for the same key. source (if provided) overrides all loaders.

Error Modes

// Default: throws EnvValidationError with all failures listed
const env = createEnv({ schema, source: process.env });

// Collect: returns partial data silently
const env = createEnv({ schema, source: process.env, onError: 'collect' });

// Warn: logs each failure via console.warn, returns partial data
const env = createEnv({ schema, source: process.env, onError: 'warn' });

Prefix Support

// Reads APP_HOST, APP_PORT from process.env; output keys are HOST, PORT
const env = createEnv({
    schema: { HOST: str().default('localhost'), PORT: num().default(3000) },
    source: process.env,
    prefix: 'APP_',
});

Presets

import { commonFields } from '@suaveplan/env/presets/common/common';
import { serverFields, databaseUrlField, sessionSecretField } from '@suaveplan/env/presets/server/server';
import { createEnv, str } from '@suaveplan/env';

const env = createEnv({
    schema: {
        ...commonFields,            // NODE_ENV, PORT, HOST, DEBUG, LOG_LEVEL
        DATABASE_URL: databaseUrlField(),
        SESSION_SECRET: sessionSecretField(),
        CUSTOM: str().optional(),
    },
    source: process.env,
});

Sensitive Values

import { validate, maskSensitive } from '@suaveplan/env/core/validator/validator';
import { str } from '@suaveplan/env';

const schema = { SECRET: str().sensitive(), PUBLIC: str() };
const result = validate({ schema, values: { SECRET: 'my-secret', PUBLIC: 'ok' } });

const safe = maskSensitive(schema, result.data);
console.log(safe.SECRET); // "****"
console.log(safe.PUBLIC); // "ok"

Errors

import { EnvValidationError, CoercionError } from '@suaveplan/env/errors';
import { ENV_CODES } from '@suaveplan/env/errors';

try {
    createEnv({ schema, source: {} });
} catch (err) {
    if (err instanceof EnvValidationError) {
        console.log(err.code);   // "ENV.VALIDATION_FAILED"
        console.log(err.errors); // [{ key, message }]
    }
}

Zod Schemas

Runtime schemas for validation at API or persistence boundaries:

import { FieldConfigSchema, ValidationResultSchema } from '@suaveplan/env/schemas';

const result = FieldConfigSchema.safeParse(unknownPayload);

Module Reference

Co-located module Description
src/core/create-env/create-env.md createEnv orchestrator
src/core/field/field.md BaseField abstract base
src/core/validator/validator.md validate and maskSensitive
src/errors/error-codes.md ENV_CODES registry
src/errors/env-error.md Error class hierarchy
src/fields/string-field/string-field.md str()
src/fields/number-field/number-field.md num()
src/fields/boolean-field/boolean-field.md bool()
src/fields/enum-field/enum-field.md enums()
src/fields/url-field/url-field.md url()
src/fields/email-field/email-field.md email()
src/fields/port-field/port-field.md port()
src/fields/json-field/json-field.md json()
src/fields/array-field/array-field.md array()
src/loaders/dotenv/dotenv.md parseDotenv, dotenvLoader
src/loaders/object/object.md objectLoader
src/transforms/coerce/coerce.md Standalone coercion functions
src/presets/common/common.md Common server field presets
src/presets/server/server.md Server connection field presets
src/schemas/env.schemas.md Zod runtime schemas
src/types/common.md Shared TypeScript types
src/utils/interpolation.md ${VAR} interpolation utilities