@naturalcycles/js-lib 14.218.0 → 14.219.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.
@@ -4,7 +4,7 @@ export interface PMapOptions {
4
4
  /**
5
5
  * Number of concurrently pending promises returned by `mapper`.
6
6
  *
7
- * @default Infinity
7
+ * Defaults to Infitity.
8
8
  */
9
9
  concurrency?: number;
10
10
  /**
@@ -23,6 +23,14 @@ export interface PMapOptions {
23
23
  logger?: CommonLogger | null;
24
24
  }
25
25
  /**
26
+ * Forked from https://github.com/sindresorhus/p-map
27
+ *
28
+ * Improvements:
29
+ * - Exported as { pMap }, so IDE auto-completion works
30
+ * - Included Typescript typings (no need for @types/p-map)
31
+ * - Compatible with pProps (that had typings issues)
32
+ * - Preserves async stack traces (in selected cases)
33
+ *
26
34
  * Returns a `Promise` that is fulfilled when all promises in `input` and ones returned from `mapper` are fulfilled,
27
35
  * or rejects if any of the promises reject. The fulfilled value is an `Array` of the fulfilled values returned
28
36
  * from `mapper` in `input` order.
@@ -1,16 +1,16 @@
1
1
  "use strict";
2
- /*
3
- Taken from https://github.com/sindresorhus/p-map
4
-
5
- Improvements:
6
- - Exported as { pMap }, so IDE auto-completion works
7
- - Included Typescript typings (no need for @types/p-map)
8
- - Compatible with pProps (that had typings issues)
9
- */
10
2
  Object.defineProperty(exports, "__esModule", { value: true });
11
3
  exports.pMap = void 0;
12
4
  const __1 = require("..");
13
5
  /**
6
+ * Forked from https://github.com/sindresorhus/p-map
7
+ *
8
+ * Improvements:
9
+ * - Exported as { pMap }, so IDE auto-completion works
10
+ * - Included Typescript typings (no need for @types/p-map)
11
+ * - Compatible with pProps (that had typings issues)
12
+ * - Preserves async stack traces (in selected cases)
13
+ *
14
14
  * Returns a `Promise` that is fulfilled when all promises in `input` and ones returned from `mapper` are fulfilled,
15
15
  * or rejects if any of the promises reject. The fulfilled value is an `Array` of the fulfilled values returned
16
16
  * from `mapper` in `input` order.
@@ -37,70 +37,26 @@ const __1 = require("..");
37
37
  * })();
38
38
  */
39
39
  async function pMap(iterable, mapper, opt = {}) {
40
- const { logger = console } = opt;
41
- const ret = [];
42
- // const iterator = iterable[Symbol.iterator]()
43
40
  const items = [...iterable];
44
41
  const itemsLength = items.length;
45
42
  if (itemsLength === 0)
46
43
  return []; // short circuit
47
- const { concurrency = itemsLength, errorMode = __1.ErrorMode.THROW_IMMEDIATELY } = opt;
48
- const errors = [];
49
- let isSettled = false;
50
- let resolvingCount = 0;
51
- let currentIndex = 0;
44
+ const { concurrency = Infinity, errorMode = __1.ErrorMode.THROW_IMMEDIATELY, logger = console } = opt;
52
45
  // Special cases that are able to preserve async stack traces
46
+ // Special case: serial execution
53
47
  if (concurrency === 1) {
54
- // Special case for concurrency == 1
55
- for (const item of items) {
56
- try {
57
- const r = await mapper(item, currentIndex++);
58
- if (r === __1.END)
59
- break;
60
- if (r !== __1.SKIP)
61
- ret.push(r);
62
- }
63
- catch (err) {
64
- if (errorMode === __1.ErrorMode.THROW_IMMEDIATELY)
65
- throw err;
66
- if (errorMode === __1.ErrorMode.THROW_AGGREGATED) {
67
- errors.push(err);
68
- }
69
- else {
70
- // otherwise, suppress (but still log via logger)
71
- logger?.error(err);
72
- }
73
- }
74
- }
75
- if (errors.length) {
76
- throw new AggregateError(errors, `pMap resulted in ${errors.length} error(s)`);
77
- }
78
- return ret;
48
+ return await pMap1(items, mapper, errorMode, logger);
79
49
  }
80
- else if (!opt.concurrency || items.length <= opt.concurrency) {
81
- // Special case for concurrency == infinity or iterable.length < concurrency
82
- if (errorMode === __1.ErrorMode.THROW_IMMEDIATELY) {
83
- return (await Promise.all(items.map((item, i) => mapper(item, i)))).filter(r => r !== __1.SKIP && r !== __1.END);
84
- }
85
- ;
86
- (await Promise.allSettled(items.map((item, i) => mapper(item, i)))).forEach(r => {
87
- if (r.status === 'fulfilled') {
88
- if (r.value !== __1.SKIP && r.value !== __1.END)
89
- ret.push(r.value);
90
- }
91
- else if (errorMode === __1.ErrorMode.THROW_AGGREGATED) {
92
- errors.push(r.reason);
93
- }
94
- else {
95
- // otherwise, suppress (but still log via logger)
96
- logger?.error(r.reason);
97
- }
98
- });
99
- if (errors.length) {
100
- throw new AggregateError(errors, `pMap resulted in ${errors.length} error(s)`);
101
- }
102
- return ret;
50
+ // Special case: items.length <= concurrency (including when concurrency === Infinity)
51
+ if (items.length <= concurrency) {
52
+ return await pMapAll(items, mapper, errorMode, logger);
103
53
  }
54
+ // General case: execution with throttled concurrency
55
+ const ret = [];
56
+ const errors = [];
57
+ let isSettled = false;
58
+ let resolvingCount = 0;
59
+ let currentIndex = 0;
104
60
  return await new Promise((resolve, reject) => {
105
61
  const next = () => {
106
62
  if (isSettled) {
@@ -159,3 +115,64 @@ async function pMap(iterable, mapper, opt = {}) {
159
115
  });
160
116
  }
161
117
  exports.pMap = pMap;
118
+ /**
119
+ pMap with serial (non-concurrent) execution.
120
+ */
121
+ async function pMap1(items, mapper, errorMode, logger) {
122
+ let i = 0;
123
+ const ret = [];
124
+ const errors = [];
125
+ for (const item of items) {
126
+ try {
127
+ const r = await mapper(item, i++);
128
+ if (r === __1.END)
129
+ break;
130
+ if (r !== __1.SKIP)
131
+ ret.push(r);
132
+ }
133
+ catch (err) {
134
+ if (errorMode === __1.ErrorMode.THROW_IMMEDIATELY)
135
+ throw err;
136
+ if (errorMode === __1.ErrorMode.THROW_AGGREGATED) {
137
+ errors.push(err);
138
+ }
139
+ else {
140
+ // otherwise, suppress (but still log via logger)
141
+ logger?.error(err);
142
+ }
143
+ }
144
+ }
145
+ if (errors.length) {
146
+ throw new AggregateError(errors, `pMap resulted in ${errors.length} error(s)`);
147
+ }
148
+ return ret;
149
+ }
150
+ /**
151
+ pMap with fully concurrent execution, like Promise.all
152
+ */
153
+ async function pMapAll(items, mapper, errorMode, logger) {
154
+ if (errorMode === __1.ErrorMode.THROW_IMMEDIATELY) {
155
+ return (await Promise.all(items.map((item, i) => mapper(item, i)))).filter(r => r !== __1.SKIP && r !== __1.END);
156
+ }
157
+ const ret = [];
158
+ const errors = [];
159
+ for (const r of await Promise.allSettled(items.map((item, i) => mapper(item, i)))) {
160
+ if (r.status === 'fulfilled') {
161
+ if (r.value === __1.END)
162
+ break;
163
+ if (r.value !== __1.SKIP)
164
+ ret.push(r.value);
165
+ }
166
+ else if (errorMode === __1.ErrorMode.THROW_AGGREGATED) {
167
+ errors.push(r.reason);
168
+ }
169
+ else {
170
+ // otherwise, suppress (but still log via logger)
171
+ logger?.error(r.reason);
172
+ }
173
+ }
174
+ if (errors.length) {
175
+ throw new AggregateError(errors, `pMap resulted in ${errors.length} error(s)`);
176
+ }
177
+ return ret;
178
+ }
@@ -1,13 +1,13 @@
1
- /*
2
- Taken from https://github.com/sindresorhus/p-map
3
-
4
- Improvements:
5
- - Exported as { pMap }, so IDE auto-completion works
6
- - Included Typescript typings (no need for @types/p-map)
7
- - Compatible with pProps (that had typings issues)
8
- */
9
1
  import { END, ErrorMode, SKIP } from '..';
10
2
  /**
3
+ * Forked from https://github.com/sindresorhus/p-map
4
+ *
5
+ * Improvements:
6
+ * - Exported as { pMap }, so IDE auto-completion works
7
+ * - Included Typescript typings (no need for @types/p-map)
8
+ * - Compatible with pProps (that had typings issues)
9
+ * - Preserves async stack traces (in selected cases)
10
+ *
11
11
  * Returns a `Promise` that is fulfilled when all promises in `input` and ones returned from `mapper` are fulfilled,
12
12
  * or rejects if any of the promises reject. The fulfilled value is an `Array` of the fulfilled values returned
13
13
  * from `mapper` in `input` order.
@@ -34,70 +34,26 @@ import { END, ErrorMode, SKIP } from '..';
34
34
  * })();
35
35
  */
36
36
  export async function pMap(iterable, mapper, opt = {}) {
37
- const { logger = console } = opt;
38
- const ret = [];
39
- // const iterator = iterable[Symbol.iterator]()
40
37
  const items = [...iterable];
41
38
  const itemsLength = items.length;
42
39
  if (itemsLength === 0)
43
40
  return []; // short circuit
44
- const { concurrency = itemsLength, errorMode = ErrorMode.THROW_IMMEDIATELY } = opt;
45
- const errors = [];
46
- let isSettled = false;
47
- let resolvingCount = 0;
48
- let currentIndex = 0;
41
+ const { concurrency = Infinity, errorMode = ErrorMode.THROW_IMMEDIATELY, logger = console } = opt;
49
42
  // Special cases that are able to preserve async stack traces
43
+ // Special case: serial execution
50
44
  if (concurrency === 1) {
51
- // Special case for concurrency == 1
52
- for (const item of items) {
53
- try {
54
- const r = await mapper(item, currentIndex++);
55
- if (r === END)
56
- break;
57
- if (r !== SKIP)
58
- ret.push(r);
59
- }
60
- catch (err) {
61
- if (errorMode === ErrorMode.THROW_IMMEDIATELY)
62
- throw err;
63
- if (errorMode === ErrorMode.THROW_AGGREGATED) {
64
- errors.push(err);
65
- }
66
- else {
67
- // otherwise, suppress (but still log via logger)
68
- logger === null || logger === void 0 ? void 0 : logger.error(err);
69
- }
70
- }
71
- }
72
- if (errors.length) {
73
- throw new AggregateError(errors, `pMap resulted in ${errors.length} error(s)`);
74
- }
75
- return ret;
45
+ return await pMap1(items, mapper, errorMode, logger);
76
46
  }
77
- else if (!opt.concurrency || items.length <= opt.concurrency) {
78
- // Special case for concurrency == infinity or iterable.length < concurrency
79
- if (errorMode === ErrorMode.THROW_IMMEDIATELY) {
80
- return (await Promise.all(items.map((item, i) => mapper(item, i)))).filter(r => r !== SKIP && r !== END);
81
- }
82
- ;
83
- (await Promise.allSettled(items.map((item, i) => mapper(item, i)))).forEach(r => {
84
- if (r.status === 'fulfilled') {
85
- if (r.value !== SKIP && r.value !== END)
86
- ret.push(r.value);
87
- }
88
- else if (errorMode === ErrorMode.THROW_AGGREGATED) {
89
- errors.push(r.reason);
90
- }
91
- else {
92
- // otherwise, suppress (but still log via logger)
93
- logger === null || logger === void 0 ? void 0 : logger.error(r.reason);
94
- }
95
- });
96
- if (errors.length) {
97
- throw new AggregateError(errors, `pMap resulted in ${errors.length} error(s)`);
98
- }
99
- return ret;
47
+ // Special case: items.length <= concurrency (including when concurrency === Infinity)
48
+ if (items.length <= concurrency) {
49
+ return await pMapAll(items, mapper, errorMode, logger);
100
50
  }
51
+ // General case: execution with throttled concurrency
52
+ const ret = [];
53
+ const errors = [];
54
+ let isSettled = false;
55
+ let resolvingCount = 0;
56
+ let currentIndex = 0;
101
57
  return await new Promise((resolve, reject) => {
102
58
  const next = () => {
103
59
  if (isSettled) {
@@ -155,3 +111,64 @@ export async function pMap(iterable, mapper, opt = {}) {
155
111
  }
156
112
  });
157
113
  }
114
+ /**
115
+ pMap with serial (non-concurrent) execution.
116
+ */
117
+ async function pMap1(items, mapper, errorMode, logger) {
118
+ let i = 0;
119
+ const ret = [];
120
+ const errors = [];
121
+ for (const item of items) {
122
+ try {
123
+ const r = await mapper(item, i++);
124
+ if (r === END)
125
+ break;
126
+ if (r !== SKIP)
127
+ ret.push(r);
128
+ }
129
+ catch (err) {
130
+ if (errorMode === ErrorMode.THROW_IMMEDIATELY)
131
+ throw err;
132
+ if (errorMode === ErrorMode.THROW_AGGREGATED) {
133
+ errors.push(err);
134
+ }
135
+ else {
136
+ // otherwise, suppress (but still log via logger)
137
+ logger === null || logger === void 0 ? void 0 : logger.error(err);
138
+ }
139
+ }
140
+ }
141
+ if (errors.length) {
142
+ throw new AggregateError(errors, `pMap resulted in ${errors.length} error(s)`);
143
+ }
144
+ return ret;
145
+ }
146
+ /**
147
+ pMap with fully concurrent execution, like Promise.all
148
+ */
149
+ async function pMapAll(items, mapper, errorMode, logger) {
150
+ if (errorMode === ErrorMode.THROW_IMMEDIATELY) {
151
+ return (await Promise.all(items.map((item, i) => mapper(item, i)))).filter(r => r !== SKIP && r !== END);
152
+ }
153
+ const ret = [];
154
+ const errors = [];
155
+ for (const r of await Promise.allSettled(items.map((item, i) => mapper(item, i)))) {
156
+ if (r.status === 'fulfilled') {
157
+ if (r.value === END)
158
+ break;
159
+ if (r.value !== SKIP)
160
+ ret.push(r.value);
161
+ }
162
+ else if (errorMode === ErrorMode.THROW_AGGREGATED) {
163
+ errors.push(r.reason);
164
+ }
165
+ else {
166
+ // otherwise, suppress (but still log via logger)
167
+ logger === null || logger === void 0 ? void 0 : logger.error(r.reason);
168
+ }
169
+ }
170
+ if (errors.length) {
171
+ throw new AggregateError(errors, `pMap resulted in ${errors.length} error(s)`);
172
+ }
173
+ return ret;
174
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@naturalcycles/js-lib",
3
- "version": "14.218.0",
3
+ "version": "14.219.1",
4
4
  "scripts": {
5
5
  "prepare": "husky",
6
6
  "build-prod": "build-prod-esm-cjs",
@@ -1,12 +1,3 @@
1
- /*
2
- Taken from https://github.com/sindresorhus/p-map
3
-
4
- Improvements:
5
- - Exported as { pMap }, so IDE auto-completion works
6
- - Included Typescript typings (no need for @types/p-map)
7
- - Compatible with pProps (that had typings issues)
8
- */
9
-
10
1
  import type { AbortableAsyncMapper, CommonLogger } from '..'
11
2
  import { END, ErrorMode, SKIP } from '..'
12
3
 
@@ -14,7 +5,7 @@ export interface PMapOptions {
14
5
  /**
15
6
  * Number of concurrently pending promises returned by `mapper`.
16
7
  *
17
- * @default Infinity
8
+ * Defaults to Infitity.
18
9
  */
19
10
  concurrency?: number
20
11
 
@@ -36,6 +27,14 @@ export interface PMapOptions {
36
27
  }
37
28
 
38
29
  /**
30
+ * Forked from https://github.com/sindresorhus/p-map
31
+ *
32
+ * Improvements:
33
+ * - Exported as { pMap }, so IDE auto-completion works
34
+ * - Included Typescript typings (no need for @types/p-map)
35
+ * - Compatible with pProps (that had typings issues)
36
+ * - Preserves async stack traces (in selected cases)
37
+ *
39
38
  * Returns a `Promise` that is fulfilled when all promises in `input` and ones returned from `mapper` are fulfilled,
40
39
  * or rejects if any of the promises reject. The fulfilled value is an `Array` of the fulfilled values returned
41
40
  * from `mapper` in `input` order.
@@ -66,73 +65,30 @@ export async function pMap<IN, OUT>(
66
65
  mapper: AbortableAsyncMapper<IN, OUT>,
67
66
  opt: PMapOptions = {},
68
67
  ): Promise<OUT[]> {
69
- const { logger = console } = opt
70
- const ret: (OUT | typeof SKIP)[] = []
71
- // const iterator = iterable[Symbol.iterator]()
72
68
  const items = [...iterable]
73
69
  const itemsLength = items.length
74
70
  if (itemsLength === 0) return [] // short circuit
75
71
 
76
- const { concurrency = itemsLength, errorMode = ErrorMode.THROW_IMMEDIATELY } = opt
77
-
78
- const errors: Error[] = []
79
- let isSettled = false
80
- let resolvingCount = 0
81
- let currentIndex = 0
72
+ const { concurrency = Infinity, errorMode = ErrorMode.THROW_IMMEDIATELY, logger = console } = opt
82
73
 
83
74
  // Special cases that are able to preserve async stack traces
84
-
75
+ // Special case: serial execution
85
76
  if (concurrency === 1) {
86
- // Special case for concurrency == 1
87
-
88
- for (const item of items) {
89
- try {
90
- const r = await mapper(item, currentIndex++)
91
- if (r === END) break
92
- if (r !== SKIP) ret.push(r)
93
- } catch (err) {
94
- if (errorMode === ErrorMode.THROW_IMMEDIATELY) throw err
95
- if (errorMode === ErrorMode.THROW_AGGREGATED) {
96
- errors.push(err as Error)
97
- } else {
98
- // otherwise, suppress (but still log via logger)
99
- logger?.error(err)
100
- }
101
- }
102
- }
103
-
104
- if (errors.length) {
105
- throw new AggregateError(errors, `pMap resulted in ${errors.length} error(s)`)
106
- }
107
-
108
- return ret as OUT[]
109
- } else if (!opt.concurrency || items.length <= opt.concurrency) {
110
- // Special case for concurrency == infinity or iterable.length < concurrency
111
-
112
- if (errorMode === ErrorMode.THROW_IMMEDIATELY) {
113
- return (await Promise.all(items.map((item, i) => mapper(item, i)))).filter(
114
- r => r !== SKIP && r !== END,
115
- ) as OUT[]
116
- }
117
-
118
- ;(await Promise.allSettled(items.map((item, i) => mapper(item, i)))).forEach(r => {
119
- if (r.status === 'fulfilled') {
120
- if (r.value !== SKIP && r.value !== END) ret.push(r.value)
121
- } else if (errorMode === ErrorMode.THROW_AGGREGATED) {
122
- errors.push(r.reason)
123
- } else {
124
- // otherwise, suppress (but still log via logger)
125
- logger?.error(r.reason)
126
- }
127
- })
128
-
129
- if (errors.length) {
130
- throw new AggregateError(errors, `pMap resulted in ${errors.length} error(s)`)
131
- }
77
+ return await pMap1(items, mapper, errorMode, logger)
78
+ }
132
79
 
133
- return ret as OUT[]
80
+ // Special case: items.length <= concurrency (including when concurrency === Infinity)
81
+ if (items.length <= concurrency) {
82
+ return await pMapAll(items, mapper, errorMode, logger)
134
83
  }
135
84
 
85
+ // General case: execution with throttled concurrency
86
+ const ret: (OUT | typeof SKIP)[] = []
87
+ const errors: Error[] = []
88
+ let isSettled = false
89
+ let resolvingCount = 0
90
+ let currentIndex = 0
91
+
136
92
  return await new Promise<OUT[]>((resolve, reject) => {
137
93
  const next = (): void => {
138
94
  if (isSettled) {
@@ -198,3 +154,76 @@ export async function pMap<IN, OUT>(
198
154
  }
199
155
  })
200
156
  }
157
+
158
+ /**
159
+ pMap with serial (non-concurrent) execution.
160
+ */
161
+ async function pMap1<IN, OUT>(
162
+ items: IN[],
163
+ mapper: AbortableAsyncMapper<IN, OUT>,
164
+ errorMode: ErrorMode,
165
+ logger: CommonLogger | null,
166
+ ): Promise<OUT[]> {
167
+ let i = 0
168
+ const ret: OUT[] = []
169
+ const errors: Error[] = []
170
+
171
+ for (const item of items) {
172
+ try {
173
+ const r = await mapper(item, i++)
174
+ if (r === END) break
175
+ if (r !== SKIP) ret.push(r)
176
+ } catch (err) {
177
+ if (errorMode === ErrorMode.THROW_IMMEDIATELY) throw err
178
+ if (errorMode === ErrorMode.THROW_AGGREGATED) {
179
+ errors.push(err as Error)
180
+ } else {
181
+ // otherwise, suppress (but still log via logger)
182
+ logger?.error(err)
183
+ }
184
+ }
185
+ }
186
+
187
+ if (errors.length) {
188
+ throw new AggregateError(errors, `pMap resulted in ${errors.length} error(s)`)
189
+ }
190
+
191
+ return ret
192
+ }
193
+
194
+ /**
195
+ pMap with fully concurrent execution, like Promise.all
196
+ */
197
+ async function pMapAll<IN, OUT>(
198
+ items: IN[],
199
+ mapper: AbortableAsyncMapper<IN, OUT>,
200
+ errorMode: ErrorMode,
201
+ logger: CommonLogger | null,
202
+ ): Promise<OUT[]> {
203
+ if (errorMode === ErrorMode.THROW_IMMEDIATELY) {
204
+ return (await Promise.all(items.map((item, i) => mapper(item, i)))).filter(
205
+ r => r !== SKIP && r !== END,
206
+ ) as OUT[]
207
+ }
208
+
209
+ const ret: OUT[] = []
210
+ const errors: Error[] = []
211
+
212
+ for (const r of await Promise.allSettled(items.map((item, i) => mapper(item, i)))) {
213
+ if (r.status === 'fulfilled') {
214
+ if (r.value === END) break
215
+ if (r.value !== SKIP) ret.push(r.value)
216
+ } else if (errorMode === ErrorMode.THROW_AGGREGATED) {
217
+ errors.push(r.reason)
218
+ } else {
219
+ // otherwise, suppress (but still log via logger)
220
+ logger?.error(r.reason)
221
+ }
222
+ }
223
+
224
+ if (errors.length) {
225
+ throw new AggregateError(errors, `pMap resulted in ${errors.length} error(s)`)
226
+ }
227
+
228
+ return ret
229
+ }