Skip to content

typescript-package/wrap-property

Repository files navigation

typescript-package/wrap-property

npm version GitHub issues GitHub license

A lightweight TypeScript package for wrapping object properties.

Table of contents

Installation

1, Install peer dependencies

npm i @typedly/callback@1.0.0-beta.4 @typedly/controller@0.0.1-beta @typedly/descriptor@5.1.0-beta --save-peer

2. Install the package

npm install @typescript-package/wrap-property --save-peer

Api

import {
  // Class.
  WrapProperty,     // Concrete class to wrap the property.

  // Abstract.
  WrapPropertyBase, // Foundational class for extension.
  WrapPropertyCore, // The abstraction for base.
} from '@typescript-package/wrap-property';

Exports

  • WrapProperty — Concrete class for wrapping properties on objects/classes.
  • WrapPropertyBase — Base abstraction to extend for custom wrappers.
  • WrapPropertyCore — The core abstraction.

WrapProperty Constructor

new WrapProperty(target, key, descriptor?)
  • target: The object or class whose property is to be wrapped.
  • key: The property key.
  • descriptor (optional): Options such as onGet, onSet, privateKey, configurable, and enumerable.

WrapProperty

Usage

1. Basic Property Wrapping

This example demonstrates how to intercept reads and writes for a property.

import { WrapProperty } from '@typescript-package/wrap-property';

class MyClass {
  myProp = 'hello';
}

const inst = new MyClass();

export const wrapped = new WrapProperty(inst, 'myProp', {
  active: true as boolean,
  enabled: true as boolean,
  onGet(key, previousValue, value) {
    console.log(
      `Accessed ${String(key)}`,
      previousValue,
      '→',
      value
    );
    return value;
  }
});

console.debug(`controller:`, wrapped.controller); // undefined, as no controller is set.
console.debug(`descriptor:`, wrapped.descriptor); // {active: true, configurable: true, enumerable: false, previousDescriptor: {…}, privateKey: '_myProp', …}

inst.myProp; // Logs: Accessed myProp hello → hello

wrapped.descriptor.enabled = false; // Disable the descriptor.

console.debug(inst.myProp); // undefined

wrapped.descriptor.enabled = true; // Enable the descriptor.
wrapped.descriptor.active = false; // Disable the active to not execute the `onGet` and `onSet` callbacks.

console.debug(inst.myProp); // hello

2. Wrapping a Property on a Class prototype

You can pass a class constructor to wrap its prototype property:

import { WrapProperty } from '@typescript-package/wrap-property';


export class Example {
  public static readonly staticValue = 42;
  public value = 1;
}

// Wrap the "value" property to log whenever it is accessed or set.
export const wrapped1 = new WrapProperty(
  Example.prototype,
  'value',
  {
    onGet(key, previousValue, value) {
      console.log(`Getting "${String(key)}":`, value);
      return value;
    },
    onSet(value, previousValue, key) {
      console.log(`Setting "${String(key)}":`, previousValue, '→', value);
      return value;
    },
  }
);

const example = new Example();

delete (example as any).value; // Remove the own property to ensure the wrap works.

example.value = 42; // Logs: Setting "value": 1 → 42
example.value; // Logs: Getting "value": 42

3. Customizing with WrapPropertyBase

You can extend WrapPropertyBase to implement your own custom behavior:

import { WrapPropertyBase } from '@typescript-package/wrap-property';

class CustomLogger extends WrapPropertyBase<typeof obj, 'someKey'> {
  constructor(object: typeof obj, key: 'someKey') {
    super(object, key, {
      onGet: (k, v) => {
        console.log(`Custom get for ${String(k)}: ${v}`);
        return v;
      }
    });
    super.wrap(object, key); // wrap.
  }
}

const obj = { someKey: 123 };

new CustomLogger(obj, 'someKey');
obj.someKey; // Logs: Custom get for someKey: 123

4. Multiple wrap and one unwrap

import { WrapProperty } from '@typescript-package/wrap-property';

export class TestObject {
  firstName = 'First name';
  lastName = 'Last name';
  age = 1000;

  constructor(param11: number, param22: string) {}
}

const object = new TestObject(0, 'test');

let wrappedAgeFirst = new WrapProperty(object, 'age', { privateKey: '_age' });
let wrappedAgeSecond = new WrapProperty(object, 'age', { privateKey: '__age' });
let wrappedAgeThird = new WrapProperty(object, 'age', { privateKey: '___age' });

wrappedAgeSecond.unwrap(); // Unwraps the last, the field __age is not connected. 

object.age = 3000;

console.debug(object.age); // 3000

Contributing

Your contributions are valued! If you'd like to contribute, please feel free to submit a pull request. Help is always appreciated.

Support

If you find this package useful and would like to support its and general development, you can contribute through one of the following payment methods. Your support helps maintain the packages and continue adding new.

Support via:

or via Trust Wallet

Code of Conduct

By participating in this project, you agree to follow Code of Conduct.

GIT

Commit

Versioning

Semantic Versioning 2.0.0

Given a version number MAJOR.MINOR.PATCH, increment the:

  • MAJOR version when you make incompatible API changes,
  • MINOR version when you add functionality in a backwards-compatible manner, and
  • PATCH version when you make backwards-compatible bug fixes.

Additional labels for pre-release and build metadata are available as extensions to the MAJOR.MINOR.PATCH format.

FAQ How should I deal with revisions in the 0.y.z initial development phase?

The simplest thing to do is start your initial development release at 0.1.0 and then increment the minor version for each subsequent release.

How do I know when to release 1.0.0?

If your software is being used in production, it should probably already be 1.0.0. If you have a stable API on which users have come to depend, you should be 1.0.0. If you’re worrying a lot about backwards compatibility, you should probably already be 1.0.0.

License

MIT © typescript-package (license)

About

A lightweight TypeScript package for wrapping object properties.

Resources

License

Stars

Watchers

Forks

Packages

No packages published