@ztimson/utils 0.26.1 → 0.26.3

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) => {
@@ -1120,15 +1141,19 @@ class Table {
1120
1141
  getAllKeys() {
1121
1142
  return this.tx(this.name, (store) => store.getAllKeys(), true);
1122
1143
  }
1123
- put(key, value) {
1124
- return this.tx(this.name, (store) => store.put(value, key));
1144
+ put(value, key) {
1145
+ return this.tx(this.name, (store) => {
1146
+ if (store.keyPath) return store.put(value);
1147
+ return store.put(value, key);
1148
+ });
1125
1149
  }
1126
1150
  read(key) {
1127
1151
  return key ? this.get(key) : this.getAll();
1128
1152
  }
1129
1153
  set(value, key) {
1130
- if (!key && !value[this.key]) return this.add(value);
1131
- return this.put(key || value[this.key], value);
1154
+ if (key) value[this.key] = key;
1155
+ if (!value[this.key]) return this.add(value);
1156
+ return this.put(value);
1132
1157
  }
1133
1158
  }
1134
1159
  class PromiseProgress extends Promise {
@@ -1719,7 +1744,7 @@ function PES(str, ...args) {
1719
1744
  }
1720
1745
  class PathError extends Error {
1721
1746
  }
1722
- class PathEvent {
1747
+ const _PathEvent = class _PathEvent {
1723
1748
  constructor(e) {
1724
1749
  /** First directory in path */
1725
1750
  __publicField(this, "module");
@@ -1731,7 +1756,14 @@ class PathEvent {
1731
1756
  __publicField(this, "name");
1732
1757
  /** List of methods */
1733
1758
  __publicField(this, "methods");
1734
- if (typeof e == "object") return Object.assign(this, e);
1759
+ if (typeof e == "object") {
1760
+ Object.assign(this, e);
1761
+ return;
1762
+ }
1763
+ if (_PathEvent.pathEventCache.has(e)) {
1764
+ Object.assign(this, _PathEvent.pathEventCache.get(e));
1765
+ return;
1766
+ }
1735
1767
  let [p, scope, method] = e.replaceAll(/\/{2,}/g, "/").split(":");
1736
1768
  if (!method) method = scope || "*";
1737
1769
  if (p == "*" || !p && method == "*") {
@@ -1744,13 +1776,14 @@ class PathEvent {
1744
1776
  this.fullPath = `${this.module}${this.module && this.path ? "/" : ""}${this.path}`;
1745
1777
  this.name = temp.pop() || "";
1746
1778
  this.methods = new ASet(method.split(""));
1779
+ _PathEvent.pathEventCache.set(e, this);
1747
1780
  }
1748
1781
  /** All/Wildcard specified */
1749
1782
  get all() {
1750
1783
  return this.methods.has("*");
1751
1784
  }
1752
1785
  set all(v) {
1753
- v ? new ASet(["*"]) : this.methods.delete("*");
1786
+ v ? this.methods = new ASet(["*"]) : this.methods.delete("*");
1754
1787
  }
1755
1788
  /** None specified */
1756
1789
  get none() {
@@ -1787,6 +1820,10 @@ class PathEvent {
1787
1820
  set delete(v) {
1788
1821
  v ? this.methods.delete("n").delete("*").add("d") : this.methods.delete("d");
1789
1822
  }
1823
+ /** Clear the cache of all PathEvents */
1824
+ static clearCache() {
1825
+ _PathEvent.pathEventCache.clear();
1826
+ }
1790
1827
  /**
1791
1828
  * Combine multiple events into one parsed object. Longest path takes precedent, but all subsequent methods are
1792
1829
  * combined until a "none" is reached
@@ -1796,7 +1833,7 @@ class PathEvent {
1796
1833
  */
1797
1834
  static combine(...paths) {
1798
1835
  let hitNone = false;
1799
- const combined = paths.map((p) => new PathEvent(p)).toSorted((p1, p2) => {
1836
+ const combined = paths.map((p) => p instanceof _PathEvent ? p : new _PathEvent(p)).toSorted((p1, p2) => {
1800
1837
  const l1 = p1.fullPath.length, l2 = p2.fullPath.length;
1801
1838
  return l1 < l2 ? 1 : l1 > l2 ? -1 : 0;
1802
1839
  }).reduce((acc, p) => {
@@ -1804,10 +1841,9 @@ class PathEvent {
1804
1841
  if (p.none) hitNone = true;
1805
1842
  if (!acc) return p;
1806
1843
  if (hitNone) return acc;
1807
- acc.methods = [...acc.methods, ...p.methods];
1844
+ acc.methods = new ASet([...acc.methods, ...p.methods]);
1808
1845
  return acc;
1809
1846
  }, null);
1810
- combined.methods = new ASet(combined.methods);
1811
1847
  return combined;
1812
1848
  }
1813
1849
  /**
@@ -1818,11 +1854,12 @@ class PathEvent {
1818
1854
  * @return {boolean} Whether there is any overlap
1819
1855
  */
1820
1856
  static filter(target, ...filter) {
1821
- const parsedTarget = makeArray(target).map((pe) => new PathEvent(pe));
1822
- const parsedFilter = makeArray(filter).map((pe) => new PathEvent(pe));
1857
+ const parsedTarget = makeArray(target).map((pe) => pe instanceof _PathEvent ? pe : new _PathEvent(pe));
1858
+ const parsedFilter = makeArray(filter).map((pe) => pe instanceof _PathEvent ? pe : new _PathEvent(pe));
1823
1859
  return parsedTarget.filter((t) => !!parsedFilter.find((r) => {
1824
1860
  const wildcard = r.fullPath == "*" || t.fullPath == "*";
1825
- const p1 = r.fullPath.slice(0, r.fullPath.indexOf("*")), p2 = t.fullPath.slice(0, t.fullPath.indexOf("*"));
1861
+ const p1 = r.fullPath.includes("*") ? r.fullPath.slice(0, r.fullPath.indexOf("*")) : r.fullPath;
1862
+ const p2 = t.fullPath.includes("*") ? t.fullPath.slice(0, t.fullPath.indexOf("*")) : t.fullPath;
1826
1863
  const scope = p1.startsWith(p2) || p2.startsWith(p1);
1827
1864
  const methods = r.all || t.all || r.methods.intersection(t.methods).length;
1828
1865
  return (wildcard || scope) && methods;
@@ -1836,11 +1873,12 @@ class PathEvent {
1836
1873
  * @return {boolean} Whether there is any overlap
1837
1874
  */
1838
1875
  static has(target, ...has) {
1839
- const parsedTarget = makeArray(target).map((pe) => new PathEvent(pe));
1840
- const parsedRequired = makeArray(has).map((pe) => new PathEvent(pe));
1876
+ const parsedTarget = makeArray(target).map((pe) => pe instanceof _PathEvent ? pe : new _PathEvent(pe));
1877
+ const parsedRequired = makeArray(has).map((pe) => pe instanceof _PathEvent ? pe : new _PathEvent(pe));
1841
1878
  return !!parsedRequired.find((r) => !!parsedTarget.find((t) => {
1842
1879
  const wildcard = r.fullPath == "*" || t.fullPath == "*";
1843
- const p1 = r.fullPath.slice(0, r.fullPath.indexOf("*")), p2 = t.fullPath.slice(0, t.fullPath.indexOf("*"));
1880
+ const p1 = r.fullPath.includes("*") ? r.fullPath.slice(0, r.fullPath.indexOf("*")) : r.fullPath;
1881
+ const p2 = t.fullPath.includes("*") ? t.fullPath.slice(0, t.fullPath.indexOf("*")) : t.fullPath;
1844
1882
  const scope = p1.startsWith(p2);
1845
1883
  const methods = r.all || t.all || r.methods.intersection(t.methods).length;
1846
1884
  return (wildcard || scope) && methods;
@@ -1854,7 +1892,7 @@ class PathEvent {
1854
1892
  * @return {boolean} Whether there is any overlap
1855
1893
  */
1856
1894
  static hasAll(target, ...has) {
1857
- return has.filter((h) => PathEvent.has(target, h)).length == has.length;
1895
+ return has.filter((h) => _PathEvent.has(target, h)).length == has.length;
1858
1896
  }
1859
1897
  /**
1860
1898
  * Same as `has` but raises an error if there is no overlap
@@ -1863,7 +1901,7 @@ class PathEvent {
1863
1901
  * @param has Target must have at least one of these path
1864
1902
  */
1865
1903
  static hasFatal(target, ...has) {
1866
- if (!PathEvent.has(target, ...has)) throw new PathError(`Requires one of: ${makeArray(has).join(", ")}`);
1904
+ if (!_PathEvent.has(target, ...has)) throw new PathError(`Requires one of: ${makeArray(has).join(", ")}`);
1867
1905
  }
1868
1906
  /**
1869
1907
  * Same as `hasAll` but raises an error if the target is missing any paths
@@ -1872,7 +1910,7 @@ class PathEvent {
1872
1910
  * @param has Target must have all these paths
1873
1911
  */
1874
1912
  static hasAllFatal(target, ...has) {
1875
- if (!PathEvent.hasAll(target, ...has)) throw new PathError(`Requires all: ${makeArray(has).join(", ")}`);
1913
+ if (!_PathEvent.hasAll(target, ...has)) throw new PathError(`Requires all: ${makeArray(has).join(", ")}`);
1876
1914
  }
1877
1915
  /**
1878
1916
  * Create event string from its components
@@ -1894,7 +1932,7 @@ class PathEvent {
1894
1932
  * @return {boolean} Whether there is any overlap
1895
1933
  */
1896
1934
  has(...has) {
1897
- return PathEvent.has(this, ...has);
1935
+ return _PathEvent.has(this, ...has);
1898
1936
  }
1899
1937
  /**
1900
1938
  * Squash 2 sets of paths & return true if the target has all paths
@@ -1903,7 +1941,7 @@ class PathEvent {
1903
1941
  * @return {boolean} Whether there is any overlap
1904
1942
  */
1905
1943
  hasAll(...has) {
1906
- return PathEvent.hasAll(this, ...has);
1944
+ return _PathEvent.hasAll(this, ...has);
1907
1945
  }
1908
1946
  /**
1909
1947
  * Same as `has` but raises an error if there is no overlap
@@ -1911,7 +1949,7 @@ class PathEvent {
1911
1949
  * @param has Target must have at least one of these path
1912
1950
  */
1913
1951
  hasFatal(...has) {
1914
- return PathEvent.hasFatal(this, ...has);
1952
+ return _PathEvent.hasFatal(this, ...has);
1915
1953
  }
1916
1954
  /**
1917
1955
  * Same as `hasAll` but raises an error if the target is missing any paths
@@ -1919,7 +1957,7 @@ class PathEvent {
1919
1957
  * @param has Target must have all these paths
1920
1958
  */
1921
1959
  hasAllFatal(...has) {
1922
- return PathEvent.hasAllFatal(this, ...has);
1960
+ return _PathEvent.hasAllFatal(this, ...has);
1923
1961
  }
1924
1962
  /**
1925
1963
  * Filter a set of paths based on this event
@@ -1928,7 +1966,7 @@ class PathEvent {
1928
1966
  * @return {boolean} Whether there is any overlap
1929
1967
  */
1930
1968
  filter(target) {
1931
- return PathEvent.filter(target, this);
1969
+ return _PathEvent.filter(target, this);
1932
1970
  }
1933
1971
  /**
1934
1972
  * Create event string from its components
@@ -1936,16 +1974,19 @@ class PathEvent {
1936
1974
  * @return {string} String representation of Event
1937
1975
  */
1938
1976
  toString() {
1939
- return PathEvent.toString(this.fullPath, this.methods);
1977
+ return _PathEvent.toString(this.fullPath, this.methods);
1940
1978
  }
1941
- }
1979
+ };
1980
+ /** Internal cache for PathEvent instances to avoid redundant parsing */
1981
+ __publicField(_PathEvent, "pathEventCache", /* @__PURE__ */ new Map());
1982
+ let PathEvent = _PathEvent;
1942
1983
  class PathEventEmitter {
1943
1984
  constructor(prefix = "") {
1944
1985
  __publicField(this, "listeners", []);
1945
1986
  this.prefix = prefix;
1946
1987
  }
1947
1988
  emit(event, ...args) {
1948
- const parsed = PE`${this.prefix}/${event}`;
1989
+ const parsed = event instanceof PathEvent ? event : new PathEvent(`${this.prefix}/${event}`);
1949
1990
  this.listeners.filter((l) => PathEvent.has(l[0], parsed)).forEach(async (l) => l[1](parsed, ...args));
1950
1991
  }
1951
1992
  off(listener) {
@@ -1953,7 +1994,7 @@ class PathEventEmitter {
1953
1994
  }
1954
1995
  on(event, listener) {
1955
1996
  makeArray(event).forEach((e) => this.listeners.push([
1956
- new PathEvent(`${this.prefix}/${e}`),
1997
+ e instanceof PathEvent ? e : new PathEvent(`${this.prefix}/${e}`),
1957
1998
  listener
1958
1999
  ]));
1959
2000
  return () => this.off(listener);