import {AnyJson, ApiResponse, HydraMetadata, METADATA_TYPE} from "~/types/data.d"; import Url from "~/services/utils/url"; /** * Classe permettant d'assurer la dé-normalization d'un objet Hydra en JSON */ class HydraDenormalizer { /** * Parse une réponse Hydra pour retourner son équivalent en Json * * @param {AnyJson} data * @return {AnyJson} réponse parsée */ public static denormalize (data: AnyJson): ApiResponse { if (data['hydra:member']) { return HydraDenormalizer.parseCollection(data) } return HydraDenormalizer.parseItem(data) } /** * Parse une réponse Hydra contenant un item * * @param hydraData * @private */ private static parseItem (hydraData: AnyJson): ApiResponse { return { data: hydraData, metadata: HydraDenormalizer.constructMetadataForItem(hydraData) } } /** * 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 : HydraDenormalizer.constructMetadataForCollection(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] HydraDenormalizer.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 } /** * Génère les metadonnées d'un item * * @param {AnyJson} hydraData */ private static constructMetadataForItem (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 } /** * Génère les métadonnées d'une collection * * @param data * @private */ private static constructMetadataForCollection(data:AnyJson){ const metadata: HydraMetadata = { totalItems: data['hydra:totalItems'] } if(data['hydra:view']){ metadata.firstPage = HydraDenormalizer.getPageFromUri(data['hydra:view']['hydra:first'], 1) as number metadata.lastPage = HydraDenormalizer.getPageFromUri(data['hydra:view']['hydra:last'], 1) as number metadata.nextPage = HydraDenormalizer.getPageFromUri(data['hydra:view']['hydra:next']) ?? undefined metadata.previousPage = HydraDenormalizer.getPageFromUri(data['hydra:view']['hydra:previous']) ?? undefined } metadata.type = METADATA_TYPE.COLLECTION return metadata } /** * 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) { HydraDenormalizer.populateAllData(value) } } } private static getPageFromUri(uri: string, default_: number | null = null): number | null { const url = 'https://foo' + uri // Pour que l'uri partielle soit parsée, on doit y ajouter une url de base bidon const page = Url.getParameter(url, 'page') return page ? parseInt(page) : default_ } } export default HydraDenormalizer