UNPKG

bookshelf-returning

Version:

Bookshelf plugin for adding returning clause to insert/update queries

99 lines (77 loc) 3.17 kB
/*! * Bookshelf-Returning * * Copyright 2016-2018 Josh Swan * Released under the MIT license * https://github.com/joshswan/bookshelf-returning/blob/master/LICENSE */ const Promise = require('bluebird'); const assign = require('lodash/assign'); const extend = require('lodash/extend'); const filter = require('lodash/filter'); function handleResponse(resp, syncing, options) { if (options.returning) { // Check for require option and empty result, return 0 to trigger NoRows__Error if (options.method !== 'insert' && options.require !== false && !resp.length) return 0; // Save previous attributes // eslint-disable-next-line no-multi-assign, no-underscore-dangle options.previousAttributes = syncing._previousAttributes = syncing.attributes; if (typeof resp[0] === 'object') { // Assign returned values to attributes syncing.attributes = assign({}, syncing.parse(syncing.attributes), syncing.parse(resp[0])); // Update model's ID syncing.id = syncing.attributes[syncing.idAttribute] || syncing.id; } } // Return raw database result return resp; } module.exports = (bookshelf) => { const ModelBase = bookshelf.Model; bookshelf.Model = ModelBase.extend({ // Override sync insert & update methods to implement options.returning sync(...args) { const sync = ModelBase.prototype.sync.apply(this, args); sync.insert = Promise.method(function syncInsert() { const { options, query, syncing, } = this; const attributes = syncing.format(extend(Object.create(null), syncing.attributes)); return query.insert(attributes, options.returning || syncing.idAttribute) .then(resp => handleResponse(resp, syncing, options)); }); sync.update = Promise.method(function syncUpdate(attrs) { const { options, query, syncing, } = this; if (syncing.id != null) query.where(syncing.format({ [syncing.idAttribute]: syncing.id })); // eslint-disable-next-line no-underscore-dangle if (filter(query._statements, { grouping: 'where' }).length === 0) { throw new Error('A model cannot be updated without a "where" clause or an idAttribute.'); } const attributes = syncing.format(extend(Object.create(null), attrs)); return query.update(attributes, options.returning || null) .then(resp => handleResponse(resp, syncing, options)); }); sync.del = Promise.method(function syncDelete() { const { options, query, syncing, } = this; if (syncing.id != null) query.where(syncing.format({ [syncing.idAttribute]: syncing.id })); // eslint-disable-next-line no-underscore-dangle if (filter(query._statements, { grouping: 'where' }).length === 0) { throw new Error('A model cannot be destroyed without a "where" clause or an idAttribute.'); } return query.del(options.returning || null) .then(resp => handleResponse(resp, syncing, options)); }); return sync; }, }); };