import { Service, Inject } from 'typedi'; import { camelCase, upperFirst } from 'lodash'; import pluralize from 'pluralize'; import { buildFilter } from 'objection-filter'; import { IModel } from 'interfaces'; import { getModelFields, } from 'lib/ViewRolesBuilder' import TenancyService from 'services/Tenancy/TenancyService'; import { ServiceError } from 'exceptions'; const ERRORS = { RESOURCE_MODEL_NOT_FOUND: 'RESOURCE_MODEL_NOT_FOUND', }; @Service() export default class ResourceService { @Inject() tenancy: TenancyService; /** * Transform resource to model name. * @param {string} resourceName */ private resourceToModelName(resourceName: string): string { return upperFirst(camelCase(pluralize.singular(resourceName))); } /** * Retrieve model fields. * @param {number} tenantId * @param {IModel} Model */ private getModelFields(tenantId: number, Model: IModel) { const { __ } = this.tenancy.i18n(tenantId); const fields = getModelFields(Model); return fields.map((field) => ({ label: __(field.label), key: field.key, dataType: field.columnType, fieldType: field.fieldType, ...(field.options) ? { options: field.options.map((option) => ({ ...option, label: __(option.label), })), } : {}, ...(field.optionsResource) ? { optionsResource: field.optionsResource, optionsKey: field.optionsKey, optionsLabel: field.optionsLabel, } : {}, })); } /** * Should model be resource-able or throw service error. * @param {IModel} model */ private shouldModelBeResourceable(model: IModel) { if (!model.resourceable) { throw new ServiceError(ERRORS.RESOURCE_MODEL_NOT_FOUND); } } /** * Retrieve resource fields from resource model name. * @param {string} resourceName */ public getResourceFields(tenantId: number, modelName: string) { const resourceModel = this.getResourceModel(tenantId, modelName); this.shouldModelBeResourceable(resourceModel); return this.getModelFields(tenantId, resourceModel); } /** * Retrieve resource model object. * @param {number} tenantId - * @param {string} inputModelName - */ public getResourceModel(tenantId: number, inputModelName: string) { const modelName = this.resourceToModelName(inputModelName); const Models = this.tenancy.models(tenantId); if (!Models[modelName]) { throw new ServiceError(ERRORS.RESOURCE_MODEL_NOT_FOUND); } return Models[modelName]; } /** * Retrieve resource data from the storage based on the given query. * @param {number} tenantId * @param {string} modelName */ public async getResourceData(tenantId: number, modelName: string, filter: any) { const resourceModel = this.getResourceModel(tenantId, modelName); this.shouldModelBeResourceable(resourceModel); return buildFilter(resourceModel).build(filter); } }