@nfd/model
v0.3.0
Published
Simple model objects.
Downloads
6
Readme
model
import model from '@nfd/model'
const vivian = model({name: 'Vivian', job: 'Software Engineer', age: 23})
vivian.on('change', console.log)
++vivian.age
/* { target: vivian,
name: 'age',
value: 24,
oldValue: 23 } */
vivian.favoriteColor = 'blue'
/* { target: vivian,
name: 'favoriteColor',
value: 'blue',
oldValue: undefined } */
Object.defineProperty(vivian, 'favoriteBook', {
value: 'The Sun Also Rises',
configurable: true,
writable: true,
})
/* { target: vivian,
name: 'favoriteBook',
value: 'The Sun Also Rises',
oldValue: undefined } */
vivian.on('favoriteBookChange', e =>
console.log(`Favorite book was: ${e.oldValue}`))
delete vivian.favoriteBook
/* Favorite book was: The Sun Also Rises */
/* { target: vivian,
name: 'favoriteBook',
value: undefined,
oldValue: 'The Sun Also Rises' } */
Installation
$ npm i @nfd/model
Usage
model(…) · class extends model { … } · new model · model.is(…) · model.deep(…) · model.tree(…) · model.fullTree(…)
model([object = {}[, {deep = false, tree = false, fullTree = false}]])
Returns a proxy for object
which emits events when its properties are created, deleted, or changed. Each change emits a change
event and a nameChange event, both with event object {target, name, value, oldValue}
, where:
- target is the model proxy;
- name is the property name;
- value is the new property value; and
- oldValue is the previous property value.
const kate = model({name: 'Kate', age: 31})
kate.on('change', console.log)
++kate.age
/* { target: kate, name: 'age', value: 32, oldValue: 31 } */
Arrays — in addition to the normal change
and nameChange events, models based on Arrays emit splice
events describing high-level structural changes to their contents. Each event object comprises {target, index, removed, added}
, where:
- target is the model proxy;
- index is the index of the first removed or added element;
- removed is an array of the removed elements; and
- added is the number of elements added in their place.
const fruits = model([])
fruits.on('splice', console.log)
fruits.push('apple', 'pear', 'mango', 'banana', 'kiwi')
/* { target: fruits, index: 0, removed: [], added: 3 } */
fruits.shift()
/* { target: fruits, index: 0, removed: ['apple'], added: 0 } */
fruits.splice(1, 2, 'guava')
/* { target: fruits, index: 1, removed: [ 'mango', 'banana' ], added: 1 } */
fruits[0] = 'orange'
/* { target: fruits, index: 0, removed: [ 'pear' ], added: 1 } */
fruits.length = 0
/* { target: fruits, index: 0, removed: [ 'orange', 'guava', 'kiwi' ], added: 0 } */
deep or model.deep(…)
— if true, all properties with object values will be automatically coerced on creation and assignment to model proxies.
const olivia = model({
name: 'Olivia',
favoriteBook: {title: 'Anna Karenina', author: 'Leo Tolstoy'},
})
olivia.favoriteBook = {title: 'The Grapes of Wrath', author: 'John Steinbeck'}
olivia.favoriteBook.on('change', console.log)
olivia.favoriteBook.year = 1939
/* { target: olivia.favoriteBook,
name: 'year',
value: 1939,
oldValue: undefined }
tree or model.tree(…)
(implies deep
) — if true, the root model proxy will emit mutate
events for all mutations to itself and its subtree. Each event object comprises {target, localTarget, path, name, value, oldValue}
, where:
- target is the root model proxy;
- localTarget is the subtree proxy whose property changed;
- path is the key path from the root to the changed property, with keys separated by
.
s; - names is the list of property names in
path
; - depth is number of intermediate objects in the path, starting at
0
for direct mutations to the root; - name is the property name;
- value is the new property value; and
- oldValue is the previous property value.
const olivia = model({
name: 'Olivia',
favoriteColor: 'blue',
favoriteBook: {title: 'The Sun Also Rises', authors: [{name: 'Ernest Hemingway'}]},
}, {tree: true})
olivia.on('mutate', console.log)
olivia.favoriteColor = 'red'
/* { target: olivia,
localTarget: olivia,
path: 'favoriteColor',
names: ['favoriteColor'],
depth: 0,
name: 'favoriteColor',
value: 'red',
oldValue: 'blue' } */
olivia.favoriteBook.authors[0].born = 1899
/* { target: olivia,
localTarget: olivia.favoriteBook.authors[0],
path: 'favoriteBook.authors.0.born',
names: ['favoriteBook', 'authors', '0', 'born'],
depth: 3,
name: 'born',
value: 1899,
oldValue: undefined } */
fullTree or model.fullTree(…)
(implies deep
and tree
) — if true, in addition to the root object, all subtree model proxies will also emit mutate
events for mutations to themselves and their respective subtrees.
const olivia = model({
name: 'Olivia',
favoriteColor: 'blue',
favoriteBook: {title: 'The Sun Also Rises', authors: [{name: 'Ernest Hemingway'}]},
}, {fullTree: true})
olivia.favoriteBook.on('mutate', console.log)
olivia.favoriteBook.authors[0].born = 1899
/* { target: olivia.favoriteBook,
localTarget: olivia.favoriteBook.authors[0],
path: 'authors.0.born',
names: ['authors', '0', 'born'],
depth: 2,
name: 'born',
value: 1899,
oldValue: undefined } */
class extends model { … }
The model
function can also be used as a base class.
class Person extends model {/* … */}
const kate = new Person('Kate', 31)
kate.on('change', console.log)
++kate.age
/* { target: kate, name: 'age', value: 32, oldValue: 31 } */
new model
Constructs a new, empty model.
const kate = new model
kate.on('change', console.log)
kate.name = 'Kate'
/* { target: kate, name: 'name', value: 'Kate', oldValue: undefined } */
kate.age = 31
/* { target: kate, name: 'age', value: 31, oldValue: undefined } */
model.is(object)
Returns true
if object
is a model proxy.
model.is({name: 'Kate', age: 31}) /* false */
model.is(model({name: 'Kate', age: 31})) /* true */
model.is(model([])) /* true */
const fruits = model([{fruit: 'kiwi', quantity: 3}])
models.is(fruits[0]) /* false */
const fruits = model([{fruit: 'kiwi', quantity: 3}], {deep: true})
model.is(fruits[0]) /* true */
model.deep
Alias function for model(object, {deep: true})
. Can be used:
- As a function:
model.deep([object = {}])
- As a base class:
class extends model.deep {…}
- As a constructor:
new model.deep
model.tree
Alias function for model(object, {tree: true})
. Can be used:
- As a function:
model.tree([object = {}])
- As a base class:
class extends model.tree {…}
- As a constructor:
new model.tree
model.fullTree
Alias function for model(object, {fullTree: true})
. Can be used:
- As a function:
model.fullTree([object = {}])
- As a base class:
class extends model.fullTree {…}
- As a constructor:
new model.fullTree