Repository  -  API  -  Source


June 13, 2019
  • Update husky to version 2.4.1: #1984
  • Bump supported knex version to 0.17: #1982


June 13, 2019

Breaking changes

  • This version requires Node.js 6+
  • Remove code that has been deprecated for a long time: #1956

Bug fixes

  • once removes all events after it has been triggered: #1972
  • Pagination details are wrong when selecting distinct values of a column: #1950
  • Fix missing attributes in some events: #1934

Test Suite

  • Fix Docker-compose.yml default postgres user: #1972
  • Fix JSON tests on PostgreSQL 10+: #1955


  • Update and fix a lot of doclets: #1951
  • Update #1940


  • Update mocha to version 6.1.1: #1968
  • Update eslint-config-prettier to 4.1.0: #1957
  • Update sinon to version 7.2.4: #1947
  • Update eslint to version 5.1.0: #1930


December 17, 2018

Bug fixes

  • Fix crash when using groupBy with table qualifier in pagination plugin: #1928
  • Fix undefined transaction object with Knex 0.15+: #1926


  • Refactor logic behind .timestamp()'s decision for when to update the updated_at column: #1892


December 9, 2018


  • Allow passing custom options to the pagination plugin's internal count method. This is useful for better interoperability with other plugins: #1914

Bug fixes

  • Fix withRelated fetch option not always grouping properly when using binary primary keys: #1918


  • Add a basic Events guide and fix some issues with the events doclets: #1917


December 9, 2018

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 in case you are affected by this change. #1848
  • Fix incorrect results in collection when models have duplicate ids. Checkout the migration guide in case you are affected by this. #1846
  • Empty hasOne relation will now return null instead of {} when serialized: #1839. There's a migration guide in the rare event this causes you problems.
  • Add more helpful error messages on bad or insufficient morphTo data: #1824. There's a migration guide in case you are affected by this.
  • Changed the existing functionality so that saving a model that hasn't changed will not update its updated_at attribute: #1798. Checkout the migration guide in case you are affected by this.


  • Make collections iterable using for ... of loops: #1830
  • Add row-level locking options: #1810

Bug fixes

  • Return clones of nested objects in previousAttributes(): #1876
  • Fix incorrect rowCount value when using groupBy with fetchPage(): #1852
  • Fix eager loading of relations when using parse/format: #1838
  • Fix inability to install bookshelf from git commit: #1835
  • Fix timestamp() setting a key named "null" in some cases: #1820
  • Fix performance of including relationships: #1800

Test Suite

  • Add test to check for adding withRelated inside events: #1853
  • Add Node.js 10 to the Travis config: #1829
  • Fix incorrect output ordering in tests in some cases: #1825


  • Change the JSDoc theme to add a Guides section (this was already released): #1909
  • Fix hasOne's doc: #1890
  • Fix many-to-many tutorial code: #1888
  • Add code syntax highlighting for tutorials: #1850
  • Fix a few issues with the collection documentation: #1836
  • Fix Model.load() relations param: #1834
  • Fix incorrect docs for collection:fetching event: #1831
  • Add note on needing the Pagination plugin to use fetchPage(): #1803
  • Fix incorrect data types and undocumented Model property: #1797


  • Replace turbocolor with colorette: #1904
  • Use prettier to format all js and json files: #1883
  • Replace chalk with turbocolor: #1878
  • Update some insecure dependencies: #1841
  • Replace Babel with Node 4 compatible JavaScript: #1835
  • Update sinon to the latest version: #1833


March 26, 2018

Potentially breaking changes

  • Saving a model that hasn't changed will not update its updated_at attribute. This was included in a patch release because the chances of any applications depending on this behavior are very small: #1798

Bug fixes

  • Clean up automatic timestamps feature: #1798


  • Expand documentation of the automatic timestamps feature: #1798


March 23, 2018

Bug fixes

  • Fix timestamps set with Invalid Date in some cases: #1796


  • Fix incorrect data types and undocumented Model#defaults property: #1797


March 18, 2018

