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

@l10nmonster/config-mancer

v3.1.1

Published

Configuration management utilities with schema validation and object construction

Downloads

360

Readme

@l10nmonster/configMancer

Configuration management utilities with schema validation and object construction for L10n Monster.

Overview

ConfigMancer provides a powerful configuration system that enables:

  • Schema-based validation: Define and validate configuration objects against schemas
  • Dynamic object construction: Automatically construct typed objects from configuration data
  • Proxy-based behavior: Extend objects with inherited behavior through proxies
  • JSON parsing with validation: Parse and validate JSON configuration files
  • Contextual properties: Inject additional properties (like @baseDir) into all constructed objects
  • File import helpers: Built-in classes for importing text and JSON files with automatic path resolution
  • Serialization: Convert objects back to JSON configuration format
  • JSON Schema generation: Generate JSON Schema files for configuration authoring and validation
  • Package discovery: Automatically discover configuration classes from npm packages
  • Module resolution: Proper handling of both CommonJS and ESM modules with correct resolution context
  • Lazy loading: Efficient schema management with support for async package loading
  • Constants support: Support for constant configuration values
  • Modular design: Separate concerns with dedicated classes for different functionality

Classes

BaseConfigMancerType

A base class that creates proxy objects allowing configuration objects to inherit behavior from their prototypes.

import { BaseConfigMancerType } from '@l10nmonster/configMancer';

class MyConfigType extends BaseConfigMancerType {
    myMethod() {
        return `Hello ${this.name}`;
    }
}

const config = new MyConfigType({ name: 'World' });
console.log(config.myMethod()); // "Hello World"

ConfigMancer

The main class for schema validation and object construction.

Creating ConfigMancer with Local Classes

For simple cases with local classes, you can use the ConfigMancer.create() method:

import { ConfigMancer, BaseConfigMancerType } from '@l10nmonster/configMancer';

class DatabaseConfig extends BaseConfigMancerType {
    static configMancerSample = {
        '@': 'database',
        host: 'localhost',
        port: 5432,
        ssl: true
    };
}

class ApiConfig extends BaseConfigMancerType {
    static configMancerSample = {
        '@': 'api',
        url: 'https://api.example.com',
        $timeout: 5000, // optional parameter (prefixed with $)
        databases: [{ '@': 'database' }] // array of database configs
    };
}

// Create with local classes
const mancer = await ConfigMancer.create({
    classes: {
        DatabaseConfig,
        ApiConfig
    }
});

Creating from Packages

ConfigMancer can automatically discover configuration classes from npm packages using the create factory method:

const mancer = await ConfigMancer.create({
    baseUrl: import.meta.url,
    packages: ['@myorg/config-package', './local-config-module.mjs']
});

This method:

  • Handles both CommonJS and ESM modules automatically
  • Dynamically imports each package using proper module resolution
  • Recursively inspects exports for objects with configMancerSample properties
  • Supports both direct exports and nested object exports
  • Creates type names in the format packageName:exportPath
  • Resolves modules from the calling code's context (fixes module resolution issues)

Mixed Sources

You can combine classes and packages in a single call:

const mancer = await ConfigMancer.create({
    baseUrl: import.meta.url,
    packages: ['@myorg/config-package'],
    classes: { LocalConfig: LocalConfigClass }
});

Note: The create() method is asynchronous and returns a Promise, even when using classes-only configurations.

Constants Support

ConfigMancer supports constant configuration values by setting configMancerSample = true:

const API_ENDPOINTS = {
    production: 'https://api.prod.example.com',
    staging: 'https://api.staging.example.com'
};
API_ENDPOINTS.configMancerSample = true;

const mancer = await ConfigMancer.create({
    classes: { ApiEndpoints: API_ENDPOINTS }
});

// In configuration file:
{
    "@": "ApiEndpoints"
}
// Returns the constant object directly

Schema Definition

Schema parameters are defined using object notation in the configMancerSample property:

  • Properties prefixed with $ are optional (e.g., $timeout)
  • Properties without $ prefix are required (e.g., host, port)
  • Arrays are indicated by using array notation with type examples (e.g., [{ '@': 'database' }])
  • Nested objects are indicated by using object notation with type references (e.g., { '@': 'otherType' })

