@naturalcycles/js-lib 14.70.2 → 14.71.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.
@@ -21,4 +21,4 @@ export declare function _try<ERR = unknown, RETURN = void>(fn: () => RETURN): [e
21
21
  * Also, intentionally types second return item as non-optional,
22
22
  * but you should check for `err` presense first!
23
23
  */
24
- export declare function pTry<ERR = unknown, RETURN = void>(promise: Promise<RETURN>): Promise<[err: ERR | null, value: RETURN]>;
24
+ export declare function pTry<ERR = unknown, RETURN = void>(promise: Promise<RETURN>): Promise<[err: ERR | null, value: Awaited<RETURN>]>;
package/dist/error/try.js CHANGED
@@ -26,6 +26,8 @@ function _try(fn) {
26
26
  }
27
27
  }
28
28
  exports._try = _try;
29
+ // todo: remove when eslint starts to know about Awaited
30
+ /* eslint-disable no-undef */
29
31
  /**
30
32
  * Like _try, but for Promises.
31
33
  *
package/dist/index.d.ts CHANGED
@@ -50,12 +50,13 @@ import { _jsonParseIfPossible } from './string/json.util';
50
50
  import { _capitalize, _lowerFirst, _nl2br, _removeWhitespace, _replaceAll, _split, _substringAfter, _substringAfterLast, _substringBefore, _substringBeforeLast, _substringBetweenLast, _truncate, _truncateMiddle, _upperFirst } from './string/string.util';
51
51
  import { JsonStringifyFunction, StringifyAnyOptions, _stringifyAny } from './string/stringifyAny';
52
52
  import { _ms, _since } from './time/time.util';
53
- import { Class, ConditionalExcept, ConditionalPick, Merge, Promisable, PromiseValue, ReadonlyDeep, Simplify } from './typeFest';
54
- import { AsyncMapper, AsyncPredicate, BaseDBEntity, CreatedUpdated, CreatedUpdatedId, ObjectWithId, AnyObjectWithId, Saved, Unsaved, BatchResult, InstanceId, IsoDate, IsoDateTime, KeyValueTuple, Mapper, ObjectMapper, ObjectPredicate, Predicate, PromiseMap, AnyObject, AnyFunction, Reviver, SavedDBEntity, StringMap, UnixTimestamp, ValueOf, ValuesOf, _noop, _objectKeys, _passNothingPredicate, _passthroughMapper, _passthroughPredicate, _passUndefinedMapper, _stringMapEntries, _stringMapValues } from './types';
53
+ import { Class, ConditionalExcept, ConditionalPick, Merge, Promisable, ReadonlyDeep, Simplify } from './typeFest';
54
+ import { AsyncMapper, AsyncPredicate, BaseDBEntity, CreatedUpdated, CreatedUpdatedId, ObjectWithId, AnyObjectWithId, Saved, Unsaved, BatchResult, InstanceId, IsoDate, IsoDateTime, KeyValueTuple, Mapper, ObjectMapper, ObjectPredicate, Predicate, PromiseMap, AnyObject, AnyFunction, Reviver, SavedDBEntity, StringMap, UnixTimestamp, ValueOf, ValuesOf, AbortableMapper, AbortableAsyncPredicate, AbortableAsyncMapper, AbortablePredicate, END, SKIP, _noop, _objectKeys, _passNothingPredicate, _passthroughMapper, _passthroughPredicate, _passUndefinedMapper, _stringMapEntries, _stringMapValues } from './types';
55
55
  import { _gb, _hb, _kb, _mb } from './unit/size.util';
56
56
  import { is } from './vendor/is';
57
57
  import { CommonLogLevel, CommonLogFunction, CommonLogger, commonLoggerMinLevel, commonLoggerNoop, commonLogLevelNumber, commonLoggerPipe, commonLoggerPrefix, CommonLogWithLevelFunction, commonLoggerCreate } from './log/commonLogger';
58
58
  import { _safeJsonStringify } from './string/safeJsonStringify';
59
59
  import { PQueue, PQueueCfg } from './promise/pQueue';
60
- export type { PQueueCfg, MemoCache, PromiseDecoratorCfg, PromiseDecoratorResp, ErrorData, ErrorObject, HttpErrorData, HttpErrorResponse, Admin401ErrorData, Admin403ErrorData, StringMap, PromiseMap, AnyObject, AnyFunction, ValuesOf, ValueOf, KeyValueTuple, ObjectMapper, ObjectPredicate, InstanceId, IsoDate, IsoDateTime, Reviver, PMapOptions, Mapper, AsyncMapper, Predicate, AsyncPredicate, BatchResult, DeferredPromise, PRetryOptions, PTimeoutOptions, TryCatchOptions, StringifyAnyOptions, JsonStringifyFunction, Merge, ReadonlyDeep, Promisable, PromiseValue, Simplify, ConditionalPick, ConditionalExcept, Class, UnixTimestamp, BaseDBEntity, SavedDBEntity, Saved, Unsaved, CreatedUpdated, CreatedUpdatedId, ObjectWithId, AnyObjectWithId, JsonSchema, JsonSchemaAny, JsonSchemaOneOf, JsonSchemaAllOf, JsonSchemaAnyOf, JsonSchemaNot, JsonSchemaRef, JsonSchemaConst, JsonSchemaEnum, JsonSchemaString, JsonSchemaNumber, JsonSchemaBoolean, JsonSchemaNull, JsonSchemaRootObject, JsonSchemaObject, JsonSchemaArray, JsonSchemaTuple, JsonSchemaBuilder, CommonLogLevel, CommonLogWithLevelFunction, CommonLogFunction, CommonLogger, };
61
- export { is, _Memo, _memoFn, _LogMethod, _getArgsSignature, _createPromiseDecorator, AppError, HttpError, AssertionError, _assert, _assertEquals, _assertDeepEquals, _assertIsError, _assertIsString, _assertIsNumber, _assertTypeOf, _randomInt, _randomArrayItem, _createDeterministicRandom, _inRange, _stringMapValues, _stringMapEntries, _objectKeys, _capitalize, _upperFirst, _lowerFirst, _split, _removeWhitespace, _substringBefore, _substringBeforeLast, _substringAfter, _substringAfterLast, _substringBetweenLast, _replaceAll, _nl2br, _truncate, _truncateMiddle, _pick, _omit, _filterFalsyValues, _filterUndefinedValues, _filterNullishValues, _filterEmptyArrays, _filterEmptyValues, _filterObject, _undefinedIfEmpty, _isObject, _isPrimitive, _mapKeys, _mapValues, _mapObject, _objectNullValuesToUndefined, _deepEquals, _deepCopy, _isEmptyObject, _isEmpty, _merge, _deepTrim, _sortObjectDeep, _sortObject, _get, _set, _has, _unset, _mask, _invert, _invertMap, _by, _groupBy, _sortBy, _sortNumbers, _toFixed, _toPrecision, _round, _findLast, _takeWhile, _takeRightWhile, _dropWhile, _dropRightWhile, _countBy, _intersection, _difference, _shuffle, _mapToObject, _findKeyByValue, _range, _uniq, _uniqBy, _flatten, _flattenDeep, _chunk, SimpleMovingAverage, _average, _averageWeighted, _percentile, _median, _debounce, _throttle, _Debounce, _Throttle, pMap, _passthroughMapper, _passUndefinedMapper, _passthroughPredicate, _passNothingPredicate, _noop, pBatch, ErrorMode, pFilter, pProps, pDelay, pDefer, pHang, pState, AggregatedError, pRetry, pTimeout, pTuple, _Retry, _Timeout, _tryCatch, _TryCatch, _try, pTry, _jsonParseIfPossible, _stringifyAny, _ms, _since, _hb, _gb, _mb, _kb, _snakeCase, _camelCase, _kebabCase, _sum, _sumBy, _clamp, _last, mergeJsonSchemaObjects, jsonSchema, JsonSchemaAnyBuilder, JSON_SCHEMA_ORDER, generateJsonSchemaFromData, _parseQueryString, _defineLazyProperty, _defineLazyProps, _lazyValue, commonLoggerMinLevel, commonLoggerNoop, commonLogLevelNumber, commonLoggerPipe, commonLoggerPrefix, commonLoggerCreate, _safeJsonStringify, PQueue, };
60
+ export * from './seq/seq';
61
+ export type { AbortableMapper, AbortablePredicate, AbortableAsyncPredicate, AbortableAsyncMapper, PQueueCfg, MemoCache, PromiseDecoratorCfg, PromiseDecoratorResp, ErrorData, ErrorObject, HttpErrorData, HttpErrorResponse, Admin401ErrorData, Admin403ErrorData, StringMap, PromiseMap, AnyObject, AnyFunction, ValuesOf, ValueOf, KeyValueTuple, ObjectMapper, ObjectPredicate, InstanceId, IsoDate, IsoDateTime, Reviver, PMapOptions, Mapper, AsyncMapper, Predicate, AsyncPredicate, BatchResult, DeferredPromise, PRetryOptions, PTimeoutOptions, TryCatchOptions, StringifyAnyOptions, JsonStringifyFunction, Merge, ReadonlyDeep, Promisable, Simplify, ConditionalPick, ConditionalExcept, Class, UnixTimestamp, BaseDBEntity, SavedDBEntity, Saved, Unsaved, CreatedUpdated, CreatedUpdatedId, ObjectWithId, AnyObjectWithId, JsonSchema, JsonSchemaAny, JsonSchemaOneOf, JsonSchemaAllOf, JsonSchemaAnyOf, JsonSchemaNot, JsonSchemaRef, JsonSchemaConst, JsonSchemaEnum, JsonSchemaString, JsonSchemaNumber, JsonSchemaBoolean, JsonSchemaNull, JsonSchemaRootObject, JsonSchemaObject, JsonSchemaArray, JsonSchemaTuple, JsonSchemaBuilder, CommonLogLevel, CommonLogWithLevelFunction, CommonLogFunction, CommonLogger, };
62
+ export { is, _Memo, _memoFn, _LogMethod, _getArgsSignature, _createPromiseDecorator, AppError, HttpError, AssertionError, _assert, _assertEquals, _assertDeepEquals, _assertIsError, _assertIsString, _assertIsNumber, _assertTypeOf, _randomInt, _randomArrayItem, _createDeterministicRandom, _inRange, _stringMapValues, _stringMapEntries, _objectKeys, _capitalize, _upperFirst, _lowerFirst, _split, _removeWhitespace, _substringBefore, _substringBeforeLast, _substringAfter, _substringAfterLast, _substringBetweenLast, _replaceAll, _nl2br, _truncate, _truncateMiddle, _pick, _omit, _filterFalsyValues, _filterUndefinedValues, _filterNullishValues, _filterEmptyArrays, _filterEmptyValues, _filterObject, _undefinedIfEmpty, _isObject, _isPrimitive, _mapKeys, _mapValues, _mapObject, _objectNullValuesToUndefined, _deepEquals, _deepCopy, _isEmptyObject, _isEmpty, _merge, _deepTrim, _sortObjectDeep, _sortObject, _get, _set, _has, _unset, _mask, _invert, _invertMap, _by, _groupBy, _sortBy, _sortNumbers, _toFixed, _toPrecision, _round, _findLast, _takeWhile, _takeRightWhile, _dropWhile, _dropRightWhile, _countBy, _intersection, _difference, _shuffle, _mapToObject, _findKeyByValue, _range, _uniq, _uniqBy, _flatten, _flattenDeep, _chunk, SimpleMovingAverage, _average, _averageWeighted, _percentile, _median, _debounce, _throttle, _Debounce, _Throttle, pMap, _passthroughMapper, _passUndefinedMapper, _passthroughPredicate, _passNothingPredicate, _noop, pBatch, ErrorMode, pFilter, pProps, pDelay, pDefer, pHang, pState, AggregatedError, pRetry, pTimeout, pTuple, _Retry, _Timeout, _tryCatch, _TryCatch, _try, pTry, _jsonParseIfPossible, _stringifyAny, _ms, _since, _hb, _gb, _mb, _kb, _snakeCase, _camelCase, _kebabCase, _sum, _sumBy, _clamp, _last, mergeJsonSchemaObjects, jsonSchema, JsonSchemaAnyBuilder, JSON_SCHEMA_ORDER, generateJsonSchemaFromData, _parseQueryString, _defineLazyProperty, _defineLazyProps, _lazyValue, commonLoggerMinLevel, commonLoggerNoop, commonLogLevelNumber, commonLoggerPipe, commonLoggerPrefix, commonLoggerCreate, _safeJsonStringify, PQueue, END, SKIP, };
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports._mapValues = exports._mapKeys = exports._isPrimitive = exports._isObject = exports._undefinedIfEmpty = exports._filterObject = exports._filterEmptyValues = exports._filterEmptyArrays = exports._filterNullishValues = exports._filterUndefinedValues = exports._filterFalsyValues = exports._omit = exports._pick = exports._truncateMiddle = exports._truncate = exports._nl2br = exports._replaceAll = exports._substringBetweenLast = exports._substringAfterLast = exports._substringAfter = exports._substringBeforeLast = exports._substringBefore = exports._removeWhitespace = exports._split = exports._lowerFirst = exports._upperFirst = exports._capitalize = exports._objectKeys = exports._stringMapEntries = exports._stringMapValues = exports._inRange = exports._createDeterministicRandom = exports._randomArrayItem = exports._randomInt = exports._assertTypeOf = exports._assertIsNumber = exports._assertIsString = exports._assertIsError = exports._assertDeepEquals = exports._assertEquals = exports._assert = exports.AssertionError = exports.HttpError = exports.AppError = exports._createPromiseDecorator = exports._getArgsSignature = exports._LogMethod = exports._memoFn = exports._Memo = exports.is = void 0;
4
4
  exports._Throttle = exports._Debounce = exports._throttle = exports._debounce = exports._median = exports._percentile = exports._averageWeighted = exports._average = exports.SimpleMovingAverage = exports._chunk = exports._flattenDeep = exports._flatten = exports._uniqBy = exports._uniq = exports._range = exports._findKeyByValue = exports._mapToObject = exports._shuffle = exports._difference = exports._intersection = exports._countBy = exports._dropRightWhile = exports._dropWhile = exports._takeRightWhile = exports._takeWhile = exports._findLast = exports._round = exports._toPrecision = exports._toFixed = exports._sortNumbers = exports._sortBy = exports._groupBy = exports._by = exports._invertMap = exports._invert = exports._mask = exports._unset = exports._has = exports._set = exports._get = exports._sortObject = exports._sortObjectDeep = exports._deepTrim = exports._merge = exports._isEmpty = exports._isEmptyObject = exports._deepCopy = exports._deepEquals = exports._objectNullValuesToUndefined = exports._mapObject = void 0;
5
5
  exports.commonLoggerNoop = exports.commonLoggerMinLevel = exports._lazyValue = exports._defineLazyProps = exports._defineLazyProperty = exports._parseQueryString = exports.generateJsonSchemaFromData = exports.JSON_SCHEMA_ORDER = exports.JsonSchemaAnyBuilder = exports.jsonSchema = exports.mergeJsonSchemaObjects = exports._last = exports._clamp = exports._sumBy = exports._sum = exports._kebabCase = exports._camelCase = exports._snakeCase = exports._kb = exports._mb = exports._gb = exports._hb = exports._since = exports._ms = exports._stringifyAny = exports._jsonParseIfPossible = exports.pTry = exports._try = exports._TryCatch = exports._tryCatch = exports._Timeout = exports._Retry = exports.pTuple = exports.pTimeout = exports.pRetry = exports.AggregatedError = exports.pState = exports.pHang = exports.pDefer = exports.pDelay = exports.pProps = exports.pFilter = exports.ErrorMode = exports.pBatch = exports._noop = exports._passNothingPredicate = exports._passthroughPredicate = exports._passUndefinedMapper = exports._passthroughMapper = exports.pMap = void 0;
6
- exports.PQueue = exports._safeJsonStringify = exports.commonLoggerCreate = exports.commonLoggerPrefix = exports.commonLoggerPipe = exports.commonLogLevelNumber = void 0;
6
+ exports.SKIP = exports.END = exports.PQueue = exports._safeJsonStringify = exports.commonLoggerCreate = exports.commonLoggerPrefix = exports.commonLoggerPipe = exports.commonLogLevelNumber = void 0;
7
7
  const tslib_1 = require("tslib");
8
8
  const array_util_1 = require("./array/array.util");
9
9
  Object.defineProperty(exports, "_by", { enumerable: true, get: function () { return array_util_1._by; } });
@@ -190,6 +190,8 @@ const time_util_1 = require("./time/time.util");
190
190
  Object.defineProperty(exports, "_ms", { enumerable: true, get: function () { return time_util_1._ms; } });
191
191
  Object.defineProperty(exports, "_since", { enumerable: true, get: function () { return time_util_1._since; } });
192
192
  const types_1 = require("./types");
193
+ Object.defineProperty(exports, "END", { enumerable: true, get: function () { return types_1.END; } });
194
+ Object.defineProperty(exports, "SKIP", { enumerable: true, get: function () { return types_1.SKIP; } });
193
195
  Object.defineProperty(exports, "_noop", { enumerable: true, get: function () { return types_1._noop; } });
194
196
  Object.defineProperty(exports, "_objectKeys", { enumerable: true, get: function () { return types_1._objectKeys; } });
195
197
  Object.defineProperty(exports, "_passNothingPredicate", { enumerable: true, get: function () { return types_1._passNothingPredicate; } });
@@ -216,3 +218,4 @@ const safeJsonStringify_1 = require("./string/safeJsonStringify");
216
218
  Object.defineProperty(exports, "_safeJsonStringify", { enumerable: true, get: function () { return safeJsonStringify_1._safeJsonStringify; } });
217
219
  const pQueue_1 = require("./promise/pQueue");
218
220
  Object.defineProperty(exports, "PQueue", { enumerable: true, get: function () { return pQueue_1.PQueue; } });
221
+ (0, tslib_1.__exportStar)(require("./seq/seq"), exports);
@@ -1,8 +1,7 @@
1
- import { BatchResult } from '..';
2
- import { AsyncMapper } from '../types';
1
+ import { AbortableAsyncMapper, BatchResult } from '..';
3
2
  /**
4
3
  * Like pMap, but doesn't fail on errors, instead returns both successful results and errors.
5
4
  */
