@naturalcycles/js-lib 14.159.0 → 14.161.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 (53) hide show
  1. package/dist/{lazy.d.ts → define.d.ts} +26 -0
  2. package/dist/define.js +118 -0
  3. package/dist/error/app.error.d.ts +16 -3
  4. package/dist/error/app.error.js +22 -19
  5. package/dist/error/assert.d.ts +1 -1
  6. package/dist/error/assert.js +2 -2
  7. package/dist/error/error.model.d.ts +7 -0
  8. package/dist/error/error.util.js +29 -22
  9. package/dist/error/httpRequestError.d.ts +2 -2
  10. package/dist/error/httpRequestError.js +7 -2
  11. package/dist/error/jsonParseError.d.ts +2 -2
  12. package/dist/error/jsonParseError.js +5 -2
  13. package/dist/error/try.js +3 -1
  14. package/dist/http/fetcher.js +6 -3
  15. package/dist/http/fetcher.model.d.ts +1 -0
  16. package/dist/http/fetcher.model.js +1 -0
  17. package/dist/index.d.ts +1 -1
  18. package/dist/index.js +1 -1
  19. package/dist/object/object.util.d.ts +16 -11
  20. package/dist/object/object.util.js +29 -12
  21. package/dist/promise/pTimeout.d.ts +3 -3
  22. package/dist/promise/pTimeout.js +2 -2
  23. package/dist/types.d.ts +9 -2
  24. package/dist/types.js +9 -2
  25. package/dist-esm/{lazy.js → define.js} +38 -0
  26. package/dist-esm/error/app.error.js +22 -19
  27. package/dist-esm/error/assert.js +2 -2
  28. package/dist-esm/error/error.util.js +30 -23
  29. package/dist-esm/error/httpRequestError.js +7 -2
  30. package/dist-esm/error/jsonParseError.js +5 -2
  31. package/dist-esm/error/try.js +3 -1
  32. package/dist-esm/http/fetcher.js +6 -3
  33. package/dist-esm/http/fetcher.model.js +1 -0
  34. package/dist-esm/index.js +1 -1
  35. package/dist-esm/object/object.util.js +27 -11
  36. package/dist-esm/promise/pTimeout.js +2 -2
  37. package/dist-esm/types.js +8 -1
  38. package/package.json +1 -1
  39. package/src/{lazy.ts → define.ts} +68 -0
  40. package/src/error/app.error.ts +39 -22
  41. package/src/error/assert.ts +2 -2
  42. package/src/error/error.model.ts +8 -0
  43. package/src/error/error.util.ts +31 -25
  44. package/src/error/httpRequestError.ts +9 -3
  45. package/src/error/jsonParseError.ts +7 -8
  46. package/src/error/try.ts +7 -1
  47. package/src/http/fetcher.model.ts +2 -0
  48. package/src/http/fetcher.ts +6 -3
  49. package/src/index.ts +1 -1
  50. package/src/object/object.util.ts +51 -30
  51. package/src/promise/pTimeout.ts +4 -4
  52. package/src/types.ts +12 -2
  53. package/dist/lazy.js +0 -65