Internally, ConfigMancer converts these to schema entries with the format [type, isMandatory, isArray].

Validation-Only Mode

// Enable validation-only mode
const mancer = await ConfigMancer.create({ classes: { DatabaseConfig } });
mancer.validationOnly = true;

// Validate configuration without constructing objects
const config = mancer.reviveFile('./config.json');

// Disable validation-only mode to construct typed objects
mancer.validationOnly = false;
const typedConfig = mancer.reviveFile('./config.json');

Serialization

ConfigMancer provides methods to serialize objects back to JSON configuration format:

// Serialize an object to JSON configuration format
const serialized = mancer.serialize(configObject);

// Serialize and write to file
mancer.serializeToPathName(configObject, './config.json');

The serialization process:

  • Recursively serializes nested objects and arrays
  • Adds @ type identifiers for configured objects
  • Handles circular reference detection
  • Preserves primitive values and plain objects

JSON Schema Generation

ConfigMancer can generate JSON Schema files that can be used for configuration authoring and validation in IDEs and other tools:

// Generate JSON Schema for a root configuration type
mancer.writeJsonSchema('ApiConfig', './config.schema.json');

The generated JSON Schema:

  • Complies with JSON Schema Draft 07 specification
  • Includes all type definitions with proper references and constraints
  • Handles complex nested structures with arrays and objects
  • Supports constant values using JSON Schema's const keyword
  • Provides proper validation rules for mandatory vs optional properties
  • Prevents circular references using $ref definitions

Generated schemas can be used with:

  • IDE/Editor support for autocomplete and validation during configuration authoring
  • JSON Schema validators for runtime validation
  • Documentation tools that support JSON Schema
  • Configuration authoring tools with JSON Schema integration

Example Configuration File

{
    "@": "api",
    "url": "https://production.example.com",
    "timeout": 10000,
    "databases": [
        {
            "@": "database",
            "host": "db1.example.com",
            "port": 5432,
            "ssl": true
        },
        {
            "@": "database", 
            "host": "db2.example.com",
            "port": 5432,
            "ssl": false
        }
    ]
}

API Reference

new ConfigMancer(schemaManager)

Creates a ConfigMancer instance with a pre-configured SchemaManager.

Parameters:

  • schemaManager: A SchemaManager instance containing type definitions

Returns: ConfigMancer instance

Note: This is a low-level constructor. Most users should use ConfigMancer.create() instead.

ConfigMancer.create(options)

Creates a ConfigMancer instance with automatic schema manager creation and package loading.

Parameters:

  • options.baseUrl: URL for module resolution (usually import.meta.url)
  • options.packages: Array of package names to search for types
  • options.classes: Object mapping type names to configuration classes

Returns: Promise instance

configMancer.validationOnly

Property that controls whether the ConfigMancer instance only validates without constructing objects.

Type: boolean Default: false

configMancer.reviveFile(pathName)

Parses and constructs typed objects from a JSON configuration file.

Parameters:

  • pathName: Path to the JSON configuration file

Returns: Constructed configuration object with typed instances

configMancer.createReviver(additionalProperties)

Creates a JSON reviver function for custom parsing with JSON.parse().

Parameters:

  • additionalProperties (optional): Object containing additional properties to be merged into all constructed objects

Returns: JSON reviver function that validates and constructs objects

Example:

// Create reviver with additional context
const reviver = mancer.createReviver({ 
    '@baseDir': '/path/to/config',
    environment: 'production' 
});

const config = JSON.parse(jsonString, reviver);
// All constructed objects will have @baseDir and environment properties

configMancer.serialize(obj, visited)

Recursively serializes an object into ConfigMancer-compatible format.

Parameters:

  • obj: The object to serialize
  • visited: Set to track visited objects (optional, used internally)

Returns: Serialized object that can be saved as JSON

configMancer.serializeToPathName(obj, pathName, indent)

