@naturalcycles/js-lib 14.217.0 → 14.219.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/array/array.util.d.ts +6 -1
- package/dist/array/array.util.js +12 -2
- package/dist/promise/pMap.d.ts +13 -1
- package/dist/promise/pMap.js +81 -64
- package/dist/string/leven.d.ts +4 -1
- package/dist/string/leven.js +9 -2
- package/dist-esm/array/array.util.js +12 -2
- package/dist-esm/promise/pMap.js +81 -64
- package/dist-esm/string/leven.js +9 -2
- package/package.json +1 -1
- package/src/array/array.util.ts +11 -2
- package/src/promise/pMap.ts +100 -67
- package/src/string/leven.ts +7 -2
|
@@ -115,8 +115,13 @@ export declare function _dropWhile<T>(items: T[], predicate: Predicate<T>): T[];
|
|
|
115
115
|
export declare function _dropRightWhile<T>(items: T[], predicate: Predicate<T>): T[];
|
|
116
116
|
/**
|
|
117
117
|
* Counts how many items match the predicate.
|
|
118
|
+
*
|
|
119
|
+
* `limit` allows to exit early when limit count is reached, skipping further iterations (perf optimization).
|
|
120
|
+
*/
|
|
121
|
+
export declare function _count<T>(items: T[], predicate: AbortablePredicate<T>, limit?: number): number;
|
|
122
|
+
/**
|
|
123
|
+
* `limit` allows to exit early when limit count is reached, skipping further iterations (perf optimization).
|
|
118
124
|
*/
|
|
119
|
-
export declare function _count<T>(items: T[], predicate: AbortablePredicate<T>): number;
|
|
120
125
|
export declare function _countBy<T>(items: T[], mapper: Mapper<T, any>): StringMap<number>;
|
|
121
126
|
/**
|
|
122
127
|
* Returns an intersection between 2 arrays.
|
package/dist/array/array.util.js
CHANGED
|
@@ -206,19 +206,29 @@ function _dropRightWhile(items, predicate) {
|
|
|
206
206
|
exports._dropRightWhile = _dropRightWhile;
|
|
207
207
|
/**
|
|
208
208
|
* Counts how many items match the predicate.
|
|
209
|
+
*
|
|
210
|
+
* `limit` allows to exit early when limit count is reached, skipping further iterations (perf optimization).
|
|
209
211
|
*/
|
|
210
|
-
function _count(items, predicate) {
|
|
212
|
+
function _count(items, predicate, limit) {
|
|
213
|
+
if (limit === 0)
|
|
214
|
+
return 0;
|
|
211
215
|
let count = 0;
|
|
212
216
|
for (const [i, item] of items.entries()) {
|
|
213
217
|
const r = predicate(item, i);
|
|
214
218
|
if (r === types_1.END)
|
|
215
219
|
break;
|
|
216
|
-
if (r)
|
|
220
|
+
if (r) {
|
|
217
221
|
count++;
|
|
222
|
+
if (limit && count >= limit)
|
|
223
|
+
break;
|
|
224
|
+
}
|
|
218
225
|
}
|
|
219
226
|
return count;
|
|
220
227
|
}
|
|
221
228
|
exports._count = _count;
|
|
229
|
+
/**
|
|
230
|
+
* `limit` allows to exit early when limit count is reached, skipping further iterations (perf optimization).
|
|
231
|
+
*/
|
|
222
232
|
function _countBy(items, mapper) {
|
|
223
233
|
const map = {};
|
|
224
234
|
items.forEach((item, i) => {
|
package/dist/promise/pMap.d.ts
CHANGED
|
@@ -4,7 +4,11 @@ export interface PMapOptions {
|
|
|
4
4
|
/**
|
|
5
5
|
* Number of concurrently pending promises returned by `mapper`.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
7
|
+
* Defaults to 16.
|
|
8
|
+
*
|
|
9
|
+
* It previously (and originally) defaulted to Infinity, which was later changed,
|
|
10
|
+
* because it's somewhat dangerous to run "infinite number of parallel promises".
|
|
11
|
+
* You can still emulate the old behavior by passing `Infinity`.
|
|
8
12
|
*/
|
|
9
13
|
concurrency?: number;
|
|
10
14
|
/**
|
|
@@ -23,6 +27,14 @@ export interface PMapOptions {
|
|
|
23
27
|
logger?: CommonLogger | null;
|
|
24
28
|
}
|
|
25
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
|
+
*
|
|
26
38
|
* Returns a `Promise` that is fulfilled when all promises in `input` and ones returned from `mapper` are fulfilled,
|
|
27
39
|
* or rejects if any of the promises reject. The fulfilled value is an `Array` of the fulfilled values returned
|
|
28
40
|
* from `mapper` in `input` order.
|
package/dist/promise/pMap.js
CHANGED
|
@@ -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 =
|
|
48
|
-
const errors = [];
|
|
49
|
-
let isSettled = false;
|
|
50
|
-
let resolvingCount = 0;
|
|
51
|
-
let currentIndex = 0;
|
|
44
|
+
const { concurrency = 16, 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
|
-
|
|
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
|
-
|
|
81
|
-
|
|
82
|
-
|
|
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: concurrency === Infinity or items.length <= concurrency
|
|
51
|
+
if (concurrency === Infinity || 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
|
+
}
|
package/dist/string/leven.d.ts
CHANGED
|
@@ -2,5 +2,8 @@
|
|
|
2
2
|
* Modified version of: https://github.com/sindresorhus/leven/
|
|
3
3
|
*
|
|
4
4
|
* Returns a Levenshtein distance between first and second word.
|
|
5
|
+
*
|
|
6
|
+
* `limit` optional parameter can be used to limit the distance calculation
|
|
7
|
+
* and skip unnecessary iterations when limit is reached.
|
|
5
8
|
*/
|
|
6
|
-
export declare function _leven(first: string, second: string): number;
|
|
9
|
+
export declare function _leven(first: string, second: string, limit?: number): number;
|
package/dist/string/leven.js
CHANGED
|
@@ -8,9 +8,12 @@ const characterCodeCache = [];
|
|
|
8
8
|
* Modified version of: https://github.com/sindresorhus/leven/
|
|
9
9
|
*
|
|
10
10
|
* Returns a Levenshtein distance between first and second word.
|
|
11
|
+
*
|
|
12
|
+
* `limit` optional parameter can be used to limit the distance calculation
|
|
13
|
+
* and skip unnecessary iterations when limit is reached.
|
|
11
14
|
*/
|
|
12
|
-
function _leven(first, second) {
|
|
13
|
-
if (first === second) {
|
|
15
|
+
function _leven(first, second, limit) {
|
|
16
|
+
if (first === second || limit === 0) {
|
|
14
17
|
return 0;
|
|
15
18
|
}
|
|
16
19
|
const swap = first;
|
|
@@ -40,6 +43,8 @@ function _leven(first, second) {
|
|
|
40
43
|
firstLength -= start;
|
|
41
44
|
secondLength -= start;
|
|
42
45
|
if (firstLength === 0) {
|
|
46
|
+
if (limit && secondLength >= limit)
|
|
47
|
+
return limit;
|
|
43
48
|
return secondLength;
|
|
44
49
|
}
|
|
45
50
|
let bCharacterCode;
|
|
@@ -56,6 +61,8 @@ function _leven(first, second) {
|
|
|
56
61
|
bCharacterCode = second.charCodeAt(start + index2);
|
|
57
62
|
temporary = index2++;
|
|
58
63
|
result = index2;
|
|
64
|
+
if (limit && result >= limit)
|
|
65
|
+
return limit; // exit early on limit
|
|
59
66
|
for (index = 0; index < firstLength; index++) {
|
|
60
67
|
temporary2 = bCharacterCode === characterCodeCache[index] ? temporary : temporary + 1;
|
|
61
68
|
temporary = array[index];
|
|
@@ -188,18 +188,28 @@ export function _dropRightWhile(items, predicate) {
|
|
|
188
188
|
}
|
|
189
189
|
/**
|
|
190
190
|
* Counts how many items match the predicate.
|
|
191
|
+
*
|
|
192
|
+
* `limit` allows to exit early when limit count is reached, skipping further iterations (perf optimization).
|
|
191
193
|
*/
|
|
192
|
-
export function _count(items, predicate) {
|
|
194
|
+
export function _count(items, predicate, limit) {
|
|
195
|
+
if (limit === 0)
|
|
196
|
+
return 0;
|
|
193
197
|
let count = 0;
|
|
194
198
|
for (const [i, item] of items.entries()) {
|
|
195
199
|
const r = predicate(item, i);
|
|
196
200
|
if (r === END)
|
|
197
201
|
break;
|
|
198
|
-
if (r)
|
|
202
|
+
if (r) {
|
|
199
203
|
count++;
|
|
204
|
+
if (limit && count >= limit)
|
|
205
|
+
break;
|
|
206
|
+
}
|
|
200
207
|
}
|
|
201
208
|
return count;
|
|
202
209
|
}
|
|
210
|
+
/**
|
|
211
|
+
* `limit` allows to exit early when limit count is reached, skipping further iterations (perf optimization).
|
|
212
|
+
*/
|
|
203
213
|
export function _countBy(items, mapper) {
|
|
204
214
|
const map = {};
|
|
205
215
|
items.forEach((item, i) => {
|
package/dist-esm/promise/pMap.js
CHANGED
|
@@ -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 =
|
|
45
|
-
const errors = [];
|
|
46
|
-
let isSettled = false;
|
|
47
|
-
let resolvingCount = 0;
|
|
48
|
-
let currentIndex = 0;
|
|
41
|
+
const { concurrency = 16, 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
|
-
|
|
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
|
-
|
|
78
|
-
|
|
79
|
-
|
|
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: concurrency === Infinity or items.length <= concurrency
|
|
48
|
+
if (concurrency === Infinity || 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/dist-esm/string/leven.js
CHANGED
|
@@ -5,9 +5,12 @@ const characterCodeCache = [];
|
|
|
5
5
|
* Modified version of: https://github.com/sindresorhus/leven/
|
|
6
6
|
*
|
|
7
7
|
* Returns a Levenshtein distance between first and second word.
|
|
8
|
+
*
|
|
9
|
+
* `limit` optional parameter can be used to limit the distance calculation
|
|
10
|
+
* and skip unnecessary iterations when limit is reached.
|
|
8
11
|
*/
|
|
9
|
-
export function _leven(first, second) {
|
|
10
|
-
if (first === second) {
|
|
12
|
+
export function _leven(first, second, limit) {
|
|
13
|
+
if (first === second || limit === 0) {
|
|
11
14
|
return 0;
|
|
12
15
|
}
|
|
13
16
|
const swap = first;
|
|
@@ -37,6 +40,8 @@ export function _leven(first, second) {
|
|
|
37
40
|
firstLength -= start;
|
|
38
41
|
secondLength -= start;
|
|
39
42
|
if (firstLength === 0) {
|
|
43
|
+
if (limit && secondLength >= limit)
|
|
44
|
+
return limit;
|
|
40
45
|
return secondLength;
|
|
41
46
|
}
|
|
42
47
|
let bCharacterCode;
|
|
@@ -53,6 +58,8 @@ export function _leven(first, second) {
|
|
|
53
58
|
bCharacterCode = second.charCodeAt(start + index2);
|
|
54
59
|
temporary = index2++;
|
|
55
60
|
result = index2;
|
|
61
|
+
if (limit && result >= limit)
|
|
62
|
+
return limit; // exit early on limit
|
|
56
63
|
for (index = 0; index < firstLength; index++) {
|
|
57
64
|
temporary2 = bCharacterCode === characterCodeCache[index] ? temporary : temporary + 1;
|
|
58
65
|
temporary = array[index];
|
package/package.json
CHANGED
package/src/array/array.util.ts
CHANGED
|
@@ -229,19 +229,28 @@ export function _dropRightWhile<T>(items: T[], predicate: Predicate<T>): T[] {
|
|
|
229
229
|
|
|
230
230
|
/**
|
|
231
231
|
* Counts how many items match the predicate.
|
|
232
|
+
*
|
|
233
|
+
* `limit` allows to exit early when limit count is reached, skipping further iterations (perf optimization).
|
|
232
234
|
*/
|
|
233
|
-
export function _count<T>(items: T[], predicate: AbortablePredicate<T
|
|
235
|
+
export function _count<T>(items: T[], predicate: AbortablePredicate<T>, limit?: number): number {
|
|
236
|
+
if (limit === 0) return 0
|
|
234
237
|
let count = 0
|
|
235
238
|
|
|
236
239
|
for (const [i, item] of items.entries()) {
|
|
237
240
|
const r = predicate(item, i)
|
|
238
241
|
if (r === END) break
|
|
239
|
-
if (r)
|
|
242
|
+
if (r) {
|
|
243
|
+
count++
|
|
244
|
+
if (limit && count >= limit) break
|
|
245
|
+
}
|
|
240
246
|
}
|
|
241
247
|
|
|
242
248
|
return count
|
|
243
249
|
}
|
|
244
250
|
|
|
251
|
+
/**
|
|
252
|
+
* `limit` allows to exit early when limit count is reached, skipping further iterations (perf optimization).
|
|
253
|
+
*/
|
|
245
254
|
export function _countBy<T>(items: T[], mapper: Mapper<T, any>): StringMap<number> {
|
|
246
255
|
const map: StringMap<number> = {}
|
|
247
256
|
|
package/src/promise/pMap.ts
CHANGED
|
@@ -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,11 @@ export interface PMapOptions {
|
|
|
14
5
|
/**
|
|
15
6
|
* Number of concurrently pending promises returned by `mapper`.
|
|
16
7
|
*
|
|
17
|
-
*
|
|
8
|
+
* Defaults to 16.
|
|
9
|
+
*
|
|
10
|
+
* It previously (and originally) defaulted to Infinity, which was later changed,
|
|
11
|
+
* because it's somewhat dangerous to run "infinite number of parallel promises".
|
|
12
|
+
* You can still emulate the old behavior by passing `Infinity`.
|
|
18
13
|
*/
|
|
19
14
|
concurrency?: number
|
|
20
15
|
|
|
@@ -36,6 +31,14 @@ export interface PMapOptions {
|
|
|
36
31
|
}
|
|
37
32
|
|
|
38
33
|
/**
|
|
34
|
+
* Forked from https://github.com/sindresorhus/p-map
|
|
35
|
+
*
|
|
36
|
+
* Improvements:
|
|
37
|
+
* - Exported as { pMap }, so IDE auto-completion works
|
|
38
|
+
* - Included Typescript typings (no need for @types/p-map)
|
|
39
|
+
* - Compatible with pProps (that had typings issues)
|
|
40
|
+
* - Preserves async stack traces (in selected cases)
|
|
41
|
+
*
|
|
39
42
|
* Returns a `Promise` that is fulfilled when all promises in `input` and ones returned from `mapper` are fulfilled,
|
|
40
43
|
* or rejects if any of the promises reject. The fulfilled value is an `Array` of the fulfilled values returned
|
|
41
44
|
* from `mapper` in `input` order.
|
|
@@ -66,73 +69,30 @@ export async function pMap<IN, OUT>(
|
|
|
66
69
|
mapper: AbortableAsyncMapper<IN, OUT>,
|
|
67
70
|
opt: PMapOptions = {},
|
|
68
71
|
): Promise<OUT[]> {
|
|
69
|
-
const { logger = console } = opt
|
|
70
|
-
const ret: (OUT | typeof SKIP)[] = []
|
|
71
|
-
// const iterator = iterable[Symbol.iterator]()
|
|
72
72
|
const items = [...iterable]
|
|
73
73
|
const itemsLength = items.length
|
|
74
74
|
if (itemsLength === 0) return [] // short circuit
|
|
75
75
|
|
|
76
|
-
const { concurrency =
|
|
77
|
-
|
|
78
|
-
const errors: Error[] = []
|
|
79
|
-
let isSettled = false
|
|
80
|
-
let resolvingCount = 0
|
|
81
|
-
let currentIndex = 0
|
|
76
|
+
const { concurrency = 16, errorMode = ErrorMode.THROW_IMMEDIATELY, logger = console } = opt
|
|
82
77
|
|
|
83
78
|
// Special cases that are able to preserve async stack traces
|
|
84
|
-
|
|
79
|
+
// Special case: serial execution
|
|
85
80
|
if (concurrency === 1) {
|
|
86
|
-
|
|
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
|
-
}
|
|
81
|
+
return await pMap1(items, mapper, errorMode, logger)
|
|
82
|
+
}
|
|
132
83
|
|
|
133
|
-
|
|
84
|
+
// Special case: concurrency === Infinity or items.length <= concurrency
|
|
85
|
+
if (concurrency === Infinity || items.length <= concurrency) {
|
|
86
|
+
return await pMapAll(items, mapper, errorMode, logger)
|
|
134
87
|
}
|
|
135
88
|
|
|
89
|
+
// General case: execution with throttled concurrency
|
|
90
|
+
const ret: (OUT | typeof SKIP)[] = []
|
|
91
|
+
const errors: Error[] = []
|
|
92
|
+
let isSettled = false
|
|
93
|
+
let resolvingCount = 0
|
|
94
|
+
let currentIndex = 0
|
|
95
|
+
|
|
136
96
|
return await new Promise<OUT[]>((resolve, reject) => {
|
|
137
97
|
const next = (): void => {
|
|
138
98
|
if (isSettled) {
|
|
@@ -198,3 +158,76 @@ export async function pMap<IN, OUT>(
|
|
|
198
158
|
}
|
|
199
159
|
})
|
|
200
160
|
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
pMap with serial (non-concurrent) execution.
|
|
164
|
+
*/
|
|
165
|
+
async function pMap1<IN, OUT>(
|
|
166
|
+
items: IN[],
|
|
167
|
+
mapper: AbortableAsyncMapper<IN, OUT>,
|
|
168
|
+
errorMode: ErrorMode,
|
|
169
|
+
logger: CommonLogger | null,
|
|
170
|
+
): Promise<OUT[]> {
|
|
171
|
+
let i = 0
|
|
172
|
+
const ret: OUT[] = []
|
|
173
|
+
const errors: Error[] = []
|
|
174
|
+
|
|
175
|
+
for (const item of items) {
|
|
176
|
+
try {
|
|
177
|
+
const r = await mapper(item, i++)
|
|
178
|
+
if (r === END) break
|
|
179
|
+
if (r !== SKIP) ret.push(r)
|
|
180
|
+
} catch (err) {
|
|
181
|
+
if (errorMode === ErrorMode.THROW_IMMEDIATELY) throw err
|
|
182
|
+
if (errorMode === ErrorMode.THROW_AGGREGATED) {
|
|
183
|
+
errors.push(err as Error)
|
|
184
|
+
} else {
|
|
185
|
+
// otherwise, suppress (but still log via logger)
|
|
186
|
+
logger?.error(err)
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
if (errors.length) {
|
|
192
|
+
throw new AggregateError(errors, `pMap resulted in ${errors.length} error(s)`)
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
return ret
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
pMap with fully concurrent execution, like Promise.all
|
|
200
|
+
*/
|
|
201
|
+
async function pMapAll<IN, OUT>(
|
|
202
|
+
items: IN[],
|
|
203
|
+
mapper: AbortableAsyncMapper<IN, OUT>,
|
|
204
|
+
errorMode: ErrorMode,
|
|
205
|
+
logger: CommonLogger | null,
|
|
206
|
+
): Promise<OUT[]> {
|
|
207
|
+
if (errorMode === ErrorMode.THROW_IMMEDIATELY) {
|
|
208
|
+
return (await Promise.all(items.map((item, i) => mapper(item, i)))).filter(
|
|
209
|
+
r => r !== SKIP && r !== END,
|
|
210
|
+
) as OUT[]
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
const ret: OUT[] = []
|
|
214
|
+
const errors: Error[] = []
|
|
215
|
+
|
|
216
|
+
for (const r of await Promise.allSettled(items.map((item, i) => mapper(item, i)))) {
|
|
217
|
+
if (r.status === 'fulfilled') {
|
|
218
|
+
if (r.value === END) break
|
|
219
|
+
if (r.value !== SKIP) ret.push(r.value)
|
|
220
|
+
} else if (errorMode === ErrorMode.THROW_AGGREGATED) {
|
|
221
|
+
errors.push(r.reason)
|
|
222
|
+
} else {
|
|
223
|
+
// otherwise, suppress (but still log via logger)
|
|
224
|
+
logger?.error(r.reason)
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
if (errors.length) {
|
|
229
|
+
throw new AggregateError(errors, `pMap resulted in ${errors.length} error(s)`)
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
return ret
|
|
233
|
+
}
|
package/src/string/leven.ts
CHANGED
|
@@ -7,9 +7,12 @@ const characterCodeCache: number[] = []
|
|
|
7
7
|
* Modified version of: https://github.com/sindresorhus/leven/
|
|
8
8
|
*
|
|
9
9
|
* Returns a Levenshtein distance between first and second word.
|
|
10
|
+
*
|
|
11
|
+
* `limit` optional parameter can be used to limit the distance calculation
|
|
12
|
+
* and skip unnecessary iterations when limit is reached.
|
|
10
13
|
*/
|
|
11
|
-
export function _leven(first: string, second: string): number {
|
|
12
|
-
if (first === second) {
|
|
14
|
+
export function _leven(first: string, second: string, limit?: number): number {
|
|
15
|
+
if (first === second || limit === 0) {
|
|
13
16
|
return 0
|
|
14
17
|
}
|
|
15
18
|
|
|
@@ -47,6 +50,7 @@ export function _leven(first: string, second: string): number {
|
|
|
47
50
|
secondLength -= start
|
|
48
51
|
|
|
49
52
|
if (firstLength === 0) {
|
|
53
|
+
if (limit && secondLength >= limit) return limit
|
|
50
54
|
return secondLength
|
|
51
55
|
}
|
|
52
56
|
|
|
@@ -66,6 +70,7 @@ export function _leven(first: string, second: string): number {
|
|
|
66
70
|
bCharacterCode = second.charCodeAt(start + index2)
|
|
67
71
|
temporary = index2++
|
|
68
72
|
result = index2
|
|
73
|
+
if (limit && result >= limit) return limit // exit early on limit
|
|
69
74
|
|
|
70
75
|
for (index = 0; index < firstLength; index++) {
|
|
71
76
|
temporary2 = bCharacterCode === characterCodeCache[index] ? temporary : temporary + 1
|