@terrygonguet/utils 0.4.1 → 0.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.
package/dist/async.d.ts CHANGED
@@ -5,11 +5,21 @@ interface RetryOptions {
5
5
  }
6
6
  declare function retry(options: RetryOptions): <T>(provider: () => Promise<T>) => Promise<T>;
7
7
  declare function retry<T>(provider: () => Promise<T>, options?: RetryOptions): Promise<T>;
8
- interface AsyncMapOptions {
8
+ interface AsyncMapOptions<FailFast extends boolean = false, WithSourceIndexes extends boolean = false> {
9
9
  concurrent?: number;
10
+ failFast?: FailFast;
11
+ withSourceIndexes?: WithSourceIndexes;
12
+ }
13
+ interface AsyncMapResultWithIndexes<U> {
14
+ results: [i: number, value: U][];
15
+ errors: [i: number, error: unknown][];
16
+ }
17
+ interface AsyncMapResult<U> {
18
+ results: U[];
19
+ errors: unknown[];
10
20
  }
11
- declare function asyncMap<T, U>(f: AsyncMapFn<T, U>, options?: AsyncMapOptions): (data: T[]) => Promise<U[]>;
12
- declare function asyncMap<T, U>(data: T[], f: AsyncMapFn<T, U>, options?: AsyncMapOptions): Promise<U[]>;
13
21
  type AsyncMapFn<T, U> = (el: T, i: number, data: T[]) => Promise<U>;
22
+ declare function asyncMap<T, U, FailFast extends boolean = false, WithSourceIndexes extends boolean = false>(f: AsyncMapFn<T, U>, options?: AsyncMapOptions<FailFast, WithSourceIndexes>): (data: T[]) => Promise<FailFast extends true ? WithSourceIndexes extends true ? [i: number, value: U][] : U[] : WithSourceIndexes extends true ? AsyncMapResultWithIndexes<U> : AsyncMapResult<U>>;
23
+ declare function asyncMap<T, U, FailFast extends boolean = false, WithSourceIndexes extends boolean = false>(data: T[], f: AsyncMapFn<T, U>, options?: AsyncMapOptions<FailFast, WithSourceIndexes>): Promise<FailFast extends true ? WithSourceIndexes extends true ? [i: number, value: U][] : U[] : WithSourceIndexes extends true ? AsyncMapResultWithIndexes<U> : AsyncMapResult<U>>;
14
24
 
15
25
  export { asyncMap, pause, retry };
package/dist/async.js CHANGED
@@ -40,34 +40,62 @@ function asyncMap(dataOrF, ForOptions, options) {
40
40
  return asyncMap_(data, f, options);
41
41
  } else throw new Error("Invalid arguments passed to asyncMap");
42
42
  }
43
- async function asyncMap_(data, f, { concurrent = 5 } = {}) {
43
+ async function asyncMap_(data, f, {
44
+ concurrent = 5,
45
+ failFast = false,
46
+ withSourceIndexes = false
47
+ } = {}) {
44
48
  return new Promise((resolve, reject) => {
45
49
  const resolved = [];
46
- const inFlight = [];
50
+ const errors = [];
51
+ const inFlight = /* @__PURE__ */ new Map();
47
52
  let next = 0;
53
+ let stop = false;
48
54
  function queue(i) {
49
- if (resolved.length == data.length && inFlight.length == 0)
50
- return finish();
51
- if (i >= data.length) return;
52
- const el = data[i];
53
- inFlight.push([
55
+ if (!stop && i > 0 && inFlight.size == 0) return finish();
56
+ if (stop || i >= data.length) return;
57
+ inFlight.set(
54
58
  i,
55
- f(el, i, data).then((result) => {
56
- resolved.push([i, result]);
57
- const j = inFlight.findIndex(([j2]) => i == j2);
58
- inFlight.splice(j, 1);
59
+ f(data[i], i, data).then(
60
+ (result) => void resolved.push([i, result]),
61
+ (error) => {
62
+ if (!failFast) errors.push([i, error]);
63
+ else {
64
+ stop = true;
65
+ reject(error);
66
+ }
67
+ }
68
+ ).finally(() => {
69
+ inFlight.delete(i);
59
70
  queue(next);
60
- }, reject)
61
- ]);
71
+ })
72
+ );
62
73
  next++;
63
74
  }
64
75
  function finish() {
65
- const sorted = resolved.sort(([a], [b]) => a - b);
66
- resolve(sorted.map(([, value]) => value));
67
- }
68
- for (let i = 0; i < concurrent; i++) {
69
- queue(next);
76
+ resolved.sort(([a], [b]) => a - b);
77
+ if (failFast) {
78
+ if (withSourceIndexes) resolve(resolved);
79
+ else resolve(resolved.map(([, value]) => value));
80
+ } else {
81
+ errors.sort(([a], [b]) => a - b);
82
+ if (withSourceIndexes)
83
+ resolve({
84
+ results: resolved,
85
+ errors
86
+ });
87
+ else
88
+ resolve({
89
+ results: resolved.map(([, value]) => value),
90
+ errors: errors.map(([, error]) => error)
91
+ });
92
+ }
70
93
  }
94
+ if (data.length == 0) finish();
95
+ else
96
+ for (let i = 0; i < concurrent; i++) {
97
+ queue(next);
98
+ }
71
99
  });
72
100
  }
73
101
  export {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@terrygonguet/utils",
3
- "version": "0.4.1",
3
+ "version": "0.5.0",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "scripts": {
@@ -34,11 +34,11 @@
34
34
  }
35
35
  },
36
36
  "devDependencies": {
37
- "prettier": "^2.8.8",
38
- "tsup": "^8.1.0",
39
- "typescript": "^5.0.2",
40
- "vite": "^5.4.8",
41
- "vitest": "^2.1.2"
37
+ "prettier": "^3.5.2",
38
+ "tsup": "^8.3.6",
39
+ "typescript": "^5.7.3",
40
+ "vite": "^6.1.1",
41
+ "vitest": "^3.0.6"
42
42
  },
43
43
  "author": {
44
44
  "email": "terry@gonguet.com",