const defaults = Object.freeze({ ignoreUnknown: false, respectType: false, respectFunctionNames: false, respectFunctionProperties: false, unorderedObjects: true, unorderedArrays: false, unorderedSets: false, excludeKeys: void 0, excludeValues: void 0, replacer: void 0 }); function objectHash(object, options) { if (options) { options = { ...defaults, ...options }; } else { options = defaults; } const hasher = createHasher(options); hasher.dispatch(object); return hasher.toString(); } const defaultPrototypesKeys = Object.freeze([ "prototype", "__proto__", "constructor" ]); function createHasher(options) { let buff = ""; let context = /* @__PURE__ */ new Map(); const write = (str) => { buff += str; }; return { toString() { return buff; }, getContext() { return context; }, dispatch(value) { if (options.replacer) { value = options.replacer(value); } const type = value === null ? "null" : typeof value; return this[type](value); }, object(object) { if (object && typeof object.toJSON === "function") { return this.object(object.toJSON()); } const objString = Object.prototype.toString.call(object); let objType = ""; const objectLength = objString.length; if (objectLength < 10) { objType = "unknown:[" + objString + "]"; } else { objType = objString.slice(8, objectLength - 1); } objType = objType.toLowerCase(); let objectNumber = null; if ((objectNumber = context.get(object)) === void 0) { context.set(object, context.size); } else { return this.dispatch("[CIRCULAR:" + objectNumber + "]"); } if (typeof Buffer !== "undefined" && Buffer.isBuffer && Buffer.isBuffer(object)) { write("buffer:"); return write(object.toString("utf8")); } if (objType !== "object" && objType !== "function" && objType !== "asyncfunction") { if (this[objType]) { this[objType](object); } else if (!options.ignoreUnknown) { this.unkown(object, objType); } } else { let keys = Object.keys(object); if (options.unorderedObjects) { keys = keys.sort(); } let extraKeys = []; if (options.respectType !== false && !isNativeFunction(object)) { extraKeys = defaultPrototypesKeys; } if (options.excludeKeys) { keys = keys.filter((key) => { return !options.excludeKeys(key); }); extraKeys = extraKeys.filter((key) => { return !options.excludeKeys(key); }); } write("object:" + (keys.length + extraKeys.length) + ":"); const dispatchForKey = (key) => { this.dispatch(key); write(":"); if (!options.excludeValues) { this.dispatch(object[key]); } write(","); }; for (const key of keys) { dispatchForKey(key); } for (const key of extraKeys) { dispatchForKey(key); } } }, array(arr, unordered) { unordered = unordered === void 0 ? options.unorderedArrays !== false : unordered; write("array:" + arr.length + ":"); if (!unordered || arr.length <= 1) { for (const entry of arr) { this.dispatch(entry); } return; } const contextAdditions = /* @__PURE__ */ new Map(); const entries = arr.map((entry) => { const hasher = createHasher(options); hasher.dispatch(entry); for (const [key, value] of hasher.getContext()) { contextAdditions.set(key, value); } return hasher.toString(); }); context = contextAdditions; entries.sort(); return this.array(entries, false); }, date(date) { return write("date:" + date.toJSON()); }, symbol(sym) { return write("symbol:" + sym.toString()); }, unkown(value, type) { write(type); if (!value) { return; } write(":"); if (value && typeof value.entries === "function") { return this.array( Array.from(value.entries()), true /* ordered */ ); } }, error(err) { return write("error:" + err.toString()); }, boolean(bool) { return write("bool:" + bool); }, string(string) { write("string:" + string.length + ":"); write(string); }, function(fn) { write("fn:"); if (isNativeFunction(fn)) { this.dispatch("[native]"); } else { this.dispatch(fn.toString()); } if (options.respectFunctionNames !== false) { this.dispatch("function-name:" + String(fn.name)); } if (options.respectFunctionProperties) { this.object(fn); } }, number(number) { return write("number:" + number); }, xml(xml) { return write("xml:" + xml.toString()); }, null() { return write("Null"); }, undefined() { return write("Undefined"); }, regexp(regex) { return write("regex:" + regex.toString()); }, uint8array(arr) { write("uint8array:"); return this.dispatch(Array.prototype.slice.call(arr)); }, uint8clampedarray(arr) { write("uint8clampedarray:"); return this.dispatch(Array.prototype.slice.call(arr)); }, int8array(arr) { write("int8array:"); return this.dispatch(Array.prototype.slice.call(arr)); }, uint16array(arr) { write("uint16array:"); return this.dispatch(Array.prototype.slice.call(arr)); }, int16array(arr) { write("int16array:"); return this.dispatch(Array.prototype.slice.call(arr)); }, uint32array(arr) { write("uint32array:"); return this.dispatch(Array.prototype.slice.call(arr)); }, int32array(arr) { write("int32array:"); return this.dispatch(Array.prototype.slice.call(arr)); }, float32array(arr) { write("float32array:"); return this.dispatch(Array.prototype.slice.call(arr)); }, float64array(arr) { write("float64array:"); return this.dispatch(Array.prototype.slice.call(arr)); }, arraybuffer(arr) { write("arraybuffer:"); return this.dispatch(new Uint8Array(arr)); }, url(url) { return write("url:" + url.toString()); }, map(map) { write("map:"); const arr = [...map]; return this.array(arr, options.unorderedSets !== false); }, set(set) { write("set:"); const arr = [...set]; return this.array(arr, options.unorderedSets !== false); }, file(file) { write("file:"); return this.dispatch([file.name, file.size, file.type, file.lastModfied]); }, blob() { if (options.ignoreUnknown) { return write("[blob]"); } throw new Error( 'Hashing Blob objects is currently not supported\nUse "options.replacer" or "options.ignoreUnknown"\n' ); }, domwindow() { return write("domwindow"); }, bigint(number) { return write("bigint:" + number.toString()); }, /* Node.js standard native objects */ process() { return write("process"); }, timer() { return write("timer"); }, pipe() { return write("pipe"); }, tcp() { return write("tcp"); }, udp() { return write("udp"); }, tty() { return write("tty"); }, statwatcher() { return write("statwatcher"); }, securecontext() { return write("securecontext"); }, connection() { return write("connection"); }, zlib() { return write("zlib"); }, context() { return write("context"); }, nodescript() { return write("nodescript"); }, httpparser() { return write("httpparser"); }, dataview() { return write("dataview"); }, signal() { return write("signal"); }, fsevent() { return write("fsevent"); }, tlswrap() { return write("tlswrap"); } }; } const nativeFunc = "[native code] }"; const nativeFuncLength = nativeFunc.length; function isNativeFunction(f) { if (typeof f !== "function") { return false; } return Function.prototype.toString.call(f).slice(-nativeFuncLength) === nativeFunc; } class WordArray { constructor(words, sigBytes) { words = this.words = words || []; this.sigBytes = sigBytes === void 0 ? words.length * 4 : sigBytes; } toString(encoder) { return (encoder || Hex).stringify(this); } concat(wordArray) { this.clamp(); if (this.sigBytes % 4) { for (let i = 0; i < wordArray.sigBytes; i++) { const thatByte = wordArray.words[i >>> 2] >>> 24 - i % 4 * 8 & 255; this.words[this.sigBytes + i >>> 2] |= thatByte << 24 - (this.sigBytes + i) % 4 * 8; } } else { for (let j = 0; j < wordArray.sigBytes; j += 4) { this.words[this.sigBytes + j >>> 2] = wordArray.words[j >>> 2]; } } this.sigBytes += wordArray.sigBytes; return this; } clamp() { this.words[this.sigBytes >>> 2] &= 4294967295 << 32 - this.sigBytes % 4 * 8; this.words.length = Math.ceil(this.sigBytes / 4); } clone() { return new WordArray([...this.words]); } } const Hex = { stringify(wordArray) { const hexChars = []; for (let i = 0; i < wordArray.sigBytes; i++) { const bite = wordArray.words[i >>> 2] >>> 24 - i % 4 * 8 & 255; hexChars.push((bite >>> 4).toString(16), (bite & 15).toString(16)); } return hexChars.join(""); } }; const Base64 = { stringify(wordArray) { const keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; const base64Chars = []; for (let i = 0; i < wordArray.sigBytes; i += 3) { const byte1 = wordArray.words[i >>> 2] >>> 24 - i % 4 * 8 & 255; const byte2 = wordArray.words[i + 1 >>> 2] >>> 24 - (i + 1) % 4 * 8 & 255; const byte3 = wordArray.words[i + 2 >>> 2] >>> 24 - (i + 2) % 4 * 8 & 255; const triplet = byte1 << 16 | byte2 << 8 | byte3; for (let j = 0; j < 4 && i * 8 + j * 6 < wordArray.sigBytes * 8; j++) { base64Chars.push(keyStr.charAt(triplet >>> 6 * (3 - j) & 63)); } } return base64Chars.join(""); } }; const Latin1 = { parse(latin1Str) { const latin1StrLength = latin1Str.length; const words = []; for (let i = 0; i < latin1StrLength; i++) { words[i >>> 2] |= (latin1Str.charCodeAt(i) & 255) << 24 - i % 4 * 8; } return new WordArray(words, latin1StrLength); } }; const Utf8 = { parse(utf8Str) { return Latin1.parse(unescape(encodeURIComponent(utf8Str))); } }; class BufferedBlockAlgorithm { constructor() { this._data = new WordArray(); this._nDataBytes = 0; this._minBufferSize = 0; this.blockSize = 512 / 32; } reset() { this._data = new WordArray(); this._nDataBytes = 0; } _append(data) { if (typeof data === "string") { data = Utf8.parse(data); } this._data.concat(data); this._nDataBytes += data.sigBytes; } // eslint-disable-next-line @typescript-eslint/no-unused-vars _doProcessBlock(_dataWords, _offset) { } _process(doFlush) { let processedWords; let nBlocksReady = this._data.sigBytes / (this.blockSize * 4); if (doFlush) { nBlocksReady = Math.ceil(nBlocksReady); } else { nBlocksReady = Math.max((nBlocksReady | 0) - this._minBufferSize, 0); } const nWordsReady = nBlocksReady * this.blockSize; const nBytesReady = Math.min(nWordsReady * 4, this._data.sigBytes); if (nWordsReady) { for (let offset = 0; offset < nWordsReady; offset += this.blockSize) { this._doProcessBlock(this._data.words, offset); } processedWords = this._data.words.splice(0, nWordsReady); this._data.sigBytes -= nBytesReady; } return new WordArray(processedWords, nBytesReady); } } class Hasher extends BufferedBlockAlgorithm { update(messageUpdate) { this._append(messageUpdate); this._process(); return this; } finalize(messageUpdate) { if (messageUpdate) { this._append(messageUpdate); } } } const H = [ 1779033703, -1150833019, 1013904242, -1521486534, 1359893119, -1694144372, 528734635, 1541459225 ]; const K = [ 1116352408, 1899447441, -1245643825, -373957723, 961987163, 1508970993, -1841331548, -1424204075, -670586216, 310598401, 607225278, 1426881987, 1925078388, -2132889090, -1680079193, -1046744716, -459576895, -272742522, 264347078, 604807628, 770255983, 1249150122, 1555081692, 1996064986, -1740746414, -1473132947, -1341970488, -1084653625, -958395405, -710438585, 113926993, 338241895, 666307205, 773529912, 1294757372, 1396182291, 1695183700, 1986661051, -2117940946, -1838011259, -1564481375, -1474664885, -1035236496, -949202525, -778901479, -694614492, -200395387, 275423344, 430227734, 506948616, 659060556, 883997877, 958139571, 1322822218, 1537002063, 1747873779, 1955562222, 2024104815, -2067236844, -1933114872, -1866530822, -1538233109, -1090935817, -965641998 ]; const W = []; class SHA256 extends Hasher { constructor() { super(...arguments); this._hash = new WordArray([...H]); } reset() { super.reset(); this._hash = new WordArray([...H]); } _doProcessBlock(M, offset) { const H2 = this._hash.words; let a = H2[0]; let b = H2[1]; let c = H2[2]; let d = H2[3]; let e = H2[4]; let f = H2[5]; let g = H2[6]; let h = H2[7]; for (let i = 0; i < 64; i++) { if (i < 16) { W[i] = M[offset + i] | 0; } else { const gamma0x = W[i - 15]; const gamma0 = (gamma0x << 25 | gamma0x >>> 7) ^ (gamma0x << 14 | gamma0x >>> 18) ^ gamma0x >>> 3; const gamma1x = W[i - 2]; const gamma1 = (gamma1x << 15 | gamma1x >>> 17) ^ (gamma1x << 13 | gamma1x >>> 19) ^ gamma1x >>> 10; W[i] = gamma0 + W[i - 7] + gamma1 + W[i - 16]; } const ch = e & f ^ ~e & g; const maj = a & b ^ a & c ^ b & c; const sigma0 = (a << 30 | a >>> 2) ^ (a << 19 | a >>> 13) ^ (a << 10 | a >>> 22); const sigma1 = (e << 26 | e >>> 6) ^ (e << 21 | e >>> 11) ^ (e << 7 | e >>> 25); const t1 = h + sigma1 + ch + K[i] + W[i]; const t2 = sigma0 + maj; h = g; g = f; f = e; e = d + t1 | 0; d = c; c = b; b = a; a = t1 + t2 | 0; } H2[0] = H2[0] + a | 0; H2[1] = H2[1] + b | 0; H2[2] = H2[2] + c | 0; H2[3] = H2[3] + d | 0; H2[4] = H2[4] + e | 0; H2[5] = H2[5] + f | 0; H2[6] = H2[6] + g | 0; H2[7] = H2[7] + h | 0; } finalize(messageUpdate) { super.finalize(messageUpdate); const nBitsTotal = this._nDataBytes * 8; const nBitsLeft = this._data.sigBytes * 8; this._data.words[nBitsLeft >>> 5] |= 128 << 24 - nBitsLeft % 32; this._data.words[(nBitsLeft + 64 >>> 9 << 4) + 14] = Math.floor( nBitsTotal / 4294967296 ); this._data.words[(nBitsLeft + 64 >>> 9 << 4) + 15] = nBitsTotal; this._data.sigBytes = this._data.words.length * 4; this._process(); return this._hash; } } function sha256(message) { return new SHA256().finalize(message).toString(); } function sha256base64(message) { return new SHA256().finalize(message).toString(Base64); } function hash(object, options = {}) { const hashed = typeof object === "string" ? object : objectHash(object, options); return sha256base64(hashed).slice(0, 10); } function murmurHash(key, seed = 0) { if (typeof key === "string") { key = createBuffer(key); } let i = 0; let h1 = seed; let k1; let h1b; const remainder = key.length & 3; const bytes = key.length - remainder; const c1 = 3432918353; const c2 = 461845907; while (i < bytes) { k1 = key[i] & 255 | (key[++i] & 255) << 8 | (key[++i] & 255) << 16 | (key[++i] & 255) << 24; ++i; k1 = (k1 & 65535) * c1 + (((k1 >>> 16) * c1 & 65535) << 16) & 4294967295; k1 = k1 << 15 | k1 >>> 17; k1 = (k1 & 65535) * c2 + (((k1 >>> 16) * c2 & 65535) << 16) & 4294967295; h1 ^= k1; h1 = h1 << 13 | h1 >>> 19; h1b = (h1 & 65535) * 5 + (((h1 >>> 16) * 5 & 65535) << 16) & 4294967295; h1 = (h1b & 65535) + 27492 + (((h1b >>> 16) + 58964 & 65535) << 16); } k1 = 0; switch (remainder) { case 3: { k1 ^= (key[i + 2] & 255) << 16; break; } case 2: { k1 ^= (key[i + 1] & 255) << 8; break; } case 1: { k1 ^= key[i] & 255; k1 = (k1 & 65535) * c1 + (((k1 >>> 16) * c1 & 65535) << 16) & 4294967295; k1 = k1 << 15 | k1 >>> 17; k1 = (k1 & 65535) * c2 + (((k1 >>> 16) * c2 & 65535) << 16) & 4294967295; h1 ^= k1; } } h1 ^= key.length; h1 ^= h1 >>> 16; h1 = (h1 & 65535) * 2246822507 + (((h1 >>> 16) * 2246822507 & 65535) << 16) & 4294967295; h1 ^= h1 >>> 13; h1 = (h1 & 65535) * 3266489909 + (((h1 >>> 16) * 3266489909 & 65535) << 16) & 4294967295; h1 ^= h1 >>> 16; return h1 >>> 0; } function createBuffer(val) { return new TextEncoder().encode(val); } function isEqual(object1, object2, hashOptions = {}) { if (object1 === object2) { return true; } if (objectHash(object1, hashOptions) === objectHash(object2, hashOptions)) { return true; } return false; } function diff(obj1, obj2, opts = {}) { const h1 = _toHashedObject(obj1, opts); const h2 = _toHashedObject(obj2, opts); return _diff(h1, h2, opts); } function _diff(h1, h2, opts = {}) { const diffs = []; const allProps = /* @__PURE__ */ new Set([ ...Object.keys(h1.props || {}), ...Object.keys(h2.props || {}) ]); if (h1.props && h2.props) { for (const prop of allProps) { const p1 = h1.props[prop]; const p2 = h2.props[prop]; if (p1 && p2) { diffs.push(..._diff(h1.props?.[prop], h2.props?.[prop], opts)); } else if (p1 || p2) { diffs.push( new DiffEntry((p2 || p1).key, p1 ? "removed" : "added", p2, p1) ); } } } if (allProps.size === 0 && h1.hash !== h2.hash) { diffs.push(new DiffEntry((h2 || h1).key, "changed", h2, h1)); } return diffs; } function _toHashedObject(obj, opts, key = "") { if (obj && typeof obj !== "object") { return new DiffHashedObject(key, obj, objectHash(obj, opts)); } const props = {}; const hashes = []; for (const _key in obj) { props[_key] = _toHashedObject( obj[_key], opts, key ? `${key}.${_key}` : _key ); hashes.push(props[_key].hash); } return new DiffHashedObject(key, obj, `{${hashes.join(":")}}`, props); } class DiffEntry { // eslint-disable-next-line no-useless-constructor constructor(key, type, newValue, oldValue) { this.key = key; this.type = type; this.newValue = newValue; this.oldValue = oldValue; } toString() { return this.toJSON(); } toJSON() { switch (this.type) { case "added": { return `Added \`${this.key}\``; } case "removed": { return `Removed \`${this.key}\``; } case "changed": { return `Changed \`${this.key}\` from \`${this.oldValue?.toString() || "-"}\` to \`${this.newValue.toString()}\``; } } } } class DiffHashedObject { // eslint-disable-next-line no-useless-constructor constructor(key, value, hash, props) { this.key = key; this.value = value; this.hash = hash; this.props = props; } toString() { if (this.props) { return `{${Object.keys(this.props).join(",")}}`; } else { return JSON.stringify(this.value); } } toJSON() { const k = this.key || "."; if (this.props) { return `${k}({${Object.keys(this.props).join(",")}})`; } return `${k}(${this.value})`; } } export { diff, hash, isEqual, murmurHash, objectHash, sha256, sha256base64 };