Breaking changes

  • Make require: true the default when deleting models: #1779
  • Remove the second argument to the model's destroyed event handler: #1777
  • Events are now triggered sequentially even when the handlers execute asynchronous code: #1768
  • Drop support for Node versions older than 4: #1696
  • Reorder saving and creating events to reflect the documentation: #1142


  • Only request returning attribute if client supports returning: #1770
  • Throw error if user doesn't pass a valid Knex instance on initialize: #1756
  • Add parameterized virtual properties to virtuals plugin: #1755
  • Add individual attribute processor plugin to core: #1741
  • Format idAttribute on save and delete: #1680
  • Add withSchema option to all database operations: #1638
  • Add a case converter plugin to core: #1093

Bug fixes

  • Fix inconsistent timestamp values between save and fetch: #1784
  • Set if attributes being .set() contain a parsed version of idAttribute: #1760
  • Fix pagination plugin's fetchPage() ignoring or hanging with transactions: #1625
  • Fix fetchPage() from pagination plugin not working for relation collections: #1561
  • Don't try to update idAttribute if it hasn't changed: #1260

Test suite

  • Increase timeout of the large arrays test: #1778
  • Add test to verify that parentId is not undefined when using fetchAll with relations: #1769
  • Fixes and general improvements to the test suite: #1753
  • Remove OracleDB tests: #1744
  • Fix invalid test related to dirty attributes: #1312


  • Improve docs about running tests: #1761
  • Fix typo on parse-and-format tutorial: #1748
  • Add Bookshelf Manager to list of community plugins: #1747



January 8, 2018


  • Fix incorrect value of second argument to model event handlers: #1723
  • Fix incorrect return value from .detach(): #1720
  • Fix incorrect return value from model.has(): #1712
  • Fix fetching:collection and fetched:collection not being generated or visible on the navigation bar: #1114
  • Update contributing document and issue templates: #1736
  • Add more information and links to Parse and Format docs: #1727
  • Add bookshelf-ez-fetch to Community Plugins: #1708
  • Add bookshelf-default-select to Community Plugins: #1706
  • Add information and examples about calling super() on model's initialize(): #1529
  • Add npm version badge to readme: f4dd792

Bug fixes

  • Fix inability to attach belongsToMany relation to models fetched with fetchAll(): #1716
  • Fix foreign key = 0 not fetching related object: #1639
  • Fix unparsed previousAttributes for related models: #1457



November 27, 2017
  • Skip visibility-plugin hidden and visible attributes #1699.
    • Used w/ <model>.toJSON({ visibility: false })
  • Updated knex peer dependency version to 0.14.x #1694.
  • Documentation typo fixes #1693.
  • Now caching node_modules to speed up travis-ci builds #1695.
  • Use Docker containers for test runs #1674.
  • Make postpublish work regardless of git remote config #1697.


November 15, 2017
  • Fixed regression #1691: File missing on postinstall
    • npm postinstall script can be run as a part of npm prepublish script.


November 15, 2017
  • Moved .babelrc -> src/.babelrc #1470
  • Timestamp on save now utilizes a date option for timestamp updates on insert and update. #1592
    • Used in options on save like so:{item: 'test'}, { date: dateInThePast })
  • Added morphValues for morphTo relation. #1326
  • Added ability to also set timestamps as model attributes in save.
  • Removed non-production files from packaging / added them to .npmignore #1679
  • Development Facing:
    • Oracle tests only run when oracle is installed.
    • Refactoring on the registry plugin.
    • Updated a lot of documents related to repo organization.


July 17, 2017
  • Allow knex 0.13.x.
  • Use uuid instead of node-uuid.
  • Test Bookshelf with Node v7.
  • Updated Author info in package.json.
  • Remove lodash from build script.
  • Add OracleDB integration tests.
  • Add opportunity to override visible and hidden behavior for toJSON function.
  • Do not load belongsTo if foreignKey is null.
  • Optimise timestamp function: respect updated_at/created_at being part of the query.
  • Fix fetchPage on Collection (pagination plugin).
  • Fixing virtuals when omitNew=true.
  • Lot's of typo fixes and documentation updates.


