import { createLogger , isNullish , upperCaseSnakeCase } from '@sap-cloud-sdk/util' ; import { EntityBase , Constructable , EntityApi } from '../entity-base' ; import { UriConverter } from '../de-serializers' ; const logger = createLogger ( { package : 'odata-common' , messageContext : 'get-resource-path' } ) ; type GetResourcePathForKeysType = < EntityT extends EntityBase > ( keys : Record < string , any > , entityApi : EntityApi < EntityT , any > ) => string ; interface GetResourcePathForKeys { getResourcePathForKeys : GetResourcePathForKeysType ; } param uriConverter returns internal export function createGetResourcePathForKeys ( uriConverter ) { typeparam param keys param entityApi returns function getResourcePathForKeys < EntityT extends EntityBase > ( keys = { } , { entityConstructor , schema } ) { keys = filterNonKeyProperties ( keys , entityConstructor ) ; validateKeys ( keys , entityConstructor ) ; if ( Object . keys ( keys ) . length ) { const byKey = Object . entries ( keys ) . map ( ( [ key , value ] ) => keyToOData ( key , value , schema ) ) . join ( ',' ) ; return `${ entityConstructor . _entityName }(${ byKey })` ; } return entityConstructor . _entityName ; } function getMissingKeys < EntityT extends EntityBase > ( keys , entityConstructor ) { const givenKeys = Object . keys ( keys ) ; return entityConstructor . _keys . map ( key => key ) . filter ( fieldName => ! givenKeys . includes ( fieldName ) ) ; } function getInvalidKeys < EntityT extends EntityBase > ( keys , entityConstructor ) { return Object . keys ( keys ) . filter ( key => ! entityConstructor . _keys . includes ( key ) ) ; } function getNullishKeys ( keys ) { return Object . entries ( keys ) . filter ( ( [ , value ] ) => isNullish ( value ) ) . map ( ( [ key ] ) => key ) ; } function filterNonKeyProperties < EntityT extends EntityBase > ( keys , entityConstructor ) { const invalidKeys = getInvalidKeys ( keys , entityConstructor ) ; if ( invalidKeys . length ) { logger . warn ( `There are too many key properties. Ignoring the following keys: ${ invalidKeys . join ( ', ' ) }` ) ; return Object . entries ( keys ) . filter ( ( [ key ] ) => ! invalidKeys . includes ( key ) ) . reduce ( ( validKeys , [ key , value ] ) => ( { ... validKeys , [ key ] : value } ) , { } ) ; } return keys ; } function keyToOData ( key , value , schema ) { const edmType = schema [ upperCaseSnakeCase ( key ) ] . edmType ; return `${ key }=${ uriConverter ( value , edmType ) }` ; } function validateKeys < EntityT extends EntityBase > ( keys , entityConstructor ) { const missingKeys = getMissingKeys ( keys , entityConstructor ) ; if ( missingKeys . length ) { throw new Error ( `Cannot get resource path for entity ${ entityConstructor . _entityName }. The following keys are missing: ${ missingKeys . join ( ', ' ) }` ) ; } const nullishKeys = getNullishKeys ( keys ) ; if ( nullishKeys . length ) { throw new Error ( `Cannot get resource path for entity ${ entityConstructor . _entityName }. The following keys have nullish values, but are not nullable: ${ nullishKeys . join ( ', ' ) }` ) ; } } return { getResourcePathForKeys } ; }