forest-express-sequelize
Version:
Official Express/Sequelize Liana for Forest
98 lines (96 loc) • 3.78 kB
JavaScript
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
require("core-js/modules/es.promise.js");
require("core-js/modules/es.array.iterator.js");
var _lodash = _interopRequireDefault(require("lodash"));
var _forestExpress = require("forest-express");
var _orm = _interopRequireDefault(require("../utils/orm"));
var _sequelizeCompatibility = _interopRequireDefault(require("../utils/sequelize-compatibility"));
var _errors = require("./errors");
var _queryOptions = _interopRequireDefault(require("./query-options"));
function getAggregateField({
aggregateField,
parentSchema,
parentModel
}) {
// NOTICE: As MySQL cannot support COUNT(table_name.*) syntax, fieldName cannot be '*'.
const fieldName = aggregateField || parentSchema.primaryKeys[0] || parentSchema.fields[0].field;
return `${parentModel.name}.${_orm.default.getColumnName(parentSchema, fieldName)}`;
}
async function getSequelizeOptionsForModel(model, user, timezone) {
const queryOptions = new _queryOptions.default(model);
const scopeFilters = await _forestExpress.scopeManager.getScopeForUser(user, model.name, true);
await queryOptions.filterByConditionTree(scopeFilters, timezone);
return queryOptions.sequelizeOptions;
}
/**
* @param {import('sequelize').Model} childModel
* @param {import('sequelize').Model} parentModel
* @param {{
* labelFieldName: string;
* aggregator: string;
* aggregateFieldName: string;
* limit: number;
* }} params
*/
function LeaderboardStatGetter(childModel, parentModel, params, user) {
const labelField = params.labelFieldName;
const aggregate = params.aggregator.toUpperCase();
const {
limit
} = params;
const childSchema = _forestExpress.Schemas.schemas[childModel.name];
const parentSchema = _forestExpress.Schemas.schemas[parentModel.name];
let associationAs = childSchema.name;
const associationFound = _lodash.default.find(parentModel.associations, function (association) {
return association.target.name === childModel.name;
});
const aggregateField = getAggregateField({
aggregateField: params.aggregateFieldName,
parentSchema,
parentModel
});
if (!associationFound) {
throw new _errors.InvalidParameterError(`Association ${childModel.name} not found`);
}
if (associationFound.as) {
associationAs = associationFound.as;
}
const labelColumn = _orm.default.getColumnName(childSchema, labelField);
const groupBy = `${associationAs}.${labelColumn}`;
this.perform = async function () {
const {
timezone
} = params;
const parentSequelizeOptions = await getSequelizeOptionsForModel(parentModel, user, timezone);
const childSequelizeOptions = await getSequelizeOptionsForModel(childModel, user, timezone);
const queryOptions = _sequelizeCompatibility.default.postProcess(parentModel, {
attributes: [[childModel.sequelize.col(groupBy), 'key'], [childModel.sequelize.fn(aggregate, childModel.sequelize.col(aggregateField)), 'value']],
where: parentSequelizeOptions.where,
includeIgnoreAttributes: false,
include: [{
model: childModel,
attributes: [labelField],
as: associationAs,
required: true,
where: childSequelizeOptions.where,
include: childSequelizeOptions.include || []
}, ...(parentSequelizeOptions.include || [])],
subQuery: false,
group: groupBy,
order: [[childModel.sequelize.literal('value'), 'DESC']],
limit,
raw: true
});
const records = await parentModel.findAll(queryOptions);
return {
value: records.map(function (data) {
return {
key: data.key,
value: Number(data.value)
};
})
};
};
}
module.exports = LeaderboardStatGetter;
;