function extractFindOptions(req, res, targetAttributes) { const result = {}; result.params = (req && req.params) ? req.params : null; if (res && res.locals) { Object.keys(res.locals).forEach(key => { result[key] = res.locals[key] }) } return result; } function parseFindOptions(findOptions, targetAttributes) { const result = {}; // Where if (findOptions.params) { result.where = findOptions.params } // Paginate if (findOptions.paginate) { result.page = findOptions.paginate.page; result.limit = findOptions.paginate.limit; } // Order if (findOptions.sort) { result.order = []; Object.keys(findOptions.sort).forEach(key => { let dir = findOptions.sort[key] ? 'ASC' : 'DESC'; result.order.push([key, dir]) }); } // Attributes if (findOptions.fields) { if (findOptions.fields.validFields) { result.attributes = findOptions.fields.validFields } if (findOptions.fields.invalidFields && Array.isArray(findOptions.fields.invalidFields)) { result.attributes = targetAttributes.filter(attr => !findOptions.fields.invalidFields.includes(attr)); } } return result; } function checkIsModel(target) { return !!target.getTableName; } function checkIsAssociation(target) { return !!target.associationType; } function resultIsAList(params) { const _params = Object.keys(params); if (_params && Array.isArray(_params) && model.primaryKeyAttributes && Array.isArray(model.primaryKeyAttributes)) { return !model.primaryKeyAttributes.every(field => _params.includes(field)); } else { return true; } } function _find(modelMaybeThunk, options = {}) { /*if (typeof modelMaybeThunk != 'function' && !checkIsModel(modelMaybeThunk) && !checkIsAssociation(modelMaybeThunk)) { throw new Error('resolverFactory should be called with a model, an association or a function (which resolves to a model or an association)'); }*/ if (options.before === undefined) options.before = (options) => options; if (options.after === undefined) options.after = (result) => result; return async function (req, res, next) { let target = typeof modelMaybeThunk === 'function' && !checkIsModel(modelMaybeThunk) ? await Promise.resolve(modelMaybeThunk(req, res, next)) : modelMaybeThunk; let isModel = checkIsModel(target), isAssociation = checkIsAssociation(target), association = isAssociation && target, isList = options.list || resultIsAList(req.params), model = isAssociation && target.target || isModel && target; let findOptions = extractFindOptions(req, res); let targetAttributes = Object.keys(model.rawAttributes); findOptions = parseFindOptions(findOptions, targetAttributes); return Promise.resolve(options.before(findOptions, req, res)) .then(findOptions => { return model[isList ? 'fetchAll' : 'fetch'](findOptions); }) .then(result => { return options.after(result, req, res); }); } } const defaultOptions = { //before: optimizeAttributes, } const find = (model, options = defaultOptions) => { return async function (req, res, next) { return _find(model, options)(req, res, next) } } module.exports = find;