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 configforgeBasic 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 target2. 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
- You don't need to use the Mapper class directly - just use
converter.convert() - Use dot notation for nested objects:
'user.profile.name' - Use bracket notation for arrays:
'items[0]','items[1]' - Transform functions get the value and context:
(value, ctx) => { ... } - Check
result.unmappedto see which fields weren't mapped - 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.