@sv443-network/userutils 8.2.0 → 8.3.1
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 +12 -0
- package/README.md +15 -4
- package/dist/index.global.js +16 -11
- package/dist/index.js +15 -10
- package/dist/lib/DataStore.d.ts +3 -2
- package/dist/lib/SelectorObserver.d.ts +3 -2
- package/dist/lib/misc.d.ts +3 -3
- package/package.json +3 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @sv443-network/userutils
|
|
2
2
|
|
|
3
|
+
## 8.3.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 390110e: Throw an error when calling `interceptEvent()` on `window` or `unsafeWindow` on FireMonkey instead of crashing the entire page
|
|
8
|
+
|
|
9
|
+
## 8.3.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- 1ecd63c: Added support for the `signal` property in `fetchAdvanced()`
|
|
14
|
+
|
|
3
15
|
## 8.2.0
|
|
4
16
|
|
|
5
17
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -622,6 +622,7 @@ If no predicate is specified, all events will be discarded.
|
|
|
622
622
|
Calling this function will set the `Error.stackTraceLimit` to 100 (if it's not already higher) to ensure the stack trace is preserved.
|
|
623
623
|
|
|
624
624
|
⚠️ This function should be called as soon as possible (I recommend using `@run-at document-start`), as it will only intercept events that are *attached* after this function is called.
|
|
625
|
+
⚠️ Due to this function modifying the `addEventListener` prototype, it might break execution of the page's main script if the userscript is running in an isolated context (like it does in FireMonkey). In that case, calling this function will throw an error.
|
|
625
626
|
|
|
626
627
|
<details><summary><b>Example - click to view</b></summary>
|
|
627
628
|
|
|
@@ -655,7 +656,8 @@ If no predicate is specified, all events will be discarded.
|
|
|
655
656
|
This is essentially the same as [`interceptEvent()`](#interceptevent), but automatically uses the `unsafeWindow` (or falls back to regular `window`).
|
|
656
657
|
|
|
657
658
|
⚠️ This function should be called as soon as possible (I recommend using `@run-at document-start`), as it will only intercept events that are *attached* after this function is called.
|
|
658
|
-
⚠️ In order
|
|
659
|
+
⚠️ In order to have the best chance at intercepting events, the directive `@grant unsafeWindow` should be set.
|
|
660
|
+
⚠️ Due to this function modifying the `addEventListener` prototype, it might break execution of the page's main script if the userscript is running in an isolated context (like it does in FireMonkey). In that case, calling this function will throw an error.
|
|
659
661
|
|
|
660
662
|
<details><summary><b>Example - click to view</b></summary>
|
|
661
663
|
|
|
@@ -1769,30 +1771,39 @@ Usage:
|
|
|
1769
1771
|
```ts
|
|
1770
1772
|
fetchAdvanced(input: string | Request | URL, options?: {
|
|
1771
1773
|
timeout?: number,
|
|
1772
|
-
// any other options from fetch()
|
|
1774
|
+
// any other options from fetch()
|
|
1773
1775
|
}): Promise<Response>
|
|
1774
1776
|
```
|
|
1775
1777
|
|
|
1776
1778
|
A drop-in replacement for the native `fetch()` function that adds options like a timeout property.
|
|
1777
1779
|
The timeout will default to 10 seconds if left undefined. Set it to a negative number to disable the timeout.
|
|
1778
|
-
|
|
1780
|
+
Pass an [AbortController's signal](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) to the `signal` property to be able to abort the request before it finishes or the timeout kicks in.
|
|
1779
1781
|
|
|
1780
1782
|
<details><summary><b>Example - click to view</b></summary>
|
|
1781
1783
|
|
|
1782
1784
|
```ts
|
|
1783
1785
|
import { fetchAdvanced } from "@sv443-network/userutils";
|
|
1784
1786
|
|
|
1787
|
+
const { signal, abort } = new AbortController();
|
|
1788
|
+
|
|
1785
1789
|
fetchAdvanced("https://jokeapi.dev/joke/Any?safe-mode", {
|
|
1790
|
+
// times out after 5 seconds:
|
|
1786
1791
|
timeout: 5000,
|
|
1787
|
-
// also accepts any other fetch options like headers:
|
|
1792
|
+
// also accepts any other fetch options like headers and signal:
|
|
1788
1793
|
headers: {
|
|
1789
1794
|
"Accept": "text/plain",
|
|
1790
1795
|
},
|
|
1796
|
+
// makes the request abortable:
|
|
1797
|
+
signal,
|
|
1791
1798
|
}).then(async (response) => {
|
|
1792
1799
|
console.log("Fetch data:", await response.text());
|
|
1793
1800
|
}).catch((err) => {
|
|
1794
1801
|
console.error("Fetch error:", err);
|
|
1795
1802
|
});
|
|
1803
|
+
|
|
1804
|
+
document.querySelector("button#cancel")?.addEventListener("click", () => {
|
|
1805
|
+
abort();
|
|
1806
|
+
});
|
|
1796
1807
|
```
|
|
1797
1808
|
</details>
|
|
1798
1809
|
|
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.1
|
|
12
12
|
// @license MIT
|
|
13
13
|
// @copyright Sv443 (https://github.com/Sv443)
|
|
14
14
|
|
|
@@ -247,13 +247,16 @@ var UserUtils = (function (exports) {
|
|
|
247
247
|
}
|
|
248
248
|
}
|
|
249
249
|
function interceptEvent(eventObject, eventName, predicate = () => true) {
|
|
250
|
+
var _a;
|
|
251
|
+
if ((eventObject === window || eventObject === getUnsafeWindow()) && ((_a = GM == null ? void 0 : GM.info) == null ? void 0 : _a.scriptHandler) && GM.info.scriptHandler === "FireMonkey")
|
|
252
|
+
throw new Error("Intercepting window events is not supported on FireMonkey due to the isolated context the userscript runs in.");
|
|
250
253
|
Error.stackTraceLimit = Math.max(Error.stackTraceLimit, 100);
|
|
251
254
|
if (isNaN(Error.stackTraceLimit))
|
|
252
255
|
Error.stackTraceLimit = 100;
|
|
253
256
|
(function(original) {
|
|
254
257
|
eventObject.__proto__.addEventListener = function(...args) {
|
|
255
|
-
var
|
|
256
|
-
const origListener = typeof args[1] === "function" ? args[1] : (_b = (
|
|
258
|
+
var _a2, _b;
|
|
259
|
+
const origListener = typeof args[1] === "function" ? args[1] : (_b = (_a2 = args[1]) == null ? void 0 : _a2.handleEvent) != null ? _b : () => void 0;
|
|
257
260
|
args[1] = function(...a) {
|
|
258
261
|
if (args[0] === eventName && predicate(Array.isArray(a) ? a[0] : a))
|
|
259
262
|
return;
|
|
@@ -1271,27 +1274,29 @@ Has: ${checksum}`);
|
|
|
1271
1274
|
});
|
|
1272
1275
|
}
|
|
1273
1276
|
function debounce(func, timeout = 300, edge = "falling") {
|
|
1274
|
-
let
|
|
1277
|
+
let id;
|
|
1275
1278
|
return function(...args) {
|
|
1276
1279
|
if (edge === "rising") {
|
|
1277
|
-
if (!
|
|
1280
|
+
if (!id) {
|
|
1278
1281
|
func.apply(this, args);
|
|
1279
|
-
|
|
1282
|
+
id = setTimeout(() => id = void 0, timeout);
|
|
1280
1283
|
}
|
|
1281
1284
|
} else {
|
|
1282
|
-
clearTimeout(
|
|
1283
|
-
|
|
1285
|
+
clearTimeout(id);
|
|
1286
|
+
id = setTimeout(() => func.apply(this, args), timeout);
|
|
1284
1287
|
}
|
|
1285
1288
|
};
|
|
1286
1289
|
}
|
|
1287
1290
|
function fetchAdvanced(_0) {
|
|
1288
1291
|
return __async(this, arguments, function* (input, options = {}) {
|
|
1292
|
+
var _a;
|
|
1289
1293
|
const { timeout = 1e4 } = options;
|
|
1294
|
+
const { signal, abort } = new AbortController();
|
|
1295
|
+
(_a = options.signal) == null ? void 0 : _a.addEventListener("abort", abort);
|
|
1290
1296
|
let signalOpts = {}, id = void 0;
|
|
1291
1297
|
if (timeout >= 0) {
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
signalOpts = { signal: controller.signal };
|
|
1298
|
+
id = setTimeout(() => abort(), timeout);
|
|
1299
|
+
signalOpts = { signal };
|
|
1295
1300
|
}
|
|
1296
1301
|
try {
|
|
1297
1302
|
const res = yield fetch(input, __spreadValues(__spreadValues({}, options), signalOpts));
|
package/dist/index.js
CHANGED
|
@@ -227,13 +227,16 @@ function openInNewTab(href, background) {
|
|
|
227
227
|
}
|
|
228
228
|
}
|
|
229
229
|
function interceptEvent(eventObject, eventName, predicate = () => true) {
|
|
230
|
+
var _a;
|
|
231
|
+
if ((eventObject === window || eventObject === getUnsafeWindow()) && ((_a = GM == null ? void 0 : GM.info) == null ? void 0 : _a.scriptHandler) && GM.info.scriptHandler === "FireMonkey")
|
|
232
|
+
throw new Error("Intercepting window events is not supported on FireMonkey due to the isolated context the userscript runs in.");
|
|
230
233
|
Error.stackTraceLimit = Math.max(Error.stackTraceLimit, 100);
|
|
231
234
|
if (isNaN(Error.stackTraceLimit))
|
|
232
235
|
Error.stackTraceLimit = 100;
|
|
233
236
|
(function(original) {
|
|
234
237
|
eventObject.__proto__.addEventListener = function(...args) {
|
|
235
|
-
var
|
|
236
|
-
const origListener = typeof args[1] === "function" ? args[1] : (_b = (
|
|
238
|
+
var _a2, _b;
|
|
239
|
+
const origListener = typeof args[1] === "function" ? args[1] : (_b = (_a2 = args[1]) == null ? void 0 : _a2.handleEvent) != null ? _b : () => void 0;
|
|
237
240
|
args[1] = function(...a) {
|
|
238
241
|
if (args[0] === eventName && predicate(Array.isArray(a) ? a[0] : a))
|
|
239
242
|
return;
|
|
@@ -1231,27 +1234,29 @@ function pauseFor(time) {
|
|
|
1231
1234
|
});
|
|
1232
1235
|
}
|
|
1233
1236
|
function debounce(func, timeout = 300, edge = "falling") {
|
|
1234
|
-
let
|
|
1237
|
+
let id;
|
|
1235
1238
|
return function(...args) {
|
|
1236
1239
|
if (edge === "rising") {
|
|
1237
|
-
if (!
|
|
1240
|
+
if (!id) {
|
|
1238
1241
|
func.apply(this, args);
|
|
1239
|
-
|
|
1242
|
+
id = setTimeout(() => id = void 0, timeout);
|
|
1240
1243
|
}
|
|
1241
1244
|
} else {
|
|
1242
|
-
clearTimeout(
|
|
1243
|
-
|
|
1245
|
+
clearTimeout(id);
|
|
1246
|
+
id = setTimeout(() => func.apply(this, args), timeout);
|
|
1244
1247
|
}
|
|
1245
1248
|
};
|
|
1246
1249
|
}
|
|
1247
1250
|
function fetchAdvanced(_0) {
|
|
1248
1251
|
return __async(this, arguments, function* (input, options = {}) {
|
|
1252
|
+
var _a;
|
|
1249
1253
|
const { timeout = 1e4 } = options;
|
|
1254
|
+
const { signal, abort } = new AbortController();
|
|
1255
|
+
(_a = options.signal) == null ? void 0 : _a.addEventListener("abort", abort);
|
|
1250
1256
|
let signalOpts = {}, id = void 0;
|
|
1251
1257
|
if (timeout >= 0) {
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
signalOpts = { signal: controller.signal };
|
|
1258
|
+
id = setTimeout(() => abort(), timeout);
|
|
1259
|
+
signalOpts = { signal };
|
|
1255
1260
|
}
|
|
1256
1261
|
try {
|
|
1257
1262
|
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.
|
|
@@ -66,7 +67,7 @@ export type DataStoreOptions<TData> = {
|
|
|
66
67
|
} | {
|
|
67
68
|
encodeData?: never;
|
|
68
69
|
decodeData?: never;
|
|
69
|
-
})
|
|
70
|
+
})>;
|
|
70
71
|
/**
|
|
71
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).
|
|
72
73
|
* Supports migrating data from older format 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/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/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.1",
|
|
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",
|