January 21, 2017
  • Drop Node support for 0.10 and 0.12.
  • Trigger creating event for attached models.
  • Add support for uninstantiated models relations.
  • Add foreignKeyTarget to relation methods.


September 22, 2016
  • Fixes memory leak introduced in 0.10.0 caused by binding this.listeners in triggerThen.
  • Fixes Bluebird warning when a Promise was internally rejected with a non-error.


September 14, 2016
  • Allows using knex 0.12 as a peerDependency.
  • knex instance used by bookshelf may be swapped out.


June 29, 2016

Breaking Changes

  • Removal/renaming of certain lodash functions from Model and Collection that were removed in lodash 4:
    • Collection Methods
      • removed CollectionBase#collect => use CollectionBase#map instead
      • removed CollectionBase#foldl => use CollectionBase#reduce instead
      • removed CollectionBase#inject => use CollectionBase#reduce instead
      • removed CollectionBase#foldr => use CollectionBase#reduceRight instead
      • removed CollectionBase#detect => use CollectionBase#find instead
      • removed CollectionBase#select => use CollectionBase#filter instead
      • removed CollectionBase#all => use CollectionBase#every instead
      • removed CollectionBase#any => use CollectionBase#some instead
      • removed CollectionBase#include => use CollectionBase#includes instead
      • removed CollectionBase#contains => use CollectionBase#includes instead
      • removed CollectionBase#rest => use CollectionBase#tail instead
      • renamed CollectionBase#invoke => CollectionBase#invokeMap
      • split CollectionBase#max into CollectionBase#maxBy - see the lodash docs for more explanation
      • split CollectionBase#min into CollectionBase#minBy - see the lodash docs for more explanation
    • Model Methods
      • renamed ModelBase#pairs => ModelBase#toPairs

Other changes

  • Update to Lodash 4. #1287
  • Registry plugin: Better support for custom relations. #1294


