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

@incanta/config

v2.1.10

Published

A hierarchical, folder-based configuration library for Node.js with environment inheritance, variable cross-referencing, kebab-to-camelCase conversion, secrets provider integration, and support for YAML, JSON, JSONC, and JSON5 file formats.

Readme

@incanta/config

A hierarchical, folder-based configuration library for Node.js with environment inheritance, variable cross-referencing, kebab-to-camelCase conversion, secrets provider integration, and support for YAML, JSON, JSONC, and JSON5 file formats.

Installation

npm install @incanta/config
# or
yarn add @incanta/config

Quick Start

import config from "@incanta/config";

const port = config.get<number>("server.port");
const debug = config.get<boolean>("environment.development");

By default, @incanta/config looks for a config directory in the current working directory and loads the default environment. You can override this with the NODE_CONFIG_DIR and NODE_CONFIG_ENV environment variables, or by creating a new Config instance directly.

Core Concepts

Directory-Based Configuration

Configuration values are defined by the folder structure, file names, and object keys within those files. Each subfolder and each file (minus its extension) adds a segment to the config key path.

Given this structure:

config/
  default/
    _index.yaml
    server.yaml
    persistence/
      database.yaml
      redis.yaml
  • _index.yaml contents are scoped to the parent folder (no path segment added)
  • server.yaml values are accessed under server.*
  • persistence/database.yaml values are accessed under persistence.database.*
  • persistence/redis.yaml values are accessed under persistence.redis.*

For example, if server.yaml contains:

port: 3000
host: "localhost"

You access these values with:

config.get<number>("server.port");    // 3000
config.get<string>("server.host");    // "localhost"

The _index.yaml / index.yaml File

Index files are special — they do not add a path segment. Their contents are scoped to the parent directory. For example, config/default/_index.yaml:

environment:
  development: true

This is accessed as environment.development, not _index.environment.development. The underscore prefix is optional but recommended to keep the file at the top of file explorers.

Supported File Formats

  • YAML (.yaml, .yml)
  • JSON (.json)
  • JSONC (.jsonc) — JSON with comments
  • JSON5 (.json5)

You can mix file formats within the same config directory.

Environments

Environments let you override default values for different deployment targets (e.g. staging, production). Only values that differ from the default need to be specified in the environment folder.

config/
  default/          # base values (always loaded first)
    server.yaml
  staging/          # overrides for staging
    server.yaml
  production/       # overrides for production
    server.yaml

Set the environment via:

  • Environment variable: NODE_CONFIG_ENV=production
  • Constructor option: new Config({ configEnv: "production" })
  • config.init() call: config.init({ configEnv: "production" })
  • Using config-env: config-env --env=production <command>

When an environment is active, its values are deep merged on top of default. Arrays are replaced entirely (not merged).

Environment Inheritance

Environments inherit from default automatically. For more complex setups, you can inherit from additional environments using a _config.json file inside the environment folder:

config/
  default/
  staging/
    _config.json    # { "parentNames": ["kubernetes"] }
  kubernetes/
  production/
    _config.json    # { "parentNames": ["staging"] }

production/_config.json:

{
  "parentNames": ["staging"]
}

This creates an inheritance chain: defaultkubernetesstagingproduction. Values are loaded and merged in that order, with later environments taking precedence.

You can specify multiple parents for complex inheritance:

{
  "parentNames": ["production", "cloud-aws"]
}

Inheritance is resolved in order: defaultproduction (and its parents) → cloud-aws → current environment.

Override File

An override.json file placed directly in the config directory root (not inside any environment folder) is loaded last and merges on top of everything:

config/
  default/
  production/
  override.json     # applied last, on top of the active environment

Variable Cross-Referencing

Config values can reference other config values using ${path.to.variable} syntax:

# docker.yaml
image-prefix: "myregistry/myapp"

# server.yaml
image: "${docker.imagePrefix}-server"

config.get<string>("server.image") resolves to "myregistry/myapp-server".

Relative References

You can use relative paths with a leading dot (.):

# realm/instances/default.yaml
key: "default"
namespace: "realm-${./key}"    # resolves to "realm-default"

Relative paths are resolved from the current object's location in the config tree.

Recursive Resolution

References are resolved recursively, so a reference can point to another value that itself contains a reference.

Kebab-Case to camelCase Conversion

By default, kebab-case keys are automatically converted to camelCase. Both forms can be used to access the value:

# server.yaml
max-connections: 100
debug-port: 9229
config.get<number>("server.maxConnections");  // 100
config.get<number>("server.max-connections"); // 100

Variable Casing Options

You can control this behavior with a variableCasing setting in _config.json (or as a key in any config object):

| Value | Behavior | |-------|----------| | "camel" | Only camelCase keys are available (default) | | "original" | Only original keys are preserved | | "both" | Both the original and camelCase keys are available |

{
  "variableCasing": "original"
}

Config Base (Template Objects)

You can define a base/template object that other sibling objects inherit from using incantaConfigBase:

