@naturalcycles/js-lib 14.74.0 → 14.77.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.
- package/dist/decorators/logMethod.decorator.js +1 -3
- package/dist/decorators/timeout.decorator.js +9 -1
- package/dist/error/try.d.ts +20 -0
- package/dist/error/try.js +47 -1
- package/dist/index.d.ts +20 -20
- package/dist/index.js +20 -52
- package/dist/promise/pRetry.d.ts +7 -2
- package/dist/promise/pRetry.js +4 -4
- package/dist/promise/pTimeout.d.ts +10 -1
- package/dist/promise/pTimeout.js +43 -29
- package/dist/seq/seq.d.ts +30 -7
- package/dist/seq/seq.js +126 -9
- package/dist/string/stringifyAny.js +12 -10
- package/dist/unit/size.util.d.ts +6 -0
- package/dist/unit/size.util.js +33 -10
- package/dist-esm/decorators/logMethod.decorator.js +2 -4
- package/dist-esm/decorators/timeout.decorator.js +9 -1
- package/dist-esm/error/try.js +43 -0
- package/dist-esm/index.js +20 -20
- package/dist-esm/promise/pRetry.js +4 -4
- package/dist-esm/promise/pTimeout.js +40 -28
- package/dist-esm/seq/seq.js +124 -8
- package/dist-esm/string/stringifyAny.js +12 -10
- package/dist-esm/unit/size.util.js +31 -9
- package/package.json +1 -1
- package/src/decorators/logMethod.decorator.ts +2 -4
- package/src/decorators/timeout.decorator.ts +12 -1
- package/src/error/try.ts +44 -0
- package/src/index.ts +20 -60
- package/src/promise/pRetry.ts +13 -5
- package/src/promise/pTimeout.ts +41 -29
- package/src/seq/seq.ts +144 -13
- package/src/string/stringifyAny.ts +13 -9
- package/src/unit/size.util.ts +22 -6
package/src/seq/seq.ts
CHANGED
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
AbortableAsyncMapper,
|
|
3
|
+
AbortableAsyncPredicate,
|
|
4
|
+
AbortableMapper,
|
|
5
|
+
AbortablePredicate,
|
|
6
|
+
END,
|
|
7
|
+
SKIP,
|
|
8
|
+
} from '../types'
|
|
2
9
|
|
|
3
10
|
/**
|
|
4
11
|
* Inspired by Kotlin Sequences.
|
|
@@ -8,7 +15,7 @@ import { AbortableMapper, AbortablePredicate, END, SKIP } from '../types'
|
|
|
8
15
|
*
|
|
9
16
|
* @experimental
|
|
10
17
|
*/
|
|
11
|
-
export class
|
|
18
|
+
export class Sequence<T> implements Iterable<T> {
|
|
12
19
|
private constructor(initialValue: T | typeof END, private nextFn: AbortableMapper<T, T>) {
|
|
13
20
|
this.currentValue = initialValue
|
|
14
21
|
}
|
|
@@ -22,29 +29,29 @@ export class Seq<T> implements Iterable<T> {
|
|
|
22
29
|
}
|
|
23
30
|
}
|
|
24
31
|
|
|
25
|
-
static create<T>(initialValue: T | typeof END, nextFn: AbortableMapper<T, T>):
|
|
26
|
-
return new
|
|
32
|
+
static create<T>(initialValue: T | typeof END, nextFn: AbortableMapper<T, T>): Sequence<T> {
|
|
33
|
+
return new Sequence(initialValue, nextFn)
|
|
27
34
|
}
|
|
28
35
|
|
|
29
|
-
static range(minIncl: number, maxExcl: number, step = 1):
|
|
36
|
+
static range(minIncl: number, maxExcl: number, step = 1): Sequence<number> {
|
|
30
37
|
const max = maxExcl - step
|
|
31
|
-
return new
|
|
38
|
+
return new Sequence(minIncl, n => (n < max ? n + step : END))
|
|
32
39
|
}
|
|
33
40
|
|
|
34
|
-
static from<T>(a: Iterable<T>):
|
|
41
|
+
static from<T>(a: Iterable<T>): Sequence<T> {
|
|
35
42
|
const it = a[Symbol.iterator]()
|
|
36
43
|
const v = it.next()
|
|
37
|
-
if (v.done) return new
|
|
44
|
+
if (v.done) return new Sequence<any>(END, () => {})
|
|
38
45
|
|
|
39
|
-
return new
|
|
46
|
+
return new Sequence(v.value, () => {
|
|
40
47
|
const v = it.next()
|
|
41
48
|
if (v.done) return END
|
|
42
49
|
return v.value
|
|
43
50
|
})
|
|
44
51
|
}
|
|
45
52
|
|
|
46
|
-
static empty<T = any>():
|
|
47
|
-
return new
|
|
53
|
+
static empty<T = any>(): Sequence<T> {
|
|
54
|
+
return new Sequence(END as any, () => {})
|
|
48
55
|
}
|
|
49
56
|
|
|
50
57
|
private currentValue: T | typeof END
|
|
@@ -133,11 +140,135 @@ export class Seq<T> implements Iterable<T> {
|
|
|
133
140
|
a.push(v)
|
|
134
141
|
}
|
|
135
142
|
}
|
|
143
|
+
|
|
144
|
+
forEach(fn: (v: T, i: number) => void): void {
|
|
145
|
+
let i = -1
|
|
146
|
+
// eslint-disable-next-line no-constant-condition
|
|
147
|
+
while (true) {
|
|
148
|
+
const v = this.next()
|
|
149
|
+
if (v === END) return
|
|
150
|
+
fn(v, ++i)
|
|
151
|
+
}
|
|
152
|
+
}
|
|
136
153
|
}
|
|
137
154
|
|
|
138
155
|
/**
|
|
139
156
|
* Convenience function to create a Sequence.
|
|
140
157
|
*/
|
|
141
|
-
export function _seq<T>(initialValue: T | typeof END, nextFn: AbortableMapper<T, T>):
|
|
142
|
-
return
|
|
158
|
+
export function _seq<T>(initialValue: T | typeof END, nextFn: AbortableMapper<T, T>): Sequence<T> {
|
|
159
|
+
return Sequence.create(initialValue, nextFn)
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/* eslint-disable no-await-in-loop */
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Experimental.
|
|
166
|
+
* Feasibility to be proven.
|
|
167
|
+
*
|
|
168
|
+
* @experimental
|
|
169
|
+
*/
|
|
170
|
+
export class AsyncSequence<T> implements AsyncIterable<T> {
|
|
171
|
+
private constructor(initialValue: T | typeof END, private nextFn: AbortableAsyncMapper<T, T>) {
|
|
172
|
+
this.currentValue = initialValue
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
[Symbol.asyncIterator](): AsyncIterator<T> {
|
|
176
|
+
return {
|
|
177
|
+
next: async () => {
|
|
178
|
+
const value = await this.next()
|
|
179
|
+
return value === END ? { done: true, value: undefined } : { value }
|
|
180
|
+
},
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
static create<T>(
|
|
185
|
+
initialValue: T | typeof END,
|
|
186
|
+
nextFn: AbortableAsyncMapper<T, T>,
|
|
187
|
+
): AsyncSequence<T> {
|
|
188
|
+
return new AsyncSequence(initialValue, nextFn)
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
static async from<T>(a: AsyncIterable<T>): Promise<AsyncSequence<T>> {
|
|
192
|
+
const it = a[Symbol.asyncIterator]()
|
|
193
|
+
const v = await it.next()
|
|
194
|
+
if (v.done) return new AsyncSequence<any>(END, () => {})
|
|
195
|
+
|
|
196
|
+
return new AsyncSequence(v.value, async () => {
|
|
197
|
+
const v = await it.next()
|
|
198
|
+
if (v.done) return END
|
|
199
|
+
return v.value
|
|
200
|
+
})
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
static empty<T = any>(): AsyncSequence<T> {
|
|
204
|
+
return new AsyncSequence(END as any, () => {})
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
private currentValue: T | typeof END
|
|
208
|
+
private sentInitialValue = false
|
|
209
|
+
private i = -1
|
|
210
|
+
|
|
211
|
+
async next(): Promise<T | typeof END> {
|
|
212
|
+
if (this.currentValue === END) return END
|
|
213
|
+
|
|
214
|
+
this.i++
|
|
215
|
+
|
|
216
|
+
let v: T | typeof SKIP | typeof END
|
|
217
|
+
|
|
218
|
+
if (!this.sentInitialValue) {
|
|
219
|
+
this.sentInitialValue = true
|
|
220
|
+
v = this.currentValue
|
|
221
|
+
} else {
|
|
222
|
+
v = await this.nextFn(this.currentValue, this.i)
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// console.log(`_seq`, v)
|
|
226
|
+
|
|
227
|
+
if (v === SKIP) return await this.next()
|
|
228
|
+
|
|
229
|
+
return (this.currentValue = v)
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// Final functions - return final value, not a chained sequence
|
|
233
|
+
async find(predicate: AbortableAsyncPredicate<T>): Promise<T | undefined> {
|
|
234
|
+
do {
|
|
235
|
+
const v = await this.next()
|
|
236
|
+
if (v === END) return // not found, end of sequence
|
|
237
|
+
const r = await predicate(v, this.i)
|
|
238
|
+
if (r === END) return
|
|
239
|
+
if (r) return v
|
|
240
|
+
// otherwise proceed
|
|
241
|
+
} while (true) // eslint-disable-line no-constant-condition
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
async some(predicate: AbortableAsyncPredicate<T>): Promise<boolean> {
|
|
245
|
+
do {
|
|
246
|
+
const v = await this.next()
|
|
247
|
+
if (v === END) return false
|
|
248
|
+
const r = await predicate(v, this.i)
|
|
249
|
+
if (r === END) return false
|
|
250
|
+
if (r) return true
|
|
251
|
+
} while (true) // eslint-disable-line no-constant-condition
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
async every(predicate: AbortableAsyncPredicate<T>): Promise<boolean> {
|
|
255
|
+
do {
|
|
256
|
+
const v = await this.next()
|
|
257
|
+
if (v === END) return true
|
|
258
|
+
const r = await predicate(v, this.i)
|
|
259
|
+
if (r === END) return true
|
|
260
|
+
if (!r) return false
|
|
261
|
+
} while (true) // eslint-disable-line no-constant-condition
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
async toArray(): Promise<T[]> {
|
|
265
|
+
const a: T[] = []
|
|
266
|
+
|
|
267
|
+
// eslint-disable-next-line no-constant-condition
|
|
268
|
+
while (true) {
|
|
269
|
+
const v = await this.next()
|
|
270
|
+
if (v === END) return a
|
|
271
|
+
a.push(v)
|
|
272
|
+
}
|
|
273
|
+
}
|
|
143
274
|
}
|
|
@@ -76,16 +76,20 @@ export function _stringifyAny(obj: any, opt: StringifyAnyOptions = {}): string {
|
|
|
76
76
|
// Error or ErrorObject
|
|
77
77
|
//
|
|
78
78
|
|
|
79
|
+
// Omit "default" error name as non-informative
|
|
80
|
+
// UPD: no, it's still important to understand that we're dealing with Error and not just some string
|
|
81
|
+
// if (obj?.name === 'Error') {
|
|
82
|
+
// s = obj.message
|
|
83
|
+
// }
|
|
84
|
+
s = [obj.name, obj.message].join(': ')
|
|
85
|
+
|
|
79
86
|
if (opt.includeErrorStack && obj.stack) {
|
|
80
|
-
//
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
//
|
|
84
|
-
//
|
|
85
|
-
|
|
86
|
-
// s = obj.message
|
|
87
|
-
// }
|
|
88
|
-
s = [obj.name, obj.message].join(': ')
|
|
87
|
+
// Here we're using the previously-generated "title line" (e.g "Error: some_message"),
|
|
88
|
+
// concatenating it with the Stack (but without the title line of the Stack)
|
|
89
|
+
// This is to fix the rare error (happened with Got) where `err.message` was changed,
|
|
90
|
+
// but err.stack had "old" err.message
|
|
91
|
+
// This should "fix" that
|
|
92
|
+
s = [s, ...obj.stack.split('\n').slice(1)].join('\n')
|
|
89
93
|
}
|
|
90
94
|
|
|
91
95
|
if (_isErrorObject(obj)) {
|
package/src/unit/size.util.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
export function _gb(b: number): number {
|
|
2
|
-
return Math.round(b /
|
|
2
|
+
return Math.round(b / 1024 ** 3)
|
|
3
3
|
}
|
|
4
4
|
|
|
5
5
|
export function _mb(b: number): number {
|
|
6
|
-
return Math.round(b /
|
|
6
|
+
return Math.round(b / 1024 ** 2)
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
export function _kb(b: number): number {
|
|
@@ -14,8 +14,24 @@ export function _kb(b: number): number {
|
|
|
14
14
|
* Byte size to Human byte size string
|
|
15
15
|
*/
|
|
16
16
|
export function _hb(b = 0): string {
|
|
17
|
-
if (b <
|
|
18
|
-
if (b <
|
|
19
|
-
if (b <
|
|
20
|
-
return `${
|
|
17
|
+
if (b < 1024) return `${Math.round(b)} byte`
|
|
18
|
+
if (b < 1024 ** 2) return `${(b / 1024).toPrecision(3)} Kb`
|
|
19
|
+
if (b < 1024 ** 3) return `${(b / 1024 ** 2).toPrecision(3)} Mb`
|
|
20
|
+
if (b < 1024 ** 4) return `${(b / 1024 ** 3).toPrecision(3)} Gb`
|
|
21
|
+
if (b < 1024 ** 5) return `${(b / 1024 ** 4).toPrecision(3)} Tb`
|
|
22
|
+
return `${Math.round(b / 1024 ** 4)} Tb`
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* hc stands for "human count", similar to "human bytes" `_hb` function.
|
|
27
|
+
* Helpful to print big numbers, as it adds `K` (kilo), `M` (mega), etc to make
|
|
28
|
+
* them more readable.
|
|
29
|
+
*/
|
|
30
|
+
export function _hc(c = 0): string {
|
|
31
|
+
if (c < 10 ** 4) return String(c)
|
|
32
|
+
if (c < 10 ** 6) return (c / 10 ** 3).toPrecision(3) + ' K'
|
|
33
|
+
if (c < 10 ** 9) return (c / 10 ** 6).toPrecision(3) + ' M' // million
|
|
34
|
+
if (c < 10 ** 12) return (c / 10 ** 9).toPrecision(3) + ' B' // billion
|
|
35
|
+
if (c < 10 ** 15) return (c / 10 ** 12).toPrecision(3) + ' T' // trillion
|
|
36
|
+
return Math.round(c / 10 ** 12) + ' T'
|
|
21
37
|
}
|