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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@nextnode/config-manager

v3.1.5

Published

A TypeScript configuration management library with automatic type generation from JSON config files. Provides environment-aware configuration loading with intelligent type inference.

Readme

@nextnode/config-manager

A powerful TypeScript configuration management library with automatic type generation from your JSON config files. Provides flexible, environment-aware configuration loading with intelligent type inference, eliminating the need for manual type annotations.

✨ Key Features

🚀 Automatic Type Generation

  • Zero configuration: Types are automatically generated from your JSON config files
  • Smart detection: Automatically detects user projects and config directories
  • Intelligent caching: Only regenerates types when config files change
  • Perfect type safety: Eliminates optional chaining (?.) in your configuration access

🎯 Enhanced Type Inference

  • No generics needed: getConfig() automatically infers precise types
  • Path-based inference: getConfig('email.from') returns the exact type
  • Module augmentation: Optional schema declaration for even more precise types

💪 Robust & Maintainable

  • Modern error handling: Meaningful error propagation without silent failures
  • Clean architecture: Refactored codebase following modern TypeScript patterns
  • Zero defensive coding: Eliminates unnecessary try-catch blocks and fallbacks

Core Features

  • 🚀 Automatic type generation - Generates precise TypeScript types from your JSON config files
  • 🎯 Intelligent type inference - No generics needed, automatic type detection from config structure
  • 🔧 Environment-based configuration - Support for multiple environments (development, staging, production)
  • 🛡️ Perfect type safety - Eliminates optional chaining with precise generated types
  • 📁 Smart config detection - Automatically finds config directories (config/, configs/, src/config/, etc.)
  • 🎯 Dot notation access - Easy access to nested configuration values with type safety
  • 🔄 Intelligent caching - Hash-based change detection, only regenerates when needed
  • Configuration validation - Built-in validation for required configuration paths
  • 🌍 Environment detection - Automatic environment detection with manual override
  • 💪 Robust error handling - Modern error patterns with meaningful error propagation
  • 📦 Zero configuration - Works out of the box for most project structures

Installation

npm install @nextnode/config-manager

Or with pnpm:

pnpm add @nextnode/config-manager

Or with yarn:

yarn add @nextnode/config-manager

Quick Start

Basic Usage

import { getConfig, initConfig } from '@nextnode/config-manager'

// Initialize the configuration system (automatically detects config/ directory)
initConfig({
	configDir: './config', // optional, auto-detected
	environment: 'development', // optional, auto-detected from NODE_ENV
	cache: true, // optional, defaults to true
})

// Get configuration values with automatic type inference
const appName = getConfig('app.name') // string - no generics needed!
const emailProvider = getConfig('email.provider') // string
const features = getConfig('app.features') // string[]

// Get entire configuration sections with perfect types
const emailConfig = getConfig('email') // EmailConfig with all properties typed
const appConfig = getConfig('app') // AppConfig with all properties typed
const fullConfig = getConfig() // Complete config object, fully typed

// Perfect type safety - no optional chaining needed!
console.log(emailConfig.from) // ✅ Direct access
console.log(appConfig.features.length) // ✅ Array methods available

Configuration File Structure

Create configuration files in your project's config directory:

config/
├── default.json          # Base configuration
├── development.json      # Development overrides
├── staging.json         # Staging overrides
└── production.json      # Production overrides

Example config/default.json:

{
	"app": {
		"name": "My Application",
		"version": "1.0.0",
		"features": ["authentication", "analytics"],
		"environment": "development"
	},
	"email": {
		"provider": "resend",
		"from": "[email protected]",
		"to": "[email protected]",
		"templates": {
			"projectRequest": {
				"subject": "New Project Request",
				"companyName": "Your Company",
				"websiteUrl": "https://example.com"
			}
		}
	}
}

Example config/production.json:

{
	"app": {
		"environment": "production"
	},
	"email": {
		"provider": "nodemailer",
		"from": "[email protected]",
		"to": "[email protected]"
	}
}

🚀 Automatic Type Generation

The library automatically generates precise TypeScript types from your JSON configuration files, providing perfect type safety without any manual setup.

How It Works

  1. Auto-Detection: When you install @nextnode/config-manager in your project, it automatically detects if you have a config/ directory
  2. Smart Generation: On first use of initConfig() or getConfig(), it scans your JSON files and generates TypeScript definitions
  3. Intelligent Caching: Types are only regenerated when your config files change (using MD5 hash comparison)
  4. Zero Configuration: Works out of the box with standard project structures

Generated Type Files

The system creates a types/config.d.ts file in your project root:

