Security News
GitHub Removes Malicious Pull Requests Targeting Open Source Repositories
GitHub removed 27 malicious pull requests attempting to inject harmful code across multiple open source repositories, in another round of low-effort attacks.
backbone.nested-types
Advanced tools
backbone.js extension adding type annotations to model attributes, easiest possible way of dealing with nested models and collections, and native properties for attributes. Providing you with a more or less complete, simple, and powerful object system for
Version 1.0.0 is here. Highlights:
NestedTypes is state-of-the-art backbonejs-compatible model framework.
It's achieved using attribute type annotations, which feels in much like statically typed programming language. Yet, this annotations are vanilla JavaScript, no transpiler step is required.
NestedTypes check types on every model update and perform dynamic type casts to ensure that attributes will always hold values of proper type.
As result, NestedTypes models are extremely reliable. It's impossible to break client-server protocol with inaccurate attribute assignment. If something will go really wrong, it will warn you with a messages in the console.
NestedTypes uses attribute type information for sophisticated optimizations targeting modern JS JIT engines.
Compared to backbonejs, model updates are about 20 times faster in Chrome/nodejs, and 4 times faster in other browsers.
NestedTypes was originally designed with an idea to make backbonejs more friendly for newbiews.
What we do, is taking intuitive newbie approach to backbonejs, and turn it from the mistake to legal way of doing things.
var User = Nested.Model.extend({
urlRoot : '/api/users',
defaults : {
// Primitive types
login : "", // String
email : String.value( null ), // null, but String
loginCount : Number.has.toJSON( false ) // 0, not serialized
active : Boolean.value( true ), // true
created : Date, // new Date()
settings : Settings, // new Settings()
// collection of models, received as an array of model ids
roles : Role.Collection.subsetOf( rolesCollection ),
// reference to model, received as model id.
office : Office.from( officeCollection )
}
});
var collection = new User.Collection();
collection.fetch().done( function(){
var user = collection.first();
console.log( user.name ); // native properties
console.log( user.office.name );
console.log( user.roles.first().name );
});
Types are being checked in run-time on assignment, but instead of throwing exceptions it tries to cast values to defined types.
user.login = 1;
console.assert( user.login === "1" );
user.active = undefined;
console.assert( user.active === false );
user.loginCount = "hjkhjkhfjkhjkfd";
console.assert( _.isNan( user.loginCount ) );
user.settings = { timeZone : 180 }; // same as user.settings.set({ timeZone : 180 })
console.assert( user.settings instanceof Settings );
CommonJS (node.js, browserify):
var Nested = require( 'nestedtypes' );
CommonJS/AMD (RequireJS). 'backbone' and 'underscore' modules must be defined in config paths.
require([ 'nestedtypes' ], function( Nested ){ ... });
Browser's script tag
<script src="underscore.js" type="text/javascript"></script>
<script src="backbone.js" type="text/javascript"></script>
<script src="nestedtypes.js" type="text/javascript"></script>
<script> var Model = Nested.Model; ... </script>
NestedTypes requires modern JS environment with support for native properties.
It's tested in IE 9+
, Chrome
, Safari
, Firefox
, which currently gives you about 95%
of all browsers being used for accessing the web.
node.js
and io.js
are also supported.
NestedTypes itself is packaged as UMD (Universal Module Definition) module, and should load dependencies properly in any environment.
NestedTypes require underscore
and backbone
libraries. They either must be included globally with <script>
tag or, if CommonJS
/AMD
loaders are used, be accessible by their standard module names.
bower install backbone.nested-types
npm install backbone.nested-types
Copy nestedtypes.js
file to desired location.
NestedTypes core functionality relies on improved Object.extend
function, which is also available as separate module
without any side dependencies. It compatible with Backbone's extend
, while providing some
additional capabilities important for NestedTypes and its applications, such as:
You can attach it to your Constructor function like this:
Object.extend.attach( MyConstructor1, MyConstructor2, ... );
Object.extend
can also be used directly to create classes.
When used as a part of NestedTypes,
all Object.extend
classes also implements Backbone.Events
, thus your custom objects are capable of sending and receiving backbone events.
You can add your own methods to all classes like this:
Object.extend.Class.prototype.myMethod = function(){...}
var MyClass = Object.extend({
a : 1,
inc : function(){ return this.a++; },
initialize : function( x ){
this.a = x;
}
},{
factory : function( x ){
return new MyClass( x );
}
});
When executed directly,
Object.extend( protoProps, staticProps )
creates constructor function and extends
its prototype with protoProps
properties, also attaching staticProps
to the constructor
itself. Constructor will call optional initialize
method.
var Subclass = MyClass.extend({
b : 2,
initialize : function( a, b ){
Subclass.__super__.initialize.apply( this, arguments );
this.b = b;
}
}
Every constructor created with Object.extend
may be further extended with extend
method.
Correct prototype chain will be built and attached to subclass constructor. Every subclass
constructor has __super__
property pointing to the prototype of the base class.
var Subclass = MyClass.extend({
b : 2,
constructor : function( a, b ){
MyClass.apply( this, arguments );
this.b = b;
}
}
You may override constructor instead of dealing with initialize
function.
##Native Properties
var Class = Object.extend({
properties: {
readOnly : function(){ return 'hello!'; },
readWrite : {
get : function(){ return this._value2; },
set : function( value ){
this._value2 = value;
}
}
}
});
Native properties can be defined with properties
spec.
For read-only properties, it's enough to supply get function as spec.
Otherwise, properties specs format is the same as accepted by standard Object.defineProperties
function.
You can access native properties as if it would be regular object member variable.
var x = c.readOnly
c.readWrite = 1;
##Forward declarations
var A = Object.extend(),
B = Object.extend( function(){ this.b = 'b'; } );
A.define({
bType : B
});
B.define({
aType : A
});
Classes can be created with an Object.extend()
, and defined later using
MyClass.define( protoProps, staticProps )
function. It can be helpful
to resolve circular dependencies.
define
cannot be used to override constructor. It can be achieved by passing
constructor function to extend
, as it is done for B
in the example.
##Console Warnings
var A = Object.extend({
a : function(){}
});
var B = A.extend({
a : 0 // Warning about type error
});
If you try to override base class function with non-function value, Object.extend
will notify you about that with a warning to the console. Cause usually it's a mistake.
In this case, you'll see in the console following message:
[Type Warning] Base class method overriden with value in Object.extend({ a : 0 }); Object = >...
function warning( Ctor, name, value ){
throw new TypeError( 'Whoops...' );
}
Object.extend.error.overrideMethodWithValue = warning;
You may override default warning handling assigning our own function to Object.extend.error.overrideMethodWithValue
.
In NestedTypes model definition's defaults
section is the specification of model's attributes.
attributes
keyword may be used instead of defaults
.
In defaults
or attributes
, you may specify attribute default value, its type, and different options of
attribute behavior. Refer to corresponding sections of the manual for details.
In NestedTypes, attribute declaration is mandatory. When you try to set an attribute which doesn't have default value, you'll got an error in the console.
Model.defaults must be an object. Functions are forbidden. var UserInfo = Nested.Model.extend({
defaults : {
name : 'test'
}
});
var DetailedUserInfo = UserInfo.extend({
attributes : { // <- alternative syntax for 'defaults'
login : '',
roles : [ 'user' ]
}
});
var user = new DetailedUserInfo();
In Backbone, 'name' attr is not inherited and would be undefined. In NestedTypes it's inherited, and you can access it directly.
console.assert( user.name === 'test' );
user.name = 'admin';
In Backbone all models will share the same instance of [ 'user' ] array. Bug. In NestedTypes, user.roles is deep copied on creation. Good practice.
user.roles.push( 'admin' );
NestedTypes automatically creates defaults
function for every model
from model attribute's spec. Base model attributes will be inherited.
Following statement can be used to return every model to its original state:
`model.set( model.defaults() )`
defaults
function accepts optional attrs
argument with attribute values hash
and fills missing attributes with default values.
When new model is being created, NestedTypes will deep clone
all items (including objects and arrays) from defaults
object.
When extending some existing model definition, NestedTypes will property
merge base model's defaults
.
NestedTypes creates native property for every attribute.
model.attr = val;
has the same effect as model.set( 'attr', val );
val = model.attr;
has the same effect as val = model.get( 'attr' );
You still might need to use model.set
in cases when you want to set multiple attributes
at once, or to pass some options.
In NestedTypes, model.id
is assignable property, linked to model.attributes[ model.idAttribute ]
.
model.id = 5
has the same effect as model.set( model.idAttribute, 5 )
var M = Nested.Model.extend({
defaults : {
a : 1
},
properties : {
b : function(){ return this.a + 1; }
}
});
var m = new M();
console.log( m.b ); // 2
Custom native properties specification. Most typical use case is calculated properties.
model.properties
is the part of Object.extend
functionality. Refer to Object.extend
manual section for details.
Set model attributes. In NestedTypes, this operation is type safe. It's guaranteed that model attribute will always hold null or value of specified type.
deep update
may be
invoked. Refer to Attribute Types
manual section for details.Attribute Options
section for details.replace:attr
events are fired,On attempt to set an attribute which is not defined, warning message will be printed to console.
In NestedTypes, you can assign individual model attributes directly, and it's faster than using set
:
model.attr = val;
Get attribute value by name. Returned value can be modified with get hook
in attribute definition.
In NestedTypes, you can access model attributes directly, and it's faster than get
:
val = model.attr;
`model.deepClone()` or `model.clone({ deep : true })`
Deeply clone model with all nested models, collections, and other complex types.
`x = model.deepGet( 'attr1.attr2.modelId.attr3.objId' )`
Get attribute by dot-separated path. Model attribute name, model.id or model.cid (for collection attribute), index (for array), or object property name ( for plain objects) may be used as an elements of the path.
If some model in the middle of path doesn't exists, it will return undefined
.
`x = model.deepSet( 'attr1.attr2.modelId.attr3.objId', x )`
Set model value by dot-separated path. If model attribute in the middle of path equals to null, empty model will be created.
var UserInfo = Nested.Model.extend({
urlBase : '/api/user/',
defaults : {
login : '',
roles : [ 'user' ]
},
collection : {
initialize : function(){
this.fetch();
}
}
});
var collection = new UserInfo.Collection();
Every model definition has its own correct Collection
type extending base Model.Collection
, which can be
accessed instantly without declaration. Collection.model
and Collection.url
properties are taken from model.
`var collection = new AnyModel.Collection();`
You could customize collection definition providing the spec in Model.collection
, which then will be passed to BaseModel.Collection.extend
.
var Tree = Nested.Mode.extend();
Tree.define({
defaults : {
branches : Tree.Collection
}
});
Forward declarations makes possible type-accurate recursive and mutually recursive model definitions.
Model.define
is the part of Object.extend
functionality. Refer to Object.extend
manual section for details.
var M = Nested.Model.extend({
defaults : {
// Attribute-level toJSON.
a : String.has.toJSON( false ),
b : 5
},
// Model-level toJSON.
toJSON : function(){
// Call NestedTypes serialization algorithm.
var json = Nested.Model.prototype.toJSON.apply( this, arguments );
// Do some json transformations...
return json;
}
});
All nested attributes will be serialized automatically.
Normally, you don't need to override this method.You can control serialization of any attribute with toJSON
attribute option. Most typical use case is to exclude attribute from those which are being sent to the server.
var M = Nested.Model.extend({
defaults : {
// Attribute-level parse transform.
a : AbstractModel.has.parse( AbstractModel.factory )
},
// Model-level parse transform.
parse : function( resp ){
// Do some resp transformations...
// (!) Call attribute-level parse transform (!)
return this._parse( resp );
}
});
All nested attributes will be parsed automatically.
Normally, you don't need to override this method.You can customize parsing of any attribute with parse
attribute option. Most typical use case is to create proper model subclass for abstract model attribute.
You may need to override model-level parse
function in order to change attribute names or top-level format.
var A = Nested.Model.extend({
defaults : {
obj1 : Ctor, // = new Ctor()
obj2 : Ctor.value( null ), // = null
obj3 : Ctor.value( something ), // = new Ctor( something )
}
});
var a = A();
a.obj2 = "dsds"; // a.obj2 = new Ctor( "dsds" );
console.assert( a.obj2 instanceof Ctor );
Type specs may be used instead of init values in Model.defaults
. They looks like this:
name : Constructor
or name : Constructor.value( x )
where Constructor
is JS constructor function, and x
is null
or value passed
as constructor's argument.
When value is not given, typed attribute is initialized invoking new Constructor()
.
When typed attribute is assigned with the value...
null
, attribute value will be set to null
.Constructor
, attribute's value will be replaced with a given one.Constructor
type, typically invoking new Constructor( value )
. Procedure might be more complex for some selected types,
such as nested models and collections.Constructor types are being serialized with JSON.stringify()
method. You may override toJSON
for your type
to customize serialization. I.e.
`this.name.toJSON()`
will be invoked to produce JSON, if this method exists.
When receiving data from server, standard type cast logic is used to convert JSON response to Constructor object. I.e.
`this.name = new Constructor( jsonResponse )`
will be invoked.
Normally, you don't need to override model.toJSON() and model.parse(). You're encouraged to properly implement constructor and toJSON of your custom type.var A = Nested.Model.extend({
defaults : {
created : Date, // = new Date()
updated : Date.value( null ), // = null
a : Date.value( 327943789 ), // = new Date( 327943789 )
b : Date.value( "2012-12-12 12:12" ) // = new Date( "2012-12-12 12:12" )
}
});
var a = A();
a.updated = '2012-12-12 12:12';
console.assert( a.updated instanceof Date );
a.updated = '/Date(32323232323)/';
console.assert( a.updated instanceof Date );
To create attribute of Date
type, pass Date
constructor instead of default value.
`time : Date` or `time : Date.value( x )`
When default value is given, it will be converted to Date using type casting rules.
Number
is treated as milliseconds from 1970 timestamps, as returned by Date.getTime().String
is treated as one of the following date-time formats (will be detected automatically):
/Date(msecs)/
time string.null
sets attribute to null
bypassing type conversion logic.Invalid Date
.Date
attributes are serialized to UTC ISO date string by default. You may customize date serialization format
providing attribute's toJSON
option. Following option will serialize time
to milliseconds.
`time : Date.has.toJSON( function( date ){ return date.getTime(); })`
You can prevent attribute from being serialized, using:
`time : Date.has.toJSON( false )`
Date
attributes are being parsed from JSON using type casting rules.
var A = Nested.Model.extend({
defaults : {
// Original backbone behaviour - no type, value is 3232
untyped : Nested.value( 3232 )
// defaults with primitive types are always 'typed'
number : 5, // same as Number.value( 5 )
integer : Integer.value( 6 ),
string : 'something', // same as String.value( 'something' )
string1 : '', // same as String
boolean : true, // same as Boolean.value( true )
initWithNull : String.value( null ), // Type is String, default value is null
}
});
var a = A();
a.boolean = "hello";
console.assert( a.boolean === true );
a.number = "5";
console.assert( a.number === 5 );
a.number = "hjhjfd";
console.assert( _.isNaN( a.number ) );
a.integer = 1.5423;
console.assert( a.integer === 2 );
a.string = 5;
console.assert( a.string === "5" );
a.boolean = 0;
console.assert( a.boolean === false );
Primitive types (Boolean, Number, String) are special in a sense that they are inferred from their values. In most cases special type annotation syntax is not really required. For example:
n : 5
is the same as n : Number.value( 5 )
b : true
is the same as b : Boolean.value( true )
s : 'hi'
is the same as s : String.value( 'hi' )
x : null
is not the same. No type will be being inferred from null
value.You can disable type inference using Nested.value( x ) or just specifying null default value.
NestedTypes adds global Integer
type, to be used in type annotations. Integer
type is not being inferred from default values, and needs to be specified explicitly.
null
will set attribute to null
for all primitive types.Number
attribute:
NaN
if conversion will fail.Integer
attribute:
Number
, but values also converted to integer using Math.round
.String
attribute:
x.toString()
method will be invoked.Boolean
attribute:
true
or false
using standard JS type cast logic.Primitives are serialized to JSON directly. You can disable serialization of particular attribute with an option:
`x : Integer.value( 5 ).toJSON( false )`
To define untyped attribute, use either of these options:
u : null
, u : []
, or u : {}
.u : x
where typeof x === 'object'.u : Nested.value( x )
for value of any type, including primitives.None
When serialized, value.toJSON
function will be invoked if it exists for particular value.
JSON responses are assigned to untyped attributes as is.
var User = Nested.Model.extend({
defaults : {
name : String,
created : Date,
group : Group,
permissions : Permission.Collection
}
});
var a = new User(),
b = a.deepClone();
To define nested model or collection, annotate attribute with Model or Collection type:
`a : MyModel` or `b : MyModel.Collection` or `c : SomeCollection`
In NestedTypes Every Model type has corresponding Collection type, which can be
referenced as Model.Collection.
Inline nested definitions
var M = Nested.Model.extend({
defaults :{
// define model extending base Nested.Model
nestedModel : Nested.defaults({
a : 1,
//define model extending specified model
b : MyModel.defaults({
// define collection of nested models
items : Nested.Collection.defaults({
a : 1,
b : 2
})
})
})
}
})
Simple models and collections can be defined with special shortened syntax.
It's useful in case of deeply nested JS objects, when you previously preferred plain objects and arrays in place of models and collections. Now you could easily convert them to nested types, enjoying nested changes detection and 'deep update' features.
Deep update example:
var user = new User();
// Following assignment...
user.group = { name: "Admin" };
// ...is the same as this:
user.group.set({ name: "Admin" });
// Following assignment...
user.permissions = [{ id: 5, type: 'full' }];
// ...is the same as this:
user.permissions.set( [{ id: 5, type: 'full' }] );
// Following assignment...
user.group = {
nestedModel : {
deeplyNestedModel : { attr : 'value' },
attr : 5
}
};
// ...is the same as this, but fire single 'change' event
user.group.nestedModel.deeplyNestedModel.attr = 'value';
user.group.nestedModel.attr = 'value';
When Model
or Collection
attribute is assigned with the value...
null
, attribute value will be set to null
.Model
/Collection
, attribute's value will be replaced with a given one.null
, new model or collection will be created taking value as constructor argument.set
method performing deep update
.Nested models and collections are serialized as nested JSON. When JSON response is received, they are being constructed or updated according to type case rules.
Event bubbling:
var M = Nested.Model.extend({
defaults: {
bubbleChanges : ModelOrCollection,
dontBubble : ModelOrCollection.has.triggerWhanChanged( false )
}),
bubbleCustomEvents : ModelOrCollection.has
.triggerWhanChanged( 'event1 event2 whatever' )
}
});
Change events will be bubbled from nested models and collections.
change
and change:attribute
events for any changes in nested models and collections. Multiple change
events from submodels during bulk updates are carefully joined together, which make it suitable to subscribe View.render to the top model's change
.replace:attribute
event when model or collection is replaced with new object. You might need it to subscribe for events from submodels.var User = Nested.Model.extend({
defaults : {
name : String,
roles : Role.Collection.subsetOf( roles ) // <- serialized as array of model ids
location : Location.from( locations ) // <- serialized as model id
}
});
var user = new User({ id: 0 });
user.fetch();
Server response: "{ id: 0, name : 'john', roles : [ 1, 2, 3 ], location : 6 }"
//ref attributes behaves like normal collections and models.
assert( user.roles instanceof Collection );
assert( user.roles.first() instanceof Role );
assert( user.location.name === "Boston" );
Sometimes it is suitable to serialize model references as an id or an array of ids.
NestedTypes provides special attribute data types to transparently handle this situation, as if you would work with normal nested models and collections.
Model.from
represent reference to the model from existing collection, which is serialized as model id.
`ref : Model.from( masterCollection )`
Attribute may be assigned with model id or model itself. On `get, attribute behaves as Model type. Model id will be resolved to model on first attribute read attempt.
If master collection is empty and thus reference cannot be resolved, it will defer id resolution and get
will return null
. If master collection is not empty, id will be resolved to model from this collection, or null
if corresponding model doesn't exists.
Attribute counts as changed only when different model or id is assigned.
Collection.subsetOf
is a collection of models taken from other 'master' collection. On first access, it will resolve model ids to real models using master collection for lookups.
If master collection is empty and thus references cannot be resolved, it will defer id resolution and just return empty collection. If master collection is not empty, it will filter out ids of non-existent models.
Collection.subsetOf
supports some additional methods:
change
events won't be bubbled from models in Collection.subsetOf. Other collection's events will.
Master collection reference may be:
string
, designating reference to the current model's member relative to 'this'.function
, which returns reference to collection and executed in the context of the model.var M = Nested.Model.extend({
defaults : {
attr : Date.has
.value( null )
.toJSON( false )
}
});
Attribute options spec gives you to customize different aspects of attribute behavior, such as:
.value
is an example of attribute option. In order to get access to other options you need to use keyword .has
. Options specs are chainable, you can specify any sequence of options separated by dot.
var M = Nested.Model.extend({
defaults : {
a : Type.has.value( value ),
b : Type.value( value )
}
});
Attribute's default value. On model construction, value
will be casted to Type
applying usual type casting rules.
var M = Nested.Model.extend({
defaults : {
a : Type.has.toJSON( function( value, name ){
return value.text;
}),
b : Type.has.toJSON( false )
}
});
When attribute will be serialized as a part of model, given function will be used instead of attribute's toJSON.
Function accepts attribute's name
and its current value
, and will be executed in the context of the model, holding an attribute.
Passing false
option will prevent attribute's serialization.
var M = Nested.Model.extend({
defaults : {
a : Type.has.parse( function( value ){
return Type.factory( value );
})
}
});
Attribute-specific parse
logic, will be executed after model's parse
method.
Function accepts attribute's name
and response value
, and will be executed in the context of the model, holding an attribute.
This option is useful to parse abstract model attributes, or handle non-standard format of specific attributes.
var M = Nested.Model.extend({
defaults : {
a : Type.has.get( function( value, name ){
return value;
})
}
});
Called during model.get( 'a' )
or model.a
in the context of the model, allowing you to modify value which will be returned without altering attribute itself.
Get hook function accepts attribute's name
and its current value
, and returns modified value.
Multiple get hooks are chainable, and will be applied in specified order.
var M = Nested.Model.extend({
defaults : {
a : Type.has.set( function( value, name ){
return value;
})
}
});
Called during attribute's update in the context of the model after type cast but before an actual set, allowing you to modify set value.
Set hook is only called when attribute value is changed. For nested models and collections case, it will be called only in case when instance will be replaced, not in case of deep update.Set hook function accepts attribute's name
and value
to be set, and returns modified value, or undefined
to cancel attribute update.
Multiple set hooks are chainable, and will be applied in specified order.
Returned value will be casted to attribute's type applying standard convertion rules. So, it's guaranteed that attribute's value will always hold the correct type.
var M = Nested.Model.extend({
defaults : {
a : Type.has.events({
'isReady isNotReady' : function(){
this.trigger( 'imwatchingyou' );
}
}),
}
});
Automatically manage events subscription for nested attribute, capable of sending events. Event handlers will be called in the context of of the parent model.
var M = Nested.Model.extend({
defaults : {
a : ModelA.has.triggerWhenChanged( 'change myEvent' ),
b : ModelB.has.triggerWhenChanged( false ),
}
});
Makes sense only for Model and Collection attributes.
Override default list of events used for nested changes detection of selected attribute.
Pass false
option to disable nested changes detection for this attribute.
var M = Nested.Model.extend({
defaults : {
a : Nested.attribute({
value : null,
toJSON : false
}),
b : Nested.attribute()
.value( null )
.toJSON( false )
}
});
Nested.attribute
function returns attribute spec as it appears after .has
, optionally accepting set of options as a hash.
There's a global store for the collections, which might be useful in case of bi-directional relationships. It's available as a member of Model (this.store), and globally as Nested.store.
Nested.store = {
roles : Role.Collection,
locations : Locations.Collection
};
var User = Nested.Model.extend({
defaults : {
name : String,
roles : Collection.subsetOf( 'store.roles' ); // this.store.roles
location : Location.from( 'store.locations' }); // this.store.locations
}
});
Store needs to be initialized with a hash of collections and models type specs. It can be initialized several times.
Format of the spec object is the same as in Model.defaults
.
On first access to every member of the store, it will fetch data from the server automatically. You need to take care of update events.
Update all store members, which are currently loaded:
`Nested.store.fetch()`
Fetches store elements with given names:
`Nested.store.fetch( 'name1', 'name2', ... )`
Returns aggregate promise for xhr objects.
Clear all store collection elements:
Nested.store.clear()
Clear selected store collections:
Nested.store.clear( 'name1', 'name2', ... )
Returns store to allow chained calls.
NestedTypes detect four error types in the runtime, which will be logged to console using console.error.
When you override function with non-function value in the subclass, it usually means an error.
This message also warn you on the situation when you made model attribute or property name the same as some base class method.
[Type Warning] Base class method overriden with value in Object.extend({ url : [object Object] }); Object = ...
First argument of Model.set must be either string, or literal object representing attribute hash.
Other situation means serious error. Something goes really wrong.
[Type Error] Attribute hash is not an object in Model.set( "http://0.0.0.0/" ); this = ...
First argument of Collection.set must be either an Array, literal object, or compatible Model.
Other situation means serious error. Something goes really wrong.
[Type Error] Wrong argument type in Collection.set( "dsds" ); this = ...
Attempt to set an attribute which is not declared in model defaults
.
[Type Error] Attribute has no default value in Model.set( "a", 0 ); this =...
FAQs
backbone.js extension adding type annotations to model attributes, easiest possible way of dealing with nested models and collections, and native properties for attributes. Providing you with a more or less complete, simple, and powerful object system for
The npm package backbone.nested-types receives a total of 0 weekly downloads. As such, backbone.nested-types popularity was classified as not popular.
We found that backbone.nested-types demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
GitHub removed 27 malicious pull requests attempting to inject harmful code across multiple open source repositories, in another round of low-effort attacks.
Security News
RubyGems.org has added a new "maintainer" role that allows for publishing new versions of gems. This new permission type is aimed at improving security for gem owners and the service overall.
Security News
Node.js will be enforcing stricter semver-major PR policies a month before major releases to enhance stability and ensure reliable release candidates.