Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

promised-models2

Package Overview
Dependencies
Maintainers
3
Versions
16
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

promised-models2 - npm Package Compare versions

Comparing version 0.1.6 to 1.0.0

lib/types/raw.js

25

lib/attribute.js

@@ -13,11 +13,17 @@

DEFAULT_BRANCH: 'DEFAULT_BRANCH',
PREVIOUS_BRANCH: 'PREVIOUS_BRANCH',
/**
* @param {String} name
* @param {Model} model
* @param {*} initValue
*/
__constructor: function (initValue) {
__constructor: function (name, model, initValue) {
var setValue;
this._cachBranches = {};
this._cachIsSetBranches = {};
this.DEFAULT_BRANCH = 'DEFAULT_BRANCH';
this.PREVIOUS_BRANCH = 'PREVIOUS_BRANCH';
this.name = name;
this.model = model;
if (initValue === undefined || initValue === null) {

@@ -128,3 +134,5 @@ this._isSet = false;

this._cachIsSetBranches[branch] = this._isSet;
this._emitCommit(branch);
if (branch === this.DEFAULT_BRANCH) {
this._emitCommit(branch);
}
}

@@ -156,4 +164,6 @@

set: function (value) {
var defaultValue;
if (!this.isEqual(value)) {
if (value === null) {
defaultValue = this._callOrGetDefault();
if (value === null && value !== defaultValue) {
this.unset();

@@ -233,6 +243,3 @@ } else {

_emitCommit: function (branch) {
branch = branch || this.DEFAULT_BRANCH;
var eventString = (branch !== this.DEFAULT_BRANCH ? branch + ':' : '') + 'commit:' + this.name;
this.model.trigger(eventString);
this.model.trigger('commit:' + this.name);
},

@@ -239,0 +246,0 @@

@@ -23,8 +23,19 @@ var Events = require('./events'),

DEFAULT_BRANCH: 'DEFAULT_BRANCH',
PREVIOUS_BRANCH: 'PREVIOUS_BRANCH',
/**
* @param {Array.<(Model|Object)>} [data]
* @param {Object} options
*/
__constructor: function (data) {
this.__base.apply(this, arguments);
__constructor: function (data, options) {
this.__base();
options = options === undefined ? {} : options;
if (options.modelType) {
this.modelType = options.modelType;
}
/**

@@ -35,9 +46,2 @@ * @type {Object.<String, Array.<Model>>}

this.DEFAULT_BRANCH = 'DEFAULT_BRANCH';
this.PREVIOUS_BRANCH = 'PREVIOUS_BRANCH';
if (!this.modelType.prototype.attributes.id) {
throw new Error ('Collection can not be used with models without identifier attribute');
}
/**

@@ -53,10 +57,3 @@ * @type {Array.<Model>}

Object.defineProperty(this, 'length', {
get: function () {
return this._models.length;
}
});
data = data || [];
this.set(data);
this.set(data || []);
this.commit();

@@ -267,10 +264,18 @@ },

set: function (models) {
this.commit(this.PREVIOUS_BRANCH);
models = models.map(this._prepareModel, this);
while (this._models.length) {
this._removeModel(this.at(0));
}
models.forEach(this._addModel, this);
this._models.forEach(function (model) {
this._removeModelReference(model);
}, this);
this._models = models.map(function (data) {
var model = this._prepareModel(data);
this._addModelReference(model);
return model;
}, this);
this.trigger('reset');
return this;

@@ -323,5 +328,5 @@ },

} else {
return new (this.modelType.inherit({
return new this.modelType(model, {
collection: this
}))(model);
});
}

@@ -346,3 +351,23 @@ },

this._models.splice(at, 0, model);
this._addModelReference(model);
this.trigger('add', model, {at: at});
},
/**
* @param {Model} model
*/
_removeModel: function (model) {
var at = this._models.indexOf(model);
this._removeModelReference(model);
this._models.splice(at, 1);
this.trigger('remove', model, {at: at});
},
/**
* @param {Model} model
*/
_addModelReference: function (model) {
if (!model.isNew()) {

@@ -353,3 +378,2 @@ this._modelsIdsMap[model.getId()] = model;

model.on('all', this._onModelEvent, this);
this.trigger('add', model, {at: at});
},

@@ -360,5 +384,3 @@

*/
_removeModel: function (model) {
var at = this._models.indexOf(model);
_removeModelReference: function (model) {
model.un('all', this._onModelEvent, this);

@@ -369,10 +391,6 @@

}
if (!model.isNew()) {
delete this._modelsIdsMap[model.getId()];
}
this._models.splice(at, 1);
this.trigger('remove', model, {at: at});
},

@@ -409,2 +427,9 @@

Object.defineProperty(Collection.prototype, 'length', {
get: function () {
return this._models.length;
}
});
module.exports = Collection;

@@ -75,14 +75,18 @@ var EventEmitter = require('eventemitter3'),

*/
trigger: function () {
var callEmitter = this.__self._eventEmitter,
args = Array.prototype.slice.call(arguments, 0);
trigger: function (event, a1, a2, a3) {
var callEmitter = this.__self._eventEmitter;
this._eventEmitter.emit.apply(this._eventEmitter, args);
this._eventEmitter.emit.apply(this._eventEmitter, arguments);
if (callEmitter) {
callEmitter.emit.apply(callEmitter, args);
callEmitter.emit.apply(callEmitter, arguments);
}
// trigger `all` event
args.unshift('all');
this._eventEmitter.emit.apply(this._eventEmitter, args);
switch (arguments.length) {
case 1: this._eventEmitter.emit('all', event); break;
case 2: this._eventEmitter.emit('all', event, a1); break;
case 3: this._eventEmitter.emit('all', event, a1, a2); break;
case 4: this._eventEmitter.emit('all', event, a1, a2, a3); break;
}
return this;

@@ -89,0 +93,0 @@ },

@@ -23,60 +23,43 @@ /**

CALCULATIONS_BRANCH: 'CALCULATIONS_BRANCH',
/**
* @param {*} [id]
* @param {Object} [data] initial data
* @param {Object} [options]
*/
__constructor: function (id, data) {
var model = this,
Storage = this.storage || Model.Storage,
modelAttributes;
__constructor: function (data, options) {
var Storage, i, n, attrName, Attribute, modelAttrsDecl;
this.__base.apply(this, arguments);
this.__base();
options = options === undefined ? {} : options;
this.CHANGE_BRANCH = uniq();
this.CALCULATIONS_BRANCH = uniq();
if (arguments.length === 1) {
if (typeof id === 'object') {
data = id;
id = null;
}
Storage = options.storage || this.storage;
if (options.collection) {
this.collection = options.collection;
}
data = data || {};
this._ready = true;
this._readyPromise = fulfill();
this.storage = new Storage();
this.storage = Storage ? new Storage() : null;
modelAttributes = this.attributes || {};
// todo: remove after removing id property support
if (id !== null && modelAttributes.id) {
data.id = id;
}
this._attributesNames = Object.keys(this.attributes || {});
this.attributes = Object.keys(modelAttributes).reduce(function (attributes, name) {
var Attribute = modelAttributes[name];
modelAttrsDecl = this.attributes;
this.attributes = {};
attributes[name] = new (Attribute.inherit({
name: name,
model: model
}))(data[name]);
for (i = 0, n = this._attributesNames.length; i < n; i++) {
attrName = this._attributesNames[i];
Attribute = modelAttrsDecl[attrName];
if (attributes[name].isId) {
this.idAttribute = attributes[name];
this.attributes[attrName] = new Attribute(attrName, this, (data || {})[attrName]);
if (this.attributes[attrName] instanceof IdAttribute) {
this.idAttribute = this.attributes[attrName];
}
}
return attributes;
}.bind(this), {});
// todo: remove after removing id property support
if (this.idAttribute) {
this.id = this.getId();
this.on('change:' + this.idAttribute.name, function () {
this.id = this.idAttribute.get();
}, this);
}
this._attributesAr = Object.keys(this.attributes).map(function (name) {
return model.attributes[name];
});
this.commit(this.CHANGE_BRANCH);

@@ -90,3 +73,3 @@ this.calculate();

getId: function () {
return this.idAttribute && this.idAttribute.isSet() ? this.idAttribute.get() : null
return this.idAttribute ? this.idAttribute.get() : null;
},

@@ -211,8 +194,21 @@

this._eventEmitter.removeAllListeners();
Object.keys(this.attributes).forEach(function (attributeName) {
this.attributes[attributeName].destruct();
this.eachAttribute(function (attribute) {
attribute.destruct();
});
},
/**
* @param {Function} cb
* @param {Object} [ctx]
*/
eachAttribute: function (cb, ctx) {
this._attributesNames.forEach(function (attrName) {
if (ctx) {
cb.call(ctx, this.attributes[attrName]);
} else {
cb(this.attributes[attrName]);
}
}, this);
},
/**

@@ -225,4 +221,4 @@ * check if model is valid

return model.ready().then(function () {
return Vow.allResolved(model._attributesAr.map(function (attribute) {
return attribute.validate();
return Vow.allResolved(model._attributesNames.map(function (attrName) {
return model.attributes[attrName].validate();
}));

@@ -254,3 +250,3 @@ }).then(function (validationPromises) {

error.attribute = model._attributesAr[index];
error.attribute = model.attributes[model._attributesNames[index]];

@@ -276,6 +272,5 @@ errors.push(error);

isChanged: function (branch) {
var model = this;
return Object.keys(this.attributes).some(function (name) {
return model.attributes[name].isChanged(branch);
});
return this._attributesNames.some(function (attrName) {
return this.attributes[attrName].isChanged(branch);
}, this);
},

@@ -288,5 +283,4 @@

revert: function (branch) {
var model = this;
return Object.keys(this.attributes).forEach(function (name) {
return model.attributes[name].revert(branch);
this.eachAttribute(function (attr) {
attr.revert(branch);
});

@@ -301,8 +295,7 @@ },

commit: function (branch) {
var model = this,
eventString,
var eventString,
changed = false;
Object.keys(this.attributes).forEach(function (name) {
changed = model.attributes[name].commit(branch) || changed;
this.eachAttribute(function (attr) {
changed = attr.commit(branch) || changed;
});

@@ -345,18 +338,16 @@

set: function (name, value) {
var model = this,
data;
var data;
if (arguments.length === 1) {
data = name;
Object.keys(data).forEach(function (name) {
this._attributesNames.forEach(function (name) {
if (data[name] !== undefined) {
model.set(name, data[name]);
this.set(name, data[name]);
}
});
}, this);
} else if (this.attributes[name]) {
this.attributes[name].set(value);
} else {
return false;
}
return true;
return this;
},

@@ -431,6 +422,8 @@

*/
trigger: function () {
var args = Array.prototype.slice.call(arguments, 0);
args.splice(1, 0, this);
return this.__base.apply(this, args);
trigger: function (event, a1, a2) {
switch (arguments.length) {
case 1: return this.__base(event, this);
case 2: return this.__base(event, this, a1);
case 3: return this.__base(event, this, a1, a2);
}
},

@@ -457,2 +450,4 @@

calculations = {},
hasCalculations = false,
promises = [],
amendings = [],

@@ -466,4 +461,4 @@ nestedCalculations = [];

if (n >= model.maxCalculations) {
return model._throwCalculationLoop();
if (n >= this.maxCalculations) {
return this._throwCalculationLoop();
}

@@ -473,35 +468,57 @@

model.commit(model.CALCULATIONS_BRANCH);
this.commit(this.CALCULATIONS_BRANCH);
model._attributesAr.forEach(function (attribute) {
this.eachAttribute(function (attribute) {
var calculationResult, amendResult, nestedResult;
if (attribute.calculate) {
calculationResult = attribute.calculate();
calculations[attribute.name] = attribute.calculate();
hasCalculations = true;
}
if (attribute.amend && attribute.isChanged(model.CHANGE_BRANCH)) {
amendings.push(attribute.amend());
amendResult = attribute.amend();
if (Vow.isPromise(amendResult) && !amendResult.isResolved()) {
promises.push(amendResult);
}
}
if (attribute.ready) {
nestedCalculations.push(attribute.ready());
}
});
return Vow.all([
Vow.all(calculations),
Vow.all(amendings),
Vow.all(nestedCalculations)
]).spread(function (calculateData) {
model._setCalculatedData(calculateData);
if (model._checkContinueCalculations()) {
return model._calculate(++n);
} else {
model._triggerEvents();
//some event habdler could change some attribute
if (model._checkContinueCalculations()) {
return model._calculate(++n);
nestedResult = attribute.ready();
if (Vow.isPromise(nestedResult) && !nestedResult.isResolved()) {
promises.push(nestedResult);
}
}
model._ready = true;
});
if (hasCalculations || promises.length) {
return Vow.all([
Vow.all(calculations),
Vow.all(promises)
]).spread(this._onCalculateSuccess.bind(this, n));
} else {
return this._onCalculateSuccess(n);
}
},
/**
* @param {Number} n
* @param {Object} [calculateData]
* @returns {?Vow.Promise}
*/
_onCalculateSuccess: function (n, calculateData) {
if (!this._setCalculatedData(calculateData) || this._checkContinueCalculations()) {
return this._calculate(++n);
} else {
this._triggerEvents();
//some event habdler could change some attribute
if (this._checkContinueCalculations()) {
return this._calculate(++n);
}
}
this._ready = true;
},
/**
* setting calculated data only if nothing have changed during calculations

@@ -513,3 +530,4 @@ * otherwise we will have racing conditions(

if (!this._checkContinueCalculations()) {
this.set(calculateData);
calculateData && this.set(calculateData);
return true;
}

@@ -526,11 +544,8 @@ },

_throwCalculationLoop: function () {
var model = this,
changedFields = model._attributesAr.filter(function (attribute) {
return attribute.isChanged(model.CALCULATIONS_BRANCH);
}).map(function (attribute) {
return attribute.name;
});
var changedFields = this._attributesNames.filter(function (attrName) {
return this.attributes[attrName].isChanged(this.CALCULATIONS_BRANCH);
}, this);
return Vow.reject(new Error(
'After ' +
model.maxCalculations +
this.maxCalculations +
' calculations fileds ' +

@@ -543,13 +558,13 @@ changedFields +

_triggerEvents: function () {
var model = this,
changedFileds;
if (model.isChanged(model.CHANGE_BRANCH)) {
changedFileds = model._attributesAr.filter(function (attribute) {
return attribute.isChanged(model.CHANGE_BRANCH);
});
model.commit(model.CHANGE_BRANCH);
changedFileds.forEach(function (attribute) {
model._emitAttributeChange(attribute);
});
model._emitChange();
var changedFileds;
if (this.isChanged(this.CHANGE_BRANCH)) {
changedFileds = this._attributesNames.filter(function (attrName) {
return this.attributes[attrName].isChanged(this.CHANGE_BRANCH);
}, this);
this.commit(this.CHANGE_BRANCH);
changedFileds.forEach(function (attrName) {
this._emitAttributeChange(this.attributes[attrName]);
}, this);
this._emitChange();
}

@@ -591,13 +606,12 @@ },

*/
_getSerializedData: function (serializeMethod) {
var model = this,
args = Array.prototype.slice.call(arguments, 1);
_getSerializedData: function (serializeMethod, a) {
var data = {};
return Object.keys(this.attributes).filter(function (name) {
return !model.attributes[name].internal;
}).reduce(function (data, name) {
var attribute = model.attributes[name];
data[name] = attribute[serializeMethod].apply(attribute, args);
return data;
}, {});
this.eachAttribute(function (attribute) {
if (!attribute.internal) {
data[attribute.name] = attribute[serializeMethod](a);
}
}, this);
return data;
}

@@ -632,3 +646,4 @@

Collection: require('./types/collection'),
Object: require('./types/object')
Object: require('./types/object'),
Raw: require('./types/raw')
},

@@ -635,0 +650,0 @@

@@ -103,3 +103,3 @@ var Attribute = require('../attribute'),

isEqual: function (value) {
return value === null && this.value === null ? true : this.__base(value);
return value === this.value;
},

@@ -117,3 +117,2 @@

var CollectionClass;
if (data instanceof Collection) {

@@ -123,8 +122,5 @@ return data;

CollectionClass = this.collectionType ? this.collectionType : Collection;
if (this.modelType) {
CollectionClass = CollectionClass.inherit({
modelType: this.modelType
});
}
return new CollectionClass(data);
return new CollectionClass(data, {
modelType: this.modelType
});
}

@@ -141,3 +137,3 @@ },

if (value === null) {
this.value.un('change add remove', this._emitChange, this);
this.value.un('reset change add remove', this._emitChange, this);
this.value = null;

@@ -154,3 +150,3 @@ } else if (this.value === null) {

_initCollection: function () {
this.value.on('change add remove', this._emitChange, this);
this.value.on('reset change add remove', this._emitChange, this);
}

@@ -157,0 +153,0 @@

@@ -10,4 +10,2 @@ /**

isId: true,
dataType: Number,

@@ -14,0 +12,0 @@

{
"description": "promise based, typed attributes, nested models and collections",
"name": "promised-models2",
"version": "0.1.6",
"version": "1.0.0",
"repository": "git@github.com:bem-node/promised-models.git",

@@ -34,4 +34,4 @@ "keywords": [

"inherit": "2.2.2",
"vow": "0.4.9"
"vow": "0.3.9"
}
}

@@ -141,3 +141,2 @@ Promised Models 2 [![Build Status](https://travis-ci.org/bem-node/promised-models.svg?branch=master)](https://travis-ci.org/bem-node/promised-models)

model = new FashionModel({
id: 1,
name: 'Kate',

@@ -147,3 +146,3 @@ surname: 'Moss',

});
model.toJSON(); // {id: 1, fullName: 'Kate Moss'}
model.toJSON(); // {fullName: 'Kate Moss'}
model.get('name'); // Kate

@@ -192,15 +191,2 @@ ```

FashionModel = Model.inherit({
attributes: {
name: Model.attributeTypes.String
}
});
var model = new FashionModel({
id: 1,
name: 'Kate'
});
model.getId() // 1
```

@@ -621,3 +607,3 @@

Creates you own collection class by extending Collection. You should define `modelType` property - constructor which will be used for new models. Models that are used in collections should have declared id attribute, to make getId and related methods to work correctly.
Creates you own collection class by extending Collection. You should define `modelType` property - constructor which will be used for new models.

@@ -624,0 +610,0 @@ ```js

@@ -40,13 +40,2 @@ var expect = require('chai').expect;

});
describe('internal model', function () {
it('should throw exception if model has no id attribute', function () {
var ModelWithoutId = Model;
expect(function () {
new (Collection.inherit({
modelType: ModelWithoutId
}));
}).to.throw(Error);
});
});

@@ -343,17 +332,11 @@ describe('length', function () {

it('should set new models', function () {
var addsCount = 0,
removeCount = 0;
var triggered = false;
collection.on('add', function () {
addsCount++;
collection.on('reset', function () {
triggered = true;
});
collection.on('remove', function () {
removeCount++;
});
collection.set([{id: 4, a: 'a-4'}, {id: 5, a: 'a-5'}]);
expect(collection.toJSON()).to.be.deep.equal([{id: 4, a: 'a-4'}, {id: 5, a: 'a-5'}]);
expect(addsCount).to.be.equal(2);
expect(removeCount).to.be.equal(3);
expect(triggered).to.be.true;
});

@@ -360,0 +343,0 @@ });

@@ -147,15 +147,4 @@

});
it('should trigger branch:commit:attribute event', function () {
model.on('branch:commit:a', function () {
count++;
expect(model.attributes.a.isChanged('branch')).to.be.false;
});
model.set('a', 'a1');
model.commit('branch');
model.commit('branch');
expect(count).to.be.equal(1);
});
});
});

@@ -9,12 +9,2 @@ var expect = require('chai').expect,

describe('Default id attribute', function () {
it('should get "id" property as id attribute from initial data', function () {
var model = new TestModel({
id: 1
});
expect(model.getId()).to.equal(1);
});
});
describe('Id attribute declaration', function () {

@@ -54,2 +44,7 @@

});
it('Model#isNew should work correctly if id attribute not defined', function () {
var model = new Model();
expect(model.isNew()).to.be.true;
});
});

@@ -71,2 +66,9 @@

});
it('should be able to unset', function () {
var model = new TestModel({id: 1});
model.unset('id');
expect(model.getId()).is.to.be.null;
});
});

@@ -76,12 +78,2 @@

it('should support old interface', function () {
var model = new TestModel(1);
expect(model.getId()).to.equal(1);
model = new TestModel({
id: 1
});
expect(model.id).to.equal(1);
});
it('should change id property when id attribute has changed', function () {

@@ -88,0 +80,0 @@ var model = new TestModel(1);

@@ -127,3 +127,3 @@ var expect = require('chai').expect,

model1.save().then(function () {
var model2 = new Persistent(model1.getId());
var model2 = new Persistent({id: model1.getId()});
return model2.fetch().then(function () {

@@ -152,3 +152,3 @@ expect(model2.get('a')).to.be.equal('a-2');

model1.save().then(function () {
var model2 = new Persistent(model1.getId());
var model2 = new Persistent({id: model1.getId()});
return model2.fetch().then(function () {

@@ -155,0 +155,0 @@ expect(model2.get('a')).to.be.equal('a-1');

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc