@ls-stack/utils 3.9.0 → 3.9.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/README.md CHANGED
@@ -1 +1,82 @@
1
- # Generic typescript utils
1
+ # @ls-stack/utils
2
+
3
+ Generic TypeScript utilities for modern JavaScript/TypeScript projects.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @ls-stack/utils
9
+ # or
10
+ pnpm add @ls-stack/utils
11
+ # or
12
+ yarn add @ls-stack/utils
13
+ ```
14
+
15
+ ## Usage
16
+
17
+ Import specific utilities from their modules:
18
+
19
+ ```typescript
20
+ import { createAsyncQueue } from '@ls-stack/utils/asyncQueue';
21
+ import { deepEqual } from '@ls-stack/utils/deepEqual';
22
+ import { debounce } from '@ls-stack/utils/debounce';
23
+ ```
24
+
25
+ ## Available Utilities
26
+
27
+ This package includes a wide range of utilities for:
28
+
29
+ - **Array manipulation** (`arrayUtils`) - sorting, grouping, filtering
30
+ - **Async operations** (`asyncQueue`, `parallelAsyncCalls`, `promiseUtils`) - queue management and promise utilities
31
+ - **Type assertions** (`assertions`) - runtime type checking
32
+ - **Caching** (`cache`) - efficient caching with TTL support
33
+ - **Concurrency control** (`concurrentCalls`, `createThrottleController`) - rate limiting and throttling
34
+ - **Object utilities** (`objUtils`) - deep operations on objects
35
+ - **String utilities** (`stringUtils`) - string manipulation and formatting
36
+ - **Math utilities** (`mathUtils`) - mathematical operations and calculations
37
+ - **And many more...**
38
+
39
+ ## Documentation
40
+
41
+ Comprehensive API documentation is available in the [`docs/`](docs/) folder. Start with the [modules overview](docs/modules.md) to explore all available utilities.
42
+
43
+ ### Generating Documentation
44
+
45
+ To regenerate the documentation after making changes:
46
+
47
+ ```bash
48
+ pnpm docs
49
+ ```
50
+
51
+ For continuous updates during development:
52
+
53
+ ```bash
54
+ pnpm docs:watch
55
+ ```
56
+
57
+ ## Development
58
+
59
+ ```bash
60
+ # Install dependencies
61
+ pnpm install
62
+
63
+ # Run tests
64
+ pnpm test
65
+
66
+ # Run tests with UI
67
+ pnpm test:ui
68
+
69
+ # Build the library
70
+ pnpm build
71
+
72
+ # Lint code
73
+ pnpm lint
74
+ ```
75
+
76
+ ## License
77
+
78
+ MIT
79
+
80
+ ## Repository
81
+
82
+ [github:lucasols/utils](https://github.com/lucasols/utils)
@@ -95,13 +95,15 @@ var AsyncQueue = class {
95
95
  return deferred.promise;
96
96
  }
97
97
  resultifyAdd(fn, options) {
98
- const cb = async (ctx) => {
99
- if (isPromise(fn)) {
100
- return await fn;
101
- }
102
- return fn(ctx);
103
- };
104
- return this.add((ctx) => (0, import_t_result.resultify)(cb(ctx)), options);
98
+ return this.add(
99
+ (ctx) => (0, import_t_result.resultify)(async () => {
100
+ if (isPromise(fn)) {
101
+ return await fn;
102
+ }
103
+ return fn(ctx);
104
+ }),
105
+ options
106
+ );
105
107
  }
106
108
  async #processQueue() {
107
109
  if (this.#pending >= this.#concurrency || this.#queue.length === 0) {
@@ -125,20 +127,20 @@ var AsyncQueue = class {
125
127
  }
126
128
  const signal = signals.length > 1 ? AbortSignal.any(signals) : signals[0];
127
129
  let abortListener;
128
- const signalAbortPromise = new Promise((_, reject) => {
129
- if (signal) {
130
+ try {
131
+ if (signal?.aborted) {
130
132
  const error = signal.reason instanceof Error ? signal.reason : new DOMException("Aborted", "AbortError");
131
- if (signal.aborted) {
132
- reject(error);
133
- return;
134
- }
135
- abortListener = () => {
136
- reject(error);
137
- };
138
- signal.addEventListener("abort", abortListener, { once: true });
133
+ throw error;
139
134
  }
140
- });
141
- try {
135
+ const signalAbortPromise = new Promise((_, reject) => {
136
+ if (signal) {
137
+ const error = signal.reason instanceof Error ? signal.reason : new DOMException("Aborted", "AbortError");
138
+ abortListener = () => {
139
+ reject(error);
140
+ };
141
+ signal.addEventListener("abort", abortListener, { once: true });
142
+ }
143
+ });
142
144
  const taskRunPromise = task.run({ signal, id: task.id });
143
145
  this.events.emit("start", { id: task.id });
144
146
  const result = await Promise.race([taskRunPromise, signalAbortPromise]);
@@ -157,7 +159,7 @@ var AsyncQueue = class {
157
159
  this.#failed++;
158
160
  this.events.emit("error", {
159
161
  id: task.id,
160
- error: (0, import_t_result.unknownToError)(error)
162
+ error
161
163
  });
162
164
  }
163
165
  } catch (error) {
@@ -50,7 +50,7 @@ declare class AsyncQueueWithId<T, I, E extends ResultValidErrors = Error> extend
50
50
  add(fn: ((ctx: RunCtx<I>) => Promise<Result<T, E>> | Result<T, E>) | Promise<Result<T, E>>, options?: AddOptionsWithId<I>): Promise<Result<T, E | Error>>;
51
51
  resultifyAdd(fn: ((ctx: RunCtx<I>) => Promise<T> | T) | Promise<T>, options?: AddOptionsWithId<I>): Promise<Result<T, E | Error>>;
52
52
  }
53
- declare function createAsyncQueue<T, E extends ResultValidErrors = Error>(options?: AsyncQueueOptions): AsyncQueue<T, E, undefined>;
53
+ declare function createAsyncQueue<T, E extends ResultValidErrors = Error>(options?: AsyncQueueOptions): AsyncQueue<T, E>;
54
54
  declare function createAsyncQueueWithId<T, I, E extends ResultValidErrors = Error>(options?: AsyncQueueOptions): AsyncQueueWithId<T, I, E>;
55
55
 
56
56
  export { createAsyncQueue, createAsyncQueueWithId };
@@ -50,7 +50,7 @@ declare class AsyncQueueWithId<T, I, E extends ResultValidErrors = Error> extend
50
50
  add(fn: ((ctx: RunCtx<I>) => Promise<Result<T, E>> | Result<T, E>) | Promise<Result<T, E>>, options?: AddOptionsWithId<I>): Promise<Result<T, E | Error>>;
51
51
  resultifyAdd(fn: ((ctx: RunCtx<I>) => Promise<T> | T) | Promise<T>, options?: AddOptionsWithId<I>): Promise<Result<T, E | Error>>;
52
52
  }
53
- declare function createAsyncQueue<T, E extends ResultValidErrors = Error>(options?: AsyncQueueOptions): AsyncQueue<T, E, undefined>;
53
+ declare function createAsyncQueue<T, E extends ResultValidErrors = Error>(options?: AsyncQueueOptions): AsyncQueue<T, E>;
54
54
  declare function createAsyncQueueWithId<T, I, E extends ResultValidErrors = Error>(options?: AsyncQueueOptions): AsyncQueueWithId<T, I, E>;
55
55
 
56
56
  export { createAsyncQueue, createAsyncQueueWithId };
package/lib/asyncQueue.js CHANGED
@@ -58,13 +58,15 @@ var AsyncQueue = class {
58
58
  return deferred.promise;
59
59
  }
60
60
  resultifyAdd(fn, options) {
61
- const cb = async (ctx) => {
62
- if (isPromise(fn)) {
63
- return await fn;
64
- }
65
- return fn(ctx);
66
- };
67
- return this.add((ctx) => resultify(cb(ctx)), options);
61
+ return this.add(
62
+ (ctx) => resultify(async () => {
63
+ if (isPromise(fn)) {
64
+ return await fn;
65
+ }
66
+ return fn(ctx);
67
+ }),
68
+ options
69
+ );
68
70
  }
69
71
  async #processQueue() {
70
72
  if (this.#pending >= this.#concurrency || this.#queue.length === 0) {
@@ -88,20 +90,20 @@ var AsyncQueue = class {
88
90
  }
89
91
  const signal = signals.length > 1 ? AbortSignal.any(signals) : signals[0];
90
92
  let abortListener;
91
- const signalAbortPromise = new Promise((_, reject) => {
92
- if (signal) {
93
+ try {
94
+ if (signal?.aborted) {
93
95
  const error = signal.reason instanceof Error ? signal.reason : new DOMException("Aborted", "AbortError");
94
- if (signal.aborted) {
95
- reject(error);
96
- return;
97
- }
98
- abortListener = () => {
99
- reject(error);
100
- };
101
- signal.addEventListener("abort", abortListener, { once: true });
96
+ throw error;
102
97
  }
103
- });
104
- try {
98
+ const signalAbortPromise = new Promise((_, reject) => {
99
+ if (signal) {
100
+ const error = signal.reason instanceof Error ? signal.reason : new DOMException("Aborted", "AbortError");
101
+ abortListener = () => {
102
+ reject(error);
103
+ };
104
+ signal.addEventListener("abort", abortListener, { once: true });
105
+ }
106
+ });
105
107
  const taskRunPromise = task.run({ signal, id: task.id });
106
108
  this.events.emit("start", { id: task.id });
107
109
  const result = await Promise.race([taskRunPromise, signalAbortPromise]);
@@ -120,7 +122,7 @@ var AsyncQueue = class {
120
122
  this.#failed++;
121
123
  this.events.emit("error", {
122
124
  id: task.id,
123
- error: unknownToError(error)
125
+ error
124
126
  });
125
127
  }
126
128
  } catch (error) {
@@ -288,7 +288,7 @@ var ConcurrentCallsWithMetadata = class {
288
288
  `${failedProcessing.length}/${total} calls failed: ${truncateArray(
289
289
  failedProcessing.map((f) => truncateString(f.error.message, 20)),
290
290
  5,
291
- (count) => `+${count} more`
291
+ "..."
292
292
  ).join("; ")}`
293
293
  ) : null;
294
294
  return {
@@ -235,7 +235,7 @@ var ConcurrentCallsWithMetadata = class {
235
235
  `${failedProcessing.length}/${total} calls failed: ${truncateArray(
236
236
  failedProcessing.map((f) => truncateString(f.error.message, 20)),
237
237
  5,
238
- (count) => `+${count} more`
238
+ "..."
239
239
  ).join("; ")}`
240
240
  ) : null;
241
241
  return {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ls-stack/utils",
3
3
  "description": "Typescript utils",
4
- "version": "3.9.0",
4
+ "version": "3.9.1",
5
5
  "license": "MIT",
6
6
  "files": [
7
7
  "lib"
@@ -179,6 +179,9 @@
179
179
  "prettier-plugin-organize-imports": "^4.1.0",
180
180
  "tsm": "^2.3.0",
181
181
  "tsup": "^8.3.5",
182
+ "typedoc": "^0.28.4",
183
+ "typedoc-plugin-markdown": "^4.6.3",
184
+ "typedoc-plugin-missing-exports": "^4.0.0",
182
185
  "typescript": "^5.7.3",
183
186
  "typescript-eslint": "^8.21.0",
184
187
  "vite": "^6.0.11",
@@ -195,12 +198,14 @@
195
198
  "tsc": "tsc -p tsconfig.prod.json",
196
199
  "tsc:watch": "tsc -p tsconfig.prod.json --watch",
197
200
  "eslint": "CI=true eslint src/ scripts/ --color --max-warnings=0",
198
- "build": "pnpm test && pnpm lint && pnpm build:no-test && pnpm build:update-exports",
201
+ "build": "pnpm test && pnpm lint && pnpm build:no-test && pnpm docs && pnpm build:update-exports",
199
202
  "build:no-test": "tsup",
200
203
  "build:update-exports": "tsm --no-warnings scripts/updatePackageExports.ts",
201
204
  "build-test": "tsup --config tsup.test.config.ts",
202
205
  "pre-publish": "./scripts/check-if-is-sync.sh && pnpm build",
203
206
  "test:console-fmt": "tsm --no-warnings scripts/testConsoleFmt.ts",
204
- "bench:deepEqual": "tsm --no-warnings benchmarks/deepEqual.ts"
207
+ "bench:deepEqual": "tsm --no-warnings benchmarks/deepEqual.ts",
208
+ "docs": "typedoc",
209
+ "docs:watch": "typedoc --watch"
205
210
  }
206
211
  }