import { lowerFirst , set , upperFirst } from 'lodash' ; import { json2xml , xml2json } from 'xml-js' ; import { Injectable } from '@nestjs/common' ; import { EidasJsonToXmlException , EidasXmlToJsonException , } from '../exceptions' ; import { IPathsObject } from '../interfaces' ; @ Injectable ( ) export class LightProtocolXmlService { xmlToJson ( xmlDoc ) { try { const options = { compact : true , spaces : 2 } ; const stringifiedJson = xml2json ( xmlDoc , options ) ; const json = JSON . parse ( stringifiedJson ) ; return json ; } catch ( error ) { throw new EidasXmlToJsonException ( error ) ; } } jsonToXml ( json ) { try { const options = { compact : true , ignoreComment : true , spaces : 2 } ; const stringifiedJson = JSON . stringify ( json ) ; return json2xml ( stringifiedJson , options ) ; } catch ( error ) { throw new EidasJsonToXmlException ( error ) ; } } recurseOnChildBasedOnType ( child , newPath , tree ) { if ( child instanceof Array ) { for ( let i = 0 ; i < child . length ; i ++ ) { this . jsonToPathsObject ( child [ i ] , `${ newPath }.${ i }` , tree ) ; } } else { this . jsonToPathsObject ( child , newPath , tree ) ; } } jsonToPathsObject ( parent , lastPath = '' , tree = { } ) { if ( typeof parent === 'string' ) { tree [ lastPath ] = parent ; } else if ( parent !== null && typeof parent === 'object' ) { Object . entries ( parent ) . forEach ( ( [ key , child ] ) => { const newPath = lastPath ? `${ lastPath }.${ key }` : key ; this . recurseOnChildBasedOnType ( child , newPath , tree ) ; } ) ; } return tree ; } removeDeclarationFields ( pathsObject ) { return this . forEachPath ( pathsObject , ( keyPath , value ) : Array < [ string , unknown ] > => { if ( ! keyPath . match ( /^_declaration/ ) ) { return [ [ keyPath , value ] ] ; } } ) ; } addDeclarationFields ( pathsObject ) { return { '_declaration._attributes.version' : '1.0' , '_declaration._attributes.encoding' : 'UTF-8' , '_declaration._attributes.standalone' : 'yes' , ... pathsObject , } ; } param value returns stripUrlAndUrnForProps ( pathsObject , props ) { const propsMatch = props . join ( '|' ) ; return this . forEachPath ( pathsObject , ( keyPath , value ) : Array < [ string , unknown ] > => { if ( keyPath . match ( propsMatch ) && typeof value === 'string' ) { return [ [ keyPath , value . split ( /[:/]/ ) . pop ( ) ] ] ; } else { return [ [ keyPath , value ] ] ; } } ) ; } prefixProps ( pathsObject , props , prefix ) { const propsMatch = props . join ( '|' ) ; return this . forEachPath ( pathsObject , ( keyPath , value ) : Array < [ string , unknown ] > => { if ( keyPath . match ( propsMatch ) && typeof value === 'string' ) { return [ [ keyPath , `${ prefix }${ value }` ] ] ; } else { return [ [ keyPath , value ] ] ; } } ) ; } lowerCaseFirstCharForProps ( pathsObject , props ) { const propsMatch = props . join ( '|' ) ; return this . forEachPath ( pathsObject , ( keyPath , value ) : Array < [ string , unknown ] > => { if ( keyPath . match ( propsMatch ) && typeof value === 'string' ) { return [ [ keyPath , lowerFirst ( value ) ] ] ; } else { return [ [ keyPath , value ] ] ; } } ) ; } upperCaseFirstCharForProps ( pathsObject , props ) { const propsMatch = props . join ( '|' ) ; return this . forEachPath ( pathsObject , ( keyPath , value ) : Array < [ string , unknown ] > => { if ( keyPath . match ( propsMatch ) && typeof value === 'string' ) { return [ [ keyPath , upperFirst ( value ) ] ] ; } else { return [ [ keyPath , value ] ] ; } } ) ; } pathsObjectToJson ( pathsObject ) { const final = { } ; this . forEachPath ( pathsObject , ( keyPath , value ) : void => { set ( final , keyPath , value ) ; } ) ; return final ; } replaceInPaths ( pathsObject , from , to ) { return this . forEachPath ( pathsObject , ( keyPath , value ) => { return [ [ keyPath . replace ( from , to ) , value ] ] ; } ) ; } forEachPath ( pathsObject , callback ) { const newPathsObject = { } ; Object . entries ( pathsObject ) . forEach ( ( [ keyPath , value ] ) => { const newPaths = callback ( keyPath , value ) || [ ] ; const cleaner = ( [ newKeyPath , newValue ] ) => newKeyPath && newValue ; const newPathsData = Object . fromEntries ( newPaths . filter ( cleaner ) ) ; Object . assign ( newPathsObject , newPathsData ) ; } ) ; return newPathsObject ; } }