import {Sequelize} from "sequelize"; import _ from "lodash"; import {isObjectType} from "graphql"; import {Col, Fn} from "sequelize/types/lib/utils"; import {SequelizeAdapter} from "../SequelizeAdapter"; type OtherOptions = { fn: string; args?: OtherArgs; } type OtherArgs = Array | OtherOptions | string | number function isCol(value: any) { return value?.col && typeof value?.col === "string"; } function isFn(value: any) { return value?.fn && typeof value?.fn === "string"; } type ColType = { col: string; as?: string; } type FnType = { fn: string; args?: OtherArgs; } export default function argsToOtherOptions(args: OtherArgs, adapter: SequelizeAdapter): { options: (string | Fn | Col)[]; associationFields: string[]; includeFields: string[]; } { const associationFields = new Set(); const includeFields = new Set(); function _argsToOtherOptions(args: OtherArgs): (string | Fn | Col)[] { const argList: (OtherOptions | string | number)[] = _.isUndefined(args) ? [] : (_.isArray(args) ? args : [args]); // @ts-ignore return argList.map((arg, i) => { if (isCol(arg)) { const [field, subField] = (arg as unknown as ColType).col.split("."); const fieldConfig = adapter.modelType.getFields()[field]; if (fieldConfig && !isObjectType(fieldConfig.type) && adapter.model.rawAttributes[field]) { includeFields.add(`${adapter.model.name}.${field}`); return Sequelize.col(adapter.model.rawAttributes[field].field || field); } else if ( fieldConfig && isObjectType(fieldConfig.type) && fieldConfig.type.getFields()[subField] && adapter.model.associations[field]?.target.rawAttributes[subField] ) { const target = adapter.model.associations[field].target; associationFields.add(field); includeFields.add(`${target.name}.${subField}`); return Sequelize.col(`${field}.${target.rawAttributes[subField].field || subField}`); } return field; } else if (isFn(arg)) { return Sequelize.fn((arg as FnType).fn, ..._argsToOtherOptions((arg as FnType).args)); } else { return arg; } }); } return { options: _argsToOtherOptions(args), associationFields: Array.from(associationFields), includeFields: Array.from(includeFields) }; }