@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.
@@ -33,7 +33,7 @@ export declare class Table<K extends IDBValidKey = any, T = any> {
33
33
  get(key: K): Promise<T>;
34
34
  getAll(): Promise<T[]>;
35
35
  getAllKeys(): Promise<K[]>;
36
- put(key: K, value: T): Promise<void>;
36
+ put(value: T, key?: string): Promise<void>;
37
37
  read(): Promise<T[]>;
38
38
  read(key: K): Promise<T>;
39
39
  set(value: T, key?: K): Promise<void>;
package/dist/index.cjs CHANGED
@@ -199,13 +199,34 @@ ${opts.message || this.desc}`;
199
199
  if (type == "function") return target.toString() == values.toString();
200
200
  return target == values;
201
201
  }
202
- function isEqual(a, b) {
203
- const ta = typeof a, tb = typeof b;
204
- if (ta != "object" || a == null || (tb != "object" || b == null))
205
- return ta == "function" && tb == "function" ? a.toString() == b.toString() : a === b;
206
- const keys = Object.keys(a);
207
- if (keys.length != Object.keys(b).length) return false;
208
- return Object.keys(a).every((key) => isEqual(a[key], b[key]));
202
+ function isEqual(a, b, seen = /* @__PURE__ */ new WeakMap()) {
203
+ if (a === b) return true;
204
+ if (a instanceof Date && b instanceof Date) return a.getTime() === b.getTime();
205
+ if (a instanceof RegExp && b instanceof RegExp) return a.source === b.source && a.flags === b.flags;
206
+ if (typeof a !== "object" || a === null || typeof b !== "object" || b === null) {
207
+ if (Number.isNaN(a) && Number.isNaN(b)) return true;
208
+ if (typeof a === "function" && typeof b === "function") return a.toString() === b.toString();
209
+ return false;
210
+ }
211
+ if (seen.has(a)) return seen.get(a) === b;
212
+ seen.set(a, b);
213
+ const isArrayA = Array.isArray(a);
214
+ const isArrayB = Array.isArray(b);
215
+ if (isArrayA && isArrayB) {
216
+ if (a.length !== b.length) return false;
217
+ for (let i = 0; i < a.length; i++) {
218
+ if (!isEqual(a[i], b[i], seen)) return false;
219
+ }
220
+ return true;
221
+ }
222
+ if (isArrayA !== isArrayB) return false;
223
+ const keysA = Object.keys(a);
224
+ const keysB = Object.keys(b);
225
+ if (keysA.length !== keysB.length) return false;
226
+ for (const key of keysA) {
227
+ if (!Object.prototype.hasOwnProperty.call(b, key) || !isEqual(a[key], b[key], seen)) return false;
228
+ }
229
+ return true;
209
230
  }
210
231
  function mixin(target, constructors) {
211
232
  constructors.forEach((c) => {
@@ -1124,15 +1145,19 @@ ${opts.message || this.desc}`;
1124
1145
  getAllKeys() {
1125
1146
  return this.tx(this.name, (store) => store.getAllKeys(), true);
1126
1147
  }
1127
- put(key, value) {
1128
- return this.tx(this.name, (store) => store.put(value, key));
1148
+ put(value, key) {
1149
+ return this.tx(this.name, (store) => {
1150
+ if (store.keyPath) return store.put(value);
1151
+ return store.put(value, key);
1152
+ });
1129
1153
  }
1130
1154
  read(key) {
1131
1155
  return key ? this.get(key) : this.getAll();
1132
1156
  }
1133
1157
  set(value, key) {
1134
- if (!key && !value[this.key]) return this.add(value);
1135
- return this.put(key || value[this.key], value);
1158
+ if (key) value[this.key] = key;
1159
+ if (!value[this.key]) return this.add(value);
1160
+ return this.put(value);
1136
1161
  }
1137
1162
  }
1138
1163
  class PromiseProgress extends Promise {
@@ -1723,7 +1748,7 @@ ${opts.message || this.desc}`;
1723
1748
  }
1724
1749
  class PathError extends Error {
1725
1750
  }
1726
- class PathEvent {
1751
+ const _PathEvent = class _PathEvent {
1727
1752
  constructor(e) {
1728
1753
  /** First directory in path */
1729
1754
  __publicField(this, "module");
@@ -1735,7 +1760,14 @@ ${opts.message || this.desc}`;
1735
1760
  __publicField(this, "name");
1736
1761
  /** List of methods */
1737
1762
  __publicField(this, "methods");
1738
- if (typeof e == "object") return Object.assign(this, e);
1763
+ if (typeof e == "object") {
1764
+ Object.assign(this, e);
1765
+ return;
1766
+ }
1767
+ if (_PathEvent.pathEventCache.has(e)) {
1768
+ Object.assign(this, _PathEvent.pathEventCache.get(e));
1769
+ return;
1770
+ }
1739
1771
  let [p, scope, method] = e.replaceAll(/\/{2,}/g, "/").split(":");
1740
1772
  if (!method) method = scope || "*";
1741
1773
  if (p == "*" || !p && method == "*") {
@@ -1748,13 +1780,14 @@ ${opts.message || this.desc}`;
1748
1780
  this.fullPath = `${this.module}${this.module && this.path ? "/" : ""}${this.path}`;
1749
1781
  this.name = temp.pop() || "";
1750
1782
  this.methods = new ASet(method.split(""));
1783
+ _PathEvent.pathEventCache.set(e, this);
1751
1784
  }
1752
1785
  /** All/Wildcard specified */
1753
1786
  get all() {
1754
1787
  return this.methods.has("*");
1755
1788
  }
1756
1789
  set all(v) {
1757
- v ? new ASet(["*"]) : this.methods.delete("*");
1790
+ v ? this.methods = new ASet(["*"]) : this.methods.delete("*");
1758
1791
  }
1759
1792
  /** None specified */
1760
1793
  get none() {
@@ -1791,6 +1824,10 @@ ${opts.message || this.desc}`;
1791
1824
  set delete(v) {
1792
1825
  v ? this.methods.delete("n").delete("*").add("d") : this.methods.delete("d");
1793
1826
  }
1827
+ /** Clear the cache of all PathEvents */
1828
+ static clearCache() {
1829
+ _PathEvent.pathEventCache.clear();
1830
+ }
1794
1831
  /**
1795
1832
  * Combine multiple events into one parsed object. Longest path takes precedent, but all subsequent methods are
1796
1833
  * combined until a "none" is reached
@@ -1800,7 +1837,7 @@ ${opts.message || this.desc}`;
1800
1837
  */
1801
1838
  static combine(...paths) {
1802
1839
  let hitNone = false;
1803
- const combined = paths.map((p) => new PathEvent(p)).toSorted((p1, p2) => {
1840
+ const combined = paths.map((p) => p instanceof _PathEvent ? p : new _PathEvent(p)).toSorted((p1, p2) => {
1804
1841
  const l1 = p1.fullPath.length, l2 = p2.fullPath.length;
1805
1842
  return l1 < l2 ? 1 : l1 > l2 ? -1 : 0;
1806
1843
  }).reduce((acc, p) => {
@@ -1808,10 +1845,9 @@ ${opts.message || this.desc}`;
1808
1845
  if (p.none) hitNone = true;
1809
1846
  if (!acc) return p;
1810
1847
  if (hitNone) return acc;
1811
- acc.methods = [...acc.methods, ...p.methods];
1848
+ acc.methods = new ASet([...acc.methods, ...p.methods]);
1812
1849
  return acc;
1813
1850
  }, null);
1814
- combined.methods = new ASet(combined.methods);
1815
1851
  return combined;
1816
1852
  }
1817
1853
  /**
@@ -1822,11 +1858,12 @@ ${opts.message || this.desc}`;
1822
1858
  * @return {boolean} Whether there is any overlap
1823
1859
  */
1824
1860
  static filter(target, ...filter) {
1825
- const parsedTarget = makeArray(target).map((pe) => new PathEvent(pe));
1826
- const parsedFilter = makeArray(filter).map((pe) => new PathEvent(pe));
1861
+ const parsedTarget = makeArray(target).map((pe) => pe instanceof _PathEvent ? pe : new _PathEvent(pe));
1862
+ const parsedFilter = makeArray(filter).map((pe) => pe instanceof _PathEvent ? pe : new _PathEvent(pe));
1827
1863
  return parsedTarget.filter((t) => !!parsedFilter.find((r) => {
1828
1864
  const wildcard = r.fullPath == "*" || t.fullPath == "*";
1829
- const p1 = r.fullPath.slice(0, r.fullPath.indexOf("*")), p2 = t.fullPath.slice(0, t.fullPath.indexOf("*"));
1865
+ const p1 = r.fullPath.includes("*") ? r.fullPath.slice(0, r.fullPath.indexOf("*")) : r.fullPath;
1866
+ const p2 = t.fullPath.includes("*") ? t.fullPath.slice(0, t.fullPath.indexOf("*")) : t.fullPath;
1830
1867
  const scope = p1.startsWith(p2) || p2.startsWith(p1);
1831
1868
  const methods = r.all || t.all || r.methods.intersection(t.methods).length;
1832
1869
  return (wildcard || scope) && methods;
@@ -1840,11 +1877,12 @@ ${opts.message || this.desc}`;
1840
1877
  * @return {boolean} Whether there is any overlap
1841
1878
  */
1842
1879
  static has(target, ...has) {
1843
- const parsedTarget = makeArray(target).map((pe) => new PathEvent(pe));
1844
- const parsedRequired = makeArray(has).map((pe) => new PathEvent(pe));
1880
+ const parsedTarget = makeArray(target).map((pe) => pe instanceof _PathEvent ? pe : new _PathEvent(pe));
1881
+ const parsedRequired = makeArray(has).map((pe) => pe instanceof _PathEvent ? pe : new _PathEvent(pe));
1845
1882
  return !!parsedRequired.find((r) => !!parsedTarget.find((t) => {
1846
1883
  const wildcard = r.fullPath == "*" || t.fullPath == "*";
1847
- const p1 = r.fullPath.slice(0, r.fullPath.indexOf("*")), p2 = t.fullPath.slice(0, t.fullPath.indexOf("*"));
1884
+ const p1 = r.fullPath.includes("*") ? r.fullPath.slice(0, r.fullPath.indexOf("*")) : r.fullPath;
1885
+ const p2 = t.fullPath.includes("*") ? t.fullPath.slice(0, t.fullPath.indexOf("*")) : t.fullPath;
1848
1886
  const scope = p1.startsWith(p2);
1849
1887
  const methods = r.all || t.all || r.methods.intersection(t.methods).length;
1850
1888
  return (wildcard || scope) && methods;
@@ -1858,7 +1896,7 @@ ${opts.message || this.desc}`;
1858
1896
  * @return {boolean} Whether there is any overlap
1859
1897
  */
1860
1898
  static hasAll(target, ...has) {
1861
- return has.filter((h) => PathEvent.has(target, h)).length == has.length;
1899
+ return has.filter((h) => _PathEvent.has(target, h)).length == has.length;
1862
1900
  }
1863
1901
  /**
1864
1902
  * Same as `has` but raises an error if there is no overlap
@@ -1867,7 +1905,7 @@ ${opts.message || this.desc}`;
1867
1905
  * @param has Target must have at least one of these path
1868
1906
  */
1869
1907
  static hasFatal(target, ...has) {
1870
- if (!PathEvent.has(target, ...has)) throw new PathError(`Requires one of: ${makeArray(has).join(", ")}`);
1908
+ if (!_PathEvent.has(target, ...has)) throw new PathError(`Requires one of: ${makeArray(has).join(", ")}`);
1871
1909
  }
1872
1910
  /**
1873
1911
  * Same as `hasAll` but raises an error if the target is missing any paths
@@ -1876,7 +1914,7 @@ ${opts.message || this.desc}`;
1876
1914
  * @param has Target must have all these paths
1877
1915
  */
1878
1916
  static hasAllFatal(target, ...has) {
1879
- if (!PathEvent.hasAll(target, ...has)) throw new PathError(`Requires all: ${makeArray(has).join(", ")}`);
1917
+ if (!_PathEvent.hasAll(target, ...has)) throw new PathError(`Requires all: ${makeArray(has).join(", ")}`);
1880
1918
  }
1881
1919
  /**
1882
1920
  * Create event string from its components
@@ -1898,7 +1936,7 @@ ${opts.message || this.desc}`;
1898
1936
  * @return {boolean} Whether there is any overlap
1899
1937
  */
1900
1938
  has(...has) {
1901
- return PathEvent.has(this, ...has);
1939
+ return _PathEvent.has(this, ...has);
1902
1940
  }
1903
1941
  /**
1904
1942
  * Squash 2 sets of paths & return true if the target has all paths
@@ -1907,7 +1945,7 @@ ${opts.message || this.desc}`;
1907
1945
  * @return {boolean} Whether there is any overlap
1908
1946
  */
1909
1947
  hasAll(...has) {
1910
- return PathEvent.hasAll(this, ...has);
1948
+ return _PathEvent.hasAll(this, ...has);
1911
1949
  }
1912
1950
  /**
1913
1951
  * Same as `has` but raises an error if there is no overlap
@@ -1915,7 +1953,7 @@ ${opts.message || this.desc}`;
1915
1953
  * @param has Target must have at least one of these path
1916
1954
  */
1917
1955
  hasFatal(...has) {
1918
- return PathEvent.hasFatal(this, ...has);
1956
+ return _PathEvent.hasFatal(this, ...has);
1919
1957
  }
1920
1958
  /**
1921
1959
  * Same as `hasAll` but raises an error if the target is missing any paths
@@ -1923,7 +1961,7 @@ ${opts.message || this.desc}`;
1923
1961
  * @param has Target must have all these paths
1924
1962
  */
1925
1963
  hasAllFatal(...has) {
1926
- return PathEvent.hasAllFatal(this, ...has);
1964
+ return _PathEvent.hasAllFatal(this, ...has);
1927
1965
  }
1928
1966
  /**
1929
1967
  * Filter a set of paths based on this event
@@ -1932,7 +1970,7 @@ ${opts.message || this.desc}`;
1932
1970
  * @return {boolean} Whether there is any overlap
1933
1971
  */
1934
1972
  filter(target) {
1935
- return PathEvent.filter(target, this);
1973
+ return _PathEvent.filter(target, this);
1936
1974
  }
1937
1975
  /**
1938
1976
  * Create event string from its components
@@ -1940,16 +1978,19 @@ ${opts.message || this.desc}`;
1940
1978
  * @return {string} String representation of Event
1941
1979
  */
1942
1980
  toString() {
1943
- return PathEvent.toString(this.fullPath, this.methods);
1981
+ return _PathEvent.toString(this.fullPath, this.methods);
1944
1982
  }
1945
- }
1983
+ };
1984
+ /** Internal cache for PathEvent instances to avoid redundant parsing */
1985
+ __publicField(_PathEvent, "pathEventCache", /* @__PURE__ */ new Map());
1986
+ let PathEvent = _PathEvent;
1946
1987
  class PathEventEmitter {
1947
1988
  constructor(prefix = "") {
1948
1989
  __publicField(this, "listeners", []);
1949
1990
  this.prefix = prefix;
1950
1991
  }
1951
1992
  emit(event, ...args) {
1952
- const parsed = PE`${this.prefix}/${event}`;
1993
+ const parsed = event instanceof PathEvent ? event : new PathEvent(`${this.prefix}/${event}`);
1953
1994
  this.listeners.filter((l) => PathEvent.has(l[0], parsed)).forEach(async (l) => l[1](parsed, ...args));
1954
1995
  }
1955
1996
  off(listener) {
@@ -1957,7 +1998,7 @@ ${opts.message || this.desc}`;
1957
1998
  }
1958
1999
  on(event, listener) {
1959
2000
  makeArray(event).forEach((e) => this.listeners.push([
1960
- new PathEvent(`${this.prefix}/${e}`),
2001
+ e instanceof PathEvent ? e : new PathEvent(`${this.prefix}/${e}`),
1961
2002
  listener
1962
2003
  ]));
1963
2004
  return () => this.off(listener);