import * as _ from "lodash" ; import { Model } from "sequelize-typescript" ; import { BaseDto } from "./base.dto" ; import { EntityNotFoundException } from "./http/exceptions" ; import { InstanceUpdateOptions , UpdateOptions , WhereOptions } from "sequelize" ; export abstract class BaseService { /**
     *  Methods analyzes existing records & records to update by primaryField.
     *  Returns [ [models_to_create], [models_to_update], [models_to_delete] ]
     */ public getCUDModels < T > ( existingRecords , recordsToUpdate , primaryField = "id" ) { const toCreate = _ . differenceBy ( recordsToUpdate , existingRecords , primaryField ) ; const toUpdate = _ . intersectionBy ( recordsToUpdate , existingRecords , primaryField ) ; const toDelete = _ . differenceBy ( existingRecords , recordsToUpdate , primaryField ) ; return [ toCreate , toUpdate , toDelete ] ; } public async exists < T extends BaseDto > ( repository , options ) { return ! ! ( await repository . findOne ( { where : options } ) ) ; } public async updateBy < T extends BaseDto > ( repository , model , entity , matchField = "id" , returning = false , fields ? ) { const fieldsToUpdate = fields || ( model as any ) . PUBLIC_ATTRIBUTES ; if ( ! fieldsToUpdate ) { throw new Error ( `No fields to update specified` ) ; } const lookupOptions = { [ matchField ] : entity [ matchField ] } ; const options = { limit : 1 , fields : fieldsToUpdate , where : lookupOptions , } ; await repository . update ( entity , options ) ; if ( returning ) { return repository . findOne ( { where : lookupOptions } ) ; } } public async destroyBy < T extends BaseDto > ( repository , attributeValue , matchField = "id" ) { const deletedAmount = await repository . destroy ( { where : { [ matchField ] : attributeValue } , limit : 1 } ) ; if ( matchField === "id" && deletedAmount !== 1 ) { throw new EntityNotFoundException ( `${ repository . name }` ) ; } } public async multipleDestroyBy < T extends BaseDto > ( repository , attributeValues , matchField = "id" ) { if ( _ . isEmpty ( attributeValues ) ) { return ; } const deletedAmount = await repository . destroy ( { where : { [ matchField ] : { $in : attributeValues } } } ) ; if ( deletedAmount !== attributeValues . length ) { } return deletedAmount ; } }