Added support for include relationship alias (as) and nested includes, fixed wrong joi json validation implementation inside parseInclude() function, fixed some associated routes resulted 404 because of prefix option

This commit is contained in:
Muhammad Labib Ramadhan
2016-11-10 01:46:42 +07:00
parent 6fa9e90ec5
commit e632f79e2b
8 changed files with 202 additions and 80 deletions

View File

@ -1,6 +1,7 @@
import { omit, identity, toNumber, isString, isUndefined } from 'lodash';
import { notImplemented } from 'boom';
import joi from 'joi';
import Promise from 'bluebird';
const sequelizeKeys = ['include', 'order', 'limit', 'offset'];
@ -9,7 +10,7 @@ const getModels = (request) => {
const noRequestModels = !request.models;
if (noGetDb && noRequestModels) {
return notImplemented('`request.getDb` or `request.models` are not defined.'
+ 'Be sure to load hapi-sequelize before hapi-sequelize-crud.');
+ 'Be sure to load hapi-sequelize before hapi-sequelize-crud.');
}
const { models } = noGetDb ? request : request.getDb();
@ -17,41 +18,69 @@ const getModels = (request) => {
return models;
};
export const parseInclude = request => {
export const parseInclude = async(request) => {
if (typeof request.query.include === 'undefined') return [];
const include = Array.isArray(request.query.include)
? request.query.include
: [request.query.include]
? request.query.include
: [request.query.include]
;
const models = getModels(request);
if (models.isBoom) return models;
return include.map(b => {
const getModelInstance = includeItem => {
return new Promise(async(resolve) => {
if (includeItem) {
if (typeof includeItem !== 'object') {
const singluarOrPluralMatch = Object.keys(models).find((modelName) => {
const { _singular, _plural } = models[modelName];
return _singular === includeItem || _plural === includeItem;
});
if (singluarOrPluralMatch) {
return resolve(models[singluarOrPluralMatch]);
}
}
if (typeof includeItem === 'string' && models.hasOwnProperty(includeItem)) {
return resolve(models[includeItem]);
} else if (typeof includeItem === 'object') {
if (
typeof includeItem.model === 'string' &&
includeItem.model.length &&
models.hasOwnProperty(includeItem.model)
) {
includeItem.model = models[includeItem.model];
}
if (includeItem.hasOwnProperty('include')) {
includeItem.include = await getModelInstance(includeItem.include);
return resolve(includeItem);
} else {
return resolve(includeItem);
}
}
} else {
return resolve(includeItem);
}
});
};
const jsonValidation = joi.string().regex(/^\{.*?"model":.*?\}$/);
const includes = include.map(async(b) => {
let a = b;
try {
if (joi.string().regex(/^\{.*?"model":.*?\}$/)) {
if (!jsonValidation.validate(a).error) {
a = JSON.parse(b);
}
} catch (e) {
//
}
if (typeof a !== 'object') {
const singluarOrPluralMatch = Object.keys(models).find((modelName) => {
const { _singular, _plural } = models[modelName];
return _singular === a || _plural === a;
});
if (singluarOrPluralMatch) return models[singluarOrPluralMatch];
}
if (typeof a === 'string') return models[a];
if (a && typeof a.model === 'string' && a.model.length) {
a.model = models[a.model];
}
return a;
return getModelInstance(a);
}).filter(identity);
return await Promise.all(includes);
};
export const parseWhere = request => {