@sap-cloud-sdk/odata-common
Version:
SAP Cloud SDK for JavaScript common functions of OData client generator and OpenAPI clint generator.
179 lines • 7.08 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.UpdateRequestBuilderBase = void 0;
exports.removePropertyOnCondition = removePropertyOnCondition;
const util_1 = require("@sap-cloud-sdk/util");
const uuid_1 = require("uuid");
const entity_deserializer_1 = require("../entity-deserializer");
const request_1 = require("../request");
const request_builder_base_1 = require("./request-builder-base");
/**
* Abstract class to create OData query to update an entity containing methods shared for OData v2 and v4.
* @typeParam EntityT - Type of the entity to be updated
*/
class UpdateRequestBuilderBase extends request_builder_base_1.MethodRequestBuilder {
/**
* Creates an instance of UpdateRequestBuilder.
* @param _entityApi - Entity API for building and executing the request.
* @param _entity - Entity to be updated.
* @param oDataUri - URI conversion functions.
* @param entitySerializer - Entity serializer.
* @param extractODataEtag - Extractor for ETag from payload.
* @param payloadManipulator - Manipulator for the payload.
*/
constructor(_entityApi, _entity, oDataUri, entitySerializer, extractODataEtag, payloadManipulator) {
super(new request_1.ODataUpdateRequestConfig(_entityApi, oDataUri));
this._entityApi = _entityApi;
this._entity = _entity;
this.oDataUri = oDataUri;
this.entitySerializer = entitySerializer;
this.extractODataEtag = extractODataEtag;
this.payloadManipulator = payloadManipulator;
this.requestConfig.eTag = _entity.versionIdentifier;
this.required = new Set();
this.ignored = new Set();
this.requestConfig.keys = this.oDataUri.getEntityKeys(this._entity, this._entityApi);
this.requestConfig.payload = this.getPayload();
}
get entity() {
return this._entity;
}
/**
* Gets identifier for the batch request.
* @returns Batch request identifier.
*/
getBatchReference() {
if (!this._batchReference) {
this.setBatchId((0, uuid_1.v4)());
}
return this._batchReference;
}
/**
* Sets user-defined identifier for the batch reference.
* @param id - User-defined batch request identifier.
*/
setBatchId(id) {
this._batchReference = { id };
}
/**
* Explicitly configure 'PUT' as the method of the update request. By default, only the properties that have changed compared to the last known remote state are sent using 'PATCH', while with 'PUT', the whole entity is sent.
* @returns The entity itself, to facilitate method chaining.
*/
replaceWholeEntityWithPut() {
this.requestConfig.updateWithPut();
this.requestConfig.payload = this.getPayload();
return this;
}
setRequiredFields(first, ...rest) {
this.required = this.toSet((0, util_1.transformVariadicArgumentToArray)(first, rest));
this.requestConfig.payload = this.getPayload();
return this;
}
setIgnoredFields(first, ...rest) {
this.ignored = this.toSet((0, util_1.transformVariadicArgumentToArray)(first, rest));
this.requestConfig.payload = this.getPayload();
return this;
}
/**
* Instructs the request to force an overwrite of the entity by sending an 'If-Match: *' header instead of sending the ETag version identifier.
* @returns The request itself to ease chaining while executing the request.
*/
ignoreVersionIdentifier() {
this.requestConfig.versionIdentifierIgnored = true;
return this;
}
/**
* Sets ETag version identifier of the entity to update.
* @param etag - Custom ETag version identifier to be sent in the header of the request.
* @returns The request itself to ease chaining while executing the request.
*/
setVersionIdentifier(etag) {
this.requestConfig.eTag = etag;
return this;
}
/**
* Executes the query.
* @param request - Request object to be executed.
* @returns A promise resolving to the entity once it was updated.
*/
async executeRequest(request) {
return (this.executeRequestRaw(request)
// Update returns 204 hence the data from the request is used to build entity for return
.then(response => {
const eTag = (0, entity_deserializer_1.extractEtagFromHeader)(response.headers) ||
this.extractODataEtag(response.data) ||
this.requestConfig.eTag;
return this._entity
.setOrInitializeRemoteState()
.setVersionIdentifier(eTag);
})
.catch(error => {
throw new util_1.ErrorWithCause('OData update request failed!', error);
}));
}
async executeRequestRaw(request) {
return request.execute();
}
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;
}
isEmptyObject(obj) {
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
return false;
}
}
return true;
}
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);
}
getKeyFieldNames() {
return this._entityApi.entityConstructor._keys;
}
toSet(fields) {
const fieldNames = Object.values(fields).map(({ _fieldName }) => _fieldName);
return new Set(fieldNames);
}
serializedDiff() {
return {
...this.entitySerializer.serializeEntity(this._entity, this._entityApi, true)
};
}
removeKeyFields(body) {
return removePropertyOnCondition(([key]) => this.getKeyFieldNames().includes(key), body);
}
removeIgnoredFields(body) {
return removePropertyOnCondition(([key]) => this.ignored.has(key), body);
}
}
exports.UpdateRequestBuilderBase = UpdateRequestBuilderBase;
/**
* @param condition - condition to remove
* @param body - body
* @returns body without condition
* @internal
*/
function removePropertyOnCondition(condition, body) {
return Object.entries(body).reduce((resultBody, [key, val]) => {
if (condition([key, val])) {
return resultBody;
}
return { ...resultBody, [key]: val };
}, {});
}
//# sourceMappingURL=update-request-builder-base.js.map