tiny-essentials 1.19.1 → 1.19.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/v1/TinyEssentials.js +178 -30
- package/dist/v1/TinyEssentials.min.js +1 -1
- package/dist/v1/TinyLocalStorage.js +179 -31
- package/dist/v1/TinyLocalStorage.min.js +1 -1
- package/dist/v1/TinyUploadClicker.js +178 -30
- package/dist/v1/TinyUploadClicker.min.js +1 -1
- package/dist/v1/libs/TinyLocalStorage.cjs +178 -30
- package/dist/v1/libs/TinyLocalStorage.d.mts +49 -7
- package/dist/v1/libs/TinyLocalStorage.mjs +166 -36
- package/docs/v1/libs/TinyLocalStorage.md +76 -4
- package/package.json +1 -1
|
@@ -445,6 +445,22 @@ const customEncoders = new Map();
|
|
|
445
445
|
/** @type {Map<any, DecodeFn>} */
|
|
446
446
|
const customDecoders = new Map();
|
|
447
447
|
|
|
448
|
+
/** @type {Set<any>} */
|
|
449
|
+
const customTypesFreezed = new Set([
|
|
450
|
+
'string',
|
|
451
|
+
'boolean',
|
|
452
|
+
'number',
|
|
453
|
+
'object',
|
|
454
|
+
'array',
|
|
455
|
+
String,
|
|
456
|
+
Boolean,
|
|
457
|
+
Number,
|
|
458
|
+
Object,
|
|
459
|
+
Array,
|
|
460
|
+
BigInt,
|
|
461
|
+
Symbol,
|
|
462
|
+
]);
|
|
463
|
+
|
|
448
464
|
/**
|
|
449
465
|
* A function that encodes a value into a serializable JSON-compatible format.
|
|
450
466
|
*
|
|
@@ -717,25 +733,48 @@ class TinyLocalStorage {
|
|
|
717
733
|
///////////////////////////////////////////////////
|
|
718
734
|
|
|
719
735
|
/**
|
|
720
|
-
*
|
|
736
|
+
* Checks whether a JSON-serializable type is already registered.
|
|
721
737
|
*
|
|
722
|
-
* @param {any} type - The type
|
|
723
|
-
*
|
|
724
|
-
* @
|
|
738
|
+
* @param {any} type - The type identifier, which can be a string (e.g., `"bigint"`, `"symbol"`)
|
|
739
|
+
* or a reference to a class/constructor function.
|
|
740
|
+
* @returns {boolean} True if the type has both an encoder and decoder registered.
|
|
725
741
|
*/
|
|
726
|
-
static
|
|
742
|
+
static hasJsonType(type) {
|
|
743
|
+
return (customEncoders.has(type) && customDecoders.has(type)) || customTypesFreezed.has(type);
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
/**
|
|
747
|
+
* Registers a new JSON-serializable type with its encoder and decoder.
|
|
748
|
+
*
|
|
749
|
+
* @param {any} type - The type identifier, which can be a string (e.g., `"bigint"`, `"symbol"`)
|
|
750
|
+
* or a reference to a class/constructor function.
|
|
751
|
+
* @param {EncodeFn} encodeFn - A function that receives a value of this type and returns a JSON-safe representation.
|
|
752
|
+
* @param {DecodeFn} decodeFn - An object with `check(value)` to identify this type and `decode(value)` to restore it.
|
|
753
|
+
* @param {boolean} [freezeType=false] - If true, prevents this type from being unregistered later.
|
|
754
|
+
* @throws {Error} Throws an error if the type is frozen and cannot be registered.
|
|
755
|
+
*/
|
|
756
|
+
static registerJsonType(type, encodeFn, decodeFn, freezeType = false) {
|
|
757
|
+
if (customTypesFreezed.has(type))
|
|
758
|
+
throw new Error(`Cannot register type "${type}" because it is frozen.`);
|
|
727
759
|
customEncoders.set(type, encodeFn);
|
|
728
760
|
customDecoders.set(type, decodeFn);
|
|
761
|
+
if (freezeType) customTypesFreezed.add(type);
|
|
729
762
|
}
|
|
730
763
|
|
|
731
764
|
/**
|
|
732
|
-
*
|
|
765
|
+
* Unregisters a previously registered custom type from the encoding/decoding system.
|
|
733
766
|
*
|
|
734
|
-
* @param {
|
|
767
|
+
* @param {any} type - The primitive name or constructor reference used in the registration.
|
|
768
|
+
* @returns {boolean} Returns true if the type existed and was removed, or false if it wasn't found.
|
|
769
|
+
* @throws {Error} Throws an error if the type is frozen and cannot be unregistered.
|
|
735
770
|
*/
|
|
736
771
|
static deleteJsonType(type) {
|
|
737
|
-
|
|
738
|
-
|
|
772
|
+
if (customTypesFreezed.has(type))
|
|
773
|
+
throw new Error(`Cannot remove type "${type}" because it is frozen.`);
|
|
774
|
+
let isDeleted = false;
|
|
775
|
+
if (customEncoders.delete(type)) isDeleted = true;
|
|
776
|
+
if (customDecoders.delete(type)) isDeleted = true;
|
|
777
|
+
return isDeleted;
|
|
739
778
|
}
|
|
740
779
|
|
|
741
780
|
//////////////////////////////////////////////////////
|
|
@@ -818,6 +857,12 @@ class TinyLocalStorage {
|
|
|
818
857
|
/** @type {Storage} */
|
|
819
858
|
#localStorage = window.localStorage;
|
|
820
859
|
|
|
860
|
+
/** @type {string|null} */
|
|
861
|
+
#dbKey = null;
|
|
862
|
+
|
|
863
|
+
/** @type {number} */
|
|
864
|
+
#version = 0;
|
|
865
|
+
|
|
821
866
|
/** @type {(ev: StorageEvent) => any} */
|
|
822
867
|
#storageEvent = (ev) => this.emit('storage', ev);
|
|
823
868
|
|
|
@@ -825,11 +870,84 @@ class TinyLocalStorage {
|
|
|
825
870
|
* Initializes the TinyLocalStorage instance and sets up cross-tab sync.
|
|
826
871
|
*
|
|
827
872
|
* Adds listener for the native `storage` event to support tab synchronization.
|
|
873
|
+
* @param {string} [dbName] - Unique database name.
|
|
828
874
|
*/
|
|
829
|
-
constructor() {
|
|
875
|
+
constructor(dbName) {
|
|
876
|
+
if (typeof dbName !== 'undefined' && typeof dbName !== 'string')
|
|
877
|
+
throw new TypeError('TinyLocalStorage: dbName must be a string if provided.');
|
|
878
|
+
if (typeof dbName === 'string') this.#dbKey = `LSDB::${dbName}`;
|
|
830
879
|
window.addEventListener('storage', this.#storageEvent);
|
|
831
880
|
}
|
|
832
881
|
|
|
882
|
+
/**
|
|
883
|
+
* Validates that a given key does not conflict with internal database keys.
|
|
884
|
+
*
|
|
885
|
+
* This method is used to prevent accidental overwriting of reserved `LSDB::` keys
|
|
886
|
+
* in `localStorage`, which are used internally by TinyLocalStorage for versioning
|
|
887
|
+
* and data management.
|
|
888
|
+
*
|
|
889
|
+
* @param {string} name - The key to validate before writing to localStorage.
|
|
890
|
+
* @throws {Error} If the key starts with `LSDB::`.
|
|
891
|
+
*/
|
|
892
|
+
#isProtectedDbKey(name) {
|
|
893
|
+
if (typeof name === 'string' && name.startsWith('LSDB::'))
|
|
894
|
+
throw new Error(`TinyLocalStorage: Key "${name}" may conflict with reserved dbKeys.`);
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
/**
|
|
898
|
+
* Updates the version of the storage and triggers migration if needed.
|
|
899
|
+
*
|
|
900
|
+
* @param {number} version - Desired version of the database.
|
|
901
|
+
* @param {(oldVersion: number, newVersion: number) => void} onUpgrade - Callback to perform migration logic.
|
|
902
|
+
* @throws {Error} If the database key has not been initialized.
|
|
903
|
+
* @throws {TypeError} If `version` is not a valid positive number.
|
|
904
|
+
* @throws {TypeError} If `onUpgrade` is not a function.
|
|
905
|
+
*/
|
|
906
|
+
updateStorageVersion(version, onUpgrade) {
|
|
907
|
+
if (typeof this.#dbKey !== 'string')
|
|
908
|
+
throw new Error(
|
|
909
|
+
'TinyLocalStorage: Database key is not initialized. Set a valid dbName in the constructor.',
|
|
910
|
+
);
|
|
911
|
+
if (typeof version !== 'number' || Number.isNaN(version) || version < 1)
|
|
912
|
+
throw new TypeError('TinyLocalStorage: version must be a positive number.');
|
|
913
|
+
if (typeof onUpgrade !== 'function')
|
|
914
|
+
throw new TypeError('TinyLocalStorage: onUpgrade must be a function.');
|
|
915
|
+
|
|
916
|
+
// @ts-ignore
|
|
917
|
+
const savedVersion = parseInt(localStorage.getItem(this.#dbKey), 10) || 0;
|
|
918
|
+
if (typeof savedVersion !== 'number' || Number.isNaN(savedVersion) || savedVersion < 0)
|
|
919
|
+
throw new TypeError('TinyLocalStorage: saved version in localStorage is not a valid number.');
|
|
920
|
+
|
|
921
|
+
if (version < savedVersion)
|
|
922
|
+
throw new Error(
|
|
923
|
+
`TinyLocalStorage: Cannot downgrade database version from ${savedVersion} to ${version}.`,
|
|
924
|
+
);
|
|
925
|
+
|
|
926
|
+
if (version > savedVersion) {
|
|
927
|
+
onUpgrade(savedVersion, version);
|
|
928
|
+
localStorage.setItem(this.#dbKey, String(version));
|
|
929
|
+
this.#version = version;
|
|
930
|
+
}
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
/**
|
|
934
|
+
* Gets the current database key used in localStorage.
|
|
935
|
+
*
|
|
936
|
+
* @returns {string|null} The database key, or null if not set.
|
|
937
|
+
*/
|
|
938
|
+
getDbKey() {
|
|
939
|
+
return this.#dbKey;
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
/**
|
|
943
|
+
* Gets the current version of the database.
|
|
944
|
+
*
|
|
945
|
+
* @returns {number} The current version number.
|
|
946
|
+
*/
|
|
947
|
+
getVersion() {
|
|
948
|
+
return this.#version;
|
|
949
|
+
}
|
|
950
|
+
|
|
833
951
|
/**
|
|
834
952
|
* Defines a custom storage interface (e.g. `sessionStorage`).
|
|
835
953
|
*
|
|
@@ -837,7 +955,7 @@ class TinyLocalStorage {
|
|
|
837
955
|
*/
|
|
838
956
|
setLocalStorage(localstorage) {
|
|
839
957
|
if (!(localstorage instanceof Storage))
|
|
840
|
-
throw new
|
|
958
|
+
throw new TypeError('Argument must be a valid instance of Storage.');
|
|
841
959
|
this.#localStorage = localstorage;
|
|
842
960
|
}
|
|
843
961
|
|
|
@@ -859,7 +977,7 @@ class TinyLocalStorage {
|
|
|
859
977
|
*/
|
|
860
978
|
#setJson(name, data) {
|
|
861
979
|
if (typeof name !== 'string' || !name.length)
|
|
862
|
-
throw new
|
|
980
|
+
throw new TypeError('Key must be a non-empty string.');
|
|
863
981
|
return TinyLocalStorage.encodeSpecialJson(data);
|
|
864
982
|
}
|
|
865
983
|
|
|
@@ -872,13 +990,14 @@ class TinyLocalStorage {
|
|
|
872
990
|
* @param {LocalStorageJsonValue} data - The data to be serialized and stored.
|
|
873
991
|
*/
|
|
874
992
|
setJson(name, data) {
|
|
993
|
+
this.#isProtectedDbKey(name);
|
|
875
994
|
if (
|
|
876
995
|
!isJsonObject(data) &&
|
|
877
996
|
!Array.isArray(data) &&
|
|
878
997
|
!(data instanceof Map) &&
|
|
879
998
|
!(data instanceof Set)
|
|
880
999
|
) {
|
|
881
|
-
throw new
|
|
1000
|
+
throw new TypeError('The storage value is not a valid JSON-compatible structure.');
|
|
882
1001
|
}
|
|
883
1002
|
const encoded = this.#setJson(name, data);
|
|
884
1003
|
this.emit('setJson', name, data);
|
|
@@ -896,7 +1015,7 @@ class TinyLocalStorage {
|
|
|
896
1015
|
*/
|
|
897
1016
|
#getJson(name, defaultData) {
|
|
898
1017
|
if (typeof name !== 'string' || !name.length)
|
|
899
|
-
throw new
|
|
1018
|
+
throw new TypeError('Key must be a non-empty string.');
|
|
900
1019
|
|
|
901
1020
|
const raw = this.#localStorage.getItem(name);
|
|
902
1021
|
const fallbackTypes = {
|
|
@@ -950,7 +1069,8 @@ class TinyLocalStorage {
|
|
|
950
1069
|
* @param {Date} data
|
|
951
1070
|
*/
|
|
952
1071
|
setDate(name, data) {
|
|
953
|
-
|
|
1072
|
+
this.#isProtectedDbKey(name);
|
|
1073
|
+
if (!(data instanceof Date)) throw new TypeError('Value must be a Date.');
|
|
954
1074
|
const encoded = this.#setJson(name, data);
|
|
955
1075
|
this.emit('setDate', name, data);
|
|
956
1076
|
return this.#localStorage.setItem(name, JSON.stringify(encoded));
|
|
@@ -972,7 +1092,8 @@ class TinyLocalStorage {
|
|
|
972
1092
|
* @param {RegExp} data
|
|
973
1093
|
*/
|
|
974
1094
|
setRegExp(name, data) {
|
|
975
|
-
|
|
1095
|
+
this.#isProtectedDbKey(name);
|
|
1096
|
+
if (!(data instanceof RegExp)) throw new TypeError('Value must be a RegExp.');
|
|
976
1097
|
const encoded = this.#setJson(name, data);
|
|
977
1098
|
this.emit('setRegExp', name, data);
|
|
978
1099
|
return this.#localStorage.setItem(name, JSON.stringify(encoded));
|
|
@@ -994,7 +1115,8 @@ class TinyLocalStorage {
|
|
|
994
1115
|
* @param {bigint} data
|
|
995
1116
|
*/
|
|
996
1117
|
setBigInt(name, data) {
|
|
997
|
-
|
|
1118
|
+
this.#isProtectedDbKey(name);
|
|
1119
|
+
if (typeof data !== 'bigint') throw new TypeError('Value must be a BigInt.');
|
|
998
1120
|
const encoded = this.#setJson(name, data);
|
|
999
1121
|
this.emit('setBigInt', name, data);
|
|
1000
1122
|
return this.#localStorage.setItem(name, JSON.stringify(encoded));
|
|
@@ -1017,7 +1139,8 @@ class TinyLocalStorage {
|
|
|
1017
1139
|
* @param {symbol} data
|
|
1018
1140
|
*/
|
|
1019
1141
|
setSymbol(name, data) {
|
|
1020
|
-
|
|
1142
|
+
this.#isProtectedDbKey(name);
|
|
1143
|
+
if (typeof data !== 'symbol') throw new TypeError('Value must be a Symbol.');
|
|
1021
1144
|
const encoded = this.#setJson(name, data);
|
|
1022
1145
|
this.emit('setSymbol', name, data);
|
|
1023
1146
|
return this.#localStorage.setItem(name, JSON.stringify(encoded));
|
|
@@ -1050,8 +1173,9 @@ class TinyLocalStorage {
|
|
|
1050
1173
|
* @param {any} data - The data to store.
|
|
1051
1174
|
*/
|
|
1052
1175
|
setItem(name, data) {
|
|
1176
|
+
this.#isProtectedDbKey(name);
|
|
1053
1177
|
if (typeof name !== 'string' || !name.length)
|
|
1054
|
-
throw new
|
|
1178
|
+
throw new TypeError('Key must be a non-empty string.');
|
|
1055
1179
|
this.emit('setItem', name, data);
|
|
1056
1180
|
return this.#localStorage.setItem(name, data);
|
|
1057
1181
|
}
|
|
@@ -1064,7 +1188,7 @@ class TinyLocalStorage {
|
|
|
1064
1188
|
*/
|
|
1065
1189
|
getItem(name) {
|
|
1066
1190
|
if (typeof name !== 'string' || !name.length)
|
|
1067
|
-
throw new
|
|
1191
|
+
throw new TypeError('Key must be a non-empty string.');
|
|
1068
1192
|
return this.#localStorage.getItem(name);
|
|
1069
1193
|
}
|
|
1070
1194
|
|
|
@@ -1075,12 +1199,19 @@ class TinyLocalStorage {
|
|
|
1075
1199
|
* @param {string} data - The string to store.
|
|
1076
1200
|
*/
|
|
1077
1201
|
setString(name, data) {
|
|
1202
|
+
this.#isProtectedDbKey(name);
|
|
1078
1203
|
if (typeof name !== 'string' || !name.length)
|
|
1079
|
-
throw new
|
|
1080
|
-
if (typeof data !== 'string') throw new
|
|
1204
|
+
throw new TypeError('Key must be a non-empty string.');
|
|
1205
|
+
if (typeof data !== 'string') throw new TypeError('Value must be a string.');
|
|
1081
1206
|
|
|
1082
1207
|
this.emit('setString', name, data);
|
|
1083
|
-
return this.#localStorage.setItem(
|
|
1208
|
+
return this.#localStorage.setItem(
|
|
1209
|
+
name,
|
|
1210
|
+
JSON.stringify({
|
|
1211
|
+
__string__: true,
|
|
1212
|
+
value: data,
|
|
1213
|
+
}),
|
|
1214
|
+
);
|
|
1084
1215
|
}
|
|
1085
1216
|
|
|
1086
1217
|
/**
|
|
@@ -1091,8 +1222,17 @@ class TinyLocalStorage {
|
|
|
1091
1222
|
*/
|
|
1092
1223
|
getString(name) {
|
|
1093
1224
|
if (typeof name !== 'string' || !name.length)
|
|
1094
|
-
throw new
|
|
1225
|
+
throw new TypeError('Key must be a non-empty string.');
|
|
1095
1226
|
let value = this.#localStorage.getItem(name);
|
|
1227
|
+
try {
|
|
1228
|
+
/** @type {{ value: string; __string__: boolean }} */
|
|
1229
|
+
// @ts-ignore
|
|
1230
|
+
value = JSON.parse(value);
|
|
1231
|
+
if (!isJsonObject(value) || !value.__string__ || typeof value.value !== 'string') return null;
|
|
1232
|
+
value = value.value;
|
|
1233
|
+
} catch {
|
|
1234
|
+
value = null;
|
|
1235
|
+
}
|
|
1096
1236
|
if (typeof value === 'string') return value;
|
|
1097
1237
|
return null;
|
|
1098
1238
|
}
|
|
@@ -1104,9 +1244,10 @@ class TinyLocalStorage {
|
|
|
1104
1244
|
* @param {number} data - The number to store.
|
|
1105
1245
|
*/
|
|
1106
1246
|
setNumber(name, data) {
|
|
1247
|
+
this.#isProtectedDbKey(name);
|
|
1107
1248
|
if (typeof name !== 'string' || !name.length)
|
|
1108
|
-
throw new
|
|
1109
|
-
if (typeof data !== 'number') throw new
|
|
1249
|
+
throw new TypeError('Key must be a non-empty string.');
|
|
1250
|
+
if (typeof data !== 'number') throw new TypeError('Value must be a number.');
|
|
1110
1251
|
this.emit('setNumber', name, data);
|
|
1111
1252
|
return this.#localStorage.setItem(name, String(data));
|
|
1112
1253
|
}
|
|
@@ -1119,7 +1260,7 @@ class TinyLocalStorage {
|
|
|
1119
1260
|
*/
|
|
1120
1261
|
getNumber(name) {
|
|
1121
1262
|
if (typeof name !== 'string' || !name.length)
|
|
1122
|
-
throw new
|
|
1263
|
+
throw new TypeError('Key must be a non-empty string.');
|
|
1123
1264
|
|
|
1124
1265
|
/** @type {number|string|null} */
|
|
1125
1266
|
let number = this.#localStorage.getItem(name);
|
|
@@ -1138,9 +1279,10 @@ class TinyLocalStorage {
|
|
|
1138
1279
|
* @param {boolean} data - The boolean value to store.
|
|
1139
1280
|
*/
|
|
1140
1281
|
setBool(name, data) {
|
|
1282
|
+
this.#isProtectedDbKey(name);
|
|
1141
1283
|
if (typeof name !== 'string' || !name.length)
|
|
1142
|
-
throw new
|
|
1143
|
-
if (typeof data !== 'boolean') throw new
|
|
1284
|
+
throw new TypeError('Key must be a non-empty string.');
|
|
1285
|
+
if (typeof data !== 'boolean') throw new TypeError('Value must be a boolean.');
|
|
1144
1286
|
this.emit('setBool', name, data);
|
|
1145
1287
|
return this.#localStorage.setItem(name, String(data));
|
|
1146
1288
|
}
|
|
@@ -1153,7 +1295,7 @@ class TinyLocalStorage {
|
|
|
1153
1295
|
*/
|
|
1154
1296
|
getBool(name) {
|
|
1155
1297
|
if (typeof name !== 'string' || !name.length)
|
|
1156
|
-
throw new
|
|
1298
|
+
throw new TypeError('Key must be a non-empty string.');
|
|
1157
1299
|
|
|
1158
1300
|
const value = this.#localStorage.getItem(name);
|
|
1159
1301
|
if (typeof value === 'boolean') return value;
|
|
@@ -1172,7 +1314,7 @@ class TinyLocalStorage {
|
|
|
1172
1314
|
*/
|
|
1173
1315
|
removeItem(name) {
|
|
1174
1316
|
if (typeof name !== 'string' || !name.length)
|
|
1175
|
-
throw new
|
|
1317
|
+
throw new TypeError('Key must be a non-empty string.');
|
|
1176
1318
|
|
|
1177
1319
|
this.emit('removeItem', name);
|
|
1178
1320
|
return this.#localStorage.removeItem(name);
|
|
@@ -1209,6 +1351,7 @@ TinyLocalStorage.registerJsonType(
|
|
|
1209
1351
|
decode: (value, decodeSpecialJson) =>
|
|
1210
1352
|
new Map(value.data.map(([k, v]) => [k, decodeSpecialJson(v)])),
|
|
1211
1353
|
},
|
|
1354
|
+
true,
|
|
1212
1355
|
);
|
|
1213
1356
|
|
|
1214
1357
|
// Set
|
|
@@ -1222,6 +1365,7 @@ TinyLocalStorage.registerJsonType(
|
|
|
1222
1365
|
check: (value) => value.__set__,
|
|
1223
1366
|
decode: (value, decodeSpecialJson) => new Set(value.data.map(decodeSpecialJson)),
|
|
1224
1367
|
},
|
|
1368
|
+
true,
|
|
1225
1369
|
);
|
|
1226
1370
|
|
|
1227
1371
|
// Date
|
|
@@ -1235,6 +1379,7 @@ TinyLocalStorage.registerJsonType(
|
|
|
1235
1379
|
check: (value) => value.__date__,
|
|
1236
1380
|
decode: (value) => new Date(value.value),
|
|
1237
1381
|
},
|
|
1382
|
+
true,
|
|
1238
1383
|
);
|
|
1239
1384
|
|
|
1240
1385
|
// Regex
|
|
@@ -1249,6 +1394,7 @@ TinyLocalStorage.registerJsonType(
|
|
|
1249
1394
|
check: (value) => value.__regexp__,
|
|
1250
1395
|
decode: (value) => new RegExp(value.source, value.flags),
|
|
1251
1396
|
},
|
|
1397
|
+
true,
|
|
1252
1398
|
);
|
|
1253
1399
|
|
|
1254
1400
|
// Big Int
|
|
@@ -1262,6 +1408,7 @@ TinyLocalStorage.registerJsonType(
|
|
|
1262
1408
|
check: (value) => value.__bigint__,
|
|
1263
1409
|
decode: (value) => BigInt(value.value),
|
|
1264
1410
|
},
|
|
1411
|
+
true,
|
|
1265
1412
|
);
|
|
1266
1413
|
|
|
1267
1414
|
// Symbol
|
|
@@ -1278,6 +1425,7 @@ TinyLocalStorage.registerJsonType(
|
|
|
1278
1425
|
return key != null ? Symbol.for(key) : Symbol();
|
|
1279
1426
|
},
|
|
1280
1427
|
},
|
|
1428
|
+
true,
|
|
1281
1429
|
);
|
|
1282
1430
|
|
|
1283
1431
|
/* harmony default export */ const libs_TinyLocalStorage = (TinyLocalStorage);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
(()=>{"use strict";var e={d:(t,r)=>{for(var n in r)e.o(r,n)&&!e.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:r[n]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)},t={};function r(e){return null!==e&&"object"==typeof e&&!Array.isArray(e)&&"[object Object]"===Object.prototype.toString.call(e)}e.d(t,{TinyLocalStorage:()=>a});const n=class{#e=new Map;#t=10;#r=!1;setThrowOnMaxListeners(e){if("boolean"!=typeof e)throw new TypeError("setThrowOnMaxListeners(value): value must be a boolean");this.#r=e}getThrowOnMaxListeners(){return this.#r}#n(e,t,{once:r=!1}={}){let n=this.#e.get(e);Array.isArray(n)||(n=[],this.#e.set(e,n)),n.unshift({handler:t,config:{once:r}});const s=this.#t;if(s>0&&n.length>s){const t=`Possible memory leak detected. ${n.length} "${e}" listeners added. Use setMaxListeners() to increase limit.`;if(this.#r)throw new Error(t);console.warn(t)}}prependListener(e,t){if("string"!=typeof e)throw new TypeError("prepend(event, handler): event name must be a string");if("function"!=typeof t)throw new TypeError("prepend(event, handler): handler must be a function");this.#n(e,t)}prependListenerOnce(e,t){if("string"!=typeof e)throw new TypeError("prependOnceListener(event, handler): event name must be a string");if("function"!=typeof t)throw new TypeError("prependOnceListener(event, handler): handler must be a function");const r=(...n)=>{this.off(e,r),t(...n)};return this.#n(e,r,{once:!0}),r}#s(e,t,{once:r=!1}={}){let n=this.#e.get(e);Array.isArray(n)||(n=[],this.#e.set(e,n)),n.push({handler:t,config:{once:r}});const s=this.#t;if(s>0&&n.length>s){const t=`Possible memory leak detected. ${n.length} "${e}" listeners added. Use setMaxListeners() to increase limit.`;if(this.#r)throw new Error(t);console.warn(t)}}on(e,t){if("string"!=typeof e)throw new TypeError("on(event, handler): event name must be a string");if("function"!=typeof t)throw new TypeError("on(event, handler): handler must be a function");return this.#s(e,t)}once(e,t){if("string"!=typeof e)throw new TypeError("The event name must be a string.");if("function"!=typeof t)throw new TypeError("once(event, handler): handler must be a function");const r=n=>{this.off(e,r),"function"==typeof t&&t(n)};return this.#s(e,r,{once:!0}),r}appendListener(e,t){return this.on(e,t)}appendListenerOnce(e,t){return this.once(e,t)}off(e,t){if("string"!=typeof e)throw new TypeError("off(event, handler): event name must be a string");if("function"!=typeof t)throw new TypeError("off(event, handler): handler must be a function");const r=this.#e.get(e);if(!Array.isArray(r))return;const n=r.findIndex(e=>e.handler===t);-1!==n&&r.splice(n,1),0===r.length&&this.#e.delete(e)}offAll(e){if("string"!=typeof e)throw new TypeError("The event name must be a string.");this.#e.delete(e)}offAllTypes(){this.#e.clear()}listenerCount(e){if("string"!=typeof e)throw new TypeError("listenerCount(event): event name must be a string");const t=this.#e.get(e);return Array.isArray(t)?t.length:0}listeners(e){if("string"!=typeof e)throw new TypeError("listeners(event): event name must be a string");const t=this.#e.get(e);return Array.isArray(t)?[...t].filter(e=>!e.config.once).map(e=>e.handler):[]}onceListeners(e){if("string"!=typeof e)throw new TypeError("onceListeners(event): event name must be a string");const t=this.#e.get(e);return Array.isArray(t)?[...t].filter(e=>e.config.once).map(e=>e.handler):[]}allListeners(e){if("string"!=typeof e)throw new TypeError("allListeners(event): event name must be a string");const t=this.#e.get(e);return Array.isArray(t)?[...t].map(e=>e.handler):[]}eventNames(){return[...this.#e.keys()]}emit(e,...t){if("string"!=typeof e)throw new TypeError("emit(event, data): event name must be a string");const r=this.#e.get(e);return!(!Array.isArray(r)||0===r.length||(r.forEach(e=>e.handler(...t)),0))}setMaxListeners(e){if(!Number.isInteger(e)||e<0)throw new TypeError("setMaxListeners(n): n must be a non-negative integer");this.#t=e}getMaxListeners(){return this.#t}},s=new Map,o=new Map;class i{#o=new n;setThrowOnMaxListeners(e){return this.#o.setThrowOnMaxListeners(e)}getThrowOnMaxListeners(){return this.#o.getThrowOnMaxListeners()}prependListener(e,t){return this.#o.prependListener(e,t)}prependListenerOnce(e,t){return this.#o.prependListenerOnce(e,t)}appendListener(e,t){return this.#o.appendListener(e,t)}appendListenerOnce(e,t){return this.#o.appendListenerOnce(e,t)}on(e,t){return this.#o.on(e,t)}once(e,t){return this.#o.once(e,t)}off(e,t){return this.#o.off(e,t)}offAll(e){return this.#o.offAll(e)}offAllTypes(){return this.#o.offAllTypes()}listenerCount(e){return this.#o.listenerCount(e)}listeners(e){return this.#o.listeners(e)}onceListeners(e){return this.#o.onceListeners(e)}allListeners(e){return this.#o.allListeners(e)}eventNames(){return this.#o.eventNames()}emit(e,...t){return this.#o.emit(e,...t)}setMaxListeners(e){return this.#o.setMaxListeners(e)}getMaxListeners(){return this.#o.getMaxListeners()}static registerJsonType(e,t,r){s.set(e,t),o.set(e,r)}static deleteJsonType(e){s.delete(e),o.delete(e)}static encodeSpecialJson(e){if(void 0===e)return{__undefined__:!0};if(null===e)return{__null__:!0};for(const[t,r]of s.entries())if("string"!=typeof t&&e instanceof t||typeof e===t)return r(e,i.encodeSpecialJson);if(Array.isArray(e))return e.map(i.encodeSpecialJson);if(r(e)){const t={};for(const r in e)t[r]=i.encodeSpecialJson(e[r]);return t}return e}static decodeSpecialJson(e){const t=r(e);if(t){if(e.__undefined__)return;if(e.__null__)return null}if(Array.isArray(e))return e.map(i.decodeSpecialJson);if(t){for(const[t,r]of o.entries())if(r.check&&r.check(e))return r.decode(e,i.decodeSpecialJson);const t={};for(const r in e)t[r]=i.decodeSpecialJson(e[r]);return t}return e}#i=window.localStorage;#a=e=>this.emit("storage",e);constructor(){window.addEventListener("storage",this.#a)}setLocalStorage(e){if(!(e instanceof Storage))throw new Error("Argument must be a valid instance of Storage.");this.#i=e}localStorageExists(){return this.#i instanceof Storage}#l(e,t){if("string"!=typeof e||!e.length)throw new Error("Key must be a non-empty string.");return i.encodeSpecialJson(t)}setJson(e,t){if(!(r(t)||Array.isArray(t)||t instanceof Map||t instanceof Set))throw new Error("The storage value is not a valid JSON-compatible structure.");const n=this.#l(e,t);return this.emit("setJson",e,t),this.#i.setItem(e,JSON.stringify(n))}#c(e,t){if("string"!=typeof e||!e.length)throw new Error("Key must be a non-empty string.");const r=this.#i.getItem(e),n={obj:()=>({}),array:()=>[],map:()=>new Map,set:()=>new Set},s="function"==typeof n[t]?n[t]():null;let o;try{o=JSON.parse(r)}catch{return s}return{decoded:i.decodeSpecialJson(o),fallback:s}}getJson(e,t){const{decoded:n,fallback:s}=this.#c(e,t);return n instanceof Map||n instanceof Set||Array.isArray(n)||r(n)?n:s}setDate(e,t){if(!(t instanceof Date))throw new Error("Value must be a Date.");const r=this.#l(e,t);return this.emit("setDate",e,t),this.#i.setItem(e,JSON.stringify(r))}getDate(e){const t=this.#c(e).decoded;return t instanceof Date?t:null}setRegExp(e,t){if(!(t instanceof RegExp))throw new Error("Value must be a RegExp.");const r=this.#l(e,t);return this.emit("setRegExp",e,t),this.#i.setItem(e,JSON.stringify(r))}getRegExp(e){const t=this.#c(e).decoded;return t instanceof RegExp?t:null}setBigInt(e,t){if("bigint"!=typeof t)throw new Error("Value must be a BigInt.");const r=this.#l(e,t);return this.emit("setBigInt",e,t),this.#i.setItem(e,JSON.stringify(r))}getBigInt(e){const t=this.#c(e).decoded;return"bigint"==typeof t?t:null}setSymbol(e,t){if("symbol"!=typeof t)throw new Error("Value must be a Symbol.");const r=this.#l(e,t);return this.emit("setSymbol",e,t),this.#i.setItem(e,JSON.stringify(r))}getSymbol(e){const t=this.#c(e).decoded;return"symbol"==typeof t?t:null}getValue(e){return this.#c(e).decoded??null}setItem(e,t){if("string"!=typeof e||!e.length)throw new Error("Key must be a non-empty string.");return this.emit("setItem",e,t),this.#i.setItem(e,t)}getItem(e){if("string"!=typeof e||!e.length)throw new Error("Key must be a non-empty string.");return this.#i.getItem(e)}setString(e,t){if("string"!=typeof e||!e.length)throw new Error("Key must be a non-empty string.");if("string"!=typeof t)throw new Error("Value must be a string.");return this.emit("setString",e,t),this.#i.setItem(e,t)}getString(e){if("string"!=typeof e||!e.length)throw new Error("Key must be a non-empty string.");let t=this.#i.getItem(e);return"string"==typeof t?t:null}setNumber(e,t){if("string"!=typeof e||!e.length)throw new Error("Key must be a non-empty string.");if("number"!=typeof t)throw new Error("Value must be a number.");return this.emit("setNumber",e,t),this.#i.setItem(e,String(t))}getNumber(e){if("string"!=typeof e||!e.length)throw new Error("Key must be a non-empty string.");let t=this.#i.getItem(e);return"number"==typeof t||"string"==typeof t&&t.length>0&&(t=parseFloat(t),!Number.isNaN(t))?t:null}setBool(e,t){if("string"!=typeof e||!e.length)throw new Error("Key must be a non-empty string.");if("boolean"!=typeof t)throw new Error("Value must be a boolean.");return this.emit("setBool",e,t),this.#i.setItem(e,String(t))}getBool(e){if("string"!=typeof e||!e.length)throw new Error("Key must be a non-empty string.");const t=this.#i.getItem(e);if("boolean"==typeof t)return t;if("string"==typeof t){if("true"===t)return!0;if("false"===t)return!1}return null}removeItem(e){if("string"!=typeof e||!e.length)throw new Error("Key must be a non-empty string.");return this.emit("removeItem",e),this.#i.removeItem(e)}clearLocalStorage(){return this.#i.clear()}destroy(){window.removeEventListener("storage",this.#a),this.#o.offAllTypes()}}i.registerJsonType(Map,(e,t)=>({__map__:!0,data:Array.from(e.entries()).map(([e,r])=>[e,t(r)])}),{check:e=>e.__map__,decode:(e,t)=>new Map(e.data.map(([e,r])=>[e,t(r)]))}),i.registerJsonType(Set,(e,t)=>({__set__:!0,data:Array.from(e).map(t)}),{check:e=>e.__set__,decode:(e,t)=>new Set(e.data.map(t))}),i.registerJsonType(Date,e=>({__date__:!0,value:e.toISOString()}),{check:e=>e.__date__,decode:e=>new Date(e.value)}),i.registerJsonType(RegExp,e=>({__regexp__:!0,source:e.source,flags:e.flags}),{check:e=>e.__regexp__,decode:e=>new RegExp(e.source,e.flags)}),i.registerJsonType("bigint",e=>({__bigint__:!0,value:e.toString()}),{check:e=>e.__bigint__,decode:e=>BigInt(e.value)}),i.registerJsonType("symbol",e=>({__symbol__:!0,key:Symbol.keyFor(e)??e.description??null}),{check:e=>e.__symbol__,decode:e=>{const t=e.key;return null!=t?Symbol.for(t):Symbol()}});const a=i;window.TinyLocalStorage=t.TinyLocalStorage})();
|
|
1
|
+
(()=>{"use strict";var e={d:(t,r)=>{for(var n in r)e.o(r,n)&&!e.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:r[n]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)},t={};function r(e){return null!==e&&"object"==typeof e&&!Array.isArray(e)&&"[object Object]"===Object.prototype.toString.call(e)}e.d(t,{TinyLocalStorage:()=>l});const n=class{#e=new Map;#t=10;#r=!1;setThrowOnMaxListeners(e){if("boolean"!=typeof e)throw new TypeError("setThrowOnMaxListeners(value): value must be a boolean");this.#r=e}getThrowOnMaxListeners(){return this.#r}#n(e,t,{once:r=!1}={}){let n=this.#e.get(e);Array.isArray(n)||(n=[],this.#e.set(e,n)),n.unshift({handler:t,config:{once:r}});const s=this.#t;if(s>0&&n.length>s){const t=`Possible memory leak detected. ${n.length} "${e}" listeners added. Use setMaxListeners() to increase limit.`;if(this.#r)throw new Error(t);console.warn(t)}}prependListener(e,t){if("string"!=typeof e)throw new TypeError("prepend(event, handler): event name must be a string");if("function"!=typeof t)throw new TypeError("prepend(event, handler): handler must be a function");this.#n(e,t)}prependListenerOnce(e,t){if("string"!=typeof e)throw new TypeError("prependOnceListener(event, handler): event name must be a string");if("function"!=typeof t)throw new TypeError("prependOnceListener(event, handler): handler must be a function");const r=(...n)=>{this.off(e,r),t(...n)};return this.#n(e,r,{once:!0}),r}#s(e,t,{once:r=!1}={}){let n=this.#e.get(e);Array.isArray(n)||(n=[],this.#e.set(e,n)),n.push({handler:t,config:{once:r}});const s=this.#t;if(s>0&&n.length>s){const t=`Possible memory leak detected. ${n.length} "${e}" listeners added. Use setMaxListeners() to increase limit.`;if(this.#r)throw new Error(t);console.warn(t)}}on(e,t){if("string"!=typeof e)throw new TypeError("on(event, handler): event name must be a string");if("function"!=typeof t)throw new TypeError("on(event, handler): handler must be a function");return this.#s(e,t)}once(e,t){if("string"!=typeof e)throw new TypeError("The event name must be a string.");if("function"!=typeof t)throw new TypeError("once(event, handler): handler must be a function");const r=n=>{this.off(e,r),"function"==typeof t&&t(n)};return this.#s(e,r,{once:!0}),r}appendListener(e,t){return this.on(e,t)}appendListenerOnce(e,t){return this.once(e,t)}off(e,t){if("string"!=typeof e)throw new TypeError("off(event, handler): event name must be a string");if("function"!=typeof t)throw new TypeError("off(event, handler): handler must be a function");const r=this.#e.get(e);if(!Array.isArray(r))return;const n=r.findIndex(e=>e.handler===t);-1!==n&&r.splice(n,1),0===r.length&&this.#e.delete(e)}offAll(e){if("string"!=typeof e)throw new TypeError("The event name must be a string.");this.#e.delete(e)}offAllTypes(){this.#e.clear()}listenerCount(e){if("string"!=typeof e)throw new TypeError("listenerCount(event): event name must be a string");const t=this.#e.get(e);return Array.isArray(t)?t.length:0}listeners(e){if("string"!=typeof e)throw new TypeError("listeners(event): event name must be a string");const t=this.#e.get(e);return Array.isArray(t)?[...t].filter(e=>!e.config.once).map(e=>e.handler):[]}onceListeners(e){if("string"!=typeof e)throw new TypeError("onceListeners(event): event name must be a string");const t=this.#e.get(e);return Array.isArray(t)?[...t].filter(e=>e.config.once).map(e=>e.handler):[]}allListeners(e){if("string"!=typeof e)throw new TypeError("allListeners(event): event name must be a string");const t=this.#e.get(e);return Array.isArray(t)?[...t].map(e=>e.handler):[]}eventNames(){return[...this.#e.keys()]}emit(e,...t){if("string"!=typeof e)throw new TypeError("emit(event, data): event name must be a string");const r=this.#e.get(e);return!(!Array.isArray(r)||0===r.length||(r.forEach(e=>e.handler(...t)),0))}setMaxListeners(e){if(!Number.isInteger(e)||e<0)throw new TypeError("setMaxListeners(n): n must be a non-negative integer");this.#t=e}getMaxListeners(){return this.#t}},s=new Map,o=new Map,i=new Set(["string","boolean","number","object","array",String,Boolean,Number,Object,Array,BigInt,Symbol]);class a{#o=new n;setThrowOnMaxListeners(e){return this.#o.setThrowOnMaxListeners(e)}getThrowOnMaxListeners(){return this.#o.getThrowOnMaxListeners()}prependListener(e,t){return this.#o.prependListener(e,t)}prependListenerOnce(e,t){return this.#o.prependListenerOnce(e,t)}appendListener(e,t){return this.#o.appendListener(e,t)}appendListenerOnce(e,t){return this.#o.appendListenerOnce(e,t)}on(e,t){return this.#o.on(e,t)}once(e,t){return this.#o.once(e,t)}off(e,t){return this.#o.off(e,t)}offAll(e){return this.#o.offAll(e)}offAllTypes(){return this.#o.offAllTypes()}listenerCount(e){return this.#o.listenerCount(e)}listeners(e){return this.#o.listeners(e)}onceListeners(e){return this.#o.onceListeners(e)}allListeners(e){return this.#o.allListeners(e)}eventNames(){return this.#o.eventNames()}emit(e,...t){return this.#o.emit(e,...t)}setMaxListeners(e){return this.#o.setMaxListeners(e)}getMaxListeners(){return this.#o.getMaxListeners()}static hasJsonType(e){return s.has(e)&&o.has(e)||i.has(e)}static registerJsonType(e,t,r,n=!1){if(i.has(e))throw new Error(`Cannot register type "${e}" because it is frozen.`);s.set(e,t),o.set(e,r),n&&i.add(e)}static deleteJsonType(e){if(i.has(e))throw new Error(`Cannot remove type "${e}" because it is frozen.`);let t=!1;return s.delete(e)&&(t=!0),o.delete(e)&&(t=!0),t}static encodeSpecialJson(e){if(void 0===e)return{__undefined__:!0};if(null===e)return{__null__:!0};for(const[t,r]of s.entries())if("string"!=typeof t&&e instanceof t||typeof e===t)return r(e,a.encodeSpecialJson);if(Array.isArray(e))return e.map(a.encodeSpecialJson);if(r(e)){const t={};for(const r in e)t[r]=a.encodeSpecialJson(e[r]);return t}return e}static decodeSpecialJson(e){const t=r(e);if(t){if(e.__undefined__)return;if(e.__null__)return null}if(Array.isArray(e))return e.map(a.decodeSpecialJson);if(t){for(const[t,r]of o.entries())if(r.check&&r.check(e))return r.decode(e,a.decodeSpecialJson);const t={};for(const r in e)t[r]=a.decodeSpecialJson(e[r]);return t}return e}#i=window.localStorage;#a=null;#l=0;#c=e=>this.emit("storage",e);constructor(e){if(void 0!==e&&"string"!=typeof e)throw new TypeError("TinyLocalStorage: dbName must be a string if provided.");"string"==typeof e&&(this.#a=`LSDB::${e}`),window.addEventListener("storage",this.#c)}#h(e){if("string"==typeof e&&e.startsWith("LSDB::"))throw new Error(`TinyLocalStorage: Key "${e}" may conflict with reserved dbKeys.`)}updateStorageVersion(e,t){if("string"!=typeof this.#a)throw new Error("TinyLocalStorage: Database key is not initialized. Set a valid dbName in the constructor.");if("number"!=typeof e||Number.isNaN(e)||e<1)throw new TypeError("TinyLocalStorage: version must be a positive number.");if("function"!=typeof t)throw new TypeError("TinyLocalStorage: onUpgrade must be a function.");const r=parseInt(localStorage.getItem(this.#a),10)||0;if("number"!=typeof r||Number.isNaN(r)||r<0)throw new TypeError("TinyLocalStorage: saved version in localStorage is not a valid number.");if(e<r)throw new Error(`TinyLocalStorage: Cannot downgrade database version from ${r} to ${e}.`);e>r&&(t(r,e),localStorage.setItem(this.#a,String(e)),this.#l=e)}getDbKey(){return this.#a}getVersion(){return this.#l}setLocalStorage(e){if(!(e instanceof Storage))throw new TypeError("Argument must be a valid instance of Storage.");this.#i=e}localStorageExists(){return this.#i instanceof Storage}#y(e,t){if("string"!=typeof e||!e.length)throw new TypeError("Key must be a non-empty string.");return a.encodeSpecialJson(t)}setJson(e,t){if(this.#h(e),!(r(t)||Array.isArray(t)||t instanceof Map||t instanceof Set))throw new TypeError("The storage value is not a valid JSON-compatible structure.");const n=this.#y(e,t);return this.emit("setJson",e,t),this.#i.setItem(e,JSON.stringify(n))}#g(e,t){if("string"!=typeof e||!e.length)throw new TypeError("Key must be a non-empty string.");const r=this.#i.getItem(e),n={obj:()=>({}),array:()=>[],map:()=>new Map,set:()=>new Set},s="function"==typeof n[t]?n[t]():null;let o;try{o=JSON.parse(r)}catch{return s}return{decoded:a.decodeSpecialJson(o),fallback:s}}getJson(e,t){const{decoded:n,fallback:s}=this.#g(e,t);return n instanceof Map||n instanceof Set||Array.isArray(n)||r(n)?n:s}setDate(e,t){if(this.#h(e),!(t instanceof Date))throw new TypeError("Value must be a Date.");const r=this.#y(e,t);return this.emit("setDate",e,t),this.#i.setItem(e,JSON.stringify(r))}getDate(e){const t=this.#g(e).decoded;return t instanceof Date?t:null}setRegExp(e,t){if(this.#h(e),!(t instanceof RegExp))throw new TypeError("Value must be a RegExp.");const r=this.#y(e,t);return this.emit("setRegExp",e,t),this.#i.setItem(e,JSON.stringify(r))}getRegExp(e){const t=this.#g(e).decoded;return t instanceof RegExp?t:null}setBigInt(e,t){if(this.#h(e),"bigint"!=typeof t)throw new TypeError("Value must be a BigInt.");const r=this.#y(e,t);return this.emit("setBigInt",e,t),this.#i.setItem(e,JSON.stringify(r))}getBigInt(e){const t=this.#g(e).decoded;return"bigint"==typeof t?t:null}setSymbol(e,t){if(this.#h(e),"symbol"!=typeof t)throw new TypeError("Value must be a Symbol.");const r=this.#y(e,t);return this.emit("setSymbol",e,t),this.#i.setItem(e,JSON.stringify(r))}getSymbol(e){const t=this.#g(e).decoded;return"symbol"==typeof t?t:null}getValue(e){return this.#g(e).decoded??null}setItem(e,t){if(this.#h(e),"string"!=typeof e||!e.length)throw new TypeError("Key must be a non-empty string.");return this.emit("setItem",e,t),this.#i.setItem(e,t)}getItem(e){if("string"!=typeof e||!e.length)throw new TypeError("Key must be a non-empty string.");return this.#i.getItem(e)}setString(e,t){if(this.#h(e),"string"!=typeof e||!e.length)throw new TypeError("Key must be a non-empty string.");if("string"!=typeof t)throw new TypeError("Value must be a string.");return this.emit("setString",e,t),this.#i.setItem(e,JSON.stringify({__string__:!0,value:t}))}getString(e){if("string"!=typeof e||!e.length)throw new TypeError("Key must be a non-empty string.");let t=this.#i.getItem(e);try{if(t=JSON.parse(t),!r(t)||!t.__string__||"string"!=typeof t.value)return null;t=t.value}catch{t=null}return"string"==typeof t?t:null}setNumber(e,t){if(this.#h(e),"string"!=typeof e||!e.length)throw new TypeError("Key must be a non-empty string.");if("number"!=typeof t)throw new TypeError("Value must be a number.");return this.emit("setNumber",e,t),this.#i.setItem(e,String(t))}getNumber(e){if("string"!=typeof e||!e.length)throw new TypeError("Key must be a non-empty string.");let t=this.#i.getItem(e);return"number"==typeof t||"string"==typeof t&&t.length>0&&(t=parseFloat(t),!Number.isNaN(t))?t:null}setBool(e,t){if(this.#h(e),"string"!=typeof e||!e.length)throw new TypeError("Key must be a non-empty string.");if("boolean"!=typeof t)throw new TypeError("Value must be a boolean.");return this.emit("setBool",e,t),this.#i.setItem(e,String(t))}getBool(e){if("string"!=typeof e||!e.length)throw new TypeError("Key must be a non-empty string.");const t=this.#i.getItem(e);if("boolean"==typeof t)return t;if("string"==typeof t){if("true"===t)return!0;if("false"===t)return!1}return null}removeItem(e){if("string"!=typeof e||!e.length)throw new TypeError("Key must be a non-empty string.");return this.emit("removeItem",e),this.#i.removeItem(e)}clearLocalStorage(){return this.#i.clear()}destroy(){window.removeEventListener("storage",this.#c),this.#o.offAllTypes()}}a.registerJsonType(Map,(e,t)=>({__map__:!0,data:Array.from(e.entries()).map(([e,r])=>[e,t(r)])}),{check:e=>e.__map__,decode:(e,t)=>new Map(e.data.map(([e,r])=>[e,t(r)]))},!0),a.registerJsonType(Set,(e,t)=>({__set__:!0,data:Array.from(e).map(t)}),{check:e=>e.__set__,decode:(e,t)=>new Set(e.data.map(t))},!0),a.registerJsonType(Date,e=>({__date__:!0,value:e.toISOString()}),{check:e=>e.__date__,decode:e=>new Date(e.value)},!0),a.registerJsonType(RegExp,e=>({__regexp__:!0,source:e.source,flags:e.flags}),{check:e=>e.__regexp__,decode:e=>new RegExp(e.source,e.flags)},!0),a.registerJsonType("bigint",e=>({__bigint__:!0,value:e.toString()}),{check:e=>e.__bigint__,decode:e=>BigInt(e.value)},!0),a.registerJsonType("symbol",e=>({__symbol__:!0,key:Symbol.keyFor(e)??e.description??null}),{check:e=>e.__symbol__,decode:e=>{const t=e.key;return null!=t?Symbol.for(t):Symbol()}},!0);const l=a;window.TinyLocalStorage=t.TinyLocalStorage})();
|