Comparing version 0.14.0 to 0.14.1
## Change Log | ||
**0.14.1** <small>_Dec 09, 2018_</small> - [Diff](https://github.com/bookshelf/bookshelf/compare/0.14.0...0.14.1) | ||
#### Warning | ||
- Incorrectly published the previous version from the wrong branch. That version doesn't contain all | ||
the work that is was supposed to. You shold use this version instead. | ||
#### Breaking changes | ||
- The `previous()` and `previousAttributes()` methods were changed so that whenever a model is saved or destroyed the previous attributes are no longer reset to the current attributes. Since the old behavior wasn't very useful it's likely this won't cause issues for many people. There's a [migration guide](https://github.com/bookshelf/bookshelf/wiki/Migrating-from-0.13.3-to-0.14.0#previous-and-previousattributes) in case you are affected by this change. [#1848](https://github.com/bookshelf/bookshelf/pull/1848) | ||
#### Bug fixes | ||
- Fix `withRelated` fetch option not always grouping properly when using binary primary keys: [#1918](https://github.com/bookshelf/bookshelf/pull/1918) | ||
**0.14.0** <small>_Dec 09, 2018_</small> - [Diff](https://github.com/bookshelf/bookshelf/compare/0.13.3...0.14.0) | ||
@@ -7,3 +22,2 @@ | ||
- The `previous()` and `previousAttributes()` methods were changed so that whenever a model is saved or destroyed the previous attributes are no longer reset to the current attributes. Since the old behavior wasn't very useful it's likely this won't cause issues for many people. There's a [migration guide](https://github.com/bookshelf/bookshelf/wiki/Migrating-from-0.13.3-to-0.14.0#previous-and-previousattributes) in case you are affected by this change. [#1848](https://github.com/bookshelf/bookshelf/pull/1848) | ||
- Fix incorrect results in collection when models have duplicate ids. Checkout the [migration guide](https://github.com/bookshelf/bookshelf/wiki/Migrating-from-0.13.3-to-0.14.0#passing-merge-false-remove-false-to-collectionset-and-default-behavior-with-duplicates) in case you are affected by this. [#1846](https://github.com/bookshelf/bookshelf/pull/1846) | ||
@@ -22,3 +36,2 @@ - Empty `hasOne` relation will now return `null` instead of `{}` when serialized: [#1839](https://github.com/bookshelf/bookshelf/pull/1839). There's a [migration guide](https://github.com/bookshelf/bookshelf/wiki/Migrating-from-0.13.3-to-0.14.0#return-value-for-empty-hasone-relation) in the rare event this causes you problems. | ||
- Fix `withRelated` fetch option not always grouping properly when using binary primary keys: [#1918](https://github.com/bookshelf/bookshelf/pull/1918) | ||
- Return clones of nested objects in `previousAttributes()`: [#1876](https://github.com/bookshelf/bookshelf/pull/1876) | ||
@@ -25,0 +38,0 @@ - Fix incorrect `rowCount` value when using `groupBy` with `fetchPage()`: [#1852](https://github.com/bookshelf/bookshelf/pull/1852) |
@@ -145,2 +145,14 @@ // Base Collection | ||
/** | ||
* @method | ||
* @private | ||
* @description | ||
* When keying a collection by ID, ensure that it is safe to use as a key | ||
* @param {any} id | ||
* @return {string|number} The id safe for using as a key in a collection | ||
*/ | ||
CollectionBase.prototype.idKey = function(id) { | ||
return _.isBuffer(id) ? id.toString('hex') : id; | ||
}; | ||
CollectionBase.prototype.toString = function() { | ||
@@ -267,4 +279,4 @@ return '[Object Collection]'; | ||
toAdd.push(model); | ||
this._byId[model.cid] = model; | ||
if (model.id != null) this._byId[model.id] = model; | ||
this._byId[this.idKey(model.cid)] = model; | ||
if (model.id != null) this._byId[this.idKey(model.id)] = model; | ||
} | ||
@@ -450,3 +462,3 @@ | ||
if (!model) continue; | ||
delete this._byId[model.id]; | ||
delete this._byId[this.idKey(model.id)]; | ||
delete this._byId[model.cid]; | ||
@@ -555,3 +567,3 @@ const index = this.indexOf(model); | ||
if (obj == null) return void 0; | ||
return this._byId[obj.id] || this._byId[obj.cid] || this._byId[obj]; | ||
return this._byId[this.idKey(obj.id)] || this._byId[obj.cid] || this._byId[this.idKey(obj)]; | ||
}; | ||
@@ -558,0 +570,0 @@ |
@@ -84,6 +84,6 @@ // Events | ||
* event handlers throw an `Error` or return a rejected promise, the promise | ||
* will be rejected. Used internally on the {@link Model#creating "creating"}, | ||
* {@link Model#updating "updating"}, {@link Model#saving "saving"}, and {@link | ||
* Model@destroying "destroying"} events, and can be helpful when needing async | ||
* event handlers (for validations, etc). | ||
* will be rejected. Used internally on the {@link Model#event:creating "creating"}, | ||
* {@link Model#event:updating "updating"}, {@link Model#event:saving "saving"}, and | ||
* {@link Model@event:destroying "destroying"} events, and can be helpful when needing | ||
* async event handlers (e.g. for validations). | ||
* | ||
@@ -90,0 +90,0 @@ * @param {string} name |
@@ -140,2 +140,3 @@ const _ = require('lodash'); | ||
* @event Collection#fetched | ||
* @tutorial events | ||
* | ||
@@ -142,0 +143,0 @@ * @description |
@@ -738,2 +738,3 @@ 'use strict'; | ||
* @event Model#fetched | ||
* @tutorial events | ||
* @param {Model} model | ||
@@ -834,2 +835,3 @@ * The model firing the event. | ||
* @event Model#fetching:collection | ||
* @tutorial events | ||
* @param {Collection} collection | ||
@@ -853,2 +855,3 @@ * The collection that is going to be fetched. At this point it's still empty since the | ||
* @event Model#fetched:collection | ||
* @tutorial events | ||
* @param {Collection} collection The collection that has been fetched. | ||
@@ -944,28 +947,33 @@ * @param {Object} response | ||
* | ||
* Several events fired on the model when saving: a {@link Model#creating | ||
* "creating"}, or {@link Model#updating "updating"} event if the model is | ||
* being inserted or updated, and a "saving" event in either case. To | ||
* prevent saving the model (with validation, etc.), throwing an error inside | ||
* one of these event listeners will stop saving the model and reject the | ||
* promise. A {@link Model#created "created"}, or {@link Model#"updated"} | ||
* event is fired after the model is saved, as well as a {@link Model#saved | ||
* "saved"} event either way. If you wish to modify the query when the {@link | ||
* Model#saving "saving"} event is fired, the knex query object should is | ||
* available in `options.query`. | ||
* Several events fire on the model when saving: a {@link Model#event:creating | ||
* "creating"}, or {@link Model#event:updating "updating"} event if the model is | ||
* being inserted or updated, and a "saving" event in either case. | ||
* | ||
* // Save with no arguments | ||
* Model.forge({id: 5, firstName: 'John', lastName: 'Smith'}).save().then(function() { | ||
* //... | ||
* }); | ||
* To prevent saving the model (for example, with validation), throwing an error | ||
* inside one of these event listeners will stop saving the model and reject the | ||
* promise. | ||
* | ||
* // Or add attributes during save | ||
* Model.forge({id: 5}).save({firstName: 'John', lastName: 'Smith'}).then(function() { | ||
* //... | ||
* }); | ||
* A {@link Model#event:created "created"}, or {@link Model#event:updated "updated"} | ||
* event is fired after the model is saved, as well as a {@link Model#event:saved "saved"} | ||
* event either way. If you wish to modify the query when the {@link Model#event:saving | ||
* "saving"} event is fired, the knex query object is available in `options.query`. | ||
* | ||
* // Or, if you prefer, for a single attribute | ||
* Model.forge({id: 5}).save('name', 'John Smith').then(function() { | ||
* //... | ||
* }); | ||
* See the {@tutorial events} guide for further details. | ||
* | ||
* @example | ||
* // Save with no arguments | ||
* Model.forge({id: 5, firstName: 'John', lastName: 'Smith'}).save().then(function() { | ||
* //... | ||
* }); | ||
* | ||
* // Or add attributes during save | ||
* Model.forge({id: 5}).save({firstName: 'John', lastName: 'Smith'}).then(function() { | ||
* //... | ||
* }); | ||
* | ||
* // Or, if you prefer, for a single attribute | ||
* Model.forge({id: 5}).save('name', 'John Smith').then(function() { | ||
* //... | ||
* }); | ||
* | ||
* @param {string=} key Attribute name. | ||
@@ -1057,2 +1065,3 @@ * @param {string=} val Attribute value. | ||
* @event Model#saving | ||
* @tutorial events | ||
* @param {Model} model | ||
@@ -1081,2 +1090,3 @@ * The model firing the event. Its attributes are already changed but | ||
* @event Model#creating | ||
* @tutorial events | ||
* @param {Model} model The model firing the event. | ||
@@ -1103,2 +1113,3 @@ * @param {Object} attrs | ||
* @event Model#updating | ||
* @tutorial events | ||
* @param {Model} model | ||
@@ -1144,2 +1155,3 @@ * The model firing the event. Its attributes are already changed but | ||
* @event Model#saved | ||
* @tutorial events | ||
* @param {Model} model The model firing the event. | ||
@@ -1160,2 +1172,3 @@ * @param {(Array|Number)} response | ||
* @event Model#created | ||
* @tutorial events | ||
* @param {Model} model The model firing the event. | ||
@@ -1173,2 +1186,3 @@ * @param {Array} newId A list containing the id of the newly created model. | ||
* @event Model#updated | ||
* @tutorial events | ||
* @param {Model} model The model firing the event. | ||
@@ -1189,8 +1203,8 @@ * @param {Number} affectedRows Number of rows affected by the update. | ||
* | ||
* A {@link Model#destroying "destroying"} event is triggered on the model before being | ||
* destroyed. To prevent destroying the model (with validation, etc.), throwing an error | ||
* inside one of these event listeners will stop destroying the model and | ||
* reject the promise. | ||
* A {@link Model#event:destroying "destroying"} event is triggered on the model | ||
* before being destroyed. To prevent destroying the model, throwing an error | ||
* inside one of the event listeners will stop destroying the model and reject the | ||
* promise. | ||
* | ||
* A {@link Model#destroyed "destroyed"} event is fired after the model's | ||
* A {@link Model#event:destroyed "destroyed"} event is fired after the model's | ||
* removal is completed. | ||
@@ -1236,2 +1250,3 @@ * | ||
* @event Model#destroying | ||
* @tutorial events | ||
* @param {Model} model The model firing the event. | ||
@@ -1261,2 +1276,3 @@ * @param {Object} options Options object passed to {@link Model#destroy destroy}. | ||
* @event Model#destroyed | ||
* @tutorial events | ||
* @param {Model} model The model firing the event. | ||
@@ -1263,0 +1279,0 @@ * @param {Object} options Options object passed to {@link Model#destroy destroy}. |
@@ -110,3 +110,3 @@ 'use strict'; | ||
const fetchOptions = _.omit(options, ['page', 'pageSize', 'limit', 'offset']); | ||
const transacting = fetchOptions.transacting; | ||
const countOptions = _.omit(fetchOptions, ['require', 'columns', 'withRelated', 'lock']); | ||
const fetchMethodName = isModel ? 'fetchAll' : 'fetch'; | ||
@@ -184,3 +184,3 @@ const targetModel = isModel ? this.constructor : this.target || this.model; | ||
}) | ||
[fetchMethodName]({transacting}) | ||
[fetchMethodName](countOptions) | ||
.then((result) => { | ||
@@ -187,0 +187,0 @@ const metadata = usingPageSize ? {page: _page, pageSize: _limit} : {offset: _offset, limit: _limit}; |
@@ -377,16 +377,17 @@ // Relation | ||
// Group all of the related models for easier association with their parent models. | ||
const idKey = (key) => (_.isBuffer(key) ? key.toString('hex') : key); | ||
const grouped = _.groupBy(related, (m) => { | ||
let key; | ||
if (m.pivot) { | ||
if (this.isInverse() && this.isThrough()) { | ||
return this.isThroughForeignKeyTargeted() ? m.pivot.get(this.throughForeignKeyTarget) : m.pivot.id; | ||
key = this.isThroughForeignKeyTargeted() ? m.pivot.get(this.throughForeignKeyTarget) : m.pivot.id; | ||
} else { | ||
key = m.pivot.get(this.key('foreignKey')); | ||
} | ||
return m.pivot.get(this.key('foreignKey')); | ||
} else if (this.isInverse()) { | ||
key = this.isForeignKeyTargeted() ? m.get(this.foreignKeyTarget) : m.id; | ||
} else { | ||
key = m.get(this.key('foreignKey')); | ||
} | ||
if (this.isInverse()) { | ||
return this.isForeignKeyTargeted() ? m.get(this.foreignKeyTarget) : m.id; | ||
} | ||
return m.get(this.key('foreignKey')); | ||
return idKey(key); | ||
}); | ||
@@ -400,7 +401,7 @@ | ||
const parsedKey = Object.keys(model.parse({[this.parentIdAttribute]: null}))[0]; | ||
groupedKey = model.get(parsedKey); | ||
groupedKey = idKey(model.get(parsedKey)); | ||
} else { | ||
const keyColumn = this.key(this.isThrough() ? 'throughForeignKey' : 'foreignKey'); | ||
const formatted = model.format(_.clone(model.attributes)); | ||
groupedKey = formatted[keyColumn]; | ||
groupedKey = idKey(formatted[keyColumn]); | ||
} | ||
@@ -407,0 +408,0 @@ if (groupedKey != null) { |
@@ -98,2 +98,3 @@ // Sync | ||
* @event Model#counting | ||
* @tutorial events | ||
* @param {Model} model The model firing the event. | ||
@@ -179,2 +180,3 @@ * @param {Object} options Options object passed to {@link Model#count count}. | ||
* @event Model#fetching | ||
* @tutorial events | ||
* @param {Model} model | ||
@@ -181,0 +183,0 @@ * The model which is about to be fetched. |
{ | ||
"name": "bookshelf", | ||
"version": "0.14.0", | ||
"version": "0.14.1", | ||
"description": "A lightweight ORM for PostgreSQL, MySQL, and SQLite3", | ||
@@ -5,0 +5,0 @@ "main": "bookshelf.js", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
277288
5957