import { ErrorWithCause , variadicArgumentToArray } from '@sap-cloud-sdk/util' ; import { HttpResponse } from '@sap-cloud-sdk/http-client' ; import { EntityApi , EntityBase , EntityIdentifiable } from '../entity-base' ; import { extractEtagFromHeader } from '../entity-deserializer' ; import { EntitySerializer } from '../entity-serializer' ; import { ODataUpdateRequestConfig , ODataRequest } from '../request' ; import { ODataUri } from '../uri-conversion' ; import { Selectable } from '../selectable' ; import { DeSerializers } from '../de-serializers' ; import { MethodRequestBuilder } from './request-builder-base' ; typeparam internal export abstract class UpdateRequestBuilderBase < EntityT extends EntityBase , DeSerializersT extends DeSerializers > extends MethodRequestBuilder < ODataUpdateRequestConfig < EntityT , DeSerializersT > > implements EntityIdentifiable < EntityT , DeSerializersT > { readonly _deSerializers : DeSerializersT ; private ignored : Set < string > ; private required : Set < string > ; param _entityApi param _entity param oDataUri param entitySerializer param extractODataEtag param payloadManipulator constructor ( readonly _entityApi , readonly _entity , readonly oDataUri , readonly entitySerializer , readonly extractODataEtag , readonly payloadManipulator ) { super ( new ODataUpdateRequestConfig ( _entityApi , oDataUri ) ) ; this . requestConfig . eTag = _entity . versionIdentifier ; this . required = new Set < string > ( ) ; this . ignored = new Set < string > ( ) ; this . requestConfig . keys = this . oDataUri . getEntityKeys ( this . _entity , this . _entityApi ) ; this . requestConfig . payload = this . getPayload ( ) ; } get entity ( ) : EntityT { return this . _entity ; } returns replaceWholeEntityWithPut ( ) { this . requestConfig . updateWithPut ( ) ; this . requestConfig . payload = this . getPayload ( ) ; return this ; } param fields returns setRequiredFields ( ... fields ) ; setRequiredFields ( fields ) ; setRequiredFields ( first , ... rest ) { this . required = this . toSet ( variadicArgumentToArray ( first , rest ) ) ; this . requestConfig . payload = this . getPayload ( ) ; return this ; } param fields returns setIgnoredFields ( ... fields ) ; setIgnoredFields ( fields ) ; setIgnoredFields ( first , ... rest ) { this . ignored = this . toSet ( variadicArgumentToArray ( first , rest ) ) ; this . requestConfig . payload = this . getPayload ( ) ; return this ; } returns ignoreVersionIdentifier ( ) { this . requestConfig . versionIdentifierIgnored = true ; return this ; } param etag returns setVersionIdentifier ( etag ) { this . requestConfig . eTag = etag ; return this ; } param request returns protected async executeRequest ( request ) { return ( this . executeRequestRaw ( request ) . then ( response => { const eTag = extractEtagFromHeader ( response . headers ) || this . extractODataEtag ( response . data ) || this . requestConfig . eTag ; return this . _entity . setOrInitializeRemoteState ( ) . setVersionIdentifier ( eTag ) ; } ) . catch ( error => { throw new ErrorWithCause ( 'OData update request failed!' , error ) ; } ) ) ; } protected async executeRequestRaw ( request ) { return request . execute ( ) ; } protected getPayload ( ) { const serializedBody = this . entitySerializer . serializeEntity ( this . _entity , this . _entityApi ) ; if ( this . requestConfig . method === 'patch' ) { let body = this . serializedDiff ( ) ; body = this . payloadManipulator ( body ) ; body = this . removeKeyFields ( body ) ; body = this . addRequiredFields ( serializedBody , body ) ; body = this . removeIgnoredFields ( body ) ; return body ; } return serializedBody ; } protected isEmptyObject ( obj ) { for ( const key in obj ) { if ( obj . hasOwnProperty ( key ) ) { return false ; } } return true ; } private addRequiredFields ( completeBody , body ) { return Array . from ( this . required ) . reduce ( ( resultBody , requiredField ) => { if ( Object . keys ( resultBody ) . includes ( requiredField ) ) { return resultBody ; } return { ... resultBody , [ requiredField ] : completeBody [ requiredField ] } ; } , body ) ; } private getKeyFieldNames ( ) { return this . _entityApi . entityConstructor . _keys ; } private toSet ( fields ) { const fieldNames = Object . values ( fields ) . map ( ( { _fieldName } ) => _fieldName ) ; return new Set ( fieldNames ) ; } private serializedDiff ( ) { return { ... this . entitySerializer . serializeEntity ( this . _entity , this . _entityApi , true ) } ; } private removeKeyFields ( body ) { return removePropertyOnCondition ( ( [ key ] ) => this . getKeyFieldNames ( ) . includes ( key ) , body ) ; } private removeIgnoredFields ( body ) { return removePropertyOnCondition ( ( [ key ] ) => this . ignored . has ( key ) , body ) ; } } param condition param body returns internal export function removePropertyOnCondition ( condition , body ) { return Object . entries ( body ) . reduce ( ( resultBody , [ key , val ] ) => { if ( condition ( [ key , val ] ) ) { return resultBody ; } return { ... resultBody , [ key ] : val } ; } , { } ) ; }