@naturalcycles/nodejs-lib 12.57.0 → 12.61.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 (87) hide show
  1. package/dist/got/getGot.js +98 -28
  2. package/dist/got/got.model.d.ts +6 -0
  3. package/dist/index.d.ts +37 -36
  4. package/dist/index.js +36 -129
  5. package/dist/log/log.util.d.ts +4 -0
  6. package/dist/log/log.util.js +11 -0
  7. package/dist/stream/ndjson/ndjsonMap.d.ts +2 -2
  8. package/dist/stream/ndjson/ndjsonMap.js +4 -3
  9. package/dist/stream/ndjson/ndjsonStreamForEach.d.ts +2 -2
  10. package/dist/stream/ndjson/transformJsonParse.js +3 -3
  11. package/dist/stream/ndjson/transformToNDJson.js +2 -2
  12. package/dist/stream/pipeline/pipeline.d.ts +25 -3
  13. package/dist/stream/pipeline/pipeline.js +76 -9
  14. package/dist/stream/readable/readableCreate.d.ts +8 -0
  15. package/dist/stream/readable/readableCreate.js +9 -1
  16. package/dist/stream/readable/readableForEach.d.ts +2 -2
  17. package/dist/stream/readable/readableFromArray.d.ts +2 -2
  18. package/dist/stream/readable/readableFromArray.js +17 -13
  19. package/dist/stream/readable/readableMap.d.ts +2 -2
  20. package/dist/stream/readable/readableMap.js +22 -17
  21. package/dist/stream/sizeStack.d.ts +9 -0
  22. package/dist/stream/sizeStack.js +48 -0
  23. package/dist/stream/stream.util.d.ts +4 -0
  24. package/dist/stream/stream.util.js +24 -0
  25. package/dist/stream/transform/transformBuffer.js +1 -1
  26. package/dist/stream/transform/transformFilter.d.ts +3 -4
  27. package/dist/stream/transform/transformFilter.js +5 -20
  28. package/dist/stream/transform/transformLimit.d.ts +32 -1
  29. package/dist/stream/transform/transformLimit.js +33 -16
  30. package/dist/stream/transform/transformLogProgress.d.ts +20 -0
  31. package/dist/stream/transform/transformLogProgress.js +36 -18
  32. package/dist/stream/transform/transformMap.d.ts +4 -10
  33. package/dist/stream/transform/transformMap.js +52 -64
  34. package/dist/stream/transform/transformMapSimple.js +1 -1
  35. package/dist/stream/transform/transformMapSync.d.ts +5 -3
  36. package/dist/stream/transform/transformMapSync.js +28 -22
  37. package/dist/stream/transform/transformNoOp.js +1 -1
  38. package/dist/stream/transform/transformTap.js +3 -3
  39. package/dist/stream/transform/transformToArray.js +1 -1
  40. package/dist/stream/transform/transformToString.js +2 -2
  41. package/dist/stream/transform/worker/transformMultiThreaded.js +1 -1
  42. package/dist/stream/transform/worker/workerClassProxy.js +1 -0
  43. package/dist/stream/writable/writableFork.js +1 -1
  44. package/dist/stream/writable/writableLimit.d.ts +9 -0
  45. package/dist/stream/writable/writableLimit.js +29 -0
  46. package/dist/stream/writable/writablePushToArray.js +1 -1
  47. package/dist/stream/writable/writableVoid.d.ts +8 -1
  48. package/dist/stream/writable/writableVoid.js +6 -2
  49. package/dist/util/zip.util.d.ts +10 -2
  50. package/dist/util/zip.util.js +10 -3
  51. package/package.json +1 -1
  52. package/src/got/getGot.ts +120 -31
  53. package/src/got/got.model.ts +8 -0
  54. package/src/index.ts +36 -194
  55. package/src/log/log.util.ts +9 -0
  56. package/src/stream/ndjson/ndjsonMap.ts +7 -5
  57. package/src/stream/ndjson/ndjsonStreamForEach.ts +2 -2
  58. package/src/stream/ndjson/transformJsonParse.ts +3 -3
  59. package/src/stream/ndjson/transformToNDJson.ts +2 -2
  60. package/src/stream/pipeline/pipeline.ts +102 -9
  61. package/src/stream/readable/readableCreate.ts +9 -1
  62. package/src/stream/readable/readableForEach.ts +2 -2
  63. package/src/stream/readable/readableFromArray.ts +18 -21
  64. package/src/stream/readable/readableMap.ts +24 -21
  65. package/src/stream/sizeStack.ts +56 -0
  66. package/src/stream/stream.util.ts +29 -0
  67. package/src/stream/transform/transformBuffer.ts +1 -1
  68. package/src/stream/transform/transformFilter.ts +6 -20
  69. package/src/stream/transform/transformLimit.ts +66 -20
  70. package/src/stream/transform/transformLogProgress.ts +72 -23
  71. package/src/stream/transform/transformMap.ts +74 -94
  72. package/src/stream/transform/transformMapSimple.ts +1 -1
  73. package/src/stream/transform/transformMapSync.ts +40 -26
  74. package/src/stream/transform/transformNoOp.ts +1 -1
  75. package/src/stream/transform/transformTap.ts +3 -3
  76. package/src/stream/transform/transformToArray.ts +1 -1
  77. package/src/stream/transform/transformToString.ts +2 -2
  78. package/src/stream/transform/worker/transformMultiThreaded.ts +1 -1
  79. package/src/stream/transform/worker/workerClassProxy.js +1 -0
  80. package/src/stream/writable/writableFork.ts +1 -1
  81. package/src/stream/writable/writableLimit.ts +28 -0
  82. package/src/stream/writable/writablePushToArray.ts +1 -1
  83. package/src/stream/writable/writableVoid.ts +14 -2
  84. package/src/util/zip.util.ts +11 -3
  85. package/dist/stream/transform/legacy/transformMap.d.ts +0 -17
  86. package/dist/stream/transform/legacy/transformMap.js +0 -94
  87. package/src/stream/transform/legacy/transformMap.ts +0 -133
