import {AnyJson, ApiResponse, HydraMetadata} from '~/types/interfaces' import BaseDenormalizer from '~/services/serializer/denormalizer/baseDenormalizer' import {DENORMALIZER_TYPE, METADATA_TYPE} from '~/types/enums' import {parseInt} from "lodash"; /** * Classe permettant d'assurer la dénormalization d'un objet Hydra en JSON */ class Hydra extends BaseDenormalizer { static support (type: DENORMALIZER_TYPE): boolean { return type === DENORMALIZER_TYPE.HYDRA } /** * Parcourt une réponse Hydra pour retourner son équivalent en Json * * @param {AnyJson} hydraData * @return {AnyJson} réponse parsée */ public static denormalize (hydraData: AnyJson): AnyJson { if (hydraData['hydra:member']) { hydraData.totalCount = hydraData['hydra:totalItems'] return Hydra.parseCollection(hydraData) } else { return Hydra.parseItem(hydraData) } } private static parseItem (hydraData: AnyJson): ApiResponse { return { data: hydraData, metadata: Hydra.definedMetadataForItem(hydraData) } } /** * Méthode de parsing appelé si on est dans un GET * * @param {AnyJson} hydraData */ private static definedMetadataForItem (hydraData: AnyJson): AnyJson { const metadata:HydraMetadata = {} // if (hydraData['hydra:previous']) { // const iriParts = hydraData['hydra:previous'].split('/') // hydraData.previous = iriParts[iriParts.length - 1] // } // if (hydraData['hydra:next']) { // const iriParts = hydraData['hydra:next'].split('/') // hydraData.next = iriParts[iriParts.length - 1] // } // if (hydraData['hydra:totalItems']) { // hydraData.totalItems = hydraData['hydra:totalItems'] // } // if (hydraData['hydra:itemPosition']) { // hydraData.itemPosition = hydraData['hydra:itemPosition'] // } metadata.type = METADATA_TYPE.ITEM return metadata } /** * Méthode de parsing appelé si on est dans un GET Collection * * @param {AnyJson} hydraData */ private static parseCollection (hydraData: AnyJson): ApiResponse { const collectionResponse:ApiResponse = { data:hydraData['hydra:member'], metadata : Hydra.definedMetadataForCollection(hydraData) } // collectionResponse.order = {} // collectionResponse.search = {} // Populate href property for all elements of the collection for (const key in collectionResponse.data) { const value = collectionResponse.data[key] Hydra.populateAllData(value) } // if (typeof (hydraData['hydra:search']) !== 'undefined') { // const collectionSearch = hydraData['hydra:search']['hydra:mapping'] // for (const key in collectionSearch) { // const value = collectionSearch[key] // if (value.variable.indexOf('filter[order]') === 0) { // collectionResponse.order[value.property] = value // } else if (value.variable.indexOf('filter[where]') === 0) { // collectionResponse.search[value.property] = value // } // } // } return collectionResponse } private static definedMetadataForCollection(data:AnyJson){ const metadata:HydraMetadata = { totalItems: data['hydra:totalItems'] } if(data['hydra:view']){ metadata.firstPage = Hydra.getPageNumber(data['hydra:view']['hydra:first']) metadata.lastPage = Hydra.getPageNumber(data['hydra:view']['hydra:last']) metadata.nextPage = Hydra.getPageNumber(data['hydra:view']['hydra:next']) metadata.previousPage = Hydra.getPageNumber(data['hydra:view']['hydra:previous']) } metadata.type = METADATA_TYPE.COLLECTION return metadata } private static getPageNumber(uri:string):number { if(uri){ const number = uri.split('page=').pop() return number ? parseInt(number) : 0 } return 0 } /** * Hydrate l'objet JSON de façon récursive (afin de gérer les objet nested) * * @param {AnyJson} data */ private static populateAllData (data: AnyJson): void { for (const key in data) { const value = data[key] if (value instanceof Object) { Hydra.populateAllData(value) } } } } export default Hydra