@ls-stack/utils 3.6.0 → 3.8.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,247 @@
1
+ import {
2
+ sleep
3
+ } from "./chunk-5DZT3Z5Z.js";
4
+ import {
5
+ invariant,
6
+ isPromise
7
+ } from "./chunk-3XCS7FVO.js";
8
+
9
+ // src/concurrentCalls.ts
10
+ import { Result, resultify, unknownToError } from "t-result";
11
+ var ConcurrentCalls = class {
12
+ #pendingCalls = [];
13
+ #alreadyRun = false;
14
+ add(...calls) {
15
+ this.#pendingCalls.push(...calls);
16
+ return this;
17
+ }
18
+ resultifyAdd(...calls) {
19
+ const processedCalls = calls.map((call) => {
20
+ if (isPromise(call)) {
21
+ return call.then((value) => Result.ok(value)).catch((err) => Result.err(unknownToError(err)));
22
+ } else {
23
+ const originalFn = call;
24
+ return async () => {
25
+ try {
26
+ const valueOrPromise = originalFn();
27
+ const value = isPromise(valueOrPromise) ? await valueOrPromise : valueOrPromise;
28
+ return Result.ok(value);
29
+ } catch (err) {
30
+ return Result.err(unknownToError(err));
31
+ }
32
+ };
33
+ }
34
+ });
35
+ const correctlyTypedProcessedCalls = processedCalls;
36
+ return this.add(...correctlyTypedProcessedCalls);
37
+ }
38
+ async runAll({ delayStart } = {}) {
39
+ invariant(!this.#alreadyRun, "Already run");
40
+ this.#alreadyRun = true;
41
+ try {
42
+ const asyncResults = await Promise.all(
43
+ this.#pendingCalls.map(async (fn, i) => {
44
+ try {
45
+ const isP = isPromise(fn);
46
+ if (delayStart) {
47
+ invariant(
48
+ !isP,
49
+ "Delay start is not supported direct promise calls"
50
+ );
51
+ await sleep(delayStart(i));
52
+ }
53
+ const result = await (isP ? fn : fn());
54
+ if (!result.ok) throw result.error;
55
+ return result.value;
56
+ } catch (exception) {
57
+ throw unknownToError(exception);
58
+ }
59
+ })
60
+ );
61
+ return Result.ok(asyncResults);
62
+ } catch (exception) {
63
+ return Result.err(unknownToError(exception));
64
+ } finally {
65
+ this.#pendingCalls = [];
66
+ }
67
+ }
68
+ async runAllSettled({ delayStart } = {}) {
69
+ invariant(!this.#alreadyRun, "Already run");
70
+ this.#alreadyRun = true;
71
+ const total = this.#pendingCalls.length;
72
+ const settledResults = await Promise.allSettled(
73
+ this.#pendingCalls.map(async (callOrPromise, i) => {
74
+ try {
75
+ const isP = isPromise(callOrPromise);
76
+ if (delayStart) {
77
+ invariant(
78
+ !isP,
79
+ "Delay start is not supported for direct promise calls"
80
+ );
81
+ await sleep(delayStart(i));
82
+ }
83
+ const result = await (isP ? callOrPromise : callOrPromise());
84
+ if (!result.ok) {
85
+ throw result.error;
86
+ }
87
+ return result.value;
88
+ } catch (exception) {
89
+ throw unknownToError(exception);
90
+ }
91
+ })
92
+ );
93
+ const succeeded = [];
94
+ const failed = [];
95
+ for (const settledResult of settledResults) {
96
+ if (settledResult.status === "fulfilled") {
97
+ succeeded.push(settledResult.value);
98
+ } else {
99
+ failed.push(settledResult.reason);
100
+ }
101
+ }
102
+ const allFailed = failed.length === total;
103
+ const aggregatedError = failed.length > 0 ? new AggregateError(failed, "One or more calls failed") : null;
104
+ this.#pendingCalls = [];
105
+ return {
106
+ succeeded,
107
+ failures: failed,
108
+ allFailed,
109
+ total,
110
+ aggregatedError
111
+ };
112
+ }
113
+ };
114
+ function concurrentCalls() {
115
+ return new ConcurrentCalls();
116
+ }
117
+ var ConcurrentCallsWithMetadata = class {
118
+ #pendingCalls = [];
119
+ #alreadyRun = false;
120
+ add(...calls) {
121
+ invariant(
122
+ !this.#alreadyRun,
123
+ "Cannot add calls after execution has started."
124
+ );
125
+ this.#pendingCalls.push(...calls);
126
+ return this;
127
+ }
128
+ resultifyAdd(...items) {
129
+ const processedItems = items.map(({ fn, metadata }) => {
130
+ const cb = isPromise(fn) ? resultify(fn) : () => resultify(async () => {
131
+ const result = await fn();
132
+ return result;
133
+ });
134
+ return {
135
+ fn: cb,
136
+ metadata
137
+ };
138
+ });
139
+ return this.add(...processedItems);
140
+ }
141
+ async runAll({ delayStart } = {}) {
142
+ invariant(!this.#alreadyRun, "Already run");
143
+ this.#alreadyRun = true;
144
+ const currentCalls = [...this.#pendingCalls];
145
+ this.#pendingCalls = [];
146
+ try {
147
+ const successfulResults = [];
148
+ for (let i = 0; i < currentCalls.length; i++) {
149
+ const call = currentCalls[i];
150
+ try {
151
+ if (delayStart) {
152
+ await sleep(delayStart(i));
153
+ }
154
+ const result = await (isPromise(call.fn) ? call.fn : call.fn());
155
+ if (!result.ok) {
156
+ throw { metadata: call.metadata, error: result.error };
157
+ }
158
+ successfulResults.push({
159
+ value: result.value,
160
+ metadata: call.metadata
161
+ });
162
+ } catch (exception) {
163
+ if (typeof exception === "object" && exception !== null && "metadata" in exception && "error" in exception && exception.metadata === call.metadata) {
164
+ throw exception;
165
+ } else {
166
+ throw {
167
+ metadata: call.metadata,
168
+ error: unknownToError(exception)
169
+ };
170
+ }
171
+ }
172
+ }
173
+ return Result.ok(successfulResults);
174
+ } catch (errorPayload) {
175
+ return Result.err(errorPayload);
176
+ }
177
+ }
178
+ async runAllSettled({ delayStart } = {}) {
179
+ invariant(!this.#alreadyRun, "Already run");
180
+ this.#alreadyRun = true;
181
+ const currentCalls = [...this.#pendingCalls];
182
+ this.#pendingCalls = [];
183
+ const total = currentCalls.length;
184
+ if (total === 0) {
185
+ return {
186
+ succeeded: [],
187
+ failed: [],
188
+ results: [],
189
+ allFailed: false,
190
+ total: 0,
191
+ aggregatedError: null
192
+ };
193
+ }
194
+ const settledOutcomes = await Promise.allSettled(
195
+ currentCalls.map(async (call, i) => {
196
+ try {
197
+ if (delayStart) {
198
+ await sleep(delayStart(i));
199
+ }
200
+ const result = await (isPromise(call.fn) ? call.fn : call.fn());
201
+ if (!result.ok) {
202
+ throw result.error;
203
+ }
204
+ return result.value;
205
+ } catch (innerException) {
206
+ throw unknownToError(innerException);
207
+ }
208
+ })
209
+ );
210
+ const succeededProcessing = [];
211
+ const failedProcessing = [];
212
+ const resultsProcessing = [];
213
+ for (let i = 0; i < settledOutcomes.length; i++) {
214
+ const outcome = settledOutcomes[i];
215
+ const { metadata } = currentCalls[i];
216
+ if (outcome.status === "fulfilled") {
217
+ const value = outcome.value;
218
+ succeededProcessing.push({ value, metadata });
219
+ resultsProcessing.push({ ok: true, value, metadata, error: false });
220
+ } else {
221
+ const error = outcome.reason;
222
+ failedProcessing.push({ error, metadata });
223
+ resultsProcessing.push({ ok: false, error, metadata });
224
+ }
225
+ }
226
+ const allFailed = failedProcessing.length === total;
227
+ const aggregatedError = failedProcessing.length > 0 ? new AggregateError(
228
+ failedProcessing.map((f) => f.error),
229
+ "One or more calls failed"
230
+ ) : null;
231
+ return {
232
+ succeeded: succeededProcessing,
233
+ failed: failedProcessing,
234
+ results: resultsProcessing,
235
+ allFailed,
236
+ total,
237
+ aggregatedError
238
+ };
239
+ }
240
+ };
241
+ function concurrentCallsWithMetadata() {
242
+ return new ConcurrentCallsWithMetadata();
243
+ }
244
+ export {
245
+ concurrentCalls,
246
+ concurrentCallsWithMetadata
247
+ };
@@ -5,8 +5,8 @@ import {
5
5
  durationObjToMs
6
6
  } from "./chunk-5MNYPLZI.js";
7
7
  import "./chunk-HTCYUMDR.js";
8
- import "./chunk-3XCS7FVO.js";
9
8
  import "./chunk-II4R3VVX.js";
9
+ import "./chunk-3XCS7FVO.js";
10
10
 
11
11
  // src/createThrottleController.ts
12
12
  function createThrottleController({
@@ -70,6 +70,8 @@ declare class ParallelAsyncResultCalls<M extends ValidMetadata | undefined = und
70
70
  *
71
71
  * @template R - The type of the result value.
72
72
  * @template M - The type of the call metadata.
73
+ *
74
+ * @deprecated Use concurrentAsyncCalls instead.
73
75
  */
74
76
  declare function parallelAsyncCalls<M extends ValidMetadata | undefined = undefined, R = unknown>(): ParallelAsyncResultCalls<M, R>;
75
77
 
@@ -70,6 +70,8 @@ declare class ParallelAsyncResultCalls<M extends ValidMetadata | undefined = und
70
70
  *
71
71
  * @template R - The type of the result value.
72
72
  * @template M - The type of the call metadata.
73
+ *
74
+ * @deprecated Use concurrentAsyncCalls instead.
73
75
  */
74
76
  declare function parallelAsyncCalls<M extends ValidMetadata | undefined = undefined, R = unknown>(): ParallelAsyncResultCalls<M, R>;
75
77
 
@@ -1,13 +1,6 @@
1
- // src/promiseUtils.ts
2
- function defer() {
3
- let resolve;
4
- let reject;
5
- const promise = new Promise((_resolve, _reject) => {
6
- resolve = _resolve;
7
- reject = _reject;
8
- });
9
- return { resolve, reject, promise };
10
- }
1
+ import {
2
+ defer
3
+ } from "./chunk-DFXNVEH6.js";
11
4
  export {
12
5
  defer
13
6
  };
package/lib/testUtils.js CHANGED
@@ -8,7 +8,7 @@ import {
8
8
  import {
9
9
  arrayWithPrevAndIndex,
10
10
  filterAndMap
11
- } from "./chunk-5JQGMNNY.js";
11
+ } from "./chunk-XMUFRC2U.js";
12
12
  import {
13
13
  clampMin
14
14
  } from "./chunk-HTCYUMDR.js";
@@ -1,13 +1,13 @@
1
1
  import {
2
2
  truncateString
3
3
  } from "./chunk-4REIIZQY.js";
4
- import {
5
- bytesToHumanReadable
6
- } from "./chunk-IATIXMCE.js";
7
4
  import {
8
5
  isObject,
9
6
  isPlainObject
10
7
  } from "./chunk-3XCS7FVO.js";
8
+ import {
9
+ bytesToHumanReadable
10
+ } from "./chunk-IATIXMCE.js";
11
11
 
12
12
  // src/yamlStringify.ts
13
13
  function yamlStringify(obj, {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ls-stack/utils",
3
3
  "description": "Typescript utils",
4
- "version": "3.6.0",
4
+ "version": "3.8.0",
5
5
  "license": "MIT",
6
6
  "files": [
7
7
  "lib"
@@ -26,6 +26,10 @@
26
26
  "import": "./lib/assertions.js",
27
27
  "require": "./lib/assertions.cjs"
28
28
  },
29
+ "./asyncQueue": {
30
+ "import": "./lib/asyncQueue.js",
31
+ "require": "./lib/asyncQueue.cjs"
32
+ },
29
33
  "./cache": {
30
34
  "import": "./lib/cache.js",
31
35
  "require": "./lib/cache.cjs"
@@ -34,6 +38,10 @@
34
38
  "import": "./lib/castValues.js",
35
39
  "require": "./lib/castValues.cjs"
36
40
  },
41
+ "./concurrentCalls": {
42
+ "import": "./lib/concurrentCalls.js",
43
+ "require": "./lib/concurrentCalls.cjs"
44
+ },
37
45
  "./consoleFmt": {
38
46
  "import": "./lib/consoleFmt.js",
39
47
  "require": "./lib/consoleFmt.cjs"
@@ -177,7 +185,8 @@
177
185
  "vitest": "^3.0.4"
178
186
  },
179
187
  "dependencies": {
180
- "t-result": "^0.2.1"
188
+ "evtmitter": "^0.3.3",
189
+ "t-result": "^0.3.0"
181
190
  },
182
191
  "scripts": {
183
192
  "test:ui": "vitest --ui",