@naturalcycles/js-lib 14.129.0 → 14.130.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.
Files changed (65) hide show
  1. package/dist/decorators/asyncMemo.decorator.d.ts +2 -2
  2. package/dist/decorators/createPromiseDecorator.d.ts +6 -6
  3. package/dist/decorators/debounce.d.ts +2 -2
  4. package/dist/decorators/memo.decorator.d.ts +2 -2
  5. package/dist/decorators/memo.util.d.ts +7 -7
  6. package/dist/error/app.error.d.ts +1 -1
  7. package/dist/error/app.error.js +2 -2
  8. package/dist/error/assert.d.ts +0 -1
  9. package/dist/error/assert.js +0 -3
  10. package/dist/error/error.model.d.ts +1 -0
  11. package/dist/error/error.util.d.ts +4 -4
  12. package/dist/error/error.util.js +26 -13
  13. package/dist/error/errorMode.d.ts +1 -1
  14. package/dist/error/errorMode.js +1 -1
  15. package/dist/error/http.error.d.ts +1 -1
  16. package/dist/error/http.error.js +2 -2
  17. package/dist/error/tryCatch.d.ts +1 -1
  18. package/dist/http/fetcher.js +4 -3
  19. package/dist/index.d.ts +0 -1
  20. package/dist/index.js +0 -1
  21. package/dist/json-schema/jsonSchemaBuilder.d.ts +1 -1
  22. package/dist/promise/pDefer.d.ts +2 -2
  23. package/dist/promise/pMap.js +3 -4
  24. package/dist/promise/pRetry.d.ts +1 -1
  25. package/dist/promise/pTimeout.d.ts +1 -1
  26. package/dist/string/pupa.d.ts +2 -2
  27. package/dist/string/readingTime.d.ts +1 -1
  28. package/dist/string/stringifyAny.d.ts +6 -0
  29. package/dist/string/stringifyAny.js +13 -1
  30. package/dist-esm/error/app.error.js +2 -2
  31. package/dist-esm/error/assert.js +0 -3
  32. package/dist-esm/error/error.util.js +26 -11
  33. package/dist-esm/error/errorMode.js +1 -1
  34. package/dist-esm/error/http.error.js +2 -2
  35. package/dist-esm/http/fetcher.js +4 -3
  36. package/dist-esm/index.js +0 -1
  37. package/dist-esm/promise/pMap.js +3 -4
  38. package/dist-esm/string/stringifyAny.js +13 -1
  39. package/package.json +1 -1
  40. package/src/decorators/asyncMemo.decorator.ts +2 -2
  41. package/src/decorators/createPromiseDecorator.ts +4 -4
  42. package/src/decorators/debounce.ts +2 -2
  43. package/src/decorators/memo.decorator.ts +2 -2
  44. package/src/decorators/memo.util.ts +7 -7
  45. package/src/error/app.error.ts +2 -2
  46. package/src/error/assert.ts +1 -5
  47. package/src/error/error.model.ts +10 -0
  48. package/src/error/error.util.ts +26 -21
  49. package/src/error/errorMode.ts +1 -1
  50. package/src/error/http.error.ts +2 -2
  51. package/src/error/tryCatch.ts +1 -1
  52. package/src/http/fetcher.ts +5 -8
  53. package/src/index.ts +0 -1
  54. package/src/json-schema/jsonSchemaBuilder.ts +1 -1
  55. package/src/promise/pDefer.ts +2 -2
  56. package/src/promise/pMap.ts +3 -4
  57. package/src/promise/pRetry.ts +1 -1
  58. package/src/promise/pTimeout.ts +1 -1
  59. package/src/string/pupa.ts +1 -1
  60. package/src/string/readingTime.ts +1 -1
  61. package/src/string/stringifyAny.ts +23 -1
  62. package/dist/promise/AggregatedError.d.ts +0 -10
  63. package/dist/promise/AggregatedError.js +0 -34
  64. package/dist-esm/promise/AggregatedError.js +0 -30
  65. package/src/promise/AggregatedError.ts +0 -36
@@ -3,7 +3,7 @@ import { AppError } from './app.error';
3
3
  * Base class for HTTP errors - errors that define HTTP error code.
