@sv443-network/userutils 6.2.0 → 7.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.
@@ -0,0 +1,44 @@
1
+ import { type DataStore } from "./index.js";
2
+ export type DataStoreSerializerOptions = {
3
+ /** Whether to add a checksum to the exported data */
4
+ addChecksum?: boolean;
5
+ /** Whether to ensure the integrity of the data when importing it (unless the checksum property doesn't exist) */
6
+ ensureIntegrity?: boolean;
7
+ };
8
+ /** Serialized data of a DataStore instance */
9
+ export type SerializedDataStore = {
10
+ /** The ID of the DataStore instance */
11
+ id: string;
12
+ /** The serialized data */
13
+ data: string;
14
+ /** The format version of the data */
15
+ formatVersion: number;
16
+ /** Whether the data is encoded */
17
+ encoded: boolean;
18
+ /** The checksum of the data - key is not present for data without a checksum */
19
+ checksum?: string;
20
+ };
21
+ /**
22
+ * Allows for easy serialization and deserialization of multiple DataStore instances.
23
+ *
24
+ * 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.
25
+ * Remember that you can call `super.methodName()` in the subclass to access the original method.
26
+ *
27
+ * ⚠️ Needs to run in a secure context (HTTPS) due to the use of the SubtleCrypto API if checksumming is enabled.
28
+ */
29
+ export declare class DataStoreSerializer {
30
+ protected stores: DataStore[];
31
+ protected options: Required<DataStoreSerializerOptions>;
32
+ constructor(stores: DataStore[], options?: DataStoreSerializerOptions);
33
+ /** Calculates the checksum of a string */
34
+ protected calcChecksum(input: string): Promise<string>;
35
+ /** Serializes a DataStore instance */
36
+ protected serializeStore(storeInst: DataStore): Promise<SerializedDataStore>;
37
+ /** Serializes the data stores into a string */
38
+ serialize(): Promise<string>;
39
+ /**
40
+ * Deserializes the data exported via {@linkcode serialize()} and imports it into the DataStore instances.
41
+ * Also triggers the migration process if the data format has changed.
42
+ */
43
+ deserialize(serializedData: string): Promise<void>;
44
+ }
@@ -20,6 +20,7 @@ type SelectorOptionsCommon = {
20
20
  /** Whether to call the function at the very first call ("rising" edge) or the very last call ("falling" edge, default) */
21
21
  debounceEdge?: "rising" | "falling";
22
22
  };
