@sv443-network/coreutils 3.3.0 → 3.5.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.
@@ -106,7 +106,8 @@ export type DataStoreOptions<TData extends DataStoreData, TMemCache extends bool
106
106
  /**
107
107
  * Generic type that represents the serializable data structure saved in a {@linkcode DataStore} instance.
108
108
  * - ⚠️ Uses `object` instead of an index signature so that interfaces without an explicit index signature can be used as `TData`.
109
- * Make sure to only use JSON-serializable types here, otherwise unexpected behavior may occur!
109
+ * However, this also means that the type system won't prevent you from using non-serializable data structures like functions or symbols in the data, which will cause errors at runtime.
110
+ * Make sure to only use types that are compatible with `JSON.stringify()`, and use `null` instead of `undefined` when you need to preserve the key of an empty value.
110
111
  */
111
112
  export type DataStoreData = object;
112
113
  /** Map of event names and their corresponding listener function signatures for the {@linkcode DataStore} class. */
@@ -142,7 +143,6 @@ export type DataStoreEventMap<TData> = {
142
143
  * - ⚠️ Make sure to call {@linkcode loadData()} at least once after creating an instance, or the returned data will be the same as `options.defaultData`
143
144
  *
144
145
  * @template TData The type of the data that is saved in persistent storage for the currently set format version
145
- * (TODO:FIXME: will be automatically inferred from `defaultData` if not provided)
146
146
  */
147
147
  export declare class DataStore<TData extends DataStoreData, TMemCache extends boolean = true> extends NanoEmitter<DataStoreEventMap<TData>> {
148
148
  readonly id: string;
@@ -2,7 +2,7 @@
2
2
  * @module DataStoreSerializer
3
3
  * This module contains the DataStoreSerializer class, which allows you to import and export serialized DataStore data - [see the documentation for more info](https://github.com/Sv443-Network/UserUtils/blob/main/docs.md#datastoreserializer)
4
4
  */
5
- import type { DataStore, DataStoreData } from "./DataStore.ts";
5
+ import type { DataStore } from "./DataStore.ts";
6
6
  /** Options for the DataStoreSerializer class */
7
7
  export type DataStoreSerializerOptions = {
8
8
  /** Whether to add a checksum to the exported data. Defaults to `true` */
@@ -35,7 +35,8 @@ export type LoadStoresDataResult = {
35
35
  /** Filter for selecting data stores */
36
36
  export type StoreFilter = string[] | ((id: string) => boolean);
37
37
  /**
38
- * Allows for easy serialization and deserialization of multiple DataStore instances.
38
+ * Allows for easy serialization and deserialization of multiple {@linkcode DataStore} instances.
39
+ * Offers methods to only serialize or deserialize a subset of the stores, and to ensure the integrity of the data by adding checksums.
39
40
  *
40
41
  * 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.
41
42
  * Remember that you can call `super.methodName()` in the subclass to access the original method.
@@ -43,10 +44,13 @@ export type StoreFilter = string[] | ((id: string) => boolean);
43
44
  * - ⚠️ Needs to run in a secure context (HTTPS) due to the use of the SubtleCrypto API if checksumming is enabled.
44
45
  */
45
46
  export declare class DataStoreSerializer {
46
- protected stores: DataStore<DataStoreData, boolean>[];
47
+ protected stores: DataStore<any, boolean>[];
47
48
  protected options: Required<DataStoreSerializerOptions>;
48
- constructor(stores: DataStore<DataStoreData, boolean>[], options?: DataStoreSerializerOptions);
49
- /** Calculates the checksum of a string */
49
+ constructor(stores: DataStore<any, boolean>[], options?: DataStoreSerializerOptions);
50
+ /**
51
+ * Calculates the checksum of a string. Uses {@linkcode computeHash()} with SHA-256 and digests as a hex string by default.
52
+ * Override this in a subclass if a custom checksum method is needed.
53
+ */
50
54
  protected calcChecksum(input: string): Promise<string>;
51
55
  /**
52
56
  * Serializes only a subset of the data stores into a string.
@@ -114,5 +118,5 @@ export declare class DataStoreSerializer {
114
118
  /** Checks if a given value is a SerializedDataStore object */
115
119
  static isSerializedDataStoreObj(obj: unknown): obj is SerializedDataStore;
116
120
  /** Returns the DataStore instances whose IDs match the provided array or function */
117
- protected getStoresFiltered(stores?: StoreFilter): DataStore<DataStoreData, boolean>[];
121
+ protected getStoresFiltered(stores?: StoreFilter): DataStore<any, boolean>[];
118
122
  }
@@ -2,7 +2,7 @@
2
2
  * @module Debouncer
3
3
  * This module contains the Debouncer class and debounce function that allow you to reduce the amount of calls in rapidly firing event listeners and such - [see the documentation for more info](https://github.com/Sv443-Network/UserUtils/blob/main/docs.md#debouncer)
4
4
  */
5
- import { NanoEmitter } from "./NanoEmitter.ts";
5
+ import { NanoEmitter, type NanoEmitterOptions } from "./NanoEmitter.ts";
6
6
  /**
7
7
  * The type of edge to use for the debouncer - [see the docs for a diagram and explanation.](https://github.com/Sv443-Network/UserUtils/blob/main/docs.md#debouncer)
8
8
  * - `immediate` - (default & recommended) - calls the listeners at the very first call ("rising" edge) and queues the latest call until the timeout expires
@@ -53,7 +53,7 @@ export declare class Debouncer<TFunc extends AnyFn> extends NanoEmitter<Debounce
53
53
  * @param timeout Timeout in milliseconds between letting through calls - defaults to 200
54
54
  * @param type The edge type to use for the debouncer - see {@linkcode DebouncerType} for details or [the documentation for an explanation and diagram](https://github.com/Sv443-Network/UserUtils/blob/main/docs.md#debouncer) - defaults to "immediate"
55
55
  */
56
- constructor(timeout?: number, type?: DebouncerType);
56
+ constructor(timeout?: number, type?: DebouncerType, nanoEmitterOptions?: NanoEmitterOptions);
57
57
  /** Adds a listener function that will be called on timeout */
58
58
  addListener(fn: TFunc): void;
59
59
  /** Removes the listener with the specified function reference */
@@ -82,5 +82,5 @@ export declare class Debouncer<TFunc extends AnyFn> extends NanoEmitter<Debounce
82
82
  *
83
83
  * Refer to the {@linkcode Debouncer} class definition or the [Debouncer documentation](https://github.com/Sv443-Network/UserUtils/blob/main/docs.md#debouncer) for more information.
84
84
  */
85
- export declare function debounce<TFunc extends (...args: any[]) => any>(fn: TFunc, timeout?: number, type?: DebouncerType): DebouncedFunction<TFunc>;
85
+ export declare function debounce<TFunc extends (...args: any[]) => any>(fn: TFunc, timeout?: number, type?: DebouncerType, nanoEmitterOptions?: NanoEmitterOptions): DebouncedFunction<TFunc>;
86
86
  export {};
@@ -77,3 +77,39 @@ export declare function scheduleExit(code?: number, timeout?: number): void;
77
77
  * @param lines The number of lines to return from the stack. Defaults to Infinity (all of them).
78
78
  */
79
79
  export declare function getCallStack<TAsArray extends boolean = true>(asArray?: TAsArray, lines?: number): TAsArray extends true ? string[] : string;
80
+ /** Options object for {@linkcode createRecurringTask()} */
81
+ export type RecurringTaskOptions<TVal extends void | unknown> = {
82
+ /** Timeout between running the task, in milliseconds. For async tasks and conditions, the timeout will be added onto the execution time of the Promises. */
83
+ timeout: number;
84
+ /**
85
+ * The task to run. Can return a value or a Promise that resolves to a value of any type, which will be passed to the optional callback once the task is finished.
86
+ * Gets passed the current iteration (starting at 0) as an argument. If no `condition` is given, the task will run indefinitely, or until aborted via the `signal`, `abortOnError` or `maxIterations` options.
87
+ */
88
+ task: (iteration: number) => TVal | Promise<TVal>;
89
+ /**
90
+ * Condition that needs to return true in order to run the task. If not given, the task will run indefinitely with the given timeout.
91
+ * Gets passed the current iteration (starting at 0) as an argument. A failing condition will still increment the iterations.
92
+ */
93
+ condition?: (iteration: number) => boolean | Promise<boolean>;
94
+ /** Gets called with the task's return value and iteration number every time it's finished. Can be an async function if asynchronous operations are needed in the callback. */
95
+ onSuccess?: (value: TVal, iteration: number) => void | Promise<void>;
96
+ /** Gets called with the error if the `task`, `condition` or `onSuccess` functions throw an error or return a rejected Promise. Can be an async function if asynchronous operations are needed in the callback. */
97
+ onError?: (error: unknown, iteration: number) => void | Promise<void>;
98
+ /**
99
+ * If true, the recurring task will stop if the condition or task functions throw an error or return a rejected Promise. Defaults to false.
100
+ * - ⚠️ If neither `onError` nor `abortOnError` are set, errors will be re-thrown, which could potentially crash the process if not handled by the caller.
101
+ */
102
+ abortOnError?: boolean;
103
+ /** Max number of times to run the task. If not given, will run indefinitely as long as the condition is true. */
104
+ maxIterations?: number;
105
+ /** Optional AbortSignal to cancel the task. */
106
+ signal?: AbortSignal;
107
+ /** Whether to run the task immediately on the first call or wait for the first timeout to pass. Defaults to true. */
108
+ immediate?: boolean;
109
+ };
110
+ /**
111
+ * Schedules a task to run immediately and repeatedly at the given timeout as long as the given condition returns true.
112
+ * Ensures no overlapping task executions and multiple ways to cleanly stop the repeated execution.
113
+ * @returns A promise that resolves once the task is stopped, either by the condition returning false, reaching the max iterations, or the signal being aborted.
114
+ */
115
+ export declare function createRecurringTask<TVal extends void | unknown>(options: RecurringTaskOptions<TVal>): Promise<void>;
@@ -39,3 +39,68 @@ export declare function joinArrayReadable(array: unknown[], separators?: string,
39
39
  export declare function secsToTimeStr(seconds: number): string;
40
40
  /** Truncates a string if it exceeds `length` and inserts `endStr` at the end (empty string to disable), so that the final string doesn't exceed the given length */
41
41
  export declare function truncStr(input: Stringifiable, length: number, endStr?: string): string;
42
+ /**
43
+ * Border styles for the `lineStyle` option of the {@linkcode createTable} function.
44
+ *
45
+ * | Style | Example |
46
+ * | :-- | :-- |
47
+ * | `single` | `┌──────┬──────┐` |
48
+ * | `double` | `╔══════╦══════╗` |
49
+ * | `none` | |
50
+ */
51
+ export type TableLineStyle = "single" | "double" | "none";
52
+ /**
53
+ * How to align cell content in a column for the `columnAlign` option of the {@linkcode createTable} function.
54
+ *
55
+ * | Alignment | Example | Description |
56
+ * | :-- | :-- | :-- |
57
+ * | `left` | `│.Text....│` | Hugs the left border, with padding determined by `minPadding`. |
58
+ * | `centerLeft` | `│..Text...│` | In the center, but if the padding is uneven, favors the left side. |
59
+ * | `centerRight` | `│...Text..│` | In the center, but if the padding is uneven, favors the right side. |
60
+ * | `right` | `│....Text.│` | Hugs the right border, with padding determined by `minPadding`. |
61
+ */
62
+ export type TableColumnAlign = "left" | "centerLeft" | "centerRight" | "right";
63
+ /** Options for the {@linkcode createTable} function. */
64
+ export type TableOptions = {
65
+ /** Alignment for each column, either a single value to apply to all columns or an array of values for each column. Defaults to `left`. */
66
+ columnAlign?: TableColumnAlign | TableColumnAlign[];
67
+ /** If set, cell content that exceeds this width will be truncated with the value of `truncEndStr` (defaults to `…`) so that the final cell content doesn't exceed this width. */
68
+ truncateAbove?: number;
69
+ /** The string to append to truncated cell content if `truncateAbove` is set. Defaults to `…`. */
70
+ truncEndStr?: string;
71
+ /** Minimum padding to add to the left and right of cell content, regardless of alignment settings. Defaults to 1, set to 0 to disable. */
72
+ minPadding?: number;
73
+ /** Which kind of line characters to use for the border of the table. Defaults to `single` (`┌──────┬──────┐`). */
74
+ lineStyle?: TableLineStyle;
75
+ /** Can be used to change the characters used for the lines dividing cells in the table. If not set, {@linkcode defaultTableLineCharset} will be used. */
76
+ lineCharset?: TableLineCharset;
77
+ /**
78
+ * Can be used to add custom values like ANSI color codes to the lines dividing cells.
79
+ * Function gets passed the row index (i) and column index (j) of the character being rendered.
80
+ * Note that each row renders three rows of characters, so the row index (i) is not the same as the index of the row in the input array, but can be used to determine it with `Math.floor(i / 3)`.
81
+ * The first value of the returned tuple will be added before the line character and the second value will be added after.
82
+ * Return an empty array to not apply any custom styling.
83
+ */
84
+ applyLineStyle?: (i: number, j: number) => [before?: string, after?: string] | void;
85
+ /**
86
+ * Can be used to add custom values like ANSI color codes to the cell content.
87
+ * Function gets passed the row index (i) and column index (j) of the cell being rendered.
88
+ * Note: cell width is calculated before applying this style, so characters with non-zero width will mess up the alignment and border placement.
89
+ * The first value of the returned tuple will be added before the cell content and the second value will be added after.
90
+ * Return an empty array to not apply any custom styling.
91
+ */
92
+ applyCellStyle?: (i: number, j: number) => [before?: string, after?: string] | void;
93
+ };
94
+ /** Characters to use for the lines dividing cells in the table generated by {@linkcode createTable}, based on the `lineStyle` option. */
95
+ export type TableLineStyleChars = Record<"horizontal" | "vertical" | `${"top" | "bottom"}${"Left" | "Right"}` | `${"left" | "right" | "top" | "bottom"}T` | "cross", string>;
96
+ /** The characters to use for the lines dividing cells in the table generated by {@linkcode createTable}, based on the `lineStyle` option. */
97
+ export type TableLineCharset = Record<TableLineStyle, TableLineStyleChars>;
98
+ /** The default characters to use for the lines dividing cells in the table generated by {@linkcode createTable}, based on the `lineStyle` option. */
99
+ export declare const defaultTableLineCharset: TableLineCharset;
100
+ /**
101
+ * Creates an ASCII table string from the given rows and options.
102
+ * Supports `\x1b` ANSI color codes in cell content: they are ignored for width calculation, included in the final output, and handled correctly during truncation (escape sequences are never split; any open color code is closed with a reset).
103
+ * @param rows Array of tuples, where each tuple represents a row and its values. The first tuple is used to determine the column count.
104
+ * @param options Object with options for customizing the table output, such as column alignment, truncation, padding and line styles.
105
+ */
106
+ export declare function createTable<TRow extends [...Stringifiable[]]>(rows: TRow[], options?: TableOptions): string;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@sv443-network/coreutils",
3
3
  "libName": "@sv443-network/coreutils",
4
- "version": "3.3.0",
4
+ "version": "3.5.0",
5
5
  "description": "Cross-platform, general-purpose, JavaScript core library for Node, Deno and the browser. Intended to be used in conjunction with `@sv443-network/userutils` and `@sv443-network/djsutils`, but can be used independently as well.",
6
6
  "main": "dist/CoreUtils.cjs",
7
7
  "module": "dist/CoreUtils.mjs",
@@ -38,30 +38,30 @@
38
38
  },
39
39
  "homepage": "https://github.com/Sv443-Network/CoreUtils",
40
40
  "dependencies": {
41
- "nanoevents": "^9.1.0"
41
+ "nanoevents": "9.1.0"
42
42
  },
43
43
  "devDependencies": {
44
- "@changesets/cli": "^2.29.8",
45
- "@eslint/eslintrc": "^3.3.3",
46
- "@eslint/js": "^9.39.2",
47
- "@swc/core": "^1.15.11",
48
- "@testing-library/dom": "^10.4.1",
49
- "@types/deno": "^2.5.0",
50
- "@types/node": "^22.19.11",
51
- "@types/tx2": "^1.0.3",
52
- "@typescript-eslint/eslint-plugin": "^8.56.0",
53
- "@typescript-eslint/parser": "^8.56.0",
54
- "@typescript-eslint/utils": "^8.56.0",
55
- "@vitest/coverage-v8": "^3.2.4",
56
- "esbuild-plugin-umd-wrapper": "^3.0.0",
57
- "eslint": "^9.39.2",
58
- "globals": "^16.5.0",
59
- "jsdom": "^26.1.0",
60
- "tslib": "^2.8.1",
61
- "tsup": "^8.5.1",
62
- "tsx": "^4.21.0",
63
- "typescript": "^5.9.3",
64
- "vitest": "^3.2.4"
44
+ "@changesets/cli": "2.30.0",
45
+ "@eslint/eslintrc": "3.3.5",
46
+ "@eslint/js": "9.39.4",
47
+ "@swc/core": "1.15.18",
48
+ "@testing-library/dom": "10.4.1",
49
+ "@types/deno": "2.5.0",
50
+ "@types/node": "22.19.15",
51
+ "@types/tx2": "1.0.3",
52
+ "@typescript-eslint/eslint-plugin": "8.56.1",
53
+ "@typescript-eslint/parser": "8.56.1",
54
+ "@typescript-eslint/utils": "8.56.1",
55
+ "@vitest/coverage-v8": "3.2.4",
56
+ "esbuild-plugin-umd-wrapper": "3.0.0",
57
+ "eslint": "9.39.4",
58
+ "globals": "16.5.0",
59
+ "jsdom": "26.1.0",
60
+ "tslib": "2.8.1",
61
+ "tsup": "8.5.1",
62
+ "tsx": "4.21.0",
63
+ "typescript": "5.9.3",
64
+ "vitest": "3.2.4"
65
65
  },
66
66
  "files": [
67
67
  "/dist/CoreUtils.cjs",