4
4
  */
5
5
  export class HttpError extends AppError {
6
- constructor(message, data) {
7
- super(message, data);
6
+ constructor(message, data, opt) {
7
+ super(message, data, opt);
8
8
  }
9
9
  }
@@ -159,11 +159,12 @@ export class Fetcher {
159
159
  res.body = JSON.parse(text, req.jsonReviver);
160
160
  }
161
161
  catch (err) {
162
- res.ok = false;
163
- res.err = _anyToError(err, HttpError, _filterNullishValues({
162
+ const { message } = _anyToError(err);
163
+ res.err = new HttpError([signature, message].join('\n'), {
164
164
  httpStatusCode: 0,
165
165
  url: req.url,
166
- }));
166
+ });
167
+ res.ok = false;
167
168
  }
168
169
  }
169
170
  else {
package/dist-esm/index.js CHANGED
@@ -37,7 +37,6 @@ export * from './object/deepEquals';
37
37
  export * from './object/object.util';
38
38
  export * from './object/sortObject';
39
39
  export * from './object/sortObjectDeep';
40
- export * from './promise/AggregatedError';
41
40
  export * from './promise/pDefer';
42
41
  export * from './promise/pDelay';
43
42
  export * from './promise/pFilter';
@@ -8,7 +8,6 @@ Improvements:
8
8
  */
9
9
  import { __asyncValues } from "tslib";
10
10
  import { END, ErrorMode, SKIP } from '..';
11
- import { AggregatedError } from './AggregatedError';
12
11
  /**
13
12
  * Returns a `Promise` that is fulfilled when all promises in `input` and ones returned from `mapper` are fulfilled,
14
13
  * or rejects if any of the promises reject. The fulfilled value is an `Array` of the fulfilled values returned
@@ -86,7 +85,7 @@ export async function pMap(iterable, mapper, opt = {}) {
86
85
  finally { if (e_1) throw e_1.error; }
87
86
  }
88
87
  if (errors.length) {
89
- throw new AggregatedError(errors, ret);
88
+ throw new AggregateError(errors, `pMap resulted in ${errors.length} error(s)`);
90
89
  }
91
90
  return ret;
92
91
  }
@@ -106,7 +105,7 @@ export async function pMap(iterable, mapper, opt = {}) {
106
105
  }
107
106
  });
108
107
  if (errors.length) {
109
- throw new AggregatedError(errors, ret);
108
+ throw new AggregateError(errors, `pMap resulted in ${errors.length} error(s)`);
110
109
  }
111
110
  return ret;
112
111
  }
@@ -122,7 +121,7 @@ export async function pMap(iterable, mapper, opt = {}) {
122
121
  isSettled = true;
123
122
  const r = ret.filter(r => r !== SKIP);
124
123
  if (errors.length) {
125
- reject(new AggregatedError(errors, r));
124
+ reject(new AggregateError(errors, `pMap resulted in ${errors.length} error(s)`));
126
125
  }
127
126
  else {
128
127
  resolve(r);
@@ -1,6 +1,7 @@
1
1
  import { _isErrorObject, _isHttpErrorObject, _isHttpErrorResponse } from '../error/error.util';
2
2
  import { _jsonParseIfPossible } from './json.util';
3
3
  import { _safeJsonStringify } from './safeJsonStringify';
4
+ const supportsAggregateError = typeof globalThis.AggregateError === 'function';
4
5
  let globalStringifyFunction = _safeJsonStringify;
5
6
  /**
6
7
  * Allows to set Global "stringifyFunction" that will be used to "pretty-print" objects
@@ -55,6 +56,7 @@ export function _stringifyAny(obj, opt = {}) {
55
56
  return _stringifyAny(obj.error, opt);
56
57
  }
57
58
  if (obj instanceof Error || _isErrorObject(obj)) {
59
+ const { includeErrorCause = true } = opt;
58
60
  //
59
61
  // Error or ErrorObject
60
62
  //
@@ -63,7 +65,7 @@ export function _stringifyAny(obj, opt = {}) {
63
65
  // if (obj?.name === 'Error') {
64
66
  // s = obj.message
65
67
  // }
66
- s = [obj.name, obj.message].join(': ');
68
+ s = [obj.name, obj.message].filter(Boolean).join(': ');
67
69
  if (opt.includeErrorStack && obj.stack) {
68
70
  // Here we're using the previously-generated "title line" (e.g "Error: some_message"),
69
71
  // concatenating it with the Stack (but without the title line of the Stack)
@@ -88,6 +90,16 @@ export function _stringifyAny(obj, opt = {}) {
88
90
  // Error that has no `data`, but has `code` property
89
91
  s = [s, `code: ${obj.code}`].join('\n');
90
92
  }
93
+ if (supportsAggregateError && obj instanceof AggregateError && obj.errors.length) {
94
+ s = [
95
+ s,
96
+ `${obj.errors.length} error(s):`,
97
+ ...obj.errors.map((err, i) => `${i + 1}. ${_stringifyAny(err, opt)}`),
98
+ ].join('\n');
99
+ }
100
+ if (obj.cause && includeErrorCause) {
101
+ s = s + '\ncaused by: ' + _stringifyAny(obj.cause, opt);
102
+ }
91
103
  }
92
104
  else if (typeof obj === 'string') {
93
105
  //
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@naturalcycles/js-lib",
3
- "version": "14.129.0",
3
+ "version": "14.130.0",
4
4
  "scripts": {
5
5
  "prepare": "husky install",
6
6
  "build-prod": "build-prod-esm-cjs",
@@ -11,12 +11,12 @@ export interface AsyncMemoOptions {
11
11
  * Function that creates an instance of `MemoCache`.
12
12
  * e.g LRUMemoCache from `@naturalcycles/nodejs-lib`.
13
13
  */
14
- cacheFactory?(): AsyncMemoCache
14
+ cacheFactory?: () => AsyncMemoCache
15
15
 
16
16
  /**
17
17
  * Provide a custom implementation of CacheKey function.
18
18
  */
19
- cacheKeyFn?(args: any[]): any
19
+ cacheKeyFn?: (args: any[]) => any
20
20
 
21
21
  /**
22
22
  * Default true.
@@ -7,14 +7,14 @@ export interface PromiseDecoratorCfg<RES = any, PARAMS = any> {
7
7
  * Called BEFORE the original function.
8
8
  * If Promise is returned - it will be awaited.
9
9
  */
10
- beforeFn?(r: PromiseDecoratorResp<PARAMS>): void | Promise<void>
10
+ beforeFn?: (r: PromiseDecoratorResp<PARAMS>) => void | Promise<void>
11
11
 
12
12
  /**
13
13
  * Called just AFTER the original function.
14
14
  * The output of this hook will be passed further,
15
15
  * so, pay attention to pass through (or modify) the result.
16
16
  */
17
- thenFn?(r: PromiseDecoratorResp<PARAMS> & { res: RES }): RES
17
+ thenFn?: (r: PromiseDecoratorResp<PARAMS> & { res: RES }) => RES
18
18
 
19
19
  /**
20
20
  * Called on Promise.reject.
@@ -23,13 +23,13 @@ export interface PromiseDecoratorCfg<RES = any, PARAMS = any> {
23
23
  * If `catchFn` is present - it's responsible for handling or re-throwing the error.
24
24
  * Whatever `catchFn` returns - passed to the original output.
25
25
  */
26
- catchFn?(r: PromiseDecoratorResp<PARAMS> & { err: any }): RES
26
+ catchFn?: (r: PromiseDecoratorResp<PARAMS> & { err: any }) => RES
27
27
 
28
28
  /**
29
29
  * Fires AFTER thenFn / catchFn, like a usual Promise.finally().
30
30
  * Doesn't have access to neither res nor err (same as Promise.finally).
31
31
  */
32
- finallyFn?(r: PromiseDecoratorResp<PARAMS>): any
32
+ finallyFn?: (r: PromiseDecoratorResp<PARAMS>) => any
33
33
  }
