@sv443-network/userutils 9.4.3 → 10.0.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.
@@ -2,12 +2,13 @@
2
2
  * @module lib/Dialog
3
3
  * This module contains the Dialog class, which allows you to quickly and easily create modal dialogs - [see the documentation for more info](https://github.com/Sv443-Network/UserUtils/blob/main/docs.md#dialog)
4
4
  */
5
- import { NanoEmitter } from "./NanoEmitter.js";
5
+ import { NanoEmitter } from "@sv443-network/coreutils";
6
6
  export declare const defaultDialogCss: string;
7
7
  /** ID of the last opened (top-most) dialog */
8
8
  export declare let currentDialogId: string | null;
9
9
  /** IDs of all currently open dialogs, top-most first */
10
10
  export declare const openDialogs: string[];
11
+ /** Default English strings used in the Dialog */
11
12
  export declare const defaultStrings: {
12
13
  closeDialogTooltip: string;
13
14
  };
@@ -0,0 +1,9 @@
1
+ /**
2
+ * @module lib/errors
3
+ * Contains custom error classes
4
+ */
5
+ import { DatedError } from "@sv443-network/coreutils";
6
+ /** Error due to the platform, like using a feature that's not supported by the browser */
7
+ export declare class PlatformError extends DatedError {
8
+ constructor(message: string, options?: ErrorOptions);
9
+ }
@@ -0,0 +1,33 @@
1
+ import { DataStoreEngine, type DataStoreData, type DataStoreEngineDSOptions, type SerializableVal } from "@sv443-network/coreutils";
2
+ /** Options for the {@linkcode GMStorageEngine} class */
3
+ export type GMStorageEngineOptions = {
4
+ /**
5
+ * Specifies the necessary options for storing data.
6
+ * - ⚠️ Only specify this if you are using this instance standalone! The parent DataStore will set this automatically.
7
+ */
8
+ dataStoreOptions?: DataStoreEngineDSOptions<DataStoreData>;
9
+ };
10
+ /**
11
+ * Storage engine for the {@linkcode DataStore} class that uses GreaseMonkey's `GM.getValue` and `GM.setValue` functions.
12
+ *
13
+ * - ⚠️ Requires the grants `GM.getValue`, `GM.setValue`, `GM.deleteValue`, and `GM.listValues` in your userscript metadata.
14
+ * - ⚠️ Don't reuse engine instances, always create a new one for each {@linkcode DataStore} instance.
15
+ */
16
+ export declare class GMStorageEngine<TData extends DataStoreData> extends DataStoreEngine<TData> {
17
+ protected options: GMStorageEngineOptions;
18
+ /**
19
+ * Creates an instance of `GMStorageEngine`.
20
+ *
21
+ * - ⚠️ Requires the grants `GM.getValue`, `GM.setValue`, `GM.deleteValue`, and `GM.listValues` in your userscript metadata.
22
+ * - ⚠️ Don't reuse engine instances, always create a new one for each {@linkcode DataStore} instance.
23
+ */
24
+ constructor(options?: GMStorageEngineOptions);
25
+ /** Fetches a value from persistent storage */
26
+ getValue<TValue extends SerializableVal = string>(name: string, defaultValue: TValue): Promise<string | TValue>;
27
+ /** Sets a value in persistent storage */
28
+ setValue<TValue extends SerializableVal = string>(name: string, value: TValue): Promise<void>;
29
+ /** Deletes a value from persistent storage */
30
+ deleteValue(name: string): Promise<void>;
31
+ /** Deletes all values from GM storage. Use with caution! */
32
+ deleteStorage(): Promise<void>;
33
+ }
@@ -2,15 +2,15 @@
2
2
  * @module lib/Mixins
3
3
  * Allows for defining and applying mixin functions to allow multiple sources to modify a value in a controlled way.
4
4
  */
5
- import type { Prettify } from "./types.js";
5
+ import { type Prettify } from "@sv443-network/coreutils";
6
6
  /** Full mixin object (either sync or async), as it is stored in the instance's mixin array. */
7
7
  export type MixinObj<TArg, TCtx> = Prettify<MixinObjSync<TArg, TCtx> | MixinObjAsync<TArg, TCtx>>;
8
- /** Asynchronous mixin object, as it is stored in the instance's mixin array. */
8
+ /** Synchronous mixin object, as it is stored in the instance's mixin array. */
9
9
  export type MixinObjSync<TArg, TCtx> = Prettify<{
10
10
  /** The mixin function */
11
11
  fn: (arg: TArg, ctx?: TCtx) => TArg;
12
12
  } & MixinObjBase>;
13
- /** Synchronous mixin object, as it is stored in the instance's mixin array. */
13
+ /** Asynchronous mixin object, as it is stored in the instance's mixin array. */
14
14
  export type MixinObjAsync<TArg, TCtx> = Prettify<{
15
15
  /** The mixin function */
16
16
  fn: (arg: TArg, ctx?: TCtx) => TArg | Promise<TArg>;
@@ -29,13 +29,13 @@ export type MixinConfig = {
29
29
  /** If set, the mixin will only be applied if the given signal is not aborted. */
30
30
  signal?: AbortSignal;
31
31
  };
32
- /** Configuration object for the Mixins class */
32
+ /** Configuration object for the {@linkcode Mixins} class */
33
33
  export type MixinsConstructorConfig = {
34
34
  /**
35
35
  * If true, when no priority is specified, an auto-incrementing integer priority will be used, starting at `defaultPriority` or 0 (unique per mixin key). Defaults to false.
36
- * If a priority value is already used, it will be incremented until a unique value is found.
37
- * This is useful to ensure that mixins are applied in the order they were added, even if they don't specify a priority.
38
- * It also allows for a finer level of interjection when the priority is a floating point number.
36
+ * This means that the first mixin added will have the lowest priority of `defaultPriority`, and the last one will have the highest priority and be applied first.
37
+ * If a priority value is already in use, it will be incremented until a unique value is found.
38
+ * A finer level of interjection can be achieved by manually setting the priority to a floating point number, while the auto-incrementing priority will always be an integer.
39
39
  */
40
40
  autoIncrementPriority: boolean;
41
41
  /** The default priority for mixins that do not specify one. Defaults to 0. */
@@ -48,8 +48,8 @@ export type MixinsConstructorConfig = {
48
48
  /**
49
49
  * The mixin class allows for defining and applying mixin functions to allow multiple sources to modify values in a controlled way.
50
50
  * Mixins are identified via their string key and can be added with {@linkcode add()}
51
- * When calling {@linkcode resolve()}, all registered mixin functions with the same key will be applied to the input value in the order of their priority.
52
- * If a mixin has the stopPropagation flag set to true, no further mixins will be applied after it.
51
+ * When calling {@linkcode resolve()}, all registered mixin functions with the same key will be applied to the input value in the order of their priority, or alternatively the order they were added.
52
+ * If a mixin function has its `stopPropagation` flag set to true when being added, no further mixin functions will be applied after it.
53
53
  * @template TMixinMap A map of mixin keys to their respective function signatures. The first argument of the function is the input value, the second argument is an optional context object. If it is defined here, it must be passed as the third argument in {@linkcode resolve()}.
54
54
  * @example ```ts
55
55
  * const ac = new AbortController();
@@ -116,12 +116,15 @@ export declare class Mixins<TMixinMap extends Record<string, (arg: any, ctx?: an
116
116
  /**
117
117
  * Applies all mixins with the given key to the input value, respecting the priority and stopPropagation settings.
118
118
  * If additional context is set in the MixinMap, it will need to be passed as the third argument.
119
- * @returns The modified value after all mixins have been applied.
119
+ * @returns The modified value after all mixins have been applied. The method will return a Promise if at least one of the mixins is async. If all mixins are indicated to be synchronous in TS, but at least one of them turns out to be asynchronous, the return type will be a Promise. With `await`, this will not make a difference, but `.then().catch()` could be affected.
120
120
  */
121
121
  resolve<TKey extends TMixinKey, TArg extends Parameters<TMixinMap[TKey]>[0], TCtx extends Parameters<TMixinMap[TKey]>[1]>(mixinKey: TKey, inputValue: TArg, ...inputCtx: TCtx extends undefined ? [void] : [TCtx]): ReturnType<TMixinMap[TKey]> extends Promise<any> ? ReturnType<TMixinMap[TKey]> : ReturnType<TMixinMap[TKey]>;
122
122
  /** Calculates the priority for a mixin based on the given configuration and the current auto-increment state of the instance */
123
123
  protected calcPriority(mixinKey: TMixinKey, config: Partial<MixinConfig>): number | undefined;
124
- /** Removes all mixins with the given key */
124
+ /**
125
+ * Removes all mixins with the given key.
126
+ * Note: this method is protected to avoid third-party code from removing mixins. If needed, you can extend the Mixins class and expose this method publicly.
127
+ */
125
128
  protected removeAll(mixinKey: TMixinKey): void;
126
129
  }
127
130
  export {};
@@ -2,8 +2,7 @@
2
2
  * @module lib/SelectorObserver
3
3
  * This module contains the SelectorObserver class, allowing you to register listeners that get called whenever the element(s) behind a selector exist in the DOM - [see the documentation for more info](https://github.com/Sv443-Network/UserUtils/blob/main/docs.md#selectorobserver)
4
4
  */
5
- import { type DebouncerType } from "./Debouncer.js";
6
- import type { Prettify } from "./types.js";
5
+ import { type DebouncerType, type Prettify } from "@sv443-network/coreutils";
7
6
  /** Options for the `onSelector()` method of {@linkcode SelectorObserver} */
8
7
  export type SelectorListenerOptions<TElem extends Element = HTMLElement> = Prettify<SelectorOptionsOne<TElem> | SelectorOptionsAll<TElem>>;
9
8
  export type SelectorOptionsOne<TElem extends Element> = SelectorOptionsCommon & {
package/dist/lib/dom.d.ts CHANGED
@@ -32,6 +32,12 @@ export declare function preloadImages(srcUrls: string[], rejects?: boolean): Pro
32
32
  * @param additionalProps Additional properties to set on the anchor element (only applies when `GM.openInTab` is not available)
33
33
  */
34
34
  export declare function openInNewTab(href: string, background?: boolean, additionalProps?: Partial<HTMLAnchorElement>): void;
35
+ /** Add stackTraceLimit to ErrorConstructor */
36
+ declare global {
37
+ interface ErrorConstructor {
38
+ stackTraceLimit: number;
39
+ }
40
+ }
35
41
  /**
36
42
  * Intercepts the specified event on the passed object and prevents it from being called if the called {@linkcode predicate} function returns a truthy value.
37
43
  * If no predicate is specified, all events will be discarded.
@@ -73,7 +79,8 @@ export declare function getSiblingsFrame<TSibling extends Element = HTMLElement>
73
79
  * Uses a [Trusted Types policy](https://developer.mozilla.org/en-US/docs/Web/API/Trusted_Types_API) on Chromium-based browsers to trick the browser into thinking the HTML is safe.
74
80
  * Use this if the page makes use of the CSP directive `require-trusted-types-for 'script'` and throws a "This document requires 'TrustedHTML' assignment" error on Chromium-based browsers.
75
81
  *
76
- * - ⚠️ This function does not perform any sanitization and should thus be used with utmost caution, as it can easily lead to XSS vulnerabilities!
82
+ * - ⚠️ This function does not perform any sanitization and should thus be used with utmost caution, as it can easily lead to XSS vulnerabilities when used with untrusted input!
83
+ * - ⚠️ Only use this function when absolutely necessary, prefer using `element.textContent = "foo"` or other safer alternatives like the [DOMPurify library](https://github.com/cure53/DOMPurify) whenever possible.
77
84
  */
78
85
  export declare function setInnerHtmlUnsafe<TElement extends Element = HTMLElement>(element: TElement, html: string): TElement;
79
86
  /**
@@ -2,19 +2,11 @@
2
2
  * @module UserUtils
3
3
  * UserUtils is a lightweight library with various utilities for userscripts, allowing you to register listeners for when CSS selectors exist, intercept events, create persistent & synchronous data stores, modify the DOM more easily and much more
4
4
  */
5
- export * from "./array.js";
6
- export * from "./colors.js";
7
- export * from "./crypto.js";
8
- export * from "./DataStore.js";
9
- export * from "./DataStoreSerializer.js";
10
- export * from "./Debouncer.js";
5
+ export * from "@sv443-network/coreutils";
11
6
  export * from "./Dialog.js";
12
7
  export * from "./dom.js";
13
- export * from "./errors.js";
14
- export * from "./math.js";
15
- export * from "./misc.js";
8
+ export * from "./Errors.js";
9
+ export * from "./GMStorageEngine.js";
16
10
  export * from "./Mixins.js";
17
- export * from "./NanoEmitter.js";
18
11
  export * from "./SelectorObserver.js";
19
12
  export * from "./translation.js";
20
- export * from "./types.js";
@@ -2,7 +2,7 @@
2
2
  * @module lib/translation
3
3
  * This module contains a translation system that supports flat and nested JSON objects and value transformation functions - [see the documentation for more info](https://github.com/Sv443-Network/UserUtils/blob/main/docs.md#translation)
4
4
  */
5
- import type { Stringifiable } from "./types.js";
5
+ import type { Stringifiable } from "@sv443-network/coreutils";
6
6
  /**
7
7
  * Translation object to pass to {@linkcode tr.addTranslations()}
8
8
  * Can be a flat object of identifier keys and the translation text as the value, or an infinitely nestable object containing the same.
package/package.json CHANGED
@@ -1,24 +1,19 @@
1
1
  {
2
2
  "name": "@sv443-network/userutils",
3
3
  "libName": "UserUtils",
4
- "version": "9.4.3",
4
+ "version": "10.0.0",
5
5
  "description": "General purpose DOM/GreaseMonkey library that allows you to register listeners for when CSS selectors exist, intercept events, create persistent & synchronous data stores, modify the DOM more easily and much more",
6
- "main": "dist/index.js",
7
- "module": "dist/index.js",
6
+ "main": "dist/UserUtils.mjs",
7
+ "module": "dist/UserUtils.mjs",
8
8
  "types": "dist/lib/index.d.ts",
9
9
  "exports": {
10
10
  ".": {
11
- "browser": "./dist/index.global.js",
11
+ "browser": "./dist/UserUtils.umd.js",
12
12
  "types": "./dist/lib/index.d.ts",
13
- "require": "./dist/index.cjs",
14
- "import": "./dist/index.js"
13
+ "require": "./dist/UserUtils.cjs",
14
+ "import": "./dist/UserUtils.mjs"
15
15
  }
16
16
  },
17
- "engines": {
18
- "pnpm": ">=9",
19
- "npm": "please-use-pnpm",
20
- "yarn": "please-use-pnpm"
21
- },
22
17
  "type": "module",
23
18
  "repository": {
24
19
  "type": "git",
@@ -38,63 +33,61 @@
38
33
  },
39
34
  "homepage": "https://github.com/Sv443-Network/UserUtils",
40
35
  "dependencies": {
41
- "nanoevents": "^9.1.0"
36
+ "@sv443-network/coreutils": "3.0.1",
37
+ "nanoevents": "9.1.0"
42
38
  },
43
39
  "devDependencies": {
44
- "@changesets/cli": "^2.27.11",
45
- "@eslint/eslintrc": "^3.2.0",
46
- "@eslint/js": "^9.23.0",
47
- "@testing-library/dom": "^10.4.0",
48
- "@types/express": "^4.17.21",
49
- "@types/greasemonkey": "^4.0.7",
50
- "@types/node": "^22.10.5",
51
- "@types/tx2": "^1.0.3",
52
- "@typescript-eslint/eslint-plugin": "^8.21.0",
53
- "@typescript-eslint/parser": "^8.21.0",
54
- "@typescript-eslint/utils": "^8.21.0",
55
- "@vitest/coverage-v8": "^3.0.9",
56
- "concurrently": "^8.2.2",
57
- "eslint": "^9.18.0",
58
- "express": "^4.21.2",
59
- "globals": "^15.14.0",
60
- "jsdom": "^26.0.0",
61
- "kleur": "^4.1.5",
62
- "tslib": "^2.8.1",
63
- "tsup": "^8.3.5",
64
- "tsx": "^4.19.2",
65
- "typescript": "^5.7.3",
66
- "vitest": "^3.0.9"
40
+ "@changesets/cli": "2.29.8",
41
+ "@eslint/eslintrc": "3.3.3",
42
+ "@eslint/js": "9.39.2",
43
+ "@swc/core": "1.15.11",
44
+ "@testing-library/dom": "10.4.1",
45
+ "@types/express": "4.17.25",
46
+ "@types/greasemonkey": "4.0.7",
47
+ "@types/node": "22.19.9",
48
+ "@types/tx2": "1.0.3",
49
+ "@typescript-eslint/eslint-plugin": "8.54.0",
50
+ "@typescript-eslint/parser": "8.54.0",
51
+ "@typescript-eslint/utils": "8.54.0",
52
+ "@vitest/coverage-v8": "3.2.4",
53
+ "concurrently": "8.2.2",
54
+ "eslint": "9.39.2",
55
+ "express": "4.22.1",
56
+ "globals": "15.15.0",
57
+ "jsdom": "26.1.0",
58
+ "kleur": "4.1.5",
59
+ "tslib": "2.8.1",
60
+ "tsup": "8.5.1",
61
+ "tsx": "4.21.0",
62
+ "typescript": "5.9.3",
63
+ "vitest": "3.2.4"
67
64
  },
68
65
  "files": [
69
- "/dist/index.js",
70
- "/dist/index.cjs",
71
- "/dist/index.mjs",
72
- "/dist/index.global.js",
73
- "/dist/index.umd.js",
66
+ "/dist/UserUtils.mjs",
67
+ "/dist/UserUtils.cjs",
68
+ "/dist/UserUtils.umd.js",
74
69
  "/dist/lib/**.d.ts",
75
70
  "/package.json",
76
71
  "/README.md",
77
72
  "/CHANGELOG.md",
78
73
  "/LICENSE.txt"
79
74
  ],
75
+ "publishConfig": {
76
+ "provenance": true
77
+ },
80
78
  "scripts": {
81
79
  "lint": "eslint . && tsc --noEmit",
82
- "build-types": "tsc --emitDeclarationOnly --declaration --outDir dist && node --import tsx ./tools/fix-dts.mts",
83
- "build-common": "tsup lib/index.ts --format cjs,esm --clean --treeshake",
84
- "build-all": "tsup lib/index.ts --format cjs,esm,iife --treeshake --onSuccess \"pnpm build-types && pnpm post-build-global\"",
85
- "build": "pnpm build-common -- && pnpm build-types",
86
- "post-build-global": "node --import tsx ./tools/post-build-global.mts",
87
- "dev": "pnpm build-common -- --sourcemap --watch --onSuccess \"pnpm build-types\"",
88
- "dev-all": "pnpm build-all -- --watch",
80
+ "build": "tsup",
81
+ "dev": "tsup --watch",
89
82
  "update-jsr-version": "node --import tsx ./tools/update-jsr-version.mts",
90
83
  "publish-package": "changeset publish",
91
84
  "publish-package-jsr": "pnpm update-jsr-version && npx jsr publish --allow-dirty",
92
- "check-jsr": "npx jsr publish --allow-dirty --dry-run",
85
+ "check-jsr": "pnpm update-jsr-version && npx jsr publish --allow-dirty --dry-run",
93
86
  "change": "changeset",
94
87
  "test-gm-serve": "node --import tsx ./test/TestPage/server.mts",
95
88
  "test-gm-dev": "cd test/TestScript && pnpm dev",
96
89
  "test-gm": "concurrently \"pnpm test-gm-serve\" \"pnpm test-gm-dev\"",
97
- "test": "vitest --passWithNoTests",
98
- "test-coverage": "vitest --passWithNoTests --coverage"
90
+ "test": "vitest",
91
+ "test-coverage": "vitest --coverage"
99
92
  }
100
93
  }