Skip to content

Comprehensive and simple Proxy implementation for ECMAScript

Notifications You must be signed in to change notification settings

Boulangerie/pimped-proxy

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

14 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

pimped-proxy

Build Status Coveralls npm version npm downloads npm dependencies npm devDependencies npm license

Pimped Proxy is a comprehensive, simple, ES5+ compatible, lightweight (~2KB) and universal implementation of Proxy for JavaScript and TypeScript. It is not a replacement of the ES2015 Proxy object but it gives a simplest way to:

  • lookup both simple properties and more complex paths
  • transform data on the fly without altering objects
  • flatten complex nested objects to a single level
  • make aggregations (like arithmetical operations) on the fly
  • create new full-proxy objects
  • give an existing object the capability to proxy some properties

Install

The easiest way is to install pimped-proxy as dependency:

npm install pimped-proxy --save

Usage

Proxy a list of properties

Creating a proxy will forward the target object properties
var Proxy = require('pimped-proxy');

var car = {
  brand: 'Peugeot',
  model: '308',
  power: '112hp'
};

var carProxy = new Proxy(car, ['brand', 'model', 'power']);

console.log(`I bought a ${carProxy.brand} ${carProxy.model} of ${carProxy.power}`);
// Displays "I bought a Peugeot 308 of 112hp"
Updating a property on the target object will update it on the proxy
var car = {
  brand: 'Peugeot',
  model: '308',
  power: '112hp'
};

var carProxy = new Proxy(car, ['brand', 'model', 'power']);
car.power = '250hp'

console.log(`I bought a ${carProxy.brand} ${carProxy.model} of ${carProxy.power}`);
// Displays "I bought a Peugeot 308 of 250hp"
Property proxying is two-way binding, then updating the proxy will update the target object
var car = {
  brand: 'Peugeot',
  model: '308',
  power: '112hp'
};

var carProxy = new Proxy(car, ['brand', 'model', 'power']);
carProxy.brand = 'Renault';
carProxy.model = 'Clio';

console.log(`I bought a ${car.brand} ${car.model} of ${car.power}`);
// Displays "I bought a Renault Clio of 112hp"
If some properties are not specified, then they won't be overridden
var car = {
  brand: 'Peugeot',
  model: '308',
  power: '112hp'
};

var carProxy = new Proxy(car, ['brand', 'model']);

console.log(`I bought a ${carProxy.brand} ${carProxy.model} of ${carProxy.power||'??'}`);
// Displays "I bought a Peugeot 308 of ??"

Proxy a list of paths

Proxying with a path will just retrieve the value from the target object after evaluation of the path
var car = {
  brand: 'Peugeot',
  model: '308',
  engine: {
    power: '112hp'
  }
};

var carProxy = new Proxy(car, {
  brand: 'brand',
  model: 'model',
  power: 'engine.power'
);

console.log(`I bought a ${carProxy.brand} ${carProxy.model} of ${carProxy.power}`);
// Displays "I bought a Peugeot 308 of 112hp"

Path resolution uses Lo-Dash like get and set methods.

Proxy a list of accessors

Defining getters are useful to tranform the data on the fly
var car = {
  brand: 'Peugeot',
  model: '308',
  power: '112hp'
};

var carProxy = new Proxy(car, {
  brand: {
    get: function (value) {
      return value
    }
  },
  model: {
    get: function (value) {
      return value + ' GTI'
    }
  },
  power: {
    get: function (value) {
      return '270hp'
    }
  }
});

console.log(`I bought a ${carProxy.brand} ${carProxy.model} of ${carProxy.power}`);
// Displays "I bought a Peugeot 308 GTI of 270hp"
Creating setters give the possibility to dynamically alter the target object
var car = {
  brand: 'Peugeot',
  model: '308',
  power: '112hp'
};

var carProxy = new Proxy(car, {
  brand: {
    set: (value) => {
      return String(value).toUpperCase()
    }
  },
  model: {
    set: (value) => {
      return value + ' GTI'
    }
  },
  power: {
    set: (value) => {
      return '270hp'
    }
  }
});

carProxy.brand = 'Renault';
carProxy.model = 'Clio';
carProxy.power = '140hp';

console.log(`I bought a ${car.brand} ${car.model} of ${car.power}`);
// Displays "I bought a RENAULT Clio GTI of 270hp"

Other examples

Mix the ways to proxy
var car = {
  brand: 'Peugeot',
  model: '308',
  engine: {
    power: '270hp'
  }
};

var carProxy = new Proxy(car, {
  brand: 'brand',
  model: {
    get: function (value) {
      return value + ' GTI'
    }
  },
  power: 'engine.power'
});

console.log(`I bought a ${carProxy.brand} ${carProxy.model} of ${carProxy.power}`);
// Displays "I bought a Peugeot 308 GTI of 270hp"
Transform an existing object into a Proxy
var existingCar = {
  name: 'MyCar',
  power: '250hp'
};

var car = {
  brand: 'Peugeot',
  model: '308',
  power: '112hp'
};

Proxy.lookup(existingCar, car, ['brand', 'model']);

console.log(`I bought a ${carProxy.brand} ${carProxy.model} of ${carProxy.power} and I called it ${carProxy.name}`);
// Displays "I bought a Peugeot 308 of 250hp and I called it MyCar"
In TypeScript?
import { Proxy } from 'pimped-proxy'

const car: ICar = {
  brand: 'Peugeot',
  model: '308',
  power: '112hp'
}

const carProxy: ICar = <ICar> new Proxy(car, ['brand', 'model', 'power'])

console.log(`I bought a ${carProxy.brand} ${carProxy.model} of ${carProxy.power}`)
// Displays "I bought a Peugeot 308 of 112hp"
And in the browser?
<script src="pimped-proxy/dist/proxy.browser.js"></script>
<script>
  var car = {
    brand: 'Peugeot',
    model: '308',
    power: '112hp'
  };

  var carProxy = new Proxy(car, ['brand', 'model', 'power']);

  console.log(`I bought a ${carProxy.brand} ${carProxy.model} of ${carProxy.power}`);
  // Displays "I bought a Peugeot 308 of 112hp"
</script>

License

Code licensed under MIT License.