docs/api.html
The Bookshelf library is initialized by passing an initialized Knex client instance. The knex documentation provides a number of examples for different databases.
knex``Knex Knex instance.
A reference to the Knex.js instance being used by Bookshelf.
// Defining and registering a model
module.exports = bookshelf.model('Customer', {
tableName: 'customers',
orders() {
return this.hasMany('Order')
}
})
// Retrieving a previously registered model
const Customer = bookshelf.model('Customer')
// Registering already defined models
// file: customer.js
const Customer = bookshelf.Model.extend({
tableName: 'customers',
orders() {
return this.hasMany('Order')
}
})
module.exports = bookshelf.model('Customer', Customer)
// file: order.js
const Order = bookshelf.Model.extend({
tableName: 'orders',
customer() {
return this.belongsTo('Customer')
}
})
module.exports = bookshelf.model('Order', Order)
name``string The name to save the model as, or the name of the model to retrieve if no further arguments are passed to this method.
[Model]``Model|Object The model to register. If a plain object is passed it will be converted to a Model. See example above.
[staticProperties]``Object If a plain object is passed as second argument, this can be used to specify additional static properties and methods for the new model that is created.
Model
The registered model.
Registers a model. Omit the second argument Model to return a previously registered model that matches the provided name.
Note that when registering a model with this method it will also be available to all relation methods, allowing you to use a string name in that case. See the calls to hasMany() in the examples above.
plugin``string|array|function The plugin or plugins to load. If you provide a string it can represent an npm package or a file somewhere on your project. You can also pass a function as argument to add it as a plugin. Finally, it's also possible to pass an array of strings or functions to add them all at once.
options``mixed This can be anything you want and it will be passed directly to the plugin as the second argument when loading it.
Bookshelf
The bookshelf instance for chaining.
This method provides a nice, tested, standardized way of adding plugins to a Bookshelf instance, injecting the current instance into the plugin, which should be a module.exports.
You can add a plugin by specifying a string with the name of the plugin to load. In this case it will try to find a module. It will pass the string to require(), so you can either require a third-party dependency by name or one of your own modules by relative path:
bookshelf.plugin('./bookshelf-plugins/my-favourite-plugin');
bookshelf.plugin('plugin-from-npm');
There are a few official plugins published in npm, along with many independently developed ones. See the list of available plugins.
You can also provide an array of strings or functions, which is the same as calling bookshelf.plugin() multiple times. In this case the same options object will be reused:
bookshelf.plugin(['cool-plugin', './my-plugins/even-cooler-plugin']);
Example plugin:
// Converts all string values to lower case when setting attributes on a model
module.exports = function(bookshelf) {
bookshelf.Model = bookshelf.Model.extend({
set(key, value, options) {
if (!key) return this
if (typeof value === 'string') value = value.toLowerCase()
return bookshelf.Model.prototype.set.call(this, key, value, options)
}
})
}
const Customer = bookshelf.model('Customer', {
tableName: 'customers'
})
bookshelf.resolve = (name) => {
if (name === 'SpecialCustomer') return Customer;
}
name``string The model name to resolve.
*
The return value will depend on what your re-implementation of this function does.
Override this in your bookshelf instance to define a custom function that will resolve the location of a model or collection when using the Bookshelf#model method or when passing a string with a model name in any of the collection methods (e.g. Model#hasOne, Model#hasMany, etc.).
This will only be used if the specified name cannot be found in the registry. Note that this function can return anything you'd like, so it's not restricted in functionality.
var Promise = require('bluebird')
Bookshelf.transaction((t) => {
return new Library({name: 'Old Books'})
.save(null, {transacting: t})
.tap(function(model) {
return Promise.map([
{title: 'Canterbury Tales'},
{title: 'Moby Dick'},
{title: 'Hamlet'}
], (info) => {
return new Book(info).save({'shelf_id': model.id}, {transacting: t})
})
})
}).then((library) => {
console.log(library.related('books').pluck('title'))
}).catch((err) => {
console.error(err)
})
transactionCallback``Bookshelf~transactionCallback Callback containing transaction logic. The callback should return a Promise.
Promise
A promise resolving to the value returned from transactionCallback.
An alias to Knex#transaction. The transaction object must be passed along in the options of any relevant Bookshelf calls, to ensure all queries are on the same connection. The entire transaction block is wrapped around a Promise that will commit the transaction if it resolves successfully, or roll it back if the Promise is rejected.
Note that there is no need to explicitly call transaction.commit() or transaction.rollback() since the entire transaction will be committed if there are no errors inside the transaction block.
When fetching inside a transaction it's possible to specify a row-level lock by passing the wanted lock type in the lock option to fetch. Available options are lock: 'forUpdate' and lock: 'forShare'.
transaction``Transaction See
Promise
The Promise will resolve to the return value of the callback, or be rejected with an error thrown inside it. If it resolves, the entire transaction is committed, otherwise it is rolled back.
This is a transaction block to be provided to Bookshelf#transaction. All of the database operations inside it can be part of the same transaction by passing the transacting: transaction option to fetch, save or destroy.
Note that unless you explicitly pass the transaction object along to any relevant model operations, those operations will not be part of the transaction, even though they may be inside the transaction callback.