UNPKG

@sap-cloud-sdk/odata-common

Version:

SAP Cloud SDK for JavaScript common functions of OData client generator and OpenAPI clint generator.

175 lines • 8.04 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.entityDeserializer = entityDeserializer; exports.extractEtagFromHeader = extractEtagFromHeader; exports.extractCustomFields = extractCustomFields; const util_1 = require("@sap-cloud-sdk/util"); const de_serializers_1 = require("./de-serializers"); const entity_base_1 = require("./entity-base"); const edm_types_1 = require("./edm-types"); const selectable_1 = require("./selectable"); const logger = (0, util_1.createLogger)({ package: 'odata-common', messageContext: 'entity-deserializer' }); /** * Constructs an entityDeserializer given the OData v2 or v4 specific methods. * The concrete deserializers are created in odata/v2/entity-deserializer.ts and odata/v4/entity-deserializer.ts. * @param deSerializers - (De-)serializers used for transformation. * @param extractODataETag - Extractor for the ETag. * @param extractDataFromOneToManyLink - Extractor for data related to one to many links. * @returns An entity deserializer as defined by {@link EntityDeserializer}. */ function entityDeserializer(deSerializers, extractODataETag, extractDataFromOneToManyLink) { const edmToTs = (0, de_serializers_1.createValueDeserializer)(deSerializers); /** * Converts the JSON payload for a single entity into an instance of the corresponding generated entity class. * It sets the remote state to the data provided by the JSON payload. * If a version identifier is found in the '__metadata' or in the request header, the method also sets it. * @param json - The JSON payload. * @param entityApi - Entity API to deserialize for. * @param requestHeader - Optional parameter which may be used to add a version identifier (ETag) to the entity. * @returns An instance of the entity class. */ function deserializeEntity(json, entityApi, requestHeader) { const etag = extractODataETag(json) || extractEtagFromHeader(requestHeader); return Object.values(entityApi.schema) .filter(field => (0, entity_base_1.isSelectedProperty)(json, field)) .reduce((entity, staticField) => { entity[(0, util_1.camelCase)(staticField._fieldName)] = getFieldValue(json, staticField); return entity; }, new entityApi.entityConstructor(entityApi)) .setCustomFields(extractCustomFields(json, entityApi.schema)) .setVersionIdentifier(etag) .setOrInitializeRemoteState(); } function getFieldValue(json, field) { if (field instanceof selectable_1.EdmTypeField) { return edmToTs(json[field._fieldName], field.edmType); } if (field instanceof selectable_1.Link) { return getLinkFromJson(json, field); } if (field instanceof selectable_1.ComplexTypeField) { if (json[field._fieldName]) { return field._complexType ? deserializeComplexType(json[field._fieldName], field._complexType) : deserializeComplexTypeLegacy(json[field._fieldName], field); } return json[field._fieldName]; } if (field instanceof selectable_1.CollectionField) { return deserializeCollectionType(json[field._fieldName], field._fieldType); } if (field instanceof selectable_1.EnumField) { return json[field._fieldName]; } } function getLinkFromJson(json, link) { return link instanceof selectable_1.OneToOneLink ? getSingleLinkFromJson(json, link) : getMultiLinkFromJson(json, link); } // Be careful: if the return type is changed to `LinkedEntityT | undefined`, the test 'navigation properties should never be undefined' of the 'business-partner.spec.ts' will fail. // Not sure the purpose of the usage of null. function getSingleLinkFromJson(json, link) { if ((0, entity_base_1.isExpandedProperty)(json, link)) { return deserializeEntity(json[link._fieldName], link._linkedEntityApi); } return null; } function getMultiLinkFromJson(json, link) { if ((0, entity_base_1.isSelectedProperty)(json, link)) { const results = extractDataFromOneToManyLink(json[link._fieldName]); return results.map(linkJson => deserializeEntity(linkJson, link._linkedEntityApi)); } } // TODO: get rid of this function in v2.0 function deserializeComplexTypeLegacy(json, complexTypeField) { logger.warn('It seems that you are using an outdated OData client. To make this warning disappear, please regenerate your client using the latest version of the SAP Cloud SDK generator.'); if (json === null) { return null; } return Object.entries(complexTypeField) .filter(([, field]) => (field instanceof selectable_1.EdmTypeField || field instanceof selectable_1.ComplexTypeField) && typeof json[field._fieldName] !== 'undefined') .reduce((complexTypeObject, [fieldName, field]) => ({ ...complexTypeObject, [(0, util_1.camelCase)(fieldName)]: field instanceof selectable_1.EdmTypeField ? edmToTs(json[field._fieldName], field.edmType) : deserializeComplexTypeLegacy(json[field._fieldName], field) }), {}); } function deserializeComplexTypeProperty(propertyValue, propertyMetadata) { if (propertyMetadata.isCollection) { return deserializeCollectionType(propertyValue, propertyMetadata.type); } if ((0, selectable_1.isComplexTypeNameSpace)(propertyMetadata.type)) { return deserializeComplexType(propertyValue, propertyMetadata.type); } return edmToTs(propertyValue, propertyMetadata.type); } function deserializeComplexType(json, complexType) { if (json === null) { return null; } return complexType._propertyMetadata .map(property => ({ ...(typeof json[property.originalName] !== 'undefined' && { [property.name]: deserializeComplexTypeProperty(json[property.originalName], property) }) })) .reduce((complexTypeInstance, property) => ({ ...complexTypeInstance, ...property })); } function deserializeCollectionType(json, fieldType) { if ((0, edm_types_1.isEdmType)(fieldType)) { return json.map(val => edmToTs(val, fieldType)); } if ((0, selectable_1.isComplexTypeNameSpace)(fieldType)) { return json.map(val => deserializeComplexType(val, fieldType)); } // Enum return json; } return { deserializeEntity, deserializeComplexType }; } /** * Extract eTag from custom header ignoring case. * @param headers - Headers from which the etag is extracted. * @returns string | undefined * @internal */ function extractEtagFromHeader(headers) { return (0, util_1.pickValueIgnoreCase)(headers, 'etag'); } /** * Extracts all custom fields from the JSON payload for a single entity. * In this context, a custom fields is every property that is not known in the corresponding entity class. * @param json - The JSON payload. * @param schema - TODO * @returns An object containing the custom fields as key-value pairs. * @internal */ function extractCustomFields(json, schema) { const regularODataProperties = [ '__metadata', '__deferred', // type assertion for backwards compatibility, TODO: remove in v2.0 ...Object.values(schema).map(field => field._fieldName) ]; const regularFields = new Set(regularODataProperties); return Object.keys(json) .filter(key => !regularFields.has(key)) .reduce((customFields, key) => { customFields[key] = json[key]; return customFields; }, {}); } //# sourceMappingURL=entity-deserializer.js.map