@ztimson/utils 0.24.12 → 0.25.1

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.d.ts CHANGED
@@ -4,6 +4,7 @@ export * from './aset';
4
4
  export * from './cache';
5
5
  export * from './color';
6
6
  export * from './csv';
7
+ export * from './database';
7
8
  export * from './files';
8
9
  export * from './emitter';
9
10
  export * from './errors';
package/dist/index.mjs CHANGED
@@ -61,7 +61,7 @@ class ArgParser {
61
61
  extras.push(arg);
62
62
  continue;
63
63
  }
64
- const value = argDef.default === false ? true : argDef.default === true ? false : queue.splice(queue.findIndex((q) => q[0] != "-"), 1)[0] || argDef.default;
64
+ const value = combined[1] != null ? combined[1] : argDef.default === false ? true : argDef.default === true ? false : queue.splice(queue.findIndex((q) => q[0] != "-"), 1)[0] || argDef.default;
65
65
  if (value == null) parsed["_error"].push(`Option missing value: ${argDef.name || combined[0]}`);
66
66
  parsed[argDef.name] = value;
67
67
  } else {
@@ -120,7 +120,7 @@ ${opts.message || this.desc}`;
120
120
  function clean(obj, undefinedOnly = false) {
121
121
  if (obj == null) throw new Error("Cannot clean a NULL value");
122
122
  if (Array.isArray(obj)) {
123
- obj = obj.filter((o) => o != null);
123
+ obj = obj.filter((o) => undefinedOnly ? o !== void 0 : o != null);
124
124
  } else {
125
125
  Object.entries(obj).forEach(([key, value]) => {
126
126
  if (undefinedOnly && value === void 0 || !undefinedOnly && value == null) delete obj[key];
@@ -171,7 +171,6 @@ function flattenObj(obj, parent, result = {}) {
171
171
  for (const key of Object.keys(obj)) {
172
172
  const propName = parent ? `${parent}.${key}` : key;
173
173
  if (typeof obj[key] === "object" && obj[key] != null && !Array.isArray(obj[key])) {
174
- console.log(propName);
175
174
  flattenObj(obj[key], propName, result);
176
175
  } else {
177
176
  result[propName] = obj[key];
@@ -227,55 +226,15 @@ function JSONSerialize(obj) {
227
226
  return obj;
228
227
  }
229
228
  function JSONSanitize(obj, space) {
229
+ const cache = [];
230
230
  return JSON.stringify(obj, (key, value) => {
231
+ if (typeof value === "object" && value !== null) {
232
+ if (cache.includes(value)) return "[Circular]";
233
+ cache.push(value);
234
+ }
231
235
  return value;
232
236
  }, space);
233
237
  }
234
- function addUnique(array, el) {
235
- if (array.indexOf(el) === -1) array.push(el);
236
- return array;
237
- }
238
- function arrayDiff(a, b) {
239
- return makeUnique([
240
- ...a.filter((v1) => !b.includes((v2) => isEqual(v1, v2))),
241
- ...b.filter((v1) => !a.includes((v2) => isEqual(v1, v2)))
242
- ]);
243
- }
244
- function caseInsensitiveSort(prop) {
245
- return function(a, b) {
246
- const aVal = dotNotation(a, prop);
247
- const bVal = dotNotation(b, prop);
248
- if (typeof aVal !== "string" || typeof bVal !== "string") return 1;
249
- return aVal.toLowerCase().localeCompare(bVal.toLowerCase());
250
- };
251
- }
252
- function findByProp(prop, value) {
253
- return (v) => isEqual(dotNotation(v, prop), value);
254
- }
255
- function flattenArr(arr, result = []) {
256
- arr.forEach((el) => Array.isArray(el) ? flattenArr(el, result) : result.push(el));
257
- return result;
258
- }
259
- function sortByProp(prop, reverse = false) {
260
- return function(a, b) {
261
- const aVal = dotNotation(a, prop);
262
- const bVal = dotNotation(b, prop);
263
- if (typeof aVal == "number" && typeof bVal == "number")
264
- return (reverse ? -1 : 1) * (aVal - bVal);
265
- if (aVal > bVal) return reverse ? -1 : 1;
266
- if (aVal < bVal) return reverse ? 1 : -1;
267
- return 0;
268
- };
269
- }
270
- function makeUnique(arr) {
271
- for (let i = arr.length - 1; i >= 0; i--) {
272
- if (arr.slice(0, i).find((n) => isEqual(n, arr[i]))) arr.splice(i, 1);
273
- }
274
- return arr;
275
- }
276
- function makeArray(value) {
277
- return Array.isArray(value) ? value : [value];
278
- }
279
238
  class ASet extends Array {
280
239
  /** Number of elements in set */
281
240
  get size() {
@@ -391,6 +350,102 @@ class ASet extends Array {
391
350
  return new ASet([...this, ...set]);
392
351
  }
393
352
  }
353
+ function addUnique(array, el) {
354
+ if (array.indexOf(el) === -1) array.push(el);
355
+ return array;
356
+ }
357
+ function arrayDiff(a, b) {
358
+ return new ASet(a).symmetricDifference(new ASet(b));
359
+ }
360
+ function caseInsensitiveSort(prop) {
361
+ return function(a, b) {
362
+ const aVal = dotNotation(a, prop);
363
+ const bVal = dotNotation(b, prop);
364
+ if (typeof aVal !== "string" || typeof bVal !== "string") return 1;
365
+ return aVal.toLowerCase().localeCompare(bVal.toLowerCase());
366
+ };
367
+ }
368
+ function findByProp(prop, value) {
369
+ return (v) => isEqual(dotNotation(v, prop), value);
370
+ }
371
+ function flattenArr(arr, result = []) {
372
+ arr.forEach((el) => Array.isArray(el) ? flattenArr(el, result) : result.push(el));
373
+ return result;
374
+ }
375
+ function sortByProp(prop, reverse = false) {
376
+ return function(a, b) {
377
+ const aVal = dotNotation(a, prop);
378
+ const bVal = dotNotation(b, prop);
379
+ if (typeof aVal == "number" && typeof bVal == "number")
380
+ return (reverse ? -1 : 1) * (aVal - bVal);
381
+ if (aVal > bVal) return reverse ? -1 : 1;
382
+ if (aVal < bVal) return reverse ? 1 : -1;
383
+ return 0;
384
+ };
385
+ }
386
+ function makeUnique(arr) {
387
+ for (let i = arr.length - 1; i >= 0; i--) {
388
+ if (arr.slice(0, i).find((n) => isEqual(n, arr[i]))) arr.splice(i, 1);
389
+ }
390
+ return arr;
391
+ }
392
+ function makeArray(value) {
393
+ return Array.isArray(value) ? value : [value];
394
+ }
395
+ class Collection {
396
+ constructor(db, collection, version, setup) {
397
+ __publicField(this, "database");
398
+ this.db = db;
399
+ this.collection = collection;
400
+ this.version = version;
401
+ this.setup = setup;
402
+ this.database = new Promise((resolve, reject) => {
403
+ const req = indexedDB.open(this.db, this.version);
404
+ req.onerror = () => reject(req.error);
405
+ req.onsuccess = () => resolve(req.result);
406
+ req.onupgradeneeded = (event) => {
407
+ const db2 = req.result;
408
+ if (!db2.objectStoreNames.contains(collection)) db2.createObjectStore(collection, { keyPath: void 0 });
409
+ if (this.setup) this.setup(db2, event);
410
+ };
411
+ });
412
+ }
413
+ async tx(collection, fn2, readonly) {
414
+ const db = await this.database;
415
+ const tx = db.transaction(collection, readonly ? "readonly" : "readwrite");
416
+ const store = tx.objectStore(collection);
417
+ return new Promise((resolve, reject) => {
418
+ const request = fn2(store);
419
+ request.onsuccess = () => resolve(request.result);
420
+ request.onerror = () => reject(request.error);
421
+ });
422
+ }
423
+ add(value, key) {
424
+ return this.tx(this.collection, (store) => store.add(value, key));
425
+ }
426
+ count() {
427
+ return this.tx(this.collection, (store) => store.count(), true);
428
+ }
429
+ put(key, value) {
430
+ debugger;
431
+ return this.tx(this.collection, (store) => store.put(value, key));
432
+ }
433
+ getAll() {
434
+ return this.tx(this.collection, (store) => store.getAll(), true);
435
+ }
436
+ getAllKeys() {
437
+ return this.tx(this.collection, (store) => store.getAllKeys(), true);
438
+ }
439
+ get(key) {
440
+ return this.tx(this.collection, (store) => store.get(key), true);
441
+ }
442
+ delete(key) {
443
+ return this.tx(this.collection, (store) => store.delete(key));
444
+ }
445
+ clear() {
446
+ return this.tx(this.collection, (store) => store.clear());
447
+ }
448
+ }
394
449
  class Cache {
395
450
  /**
396
451
  * Create new cache
@@ -406,14 +461,19 @@ class Cache {
406
461
  * @return {T[]} Array of items
407
462
  */
408
463
  __publicField(this, "values", this.all());
464
+ var _a;
409
465
  this.key = key;
410
466
  this.options = options;
411
- if (options.storageKey && !options.storage && typeof Storage !== "undefined")
412
- options.storage = localStorage;
413
- if (options.storageKey && options.storage) {
414
- const stored = options.storage.getItem(options.storageKey);
415
- if (stored) {
416
- try {
467
+ if (options.storageKey && !options.storage && typeof Storage !== "undefined") options.storage = localStorage;
468
+ if (options.storage) {
469
+ if (options.storage instanceof Collection) {
470
+ (async () => {
471
+ var _a2;
472
+ (await ((_a2 = options.storage) == null ? void 0 : _a2.getAll())).forEach((v) => this.add(v));
473
+ })();
474
+ } else if (options.storageKey) {
475
+ const stored = (_a = options.storage) == null ? void 0 : _a.getItem(options.storageKey);
476
+ if (stored != null) try {
417
477
  Object.assign(this.store, JSON.parse(stored));
418
478
  } catch {
419
479
  }
@@ -435,9 +495,14 @@ class Cache {
435
495
  if (!this.key) throw new Error("No key defined");
436
496
  return value[this.key];
437
497
  }
438
- save() {
439
- if (this.options.storageKey && this.options.storage)
440
- this.options.storage.setItem(this.options.storageKey, JSON.stringify(this.store));
498
+ save(key) {
499
+ if (this.options.storage) {
500
+ if (this.options.storage instanceof Collection) {
501
+ this.options.storage.put(key, this.store[key]);
502
+ } else if (this.options.storageKey) {
503
+ this.options.storage.setItem(this.options.storageKey, JSONSanitize(this.store));
504
+ }
505
+ }
441
506
  }
442
507
  /**
443
508
  * Get all cached items
@@ -475,6 +540,7 @@ class Cache {
475
540
  clear() {
476
541
  this.complete = false;
477
542
  this.store = {};
543
+ return this;
478
544
  }
479
545
  /**
480
546
  * Delete an item from the cache
@@ -482,7 +548,8 @@ class Cache {
482
548
  */
483
549
  delete(key) {
484
550
  delete this.store[key];
485
- this.save();
551
+ this.save(key);
552
+ return this;
486
553
  }
487
554
  /**
488
555
  * Return cache as an array of key-value pairs
@@ -499,6 +566,7 @@ class Cache {
499
566
  this.complete = false;
500
567
  if (this.options.expiryPolicy == "keep") this.store[key]._expired = true;
501
568
  else this.delete(key);
569
+ return this;
502
570
  }
503
571
  /**
504
572
  * Get item from the cache
@@ -538,18 +606,18 @@ class Cache {
538
606
  set(key, value, ttl = this.options.ttl) {
539
607
  if (this.options.expiryPolicy == "keep") delete value._expired;
540
608
  this.store[key] = value;
541
- this.save();
609
+ this.save(key);
542
610
  if (ttl) setTimeout(() => {
543
611
  this.expire(key);
544
- this.save();
545
- }, ttl * 1e3);
612
+ this.save(key);
613
+ }, (ttl || 0) * 1e3);
546
614
  return this;
547
615
  }
548
616
  }
549
- function blackOrWhite(background) {
550
- const exploded = background == null ? void 0 : background.match(background.length >= 6 ? /\w\w/g : /\w/g);
551
- if (!exploded) return "black";
552
- const [r, g, b] = exploded.map((hex) => parseInt(hex, 16));
617
+ function contrast(background) {
618
+ const exploded = background == null ? void 0 : background.match(background.length >= 6 ? /[0-9a-fA-F]{2}/g : /[0-9a-fA-F]/g);
619
+ if (!exploded || (exploded == null ? void 0 : exploded.length) < 3) return "black";
620
+ const [r, g, b] = exploded.map((hex) => parseInt(hex.length == 1 ? `${hex}${hex}` : hex, 16));
553
621
  const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255;
554
622
  return luminance > 0.5 ? "black" : "white";
555
623
  }
@@ -559,7 +627,7 @@ const SYMBOL_LIST = "~`!@#$%^&*()_-+={[}]|\\:;\"'<,>.?/";
559
627
  const CHAR_LIST = LETTER_LIST + LETTER_LIST.toLowerCase() + NUMBER_LIST + SYMBOL_LIST;
560
628
  function camelCase(str) {
561
629
  const text = pascalCase(str);
562
- return text[0].toLowerCase() + text.slice(1);
630
+ return !text ? "" : text[0].toLowerCase() + text.slice(1);
563
631
  }
564
632
  function formatBytes(bytes, decimals = 2) {
565
633
  if (bytes === 0) return "0 Bytes";
@@ -585,12 +653,9 @@ function pad(text, length, char = " ", start = true) {
585
653
  return text.toString().padEnd(length, char);
586
654
  }
587
655
  function pascalCase(str) {
656
+ var _a;
588
657
  if (!str) return "";
589
- const text = str.replaceAll(/(^[^a-zA-Z]+|[^a-zA-Z0-9-_])/g, "").replaceAll(/[^a-zA-Z0-9]+(\w?)/g, (...args) => {
590
- var _a;
591
- return ((_a = args[1]) == null ? void 0 : _a.toUpperCase()) || "";
592
- });
593
- return text[0].toUpperCase() + text.slice(1);
658
+ return ((_a = str.match(/[a-zA-Z0-9]+/g)) == null ? void 0 : _a.map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join("")) ?? "";
594
659
  }
595
660
  function randomHex(length) {
596
661
  return Array(length).fill(null).map(() => Math.round(Math.random() * 15).toString(16)).join("");
@@ -1012,7 +1077,7 @@ class TypedEmitter {
1012
1077
  }
1013
1078
  static off(event, listener) {
1014
1079
  const e = event.toString();
1015
- this.listeners[e] = (this.listeners[e] || []).filter((l) => l === listener);
1080
+ this.listeners[e] = (this.listeners[e] || []).filter((l) => l != listener);
1016
1081
  }
1017
1082
  static on(event, listener) {
1018
1083
  var _a;
@@ -1035,7 +1100,7 @@ class TypedEmitter {
1035
1100
  (this.listeners[event] || []).forEach((l) => l(...args));
1036
1101
  }
1037
1102
  off(event, listener) {
1038
- this.listeners[event] = (this.listeners[event] || []).filter((l) => l === listener);
1103
+ this.listeners[event] = (this.listeners[event] || []).filter((l) => l != listener);
1039
1104
  }
1040
1105
  on(event, listener) {
1041
1106
  var _a;
@@ -1332,6 +1397,11 @@ const _Http = class _Http {
1332
1397
  __publicField(_Http, "interceptors", {});
1333
1398
  __publicField(_Http, "headers", {});
1334
1399
  let Http = _Http;
1400
+ function createJwt(payload, signature = "unsigned") {
1401
+ const header = Buffer.from(JSON.stringify({ alg: "HS256", typ: "JWT" })).toString("base64url");
1402
+ const body = Buffer.from(JSON.stringify(payload)).toString("base64url");
1403
+ return `${header}.${body}.${signature}`;
1404
+ }
1335
1405
  function decodeJwt(token) {
1336
1406
  const base64 = token.split(".")[1].replace(/-/g, "+").replace(/_/g, "/");
1337
1407
  return JSONAttemptParse(decodeURIComponent(atob(base64).split("").map(function(c) {
@@ -1427,20 +1497,22 @@ const _Logger = class _Logger extends TypedEmitter {
1427
1497
  };
1428
1498
  __publicField(_Logger, "LOG_LEVEL", 4);
1429
1499
  let Logger = _Logger;
1430
- function dec2Frac(num) {
1431
- const gcd = (a, b) => {
1432
- if (b < 1e-7) return a;
1433
- return gcd(b, ~~(a % b));
1434
- };
1435
- const len = num.toString().length - 2;
1436
- let denominator = Math.pow(10, len);
1437
- let numerator = num * denominator;
1438
- const divisor = gcd(numerator, denominator);
1439
- numerator = ~~(numerator / divisor);
1440
- denominator = ~~(denominator / divisor);
1441
- const remainder = ~~(numerator / denominator);
1442
- numerator -= remainder * denominator;
1443
- return `${remainder ? remainder + " " : ""}${~~numerator}/${~~denominator}`;
1500
+ function dec2Frac(num, maxDen = 1e3) {
1501
+ let sign = Math.sign(num);
1502
+ num = Math.abs(num);
1503
+ if (Number.isInteger(num)) return sign * num + "";
1504
+ let closest = { n: 0, d: 1, diff: Math.abs(num) };
1505
+ for (let d = 1; d <= maxDen; d++) {
1506
+ let n = Math.round(num * d);
1507
+ let diff = Math.abs(num - n / d);
1508
+ if (diff < closest.diff) {
1509
+ closest = { n, d, diff };
1510
+ if (diff < 1e-8) break;
1511
+ }
1512
+ }
1513
+ let integer = Math.floor(closest.n / closest.d);
1514
+ let numerator = closest.n - integer * closest.d;
1515
+ return (sign < 0 ? "-" : "") + (integer ? integer + " " : "") + (numerator ? numerator + "/" + closest.d : "");
1444
1516
  }
1445
1517
  function fracToDec(frac) {
1446
1518
  let split = frac.split(" ");
@@ -1560,6 +1632,7 @@ class PathEvent {
1560
1632
  const l1 = p1.fullPath.length, l2 = p2.fullPath.length;
1561
1633
  return l1 < l2 ? 1 : l1 > l2 ? -1 : 0;
1562
1634
  }).reduce((acc, p) => {
1635
+ if (acc && !acc.fullPath.startsWith(p.fullPath)) return acc;
1563
1636
  if (p.none) hitNone = true;
1564
1637
  if (!acc) return p;
1565
1638
  if (hitNone) return acc;
@@ -1667,15 +1740,15 @@ class PathEventEmitter {
1667
1740
  this.prefix = prefix;
1668
1741
  }
1669
1742
  emit(event, ...args) {
1670
- const parsed = new PathEvent(`${this.prefix}/${typeof event == "string" ? event : event.toString()}`);
1671
- this.listeners.filter((l) => PathEvent.has(l[0], event)).forEach(async (l) => l[1](parsed, ...args));
1743
+ const parsed = new PathEvent(`${this.prefix}/${new PathEvent(event).toString()}`);
1744
+ this.listeners.filter((l) => PathEvent.has(l[0], `${this.prefix}/${event}`)).forEach(async (l) => l[1](parsed, ...args));
1672
1745
  }
1673
1746
  off(listener) {
1674
1747
  this.listeners = this.listeners.filter((l) => l[1] != listener);
1675
1748
  }
1676
1749
  on(event, listener) {
1677
1750
  makeArray(event).forEach((e) => this.listeners.push([
1678
- new PathEvent(`${this.prefix}/${typeof e == "string" ? event : event.toString()}`),
1751
+ new PathEvent(`${this.prefix}/${new PathEvent(e).toString()}`),
1679
1752
  listener
1680
1753
  ]));
1681
1754
  return () => this.off(listener);
@@ -1746,9 +1819,6 @@ function logicTest(target, condition) {
1746
1819
  }).length == and.length;
1747
1820
  });
1748
1821
  }
1749
- function typeKeys() {
1750
- return Object.keys({});
1751
- }
1752
1822
  var commonjsGlobal = typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : {};
1753
1823
  var dist = {};
1754
1824
  var persist$1 = {};
@@ -1929,6 +1999,7 @@ export {
1929
1999
  CliBackground,
1930
2000
  CliEffects,
1931
2001
  CliForeground,
2002
+ Collection,
1932
2003
  CustomError,
1933
2004
  ForbiddenError,
1934
2005
  GatewayTimeoutError,
@@ -1959,10 +2030,11 @@ export {
1959
2030
  addUnique,
1960
2031
  adjustedInterval,
1961
2032
  arrayDiff,
1962
- blackOrWhite,
1963
2033
  camelCase,
1964
2034
  caseInsensitiveSort,
1965
2035
  clean,
2036
+ contrast,
2037
+ createJwt,
1966
2038
  dec2Frac,
1967
2039
  decodeJwt,
1968
2040
  deepCopy,
@@ -2012,7 +2084,6 @@ export {
2012
2084
  timeUntil,
2013
2085
  timestampFilename,
2014
2086
  toCsv,
2015
- typeKeys,
2016
2087
  uploadWithProgress,
2017
2088
  validateEmail
2018
2089
  };