May 15, 2016
  • Add pagination plugin. #1183
  • Fire {@link Model#event:fetched} on eagerly loaded relations. #1206
  • Correct cloning of {@link Model#belongsToMany} decorated relations. #1222
  • Update Knex to 0.11.x. #1227
  • Update minimum lodash version. #1230


April 3, 2016
  • Include babel-runtime as a dependency. #1188


April 3, 2016
  • Bugfix: Restore support for camelCase and colon:separated event names. #1184


February 17, 2016
  • Permit up to Knex 0.11.0 via peerDependencies.
  • Model.forge works for ES6 classes. #924
  • Fix Collection#count for hasMany relations. #1115


November 4, 2015
  • {@link Events#off} can now unregister multiple methods at once. #983
  • Permit Knex 0.10.0 via peerDependencies. #998


November 1, 2015
  • Repo no longer includes built source or generated documentation. Release script updated to include these only in the tagged release commit. #950.
  • {@link Model#previous} returned undefined instead of null for non-existent attributes.
  • Update tests and documentation to confirm that null (rather than undefined) is returned from {@link Model#fetch} and {@link Collection#fetchOne}.
  • Fix error in virtuals plugin - #936
  • Correct error updating parsed/formatted {@link Model#idAttribute} after successful insert operation. #955
  • Many documentation fixes.


August 20, 2015
  • ES6/7: Move code base to /src — code is now compiled into /lib via Babel.
  • Add collection.count, model.count and Model.count.
  • Add model.refresh. #796
  • Prevent fetch and refresh from trying to add JSON attributes to a where clause. #550 #778
  • Virtuals plugin now supports {patch: true} argument to #542
  • Restored model.clone and collection.clone, which were not previously working. #744
  • Allow bookshelf.Collection to be modified and extended by plugins (so that relations and fetchAll operations will return the extended instance). #681 #688
  • Fix model.timestamps behavior which deviated from documentation. Also ensure that createdAt is set when {method: "insert"} is passed explicitly. #787
  • Calling create on a through relationship no longer tries to make a pivot object. Previously this would attempt to create an object with invalid foreign keys. #768
  • Parse foreign keys set during create in a relation. #770


May 12, 2015
  • Fix for regression in initialize not being called in Collection constructor, #737.
  • Fix for regression, removing omitPivot in 0.8 #721
  • Added serialize, a method which contains toJSON logic for easier customization.


May 1, 2015
  • Dropped Backbone dependency.
  • More specific errors throughout, #522
  • Support {require: true} for model.destroy #617
  • Add lifecycle events on pivot models for belongsToMany, .through #578
  • Allows for select/column calls in the query builder closure, #633.
  • Added per-constructor error classes #694 (note: this will not work in CoffeeScript).

Breaking Changes

  • Removed the __super__ internal property on the constructor, this shouldn't have been something you were relying on anyway.


October 28, 2014
  • Fix for regression in columns / eager fetch query constraints, (#510).


October 28, 2014
  • Timestamp created_at is now saved with any insert.
  • Fix for regression created by #429.
  • New events, attaching, attached, detaching, detached #452.
  • Ability to specify custom column names in morphTo, #454
  • Fix for stack overflow with model list as arguments, #482
  • Modified location of eager fetch query constraints internally.


July 23, 2014
  • Fix for formatting on polymorphic keys, (#429).
  • Added a resolve method for specifying a custom resolver function for the registry plugin.


June 29, 2014
  • Add omitPivot flag on toJSON options for omitting the _pivot_ keys in through and belongsToMany relations (#404).


June 23, 2014
  • Fix missing NotFoundError & EmptyError on Model & Collection, respectively (#389, #399).


June 18, 2014
  • Added bookshelf.model(name, protoProps, [staticProps]) syntax for registry plugin.


June 17, 2014
  • Fix for collection dropping models early in set, #376.


June 12, 2014
  • Pass a cloned copy of the model's attributes to format rather than the original, related to #315.


June 10, 2014
  • Ensure the knex version >= 0.6.10, where a major regression affecting column names was fixed.


June 9, 2014
  • Added {@link Model#fetchAll}, for fetching a collection of models from a model.
  • Added {@link Model#where}, as a shortcut for the most commonly used {@linkplain Model#query query method}.
  • Initializing via a plain options object is deprecated, you must now pass in an initialized knex instance.
  • Adding typed errors (#221).
  • Upgrade to support knex 0.6.x


June 5, 2014
  • Fix for eager loaded belongsTo relation bug with custom parse/format (#377).


June 4, 2014
  • Temporarily add knex to peerDependencies until 0.7 is released to support knex 0.6 and there exists a better internal method of doing a semver check.
  • Fix for belongsTo relation bug (#353).


April 3, 2014
  • Bumping dependencies, including upgrading to Bluebird 1.2, trigger-then 0.3, fixing an erroneous "unhandledRejection" (#310).
  • fetchOne properly resets the query on the collection, (#300).


April 3, 2014
  • Only prefix model fields with the "tableName" after format has been called, (#308).


March 6, 2014
  • Virtuals plugin may now accept a hash of attributes to set.
  • Properly fix issue addressed in 0.6.7.


March 2, 2014
  • Bugfix for edge case for eager loaded relations and relatedData settings.


March 1, 2014
  • Bugfix for registry plugin, resolving correct models for "through" relations. (#260)


February 28, 2014
  • Added {@link Collection#reduceThen} as a passthrough to Bluebird's "reduce" method with models.
  • Options are now passed to "plugin" method. (#254)
  • Bugfix for registry plugin. (#259)


February 11, 2014
  • Adds static method {@link Model.collection Model.collection()} as a shortcut for creating a collection with the current model.


February 9, 2014
  • Added anRelation#updatePivot method for updating tables on a "belongsToMany" relation. (#134, #230)
  • Allow mutating the options for passing constraints to eager loaded relations. (#151)
  • All keys of an object passed into sync are properly prefixed before sync. (#177)
  • Clearer error messages for debugging. (#204, #197)
  • Fixed error message for updates that don't affect rows. (#228)
  • Group by the correct key on "belongsTo.through" relations. (#214)
  • Ability to only use created_at or updated_at as timestamp properties. (#158)
  • Numerous documentation corrections, clarifications, enhancements.
  • Bumped Bluebird dependency to ~1.0.0.


  • Added the registry plugin for registering models as strings, helping with the circular dependency problem.
  • Added the virtuals plugin for getting/setting virtual (computed) properties on the model.
  • Added the visibility plugin for specifying a whitelist/blacklist of keys when a model is serialized with toJSON.


December 18, 2013
  • Debug may now be passed as an option in any sync method, to log queries, including relations.
  • Save now triggers an error in updates with no affected rows. (#119)
  • The attribute is only set on insert if it's empty. (#130)
  • Ensure eager loaded relations can use attach/detach. (#120)


November 26, 2013
  • Fixes bug with promise code and saving event firing, where promises are not properly resolved with ".all" during saving events.


November 25, 2013
  • Updating dependency to knex.js 0.5.x.
  • Switched from when.js to bluebird for promise implementation, with shim for backward compatibility.
  • Switched from underscore to lodash, for semver reliability.


November 24, 2013
  • Parse models after all relations have been eager loaded, for appropriate column name matching (thanks @benesch) (#97)
  • Specify table for withRelated fetches to prevent column naming conflicts (#96).
  • Fix for polymorphic relation loading (#95).
  • Other documentation tweaks and other internal code cleanup.


October 11, 2013
  • The "fetching" event is now fired on eager loaded relation fetches.


October 10, 2013
  • The options.query now contains the appropriate knex instance during the "fetching" event handler.


October 1, 2013
  • An eager loaded morphTo relation may now have child relations nested beneath it that are properly eager loaded, depending on the parent.


October 1, 2013
  • Fix issue where the relatedData context was not appropriately maintained for subsequent {@link Collection#create} calls after an eager load (#77).
  • Documentation improvements, encouraging the use of {@link Model#related} rather than calling a relation method directly, to keep association with the parent model's {@link Model#relations relations} hash.


September 26, 2013
  • The columns explicitly specified in a fetch are no-longer passed along when eager loading relations, fixes (#70).


September 22, 2013
  • Fixed incorrect eager loading in belongsTo relations (#65).


September 21, 2013
  • Fixed incorrect eager loading in hasOne relations (#63).


September 20, 2013

Major Breaking Changes

  • Global state is no longer stored in the library, an instance is returned from Bookshelf.initialize, so you will need to call this once and then reference this Bookshelf client elsewhere in your application.
  • Lowercasing of bookshelf.initialize, bookshelf.knex, bookshelf.transaction.
  • During the lifecycle events, such as "fetching", "saving", or "destroying", the model no-longer contains the active query builder instance at the time it is saved. If you need to modify the query builder chain inside of an event handler, you may now use options.query inside the event handlers.

Other changes

  • Added tableName for all queries, so joins use the correct id (#61).
  • The attach & detach now remove models from the associated collection, as appropriate (#59).
  • A withPivot no longer accepts an object to specify the keys for the returned pivot items, if you wish to specify how these pivot objects are defined on the object, a custom toJSON is your best bet.
  • Added {@link Collection#invokeThen} and {@link Collection#mapThen} as convenience helpers for Promise.all(collection.invoke(method, args*)) and Promise.all(, iterator, [context])), respectively.
  • Added a Bookshelf.plugin method, for a standard way to extend Bookshelf instances.
  • A re-written modular architecture, to move the library toward becoming a database agnostic "data mapper" foundation, with the ablitiy to form relations between different data stores and types, not just SQL (although SQL is the primary focus for now). Also, support for AMD, for eventual use outside of Node.js runtime (with webSQL and likewise).


August 29, 2013
  • Docs
  • Fixed regression in belongsToMany custom column name order.


August 28, 2013
  • Support for a {@link Model#through} clause on various model relations.
  • Creating a model from a related collection maintains the appropriate relation data (#35).
  • Support for a {patch: true} flag on save, to only update specific saved attributes.
  • Added a fetchOne method, for pulling out a single model from a collection, mostly useful for related collection instances.
  • Updated to Knex "0.2.x" syntax for insert / returning.
  • Ability to specify a morphValue on {@link Model#morphOne} or {@link Model#morphMany} relations.
  • Internal refactor of relations for more consistent behavior.


August 26, 2013
  • Some minor fixes to make the Sync methods more consistent in their behavior when called directly, (#53).


August 21, 2013
  • Timestamp for created_at is not set during an "update" query, and the update where clause does not include the idAttribute if it isn't present (#51).


August 21, 2013
  • Fixes bug with query function feature added in 0.2.5, mentioned in (#51).


August 19, 2013
  • The {@link Model#query} method may now accept a function, for even more dynamic query building (#45).
  • Fix for relations not allowing 0 as a valid foreign key value (#49).


July 30, 2013
  • More consistent query resetting, fixing query issues on post-query event handlers.
  • The toJSON is only called on a related model if the method exists, allowing for objects or arrays to be manually specified on the relations hash and serialized properly on the parent's toJSON.


July 7, 2013
  • Fixing bug where triggerThen wasn't actually being used for several of the events as noted in 0.2.1 release.


July 2, 2013
  • The Model's related method is now a no-op if the model doesn't have the related method.
  • Any withPivot columns on many-to-many relations are now prefixed with _pivot rather than pivot unless named otherwise, for consistency.
  • The _reset is not called until after all triggered events so that hasChanged can be used on the current model state in the "created", "updated", "saved", and "destroyed" events.
  • Eager queries may be specified as an object with a function, to constrain the eager queries:
user.fetch({withRelated: ['accounts', {
'accounts.settings': function(qb) { qb.where('status', 'enabled'); }
}, 'other_data']}).then(...


June 26, 2013
  • Using triggerThen instead of trigger for "created", "updated", "saved", "destroyed", and "fetched" events - if any async operations are needed after the model is created but before resolving the original promise.


June 24, 2013
  • Resolve Model's fetch promise with null rather than undefined.
  • An object of query constraints (e.g. {where: {...}, orWhere: {...}}may be passed to the query method (#30).
  • Fix for empty eager relation responses not providing an empty model or collection instance on the model.relations object.


June 19, 2013
  • Resolve Model's fetch promise with undefined if no model was returned.
  • An array of "created at" and "updated at" values may be used for hasTimestamps.
  • Format is called on the Model#fetch method.
  • Added an exec plugin to provide a node callback style interface for any of the promise methods.


June 18, 2013
  • Added support for polymorphic associations, with morphOne, morphMany, and morphTo model methods.


June 15, 2013
  • Bugfix where detach may be used with no parameters to detach all related items (#19).


June 15, 2013
  • Fixing bug allowing custom idAttribute values to be used in eager loaded many-to-many relations (#18).


June 11, 2013
  • Ensuring each of the _previousAttribute and changed values are properly reset on related models after sync actions.


June 10, 2013
  • Fixing issue with idAttribute not being assigned after database inserts.
  • Removing various aliases {@link Events} methods for clarity.


June 10, 2013
  • Added {@link Model#hasChanged}, {@link Model#previous}, and {@link Model#previousAttributes} methods, for getting the previous value of the model since the last sync.
  • Using Object.create(null) for various internal model objects dealing with user values.
  • Calling {@link Model#related} on a model will now create an empty related object if one is not present on the relations object.
  • Removed the {patch: true} option on save, instead only applying defaults if the object isNew, or if {defaults: true} is passed.
  • Fix for model.clone's relation responses.


May 17, 2013
  • Added triggerThen and emitThen for promise based events, used internally in the "creating", "updating", "saving", and "destroying" events.
  • Docs updates, fixing {patch: true} on update to have intended functionality.
  • A model's toJSON is now correctly called on any related properties.


May 16, 2013
  • Fixed bug with eager loaded belongsTo relations (#14).


May 13, 2013
  • Initial Bookshelf release.