Launch Week Day 2: Introducing Reports: An Extensible Reporting Framework for Socket Data.Learn More
Socket
Book a DemoSign in
Socket

envarna

Package Overview
Dependencies
Maintainers
1
Versions
33
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

envarna

Settings managed. A powerful library for managing configuration details.

latest
Source
npmnpm
Version
1.0.5
Version published
Weekly downloads
517
0.98%
Maintainers
1
Weekly downloads
 
Created
Source

envarna

Settings managed.

Envarna is a TypeScript library that helps you manage application configuration. These are the settings that control how an application behaves and how it connects to other services. It is a lightweight wrapper over the Zod validation library, the dotenv environment variable loader, with some syntactic sugar to make it all easy to use.

(full docs here)

Quick start

Create settings classes

(recommend in /src/settings)

For each group of settings create a class as follows:

import { BaseSettings, setting } from "envarna";

export class SmtpSettings extends BaseSettings {
  @setting.string()
  host: string = 'localhost';

  @setting.number()
  port: number = 25;

  @setting.string()
  fromEmail: string = 'noreply@example.org';
}

Configuration by convention

The environment variables that populate the fields of the class are derived from the naming convention of the class and the fields themselves. In the above example:

  • host is populated by the envar SMTP_HOST
  • port is populated by SMTP_PORT
  • fromEmail is populated by SMTP_FROM_EMAIL

Each environment variable is derived from the class name (SMTP_) plus the field name (FROM_EMAIL)

Create a settings object (typed proxy)

If your settings classes live in src/settings, expose a single, typed settings object. Pass the classes for IntelliSense, then initialize once at startup.

// src/settings/index.ts
import { createSettingsProxy } from 'envarna'
import { SmtpSettings } from './smtp'
import { MongoSettings } from './mongo'

export const settings = createSettingsProxy({
  smtp: SmtpSettings,
  mongo: MongoSettings,
})

// Apply overrides (optional): resolve and cache specific keys (sync or async)
export async function applyOverrides() {
  await settings.$override({
    smtp: () => SmtpSettings.load(),
    mongo: () => MongoSettings.load(), // can be async if needed
  })
}

This loads values from process environment variables or a .env file. For secrets, use an async loader:

await settings.$override({
  mongo: async () => {
    const s = MongoSettings.load()
    // e.g., fetch from a secrets manager
    // s.uri = await getSecret('prod-mongo-uri')
    return s
  },
})

Putting it all together

The above produces the following settings for smtp:

Env Var          Usual Path               Default
-------          ----------               -------
SMTP_HOST        settings.smtp.host       localhost
SMTP_PORT        settings.smtp.port       25
SMTP_FROM_EMAIL  settings.smtp.fromEmail  noreply@example.org
  • In your code,
import { settings } from './settings'

Then when you need a settings value, you use settings.smtp.host

(full docs here)

Command Line

Generate docs and environment artifacts directly from your settings classes.

  • Basics: npx envarna --help
    envarna <command>
    
    Commands:
      envarna list         Display settings details
      envarna env          Write ".env.template"
      envarna md           Write "SETTINGS.md"
      envarna values       Write "values.yaml"
      envarna compose      Display docker-compose style environment yaml
      envarna k8s          Display kubernetes style env var structure
      envarna json [root]  Display JSON settings structure
      envarna yaml [root]  Display YAML settings structure
      envarna raw          Display the raw structure extracted from the settings
                           classes used to power the other formats
    
    Options:
      --version   Show version number                                      [boolean]
      --skip-dev  Exclude fields marked @devOnly          [boolean] [default: false]
      --help      Show help                                                [boolean]
    

For json and yaml:

  • json --root <name> --flat --code: set root object, flatten groups, and use field names instead of ENVAR keys.
  • yaml --root <name> --flat --code: same for YAML output.

Example

npx envarna list
npx envarna env
npx envarna json --root cfg --flat --code --skip-dev

Error handling

When validation fails, envarna throws an EnvarnaValidationError. Use the provided type guard to branch without importing Zod.

import { isValidationError } from 'envarna'

try {
  const s = SmtpSettings.load()
} catch (err) {
  if (isValidationError(err)) {
    console.error('Invalid configuration:')
    err.issues.forEach(i => console.error(`${i.path.join('.')}${i.message}`))
  } else {
    throw err
  }
}

See the docs for details: https://pointw-dev.github.io/envarna/reference/error-handling

Testing

Envarna keeps testing simple without DI or heavy mocks. Two common patterns are supported:

  • Per-test override: Set the value that drives behavior inside each test, then restore.
  • Suite-level override: Set once in beforeEach (or beforeAll) when shared across tests.

Note: You can still DI or mock the module that exports settings , or the indivdual settings classes if preferred

Per-test override (behavior-driven)

// settings/pagination.ts
export class PaginationSettings extends BaseSettings {
  @setting.number() maxPageSize = 10
}

// settings/index.ts (lazy proxy)
export const settings = createSettingsProxy({ pagination: () => PaginationSettings.load() })

// showWidgets.test.ts
import { PaginationSettings } from './settings/pagination'
import { settings } from './settings'

it('prints 7 widgets when maxPageSize=7', () => {
  try {
    PaginationSettings.overrideForTest({ maxPageSize: 7 })
    expect(settings.pagination.maxPageSize).toBe(7)
  } finally {
    PaginationSettings.clearOverride()
  }
})

Suite-level override (shared setup)

beforeEach(() => PaginationSettings.overrideForTest({ maxPageSize: 7 }))
afterEach(() => PaginationSettings.clearOverride())

Jest-style mock (optional)

jest.mock('./settings', () => ({ settings: { pagination: { maxPageSize: 3 } } }))

Tip: For BDD or multi-scenario tests, be sure to clearOverride() and reset any cached keys if you used $override during a scenario.

Keywords

settings

FAQs

Package last updated on 31 Mar 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts