UNPKG

ravendb

Version:
248 lines 10.8 kB
import { TypeUtil } from "../../Utility/TypeUtil.js"; import { CONSTANTS } from "../../Constants.js"; import { throwError } from "../../Exceptions/index.js"; import { SetupDocumentBase } from "../SetupDocumentBase.js"; export class EntityToJson { _session; /** * All the listeners for this session */ constructor(session) { this._session = session; } _missingDictionary = new Map(); get missingDictionary() { return this._missingDictionary; } convertEntityToJson(entity, documentInfo) { if (documentInfo) { this._session.onBeforeConversionToDocumentInvoke(documentInfo.id, entity); } let document = EntityToJson._convertEntityToJsonInternal(entity, this._session.conventions, documentInfo); if (documentInfo) { const documentReference = { value: document }; this._session.onAfterConversionToDocumentInvoke(documentInfo.id, entity, documentReference); document = documentReference.value; } return document; } static _convertEntityToJsonInternal(entity, conventions, documentInfo, removeIdentityProperty = true) { const entityMapper = conventions.objectMapper; let typeInfo; let jsonNode = entityMapper.toObjectLiteral(entity, (_typeInfo) => { typeInfo = _typeInfo; }, conventions.knownEntityTypesByName); if (entity instanceof SetupDocumentBase) { jsonNode = entity.toRemoteFieldNames(); } else { jsonNode = conventions.transformObjectKeysToRemoteFieldNameConvention(jsonNode); } EntityToJson._writeMetadata(jsonNode, typeInfo, documentInfo); if (removeIdentityProperty) { const type = TypeUtil.findType(entity, conventions.knownEntityTypes); EntityToJson._tryRemoveIdentityProperty(jsonNode, type, conventions); } return jsonNode; } static convertEntityToJson(entity, conventions, documentInfo, removeIdentityProperty = true) { let typeInfo; const jsonNode = conventions.objectMapper.toObjectLiteral(entity, (_typeInfo) => { typeInfo = _typeInfo; }); EntityToJson._writeMetadata(jsonNode, typeInfo, documentInfo); if (removeIdentityProperty) { EntityToJson._tryRemoveIdentityProperty(jsonNode, typeInfo.typeName, conventions); } return jsonNode; } static nestedTypes = CONSTANTS.Documents.Metadata.NESTED_OBJECT_TYPES; static ravenJsType = CONSTANTS.Documents.Metadata.RAVEN_JS_TYPE; static _writeMetadata(jsonNode, typeInfo, documentInfo) { if (!documentInfo) { return; } if (documentInfo.metadata) { documentInfo.metadata[EntityToJson.nestedTypes] = typeInfo.nestedTypes; documentInfo.metadata[EntityToJson.ravenJsType] ??= typeInfo.typeName; } function differentNestedTypes() { const existing = documentInfo.metadataInstance[EntityToJson.nestedTypes]; if (!existing) { return true; } if (Object.keys(existing).length !== Object.keys(typeInfo.nestedTypes).length) { return true; } for (const key in typeInfo.nestedTypes) { if (typeInfo.nestedTypes[key] !== existing[key]) { return true; } } return false; } if (documentInfo.metadataInstance) { if (differentNestedTypes()) { documentInfo.metadataInstance[EntityToJson.nestedTypes] = typeInfo.nestedTypes; } documentInfo.metadataInstance[EntityToJson.ravenJsType] ??= typeInfo.typeName; } let setMetadata = false; const metadataNode = {}; if (documentInfo.metadata && Object.keys(documentInfo.metadata).length > 0) { setMetadata = true; Object.assign(metadataNode, documentInfo.metadata); // Add the document @metadata fields (for RDBC-213) const entityMeta = documentInfo.entity[CONSTANTS.Documents.Metadata.KEY]; for (const metadataItem in entityMeta) { // eslint-disable-next-line no-prototype-builtins if (entityMeta.hasOwnProperty(metadataItem)) { setMetadata = true; metadataNode[metadataItem] = entityMeta[metadataItem]; } } } else if (documentInfo.metadataInstance) { setMetadata = true; Object.assign(metadataNode, documentInfo.metadataInstance); } if (documentInfo.collection) { setMetadata = true; metadataNode["@collection"] = documentInfo.collection; } if (setMetadata) { jsonNode[CONSTANTS.Documents.Metadata.KEY] = metadataNode; } } /** * Converts a json object to an entity. */ convertToEntity(targetEntityType, id, document, trackEntity) { const conventions = this._session.conventions; const entityType = conventions.getJsTypeByDocumentType(targetEntityType); try { if (TypeUtil.isType(document, targetEntityType)) { return document; } const documentRef = { value: document }; this._session.onBeforeConversionToEntityInvoke(id, entityType, documentRef); document = documentRef.value; let entity; //TODO: if track! -> RegisterMissingProperties const documentTypeFromConventions = conventions.getJsType(id, document); const entityTypeInfoFromMetadata = EntityToJson._getEntityTypeInfoFromMetadata(document); if (documentTypeFromConventions) { const passedEntityTypeIsAssignableFromConventionsDocType = entityType && ((entityType.name === documentTypeFromConventions.name) || TypeUtil.isInstanceOf(entityType, documentTypeFromConventions)); if (passedEntityTypeIsAssignableFromConventionsDocType) { const mapper = conventions.objectMapper; entity = mapper.fromObjectLiteral(document, entityTypeInfoFromMetadata); } } if (!entity) { const mapper = conventions.objectMapper; let passedTypeInfo = entityTypeInfoFromMetadata; if (entityType) { passedTypeInfo = Object.assign(passedTypeInfo, { typeName: entityType.name }); } entity = mapper.fromObjectLiteral(document, passedTypeInfo); } const isProjection = !!document[CONSTANTS.Documents.Metadata.PROJECTION]; if (id) { this._session.generateEntityIdOnTheClient.trySetIdentity(entity, id, isProjection); } return entity; } catch (err) { throwError("InvalidOperationException", `Could not convert document ${id} to entity of type ` + `${entityType ? entityType.name : entityType}: ${err.stack}`, err); } } static _getEntityTypeInfoFromMetadata(document) { const metadata = document[CONSTANTS.Documents.Metadata.KEY]; if (!metadata) { return {}; } return { typeName: metadata[CONSTANTS.Documents.Metadata.RAVEN_JS_TYPE], nestedTypes: metadata[CONSTANTS.Documents.Metadata.NESTED_OBJECT_TYPES] }; } populateEntity(entity, id, document) { if (!id) { throwError("InvalidArgumentException", "Id cannot be null."); } EntityToJson.populateEntity(entity, document, this._session.conventions.objectMapper); this._session.generateEntityIdOnTheClient.trySetIdentity(entity, id); } static populateEntity(entity, document, objectMapper) { if (!entity) { throwError("InvalidArgumentException", "Entity cannot be null"); } if (!document) { throwError("InvalidArgumentException", "Document cannot be null"); } if (!objectMapper) { throwError("InvalidArgumentException", "ObjectMapper cannot be null"); } try { const entityValue = objectMapper.fromObjectLiteral(document); Object.assign(entity, entityValue); } catch (e) { throwError("InvalidOperationException", "Could not populate entity.", e); } } static _tryRemoveIdentityProperty(document, entityType, conventions) { const identityProperty = conventions.getIdentityProperty(entityType); if (!identityProperty) { return false; } delete document[identityProperty]; return true; } static convertToEntity(entityClass, id, document, conventions) { const entityType = conventions.getJsTypeByDocumentType(entityClass); try { let entity; const documentTypeFromConventions = conventions.getJsType(id, document); const entityTypeInfoFromMetadata = EntityToJson._getEntityTypeInfoFromMetadata(document); if (documentTypeFromConventions) { const passedEntityTypeIsAssignableFromConventionsDocType = entityType && ((entityType.name === documentTypeFromConventions.name) || TypeUtil.isInstanceOf(entityType, documentTypeFromConventions)); if (passedEntityTypeIsAssignableFromConventionsDocType) { const mapper = conventions.objectMapper; entity = mapper.fromObjectLiteral(document, entityTypeInfoFromMetadata); } } if (!entity) { const mapper = conventions.objectMapper; let passedTypeInfo = entityTypeInfoFromMetadata; if (entityType) { passedTypeInfo = Object.assign(passedTypeInfo, { typeName: entityType.name }); } entity = mapper.fromObjectLiteral(document, passedTypeInfo); } return entity; } catch (err) { throwError("InvalidOperationException", `Could not convert document ${id} to entity of type ` + `${entityType ? entityType.name : entityType}: ${err.stack}`, err); } } removeFromMissing(entity) { this._missingDictionary.delete(entity); } clear() { this._missingDictionary.clear(); } } //# sourceMappingURL=EntityToJson.js.map