6
- export declare function pBatch<IN, OUT>(iterable: Iterable<IN | PromiseLike<IN>>, mapper: AsyncMapper<IN, OUT>, opt?: {
5
+ export declare function pBatch<IN, OUT>(iterable: Iterable<IN | PromiseLike<IN>>, mapper: AbortableAsyncMapper<IN, OUT>, opt?: {
7
6
  concurrency?: number;
8
7
  }): Promise<BatchResult<OUT>>;
@@ -1,3 +1,3 @@
1
- import { AsyncPredicate } from '../types';
1
+ import { AbortableAsyncPredicate } from '../types';
2
2
  import { PMapOptions } from './pMap';
3
- export declare function pFilter<T>(iterable: Iterable<T | PromiseLike<T>>, filterFn: AsyncPredicate<T>, opt?: PMapOptions): Promise<T[]>;
3
+ export declare function pFilter<T>(iterable: Iterable<T | PromiseLike<T>>, filterFn: AbortableAsyncPredicate<T>, opt?: PMapOptions): Promise<T[]>;
@@ -1,5 +1,4 @@
1
- import { ErrorMode } from '..';
2
- import { AsyncMapper } from '../types';
1
+ import { AbortableAsyncMapper, ErrorMode } from '..';
3
2
  export interface PMapOptions {
4
3
  /**
5
4
  * Number of concurrently pending promises returned by `mapper`.
@@ -42,4 +41,4 @@ export interface PMapOptions {
42
41
  * //=> ['http://ava.li/', 'http://todomvc.com/']
43
42
  * })();
44
43
  */
45
- export declare function pMap<IN, OUT>(iterable: Iterable<IN | PromiseLike<IN>>, mapper: AsyncMapper<IN, OUT>, opt?: PMapOptions): Promise<OUT[]>;
44
+ export declare function pMap<IN, OUT>(iterable: Iterable<IN | PromiseLike<IN>>, mapper: AbortableAsyncMapper<IN, OUT>, opt?: PMapOptions): Promise<OUT[]>;
@@ -43,25 +43,27 @@ async function pMap(iterable, mapper, opt = {}) {
43
43
  const ret = [];
44
44
  const iterator = iterable[Symbol.iterator]();
45
45
  const errors = [];
46
- let isRejected = false;
46
+ let isSettled = false;
47
47
  let isIterableDone = false;
48
48
  let resolvingCount = 0;
49
49
  let currentIndex = 0;
50
- const next = () => {
51
- if (isRejected) {
50
+ const next = (skipped = false) => {
51
+ if (isSettled) {
52
52
  return;
53
53
  }
54
54
  const nextItem = iterator.next();
55
55
  const i = currentIndex;
56
- currentIndex++;
56
+ if (!skipped)
57
+ currentIndex++;
57
58
  if (nextItem.done) {
58
59
  isIterableDone = true;
59
60
  if (resolvingCount === 0) {
61
+ const r = ret.filter(r => r !== __1.SKIP);
60
62
  if (errors.length && errorMode === __1.ErrorMode.THROW_AGGREGATED) {
61
- reject(new AggregatedError_1.AggregatedError(errors, ret));
63
+ reject(new AggregatedError_1.AggregatedError(errors, r));
62
64
  }
63
65
  else {
64
- resolve(ret);
66
+ resolve(r);
65
67
  }
66
68
  }
67
69
  return;
@@ -70,12 +72,16 @@ async function pMap(iterable, mapper, opt = {}) {
70
72
  Promise.resolve(nextItem.value)
71
73
  .then(async (element) => await mapper(element, i))
72
74
  .then(value => {
75
+ if (value === __1.END) {
76
+ isSettled = true;
77
+ return resolve(ret.filter(r => r !== __1.SKIP));
78
+ }
73
79
  ret[i] = value;
74
80
  resolvingCount--;
75
81
  next();
76
82
  }, err => {
77
83
  if (errorMode === __1.ErrorMode.THROW_IMMEDIATELY) {
78
- isRejected = true;
84
+ isSettled = true;
79
85
  reject(err);
80
86
  }
81
87
  else {
@@ -5,4 +5,6 @@ import { PMapOptions } from './pMap';
5
5
  */
6
6
  export declare function pProps<T>(input: {
7
7
  [K in keyof T]: T[K] | Promise<T[K]>;
8
- }, opt?: PMapOptions): Promise<T>;
8
+ }, opt?: PMapOptions): Promise<{
9
+ [K in keyof T]: Awaited<T[K]>;
10
+ }>;
@@ -11,17 +11,16 @@ Improvements:
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.pProps = void 0;
13
13
  const pMap_1 = require("./pMap");
14
+ // todo: remove when eslint starts to know about Awaited
15
+ /* eslint-disable no-undef */
14
16
  /**
15
17
  * Promise.all for Object instead of Array.
16
18
  * Supports concurrency.
17
19
  */
18
20
  async function pProps(input, opt) {
19
- const keys = Object.keys(input);
20
- const values = await (0, pMap_1.pMap)(Object.values(input), r => r, opt);
21
21
  const r = {};
22
- values.forEach((v, i) => {
23
- r[keys[i]] = v;
24
- });
22
+ const keys = Object.keys(input);
23
+ await (0, pMap_1.pMap)(Object.values(input), (v, i) => (r[keys[i]] = v), opt);
25
24
  return r;
26
25
  }
27
26
  exports.pProps = pProps;
@@ -0,0 +1,30 @@
1
+ import { AbortableMapper, AbortablePredicate, END } from '../types';
2
+ /**
3
+ * Inspired by Kotlin Sequences.
4
+ * Similar to arrays, but with lazy evaluation, abortable.
5
+ * Can be useful when it's not feasible/performant to create an array of values to iterate upfront
6
+ * (e.g to construct 1000 Dayjs instances only to find that 2 of them were needed).
7
+ *
8
+ * @experimental
9
+ */
10
+ export declare class Seq<T> implements Iterable<T> {
11
+ private nextFn;
12
+ private constructor();
13
+ [Symbol.iterator](): Iterator<T>;
14
+ static create<T>(initialValue: T | typeof END, nextFn: AbortableMapper<T, T>): Seq<T>;
15
+ static range(minIncl: number, maxExcl: number, step?: number): Seq<number>;
16
+ static from<T>(a: Iterable<T>): Seq<T>;
17
+ static empty<T = any>(): Seq<T>;
18
+ private currentValue;
19
+ private sentInitialValue;
20
+ private i;
21
+ next(): T | typeof END;
22
+ find(predicate: AbortablePredicate<T>): T | undefined;
23
+ some(predicate: AbortablePredicate<T>): boolean;
24
+ every(predicate: AbortablePredicate<T>): boolean;
25
+ toArray(): T[];
26
+ }
27
+ /**
28
+ * Convenience function to create a Sequence.
29
+ */
30
+ export declare function _seq<T>(initialValue: T | typeof END, nextFn: AbortableMapper<T, T>): Seq<T>;
@@ -0,0 +1,141 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports._seq = exports.Seq = void 0;
4
+ const types_1 = require("../types");
5
+ /**
6
+ * Inspired by Kotlin Sequences.
7
+ * Similar to arrays, but with lazy evaluation, abortable.
8
+ * Can be useful when it's not feasible/performant to create an array of values to iterate upfront
9
+ * (e.g to construct 1000 Dayjs instances only to find that 2 of them were needed).
10
+ *
11
+ * @experimental
12
+ */
13
+ class Seq {
14
+ constructor(initialValue, nextFn) {
15
+ this.nextFn = nextFn;
16
+ this.sentInitialValue = false;
17
+ this.i = -1;
18
+ this.currentValue = initialValue;
19
+ }
20
+ [Symbol.iterator]() {
21
+ return {
22
+ next: () => {
23
+ const value = this.next();
24
+ return value === types_1.END ? { done: true, value: undefined } : { value };
25
+ },
26
+ };
27
+ }
28
+ static create(initialValue, nextFn) {
29
+ return new Seq(initialValue, nextFn);
30
+ }
31
+ static range(minIncl, maxExcl, step = 1) {
32
+ const max = maxExcl - step;
33
+ return new Seq(minIncl, n => (n < max ? n + step : types_1.END));
34
+ }
35
+ static from(a) {
36
+ const it = a[Symbol.iterator]();
37
+ const v = it.next();
38
+ if (v.done)
39
+ return new Seq(types_1.END, () => { });
40
+ return new Seq(v.value, () => {
41
+ const v = it.next();
42
+ if (v.done)
43
+ return types_1.END;
44
+ return v.value;
45
+ });
46
+ }
47
+ static empty() {
48
+ return new Seq(types_1.END, () => { });
49
+ }
50
+ next() {
51
+ if (this.currentValue === types_1.END)
52
+ return types_1.END;
53
+ this.i++;
54
+ let v;
55
+ if (!this.sentInitialValue) {
56
+ this.sentInitialValue = true;
57
+ v = this.currentValue;
58
+ }
59
+ else {
60
+ v = this.nextFn(this.currentValue, this.i);
61
+ }
62
+ // console.log(`_seq`, v)
63
+ if (v === types_1.SKIP)
64
+ return this.next();
65
+ return (this.currentValue = v);
66
+ }
67
+ // Chainable functions - return another (chained) Sequence
68
+ // map<OUT>(mapper: Mapper<T, OUT | typeof SKIP | typeof END>): Seq<OUT> {
69
+ // if (this.currentValue === END) return this as any
70
+ //
71
+ // // Iterate until first valid value, to have as `initialValue` of the new Sequence
72
+ // let v: OUT | typeof SKIP | typeof END
73
+ //
74
+ // while (true) {
75
+ // v = mapper(this.currentValue, ++this.i)
76
+ // if (v === SKIP) continue
77
+ // if (v === END) return this as any
78
+ // }
79
+ //
80
+ // return new Seq<OUT>(v as OUT, (current, i) => {
81
+ // const v = mapper(current, i)
82
+ //
83
+ // })
84
+ // }
85
+ // Final functions - return final value, not a chained sequence
86
+ find(predicate) {
87
+ do {
88
+ const v = this.next();
89
+ if (v === types_1.END)
90
+ return; // not found, end of sequence
91
+ const r = predicate(v, this.i);
92
+ if (r === types_1.END)
93
+ return;
94
+ if (r)
95
+ return v;
96
+ // otherwise proceed
97
+ } while (true); // eslint-disable-line no-constant-condition
98
+ }
99
+ some(predicate) {
100
+ do {
101
+ const v = this.next();
102
+ if (v === types_1.END)
103
+ return false;
104
+ const r = predicate(v, this.i);
105
+ if (r === types_1.END)
106
+ return false;
107
+ if (r)
108
+ return true;
109
+ } while (true); // eslint-disable-line no-constant-condition
110
+ }
111
+ every(predicate) {
112
+ do {
113
+ const v = this.next();
114
+ if (v === types_1.END)
115
+ return true;
116
+ const r = predicate(v, this.i);
117
+ if (r === types_1.END)
118
+ return true;
119
+ if (!r)
120
+ return false;
121
+ } while (true); // eslint-disable-line no-constant-condition
122
+ }
123
+ toArray() {
124
+ const a = [];
125
+ // eslint-disable-next-line no-constant-condition
126
+ while (true) {
127
+ const v = this.next();
128
+ if (v === types_1.END)
129
+ return a;
130
+ a.push(v);
131
+ }
132
+ }
133
+ }
134
+ exports.Seq = Seq;
135
+ /**
136
+ * Convenience function to create a Sequence.
137
+ */
138
+ function _seq(initialValue, nextFn) {
139
+ return Seq.create(initialValue, nextFn);
140
+ }
141
+ exports._seq = _seq;
@@ -130,36 +130,6 @@ export declare type Merge<FirstType, SecondType> = Simplify<Merge_<FirstType, Se
130
130
  ```
131
131
  */
132
132
  export declare type Promisable<T> = T | PromiseLike<T>;
133
- /**
134
- Returns the type that is wrapped inside a `Promise` type.
135
- If the type is a nested Promise, it is unwrapped recursively until a non-Promise type is obtained.
136
- If the type is not a `Promise`, the type itself is returned.
137
-
138
- @example
139
- ```
140
- import {PromiseValue} from 'type-fest';
141
-
142
- type AsyncData = Promise<string>;
143
- let asyncData: PromiseValue<AsyncData> = Promise.resolve('ABC');
144
-
145
- type Data = PromiseValue<AsyncData>;
146
- let data: Data = await asyncData;
147
-
148
- // Here's an example that shows how this type reacts to non-Promise types.
149
- type SyncData = PromiseValue<string>;
150
- let syncData: SyncData = getSyncData();
151
-
152
- // Here's an example that shows how this type reacts to recursive Promise types.
153
- type RecursiveAsyncData = Promise<Promise<string> >;
154
- let recursiveAsyncData: PromiseValue<RecursiveAsyncData> = Promise.resolve(Promise.resolve('ABC'));
155
- ```
156
-
157
- @category Utilities
158
- */
159
- export declare type PromiseValue<PromiseType, Otherwise = PromiseType> = PromiseType extends Promise<infer Value> ? {
160
- 0: PromiseValue<Value>;
161
- 1: Value;
162
- }[PromiseType extends Promise<unknown> ? 0 : 1] : Otherwise;
163
133
  /**
164
134
  Extract the keys from a type where the value type of the key extends the given `Condition`.
165
135
  Internally this is used for the `ConditionalPick` and `ConditionalExcept` types.
package/dist/types.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Merge } from './typeFest';
1
+ import { Merge, Promisable } from './typeFest';
2
2
  /**
3
3
  * Map from String to String (or <T>).
4
4
  *
@@ -37,6 +37,14 @@ export interface AnyObjectWithId extends AnyObject, ObjectWithId {
37
37
  * Because `Function` type is discouraged by eslint.
38
38
  */
39
39
  export declare type AnyFunction = (...args: any[]) => any;
40
+ /**
41
+ * Symbol to indicate END of Sequence.
42
+ */
43
+ export declare const END: unique symbol;
44
+ /**
45
+ * Symbol to indicate SKIP of item (e.g in AbortableMapper)
46
+ */
47
+ export declare const SKIP: unique symbol;
40
48
  /**
41
49
  * Function which is called for every item in `input`. Expected to return a `Promise` or value.
42
50
  */
@@ -50,6 +58,10 @@ export declare const _passUndefinedMapper: Mapper<any, void>;
50
58
  export declare const _noop: (..._args: any[]) => undefined;
51
59
  export declare type Predicate<T> = (item: T, index: number) => boolean;
52
60
  export declare type AsyncPredicate<T> = (item: T, index: number) => boolean | PromiseLike<boolean>;
61
+ export declare type AbortablePredicate<T> = (item: T, i: number) => boolean | typeof END;
62
+ export declare type AbortableAsyncPredicate<T> = (item: T, i: number) => Promisable<boolean | typeof END>;
63
+ export declare type AbortableMapper<IN = any, OUT = any> = (input: IN, i: number) => OUT | typeof SKIP | typeof END;
64
+ export declare type AbortableAsyncMapper<IN = any, OUT = any> = (input: IN, i: number) => Promisable<OUT | typeof SKIP | typeof END>;
53
65
  export declare const _passthroughPredicate: Predicate<any>;
54
66
  export declare const _passNothingPredicate: Predicate<any>;
55
67
  export interface BatchResult<RES = any, ERR = Error> {
package/dist/types.js CHANGED
@@ -1,6 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports._objectKeys = exports._stringMapEntries = exports._stringMapValues = exports._passNothingPredicate = exports._passthroughPredicate = exports._noop = exports._passUndefinedMapper = exports._passthroughMapper = void 0;
3
+ exports._objectKeys = exports._stringMapEntries = exports._stringMapValues = exports._passNothingPredicate = exports._passthroughPredicate = exports._noop = exports._passUndefinedMapper = exports._passthroughMapper = exports.SKIP = exports.END = void 0;
4
+ /**
5
+ * Symbol to indicate END of Sequence.
6
+ */
7
+ exports.END = Symbol('END');
8
+ /**
9
+ * Symbol to indicate SKIP of item (e.g in AbortableMapper)
10
+ */
11
+ exports.SKIP = Symbol('SKIP');
4
12
  const _passthroughMapper = item => item;
5
13
  exports._passthroughMapper = _passthroughMapper;
6
14
  const _passUndefinedMapper = () => undefined;
@@ -22,6 +22,8 @@ export function _try(fn) {
22
22
  return [err, undefined];
23
23
  }
24
24
  }
25
+ // todo: remove when eslint starts to know about Awaited
26
+ /* eslint-disable no-undef */
25
27
  /**
26
28
  * Like _try, but for Promises.
27
29
  *
package/dist-esm/index.js CHANGED
@@ -47,10 +47,11 @@ import { _jsonParseIfPossible } from './string/json.util';
47
47
  import { _capitalize, _lowerFirst, _nl2br, _removeWhitespace, _replaceAll, _split, _substringAfter, _substringAfterLast, _substringBefore, _substringBeforeLast, _substringBetweenLast, _truncate, _truncateMiddle, _upperFirst, } from './string/string.util';
48
48
  import { _stringifyAny } from './string/stringifyAny';
49
49
  import { _ms, _since } from './time/time.util';
50
- import { _noop, _objectKeys, _passNothingPredicate, _passthroughMapper, _passthroughPredicate, _passUndefinedMapper, _stringMapEntries, _stringMapValues, } from './types';
50
+ import { END, SKIP, _noop, _objectKeys, _passNothingPredicate, _passthroughMapper, _passthroughPredicate, _passUndefinedMapper, _stringMapEntries, _stringMapValues, } from './types';
51
51
  import { _gb, _hb, _kb, _mb } from './unit/size.util';
52
52
  import { is } from './vendor/is';
53
53
  import { commonLoggerMinLevel, commonLoggerNoop, commonLogLevelNumber, commonLoggerPipe, commonLoggerPrefix, commonLoggerCreate, } from './log/commonLogger';
54
54
  import { _safeJsonStringify } from './string/safeJsonStringify';
55
55
  import { PQueue } from './promise/pQueue';
56
- export { is, _Memo, _memoFn, _LogMethod, _getArgsSignature, _createPromiseDecorator, AppError, HttpError, AssertionError, _assert, _assertEquals, _assertDeepEquals, _assertIsError, _assertIsString, _assertIsNumber, _assertTypeOf, _randomInt, _randomArrayItem, _createDeterministicRandom, _inRange, _stringMapValues, _stringMapEntries, _objectKeys, _capitalize, _upperFirst, _lowerFirst, _split, _removeWhitespace, _substringBefore, _substringBeforeLast, _substringAfter, _substringAfterLast, _substringBetweenLast, _replaceAll, _nl2br, _truncate, _truncateMiddle, _pick, _omit, _filterFalsyValues, _filterUndefinedValues, _filterNullishValues, _filterEmptyArrays, _filterEmptyValues, _filterObject, _undefinedIfEmpty, _isObject, _isPrimitive, _mapKeys, _mapValues, _mapObject, _objectNullValuesToUndefined, _deepEquals, _deepCopy, _isEmptyObject, _isEmpty, _merge, _deepTrim, _sortObjectDeep, _sortObject, _get, _set, _has, _unset, _mask, _invert, _invertMap, _by, _groupBy, _sortBy, _sortNumbers, _toFixed, _toPrecision, _round, _findLast, _takeWhile, _takeRightWhile, _dropWhile, _dropRightWhile, _countBy, _intersection, _difference, _shuffle, _mapToObject, _findKeyByValue, _range, _uniq, _uniqBy, _flatten, _flattenDeep, _chunk, SimpleMovingAverage, _average, _averageWeighted, _percentile, _median, _debounce, _throttle, _Debounce, _Throttle, pMap, _passthroughMapper, _passUndefinedMapper, _passthroughPredicate, _passNothingPredicate, _noop, pBatch, ErrorMode, pFilter, pProps, pDelay, pDefer, pHang, pState, AggregatedError, pRetry, pTimeout, pTuple, _Retry, _Timeout, _tryCatch, _TryCatch, _try, pTry, _jsonParseIfPossible, _stringifyAny, _ms, _since, _hb, _gb, _mb, _kb, _snakeCase, _camelCase, _kebabCase, _sum, _sumBy, _clamp, _last, mergeJsonSchemaObjects, jsonSchema, JsonSchemaAnyBuilder, JSON_SCHEMA_ORDER, generateJsonSchemaFromData, _parseQueryString, _defineLazyProperty, _defineLazyProps, _lazyValue, commonLoggerMinLevel, commonLoggerNoop, commonLogLevelNumber, commonLoggerPipe, commonLoggerPrefix, commonLoggerCreate, _safeJsonStringify, PQueue, };
56
+ export * from './seq/seq';
57
+ export { is, _Memo, _memoFn, _LogMethod, _getArgsSignature, _createPromiseDecorator, AppError, HttpError, AssertionError, _assert, _assertEquals, _assertDeepEquals, _assertIsError, _assertIsString, _assertIsNumber, _assertTypeOf, _randomInt, _randomArrayItem, _createDeterministicRandom, _inRange, _stringMapValues, _stringMapEntries, _objectKeys, _capitalize, _upperFirst, _lowerFirst, _split, _removeWhitespace, _substringBefore, _substringBeforeLast, _substringAfter, _substringAfterLast, _substringBetweenLast, _replaceAll, _nl2br, _truncate, _truncateMiddle, _pick, _omit, _filterFalsyValues, _filterUndefinedValues, _filterNullishValues, _filterEmptyArrays, _filterEmptyValues, _filterObject, _undefinedIfEmpty, _isObject, _isPrimitive, _mapKeys, _mapValues, _mapObject, _objectNullValuesToUndefined, _deepEquals, _deepCopy, _isEmptyObject, _isEmpty, _merge, _deepTrim, _sortObjectDeep, _sortObject, _get, _set, _has, _unset, _mask, _invert, _invertMap, _by, _groupBy, _sortBy, _sortNumbers, _toFixed, _toPrecision, _round, _findLast, _takeWhile, _takeRightWhile, _dropWhile, _dropRightWhile, _countBy, _intersection, _difference, _shuffle, _mapToObject, _findKeyByValue, _range, _uniq, _uniqBy, _flatten, _flattenDeep, _chunk, SimpleMovingAverage, _average, _averageWeighted, _percentile, _median, _debounce, _throttle, _Debounce, _Throttle, pMap, _passthroughMapper, _passUndefinedMapper, _passthroughPredicate, _passNothingPredicate, _noop, pBatch, ErrorMode, pFilter, pProps, pDelay, pDefer, pHang, pState, AggregatedError, pRetry, pTimeout, pTuple, _Retry, _Timeout, _tryCatch, _TryCatch, _try, pTry, _jsonParseIfPossible, _stringifyAny, _ms, _since, _hb, _gb, _mb, _kb, _snakeCase, _camelCase, _kebabCase, _sum, _sumBy, _clamp, _last, mergeJsonSchemaObjects, jsonSchema, JsonSchemaAnyBuilder, JSON_SCHEMA_ORDER, generateJsonSchemaFromData, _parseQueryString, _defineLazyProperty, _defineLazyProps, _lazyValue, commonLoggerMinLevel, commonLoggerNoop, commonLogLevelNumber, commonLoggerPipe, commonLoggerPrefix, commonLoggerCreate, _safeJsonStringify, PQueue, END, SKIP, };
@@ -6,7 +6,7 @@ Improvements:
6
6
  - Included Typescript typings (no need for @types/p-map)
7
7
  - Compatible with pProps (that had typings issues)
8
8
  */
9
- import { ErrorMode } from '..';
9
+ import { END, ErrorMode, SKIP } from '..';
10
10
  import { AggregatedError } from './AggregatedError';
11
11
  /**
12
12
  * Returns a `Promise` that is fulfilled when all promises in `input` and ones returned from `mapper` are fulfilled,
@@ -40,25 +40,27 @@ export async function pMap(iterable, mapper, opt = {}) {
40
40
  const ret = [];
41
41
  const iterator = iterable[Symbol.iterator]();
42
42
  const errors = [];
43
- let isRejected = false;
43
+ let isSettled = false;
44
44
  let isIterableDone = false;
45
45
  let resolvingCount = 0;
46
46
  let currentIndex = 0;
47
- const next = () => {
48
- if (isRejected) {
47
+ const next = (skipped = false) => {
48
+ if (isSettled) {
49
49
  return;
50
50
  }
51
51
  const nextItem = iterator.next();
52
52
  const i = currentIndex;
53
- currentIndex++;
53
+ if (!skipped)
54
+ currentIndex++;
54
55
  if (nextItem.done) {
55
56
  isIterableDone = true;
56
57
  if (resolvingCount === 0) {
58
+ const r = ret.filter(r => r !== SKIP);
57
59
  if (errors.length && errorMode === ErrorMode.THROW_AGGREGATED) {
58
- reject(new AggregatedError(errors, ret));
60
+ reject(new AggregatedError(errors, r));
59
61
  }
60
62
  else {
61
- resolve(ret);
63
+ resolve(r);
62
64
  }
63
65
  }
64
66
  return;
@@ -67,12 +69,16 @@ export async function pMap(iterable, mapper, opt = {}) {
67
69
  Promise.resolve(nextItem.value)
68
70
  .then(async (element) => await mapper(element, i))
69
71
  .then(value => {
72
+ if (value === END) {
73
+ isSettled = true;
74
+ return resolve(ret.filter(r => r !== SKIP));
75
+ }
70
76
  ret[i] = value;
71
77
  resolvingCount--;
72
78
  next();
73
79
  }, err => {
74
80
  if (errorMode === ErrorMode.THROW_IMMEDIATELY) {
75
- isRejected = true;
81
+ isSettled = true;
76
82
  reject(err);
77
83
  }
78
84
  else {
@@ -8,16 +8,15 @@ Improvements:
8
8
  - Included Typescript typings (no need for @types/p-props)
9
9
  */
10
10
  import { pMap } from './pMap';
11
+ // todo: remove when eslint starts to know about Awaited
12
+ /* eslint-disable no-undef */
11
13
  /**
12
14
  * Promise.all for Object instead of Array.
13
15
  * Supports concurrency.
14
16
  */
15
17
  export async function pProps(input, opt) {
16
- const keys = Object.keys(input);
17
- const values = await pMap(Object.values(input), r => r, opt);
18
18
  const r = {};
19
- values.forEach((v, i) => {
20
- r[keys[i]] = v;
21
- });
19
+ const keys = Object.keys(input);
20
+ await pMap(Object.values(input), (v, i) => (r[keys[i]] = v), opt);
22
21
  return r;
23
22
  }
@@ -0,0 +1,136 @@
1
+ import { END, SKIP } from '../types';
2
+ /**
3
+ * Inspired by Kotlin Sequences.
4
+ * Similar to arrays, but with lazy evaluation, abortable.
5
+ * Can be useful when it's not feasible/performant to create an array of values to iterate upfront
6
+ * (e.g to construct 1000 Dayjs instances only to find that 2 of them were needed).
7
+ *
8
+ * @experimental
9
+ */
10
+ export class Seq {
11
+ constructor(initialValue, nextFn) {
12
+ this.nextFn = nextFn;
13
+ this.sentInitialValue = false;
14
+ this.i = -1;
15
+ this.currentValue = initialValue;
16
+ }
17
+ [Symbol.iterator]() {
18
+ return {
19
+ next: () => {
20
+ const value = this.next();
21
+ return value === END ? { done: true, value: undefined } : { value };
22
+ },
23
+ };
24
+ }
25
+ static create(initialValue, nextFn) {
26
+ return new Seq(initialValue, nextFn);
27
+ }
28
+ static range(minIncl, maxExcl, step = 1) {
29
+ const max = maxExcl - step;
30
+ return new Seq(minIncl, n => (n < max ? n + step : END));
31
+ }
32
+ static from(a) {
33
+ const it = a[Symbol.iterator]();
34
+ const v = it.next();
35
+ if (v.done)
36
+ return new Seq(END, () => { });
37
+ return new Seq(v.value, () => {
38
+ const v = it.next();
39
+ if (v.done)
40
+ return END;
41
+ return v.value;
42
+ });
43
+ }
44
+ static empty() {
45
+ return new Seq(END, () => { });
46
+ }
47
+ next() {
48
+ if (this.currentValue === END)
49
+ return END;
50
+ this.i++;
51
+ let v;
52
+ if (!this.sentInitialValue) {
53
+ this.sentInitialValue = true;
54
+ v = this.currentValue;
55
+ }
56
+ else {
57
+ v = this.nextFn(this.currentValue, this.i);
58
+ }
59
+ // console.log(`_seq`, v)
60
+ if (v === SKIP)
61
+ return this.next();
62
+ return (this.currentValue = v);
63
+ }
64
+ // Chainable functions - return another (chained) Sequence
65
+ // map<OUT>(mapper: Mapper<T, OUT | typeof SKIP | typeof END>): Seq<OUT> {
66
+ // if (this.currentValue === END) return this as any
67
+ //
68
+ // // Iterate until first valid value, to have as `initialValue` of the new Sequence
69
+ // let v: OUT | typeof SKIP | typeof END
70
+ //
71
+ // while (true) {
72
+ // v = mapper(this.currentValue, ++this.i)
73
+ // if (v === SKIP) continue
74
+ // if (v === END) return this as any
75
+ // }
76
+ //
77
+ // return new Seq<OUT>(v as OUT, (current, i) => {
78
+ // const v = mapper(current, i)
79
+ //
80
+ // })
81
+ // }
82
+ // Final functions - return final value, not a chained sequence
83
+ find(predicate) {
84
+ do {
85
+ const v = this.next();
86
+ if (v === END)
87
+ return; // not found, end of sequence
88
+ const r = predicate(v, this.i);
89
+ if (r === END)
90
+ return;
91
+ if (r)
92
+ return v;
93
+ // otherwise proceed
94
+ } while (true); // eslint-disable-line no-constant-condition
95
+ }
96
+ some(predicate) {
97
+ do {
98
+ const v = this.next();
99
+ if (v === END)
100
+ return false;
101
+ const r = predicate(v, this.i);
102
+ if (r === END)
103
+ return false;
104
+ if (r)
105
+ return true;
106
+ } while (true); // eslint-disable-line no-constant-condition
107
+ }
108
+ every(predicate) {
109
+ do {
110
+ const v = this.next();
111
+ if (v === END)
112
+ return true;
113
+ const r = predicate(v, this.i);
114
+ if (r === END)
115
+ return true;
116
+ if (!r)
117
+ return false;
118
+ } while (true); // eslint-disable-line no-constant-condition
119
+ }
120
+ toArray() {
121
+ const a = [];
122
+ // eslint-disable-next-line no-constant-condition
123
+ while (true) {
124
+ const v = this.next();
125
+ if (v === END)
126
+ return a;
127
+ a.push(v);
128
+ }
129
+ }
130
+ }
131
+ /**
132
+ * Convenience function to create a Sequence.
133
+ */
134
+ export function _seq(initialValue, nextFn) {
135
+ return Seq.create(initialValue, nextFn);
136
+ }
package/dist-esm/types.js CHANGED
@@ -1,3 +1,11 @@
1
+ /**
2
+ * Symbol to indicate END of Sequence.
3
+ */
4
+ export const END = Symbol('END');
5
+ /**
6
+ * Symbol to indicate SKIP of item (e.g in AbortableMapper)
7
+ */
8
+ export const SKIP = Symbol('SKIP');
1
9
  export const _passthroughMapper = item => item;
2
10
  export const _passUndefinedMapper = () => undefined;
3
11
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@naturalcycles/js-lib",
3
- "version": "14.70.2",
3
+ "version": "14.71.0",
4
4
  "scripts": {
5
5
  "prepare": "husky install",
6
6
  "build-prod": "build-prod-esm-cjs",
package/src/error/try.ts CHANGED
@@ -24,6 +24,9 @@ export function _try<ERR = unknown, RETURN = void>(
24
24
  }
25
25
  }
26
26
 
27
+ // todo: remove when eslint starts to know about Awaited
28
+ /* eslint-disable no-undef */
29
+
27
30
  /**
28
31
  * Like _try, but for Promises.
29
32
  *
@@ -32,7 +35,7 @@ export function _try<ERR = unknown, RETURN = void>(
32
35
  */
33
36
  export async function pTry<ERR = unknown, RETURN = void>(
34
37
  promise: Promise<RETURN>,
35
- ): Promise<[err: ERR | null, value: RETURN]> {
38
+ ): Promise<[err: ERR | null, value: Awaited<RETURN>]> {
36
39
  try {
37
40
  return [null, await promise]
38
41
  } catch (err) {
package/src/index.ts CHANGED
@@ -173,7 +173,6 @@ import {
173
173
  ConditionalPick,
174
174
  Merge,
175
175
  Promisable,
176
- PromiseValue,
177
176
  ReadonlyDeep,
178
177
  Simplify,
179
178
  } from './typeFest'
@@ -205,6 +204,12 @@ import {
205
204
  UnixTimestamp,
206
205
  ValueOf,
207
206
  ValuesOf,
207
+ AbortableMapper,
208
+ AbortableAsyncPredicate,
209
+ AbortableAsyncMapper,
210
+ AbortablePredicate,
211
+ END,
212
+ SKIP,
208
213
  _noop,
209
214
  _objectKeys,
210
215
  _passNothingPredicate,
@@ -230,8 +235,13 @@ import {
230
235
  } from './log/commonLogger'
231
236
  import { _safeJsonStringify } from './string/safeJsonStringify'
232
237
  import { PQueue, PQueueCfg } from './promise/pQueue'
238
+ export * from './seq/seq'
233
239
 
234
240
  export type {
241
+ AbortableMapper,
242
+ AbortablePredicate,
243
+ AbortableAsyncPredicate,
244
+ AbortableAsyncMapper,
235
245
  PQueueCfg,
236
246
  MemoCache,
237
247
  PromiseDecoratorCfg,
@@ -270,7 +280,6 @@ export type {
270
280
  Merge,
271
281
  ReadonlyDeep,
272
282
  Promisable,
273
- PromiseValue,
274
283
  Simplify,
275
284
  ConditionalPick,
276
285
  ConditionalExcept,
@@ -465,4 +474,6 @@ export {
465
474
  commonLoggerCreate,
466
475
  _safeJsonStringify,
467
476
  PQueue,
477
+ END,
478
+ SKIP,
468
479
  }
@@ -1,5 +1,4 @@
1
- import { BatchResult, ErrorMode } from '..'
2
- import { AsyncMapper } from '../types'
1
+ import { AbortableAsyncMapper, BatchResult, ErrorMode } from '..'
3
2
  import { AggregatedError } from './AggregatedError'
4
3
  import { pMap } from './pMap'
5
4
 
@@ -8,7 +7,7 @@ import { pMap } from './pMap'
8
7
  */
9
8
  export async function pBatch<IN, OUT>(
10
9
  iterable: Iterable<IN | PromiseLike<IN>>,
11
- mapper: AsyncMapper<IN, OUT>,
10
+ mapper: AbortableAsyncMapper<IN, OUT>,
12
11
  opt?: { concurrency?: number },
13
12
  ): Promise<BatchResult<OUT>> {
14
13
  try {
@@ -1,9 +1,9 @@
1
- import { AsyncPredicate } from '../types'
1
+ import { AbortableAsyncPredicate } from '../types'
2
2
  import { pMap, PMapOptions } from './pMap'
3
3
 
4
4
  export async function pFilter<T>(
5
5
  iterable: Iterable<T | PromiseLike<T>>,
6
- filterFn: AsyncPredicate<T>,
6
+ filterFn: AbortableAsyncPredicate<T>,
7
7
  opt?: PMapOptions,
8
8
  ): Promise<T[]> {
9
9
  const values = await pMap(
@@ -7,8 +7,7 @@ Improvements:
7
7
  - Compatible with pProps (that had typings issues)
8
8
  */
9
9
 
10
- import { ErrorMode } from '..'
11
- import { AsyncMapper } from '../types'
10
+ import { AbortableAsyncMapper, END, ErrorMode, SKIP } from '..'
12
11
  import { AggregatedError } from './AggregatedError'
13
12
 
14
13
  export interface PMapOptions {
@@ -57,37 +56,38 @@ export interface PMapOptions {
57
56
  */
58
57
  export async function pMap<IN, OUT>(
59
58
  iterable: Iterable<IN | PromiseLike<IN>>,
60
- mapper: AsyncMapper<IN, OUT>,
59
+ mapper: AbortableAsyncMapper<IN, OUT>,
61
60
  opt: PMapOptions = {},
62
61
  ): Promise<OUT[]> {
63
62
  return new Promise<OUT[]>((resolve, reject) => {
64
63
  const { concurrency = Number.POSITIVE_INFINITY, errorMode = ErrorMode.THROW_IMMEDIATELY } = opt
65
64
 
66
- const ret: OUT[] = []
65
+ const ret: (OUT | typeof SKIP)[] = []
67
66
  const iterator = iterable[Symbol.iterator]()
68
67
  const errors: Error[] = []
69
- let isRejected = false
68
+ let isSettled = false
70
69
  let isIterableDone = false
71
70
  let resolvingCount = 0
72
71
  let currentIndex = 0
73
72
 
74
- const next = () => {
75
- if (isRejected) {
73
+ const next = (skipped = false) => {
74
+ if (isSettled) {
76
75
  return
77
76
  }
78
77
 
79
78
  const nextItem = iterator.next()
80
79
  const i = currentIndex
81
- currentIndex++
80
+ if (!skipped) currentIndex++
82
81
 
83
82
  if (nextItem.done) {
84
83
  isIterableDone = true
85
84
 
86
85
  if (resolvingCount === 0) {
86
+ const r = ret.filter(r => r !== SKIP) as OUT[]
87
87
  if (errors.length && errorMode === ErrorMode.THROW_AGGREGATED) {
88
- reject(new AggregatedError(errors, ret))
88
+ reject(new AggregatedError(errors, r))
89
89
  } else {
90
- resolve(ret)
90
+ resolve(r)
91
91
  }
92
92
  }
93
93
 
@@ -100,13 +100,18 @@ export async function pMap<IN, OUT>(
100
100
  .then(async element => await mapper(element, i))
101
101
  .then(
102
102
  value => {
103
+ if (value === END) {
104
+ isSettled = true
105
+ return resolve(ret.filter(r => r !== SKIP) as OUT[])
106
+ }
107
+
103
108
  ret[i] = value
104
109
  resolvingCount--
105
110
  next()
106
111
  },
107
112
  err => {
108
113
  if (errorMode === ErrorMode.THROW_IMMEDIATELY) {
109
- isRejected = true
114
+ isSettled = true
110
115
  reject(err)
111
116
  } else {
112
117
  errors.push(err)
@@ -10,6 +10,9 @@ Improvements:
10
10
 
11
11
  import { pMap, PMapOptions } from './pMap'
12
12
 
13
+ // todo: remove when eslint starts to know about Awaited
14
+ /* eslint-disable no-undef */
15
+
13
16
  /**
14
17
  * Promise.all for Object instead of Array.
15
18
  * Supports concurrency.
@@ -17,13 +20,9 @@ import { pMap, PMapOptions } from './pMap'
17
20
  export async function pProps<T>(
18
21
  input: { [K in keyof T]: T[K] | Promise<T[K]> },
19
22
  opt?: PMapOptions,
20
- ): Promise<T> {
23
+ ): Promise<{ [K in keyof T]: Awaited<T[K]> }> {
24
+ const r = {} as { [K in keyof T]: Awaited<T[K]> }
21
25
  const keys = Object.keys(input) as (keyof T)[]
22
- const values = await pMap(Object.values(input), r => r, opt)
23
-
24
- const r = {} as T
25
- values.forEach((v, i) => {
26
- r[keys[i]!] = v
27
- })
26
+ await pMap(Object.values(input), (v, i) => (r[keys[i]!] = v), opt)
28
27
  return r
29
28
  }
package/src/seq/seq.ts ADDED
@@ -0,0 +1,143 @@
1
+ import { AbortableMapper, AbortablePredicate, END, SKIP } from '../types'
2
+
3
+ /**
4
+ * Inspired by Kotlin Sequences.
5
+ * Similar to arrays, but with lazy evaluation, abortable.
6
+ * Can be useful when it's not feasible/performant to create an array of values to iterate upfront
7
+ * (e.g to construct 1000 Dayjs instances only to find that 2 of them were needed).
8
+ *
9
+ * @experimental
10
+ */
11
+ export class Seq<T> implements Iterable<T> {
12
+ private constructor(initialValue: T | typeof END, private nextFn: AbortableMapper<T, T>) {
13
+ this.currentValue = initialValue
14
+ }
15
+
16
+ [Symbol.iterator](): Iterator<T> {
17
+ return {
18
+ next: () => {
19
+ const value = this.next()
20
+ return value === END ? { done: true, value: undefined } : { value }
21
+ },
22
+ }
23
+ }
24
+
25
+ static create<T>(initialValue: T | typeof END, nextFn: AbortableMapper<T, T>): Seq<T> {
26
+ return new Seq(initialValue, nextFn)
27
+ }
28
+
29
+ static range(minIncl: number, maxExcl: number, step = 1): Seq<number> {
30
+ const max = maxExcl - step
31
+ return new Seq(minIncl, n => (n < max ? n + step : END))
32
+ }
33
+
34
+ static from<T>(a: Iterable<T>): Seq<T> {
35
+ const it = a[Symbol.iterator]()
36
+ const v = it.next()
37
+ if (v.done) return new Seq<any>(END, () => {})
38
+
39
+ return new Seq(v.value, () => {
40
+ const v = it.next()
41
+ if (v.done) return END
42
+ return v.value
43
+ })
44
+ }
45
+
46
+ static empty<T = any>(): Seq<T> {
47
+ return new Seq(END as any, () => {})
48
+ }
49
+
50
+ private currentValue: T | typeof END
51
+ private sentInitialValue = false
52
+ private i = -1
53
+
54
+ next(): T | typeof END {
55
+ if (this.currentValue === END) return END
56
+
57
+ this.i++
58
+
59
+ let v: T | typeof SKIP | typeof END
60
+
61
+ if (!this.sentInitialValue) {
62
+ this.sentInitialValue = true
63
+ v = this.currentValue
64
+ } else {
65
+ v = this.nextFn(this.currentValue, this.i)
66
+ }
67
+
68
+ // console.log(`_seq`, v)
69
+
70
+ if (v === SKIP) return this.next()
71
+
72
+ return (this.currentValue = v)
73
+ }
74
+
75
+ // Chainable functions - return another (chained) Sequence
76
+ // map<OUT>(mapper: Mapper<T, OUT | typeof SKIP | typeof END>): Seq<OUT> {
77
+ // if (this.currentValue === END) return this as any
78
+ //
79
+ // // Iterate until first valid value, to have as `initialValue` of the new Sequence
80
+ // let v: OUT | typeof SKIP | typeof END
81
+ //
82
+ // while (true) {
83
+ // v = mapper(this.currentValue, ++this.i)
84
+ // if (v === SKIP) continue
85
+ // if (v === END) return this as any
86
+ // }
87
+ //
88
+ // return new Seq<OUT>(v as OUT, (current, i) => {
89
+ // const v = mapper(current, i)
90
+ //
91
+ // })
92
+ // }
93
+
94
+ // Final functions - return final value, not a chained sequence
95
+ find(predicate: AbortablePredicate<T>): T | undefined {
96
+ do {
97
+ const v = this.next()
98
+ if (v === END) return // not found, end of sequence
99
+ const r = predicate(v, this.i)
100
+ if (r === END) return
101
+ if (r) return v
102
+ // otherwise proceed
103
+ } while (true) // eslint-disable-line no-constant-condition
104
+ }
105
+
106
+ some(predicate: AbortablePredicate<T>): boolean {
107
+ do {
108
+ const v = this.next()
109
+ if (v === END) return false
110
+ const r = predicate(v, this.i)
111
+ if (r === END) return false
112
+ if (r) return true
113
+ } while (true) // eslint-disable-line no-constant-condition
114
+ }
115
+
116
+ every(predicate: AbortablePredicate<T>): boolean {
117
+ do {
118
+ const v = this.next()
119
+ if (v === END) return true
120
+ const r = predicate(v, this.i)
121
+ if (r === END) return true
122
+ if (!r) return false
123
+ } while (true) // eslint-disable-line no-constant-condition
124
+ }
125
+
126
+ toArray(): T[] {
127
+ const a: T[] = []
128
+
129
+ // eslint-disable-next-line no-constant-condition
130
+ while (true) {
131
+ const v = this.next()
132
+ if (v === END) return a
133
+ a.push(v)
134
+ }
135
+ }
136
+ }
137
+
138
+ /**
139
+ * Convenience function to create a Sequence.
140
+ */
141
+ export function _seq<T>(initialValue: T | typeof END, nextFn: AbortableMapper<T, T>): Seq<T> {
142
+ return Seq.create(initialValue, nextFn)
143
+ }
package/src/typeFest.ts CHANGED
@@ -151,38 +151,6 @@ export type Merge<FirstType, SecondType> = Simplify<Merge_<FirstType, SecondType
151
151
  */
152
152
  export type Promisable<T> = T | PromiseLike<T>
153
153
 
154
- /**
155
- Returns the type that is wrapped inside a `Promise` type.
156
- If the type is a nested Promise, it is unwrapped recursively until a non-Promise type is obtained.
157
- If the type is not a `Promise`, the type itself is returned.
158
-
159
- @example
160
- ```
161
- import {PromiseValue} from 'type-fest';
162
-
163
- type AsyncData = Promise<string>;
164
- let asyncData: PromiseValue<AsyncData> = Promise.resolve('ABC');
165
-
166
- type Data = PromiseValue<AsyncData>;
167
- let data: Data = await asyncData;
168
-
169
- // Here's an example that shows how this type reacts to non-Promise types.
170
- type SyncData = PromiseValue<string>;
171
- let syncData: SyncData = getSyncData();
172
-
173
- // Here's an example that shows how this type reacts to recursive Promise types.
174
- type RecursiveAsyncData = Promise<Promise<string> >;
175
- let recursiveAsyncData: PromiseValue<RecursiveAsyncData> = Promise.resolve(Promise.resolve('ABC'));
176
- ```
177
-
178
- @category Utilities
179
- */
180
- export type PromiseValue<PromiseType, Otherwise = PromiseType> = PromiseType extends Promise<
181
- infer Value
182
- >
183
- ? { 0: PromiseValue<Value>; 1: Value }[PromiseType extends Promise<unknown> ? 0 : 1]
184
- : Otherwise
185
-
186
154
  /**
187
155
  Extract the keys from a type where the value type of the key extends the given `Condition`.
188
156
  Internally this is used for the `ConditionalPick` and `ConditionalExcept` types.
package/src/types.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Merge } from './typeFest'
1
+ import { Merge, Promisable } from './typeFest'
2
2
 
3
3
  /**
4
4
  * Map from String to String (or <T>).
@@ -45,6 +45,16 @@ export interface AnyObjectWithId extends AnyObject, ObjectWithId {}
45
45
  */
46
46
  export type AnyFunction = (...args: any[]) => any
47
47
 
48
+ /**
49
+ * Symbol to indicate END of Sequence.
50
+ */
51
+ export const END = Symbol('END')
52
+
53
+ /**
54
+ * Symbol to indicate SKIP of item (e.g in AbortableMapper)
55
+ */
56
+ export const SKIP = Symbol('SKIP')
57
+
48
58
  /**
49
59
  * Function which is called for every item in `input`. Expected to return a `Promise` or value.
50
60
  */
@@ -62,6 +72,17 @@ export const _noop = (..._args: any[]): undefined => undefined
62
72
  export type Predicate<T> = (item: T, index: number) => boolean
63
73
  export type AsyncPredicate<T> = (item: T, index: number) => boolean | PromiseLike<boolean>
64
74
 
75
+ export type AbortablePredicate<T> = (item: T, i: number) => boolean | typeof END
76
+ export type AbortableAsyncPredicate<T> = (item: T, i: number) => Promisable<boolean | typeof END>
77
+ export type AbortableMapper<IN = any, OUT = any> = (
78
+ input: IN,
79
+ i: number,
80
+ ) => OUT | typeof SKIP | typeof END
81
+ export type AbortableAsyncMapper<IN = any, OUT = any> = (
82
+ input: IN,
83
+ i: number,
84
+ ) => Promisable<OUT | typeof SKIP | typeof END>
85
+
65
86
  export const _passthroughPredicate: Predicate<any> = () => true
66
87
  export const _passNothingPredicate: Predicate<any> = () => false
67
88