tiny-essentials 1.19.2 → 1.20.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/v1/TinyEssentials.js +1009 -22
- package/dist/v1/TinyEssentials.min.js +1 -1
- package/dist/v1/TinyIframeEvents.js +854 -0
- package/dist/v1/TinyIframeEvents.min.js +1 -0
- package/dist/v1/TinyLocalStorage.js +109 -21
- package/dist/v1/TinyLocalStorage.min.js +1 -1
- package/dist/v1/TinyNewWinEvents.js +888 -0
- package/dist/v1/TinyNewWinEvents.min.js +1 -0
- package/dist/v1/TinyUploadClicker.js +1022 -37
- package/dist/v1/TinyUploadClicker.min.js +1 -1
- package/dist/v1/build/TinyIframeEvents.cjs +7 -0
- package/dist/v1/build/TinyIframeEvents.d.mts +3 -0
- package/dist/v1/build/TinyIframeEvents.mjs +2 -0
- package/dist/v1/build/TinyNewWinEvents.cjs +7 -0
- package/dist/v1/build/TinyNewWinEvents.d.mts +3 -0
- package/dist/v1/build/TinyNewWinEvents.mjs +2 -0
- package/dist/v1/index.cjs +4 -0
- package/dist/v1/index.d.mts +3 -1
- package/dist/v1/index.mjs +3 -1
- package/dist/v1/libs/TinyIframeEvents.cjs +409 -0
- package/dist/v1/libs/TinyIframeEvents.d.mts +193 -0
- package/dist/v1/libs/TinyIframeEvents.mjs +348 -0
- package/dist/v1/libs/TinyLocalStorage.cjs +109 -21
- package/dist/v1/libs/TinyLocalStorage.d.mts +29 -0
- package/dist/v1/libs/TinyLocalStorage.mjs +97 -21
- package/dist/v1/libs/TinyNewWinEvents.cjs +486 -0
- package/dist/v1/libs/TinyNewWinEvents.d.mts +241 -0
- package/dist/v1/libs/TinyNewWinEvents.mjs +437 -0
- package/docs/v1/README.md +2 -0
- package/docs/v1/libs/TinyIframeEvents.md +149 -0
- package/docs/v1/libs/TinyLocalStorage.md +53 -0
- package/docs/v1/libs/TinyNewWinEvents.md +186 -0
- package/docs/v1/libs/TinyNotifyCenter.md +1 -1
- package/package.json +1 -1
|
@@ -375,16 +375,83 @@ class TinyLocalStorage {
|
|
|
375
375
|
//////////////////////////////////////////////////////
|
|
376
376
|
/** @type {Storage} */
|
|
377
377
|
#localStorage = window.localStorage;
|
|
378
|
+
/** @type {string|null} */
|
|
379
|
+
#dbKey = null;
|
|
380
|
+
/** @type {number} */
|
|
381
|
+
#version = 0;
|
|
378
382
|
/** @type {(ev: StorageEvent) => any} */
|
|
379
383
|
#storageEvent = (ev) => this.emit('storage', ev);
|
|
380
384
|
/**
|
|
381
385
|
* Initializes the TinyLocalStorage instance and sets up cross-tab sync.
|
|
382
386
|
*
|
|
383
387
|
* Adds listener for the native `storage` event to support tab synchronization.
|
|
388
|
+
* @param {string} [dbName] - Unique database name.
|
|
384
389
|
*/
|
|
385
|
-
constructor() {
|
|
390
|
+
constructor(dbName) {
|
|
391
|
+
if (typeof dbName !== 'undefined' && typeof dbName !== 'string')
|
|
392
|
+
throw new TypeError('TinyLocalStorage: dbName must be a string if provided.');
|
|
393
|
+
if (typeof dbName === 'string')
|
|
394
|
+
this.#dbKey = `LSDB::${dbName}`;
|
|
386
395
|
window.addEventListener('storage', this.#storageEvent);
|
|
387
396
|
}
|
|
397
|
+
/**
|
|
398
|
+
* Validates that a given key does not conflict with internal database keys.
|
|
399
|
+
*
|
|
400
|
+
* This method is used to prevent accidental overwriting of reserved `LSDB::` keys
|
|
401
|
+
* in `localStorage`, which are used internally by TinyLocalStorage for versioning
|
|
402
|
+
* and data management.
|
|
403
|
+
*
|
|
404
|
+
* @param {string} name - The key to validate before writing to localStorage.
|
|
405
|
+
* @throws {Error} If the key starts with `LSDB::`.
|
|
406
|
+
*/
|
|
407
|
+
#isProtectedDbKey(name) {
|
|
408
|
+
if (typeof name === 'string' && name.startsWith('LSDB::'))
|
|
409
|
+
throw new Error(`TinyLocalStorage: Key "${name}" may conflict with reserved dbKeys.`);
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* Updates the version of the storage and triggers migration if needed.
|
|
413
|
+
*
|
|
414
|
+
* @param {number} version - Desired version of the database.
|
|
415
|
+
* @param {(oldVersion: number, newVersion: number) => void} onUpgrade - Callback to perform migration logic.
|
|
416
|
+
* @throws {Error} If the database key has not been initialized.
|
|
417
|
+
* @throws {TypeError} If `version` is not a valid positive number.
|
|
418
|
+
* @throws {TypeError} If `onUpgrade` is not a function.
|
|
419
|
+
*/
|
|
420
|
+
updateStorageVersion(version, onUpgrade) {
|
|
421
|
+
if (typeof this.#dbKey !== 'string')
|
|
422
|
+
throw new Error('TinyLocalStorage: Database key is not initialized. Set a valid dbName in the constructor.');
|
|
423
|
+
if (typeof version !== 'number' || Number.isNaN(version) || version < 1)
|
|
424
|
+
throw new TypeError('TinyLocalStorage: version must be a positive number.');
|
|
425
|
+
if (typeof onUpgrade !== 'function')
|
|
426
|
+
throw new TypeError('TinyLocalStorage: onUpgrade must be a function.');
|
|
427
|
+
// @ts-ignore
|
|
428
|
+
const savedVersion = parseInt(localStorage.getItem(this.#dbKey), 10) || 0;
|
|
429
|
+
if (typeof savedVersion !== 'number' || Number.isNaN(savedVersion) || savedVersion < 0)
|
|
430
|
+
throw new TypeError('TinyLocalStorage: saved version in localStorage is not a valid number.');
|
|
431
|
+
if (version < savedVersion)
|
|
432
|
+
throw new Error(`TinyLocalStorage: Cannot downgrade database version from ${savedVersion} to ${version}.`);
|
|
433
|
+
if (version > savedVersion) {
|
|
434
|
+
onUpgrade(savedVersion, version);
|
|
435
|
+
localStorage.setItem(this.#dbKey, String(version));
|
|
436
|
+
this.#version = version;
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
/**
|
|
440
|
+
* Gets the current database key used in localStorage.
|
|
441
|
+
*
|
|
442
|
+
* @returns {string|null} The database key, or null if not set.
|
|
443
|
+
*/
|
|
444
|
+
getDbKey() {
|
|
445
|
+
return this.#dbKey;
|
|
446
|
+
}
|
|
447
|
+
/**
|
|
448
|
+
* Gets the current version of the database.
|
|
449
|
+
*
|
|
450
|
+
* @returns {number} The current version number.
|
|
451
|
+
*/
|
|
452
|
+
getVersion() {
|
|
453
|
+
return this.#version;
|
|
454
|
+
}
|
|
388
455
|
/**
|
|
389
456
|
* Defines a custom storage interface (e.g. `sessionStorage`).
|
|
390
457
|
*
|
|
@@ -392,7 +459,7 @@ class TinyLocalStorage {
|
|
|
392
459
|
*/
|
|
393
460
|
setLocalStorage(localstorage) {
|
|
394
461
|
if (!(localstorage instanceof Storage))
|
|
395
|
-
throw new
|
|
462
|
+
throw new TypeError('Argument must be a valid instance of Storage.');
|
|
396
463
|
this.#localStorage = localstorage;
|
|
397
464
|
}
|
|
398
465
|
/**
|
|
@@ -412,7 +479,7 @@ class TinyLocalStorage {
|
|
|
412
479
|
*/
|
|
413
480
|
#setJson(name, data) {
|
|
414
481
|
if (typeof name !== 'string' || !name.length)
|
|
415
|
-
throw new
|
|
482
|
+
throw new TypeError('Key must be a non-empty string.');
|
|
416
483
|
return TinyLocalStorage.encodeSpecialJson(data);
|
|
417
484
|
}
|
|
418
485
|
/**
|
|
@@ -424,11 +491,12 @@ class TinyLocalStorage {
|
|
|
424
491
|
* @param {LocalStorageJsonValue} data - The data to be serialized and stored.
|
|
425
492
|
*/
|
|
426
493
|
setJson(name, data) {
|
|
494
|
+
this.#isProtectedDbKey(name);
|
|
427
495
|
if (!isJsonObject(data) &&
|
|
428
496
|
!Array.isArray(data) &&
|
|
429
497
|
!(data instanceof Map) &&
|
|
430
498
|
!(data instanceof Set)) {
|
|
431
|
-
throw new
|
|
499
|
+
throw new TypeError('The storage value is not a valid JSON-compatible structure.');
|
|
432
500
|
}
|
|
433
501
|
const encoded = this.#setJson(name, data);
|
|
434
502
|
this.emit('setJson', name, data);
|
|
@@ -445,7 +513,7 @@ class TinyLocalStorage {
|
|
|
445
513
|
*/
|
|
446
514
|
#getJson(name, defaultData) {
|
|
447
515
|
if (typeof name !== 'string' || !name.length)
|
|
448
|
-
throw new
|
|
516
|
+
throw new TypeError('Key must be a non-empty string.');
|
|
449
517
|
const raw = this.#localStorage.getItem(name);
|
|
450
518
|
const fallbackTypes = {
|
|
451
519
|
obj: () => ({}),
|
|
@@ -491,8 +559,9 @@ class TinyLocalStorage {
|
|
|
491
559
|
* @param {Date} data
|
|
492
560
|
*/
|
|
493
561
|
setDate(name, data) {
|
|
562
|
+
this.#isProtectedDbKey(name);
|
|
494
563
|
if (!(data instanceof Date))
|
|
495
|
-
throw new
|
|
564
|
+
throw new TypeError('Value must be a Date.');
|
|
496
565
|
const encoded = this.#setJson(name, data);
|
|
497
566
|
this.emit('setDate', name, data);
|
|
498
567
|
return this.#localStorage.setItem(name, JSON.stringify(encoded));
|
|
@@ -512,8 +581,9 @@ class TinyLocalStorage {
|
|
|
512
581
|
* @param {RegExp} data
|
|
513
582
|
*/
|
|
514
583
|
setRegExp(name, data) {
|
|
584
|
+
this.#isProtectedDbKey(name);
|
|
515
585
|
if (!(data instanceof RegExp))
|
|
516
|
-
throw new
|
|
586
|
+
throw new TypeError('Value must be a RegExp.');
|
|
517
587
|
const encoded = this.#setJson(name, data);
|
|
518
588
|
this.emit('setRegExp', name, data);
|
|
519
589
|
return this.#localStorage.setItem(name, JSON.stringify(encoded));
|
|
@@ -533,8 +603,9 @@ class TinyLocalStorage {
|
|
|
533
603
|
* @param {bigint} data
|
|
534
604
|
*/
|
|
535
605
|
setBigInt(name, data) {
|
|
606
|
+
this.#isProtectedDbKey(name);
|
|
536
607
|
if (typeof data !== 'bigint')
|
|
537
|
-
throw new
|
|
608
|
+
throw new TypeError('Value must be a BigInt.');
|
|
538
609
|
const encoded = this.#setJson(name, data);
|
|
539
610
|
this.emit('setBigInt', name, data);
|
|
540
611
|
return this.#localStorage.setItem(name, JSON.stringify(encoded));
|
|
@@ -555,8 +626,9 @@ class TinyLocalStorage {
|
|
|
555
626
|
* @param {symbol} data
|
|
556
627
|
*/
|
|
557
628
|
setSymbol(name, data) {
|
|
629
|
+
this.#isProtectedDbKey(name);
|
|
558
630
|
if (typeof data !== 'symbol')
|
|
559
|
-
throw new
|
|
631
|
+
throw new TypeError('Value must be a Symbol.');
|
|
560
632
|
const encoded = this.#setJson(name, data);
|
|
561
633
|
this.emit('setSymbol', name, data);
|
|
562
634
|
return this.#localStorage.setItem(name, JSON.stringify(encoded));
|
|
@@ -586,8 +658,9 @@ class TinyLocalStorage {
|
|
|
586
658
|
* @param {any} data - The data to store.
|
|
587
659
|
*/
|
|
588
660
|
setItem(name, data) {
|
|
661
|
+
this.#isProtectedDbKey(name);
|
|
589
662
|
if (typeof name !== 'string' || !name.length)
|
|
590
|
-
throw new
|
|
663
|
+
throw new TypeError('Key must be a non-empty string.');
|
|
591
664
|
this.emit('setItem', name, data);
|
|
592
665
|
return this.#localStorage.setItem(name, data);
|
|
593
666
|
}
|
|
@@ -599,7 +672,7 @@ class TinyLocalStorage {
|
|
|
599
672
|
*/
|
|
600
673
|
getItem(name) {
|
|
601
674
|
if (typeof name !== 'string' || !name.length)
|
|
602
|
-
throw new
|
|
675
|
+
throw new TypeError('Key must be a non-empty string.');
|
|
603
676
|
return this.#localStorage.getItem(name);
|
|
604
677
|
}
|
|
605
678
|
/**
|
|
@@ -609,10 +682,11 @@ class TinyLocalStorage {
|
|
|
609
682
|
* @param {string} data - The string to store.
|
|
610
683
|
*/
|
|
611
684
|
setString(name, data) {
|
|
685
|
+
this.#isProtectedDbKey(name);
|
|
612
686
|
if (typeof name !== 'string' || !name.length)
|
|
613
|
-
throw new
|
|
687
|
+
throw new TypeError('Key must be a non-empty string.');
|
|
614
688
|
if (typeof data !== 'string')
|
|
615
|
-
throw new
|
|
689
|
+
throw new TypeError('Value must be a string.');
|
|
616
690
|
this.emit('setString', name, data);
|
|
617
691
|
return this.#localStorage.setItem(name, JSON.stringify({
|
|
618
692
|
__string__: true,
|
|
@@ -627,7 +701,7 @@ class TinyLocalStorage {
|
|
|
627
701
|
*/
|
|
628
702
|
getString(name) {
|
|
629
703
|
if (typeof name !== 'string' || !name.length)
|
|
630
|
-
throw new
|
|
704
|
+
throw new TypeError('Key must be a non-empty string.');
|
|
631
705
|
let value = this.#localStorage.getItem(name);
|
|
632
706
|
try {
|
|
633
707
|
/** @type {{ value: string; __string__: boolean }} */
|
|
@@ -651,10 +725,11 @@ class TinyLocalStorage {
|
|
|
651
725
|
* @param {number} data - The number to store.
|
|
652
726
|
*/
|
|
653
727
|
setNumber(name, data) {
|
|
728
|
+
this.#isProtectedDbKey(name);
|
|
654
729
|
if (typeof name !== 'string' || !name.length)
|
|
655
|
-
throw new
|
|
730
|
+
throw new TypeError('Key must be a non-empty string.');
|
|
656
731
|
if (typeof data !== 'number')
|
|
657
|
-
throw new
|
|
732
|
+
throw new TypeError('Value must be a number.');
|
|
658
733
|
this.emit('setNumber', name, data);
|
|
659
734
|
return this.#localStorage.setItem(name, String(data));
|
|
660
735
|
}
|
|
@@ -666,7 +741,7 @@ class TinyLocalStorage {
|
|
|
666
741
|
*/
|
|
667
742
|
getNumber(name) {
|
|
668
743
|
if (typeof name !== 'string' || !name.length)
|
|
669
|
-
throw new
|
|
744
|
+
throw new TypeError('Key must be a non-empty string.');
|
|
670
745
|
/** @type {number|string|null} */
|
|
671
746
|
let number = this.#localStorage.getItem(name);
|
|
672
747
|
if (typeof number === 'number')
|
|
@@ -685,10 +760,11 @@ class TinyLocalStorage {
|
|
|
685
760
|
* @param {boolean} data - The boolean value to store.
|
|
686
761
|
*/
|
|
687
762
|
setBool(name, data) {
|
|
763
|
+
this.#isProtectedDbKey(name);
|
|
688
764
|
if (typeof name !== 'string' || !name.length)
|
|
689
|
-
throw new
|
|
765
|
+
throw new TypeError('Key must be a non-empty string.');
|
|
690
766
|
if (typeof data !== 'boolean')
|
|
691
|
-
throw new
|
|
767
|
+
throw new TypeError('Value must be a boolean.');
|
|
692
768
|
this.emit('setBool', name, data);
|
|
693
769
|
return this.#localStorage.setItem(name, String(data));
|
|
694
770
|
}
|
|
@@ -700,7 +776,7 @@ class TinyLocalStorage {
|
|
|
700
776
|
*/
|
|
701
777
|
getBool(name) {
|
|
702
778
|
if (typeof name !== 'string' || !name.length)
|
|
703
|
-
throw new
|
|
779
|
+
throw new TypeError('Key must be a non-empty string.');
|
|
704
780
|
const value = this.#localStorage.getItem(name);
|
|
705
781
|
if (typeof value === 'boolean')
|
|
706
782
|
return value;
|
|
@@ -719,7 +795,7 @@ class TinyLocalStorage {
|
|
|
719
795
|
*/
|
|
720
796
|
removeItem(name) {
|
|
721
797
|
if (typeof name !== 'string' || !name.length)
|
|
722
|
-
throw new
|
|
798
|
+
throw new TypeError('Key must be a non-empty string.');
|
|
723
799
|
this.emit('removeItem', name);
|
|
724
800
|
return this.#localStorage.removeItem(name);
|
|
725
801
|
}
|