bookshelf-jsonapi-params
Version:
Automatically applies relations, filters, and more from the JSON API spec to your Bookshelf.js results
128 lines (108 loc) • 18.8 kB
JavaScript
;var _lodash = require('lodash');function _toConsumableArray(arr) {if (Array.isArray(arr)) {for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) {arr2[i] = arr[i];}return arr2;} else {return Array.from(arr);}}
// Output postgres compliant query stub that accesses a property of a jsonb column
var pgAttributeChain = function pgAttributeChain(column, jsonColumn, dataType) {var _ref = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {},_ref$includeAs = _ref.includeAs,includeAs = _ref$includeAs === undefined ? false : _ref$includeAs;
var propertyChain = jsonColumn.split('.');
var bindings = [column].concat(_toConsumableArray(propertyChain));
var sanitizedDataType = null;
if (dataType === 'numeric') {
sanitizedDataType = 'numeric';
} else
if (dataType === 'date') {
sanitizedDataType = 'date';
} else
if (dataType === 'timestamp') {
sanitizedDataType = 'timestamp';
}
var jsonSQL = '??#>>\'{' + propertyChain.map(function () {return '??';}).join(',') + '}\'';
if (sanitizedDataType) {
jsonSQL = '(' + jsonSQL + ')::' + sanitizedDataType;
}
if (includeAs) {
jsonSQL = jsonSQL + ' as ??';
// for JSONB, the leaf attribute of the object access is the column name
bindings.push(propertyChain[propertyChain.length - 1]);
}
return { jsonSQL: jsonSQL, bindings: bindings };
};
var equalityJsonFilter = function equalityJsonFilter(jsonSQL, values, hasNull, qb, bindings, knex) {var whereType = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : 'where';
var rawQueryStringWithBindings = jsonSQL + ' in (' + values.map(function () {return '?';}).join(',') + ')';
if (hasNull) {
qb[whereType](function (qbWhere) {
// Clone the bindings array to avoid sharing the same array with the orWhere below
qbWhere.whereRaw(jsonSQL + ' is null', [].concat(_toConsumableArray(bindings)));
if (!(0, _lodash.isEmpty)(values)) {
qbWhere.orWhere(knex.raw(rawQueryStringWithBindings, [].concat(_toConsumableArray(bindings), _toConsumableArray(values))));
}
});
} else
{
qb[whereType + 'Raw'](rawQueryStringWithBindings, [].concat(_toConsumableArray(bindings), _toConsumableArray(values)));
}
};
module.exports.buildFilterWithType = function (_ref2) {var nullString = _ref2.nullString,qb = _ref2.qb,knex = _ref2.knex,filterType = _ref2.filterType,values = _ref2.values,column = _ref2.column,jsonColumn = _ref2.jsonColumn,dataType = _ref2.dataType,extraEqualityFilterValues = _ref2.extraEqualityFilterValues;var _pgAttributeChain =
pgAttributeChain(column, jsonColumn, dataType),jsonSQL = _pgAttributeChain.jsonSQL,bindings = _pgAttributeChain.bindings;
// Remove all null and 'null' from the values array. If the length is different after removal, there were nulls
var hasNull = values.length !== (0, _lodash.pull)(values, null, nullString).length;
if (filterType === 'equal') {
equalityJsonFilter(jsonSQL, values, hasNull, qb, bindings, knex);
} else
if (filterType === 'like') {
qb.where(function (qbWhere) {
var where = 'where';
(0, _lodash.forEach)(values, function (value) {
var subBindings = [].concat(_toConsumableArray(bindings), ['%' + value + '%']);
qbWhere[where](knex.raw('(' + jsonSQL + ')::text ilike ?', subBindings));
// Change to orWhere after the first where
if (where === 'where') {
where = 'orWhere';
}
});
/// Handle if key is also in equality filter
if (extraEqualityFilterValues) {
var extraHasNull = extraEqualityFilterValues.length !== (0, _lodash.pull)(extraEqualityFilterValues, null, nullString).length;
equalityJsonFilter(jsonSQL, extraEqualityFilterValues, extraHasNull, qbWhere, bindings, knex, 'orWhere');
}
});
} else
if (filterType === 'not') {
if (hasNull) {
qb.whereRaw(jsonSQL + ' is not null', bindings);
}
if (!(0, _lodash.isEmpty)(values)) {
bindings.push.apply(bindings, _toConsumableArray(values));
qb.whereRaw(jsonSQL + ' not in (' + values.map(function () {return '?';}).join(',') + ')', bindings);
}
}
// All other filter types, the values is expected to NOT be an array. This follows the logic in the main index file.
else if (filterType === 'gt') {
bindings.push.apply(bindings, _toConsumableArray(values));
qb.whereRaw(jsonSQL + ' > ?', bindings);
} else
if (filterType === 'gte') {
bindings.push.apply(bindings, _toConsumableArray(values));
qb.whereRaw(jsonSQL + ' >= ?', bindings);
} else
if (filterType === 'lt') {
bindings.push.apply(bindings, _toConsumableArray(values));
qb.whereRaw(jsonSQL + ' < ?', bindings);
} else
if (filterType === 'lte') {
bindings.push.apply(bindings, _toConsumableArray(values));
qb.whereRaw(jsonSQL + ' <= ?', bindings);
}
};
module.exports.buildSelect = function (qb, knex, column, jsonColumn, dataType) {
// TODO: aggregate functions count, sum, avg, max, min
var _pgAttributeChain2 = pgAttributeChain(column, jsonColumn, dataType, { includeAs: true }),jsonSQL = _pgAttributeChain2.jsonSQL,bindings = _pgAttributeChain2.bindings;
qb.select(knex.raw(jsonSQL, bindings));
};
module.exports.buildSort = function (qb, sortType, column, jsonColumn, dataType) {
// Ensure that the sort direction can not be injected
var sanitizedSortType = 'asc';
if (sortType === 'desc') {
sanitizedSortType = 'desc';
}var _pgAttributeChain3 =
pgAttributeChain(column, jsonColumn, dataType),jsonSQL = _pgAttributeChain3.jsonSQL,bindings = _pgAttributeChain3.bindings;
qb.orderByRaw(jsonSQL + ' ' + sanitizedSortType, bindings);
};
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9qc29uLWZpZWxkcy5qcyJdLCJuYW1lcyI6WyJwZ0F0dHJpYnV0ZUNoYWluIiwiY29sdW1uIiwianNvbkNvbHVtbiIsImRhdGFUeXBlIiwiaW5jbHVkZUFzIiwicHJvcGVydHlDaGFpbiIsInNwbGl0IiwiYmluZGluZ3MiLCJzYW5pdGl6ZWREYXRhVHlwZSIsImpzb25TUUwiLCJtYXAiLCJqb2luIiwicHVzaCIsImxlbmd0aCIsImVxdWFsaXR5SnNvbkZpbHRlciIsInZhbHVlcyIsImhhc051bGwiLCJxYiIsImtuZXgiLCJ3aGVyZVR5cGUiLCJyYXdRdWVyeVN0cmluZ1dpdGhCaW5kaW5ncyIsInFiV2hlcmUiLCJ3aGVyZVJhdyIsIm9yV2hlcmUiLCJyYXciLCJtb2R1bGUiLCJleHBvcnRzIiwiYnVpbGRGaWx0ZXJXaXRoVHlwZSIsIm51bGxTdHJpbmciLCJmaWx0ZXJUeXBlIiwiZXh0cmFFcXVhbGl0eUZpbHRlclZhbHVlcyIsIndoZXJlIiwidmFsdWUiLCJzdWJCaW5kaW5ncyIsImV4dHJhSGFzTnVsbCIsImJ1aWxkU2VsZWN0Iiwic2VsZWN0IiwiYnVpbGRTb3J0Iiwic29ydFR5cGUiLCJzYW5pdGl6ZWRTb3J0VHlwZSIsIm9yZGVyQnlSYXciXSwibWFwcGluZ3MiOiJhQUFBLGdDOzs7Ozs7QUFNQTtBQUNBLElBQU1BLG1CQUFtQixTQUFuQkEsZ0JBQW1CLENBQVVDLE1BQVYsRUFBa0JDLFVBQWxCLEVBQThCQyxRQUE5QixFQUFvRSxnRkFBSixFQUFJLHVCQUExQkMsU0FBMEIsQ0FBMUJBLFNBQTBCLGtDQUFkLEtBQWM7O0FBRXpGLFFBQU1DLGdCQUFnQkgsV0FBV0ksS0FBWCxDQUFpQixHQUFqQixDQUF0QjtBQUNBLFFBQU1DLFlBQVlOLE1BQVosNEJBQXVCSSxhQUF2QixFQUFOO0FBQ0EsUUFBSUcsb0JBQW9CLElBQXhCO0FBQ0EsUUFBSUwsYUFBYSxTQUFqQixFQUE0QjtBQUN4QkssNEJBQW9CLFNBQXBCO0FBQ0gsS0FGRDtBQUdLLFFB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NUIsRUFBaURoQyxRQUFqRDtBQUNILENBVEQiLCJmaWxlIjoianNvbi1maWVsZHMuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICAgIGZvckVhY2ggYXMgX2ZvckVhY2gsXG4gICAgaXNFbXB0eSBhcyBfaXNFbXB0eSxcbiAgICBwdWxsIGFzIF9wdWxsXG59IGZyb20gJ2xvZGFzaCc7XG5cbi8vIE91dHB1dCBwb3N0Z3JlcyBjb21wbGlhbnQgcXVlcnkgc3R1YiB0aGF0IGFjY2Vzc2VzIGEgcHJvcGVydHkgb2YgYSBqc29uYiBjb2x1bW5cbmNvbnN0IHBnQXR0cmlidXRlQ2hhaW4gPSBmdW5jdGlvbiAoY29sdW1uLCBqc29uQ29sdW1uLCBkYXRhVHlwZSwgeyBpbmNsdWRlQXMgPSBmYWxzZSB9ID0ge30pIHtcblxuICAgIGNvbnN0IHByb3BlcnR5Q2hhaW4gPSBqc29uQ29sdW1uLnNwbGl0KCcuJyk7XG4gICAgY29uc3QgYmluZGluZ3MgPSBbY29sdW1uLCAuLi5wcm9wZXJ0eUNoYWluXTtcbiAgICBsZXQgc2FuaXRpemVkRGF0YVR5cGUgPSBudWxsO1xuICAgIGlmIChkYXRhVHlwZSA9PT0gJ251bWVyaWMnKSB7XG4gICAgICAgIHNhbml0aXplZERhdGFUeXBlID0gJ251bWVyaWMnO1xuICAgIH1cbiAgICBlbHNlIGlmIChkYXRhVHlwZSA9PT0gJ2RhdGUnKSB7XG4gICAgICAgIHNhbml0aXplZERhdGFUeXBlID0gJ2RhdGUnO1xuICAgIH1cbiAgICBlbHNlIGlmIChkYXRhVHlwZSA9PT0gJ3RpbWVzdGFtcCcpIHtcbiAgICAgICAgc2FuaXRpemVkRGF0YVR5cGUgPSAndGltZXN0YW1wJztcbiAgICB9XG4gICAgbGV0IGpzb25TUUwgPSBgPz8jPj4neyR7cHJvcGVydHlDaGFpbi5tYXAoKCkgPT4gJz8/Jykuam9pbignLCcpfX0nYDtcbiAgICBpZiAoc2FuaXRpemVkRGF0YVR5cGUpIHtcbiAgICAgICAganNvblNRTCA9IGAoJHtqc29uU1FMfSk6OiR7c2FuaXRpemVkRGF0YVR5cGV9YDtcbiAgICB9XG4gICAgaWYgKGluY2x1ZGVBcykge1xuICAgICAgICBqc29uU1FMID0gYCR7anNvblNRTH0gYXMgPz9gO1xuICAgICAgICAvLyBmb3IgSlNPTkIsIHRoZSBsZWFmIGF0dHJpYnV0ZSBvZiB0aGUgb2JqZWN0IGFjY2VzcyBpcyB0aGUgY29sdW1uIG5hbWVcbiAgICAgICAgYmluZGluZ3MucHVzaChwcm9wZXJ0eUNoYWluW3Byb3BlcnR5Q2hhaW4ubGVuZ3RoIC0gMV0pO1xuICAgIH1cblxuICAgIHJldHVybiB7IGpzb25TUUwsIGJpbmRpbmdzIH07XG59O1xuXG5jb25zdCBlcXVhbGl0eUpzb25GaWx0ZXIgPSBmdW5jdGlvbiAoanNvblNRTCwgdmFsdWVzLCBoYXNOdWxsLCBxYiwgYmluZGluZ3MsIGtuZXgsIHdoZXJlVHlwZSA9ICd3aGVyZScpIHtcblxuICAgIGNvbnN0IHJhd1F1ZXJ5U3RyaW5nV2l0aEJpbmRpbmdzID0gYCR7anNvblNRTH0gaW4gKCR7dmFsdWVzLm1hcCgoKSA9PiAnPycpLmpvaW4oJywnKX0pYDtcbiAgICBpZiAoaGFzTnVsbCkge1xuICAgICAgICBxYlt3aGVyZVR5cGVdKChxYldoZXJlKSA9PiB7XG4gICAgICAgICAgICAvLyBDbG9uZSB0aGUgYmluZGluZ3MgYXJyYXkgdG8gYXZvaWQgc2hhcmluZyB0aGUgc2FtZSBhcnJheSB3aXRoIHRoZSBvcldoZXJlIGJlbG93XG4gICAgICAgICAgICBxYldoZXJlLndoZXJlUmF3KGAke2pzb25TUUx9IGlzIG51bGxgLCBbLi4uYmluZGluZ3NdKTtcbiAgICAgICAgICAgIGlmICghX2lzRW1wdHkodmFsdWVzKSkge1xuICAgICAgICAgICAgICAgIHFiV2hlcmUub3JXaGVyZShrbmV4LnJhdyhyYXdRdWVyeVN0cmluZ1dpdGhCaW5kaW5ncywgWy4uLmJpbmRpbmdzLCAuLi52YWx1ZXNdKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgcWJbYCR7d2hlcmVUeXBlfVJhd2BdKHJhd1F1ZXJ5U3RyaW5nV2l0aEJpbmRpbmdzLCBbLi4uYmluZGluZ3MsIC4uLnZhbHVlc10pO1xuICAgIH1cbn07XG5cbm1vZHVsZS5leHBvcnRzLmJ1aWxkRmlsdGVyV2l0aFR5cGUgPSBmdW5jdGlvbiAoeyBudWxsU3RyaW5nLCBxYiwga25leCwgZmlsdGVyVHlwZSwgdmFsdWVzLCBjb2x1bW4sIGpzb25Db2x1bW4sIGRhdGFUeXBlLCBleHRyYUVxdWFsaXR5RmlsdGVyVmFsdWVzIH0pIHtcblxuICAgIGNvbnN0IHsganNvblNRTCwgYmluZGluZ3MgfSA9IHBnQXR0cmlidXRlQ2hhaW4oY29sdW1uLCBqc29uQ29sdW1uLCBkYXRhVHlwZSk7XG5cbiAgICAvLyBSZW1vdmUgYWxsIG51bGwgYW5kICdudWxsJyBmcm9tIHRoZSB2YWx1ZXMgYXJyYXkuIElmIHRoZSBsZW5ndGggaXMgZGlmZmVyZW50IGFmdGVyIHJlbW92YWwsIHRoZXJlIHdlcmUgbnVsbHNcbiAgICBjb25zdCBoYXNOdWxsID0gdmFsdWVzLmxlbmd0aCAhPT0gX3B1bGwodmFsdWVzLCBudWxsLCBudWxsU3RyaW5nKS5sZW5ndGg7XG5cbiAgICBpZiAoZmlsdGVyVHlwZSA9PT0gJ2VxdWFsJykge1xuICAgICAgICBlcXVhbGl0eUpzb25GaWx0ZXIoanNvblNRTCwgdmFsdWVzLCBoYXNOdWxsLCBxYiwgYmluZGluZ3MsIGtuZXgpO1xuICAgIH1cbiAgICBlbHNlIGlmIChmaWx0ZXJUeXBlID09PSAnbGlrZScpIHtcbiAgICAgICAgcWIud2hlcmUoKHFiV2hlcmUpID0+IHtcblxuICAgICAgICAgICAgbGV0IHdoZXJlID0gJ3doZXJlJztcbiAgICAgICAgICAgIF9mb3JFYWNoKHZhbHVlcywgKHZhbHVlKSA9PiB7XG5cbiAgICAgICAgICAgICAgICBjb25zdCBzdWJCaW5kaW5ncyA9IFsuLi5iaW5kaW5ncywgYCUke3ZhbHVlfSVgXTtcbiAgICAgICAgICAgICAgICBxYldoZXJlW3doZXJlXShrbmV4LnJhdyhgKCR7anNvblNRTH0pOjp0ZXh0IGlsaWtlID9gLCBzdWJCaW5kaW5ncykpO1xuXG4gICAgICAgICAgICAgICAgLy8gQ2hhbmdlIHRvIG9yV2hlcmUgYWZ0ZXIgdGhlIGZpcnN0IHdoZXJlXG4gICAgICAgICAgICAgICAgaWYgKHdoZXJlID09PSAnd2hlcmUnKXtcbiAgICAgICAgICAgICAgICAgICAgd2hlcmUgPSAnb3JXaGVyZSc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIC8vLyBIYW5kbGUgaWYga2V5IGlzIGFsc28gaW4gZXF1YWxpdHkgZmlsdGVyXG4gICAgICAgICAgICBpZiAoZXh0cmFFcXVhbGl0eUZpbHRlclZhbHVlcykge1xuICAgICAgICAgICAgICAgIGNvbnN0IGV4dHJhSGFzTnVsbCA9IGV4dHJhRXF1YWxpdHlGaWx0ZXJWYWx1ZXMubGVuZ3RoICE9PSBfcHVsbChleHRyYUVxdWFsaXR5RmlsdGVyVmFsdWVzLCBudWxsLCBudWxsU3RyaW5nKS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgZXF1YWxpdHlKc29uRmlsdGVyKGpzb25TUUwsIGV4dHJhRXF1YWxpdHlGaWx0ZXJWYWx1ZXMsIGV4dHJhSGFzTnVsbCwgcWJXaGVyZSwgYmluZGluZ3MsIGtuZXgsICdvcldoZXJlJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBlbHNlIGlmIChmaWx0ZXJUeXBlID09PSAnbm90Jykge1xuICAgICAgICBpZiAoaGFzTnVsbCkge1xuICAgICAgICAgICAgcWIud2hlcmVSYXcoYCR7anNvblNRTH0gaXMgbm90IG51bGxgLCBiaW5kaW5ncyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFfaXNFbXB0eSh2YWx1ZXMpKSB7XG4gICAgICAgICAgICBiaW5kaW5ncy5wdXNoKC4uLnZhbHVlcyk7XG4gICAgICAgICAgICBxYi53aGVyZVJhdyhgJHtqc29uU1FMfSBub3QgaW4gKCR7dmFsdWVzLm1hcCgoKSA9PiAnPycpLmpvaW4oJywnKX0pYCwgYmluZGluZ3MpO1xuICAgICAgICB9XG4gICAgfVxuICAgIC8vIEFsbCBvdGhlciBmaWx0ZXIgdHlwZXMsIHRoZSB2YWx1ZXMgaXMgZXhwZWN0ZWQgdG8gTk9UIGJlIGFuIGFycmF5LiBUaGlzIGZvbGxvd3MgdGhlIGxvZ2ljIGluIHRoZSBtYWluIGluZGV4IGZpbGUuXG4gICAgZWxzZSBpZiAoZmlsdGVyVHlwZSA9PT0gJ2d0Jykge1xuICAgICAgICBiaW5kaW5ncy5wdXNoKC4uLnZhbHVlcyk7XG4gICAgICAgIHFiLndoZXJlUmF3KGAke2pzb25TUUx9ID4gP2AsIGJpbmRpbmdzKTtcbiAgICB9XG4gICAgZWxzZSBpZiAoZmlsdGVyVHlwZSA9PT0gJ2d0ZScpIHtcbiAgICAgICAgYmluZGluZ3MucHVzaCguLi52YWx1ZXMpO1xuICAgICAgICBxYi53aGVyZVJhdyhgJHtqc29uU1FMfSA+PSA/YCwgYmluZGluZ3MpO1xuICAgIH1cbiAgICBlbHNlIGlmIChmaWx0ZXJUeXBlID09PSAnbHQnKSB7XG4gICAgICAgIGJpbmRpbmdzLnB1c2goLi4udmFsdWVzKTtcbiAgICAgICAgcWIud2hlcmVSYXcoYCR7anNvblNRTH0gPCA/YCwgYmluZGluZ3MpO1xuICAgIH1cbiAgICBlbHNlIGlmIChmaWx0ZXJUeXBlID09PSAnbHRlJykge1xuICAgICAgICBiaW5kaW5ncy5wdXNoKC4uLnZhbHVlcyk7XG4gICAgICAgIHFiLndoZXJlUmF3KGAke2pzb25TUUx9IDw9ID9gLCBiaW5kaW5ncyk7XG4gICAgfVxufTtcblxubW9kdWxlLmV4cG9ydHMuYnVpbGRTZWxlY3QgPSBmdW5jdGlvbiAocWIsIGtuZXgsIGNvbHVtbiwganNvbkNvbHVtbiwgZGF0YVR5cGUpIHtcbiAgICAvLyBUT0RPOiBhZ2dyZWdhdGUgZnVuY3Rpb25zIGNvdW50LCBzdW0sIGF2ZywgbWF4LCBtaW5cbiAgICBjb25zdCB7IGpzb25TUUwsIGJpbmRpbmdzIH0gPSBwZ0F0dHJpYnV0ZUNoYWluKGNvbHVtbiwganNvbkNvbHVtbiwgZGF0YVR5cGUsIHsgaW5jbHVkZUFzOiB0cnVlIH0pO1xuICAgIHFiLnNlbGVjdChrbmV4LnJhdyhqc29uU1FMLCBiaW5kaW5ncykpO1xufTtcblxubW9kdWxlLmV4cG9ydHMuYnVpbGRTb3J0ID0gZnVuY3Rpb24gKHFiLCBzb3J0VHlwZSwgY29sdW1uLCBqc29uQ29sdW1uLCBkYXRhVHlwZSkge1xuXG4gICAgLy8gRW5zdXJlIHRoYXQgdGhlIHNvcnQgZGlyZWN0aW9uIGNhbiBub3QgYmUgaW5qZWN0ZWRcbiAgICBsZXQgc2FuaXRpemVkU29ydFR5cGUgPSAnYXNjJztcbiAgICBpZiAoc29ydFR5cGUgPT09ICdkZXNjJyl7XG4gICAgICAgIHNhbml0aXplZFNvcnRUeXBlID0gJ2Rlc2MnO1xuICAgIH1cbiAgICBjb25zdCB7IGpzb25TUUwsIGJpbmRpbmdzIH0gPSBwZ0F0dHJpYnV0ZUNoYWluKGNvbHVtbiwganNvbkNvbHVtbiwgZGF0YVR5cGUpO1xuICAgIHFiLm9yZGVyQnlSYXcoYCR7anNvblNRTH0gJHtzYW5pdGl6ZWRTb3J0VHlwZX1gLCBiaW5kaW5ncyk7XG59O1xuIl19