or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

async-config.mdconfig-utilities.mdcore-config.mddeferred-config.mdenvironment-integration.mdindex.mdraw-config.md
tile.json

raw-config.mddocs/

Raw Configuration

Protection for configuration objects that should remain unmodified by the config system. Prevents the config system from attaching prototype methods, making properties immutable, or performing other transformations.

Capabilities

Raw Configuration Creation

Wrap objects to prevent config system modifications while preserving their original structure and behavior.

/**
 * Wrap object to prevent config system modifications
 * @param rawObj - Object to protect from config system transformations
 * @returns Raw configuration wrapper that resolves to original object
 */
function raw(rawObj: any): RawConfig;

interface RawConfig {
  resolve(): any; // Returns the original wrapped object
}

Usage Examples:

const { raw } = require('config/raw');

// Protect a Date object
const protectedDate = raw(new Date('2023-01-01'));

// Protect a RegExp object  
const protectedRegex = raw(/^[a-zA-Z0-9]+$/);

// Protect a custom class instance
class CustomService {
  constructor(name) {
    this.name = name;
  }
  
  execute() {
    return `Executing ${this.name}`;
  }
}

const service = new CustomService('MyService');
const protectedService = raw(service);

// Protect complex objects with methods
const apiClient = raw({
  baseUrl: 'https://api.example.com',
  request: function(endpoint) {
    return fetch(`${this.baseUrl}${endpoint}`);
  },
  // This object won't get Config prototype methods attached
});

Configuration File Integration

Raw configurations can be defined directly in configuration files to protect specific values from config system processing.

Usage Examples:

// In config/default.js
const { raw } = require('config/raw');

module.exports = {
  database: {
    host: 'localhost',
    port: 5432,
    // Protect connection pool configuration object
    pool: raw({
      min: 0,
      max: 10,
      acquireTimeoutMillis: 60000,
      createTimeoutMillis: 30000,
      destroyTimeoutMillis: 5000,
      idleTimeoutMillis: 30000,
      reapIntervalMillis: 1000,
      createRetryIntervalMillis: 200,
      // This object maintains its exact structure
      validate: function(client) {
        return client.query('SELECT 1').then(() => true);
      }
    })
  },
  
  server: {
    host: 'localhost',
    port: 3000,
    // Protect middleware configuration
    middleware: raw([
      function(req, res, next) {
        console.log('Request:', req.method, req.url);
        next();
      },
      function(req, res, next) {
        res.setHeader('X-Powered-By', 'MyApp');
        next();
      }
    ])
  },
  
  logging: {
    level: 'info',
    // Protect logger instance
    transport: raw(new CustomLogTransport({
      filename: './logs/app.log',
      maxFiles: 5,
      maxsize: 1024 * 1024 * 10 // 10MB
    }))
  },
  
  validation: {
    // Protect regex patterns
    emailPattern: raw(/^[^\s@]+@[^\s@]+\.[^\s@]+$/),
    phonePattern: raw(/^\+?[\d\s\-\(\)]+$/),
    
    // Protect validation functions
    customValidator: raw(function(value, context) {
      return typeof value === 'string' && value.length > 0;
    })
  }
};

// In application code
const config = require('config');

// Raw objects maintain their original behavior
const pool = config.get('database.pool');
console.log(typeof pool.validate); // 'function' - method preserved

const middleware = config.get('server.middleware');
console.log(Array.isArray(middleware)); // true - array behavior preserved

const emailPattern = config.get('validation.emailPattern');
console.log(emailPattern instanceof RegExp); // true - RegExp behavior preserved

Use Cases for Raw Configuration

Common scenarios where raw configuration is essential for maintaining object integrity.

Usage Examples:

const { raw } = require('config/raw');

// Protect class instances that should not be modified
class DatabaseConnection {
  constructor(config) {
    this.config = config;
    this.connected = false;
  }
  
  async connect() {
    // Connection logic
    this.connected = true;
  }
  
  query(sql, params) {
    if (!this.connected) {
      throw new Error('Not connected to database');
    }
    // Query logic
  }
}

const dbConnection = raw(new DatabaseConnection({
  host: 'localhost',
  port: 5432
}));

// Protect objects with circular references
const circularObj = { name: 'parent' };
circularObj.self = circularObj; // Circular reference
const protectedCircular = raw(circularObj);

// Protect functions that need to maintain their context
const utilityFunctions = raw({
  formatDate: function(date) {
    return date.toISOString().split('T')[0];
  },
  
  parseJson: function(str) {
    try {
      return JSON.parse(str);
    } catch (e) {
      return null;
    }
  },
  
  // These functions won't get Config methods mixed in
});

// Protect third-party library instances
const moment = require('moment');
const protectedMoment = raw(moment('2023-01-01'));

// Protect arrays that should remain as plain arrays
const plainArray = raw(['item1', 'item2', 'item3']);

Raw Configuration Resolution

Understanding how raw configurations are resolved and accessed within the config system.

// Raw configurations are resolved automatically when accessed
// The resolve() method is called internally by the config system
// Users typically don't need to call resolve() directly

Usage Examples:

const { raw } = require('config/raw');
const config = require('config');

// Define raw configuration
const rawValue = raw({ 
  data: 'original',
  method: function() { return this.data; }
});

// In configuration object
const myConfig = {
  protected: rawValue,
  normal: { data: 'normal' }
};

// When accessed through config system
const protectedValue = config.get('protected');
console.log(protectedValue.data); // 'original'
console.log(protectedValue.method()); // 'original' - method works correctly

const normalValue = config.get('normal');
console.log(typeof normalValue.get); // 'function' - Config methods attached

// Raw objects don't get Config prototype methods
console.log(typeof protectedValue.get); // 'undefined' - no Config methods
console.log(typeof protectedValue.has); // 'undefined' - no Config methods

// Manual resolution (rarely needed)
const manuallyResolved = rawValue.resolve();
console.log(manuallyResolved === protectedValue); // true

Important Considerations

Key points to understand when using raw configurations.

Usage Examples:

const { raw } = require('config/raw');

// Raw objects are resolved during immutability processing
// This means they maintain their original behavior even when config is made immutable

const myConfig = {
  mutableObject: { value: 'can be changed' },
  rawObject: raw({ value: 'protected' })
};

// After config.util.makeImmutable() is called
config.util.makeImmutable(myConfig);

// Normal objects become immutable
try {
  myConfig.mutableObject.value = 'new value'; // This will throw an error
} catch (error) {
  console.log('Cannot modify immutable config');
}

// Raw objects maintain their original mutability
myConfig.rawObject.value = 'still changeable'; // This works
console.log(myConfig.rawObject.value); // 'still changeable'

// Raw configurations don't participate in deep object operations
const original = {
  normal: { a: 1, b: 2 },
  protected: raw({ a: 1, b: 2 })
};

// Deep cloning operations handle raw objects specially
const cloned = config.util.cloneDeep(original);
console.log(cloned.normal !== original.normal); // true - deep cloned
console.log(cloned.protected === original.protected); // depends on implementation

// Raw objects are identified by their prototype
console.log(protectedValue instanceof RawConfig); // false (after resolution)
console.log(rawValue instanceof RawConfig); // true (before resolution)