index.mjs 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765
  1. const defaults = Object.freeze({
  2. ignoreUnknown: false,
  3. respectType: false,
  4. respectFunctionNames: false,
  5. respectFunctionProperties: false,
  6. unorderedObjects: true,
  7. unorderedArrays: false,
  8. unorderedSets: false,
  9. excludeKeys: void 0,
  10. excludeValues: void 0,
  11. replacer: void 0
  12. });
  13. function objectHash(object, options) {
  14. if (options) {
  15. options = { ...defaults, ...options };
  16. } else {
  17. options = defaults;
  18. }
  19. const hasher = createHasher(options);
  20. hasher.dispatch(object);
  21. return hasher.toString();
  22. }
  23. const defaultPrototypesKeys = Object.freeze([
  24. "prototype",
  25. "__proto__",
  26. "constructor"
  27. ]);
  28. function createHasher(options) {
  29. let buff = "";
  30. let context = /* @__PURE__ */ new Map();
  31. const write = (str) => {
  32. buff += str;
  33. };
  34. return {
  35. toString() {
  36. return buff;
  37. },
  38. getContext() {
  39. return context;
  40. },
  41. dispatch(value) {
  42. if (options.replacer) {
  43. value = options.replacer(value);
  44. }
  45. const type = value === null ? "null" : typeof value;
  46. return this[type](value);
  47. },
  48. object(object) {
  49. if (object && typeof object.toJSON === "function") {
  50. return this.object(object.toJSON());
  51. }
  52. const objString = Object.prototype.toString.call(object);
  53. let objType = "";
  54. const objectLength = objString.length;
  55. if (objectLength < 10) {
  56. objType = "unknown:[" + objString + "]";
  57. } else {
  58. objType = objString.slice(8, objectLength - 1);
  59. }
  60. objType = objType.toLowerCase();
  61. let objectNumber = null;
  62. if ((objectNumber = context.get(object)) === void 0) {
  63. context.set(object, context.size);
  64. } else {
  65. return this.dispatch("[CIRCULAR:" + objectNumber + "]");
  66. }
  67. if (typeof Buffer !== "undefined" && Buffer.isBuffer && Buffer.isBuffer(object)) {
  68. write("buffer:");
  69. return write(object.toString("utf8"));
  70. }
  71. if (objType !== "object" && objType !== "function" && objType !== "asyncfunction") {
  72. if (this[objType]) {
  73. this[objType](object);
  74. } else if (!options.ignoreUnknown) {
  75. this.unkown(object, objType);
  76. }
  77. } else {
  78. let keys = Object.keys(object);
  79. if (options.unorderedObjects) {
  80. keys = keys.sort();
  81. }
  82. let extraKeys = [];
  83. if (options.respectType !== false && !isNativeFunction(object)) {
  84. extraKeys = defaultPrototypesKeys;
  85. }
  86. if (options.excludeKeys) {
  87. keys = keys.filter((key) => {
  88. return !options.excludeKeys(key);
  89. });
  90. extraKeys = extraKeys.filter((key) => {
  91. return !options.excludeKeys(key);
  92. });
  93. }
  94. write("object:" + (keys.length + extraKeys.length) + ":");
  95. const dispatchForKey = (key) => {
  96. this.dispatch(key);
  97. write(":");
  98. if (!options.excludeValues) {
  99. this.dispatch(object[key]);
  100. }
  101. write(",");
  102. };
  103. for (const key of keys) {
  104. dispatchForKey(key);
  105. }
  106. for (const key of extraKeys) {
  107. dispatchForKey(key);
  108. }
  109. }
  110. },
  111. array(arr, unordered) {
  112. unordered = unordered === void 0 ? options.unorderedArrays !== false : unordered;
  113. write("array:" + arr.length + ":");
  114. if (!unordered || arr.length <= 1) {
  115. for (const entry of arr) {
  116. this.dispatch(entry);
  117. }
  118. return;
  119. }
  120. const contextAdditions = /* @__PURE__ */ new Map();
  121. const entries = arr.map((entry) => {
  122. const hasher = createHasher(options);
  123. hasher.dispatch(entry);
  124. for (const [key, value] of hasher.getContext()) {
  125. contextAdditions.set(key, value);
  126. }
  127. return hasher.toString();
  128. });
  129. context = contextAdditions;
  130. entries.sort();
  131. return this.array(entries, false);
  132. },
  133. date(date) {
  134. return write("date:" + date.toJSON());
  135. },
  136. symbol(sym) {
  137. return write("symbol:" + sym.toString());
  138. },
  139. unkown(value, type) {
  140. write(type);
  141. if (!value) {
  142. return;
  143. }
  144. write(":");
  145. if (value && typeof value.entries === "function") {
  146. return this.array(
  147. Array.from(value.entries()),
  148. true
  149. /* ordered */
  150. );
  151. }
  152. },
  153. error(err) {
  154. return write("error:" + err.toString());
  155. },
  156. boolean(bool) {
  157. return write("bool:" + bool);
  158. },
  159. string(string) {
  160. write("string:" + string.length + ":");
  161. write(string);
  162. },
  163. function(fn) {
  164. write("fn:");
  165. if (isNativeFunction(fn)) {
  166. this.dispatch("[native]");
  167. } else {
  168. this.dispatch(fn.toString());
  169. }
  170. if (options.respectFunctionNames !== false) {
  171. this.dispatch("function-name:" + String(fn.name));
  172. }
  173. if (options.respectFunctionProperties) {
  174. this.object(fn);
  175. }
  176. },
  177. number(number) {
  178. return write("number:" + number);
  179. },
  180. xml(xml) {
  181. return write("xml:" + xml.toString());
  182. },
  183. null() {
  184. return write("Null");
  185. },
  186. undefined() {
  187. return write("Undefined");
  188. },
  189. regexp(regex) {
  190. return write("regex:" + regex.toString());
  191. },
  192. uint8array(arr) {
  193. write("uint8array:");
  194. return this.dispatch(Array.prototype.slice.call(arr));
  195. },
  196. uint8clampedarray(arr) {
  197. write("uint8clampedarray:");
  198. return this.dispatch(Array.prototype.slice.call(arr));
  199. },
  200. int8array(arr) {
  201. write("int8array:");
  202. return this.dispatch(Array.prototype.slice.call(arr));
  203. },
  204. uint16array(arr) {
  205. write("uint16array:");
  206. return this.dispatch(Array.prototype.slice.call(arr));
  207. },
  208. int16array(arr) {
  209. write("int16array:");
  210. return this.dispatch(Array.prototype.slice.call(arr));
  211. },
  212. uint32array(arr) {
  213. write("uint32array:");
  214. return this.dispatch(Array.prototype.slice.call(arr));
  215. },
  216. int32array(arr) {
  217. write("int32array:");
  218. return this.dispatch(Array.prototype.slice.call(arr));
  219. },
  220. float32array(arr) {
  221. write("float32array:");
  222. return this.dispatch(Array.prototype.slice.call(arr));
  223. },
  224. float64array(arr) {
  225. write("float64array:");
  226. return this.dispatch(Array.prototype.slice.call(arr));
  227. },
  228. arraybuffer(arr) {
  229. write("arraybuffer:");
  230. return this.dispatch(new Uint8Array(arr));
  231. },
  232. url(url) {
  233. return write("url:" + url.toString());
  234. },
  235. map(map) {
  236. write("map:");
  237. const arr = [...map];
  238. return this.array(arr, options.unorderedSets !== false);
  239. },
  240. set(set) {
  241. write("set:");
  242. const arr = [...set];
  243. return this.array(arr, options.unorderedSets !== false);
  244. },
  245. file(file) {
  246. write("file:");
  247. return this.dispatch([file.name, file.size, file.type, file.lastModfied]);
  248. },
  249. blob() {
  250. if (options.ignoreUnknown) {
  251. return write("[blob]");
  252. }
  253. throw new Error(
  254. 'Hashing Blob objects is currently not supported\nUse "options.replacer" or "options.ignoreUnknown"\n'
  255. );
  256. },
  257. domwindow() {
  258. return write("domwindow");
  259. },
  260. bigint(number) {
  261. return write("bigint:" + number.toString());
  262. },
  263. /* Node.js standard native objects */
  264. process() {
  265. return write("process");
  266. },
  267. timer() {
  268. return write("timer");
  269. },
  270. pipe() {
  271. return write("pipe");
  272. },
  273. tcp() {
  274. return write("tcp");
  275. },
  276. udp() {
  277. return write("udp");
  278. },
  279. tty() {
  280. return write("tty");
  281. },
  282. statwatcher() {
  283. return write("statwatcher");
  284. },
  285. securecontext() {
  286. return write("securecontext");
  287. },
  288. connection() {
  289. return write("connection");
  290. },
  291. zlib() {
  292. return write("zlib");
  293. },
  294. context() {
  295. return write("context");
  296. },
  297. nodescript() {
  298. return write("nodescript");
  299. },
  300. httpparser() {
  301. return write("httpparser");
  302. },
  303. dataview() {
  304. return write("dataview");
  305. },
  306. signal() {
  307. return write("signal");
  308. },
  309. fsevent() {
  310. return write("fsevent");
  311. },
  312. tlswrap() {
  313. return write("tlswrap");
  314. }
  315. };
  316. }
  317. const nativeFunc = "[native code] }";
  318. const nativeFuncLength = nativeFunc.length;
  319. function isNativeFunction(f) {
  320. if (typeof f !== "function") {
  321. return false;
  322. }
  323. return Function.prototype.toString.call(f).slice(-nativeFuncLength) === nativeFunc;
  324. }
  325. class WordArray {
  326. constructor(words, sigBytes) {
  327. words = this.words = words || [];
  328. this.sigBytes = sigBytes === void 0 ? words.length * 4 : sigBytes;
  329. }
  330. toString(encoder) {
  331. return (encoder || Hex).stringify(this);
  332. }
  333. concat(wordArray) {
  334. this.clamp();
  335. if (this.sigBytes % 4) {
  336. for (let i = 0; i < wordArray.sigBytes; i++) {
  337. const thatByte = wordArray.words[i >>> 2] >>> 24 - i % 4 * 8 & 255;
  338. this.words[this.sigBytes + i >>> 2] |= thatByte << 24 - (this.sigBytes + i) % 4 * 8;
  339. }
  340. } else {
  341. for (let j = 0; j < wordArray.sigBytes; j += 4) {
  342. this.words[this.sigBytes + j >>> 2] = wordArray.words[j >>> 2];
  343. }
  344. }
  345. this.sigBytes += wordArray.sigBytes;
  346. return this;
  347. }
  348. clamp() {
  349. this.words[this.sigBytes >>> 2] &= 4294967295 << 32 - this.sigBytes % 4 * 8;
  350. this.words.length = Math.ceil(this.sigBytes / 4);
  351. }
  352. clone() {
  353. return new WordArray([...this.words]);
  354. }
  355. }
  356. const Hex = {
  357. stringify(wordArray) {
  358. const hexChars = [];
  359. for (let i = 0; i < wordArray.sigBytes; i++) {
  360. const bite = wordArray.words[i >>> 2] >>> 24 - i % 4 * 8 & 255;
  361. hexChars.push((bite >>> 4).toString(16), (bite & 15).toString(16));
  362. }
  363. return hexChars.join("");
  364. }
  365. };
  366. const Base64 = {
  367. stringify(wordArray) {
  368. const keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
  369. const base64Chars = [];
  370. for (let i = 0; i < wordArray.sigBytes; i += 3) {
  371. const byte1 = wordArray.words[i >>> 2] >>> 24 - i % 4 * 8 & 255;
  372. const byte2 = wordArray.words[i + 1 >>> 2] >>> 24 - (i + 1) % 4 * 8 & 255;
  373. const byte3 = wordArray.words[i + 2 >>> 2] >>> 24 - (i + 2) % 4 * 8 & 255;
  374. const triplet = byte1 << 16 | byte2 << 8 | byte3;
  375. for (let j = 0; j < 4 && i * 8 + j * 6 < wordArray.sigBytes * 8; j++) {
  376. base64Chars.push(keyStr.charAt(triplet >>> 6 * (3 - j) & 63));
  377. }
  378. }
  379. return base64Chars.join("");
  380. }
  381. };
  382. const Latin1 = {
  383. parse(latin1Str) {
  384. const latin1StrLength = latin1Str.length;
  385. const words = [];
  386. for (let i = 0; i < latin1StrLength; i++) {
  387. words[i >>> 2] |= (latin1Str.charCodeAt(i) & 255) << 24 - i % 4 * 8;
  388. }
  389. return new WordArray(words, latin1StrLength);
  390. }
  391. };
  392. const Utf8 = {
  393. parse(utf8Str) {
  394. return Latin1.parse(unescape(encodeURIComponent(utf8Str)));
  395. }
  396. };
  397. class BufferedBlockAlgorithm {
  398. constructor() {
  399. this._data = new WordArray();
  400. this._nDataBytes = 0;
  401. this._minBufferSize = 0;
  402. this.blockSize = 512 / 32;
  403. }
  404. reset() {
  405. this._data = new WordArray();
  406. this._nDataBytes = 0;
  407. }
  408. _append(data) {
  409. if (typeof data === "string") {
  410. data = Utf8.parse(data);
  411. }
  412. this._data.concat(data);
  413. this._nDataBytes += data.sigBytes;
  414. }
  415. // eslint-disable-next-line @typescript-eslint/no-unused-vars
  416. _doProcessBlock(_dataWords, _offset) {
  417. }
  418. _process(doFlush) {
  419. let processedWords;
  420. let nBlocksReady = this._data.sigBytes / (this.blockSize * 4);
  421. if (doFlush) {
  422. nBlocksReady = Math.ceil(nBlocksReady);
  423. } else {
  424. nBlocksReady = Math.max((nBlocksReady | 0) - this._minBufferSize, 0);
  425. }
  426. const nWordsReady = nBlocksReady * this.blockSize;
  427. const nBytesReady = Math.min(nWordsReady * 4, this._data.sigBytes);
  428. if (nWordsReady) {
  429. for (let offset = 0; offset < nWordsReady; offset += this.blockSize) {
  430. this._doProcessBlock(this._data.words, offset);
  431. }
  432. processedWords = this._data.words.splice(0, nWordsReady);
  433. this._data.sigBytes -= nBytesReady;
  434. }
  435. return new WordArray(processedWords, nBytesReady);
  436. }
  437. }
  438. class Hasher extends BufferedBlockAlgorithm {
  439. update(messageUpdate) {
  440. this._append(messageUpdate);
  441. this._process();
  442. return this;
  443. }
  444. finalize(messageUpdate) {
  445. if (messageUpdate) {
  446. this._append(messageUpdate);
  447. }
  448. }
  449. }
  450. const H = [
  451. 1779033703,
  452. -1150833019,
  453. 1013904242,
  454. -1521486534,
  455. 1359893119,
  456. -1694144372,
  457. 528734635,
  458. 1541459225
  459. ];
  460. const K = [
  461. 1116352408,
  462. 1899447441,
  463. -1245643825,
  464. -373957723,
  465. 961987163,
  466. 1508970993,
  467. -1841331548,
  468. -1424204075,
  469. -670586216,
  470. 310598401,
  471. 607225278,
  472. 1426881987,
  473. 1925078388,
  474. -2132889090,
  475. -1680079193,
  476. -1046744716,
  477. -459576895,
  478. -272742522,
  479. 264347078,
  480. 604807628,
  481. 770255983,
  482. 1249150122,
  483. 1555081692,
  484. 1996064986,
  485. -1740746414,
  486. -1473132947,
  487. -1341970488,
  488. -1084653625,
  489. -958395405,
  490. -710438585,
  491. 113926993,
  492. 338241895,
  493. 666307205,
  494. 773529912,
  495. 1294757372,
  496. 1396182291,
  497. 1695183700,
  498. 1986661051,
  499. -2117940946,
  500. -1838011259,
  501. -1564481375,
  502. -1474664885,
  503. -1035236496,
  504. -949202525,
  505. -778901479,
  506. -694614492,
  507. -200395387,
  508. 275423344,
  509. 430227734,
  510. 506948616,
  511. 659060556,
  512. 883997877,
  513. 958139571,
  514. 1322822218,
  515. 1537002063,
  516. 1747873779,
  517. 1955562222,
  518. 2024104815,
  519. -2067236844,
  520. -1933114872,
  521. -1866530822,
  522. -1538233109,
  523. -1090935817,
  524. -965641998
  525. ];
  526. const W = [];
  527. class SHA256 extends Hasher {
  528. constructor() {
  529. super(...arguments);
  530. this._hash = new WordArray([...H]);
  531. }
  532. reset() {
  533. super.reset();
  534. this._hash = new WordArray([...H]);
  535. }
  536. _doProcessBlock(M, offset) {
  537. const H2 = this._hash.words;
  538. let a = H2[0];
  539. let b = H2[1];
  540. let c = H2[2];
  541. let d = H2[3];
  542. let e = H2[4];
  543. let f = H2[5];
  544. let g = H2[6];
  545. let h = H2[7];
  546. for (let i = 0; i < 64; i++) {
  547. if (i < 16) {
  548. W[i] = M[offset + i] | 0;
  549. } else {
  550. const gamma0x = W[i - 15];
  551. const gamma0 = (gamma0x << 25 | gamma0x >>> 7) ^ (gamma0x << 14 | gamma0x >>> 18) ^ gamma0x >>> 3;
  552. const gamma1x = W[i - 2];
  553. const gamma1 = (gamma1x << 15 | gamma1x >>> 17) ^ (gamma1x << 13 | gamma1x >>> 19) ^ gamma1x >>> 10;
  554. W[i] = gamma0 + W[i - 7] + gamma1 + W[i - 16];
  555. }
  556. const ch = e & f ^ ~e & g;
  557. const maj = a & b ^ a & c ^ b & c;
  558. const sigma0 = (a << 30 | a >>> 2) ^ (a << 19 | a >>> 13) ^ (a << 10 | a >>> 22);
  559. const sigma1 = (e << 26 | e >>> 6) ^ (e << 21 | e >>> 11) ^ (e << 7 | e >>> 25);
  560. const t1 = h + sigma1 + ch + K[i] + W[i];
  561. const t2 = sigma0 + maj;
  562. h = g;
  563. g = f;
  564. f = e;
  565. e = d + t1 | 0;
  566. d = c;
  567. c = b;
  568. b = a;
  569. a = t1 + t2 | 0;
  570. }
  571. H2[0] = H2[0] + a | 0;
  572. H2[1] = H2[1] + b | 0;
  573. H2[2] = H2[2] + c | 0;
  574. H2[3] = H2[3] + d | 0;
  575. H2[4] = H2[4] + e | 0;
  576. H2[5] = H2[5] + f | 0;
  577. H2[6] = H2[6] + g | 0;
  578. H2[7] = H2[7] + h | 0;
  579. }
  580. finalize(messageUpdate) {
  581. super.finalize(messageUpdate);
  582. const nBitsTotal = this._nDataBytes * 8;
  583. const nBitsLeft = this._data.sigBytes * 8;
  584. this._data.words[nBitsLeft >>> 5] |= 128 << 24 - nBitsLeft % 32;
  585. this._data.words[(nBitsLeft + 64 >>> 9 << 4) + 14] = Math.floor(
  586. nBitsTotal / 4294967296
  587. );
  588. this._data.words[(nBitsLeft + 64 >>> 9 << 4) + 15] = nBitsTotal;
  589. this._data.sigBytes = this._data.words.length * 4;
  590. this._process();
  591. return this._hash;
  592. }
  593. }
  594. function sha256(message) {
  595. return new SHA256().finalize(message).toString();
  596. }
  597. function sha256base64(message) {
  598. return new SHA256().finalize(message).toString(Base64);
  599. }
  600. function hash(object, options = {}) {
  601. const hashed = typeof object === "string" ? object : objectHash(object, options);
  602. return sha256base64(hashed).slice(0, 10);
  603. }
  604. function murmurHash(key, seed = 0) {
  605. if (typeof key === "string") {
  606. key = createBuffer(key);
  607. }
  608. let i = 0;
  609. let h1 = seed;
  610. let k1;
  611. let h1b;
  612. const remainder = key.length & 3;
  613. const bytes = key.length - remainder;
  614. const c1 = 3432918353;
  615. const c2 = 461845907;
  616. while (i < bytes) {
  617. k1 = key[i] & 255 | (key[++i] & 255) << 8 | (key[++i] & 255) << 16 | (key[++i] & 255) << 24;
  618. ++i;
  619. k1 = (k1 & 65535) * c1 + (((k1 >>> 16) * c1 & 65535) << 16) & 4294967295;
  620. k1 = k1 << 15 | k1 >>> 17;
  621. k1 = (k1 & 65535) * c2 + (((k1 >>> 16) * c2 & 65535) << 16) & 4294967295;
  622. h1 ^= k1;
  623. h1 = h1 << 13 | h1 >>> 19;
  624. h1b = (h1 & 65535) * 5 + (((h1 >>> 16) * 5 & 65535) << 16) & 4294967295;
  625. h1 = (h1b & 65535) + 27492 + (((h1b >>> 16) + 58964 & 65535) << 16);
  626. }
  627. k1 = 0;
  628. switch (remainder) {
  629. case 3: {
  630. k1 ^= (key[i + 2] & 255) << 16;
  631. break;
  632. }
  633. case 2: {
  634. k1 ^= (key[i + 1] & 255) << 8;
  635. break;
  636. }
  637. case 1: {
  638. k1 ^= key[i] & 255;
  639. k1 = (k1 & 65535) * c1 + (((k1 >>> 16) * c1 & 65535) << 16) & 4294967295;
  640. k1 = k1 << 15 | k1 >>> 17;
  641. k1 = (k1 & 65535) * c2 + (((k1 >>> 16) * c2 & 65535) << 16) & 4294967295;
  642. h1 ^= k1;
  643. }
  644. }
  645. h1 ^= key.length;
  646. h1 ^= h1 >>> 16;
  647. h1 = (h1 & 65535) * 2246822507 + (((h1 >>> 16) * 2246822507 & 65535) << 16) & 4294967295;
  648. h1 ^= h1 >>> 13;
  649. h1 = (h1 & 65535) * 3266489909 + (((h1 >>> 16) * 3266489909 & 65535) << 16) & 4294967295;
  650. h1 ^= h1 >>> 16;
  651. return h1 >>> 0;
  652. }
  653. function createBuffer(val) {
  654. return new TextEncoder().encode(val);
  655. }
  656. function isEqual(object1, object2, hashOptions = {}) {
  657. if (object1 === object2) {
  658. return true;
  659. }
  660. if (objectHash(object1, hashOptions) === objectHash(object2, hashOptions)) {
  661. return true;
  662. }
  663. return false;
  664. }
  665. function diff(obj1, obj2, opts = {}) {
  666. const h1 = _toHashedObject(obj1, opts);
  667. const h2 = _toHashedObject(obj2, opts);
  668. return _diff(h1, h2, opts);
  669. }
  670. function _diff(h1, h2, opts = {}) {
  671. const diffs = [];
  672. const allProps = /* @__PURE__ */ new Set([
  673. ...Object.keys(h1.props || {}),
  674. ...Object.keys(h2.props || {})
  675. ]);
  676. if (h1.props && h2.props) {
  677. for (const prop of allProps) {
  678. const p1 = h1.props[prop];
  679. const p2 = h2.props[prop];
  680. if (p1 && p2) {
  681. diffs.push(..._diff(h1.props?.[prop], h2.props?.[prop], opts));
  682. } else if (p1 || p2) {
  683. diffs.push(
  684. new DiffEntry((p2 || p1).key, p1 ? "removed" : "added", p2, p1)
  685. );
  686. }
  687. }
  688. }
  689. if (allProps.size === 0 && h1.hash !== h2.hash) {
  690. diffs.push(new DiffEntry((h2 || h1).key, "changed", h2, h1));
  691. }
  692. return diffs;
  693. }
  694. function _toHashedObject(obj, opts, key = "") {
  695. if (obj && typeof obj !== "object") {
  696. return new DiffHashedObject(key, obj, objectHash(obj, opts));
  697. }
  698. const props = {};
  699. const hashes = [];
  700. for (const _key in obj) {
  701. props[_key] = _toHashedObject(
  702. obj[_key],
  703. opts,
  704. key ? `${key}.${_key}` : _key
  705. );
  706. hashes.push(props[_key].hash);
  707. }
  708. return new DiffHashedObject(key, obj, `{${hashes.join(":")}}`, props);
  709. }
  710. class DiffEntry {
  711. // eslint-disable-next-line no-useless-constructor
  712. constructor(key, type, newValue, oldValue) {
  713. this.key = key;
  714. this.type = type;
  715. this.newValue = newValue;
  716. this.oldValue = oldValue;
  717. }
  718. toString() {
  719. return this.toJSON();
  720. }
  721. toJSON() {
  722. switch (this.type) {
  723. case "added": {
  724. return `Added \`${this.key}\``;
  725. }
  726. case "removed": {
  727. return `Removed \`${this.key}\``;
  728. }
  729. case "changed": {
  730. return `Changed \`${this.key}\` from \`${this.oldValue?.toString() || "-"}\` to \`${this.newValue.toString()}\``;
  731. }
  732. }
  733. }
  734. }
  735. class DiffHashedObject {
  736. // eslint-disable-next-line no-useless-constructor
  737. constructor(key, value, hash, props) {
  738. this.key = key;
  739. this.value = value;
  740. this.hash = hash;
  741. this.props = props;
  742. }
  743. toString() {
  744. if (this.props) {
  745. return `{${Object.keys(this.props).join(",")}}`;
  746. } else {
  747. return JSON.stringify(this.value);
  748. }
  749. }
  750. toJSON() {
  751. const k = this.key || ".";
  752. if (this.props) {
  753. return `${k}({${Object.keys(this.props).join(",")}})`;
  754. }
  755. return `${k}(${this.value})`;
  756. }
  757. }
  758. export { diff, hash, isEqual, murmurHash, objectHash, sha256, sha256base64 };