matrix-react-sdk
Version:
SDK for matrix.org using React
154 lines (144 loc) • 17.6 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.isObject = isObject;
exports.objectClone = objectClone;
exports.objectDiff = objectDiff;
exports.objectExcluding = objectExcluding;
exports.objectHasDiff = objectHasDiff;
exports.objectKeyChanges = objectKeyChanges;
exports.objectShallowClone = objectShallowClone;
exports.objectWithOnly = objectWithOnly;
var _arrays = require("./arrays");
/*
Copyright 2024 New Vector Ltd.
Copyright 2020, 2021 The Matrix.org Foundation C.I.C.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
Please see LICENSE files in the repository root for full details.
*/
/**
* Gets a new object which represents the provided object, excluding some properties.
* @param a The object to strip properties of. Must be defined.
* @param props The property names to remove.
* @returns The new object without the provided properties.
*/
function objectExcluding(a, props) {
// We use a Map to avoid hammering the `delete` keyword, which is slow and painful.
const tempMap = new Map(Object.entries(a));
for (const prop of props) {
tempMap.delete(prop);
}
// Convert the map to an object again
return Array.from(tempMap.entries()).reduce((c, [k, v]) => {
c[k] = v;
return c;
}, {});
}
/**
* Gets a new object which represents the provided object, with only some properties
* included.
* @param a The object to clone properties of. Must be defined.
* @param props The property names to keep.
* @returns The new object with only the provided properties.
*/
function objectWithOnly(a, props) {
const existingProps = Object.keys(a);
const diff = (0, _arrays.arrayDiff)(existingProps, props);
if (diff.removed.length === 0) {
return objectShallowClone(a);
} else {
return objectExcluding(a, diff.removed);
}
}
/**
* Clones an object to a caller-controlled depth. When a propertyCloner is supplied, the
* object's properties will be passed through it with the return value used as the new
* object's type. This is intended to be used to deep clone a reference, but without
* having to deep clone the entire object. This function is safe to call recursively within
* the propertyCloner.
* @param a The object to clone. Must be defined.
* @param propertyCloner The function to clone the properties of the object with, optionally.
* First argument is the property key with the second being the current value.
* @returns A cloned object.
*/
function objectShallowClone(a, propertyCloner) {
const newObj = {};
for (const [k, v] of Object.entries(a)) {
newObj[k] = v;
if (propertyCloner) {
newObj[k] = propertyCloner(k, v);
}
}
return newObj;
}
/**
* Determines if any keys were added, removed, or changed between two objects.
* For changes, simple triple equal comparisons are done, not in-depth
* tree checking.
* @param a The first object. Must be defined.
* @param b The second object. Must be defined.
* @returns True if there's a difference between the objects, false otherwise
*/
function objectHasDiff(a, b) {
if (a === b) return false;
const aKeys = Object.keys(a);
const bKeys = Object.keys(b);
if (aKeys.length !== bKeys.length) return true;
const possibleChanges = (0, _arrays.arrayIntersection)(aKeys, bKeys);
// if the amalgamation of both sets of keys has the a different length to the inputs then there must be a change
if (possibleChanges.length !== aKeys.length) return true;
return possibleChanges.some(k => a[k] !== b[k]);
}
/**
* Determines the keys added, changed, and removed between two objects.
* For changes, simple triple equal comparisons are done, not in-depth
* tree checking.
* @param a The first object. Must be defined.
* @param b The second object. Must be defined.
* @returns The difference between the keys of each object.
*/
function objectDiff(a, b) {
const aKeys = Object.keys(a);
const bKeys = Object.keys(b);
const keyDiff = (0, _arrays.arrayDiff)(aKeys, bKeys);
const possibleChanges = (0, _arrays.arrayIntersection)(aKeys, bKeys);
const changes = possibleChanges.filter(k => a[k] !== b[k]);
return {
changed: changes,
added: keyDiff.added,
removed: keyDiff.removed
};
}
/**
* Gets all the key changes (added, removed, or value difference) between
* two objects. Triple equals is used to compare values, not in-depth tree
* checking.
* @param a The first object. Must be defined.
* @param b The second object. Must be defined.
* @returns The keys which have been added, removed, or changed between the
* two objects.
*/
function objectKeyChanges(a, b) {
const diff = objectDiff(a, b);
return (0, _arrays.arrayUnion)(diff.removed, diff.added, diff.changed);
}
/**
* Clones an object by running it through JSON parsing. Note that this
* will destroy any complicated object types which do not translate to
* JSON.
* @param obj The object to clone.
* @returns The cloned object
*/
function objectClone(obj) {
return JSON.parse(JSON.stringify(obj));
}
/**
* Simple object check.
* @param item
* @returns {boolean}
*/
function isObject(item) {
return item && typeof item === "object" && !Array.isArray(item);
}
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfYXJyYXlzIiwicmVxdWlyZSIsIm9iamVjdEV4Y2x1ZGluZyIsImEiLCJwcm9wcyIsInRlbXBNYXAiLCJNYXAiLCJPYmplY3QiLCJlbnRyaWVzIiwicHJvcCIsImRlbGV0ZSIsIkFycmF5IiwiZnJvbSIsInJlZHVjZSIsImMiLCJrIiwidiIsIm9iamVjdFdpdGhPbmx5IiwiZXhpc3RpbmdQcm9wcyIsImtleXMiLCJkaWZmIiwiYXJyYXlEaWZmIiwicmVtb3ZlZCIsImxlbmd0aCIsIm9iamVjdFNoYWxsb3dDbG9uZSIsInByb3BlcnR5Q2xvbmVyIiwibmV3T2JqIiwib2JqZWN0SGFzRGlmZiIsImIiLCJhS2V5cyIsImJLZXlzIiwicG9zc2libGVDaGFuZ2VzIiwiYXJyYXlJbnRlcnNlY3Rpb24iLCJzb21lIiwib2JqZWN0RGlmZiIsImtleURpZmYiLCJjaGFuZ2VzIiwiZmlsdGVyIiwiY2hhbmdlZCIsImFkZGVkIiwib2JqZWN0S2V5Q2hhbmdlcyIsImFycmF5VW5pb24iLCJvYmplY3RDbG9uZSIsIm9iaiIsIkpTT04iLCJwYXJzZSIsInN0cmluZ2lmeSIsImlzT2JqZWN0IiwiaXRlbSIsImlzQXJyYXkiXSwic291cmNlcyI6WyIuLi8uLi9zcmMvdXRpbHMvb2JqZWN0cy50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuQ29weXJpZ2h0IDIwMjQgTmV3IFZlY3RvciBMdGQuXG5Db3B5cmlnaHQgMjAyMCwgMjAyMSBUaGUgTWF0cml4Lm9yZyBGb3VuZGF0aW9uIEMuSS5DLlxuXG5TUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQUdQTC0zLjAtb25seSBPUiBHUEwtMy4wLW9ubHlcblBsZWFzZSBzZWUgTElDRU5TRSBmaWxlcyBpbiB0aGUgcmVwb3NpdG9yeSByb290IGZvciBmdWxsIGRldGFpbHMuXG4qL1xuXG5pbXBvcnQgeyBhcnJheURpZmYsIGFycmF5VW5pb24sIGFycmF5SW50ZXJzZWN0aW9uIH0gZnJvbSBcIi4vYXJyYXlzXCI7XG5cbnR5cGUgT2JqZWN0RXhjbHVkaW5nPE8gZXh0ZW5kcyB7fSwgUCBleHRlbmRzIChrZXlvZiBPKVtdPiA9IHsgW2sgaW4gRXhjbHVkZTxrZXlvZiBPLCBQW251bWJlcl0+XTogT1trXSB9O1xuXG4vKipcbiAqIEdldHMgYSBuZXcgb2JqZWN0IHdoaWNoIHJlcHJlc2VudHMgdGhlIHByb3ZpZGVkIG9iamVjdCwgZXhjbHVkaW5nIHNvbWUgcHJvcGVydGllcy5cbiAqIEBwYXJhbSBhIFRoZSBvYmplY3QgdG8gc3RyaXAgcHJvcGVydGllcyBvZi4gTXVzdCBiZSBkZWZpbmVkLlxuICogQHBhcmFtIHByb3BzIFRoZSBwcm9wZXJ0eSBuYW1lcyB0byByZW1vdmUuXG4gKiBAcmV0dXJucyBUaGUgbmV3IG9iamVjdCB3aXRob3V0IHRoZSBwcm92aWRlZCBwcm9wZXJ0aWVzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gb2JqZWN0RXhjbHVkaW5nPE8gZXh0ZW5kcyB7fSwgUCBleHRlbmRzIEFycmF5PGtleW9mIE8+PihhOiBPLCBwcm9wczogUCk6IE9iamVjdEV4Y2x1ZGluZzxPLCBQPiB7XG4gICAgLy8gV2UgdXNlIGEgTWFwIHRvIGF2b2lkIGhhbW1lcmluZyB0aGUgYGRlbGV0ZWAga2V5d29yZCwgd2hpY2ggaXMgc2xvdyBhbmQgcGFpbmZ1bC5cbiAgICBjb25zdCB0ZW1wTWFwID0gbmV3IE1hcDxrZXlvZiBPLCBhbnk+KE9iamVjdC5lbnRyaWVzKGEpIGFzIFtrZXlvZiBPLCBhbnldW10pO1xuICAgIGZvciAoY29uc3QgcHJvcCBvZiBwcm9wcykge1xuICAgICAgICB0ZW1wTWFwLmRlbGV0ZShwcm9wKTtcbiAgICB9XG5cbiAgICAvLyBDb252ZXJ0IHRoZSBtYXAgdG8gYW4gb2JqZWN0IGFnYWluXG4gICAgcmV0dXJuIEFycmF5LmZyb20odGVtcE1hcC5lbnRyaWVzKCkpLnJlZHVjZSgoYywgW2ssIHZdKSA9PiB7XG4gICAgICAgIGNba10gPSB2O1xuICAgICAgICByZXR1cm4gYztcbiAgICB9LCB7fSBhcyBPKTtcbn1cblxuLyoqXG4gKiBHZXRzIGEgbmV3IG9iamVjdCB3aGljaCByZXByZXNlbnRzIHRoZSBwcm92aWRlZCBvYmplY3QsIHdpdGggb25seSBzb21lIHByb3BlcnRpZXNcbiAqIGluY2x1ZGVkLlxuICogQHBhcmFtIGEgVGhlIG9iamVjdCB0byBjbG9uZSBwcm9wZXJ0aWVzIG9mLiBNdXN0IGJlIGRlZmluZWQuXG4gKiBAcGFyYW0gcHJvcHMgVGhlIHByb3BlcnR5IG5hbWVzIHRvIGtlZXAuXG4gKiBAcmV0dXJucyBUaGUgbmV3IG9iamVjdCB3aXRoIG9ubHkgdGhlIHByb3ZpZGVkIHByb3BlcnRpZXMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBvYmplY3RXaXRoT25seTxPIGV4dGVuZHMge30sIFAgZXh0ZW5kcyBBcnJheTxrZXlvZiBPPj4oYTogTywgcHJvcHM6IFApOiB7IFtrIGluIFBbbnVtYmVyXV06IE9ba10gfSB7XG4gICAgY29uc3QgZXhpc3RpbmdQcm9wcyA9IE9iamVjdC5rZXlzKGEpIGFzIChrZXlvZiBPKVtdO1xuICAgIGNvbnN0IGRpZmYgPSBhcnJheURpZmYoZXhpc3RpbmdQcm9wcywgcHJvcHMpO1xuICAgIGlmIChkaWZmLnJlbW92ZWQubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHJldHVybiBvYmplY3RTaGFsbG93Q2xvbmUoYSk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIG9iamVjdEV4Y2x1ZGluZyhhLCBkaWZmLnJlbW92ZWQpIGFzIHsgW2sgaW4gUFtudW1iZXJdXTogT1trXSB9O1xuICAgIH1cbn1cblxuLyoqXG4gKiBDbG9uZXMgYW4gb2JqZWN0IHRvIGEgY2FsbGVyLWNvbnRyb2xsZWQgZGVwdGguIFdoZW4gYSBwcm9wZXJ0eUNsb25lciBpcyBzdXBwbGllZCwgdGhlXG4gKiBvYmplY3QncyBwcm9wZXJ0aWVzIHdpbGwgYmUgcGFzc2VkIHRocm91Z2ggaXQgd2l0aCB0aGUgcmV0dXJuIHZhbHVlIHVzZWQgYXMgdGhlIG5ld1xuICogb2JqZWN0J3MgdHlwZS4gVGhpcyBpcyBpbnRlbmRlZCB0byBiZSB1c2VkIHRvIGRlZXAgY2xvbmUgYSByZWZlcmVuY2UsIGJ1dCB3aXRob3V0XG4gKiBoYXZpbmcgdG8gZGVlcCBjbG9uZSB0aGUgZW50aXJlIG9iamVjdC4gVGhpcyBmdW5jdGlvbiBpcyBzYWZlIHRvIGNhbGwgcmVjdXJzaXZlbHkgd2l0aGluXG4gKiB0aGUgcHJvcGVydHlDbG9uZXIuXG4gKiBAcGFyYW0gYSBUaGUgb2JqZWN0IHRvIGNsb25lLiBNdXN0IGJlIGRlZmluZWQuXG4gKiBAcGFyYW0gcHJvcGVydHlDbG9uZXIgVGhlIGZ1bmN0aW9uIHRvIGNsb25lIHRoZSBwcm9wZXJ0aWVzIG9mIHRoZSBvYmplY3Qgd2l0aCwgb3B0aW9uYWxseS5cbiAqIEZpcnN0IGFyZ3VtZW50IGlzIHRoZSBwcm9wZXJ0eSBrZXkgd2l0aCB0aGUgc2Vjb25kIGJlaW5nIHRoZSBjdXJyZW50IHZhbHVlLlxuICogQHJldHVybnMgQSBjbG9uZWQgb2JqZWN0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gb2JqZWN0U2hhbGxvd0Nsb25lPE8gZXh0ZW5kcyB7fT4oYTogTywgcHJvcGVydHlDbG9uZXI/OiAoazoga2V5b2YgTywgdjogT1trZXlvZiBPXSkgPT4gYW55KTogTyB7XG4gICAgY29uc3QgbmV3T2JqID0ge30gYXMgTztcbiAgICBmb3IgKGNvbnN0IFtrLCB2XSBvZiBPYmplY3QuZW50cmllcyhhKSBhcyBba2V5b2YgTywgT1trZXlvZiBPXV1bXSkge1xuICAgICAgICBuZXdPYmpba10gPSB2O1xuICAgICAgICBpZiAocHJvcGVydHlDbG9uZXIpIHtcbiAgICAgICAgICAgIG5ld09ialtrXSA9IHByb3BlcnR5Q2xvbmVyKGssIHYpO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBuZXdPYmo7XG59XG5cbi8qKlxuICogRGV0ZXJtaW5lcyBpZiBhbnkga2V5cyB3ZXJlIGFkZGVkLCByZW1vdmVkLCBvciBjaGFuZ2VkIGJldHdlZW4gdHdvIG9iamVjdHMuXG4gKiBGb3IgY2hhbmdlcywgc2ltcGxlIHRyaXBsZSBlcXVhbCBjb21wYXJpc29ucyBhcmUgZG9uZSwgbm90IGluLWRlcHRoXG4gKiB0cmVlIGNoZWNraW5nLlxuICogQHBhcmFtIGEgVGhlIGZpcnN0IG9iamVjdC4gTXVzdCBiZSBkZWZpbmVkLlxuICogQHBhcmFtIGIgVGhlIHNlY29uZCBvYmplY3QuIE11c3QgYmUgZGVmaW5lZC5cbiAqIEByZXR1cm5zIFRydWUgaWYgdGhlcmUncyBhIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgb2JqZWN0cywgZmFsc2Ugb3RoZXJ3aXNlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBvYmplY3RIYXNEaWZmPE8gZXh0ZW5kcyB7fT4oYTogTywgYjogTyk6IGJvb2xlYW4ge1xuICAgIGlmIChhID09PSBiKSByZXR1cm4gZmFsc2U7XG4gICAgY29uc3QgYUtleXMgPSBPYmplY3Qua2V5cyhhKTtcbiAgICBjb25zdCBiS2V5cyA9IE9iamVjdC5rZXlzKGIpO1xuICAgIGlmIChhS2V5cy5sZW5ndGggIT09IGJLZXlzLmxlbmd0aCkgcmV0dXJuIHRydWU7XG4gICAgY29uc3QgcG9zc2libGVDaGFuZ2VzID0gYXJyYXlJbnRlcnNlY3Rpb24oYUtleXMsIGJLZXlzKSBhcyBBcnJheTxrZXlvZiBPPjtcbiAgICAvLyBpZiB0aGUgYW1hbGdhbWF0aW9uIG9mIGJvdGggc2V0cyBvZiBrZXlzIGhhcyB0aGUgYSBkaWZmZXJlbnQgbGVuZ3RoIHRvIHRoZSBpbnB1dHMgdGhlbiB0aGVyZSBtdXN0IGJlIGEgY2hhbmdlXG4gICAgaWYgKHBvc3NpYmxlQ2hhbmdlcy5sZW5ndGggIT09IGFLZXlzLmxlbmd0aCkgcmV0dXJuIHRydWU7XG5cbiAgICByZXR1cm4gcG9zc2libGVDaGFuZ2VzLnNvbWUoKGspID0+IGFba10gIT09IGJba10pO1xufVxuXG50eXBlIERpZmY8Sz4gPSB7IGNoYW5nZWQ6IEtbXTsgYWRkZWQ6IEtbXTsgcmVtb3ZlZDogS1tdIH07XG5cbi8qKlxuICogRGV0ZXJtaW5lcyB0aGUga2V5cyBhZGRlZCwgY2hhbmdlZCwgYW5kIHJlbW92ZWQgYmV0d2VlbiB0d28gb2JqZWN0cy5cbiAqIEZvciBjaGFuZ2VzLCBzaW1wbGUgdHJpcGxlIGVxdWFsIGNvbXBhcmlzb25zIGFyZSBkb25lLCBub3QgaW4tZGVwdGhcbiAqIHRyZWUgY2hlY2tpbmcuXG4gKiBAcGFyYW0gYSBUaGUgZmlyc3Qgb2JqZWN0LiBNdXN0IGJlIGRlZmluZWQuXG4gKiBAcGFyYW0gYiBUaGUgc2Vjb25kIG9iamVjdC4gTXVzdCBiZSBkZWZpbmVkLlxuICogQHJldHVybnMgVGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUga2V5cyBvZiBlYWNoIG9iamVjdC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG9iamVjdERpZmY8TyBleHRlbmRzIHt9PihhOiBPLCBiOiBPKTogRGlmZjxrZXlvZiBPPiB7XG4gICAgY29uc3QgYUtleXMgPSBPYmplY3Qua2V5cyhhKSBhcyAoa2V5b2YgTylbXTtcbiAgICBjb25zdCBiS2V5cyA9IE9iamVjdC5rZXlzKGIpIGFzIChrZXlvZiBPKVtdO1xuICAgIGNvbnN0IGtleURpZmYgPSBhcnJheURpZmYoYUtleXMsIGJLZXlzKTtcbiAgICBjb25zdCBwb3NzaWJsZUNoYW5nZXMgPSBhcnJheUludGVyc2VjdGlvbihhS2V5cywgYktleXMpO1xuICAgIGNvbnN0IGNoYW5nZXMgPSBwb3NzaWJsZUNoYW5nZXMuZmlsdGVyKChrKSA9PiBhW2tdICE9PSBiW2tdKTtcblxuICAgIHJldHVybiB7IGNoYW5nZWQ6IGNoYW5nZXMsIGFkZGVkOiBrZXlEaWZmLmFkZGVkLCByZW1vdmVkOiBrZXlEaWZmLnJlbW92ZWQgfTtcbn1cblxuLyoqXG4gKiBHZXRzIGFsbCB0aGUga2V5IGNoYW5nZXMgKGFkZGVkLCByZW1vdmVkLCBvciB2YWx1ZSBkaWZmZXJlbmNlKSBiZXR3ZWVuXG4gKiB0d28gb2JqZWN0cy4gVHJpcGxlIGVxdWFscyBpcyB1c2VkIHRvIGNvbXBhcmUgdmFsdWVzLCBub3QgaW4tZGVwdGggdHJlZVxuICogY2hlY2tpbmcuXG4gKiBAcGFyYW0gYSBUaGUgZmlyc3Qgb2JqZWN0LiBNdXN0IGJlIGRlZmluZWQuXG4gKiBAcGFyYW0gYiBUaGUgc2Vjb25kIG9iamVjdC4gTXVzdCBiZSBkZWZpbmVkLlxuICogQHJldHVybnMgVGhlIGtleXMgd2hpY2ggaGF2ZSBiZWVuIGFkZGVkLCByZW1vdmVkLCBvciBjaGFuZ2VkIGJldHdlZW4gdGhlXG4gKiB0d28gb2JqZWN0cy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG9iamVjdEtleUNoYW5nZXM8TyBleHRlbmRzIHt9PihhOiBPLCBiOiBPKTogKGtleW9mIE8pW10ge1xuICAgIGNvbnN0IGRpZmYgPSBvYmplY3REaWZmKGEsIGIpO1xuICAgIHJldHVybiBhcnJheVVuaW9uKGRpZmYucmVtb3ZlZCwgZGlmZi5hZGRlZCwgZGlmZi5jaGFuZ2VkKTtcbn1cblxuLyoqXG4gKiBDbG9uZXMgYW4gb2JqZWN0IGJ5IHJ1bm5pbmcgaXQgdGhyb3VnaCBKU09OIHBhcnNpbmcuIE5vdGUgdGhhdCB0aGlzXG4gKiB3aWxsIGRlc3Ryb3kgYW55IGNvbXBsaWNhdGVkIG9iamVjdCB0eXBlcyB3aGljaCBkbyBub3QgdHJhbnNsYXRlIHRvXG4gKiBKU09OLlxuICogQHBhcmFtIG9iaiBUaGUgb2JqZWN0IHRvIGNsb25lLlxuICogQHJldHVybnMgVGhlIGNsb25lZCBvYmplY3RcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG9iamVjdENsb25lPE8gZXh0ZW5kcyB7fT4ob2JqOiBPKTogTyB7XG4gICAgcmV0dXJuIEpTT04ucGFyc2UoSlNPTi5zdHJpbmdpZnkob2JqKSk7XG59XG5cbi8qKlxuICogU2ltcGxlIG9iamVjdCBjaGVjay5cbiAqIEBwYXJhbSBpdGVtXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzT2JqZWN0KGl0ZW06IGFueSk6IGl0ZW0gaXMgb2JqZWN0IHtcbiAgICByZXR1cm4gaXRlbSAmJiB0eXBlb2YgaXRlbSA9PT0gXCJvYmplY3RcIiAmJiAhQXJyYXku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