@@ -109,41 +109,47 @@ export function _errorObjectToError<DATA_TYPE extends ErrorData, ERROR_TYPE exte
109
109
  ): ERROR_TYPE {
110
110
  if (o instanceof errorClass) return o
111
111
 
112
- const err = new errorClass(o.message)
112
+ // Here we pass constructor values assuming it's AppError or sub-class of it
113
+ // If not - will be checked at the next step
114
+ // We cannot check `if (errorClass instanceof AppError)`, only `err instanceof AppError`
115
+ const { name, cause } = o
116
+ const err = new errorClass(o.message, o.data, { name, cause })
113
117
  // name: err.name, // cannot be assigned to a readonly property like this
114
118
  // stack: o.stack, // also readonly e.g in Firefox
115
119
 
116
- Object.defineProperty(err, 'name', {
117
- value: o.name,
118
- configurable: true,
119
- writable: true,
120
- })
121
-
122
- Object.defineProperty(err.constructor, 'name', {
123
- value: o.name,
124
- configurable: true,
125
- writable: true,
126
- })
127
-
128
- Object.defineProperty(err, 'data', {
129
- value: o.data,
130
- writable: true,
131
- configurable: true,
132
- enumerable: false,
133
- })
134
-
135
120
  if (o.stack) {
136
121
  Object.defineProperty(err, 'stack', {
137
122
  value: o.stack,
138
123
  })
139
124
  }
140
125
 
141
- if (o.cause) {
142
- Object.defineProperty(err, 'cause', {
143
- value: o.cause,
144
- writable: true,
126
+ if (!(err instanceof AppError)) {
127
+ // Following actions are only needed for non-AppError-like errors
128
+
129
+ Object.defineProperties(err, {
130
+ name: {
131
+ value: name,
132
+ configurable: true,
133
+ writable: true,
134
+ },
135
+ data: {
136
+ value: o.data,
137
+ writable: true,
138
+ configurable: true,
139
+ enumerable: false,
140
+ },
141
+ cause: {
142
+ value: cause,
143
+ writable: true,
144
+ configurable: true,
145
+ enumerable: true,
146
+ },
147
+ })
148
+
149
+ Object.defineProperty(err.constructor, 'name', {
150
+ value: name,
145
151
  configurable: true,
146
- enumerable: false,
152
+ writable: true,
147
153
  })
148
154
  }
149
155
 
@@ -1,4 +1,4 @@
1
- import { AppError } from './app.error'
1
+ import { AppError, AppErrorOptions } from './app.error'
2
2
  import type { ErrorObject, HttpRequestErrorData } from './error.model'
3
3
 
4
4
  /**
@@ -19,8 +19,14 @@ import type { ErrorObject, HttpRequestErrorData } from './error.model'
19
19
  * (by default).
20
20
  */
21
21
  export class HttpRequestError extends AppError<HttpRequestErrorData> {
22
- constructor(message: string, data: HttpRequestErrorData, cause: ErrorObject) {
23
- super(message, data, cause, 'HttpRequestError')
22
+ constructor(message: string, data: HttpRequestErrorData, opt?: AppErrorOptions) {
23
+ if (data.response) {
24
+ Object.defineProperty(data, 'response', {
25
+ enumerable: false,
26
+ })
27
+ }
28
+
29
+ super(message, data, { ...opt, name: 'HttpRequestError' })
24
30
  }
25
31
 
26
32
  /**
@@ -1,6 +1,6 @@
1
1
  import { _truncateMiddle } from '../string/string.util'
2
2
  import { AppError } from './app.error'
3
- import { ErrorData, ErrorObject } from './error.model'
3
+ import { ErrorData } from './error.model'
4
4
 
5
5
  export interface JsonParseErrorData extends ErrorData {
6
6
  /**
@@ -10,12 +10,11 @@ export interface JsonParseErrorData extends ErrorData {
10
10
  }
11
11
 
12
12
  export class JsonParseError extends AppError<JsonParseErrorData> {
13
- constructor(data: JsonParseErrorData, cause?: ErrorObject) {
14
- super(
15
- ['Failed to parse', data.text && _truncateMiddle(data.text, 200)].filter(Boolean).join(': '),
16
- data,
17
- cause,
18
- 'JsonParseError',
19
- )
13
+ constructor(data: JsonParseErrorData) {
14
+ const message = ['Failed to parse', data.text && _truncateMiddle(data.text, 200)]
15
+ .filter(Boolean)
16
+ .join(': ')
17
+
18
+ super(message, data, { name: 'JsonParseError' })
20
19
  }
21
20
  }
package/src/error/try.ts CHANGED
@@ -62,7 +62,13 @@ export async function pTry<T, ERR extends Error = Error>(
62
62
  */
63
63
  export class UnexpectedPassError extends AppError {
64
64
  constructor() {
65
- super('expected error was not thrown', {}, undefined, 'UnexpectedPassError')
65
+ super(
66
+ 'expected error was not thrown',
67
+ {},
68
+ {
69
+ name: 'UnexpectedPassError',
70
+ },
71
+ )
66
72
  }
67
73
  }
68
74
 
@@ -1,3 +1,5 @@
1
+ /// <reference lib="dom"/>
2
+
1
3
  import type { CommonLogger } from '../log/commonLogger'
2
4
  import type { Promisable } from '../typeFest'
3
5
  import type { AnyObject, NumberOfMilliseconds, Reviver, UnixTimestampMillisNumber } from '../types'
@@ -395,6 +395,7 @@ export class Fetcher {
395
395
  res.err = new HttpRequestError(
396
396
  message,
397
397
  _filterNullishValues({
398
+ response: res.fetchResponse,
398
399
  responseStatusCode: res.fetchResponse?.status || 0,
399
400
  // These properties are provided to be used in e.g custom Sentry error grouping
400
401
  // Actually, disabled now, to avoid unnecessary error printing when both msg and data are printed
@@ -402,12 +403,14 @@ export class Fetcher {
402
403
  // method: req.method,
403
404
  // tryCount: req.tryCount,
404
405
  requestUrl: res.req.fullUrl,
405
- requestBaseUrl: this.cfg.baseUrl || (null as any),
406
+ requestBaseUrl: this.cfg.baseUrl || undefined,
406
407
  requestMethod: res.req.init.method,
407
408
  requestSignature: res.signature,
408
409
  requestDuration: Date.now() - res.req.started,
409
410
  }),
410
- cause,
411
+ {
412
+ cause,
413
+ },
411
414
  )
412
415
 
413
416
  await this.processRetry(res)
@@ -660,7 +663,7 @@ export class Fetcher {
660
663
 
661
664
  if (Object.keys(searchParams).length) {
662
665
  const qs = new URLSearchParams(searchParams).toString()
663
- req.fullUrl += req.fullUrl.includes('?') ? '&' : '?' + qs
666
+ req.fullUrl += (req.fullUrl.includes('?') ? '&' : '?') + qs
664
667
  }
665
668
 
666
669
  // setup request body
package/src/index.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export * from './array/array.util'
2
- export * from './lazy'
2
+ export * from './define'
3
3
  export * from './string/url.util'
4
4
  export * from './array/range'
5
5
  export * from './decorators/createPromiseDecorator'
@@ -1,6 +1,7 @@
1
1
  import { _isEmpty, _isObject } from '../is.util'
2
2
  import type { PropertyPath } from '../lodash.types'
3
- import type { AnyObject, ObjectMapper, ObjectPredicate, StringMap, ValueOf } from '../types'
3
+ import { _objectEntries, KeyValueTuple, SKIP } from '../types'
4
+ import type { AnyObject, ObjectMapper, ObjectPredicate, ValueOf } from '../types'
4
5
 
5
6
  /**
6
7
  * Returns clone of `obj` with only `props` preserved.
@@ -111,24 +112,22 @@ export function _filterObject<T extends AnyObject>(
111
112
  * 'pebbles': { 'user': 'pebbles', 'age': 1 }
112
113
  * }
113
114
  *
114
- * _.mapValues(users, function(_key, value) { return value.age; });
115
+ * _mapValues(users, (_key, value) => value.age)
115
116
  * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
116
117
  *
117
- * // The `_.property` iteratee shorthand.
118
- * _.mapValues(users, 'age')
119
- * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
118
+ * To skip some key-value pairs - use _mapObject instead.
120
119
  */
121
- export function _mapValues<T extends AnyObject, OUT = T>(
120
+ export function _mapValues<T extends AnyObject>(
122
121
  obj: T,
123
122
  mapper: ObjectMapper<T, any>,
124
123
  mutate = false,
125
- ): OUT {
126
- return Object.entries(obj).reduce(
124
+ ): T {
125
+ return _objectEntries(obj).reduce(
127
126
  (map, [k, v]) => {
128
- map[k as keyof OUT] = mapper(k, v, obj)
127
+ map[k] = mapper(k, v, obj)
129
128
  return map
130
129
  },
131
- (mutate ? obj : {}) as OUT,
130
+ mutate ? obj : ({} as T),
132
131
  )
133
132
  }
134
133
 
@@ -137,15 +136,20 @@ export function _mapValues<T extends AnyObject, OUT = T>(
137
136
  * // => { 'a1': 1, 'b2': 2 }
138
137
  *
139
138
  * Does not support `mutate` flag.
139
+ *
140
+ * To skip some key-value pairs - use _mapObject instead.
140
141
  */
141
142
  export function _mapKeys<T extends AnyObject>(
142
143
  obj: T,
143
144
  mapper: ObjectMapper<T, string>,
144
- ): StringMap<T[keyof T]> {
145
- return Object.entries(obj).reduce((map, [k, v]) => {
146
- map[mapper(k, v, obj) as keyof T] = v
147
- return map
148
- }, {} as T)
145
+ ): Record<string, T[keyof T]> {
146
+ return _objectEntries(obj).reduce(
147
+ (map, [k, v]) => {
148
+ map[mapper(k, v, obj)] = v
149
+ return map
150
+ },
151
+ {} as Record<string, T[keyof T]>,
152
+ )
149
153
  }
150
154
 
151
155
  /**
@@ -160,24 +164,21 @@ export function _mapKeys<T extends AnyObject>(
160
164
  * 0 - key of returned object (string)
161
165
  * 1 - value of returned object (any)
162
166
  *
163
- * If predicate returns falsy value (e.g undefined), or a tuple where key (first item) is falsy - then such key/value pair is ignored (filtered out).
167
+ * If predicate returns SKIP symbol - such key/value pair is ignored (filtered out).
164
168
  *
165
169
  * Non-string keys are passed via String(...)
166
170
  */
167
- export function _mapObject<IN extends AnyObject, OUT>(
168
- obj: IN,
169
- mapper: ObjectMapper<IN, [key: string, value: any]>,
170
- ): { [P in keyof IN]: OUT } {
171
- return Object.entries(obj).reduce(
172
- (map, [k, v]) => {
173
- const r = mapper(k, v, obj) || []
174
- if (r[0]) {
175
- ;(map[r[0]] as any) = r[1]
176
- }
177
- return map
178
- },
179
- {} as { [P in keyof IN]: OUT },
180
- )
171
+ export function _mapObject<T extends AnyObject>(
172
+ obj: T,
173
+ mapper: ObjectMapper<T, KeyValueTuple<string, any> | typeof SKIP>,
174
+ ): T {
175
+ return Object.entries(obj).reduce((map, [k, v]) => {
176
+ const r = mapper(k, v, obj)
177
+ if (r !== SKIP) {
178
+ map[r[0]] = r[1]
179
+ }
180
+ return map
181
+ }, {} as AnyObject) as T
181
182
  }
182
183
 
183
184
  export function _findKeyByValue<T extends AnyObject>(obj: T, v: ValueOf<T>): keyof T | undefined {
@@ -404,3 +405,23 @@ export function _has<T extends AnyObject>(obj: T, path: string): boolean {
404
405
  const v = _get(obj, path)
405
406
  return v !== undefined && v !== null
406
407
  }
408
+
409
+ /**
410
+ * Does Object.freeze recursively for given object.
411
+ *
412
+ * Based on: https://github.com/substack/deep-freeze/blob/master/index.js
413
+ */
414
+ export function _deepFreeze(o: any): void {
415
+ Object.freeze(o)
416
+
417
+ Object.getOwnPropertyNames(o).forEach(prop => {
418
+ if (
419
+ o.hasOwnProperty(prop) && // eslint-disable-line no-prototype-builtins
420
+ o[prop] !== null &&
421
+ (typeof o[prop] === 'object' || typeof o[prop] === 'function') &&
422
+ !Object.isFrozen(o[prop])
423
+ ) {
424
+ _deepFreeze(o[prop])
425
+ }
426
+ })
427
+ }
@@ -1,11 +1,11 @@
1
- import { AppError } from '../error/app.error'
2
- import type { ErrorData, ErrorObject } from '../error/error.model'
1
+ import { AppError, AppErrorOptions } from '../error/app.error'
2
+ import type { ErrorData } from '../error/error.model'
3
3
  import { _errorDataAppend } from '../error/error.util'
4
4
  import type { AnyAsyncFunction, NumberOfMilliseconds } from '../types'
5
5
 
6
6
  export class TimeoutError extends AppError {
7
- constructor(message: string, data = {}, cause?: ErrorObject) {
8
- super(message, data, cause, 'TimeoutError')
7
+ constructor(message: string, data?: ErrorData, opt?: AppErrorOptions) {
8
+ super(message, data, { ...opt, name: 'TimeoutError' })
9
9
  }
10
10
  }
11
11
 
package/src/types.ts CHANGED
@@ -163,7 +163,7 @@ export type KeyValueTuple<K, V> = [key: K, value: V]
163
163
 
164
164
  // Exclude<something, undefined> is used here to support StringMap<OBJ> (because values of StringMap add `undefined`)
165
165
  export type ObjectMapper<OBJ, OUT> = (
166
- key: string,
166
+ key: keyof OBJ,
167
167
  value: Exclude<OBJ[keyof OBJ], undefined>,
168
168
  obj: OBJ,
169
169
  ) => OUT
@@ -250,11 +250,21 @@ export const _stringMapValues = Object.values as <T>(m: StringMap<T>) => T[]
250
250
  export const _stringMapEntries = Object.entries as <T>(m: StringMap<T>) => [k: string, v: T][]
251
251
 
252
252
  /**
253
- * Like `Object.keys`, but returns keys typed as `keyof T`, not as just `string`.
253
+ * Alias of `Object.keys`, but returns keys typed as `keyof T`, not as just `string`.
254
254
  * This is how TypeScript should work, actually.
255
255
  */
256
256
  export const _objectKeys = Object.keys as <T extends AnyObject>(obj: T) => (keyof T)[]
257
257
 
258
+ /**
259
+ * Alias of `Object.entries`, but returns better-typed output.
260
+ *
261
+ * So e.g you can use _objectEntries(obj).map([k, v] => {})
262
+ * and `k` will be `keyof obj` instead of generic `string`.
263
+ */
264
+ export const _objectEntries = Object.entries as <T extends AnyObject>(
265
+ obj: T,
266
+ ) => [k: keyof T, v: T[keyof T]][]
267
+
258
268
  export type NullishValue = null | undefined
259
269
  export type FalsyValue = false | '' | 0 | null | undefined
260
270
 
package/dist/lazy.js DELETED
@@ -1,65 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports._defineLazyProps = exports._defineLazyProperty = exports._lazyValue = void 0;
4
- /**
5
- * const value = lazyValue(() => expensiveComputation())
6
- *
7
- * value() // calls expensiveComputation() once
8
- * value() // returns cached result
9
- * value() // returns cached result
10
- *
11
- * Based on: https://github.com/sindresorhus/lazy-value
12
- */
13
- function _lazyValue(fn) {
14
- let isCalled = false;
15
- let result;
16
- return (() => {
17
- if (!isCalled) {
18
- isCalled = true;
19
- result = fn();
20
- }
21
- return result;
22
- });
23
- }
24
- exports._lazyValue = _lazyValue;
25
- /**
26
- * interface Obj {
27
- * v: number
28
- * }
29
- *
30
- * const obj = {} as Obj
31
- *
32
- * _defineLazyProperty(obj, 'v', () => expensiveComputation())
33
- * obj.v // runs expensiveComputation() once
34
- * obj.v // cached value
35
- * obj.v // cached value
36
- *
37
- * Based on: https://github.com/sindresorhus/define-lazy-prop
38
- */
39
- function _defineLazyProperty(obj, propertyName, fn) {
40
- const define = (value) => {
41
- Object.defineProperty(obj, propertyName, { value, enumerable: true, writable: true });
42
- };
43
- Object.defineProperty(obj, propertyName, {
44
- configurable: true,
45
- enumerable: true,
46
- get() {
47
- const result = fn();
48
- define(result);
49
- return result;
50
- },
51
- set(value) {
52
- define(value);
53
- },
54
- });
55
- return obj;
56
- }
57
- exports._defineLazyProperty = _defineLazyProperty;
58
- /**
59
- * Like _defineLazyProperty, but allows to define multiple props at once.
60
- */
61
- function _defineLazyProps(obj, props) {
62
- Object.entries(props).forEach(([k, fn]) => _defineLazyProperty(obj, k, fn));
63
- return obj;
64
- }
65
- exports._defineLazyProps = _defineLazyProps;