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

kfg

v1.8.0

Published

Powerful, type-safe configuration system for Node.js, Bun, and Deno. Built on TypeBox with Laravel-style rules and smart environment tracing.

Readme

K(con)fg - Simple, Type-Safe Configuration Management

npm version Build Documentation

Kfg is a robust and 100% type-safe configuration management system for Node.js, Bun, and Deno. It provides a structured way to define, validate, and access environment variables and other configuration sources with the power of TypeScript.

  • ✅ Fully Typed: Autocomplete and type safety for all your configurations.
  • ✅ Flexible Drivers: Load configurations from .env files, JSON, or create your own driver.
  • ✅ Built-in Validation: Define rules and formats (email, url, etc.) directly in the schema.
  • ✅ Smart Defaults: Define defaults that are applied automatically.
  • ✅ Nested Structures: Organize your configurations logically.
  • ✅ Scoped Pools: One configuration per tenant, guild, or project — same API, no call-site changes.
  • ✅ Safeguarded Writes: Atomic write + verify, cross-process locking, backup with auto-recovery.
  • ✅ Sync or Async: JsonDriver blocks; JsonAsyncDriver does the same work without stalling the event loop.

📖 Documentation

Installation

npm install kfg
# or
yarn add kfg
# or
bun add kfg

Quick Example

1. Define your schema (schema.ts):

import { c } from "kfg";

export const AppSchema = {
  server: {
    host: c.string({ default: "0.0.0.0" }),
    port: c.number({ default: 3000 }),
  },
  database: {
    url: c.string({ prop: "DATABASE_URL" }), // Reads from the DATABASE_URL environment variable
  },
};

2. Create and load your instance (config.ts):

import { Kfg, EnvDriver } from "kfg";
import { AppSchema } from "./schema";

const config = new Kfg(new EnvDriver(), AppSchema);
config.load(); // Loads values from .env and process.env

export default config;

3. Use it anywhere (index.ts):

import config from "./config";

const port = config.get("server.port"); // Inferred as `number`
const dbUrl = config.get("database.url"); // Inferred as `string`

console.log(`Server running on port ${port}`);

// Type Error! TypeScript prevents incorrect assignments.
// config.set("server.port", "not-a-number");

File-based Configuration with JsonDriver

JsonDriver persists the configuration to a JSON file, with the same API and typing:

import { Kfg, JsonDriver, c } from "kfg";

const config = new Kfg(new JsonDriver({ path: "resources/config.json" }), {
  items: c.array(c.string(), { default: [] }),
  owner: c.string({ default: "unknown" }),
});

config.load();
config.set("owner", "Alice");
config.set("items", ["sword", "shield"]);

Every write goes through the safeguard layer: the content is written to a temp file, read back and verified, then atomically renamed over the target, under a lock file that keeps concurrent processes from clobbering each other. A mirror is kept in <file>.bak and restored automatically if the main file is ever corrupted.

When several keys change at once, write them in a single transaction instead of one set per key — it is both atomic across processes and far cheaper:

config.mutate((draft) => {
  draft.owner = "Alice";
  draft.items = ["sword", "shield"];
});

Scoped Configuration with Kfg.pool

For one configuration per tenant, guild, or project, Kfg.pool keeps an instance per scope id and exposes the exact same API as a single instance — existing call sites keep their types and autocompletion:

import { Kfg, JsonDriver, c } from "kfg";

const Config = Kfg.pool(schema, {
    driver: (id) => new JsonDriver({ path: `resources/guilds/${id}/config.json` }),
    max: 500,            // keep at most 500 configs in memory (LRU)
});

// Ambient scope: everything inside sees this guild, including awaited code.
await Config.run(guildId, async () => {
    Config.get("tks.category");
    Config.set("tks.enabled", true);
});

// Or address a scope explicitly — for dashboards and background jobs.
Config.for(guildId).set("tks.enabled", false);

Instances are created on first access and reloaded lazily. A corrupted file for one scope throws a KfgValidationError carrying that scope instead of exiting the process, so the other scopes keep working.

Without an active scope, operations throw KfgScopeError rather than guessing. During a migration you can set defaultScope and watch missingScopeCount (or pass onMissingScope) to find the call sites that still run outside a scope.

License

MIT