23
+ type UnsubscribeFunction = () => void;
23
24
  export type SelectorObserverOptions = {
24
25
  /** If set, applies this debounce in milliseconds to all listeners that don't have their own debounce set */
25
26
  defaultDebounce?: number;
@@ -32,13 +33,15 @@ export type SelectorObserverOptions = {
32
33
  disableOnNoListeners?: boolean;
33
34
  /** Whether to ensure the observer is enabled when a new listener is added - default is true */
34
35
  enableOnAddListener?: boolean;
36
+ /** 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
+ checkInterval?: number;
35
38
  };
36
39
  export type SelectorObserverConstructorOptions = MutationObserverInit & SelectorObserverOptions;
37
40
  /** Observes the children of the given element for changes */
38
41
  export declare class SelectorObserver {
39
42
  private enabled;
40
43
  private baseElement;
41
- private observer;
44
+ private observer?;
42
45
  private observerOptions;
43
46
  private customOptions;
44
47
  private listenerMap;
@@ -54,9 +57,10 @@ export declare class SelectorObserver {
54
57
  * @param options Fine-tune what triggers the MutationObserver's checking function - `subtree` and `childList` are set to true by default
55
58
  */
56
59
  constructor(baseElement: Element, options?: SelectorObserverConstructorOptions);
57
- private checkAllSelectors;
58
- private checkSelector;
59
- private debounce;
60
+ /** Call to check all selectors in the {@linkcode listenerMap} using {@linkcode checkSelector()} */
61
+ protected checkAllSelectors(): void;
62
+ /** Checks if the element(s) with the given {@linkcode selector} exist in the DOM and calls the respective {@linkcode listeners} accordingly */
63
+ protected checkSelector(selector: string, listeners: SelectorListenerOptions[]): void;
60
64
  /**
61
65
  * Starts observing the children of the base element for changes to the given {@linkcode selector} according to the set {@linkcode options}
62
66
  * @param selector The selector to observe
@@ -65,8 +69,9 @@ export declare class SelectorObserver {
65
69
  * @param [options.all] Whether to use `querySelectorAll()` instead - default is false
66
70
  * @param [options.continuous] Whether to call the listener continuously instead of just once - default is false
67
71
  * @param [options.debounce] Whether to debounce the listener to reduce calls to `querySelector` or `querySelectorAll` - set undefined or <=0 to disable (default)
72
+ * @returns Returns a function that can be called to remove this listener more easily
68
73
  */
69
- addListener<TElem extends Element = HTMLElement>(selector: string, options: SelectorListenerOptions<TElem>): void;
74
+ addListener<TElem extends Element = HTMLElement>(selector: string, options: SelectorListenerOptions<TElem>): UnsubscribeFunction;
70
75
  /** Disables the observation of the child elements */
71
76
  disable(): void;
72
77
  /**
package/dist/lib/dom.d.ts CHANGED
@@ -2,16 +2,11 @@
2
2
  * Returns `unsafeWindow` if the `@grant unsafeWindow` is given, otherwise falls back to the regular `window`
3
3
  */
4
4
  export declare function getUnsafeWindow(): Window;
5
- /**
6
- * Inserts {@linkcode afterElement} as a sibling just after the provided {@linkcode beforeElement}
7
- * @returns Returns the {@linkcode afterElement}
8
- */
9
- export declare function insertAfter(beforeElement: Element, afterElement: Element): Element;
10
5
  /**
11
6
  * Adds a parent container around the provided element
12
7
  * @returns Returns the new parent element
13
8
  */
14
- export declare function addParent(element: Element, newParent: Element): Element;
9
+ export declare function addParent<TElem extends Element, TParentElem extends Element>(element: TElem, newParent: TParentElem): TParentElem;
15
10
  /**
16
11
  * Adds global CSS style in the form of a `<style>` element in the document's `<head>`
17
12
  * This needs to be run after the `DOMContentLoaded` event has fired on the document object (or instantly if `@run-at document-end` is used).
@@ -24,14 +19,14 @@ export declare function addGlobalStyle(style: string): HTMLStyleElement;
24
19
  * @param rejects If set to `true`, the returned PromiseSettledResults will contain rejections for any of the images that failed to load
25
20
  * @returns Returns an array of `PromiseSettledResult` - each resolved result will contain the loaded image element, while each rejected result will contain an `ErrorEvent`
26
21
  */
27
- export declare function preloadImages(srcUrls: string[], rejects?: boolean): Promise<PromiseSettledResult<unknown>[]>;
22
+ export declare function preloadImages(srcUrls: string[], rejects?: boolean): Promise<PromiseSettledResult<HTMLImageElement>[]>;
28
23
  /**
29
- * Creates an invisible anchor with a `_blank` target and clicks it.
30
- * Contrary to `window.open()`, this has a lesser chance to get blocked by the browser's popup blocker and doesn't open the URL as a new window.
31
- *
32
- * This function has to be run in response to a user interaction event, else the browser might reject it.
24
+ * Tries to use `GM.openInTab` to open the given URL in a new tab, otherwise if the grant is not given, creates an invisible anchor element and clicks it.
25
+ * For the fallback to work, this function needs to be run in response to a user interaction event, else the browser might reject it.
26
+ * @param href The URL to open in a new tab
27
+ * @param background If set to `true`, the tab will be opened in the background - set to `undefined` (default) to use the browser's default behavior
33
28
  */
34
- export declare function openInNewTab(href: string): void;
29
+ export declare function openInNewTab(href: string, background?: boolean): void;
35
30
  /**
36
31
  * 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
32
  * If no predicate is specified, all events will be discarded.
@@ -47,10 +42,7 @@ export declare function interceptEvent<TEvtObj extends EventTarget, TPredicateEv
47
42
  */
48
43
  export declare function interceptWindowEvent<TEvtKey extends keyof WindowEventMap>(eventName: TEvtKey, predicate?: (event: WindowEventMap[TEvtKey]) => boolean): void;
49
44
  /** Checks if an element is scrollable in the horizontal and vertical directions */
50
- export declare function isScrollable(element: Element): {
51
- vertical: boolean;
52
- horizontal: boolean;
53
- };
45
+ export declare function isScrollable(element: Element): Record<"vertical" | "horizontal", boolean>;
54
46
  /**
55
47
  * Executes the callback when the passed element's property changes.
56
48
  * Contrary to an element's attributes, properties can usually not be observed with a MutationObserver.
@@ -1,7 +1,9 @@
1
- export * from "./array";
2
- export * from "./DataStore";
3
- export * from "./dom";
4
- export * from "./math";
5
- export * from "./misc";
6
- export * from "./SelectorObserver";
7
- export * from "./translation";
1
+ export * from "./array.js";
2
+ export * from "./DataStore.js";
3
+ export * from "./DataStoreSerializer.js";
4
+ export * from "./dom.js";
5
+ export * from "./math.js";
6
+ export * from "./misc.js";
7
+ export * from "./SelectorObserver.js";
8
+ export * from "./translation.js";
9
+ export * from "./types.js";
@@ -9,11 +9,3 @@ export declare function mapRange(value: number, range1min: number, range1max: nu
9
9
  export declare function randRange(min: number, max: number): number;
10
10
  /** Returns a random number between 0 and {@linkcode max} (inclusive) */
11
11
  export declare function randRange(max: number): number;
12
- /**
13
- * Generates a random ID with the specified length and radix (16 characters and hexadecimal by default)
14
- * Uses [`crypto.getRandomValues()`](https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues) for better cryptographic randomness
15
- * ⚠️ Not suitable for generating encryption keys! Use [`crypto.subtle.generateKey()`](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/generateKey) for that.
16
- * @param length The length of the ID to generate (defaults to 16)
17
- * @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.)
18
- */
19
- export declare function randomId(length?: number, radix?: number): string;
@@ -1,20 +1,4 @@
1
- /** Represents any value that is either a string itself or can be converted to one (implicitly and explicitly) because it has a toString() method */
2
- export type Stringifiable = string | {
3
- toString(): string;
4
- };
5
- /**
6
- * A type that offers autocomplete for the passed union but also allows any arbitrary value of the same type to be passed.
7
- * Supports unions of strings, numbers and objects.
8
- */
9
- export type LooseUnion<TUnion extends string | number | object> = (TUnion) | (TUnion extends string ? (string & {}) : (TUnion extends number ? (number & {}) : (TUnion extends Record<keyof any, unknown> ? (object & {}) : never)));
10
- /**
11
- * A type that allows all strings except for empty ones
12
- * @example
13
- * function foo<T extends string>(bar: NonEmptyString<T>) {
14
- * console.log(bar);
15
- * }
16
- */
17
- export type NonEmptyString<TString extends string> = TString extends "" ? never : TString;
1
+ import type { Stringifiable } from "./types.js";
18
2
  /**
19
3
  * Automatically appends an `s` to the passed {@linkcode word}, if {@linkcode num} is not equal to 1
20
4
  * @param word A word in singular form, to auto-convert to plural
@@ -30,7 +14,8 @@ export declare function pauseFor(time: number): Promise<void>;
30
14
  * @param timeout The time in ms to wait before calling the function
31
15
  * @param edge Whether to call the function at the very first call ("rising" edge) or the very last call ("falling" edge, default)
32
16
  */
33
- export declare function debounce<TFunc extends (...args: TArgs[]) => void, TArgs = any>(func: TFunc, timeout?: number, edge?: "rising" | "falling"): (...args: TArgs[]) => void;
17
+ export declare function debounce<TFunc extends (...args: TArgs[]) => void, // eslint-disable-next-line @typescript-eslint/no-explicit-any
18
+ TArgs = any>(func: TFunc, timeout?: number, edge?: "rising" | "falling"): (...args: TArgs[]) => void;
34
19
  /** Options for the `fetchAdvanced()` function */
35
20
  export type FetchAdvancedOpts = Omit<RequestInit & Partial<{
36
21
  /** Timeout in milliseconds after which the fetch call will be canceled with an AbortController signal */
@@ -53,3 +38,19 @@ export declare function compress(input: string | ArrayBuffer, compressionFormat:
53
38
  export declare function decompress(input: string | ArrayBuffer, compressionFormat: CompressionFormat, outputType?: "string"): Promise<string>;
54
39
  /** Decompresses a previously compressed base64 string or ArrayBuffer, with the format passed by {@linkcode compressionFormat}, converted to an ArrayBuffer */
55
40
  export declare function decompress(input: string | ArrayBuffer, compressionFormat: CompressionFormat, outputType: "arrayBuffer"): Promise<ArrayBuffer>;
41
+ /**
42
+ * Creates a hash / checksum of the given {@linkcode input} string or ArrayBuffer using the specified {@linkcode algorithm} ("SHA-256" by default).
43
+ *
44
+ * ⚠️ Uses the SubtleCrypto API so it needs to run in a secure context (HTTPS).
45
+ * ⚠️ If you use this for cryptography, make sure to use a secure algorithm (under no circumstances use SHA-1) and to [salt](https://en.wikipedia.org/wiki/Salt_(cryptography)) your input data.
46
+ */
47
+ export declare function computeHash(input: string | ArrayBuffer, algorithm?: string): Promise<string>;
48
+ /**
49
+ * Generates a random ID with the specified length and radix (16 characters and hexadecimal by default)
50
+ *
51
+ * ⚠️ 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.
52
+ * @param length The length of the ID to generate (defaults to 16)
53
+ * @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.)
54
+ * @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 MUCH longer to generate)
55
+ */
56
+ export declare function randomId(length?: number, radix?: number, enhancedEntropy?: boolean): string;
@@ -1,4 +1,4 @@
1
- import { Stringifiable } from "./misc";
1
+ import type { Stringifiable } from "./types.js";
2
2
  /**
3
3
  * Returns the translated text for the specified key in the current language set by {@linkcode tr.setLanguage()}
4
4
  * If the key is not found in the previously registered translation, the key itself is returned.
@@ -0,0 +1,17 @@
1
+ /** Represents any value that is either a string itself or can be converted to one (implicitly and explicitly) because it has a toString() method */
2
+ export type Stringifiable = string | {
3
+ toString(): string;
4
+ };
5
+ /**
6
+ * A type that offers autocomplete for the passed union but also allows any arbitrary value of the same type to be passed.
7
+ * Supports unions of strings, numbers and objects.
8
+ */
9
+ export type LooseUnion<TUnion extends string | number | object> = (TUnion) | (TUnion extends string ? (string & {}) : (TUnion extends number ? (number & {}) : (TUnion extends Record<keyof any, unknown> ? (object & {}) : never)));
10
+ /**
11
+ * A type that allows all strings except for empty ones
12
+ * @example
13
+ * function foo<T extends string>(bar: NonEmptyString<T>) {
14
+ * console.log(bar);
15
+ * }
16
+ */
17
+ export type NonEmptyString<TString extends string> = TString extends "" ? never : TString;
package/package.json CHANGED
@@ -1,10 +1,11 @@
1
1
  {
2
2
  "name": "@sv443-network/userutils",
3
3
  "libName": "UserUtils",
4
- "version": "6.2.0",
5
- "description": "Library with various utilities for userscripts - register listeners for when CSS selectors exist, intercept events, manage persistent user configurations, modify the DOM more easily and more",
4
+ "version": "7.0.0",
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.mjs",
8
+ "exports": "./lib/index.ts",
8
9
  "types": "dist/lib/index.d.ts",
9
10
  "scripts": {
10
11
  "lint": "tsc --noEmit && eslint .",