UNPKG

ravendb

Version:
193 lines 8.75 kB
import { TypeUtil } from "../Utility/TypeUtil.js"; import { DocumentsChanges } from "../Documents/Session/DocumentsChanges.js"; import { CONSTANTS } from "../Constants.js"; import { throwError } from "../Exceptions/index.js"; export class JsonOperation { static entityChanged(newObj, documentInfo, changes) { const docChanges = changes ? [] : null; if (!documentInfo.newDocument && documentInfo.document) { return JsonOperation._compareJson("", documentInfo.id, documentInfo.document, newObj, changes, docChanges); } if (!changes) { return true; } JsonOperation._newChange(null, null, null, null, docChanges, "DocumentAdded"); changes[documentInfo.id] = docChanges; return true; } static _fieldPathCombine(path1, path2) { return !path1 ? path2 : path1 + "." + path2; } static _compareJson(fieldPath, id, originalJson, newJson, changes, docChanges) { const newJsonProps = Object.entries(newJson).filter(([_, value]) => typeof value !== "undefined").map(x => x[0]); const oldJsonProps = Object.entries(originalJson).filter(([_, value]) => typeof value !== "undefined").map(x => x[0]); const newFields = new Set(newJsonProps.filter(x => !oldJsonProps.includes(x))); const removedFields = oldJsonProps.filter(x => !newJsonProps.includes(x)); for (const field of removedFields) { if (!changes) { return true; } JsonOperation._newChange(fieldPath, field, null, originalJson[field], docChanges, "RemovedField"); } for (const prop of newJsonProps) { if (CONSTANTS.Documents.Metadata.LAST_MODIFIED === prop || CONSTANTS.Documents.Metadata.COLLECTION === prop || CONSTANTS.Documents.Metadata.CHANGE_VECTOR === prop || CONSTANTS.Documents.Metadata.ID === prop || CONSTANTS.Documents.Metadata.KEY === prop) { continue; } if (newFields.has(prop)) { if (!changes) { return true; } JsonOperation._newChange(fieldPath, prop, newJson[prop], null, docChanges, "NewField"); continue; } const newProp = newJson[prop]; const oldProp = originalJson[prop]; let changed; const typeOfNewProp = typeof newProp; if (typeOfNewProp === "number" || typeOfNewProp === "boolean" || typeOfNewProp === "string") { if (newProp === oldProp || JsonOperation._compareValues(oldProp, newProp)) { continue; } if (!changes) { return true; } JsonOperation._newChange(fieldPath, prop, newProp, oldProp, docChanges, "FieldChanged"); } else if (!newProp) { if (oldProp) { if (!changes) { return true; } JsonOperation._newChange(fieldPath, prop, null, oldProp, docChanges, "FieldChanged"); } } else if (Array.isArray(newProp)) { if (!Array.isArray(oldProp)) { if (!changes) { return true; } JsonOperation._newChange(fieldPath, prop, newProp, oldProp, docChanges, "FieldChanged"); } changed = JsonOperation._compareJsonArray(JsonOperation._fieldPathCombine(fieldPath, prop), id, oldProp, newProp, changes, docChanges, prop); if (!changes && changed) { return true; } } else if (TypeUtil.isObject(newProp)) { if (!oldProp) { if (!changes) { return true; } JsonOperation._newChange(fieldPath, prop, newProp, null, docChanges, "FieldChanged"); } else { changed = JsonOperation._compareJson(JsonOperation._fieldPathCombine(fieldPath, prop), id, oldProp, newProp, changes, docChanges); if (!changes && changed) { return true; } } } else { throwError("InvalidArgumentException", `Unknown type of JSON property: ${typeOfNewProp}.`); } } if (!changes || docChanges.length <= 0) { return false; } changes[id] = docChanges; return true; } static _compareValues(oldProp, newProp) { return oldProp === newProp; // triple equals compares type as well } static _compareJsonArray(fieldPath, id, oldArray, newArray, changes, docChanges, propName) { // if we don't care about the changes if (oldArray.length !== newArray.length && !changes) { return true; } let position = 0; let changed = false; let oldArrayItem = oldArray[position]; let typeOfOldArrayItem = typeof oldArrayItem; let newArrayItem = newArray[position]; let typeOfNewArrayItem = typeof newArrayItem; while (position < oldArray.length && position < newArray.length) { if (TypeUtil.isObject(oldArrayItem)) { if (TypeUtil.isObject(newArrayItem)) { changed = changed || this._compareJson(JsonOperation._addIndexFieldPath(fieldPath, position), id, oldArrayItem, newArrayItem, changes, docChanges); } else { changed = true; if (changes) { this._newChange(JsonOperation._addIndexFieldPath(fieldPath, position), propName, newArrayItem, oldArrayItem, docChanges, "ArrayValueAdded"); } } } else if (Array.isArray(oldArrayItem)) { if (Array.isArray(newArrayItem)) { changed = changed || this._compareJsonArray(JsonOperation._addIndexFieldPath(fieldPath, position), id, oldArrayItem, newArrayItem, changes, docChanges, propName); } else { changed = true; if (changes) { this._newChange(JsonOperation._addIndexFieldPath(fieldPath, position), propName, newArrayItem, oldArrayItem, docChanges, "ArrayValueChanged"); } } } else if (!oldArrayItem) { if (newArrayItem) { changed = true; if (changes) { this._newChange(JsonOperation._addIndexFieldPath(fieldPath, position), propName, newArrayItem, oldArrayItem, docChanges, "ArrayValueAdded"); } } } else { if (oldArrayItem !== newArrayItem) { if (changes) { this._newChange(JsonOperation._addIndexFieldPath(fieldPath, position), propName, newArrayItem, oldArrayItem, docChanges, "ArrayValueChanged"); } changed = true; } } position++; oldArrayItem = oldArray[position]; typeOfOldArrayItem = typeof oldArrayItem; newArrayItem = newArray[position]; typeOfNewArrayItem = typeof newArrayItem; } if (!changes) { return changed; } // if one of the arrays is larger than the other while (position < oldArray.length) { this._newChange(fieldPath, propName, null, oldArray[position], docChanges, "ArrayValueRemoved"); position++; } while (position < newArray.length) { this._newChange(fieldPath, propName, newArray[position], null, docChanges, "ArrayValueAdded"); position++; } return changed; } static _addIndexFieldPath(fieldPath, position) { return fieldPath + "[" + position + "]"; } static _newChange(fieldPath, name, newValue, oldValue, docChanges, change) { const documentsChanges = new DocumentsChanges(); documentsChanges.fieldName = name; documentsChanges.fieldNewValue = newValue; documentsChanges.fieldOldValue = oldValue; documentsChanges.change = change; documentsChanges.fieldPath = fieldPath; docChanges.push(documentsChanges); } } //# sourceMappingURL=JsonOperation.js.map