// types/config.d.ts (auto-generated)
declare module '@nextnode/config-manager' {
	interface UserConfigSchema {
		app: {
			name: string
			version: string
			features: string[]
			environment: string
		}
		email: {
			provider: string
			from: string
			to: string
			templates: {
				projectRequest: {
					subject: string
					companyName: string
					websiteUrl: string
				}
			}
		}
	}
}

Project Detection

The auto-generation system detects user projects by:

  • ✅ Finding a config/ directory in your project root
  • ✅ Checking that the current project is NOT @nextnode/config-manager itself
  • ✅ Supporting various config directory names (config/, configs/, src/config/, etc.)

Manual Type Generation

You can also generate types manually using the CLI:

# Generate types for your config directory
npx @nextnode/config-manager generate-types

# Custom config directory
npx @nextnode/config-manager generate-types ./my-config ./types/my-config.d.ts

API Reference

Configuration Functions

initConfig(options?)

Initialize the configuration system with custom options. Automatically triggers type generation for user projects.

initConfig({
  environment?: string    // Override auto-detected environment
  configDir?: string     // Custom config directory path (auto-detected if not provided)
  cache?: boolean        // Enable/disable caching (default: true)
})

New Behavior:

  • Automatically detects config/ directory in your project root
  • Triggers type generation on first initialization
  • Only regenerates types when config files change

getConfig(path?, environment?) / getConfig<T>(path?, environment?)

Get configuration value with automatic type inference. No generics needed in most cases!

// ✨ NEW: Automatic type inference (recommended)
const value = getConfig('email.from') // string
const features = getConfig('app.features') // string[]
const emailConfig = getConfig('email') // EmailConfig
const allConfig = getConfig() // Full config object

// Legacy: Manual type specification (still supported)
const value = getConfig<string>('email.from')
const features = getConfig<string[]>('app.features')

// Environment override
const prodEmail = getConfig('email.from', 'production')

Type Inference Features:

  • Path-based inference: Return type automatically matches your config structure
  • Section inference: Getting 'email' returns the complete EmailConfig interface
  • Full config inference: Calling getConfig() returns the complete typed configuration

hasConfig(path, environment?)

Check if a configuration path exists.

if (hasConfig('email.templates.welcome')) {
	// Configuration exists
}

validateRequiredConfig(requiredPaths, environment?)

Validate that required configuration paths exist.

const validation = validateRequiredConfig([
	'app.name',
	'email.from',
	'email.provider',
])

if (!validation.valid) {
	console.error('Missing required config:', validation.missing)
}

Utility Functions

getEnvironment()

Get the current environment name.

const env = getEnvironment() // 'development', 'staging', 'production', etc.

getAvailableEnvironments()

Get list of all available configuration environments.

const environments = getAvailableEnvironments()
// ['default', 'development', 'staging', 'production']

clearConfigCache()

Clear the configuration cache (useful for testing or hot reloading).

clearConfigCache()

Advanced Utilities

deepMerge(target, source)

Deep merge configuration objects.

import { deepMerge } from '@nextnode/config-manager'

const merged = deepMerge(baseConfig, overrideConfig)

getNestedValue<T>(object, path)

Get nested value using dot notation.

import { getNestedValue } from '@nextnode/config-manager'

const value = getNestedValue(config, 'email.templates.welcome.subject')

setNestedValue(object, path, value)

Set nested value using dot notation.

import { setNestedValue } from '@nextnode/config-manager'

setNestedValue(config, 'email.provider', 'sendgrid')

TypeScript Support

🚀 Automatic Type Generation (Recommended)

The library now automatically generates precise TypeScript definitions from your JSON config files:

// types/config.d.ts (auto-generated from your JSON files)
declare module '@nextnode/config-manager' {
	interface UserConfigSchema {
		app: {
			name: string
			version: string
			features: string[]
			environment: string
		}
		email: {
			provider: 'resend' | 'nodemailer' // Inferred from your actual values
			from: string
			to: string
			replyTo?: string // Optional if null in any config
			templates: {
				projectRequest: {
					subject: string
					companyName: string
					websiteUrl: string
					companyLogo?: string
				}
			}
		}
	}
}

// Now your code has perfect type safety:
const config = getConfig() // Fully typed!
const provider = getConfig('email.provider') // 'resend' | 'nodemailer'

Manual Module Augmentation (Advanced)

For even more precise types, you can manually declare your configuration schema:

// In your project, create a types/config.d.ts file:
declare module '@nextnode/config-manager' {
	interface UserConfigSchema {
		app: {
			name: string
			version: string
			features: ('auth' | 'analytics' | 'payments')[] // Specific union types
			environment: 'development' | 'staging' | 'production'
			debug?: boolean
		}
		email: {
			provider: 'sendgrid' | 'resend' | 'mock'
			from: string
			to: string
			apiKey?: string // Only in production
		}
		database: {
			host: string
			port: number
			ssl: boolean
			credentials: {
				username: string
				password: string
			}
		}
	}
}

