@ztimson/utils 0.25.27 → 0.26.0
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.cjs +383 -382
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +383 -382
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -392,315 +392,6 @@ function makeUnique(arr) {
|
|
|
392
392
|
function makeArray(value) {
|
|
393
393
|
return Array.isArray(value) ? value : [value];
|
|
394
394
|
}
|
|
395
|
-
function adjustedInterval(cb, ms) {
|
|
396
|
-
let cancel = false, timeout = null;
|
|
397
|
-
const p = async () => {
|
|
398
|
-
if (cancel) return;
|
|
399
|
-
const start = (/* @__PURE__ */ new Date()).getTime();
|
|
400
|
-
await cb();
|
|
401
|
-
const end = (/* @__PURE__ */ new Date()).getTime();
|
|
402
|
-
timeout = setTimeout(() => p(), ms - (end - start) || 1);
|
|
403
|
-
};
|
|
404
|
-
p();
|
|
405
|
-
return () => {
|
|
406
|
-
cancel = true;
|
|
407
|
-
if (timeout) clearTimeout(timeout);
|
|
408
|
-
};
|
|
409
|
-
}
|
|
410
|
-
function formatDate(format = "YYYY-MM-DD H:mm", date = /* @__PURE__ */ new Date(), tz) {
|
|
411
|
-
const timezones = [
|
|
412
|
-
["IDLW", -12],
|
|
413
|
-
["SST", -11],
|
|
414
|
-
["HST", -10],
|
|
415
|
-
["AKST", -9],
|
|
416
|
-
["PST", -8],
|
|
417
|
-
["MST", -7],
|
|
418
|
-
["CST", -6],
|
|
419
|
-
["EST", -5],
|
|
420
|
-
["AST", -4],
|
|
421
|
-
["BRT", -3],
|
|
422
|
-
["MAT", -2],
|
|
423
|
-
["AZOT", -1],
|
|
424
|
-
["UTC", 0],
|
|
425
|
-
["CET", 1],
|
|
426
|
-
["EET", 2],
|
|
427
|
-
["MSK", 3],
|
|
428
|
-
["AST", 4],
|
|
429
|
-
["PKT", 5],
|
|
430
|
-
["IST", 5.5],
|
|
431
|
-
["BST", 6],
|
|
432
|
-
["ICT", 7],
|
|
433
|
-
["CST", 8],
|
|
434
|
-
["JST", 9],
|
|
435
|
-
["AEST", 10],
|
|
436
|
-
["SBT", 11],
|
|
437
|
-
["FJT", 12],
|
|
438
|
-
["TOT", 13],
|
|
439
|
-
["LINT", 14]
|
|
440
|
-
];
|
|
441
|
-
function adjustTz(date2, gmt) {
|
|
442
|
-
const currentOffset = date2.getTimezoneOffset();
|
|
443
|
-
const adjustedOffset = gmt * 60;
|
|
444
|
-
return new Date(date2.getTime() + (adjustedOffset + currentOffset) * 6e4);
|
|
445
|
-
}
|
|
446
|
-
function day(num) {
|
|
447
|
-
return ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"][num] || "Unknown";
|
|
448
|
-
}
|
|
449
|
-
function doy(date2) {
|
|
450
|
-
const start = /* @__PURE__ */ new Date(`${date2.getFullYear()}-01-01 0:00:00`);
|
|
451
|
-
return Math.ceil((date2.getTime() - start.getTime()) / (1e3 * 60 * 60 * 24));
|
|
452
|
-
}
|
|
453
|
-
function month(num) {
|
|
454
|
-
return ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"][num] || "Unknown";
|
|
455
|
-
}
|
|
456
|
-
function suffix(num) {
|
|
457
|
-
if (num % 100 >= 11 && num % 100 <= 13) return `${num}th`;
|
|
458
|
-
switch (num % 10) {
|
|
459
|
-
case 1:
|
|
460
|
-
return `${num}st`;
|
|
461
|
-
case 2:
|
|
462
|
-
return `${num}nd`;
|
|
463
|
-
case 3:
|
|
464
|
-
return `${num}rd`;
|
|
465
|
-
default:
|
|
466
|
-
return `${num}th`;
|
|
467
|
-
}
|
|
468
|
-
}
|
|
469
|
-
function tzOffset(offset) {
|
|
470
|
-
const hours = ~~(offset / 60);
|
|
471
|
-
const minutes = offset % 60;
|
|
472
|
-
return (offset > 0 ? "-" : "") + `${hours}:${minutes.toString().padStart(2, "0")}`;
|
|
473
|
-
}
|
|
474
|
-
if (typeof date == "number" || typeof date == "string" || date == null) date = new Date(date);
|
|
475
|
-
let t;
|
|
476
|
-
if (tz == null) tz = -(date.getTimezoneOffset() / 60);
|
|
477
|
-
t = timezones.find((t2) => isNaN(tz) ? t2[0] == tz : t2[1] == tz);
|
|
478
|
-
if (!t) throw new Error(`Unknown timezone: ${tz}`);
|
|
479
|
-
date = adjustTz(date, t[1]);
|
|
480
|
-
const tokens = {
|
|
481
|
-
"YYYY": date.getFullYear().toString(),
|
|
482
|
-
"YY": date.getFullYear().toString().slice(2),
|
|
483
|
-
"MMMM": month(date.getMonth()),
|
|
484
|
-
"MMM": month(date.getMonth()).slice(0, 3),
|
|
485
|
-
"MM": (date.getMonth() + 1).toString().padStart(2, "0"),
|
|
486
|
-
"M": (date.getMonth() + 1).toString(),
|
|
487
|
-
"DDD": doy(date).toString(),
|
|
488
|
-
"DD": date.getDate().toString().padStart(2, "0"),
|
|
489
|
-
"Do": suffix(date.getDate()),
|
|
490
|
-
"D": date.getDate().toString(),
|
|
491
|
-
"dddd": day(date.getDay()),
|
|
492
|
-
"ddd": day(date.getDay()).slice(0, 3),
|
|
493
|
-
"HH": date.getHours().toString().padStart(2, "0"),
|
|
494
|
-
"H": date.getHours().toString(),
|
|
495
|
-
"hh": (date.getHours() % 12 || 12).toString().padStart(2, "0"),
|
|
496
|
-
"h": (date.getHours() % 12 || 12).toString(),
|
|
497
|
-
"mm": date.getMinutes().toString().padStart(2, "0"),
|
|
498
|
-
"m": date.getMinutes().toString(),
|
|
499
|
-
"ss": date.getSeconds().toString().padStart(2, "0"),
|
|
500
|
-
"s": date.getSeconds().toString(),
|
|
501
|
-
"SSS": date.getMilliseconds().toString().padStart(3, "0"),
|
|
502
|
-
"A": date.getHours() >= 12 ? "PM" : "AM",
|
|
503
|
-
"a": date.getHours() >= 12 ? "pm" : "am",
|
|
504
|
-
"ZZ": tzOffset(t[1] * 60).replace(":", ""),
|
|
505
|
-
"Z": tzOffset(t[1] * 60),
|
|
506
|
-
"z": typeof tz == "string" ? tz : t[0]
|
|
507
|
-
};
|
|
508
|
-
return format.replace(/YYYY|YY|MMMM|MMM|MM|M|DDD|DD|Do|D|dddd|ddd|HH|H|hh|h|mm|m|ss|s|SSS|A|a|ZZ|Z|z/g, (token) => tokens[token]);
|
|
509
|
-
}
|
|
510
|
-
function instantInterval(fn2, interval) {
|
|
511
|
-
fn2();
|
|
512
|
-
return setInterval(fn2, interval);
|
|
513
|
-
}
|
|
514
|
-
function sleep(ms) {
|
|
515
|
-
return new Promise((res) => setTimeout(res, ms));
|
|
516
|
-
}
|
|
517
|
-
async function sleepWhile(fn2, checkInterval = 100) {
|
|
518
|
-
while (await fn2()) await sleep(checkInterval);
|
|
519
|
-
}
|
|
520
|
-
function timeUntil(date) {
|
|
521
|
-
return (date instanceof Date ? date.getTime() : date) - (/* @__PURE__ */ new Date()).getTime();
|
|
522
|
-
}
|
|
523
|
-
function timezoneOffset(tz, date = /* @__PURE__ */ new Date()) {
|
|
524
|
-
const dtf = new Intl.DateTimeFormat("en-US", {
|
|
525
|
-
timeZone: tz,
|
|
526
|
-
hour12: false,
|
|
527
|
-
year: "numeric",
|
|
528
|
-
month: "2-digit",
|
|
529
|
-
day: "2-digit",
|
|
530
|
-
hour: "2-digit",
|
|
531
|
-
minute: "2-digit",
|
|
532
|
-
second: "2-digit"
|
|
533
|
-
});
|
|
534
|
-
const parts = dtf.formatToParts(date);
|
|
535
|
-
const get = (type) => {
|
|
536
|
-
var _a;
|
|
537
|
-
return Number((_a = parts.find((v) => v.type === type)) == null ? void 0 : _a.value);
|
|
538
|
-
};
|
|
539
|
-
const y = get("year");
|
|
540
|
-
const mo = get("month");
|
|
541
|
-
const d = get("day");
|
|
542
|
-
const h = get("hour");
|
|
543
|
-
const m = get("minute");
|
|
544
|
-
const s = get("second");
|
|
545
|
-
const asUTC = Date.UTC(y, mo - 1, d, h, m, s);
|
|
546
|
-
const asLocal = date.getTime();
|
|
547
|
-
return Math.round((asLocal - asUTC) / 6e4);
|
|
548
|
-
}
|
|
549
|
-
class AsyncLock {
|
|
550
|
-
constructor() {
|
|
551
|
-
__publicField(this, "p", Promise.resolve());
|
|
552
|
-
}
|
|
553
|
-
run(fn2) {
|
|
554
|
-
const res = this.p.then(fn2, fn2);
|
|
555
|
-
this.p = res.then(() => {
|
|
556
|
-
}, () => {
|
|
557
|
-
});
|
|
558
|
-
return res;
|
|
559
|
-
}
|
|
560
|
-
}
|
|
561
|
-
class Database {
|
|
562
|
-
constructor(database, tables, version) {
|
|
563
|
-
__publicField(this, "schemaLock", new AsyncLock());
|
|
564
|
-
__publicField(this, "upgrading", false);
|
|
565
|
-
__publicField(this, "connection");
|
|
566
|
-
__publicField(this, "tables");
|
|
567
|
-
__publicField(this, "waitForUpgrade", () => sleepWhile(() => this.upgrading));
|
|
568
|
-
this.database = database;
|
|
569
|
-
this.version = version;
|
|
570
|
-
this.connection = new Promise((resolve, reject) => {
|
|
571
|
-
const req = indexedDB.open(this.database, this.version);
|
|
572
|
-
this.tables = !tables ? [] : tables.map((t) => {
|
|
573
|
-
t = typeof t == "object" ? t : { name: t };
|
|
574
|
-
return { ...t, name: t.name.toString() };
|
|
575
|
-
});
|
|
576
|
-
req.onerror = () => reject(req.error);
|
|
577
|
-
req.onsuccess = () => {
|
|
578
|
-
const db = req.result;
|
|
579
|
-
const existing = Array.from(db.objectStoreNames);
|
|
580
|
-
if (!tables) this.tables = existing.map((t) => {
|
|
581
|
-
const tx = db.transaction(t, "readonly");
|
|
582
|
-
const store = tx.objectStore(t);
|
|
583
|
-
return { name: t, key: store.keyPath };
|
|
584
|
-
});
|
|
585
|
-
const desired = new ASet((tables || []).map((t) => typeof t == "string" ? t : t.name));
|
|
586
|
-
if (tables && desired.symmetricDifference(new ASet(existing)).length) {
|
|
587
|
-
db.close();
|
|
588
|
-
Object.assign(this, new Database(this.database, this.tables, db.version + 1));
|
|
589
|
-
this.connection.then(resolve);
|
|
590
|
-
} else {
|
|
591
|
-
this.version = db.version;
|
|
592
|
-
resolve(db);
|
|
593
|
-
}
|
|
594
|
-
this.upgrading = false;
|
|
595
|
-
};
|
|
596
|
-
req.onupgradeneeded = () => {
|
|
597
|
-
this.upgrading = true;
|
|
598
|
-
const db = req.result;
|
|
599
|
-
const existingTables = new ASet(Array.from(db.objectStoreNames));
|
|
600
|
-
if (tables) {
|
|
601
|
-
const desired = new ASet((tables || []).map((t) => typeof t == "string" ? t : t.name));
|
|
602
|
-
existingTables.difference(desired).forEach((name) => db.deleteObjectStore(name));
|
|
603
|
-
desired.difference(existingTables).forEach((name) => {
|
|
604
|
-
const t = this.tables.find(findByProp("name", name));
|
|
605
|
-
db.createObjectStore(name, {
|
|
606
|
-
keyPath: t == null ? void 0 : t.key,
|
|
607
|
-
autoIncrement: (t == null ? void 0 : t.autoIncrement) || !(t == null ? void 0 : t.key)
|
|
608
|
-
});
|
|
609
|
-
});
|
|
610
|
-
}
|
|
611
|
-
};
|
|
612
|
-
});
|
|
613
|
-
}
|
|
614
|
-
get ready() {
|
|
615
|
-
return !this.upgrading;
|
|
616
|
-
}
|
|
617
|
-
async createTable(table) {
|
|
618
|
-
return this.schemaLock.run(async () => {
|
|
619
|
-
if (typeof table == "string") table = { name: table };
|
|
620
|
-
const conn = await this.connection;
|
|
621
|
-
if (!this.includes(table.name)) {
|
|
622
|
-
const newDb = new Database(this.database, [...this.tables, table], (this.version ?? 0) + 1);
|
|
623
|
-
conn.close();
|
|
624
|
-
Object.assign(this, newDb);
|
|
625
|
-
await this.connection;
|
|
626
|
-
}
|
|
627
|
-
return this.table(table.name);
|
|
628
|
-
});
|
|
629
|
-
}
|
|
630
|
-
async deleteTable(table) {
|
|
631
|
-
return this.schemaLock.run(async () => {
|
|
632
|
-
if (typeof table == "string") table = { name: table };
|
|
633
|
-
if (!this.includes(table.name)) return;
|
|
634
|
-
const conn = await this.connection;
|
|
635
|
-
const newDb = new Database(this.database, this.tables.filter((t) => t.name != table.name), (this.version ?? 0) + 1);
|
|
636
|
-
conn.close();
|
|
637
|
-
Object.assign(this, newDb);
|
|
638
|
-
await this.connection;
|
|
639
|
-
});
|
|
640
|
-
}
|
|
641
|
-
includes(name) {
|
|
642
|
-
return !!this.tables.find((t) => t.name == (typeof name == "object" ? name.name : name.toString()));
|
|
643
|
-
}
|
|
644
|
-
table(name) {
|
|
645
|
-
return new Table(this, name.toString());
|
|
646
|
-
}
|
|
647
|
-
}
|
|
648
|
-
class Table {
|
|
649
|
-
constructor(database, name, key = "id") {
|
|
650
|
-
__publicField(this, "all", this.getAll);
|
|
651
|
-
__publicField(this, "create", this.add);
|
|
652
|
-
__publicField(this, "update", this.set);
|
|
653
|
-
this.database = database;
|
|
654
|
-
this.name = name;
|
|
655
|
-
this.key = key;
|
|
656
|
-
this.database.connection.then(() => {
|
|
657
|
-
const exists = !!this.database.tables.find(findByProp("name", this.name));
|
|
658
|
-
if (!exists) this.database.createTable(this.name);
|
|
659
|
-
});
|
|
660
|
-
}
|
|
661
|
-
async tx(table, fn2, readonly = false) {
|
|
662
|
-
await this.database.waitForUpgrade();
|
|
663
|
-
const db = await this.database.connection;
|
|
664
|
-
const tx = db.transaction(table, readonly ? "readonly" : "readwrite");
|
|
665
|
-
const store = tx.objectStore(table);
|
|
666
|
-
return new Promise((resolve, reject) => {
|
|
667
|
-
const request = fn2(store);
|
|
668
|
-
request.onsuccess = () => resolve(request.result);
|
|
669
|
-
request.onerror = () => reject(request.error);
|
|
670
|
-
});
|
|
671
|
-
}
|
|
672
|
-
add(value, key) {
|
|
673
|
-
return this.tx(this.name, (store) => store.add(value, key));
|
|
674
|
-
}
|
|
675
|
-
clear() {
|
|
676
|
-
return this.tx(this.name, (store) => store.clear());
|
|
677
|
-
}
|
|
678
|
-
count() {
|
|
679
|
-
return this.tx(this.name, (store) => store.count(), true);
|
|
680
|
-
}
|
|
681
|
-
delete(key) {
|
|
682
|
-
return this.tx(this.name, (store) => store.delete(key));
|
|
683
|
-
}
|
|
684
|
-
get(key) {
|
|
685
|
-
return this.tx(this.name, (store) => store.get(key), true);
|
|
686
|
-
}
|
|
687
|
-
getAll() {
|
|
688
|
-
return this.tx(this.name, (store) => store.getAll(), true);
|
|
689
|
-
}
|
|
690
|
-
getAllKeys() {
|
|
691
|
-
return this.tx(this.name, (store) => store.getAllKeys(), true);
|
|
692
|
-
}
|
|
693
|
-
put(key, value) {
|
|
694
|
-
return this.tx(this.name, (store) => store.put(value, key));
|
|
695
|
-
}
|
|
696
|
-
read(key) {
|
|
697
|
-
return key ? this.get(key) : this.getAll();
|
|
698
|
-
}
|
|
699
|
-
set(value, key) {
|
|
700
|
-
if (!key && !value[this.key]) return this.add(value);
|
|
701
|
-
return this.put(key || value[this.key], value);
|
|
702
|
-
}
|
|
703
|
-
}
|
|
704
395
|
class Cache {
|
|
705
396
|
/**
|
|
706
397
|
* Create new cache
|
|
@@ -761,9 +452,10 @@ class Cache {
|
|
|
761
452
|
return value[this.key];
|
|
762
453
|
}
|
|
763
454
|
save(key) {
|
|
455
|
+
var _a, _b;
|
|
764
456
|
const persists = this.options.persistentStorage;
|
|
765
457
|
if (!!(persists == null ? void 0 : persists.storage)) {
|
|
766
|
-
if (persists.storage
|
|
458
|
+
if (((_a = persists.storage) == null ? void 0 : _a.constructor.name) == "Database") {
|
|
767
459
|
persists.storage.createTable({ name: persists.storage.key, key: this.key }).then((table) => {
|
|
768
460
|
if (key) {
|
|
769
461
|
table.set(key, this.get(key));
|
|
@@ -772,7 +464,7 @@ class Cache {
|
|
|
772
464
|
this.all().forEach((row) => table.add(row));
|
|
773
465
|
}
|
|
774
466
|
});
|
|
775
|
-
} else {
|
|
467
|
+
} else if (((_b = persists.storage) == null ? void 0 : _b.constructor.name) == "Storage") {
|
|
776
468
|
persists.storage.setItem(persists.storage.key, JSONSanitize(this.all(true)));
|
|
777
469
|
}
|
|
778
470
|
}
|
|
@@ -1048,87 +740,396 @@ function md5_ff(d, _, m, f, r, i, n) {
|
|
|
1048
740
|
function md5_gg(d, _, m, f, r, i, n) {
|
|
1049
741
|
return md5_cmn(_ & f | m & ~f, d, _, r, i, n);
|
|
1050
742
|
}
|
|
1051
|
-
function md5_hh(d, _, m, f, r, i, n) {
|
|
1052
|
-
return md5_cmn(_ ^ m ^ f, d, _, r, i, n);
|
|
743
|
+
function md5_hh(d, _, m, f, r, i, n) {
|
|
744
|
+
return md5_cmn(_ ^ m ^ f, d, _, r, i, n);
|
|
745
|
+
}
|
|
746
|
+
function md5_ii(d, _, m, f, r, i, n) {
|
|
747
|
+
return md5_cmn(m ^ (_ | ~f), d, _, r, i, n);
|
|
748
|
+
}
|
|
749
|
+
function safe_add(d, _) {
|
|
750
|
+
var m = (65535 & d) + (65535 & _);
|
|
751
|
+
return (d >> 16) + (_ >> 16) + (m >> 16) << 16 | 65535 & m;
|
|
752
|
+
}
|
|
753
|
+
function bit_rol(d, _) {
|
|
754
|
+
return d << _ | d >>> 32 - _;
|
|
755
|
+
}
|
|
756
|
+
function wordSegments(str) {
|
|
757
|
+
if (!str) return [];
|
|
758
|
+
return str.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").replace(/([0-9]+)([a-zA-Z])/g, "$1 $2").replace(/([a-zA-Z])([0-9]+)/g, "$1 $2").replace(/[_\-\s]+/g, " ").trim().split(/\s+/).filter(Boolean);
|
|
759
|
+
}
|
|
760
|
+
function validateEmail(email) {
|
|
761
|
+
return /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/.test(email);
|
|
762
|
+
}
|
|
763
|
+
function fromCsv(csv, hasHeaders = true) {
|
|
764
|
+
var _a;
|
|
765
|
+
function parseLine(line) {
|
|
766
|
+
const columns = [];
|
|
767
|
+
let current = "", inQuotes2 = false;
|
|
768
|
+
for (let i = 0; i < line.length; i++) {
|
|
769
|
+
const char = line[i];
|
|
770
|
+
const nextChar = line[i + 1];
|
|
771
|
+
if (char === '"') {
|
|
772
|
+
if (inQuotes2 && nextChar === '"') {
|
|
773
|
+
current += '"';
|
|
774
|
+
i++;
|
|
775
|
+
} else inQuotes2 = !inQuotes2;
|
|
776
|
+
} else if (char === "," && !inQuotes2) {
|
|
777
|
+
columns.push(current.trim());
|
|
778
|
+
current = "";
|
|
779
|
+
} else current += char;
|
|
780
|
+
}
|
|
781
|
+
columns.push(current.trim());
|
|
782
|
+
return columns.map((col) => col.replace(/^"|"$/g, "").replace(/""/g, '"'));
|
|
783
|
+
}
|
|
784
|
+
const rows = [];
|
|
785
|
+
let currentRow = "", inQuotes = false;
|
|
786
|
+
for (const char of csv.replace(/\r\n/g, "\n")) {
|
|
787
|
+
if (char === '"') inQuotes = !inQuotes;
|
|
788
|
+
if (char === "\n" && !inQuotes) {
|
|
789
|
+
rows.push(currentRow.trim());
|
|
790
|
+
currentRow = "";
|
|
791
|
+
} else currentRow += char;
|
|
792
|
+
}
|
|
793
|
+
if (currentRow) rows.push(currentRow.trim());
|
|
794
|
+
let headers = hasHeaders ? rows.splice(0, 1)[0] : null;
|
|
795
|
+
if (headers) headers = (_a = headers.match(/(?:[^,"']+|"(?:[^"]|"")*"|'(?:[^']|'')*')+/g)) == null ? void 0 : _a.map((h) => h.trim());
|
|
796
|
+
return rows.map((r) => {
|
|
797
|
+
const props = parseLine(r);
|
|
798
|
+
const h = headers || Array(props.length).fill(null).map((_, i) => {
|
|
799
|
+
let letter = "";
|
|
800
|
+
const first = i / 26;
|
|
801
|
+
if (first > 1) letter += LETTER_LIST[Math.floor(first - 1)];
|
|
802
|
+
letter += LETTER_LIST[i % 26];
|
|
803
|
+
return letter;
|
|
804
|
+
});
|
|
805
|
+
return h.reduce((acc, h2, i) => {
|
|
806
|
+
dotNotation(acc, h2, props[i]);
|
|
807
|
+
return acc;
|
|
808
|
+
}, {});
|
|
809
|
+
});
|
|
810
|
+
}
|
|
811
|
+
function toCsv(target, flatten = true) {
|
|
812
|
+
const t = makeArray(target);
|
|
813
|
+
const headers = new ASet(t.reduce((acc, row) => [...acc, ...Object.keys(flatten ? flattenObj(row) : row)], []));
|
|
814
|
+
return [
|
|
815
|
+
headers.join(","),
|
|
816
|
+
...t.map((row) => headers.map((h) => {
|
|
817
|
+
const value = dotNotation(row, h);
|
|
818
|
+
if (value == null) return "";
|
|
819
|
+
if (typeof value == "object") return `"${JSONSanitize(value).replaceAll('"', '""')}"`;
|
|
820
|
+
if (typeof value == "string" && /[\n",]/g.test(value)) return `"${value.replaceAll('"', '""')}"`;
|
|
821
|
+
return value;
|
|
822
|
+
}).join(","))
|
|
823
|
+
].join("\n");
|
|
824
|
+
}
|
|
825
|
+
function adjustedInterval(cb, ms) {
|
|
826
|
+
let cancel = false, timeout = null;
|
|
827
|
+
const p = async () => {
|
|
828
|
+
if (cancel) return;
|
|
829
|
+
const start = (/* @__PURE__ */ new Date()).getTime();
|
|
830
|
+
await cb();
|
|
831
|
+
const end = (/* @__PURE__ */ new Date()).getTime();
|
|
832
|
+
timeout = setTimeout(() => p(), ms - (end - start) || 1);
|
|
833
|
+
};
|
|
834
|
+
p();
|
|
835
|
+
return () => {
|
|
836
|
+
cancel = true;
|
|
837
|
+
if (timeout) clearTimeout(timeout);
|
|
838
|
+
};
|
|
839
|
+
}
|
|
840
|
+
function formatDate(format = "YYYY-MM-DD H:mm", date = /* @__PURE__ */ new Date(), tz) {
|
|
841
|
+
const timezones = [
|
|
842
|
+
["IDLW", -12],
|
|
843
|
+
["SST", -11],
|
|
844
|
+
["HST", -10],
|
|
845
|
+
["AKST", -9],
|
|
846
|
+
["PST", -8],
|
|
847
|
+
["MST", -7],
|
|
848
|
+
["CST", -6],
|
|
849
|
+
["EST", -5],
|
|
850
|
+
["AST", -4],
|
|
851
|
+
["BRT", -3],
|
|
852
|
+
["MAT", -2],
|
|
853
|
+
["AZOT", -1],
|
|
854
|
+
["UTC", 0],
|
|
855
|
+
["CET", 1],
|
|
856
|
+
["EET", 2],
|
|
857
|
+
["MSK", 3],
|
|
858
|
+
["AST", 4],
|
|
859
|
+
["PKT", 5],
|
|
860
|
+
["IST", 5.5],
|
|
861
|
+
["BST", 6],
|
|
862
|
+
["ICT", 7],
|
|
863
|
+
["CST", 8],
|
|
864
|
+
["JST", 9],
|
|
865
|
+
["AEST", 10],
|
|
866
|
+
["SBT", 11],
|
|
867
|
+
["FJT", 12],
|
|
868
|
+
["TOT", 13],
|
|
869
|
+
["LINT", 14]
|
|
870
|
+
];
|
|
871
|
+
function adjustTz(date2, gmt) {
|
|
872
|
+
const currentOffset = date2.getTimezoneOffset();
|
|
873
|
+
const adjustedOffset = gmt * 60;
|
|
874
|
+
return new Date(date2.getTime() + (adjustedOffset + currentOffset) * 6e4);
|
|
875
|
+
}
|
|
876
|
+
function day(num) {
|
|
877
|
+
return ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"][num] || "Unknown";
|
|
878
|
+
}
|
|
879
|
+
function doy(date2) {
|
|
880
|
+
const start = /* @__PURE__ */ new Date(`${date2.getFullYear()}-01-01 0:00:00`);
|
|
881
|
+
return Math.ceil((date2.getTime() - start.getTime()) / (1e3 * 60 * 60 * 24));
|
|
882
|
+
}
|
|
883
|
+
function month(num) {
|
|
884
|
+
return ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"][num] || "Unknown";
|
|
885
|
+
}
|
|
886
|
+
function suffix(num) {
|
|
887
|
+
if (num % 100 >= 11 && num % 100 <= 13) return `${num}th`;
|
|
888
|
+
switch (num % 10) {
|
|
889
|
+
case 1:
|
|
890
|
+
return `${num}st`;
|
|
891
|
+
case 2:
|
|
892
|
+
return `${num}nd`;
|
|
893
|
+
case 3:
|
|
894
|
+
return `${num}rd`;
|
|
895
|
+
default:
|
|
896
|
+
return `${num}th`;
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
function tzOffset(offset) {
|
|
900
|
+
const hours = ~~(offset / 60);
|
|
901
|
+
const minutes = offset % 60;
|
|
902
|
+
return (offset > 0 ? "-" : "") + `${hours}:${minutes.toString().padStart(2, "0")}`;
|
|
903
|
+
}
|
|
904
|
+
if (typeof date == "number" || typeof date == "string" || date == null) date = new Date(date);
|
|
905
|
+
let t;
|
|
906
|
+
if (tz == null) tz = -(date.getTimezoneOffset() / 60);
|
|
907
|
+
t = timezones.find((t2) => isNaN(tz) ? t2[0] == tz : t2[1] == tz);
|
|
908
|
+
if (!t) throw new Error(`Unknown timezone: ${tz}`);
|
|
909
|
+
date = adjustTz(date, t[1]);
|
|
910
|
+
const tokens = {
|
|
911
|
+
"YYYY": date.getFullYear().toString(),
|
|
912
|
+
"YY": date.getFullYear().toString().slice(2),
|
|
913
|
+
"MMMM": month(date.getMonth()),
|
|
914
|
+
"MMM": month(date.getMonth()).slice(0, 3),
|
|
915
|
+
"MM": (date.getMonth() + 1).toString().padStart(2, "0"),
|
|
916
|
+
"M": (date.getMonth() + 1).toString(),
|
|
917
|
+
"DDD": doy(date).toString(),
|
|
918
|
+
"DD": date.getDate().toString().padStart(2, "0"),
|
|
919
|
+
"Do": suffix(date.getDate()),
|
|
920
|
+
"D": date.getDate().toString(),
|
|
921
|
+
"dddd": day(date.getDay()),
|
|
922
|
+
"ddd": day(date.getDay()).slice(0, 3),
|
|
923
|
+
"HH": date.getHours().toString().padStart(2, "0"),
|
|
924
|
+
"H": date.getHours().toString(),
|
|
925
|
+
"hh": (date.getHours() % 12 || 12).toString().padStart(2, "0"),
|
|
926
|
+
"h": (date.getHours() % 12 || 12).toString(),
|
|
927
|
+
"mm": date.getMinutes().toString().padStart(2, "0"),
|
|
928
|
+
"m": date.getMinutes().toString(),
|
|
929
|
+
"ss": date.getSeconds().toString().padStart(2, "0"),
|
|
930
|
+
"s": date.getSeconds().toString(),
|
|
931
|
+
"SSS": date.getMilliseconds().toString().padStart(3, "0"),
|
|
932
|
+
"A": date.getHours() >= 12 ? "PM" : "AM",
|
|
933
|
+
"a": date.getHours() >= 12 ? "pm" : "am",
|
|
934
|
+
"ZZ": tzOffset(t[1] * 60).replace(":", ""),
|
|
935
|
+
"Z": tzOffset(t[1] * 60),
|
|
936
|
+
"z": typeof tz == "string" ? tz : t[0]
|
|
937
|
+
};
|
|
938
|
+
return format.replace(/YYYY|YY|MMMM|MMM|MM|M|DDD|DD|Do|D|dddd|ddd|HH|H|hh|h|mm|m|ss|s|SSS|A|a|ZZ|Z|z/g, (token) => tokens[token]);
|
|
939
|
+
}
|
|
940
|
+
function instantInterval(fn2, interval) {
|
|
941
|
+
fn2();
|
|
942
|
+
return setInterval(fn2, interval);
|
|
1053
943
|
}
|
|
1054
|
-
function
|
|
1055
|
-
return
|
|
944
|
+
function sleep(ms) {
|
|
945
|
+
return new Promise((res) => setTimeout(res, ms));
|
|
1056
946
|
}
|
|
1057
|
-
function
|
|
1058
|
-
|
|
1059
|
-
return (d >> 16) + (_ >> 16) + (m >> 16) << 16 | 65535 & m;
|
|
947
|
+
async function sleepWhile(fn2, checkInterval = 100) {
|
|
948
|
+
while (await fn2()) await sleep(checkInterval);
|
|
1060
949
|
}
|
|
1061
|
-
function
|
|
1062
|
-
return
|
|
950
|
+
function timeUntil(date) {
|
|
951
|
+
return (date instanceof Date ? date.getTime() : date) - (/* @__PURE__ */ new Date()).getTime();
|
|
1063
952
|
}
|
|
1064
|
-
function
|
|
1065
|
-
|
|
1066
|
-
|
|
953
|
+
function timezoneOffset(tz, date = /* @__PURE__ */ new Date()) {
|
|
954
|
+
const dtf = new Intl.DateTimeFormat("en-US", {
|
|
955
|
+
timeZone: tz,
|
|
956
|
+
hour12: false,
|
|
957
|
+
year: "numeric",
|
|
958
|
+
month: "2-digit",
|
|
959
|
+
day: "2-digit",
|
|
960
|
+
hour: "2-digit",
|
|
961
|
+
minute: "2-digit",
|
|
962
|
+
second: "2-digit"
|
|
963
|
+
});
|
|
964
|
+
const parts = dtf.formatToParts(date);
|
|
965
|
+
const get = (type) => {
|
|
966
|
+
var _a;
|
|
967
|
+
return Number((_a = parts.find((v) => v.type === type)) == null ? void 0 : _a.value);
|
|
968
|
+
};
|
|
969
|
+
const y = get("year");
|
|
970
|
+
const mo = get("month");
|
|
971
|
+
const d = get("day");
|
|
972
|
+
const h = get("hour");
|
|
973
|
+
const m = get("minute");
|
|
974
|
+
const s = get("second");
|
|
975
|
+
const asUTC = Date.UTC(y, mo - 1, d, h, m, s);
|
|
976
|
+
const asLocal = date.getTime();
|
|
977
|
+
return Math.round((asLocal - asUTC) / 6e4);
|
|
1067
978
|
}
|
|
1068
|
-
|
|
1069
|
-
|
|
979
|
+
class AsyncLock {
|
|
980
|
+
constructor() {
|
|
981
|
+
__publicField(this, "p", Promise.resolve());
|
|
982
|
+
}
|
|
983
|
+
run(fn2) {
|
|
984
|
+
const res = this.p.then(fn2, fn2);
|
|
985
|
+
this.p = res.then(() => {
|
|
986
|
+
}, () => {
|
|
987
|
+
});
|
|
988
|
+
return res;
|
|
989
|
+
}
|
|
1070
990
|
}
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
991
|
+
class Database {
|
|
992
|
+
constructor(database, tables, version) {
|
|
993
|
+
__publicField(this, "schemaLock", new AsyncLock());
|
|
994
|
+
__publicField(this, "upgrading", false);
|
|
995
|
+
__publicField(this, "connection");
|
|
996
|
+
__publicField(this, "tables");
|
|
997
|
+
__publicField(this, "waitForUpgrade", () => sleepWhile(() => this.upgrading));
|
|
998
|
+
this.database = database;
|
|
999
|
+
this.version = version;
|
|
1000
|
+
this.connection = new Promise((resolve, reject) => {
|
|
1001
|
+
const req = indexedDB.open(this.database, this.version);
|
|
1002
|
+
this.tables = !tables ? [] : tables.map((t) => {
|
|
1003
|
+
t = typeof t == "object" ? t : { name: t };
|
|
1004
|
+
return { ...t, name: t.name.toString() };
|
|
1005
|
+
});
|
|
1006
|
+
req.onerror = () => reject(req.error);
|
|
1007
|
+
req.onsuccess = () => {
|
|
1008
|
+
const db = req.result;
|
|
1009
|
+
const existing = Array.from(db.objectStoreNames);
|
|
1010
|
+
if (!tables) this.tables = existing.map((t) => {
|
|
1011
|
+
const tx = db.transaction(t, "readonly");
|
|
1012
|
+
const store = tx.objectStore(t);
|
|
1013
|
+
return { name: t, key: store.keyPath };
|
|
1014
|
+
});
|
|
1015
|
+
const desired = new ASet((tables || []).map((t) => typeof t == "string" ? t : t.name));
|
|
1016
|
+
if (tables && desired.symmetricDifference(new ASet(existing)).length) {
|
|
1017
|
+
db.close();
|
|
1018
|
+
Object.assign(this, new Database(this.database, this.tables, db.version + 1));
|
|
1019
|
+
this.connection.then(resolve);
|
|
1020
|
+
} else {
|
|
1021
|
+
this.version = db.version;
|
|
1022
|
+
resolve(db);
|
|
1023
|
+
}
|
|
1024
|
+
this.upgrading = false;
|
|
1025
|
+
};
|
|
1026
|
+
req.onupgradeneeded = () => {
|
|
1027
|
+
this.upgrading = true;
|
|
1028
|
+
const db = req.result;
|
|
1029
|
+
const existingTables = new ASet(Array.from(db.objectStoreNames));
|
|
1030
|
+
if (tables) {
|
|
1031
|
+
const desired = new ASet((tables || []).map((t) => typeof t == "string" ? t : t.name));
|
|
1032
|
+
existingTables.difference(desired).forEach((name) => db.deleteObjectStore(name));
|
|
1033
|
+
desired.difference(existingTables).forEach((name) => {
|
|
1034
|
+
const t = this.tables.find(findByProp("name", name));
|
|
1035
|
+
db.createObjectStore(name, {
|
|
1036
|
+
keyPath: t == null ? void 0 : t.key,
|
|
1037
|
+
autoIncrement: (t == null ? void 0 : t.autoIncrement) || !(t == null ? void 0 : t.key)
|
|
1038
|
+
});
|
|
1039
|
+
});
|
|
1040
|
+
}
|
|
1041
|
+
};
|
|
1042
|
+
});
|
|
1091
1043
|
}
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
for (const char of csv.replace(/\r\n/g, "\n")) {
|
|
1095
|
-
if (char === '"') inQuotes = !inQuotes;
|
|
1096
|
-
if (char === "\n" && !inQuotes) {
|
|
1097
|
-
rows.push(currentRow.trim());
|
|
1098
|
-
currentRow = "";
|
|
1099
|
-
} else currentRow += char;
|
|
1044
|
+
get ready() {
|
|
1045
|
+
return !this.upgrading;
|
|
1100
1046
|
}
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
return
|
|
1047
|
+
async createTable(table) {
|
|
1048
|
+
return this.schemaLock.run(async () => {
|
|
1049
|
+
if (typeof table == "string") table = { name: table };
|
|
1050
|
+
const conn = await this.connection;
|
|
1051
|
+
if (!this.includes(table.name)) {
|
|
1052
|
+
const newDb = new Database(this.database, [...this.tables, table], (this.version ?? 0) + 1);
|
|
1053
|
+
conn.close();
|
|
1054
|
+
Object.assign(this, newDb);
|
|
1055
|
+
await this.connection;
|
|
1056
|
+
}
|
|
1057
|
+
return this.table(table.name);
|
|
1112
1058
|
});
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1059
|
+
}
|
|
1060
|
+
async deleteTable(table) {
|
|
1061
|
+
return this.schemaLock.run(async () => {
|
|
1062
|
+
if (typeof table == "string") table = { name: table };
|
|
1063
|
+
if (!this.includes(table.name)) return;
|
|
1064
|
+
const conn = await this.connection;
|
|
1065
|
+
const newDb = new Database(this.database, this.tables.filter((t) => t.name != table.name), (this.version ?? 0) + 1);
|
|
1066
|
+
conn.close();
|
|
1067
|
+
Object.assign(this, newDb);
|
|
1068
|
+
await this.connection;
|
|
1069
|
+
});
|
|
1070
|
+
}
|
|
1071
|
+
includes(name) {
|
|
1072
|
+
return !!this.tables.find((t) => t.name == (typeof name == "object" ? name.name : name.toString()));
|
|
1073
|
+
}
|
|
1074
|
+
table(name) {
|
|
1075
|
+
return new Table(this, name.toString());
|
|
1076
|
+
}
|
|
1118
1077
|
}
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
})
|
|
1131
|
-
|
|
1078
|
+
class Table {
|
|
1079
|
+
constructor(database, name, key = "id") {
|
|
1080
|
+
__publicField(this, "all", this.getAll);
|
|
1081
|
+
__publicField(this, "create", this.add);
|
|
1082
|
+
__publicField(this, "update", this.set);
|
|
1083
|
+
this.database = database;
|
|
1084
|
+
this.name = name;
|
|
1085
|
+
this.key = key;
|
|
1086
|
+
this.database.connection.then(() => {
|
|
1087
|
+
const exists = !!this.database.tables.find(findByProp("name", this.name));
|
|
1088
|
+
if (!exists) this.database.createTable(this.name);
|
|
1089
|
+
});
|
|
1090
|
+
}
|
|
1091
|
+
async tx(table, fn2, readonly = false) {
|
|
1092
|
+
await this.database.waitForUpgrade();
|
|
1093
|
+
const db = await this.database.connection;
|
|
1094
|
+
const tx = db.transaction(table, readonly ? "readonly" : "readwrite");
|
|
1095
|
+
const store = tx.objectStore(table);
|
|
1096
|
+
return new Promise((resolve, reject) => {
|
|
1097
|
+
const request = fn2(store);
|
|
1098
|
+
request.onsuccess = () => resolve(request.result);
|
|
1099
|
+
request.onerror = () => reject(request.error);
|
|
1100
|
+
});
|
|
1101
|
+
}
|
|
1102
|
+
add(value, key) {
|
|
1103
|
+
return this.tx(this.name, (store) => store.add(value, key));
|
|
1104
|
+
}
|
|
1105
|
+
clear() {
|
|
1106
|
+
return this.tx(this.name, (store) => store.clear());
|
|
1107
|
+
}
|
|
1108
|
+
count() {
|
|
1109
|
+
return this.tx(this.name, (store) => store.count(), true);
|
|
1110
|
+
}
|
|
1111
|
+
delete(key) {
|
|
1112
|
+
return this.tx(this.name, (store) => store.delete(key));
|
|
1113
|
+
}
|
|
1114
|
+
get(key) {
|
|
1115
|
+
return this.tx(this.name, (store) => store.get(key), true);
|
|
1116
|
+
}
|
|
1117
|
+
getAll() {
|
|
1118
|
+
return this.tx(this.name, (store) => store.getAll(), true);
|
|
1119
|
+
}
|
|
1120
|
+
getAllKeys() {
|
|
1121
|
+
return this.tx(this.name, (store) => store.getAllKeys(), true);
|
|
1122
|
+
}
|
|
1123
|
+
put(key, value) {
|
|
1124
|
+
return this.tx(this.name, (store) => store.put(value, key));
|
|
1125
|
+
}
|
|
1126
|
+
read(key) {
|
|
1127
|
+
return key ? this.get(key) : this.getAll();
|
|
1128
|
+
}
|
|
1129
|
+
set(value, key) {
|
|
1130
|
+
if (!key && !value[this.key]) return this.add(value);
|
|
1131
|
+
return this.put(key || value[this.key], value);
|
|
1132
|
+
}
|
|
1132
1133
|
}
|
|
1133
1134
|
class PromiseProgress extends Promise {
|
|
1134
1135
|
constructor(executor) {
|