JSPM

  • Created
  • Published
  • Downloads 8
  • Score
    100M100P100Q47195F
  • License SEE LICENSE IN LICENSE.md

Universal config converter framework with exceptional developer experience

Package Exports

  • configforge
  • configforge/dist/index.js

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (configforge) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

ConfigForge

Universal config converter framework with a fluent API

ConfigForge makes it easy to convert configuration files between different formats and structures. Just define your mappings and let ConfigForge handle the rest.

🚀 Quick Start

Installation

npm install configforge

Basic Usage

const { forge } = require('configforge');

// Your source configuration
const sourceConfig = {
  name: 'MyApp',
  version: '1.0',
  author: {
    firstName: 'John',
    lastName: 'Doe',
  },
  items: ['apple', 'banana', 'cherry'],
};

// Create converter and define mappings
const converter = forge()
  .from('source')
  .to('target')
  .map('name', 'appName')
  .map('version', 'appVersion')
  .map('author.firstName', 'authorName')
  .map('items[0]', 'firstItem');

// Convert the data
const result = await converter.convert(sourceConfig);

console.log(result.data);
// Output:
// {
//   appName: 'MyApp',
//   appVersion: '1.0',
//   authorName: 'John',
//   firstItem: 'apple'
// }

📖 How It Works

1. Create a Converter

const converter = forge()
  .from('sourceSchema') // Define source
  .to('targetSchema'); // Define target

2. Map Fields

// Simple field mapping
.map('oldField', 'newField')

// Nested object mapping
.map('user.profile.name', 'displayName')

// Array element mapping
.map('items[0]', 'firstItem')
.map('items[1]', 'secondItem')

3. Add Transformations

// Transform values during mapping
.map('name', 'displayName', (value) => value.toUpperCase())

// Access source data in transforms
.map('firstName', 'fullName', (firstName, ctx) => {
  return `${firstName} ${ctx.source.lastName}`;
})

4. Set Default Values

.defaults({
  version: '1.0.0',
  enabled: true,
  environment: 'production'
})

5. Convert Data

// Convert object data
const result = await converter.convert(sourceConfig);

// Convert from file
const result = await converter.convert('./config.yml');

// Synchronous conversion (objects only)
const result = converter.convertSync(sourceConfig);

🔧 Working with Results

const result = await converter.convert(data);

// Access converted data
console.log(result.data);

// Check conversion statistics
console.log(result.stats);
// {
//   fieldsProcessed: 10,
//   fieldsMapped: 5,
//   fieldsUnmapped: 5,
//   transformsApplied: 2,
//   duration: 3
// }

// See unmapped fields
console.log(result.unmapped);
// ['author.lastName', 'items[1]', 'items[2]']

// Pretty print report
result.print();

// Save to file
await result.save('./output.json'); // Saves as JSON
await result.save('./output.yml'); // Saves as YAML

// Get as string
const jsonString = result.toJSON();
const yamlString = result.toYAML();

📝 Real Examples

Example 1: Simple Config Transformation

const { forge } = require('configforge');

const oldConfig = {
  app_name: 'MyApp',
  app_version: '2.1.0',
  database: {
    host: 'localhost',
    port: 5432,
  },
};

const converter = forge()
  .from('old')
  .to('new')
  .map('app_name', 'name')
  .map('app_version', 'version')
  .map('database.host', 'db.hostname')
  .map('database.port', 'db.port')
  .defaults({
    environment: 'development',
  });

const result = await converter.convert(oldConfig);
console.log(result.data);
// {
//   name: 'MyApp',
//   version: '2.1.0',
//   db: {
//     hostname: 'localhost',
//     port: 5432
//   },
//   environment: 'development'
// }

Example 2: With Transformations

const userConfig = {
  user: {
    first_name: 'john',
    last_name: 'doe',
    email: 'JOHN.DOE@EXAMPLE.COM',
  },
  settings: {
    theme: 'dark',
    notifications: 'true',
  },
};

const converter = forge()
  .from('user')
  .to('profile')
  .map(
    'user.first_name',
    'name',
    name => name.charAt(0).toUpperCase() + name.slice(1)
  )
  .map('user.email', 'email', email => email.toLowerCase())
  .map('user.first_name', 'displayName', (firstName, ctx) => {
    const lastName = ctx.source.user.last_name;
    return `${firstName} ${lastName}`.replace(/\b\w/g, l => l.toUpperCase());
  })
  .map(
    'settings.notifications',
    'notificationsEnabled',
    value => value === 'true'
  );

const result = await converter.convert(userConfig);
console.log(result.data);
// {
//   name: 'John',
//   email: 'john.doe@example.com',
//   displayName: 'John Doe',
//   notificationsEnabled: true
// }

Example 3: File Conversion

// Convert YAML file to JSON structure
const converter = forge()
  .from('yaml')
  .to('json')
  .map('server.host', 'hostname')
  .map('server.port', 'port')
  .map('database.url', 'dbUrl');

// Read and convert file
const result = await converter.convert('./config.yml');

// Save as JSON
await result.save('./config.json');

🎯 Key Features

  • Simple API: Just map fields and convert
  • No direct Mapper usage needed: The convert() method handles everything
  • Nested object support: Use dot notation like user.profile.name
  • Array access: Use bracket notation like items[0]
  • Transformations: Transform values during mapping
  • Default values: Set fallback values
  • File support: Convert YAML, JSON files directly
  • Statistics: Get detailed conversion reports
  • TypeScript: Full type safety

🔄 Current Implementation Status

✅ Working Features:

  • Basic field mapping with map()
  • Nested object and array access
  • Value transformations
  • Default values with defaults()
  • File parsing (YAML, JSON)
  • Conversion statistics and reporting
  • Before/after hooks

🚧 Coming Soon:

  • Conditional mapping with when()
  • Array processing with forEach()
  • Field validation
  • CLI generation
  • Plugin system

💡 Tips

  1. You don't need to use the Mapper class directly - just use converter.convert()
  2. Use dot notation for nested objects: 'user.profile.name'
  3. Use bracket notation for arrays: 'items[0]', 'items[1]'
  4. Transform functions get the value and context: (value, ctx) => { ... }
  5. Check result.unmapped to see which fields weren't mapped
  6. Use result.print() for a nice conversion report

That's it! ConfigForge makes config conversion simple and straightforward. No complex setup, no direct class manipulation - just define your mappings and convert.