CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-delegates

Node method and accessor delegation utility for creating clean object composition patterns

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

Delegates

Delegates is a Node.js utility for creating delegation patterns in JavaScript. It allows methods and property accessors to be delegated from one object to a property of that object, providing a fluent API for setting up clean object composition without manually writing wrapper functions.

Package Information

  • Package Name: delegates
  • Package Type: npm
  • Language: JavaScript
  • Installation: npm install delegates

Core Imports

const delegate = require('delegates');

Basic Usage

const delegate = require('delegates');

// Create a simple object with a target property
const obj = {
  request: {
    method: 'GET',
    url: '/api/users',
    headers: { 'Content-Type': 'application/json' }
  }
};

// Set up delegation from obj to obj.request
delegate(obj, 'request')
  .method('send')           // Delegate method calls
  .access('method')         // Delegate getter and setter
  .getter('headers')        // Delegate getter only
  .setter('timeout')        // Delegate setter only
  .fluent('url');          // Delegate fluent accessor

// Now you can use delegated methods and properties directly on obj
obj.method = 'POST';        // Sets obj.request.method
console.log(obj.method);    // Gets obj.request.method
obj.url('/api/posts');      // Sets obj.request.url and returns obj for chaining

Architecture

Delegates uses the delegation pattern to avoid writing repetitive proxy methods. Instead of manually creating getter/setter functions, it dynamically defines properties and methods on a host object that forward to a target property.

Key components:

  • Delegator: Main class that configures delegation rules
  • Target Property: The object property that receives delegated calls
  • Host Object: The object that gains the delegated functionality
  • Delegation Types: Method calls, property access (getter/setter), and fluent accessors

The library supports both constructor-style (new Delegator()) and factory-style (delegate()) instantiation, with all configuration methods returning the delegator instance for method chaining.

Capabilities

Constructor

Creates a delegator instance for configuring method and property delegation.

/**
 * Creates a delegator instance used to configure delegation
 * @param {Object} proto - The object to add delegated methods/properties to
 * @param {string} target - The property name that methods/properties will be delegated to
 * @returns {Delegator} Delegator instance for chaining configuration calls
 */
function delegate(proto, target);

The constructor can be called with or without new:

  • delegate(proto, target)
  • new delegate(proto, target)

Method Delegation

Delegates method calls from the host object to the target property.

/**
 * Delegate method calls to the target object
 * @param {string} name - The method name to delegate
 * @returns {Delegator} Self for method chaining
 */
method(name);

Usage Example:

const obj = {
  request: {
    send: function() { return 'sent'; },
    abort: function() { return 'aborted'; }
  }
};

delegate(obj, 'request')
  .method('send')
  .method('abort');

// Now obj.send() calls obj.request.send()
obj.send();  // Returns 'sent'
obj.abort(); // Returns 'aborted'

Property Access Delegation

Creates both getter and setter for a property (full accessor).

/**
 * Create both getter and setter for a property
 * @param {string} name - The property name to create accessor for
 * @returns {Delegator} Self for method chaining
 */
access(name);

Usage Example:

const obj = {
  config: {
    timeout: 5000,
    retries: 3
  }
};

delegate(obj, 'config')
  .access('timeout')
  .access('retries');

// Both getting and setting work
obj.timeout = 10000;        // Sets obj.config.timeout
console.log(obj.timeout);   // Gets obj.config.timeout (10000)

Getter Delegation

Creates a getter property that delegates to the target object.

/**
 * Create a getter property that delegates to the target object
 * @param {string} name - The property name to create getter for
 * @returns {Delegator} Self for method chaining
 */
getter(name);

Usage Example:

const obj = {
  response: {
    get status() { return 200; },
    get headers() { return { 'content-type': 'application/json' }; }
  }
};

delegate(obj, 'response')
  .getter('status')
  .getter('headers');

// Read-only access to response properties
console.log(obj.status);   // 200
console.log(obj.headers);  // { 'content-type': 'application/json' }

Setter Delegation

Creates a setter property that delegates to the target object.

/**
 * Create a setter property that delegates to the target object
 * @param {string} name - The property name to create setter for
 * @returns {Delegator} Self for method chaining
 */
setter(name);

Usage Example:

const obj = {
  config: {
    _timeout: 5000,
    set timeout(value) { this._timeout = value; }
  }
};

delegate(obj, 'config')
  .setter('timeout');

// Write-only access to config property
obj.timeout = 10000;  // Sets obj.config.timeout

Fluent Accessor Delegation

Creates a fluent accessor that works as both getter and chainable setter.

/**
 * Create a fluent accessor that works as both getter and chainable setter
 * @param {string} name - The property name to create fluent accessor for
 * @returns {Delegator} Self for method chaining
 */
fluent(name);

Usage Example:

const obj = {
  request: {
    method: 'GET',
    url: '/'
  }
};

delegate(obj, 'request')
  .fluent('method')
  .fluent('url');

// Getter usage (no arguments)
console.log(obj.method());  // 'GET'
console.log(obj.url());     // '/'

// Setter usage (with argument) - returns obj for chaining
obj.method('POST').url('/api/users');
console.log(obj.request.method);  // 'POST'
console.log(obj.request.url);     // '/api/users'

Types

/**
 * Delegator constructor function
 * @constructor
 * @param {Object} proto - The object to add delegated methods/properties to
 * @param {string} target - The property name that delegation targets
 */
function Delegator(proto, target);

/**
 * Delegator instance with chainable methods
 */
interface Delegator {
  /** The object being extended with delegated functionality */
  proto: Object;
  /** The property name on proto that delegation targets */
  target: string;
  /** Array of delegated method names */
  methods: string[];
  /** Array of delegated getter names */
  getters: string[];
  /** Array of delegated setter names */
  setters: string[];
  /** Array of delegated fluent accessor names */
  fluents: string[];
  
  /** Delegate a method call */
  method(name: string): Delegator;
  /** Create both getter and setter */
  access(name: string): Delegator;
  /** Create a getter only */
  getter(name: string): Delegator;
  /** Create a setter only */
  setter(name: string): Delegator;
  /** Create a fluent accessor (getter/chainable setter) */
  fluent(name: string): Delegator;
}

Advanced Usage Patterns

Complex Delegation Setup

const delegate = require('delegates');

// HTTP request-like object
function Request(options) {
  this.options = options || {};
  this.headers = {};
}

// Delegate multiple aspects to different properties
delegate(Request.prototype, 'options')
  .access('method')
  .access('url')
  .access('timeout')
  .fluent('json');

delegate(Request.prototype, 'headers')
  .fluent('contentType')
  .fluent('authorization');

// Usage
const req = new Request({ method: 'GET', url: '/api' });
req.method = 'POST';
req.contentType('application/json')
   .authorization('Bearer token123');

Framework Integration Pattern

// Common pattern used in frameworks like Koa.js
function Context(req, res) {
  this.request = req;
  this.response = res;
}

// Delegate request properties and methods
delegate(Context.prototype, 'request')
  .method('acceptsLanguages')
  .method('acceptsCharsets')
  .access('querystring')
  .access('search')
  .getter('protocol')
  .getter('secure');

// Delegate response properties and methods  
delegate(Context.prototype, 'response')
  .method('redirect')
  .access('status')
  .access('body')
  .setter('type');

Install with Tessl CLI

npx tessl i tessl/npm-delegates
Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/delegates@1.0.x
Publish Source
CLI
Badge
tessl/npm-delegates badge