34
34
 
35
35
  export interface PromiseDecoratorResp<PARAMS> {
@@ -1,8 +1,8 @@
1
1
  import type { AnyFunction } from '../types'
2
2
 
3
3
  export interface Cancelable {
4
- cancel(): void
5
- flush(): void
4
+ cancel: () => void
5
+ flush: () => void
6
6
  }
7
7
 
8
8
  export interface ThrottleOptions {
@@ -11,12 +11,12 @@ export interface MemoOptions {
11
11
  * Function that creates an instance of `MemoCache`.
12
12
  * e.g LRUMemoCache from `@naturalcycles/nodejs-lib`
13
13
  */
14
- cacheFactory?(): MemoCache
14
+ cacheFactory?: () => MemoCache
15
15
 
16
16
  /**
17
17
  * Provide a custom implementation of CacheKey function.
18
18
  */
19
- cacheKeyFn?(args: any[]): any
19
+ cacheKeyFn?: (args: any[]) => any
20
20
 
21
21
  /**
22
22
  * Defaults to true.
@@ -10,15 +10,15 @@ export const jsonMemoSerializer: MemoSerializer = args => {
10
10
  }
11
11
 
12
12
  export interface MemoCache<KEY = any, VALUE = any> {
13
- has(k: KEY): boolean
14
- get(k: KEY): VALUE | Error | undefined
15
- set(k: KEY, v: VALUE | Error): void
13
+ has: (k: KEY) => boolean
14
+ get: (k: KEY) => VALUE | Error | undefined
15
+ set: (k: KEY, v: VALUE | Error) => void
16
16
 
17
17
  /**
18
18
  * Clear is only called when `.dropCache()` is called.
19
19
  * Otherwise the Cache is "persistent" (never cleared).
20
20
  */
21
- clear(): void
21
+ clear: () => void
22
22
  }
23
23
 
24
24
  export interface AsyncMemoCache<KEY = any, VALUE = any> {
@@ -29,14 +29,14 @@ export interface AsyncMemoCache<KEY = any, VALUE = any> {
29
29
  * This also means that you CANNOT store `undefined` value in the Cache, as it'll be treated as a MISS.
30
30
  * You CAN store `null` value instead, it will be treated as a HIT.
31
31
  */
32
- get(k: KEY): Promisable<VALUE | Error | undefined>
33
- set(k: KEY, v: VALUE | Error): Promisable<void>
32
+ get: (k: KEY) => Promisable<VALUE | Error | undefined>
33
+ set: (k: KEY, v: VALUE | Error) => Promisable<void>
34
34
 
35
35
  /**
36
36
  * Clear is only called when `.dropCache()` is called.
37
37
  * Otherwise the Cache is "persistent" (never cleared).
38
38
  */
39
- clear(): Promisable<void>
39
+ clear: () => Promisable<void>
40
40
  }
41
41
 
42
42
  // SingleValueMemoCache and ObjectMemoCache are example-only, not used in production code
@@ -12,8 +12,8 @@ import type { ErrorData } from './error.model'
12
12
  export class AppError<DATA_TYPE extends ErrorData = ErrorData> extends Error {
13
13
  data!: DATA_TYPE
14
14
 
15
- constructor(message: string, data = {} as DATA_TYPE) {
16
- super(message)
15
+ constructor(message: string, data = {} as DATA_TYPE, opt?: ErrorOptions) {
16
+ super(message, opt)
17
17
 
18
18
  Object.defineProperty(this, 'name', {
19
19
  value: this.constructor.name,
@@ -123,8 +123,4 @@ export function _assertTypeOf<T>(v: any, expectedType: string, message?: string)
123
123
  }
124
124
  }
125
125
 
126
- export class AssertionError extends AppError {
127
- constructor(message: string, data = {} as ErrorData) {
128
- super(message, data)
129
- }
130
- }
126
+ export class AssertionError extends AppError {}
@@ -76,6 +76,14 @@ export interface Admin403ErrorData extends HttpErrorData {
76
76
  adminPermissionsRequired: string[]
77
77
  }
78
78
 
79
+ // export interface ErrorLike {
80
+ // name: string
81
+ // message: string
82
+ // stack?: string
83
+ // data?: any
84
+ // cause?: any
85
+ // }
86
+
79
87
  /**
80
88
  * Portable object that represents Error.
81
89
  * Has extendable generic `data` property.
@@ -114,6 +122,8 @@ export interface ErrorObject<DATA_TYPE extends ErrorData = ErrorData> {
114
122
  * It's non-optional, to save some null-checks.
115
123
  */
116
124
  data: DATA_TYPE
125
+
126
+ cause?: any
117
127
  }
118
128
 
119
129
  /**
@@ -1,11 +1,4 @@
1
- import type {
2
- ErrorData,
3
- ErrorObject,
4
- HttpErrorData,
5
- HttpErrorResponse,
6
- StringifyAnyOptions,
7
- Class,
8
- } from '..'
1
+ import type { ErrorData, ErrorObject, HttpErrorData, HttpErrorResponse, Class } from '..'
9
2
  import { AppError, _jsonParseIfPossible, _stringifyAny } from '..'
10
3
 
11
4
  /**
@@ -20,7 +13,6 @@ export function _anyToError<ERROR_TYPE extends Error = Error>(
20
13
  o: any,
21
14
  errorClass: Class<ERROR_TYPE> = Error as any,
22
15
  errorData?: ErrorData,
23
- opt?: StringifyAnyOptions,
24
16
  ): ERROR_TYPE {
25
17
  let e: ERROR_TYPE
26
18
 
@@ -29,8 +21,8 @@ export function _anyToError<ERROR_TYPE extends Error = Error>(
29
21
  } else {
30
22
  // If it's an instance of Error, but ErrorClass is something else (e.g AppError) - it'll be "repacked" into AppError
31
23
 
32
- const errorObject = _isErrorObject(o) ? o : _anyToErrorObject(o, {}, opt)
33
- e = _errorObjectToError(errorObject, errorClass) as any
24
+ const errorObject = _anyToErrorObject(o)
25
+ e = _errorObjectToError(errorObject, errorClass)
34
26
  }
35
27
 
36
28
  if (errorData) {
@@ -52,12 +44,11 @@ export function _anyToError<ERROR_TYPE extends Error = Error>(
52
44
  export function _anyToErrorObject<DATA_TYPE extends ErrorData = ErrorData>(
53
45
  o: any,
54
46
  errorData?: Partial<DATA_TYPE>,
55
- opt?: StringifyAnyOptions,
56
47
  ): ErrorObject<DATA_TYPE> {
57
48
  let eo: ErrorObject<DATA_TYPE>
58
49
 
59
50
  if (o instanceof Error) {
60
- eo = _errorToErrorObject<DATA_TYPE>(o, opt?.includeErrorStack ?? true)
51
+ eo = _errorToErrorObject<DATA_TYPE>(o)
61
52
  } else {
62
53
  o = _jsonParseIfPossible(o)
63
54
 
@@ -70,10 +61,7 @@ export function _anyToErrorObject<DATA_TYPE extends ErrorData = ErrorData>(
70
61
  // so, fair to return `data: {}` in the end
71
62
  // Also we're sure it includes no "error name", e.g no `Error: ...`,
72
63
  // so, fair to include `name: 'Error'`
73
- const message = _stringifyAny(o, {
74
- includeErrorData: true, // cause we're returning an ErrorObject, not a stringified error (yet)
75
- ...opt,
76
- })
64
+ const message = _stringifyAny(o)
77
65
 
78
66
  eo = {
79
67
  name: 'Error',
@@ -89,16 +77,16 @@ export function _anyToErrorObject<DATA_TYPE extends ErrorData = ErrorData>(
89
77
 
90
78
  export function _errorToErrorObject<DATA_TYPE extends ErrorData = ErrorData>(
91
79
  e: AppError<DATA_TYPE> | Error,
92
- includeErrorStack = true,
93
80
  ): ErrorObject<DATA_TYPE> {
94
81
  const obj: ErrorObject<DATA_TYPE> = {
95
82
  name: e.name,
96
83
  message: e.message,
97
84
  data: { ...(e as any).data }, // empty by default
85
+ stack: e.stack,
98
86
  }
99
87
 
100
- if (includeErrorStack) {
101
- obj.stack = e.stack
88
+ if (e.cause) {
89
+ obj.cause = _anyToErrorObject(e.cause)
102
90
  }
103
91
 
104
92
  return obj
@@ -138,6 +126,15 @@ export function _errorObjectToError<DATA_TYPE extends ErrorData, ERROR_TYPE exte
138
126
  })
139
127
  }
140
128
 
129
+ if (o.cause) {
130
+ Object.defineProperty(err, 'cause', {
131
+ value: o.cause,
132
+ writable: true,
133
+ configurable: true,
134
+ enumerable: false,
135
+ })
136
+ }
137
+
141
138
  return err
142
139
  }
143
140
 
@@ -159,10 +156,18 @@ export function _isHttpErrorObject(o: any): o is ErrorObject<HttpErrorData> {
159
156
  */
160
157
  export function _isErrorObject(o: any): o is ErrorObject {
161
158
  return (
162
- !!o && typeof o.name === 'string' && typeof o.message === 'string' && typeof o.data === 'object'
159
+ !!o &&
160
+ typeof o === 'object' &&
161
+ typeof o.name === 'string' &&
162
+ typeof o.message === 'string' &&
163
+ typeof o.data === 'object'
163
164
  )
164
165
  }
165
166
 
167
+ // export function _isErrorLike(o: any): o is ErrorLike {
168
+ // return !!o && typeof o === 'object' && typeof o.name === 'string' && typeof o.message === 'string'
169
+ // }
170
+
166
171
  /**
167
172
  * Convenience function to safely add properties to Error's `data` object
168
173
  * (even if it wasn't previously existing)
@@ -10,7 +10,7 @@ export enum ErrorMode {
10
10
  THROW_IMMEDIATELY = 'THROW_IMMEDIATELY',
11
11
 
12
12
  /**
13
- * Don't throw on errors, but collect them and throw as AggregatedError in the end.
13
+ * Don't throw on errors, but collect them and throw as AggregateError in the end.
14
14
  */
15
15
  THROW_AGGREGATED = 'THROW_AGGREGATED',
16
16
 
@@ -7,7 +7,7 @@ import type { HttpErrorData } from './error.model'
7
7
  export class HttpError<
8
8
  DATA_TYPE extends HttpErrorData = HttpErrorData,
9
9
  > extends AppError<DATA_TYPE> {
10
- constructor(message: string, data: DATA_TYPE) {
11
- super(message, data)
10
+ constructor(message: string, data: DATA_TYPE, opt?: ErrorOptions) {
11
+ super(message, data, opt)
12
12
  }
13
13
  }
@@ -7,7 +7,7 @@ export interface TryCatchOptions {
7
7
  * The value returned from the function will be returned from the wrapped method (!).
8
8
  * onError function may be asynchronous.
9
9
  */
10
- onError?(err: Error): any
10
+ onError?: (err: Error) => any
11
11
 
12
12
  /**
13
13
  * @default false
@@ -219,15 +219,12 @@ export class Fetcher {
219
219
  res.body = text
220
220
  res.body = JSON.parse(text, req.jsonReviver)
221
221
  } catch (err) {
222
+ const { message } = _anyToError(err)
223
+ res.err = new HttpError([signature, message].join('\n'), {
224
+ httpStatusCode: 0,
225
+ url: req.url,
226
+ })
222
227
  res.ok = false
223
- res.err = _anyToError(
224
- err,
225
- HttpError,
226
- _filterNullishValues({
227
- httpStatusCode: 0,
228
- url: req.url,
229
- }),
230
- )
231
228
  }
232
229
  } else {
233
230
  // Body had a '' (empty string)
package/src/index.ts CHANGED
@@ -37,7 +37,6 @@ export * from './object/deepEquals'
37
37
  export * from './object/object.util'
38
38
  export * from './object/sortObject'
39
39
  export * from './object/sortObjectDeep'
40
- export * from './promise/AggregatedError'
41
40
  export * from './promise/pDefer'
42
41
  export * from './promise/pDelay'
43
42
  export * from './promise/pFilter'
@@ -26,7 +26,7 @@ import type {
26
26
  /* eslint-disable id-blacklist, @typescript-eslint/explicit-module-boundary-types */
27
27
 
28
28
  export interface JsonSchemaBuilder<T = unknown> {
29
- build(): JsonSchema<T>
29
+ build: () => JsonSchema<T>
30
30
  }
31
31
 
32
32
  /**
@@ -2,8 +2,8 @@
2
2
  * Similar to Deferred object, which is also a promise itself (instead of deferred.promise).
3
3
  */
4
4
  export interface DeferredPromise<T = void> extends Promise<T> {
5
- resolve(a?: T): void
6
- reject(e?: Error): void
5
+ resolve: (a?: T) => void
6
+ reject: (e?: Error) => void
7
7
  }
8
8
 
9
9
  /* eslint-disable @typescript-eslint/promise-function-async */
@@ -9,7 +9,6 @@ Improvements:
9
9
 
10
10
  import type { AbortableAsyncMapper } from '..'
11
11
  import { END, ErrorMode, SKIP } from '..'
12
- import { AggregatedError } from './AggregatedError'
13
12
 
14
13
  export interface PMapOptions {
15
14
  /**
@@ -93,7 +92,7 @@ export async function pMap<IN, OUT>(
93
92
  }
94
93
 
95
94
  if (errors.length) {
96
- throw new AggregatedError(errors, ret)
95
+ throw new AggregateError(errors, `pMap resulted in ${errors.length} error(s)`)
97
96
  }
98
97
 
99
98
  return ret as OUT[]
@@ -115,7 +114,7 @@ export async function pMap<IN, OUT>(
115
114
  })
116
115
 
117
116
  if (errors.length) {
118
- throw new AggregatedError(errors, ret)
117
+ throw new AggregateError(errors, `pMap resulted in ${errors.length} error(s)`)
119
118
  }
120
119
 
121
120
  return ret as OUT[]
@@ -135,7 +134,7 @@ export async function pMap<IN, OUT>(
135
134
  isSettled = true
136
135
  const r = ret.filter(r => r !== SKIP) as OUT[]
137
136
  if (errors.length) {
138
- reject(new AggregatedError(errors, r))
137
+ reject(new AggregateError(errors, `pMap resulted in ${errors.length} error(s)`))
139
138
  } else {
140
139
  resolve(r)
141
140
  }
@@ -43,7 +43,7 @@ export interface PRetryOptions {
43
43
  *
44
44
  * @default () => true
45
45
  */
46
- predicate?(err: Error, attempt: number, maxAttempts: number): boolean
46
+ predicate?: (err: Error, attempt: number, maxAttempts: number) => boolean
47
47
 
48
48
  /**
49
49
  * Log the first attempt (which is not a "retry" yet).
@@ -23,7 +23,7 @@ export interface PTimeoutOptions {
23
23
  * err (which is TimeoutError) is passed as an argument for convenience, so it can
24
24
  * be logged or such. You don't have to consume it in any way though.
25
25
  */
26
- onTimeout?(err: TimeoutError): any
26
+ onTimeout?: (err: TimeoutError) => any
27
27
 
28
28
  /**
29
29
  * Defaults to true.
@@ -31,7 +31,7 @@ export interface PupaOptions {
31
31
  /**
32
32
  * Performs arbitrary operation for each interpolation. If the returned value was `undefined`, it behaves differently depending on the `ignoreMissing` option. Otherwise, the returned value will be interpolated into a string (and escaped when double-braced) and embedded into the template.
33
33
  */
34
- transform?(data: { value: any; key: string }): unknown
34
+ transform?: (data: { value: any; key: string }) => unknown
35
35
  }
36
36
 
37
37
  /**
@@ -16,7 +16,7 @@ export interface ReadingTimeOptions {
16
16
  * A function that returns a boolean value depending on if a character is considered as a word bound.
17
17
  * Default: spaces, new lines and tabs
18
18
  */
19
- wordBound?(char: string): boolean
19
+ wordBound?: (char: string) => boolean
20
20
  /**
21
21
  * Default 200
22
22
  */
@@ -3,6 +3,8 @@ import type { Reviver } from '../types'
3
3
  import { _jsonParseIfPossible } from './json.util'
4
4
  import { _safeJsonStringify } from './safeJsonStringify'
5
5
 
6
+ const supportsAggregateError = typeof globalThis.AggregateError === 'function'
7
+
6
8
  let globalStringifyFunction: JsonStringifyFunction = _safeJsonStringify
7
9
 
8
10
  /**
@@ -45,6 +47,13 @@ export interface StringifyAnyOptions {
45
47
  */
46
48
  includeErrorStack?: boolean
47
49
 
50
+ /**
51
+ * Set to false to skip including Error.cause.
52
+ *
53
+ * @default true
54
+ */
55
+ includeErrorCause?: boolean
56
+
48
57
  /**
49
58
  * Allows to pass custom "stringify function".
50
59
  * E.g in Node.js you can pass `util.inspect` instead.
@@ -91,6 +100,7 @@ export function _stringifyAny(obj: any, opt: StringifyAnyOptions = {}): string {
91
100
  }
92
101
 
93
102
  if (obj instanceof Error || _isErrorObject(obj)) {
103
+ const { includeErrorCause = true } = opt
94
104
  //
95
105
  // Error or ErrorObject
96
106
  //
@@ -100,7 +110,7 @@ export function _stringifyAny(obj: any, opt: StringifyAnyOptions = {}): string {
100
110
  // if (obj?.name === 'Error') {
101
111
  // s = obj.message
102
112
  // }
103
- s = [obj.name, obj.message].join(': ')
113
+ s = [obj.name, obj.message].filter(Boolean).join(': ')
104
114
 
105
115
  if (opt.includeErrorStack && obj.stack) {
106
116
  // Here we're using the previously-generated "title line" (e.g "Error: some_message"),
@@ -128,6 +138,18 @@ export function _stringifyAny(obj: any, opt: StringifyAnyOptions = {}): string {
128
138
  // Error that has no `data`, but has `code` property
129
139
  s = [s, `code: ${(obj as any).code}`].join('\n')
130
140
  }
141
+
142
+ if (supportsAggregateError && obj instanceof AggregateError && obj.errors.length) {
143
+ s = [
144
+ s,
145
+ `${obj.errors.length} error(s):`,
146
+ ...obj.errors.map((err, i) => `${i + 1}. ${_stringifyAny(err, opt)}`),
147
+ ].join('\n')
148
+ }
149
+
150
+ if (obj.cause && includeErrorCause) {
151
+ s = s + '\ncaused by: ' + _stringifyAny(obj.cause, opt)
152
+ }
131
153
  } else if (typeof obj === 'string') {
132
154
  //
133
155
  // String
@@ -1,10 +0,0 @@
1
- /**
2
- * Error that aggregates a number of other errors.
3
- * .errors contain raw original errors to be accessed if needed.
4
- * .results contain the results of some batch operation (if needed).
5
- */
6
- export declare class AggregatedError<RESULT = any> extends Error {
7
- errors: Error[];
8
- results: RESULT[];
9
- constructor(errors: Error[], results?: RESULT[]);
10
- }
@@ -1,34 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.AggregatedError = void 0;
4
- /**
5
- * Error that aggregates a number of other errors.
6
- * .errors contain raw original errors to be accessed if needed.
7
- * .results contain the results of some batch operation (if needed).
8
- */
9
- class AggregatedError extends Error {
10
- constructor(errors, results = []) {
11
- const message = [
12
- `${errors.length} errors:`,
13
- ...errors.map((e, i) => `${i + 1}. ${e.message}`),
14
- ].join('\n');
15
- super(message);
16
- this.errors = errors;
17
- this.results = results;
18
- Object.defineProperty(this, 'name', {
19
- value: this.constructor.name,
20
- configurable: true,
21
- });
22
- if (Error.captureStackTrace) {
23
- Error.captureStackTrace(this, this.constructor);
24
- }
25
- else {
26
- Object.defineProperty(this, 'stack', {
27
- value: new Error().stack,
28
- writable: true,
29
- configurable: true,
30
- });
31
- }
32
- }
33
- }
34
- exports.AggregatedError = AggregatedError;