import ApiRequestService from "./apiRequestService"; import {AssociativeArray} from "./data"; import {useRepo} from "pinia-orm"; import UrlBuilder from "~/services/utils/urlBuilder"; import ModelNormalizer from "./serializer/normalizer/modelNormalizer"; import HydraDenormalizer from "./serializer/denormalizer/hydraDenormalizer"; import ApiModel from "~/models/ApiModel"; /** * Entity manager: make operations on the models defined with the Pinia-Orm library * * @see https://pinia-orm.codedredd.de/ */ class EntityManager { private apiRequestService: ApiRequestService; public constructor(apiRequestService: ApiRequestService) { this.apiRequestService = apiRequestService } public getRepository(model: typeof ApiModel) { return useRepo(model) } private static getEntityModel(entity: ApiModel): typeof ApiModel{ return Object.getPrototypeOf(entity) } /** * Fetch one entity by its id, save it to the store and returns it * * @param model Model of the object to fetch * @param id Id of the object to fetch * @param forceRefresh Force a new get request to the api ; * current object in store will be overwritten if it exists */ public async fetch(model: typeof ApiModel, id: number, forceRefresh: boolean = false) { const repository = this.getRepository(model) // If the entity is already in the store and forceRefresh is false, return the object in store if (!forceRefresh) { const item = repository.find(id) if (item && typeof item !== 'undefined') { return item } } // Else, get the object from the API const url = UrlBuilder.concat('api', model.entity, String(id)) const response = await this.apiRequestService.get(url) // deserialize the response const entity = await HydraDenormalizer.denormalize(response) entity.persisted = true entity.initialState = structuredClone(entity) // Save data into the store repository.save(entity) return entity } public findBy(model: typeof ApiModel, query: AssociativeArray) { // TODO: implement } public fetchAll(model: typeof ApiModel) { // TODO: implement } public async persist(model: typeof ApiModel, entity: ApiModel) { const data = ModelNormalizer.normalize(entity) let url = UrlBuilder.concat('api', model.entity) let response = null if (entity.persisted) { url = UrlBuilder.concat(url, String(entity.id)) response = await this.apiRequestService.put(url, data) } else { response = await this.apiRequestService.post(url, data) } const fetchedEntity = await HydraDenormalizer.denormalize(response) fetchedEntity.persisted = true // Save data into the store const repository = this.getRepository(model) repository.save(fetchedEntity) return fetchedEntity } public async delete(model: typeof ApiModel, id: number) { const repository = this.getRepository(model) const entity = repository.find(id) as ApiModel if (!entity || typeof entity === 'undefined') { throw new Error(model + ' ' + id + ' does not exists in store') } // If object has been persisted to the datasource, send a delete request if (entity.persisted) { const url = UrlBuilder.concat('api', model.entity, String(id)) await this.apiRequestService.delete(url) } // update the store repository.destroy(id) } public new(model: typeof ApiModel) { const repository = this.getRepository(model) const entity = repository.make() entity.persisted = false // Save data into the store repository.save(entity) return entity } public reset(entity: ApiModel) { if (entity.initialState === null) { console.log('object has no initial state - abort') return } entity = entity.initialState as ApiModel entity.initialState = structuredClone(entity) const repository = this.getRepository(this.getEntityModel(entity)) repository.save(entity) } } export default EntityManager