@nxtedition/lib 23.3.17 → 23.3.19
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/errors.js +16 -13
- package/http.js +135 -129
- package/package.json +1 -1
- package/serializers.js +15 -25
package/errors.js
CHANGED
|
@@ -123,19 +123,22 @@ function _serializeError(error, { depth }) {
|
|
|
123
123
|
|
|
124
124
|
return [
|
|
125
125
|
JSON.parse(
|
|
126
|
-
JSON.stringify(
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
126
|
+
JSON.stringify(
|
|
127
|
+
{
|
|
128
|
+
...properties,
|
|
129
|
+
message: message ?? 'Unknown error',
|
|
130
|
+
type: type !== 'Object' ? type : undefined,
|
|
131
|
+
code: code ?? undefined,
|
|
132
|
+
exitCode: exitCode ?? undefined,
|
|
133
|
+
signalCode: signalCode ?? undefined,
|
|
134
|
+
statusCode: statusCode ?? undefined,
|
|
135
|
+
headers: headers ?? undefined,
|
|
136
|
+
data: data ?? undefined,
|
|
137
|
+
cause: cause ?? undefined,
|
|
138
|
+
errors: fp.isEmpty(errors) ? undefined : undefined,
|
|
139
|
+
},
|
|
140
|
+
(k, v) => (typeof v === 'bigint' ? v.toString() : v),
|
|
141
|
+
),
|
|
139
142
|
),
|
|
140
143
|
]
|
|
141
144
|
}
|
package/http.js
CHANGED
|
@@ -251,135 +251,6 @@ export async function requestMiddleware(ctx, next) {
|
|
|
251
251
|
}
|
|
252
252
|
}
|
|
253
253
|
|
|
254
|
-
export async function request(ctx, next) {
|
|
255
|
-
const { req, res, logger } = ctx
|
|
256
|
-
const startTime = performance.now()
|
|
257
|
-
|
|
258
|
-
const ac = ctx.signal !== undefined ? null : new AbortController()
|
|
259
|
-
|
|
260
|
-
let reqLogger = logger
|
|
261
|
-
|
|
262
|
-
pendingSet.add(ctx)
|
|
263
|
-
try {
|
|
264
|
-
ctx.url = requestTarget(req)
|
|
265
|
-
if (!ctx.url) {
|
|
266
|
-
throw new createError.BadRequest('invalid url')
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
ctx.id = req.id = res.id = req.headers['request-id'] || genReqId()
|
|
270
|
-
ctx.userAgent = req['user-agent'] || req['User-Agent'] || ''
|
|
271
|
-
ctx.method = req.method
|
|
272
|
-
ctx.query = ctx.url.search.length > 1 ? querystring.parse(ctx.url.search.slice(1)) : {}
|
|
273
|
-
ctx.logger =
|
|
274
|
-
req.log =
|
|
275
|
-
res.log =
|
|
276
|
-
logger.child({ req: { id: req.id, url: req.url, userAgent: ctx.userAgent } })
|
|
277
|
-
|
|
278
|
-
if (ac) {
|
|
279
|
-
ctx.signal = ac.signal
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
if (req.method === 'GET' || req.method === 'HEAD') {
|
|
283
|
-
req.resume() // Dump the body if there is one.
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
res.setHeader('request-id', req.id)
|
|
287
|
-
|
|
288
|
-
const isHealthcheck = ctx.url.pathname === '/healthcheck' || ctx.url.pathname === '/_up'
|
|
289
|
-
|
|
290
|
-
reqLogger = logger.child({ req })
|
|
291
|
-
if (!isHealthcheck) {
|
|
292
|
-
reqLogger.debug('request started')
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
const nextPromise = next()
|
|
296
|
-
const responsePromise = new Promise((resolve, reject) => {
|
|
297
|
-
res.on('timeout', onTimeout).on('error', reject).on('close', resolve)
|
|
298
|
-
})
|
|
299
|
-
|
|
300
|
-
if (nextPromise) {
|
|
301
|
-
await Promise.all([nextPromise, responsePromise])
|
|
302
|
-
} else if (!res.closed) {
|
|
303
|
-
await responsePromise
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
const elapsedTime = performance.now() - startTime
|
|
307
|
-
|
|
308
|
-
if (isHealthcheck) {
|
|
309
|
-
// Do nothing...
|
|
310
|
-
} else if (!res.writableEnded) {
|
|
311
|
-
reqLogger.debug({ res, elapsedTime }, 'request aborted')
|
|
312
|
-
} else if (res.statusCode >= 500) {
|
|
313
|
-
reqLogger.error({ res, elapsedTime }, 'request error')
|
|
314
|
-
} else if (res.statusCode >= 400) {
|
|
315
|
-
reqLogger.warn({ res, elapsedTime }, 'request failed')
|
|
316
|
-
} else {
|
|
317
|
-
reqLogger.debug({ res, elapsedTime }, 'request completed')
|
|
318
|
-
}
|
|
319
|
-
} catch (err) {
|
|
320
|
-
ac?.abort(err)
|
|
321
|
-
|
|
322
|
-
const statusCode = err.statusCode || err.$metadata?.httpStatusCode || 500
|
|
323
|
-
const elapsedTime = performance.now() - startTime
|
|
324
|
-
|
|
325
|
-
if (!res.headersSent && !res.destroyed) {
|
|
326
|
-
res.statusCode = statusCode
|
|
327
|
-
|
|
328
|
-
let reqId = req?.id || err.id
|
|
329
|
-
for (const name of res.getHeaderNames()) {
|
|
330
|
-
if (!reqId && name === 'request-id') {
|
|
331
|
-
reqId = res.getHeader(name)
|
|
332
|
-
}
|
|
333
|
-
res.removeHeader(name)
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
if (reqId) {
|
|
337
|
-
res.setHeader('request-id', reqId)
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
if (fp.isPlainObject(err.headers)) {
|
|
341
|
-
for (const [key, val] of Object.entries(err.headers)) {
|
|
342
|
-
if (!ERR_HEADER_EXPR.test(key)) {
|
|
343
|
-
res.setHeader(key, val)
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
if (fp.isPlainObject(err.body)) {
|
|
349
|
-
res.setHeader('content-type', 'application/json')
|
|
350
|
-
res.end(JSON.stringify(err.body))
|
|
351
|
-
} else if (typeof err.body === 'string') {
|
|
352
|
-
res.end(err.body)
|
|
353
|
-
} else if (Buffer.isBuffer(err.body)) {
|
|
354
|
-
res.end(err.body)
|
|
355
|
-
} else {
|
|
356
|
-
res.end()
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
if (statusCode < 500) {
|
|
360
|
-
reqLogger.warn({ res, err, elapsedTime }, 'request failed')
|
|
361
|
-
} else {
|
|
362
|
-
reqLogger.error({ res, err, elapsedTime }, 'request error')
|
|
363
|
-
}
|
|
364
|
-
} else {
|
|
365
|
-
if (req.aborted || !res.writableEnded || err.name === 'AbortError') {
|
|
366
|
-
reqLogger.debug({ res, err, elapsedTime }, 'request aborted')
|
|
367
|
-
} else if (statusCode < 500) {
|
|
368
|
-
reqLogger.warn({ res, err, elapsedTime }, 'request failed')
|
|
369
|
-
} else {
|
|
370
|
-
reqLogger.error({ res, err, elapsedTime }, 'request error')
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
} finally {
|
|
374
|
-
pendingSet.delete(ctx)
|
|
375
|
-
|
|
376
|
-
if (!res.writableEnded) {
|
|
377
|
-
res.destroy()
|
|
378
|
-
logger.debug('request destroyed')
|
|
379
|
-
}
|
|
380
|
-
}
|
|
381
|
-
}
|
|
382
|
-
|
|
383
254
|
export class ServerResponse extends http.ServerResponse {
|
|
384
255
|
#created = 0
|
|
385
256
|
#bytesWritten = 0
|
|
@@ -570,6 +441,137 @@ export class Http2ServerResponse extends http2.Http2ServerResponse {
|
|
|
570
441
|
}
|
|
571
442
|
}
|
|
572
443
|
|
|
444
|
+
/** @deprecated */
|
|
445
|
+
export async function request(ctx, next) {
|
|
446
|
+
const { req, res, logger } = ctx
|
|
447
|
+
const startTime = performance.now()
|
|
448
|
+
|
|
449
|
+
const ac = ctx.signal !== undefined ? null : new AbortController()
|
|
450
|
+
|
|
451
|
+
let reqLogger = logger
|
|
452
|
+
|
|
453
|
+
pendingSet.add(ctx)
|
|
454
|
+
try {
|
|
455
|
+
ctx.url = requestTarget(req)
|
|
456
|
+
if (!ctx.url) {
|
|
457
|
+
throw new createError.BadRequest('invalid url')
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
ctx.id = req.id = res.id = req.headers['request-id'] || genReqId()
|
|
461
|
+
ctx.userAgent = req['user-agent'] || req['User-Agent'] || ''
|
|
462
|
+
ctx.method = req.method
|
|
463
|
+
ctx.query = ctx.url.search.length > 1 ? querystring.parse(ctx.url.search.slice(1)) : {}
|
|
464
|
+
ctx.logger =
|
|
465
|
+
req.log =
|
|
466
|
+
res.log =
|
|
467
|
+
logger.child({ req: { id: req.id, url: req.url, userAgent: ctx.userAgent } })
|
|
468
|
+
|
|
469
|
+
if (ac) {
|
|
470
|
+
ctx.signal = ac.signal
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
if (req.method === 'GET' || req.method === 'HEAD') {
|
|
474
|
+
req.resume() // Dump the body if there is one.
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
res.setHeader('request-id', req.id)
|
|
478
|
+
|
|
479
|
+
const isHealthcheck = ctx.url.pathname === '/healthcheck' || ctx.url.pathname === '/_up'
|
|
480
|
+
|
|
481
|
+
reqLogger = logger.child({ req })
|
|
482
|
+
if (!isHealthcheck) {
|
|
483
|
+
reqLogger.debug('request started')
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
const nextPromise = next()
|
|
487
|
+
const responsePromise = new Promise((resolve, reject) => {
|
|
488
|
+
res.on('timeout', onTimeout).on('error', reject).on('close', resolve)
|
|
489
|
+
})
|
|
490
|
+
|
|
491
|
+
if (nextPromise) {
|
|
492
|
+
await Promise.all([nextPromise, responsePromise])
|
|
493
|
+
} else if (!res.closed) {
|
|
494
|
+
await responsePromise
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
const elapsedTime = performance.now() - startTime
|
|
498
|
+
|
|
499
|
+
if (isHealthcheck) {
|
|
500
|
+
// Do nothing...
|
|
501
|
+
} else if (!res.writableEnded) {
|
|
502
|
+
reqLogger.debug({ res, elapsedTime }, 'request aborted')
|
|
503
|
+
} else if (res.statusCode >= 500) {
|
|
504
|
+
reqLogger.error({ res, elapsedTime }, 'request error')
|
|
505
|
+
} else if (res.statusCode >= 400) {
|
|
506
|
+
reqLogger.warn({ res, elapsedTime }, 'request failed')
|
|
507
|
+
} else {
|
|
508
|
+
reqLogger.debug({ res, elapsedTime }, 'request completed')
|
|
509
|
+
}
|
|
510
|
+
} catch (err) {
|
|
511
|
+
ac?.abort(err)
|
|
512
|
+
|
|
513
|
+
const statusCode = err.statusCode || err.$metadata?.httpStatusCode || 500
|
|
514
|
+
const elapsedTime = performance.now() - startTime
|
|
515
|
+
|
|
516
|
+
if (!res.headersSent && !res.destroyed) {
|
|
517
|
+
res.statusCode = statusCode
|
|
518
|
+
|
|
519
|
+
let reqId = req?.id || err.id
|
|
520
|
+
for (const name of res.getHeaderNames()) {
|
|
521
|
+
if (!reqId && name === 'request-id') {
|
|
522
|
+
reqId = res.getHeader(name)
|
|
523
|
+
}
|
|
524
|
+
res.removeHeader(name)
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
if (reqId) {
|
|
528
|
+
res.setHeader('request-id', reqId)
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
if (fp.isPlainObject(err.headers)) {
|
|
532
|
+
for (const [key, val] of Object.entries(err.headers)) {
|
|
533
|
+
if (!ERR_HEADER_EXPR.test(key)) {
|
|
534
|
+
res.setHeader(key, val)
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
if (fp.isPlainObject(err.body)) {
|
|
540
|
+
res.setHeader('content-type', 'application/json')
|
|
541
|
+
res.end(JSON.stringify(err.body))
|
|
542
|
+
} else if (typeof err.body === 'string') {
|
|
543
|
+
res.end(err.body)
|
|
544
|
+
} else if (Buffer.isBuffer(err.body)) {
|
|
545
|
+
res.end(err.body)
|
|
546
|
+
} else {
|
|
547
|
+
res.end()
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
if (statusCode < 500) {
|
|
551
|
+
reqLogger.warn({ res, err, elapsedTime }, 'request failed')
|
|
552
|
+
} else {
|
|
553
|
+
reqLogger.error({ res, err, elapsedTime }, 'request error')
|
|
554
|
+
}
|
|
555
|
+
} else {
|
|
556
|
+
if (req.aborted || !res.writableEnded || err.name === 'AbortError') {
|
|
557
|
+
reqLogger.debug({ res, err, elapsedTime }, 'request aborted')
|
|
558
|
+
} else if (statusCode < 500) {
|
|
559
|
+
reqLogger.warn({ res, err, elapsedTime }, 'request failed')
|
|
560
|
+
} else {
|
|
561
|
+
reqLogger.error({ res, err, elapsedTime }, 'request error')
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
} finally {
|
|
565
|
+
pendingSet.delete(ctx)
|
|
566
|
+
|
|
567
|
+
if (!res.writableEnded) {
|
|
568
|
+
res.destroy()
|
|
569
|
+
logger.debug('request destroyed')
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
/** @deprecated */
|
|
573
575
|
export function createServer(options, ctx, middleware) {
|
|
574
576
|
middleware = Array.isArray(middleware) ? middleware : [middleware]
|
|
575
577
|
middleware = fp.values(middleware)
|
|
@@ -598,6 +600,7 @@ export function createServer(options, ctx, middleware) {
|
|
|
598
600
|
return server
|
|
599
601
|
}
|
|
600
602
|
|
|
603
|
+
/** @deprecated */
|
|
601
604
|
export async function upgrade(ctx, next) {
|
|
602
605
|
const { req, res, socket = res, logger } = ctx
|
|
603
606
|
|
|
@@ -674,6 +677,7 @@ export async function upgrade(ctx, next) {
|
|
|
674
677
|
}
|
|
675
678
|
}
|
|
676
679
|
|
|
680
|
+
/** @deprecated */
|
|
677
681
|
export function isConnectionError(err) {
|
|
678
682
|
// AWS compat.
|
|
679
683
|
const statusCode = err?.statusCode ?? err?.$metadata?.httpStatusCode
|
|
@@ -696,6 +700,7 @@ export function isConnectionError(err) {
|
|
|
696
700
|
: false
|
|
697
701
|
}
|
|
698
702
|
|
|
703
|
+
/** @deprecated */
|
|
699
704
|
export function defaultDelay(err, retryCount, options) {
|
|
700
705
|
const { signal, logger = null } = options ?? {}
|
|
701
706
|
if (isConnectionError(err)) {
|
|
@@ -708,6 +713,7 @@ export function defaultDelay(err, retryCount, options) {
|
|
|
708
713
|
}
|
|
709
714
|
}
|
|
710
715
|
|
|
716
|
+
/** @deprecated */
|
|
711
717
|
export async function retry(fn, options) {
|
|
712
718
|
const { maxRetries = 8, count = maxRetries, delay = defaultDelay, signal } = options ?? {}
|
|
713
719
|
|
package/package.json
CHANGED
package/serializers.js
CHANGED
|
@@ -214,34 +214,24 @@ Object.defineProperty(pinoErrProto, rawSymbol, {
|
|
|
214
214
|
value: {},
|
|
215
215
|
})
|
|
216
216
|
|
|
217
|
-
function
|
|
218
|
-
if (
|
|
219
|
-
return
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
if (Array.isArray(obj)) {
|
|
223
|
-
return obj.map(copyAndReplaceBigInts)
|
|
217
|
+
function errSerializer(err) {
|
|
218
|
+
if (Array.isArray(err)) {
|
|
219
|
+
return err.length === 0 ? undefined : errSerializer({ message: '', errors: err })
|
|
224
220
|
}
|
|
225
221
|
|
|
226
|
-
if (
|
|
227
|
-
|
|
228
|
-
for (const [key, value] of Object.entries(obj)) {
|
|
229
|
-
dst[key] = copyAndReplaceBigInts(value)
|
|
230
|
-
}
|
|
231
|
-
return dst
|
|
222
|
+
if (!isErrorLike(err)) {
|
|
223
|
+
return undefined
|
|
232
224
|
}
|
|
233
225
|
|
|
234
|
-
|
|
235
|
-
|
|
226
|
+
const errors = Array.isArray(err?.errors)
|
|
227
|
+
? err.errors.map((err) => errSerializer(err)).filter(Boolean)
|
|
228
|
+
: null
|
|
236
229
|
|
|
237
|
-
|
|
238
|
-
if (Array.isArray(err)) {
|
|
239
|
-
return err.length === 0 ? undefined : errSerializer({ message: '', errors: err })
|
|
240
|
-
} else if (!isErrorLike(err)) {
|
|
230
|
+
if (err.message === '' && errors != null && errors.length === 0) {
|
|
241
231
|
return undefined
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
if (err.message === '' && errors != null && errors.length === 1) {
|
|
245
235
|
return errSerializer(err.errors[0])
|
|
246
236
|
}
|
|
247
237
|
|
|
@@ -253,8 +243,8 @@ function errSerializer(err) {
|
|
|
253
243
|
_err.message = err.message
|
|
254
244
|
_err.stack = err.stack
|
|
255
245
|
|
|
256
|
-
if (
|
|
257
|
-
_err.aggregateErrors =
|
|
246
|
+
if (errors != null) {
|
|
247
|
+
_err.aggregateErrors = errors
|
|
258
248
|
}
|
|
259
249
|
|
|
260
250
|
if (isErrorLike(err.cause) && !Object.prototype.hasOwnProperty.call(err.cause, seen)) {
|
|
@@ -271,7 +261,7 @@ function errSerializer(err) {
|
|
|
271
261
|
} else if (typeof val === 'bigint') {
|
|
272
262
|
_err[key] = `${val.toString()}`
|
|
273
263
|
} else if (val != null && !/^[A-Z0-9_]+$/.test(key)) {
|
|
274
|
-
_err[key] =
|
|
264
|
+
_err[key] = val
|
|
275
265
|
}
|
|
276
266
|
}
|
|
277
267
|
}
|