@naturalcycles/js-lib 14.95.1 → 14.97.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.
@@ -1,6 +1,6 @@
1
1
  import { _assert } from '../error/assert'
2
2
  import { Sequence } from '../seq/seq'
3
- import { END, IsoDate, UnixTimestamp } from '../types'
3
+ import { END, IsoDateString, UnixTimestampNumber } from '../types'
4
4
  import { LocalTime } from './localTime'
5
5
 
6
6
  export type LocalDateUnit = 'year' | 'month' | 'day'
@@ -10,11 +10,13 @@ const m31 = new Set<number>([1, 3, 5, 7, 8, 10, 12])
10
10
 
11
11
  export type LocalDateConfig = LocalDate | string
12
12
 
13
+ /* eslint-disable no-dupe-class-members */
14
+
13
15
  /**
14
16
  * @experimental
15
17
  */
16
18
  export class LocalDate {
17
- private constructor(public year: number, public month: number, public day: number) {}
19
+ private constructor(private $year: number, private $month: number, private $day: number) {}
18
20
 
19
21
  static create(year: number, month: number, day: number): LocalDate {
20
22
  return new LocalDate(year, month, day)
@@ -151,7 +153,7 @@ export class LocalDate {
151
153
  maxExcl: LocalDateConfig,
152
154
  step = 1,
153
155
  stepUnit: LocalDateUnit = 'day',
154
- ): IsoDate[] {
156
+ ): IsoDateString[] {
155
157
  return LocalDate.range(minIncl, maxExcl, step, stepUnit).map(ld => ld.toString())
156
158
  }
157
159
 
@@ -169,15 +171,49 @@ export class LocalDate {
169
171
  maxIncl: LocalDateConfig,
170
172
  step = 1,
171
173
  stepUnit: LocalDateUnit = 'day',
172
- ): IsoDate[] {
174
+ ): IsoDateString[] {
173
175
  return LocalDate.range(minIncl, LocalDate.of(maxIncl).add(1, stepUnit), step, stepUnit).map(
174
176
  ld => ld.toString(),
175
177
  )
176
178
  }
177
179
 
180
+ get(unit: LocalDateUnit): number {
181
+ return unit === 'year' ? this.$year : unit === 'month' ? this.$month : this.$day
182
+ }
183
+
184
+ set(unit: LocalDateUnit, v: number, mutate = false): LocalDate {
185
+ const t = mutate ? this : this.clone()
186
+
187
+ if (unit === 'year') {
188
+ t.$year = v
189
+ } else if (unit === 'month') {
190
+ t.$month = v
191
+ } else {
192
+ t.$day = v
193
+ }
194
+
195
+ return t
196
+ }
197
+
198
+ year(): number
199
+ year(v: number): LocalDate
200
+ year(v?: number): number | LocalDate {
201
+ return v === undefined ? this.$year : this.set('year', v)
202
+ }
203
+ month(): number
204
+ month(v: number): LocalDate
205
+ month(v?: number): number | LocalDate {
206
+ return v === undefined ? this.$month : this.set('month', v)
207
+ }
208
+ day(): number
209
+ day(v: number): LocalDate
210
+ day(v?: number): number | LocalDate {
211
+ return v === undefined ? this.$day : this.set('day', v)
212
+ }
213
+
178
214
  isSame(d: LocalDateConfig): boolean {
179
215
  d = LocalDate.of(d)
180
- return this.day === d.day && this.month === d.month && this.year === d.year
216
+ return this.$day === d.$day && this.$month === d.$month && this.$year === d.$year
181
217
  }
182
218
 
183
219
  isBefore(d: LocalDateConfig): boolean {
@@ -211,12 +247,12 @@ export class LocalDate {
211
247
  */
212
248
  cmp(d: LocalDateConfig): -1 | 0 | 1 {
213
249
  d = LocalDate.of(d)
214
- if (this.year < d.year) return -1
215
- if (this.year > d.year) return 1
216
- if (this.month < d.month) return -1
217
- if (this.month > d.month) return 1
218
- if (this.day < d.day) return -1
219
- if (this.day > d.day) return 1
250
+ if (this.$year < d.$year) return -1
251
+ if (this.$year > d.$year) return 1
252
+ if (this.$month < d.$month) return -1
253
+ if (this.$month > d.$month) return 1
254
+ if (this.$day < d.$day) return -1
255
+ if (this.$day > d.$day) return 1
220
256
  return 0
221
257
  }
222
258
 
@@ -236,33 +272,33 @@ export class LocalDate {
236
272
  d = LocalDate.of(d)
237
273
 
238
274
  if (unit === 'year') {
239
- return this.year - d.year
275
+ return this.$year - d.$year
240
276
  }
241
277
 
242
278
  if (unit === 'month') {
243
- return (this.year - d.year) * 12 + (this.month - d.month)
279
+ return (this.$year - d.$year) * 12 + (this.$month - d.$month)
244
280
  }
245
281
 
246
282
  // unit is 'day'
247
- let days = this.day - d.day
283
+ let days = this.$day - d.$day
248
284
 
249
- if (d.year < this.year) {
250
- for (let year = d.year; year < this.year; year++) {
285
+ if (d.$year < this.$year) {
286
+ for (let year = d.$year; year < this.$year; year++) {
251
287
  days += LocalDate.getYearLength(year)
252
288
  }
253
- } else if (this.year < d.year) {
254
- for (let year = this.year; year < d.year; year++) {
289
+ } else if (this.$year < d.$year) {
290
+ for (let year = this.$year; year < d.$year; year++) {
255
291
  days -= LocalDate.getYearLength(year)
256
292
  }
257
293
  }
258
294
 
259
- if (d.month < this.month) {
260
- for (let month = d.month; month < this.month; month++) {
261
- days += LocalDate.getMonthLength(this.year, month)
295
+ if (d.$month < this.$month) {
296
+ for (let month = d.$month; month < this.$month; month++) {
297
+ days += LocalDate.getMonthLength(this.$year, month)
262
298
  }
263
- } else if (this.month < d.month) {
264
- for (let month = this.month; month < d.month; month++) {
265
- days -= LocalDate.getMonthLength(d.year, month)
299
+ } else if (this.$month < d.$month) {
300
+ for (let month = this.$month; month < d.$month; month++) {
301
+ days -= LocalDate.getMonthLength(d.$year, month)
266
302
  }
267
303
  }
268
304
 
@@ -270,57 +306,57 @@ export class LocalDate {
270
306
  }
271
307
 
272
308
  add(num: number, unit: LocalDateUnit, mutate = false): LocalDate {
273
- let { day, month, year } = this
309
+ let { $day, $month, $year } = this
274
310
 
275
311
  if (unit === 'day') {
276
- day += num
312
+ $day += num
277
313
  } else if (unit === 'month') {
278
- month += num
314
+ $month += num
279
315
  } else if (unit === 'year') {
280
- year += num
316
+ $year += num
281
317
  }
282
318
 
283
319
  // check day overflow
284
- let monLen = LocalDate.getMonthLength(year, month)
285
- while (day > monLen) {
286
- day -= monLen
287
- month += 1
288
- if (month > 12) {
289
- year += 1
290
- month -= 12
320
+ let monLen = LocalDate.getMonthLength($year, $month)
321
+ while ($day > monLen) {
322
+ $day -= monLen
323
+ $month += 1
324
+ if ($month > 12) {
325
+ $year += 1
326
+ $month -= 12
291
327
  }
292
328
 
293
- monLen = LocalDate.getMonthLength(year, month)
329
+ monLen = LocalDate.getMonthLength($year, $month)
294
330
  }
295
- while (day < 1) {
296
- day += monLen
297
- month -= 1
298
- if (month < 1) {
299
- year -= 1
300
- month += 12
331
+ while ($day < 1) {
332
+ $day += monLen
333
+ $month -= 1
334
+ if ($month < 1) {
335
+ $year -= 1
336
+ $month += 12
301
337
  }
302
338
 
303
- monLen = LocalDate.getMonthLength(year, month)
339
+ monLen = LocalDate.getMonthLength($year, $month)
304
340
  }
305
341
 
306
342
  // check month overflow
307
- while (month > 12) {
308
- year += 1
309
- month -= 12
343
+ while ($month > 12) {
344
+ $year += 1
345
+ $month -= 12
310
346
  }
311
- while (month < 1) {
312
- year -= 1
313
- month += 12
347
+ while ($month < 1) {
348
+ $year -= 1
349
+ $month += 12
314
350
  }
315
351
 
316
352
  if (mutate) {
317
- this.year = year
318
- this.month = month
319
- this.day = day
353
+ this.$year = $year
354
+ this.$month = $month
355
+ this.$day = $day
320
356
  return this
321
357
  }
322
358
 
323
- return new LocalDate(year, month, day)
359
+ return new LocalDate($year, $month, $day)
324
360
  }
325
361
 
326
362
  subtract(num: number, unit: LocalDateUnit, mutate = false): LocalDate {
@@ -329,21 +365,21 @@ export class LocalDate {
329
365
 
330
366
  startOf(unit: LocalDateUnit): LocalDate {
331
367
  if (unit === 'day') return this
332
- if (unit === 'month') return LocalDate.create(this.year, this.month, 1)
368
+ if (unit === 'month') return LocalDate.create(this.$year, this.$month, 1)
333
369
  // year
334
- return LocalDate.create(this.year, 1, 1)
370
+ return LocalDate.create(this.$year, 1, 1)
335
371
  }
336
372
 
337
373
  endOf(unit: LocalDateUnit): LocalDate {
338
374
  if (unit === 'day') return this
339
375
  if (unit === 'month')
340
376
  return LocalDate.create(
341
- this.year,
342
- this.month,
343
- LocalDate.getMonthLength(this.year, this.month),
377
+ this.$year,
378
+ this.$month,
379
+ LocalDate.getMonthLength(this.$year, this.$month),
344
380
  )
345
381
  // year
346
- return LocalDate.create(this.year, 12, 31)
382
+ return LocalDate.create(this.$year, 12, 31)
347
383
  }
348
384
 
349
385
  static getYearLength(year: number): number {
@@ -362,7 +398,7 @@ export class LocalDate {
362
398
  }
363
399
 
364
400
  clone(): LocalDate {
365
- return new LocalDate(this.year, this.month, this.day)
401
+ return new LocalDate(this.$year, this.$month, this.$day)
366
402
  }
367
403
 
368
404
  /**
@@ -372,35 +408,35 @@ export class LocalDate {
372
408
  * Timezone will match local timezone.
373
409
  */
374
410
  toDate(): Date {
375
- return new Date(this.year, this.month - 1, this.day)
411
+ return new Date(this.$year, this.$month - 1, this.$day)
376
412
  }
377
413
 
378
414
  toLocalTime(): LocalTime {
379
415
  return LocalTime.of(this.toDate())
380
416
  }
381
417
 
382
- toISODate(): IsoDate {
418
+ toISODate(): IsoDateString {
383
419
  return this.toString()
384
420
  }
385
421
 
386
- toString(): IsoDate {
422
+ toString(): IsoDateString {
387
423
  return [
388
- String(this.year).padStart(4, '0'),
389
- String(this.month).padStart(2, '0'),
390
- String(this.day).padStart(2, '0'),
424
+ String(this.$year).padStart(4, '0'),
425
+ String(this.$month).padStart(2, '0'),
426
+ String(this.$day).padStart(2, '0'),
391
427
  ].join('-')
392
428
  }
393
429
 
394
430
  toStringCompact(): string {
395
431
  return [
396
- String(this.year).padStart(4, '0'),
397
- String(this.month).padStart(2, '0'),
398
- String(this.day).padStart(2, '0'),
432
+ String(this.$year).padStart(4, '0'),
433
+ String(this.$month).padStart(2, '0'),
434
+ String(this.$day).padStart(2, '0'),
399
435
  ].join('')
400
436
  }
401
437
 
402
438
  // May be not optimal, as LocalTime better suits it
403
- unix(): UnixTimestamp {
439
+ unix(): UnixTimestampNumber {
404
440
  return Math.floor(this.toDate().valueOf() / 1000)
405
441
  }
406
442
 
@@ -408,7 +444,7 @@ export class LocalDate {
408
444
  return this.toDate().valueOf()
409
445
  }
410
446
 
411
- toJSON(): IsoDate {
447
+ toJSON(): IsoDateString {
412
448
  return this.toString()
413
449
  }
414
450
  }
@@ -1,11 +1,11 @@
1
1
  import { _assert } from '../error/assert'
2
2
  import { _ms } from '../time/time.util'
3
- import { IsoDate, IsoDateTime, UnixTimestamp } from '../types'
3
+ import { IsoDateString, IsoDateTimeString, UnixTimestampNumber } from '../types'
4
4
  import { Inclusiveness, LocalDate } from './localDate'
5
5
 
6
6
  export type LocalTimeUnit = 'year' | 'month' | 'day' | 'hour' | 'minute' | 'second'
7
7
 
8
- export type LocalTimeConfig = LocalTime | Date | IsoDateTime | UnixTimestamp
8
+ export type LocalTimeConfig = LocalTime | Date | IsoDateTimeString | UnixTimestampNumber
9
9
 
10
10
  export interface LocalTimeComponents {
11
11
  year: number
@@ -18,18 +18,6 @@ export interface LocalTimeComponents {
18
18
 
19
19
  /* eslint-disable no-dupe-class-members */
20
20
 
21
- // Design choices:
22
- // No milliseconds
23
- // No timezone support, ISO8601 is parsed as LocalDateTime, discarding Timezone information
24
- // Formats as unix timestamp, ISO8601 or "pretty string"
25
- // toString and .toJSON formats as unix timestamp
26
- // No "unixMillis", just pure unixtimestamp
27
- // .valueOf returns unix timestamp (no millis)
28
- // Prevents dayjs(undefined) being dayjs.now()
29
- // Validates on parse, throws if invalid. Doesn't allow invalid objects
30
- // No arbitrary .format('') (which is slow to parse) vs well-defined (opinionated) formats
31
- // Separate LocalTime, powered by native js Date, and LocalDate - a smaller functionality class when
32
- // you only need "whole dates", no time, no timezone worry
33
21
  /**
34
22
  * @experimental
35
23
  */
@@ -156,9 +144,9 @@ export class LocalTime {
156
144
  month(v?: number): number | LocalTime {
157
145
  return v === undefined ? this.get('month') : this.set('month', v)
158
146
  }
159
- date(): number
160
- date(v: number): LocalTime
161
- date(v?: number): number | LocalTime {
147
+ day(): number
148
+ day(v: number): LocalTime
149
+ day(v?: number): number | LocalTime {
162
150
  return v === undefined ? this.get('day') : this.set('day', v)
163
151
  }
164
152
  hour(): number
@@ -387,7 +375,7 @@ export class LocalTime {
387
375
  return new LocalTime(new Date(this.$date), this.utcMode)
388
376
  }
389
377
 
390
- unix(): UnixTimestamp {
378
+ unix(): UnixTimestampNumber {
391
379
  return Math.floor(this.$date.valueOf() / 1000)
392
380
  }
393
381
 
@@ -395,7 +383,7 @@ export class LocalTime {
395
383
  return this.$date.valueOf()
396
384
  }
397
385
 
398
- valueOf(): UnixTimestamp {
386
+ valueOf(): UnixTimestampNumber {
399
387
  return Math.floor(this.$date.valueOf() / 1000)
400
388
  }
401
389
 
@@ -415,7 +403,7 @@ export class LocalTime {
415
403
  )
416
404
  }
417
405
 
418
- toPretty(seconds = true): IsoDateTime {
406
+ toPretty(seconds = true): IsoDateTimeString {
419
407
  const { year, month, day, hour, minute, second } = this.components()
420
408
 
421
409
  return (
@@ -444,14 +432,14 @@ export class LocalTime {
444
432
  /**
445
433
  * Returns e.g: `1984-06-21T17:56:21`, only the date part of DateTime
446
434
  */
447
- toISODateTime(): IsoDateTime {
435
+ toISODateTime(): IsoDateTimeString {
448
436
  return this.$date.toISOString().slice(0, 19)
449
437
  }
450
438
 
451
439
  /**
452
440
  * Returns e.g: `1984-06-21`, only the date part of DateTime
453
441
  */
454
- toISODate(): IsoDate {
442
+ toISODate(): IsoDateString {
455
443
  const { year, month, day } = this.components()
456
444
 
457
445
  return [
@@ -500,7 +488,7 @@ export class LocalTime {
500
488
  return String(this.unix())
501
489
  }
502
490
 
503
- toJSON(): UnixTimestamp {
491
+ toJSON(): UnixTimestampNumber {
504
492
  return this.unix()
505
493
  }
506
494
  }
package/src/error/try.ts CHANGED
@@ -6,18 +6,24 @@ import { AppError } from './app.error'
6
6
  * Allows to write shorter code that avoids `try/catch`.
7
7
  * Useful e.g. in unit tests.
8
8
  *
9
- * Similar to pTuple, but for sync functions.
9
+ * Similar to pTry, but for sync functions.
10
10
  *
11
11
  * For convenience, second argument type is non-optional,
12
12
  * so you can use it without `!`. But you SHOULD always check `if (err)` first!
13
13
  *
14
+ * ERR is typed as Error, not `unknown`. While unknown would be more correct,
15
+ * according to recent TypeScript, Error gives more developer convenience.
16
+ * In our code we NEVER throw non-errors.
17
+ * Only possibility of non-error is in the 3rd-party library code, in these cases it
18
+ * can be manually cast to `unknown` for extra safety.
19
+ *
14
20
  * @example
15
21
  *
16
22
  * const [err, v] = _try(() => someFunction())
17
23
  * if (err) ...do something...
18
24
  * v // go ahead and use v
19
25
  */
20
- export function _try<ERR = unknown, RETURN = void>(
26
+ export function _try<ERR = Error, RETURN = void>(
21
27
  fn: () => RETURN,
22
28
  ): [err: ERR | null, value: RETURN] {
23
29
  try {
@@ -33,7 +39,7 @@ export function _try<ERR = unknown, RETURN = void>(
33
39
  * Also, intentionally types second return item as non-optional,
34
40
  * but you should check for `err` presense first!
35
41
  */
36
- export async function pTry<ERR = unknown, RETURN = void>(
42
+ export async function pTry<ERR = Error, RETURN = void>(
37
43
  promise: Promise<RETURN>,
38
44
  ): Promise<[err: ERR | null, value: Awaited<RETURN>]> {
39
45
  try {
@@ -50,7 +56,7 @@ export async function pTry<ERR = unknown, RETURN = void>(
50
56
  */
51
57
  export class UnexpectedPassError extends AppError {
52
58
  constructor() {
53
- super('_expectedError passed unexpectedly')
59
+ super('expected error was not thrown')
54
60
  }
55
61
  }
56
62
 
@@ -1,4 +1,4 @@
1
- import { _since, _stringifyAny, CommonLogger } from '../index'
1
+ import { _anyToError, _since, _stringifyAny, CommonLogger } from '../index'
2
2
  import { AnyFunction } from '../types'
3
3
 
4
4
  export interface TryCatchOptions {
@@ -6,7 +6,7 @@ export interface TryCatchOptions {
6
6
  * The value returned from the function will be returned from the wrapped method (!).
7
7
  * onError function may be asynchronous.
8
8
  */
9
- onError?: (err: unknown) => any
9
+ onError?: (err: Error) => any
10
10
 
11
11
  /**
12
12
  * @default false
@@ -59,7 +59,7 @@ export function _tryCatch<T extends AnyFunction>(fn: T, opt: TryCatchOptions = {
59
59
 
60
60
  if (onError) {
61
61
  try {
62
- return await onError(err) // eslint-disable-line @typescript-eslint/return-await
62
+ return await onError(_anyToError(err)) // eslint-disable-line @typescript-eslint/return-await
63
63
  } catch {}
64
64
  }
65
65
  // returns undefined, but doesn't rethrow
package/src/index.ts CHANGED
@@ -78,7 +78,6 @@ export * from './promise/pProps'
78
78
  import { pRetry, pRetryFn, PRetryOptions } from './promise/pRetry'
79
79
  export * from './promise/pState'
80
80
  import { pTimeout, pTimeoutFn, PTimeoutOptions } from './promise/pTimeout'
81
- export * from './promise/pTuple'
82
81
  export * from './string/case'
83
82
  export * from './string/json.util'
84
83
  export * from './string/string.util'
@@ -106,7 +105,8 @@ import {
106
105
  BatchResult,
107
106
  InstanceId,
108
107
  IsoDate,
109
- IsoDateTime,
108
+ IsoDateString,
109
+ IsoDateTimeString,
110
110
  KeyValueTuple,
111
111
  Mapper,
112
112
  ObjectMapper,
@@ -118,6 +118,7 @@ import {
118
118
  Reviver,
119
119
  SavedDBEntity,
120
120
  StringMap,
121
+ UnixTimestampNumber,
121
122
  UnixTimestamp,
122
123
  Integer,
123
124
  ValueOf,
@@ -198,7 +199,8 @@ export type {
198
199
  ObjectPredicate,
199
200
  InstanceId,
200
201
  IsoDate,
201
- IsoDateTime,
202
+ IsoDateString,
203
+ IsoDateTimeString,
202
204
  Reviver,
203
205
  PMapOptions,
204
206
  Mapper,
@@ -219,6 +221,7 @@ export type {
219
221
  ConditionalPick,
220
222
  ConditionalExcept,
221
223
  Class,
224
+ UnixTimestampNumber,
222
225
  UnixTimestamp,
223
226
  Integer,
224
227
  BaseDBEntity,
package/src/types.ts CHANGED
@@ -150,6 +150,11 @@ export interface InstanceId {
150
150
  *
151
151
  * @example '2019-06-21'
152
152
  */
153
+ export type IsoDateString = string
154
+
155
+ /**
156
+ * @deprecated use IsoDateString
157
+ */
153
158
  export type IsoDate = string
154
159
 
155
160
  /**
@@ -157,13 +162,18 @@ export type IsoDate = string
157
162
  *
158
163
  * @example '2019-06-21T05:21:73Z'
159
164
  */
160
- export type IsoDateTime = string
165
+ export type IsoDateTimeString = string
161
166
 
162
167
  /**
163
168
  * Interface explicitly states that the value is a Unix timestamp (in seconds).
164
169
  *
165
170
  * @example 1628945450
166
171
  */
172
+ export type UnixTimestampNumber = number
173
+
174
+ /**
175
+ * @deprecated use UnixTimestampNumber
176
+ */
167
177
  export type UnixTimestamp = number
168
178
 
169
179
  /**
@@ -180,12 +190,12 @@ export interface SavedDBEntity<ID = string> {
180
190
  /**
181
191
  * unixTimestamp of when the entity was first created (in the DB).
182
192
  */
183
- created: UnixTimestamp
193
+ created: UnixTimestampNumber
184
194
 
185
195
  /**
186
196
  * unixTimestamp of when the entity was last updated (in the DB).
187
197
  */
188
- updated: UnixTimestamp
198
+ updated: UnixTimestampNumber
189
199
  }
190
200
 
191
201
  /**
@@ -1,7 +0,0 @@
1
- /**
2
- * Wraps async calls in try catch blocks
3
- * to simplify syntax.
4
- *
5
- * source: https://github.com/scopsy/await-to-js/blob/master/src/await-to-js.ts
6
- */
7
- export declare function pTuple<RETURN, ERR = Error>(promise: Promise<RETURN>): Promise<[ERR, undefined] | [null, RETURN]>;
@@ -1,13 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.pTuple = void 0;
4
- /**
5
- * Wraps async calls in try catch blocks
6
- * to simplify syntax.
7
- *
8
- * source: https://github.com/scopsy/await-to-js/blob/master/src/await-to-js.ts
9
- */
10
- async function pTuple(promise) {
11
- return promise.then(data => [null, data]).catch(err => [err, undefined]);
12
- }
13
- exports.pTuple = pTuple;
@@ -1,9 +0,0 @@
1
- /**
2
- * Wraps async calls in try catch blocks
3
- * to simplify syntax.
4
- *
5
- * source: https://github.com/scopsy/await-to-js/blob/master/src/await-to-js.ts
6
- */
7
- export async function pTuple(promise) {
8
- return promise.then(data => [null, data]).catch(err => [err, undefined]);
9
- }
@@ -1,11 +0,0 @@
1
- /**
2
- * Wraps async calls in try catch blocks
3
- * to simplify syntax.
4
- *
5
- * source: https://github.com/scopsy/await-to-js/blob/master/src/await-to-js.ts
6
- */
7
- export async function pTuple<RETURN, ERR = Error>(
8
- promise: Promise<RETURN>,
9
- ): Promise<[ERR, undefined] | [null, RETURN]> {
10
- return promise.then(data => [null, data] as [null, RETURN]).catch(err => [err as ERR, undefined])
11
- }