bookshelf-json-columns
Version:
Parse JSON columns with Bookshelf.js
130 lines (102 loc) • 3.66 kB
JavaScript
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
/**
* Stringify JSON columns.
*/
function stringify(model, attributes, options) {
// Mark json columns as stringfied.
options.parseJsonColumns = true;
this.constructor.jsonColumns.forEach(column => {
if (this.attributes[column]) {
this.attributes[column] = JSON.stringify(this.attributes[column]);
}
});
}
/**
* Parse JSON columns.
*/
function parse(model, response) {
let options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
// Do not parse on `fetched` event after saving.
// eslint-disable-next-line no-underscore-dangle
if (!options.parseJsonColumns && options.query && options.query._method !== 'select') {
return;
}
this.constructor.jsonColumns.forEach(column => {
const value = this.attributes[column];
if (value && typeof value === 'string') {
this.attributes[column] = JSON.parse(value);
}
});
}
/**
* Export `bookshelf-json-columns` plugin.
*/
exports.default = Bookshelf => {
const Model = Bookshelf.Model.prototype;
const client = Bookshelf.knex.client.config.client;
const parseOnFetch = client === 'sqlite' || client === 'sqlite3' || client === 'mysql';
Bookshelf.Model = Bookshelf.Model.extend({
initialize: function initialize() {
if (!this.constructor.jsonColumns) {
return Model.initialize.apply(this, arguments);
}
// Stringify JSON columns before model is saved.
this.on('saving', stringify.bind(this));
// Parse JSON columns after model is saved.
this.on('saved', parse.bind(this));
if (parseOnFetch) {
// Parse JSON columns after model is fetched.
this.on('fetched', parse.bind(this));
}
return Model.initialize.apply(this, arguments);
},
save: function save(key, value, options) {
if (!this.constructor.jsonColumns) {
return Model.save.apply(this, arguments);
}
// Handle arguments as Bookshelf.
let attributes;
if (key === null || typeof key === 'object') {
attributes = key || {};
options = value ? _extends({}, value) : {};
} else {
(attributes = {})[key] = value;
options = options ? _extends({}, options) : {};
}
// Only handle arguments with `patch` option.
if (!options.patch) {
return Model.save.apply(this, arguments);
}
// Stringify JSON columns.
Object.keys(attributes).forEach(attribute => {
if (this.constructor.jsonColumns.indexOf(attribute) !== -1 && attributes[attribute]) {
attributes[attribute] = JSON.stringify(attributes[attribute]);
}
});
return Model.save.call(this, attributes, options);
}
});
if (!parseOnFetch) {
return;
}
const Collection = Bookshelf.Collection.prototype;
Bookshelf.Collection = Bookshelf.Collection.extend({
initialize: function initialize() {
if (!this.model.jsonColumns) {
return Collection.initialize.apply(this, arguments);
}
// Parse JSON columns after collection is fetched.
this.on('fetched', collection => {
collection.models.forEach(model => {
parse.apply(model);
});
});
return Collection.initialize.apply(this, arguments);
}
});
};
module.exports = exports['default'];