# instances/_index.yaml
incantaConfigBase: "base"
# instances/base.yaml
foo: "bar"
hello: "world"
num: 42
# instances/custom.yaml
hello: "city"

The custom object will inherit values from base and override only the specified keys:

config.get<string>("instances.custom.foo");   // "bar" (inherited)
config.get<string>("instances.custom.hello"); // "city" (overridden)
config.get<number>("instances.custom.num");   // 42 (inherited)

Secrets

@incanta/config has built-in support for fetching secrets from external providers. Any config value prefixed with secret| is treated as a secret reference:

password: "secret|my-secret-key"

Supported Providers

| Provider | Config Value | |----------|-------------| | HashiCorp Vault | "vault" | | AWS Secrets Manager | "aws-secrets-manager" | | Azure Key Vault | "azure-key-vault" | | GCP Secret Manager | "gcp-secret-manager" | | Local (file-based) | "local" | | None (disabled) | "none" |

Configure the provider in your config files:

# secrets.yaml
provider: "none"
cache-duration-seconds: 300

Fetching Secrets

Use getWithSecrets() to resolve secret references:

const dbConfig = await config.getWithSecrets<IDatabaseConfig>(
  "persistence.database"
);

This recursively walks the returned object and replaces any "secret|..." strings with values fetched from the configured secrets provider. Results are cached according to secrets.cache-duration-seconds.

Environment Variable Injection (config-env)

The package includes a config-env CLI tool that injects config values as environment variables into a child process. This tool will also inject the NODE_CONFIG_ENV variable to the child process.

Define an environment.yaml (or environment.json, etc.) file in the config directory root mapping environment variable names to config paths:

# environment.yaml
DATABASE_HOST: "persistence.database.host"
DATABASE_PORT: "persistence.database.port"

CLI Usage

npx config-env <command>

# With a specific config environment:
npx config-env --env=production <command>
npx config-env -e=production <command>

Programmatic Usage

import config from "@incanta/config";

const envVars = config.getConfiguredEnv();
// { DATABASE_HOST: "localhost", DATABASE_PORT: "5432" }

config-settings.json

Place a config-settings.json file in the working directory root to customize the config system's behavior:

{
  "defaults": {
    "dir": "config/node",       // default config directory (default: "config")
    "env": "my-default-env"     // default environment name (default: "default")
  },
  "extraDirs": [
    "/path/to/additional/config"  // extra directories to search for environments
  ]
}

Extra Directories

extraDirs allows environment folders to live outside the main config directory. This is useful when you want to keep project-specific configuration separate from shared configuration:

{
  "extraDirs": [
    "C:\\path\\to\\MyProject\\Config\\Backend"
  ]
}

When resolving an environment name, the library first checks the main config directory, then checks each extra directory in order.

API Reference

Default Export (Singleton)

import config from "@incanta/config";

Returns a singleton Config instance, initialized with defaults on first access.

Config Class

import Config from "@incanta/config/config";

Constructor

const config = new Config(options?: IConfigOptions);

| Option | Type | Description | |--------|------|-------------| | configDir | string | Path to the config directory | | configEnv | string | Environment name to load | | cwd | string | Working directory for resolving relative paths |

Methods

| Method | Returns | Description | |--------|---------|-------------| | init(options?) | void | Re-initialize with new options | | get<T>(key) | T | Get a value by dot-separated path; throws if not found | | tryGet<T>(key) | T \| null | Get a value, returning null if the key doesn't exist | | getWithSecrets<T>(key) | Promise<T> | Get a value and resolve any secret\|... references | | processSecrets<T>(value) | Promise<T> | Recursively resolve secrets in an arbitrary value | | getConfiguredEnv() | object | Get env vars mapped from the environment.* config file | | getJson() | object | Get the entire resolved config as a plain object | | set<T>(key, value) | void | Set a runtime config value | | dir() | string | Get the active config directory path | | env() | string | Get the active environment name | | cwd() | string | Get the working directory |

Environment Variables

| Variable | Description | |----------|-------------| | NODE_CONFIG_DIR | Override the config directory path | | NODE_CONFIG_ENV | Override the config environment name | | NODE_CONFIG_SKIP_ENV_WARNING | Set to "true" to suppress missing environment warnings |

Example Project Structure

A typical project using @incanta/config:

my-project/
  config-settings.json           # optional: customize defaults and extra dirs
  config/
    environment.yaml             # env var mappings for config-env CLI
    override.json                # optional: final overrides
    default/                     # base configuration
      _index.yaml
      server.yaml
      persistence/
        database.yaml
        redis.yaml
    staging/                     # staging overrides
      _config.json               # { "parentNames": ["kubernetes"] }
      _index.yaml
    kubernetes/                  # kubernetes-specific values
      server.yaml
    production/                  # production overrides
      _config.json               # { "parentNames": ["staging"] }
      persistence/
        database.yaml
  src/
    index.ts

License

MIT