Serializes an object and writes it to a file as JSON.

Parameters:

  • obj: The object to serialize and write
  • pathName: Path to the file where the serialized object will be written
  • indent: Number of spaces for JSON indentation (default: 2)

configMancer.writeJsonSchema(rootType, pathName)

Generates a JSON Schema for the specified root type and writes it to a file.

Parameters:

  • rootType: The name of the root type to generate schema for
  • pathName: Path to the file where the JSON schema will be written

Returns: None (writes to file)

Throws: Error if the root type is not found in the schema or file cannot be written

configMancer.generateSchemaDocs()

Generates comprehensive markdown documentation for the entire schema.

Returns: String containing markdown documentation

Example:

const mancer = await ConfigMancer.create({
    classes: { DatabaseConfig, ApiConfig }
});

const docs = mancer.generateSchemaDocs();
console.log(docs);
// Outputs structured markdown documentation

The generated documentation includes:

  • Organized by supertype: Types are grouped under major headings based on their superType
  • Root types first: Types where superType === typeName are listed under "Root Types" heading
  • Alphabetical sorting: Both supertypes and types within each supertype are sorted alphabetically
  • Parameter details: Each type shows all parameters with their types, whether they're required/optional, and array indicators
  • Constant values: Constant configuration values are documented with their type and value
  • Comprehensive coverage: Documents all types in the schema including those from packages

Sample output:

# ConfigMancer Schema Documentation

## Root Types

### DatabaseConfig
**Parameters:**
- `host` (required): `string`
- `port` (required): `number`
- `ssl` (required): `boolean`
- `timeout` (optional): `number`

## object

### MyPackage:SomeConstant
**Constant value of type:** `object`
**Value:** `{"endpoint": "https://api.example.com"}`

Custom Configuration Classes

Extending BaseConfigMancerType

class MyConfig extends BaseConfigMancerType {
    static configMancerSample = {
        '@': 'myconfig',
        name: 'example',
        value: 42
    };

    getDisplayName() {
        return `${this.name}: ${this.value}`;
    }
}

Custom Classes (without extending BaseConfigMancerType)

class CustomConfig {
    static configMancerSample = {
        '@': 'custom',
        name: 'example',
        value: 42
    };

    static configMancerFactory(obj) {
        return new CustomConfig(obj);
    }

    constructor(obj) {
        Object.assign(this, obj);
    }

    configMancerSerializer() {
        return {
            name: this.name,
            value: this.value
        };
    }
}

Helper Classes

ConfigMancer includes built-in helper classes for common configuration patterns.

File Import Helpers

ImportTextFile

Imports text content from a file. Useful for loading templates, schemas, or other text-based resources.

// In configuration JSON:
{
    "@": "ImportTextFile",
    "fileName": "schema.sql"
}

// Returns the text content of the file as a string

ImportJsonFile

Imports and parses JSON content from a file. Useful for loading external JSON configurations or data files.

// In configuration JSON:
{
    "@": "ImportJsonFile", 
    "fileName": "database-config.json"
}

// Returns the parsed JSON object

File Path Resolution

Both helper classes support automatic path resolution using the @baseDir property, which is automatically provided by reviveFile():

// config.json (in /app/config/ directory)
{
    "@": "AppConfig",
    "database": {
        "@": "ImportJsonFile",
        "fileName": "database.json"  // Resolves to /app/config/database.json
    },
    "schema": {
        "@": "ImportTextFile", 
        "fileName": "schema.sql"     // Resolves to /app/config/schema.sql
    }
}

// Load configuration
const config = mancer.reviveFile('/app/config/config.json');
// Files are loaded relative to the config file location

You can also provide @baseDir explicitly when using createReviver():

const reviver = mancer.createReviver({ '@baseDir': '/custom/path' });
const config = JSON.parse(jsonString, reviver);

Error Handling

The file import helpers provide clear error messages for common issues:

  • File not found: Throws ENOENT error with the full file path
  • Malformed JSON: For ImportJsonFile, throws JSON parsing errors with location details
  • Permission errors: Throws appropriate file system errors