@@ -10,7 +10,7 @@ const gunzip = (0, util_1.promisify)(zlib.gunzip.bind(zlib));
10
10
  // string > zip
11
11
  /**
12
12
  * zipBuffer uses `deflate`.
13
- * It's 9 bytes shorter than gzip.
13
+ * It's 9 bytes shorter than `gzip`.
14
14
  */
15
15
  async function zipBuffer(buf, options = {}) {
16
16
  return await deflate(buf, options);
@@ -18,7 +18,7 @@ async function zipBuffer(buf, options = {}) {
18
18
  exports.zipBuffer = zipBuffer;
19
19
  /**
20
20
  * gzipBuffer uses `gzip`
21
- * It's 9 bytes longer than deflate.
21
+ * It's 9 bytes longer than `deflate`.
22
22
  */
23
23
  async function gzipBuffer(buf, options = {}) {
24
24
  return await gzip(buf, options);
@@ -33,11 +33,18 @@ async function gunzipBuffer(buf, options = {}) {
33
33
  return await gunzip(buf, options);
34
34
  }
35
35
  exports.gunzipBuffer = gunzipBuffer;
36
- // convenience
36
+ /**
37
+ * zipString uses `deflate`.
38
+ * It's 9 bytes shorter than `gzip`.
39
+ */
37
40
  async function zipString(s, options) {
38
41
  return await zipBuffer(Buffer.from(s), options);
39
42
  }
40
43
  exports.zipString = zipString;
44
+ /**
45
+ * gzipString uses `gzip`.
46
+ * It's 9 bytes longer than `deflate`.
47
+ */
41
48
  async function gzipString(s, options) {
42
49
  return await gzipBuffer(Buffer.from(s), options);
43
50
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@naturalcycles/nodejs-lib",
3
- "version": "12.57.0",
3
+ "version": "12.61.0",
4
4
  "scripts": {
5
5
  "prepare": "husky install",
6
6
  "docs-serve": "vuepress dev docs",
package/src/got/getGot.ts CHANGED
@@ -1,8 +1,13 @@
1
1
  import { URL } from 'url'
2
2
  import { _since } from '@naturalcycles/js-lib'
3
- import got, { AfterResponseHook, BeforeErrorHook, BeforeRequestHook, Got, HTTPError } from 'got'
3
+ import got, {
4
+ AfterResponseHook,
5
+ BeforeErrorHook,
6
+ BeforeRequestHook,
7
+ BeforeRetryHook,
8
+ Got,
9
+ } from 'got'
4
10
  import { inspectAny } from '..'
5
- import { dimGrey, grey, red, yellow } from '../colors'
6
11
  import { GetGotOptions, GotRequestContext } from './got.model'
7
12
 
8
13
  /**
@@ -15,12 +20,33 @@ import { GetGotOptions, GotRequestContext } from './got.model'
15
20
  export function getGot(opt: GetGotOptions = {}): Got {
16
21
  opt.logger ||= console
17
22
 
23
+ if (opt.debug) {
24
+ opt.logStart = opt.logFinished = opt.logResponse = true
25
+ }
26
+
18
27
  return got.extend({
19
28
  // Most-important is to set to anything non-empty (so, requests don't "hang" by default).
20
29
  // Should be long enough to handle for slow responses from scaled cloud APIs in times of spikes
21
30
  // Ideally should be LESS than default Request timeout in backend-lib (so, it has a chance to error
22
31
  // before server times out with 503).
23
- timeout: 90_000,
32
+ //
33
+ // UPD 2021-11-27
34
+ // There are 2 types/strategies for requests:
35
+ // 1. Optimized to get result no matter what. E.g in Cron jobs, where otherwise there'll be a job failure
36
+ // 2. Part of the Backend request, where we better retry quickly and fail on timeout before Backend aborts it with "503 Request timeout"
37
+ //
38
+ // Here it's hard to set the default timeout right for both use-cases.
39
+ // So, if it's important, you should override it according to your use-cases:
40
+ // - set it longer for Type 1 (e.g 120 seconds)
41
+ // - set it shorter for Type 2 (e.g 10/20 seconds)
42
+ // Please beware of default Retry strategy of Got:
43
+ // by default it will retry 2 times (after first try)
44
+ // First delay between tries will be ~1 second, then ~2 seconds
45
+ // Each retry it'll wait up to `timeout` (so, up to 60 seconds by default).
46
+ // So, for 3 tries it multiplies your timeout by 3 (+3 seconds between the tries).
47
+ // So, e.g 60 seconds timeout with 2 retries becomes up to 183 seconds.
48
+ // Which definitely doesn't fit into default "RequestTimeout"
49
+ timeout: 60_000,
24
50
  ...opt,
25
51
  hooks: {
26
52
  ...opt.hooks,
@@ -34,6 +60,11 @@ export function getGot(opt: GetGotOptions = {}): Got {
34
60
  // User hooks go AFTER
35
61
  ...(opt.hooks?.beforeRequest || []),
36
62
  ],
63
+ beforeRetry: [
64
+ gotBeforeRetryHook(opt),
65
+ // User hooks go AFTER
66
+ ...(opt.hooks?.beforeRetry || []),
67
+ ],
37
68
  afterResponse: [
38
69
  ...(opt.hooks?.afterResponse || []),
39
70
  // User hooks go BEFORE
@@ -71,22 +102,38 @@ function gotErrorHook(opt: GetGotOptions = {}): BeforeErrorHook {
71
102
  const { maxResponseLength = 10_000 } = opt
72
103
 
73
104
  return err => {
74
- if (err instanceof HTTPError) {
75
- const { statusCode } = err.response
76
- const { method, url, prefixUrl } = err.options
77
- const shortUrl = getShortUrl(opt, url, prefixUrl)
78
- // const { started } = context as GotRequestContext
79
-
80
- const body = inspectAny(err.response.body, {
81
- maxLen: maxResponseLength,
82
- colors: false,
83
- })
84
-
85
- // timings are not part of err.message to allow automatic error grouping in Sentry
86
- err.message = [[statusCode, method, shortUrl].filter(Boolean).join(' '), body]
105
+ const statusCode = err.response?.statusCode || 0
106
+ const { method, url, prefixUrl } = err.options
107
+ const shortUrl = getShortUrl(opt, url, prefixUrl)
108
+ const { started, retryCount } = (err.request?.options.context || {}) as GotRequestContext
109
+
110
+ const body = err.response?.body
111
+ ? inspectAny(err.response.body, {
112
+ maxLen: maxResponseLength,
113
+ colors: false,
114
+ })
115
+ : err.message
116
+
117
+ // We don't include Response/Body/Message in the log, because it's included in the Error thrown from here
118
+ opt.logger!.log(
119
+ [
120
+ ' <<',
121
+ statusCode,
122
+ method,
123
+ shortUrl,
124
+ retryCount && `(retry ${retryCount})`,
125
+ 'error',
126
+ started && 'in ' + _since(started),
127
+ ]
87
128
  .filter(Boolean)
88
- .join('\n')
89
- }
129
+ .join(' '),
130
+ )
131
+
132
+ // timings are not part of err.message to allow automatic error grouping in Sentry
133
+ // Colors are not used, because there's high chance that this Error will be propagated all the way to the Frontend
134
+ err.message = [[statusCode, method, shortUrl].filter(Boolean).join(' '), body]
135
+ .filter(Boolean)
136
+ .join('\n')
90
137
 
91
138
  return err
92
139
  }
@@ -100,28 +147,76 @@ function gotBeforeRequestHook(opt: GetGotOptions): BeforeRequestHook {
100
147
  } as GotRequestContext
101
148
 
102
149
  if (opt.logStart) {
150
+ const { retryCount } = options.context as GotRequestContext
103
151
  const shortUrl = getShortUrl(opt, options.url, options.prefixUrl)
104
- opt.logger!.log([dimGrey(' >>'), dimGrey(options.method), grey(shortUrl)].join(' '))
152
+ opt.logger!.log(
153
+ [' >>', options.method, shortUrl, retryCount && `(retry ${retryCount})`].join(' '),
154
+ )
105
155
  }
106
156
  }
107
157
  }
108
158
 
159
+ // Here we log always, because it's similar to ErrorHook - we always log errors
160
+ // Because Retries are always result of some Error
161
+ function gotBeforeRetryHook(opt: GetGotOptions): BeforeRetryHook {
162
+ const { maxResponseLength = 10_000 } = opt
163
+
164
+ return (options, err, retryCount) => {
165
+ // opt.logger!.log('beforeRetry', retryCount)
166
+ const statusCode = err?.response?.statusCode || 0
167
+ const { method, url, prefixUrl } = options
168
+ const shortUrl = getShortUrl(opt, url, prefixUrl)
169
+ const { started } = options.context as GotRequestContext
170
+ Object.assign(options.context, { retryCount })
171
+
172
+ const body = err?.response?.body
173
+ ? inspectAny(err.response.body, {
174
+ maxLen: maxResponseLength,
175
+ colors: false,
176
+ })
177
+ : err?.message
178
+
179
+ // We don't include Response/Body/Message in the log, because it's included in the Error thrown from here
180
+ opt.logger!.warn(
181
+ [
182
+ [
183
+ ' <<',
184
+ statusCode,
185
+ method,
186
+ shortUrl,
187
+ retryCount && retryCount > 1 ? `(retry ${retryCount - 1})` : '(first try)',
188
+ 'error',
189
+ started && 'in ' + _since(started),
190
+ ]
191
+ .filter(Boolean)
192
+ .join(' '),
193
+ body,
194
+ ]
195
+ .filter(Boolean)
196
+ .join('\n'),
197
+ )
198
+ }
199
+ }
200
+
201
+ // AfterResponseHook is never called on Error
202
+ // So, coloredHttpCode(resp.statusCode) is probably useless
109
203
  function gotAfterResponseHook(opt: GetGotOptions = {}): AfterResponseHook {
110
204
  return resp => {
111
205
  const success = resp.statusCode >= 200 && resp.statusCode < 400
112
206
 
113
207
  if (opt.logFinished) {
114
- const { started } = resp.request.options.context as GotRequestContext
208
+ const { started, retryCount } = resp.request.options.context as GotRequestContext
115
209
  const { url, prefixUrl, method } = resp.request.options
116
210
  const shortUrl = getShortUrl(opt, url, prefixUrl)
117
211
 
118
212
  opt.logger!.log(
119
213
  [
120
- dimGrey(' <<'),
121
- coloredHttpCode(resp.statusCode),
122
- dimGrey(method),
123
- grey(shortUrl),
124
- started && dimGrey('in ' + _since(started)),
214
+ ' <<',
215
+ resp.statusCode,
216
+ method,
217
+ shortUrl,
218
+ retryCount && `(retry ${retryCount - 1})`,
219
+ started && 'in ' + _since(started),
125
220
  ]
126
221
  .filter(Boolean)
127
222
  .join(' '),
@@ -138,12 +233,6 @@ function gotAfterResponseHook(opt: GetGotOptions = {}): AfterResponseHook {
138
233
  }
139
234
  }
140
235
 
141
- function coloredHttpCode(statusCode: number): string {
142
- if (statusCode < 400) return dimGrey(statusCode) // default
143
- if (statusCode < 500) return yellow(statusCode)
144
- return red(statusCode)
145
- }
146
-
147
236
  function getShortUrl(opt: GetGotOptions, url: URL, prefixUrl?: string): string {
148
237
  let shortUrl = url.toString()
149
238
 
@@ -2,6 +2,12 @@ import { AnyObject, CommonLogger } from '@naturalcycles/js-lib'
2
2
  import type { Options } from 'got'
3
3
 
4
4
  export interface GetGotOptions extends Options {
5
+ /**
6
+ * Set to `true` to enable all possible debug logging.
7
+ * Not safe in prod (as it logs Responses), but great to use during development.
8
+ */
9
+ debug?: boolean
10
+
5
11
  /**
6
12
  * @default false
7
13
  */
@@ -51,4 +57,6 @@ export interface GotRequestContext extends AnyObject {
51
57
  * Millisecond-timestamp of when the request was started. To be able to count "time spent".
52
58
  */
53
59
  started: number
60
+
61
+ retryCount?: number
54
62
  }
package/src/index.ts CHANGED
@@ -1,44 +1,18 @@
1
1
  import Ajv from 'ajv'
2
- import { HTTPError, TimeoutError } from 'got'
2
+ import { RequestError, TimeoutError } from 'got'
3
3
  import type { AfterResponseHook, BeforeErrorHook, BeforeRequestHook, Got } from 'got'
4
4
  import { AnySchema, ValidationErrorItem } from 'joi'
5
5
  import { _chunkBuffer } from './buffer/buffer.util'
6
6
  import { tableDiff, TableDiffOptions } from './diff/tableDiff'
7
- import { getGot } from './got/getGot'
7
+ export * from './got/getGot'
8
8
  import { GetGotOptions } from './got/got.model'
9
- import { memoryUsage, memoryUsageFull, processSharedUtil } from './infra/process.util'
9
+ export * from './infra/process.util'
10
10
  import { Debug, IDebug, IDebugger } from './log/debug'
11
- import {
12
- base64ToBuffer,
13
- base64ToString,
14
- bufferToBase64,
15
- hash,
16
- md5,
17
- hashAsBuffer,
18
- md5AsBuffer,
19
- stringToBase64,
20
- } from './security/hash.util'
21
- import {
22
- ALPHABET_ALPHANUMERIC,
23
- ALPHABET_ALPHANUMERIC_LOWERCASE,
24
- ALPHABET_ALPHANUMERIC_UPPERCASE,
25
- ALPHABET_LOWERCASE,
26
- ALPHABET_NUMBER,
27
- ALPHABET_UPPERCASE,
28
- stringId,
29
- stringIdAsync,
30
- stringIdUnsafe,
31
- } from './security/id.util'
32
- import {
33
- getSecretMap,
34
- loadSecretsFromEnv,
35
- loadSecretsFromJsonFile,
36
- removeSecretsFromEnv,
37
- secret,
38
- secretOptional,
39
- setSecretMap,
40
- } from './security/secret.util'
41
- import { hasColors } from './colors/colors'
11
+ export * from './security/hash.util'
12
+ export * from './security/id.util'
13
+ export * from './security/secret.util'
14
+ export * from './colors/colors'
15
+ export * from './log/log.util'
42
16
  import { slackDefaultMessagePrefixHook, SlackService } from './slack/slack.service'
43
17
  import {
44
18
  SlackApiBody,
@@ -48,9 +22,9 @@ import {
48
22
  SlackServiceCfg,
49
23
  } from './slack/slack.service.model'
50
24
  import { NDJsonStats } from './stream/ndjson/ndjson.model'
51
- import { ndJsonFileRead } from './stream/ndjson/ndJsonFileRead'
52
- import { ndJsonFileWrite } from './stream/ndjson/ndJsonFileWrite'
53
- import { ndjsonMap } from './stream/ndjson/ndjsonMap'
25
+ export * from './stream/ndjson/ndJsonFileRead'
26
+ export * from './stream/ndjson/ndJsonFileWrite'
27
+ export * from './stream/ndjson/ndjsonMap'
54
28
  import {
55
29
  ndjsonStreamForEach,
56
30
  NDJSONStreamForEachOptions,
@@ -70,34 +44,31 @@ import {
70
44
  TransformJsonParseOptions,
71
45
  } from './stream/ndjson/transformJsonParse'
72
46
  import { transformToNDJson, TransformToNDJsonOptions } from './stream/ndjson/transformToNDJson'
73
- import { _pipeline } from './stream/pipeline/pipeline'
74
- import { readableCreate, readableFrom } from './stream/readable/readableCreate'
75
- import { readableForEach, readableForEachSync } from './stream/readable/readableForEach'
76
- import { readableFromArray } from './stream/readable/readableFromArray'
77
- import { readableMap } from './stream/readable/readableMap'
78
- import { readableMapToArray } from './stream/readable/readableMapToArray'
79
- import { readableToArray } from './stream/readable/readableToArray'
47
+ export * from './stream/pipeline/pipeline'
48
+ export * from './stream/readable/readableCreate'
49
+ export * from './stream/readable/readableForEach'
50
+ export * from './stream/readable/readableFromArray'
51
+ export * from './stream/readable/readableMap'
52
+ export * from './stream/readable/readableMapToArray'
53
+ export * from './stream/readable/readableToArray'
80
54
  import {
81
55
  ReadableTyped,
82
56
  TransformOptions,
83
57
  TransformTyped,
84
58
  WritableTyped,
85
59
  } from './stream/stream.model'
86
- import { transformBuffer } from './stream/transform/transformBuffer'
87
- import { transformFilter, transformFilterSync } from './stream/transform/transformFilter'
88
- import { transformLimit } from './stream/transform/transformLimit'
89
- import {
90
- transformLogProgress,
91
- TransformLogProgressOptions,
92
- } from './stream/transform/transformLogProgress'
60
+ export * from './stream/transform/transformBuffer'
61
+ export * from './stream/transform/transformFilter'
62
+ export * from './stream/transform/transformLimit'
63
+ export * from './stream/transform/transformLogProgress'
93
64
  import { transformMap, TransformMapOptions } from './stream/transform/transformMap'
94
- import { transformMapSimple } from './stream/transform/transformMapSimple'
95
- import { transformNoOp } from './stream/transform/transformNoOp'
65
+ export * from './stream/transform/transformMapSimple'
66
+ export * from './stream/transform/transformNoOp'
96
67
  import { transformMapSync, TransformMapSyncOptions } from './stream/transform/transformMapSync'
97
- import { transformSplit } from './stream/transform/transformSplit'
98
- import { transformTap } from './stream/transform/transformTap'
99
- import { transformToArray } from './stream/transform/transformToArray'
100
- import { transformToString } from './stream/transform/transformToString'
68
+ export * from './stream/transform/transformSplit'
69
+ export * from './stream/transform/transformTap'
70
+ export * from './stream/transform/transformToArray'
71
+ export * from './stream/transform/transformToString'
101
72
  import { BaseWorkerClass, WorkerClassInterface } from './stream/transform/worker/baseWorkerClass'
102
73
  import {
103
74
  transformMultiThreaded,
@@ -105,26 +76,17 @@ import {
105
76
  } from './stream/transform/worker/transformMultiThreaded'
106
77
  import { WorkerInput, WorkerOutput } from './stream/transform/worker/transformMultiThreaded.model'
107
78
  export * from './stream/writable/writableForEach'
108
- import { writableFork } from './stream/writable/writableFork'
109
- import { writablePushToArray } from './stream/writable/writablePushToArray'
110
- import { writableVoid } from './stream/writable/writableVoid'
79
+ export * from './stream/writable/writableFork'
80
+ export * from './stream/writable/writablePushToArray'
81
+ export * from './stream/writable/writableVoid'
111
82
  import { inspectAny, InspectAnyOptions, inspectAnyStringifyFn } from './string/inspectAny'
112
- import { requireEnvKeys, requireFileToExist } from './util/env.util'
83
+ export * from './util/env.util'
113
84
  import { LRUMemoCache } from './util/lruMemoCache'
114
- import {
115
- gunzipBuffer,
116
- gunzipToString,
117
- gzipBuffer,
118
- gzipString,
119
- unzipBuffer,
120
- unzipToString,
121
- zipBuffer,
122
- zipString,
123
- } from './util/zip.util'
85
+ export * from './util/zip.util'
124
86
  import { readAjvSchemas, readJsonSchemas } from './validation/ajv/ajv.util'
125
87
  import { AjvSchema, AjvSchemaCfg, AjvValidationOptions } from './validation/ajv/ajvSchema'
126
88
  import { AjvValidationError, AjvValidationErrorData } from './validation/ajv/ajvValidationError'
127
- import { getAjv } from './validation/ajv/getAjv'
89
+ export * from './validation/ajv/getAjv'
128
90
  import { ExtendedJoi, Joi } from './validation/joi/joi.extensions'
129
91
  import {
130
92
  AnySchemaTyped,
@@ -135,34 +97,7 @@ import {
135
97
  SchemaTyped,
136
98
  StringSchemaTyped,
137
99
  } from './validation/joi/joi.model'
138
- import {
139
- anyObjectSchema,
140
- anySchema,
141
- arraySchema,
142
- oneOfSchema,
143
- binarySchema,
144
- booleanDefaultToFalseSchema,
145
- booleanSchema,
146
- dateStringSchema,
147
- emailSchema,
148
- baseDBEntitySchema,
149
- savedDBEntitySchema,
150
- idSchema,
151
- integerSchema,
152
- ipAddressSchema,
153
- numberSchema,
154
- objectSchema,
155
- percentageSchema,
156
- semVerSchema,
157
- SEM_VER_PATTERN,
158
- slugSchema,
159
- stringSchema,
160
- unixTimestampSchema,
161
- urlSchema,
162
- userAgentSchema,
163
- utcOffsetSchema,
164
- verSchema,
165
- } from './validation/joi/joi.shared.schemas'
100
+ export * from './validation/joi/joi.shared.schemas'
166
101
  import { JoiValidationError, JoiValidationErrorData } from './validation/joi/joi.validation.error'
167
102
  import {
168
103
  convert,
@@ -207,7 +142,6 @@ export type {
207
142
  TransformMapSyncOptions,
208
143
  NDJSONStreamForEachOptions,
209
144
  TransformOptions,
210
- TransformLogProgressOptions,
211
145
  TransformMultiThreadedOptions,
212
146
  WorkerClassInterface,
213
147
  WorkerInput,
@@ -233,86 +167,10 @@ export {
233
167
  undefinedIfInvalid,
234
168
  convert,
235
169
  Joi,
236
- booleanSchema,
237
- booleanDefaultToFalseSchema,
238
- stringSchema,
239
- numberSchema,
240
- integerSchema,
241
- percentageSchema,
242
- dateStringSchema,
243
- arraySchema,
244
- binarySchema,
245
- objectSchema,
246
- oneOfSchema,
247
- anySchema,
248
- anyObjectSchema,
249
- baseDBEntitySchema,
250
- savedDBEntitySchema,
251
- idSchema,
252
- unixTimestampSchema,
253
- verSchema,
254
- emailSchema,
255
- SEM_VER_PATTERN,
256
- semVerSchema,
257
- userAgentSchema,
258
- utcOffsetSchema,
259
- ipAddressSchema,
260
- slugSchema,
261
- urlSchema,
262
- processSharedUtil,
263
- zipBuffer,
264
- gzipBuffer,
265
- unzipBuffer,
266
- gunzipBuffer,
267
- zipString,
268
- gzipString,
269
- unzipToString,
270
- gunzipToString,
271
- requireEnvKeys,
272
- requireFileToExist,
273
170
  LRUMemoCache,
274
- stringId,
275
- stringIdAsync,
276
- stringIdUnsafe,
277
- ALPHABET_NUMBER,
278
- ALPHABET_LOWERCASE,
279
- ALPHABET_UPPERCASE,
280
- ALPHABET_ALPHANUMERIC_LOWERCASE,
281
- ALPHABET_ALPHANUMERIC_UPPERCASE,
282
- ALPHABET_ALPHANUMERIC,
283
- md5,
284
- hash,
285
- hashAsBuffer,
286
- md5AsBuffer,
287
- stringToBase64,
288
- base64ToString,
289
- bufferToBase64,
290
- base64ToBuffer,
291
171
  Debug,
292
- getSecretMap,
293
- setSecretMap,
294
- loadSecretsFromEnv,
295
- loadSecretsFromJsonFile,
296
- removeSecretsFromEnv,
297
- secret,
298
- secretOptional,
299
- memoryUsage,
300
- memoryUsageFull,
301
172
  SlackService,
302
173
  slackDefaultMessagePrefixHook,
303
- readableCreate,
304
- readableFrom,
305
- readableFromArray,
306
- readableToArray,
307
- readableForEach,
308
- readableForEachSync,
309
- readableMap,
310
- readableMapToArray,
311
- _pipeline,
312
- transformBuffer,
313
- ndjsonMap,
314
- ndJsonFileRead,
315
- ndJsonFileWrite,
316
174
  ndjsonStreamForEach,
317
175
  pipelineFromNDJsonFile,
318
176
  pipelineToNDJsonFile,
@@ -321,37 +179,21 @@ export {
321
179
  transformJsonParse,
322
180
  bufferReviver,
323
181
  transformToNDJson,
324
- transformFilter,
325
- transformFilterSync,
326
182
  transformMap,
327
183
  transformMapSync,
328
- transformMapSimple,
329
- transformNoOp,
330
- writablePushToArray,
331
- transformSplit,
332
- transformToString,
333
- transformToArray,
334
- transformTap,
335
- transformLogProgress,
336
- transformLimit,
337
- writableVoid,
338
- writableFork,
339
184
  transformMultiThreaded,
340
185
  BaseWorkerClass,
341
186
  tableDiff,
342
187
  inspectAny,
343
188
  inspectAnyStringifyFn,
344
- getGot,
345
- HTTPError,
189
+ RequestError,
346
190
  TimeoutError,
347
191
  _chunkBuffer,
348
192
  Ajv,
349
- getAjv,
350
193
  AjvSchema,
351
194
  AjvValidationError,
352
195
  readJsonSchemas,
353
196
  readAjvSchemas,
354
- hasColors,
355
197
  sanitizeHTML,
356
198
  runScript,
357
199
  }
@@ -0,0 +1,9 @@
1
+ import { commonLoggerCreate } from '@naturalcycles/js-lib'
2
+ import { inspectAny } from '../index'
3
+
4
+ /**
5
+ * CommonLogger that logs to process.stdout directly (bypassing console.log).
6
+ */
7
+ export const stdoutLogger = commonLoggerCreate((_level, args) => {
8
+ process.stdout.write(args.map(a => inspectAny(a)).join(' ') + '\n')
9
+ })
@@ -1,6 +1,6 @@
1
1
  import { createReadStream, createWriteStream } from 'fs'
2
2
  import { createGzip, createUnzip } from 'zlib'
3
- import { AsyncMapper, ErrorMode } from '@naturalcycles/js-lib'
3
+ import { AbortableAsyncMapper, ErrorMode } from '@naturalcycles/js-lib'
4
4
  import {
5
5
  requireFileToExist,
6
6
  transformJsonParse,
@@ -41,7 +41,7 @@ export interface NDJSONMapOptions<IN = any, OUT = IN>
41
41
  * Zips output file automatically, if it ends with `.gz`.
42
42
  */
43
43
  export async function ndjsonMap<IN = any, OUT = any>(
44
- mapper: AsyncMapper<IN, OUT>,
44
+ mapper: AbortableAsyncMapper<IN, OUT>,
45
45
  opt: NDJSONMapOptions<IN, OUT>,
46
46
  ): Promise<void> {
47
47
  const { inputFilePath, outputFilePath, logEveryOutput = 100_000, limitInput, limitOutput } = opt
@@ -56,19 +56,21 @@ export async function ndjsonMap<IN = any, OUT = any>(
56
56
  const transformUnzip = inputFilePath.endsWith('.gz') ? [createUnzip()] : []
57
57
  const transformZip = outputFilePath.endsWith('.gz') ? [createGzip()] : []
58
58
 
59
+ const readable = createReadStream(inputFilePath)
60
+
59
61
  await _pipeline([
60
- createReadStream(inputFilePath),
62
+ readable,
61
63
  ...transformUnzip,
62
64
  transformSplit(), // splits by \n
63
65
  transformJsonParse(),
64
- transformLimit(limitInput),
66
+ transformLimit({ limit: limitInput, sourceReadable: readable }),
65
67
  transformLogProgress({ metric: 'read', ...opt }),
66
68
  transformMap(mapper, {
67
69
  flattenArrayOutput: true,
68
70
  errorMode: ErrorMode.SUPPRESS,
69
71
  ...opt,
70
72
  }),
71
- transformLimit(limitOutput),
73
+ transformLimit({ limit: limitOutput, sourceReadable: readable }),
72
74
  transformLogProgress({ metric: 'saved', logEvery: logEveryOutput }),
73
75
  transformToNDJson(),
74
76
  ...transformZip,
@@ -1,6 +1,6 @@
1
1
  import * as fs from 'fs'
2
2
  import { createUnzip } from 'zlib'
3
- import { AsyncMapper, ErrorMode } from '@naturalcycles/js-lib'
3
+ import { AbortableAsyncMapper, ErrorMode } from '@naturalcycles/js-lib'
4
4
  import {
5
5
  requireFileToExist,
6
6
  transformJsonParse,
@@ -23,7 +23,7 @@ export interface NDJSONStreamForEachOptions<IN = any>
23
23
  * Convenience function to `forEach` through an ndjson file.
24
24
  */
25
25
  export async function ndjsonStreamForEach<T>(
26
- mapper: AsyncMapper<T, void>,
26
+ mapper: AbortableAsyncMapper<T, void>,
27
27
  opt: NDJSONStreamForEachOptions<T>,
28
28
  ): Promise<void> {
29
29
  requireFileToExist(opt.inputFilePath)