@ztimson/utils 0.26.0 → 0.26.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -195,13 +195,34 @@ function includes(target, values, allowMissing = false) {
195
195
  if (type == "function") return target.toString() == values.toString();
196
196
  return target == values;
197
197
  }
198
- function isEqual(a, b) {
199
- const ta = typeof a, tb = typeof b;
200
- if (ta != "object" || a == null || (tb != "object" || b == null))
201
- return ta == "function" && tb == "function" ? a.toString() == b.toString() : a === b;
202
- const keys = Object.keys(a);
203
- if (keys.length != Object.keys(b).length) return false;
204
- return Object.keys(a).every((key) => isEqual(a[key], b[key]));
198
+ function isEqual(a, b, seen = /* @__PURE__ */ new WeakMap()) {
199
+ if (a === b) return true;
200
+ if (a instanceof Date && b instanceof Date) return a.getTime() === b.getTime();
201
+ if (a instanceof RegExp && b instanceof RegExp) return a.source === b.source && a.flags === b.flags;
202
+ if (typeof a !== "object" || a === null || typeof b !== "object" || b === null) {
203
+ if (Number.isNaN(a) && Number.isNaN(b)) return true;
204
+ if (typeof a === "function" && typeof b === "function") return a.toString() === b.toString();
205
+ return false;
206
+ }
207
+ if (seen.has(a)) return seen.get(a) === b;
208
+ seen.set(a, b);
209
+ const isArrayA = Array.isArray(a);
210
+ const isArrayB = Array.isArray(b);
211
+ if (isArrayA && isArrayB) {
212
+ if (a.length !== b.length) return false;
213
+ for (let i = 0; i < a.length; i++) {
214
+ if (!isEqual(a[i], b[i], seen)) return false;
215
+ }
216
+ return true;
217
+ }
218
+ if (isArrayA !== isArrayB) return false;
219
+ const keysA = Object.keys(a);
220
+ const keysB = Object.keys(b);
221
+ if (keysA.length !== keysB.length) return false;
222
+ for (const key of keysA) {
223
+ if (!Object.prototype.hasOwnProperty.call(b, key) || !isEqual(a[key], b[key], seen)) return false;
224
+ }
225
+ return true;
205
226
  }
206
227
  function mixin(target, constructors) {
207
228
  constructors.forEach((c) => {
@@ -456,7 +477,7 @@ class Cache {
456
477
  const persists = this.options.persistentStorage;
457
478
  if (!!(persists == null ? void 0 : persists.storage)) {
458
479
  if (((_a = persists.storage) == null ? void 0 : _a.constructor.name) == "Database") {
459
- persists.storage.createTable({ name: persists.storage.key, key: this.key }).then((table) => {
480
+ persists.storage.createTable({ name: persists.key, key: this.key }).then((table) => {
460
481
  if (key) {
461
482
  table.set(key, this.get(key));
462
483
  } else {
@@ -1719,7 +1740,7 @@ function PES(str, ...args) {
1719
1740
  }
1720
1741
  class PathError extends Error {
1721
1742
  }
1722
- class PathEvent {
1743
+ const _PathEvent = class _PathEvent {
1723
1744
  constructor(e) {
1724
1745
  /** First directory in path */
1725
1746
  __publicField(this, "module");
@@ -1731,7 +1752,14 @@ class PathEvent {
1731
1752
  __publicField(this, "name");
1732
1753
  /** List of methods */
1733
1754
  __publicField(this, "methods");
1734
- if (typeof e == "object") return Object.assign(this, e);
1755
+ if (typeof e == "object") {
1756
+ Object.assign(this, e);
1757
+ return;
1758
+ }
1759
+ if (_PathEvent.pathEventCache.has(e)) {
1760
+ Object.assign(this, _PathEvent.pathEventCache.get(e));
1761
+ return;
1762
+ }
1735
1763
  let [p, scope, method] = e.replaceAll(/\/{2,}/g, "/").split(":");
1736
1764
  if (!method) method = scope || "*";
1737
1765
  if (p == "*" || !p && method == "*") {
@@ -1744,13 +1772,14 @@ class PathEvent {
1744
1772
  this.fullPath = `${this.module}${this.module && this.path ? "/" : ""}${this.path}`;
1745
1773
  this.name = temp.pop() || "";
1746
1774
  this.methods = new ASet(method.split(""));
1775
+ _PathEvent.pathEventCache.set(e, this);
1747
1776
  }
1748
1777
  /** All/Wildcard specified */
1749
1778
  get all() {
1750
1779
  return this.methods.has("*");
1751
1780
  }
1752
1781
  set all(v) {
1753
- v ? new ASet(["*"]) : this.methods.delete("*");
1782
+ v ? this.methods = new ASet(["*"]) : this.methods.delete("*");
1754
1783
  }
1755
1784
  /** None specified */
1756
1785
  get none() {
@@ -1787,6 +1816,10 @@ class PathEvent {
1787
1816
  set delete(v) {
1788
1817
  v ? this.methods.delete("n").delete("*").add("d") : this.methods.delete("d");
1789
1818
  }
1819
+ /** Clear the cache of all PathEvents */
1820
+ static clearCache() {
1821
+ _PathEvent.pathEventCache.clear();
1822
+ }
1790
1823
  /**
1791
1824
  * Combine multiple events into one parsed object. Longest path takes precedent, but all subsequent methods are
1792
1825
  * combined until a "none" is reached
@@ -1796,7 +1829,7 @@ class PathEvent {
1796
1829
  */
1797
1830
  static combine(...paths) {
1798
1831
  let hitNone = false;
1799
- const combined = paths.map((p) => new PathEvent(p)).toSorted((p1, p2) => {
1832
+ const combined = paths.map((p) => p instanceof _PathEvent ? p : new _PathEvent(p)).toSorted((p1, p2) => {
1800
1833
  const l1 = p1.fullPath.length, l2 = p2.fullPath.length;
1801
1834
  return l1 < l2 ? 1 : l1 > l2 ? -1 : 0;
1802
1835
  }).reduce((acc, p) => {
@@ -1804,10 +1837,9 @@ class PathEvent {
1804
1837
  if (p.none) hitNone = true;
1805
1838
  if (!acc) return p;
1806
1839
  if (hitNone) return acc;
1807
- acc.methods = [...acc.methods, ...p.methods];
1840
+ acc.methods = new ASet([...acc.methods, ...p.methods]);
1808
1841
  return acc;
1809
1842
  }, null);
1810
- combined.methods = new ASet(combined.methods);
1811
1843
  return combined;
1812
1844
  }
1813
1845
  /**
@@ -1818,11 +1850,12 @@ class PathEvent {
1818
1850
  * @return {boolean} Whether there is any overlap
1819
1851
  */
1820
1852
  static filter(target, ...filter) {
1821
- const parsedTarget = makeArray(target).map((pe) => new PathEvent(pe));
1822
- const parsedFilter = makeArray(filter).map((pe) => new PathEvent(pe));
1853
+ const parsedTarget = makeArray(target).map((pe) => pe instanceof _PathEvent ? pe : new _PathEvent(pe));
1854
+ const parsedFilter = makeArray(filter).map((pe) => pe instanceof _PathEvent ? pe : new _PathEvent(pe));
1823
1855
  return parsedTarget.filter((t) => !!parsedFilter.find((r) => {
1824
1856
  const wildcard = r.fullPath == "*" || t.fullPath == "*";
1825
- const p1 = r.fullPath.slice(0, r.fullPath.indexOf("*")), p2 = t.fullPath.slice(0, t.fullPath.indexOf("*"));
1857
+ const p1 = r.fullPath.includes("*") ? r.fullPath.slice(0, r.fullPath.indexOf("*")) : r.fullPath;
1858
+ const p2 = t.fullPath.includes("*") ? t.fullPath.slice(0, t.fullPath.indexOf("*")) : t.fullPath;
1826
1859
  const scope = p1.startsWith(p2) || p2.startsWith(p1);
1827
1860
  const methods = r.all || t.all || r.methods.intersection(t.methods).length;
1828
1861
  return (wildcard || scope) && methods;
@@ -1836,11 +1869,12 @@ class PathEvent {
1836
1869
  * @return {boolean} Whether there is any overlap
1837
1870
  */
1838
1871
  static has(target, ...has) {
1839
- const parsedTarget = makeArray(target).map((pe) => new PathEvent(pe));
1840
- const parsedRequired = makeArray(has).map((pe) => new PathEvent(pe));
1872
+ const parsedTarget = makeArray(target).map((pe) => pe instanceof _PathEvent ? pe : new _PathEvent(pe));
1873
+ const parsedRequired = makeArray(has).map((pe) => pe instanceof _PathEvent ? pe : new _PathEvent(pe));
1841
1874
  return !!parsedRequired.find((r) => !!parsedTarget.find((t) => {
1842
1875
  const wildcard = r.fullPath == "*" || t.fullPath == "*";
1843
- const p1 = r.fullPath.slice(0, r.fullPath.indexOf("*")), p2 = t.fullPath.slice(0, t.fullPath.indexOf("*"));
1876
+ const p1 = r.fullPath.includes("*") ? r.fullPath.slice(0, r.fullPath.indexOf("*")) : r.fullPath;
1877
+ const p2 = t.fullPath.includes("*") ? t.fullPath.slice(0, t.fullPath.indexOf("*")) : t.fullPath;
1844
1878
  const scope = p1.startsWith(p2);
1845
1879
  const methods = r.all || t.all || r.methods.intersection(t.methods).length;
1846
1880
  return (wildcard || scope) && methods;
@@ -1854,7 +1888,7 @@ class PathEvent {
1854
1888
  * @return {boolean} Whether there is any overlap
1855
1889
  */
1856
1890
  static hasAll(target, ...has) {
1857
- return has.filter((h) => PathEvent.has(target, h)).length == has.length;
1891
+ return has.filter((h) => _PathEvent.has(target, h)).length == has.length;
1858
1892
  }
1859
1893
  /**
1860
1894
  * Same as `has` but raises an error if there is no overlap
@@ -1863,7 +1897,7 @@ class PathEvent {
1863
1897
  * @param has Target must have at least one of these path
1864
1898
  */
1865
1899
  static hasFatal(target, ...has) {
1866
- if (!PathEvent.has(target, ...has)) throw new PathError(`Requires one of: ${makeArray(has).join(", ")}`);
1900
+ if (!_PathEvent.has(target, ...has)) throw new PathError(`Requires one of: ${makeArray(has).join(", ")}`);
1867
1901
  }
1868
1902
  /**
1869
1903
  * Same as `hasAll` but raises an error if the target is missing any paths
@@ -1872,7 +1906,7 @@ class PathEvent {
1872
1906
  * @param has Target must have all these paths
1873
1907
  */
1874
1908
  static hasAllFatal(target, ...has) {
1875
- if (!PathEvent.hasAll(target, ...has)) throw new PathError(`Requires all: ${makeArray(has).join(", ")}`);
1909
+ if (!_PathEvent.hasAll(target, ...has)) throw new PathError(`Requires all: ${makeArray(has).join(", ")}`);
1876
1910
  }
1877
1911
  /**
1878
1912
  * Create event string from its components
@@ -1894,7 +1928,7 @@ class PathEvent {
1894
1928
  * @return {boolean} Whether there is any overlap
1895
1929
  */
1896
1930
  has(...has) {
1897
- return PathEvent.has(this, ...has);
1931
+ return _PathEvent.has(this, ...has);
1898
1932
  }
1899
1933
  /**
1900
1934
  * Squash 2 sets of paths & return true if the target has all paths
@@ -1903,7 +1937,7 @@ class PathEvent {
1903
1937
  * @return {boolean} Whether there is any overlap
1904
1938
  */
1905
1939
  hasAll(...has) {
1906
- return PathEvent.hasAll(this, ...has);
1940
+ return _PathEvent.hasAll(this, ...has);
1907
1941
  }
1908
1942
  /**
1909
1943
  * Same as `has` but raises an error if there is no overlap
@@ -1911,7 +1945,7 @@ class PathEvent {
1911
1945
  * @param has Target must have at least one of these path
1912
1946
  */
1913
1947
  hasFatal(...has) {
1914
- return PathEvent.hasFatal(this, ...has);
1948
+ return _PathEvent.hasFatal(this, ...has);
1915
1949
  }
1916
1950
  /**
1917
1951
  * Same as `hasAll` but raises an error if the target is missing any paths
@@ -1919,7 +1953,7 @@ class PathEvent {
1919
1953
  * @param has Target must have all these paths
1920
1954
  */
1921
1955
  hasAllFatal(...has) {
1922
- return PathEvent.hasAllFatal(this, ...has);
1956
+ return _PathEvent.hasAllFatal(this, ...has);
1923
1957
  }
1924
1958
  /**
1925
1959
  * Filter a set of paths based on this event
@@ -1928,7 +1962,7 @@ class PathEvent {
1928
1962
  * @return {boolean} Whether there is any overlap
1929
1963
  */
1930
1964
  filter(target) {
1931
- return PathEvent.filter(target, this);
1965
+ return _PathEvent.filter(target, this);
1932
1966
  }
1933
1967
  /**
1934
1968
  * Create event string from its components
@@ -1936,16 +1970,19 @@ class PathEvent {
1936
1970
  * @return {string} String representation of Event
1937
1971
  */
1938
1972
  toString() {
1939
- return PathEvent.toString(this.fullPath, this.methods);
1973
+ return _PathEvent.toString(this.fullPath, this.methods);
1940
1974
  }
1941
- }
1975
+ };
1976
+ /** Internal cache for PathEvent instances to avoid redundant parsing */
1977
+ __publicField(_PathEvent, "pathEventCache", /* @__PURE__ */ new Map());
1978
+ let PathEvent = _PathEvent;
1942
1979
  class PathEventEmitter {
1943
1980
  constructor(prefix = "") {
1944
1981
  __publicField(this, "listeners", []);
1945
1982
  this.prefix = prefix;
1946
1983
  }
1947
1984
  emit(event, ...args) {
1948
- const parsed = PE`${this.prefix}/${event}`;
1985
+ const parsed = event instanceof PathEvent ? event : new PathEvent(`${this.prefix}/${event}`);
1949
1986
  this.listeners.filter((l) => PathEvent.has(l[0], parsed)).forEach(async (l) => l[1](parsed, ...args));
1950
1987
  }
1951
1988
  off(listener) {
@@ -1953,7 +1990,7 @@ class PathEventEmitter {
1953
1990
  }
1954
1991
  on(event, listener) {
1955
1992
  makeArray(event).forEach((e) => this.listeners.push([
1956
- new PathEvent(`${this.prefix}/${e}`),
1993
+ e instanceof PathEvent ? e : new PathEvent(`${this.prefix}/${e}`),
1957
1994
  listener
1958
1995
  ]));
1959
1996
  return () => this.off(listener);