app2-api/helpers/service.helper.js
2019-05-09 18:23:54 +02:00

206 lines
7.1 KiB
JavaScript

const _ = require('lodash');
const parseParamsToFindOptions = (params) => {
const result = {};
// Query
if (params.query) {
result.query = params.query
}
// Where
if (params.params) {
result.where = params.params
}
// Paginate
if (params.paginate) {
result.offset = params.paginate.limit * (params.paginate.page - 1);
result.limit = result.offset + params.paginate.limit;
}
// Order
if (params.sort) {
result.order = [];
Object.keys(params.sort).forEach(key => {
let dir = params.sort[key] ? 'ASC' : 'DESC';
result.order.push([key, dir])
});
}
// Attributes
if (params.fields) {
if (params.fields.validFields) {
result.attributes = params.fields.validFields
}
if (params.fields.invalidFields && Array.isArray(params.fields.invalidFields)) {
result.attributes = {
...result.attributes,
exclude: params.fields.invalidFields
}
}
}
return result;
}
const defaultOptions = {};
const generateService = (model, extraMethods = {}, options = defaultOptions) => {
const defaultService = {
fetchAll: async (params, context) => {
const findOptions = parseParamsToFindOptions(params);
return await model.findAndCountAll(findOptions);
},
fetchOne: async (params, context) => {
return await model.findOne({ where: { 'id': params.id } });
},
count: async (params, context) => {
// Convert `params` object to filters compatible with Bookshelf.
//const filters = strapi.utils.models.convertParams('post', params);
return await model.count(params);
},
create: async (values, context) => {
return await model.create(values);
},
update: async (params, values, context) => {
// Extract values related to relational data.
const relations = _.pick(values, Post.associations.map(ast => ast.alias));
const data = _.omit(values, Post.associations.map(ast => ast.alias));
// Create entry with no-relational data.
const entry = await Post.forge(params).save(data);
// Create relational data and return the entry.
return Post.updateRelations(Object.assign(params, {
values: relations
}));
},
delete: async (params, context) => {
const numAffectedRows = await model.destroy({ where: { 'id': params.id } });
return (numAffectedRows > 0);
/*params.values = {};
Post.associations.map(association => {
switch (association.nature) {
case 'oneWay':
case 'oneToOne':
case 'manyToOne':
case 'oneToManyMorph':
params.values[association.alias] = null;
break;
case 'oneToMany':
case 'manyToMany':
case 'manyToManyMorph':
params.values[association.alias] = [];
break;
default:
}
});
await Post.updateRelations(params);
return Post.forge(params).destroy();*/
},
search: async (params, context) => {
// Convert `params` object to filters compatible with Bookshelf.
const filters = strapi.utils.models.convertParams('post', params);
// Select field to populate.
const populate = Post.associations
.filter(ast => ast.autoPopulate !== false)
.map(ast => ast.alias);
const associations = Post.associations.map(x => x.alias);
const searchText = Object.keys(Post._attributes)
.filter(attribute => attribute !== Post.primaryKey && !associations.includes(attribute))
.filter(attribute => ['string', 'text'].includes(Post._attributes[attribute].type));
const searchNoText = Object.keys(Post._attributes)
.filter(attribute => attribute !== Post.primaryKey && !associations.includes(attribute))
.filter(attribute => !['string', 'text', 'boolean', 'integer', 'decimal', 'float'].includes(Post._attributes[attribute].type));
const searchInt = Object.keys(Post._attributes)
.filter(attribute => attribute !== Post.primaryKey && !associations.includes(attribute))
.filter(attribute => ['integer', 'decimal', 'float'].includes(Post._attributes[attribute].type));
const searchBool = Object.keys(Post._attributes)
.filter(attribute => attribute !== Post.primaryKey && !associations.includes(attribute))
.filter(attribute => ['boolean'].includes(Post._attributes[attribute].type));
const query = (params._q || '').replace(/[^a-zA-Z0-9.-\s]+/g, '');
return Post.query(qb => {
// Search in columns which are not text value.
searchNoText.forEach(attribute => {
qb.orWhereRaw(`LOWER(${attribute}) LIKE '%${_.toLower(query)}%'`);
});
if (!_.isNaN(_.toNumber(query))) {
searchInt.forEach(attribute => {
qb.orWhereRaw(`${attribute} = ${_.toNumber(query)}`);
});
}
if (query === 'true' || query === 'false') {
searchBool.forEach(attribute => {
qb.orWhereRaw(`${attribute} = ${_.toNumber(query === 'true')}`);
});
}
// Search in columns with text using index.
switch (Post.client) {
case 'mysql':
qb.orWhereRaw(`MATCH(${searchText.join(',')}) AGAINST(? IN BOOLEAN MODE)`, `*${query}*`);
break;
case 'pg':
{
const searchQuery = searchText.map(attribute =>
_.toLower(attribute) === attribute ?
`to_tsvector(${attribute})` :
`to_tsvector('${attribute}')`
);
qb.orWhereRaw(`${searchQuery.join(' || ')} @@ to_tsquery(?)`, query);
break;
}
}
if (filters.sort) {
qb.orderBy(filters.sort.key, filters.sort.order);
}
if (filters.skip) {
qb.offset(_.toNumber(filters.skip));
}
if (filters.limit) {
qb.limit(_.toNumber(filters.limit));
}
}).fetchAll({
withRelated: populate
});
}
}
return {
...defaultService,
//...associationControllers
...extraMethods
}
}
module.exports = {
generateService,
parseParamsToFindOptions,
defaultOptions
}