@sv443-network/userutils 8.0.1 → 8.1.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/CHANGELOG.md +13 -0
- package/README.md +183 -67
- package/dist/index.global.js +59 -2
- package/dist/index.js +58 -1
- package/dist/lib/DataStore.d.ts +19 -8
- package/dist/lib/DataStoreSerializer.d.ts +20 -0
- package/package.json +4 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# @sv443-network/userutils
|
|
2
2
|
|
|
3
|
+
## 8.1.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 6296529: Added new DataStoreSerializer methods `loadStoresData()`, `resetStoresData()` and `deleteStoresData()` for parallelized bulk operations on DataStore instances
|
|
8
|
+
- b0bce9c: Added DataStore method `migrateId()` to be able to migrate to a new ID
|
|
9
|
+
|
|
10
|
+
## 8.0.2
|
|
11
|
+
|
|
12
|
+
### Patch Changes
|
|
13
|
+
|
|
14
|
+
- a8bca8f: Added `exports.types` in addition to just `types` in package.json
|
|
15
|
+
|
|
3
16
|
## 8.0.1
|
|
4
17
|
|
|
5
18
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -186,8 +186,9 @@ Additionally, there are the following extra options:
|
|
|
186
186
|
|
|
187
187
|
<br>
|
|
188
188
|
|
|
189
|
-
|
|
190
|
-
`addListener
|
|
189
|
+
### Methods:
|
|
190
|
+
#### `SelectorObserver.addListener()`
|
|
191
|
+
Usage: `SelectorObserver.addListener<TElement = HTMLElement>(selector: string, options: SelectorListenerOptions): void`
|
|
191
192
|
Adds a listener (specified in `options.listener`) for the given selector that will be called once the selector exists in the DOM. It will be passed the element(s) that match the selector as the only argument.
|
|
192
193
|
The listener will be called immediately if the selector already exists in the DOM.
|
|
193
194
|
|
|
@@ -216,45 +217,53 @@ The listener will be called immediately if the selector already exists in the DO
|
|
|
216
217
|
|
|
217
218
|
<br>
|
|
218
219
|
|
|
219
|
-
`enable(
|
|
220
|
+
#### `SelectorObserver.enable()`
|
|
221
|
+
Usage: `SelectorObserver.enable(immediatelyCheckSelectors?: boolean): boolean`
|
|
220
222
|
Enables the observation of the child elements for the first time or if it was disabled before.
|
|
221
223
|
`immediatelyCheckSelectors` is set to true by default, which means all previously registered selectors will be checked. Set to false to only check them on the first detected mutation.
|
|
222
224
|
Returns true if the observation was enabled, false if it was already enabled or the passed `baseElementSelector` couldn't be found.
|
|
223
225
|
|
|
224
226
|
<br>
|
|
225
227
|
|
|
226
|
-
`disable()
|
|
228
|
+
#### `SelectorObserver.disable()`
|
|
229
|
+
Usage: `SelectorObserver.disable(): void`
|
|
227
230
|
Disables the observation of the child elements.
|
|
228
231
|
If selectors are currently being checked, the current selector will be finished before disabling.
|
|
229
232
|
|
|
230
233
|
<br>
|
|
231
234
|
|
|
232
|
-
`isEnabled()
|
|
235
|
+
#### `SelectorObserver.isEnabled()`
|
|
236
|
+
Usage: `SelectorObserver.isEnabled(): boolean`
|
|
233
237
|
Returns whether the observation of the child elements is currently enabled.
|
|
234
238
|
|
|
235
239
|
<br>
|
|
236
240
|
|
|
237
|
-
`clearListeners()
|
|
241
|
+
#### `SelectorObserver.clearListeners()`
|
|
242
|
+
Usage: `SelectorObserver.clearListeners(): void`
|
|
238
243
|
Removes all listeners for all selectors.
|
|
239
244
|
|
|
240
245
|
<br>
|
|
241
246
|
|
|
242
|
-
`removeAllListeners(
|
|
247
|
+
#### `SelectorObserver.removeAllListeners()`
|
|
248
|
+
Usage: `SelectorObserver.removeAllListeners(selector: string): boolean`
|
|
243
249
|
Removes all listeners for the given selector.
|
|
244
250
|
|
|
245
251
|
<br>
|
|
246
252
|
|
|
247
|
-
`removeListener(
|
|
253
|
+
#### `SelectorObserver.removeListener()`
|
|
254
|
+
Usage: `SelectorObserver.removeListener(selector: string, options: SelectorListenerOptions): boolean`
|
|
248
255
|
Removes a specific listener for the given selector and options.
|
|
249
256
|
|
|
250
257
|
<br>
|
|
251
258
|
|
|
252
|
-
`getAllListeners()
|
|
259
|
+
#### `SelectorObserver.getAllListeners()`
|
|
260
|
+
Usage: `SelectorObserver.getAllListeners(): Map<string, SelectorListenerOptions[]>`
|
|
253
261
|
Returns a Map of all selectors and their listeners.
|
|
254
262
|
|
|
255
263
|
<br>
|
|
256
264
|
|
|
257
|
-
`getListeners(
|
|
265
|
+
#### `SelectorObserver.getListeners()`
|
|
266
|
+
Usage: `SelectorObserver.getListeners(selector: string): SelectorListenerOptions[] | undefined`
|
|
258
267
|
Returns all listeners for the given selector or undefined if there are none.
|
|
259
268
|
|
|
260
269
|
<br>
|
|
@@ -995,7 +1004,7 @@ It combines the data of multiple DataStore instances into a single object that c
|
|
|
995
1004
|
The options object has the following properties:
|
|
996
1005
|
| Property | Description |
|
|
997
1006
|
| :-- | :-- |
|
|
998
|
-
| `id` | A unique internal identification string for this instance. If two DataStores share the same ID, they will overwrite each other's data
|
|
1007
|
+
| `id` | A unique internal identification string for this instance. If two DataStores share the same ID, they will overwrite each other's data, so it is recommended that you use a prefix that is unique to your project. |
|
|
999
1008
|
| `defaultData` | The default data to use if no data is saved in persistent storage yet. Until the data is loaded from persistent storage, this will be the data returned by `getData()`. For TypeScript, the type of the data passed here is what will be used for all other methods of the instance. |
|
|
1000
1009
|
| `formatVersion` | An incremental version of the data format. If the format of the data is changed in any way, this number should be incremented, in which case all necessary functions of the migrations dictionary will be run consecutively. Never decrement this number or skip numbers. |
|
|
1001
1010
|
| `migrations?` | (Optional) A dictionary of functions that can be used to migrate data from older versions of the data to newer ones. The keys of the dictionary should be the format version that the functions can migrate to, from the previous whole integer value. The values should be functions that take the data in the old format and return the data in the new format. The functions will be run in order from the oldest to the newest version. If the current format version is not in the dictionary, no migrations will be run. |
|
|
@@ -1005,34 +1014,60 @@ The options object has the following properties:
|
|
|
1005
1014
|
|
|
1006
1015
|
<br>
|
|
1007
1016
|
|
|
1008
|
-
|
|
1009
|
-
`loadData()
|
|
1017
|
+
### Methods:
|
|
1018
|
+
#### `DataStore.loadData()`
|
|
1019
|
+
Usage: `loadData(): Promise<TData>`
|
|
1010
1020
|
Asynchronously loads the data from persistent storage and returns it.
|
|
1011
1021
|
If no data was saved in persistent storage before, the value of `options.defaultData` will be returned and written to persistent storage.
|
|
1012
|
-
If the formatVersion of the saved data is lower than the current one and the `options.migrations` property is present, the data will be migrated to the latest format before the Promise resolves.
|
|
1013
|
-
|
|
1014
|
-
|
|
1022
|
+
If the formatVersion of the saved data is lower than the current one and the `options.migrations` property is present, the data will be migrated to the latest format before the Promise resolves.
|
|
1023
|
+
|
|
1024
|
+
<br>
|
|
1025
|
+
|
|
1026
|
+
#### `DataStore.getData()`
|
|
1027
|
+
Usage: `getData(): TData`
|
|
1015
1028
|
Synchronously returns the current data that is stored in the internal cache.
|
|
1016
|
-
If no data was loaded from persistent storage yet using `loadData()`, the value of `options.defaultData` will be returned.
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
`
|
|
1022
|
-
Writes the
|
|
1023
|
-
|
|
1024
|
-
|
|
1029
|
+
If no data was loaded from persistent storage yet using `loadData()`, the value of `options.defaultData` will be returned.
|
|
1030
|
+
|
|
1031
|
+
<br>
|
|
1032
|
+
|
|
1033
|
+
#### `DataStore.setData()`
|
|
1034
|
+
Usage: `setData(data: TData): Promise<void>`
|
|
1035
|
+
Writes the given data synchronously to the internal cache and asynchronously to persistent storage.
|
|
1036
|
+
|
|
1037
|
+
<br>
|
|
1038
|
+
|
|
1039
|
+
#### `DataStore.saveDefaultData()`
|
|
1040
|
+
Usage: `saveDefaultData(): Promise<void>`
|
|
1041
|
+
Writes the default data given in `options.defaultData` synchronously to the internal cache and asynchronously to persistent storage.
|
|
1042
|
+
|
|
1043
|
+
<br>
|
|
1044
|
+
|
|
1045
|
+
#### `DataStore.deleteData()`
|
|
1046
|
+
Usage: `deleteData(): Promise<void>`
|
|
1025
1047
|
Fully deletes the data from persistent storage only.
|
|
1026
1048
|
The internal cache will be left untouched, so any subsequent calls to `getData()` will return the data that was last loaded.
|
|
1027
1049
|
If `loadData()` or `setData()` are called after this, the persistent storage will be populated with the value of `options.defaultData` again.
|
|
1028
1050
|
This is why you should either immediately repopulate the cache and persistent storage or the page should probably be reloaded or closed after this method is called.
|
|
1029
|
-
⚠️ If you want to use this method, the additional directive `@grant GM.deleteValue` is required.
|
|
1030
|
-
|
|
1031
|
-
|
|
1051
|
+
⚠️ If you want to use this method, the additional directive `@grant GM.deleteValue` is required.
|
|
1052
|
+
|
|
1053
|
+
<br>
|
|
1054
|
+
|
|
1055
|
+
#### `DataStore.runMigrations()`
|
|
1056
|
+
Usage: `runMigrations(oldData: any, oldFmtVer: number, resetOnError?: boolean): Promise<TData>`
|
|
1032
1057
|
Runs all necessary migration functions to migrate the given `oldData` to the latest format.
|
|
1033
|
-
If `resetOnError` is set to `false`, the migration will be aborted if an error is thrown and no data will be committed. If it is set to `true` (default) and an error is encountered, it will be suppressed and the `defaultData` will be saved to persistent storage and returned.
|
|
1034
|
-
|
|
1035
|
-
|
|
1058
|
+
If `resetOnError` is set to `false`, the migration will be aborted if an error is thrown and no data will be committed. If it is set to `true` (default) and an error is encountered, it will be suppressed and the `defaultData` will be saved to persistent storage and returned.
|
|
1059
|
+
|
|
1060
|
+
<br>
|
|
1061
|
+
|
|
1062
|
+
#### `DataStore.migrateId()`
|
|
1063
|
+
Usage: `migrateId(oldIds: string | string[]): Promise<void>`
|
|
1064
|
+
Tries to migrate the currently saved persistent data from one or more old IDs to the ID set in the constructor.
|
|
1065
|
+
If no data exist for the old ID(s), nothing will be done, but some time may still pass trying to fetch the non-existent data.
|
|
1066
|
+
|
|
1067
|
+
<br>
|
|
1068
|
+
|
|
1069
|
+
#### `DataStore.encodingEnabled()`
|
|
1070
|
+
Usage: `encodingEnabled(): boolean`
|
|
1036
1071
|
Returns `true` if both `options.encodeData` and `options.decodeData` are set, else `false`.
|
|
1037
1072
|
Uses TypeScript's type guard notation for easier use in conditional statements.
|
|
1038
1073
|
|
|
@@ -1085,7 +1120,7 @@ const migrations = {
|
|
|
1085
1120
|
|
|
1086
1121
|
// You probably want to export this instance (or helper functions) so you can use it anywhere in your script:
|
|
1087
1122
|
export const manager = new DataStore({
|
|
1088
|
-
/** A unique ID for this instance
|
|
1123
|
+
/** A unique ID for this instance */
|
|
1089
1124
|
id: "my-userscript-config",
|
|
1090
1125
|
/** Default, initial and fallback data */
|
|
1091
1126
|
defaultData,
|
|
@@ -1161,12 +1196,9 @@ The options object has the following properties:
|
|
|
1161
1196
|
|
|
1162
1197
|
<br>
|
|
1163
1198
|
|
|
1164
|
-
|
|
1165
|
-
`
|
|
1166
|
-
|
|
1167
|
-
If no options are passed, the defaults will be used.
|
|
1168
|
-
|
|
1169
|
-
`serialize(): Promise<string>`
|
|
1199
|
+
### Methods:
|
|
1200
|
+
#### `DataStoreSerializer.serialize()`
|
|
1201
|
+
Usage: `serialize(): Promise<string>`
|
|
1170
1202
|
Serializes all DataStore instances passed in the constructor and returns the serialized data as a JSON string.
|
|
1171
1203
|
<details><summary>Click to view the structure of the returned data.</summary>
|
|
1172
1204
|
|
|
@@ -1185,15 +1217,65 @@ Serializes all DataStore instances passed in the constructor and returns the ser
|
|
|
1185
1217
|
]
|
|
1186
1218
|
```
|
|
1187
1219
|
</details>
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1220
|
+
|
|
1221
|
+
<br>
|
|
1222
|
+
|
|
1223
|
+
#### `DataStoreSerializer.deserialize()`
|
|
1224
|
+
Usage: `deserialize(data: string): Promise<void>`
|
|
1225
|
+
Deserializes the given string that was created with `serialize()` and imports the contained data each DataStore instance.
|
|
1191
1226
|
In the process of importing the data, the migrations will be run, if the `formatVersion` property is lower than the one set on the DataStore instance.
|
|
1192
1227
|
|
|
1193
1228
|
If `ensureIntegrity` is set to `true` and the checksum doesn't match, an error will be thrown.
|
|
1194
1229
|
If `ensureIntegrity` is set to `false`, the checksum check will be skipped entirely.
|
|
1195
1230
|
If the `checksum` property is missing on the imported data, the checksum check will also be skipped.
|
|
1196
1231
|
If `encoded` is set to `true`, the data will be decoded using the `decodeData` function set on the DataStore instance.
|
|
1232
|
+
|
|
1233
|
+
<br>
|
|
1234
|
+
|
|
1235
|
+
#### `DataStoreSerializer.loadStoresData()`
|
|
1236
|
+
Usage: `loadStoresData(): PromiseSettledResult<{ id: string, data: object }>[];`
|
|
1237
|
+
Loads the persistent data of the DataStore instances into the in-memory cache of each DataStore instance.
|
|
1238
|
+
Also triggers the migration process if the data format has changed.
|
|
1239
|
+
See the [`DataStore.loadData()`](#datastoreloaddata) method for more information.
|
|
1240
|
+
|
|
1241
|
+
<details><summary>Click to view the structure of the returned data.</summary>
|
|
1242
|
+
|
|
1243
|
+
```jsonc
|
|
1244
|
+
[
|
|
1245
|
+
{
|
|
1246
|
+
"status": "fulfilled",
|
|
1247
|
+
"value": {
|
|
1248
|
+
"id": "foo-data",
|
|
1249
|
+
"data": {
|
|
1250
|
+
"foo": "hello",
|
|
1251
|
+
"bar": "world"
|
|
1252
|
+
}
|
|
1253
|
+
}
|
|
1254
|
+
},
|
|
1255
|
+
{
|
|
1256
|
+
"status": "rejected",
|
|
1257
|
+
"reason": "Checksum mismatch for DataStore with ID \"bar-data\"!\nExpected: 69beefdead420\nHas: 420abcdef69"
|
|
1258
|
+
}
|
|
1259
|
+
]
|
|
1260
|
+
```
|
|
1261
|
+
|
|
1262
|
+
</details>
|
|
1263
|
+
|
|
1264
|
+
<br>
|
|
1265
|
+
|
|
1266
|
+
#### `DataStoreSerializer.resetStoresData()`
|
|
1267
|
+
Usage: `resetStoresData(): PromiseSettledResult[];`
|
|
1268
|
+
Resets the persistent data of the DataStore instances to their default values.
|
|
1269
|
+
This affects both the in-memory cache and the persistent storage.
|
|
1270
|
+
Any call to `serialize()` will then use the value of `options.defaultData` of the respective DataStore instance.
|
|
1271
|
+
|
|
1272
|
+
<br>
|
|
1273
|
+
|
|
1274
|
+
#### `DataStoreSerializer.deleteStoresData()`
|
|
1275
|
+
Usage: `deleteStoresData(): PromiseSettledResult[];`
|
|
1276
|
+
Deletes the persistent data of the DataStore instances from the set storage method.
|
|
1277
|
+
Leaves the in-memory cache of the DataStore instances untouched.
|
|
1278
|
+
Any call to `setData()` on the instances will recreate their own persistent storage data.
|
|
1197
1279
|
|
|
1198
1280
|
<br>
|
|
1199
1281
|
|
|
@@ -1234,9 +1316,8 @@ const serializer = new DataStoreSerializer([fooStore, barStore], {
|
|
|
1234
1316
|
});
|
|
1235
1317
|
|
|
1236
1318
|
async function exportMyDataPls() {
|
|
1237
|
-
// first, make sure the persistent data of
|
|
1238
|
-
await
|
|
1239
|
-
await barStore.loadData();
|
|
1319
|
+
// first, make sure the persistent data of all stores is loaded into their caches:
|
|
1320
|
+
await serializer.loadStoresData();
|
|
1240
1321
|
|
|
1241
1322
|
// now serialize the data:
|
|
1242
1323
|
const serializedData = await serializer.serialize();
|
|
@@ -1269,11 +1350,11 @@ async function exportMyDataPls() {
|
|
|
1269
1350
|
}
|
|
1270
1351
|
|
|
1271
1352
|
async function importMyDataPls() {
|
|
1272
|
-
// grab the data from the file by using the system file picker or
|
|
1353
|
+
// grab the data from the file by using the system file picker or a text field or something similar
|
|
1273
1354
|
const data = await getDataFromSomewhere();
|
|
1274
1355
|
|
|
1275
1356
|
try {
|
|
1276
|
-
// import the data
|
|
1357
|
+
// import the data and run migrations if necessary
|
|
1277
1358
|
await serializer.deserialize(data);
|
|
1278
1359
|
}
|
|
1279
1360
|
catch(err) {
|
|
@@ -1281,6 +1362,11 @@ async function importMyDataPls() {
|
|
|
1281
1362
|
alert(`Data import failed: ${err}`);
|
|
1282
1363
|
}
|
|
1283
1364
|
}
|
|
1365
|
+
|
|
1366
|
+
async function resetMyDataPls() {
|
|
1367
|
+
// reset the data of all stores in both the cache and the persistent storage
|
|
1368
|
+
await serializer.resetStoresData();
|
|
1369
|
+
}
|
|
1284
1370
|
```
|
|
1285
1371
|
</details>
|
|
1286
1372
|
|
|
@@ -1313,41 +1399,71 @@ The options object has the following properties:
|
|
|
1313
1399
|
| `verticalAlign?: "top" \| "center" \| "bottom"` | (Optional) Where to align or anchor the dialog vertically. Defaults to `"center"`. |
|
|
1314
1400
|
| `strings?: Partial<typeof defaultStrings>` | (Optional) Strings used in the dialog (used for translations). Defaults to the default English strings (importable with the name `defaultStrings`). |
|
|
1315
1401
|
| `dialogCss?: string` | (Optional) CSS to apply to the dialog. Defaults to the default (importable with the name `defaultDialogCss`). |
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1402
|
+
|
|
1403
|
+
<br>
|
|
1404
|
+
|
|
1405
|
+
### Methods:
|
|
1406
|
+
#### `Dialog.open()`
|
|
1407
|
+
Usage: `open(): Promise<void>`
|
|
1319
1408
|
Opens the dialog.
|
|
1320
|
-
|
|
1321
|
-
|
|
1409
|
+
|
|
1410
|
+
<br>
|
|
1411
|
+
|
|
1412
|
+
#### `Dialog.close()`
|
|
1413
|
+
Usage: `close(): void`
|
|
1322
1414
|
Closes the dialog.
|
|
1323
|
-
|
|
1324
|
-
|
|
1415
|
+
|
|
1416
|
+
<br>
|
|
1417
|
+
|
|
1418
|
+
#### `Dialog.mount()`
|
|
1419
|
+
Usage: `mount(): Promise<void>`
|
|
1325
1420
|
Mounts the dialog to the DOM by calling the render functions provided in the options object.
|
|
1326
1421
|
Can be done before opening the dialog to avoid a delay.
|
|
1327
|
-
|
|
1328
|
-
|
|
1422
|
+
|
|
1423
|
+
<br>
|
|
1424
|
+
|
|
1425
|
+
#### `Dialog.unmount()`
|
|
1426
|
+
Usage: `unmount(): void`
|
|
1329
1427
|
Unmounts the dialog from the DOM.
|
|
1330
|
-
|
|
1331
|
-
|
|
1428
|
+
|
|
1429
|
+
<br>
|
|
1430
|
+
|
|
1431
|
+
#### `Dialog.remount()`
|
|
1432
|
+
Usage: `remount(): Promise<void>`
|
|
1332
1433
|
Unmounts and mounts the dialog again.
|
|
1333
1434
|
The render functions in the options object will be called again.
|
|
1334
1435
|
May cause a flickering effect due to the rendering delay.
|
|
1335
|
-
|
|
1336
|
-
|
|
1436
|
+
|
|
1437
|
+
<br>
|
|
1438
|
+
|
|
1439
|
+
#### `Dialog.isOpen()`
|
|
1440
|
+
Usage: `isOpen(): boolean`
|
|
1337
1441
|
Returns `true` if the dialog is open, else `false`.
|
|
1338
|
-
|
|
1339
|
-
|
|
1442
|
+
|
|
1443
|
+
<br>
|
|
1444
|
+
|
|
1445
|
+
#### `Dialog.isMounted()`
|
|
1446
|
+
Usage: `isMounted(): boolean`
|
|
1340
1447
|
Returns `true` if the dialog is mounted, else `false`.
|
|
1341
|
-
|
|
1342
|
-
|
|
1448
|
+
|
|
1449
|
+
<br>
|
|
1450
|
+
|
|
1451
|
+
#### `Dialog.destroy()`
|
|
1452
|
+
Usage: `destroy(): void`
|
|
1343
1453
|
Destroys the dialog.
|
|
1344
1454
|
Removes all listeners and unmounts the dialog by default.
|
|
1345
|
-
|
|
1346
|
-
|
|
1455
|
+
|
|
1456
|
+
<br>
|
|
1457
|
+
|
|
1458
|
+
#### `Dialog.getCurrentDialogId()`
|
|
1459
|
+
Usage: `static getCurrentDialogId(): string`
|
|
1347
1460
|
Static method that returns the ID of the currently open dialog.
|
|
1348
1461
|
Needs to be called without creating an instance of the class.
|
|
1349
|
-
|
|
1350
|
-
|
|
1462
|
+
|
|
1463
|
+
<br>
|
|
1464
|
+
|
|
1465
|
+
#### `Dialog.getOpenDialogs()`
|
|
1466
|
+
Usage: `static getOpenDialogs(): string[]`
|
|
1351
1467
|
Static method that returns an array of the IDs of all open dialogs.
|
|
1352
1468
|
Needs to be called without creating an instance of the class.
|
|
1353
1469
|
|
package/dist/index.global.js
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
// ==UserLibrary==
|
|
9
9
|
// @name UserUtils
|
|
10
10
|
// @description Library with various utilities for userscripts - register listeners for when CSS selectors exist, intercept events, create persistent & synchronous data stores, modify the DOM more easily and more
|
|
11
|
-
// @version 8.0
|
|
11
|
+
// @version 8.1.0
|
|
12
12
|
// @license MIT
|
|
13
13
|
// @copyright Sv443 (https://github.com/Sv443)
|
|
14
14
|
|
|
@@ -478,7 +478,7 @@ var UserUtils = (function (exports) {
|
|
|
478
478
|
* The in-memory cache will be left untouched, so you may still access the data with {@linkcode getData()}
|
|
479
479
|
* Calling {@linkcode loadData()} or {@linkcode setData()} after this method was called will recreate persistent storage with the cached or default data.
|
|
480
480
|
*
|
|
481
|
-
* ⚠️ This requires the additional directive `@grant GM.deleteValue`
|
|
481
|
+
* ⚠️ This requires the additional directive `@grant GM.deleteValue` if the storageMethod is left as the default of `"GM"`
|
|
482
482
|
*/
|
|
483
483
|
deleteData() {
|
|
484
484
|
return __async(this, null, function* () {
|
|
@@ -532,6 +532,31 @@ var UserUtils = (function (exports) {
|
|
|
532
532
|
return this.cachedData = __spreadValues({}, newData);
|
|
533
533
|
});
|
|
534
534
|
}
|
|
535
|
+
/**
|
|
536
|
+
* Tries to migrate the currently saved persistent data from one or more old IDs to the ID set in the constructor.
|
|
537
|
+
* If no data exist for the old ID(s), nothing will be done, but some time may still pass trying to fetch the non-existent data.
|
|
538
|
+
*/
|
|
539
|
+
migrateId(oldIds) {
|
|
540
|
+
return __async(this, null, function* () {
|
|
541
|
+
const ids = Array.isArray(oldIds) ? oldIds : [oldIds];
|
|
542
|
+
yield Promise.all(ids.map((id) => __async(this, null, function* () {
|
|
543
|
+
const data = yield this.getValue(`_uucfg-${id}`, JSON.stringify(this.defaultData));
|
|
544
|
+
const fmtVer = Number(yield this.getValue(`_uucfgver-${id}`, NaN));
|
|
545
|
+
const isEncoded = Boolean(yield this.getValue(`_uucfgenc-${id}`, false));
|
|
546
|
+
if (data === void 0 || isNaN(fmtVer))
|
|
547
|
+
return;
|
|
548
|
+
const parsed = yield this.deserializeData(data, isEncoded);
|
|
549
|
+
yield Promise.allSettled([
|
|
550
|
+
this.setValue(`_uucfg-${this.id}`, yield this.serializeData(parsed)),
|
|
551
|
+
this.setValue(`_uucfgver-${this.id}`, fmtVer),
|
|
552
|
+
this.setValue(`_uucfgenc-${this.id}`, isEncoded),
|
|
553
|
+
this.deleteValue(`_uucfg-${id}`),
|
|
554
|
+
this.deleteValue(`_uucfgver-${id}`),
|
|
555
|
+
this.deleteValue(`_uucfgenc-${id}`)
|
|
556
|
+
]);
|
|
557
|
+
})));
|
|
558
|
+
});
|
|
559
|
+
}
|
|
535
560
|
//#region serialization
|
|
536
561
|
/** Serializes the data using the optional this.encodeData() and returns it as a string */
|
|
537
562
|
serializeData(data, useEncoding = true) {
|
|
@@ -673,6 +698,38 @@ Has: ${checksum}`);
|
|
|
673
698
|
}
|
|
674
699
|
});
|
|
675
700
|
}
|
|
701
|
+
/**
|
|
702
|
+
* Loads the persistent data of the DataStore instances into the in-memory cache.
|
|
703
|
+
* Also triggers the migration process if the data format has changed.
|
|
704
|
+
* @returns Returns a PromiseSettledResult array with the results of each DataStore instance in the format `{ id: string, data: object }`
|
|
705
|
+
*/
|
|
706
|
+
loadStoresData() {
|
|
707
|
+
return __async(this, null, function* () {
|
|
708
|
+
return Promise.allSettled(this.stores.map(
|
|
709
|
+
(store) => __async(this, null, function* () {
|
|
710
|
+
return {
|
|
711
|
+
id: store.id,
|
|
712
|
+
data: yield store.loadData()
|
|
713
|
+
};
|
|
714
|
+
})
|
|
715
|
+
));
|
|
716
|
+
});
|
|
717
|
+
}
|
|
718
|
+
/** Resets the persistent data of the DataStore instances to their default values. */
|
|
719
|
+
resetStoresData() {
|
|
720
|
+
return __async(this, null, function* () {
|
|
721
|
+
return Promise.allSettled(this.stores.map((store) => store.saveDefaultData()));
|
|
722
|
+
});
|
|
723
|
+
}
|
|
724
|
+
/**
|
|
725
|
+
* Deletes the persistent data of the DataStore instances.
|
|
726
|
+
* Leaves the in-memory data untouched.
|
|
727
|
+
*/
|
|
728
|
+
deleteStoresData() {
|
|
729
|
+
return __async(this, null, function* () {
|
|
730
|
+
return Promise.allSettled(this.stores.map((store) => store.deleteData()));
|
|
731
|
+
});
|
|
732
|
+
}
|
|
676
733
|
};
|
|
677
734
|
|
|
678
735
|
// node_modules/nanoevents/index.js
|
package/dist/index.js
CHANGED
|
@@ -458,7 +458,7 @@ var DataStore = class {
|
|
|
458
458
|
* The in-memory cache will be left untouched, so you may still access the data with {@linkcode getData()}
|
|
459
459
|
* Calling {@linkcode loadData()} or {@linkcode setData()} after this method was called will recreate persistent storage with the cached or default data.
|
|
460
460
|
*
|
|
461
|
-
* ⚠️ This requires the additional directive `@grant GM.deleteValue`
|
|
461
|
+
* ⚠️ This requires the additional directive `@grant GM.deleteValue` if the storageMethod is left as the default of `"GM"`
|
|
462
462
|
*/
|
|
463
463
|
deleteData() {
|
|
464
464
|
return __async(this, null, function* () {
|
|
@@ -512,6 +512,31 @@ var DataStore = class {
|
|
|
512
512
|
return this.cachedData = __spreadValues({}, newData);
|
|
513
513
|
});
|
|
514
514
|
}
|
|
515
|
+
/**
|
|
516
|
+
* Tries to migrate the currently saved persistent data from one or more old IDs to the ID set in the constructor.
|
|
517
|
+
* If no data exist for the old ID(s), nothing will be done, but some time may still pass trying to fetch the non-existent data.
|
|
518
|
+
*/
|
|
519
|
+
migrateId(oldIds) {
|
|
520
|
+
return __async(this, null, function* () {
|
|
521
|
+
const ids = Array.isArray(oldIds) ? oldIds : [oldIds];
|
|
522
|
+
yield Promise.all(ids.map((id) => __async(this, null, function* () {
|
|
523
|
+
const data = yield this.getValue(`_uucfg-${id}`, JSON.stringify(this.defaultData));
|
|
524
|
+
const fmtVer = Number(yield this.getValue(`_uucfgver-${id}`, NaN));
|
|
525
|
+
const isEncoded = Boolean(yield this.getValue(`_uucfgenc-${id}`, false));
|
|
526
|
+
if (data === void 0 || isNaN(fmtVer))
|
|
527
|
+
return;
|
|
528
|
+
const parsed = yield this.deserializeData(data, isEncoded);
|
|
529
|
+
yield Promise.allSettled([
|
|
530
|
+
this.setValue(`_uucfg-${this.id}`, yield this.serializeData(parsed)),
|
|
531
|
+
this.setValue(`_uucfgver-${this.id}`, fmtVer),
|
|
532
|
+
this.setValue(`_uucfgenc-${this.id}`, isEncoded),
|
|
533
|
+
this.deleteValue(`_uucfg-${id}`),
|
|
534
|
+
this.deleteValue(`_uucfgver-${id}`),
|
|
535
|
+
this.deleteValue(`_uucfgenc-${id}`)
|
|
536
|
+
]);
|
|
537
|
+
})));
|
|
538
|
+
});
|
|
539
|
+
}
|
|
515
540
|
//#region serialization
|
|
516
541
|
/** Serializes the data using the optional this.encodeData() and returns it as a string */
|
|
517
542
|
serializeData(data, useEncoding = true) {
|
|
@@ -653,6 +678,38 @@ Has: ${checksum}`);
|
|
|
653
678
|
}
|
|
654
679
|
});
|
|
655
680
|
}
|
|
681
|
+
/**
|
|
682
|
+
* Loads the persistent data of the DataStore instances into the in-memory cache.
|
|
683
|
+
* Also triggers the migration process if the data format has changed.
|
|
684
|
+
* @returns Returns a PromiseSettledResult array with the results of each DataStore instance in the format `{ id: string, data: object }`
|
|
685
|
+
*/
|
|
686
|
+
loadStoresData() {
|
|
687
|
+
return __async(this, null, function* () {
|
|
688
|
+
return Promise.allSettled(this.stores.map(
|
|
689
|
+
(store) => __async(this, null, function* () {
|
|
690
|
+
return {
|
|
691
|
+
id: store.id,
|
|
692
|
+
data: yield store.loadData()
|
|
693
|
+
};
|
|
694
|
+
})
|
|
695
|
+
));
|
|
696
|
+
});
|
|
697
|
+
}
|
|
698
|
+
/** Resets the persistent data of the DataStore instances to their default values. */
|
|
699
|
+
resetStoresData() {
|
|
700
|
+
return __async(this, null, function* () {
|
|
701
|
+
return Promise.allSettled(this.stores.map((store) => store.saveDefaultData()));
|
|
702
|
+
});
|
|
703
|
+
}
|
|
704
|
+
/**
|
|
705
|
+
* Deletes the persistent data of the DataStore instances.
|
|
706
|
+
* Leaves the in-memory data untouched.
|
|
707
|
+
*/
|
|
708
|
+
deleteStoresData() {
|
|
709
|
+
return __async(this, null, function* () {
|
|
710
|
+
return Promise.allSettled(this.stores.map((store) => store.deleteData()));
|
|
711
|
+
});
|
|
712
|
+
}
|
|
656
713
|
};
|
|
657
714
|
var NanoEmitter = class {
|
|
658
715
|
constructor(options = {}) {
|
package/dist/lib/DataStore.d.ts
CHANGED
|
@@ -5,11 +5,15 @@ type MigrationFunc = (oldData: any) => any | Promise<any>;
|
|
|
5
5
|
export type DataMigrationsDict = Record<number, MigrationFunc>;
|
|
6
6
|
/** Options for the DataStore instance */
|
|
7
7
|
export type DataStoreOptions<TData> = {
|
|
8
|
-
/**
|
|
8
|
+
/**
|
|
9
|
+
* A unique internal ID for this data store.
|
|
10
|
+
* To avoid conflicts with other scripts, it is recommended to use a prefix that is unique to your script.
|
|
11
|
+
* If you want to change the ID, you should make use of the {@linkcode DataStore.migrateId()} method.
|
|
12
|
+
*/
|
|
9
13
|
id: string;
|
|
10
14
|
/**
|
|
11
15
|
* The default data object to use if no data is saved in persistent storage yet.
|
|
12
|
-
* Until the data is loaded from persistent storage with
|
|
16
|
+
* Until the data is loaded from persistent storage with {@linkcode DataStore.loadData()}, this will be the data returned by {@linkcode DataStore.getData()}.
|
|
13
17
|
*
|
|
14
18
|
* ⚠️ This has to be an object that can be serialized to JSON using `JSON.stringify()`, so no functions or circular references are allowed, they will cause unexpected behavior.
|
|
15
19
|
*/
|
|
@@ -31,8 +35,8 @@ export type DataStoreOptions<TData> = {
|
|
|
31
35
|
migrations?: DataMigrationsDict;
|
|
32
36
|
/**
|
|
33
37
|
* Where the data should be saved (`"GM"` by default).
|
|
34
|
-
* The protected methods
|
|
35
|
-
*
|
|
38
|
+
* The protected methods {@linkcode DataStore.getValue()}, {@linkcode DataStore.setValue()} and {@linkcode DataStore.deleteValue()} are used to interact with the storage.
|
|
39
|
+
* `"GM"` storage, `"localStorage"` and `"sessionStorage"` are supported out of the box, but in an extended class you can overwrite those methods to implement any other storage method.
|
|
36
40
|
*/
|
|
37
41
|
storageMethod?: "GM" | "localStorage" | "sessionStorage";
|
|
38
42
|
} & ({
|
|
@@ -57,16 +61,18 @@ export type DataStoreOptions<TData> = {
|
|
|
57
61
|
decodeData?: never;
|
|
58
62
|
});
|
|
59
63
|
/**
|
|
60
|
-
* Manages a hybrid synchronous & asynchronous persistent JSON database that is cached in memory and persistently saved across sessions using [GM storage
|
|
64
|
+
* Manages a hybrid synchronous & asynchronous persistent JSON database that is cached in memory and persistently saved across sessions using [GM storage](https://wiki.greasespot.net/GM.setValue) (default), [localStorage](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage) or [sessionStorage](https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage).
|
|
61
65
|
* Supports migrating data from older format versions to newer ones and populating the cache with default data if no persistent data is found.
|
|
66
|
+
* Can be overridden to implement any other storage method.
|
|
62
67
|
*
|
|
63
68
|
* All methods are at least `protected`, so you can easily extend this class and overwrite them to use a different storage method or to add additional functionality.
|
|
64
69
|
* Remember that you can call `super.methodName()` in the subclass to access the original method.
|
|
65
70
|
*
|
|
66
|
-
* ⚠️
|
|
71
|
+
* ⚠️ The stored data has to be **serializable using `JSON.stringify()`**, meaning no undefined, circular references, etc. are allowed.
|
|
72
|
+
* ⚠️ If the storageMethod is left as the default of `"GM"` the directives `@grant GM.getValue` and `@grant GM.setValue` are required. If you then also use the method {@linkcode DataStore.deleteData()}, the extra directive `@grant GM.deleteValue` is needed too.
|
|
67
73
|
* ⚠️ Make sure to call {@linkcode loadData()} at least once after creating an instance, or the returned data will be the same as `options.defaultData`
|
|
68
74
|
*
|
|
69
|
-
* @template TData The type of the data that is saved in persistent storage for the currently set format version (will be automatically inferred from `defaultData` if not provided)
|
|
75
|
+
* @template TData The type of the data that is saved in persistent storage for the currently set format version (will be automatically inferred from `defaultData` if not provided)
|
|
70
76
|
*/
|
|
71
77
|
export declare class DataStore<TData extends object = object> {
|
|
72
78
|
readonly id: string;
|
|
@@ -109,7 +115,7 @@ export declare class DataStore<TData extends object = object> {
|
|
|
109
115
|
* The in-memory cache will be left untouched, so you may still access the data with {@linkcode getData()}
|
|
110
116
|
* Calling {@linkcode loadData()} or {@linkcode setData()} after this method was called will recreate persistent storage with the cached or default data.
|
|
111
117
|
*
|
|
112
|
-
* ⚠️ This requires the additional directive `@grant GM.deleteValue`
|
|
118
|
+
* ⚠️ This requires the additional directive `@grant GM.deleteValue` if the storageMethod is left as the default of `"GM"`
|
|
113
119
|
*/
|
|
114
120
|
deleteData(): Promise<void>;
|
|
115
121
|
/** Returns whether encoding and decoding are enabled for this DataStore instance */
|
|
@@ -122,6 +128,11 @@ export declare class DataStore<TData extends object = object> {
|
|
|
122
128
|
* If one of the migrations fails, the data will be reset to the default value if `resetOnError` is set to `true` (default). Otherwise, an error will be thrown and no data will be saved.
|
|
123
129
|
*/
|
|
124
130
|
runMigrations(oldData: any, oldFmtVer: number, resetOnError?: boolean): Promise<TData>;
|
|
131
|
+
/**
|
|
132
|
+
* Tries to migrate the currently saved persistent data from one or more old IDs to the ID set in the constructor.
|
|
133
|
+
* If no data exist for the old ID(s), nothing will be done, but some time may still pass trying to fetch the non-existent data.
|
|
134
|
+
*/
|
|
135
|
+
migrateId(oldIds: string | string[]): Promise<void>;
|
|
125
136
|
/** Serializes the data using the optional this.encodeData() and returns it as a string */
|
|
126
137
|
protected serializeData(data: TData, useEncoding?: boolean): Promise<string>;
|
|
127
138
|
/** Deserializes the data using the optional this.decodeData() and returns it as a JSON object */
|
|
@@ -18,6 +18,13 @@ export type SerializedDataStore = {
|
|
|
18
18
|
/** The checksum of the data - key is not present for data without a checksum */
|
|
19
19
|
checksum?: string;
|
|
20
20
|
};
|
|
21
|
+
/** Result of {@linkcode DataStoreSerializer.loadStoresData()} */
|
|
22
|
+
export type LoadStoresDataResult = {
|
|
23
|
+
/** The ID of the DataStore instance */
|
|
24
|
+
id: string;
|
|
25
|
+
/** The in-memory data object */
|
|
26
|
+
data: object;
|
|
27
|
+
};
|
|
21
28
|
/**
|
|
22
29
|
* Allows for easy serialization and deserialization of multiple DataStore instances.
|
|
23
30
|
*
|
|
@@ -41,4 +48,17 @@ export declare class DataStoreSerializer {
|
|
|
41
48
|
* Also triggers the migration process if the data format has changed.
|
|
42
49
|
*/
|
|
43
50
|
deserialize(serializedData: string): Promise<void>;
|
|
51
|
+
/**
|
|
52
|
+
* Loads the persistent data of the DataStore instances into the in-memory cache.
|
|
53
|
+
* Also triggers the migration process if the data format has changed.
|
|
54
|
+
* @returns Returns a PromiseSettledResult array with the results of each DataStore instance in the format `{ id: string, data: object }`
|
|
55
|
+
*/
|
|
56
|
+
loadStoresData(): Promise<PromiseSettledResult<LoadStoresDataResult>[]>;
|
|
57
|
+
/** Resets the persistent data of the DataStore instances to their default values. */
|
|
58
|
+
resetStoresData(): Promise<PromiseSettledResult<void>[]>;
|
|
59
|
+
/**
|
|
60
|
+
* Deletes the persistent data of the DataStore instances.
|
|
61
|
+
* Leaves the in-memory data untouched.
|
|
62
|
+
*/
|
|
63
|
+
deleteStoresData(): Promise<PromiseSettledResult<void>[]>;
|
|
44
64
|
}
|
package/package.json
CHANGED
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sv443-network/userutils",
|
|
3
3
|
"libName": "UserUtils",
|
|
4
|
-
"version": "8.0
|
|
4
|
+
"version": "8.1.0",
|
|
5
5
|
"description": "Library with various utilities for userscripts - register listeners for when CSS selectors exist, intercept events, create persistent & synchronous data stores, modify the DOM more easily and more",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"module": "dist/index.js",
|
|
8
|
+
"types": "dist/lib/index.d.ts",
|
|
8
9
|
"exports": {
|
|
9
10
|
".": {
|
|
10
11
|
"import": "./dist/index.js",
|
|
11
12
|
"require": "./dist/index.cjs",
|
|
12
|
-
"browser": "./dist/index.global.js"
|
|
13
|
+
"browser": "./dist/index.global.js",
|
|
14
|
+
"types": "./dist/lib/index.d.ts"
|
|
13
15
|
}
|
|
14
16
|
},
|
|
15
|
-
"types": "dist/lib/index.d.ts",
|
|
16
17
|
"type": "module",
|
|
17
18
|
"scripts": {
|
|
18
19
|
"lint": "tsc --noEmit && eslint .",
|