Example Configuration

// app-config.json
{
    "@": "ApplicationConfig",
    "name": "My Application",
    "database": {
        "@": "ImportJsonFile",
        "fileName": "database.json"
    },
    "apiSchema": {
        "@": "ImportTextFile", 
        "fileName": "api-schema.graphql"
    },
    "routes": {
        "@": "ImportJsonFile",
        "fileName": "routes/main.json"
    }
}

// database.json
{
    "host": "localhost",
    "port": 5432,
    "ssl": true
}

// Usage
const config = mancer.reviveFile('./app-config.json');
console.log(config.name);          // "My Application"
console.log(config.database.host); // "localhost"
console.log(config.apiSchema);     // GraphQL schema as string

Schema Definition Format

Configuration classes must include a static configMancerSample property that defines the schema:

static configMancerSample = {
    '@': 'typeName',           // Type identifier
    mandatoryParam: 'string',  // Required parameter
    $optionalParam: 42,        // Optional parameter (prefixed with $)
    arrayParam: [{ '@': 'childType' }], // Array of typed objects
    nestedParam: { '@': 'otherType' }   // Nested typed object
};

For constant values, set configMancerSample = true:

const CONSTANT_CONFIG = {
    value1: 'constant',
    value2: 42
};
CONSTANT_CONFIG.configMancerSample = true;

Required Methods

For ConfigMancer Integration

All configuration classes must implement:

  • static configMancerSample: Schema definition
  • static configMancerFactory(obj): Factory method for creating instances

For Serialization

Classes that need serialization support must implement:

  • configMancerSerializer(): Returns a plain object representing the instance's data

Error Handling

ConfigMancer provides detailed error messages for:

  • Missing mandatory properties
  • Type mismatches
  • Invalid array configurations
  • Schema violations
  • Unknown configuration types
  • Circular references during serialization
  • Missing required methods (configMancerFactory, configMancerSerializer)

All errors include context about the specific configuration path and expected values.

Complete Example

import { ConfigMancer, BaseConfigMancerType } from '@l10nmonster/configMancer';

// Define configuration classes
class DatabaseConfig extends BaseConfigMancerType {
    static configMancerSample = {
        '@': 'database',
        host: 'localhost',
        port: 5432,
        ssl: true,
        $timeout: 30000
    };

    getConnectionString() {
        return `${this.host}:${this.port}`;
    }
}

class ApiConfig extends BaseConfigMancerType {
    static configMancerSample = {
        '@': 'api',
        url: 'https://api.example.com',
        $timeout: 5000,
        databases: [{ '@': 'database' }]
    };

    getPrimaryDatabase() {
        return this.databases[0];
    }
}

// Create ConfigMancer
const mancer = await ConfigMancer.create({
    classes: {
        DatabaseConfig,
        ApiConfig
    }
});

// Load and validate configuration
const config = mancer.reviveFile('./config.json');
console.log(config.getPrimaryDatabase().getConnectionString());

// Generate JSON Schema
mancer.writeJsonSchema('ApiConfig', './config.schema.json');

// Serialize configuration
const serialized = mancer.serialize(config);
mancer.serializeToPathName(serialized, './output.json');

Migration from Previous Versions

Constructor Changes

Before:

const mancer = new ConfigMancer({ classes: { MyConfig } });
const mancer = new ConfigMancer({ classes: { MyConfig } }, true); // validation only

After:

const mancer = await ConfigMancer.create({ classes: { MyConfig } });
mancer.validationOnly = true; // set property directly

Factory Method Changes

Before:

const mancer = await ConfigMancer.createFromSources([
    '@myorg/config-package'
], import.meta.url, true);

After:

const mancer = await ConfigMancer.create({
    baseUrl: import.meta.url,
    packages: ['@myorg/config-package']
});
mancer.validationOnly = true; // set property directly

Removed Methods

  • configMancer.initialize() - Use ConfigMancer.create() instead
  • configMancer.schema - Use configMancer.schemaManager.schema instead
  • ConfigMancer.createFromSources() - Use ConfigMancer.create() instead