Environment Detection

The configuration system automatically detects the environment in this order:

  1. environment option passed to initConfig()
  2. NODE_ENV environment variable
  3. Defaults to 'development'

Configuration Loading Priority

Configurations are merged in this order (later configs override earlier ones):

  1. default.json - Base configuration
  2. {environment}.json - Environment-specific configuration
  3. local.json - Local overrides (git-ignored, optional)

Best Practices

1. Leverage Automatic Type Generation 🚀

// ✅ RECOMMENDED: Let the library handle types automatically
initConfig({ configDir: './config' })
const emailConfig = getConfig('email') // Perfectly typed!
const dbHost = getConfig('database.host') // string

// ❌ AVOID: Manual type annotations (unless needed for specific unions)
const emailConfig = getConfig<EmailConfig>('email')

2. Organize Configuration by Feature

{
	"database": {
		"host": "localhost",
		"port": 5432,
		"ssl": false
	},
	"redis": {
		"host": "localhost",
		"port": 6379
	},
	"email": {
		"provider": "resend",
		"from": "[email protected]"
	},
	"features": {
		"authentication": true,
		"analytics": false,
		"payments": true
	}
}

3. Use Environment Variables for Secrets

{
	"database": {
		"password": "${DATABASE_PASSWORD}"
	},
	"email": {
		"apiKey": "${EMAIL_API_KEY}"
	},
	"auth": {
		"jwtSecret": "${JWT_SECRET}"
	}
}

4. Validate Required Configuration at Startup

// ✅ With automatic type inference, validation is easier
const validation = validateRequiredConfig([
	'database.host',
	'database.password',
	'email.apiKey',
	'auth.jwtSecret',
])

if (!validation.valid) {
	console.error('Missing required configuration:', validation.missing)
	process.exit(1)
}

// ✅ Direct access with confidence (no optional chaining needed)
const config = getConfig()
console.log(`Connecting to ${config.database.host}:${config.database.port}`)

5. Handle Configuration Errors Gracefully

// ✅ The library now propagates meaningful errors
try {
	await initConfig({ configDir: './config' })
} catch (error) {
	// You'll get specific error messages for:
	// - Missing config directory
	// - Invalid JSON syntax
	// - Configuration validation failures
	// - Type generation issues
	console.error('Configuration initialization failed:', error.message)
	process.exit(1)
}

6. Structure for Multiple Environments

config/
├── default.json         # Base configuration
├── development.json     # Development overrides
├── staging.json        # Staging environment
├── production.json     # Production environment
├── test.json          # Test environment
└── local.json         # Git-ignored local overrides

Troubleshooting

Configuration Not Found

  • Verify the config directory path
  • Check file naming (must match environment name)
  • Ensure JSON syntax is valid

Type Errors

  • Ensure TypeScript types match your configuration structure
  • Use generic types for custom configuration schemas
  • Check that optional fields are properly marked

Environment Issues

  • Verify NODE_ENV is set correctly
  • Use getEnvironment() to debug current environment
  • Check getAvailableEnvironments() for valid options

Error Handling

  • The library uses modern error propagation patterns
  • Errors are no longer silently swallowed - you'll see meaningful messages
  • Configuration and type generation failures surface with specific details
  • Use try-catch blocks around initConfig() for graceful error handling

Contributing

We welcome contributions! Please ensure your code:

  • Follows TypeScript best practices
  • Includes proper type definitions
  • Has comprehensive test coverage
  • Follows the existing code style

Development

# Install dependencies
pnpm install

# Generate config types from test fixtures
pnpm generate-test-types

# Run tests with full coverage
pnpm test

# Type checking (includes test type generation)
pnpm type-check

# Linting
pnpm lint

# Build the library
pnpm build

# Format code
pnpm format

# Manual type generation for config directory
pnpm generate-config-types [configDir] [outputFile]

Development Workflow

  1. Type Generation: The library includes automatic type generation for both library development and user projects
  2. Test Types: Run pnpm generate-test-types to generate types from test fixtures
  3. Type Safety: The type-check script automatically generates test types before checking
  4. Continuous Integration: All scripts are designed to work in CI environments

Working with Generated Types

During development, you may need to regenerate types:

# Regenerate types from your project's config files
node src/generate-types.js ./config ./types/config.d.ts

# Or use the npm script for test fixtures
pnpm generate-test-types

License

ISC