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

bookshelf

Package Overview
Dependencies
Maintainers
1
Versions
87
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

bookshelf - npm Package Compare versions

Comparing version 0.0.0 to 0.0.1

242

bookshelf.js

@@ -12,3 +12,2 @@ // Bookshelf.js 0.1.0

// -------------
var Bookshelf = {};

@@ -26,6 +25,2 @@

// Attach `Knex` & `Knex.Transaction` for convenience.
Bookshelf.Knex = Knex;
Bookshelf.Transaction = Knex.Transaction;
// Keep in sync with package.json.

@@ -38,4 +33,4 @@ Bookshelf.VERSION = '0.0.0';

var Events = Bookshelf.Events = Backbone.Events;
Events.emit = function() { this.trigger.apply(this, arguments); };
Events.removeAllListeners = function(event) { this.off(event, null, null); };
Events.emit = function() { this.trigger.apply(this, arguments); };

@@ -49,2 +44,7 @@ // `Bookshelf` may be used as a top-level pub-sub bus.

// Returns an instance of the query builder.
builder: function(table) {
return Bookshelf.Knex(table);
},
// If there are no arguments, return the current object's

@@ -55,3 +55,3 @@ // query builder (or create a new one). If there are arguments,

query: function() {
this._builder || (this._builder = Bookshelf.Knex(_.result(this, 'tableName')));
this._builder || (this._builder = this.builder(_.result(this, 'tableName')));
var args = _.toArray(arguments);

@@ -109,3 +109,3 @@ if (args.length === 0) return this._builder;

// A Bookshelf Model represents an individual row in the database table --
// It is a similar implementation to the `Backbone.Model`
// It has a similar implementation to the `Backbone.Model`
// constructor, except that defaults are not set until the

@@ -123,3 +123,3 @@ // object is persisted, and the collection property is not used.

this._configure(options);
if (options && options.parse) attrs = this.parse(attrs, options) || {};
if (options.parse) attrs = this.parse(attrs, options) || {};
options.protect || (options.protect = false);

@@ -132,3 +132,4 @@ this.set(attrs, options);

// A list of properties that are omitted from the `Backbone.Model.prototype`, since we're not
// handling validations, or tracking changes, we can drop all of these related features.
// handling validations, or tracking changes in the same way as Backbone, we can drop all of
// these related features.
var modelOmitted = ['isValid', 'hasChanged', 'changedAttributes', 'previous', 'previousAttributes'];

@@ -215,3 +216,3 @@

if (key == null || typeof key === "object") {
attrs = key;
attrs = key || {};
options = val || {};

@@ -223,26 +224,19 @@ } else {

// Don't allow setting an id attribute on save, unless the
// `{existing: true}` flag is set on the options hash.
if (attrs) id = attrs[this.idAttribute];
if (id && id !== this.id && !options.existing) {
Q.reject(new Error('The model cannot be saved with an idAttribute'));
// If the model has timestamp columns,
// set them as attributes on the model, even
// if the method is set to "patch".
if (this.hasTimestamps) {
_.extend(attrs, this.timestamp(options));
}
// Handle the defaults at the `save` level rather than the
// object creation level.
// Merge any defaults here rather than during object creation.
var defaults = _.result(this, 'defaults');
var vals = attrs;
if (defaults) {
attrs = _.extend({}, defaults, this.attributes);
vals = _.extend({}, defaults, this.attributes, vals);
}
// Set the model, and maintain a reference to use below.
var model = this.set(attrs);
// If the model has timestamp columns,
// set them as attributes on the model
if (model.hasTimestamps) {
model.timestamp(options);
}
var sync = model.sync(model, options);
// Set the attributes on the model, and maintain a reference to use below.
var model = this.set(vals);
var sync = model.sync(model, options);
var method = options.method || (model.isNew(options) ? 'insert' : 'update');

@@ -254,3 +248,3 @@

return sync[method]().then(function(resp) {
return sync[method](attrs, options).then(function(resp) {

@@ -301,6 +295,6 @@ // After a successful database save, the id is updated

var d = new Date();
this.set('updated_at', d);
if (this.isNew(options)) {
this.set('created_at', d);
}
var vals = {};
vals.updated_at = d;
if (this.isNew(options)) vals.created_at = d;
return vals;
},

@@ -405,9 +399,2 @@

// Efficiently persists any models in the current collection, only saving models that have
// been changed, batch inserting or updating where appropriate, and retuning
// a promise resolving with the `collection`.
save: function(options) {
// TODO
},
// Shortcut for creating a new model, saving, and adding to the collection.

@@ -422,3 +409,2 @@ // Returns a promise which will resolve with the model added to the collection.

if (options.success) options.success(model, resp, options);
this.add(model, options);
return model;

@@ -449,9 +435,2 @@ });

// Temporary helper object for handling the response of an `EagerRelation` load.
var RelatedModels = function(models) {
this.models = models;
this.length = this.models.length;
};
_.extend(RelatedModels.prototype, _.pick(Collection.prototype, 'find', 'where', 'filter', 'findWhere'));
// An `EagerRelation` object temporarily stores the models from an eager load,

@@ -476,3 +455,3 @@ // and handles matching eager loaded objects with their parent(s).

Bookshelf.addEagerConstraints(opts.type, this, opts.parentResponse);
Bookshelf.addConstraints(opts.type, this, opts.parentResponse);

@@ -608,13 +587,11 @@ return this.query().select(opts.columns).then(function(resp) {

// Adds the basic relation constraints onto the query.
Bookshelf.addConstraints = function(type, target) {
if (type !== 'belongsToMany') {
return constraints(target);
} else {
return belongsToMany(target);
}
// Temporary helper object for handling the response of an `EagerRelation` load.
var RelatedModels = function(models) {
this.models = models;
this.length = this.models.length;
};
_.extend(RelatedModels.prototype, _.pick(Collection.prototype, 'find', 'where', 'filter', 'findWhere'));
// Adds eager loading relationship constraints onto the query.
Bookshelf.addEagerConstraints = function(type, target, resp) {
// Adds the relation constraints onto the query.
Bookshelf.addConstraints = function(type, target, resp) {
if (type !== 'belongsToMany') {

@@ -659,15 +636,13 @@ return constraints(target, resp);

var belongsToMany = function(target, resp) {
var relation, columns, builder, idAttribute, tableName,
otherKey, foreignKey, pivotColumns, joinTableName;
relation = target._relation;
columns = relation.columns || (relation.columns = []);
builder = target.query();
var
relation = target._relation,
columns = relation.columns || (relation.columns = []),
builder = target.query(),
tableName = _.result(target, 'tableName');
idAttribute = _.result(target, 'idAttribute');
tableName = _.result(target, 'tableName'),
idAttribute = _.result(target, 'idAttribute'),
otherKey = relation.otherKey;
foreignKey = relation.foreignKey;
pivotColumns = relation.pivotColumns;
otherKey = relation.otherKey,
foreignKey = relation.foreignKey,
pivotColumns = relation.pivotColumns,
joinTableName = relation.joinTableName;

@@ -699,2 +674,13 @@

// The `forge` function properly instantiates a new Model or Collection
// without needing the "new" keyword... to make object creation cleaner
// and more chainable.
Model.forge = Collection.forge = function() {
var Ctor = function() {};
Ctor.prototype = this.prototype;
var inst = new Ctor();
var obj = this.apply(inst, arguments);
return (Object(obj) === obj ? obj : inst);
};
// Bookshelf.Sync

@@ -707,3 +693,3 @@ // -------------------

// If the `transacting` option is set, the query is assumed to be
// part of a transaction, and this information is passed along to Knex.
// part of a transaction, and this information is passed along to `Knex`.
var Sync = Bookshelf.Sync = function(model, options) {

@@ -769,12 +755,14 @@ options || (options = {});

}
// TODO: any handling for empty responses?
// If `{require: true}` is set as an option, the fetch is considered
// a failure if the model comes up blank.
if (options.require) return Q.reject('EmptyResponse');
if (model instanceof Model) {
model.clear();
return {};
} else {
model.reset([], {silent: true});
return [];
}
model.reset([], {silent: true});
return [];

@@ -796,3 +784,4 @@ }).then(function(resp) {

// Issues an `update` command on the query.
update: function() {
update: function(attrs, options) {
attrs = (attrs && options.patch ? attrs : this.model.attributes);
return this.query.where(this.model.idAttribute, this.model.id)

@@ -828,3 +817,4 @@ .update(this.model.format(_.extend({}, this.model.attributes)));

var pivot = this._relation;
return Q.allResolved(_.map(ids, function(item) {
var context = this;
return Q.all(_.map(ids, function(item) {
var data = {};

@@ -845,3 +835,3 @@ data[pivot.otherKey] = pivot.fkValue;

}
var builder = Bookshelf.Knex(pivot.joinTableName);
var builder = context.builder(pivot.joinTableName);
if (options && options.transacting) {

@@ -894,44 +884,2 @@ builder.transacting(options.transacting);

// Inherit standard Backbone.js Collections & Models from the client,
// transforming a client `Backbone.Model` or `Backbone.Collection` to a
// `Bookshelf` compatible object, to reuse validations, defaults, user methods, etc.
Model.convert = Collection.convert = function(Target, protoProps, staticProps) {
var parent = this;
// Don't allow convert to work with an object instance.
if (!Target.prototype) {
throw new Error('Bookshelf.convert can only work with a constructor object');
}
// Traverse the prototype chain, breaking once we hit the prototype of the
// Model or Collection we're converting. This way we can put the prototype chain
// back together starting from the base "extend" so inheritance works properly.
var current = Target;
var depth = [];
var passed = false;
while (passed !== true) {
if (_.isEqual(current.prototype, Backbone.Model.prototype) ||
_.isEqual(current.prototype, Backbone.Collection.prototype)) {
passed = true;
} else if (!current.__super__) {
throw new Error("Only Backbone objects may be converted.");
} else {
depth.push(_.pick(current.prototype, _.keys(current.prototype)));
current = current.__super__.constructor;
}
}
// Setup the correct prototype chain.
var currentObj = this;
for (var i = depth.length; i > 0; i--) {
// Omit parse and toJSON, as these have fundamentally different meanings
// on the client and server.
currentObj = currentObj.extend(_.omit(depth[i - 1], 'parse', 'toJSON'));
}
return currentObj.extend(protoProps, staticProps);
};
// Filters an array of objects, cleaning out any nested properties.

@@ -944,2 +892,7 @@ var skim = function(data) {

// References to the default `Knex` and `Knex.Transaction`, overwritten
// when a new database connection is created in `Initialize` below.
Bookshelf.Knex = Knex;
Bookshelf.Transaction = Knex.Transaction;
// Bookshelf.Initialize

@@ -949,9 +902,48 @@ // -------------------

// Configure the `Bookshelf` settings (database adapter, etc.) once,
// so it is ready on first model initialization.
Bookshelf.Initialize = function(options) {
return Knex.Initialize(options);
// so it is ready on first model initialization. Optionally, provide
// a `name` so a named instance of
Bookshelf.Initialize = function(name, options) {
var Target;
if (_.isObject(name)) {
options = name;
name = 'default';
}
if (Bookshelf.Instances[name]) {
throw new Error('A ' + name + ' instance of Bookshelf already exists');
}
// If an object with this name already exists in `Knex.Instances`, we will
// use that copy of `Knex` without trying to re-initialize.
var Builder = (Knex[name] || Knex.Initialize(name, options));
if (name === 'default') {
Target = Bookshelf.Instances['default'] = Bookshelf;
} else {
Target = Bookshelf.Instances[name] = {};
// Create a new `Bookshelf` instance for this database.
_.extend(Target, _.omit(Bookshelf, 'Instances', 'Initialize', 'Knex', 'Transaction'), {
Knex: Builder,
Transaction: Builder.Transaction
});
// Attach a new builder function that references the correct connection.
_.each(['Model', 'Collection', 'EagerRelation'], function(item) {
Target[item].prototype.builder = function(table) {
return Target(table);
};
});
}
// Return the initialized instance.
return Target;
};
// Named instances of Bookshelf, presumably with different `Knex`
// options, to initialize different databases.
// The main instance being named "default"...
Bookshelf.Instances = {};
module.exports = Bookshelf;
}).call(this);

@@ -7,3 +7,3 @@ {

},
"version": "0.0.0",
"version": "0.0.1",
"description": "A promise based ORM in the style of Backbone.js",

@@ -27,3 +27,3 @@ "main": "bookshelf.js",

"backbone": "1.0.x",
"knex": ">=0.0.0",
"knex": ">=0.0.1",
"underscore": "1.4.4",

@@ -30,0 +30,0 @@ "q": "0.9.x",

@@ -47,33 +47,15 @@ var Bookshelf = require('../bookshelf');

describe('convert', function() {
describe('forge', function() {
it('properly handles the inheritance chain', function() {
var One = Backbone.Collection.extend({
customMethod: function(val) { return val || 1; }
it('should create a new collection instance', function() {
var User = Bookshelf.Model.extend({
tableName: 'users'
});
var Two = One.extend({
secondMethod: function(val) { return One.prototype.customMethod.call(this, val || 2); }
var Users = Bookshelf.Collection.extend({
model: User
});
var Three = Two.extend({
thirdCustomMethod: function() { return this.secondMethod(3); }
});
var Converted = Bookshelf.Collection.convert(Three, {
test: function() {
equal(this.thirdCustomMethod(Converted), 3);
equal(this.secondMethod(), 2);
equal(this.customMethod(), 1);
}
});
new Converted().test();
var users = Users.forge();
equal(users.tableName(), 'users');
});
it('breaks on invalid object conversions', function() {
var Invalid = function() {};
Invalid.prototype = {testMethod: function() {}};
try {
Bookshelf.Collection.convert(Invalid, {newMethod: function() {}});
} catch (e) {
equal(e.toString(), 'Error: Only Backbone objects may be converted.');
}
});
});

@@ -80,0 +62,0 @@

@@ -20,12 +20,2 @@ var Q = require('q');

// var base;
// var Base = Bookshelf.Model.extend({
// tableName: 'authors'
// });
// beforeEach(function() {
// if (base) base.off();
// base = new Base();
// });
describe('extend/constructor/initialize', function() {

@@ -69,33 +59,12 @@

describe('convert', function() {
describe('forge', function() {
it('properly handles the inheritance chain', function() {
var One = Backbone.Model.extend({
customMethod: function(val) { return val || 1; }
it('should create a new model instance', function() {
var User = Bookshelf.Model.extend({
tableName: 'users'
});
var Two = One.extend({
secondMethod: function(val) { return One.prototype.customMethod.call(this, val || 2); }
});
var Three = Two.extend({
thirdCustomMethod: function() { return this.secondMethod(3); }
});
var Converted = Bookshelf.Model.convert(Three, {
test: function() {
equal(this.thirdCustomMethod(Converted), 3);
equal(this.secondMethod(), 2);
equal(this.customMethod(), 1);
}
});
new Converted().test();
var user = User.forge();
equal(user.tableName, 'users');
});
it('breaks on invalid object conversions', function() {
var Invalid = function() {};
Invalid.prototype = {testMethod: function() {}};
try {
Bookshelf.Model.convert(Invalid, {newMethod: function() {}});
} catch (e) {
equal(e.toString(), 'Error: Only Backbone objects may be converted.');
}
});
});

@@ -373,8 +342,8 @@

var m1 = new Bookshelf.Model({id: 1});
m.timestamp();
m1.timestamp();
equal(_.isDate(m.get('created_at')), true);
equal(_.isDate(m.get('updated_at')), true);
equal(_.isEmpty(m1.get('created_at')), true);
equal(_.isDate(m1.get('updated_at')), true);
var ts = m.timestamp();
var ts2 = m1.timestamp();
equal(_.isDate(ts.created_at), true);
equal(_.isDate(ts.updated_at), true);
equal(_.isEmpty(ts2.created_at), true);
equal(_.isDate(ts2.updated_at), true);
});

@@ -381,0 +350,0 @@ });

@@ -20,6 +20,6 @@ var Q = require('q');

// Collections
var Sites = Collections.Sites;
var Admins = Collections.Admins;
var Blogs = Collections.Blogs;
var Posts = Collections.Posts;
var Sites = Collections.Sites;
var Admins = Collections.Admins;
var Blogs = Collections.Blogs;
var Posts = Collections.Posts;
var Comments = Collections.Comment;

@@ -26,0 +26,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