@naturalcycles/js-lib 14.69.4 → 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.
@@ -7,13 +7,12 @@ import { AppError, _jsonParseIfPossible, _stringifyAny, } from '..';
7
7
  *
8
8
  * Alternatively, if you're sure it's Error - you can use `_assertIsError(err)`.
9
9
  */
10
- export function _anyToError(o, opt) {
11
- if (o instanceof Error) {
12
- // Already an Error - return as-is
10
+ export function _anyToError(o, errorClass = Error, opt) {
11
+ if (o instanceof errorClass)
13
12
  return o;
14
- }
15
- const message = _stringifyAny(o, opt);
16
- return new Error(message);
13
+ // If it's an instance of Error, but ErrorClass is something else (e.g AppError) - it'll be "repacked" into AppError
14
+ const errorObject = _isErrorObject(o) ? o : _anyToErrorObject(o, opt);
15
+ return _errorObjectToError(errorObject, errorClass);
17
16
  }
18
17
  /**
19
18
  * Converts "anything" to ErrorObject.
@@ -22,8 +21,9 @@ export function _anyToError(o, opt) {
22
21
  * Objects (not Errors) get converted to prettified JSON string (via `_stringifyAny`).
23
22
  */
24
23
  export function _anyToErrorObject(o, opt) {
24
+ var _a;
25
25
  if (o instanceof Error) {
26
- return _errorToErrorObject(o, opt === null || opt === void 0 ? void 0 : opt.includeErrorStack);
26
+ return _errorToErrorObject(o, (_a = opt === null || opt === void 0 ? void 0 : opt.includeErrorStack) !== null && _a !== void 0 ? _a : true);
27
27
  }
28
28
  o = _jsonParseIfPossible(o);
29
29
  if (_isHttpErrorResponse(o)) {
@@ -43,7 +43,7 @@ export function _anyToErrorObject(o, opt) {
43
43
  data: {}, // empty
44
44
  };
45
45
  }
46
- export function _errorToErrorObject(e, includeErrorStack = false) {
46
+ export function _errorToErrorObject(e, includeErrorStack = true) {
47
47
  const obj = {
48
48
  name: e.name,
49
49
  message: e.message,
@@ -55,17 +55,29 @@ export function _errorToErrorObject(e, includeErrorStack = false) {
55
55
  return obj;
56
56
  }
57
57
  export function _errorObjectToAppError(o) {
58
- const err = Object.assign(new AppError(o.message, o.data), {
58
+ return _errorObjectToError(o, AppError);
59
+ }
60
+ export function _errorObjectToError(o, errorClass = Error) {
61
+ if (o instanceof errorClass)
62
+ return o;
63
+ const err = new errorClass(o.message);
59
64
  // name: err.name, // cannot be assigned to a readonly property like this
60
65
  // stack: o.stack, // also readonly e.g in Firefox
61
- });
62
66
  Object.defineProperty(err, 'name', {
63
67
  value: o.name,
64
68
  configurable: true,
65
69
  });
66
- Object.defineProperty(err, 'stack', {
67
- value: o.stack,
70
+ Object.defineProperty(err, 'data', {
71
+ value: o.data,
72
+ writable: true,
73
+ configurable: true,
74
+ enumerable: false,
68
75
  });
76
+ if (o.stack) {
77
+ Object.defineProperty(err, 'stack', {
78
+ value: o.stack,
79
+ });
80
+ }
69
81
  return err;
70
82
  }
71
83
  export function _isHttpErrorResponse(o) {
@@ -73,10 +85,14 @@ export function _isHttpErrorResponse(o) {
73
85
  }
74
86
  export function _isHttpErrorObject(o) {
75
87
  var _a;
76
- return (typeof (o === null || o === void 0 ? void 0 : o.name) === 'string' &&
77
- typeof (o === null || o === void 0 ? void 0 : o.message) === 'string' &&
78
- typeof ((_a = o === null || o === void 0 ? void 0 : o.data) === null || _a === void 0 ? void 0 : _a.httpStatusCode) === 'number');
88
+ return (!!o &&
89
+ typeof o.name === 'string' &&
90
+ typeof o.message === 'string' &&
91
+ typeof ((_a = o.data) === null || _a === void 0 ? void 0 : _a.httpStatusCode) === 'number');
79
92
  }
93
+ /**
94
+ * Note: any instance of AppError is also automatically an ErrorObject
95
+ */
80
96
  export function _isErrorObject(o) {
81
- return (typeof (o === null || o === void 0 ? void 0 : o.name) === 'string' && typeof (o === null || o === void 0 ? void 0 : o.message) === 'string' && typeof (o === null || o === void 0 ? void 0 : o.data) === 'object');
97
+ return (!!o && typeof o.name === 'string' && typeof o.message === 'string' && typeof o.data === 'object');
82
98
  }
@@ -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
@@ -13,7 +13,7 @@ import { _Retry } from './decorators/retry.decorator';
13
13
  import { _Timeout } from './decorators/timeout.decorator';
14
14
  import { AppError } from './error/app.error';
15
15
  import { AssertionError, _assert, _assertDeepEquals, _assertEquals, _assertIsError, _assertIsNumber, _assertIsString, _assertTypeOf, } from './error/assert';
16
- import { _anyToError, _anyToErrorObject, _errorObjectToAppError, _errorToErrorObject, _isErrorObject, _isHttpErrorObject, _isHttpErrorResponse, } from './error/error.util';
16
+ export * from './error/error.util';
17
17
  import { ErrorMode } from './error/errorMode';
18
18
  import { HttpError } from './error/http.error';
19
19
  import { _try, pTry } from './error/try';
@@ -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, _isErrorObject, _isHttpErrorObject, _isHttpErrorResponse, _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, _anyToError, _anyToErrorObject, _errorToErrorObject, _errorObjectToAppError, _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
+ }
@@ -1,9 +1,12 @@
1
+ // const possibleJsonStartTokens = ['{', '[', '"']
2
+ const DETECT_JSON = /^\s*[{["\-\d]/;
1
3
  /**
2
4
  * Attempts to parse object as JSON.
3
5
  * Returns original object if JSON parse failed (silently).
4
6
  */
5
7
  export function _jsonParseIfPossible(obj, reviver) {
6
- if (typeof obj === 'string' && obj) {
8
+ // Optimization: only try to parse if it looks like JSON: starts with a json possible character
9
+ if (typeof obj === 'string' && obj && DETECT_JSON.test(obj)) {
7
10
  try {
8
11
  return JSON.parse(obj, reviver);
9
12
  }
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.69.4",
3
+ "version": "14.71.0",
4
4
  "scripts": {
5
5
  "prepare": "husky install",
6
6
  "build-prod": "build-prod-esm-cjs",
@@ -7,6 +7,7 @@ import {
7
7
  StringifyAnyOptions,
8
8
  _jsonParseIfPossible,
9
9
  _stringifyAny,
10
+ Class,
10
11
  } from '..'
11
12
 
12
13
  /**
@@ -17,14 +18,17 @@ import {
17
18
  *
18
19
  * Alternatively, if you're sure it's Error - you can use `_assertIsError(err)`.
19
20
  */
20
- export function _anyToError(o: any, opt?: StringifyAnyOptions): Error {
21
- if (o instanceof Error) {
22
- // Already an Error - return as-is
23
- return o
24
- }
21
+ export function _anyToError<ERROR_TYPE extends Error = Error>(
22
+ o: any,
23
+ errorClass: Class<ERROR_TYPE> = Error as any,
24
+ opt?: StringifyAnyOptions,
25
+ ): ERROR_TYPE {
26
+ if (o instanceof errorClass) return o
25
27
 
26
- const message = _stringifyAny(o, opt)
27
- return new Error(message)
28
+ // If it's an instance of Error, but ErrorClass is something else (e.g AppError) - it'll be "repacked" into AppError
29
+
30
+ const errorObject = _isErrorObject(o) ? o : _anyToErrorObject(o, opt)
31
+ return _errorObjectToError(errorObject, errorClass)
28
32
  }
29
33
 
30
34
  /**
@@ -38,7 +42,7 @@ export function _anyToErrorObject<DATA_TYPE extends ErrorData = ErrorData>(
38
42
  opt?: StringifyAnyOptions,
39
43
  ): ErrorObject<DATA_TYPE> {
40
44
  if (o instanceof Error) {
41
- return _errorToErrorObject<DATA_TYPE>(o, opt?.includeErrorStack)
45
+ return _errorToErrorObject<DATA_TYPE>(o, opt?.includeErrorStack ?? true)
42
46
  }
43
47
 
44
48
  o = _jsonParseIfPossible(o)
@@ -70,7 +74,7 @@ export function _anyToErrorObject<DATA_TYPE extends ErrorData = ErrorData>(
70
74
 
71
75
  export function _errorToErrorObject<DATA_TYPE extends ErrorData = ErrorData>(
72
76
  e: AppError<DATA_TYPE> | Error,
73
- includeErrorStack = false,
77
+ includeErrorStack = true,
74
78
  ): ErrorObject<DATA_TYPE> {
75
79
  const obj: ErrorObject<DATA_TYPE> = {
76
80
  name: e.name,
@@ -86,20 +90,37 @@ export function _errorToErrorObject<DATA_TYPE extends ErrorData = ErrorData>(
86
90
  }
87
91
 
88
92
  export function _errorObjectToAppError<DATA_TYPE>(o: ErrorObject<DATA_TYPE>): AppError<DATA_TYPE> {
89
- const err = Object.assign(new AppError(o.message, o.data), {
90
- // name: err.name, // cannot be assigned to a readonly property like this
91
- // stack: o.stack, // also readonly e.g in Firefox
92
- })
93
+ return _errorObjectToError(o, AppError)
94
+ }
95
+
96
+ export function _errorObjectToError<DATA_TYPE, ERROR_TYPE extends Error>(
97
+ o: ErrorObject<DATA_TYPE>,
98
+ errorClass: Class<ERROR_TYPE> = Error as any,
99
+ ): ERROR_TYPE {
100
+ if (o instanceof errorClass) return o
101
+
102
+ const err = new errorClass(o.message)
103
+ // name: err.name, // cannot be assigned to a readonly property like this
104
+ // stack: o.stack, // also readonly e.g in Firefox
93
105
 
94
106
  Object.defineProperty(err, 'name', {
95
107
  value: o.name,
96
108
  configurable: true,
97
109
  })
98
110
 
99
- Object.defineProperty(err, 'stack', {
100
- value: o.stack,
111
+ Object.defineProperty(err, 'data', {
112
+ value: o.data,
113
+ writable: true,
114
+ configurable: true,
115
+ enumerable: false,
101
116
  })
102
117
 
118
+ if (o.stack) {
119
+ Object.defineProperty(err, 'stack', {
120
+ value: o.stack,
121
+ })
122
+ }
123
+
103
124
  return err
104
125
  }
105
126
 
@@ -109,14 +130,18 @@ export function _isHttpErrorResponse(o: any): o is HttpErrorResponse {
109
130
 
110
131
  export function _isHttpErrorObject(o: any): o is ErrorObject<HttpErrorData> {
111
132
  return (
112
- typeof o?.name === 'string' &&
113
- typeof o?.message === 'string' &&
114
- typeof o?.data?.httpStatusCode === 'number'
133
+ !!o &&
134
+ typeof o.name === 'string' &&
135
+ typeof o.message === 'string' &&
136
+ typeof o.data?.httpStatusCode === 'number'
115
137
  )
116
138
  }
117
139
 
140
+ /**
141
+ * Note: any instance of AppError is also automatically an ErrorObject
142
+ */
118
143
  export function _isErrorObject(o: any): o is ErrorObject {
119
144
  return (
120
- typeof o?.name === 'string' && typeof o?.message === 'string' && typeof o?.data === 'object'
145
+ !!o && typeof o.name === 'string' && typeof o.message === 'string' && typeof o.data === 'object'
121
146
  )
122
147
  }
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
@@ -57,15 +57,7 @@ import {
57
57
  HttpErrorData,
58
58
  HttpErrorResponse,
59
59
  } from './error/error.model'
60
- import {
61
- _anyToError,
62
- _anyToErrorObject,
63
- _errorObjectToAppError,
64
- _errorToErrorObject,
65
- _isErrorObject,
66
- _isHttpErrorObject,
67
- _isHttpErrorResponse,
68
- } from './error/error.util'
60
+ export * from './error/error.util'
69
61
  import { ErrorMode } from './error/errorMode'
70
62
  import { HttpError } from './error/http.error'
71
63
  import { _try, pTry } from './error/try'
@@ -181,7 +173,6 @@ import {
181
173
  ConditionalPick,
182
174
  Merge,
183
175
  Promisable,
184
- PromiseValue,
185
176
  ReadonlyDeep,
186
177
  Simplify,
187
178
  } from './typeFest'
@@ -213,6 +204,12 @@ import {
213
204
  UnixTimestamp,
214
205
  ValueOf,
215
206
  ValuesOf,
207
+ AbortableMapper,
208
+ AbortableAsyncPredicate,
209
+ AbortableAsyncMapper,
210
+ AbortablePredicate,
211
+ END,
212
+ SKIP,
216
213
  _noop,
217
214
  _objectKeys,
218
215
  _passNothingPredicate,
@@ -238,8 +235,13 @@ import {
238
235
  } from './log/commonLogger'
239
236
  import { _safeJsonStringify } from './string/safeJsonStringify'
240
237
  import { PQueue, PQueueCfg } from './promise/pQueue'
238
+ export * from './seq/seq'
241
239
 
242
240
  export type {
241
+ AbortableMapper,
242
+ AbortablePredicate,
243
+ AbortableAsyncPredicate,
244
+ AbortableAsyncMapper,
243
245
  PQueueCfg,
244
246
  MemoCache,
245
247
  PromiseDecoratorCfg,
@@ -278,7 +280,6 @@ export type {
278
280
  Merge,
279
281
  ReadonlyDeep,
280
282
  Promisable,
281
- PromiseValue,
282
283
  Simplify,
283
284
  ConditionalPick,
284
285
  ConditionalExcept,
@@ -326,9 +327,6 @@ export {
326
327
  AppError,
327
328
  HttpError,
328
329
  AssertionError,
329
- _isErrorObject,
330
- _isHttpErrorObject,
331
- _isHttpErrorResponse,
332
330
  _assert,
333
331
  _assertEquals,
334
332
  _assertDeepEquals,
@@ -405,10 +403,6 @@ export {
405
403
  _shuffle,
406
404
  _mapToObject,
407
405
  _findKeyByValue,
408
- _anyToError,
409
- _anyToErrorObject,
410
- _errorToErrorObject,
411
- _errorObjectToAppError,
412
406
  _range,
413
407
  _uniq,
414
408
  _uniqBy,
@@ -480,4 +474,6 @@ export {
480
474
  commonLoggerCreate,
481
475
  _safeJsonStringify,
482
476
  PQueue,
477
+ END,
478
+ SKIP,
483
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(