@sv443-network/userutils 8.1.0 → 8.3.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 +16 -0
- package/README.md +149 -33
- package/dist/index.global.js +54 -21
- package/dist/index.js +53 -20
- package/dist/lib/DataStore.d.ts +11 -2
- package/dist/lib/SelectorObserver.d.ts +3 -2
- package/dist/lib/crypto.d.ts +3 -2
- package/dist/lib/math.d.ts +16 -5
- package/dist/lib/misc.d.ts +3 -3
- package/dist/lib/types.d.ts +7 -0
- package/package.json +3 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# @sv443-network/userutils
|
|
2
2
|
|
|
3
|
+
## 8.3.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 1ecd63c: Added support for the `signal` property in `fetchAdvanced()`
|
|
8
|
+
|
|
9
|
+
## 8.2.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- 3fe8b25: Added overload to `mapRange()` that only needs both `max` values and assumes 0 for both `min` values
|
|
14
|
+
- d7e8a31: Added utility type `Prettify` to make complex types more readable
|
|
15
|
+
- 8ec2010: Added `randomCase` parameter to the function `randomId()` (true by default)
|
|
16
|
+
- d9a36d5: Added property `migrateIds` to the constructor of `DataStore` for easier ID migration
|
|
17
|
+
- b2f757e: Added `enhancedEntropy` parameter to the function `randRange()` (false by default)
|
|
18
|
+
|
|
3
19
|
## 8.1.0
|
|
4
20
|
|
|
5
21
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -78,6 +78,7 @@ View the documentation of previous major releases:
|
|
|
78
78
|
- [`NonEmptyArray`](#nonemptyarray) - any array that should have at least one item
|
|
79
79
|
- [`NonEmptyString`](#nonemptystring) - any string that should have at least one character
|
|
80
80
|
- [`LooseUnion`](#looseunion) - a union that gives autocomplete in the IDE but also allows any other value of the same type
|
|
81
|
+
- [`Prettify`](#prettify) - expands a complex type into a more readable format while keeping functionality the same
|
|
81
82
|
|
|
82
83
|
<br><br>
|
|
83
84
|
|
|
@@ -930,16 +931,12 @@ clamp(99999, 0, Infinity); // 99999
|
|
|
930
931
|
### mapRange()
|
|
931
932
|
Usage:
|
|
932
933
|
```ts
|
|
933
|
-
mapRange(
|
|
934
|
-
|
|
935
|
-
range1min: number,
|
|
936
|
-
range1max: number,
|
|
937
|
-
range2min: number,
|
|
938
|
-
range2max: number
|
|
939
|
-
): number
|
|
934
|
+
mapRange(value: number, range1min: number, range1max: number, range2min: number, range2max: number): number
|
|
935
|
+
mapRange(value: number, range1max: number, range2max: number): number
|
|
940
936
|
```
|
|
941
937
|
|
|
942
938
|
Maps a number from one range to the spot it would be in another range.
|
|
939
|
+
If only the `max` arguments are passed, the function will set the `min` for both ranges to 0.
|
|
943
940
|
|
|
944
941
|
<details><summary><b>Example - click to view</b></summary>
|
|
945
942
|
|
|
@@ -948,6 +945,7 @@ import { mapRange } from "@sv443-network/userutils";
|
|
|
948
945
|
|
|
949
946
|
mapRange(5, 0, 10, 0, 100); // 50
|
|
950
947
|
mapRange(5, 0, 10, 0, 50); // 25
|
|
948
|
+
mapRange(5, 10, 50); // 25
|
|
951
949
|
|
|
952
950
|
// to calculate a percentage from arbitrary values, use 0 and 100 as the second range
|
|
953
951
|
// for example, if 4 files of a total of 13 were downloaded:
|
|
@@ -960,21 +958,41 @@ mapRange(4, 0, 13, 0, 100); // 30.76923076923077
|
|
|
960
958
|
### randRange()
|
|
961
959
|
Usages:
|
|
962
960
|
```ts
|
|
963
|
-
randRange(min: number, max: number): number
|
|
964
|
-
randRange(max: number): number
|
|
961
|
+
randRange(min: number, max: number, enhancedEntropy?: boolean): number
|
|
962
|
+
randRange(max: number, enhancedEntropy?: boolean): number
|
|
965
963
|
```
|
|
966
964
|
|
|
967
965
|
Returns a random number between `min` and `max` (inclusive).
|
|
968
966
|
If only one argument is passed, it will be used as the `max` value and `min` will be set to 0.
|
|
969
967
|
|
|
968
|
+
If `enhancedEntropy` is set to true (false by default), the [Web Crypto API](https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues) is used for generating the random numbers.
|
|
969
|
+
Note that this makes the function call take longer, but the generated IDs will have a higher entropy.
|
|
970
|
+
|
|
970
971
|
<details><summary><b>Example - click to view</b></summary>
|
|
971
972
|
|
|
972
973
|
```ts
|
|
973
974
|
import { randRange } from "@sv443-network/userutils";
|
|
974
975
|
|
|
975
|
-
randRange(0, 10);
|
|
976
|
-
randRange(10, 20);
|
|
977
|
-
randRange(10);
|
|
976
|
+
randRange(0, 10); // 4
|
|
977
|
+
randRange(10, 20); // 17
|
|
978
|
+
randRange(10); // 7
|
|
979
|
+
randRange(0, 10, true); // 4 (the devil is in the details)
|
|
980
|
+
|
|
981
|
+
|
|
982
|
+
function benchmark(enhancedEntropy: boolean) {
|
|
983
|
+
const timestamp = Date.now();
|
|
984
|
+
for(let i = 0; i < 100_000; i++)
|
|
985
|
+
randRange(0, 100, enhancedEntropy);
|
|
986
|
+
console.log(`Generated 100k in ${Date.now() - timestamp}ms`)
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
// using Math.random():
|
|
990
|
+
benchmark(false); // Generated 100k in 90ms
|
|
991
|
+
|
|
992
|
+
// using crypto.getRandomValues():
|
|
993
|
+
benchmark(true); // Generated 100k in 461ms
|
|
994
|
+
|
|
995
|
+
// about a 5x slowdown, but the generated numbers are more entropic
|
|
978
996
|
```
|
|
979
997
|
</details>
|
|
980
998
|
|
|
@@ -1008,6 +1026,7 @@ The options object has the following properties:
|
|
|
1008
1026
|
| `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. |
|
|
1009
1027
|
| `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. |
|
|
1010
1028
|
| `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. |
|
|
1029
|
+
| `migrateIds?` | (Optional) A string or array of strings that migrate from one or more old IDs to the ID set in the constructor. 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. The ID migration will be done once per session in the call to [`loadData()`](#datastoreloaddata). |
|
|
1011
1030
|
| `storageMethod?` | (Optional) The method that is used to store the data. Can be `"GM"` (default), `"localStorage"` or `"sessionStorage"`. If you want to store the data in a different way, you can override the methods of the DataStore class. |
|
|
1012
1031
|
| `encodeData?` | (Optional, but required when `decodeData` is set) Function that encodes the data before saving - you can use [compress()](#compress) here to save space at the cost of a little bit of performance |
|
|
1013
1032
|
| `decodeData?` | (Optional, but required when `encodeData` is set) Function that decodes the data when loading - you can use [decompress()](#decompress) here to decode data that was previously compressed with [compress()](#compress) |
|
|
@@ -1018,8 +1037,9 @@ The options object has the following properties:
|
|
|
1018
1037
|
#### `DataStore.loadData()`
|
|
1019
1038
|
Usage: `loadData(): Promise<TData>`
|
|
1020
1039
|
Asynchronously loads the data from persistent storage and returns it.
|
|
1021
|
-
If no data was saved in persistent storage before, the value of `options.defaultData` will be returned and written to persistent storage.
|
|
1022
|
-
If the
|
|
1040
|
+
If no data was saved in persistent storage before, the value of `options.defaultData` will be returned and also written to persistent storage before resolving.
|
|
1041
|
+
If the `options.migrateIds` property is present and this is the first time calling this function in this session, the data will be migrated from the old ID(s) to the current one.
|
|
1042
|
+
Then, if the `formatVersion` of the saved data is lower than the current one and the `options.migrations` property is present, the instance will try to migrate the data to the latest format before resolving, updating the in-memory cache and persistent storage.
|
|
1023
1043
|
|
|
1024
1044
|
<br>
|
|
1025
1045
|
|
|
@@ -1062,7 +1082,8 @@ If `resetOnError` is set to `false`, the migration will be aborted if an error i
|
|
|
1062
1082
|
#### `DataStore.migrateId()`
|
|
1063
1083
|
Usage: `migrateId(oldIds: string | string[]): Promise<void>`
|
|
1064
1084
|
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.
|
|
1085
|
+
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.
|
|
1086
|
+
Instead of calling this manually, consider setting the `migrateIds` property in the constructor to automatically migrate the data once per session in the call to `loadData()`, unless you know that you need to migrate the ID(s) manually.
|
|
1066
1087
|
|
|
1067
1088
|
<br>
|
|
1068
1089
|
|
|
@@ -1124,10 +1145,12 @@ export const manager = new DataStore({
|
|
|
1124
1145
|
id: "my-userscript-config",
|
|
1125
1146
|
/** Default, initial and fallback data */
|
|
1126
1147
|
defaultData,
|
|
1127
|
-
/** The current version of the data format */
|
|
1148
|
+
/** The current version of the data format - should be a whole number that is only ever incremented */
|
|
1128
1149
|
formatVersion,
|
|
1129
1150
|
/** Data format migration functions called when the formatVersion is increased */
|
|
1130
1151
|
migrations,
|
|
1152
|
+
/** If the data was saved under different ID(s) before, providing them here will make sure the data is migrated to the current ID when `loadData()` is called */
|
|
1153
|
+
migrateIds: ["my-data", "config"],
|
|
1131
1154
|
/**
|
|
1132
1155
|
* Where the data should be stored.
|
|
1133
1156
|
* For example, you could use `"sessionStorage"` to make the data be automatically deleted after the browser session is finished, or use `"localStorage"` if you don't have access to GM storage for some reason.
|
|
@@ -1254,7 +1277,7 @@ See the [`DataStore.loadData()`](#datastoreloaddata) method for more information
|
|
|
1254
1277
|
},
|
|
1255
1278
|
{
|
|
1256
1279
|
"status": "rejected",
|
|
1257
|
-
"reason": "Checksum mismatch for DataStore with ID \"bar-data\"!\nExpected: 69beefdead420\nHas:
|
|
1280
|
+
"reason": "Checksum mismatch for DataStore with ID \"bar-data\"!\nExpected: 69beefdead420\nHas: abcdef42"
|
|
1258
1281
|
}
|
|
1259
1282
|
]
|
|
1260
1283
|
```
|
|
@@ -1406,25 +1429,28 @@ The options object has the following properties:
|
|
|
1406
1429
|
#### `Dialog.open()`
|
|
1407
1430
|
Usage: `open(): Promise<void>`
|
|
1408
1431
|
Opens the dialog.
|
|
1432
|
+
If the dialog is not mounted yet, it will be mounted before opening.
|
|
1409
1433
|
|
|
1410
1434
|
<br>
|
|
1411
1435
|
|
|
1412
1436
|
#### `Dialog.close()`
|
|
1413
1437
|
Usage: `close(): void`
|
|
1414
1438
|
Closes the dialog.
|
|
1439
|
+
If `options.destroyOnClose` is set to `true`, [`Dialog.destroy()`](#dialogdestroy) will be called immediately after closing.
|
|
1415
1440
|
|
|
1416
1441
|
<br>
|
|
1417
1442
|
|
|
1418
1443
|
#### `Dialog.mount()`
|
|
1419
1444
|
Usage: `mount(): Promise<void>`
|
|
1420
1445
|
Mounts the dialog to the DOM by calling the render functions provided in the options object.
|
|
1421
|
-
|
|
1446
|
+
After calling, the dialog will exist in the DOM but will be invisible until [`Dialog.open()`](#dialogopen) is called.
|
|
1447
|
+
Call this before opening the dialog to avoid a rendering delay.
|
|
1422
1448
|
|
|
1423
1449
|
<br>
|
|
1424
1450
|
|
|
1425
1451
|
#### `Dialog.unmount()`
|
|
1426
1452
|
Usage: `unmount(): void`
|
|
1427
|
-
|
|
1453
|
+
Closes the dialog first if it's open, then removes it from the DOM.
|
|
1428
1454
|
|
|
1429
1455
|
<br>
|
|
1430
1456
|
|
|
@@ -1451,7 +1477,7 @@ Returns `true` if the dialog is mounted, else `false`.
|
|
|
1451
1477
|
#### `Dialog.destroy()`
|
|
1452
1478
|
Usage: `destroy(): void`
|
|
1453
1479
|
Destroys the dialog.
|
|
1454
|
-
Removes all listeners and unmounts the dialog
|
|
1480
|
+
Removes all listeners by default and closes and unmounts the dialog.
|
|
1455
1481
|
|
|
1456
1482
|
<br>
|
|
1457
1483
|
|
|
@@ -1508,6 +1534,10 @@ fooDialog.on("close", () => {
|
|
|
1508
1534
|
console.log("Dialog closed");
|
|
1509
1535
|
});
|
|
1510
1536
|
|
|
1537
|
+
fooDialog.on("open", () => {
|
|
1538
|
+
console.log("Currently open dialogs:", Dialog.getOpenDialogs());
|
|
1539
|
+
});
|
|
1540
|
+
|
|
1511
1541
|
fooDialog.open();
|
|
1512
1542
|
```
|
|
1513
1543
|
</details>
|
|
@@ -1587,6 +1617,7 @@ myInstance.on("foo", (bar) => {
|
|
|
1587
1617
|
console.log("foo event (outside):", bar);
|
|
1588
1618
|
});
|
|
1589
1619
|
|
|
1620
|
+
// only works if publicEmit is set to true
|
|
1590
1621
|
myInstance.emit("baz", "hello from the outside");
|
|
1591
1622
|
|
|
1592
1623
|
myInstance.unsubscribeAll();
|
|
@@ -1620,6 +1651,7 @@ myEmitter.once("baz", (qux) => {
|
|
|
1620
1651
|
});
|
|
1621
1652
|
|
|
1622
1653
|
function doStuff() {
|
|
1654
|
+
// only works if publicEmit is set to true
|
|
1623
1655
|
myEmitter.emit("foo", "hello");
|
|
1624
1656
|
myEmitter.emit("baz", 42);
|
|
1625
1657
|
myEmitter.emit("foo", "world");
|
|
@@ -1743,24 +1775,32 @@ fetchAdvanced(input: string | Request | URL, options?: {
|
|
|
1743
1775
|
|
|
1744
1776
|
A drop-in replacement for the native `fetch()` function that adds options like a timeout property.
|
|
1745
1777
|
The timeout will default to 10 seconds if left undefined. Set it to a negative number to disable the timeout.
|
|
1746
|
-
Note that the `signal` option will be overwritten if passed.
|
|
1747
1778
|
|
|
1748
1779
|
<details><summary><b>Example - click to view</b></summary>
|
|
1749
1780
|
|
|
1750
1781
|
```ts
|
|
1751
1782
|
import { fetchAdvanced } from "@sv443-network/userutils";
|
|
1752
1783
|
|
|
1784
|
+
const { signal, abort } = new AbortController();
|
|
1785
|
+
|
|
1753
1786
|
fetchAdvanced("https://jokeapi.dev/joke/Any?safe-mode", {
|
|
1787
|
+
// times out after 5 seconds:
|
|
1754
1788
|
timeout: 5000,
|
|
1755
|
-
// also accepts any other fetch options like headers:
|
|
1789
|
+
// also accepts any other fetch options like headers and signal:
|
|
1756
1790
|
headers: {
|
|
1757
1791
|
"Accept": "text/plain",
|
|
1758
1792
|
},
|
|
1793
|
+
// makes the request abortable:
|
|
1794
|
+
signal,
|
|
1759
1795
|
}).then(async (response) => {
|
|
1760
1796
|
console.log("Fetch data:", await response.text());
|
|
1761
1797
|
}).catch((err) => {
|
|
1762
1798
|
console.error("Fetch error:", err);
|
|
1763
1799
|
});
|
|
1800
|
+
|
|
1801
|
+
document.querySelector("button#cancel")?.addEventListener("click", () => {
|
|
1802
|
+
abort();
|
|
1803
|
+
});
|
|
1764
1804
|
```
|
|
1765
1805
|
</details>
|
|
1766
1806
|
|
|
@@ -1900,7 +1940,7 @@ run();
|
|
|
1900
1940
|
### randomId()
|
|
1901
1941
|
Usage:
|
|
1902
1942
|
```ts
|
|
1903
|
-
randomId(length?: number, radix?: number, enhancedEntropy?: boolean): string
|
|
1943
|
+
randomId(length?: number, radix?: number, enhancedEntropy?: boolean, randomCase?: boolean): string
|
|
1904
1944
|
```
|
|
1905
1945
|
|
|
1906
1946
|
Generates a random ID of a given length and [radix (base).](https://en.wikipedia.org/wiki/Radix)
|
|
@@ -1910,20 +1950,41 @@ You may change the radix to get digits from different numerical systems.
|
|
|
1910
1950
|
Use 2 for binary, 8 for octal, 10 for decimal, 16 for hexadecimal and 36 for alphanumeric.
|
|
1911
1951
|
|
|
1912
1952
|
If `enhancedEntropy` is set to true (false by default), the [Web Crypto API](https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues) is used for generating the random numbers.
|
|
1913
|
-
Note that this
|
|
1953
|
+
Note that this makes the function call take longer, but the generated IDs will have a higher entropy.
|
|
1954
|
+
|
|
1955
|
+
If `randomCase` is set to true (which it is by default), the generated ID will contain both upper and lower case letters.
|
|
1956
|
+
This randomization is also affected by the `enhancedEntropy` setting, unless there are no alphabetic characters in the output in which case it will be skipped.
|
|
1914
1957
|
|
|
1915
|
-
⚠️
|
|
1958
|
+
⚠️ This is not suitable for generating anything related to cryptography! Use [SubtleCrypto's `generateKey()`](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/generateKey) for that instead.
|
|
1916
1959
|
|
|
1917
1960
|
<details><summary><b>Example - click to view</b></summary>
|
|
1918
1961
|
|
|
1919
1962
|
```ts
|
|
1920
1963
|
import { randomId } from "@sv443-network/userutils";
|
|
1921
1964
|
|
|
1922
|
-
randomId();
|
|
1923
|
-
randomId(10);
|
|
1924
|
-
randomId(10, 2);
|
|
1925
|
-
randomId(10, 10);
|
|
1926
|
-
randomId(10, 36); // "
|
|
1965
|
+
randomId(); // "1bda419a73629d4f" (length 16, radix 16)
|
|
1966
|
+
randomId(10); // "f86cd354a4" (length 10, radix 16)
|
|
1967
|
+
randomId(10, 2); // "1010001101" (length 10, radix 2)
|
|
1968
|
+
randomId(10, 10); // "0183428506" (length 10, radix 10)
|
|
1969
|
+
randomId(10, 36, false, true); // "z46jFPa37R" (length 10, radix 36, random case)
|
|
1970
|
+
|
|
1971
|
+
|
|
1972
|
+
function benchmark(enhancedEntropy: boolean, randomCase: boolean) {
|
|
1973
|
+
const timestamp = Date.now();
|
|
1974
|
+
for(let i = 0; i < 10_000; i++)
|
|
1975
|
+
randomId(16, 36, enhancedEntropy, randomCase);
|
|
1976
|
+
console.log(`Generated 10k in ${Date.now() - timestamp}ms`)
|
|
1977
|
+
}
|
|
1978
|
+
|
|
1979
|
+
// using Math.random():
|
|
1980
|
+
benchmark(false, false); // Generated 10k in 239ms
|
|
1981
|
+
benchmark(false, true); // Generated 10k in 248ms
|
|
1982
|
+
|
|
1983
|
+
// using crypto.getRandomValues():
|
|
1984
|
+
benchmark(true, false); // Generated 10k in 1076ms
|
|
1985
|
+
benchmark(true, true); // Generated 10k in 1054ms
|
|
1986
|
+
|
|
1987
|
+
// 3rd and 4th have a similar time, but in reality the 4th blocks the event loop for much longer
|
|
1927
1988
|
```
|
|
1928
1989
|
</details>
|
|
1929
1990
|
|
|
@@ -2411,7 +2472,7 @@ Usage:
|
|
|
2411
2472
|
NonEmptyArray<TItem = unknown>
|
|
2412
2473
|
```
|
|
2413
2474
|
|
|
2414
|
-
This type describes an array that has at least one item.
|
|
2475
|
+
This generic type describes an array that has at least one item.
|
|
2415
2476
|
Use the generic parameter to specify the type of the items in the array.
|
|
2416
2477
|
|
|
2417
2478
|
<details><summary><b>Example - click to view</b></summary>
|
|
@@ -2441,7 +2502,7 @@ Usage:
|
|
|
2441
2502
|
NonEmptyString<TString extends string>
|
|
2442
2503
|
```
|
|
2443
2504
|
|
|
2444
|
-
This type describes a string that has at least one character.
|
|
2505
|
+
This generic type describes a string that has at least one character.
|
|
2445
2506
|
|
|
2446
2507
|
<details><summary><b>Example - click to view</b></summary>
|
|
2447
2508
|
|
|
@@ -2465,7 +2526,7 @@ Usage:
|
|
|
2465
2526
|
LooseUnion<TUnion extends string | number | object>
|
|
2466
2527
|
```
|
|
2467
2528
|
|
|
2468
|
-
A type that offers autocomplete in the IDE for the passed union but also allows any value of the same type to be passed.
|
|
2529
|
+
A generic type that offers autocomplete in the IDE for the passed union but also allows any value of the same type to be passed.
|
|
2469
2530
|
Supports unions of strings, numbers and objects.
|
|
2470
2531
|
|
|
2471
2532
|
<details><summary><b>Example - click to view</b></summary>
|
|
@@ -2484,6 +2545,61 @@ foo(1); // type error: Argument of type '1' is not assignable to parameter of
|
|
|
2484
2545
|
```
|
|
2485
2546
|
</details>
|
|
2486
2547
|
|
|
2548
|
+
<br>
|
|
2549
|
+
|
|
2550
|
+
## Prettify
|
|
2551
|
+
Usage:
|
|
2552
|
+
```ts
|
|
2553
|
+
Prettify<T>
|
|
2554
|
+
```
|
|
2555
|
+
|
|
2556
|
+
A generic type that makes TypeScript and your IDE display the type in a more readable way.
|
|
2557
|
+
This is especially useful for types that reference other types or are very complex.
|
|
2558
|
+
It will also make a variable show its type's structure instead of just the type name (see example).
|
|
2559
|
+
|
|
2560
|
+
<details><summary><b>Example - click to view</b></summary>
|
|
2561
|
+
|
|
2562
|
+
```ts
|
|
2563
|
+
// tooltip shows all constituent types, leaving you to figure it out yourself:
|
|
2564
|
+
// type Foo = {
|
|
2565
|
+
// a: number;
|
|
2566
|
+
// } & Omit<{
|
|
2567
|
+
// b: string;
|
|
2568
|
+
// c: boolean;
|
|
2569
|
+
// }, "c">
|
|
2570
|
+
type Foo = {
|
|
2571
|
+
a: number;
|
|
2572
|
+
} & Omit<{
|
|
2573
|
+
b: string;
|
|
2574
|
+
c: boolean;
|
|
2575
|
+
}, "c">;
|
|
2576
|
+
|
|
2577
|
+
// tooltip shows just the type name:
|
|
2578
|
+
// const foo: Foo
|
|
2579
|
+
const foo: Foo = {
|
|
2580
|
+
a: 1,
|
|
2581
|
+
b: "2"
|
|
2582
|
+
};
|
|
2583
|
+
|
|
2584
|
+
// tooltip shows the actual type structure:
|
|
2585
|
+
// type Bar = {
|
|
2586
|
+
// a: number;
|
|
2587
|
+
// b: string;
|
|
2588
|
+
// }
|
|
2589
|
+
type Bar = Prettify<Foo>;
|
|
2590
|
+
|
|
2591
|
+
// tooltip again shows the actual type structure:
|
|
2592
|
+
// const bar: {
|
|
2593
|
+
// a: number;
|
|
2594
|
+
// b: string;
|
|
2595
|
+
// }
|
|
2596
|
+
const bar: Bar = {
|
|
2597
|
+
a: 1,
|
|
2598
|
+
b: "2"
|
|
2599
|
+
};
|
|
2600
|
+
```
|
|
2601
|
+
</details>
|
|
2602
|
+
|
|
2487
2603
|
<br><br><br><br>
|
|
2488
2604
|
|
|
2489
2605
|
<!-- #region Footer -->
|
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.
|
|
11
|
+
// @version 8.3.0
|
|
12
12
|
// @license MIT
|
|
13
13
|
// @copyright Sv443 (https://github.com/Sv443)
|
|
14
14
|
|
|
@@ -78,12 +78,18 @@ var UserUtils = (function (exports) {
|
|
|
78
78
|
return Math.max(Math.min(value, max), min);
|
|
79
79
|
}
|
|
80
80
|
function mapRange(value, range1min, range1max, range2min, range2max) {
|
|
81
|
+
if (typeof range2min === "undefined" || range2max === void 0) {
|
|
82
|
+
range2max = range1max;
|
|
83
|
+
range2min = 0;
|
|
84
|
+
range1max = range1min;
|
|
85
|
+
range1min = 0;
|
|
86
|
+
}
|
|
81
87
|
if (Number(range1min) === 0 && Number(range2min) === 0)
|
|
82
88
|
return value * (range2max / range1max);
|
|
83
89
|
return (value - range1min) * ((range2max - range2min) / (range1max - range1min)) + range2min;
|
|
84
90
|
}
|
|
85
91
|
function randRange(...args) {
|
|
86
|
-
let min, max;
|
|
92
|
+
let min, max, enhancedEntropy = false;
|
|
87
93
|
if (typeof args[0] === "number" && typeof args[1] === "number")
|
|
88
94
|
[min, max] = args;
|
|
89
95
|
else if (typeof args[0] === "number" && typeof args[1] !== "number") {
|
|
@@ -91,13 +97,25 @@ var UserUtils = (function (exports) {
|
|
|
91
97
|
[max] = args;
|
|
92
98
|
} else
|
|
93
99
|
throw new TypeError(`Wrong parameter(s) provided - expected: "number" and "number|undefined", got: "${typeof args[0]}" and "${typeof args[1]}"`);
|
|
100
|
+
if (typeof args[2] === "boolean")
|
|
101
|
+
enhancedEntropy = args[2];
|
|
102
|
+
else if (typeof args[1] === "boolean")
|
|
103
|
+
enhancedEntropy = args[1];
|
|
94
104
|
min = Number(min);
|
|
95
105
|
max = Number(max);
|
|
96
106
|
if (isNaN(min) || isNaN(max))
|
|
97
107
|
return NaN;
|
|
98
108
|
if (min > max)
|
|
99
109
|
throw new TypeError(`Parameter "min" can't be bigger than "max"`);
|
|
100
|
-
|
|
110
|
+
if (enhancedEntropy) {
|
|
111
|
+
const uintArr = new Uint8Array(1);
|
|
112
|
+
crypto.getRandomValues(uintArr);
|
|
113
|
+
return Number(Array.from(
|
|
114
|
+
uintArr,
|
|
115
|
+
(v) => Math.round(mapRange(v, 0, 255, min, max)).toString(10).substring(0, 1)
|
|
116
|
+
).join(""));
|
|
117
|
+
} else
|
|
118
|
+
return Math.floor(Math.random() * (max - min + 1)) + min;
|
|
101
119
|
}
|
|
102
120
|
|
|
103
121
|
// lib/array.ts
|
|
@@ -356,19 +374,25 @@ var UserUtils = (function (exports) {
|
|
|
356
374
|
return hashHex;
|
|
357
375
|
});
|
|
358
376
|
}
|
|
359
|
-
function randomId(length = 16, radix = 16, enhancedEntropy = false) {
|
|
377
|
+
function randomId(length = 16, radix = 16, enhancedEntropy = false, randomCase = true) {
|
|
378
|
+
let arr = [];
|
|
379
|
+
const caseArr = randomCase ? [0, 1] : [0];
|
|
360
380
|
if (enhancedEntropy) {
|
|
361
|
-
const
|
|
362
|
-
crypto.getRandomValues(
|
|
363
|
-
|
|
364
|
-
|
|
381
|
+
const uintArr = new Uint8Array(length);
|
|
382
|
+
crypto.getRandomValues(uintArr);
|
|
383
|
+
arr = Array.from(
|
|
384
|
+
uintArr,
|
|
365
385
|
(v) => mapRange(v, 0, 255, 0, radix).toString(radix).substring(0, 1)
|
|
366
|
-
)
|
|
386
|
+
);
|
|
387
|
+
} else {
|
|
388
|
+
arr = Array.from(
|
|
389
|
+
{ length },
|
|
390
|
+
() => Math.floor(Math.random() * radix).toString(radix)
|
|
391
|
+
);
|
|
367
392
|
}
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
).join("");
|
|
393
|
+
if (!arr.some((v) => /[a-zA-Z]/.test(v)))
|
|
394
|
+
return arr.join("");
|
|
395
|
+
return arr.map((v) => caseArr[randRange(0, caseArr.length - 1, enhancedEntropy)] === 1 ? v.toUpperCase() : v).join("");
|
|
372
396
|
}
|
|
373
397
|
|
|
374
398
|
// lib/DataStore.ts
|
|
@@ -392,12 +416,15 @@ var UserUtils = (function (exports) {
|
|
|
392
416
|
__publicField(this, "storageMethod");
|
|
393
417
|
__publicField(this, "cachedData");
|
|
394
418
|
__publicField(this, "migrations");
|
|
419
|
+
__publicField(this, "migrateIds", []);
|
|
395
420
|
var _a;
|
|
396
421
|
this.id = options.id;
|
|
397
422
|
this.formatVersion = options.formatVersion;
|
|
398
423
|
this.defaultData = options.defaultData;
|
|
399
424
|
this.cachedData = options.defaultData;
|
|
400
425
|
this.migrations = options.migrations;
|
|
426
|
+
if (options.migrateIds)
|
|
427
|
+
this.migrateIds = Array.isArray(options.migrateIds) ? options.migrateIds : [options.migrateIds];
|
|
401
428
|
this.storageMethod = (_a = options.storageMethod) != null ? _a : "GM";
|
|
402
429
|
this.encodeData = options.encodeData;
|
|
403
430
|
this.decodeData = options.decodeData;
|
|
@@ -411,6 +438,10 @@ var UserUtils = (function (exports) {
|
|
|
411
438
|
loadData() {
|
|
412
439
|
return __async(this, null, function* () {
|
|
413
440
|
try {
|
|
441
|
+
if (this.migrateIds.length > 0) {
|
|
442
|
+
yield this.migrateId(this.migrateIds);
|
|
443
|
+
this.migrateIds = [];
|
|
444
|
+
}
|
|
414
445
|
const gmData = yield this.getValue(`_uucfg-${this.id}`, JSON.stringify(this.defaultData));
|
|
415
446
|
let gmFmtVer = Number(yield this.getValue(`_uucfgver-${this.id}`, NaN));
|
|
416
447
|
if (typeof gmData !== "string") {
|
|
@@ -1240,27 +1271,29 @@ Has: ${checksum}`);
|
|
|
1240
1271
|
});
|
|
1241
1272
|
}
|
|
1242
1273
|
function debounce(func, timeout = 300, edge = "falling") {
|
|
1243
|
-
let
|
|
1274
|
+
let id;
|
|
1244
1275
|
return function(...args) {
|
|
1245
1276
|
if (edge === "rising") {
|
|
1246
|
-
if (!
|
|
1277
|
+
if (!id) {
|
|
1247
1278
|
func.apply(this, args);
|
|
1248
|
-
|
|
1279
|
+
id = setTimeout(() => id = void 0, timeout);
|
|
1249
1280
|
}
|
|
1250
1281
|
} else {
|
|
1251
|
-
clearTimeout(
|
|
1252
|
-
|
|
1282
|
+
clearTimeout(id);
|
|
1283
|
+
id = setTimeout(() => func.apply(this, args), timeout);
|
|
1253
1284
|
}
|
|
1254
1285
|
};
|
|
1255
1286
|
}
|
|
1256
1287
|
function fetchAdvanced(_0) {
|
|
1257
1288
|
return __async(this, arguments, function* (input, options = {}) {
|
|
1289
|
+
var _a;
|
|
1258
1290
|
const { timeout = 1e4 } = options;
|
|
1291
|
+
const { signal, abort } = new AbortController();
|
|
1292
|
+
(_a = options.signal) == null ? void 0 : _a.addEventListener("abort", abort);
|
|
1259
1293
|
let signalOpts = {}, id = void 0;
|
|
1260
1294
|
if (timeout >= 0) {
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
signalOpts = { signal: controller.signal };
|
|
1295
|
+
id = setTimeout(() => abort(), timeout);
|
|
1296
|
+
signalOpts = { signal };
|
|
1264
1297
|
}
|
|
1265
1298
|
try {
|
|
1266
1299
|
const res = yield fetch(input, __spreadValues(__spreadValues({}, options), signalOpts));
|
package/dist/index.js
CHANGED
|
@@ -58,12 +58,18 @@ function clamp(value, min, max) {
|
|
|
58
58
|
return Math.max(Math.min(value, max), min);
|
|
59
59
|
}
|
|
60
60
|
function mapRange(value, range1min, range1max, range2min, range2max) {
|
|
61
|
+
if (typeof range2min === "undefined" || range2max === void 0) {
|
|
62
|
+
range2max = range1max;
|
|
63
|
+
range2min = 0;
|
|
64
|
+
range1max = range1min;
|
|
65
|
+
range1min = 0;
|
|
66
|
+
}
|
|
61
67
|
if (Number(range1min) === 0 && Number(range2min) === 0)
|
|
62
68
|
return value * (range2max / range1max);
|
|
63
69
|
return (value - range1min) * ((range2max - range2min) / (range1max - range1min)) + range2min;
|
|
64
70
|
}
|
|
65
71
|
function randRange(...args) {
|
|
66
|
-
let min, max;
|
|
72
|
+
let min, max, enhancedEntropy = false;
|
|
67
73
|
if (typeof args[0] === "number" && typeof args[1] === "number")
|
|
68
74
|
[min, max] = args;
|
|
69
75
|
else if (typeof args[0] === "number" && typeof args[1] !== "number") {
|
|
@@ -71,13 +77,25 @@ function randRange(...args) {
|
|
|
71
77
|
[max] = args;
|
|
72
78
|
} else
|
|
73
79
|
throw new TypeError(`Wrong parameter(s) provided - expected: "number" and "number|undefined", got: "${typeof args[0]}" and "${typeof args[1]}"`);
|
|
80
|
+
if (typeof args[2] === "boolean")
|
|
81
|
+
enhancedEntropy = args[2];
|
|
82
|
+
else if (typeof args[1] === "boolean")
|
|
83
|
+
enhancedEntropy = args[1];
|
|
74
84
|
min = Number(min);
|
|
75
85
|
max = Number(max);
|
|
76
86
|
if (isNaN(min) || isNaN(max))
|
|
77
87
|
return NaN;
|
|
78
88
|
if (min > max)
|
|
79
89
|
throw new TypeError(`Parameter "min" can't be bigger than "max"`);
|
|
80
|
-
|
|
90
|
+
if (enhancedEntropy) {
|
|
91
|
+
const uintArr = new Uint8Array(1);
|
|
92
|
+
crypto.getRandomValues(uintArr);
|
|
93
|
+
return Number(Array.from(
|
|
94
|
+
uintArr,
|
|
95
|
+
(v) => Math.round(mapRange(v, 0, 255, min, max)).toString(10).substring(0, 1)
|
|
96
|
+
).join(""));
|
|
97
|
+
} else
|
|
98
|
+
return Math.floor(Math.random() * (max - min + 1)) + min;
|
|
81
99
|
}
|
|
82
100
|
|
|
83
101
|
// lib/array.ts
|
|
@@ -336,19 +354,25 @@ function computeHash(input, algorithm = "SHA-256") {
|
|
|
336
354
|
return hashHex;
|
|
337
355
|
});
|
|
338
356
|
}
|
|
339
|
-
function randomId(length = 16, radix = 16, enhancedEntropy = false) {
|
|
357
|
+
function randomId(length = 16, radix = 16, enhancedEntropy = false, randomCase = true) {
|
|
358
|
+
let arr = [];
|
|
359
|
+
const caseArr = randomCase ? [0, 1] : [0];
|
|
340
360
|
if (enhancedEntropy) {
|
|
341
|
-
const
|
|
342
|
-
crypto.getRandomValues(
|
|
343
|
-
|
|
344
|
-
|
|
361
|
+
const uintArr = new Uint8Array(length);
|
|
362
|
+
crypto.getRandomValues(uintArr);
|
|
363
|
+
arr = Array.from(
|
|
364
|
+
uintArr,
|
|
345
365
|
(v) => mapRange(v, 0, 255, 0, radix).toString(radix).substring(0, 1)
|
|
346
|
-
)
|
|
366
|
+
);
|
|
367
|
+
} else {
|
|
368
|
+
arr = Array.from(
|
|
369
|
+
{ length },
|
|
370
|
+
() => Math.floor(Math.random() * radix).toString(radix)
|
|
371
|
+
);
|
|
347
372
|
}
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
).join("");
|
|
373
|
+
if (!arr.some((v) => /[a-zA-Z]/.test(v)))
|
|
374
|
+
return arr.join("");
|
|
375
|
+
return arr.map((v) => caseArr[randRange(0, caseArr.length - 1, enhancedEntropy)] === 1 ? v.toUpperCase() : v).join("");
|
|
352
376
|
}
|
|
353
377
|
|
|
354
378
|
// lib/DataStore.ts
|
|
@@ -372,12 +396,15 @@ var DataStore = class {
|
|
|
372
396
|
__publicField(this, "storageMethod");
|
|
373
397
|
__publicField(this, "cachedData");
|
|
374
398
|
__publicField(this, "migrations");
|
|
399
|
+
__publicField(this, "migrateIds", []);
|
|
375
400
|
var _a;
|
|
376
401
|
this.id = options.id;
|
|
377
402
|
this.formatVersion = options.formatVersion;
|
|
378
403
|
this.defaultData = options.defaultData;
|
|
379
404
|
this.cachedData = options.defaultData;
|
|
380
405
|
this.migrations = options.migrations;
|
|
406
|
+
if (options.migrateIds)
|
|
407
|
+
this.migrateIds = Array.isArray(options.migrateIds) ? options.migrateIds : [options.migrateIds];
|
|
381
408
|
this.storageMethod = (_a = options.storageMethod) != null ? _a : "GM";
|
|
382
409
|
this.encodeData = options.encodeData;
|
|
383
410
|
this.decodeData = options.decodeData;
|
|
@@ -391,6 +418,10 @@ var DataStore = class {
|
|
|
391
418
|
loadData() {
|
|
392
419
|
return __async(this, null, function* () {
|
|
393
420
|
try {
|
|
421
|
+
if (this.migrateIds.length > 0) {
|
|
422
|
+
yield this.migrateId(this.migrateIds);
|
|
423
|
+
this.migrateIds = [];
|
|
424
|
+
}
|
|
394
425
|
const gmData = yield this.getValue(`_uucfg-${this.id}`, JSON.stringify(this.defaultData));
|
|
395
426
|
let gmFmtVer = Number(yield this.getValue(`_uucfgver-${this.id}`, NaN));
|
|
396
427
|
if (typeof gmData !== "string") {
|
|
@@ -1200,27 +1231,29 @@ function pauseFor(time) {
|
|
|
1200
1231
|
});
|
|
1201
1232
|
}
|
|
1202
1233
|
function debounce(func, timeout = 300, edge = "falling") {
|
|
1203
|
-
let
|
|
1234
|
+
let id;
|
|
1204
1235
|
return function(...args) {
|
|
1205
1236
|
if (edge === "rising") {
|
|
1206
|
-
if (!
|
|
1237
|
+
if (!id) {
|
|
1207
1238
|
func.apply(this, args);
|
|
1208
|
-
|
|
1239
|
+
id = setTimeout(() => id = void 0, timeout);
|
|
1209
1240
|
}
|
|
1210
1241
|
} else {
|
|
1211
|
-
clearTimeout(
|
|
1212
|
-
|
|
1242
|
+
clearTimeout(id);
|
|
1243
|
+
id = setTimeout(() => func.apply(this, args), timeout);
|
|
1213
1244
|
}
|
|
1214
1245
|
};
|
|
1215
1246
|
}
|
|
1216
1247
|
function fetchAdvanced(_0) {
|
|
1217
1248
|
return __async(this, arguments, function* (input, options = {}) {
|
|
1249
|
+
var _a;
|
|
1218
1250
|
const { timeout = 1e4 } = options;
|
|
1251
|
+
const { signal, abort } = new AbortController();
|
|
1252
|
+
(_a = options.signal) == null ? void 0 : _a.addEventListener("abort", abort);
|
|
1219
1253
|
let signalOpts = {}, id = void 0;
|
|
1220
1254
|
if (timeout >= 0) {
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
signalOpts = { signal: controller.signal };
|
|
1255
|
+
id = setTimeout(() => abort(), timeout);
|
|
1256
|
+
signalOpts = { signal };
|
|
1224
1257
|
}
|
|
1225
1258
|
try {
|
|
1226
1259
|
const res = yield fetch(input, __spreadValues(__spreadValues({}, options), signalOpts));
|
package/dist/lib/DataStore.d.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
/// <reference types="greasemonkey" />
|
|
2
|
+
import type { Prettify } from "./types.js";
|
|
2
3
|
/** Function that takes the data in the old format and returns the data in the new format. Also supports an asynchronous migration. */
|
|
3
4
|
type MigrationFunc = (oldData: any) => any | Promise<any>;
|
|
4
5
|
/** Dictionary of format version numbers and the function that migrates to them from the previous whole integer */
|
|
5
6
|
export type DataMigrationsDict = Record<number, MigrationFunc>;
|
|
6
7
|
/** Options for the DataStore instance */
|
|
7
|
-
export type DataStoreOptions<TData> = {
|
|
8
|
+
export type DataStoreOptions<TData> = Prettify<{
|
|
8
9
|
/**
|
|
9
10
|
* A unique internal ID for this data store.
|
|
10
11
|
* To avoid conflicts with other scripts, it is recommended to use a prefix that is unique to your script.
|
|
@@ -33,6 +34,13 @@ export type DataStoreOptions<TData> = {
|
|
|
33
34
|
* If the current format version is not in the dictionary, no migrations will be run.
|
|
34
35
|
*/
|
|
35
36
|
migrations?: DataMigrationsDict;
|
|
37
|
+
/**
|
|
38
|
+
* If an ID or multiple IDs are passed here, the data will be migrated from the old ID(s) to the current ID.
|
|
39
|
+
* This will happen once per page load, when {@linkcode DataStore.loadData()} is called.
|
|
40
|
+
* All future calls to {@linkcode DataStore.loadData()} in the session will not check for the old ID(s) anymore.
|
|
41
|
+
* To migrate IDs manually, use the method {@linkcode DataStore.migrateId()} instead.
|
|
42
|
+
*/
|
|
43
|
+
migrateIds?: string | string[];
|
|
36
44
|
/**
|
|
37
45
|
* Where the data should be saved (`"GM"` by default).
|
|
38
46
|
* The protected methods {@linkcode DataStore.getValue()}, {@linkcode DataStore.setValue()} and {@linkcode DataStore.deleteValue()} are used to interact with the storage.
|
|
@@ -59,7 +67,7 @@ export type DataStoreOptions<TData> = {
|
|
|
59
67
|
} | {
|
|
60
68
|
encodeData?: never;
|
|
61
69
|
decodeData?: never;
|
|
62
|
-
})
|
|
70
|
+
})>;
|
|
63
71
|
/**
|
|
64
72
|
* 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).
|
|
65
73
|
* Supports migrating data from older format versions to newer ones and populating the cache with default data if no persistent data is found.
|
|
@@ -83,6 +91,7 @@ export declare class DataStore<TData extends object = object> {
|
|
|
83
91
|
readonly storageMethod: Required<DataStoreOptions<TData>>["storageMethod"];
|
|
84
92
|
private cachedData;
|
|
85
93
|
private migrations?;
|
|
94
|
+
private migrateIds;
|
|
86
95
|
/**
|
|
87
96
|
* Creates an instance of DataStore to manage a sync & async database that is cached in memory and persistently saved across sessions.
|
|
88
97
|
* Supports migrating data from older versions to newer ones and populating the cache with default data if no persistent data is found.
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import type { Prettify } from "./types.js";
|
|
1
2
|
/** Options for the `onSelector()` method of {@linkcode SelectorObserver} */
|
|
2
|
-
export type SelectorListenerOptions<TElem extends Element = HTMLElement> = SelectorOptionsOne<TElem> | SelectorOptionsAll<TElem
|
|
3
|
+
export type SelectorListenerOptions<TElem extends Element = HTMLElement> = Prettify<SelectorOptionsOne<TElem> | SelectorOptionsAll<TElem>>;
|
|
3
4
|
type SelectorOptionsOne<TElem extends Element> = SelectorOptionsCommon & {
|
|
4
5
|
/** Whether to use `querySelectorAll()` instead - default is false */
|
|
5
6
|
all?: false;
|
|
@@ -36,7 +37,7 @@ export type SelectorObserverOptions = {
|
|
|
36
37
|
/** If set to a number, the checks will be run on interval instead of on mutation events - in that case all MutationObserverInit props will be ignored */
|
|
37
38
|
checkInterval?: number;
|
|
38
39
|
};
|
|
39
|
-
export type SelectorObserverConstructorOptions =
|
|
40
|
+
export type SelectorObserverConstructorOptions = Prettify<SelectorObserverOptions & MutationObserverInit>;
|
|
40
41
|
/** Observes the children of the given element for changes */
|
|
41
42
|
export declare class SelectorObserver {
|
|
42
43
|
private enabled;
|
package/dist/lib/crypto.d.ts
CHANGED
|
@@ -19,6 +19,7 @@ export declare function computeHash(input: string | ArrayBuffer, algorithm?: str
|
|
|
19
19
|
* ⚠️ Not suitable for generating anything related to cryptography! Use [SubtleCrypto's `generateKey()`](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/generateKey) for that instead.
|
|
20
20
|
* @param length The length of the ID to generate (defaults to 16)
|
|
21
21
|
* @param radix The [radix](https://en.wikipedia.org/wiki/Radix) of each digit (defaults to 16 which is hexadecimal. Use 2 for binary, 10 for decimal, 36 for alphanumeric, etc.)
|
|
22
|
-
* @param enhancedEntropy If set to true, uses [`crypto.getRandomValues()`](https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues) for better cryptographic randomness (this also makes it take
|
|
22
|
+
* @param enhancedEntropy If set to true, uses [`crypto.getRandomValues()`](https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues) for better cryptographic randomness (this also makes it take longer to generate)
|
|
23
|
+
* @param randomCase If set to false, the generated ID will be lowercase only - also makes use of the `enhancedEntropy` parameter unless the output doesn't contain letters
|
|
23
24
|
*/
|
|
24
|
-
export declare function randomId(length?: number, radix?: number, enhancedEntropy?: boolean): string;
|
|
25
|
+
export declare function randomId(length?: number, radix?: number, enhancedEntropy?: boolean, randomCase?: boolean): string;
|
package/dist/lib/math.d.ts
CHANGED
|
@@ -1,11 +1,22 @@
|
|
|
1
1
|
/** Ensures the passed {@linkcode value} always stays between {@linkcode min} and {@linkcode max} */
|
|
2
2
|
export declare function clamp(value: number, min: number, max: number): number;
|
|
3
3
|
/**
|
|
4
|
-
* Transforms the value parameter from the numerical range `range1min
|
|
4
|
+
* Transforms the value parameter from the numerical range `range1min` to `range1max` to the numerical range `range2min` to `range2max`
|
|
5
5
|
* For example, you can map the value 2 in the range of 0-5 to the range of 0-10 and you'd get a 4 as a result.
|
|
6
6
|
*/
|
|
7
7
|
export declare function mapRange(value: number, range1min: number, range1max: number, range2min: number, range2max: number): number;
|
|
8
|
-
/**
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
/**
|
|
9
|
+
* Transforms the value parameter from the numerical range `0` to `range1max` to the numerical range `0` to `range2max`
|
|
10
|
+
* For example, you can map the value 2 in the range of 0-5 to the range of 0-10 and you'd get a 4 as a result.
|
|
11
|
+
*/
|
|
12
|
+
export declare function mapRange(value: number, range1max: number, range2max: number): number;
|
|
13
|
+
/**
|
|
14
|
+
* Returns a random number between {@linkcode min} and {@linkcode max} (inclusive)
|
|
15
|
+
* Set {@linkcode enhancedEntropy} to true to use `crypto.getRandomValues()` for better cryptographic randomness (this also makes it take longer to generate)
|
|
16
|
+
*/
|
|
17
|
+
export declare function randRange(min: number, max: number, enhancedEntropy?: boolean): number;
|
|
18
|
+
/**
|
|
19
|
+
* Returns a random number between 0 and {@linkcode max} (inclusive)
|
|
20
|
+
* Set {@linkcode enhancedEntropy} to true to use `crypto.getRandomValues()` for better cryptographic randomness (this also makes it take longer to generate)
|
|
21
|
+
*/
|
|
22
|
+
export declare function randRange(max: number, enhancedEntropy?: boolean): number;
|
package/dist/lib/misc.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Stringifiable } from "./types.js";
|
|
1
|
+
import type { Prettify, Stringifiable } from "./types.js";
|
|
2
2
|
/**
|
|
3
3
|
* Automatically appends an `s` to the passed {@linkcode word}, if {@linkcode num} is not equal to 1
|
|
4
4
|
* @param word A word in singular form, to auto-convert to plural
|
|
@@ -24,9 +24,9 @@ export declare function pauseFor(time: number): Promise<void>;
|
|
|
24
24
|
export declare function debounce<TFunc extends (...args: TArgs[]) => void, // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
25
25
|
TArgs = any>(func: TFunc, timeout?: number, edge?: "rising" | "falling"): (...args: TArgs[]) => void;
|
|
26
26
|
/** Options for the `fetchAdvanced()` function */
|
|
27
|
-
export type FetchAdvancedOpts =
|
|
27
|
+
export type FetchAdvancedOpts = Prettify<Partial<{
|
|
28
28
|
/** Timeout in milliseconds after which the fetch call will be canceled with an AbortController signal */
|
|
29
29
|
timeout: number;
|
|
30
|
-
}
|
|
30
|
+
}> & RequestInit>;
|
|
31
31
|
/** Calls the fetch API with special options like a timeout */
|
|
32
32
|
export declare function fetchAdvanced(input: RequestInfo | URL, options?: FetchAdvancedOpts): Promise<Response>;
|
package/dist/lib/types.d.ts
CHANGED
|
@@ -15,3 +15,10 @@ export type LooseUnion<TUnion extends string | number | object> = (TUnion) | (TU
|
|
|
15
15
|
* }
|
|
16
16
|
*/
|
|
17
17
|
export type NonEmptyString<TString extends string> = TString extends "" ? never : TString;
|
|
18
|
+
/**
|
|
19
|
+
* Makes the structure of a type more readable by expanding it.
|
|
20
|
+
* This can be useful for debugging or for improving the readability of complex types.
|
|
21
|
+
*/
|
|
22
|
+
export type Prettify<T> = {
|
|
23
|
+
[K in keyof T]: T[K];
|
|
24
|
+
} & {};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sv443-network/userutils",
|
|
3
3
|
"libName": "UserUtils",
|
|
4
|
-
"version": "8.
|
|
4
|
+
"version": "8.3.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",
|
|
@@ -26,7 +26,8 @@
|
|
|
26
26
|
"dev-all": "npm run build-all -- --watch",
|
|
27
27
|
"update-jsr-version": "npm run node-ts -- ./tools/update-jsr-version.mts",
|
|
28
28
|
"publish-package": "changeset publish",
|
|
29
|
-
"publish-package-jsr": "npm run update-jsr-version && npx jsr publish",
|
|
29
|
+
"publish-package-jsr": "npm run update-jsr-version && npx jsr publish --allow-dirty",
|
|
30
|
+
"change": "changeset",
|
|
30
31
|
"node-ts": "node --no-warnings=ExperimentalWarning --enable-source-maps --loader ts-node/esm",
|
|
31
32
|
"test-serve": "npm run node-ts -- ./test/TestPage/server.mts",
|
|
32
33
|
"test-dev": "cd test/TestScript && npm run dev",
|