@fuzdev/fuz_util 0.45.2 → 0.45.3
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/dist/async.d.ts +18 -0
- package/dist/async.d.ts.map +1 -1
- package/dist/async.js +63 -3
- package/package.json +1 -1
- package/src/lib/async.ts +72 -3
package/dist/async.d.ts
CHANGED
|
@@ -19,6 +19,24 @@ export interface Deferred<T> {
|
|
|
19
19
|
* Creates a object with a `promise` and its `resolve`/`reject` handlers.
|
|
20
20
|
*/
|
|
21
21
|
export declare const create_deferred: <T>() => Deferred<T>;
|
|
22
|
+
/**
|
|
23
|
+
* Runs an async function on each item with controlled concurrency.
|
|
24
|
+
* Like `map_concurrent` but doesn't collect results (more efficient for side effects).
|
|
25
|
+
*
|
|
26
|
+
* @param items array of items to process
|
|
27
|
+
* @param fn async function to apply to each item
|
|
28
|
+
* @param concurrency maximum number of concurrent operations
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```ts
|
|
32
|
+
* await each_concurrent(
|
|
33
|
+
* file_paths,
|
|
34
|
+
* async (path) => { await unlink(path); },
|
|
35
|
+
* 5, // max 5 concurrent deletions
|
|
36
|
+
* );
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
export declare const each_concurrent: <T>(items: Array<T>, fn: (item: T, index: number) => Promise<void>, concurrency: number) => Promise<void>;
|
|
22
40
|
/**
|
|
23
41
|
* Maps over items with controlled concurrency, preserving input order.
|
|
24
42
|
*
|
package/dist/async.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"async.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/async.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;AAExE;;GAEG;AACH,eAAO,MAAM,IAAI,GAAI,iBAAY,KAAG,OAAO,CAAC,IAAI,CACQ,CAAC;AAEzD;;GAEG;AACH,eAAO,MAAM,UAAU,GAAI,OAAO,OAAO,KAAG,KAAK,IAAI,OAAO,CAAC,OAAO,CACI,CAAC;AAEzE;;GAEG;AACH,MAAM,WAAW,QAAQ,CAAC,CAAC;IAC1B,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IACpB,OAAO,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAAC;IAC5B,MAAM,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,IAAI,CAAC;CAC9B;AAED;;GAEG;AACH,eAAO,MAAM,eAAe,GAAI,CAAC,OAAK,QAAQ,CAAC,CAAC,CAQ/C,CAAC;AAEF;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,cAAc,GAAU,CAAC,EAAE,CAAC,EACxC,OAAO,KAAK,CAAC,CAAC,CAAC,EACf,IAAI,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,EAC1C,aAAa,MAAM,KACjB,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"async.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/async.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;AAExE;;GAEG;AACH,eAAO,MAAM,IAAI,GAAI,iBAAY,KAAG,OAAO,CAAC,IAAI,CACQ,CAAC;AAEzD;;GAEG;AACH,eAAO,MAAM,UAAU,GAAI,OAAO,OAAO,KAAG,KAAK,IAAI,OAAO,CAAC,OAAO,CACI,CAAC;AAEzE;;GAEG;AACH,MAAM,WAAW,QAAQ,CAAC,CAAC;IAC1B,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IACpB,OAAO,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAAC;IAC5B,MAAM,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,IAAI,CAAC;CAC9B;AAED;;GAEG;AACH,eAAO,MAAM,eAAe,GAAI,CAAC,OAAK,QAAQ,CAAC,CAAC,CAQ/C,CAAC;AAEF;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,eAAe,GAAU,CAAC,EACtC,OAAO,KAAK,CAAC,CAAC,CAAC,EACf,IAAI,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,EAC7C,aAAa,MAAM,KACjB,OAAO,CAAC,IAAI,CAgDd,CAAC;AAEF;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,cAAc,GAAU,CAAC,EAAE,CAAC,EACxC,OAAO,KAAK,CAAC,CAAC,CAAC,EACf,IAAI,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,EAC1C,aAAa,MAAM,KACjB,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAkDlB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,sBAAsB,GAAU,CAAC,EAAE,CAAC,EAChD,OAAO,KAAK,CAAC,CAAC,CAAC,EACf,IAAI,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,EAC1C,aAAa,MAAM,KACjB,OAAO,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC,CA6CxC,CAAC"}
|
package/dist/async.js
CHANGED
|
@@ -18,6 +18,68 @@ export const create_deferred = () => {
|
|
|
18
18
|
});
|
|
19
19
|
return { promise, resolve, reject };
|
|
20
20
|
};
|
|
21
|
+
/**
|
|
22
|
+
* Runs an async function on each item with controlled concurrency.
|
|
23
|
+
* Like `map_concurrent` but doesn't collect results (more efficient for side effects).
|
|
24
|
+
*
|
|
25
|
+
* @param items array of items to process
|
|
26
|
+
* @param fn async function to apply to each item
|
|
27
|
+
* @param concurrency maximum number of concurrent operations
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```ts
|
|
31
|
+
* await each_concurrent(
|
|
32
|
+
* file_paths,
|
|
33
|
+
* async (path) => { await unlink(path); },
|
|
34
|
+
* 5, // max 5 concurrent deletions
|
|
35
|
+
* );
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export const each_concurrent = async (items, fn, concurrency) => {
|
|
39
|
+
if (concurrency < 1) {
|
|
40
|
+
throw new Error('concurrency must be at least 1');
|
|
41
|
+
}
|
|
42
|
+
let next_index = 0;
|
|
43
|
+
let active_count = 0;
|
|
44
|
+
let rejected = false;
|
|
45
|
+
return new Promise((resolve, reject) => {
|
|
46
|
+
const run_next = () => {
|
|
47
|
+
// Stop spawning if we've rejected
|
|
48
|
+
if (rejected)
|
|
49
|
+
return;
|
|
50
|
+
// Check if we're done
|
|
51
|
+
if (next_index >= items.length && active_count === 0) {
|
|
52
|
+
resolve();
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
// Spawn workers up to concurrency limit
|
|
56
|
+
while (active_count < concurrency && next_index < items.length) {
|
|
57
|
+
const index = next_index++;
|
|
58
|
+
const item = items[index];
|
|
59
|
+
active_count++;
|
|
60
|
+
fn(item, index)
|
|
61
|
+
.then(() => {
|
|
62
|
+
if (rejected)
|
|
63
|
+
return;
|
|
64
|
+
active_count--;
|
|
65
|
+
run_next();
|
|
66
|
+
})
|
|
67
|
+
.catch((error) => {
|
|
68
|
+
if (rejected)
|
|
69
|
+
return;
|
|
70
|
+
rejected = true;
|
|
71
|
+
reject(error); // eslint-disable-line @typescript-eslint/prefer-promise-reject-errors
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
// Handle empty array
|
|
76
|
+
if (items.length === 0) {
|
|
77
|
+
resolve();
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
run_next();
|
|
81
|
+
});
|
|
82
|
+
};
|
|
21
83
|
/**
|
|
22
84
|
* Maps over items with controlled concurrency, preserving input order.
|
|
23
85
|
*
|
|
@@ -43,7 +105,6 @@ export const map_concurrent = async (items, fn, concurrency) => {
|
|
|
43
105
|
let next_index = 0;
|
|
44
106
|
let active_count = 0;
|
|
45
107
|
let rejected = false;
|
|
46
|
-
let reject_error;
|
|
47
108
|
return new Promise((resolve, reject) => {
|
|
48
109
|
const run_next = () => {
|
|
49
110
|
// Stop spawning if we've rejected
|
|
@@ -71,8 +132,7 @@ export const map_concurrent = async (items, fn, concurrency) => {
|
|
|
71
132
|
if (rejected)
|
|
72
133
|
return;
|
|
73
134
|
rejected = true;
|
|
74
|
-
|
|
75
|
-
reject(reject_error); // eslint-disable-line @typescript-eslint/prefer-promise-reject-errors
|
|
135
|
+
reject(error); // eslint-disable-line @typescript-eslint/prefer-promise-reject-errors
|
|
76
136
|
});
|
|
77
137
|
}
|
|
78
138
|
};
|
package/package.json
CHANGED
package/src/lib/async.ts
CHANGED
|
@@ -34,6 +34,77 @@ export const create_deferred = <T>(): Deferred<T> => {
|
|
|
34
34
|
return {promise, resolve, reject};
|
|
35
35
|
};
|
|
36
36
|
|
|
37
|
+
/**
|
|
38
|
+
* Runs an async function on each item with controlled concurrency.
|
|
39
|
+
* Like `map_concurrent` but doesn't collect results (more efficient for side effects).
|
|
40
|
+
*
|
|
41
|
+
* @param items array of items to process
|
|
42
|
+
* @param fn async function to apply to each item
|
|
43
|
+
* @param concurrency maximum number of concurrent operations
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* ```ts
|
|
47
|
+
* await each_concurrent(
|
|
48
|
+
* file_paths,
|
|
49
|
+
* async (path) => { await unlink(path); },
|
|
50
|
+
* 5, // max 5 concurrent deletions
|
|
51
|
+
* );
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
export const each_concurrent = async <T>(
|
|
55
|
+
items: Array<T>,
|
|
56
|
+
fn: (item: T, index: number) => Promise<void>,
|
|
57
|
+
concurrency: number,
|
|
58
|
+
): Promise<void> => {
|
|
59
|
+
if (concurrency < 1) {
|
|
60
|
+
throw new Error('concurrency must be at least 1');
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
let next_index = 0;
|
|
64
|
+
let active_count = 0;
|
|
65
|
+
let rejected = false;
|
|
66
|
+
|
|
67
|
+
return new Promise((resolve, reject) => {
|
|
68
|
+
const run_next = (): void => {
|
|
69
|
+
// Stop spawning if we've rejected
|
|
70
|
+
if (rejected) return;
|
|
71
|
+
|
|
72
|
+
// Check if we're done
|
|
73
|
+
if (next_index >= items.length && active_count === 0) {
|
|
74
|
+
resolve();
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Spawn workers up to concurrency limit
|
|
79
|
+
while (active_count < concurrency && next_index < items.length) {
|
|
80
|
+
const index = next_index++;
|
|
81
|
+
const item = items[index]!;
|
|
82
|
+
active_count++;
|
|
83
|
+
|
|
84
|
+
fn(item, index)
|
|
85
|
+
.then(() => {
|
|
86
|
+
if (rejected) return;
|
|
87
|
+
active_count--;
|
|
88
|
+
run_next();
|
|
89
|
+
})
|
|
90
|
+
.catch((error) => {
|
|
91
|
+
if (rejected) return;
|
|
92
|
+
rejected = true;
|
|
93
|
+
reject(error); // eslint-disable-line @typescript-eslint/prefer-promise-reject-errors
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
// Handle empty array
|
|
99
|
+
if (items.length === 0) {
|
|
100
|
+
resolve();
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
run_next();
|
|
105
|
+
});
|
|
106
|
+
};
|
|
107
|
+
|
|
37
108
|
/**
|
|
38
109
|
* Maps over items with controlled concurrency, preserving input order.
|
|
39
110
|
*
|
|
@@ -64,7 +135,6 @@ export const map_concurrent = async <T, R>(
|
|
|
64
135
|
let next_index = 0;
|
|
65
136
|
let active_count = 0;
|
|
66
137
|
let rejected = false;
|
|
67
|
-
let reject_error: unknown;
|
|
68
138
|
|
|
69
139
|
return new Promise((resolve, reject) => {
|
|
70
140
|
const run_next = (): void => {
|
|
@@ -93,8 +163,7 @@ export const map_concurrent = async <T, R>(
|
|
|
93
163
|
.catch((error) => {
|
|
94
164
|
if (rejected) return;
|
|
95
165
|
rejected = true;
|
|
96
|
-
|
|
97
|
-
reject(reject_error); // eslint-disable-line @typescript-eslint/prefer-promise-reject-errors
|
|
166
|
+
reject(error); // eslint-disable-line @typescript-eslint/prefer-promise-reject-errors
|
|
98
167
|
});
|
|
99
168
|
}
|
|
100
169
|
};
|