feathers-cassandra
Version:
Feathers service adapter for Cassandra DB based on Express-Cassandra ORM and CassanKnex query builder
188 lines (187 loc) • 6.83 kB
JavaScript
function _extends() { _extends = Object.assign ? Object.assign.bind() : 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; }; return _extends.apply(this, arguments); }
const errors = require('@feathersjs/errors');
const _isEqual = require('lodash.isequal');
const types = require('cassandra-driver').types;
exports.isPlainObject = obj => {
return obj && obj.constructor === {}.constructor;
};
exports.extractIds = (id, idKey, idSeparator) => {
if (typeof id === 'object') {
return idKey.map(idKey => id[idKey]);
}
if (id[0] === '[' && id[id.length - 1] === ']') {
return JSON.parse(id);
}
if (id[0] === '{' && id[id.length - 1] === '}') {
const obj = JSON.parse(id);
return Object.keys(obj).map(key => obj[key]);
}
if (typeof id !== 'string' || !id.includes(idSeparator)) {
throw new errors.BadRequest('When using composite primary key, id must contain values for all primary keys');
}
return id.split(idSeparator);
};
exports.runFilters = (params, query, filtersExpression, filtersFunctions) => {
const filters = [];
const filtersNames = filtersExpression.replace(/[^a-zA-Z0-9_,]/g, '').split(',');
for (const name of filtersNames) {
if (name && filtersFunctions[name]) {
filters.push(filtersFunctions[name]);
}
}
for (const filter of filters) {
filter(query);
}
return filters;
};
exports.getFieldType = field => {
return exports.isPlainObject(field) ? field.type : field;
};
exports.getFieldRule = field => {
return exports.isPlainObject(field) ? field.rule : null;
};
exports.prepareUpdateResult = (data, oldData, newObject, fields) => {
Object.keys(data).forEach(field => {
const fieldType = exports.getFieldType(fields[field]);
const value = data[field];
const oldFieldValue = oldData[field];
if (fieldType && ['map', 'list', 'set'].includes(fieldType) && exports.isPlainObject(value)) {
const methodKey = Object.keys(value)[0];
const fieldValue = value[methodKey];
if (methodKey === '$add') {
if (fieldType === 'map') {
newObject[field] = oldFieldValue ? _extends({}, oldFieldValue, fieldValue) : fieldValue;
} else if (fieldType === 'list') {
newObject[field] = oldFieldValue ? oldFieldValue.concat(fieldValue) : fieldValue;
} else if (fieldType === 'set') {
newObject[field] = Array.from(new Set(oldFieldValue ? oldFieldValue.concat(fieldValue) : fieldValue)).sort();
}
} else if (methodKey === '$remove' && oldFieldValue) {
if (fieldType === 'map') {
newObject[field] = oldFieldValue;
fieldValue.forEach(prop => delete newObject[field][prop]);
if (!Object.keys(newObject[field]).length) {
newObject[field] = null;
}
} else if (fieldType === 'list' || fieldType === 'set') {
newObject[field] = oldFieldValue.filter(val => !fieldValue.includes(val));
if (!newObject[field].length) {
newObject[field] = null;
}
}
}
} else if (fieldType === 'set') {
newObject[field] = Array.from(new Set(value)).sort();
} else if (fieldType === 'counter' && exports.isPlainObject(value)) {
const methodKey = Object.keys(value)[0];
const fieldValue = value[methodKey];
if (methodKey === '$increment') {
newObject[field] = oldFieldValue.add(Number(fieldValue));
} else if (methodKey === '$decrement') {
newObject[field] = oldFieldValue.subtract(Number(fieldValue));
}
}
});
};
exports.prepareIfCondition = (id, query, idKey) => {
if (id !== null && !query.$if) {
query.$if = {};
Object.keys(query).forEach(key => {
const idField = Array.isArray(idKey) ? idKey.includes(key) : key === idKey;
if (!idField && key[0] !== '$') {
query.$if[key] = query[key];
delete query[key];
}
});
}
};
exports.getMaterializedView = (query, materializedViews) => {
const keys = Object.keys(query);
if (materializedViews.length > 0 && keys.length > 0) {
for (const mv of materializedViews) {
if (_isEqual(mv.keys.sort(), keys.sort())) {
return mv.view;
}
}
}
return null;
};
exports.prepareData = (query, data, methods) => {
for (const field of Object.keys(data)) {
const value = data[field];
let removeKey = false;
if (exports.isPlainObject(value)) {
const key = Object.keys(value)[0];
const fieldValue = value[key];
if (key === '$add' || key === '$remove' || key === '$increment' || key === '$decrement') {
query[methods[key]](field, key === '$add' && Array.isArray(fieldValue) ? [fieldValue] : fieldValue);
removeKey = true;
}
}
if (removeKey) {
delete data[field];
}
}
};
exports.setTimestampFields = (data, updatedAt, createdAt, timestamps) => {
if (timestamps) {
const now = new Date().toISOString();
const createdAtFieldName = 'createdAt';
const updatedAtFieldName = 'updatedAt';
if (createdAt && timestamps.createdAt) {
data[typeof timestamps.createdAt === 'string' ? timestamps.createdAt : createdAtFieldName] = now;
}
if (updatedAt && timestamps.updatedAt) {
data[typeof timestamps.updatedAt === 'string' ? timestamps.updatedAt : updatedAtFieldName] = now;
}
}
};
exports.setVersionField = (data, versions) => {
if (versions) {
const timeuuidVersion = types.TimeUuid.now();
const versionFieldName = '__v';
data[typeof versions.key === 'string' ? versions.key : versionFieldName] = timeuuidVersion;
}
};
exports.getHookOptions = (query = {}) => {
const options = {};
Object.keys(query).forEach(key => {
if (key[0] === '$') {
const optionName = key.substr(1).replace(/([A-Z])/g, (match, p1) => '_' + p1.toLowerCase());
options[optionName] = query[key];
}
});
return options;
};
exports.exec = (query, params) => {
return new Promise((resolve, reject) => {
const callback = (err, res) => {
if (err) return reject(err);
resolve(res);
};
if (params && params.queryOptions) {
query.exec(params.queryOptions, callback);
} else {
query.exec(callback);
}
});
};
exports.batch = (cassanKnex, queries, params) => {
return new Promise((resolve, reject) => {
const callback = (err, res) => {
if (err) return reject(err);
resolve(res);
};
if (params && params.queryOptions) {
cassanKnex().batch({
prepare: true,
...params.queryOptions
}, queries, callback);
} else {
cassanKnex().batch({
prepare: true
}, queries, callback);
}
});
};
;