Socket
Socket
Sign inDemoInstall

ampersand-state

Package Overview
Dependencies
Maintainers
1
Versions
65
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

ampersand-state - npm Package Compare versions

Comparing version 2.0.1 to 3.0.0

dataTypes.js

141

ampersand-state.js
var _ = require('underscore');
var BBEvents = require('backbone-events-standalone');
var arrayNext = require('array-next');
var dataTypes = require('./dataTypes');

@@ -49,5 +50,4 @@

var triggers = [];
var changing, previous, changes, newType,
interpretedType, newVal, def, attr, attrs,
silent, unset, currentVal, initial;
var changing, previous, changes, newType, newVal, def, cast, err, attr,
attrs, dataType, silent, unset, currentVal, initial, hasChanged;

@@ -100,5 +100,7 @@ // Handle both `"key", value` and `{key: value}` -style arguments.

dataType = this._dataTypes[def.type];
// check type if we have one
if (dataTypes[def.type]) {
var cast = dataTypes[def.type].set(newVal);
if (dataType && dataType.set) {
cast = dataType.set(newVal);
newVal = cast.val;

@@ -110,3 +112,3 @@ newType = cast.type;

if (def.test) {
var err = def.test.call(this, newVal, newType);
err = def.test.call(this, newVal, newType);
if (err) {

@@ -134,4 +136,10 @@ throw new TypeError('Property \'' + attr + '\' failed validation with error: ' + err);

if (dataType && dataType.compare) {
hasChanged = !dataType.compare(currentVal, newVal);
} else {
hasChanged = !_.isEqual(currentVal, newVal);
}
// enforce `setOnce` for properties if set
if (def.setOnce && currentVal !== undefined && !_.isEqual(currentVal, newVal)) {
if (def.setOnce && currentVal !== undefined && hasChanged) {
throw new TypeError('Property \'' + key + '\' can only be set once.');

@@ -141,3 +149,3 @@ }

// push to changes array if different
if (!_.isEqual(currentVal, newVal)) {
if (hasChanged) {
changes.push({prev: currentVal, val: newVal, key: attr});

@@ -290,9 +298,4 @@ }

_getDefaultForType: function (type) {
if (type === 'string') {
return '';
} else if (type === 'object') {
return {};
} else if (type === 'array') {
return [];
}
var dataType = this._dataTypes[type];
return dataType && dataType.default && dataType.default();
},

@@ -318,3 +321,3 @@

_ensureValidType: function (type) {
return _.contains(['string', 'number', 'boolean', 'array', 'object', 'date', 'any'].concat(_.keys(dataTypes)), type) ? type : undefined;
return _.contains(['string', 'number', 'boolean', 'array', 'object', 'date', 'any'].concat(_.keys(this._dataTypes)), type) ? type : undefined;
},

@@ -428,5 +431,6 @@

var result = this._values[name];
var typeDef = this._dataTypes[def.type];
if (typeof result !== 'undefined') {
if (dataTypes[def.type] && dataTypes[def.type].get) {
result = dataTypes[def.type].get(result);
if (typeDef && typeDef.get) {
result = typeDef.get(result);
}

@@ -499,2 +503,3 @@ return result;

child.prototype._collections = _.extend({}, parent.prototype._collections);
child.prototype._dataTypes = _.extend({}, parent.prototype._dataTypes || dataTypes);

@@ -504,21 +509,32 @@ // Mix in all prototype properties to the subclass if supplied.

args.forEach(function processArg(def) {
_.each(def, function (value, key) {
if (key === 'props' || key === 'session') {
_.each(value, function (def, name) {
createPropertyDefinition(child.prototype, name, def, key === 'session');
});
} else if (key === 'derived') {
_.each(value, function (def, name) {
createDerivedProperty(child.prototype, name, def);
});
} else if (key === 'collections') {
_.each(value, function (constructor, name) {
child.prototype._collections[name] = constructor;
});
}
});
delete def.props;
delete def.session;
delete def.derived;
delete def.collections;
if (def.dataTypes) {
_.each(def.dataTypes, function (def, name) {
child.prototype._dataTypes[name] = def;
});
delete def.dataTypes;
}
if (def.props) {
_.each(def.props, function (def, name) {
createPropertyDefinition(child.prototype, name, def);
});
delete def.props;
}
if (def.session) {
_.each(def.session, function (def, name) {
createPropertyDefinition(child.prototype, name, def, true);
});
delete def.session;
}
if (def.derived) {
_.each(def.derived, function (def, name) {
createDerivedProperty(child.prototype, name, def);
});
delete def.derived;
}
if (def.collections) {
_.each(def.collections, function (constructor, name) {
child.prototype._collections[name] = constructor;
});
delete def.collections;
}
_.extend(child.prototype, def);

@@ -537,53 +553,2 @@ });

// also expose data types in our export
var dataTypes = Base.dataTypes = {
date: {
set: function (newVal) {
var newType;
if (!_.isDate(newVal)) {
try {
newVal = (new Date(parseInt(newVal, 10))).valueOf();
newType = 'date';
} catch (e) {
newType = typeof newVal;
}
} else {
newType = 'date';
newVal = newVal.valueOf();
}
return {
val: newVal,
type: newType
};
},
get: function (val) {
return new Date(val);
}
},
array: {
set: function (newVal) {
return {
val: newVal,
type: _.isArray(newVal) ? 'array' : typeof newVal
};
}
},
object: {
set: function (newVal) {
var newType = typeof newVal;
// we have to have a way of supporting "missing" objects.
// Null is an object, but setting a value to undefined
// should work too, IMO. We just override it, in that case.
if (newType !== 'object' && _.isUndefined(newVal)) {
newVal = null;
newType = 'object';
}
return {
val: newVal,
type: newType
};
}
}
};
Base.extend = extend;

@@ -590,0 +555,0 @@

{
"name": "ampersand-state",
"description": "An observable, extensible state object with derived watchable properties.",
"version": "2.0.1",
"version": "3.0.0",
"author": "Henrik Joreteg <henrik@andyet.net>",

@@ -6,0 +6,0 @@ "bugs": {

@@ -175,17 +175,21 @@ var tape = require('tape');

test('should throw a type error for bad data types', function (t) {
try { new Foo({firstName: 3}); }
catch (err) { t.ok(err instanceof TypeError); }
try { new Foo({num: 'foo'}); }
catch (err) { t.ok(err instanceof TypeError); }
try { new Foo({hash: 10}); }
catch (err) { t.ok(err instanceof TypeError); }
try { new Foo({today: 10}); }
catch (err) { t.ok(err instanceof TypeError); }
try { new Foo({list: 10}); }
catch (err) { t.ok(err instanceof TypeError); }
t.throws(function () {
new Foo({firstName: 3});
}, TypeError);
t.throws(function () {
new Foo({num: 'foo'});
}, TypeError);
t.throws(function () {
new Foo({hash: 10});
}, TypeError);
t.throws(function () {
new Foo({today: 'asdfadsfa'});
}, TypeError);
t.doesNotThrow(function () {
new Foo({today: 1397631169892});
new Foo({today: '1397631169892'});
});
t.throws(function () {
new Foo({list: 10});
}, TypeError);
t.end();

@@ -499,17 +503,18 @@ });

test('Should be able to define and use custom data types', function (t) {
State.dataTypes.crazyType = {
set: function (newVal) {
return {
val: newVal,
type: 'crazyType'
};
},
get: function (val) {
return val + 'crazy!';
}
};
var Foo = State.extend({
props: {
silliness: 'crazyType'
},
dataTypes: {
crazyType: {
set: function (newVal) {
return {
val: newVal,
type: 'crazyType'
};
},
get: function (val) {
return val + 'crazy!';
}
}
}

@@ -516,0 +521,0 @@ });

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