@nxtedition/lib 19.8.1 → 19.8.3
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/couch.js +96 -189
- package/package.json +18 -17
- package/weakCache.d.ts +4 -0
package/couch.js
CHANGED
|
@@ -8,8 +8,7 @@ import { defaultDelay as delay } from './http.js'
|
|
|
8
8
|
import urljoin from 'url-join'
|
|
9
9
|
import undici, { util as undiciUtil } from 'undici'
|
|
10
10
|
import { AbortError } from './errors.js'
|
|
11
|
-
import
|
|
12
|
-
import { parse as parseContentType } from 'content-type'
|
|
11
|
+
import { interceptors } from '@nxtedition/nxt-undici'
|
|
13
12
|
|
|
14
13
|
// https://github.com/fastify/fastify/blob/main/lib/reqIdGenFactory.js
|
|
15
14
|
// 2,147,483,647 (2^31 − 1) stands for max SMI value (an internal optimization of V8).
|
|
@@ -265,11 +264,7 @@ export function makeCouch(opts) {
|
|
|
265
264
|
})
|
|
266
265
|
}
|
|
267
266
|
|
|
268
|
-
src =
|
|
269
|
-
ures.body,
|
|
270
|
-
split2('\n', { writableHighWaterMark: highWaterMark ?? 256 * 1024 }),
|
|
271
|
-
() => {},
|
|
272
|
-
)
|
|
267
|
+
src = ures.body
|
|
273
268
|
|
|
274
269
|
const changes = []
|
|
275
270
|
|
|
@@ -297,42 +292,59 @@ export function makeCouch(opts) {
|
|
|
297
292
|
})
|
|
298
293
|
.on('close', maybeResume)
|
|
299
294
|
|
|
295
|
+
let str = ''
|
|
300
296
|
while (true) {
|
|
301
|
-
const
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
297
|
+
const chunk = src.read()
|
|
298
|
+
|
|
299
|
+
if (chunk !== null) {
|
|
300
|
+
const lines = (str + chunk).split(/\r?\n/)
|
|
301
|
+
str = lines.pop() ?? ''
|
|
302
|
+
|
|
303
|
+
for (const line of lines) {
|
|
304
|
+
if (line === '') {
|
|
305
|
+
// hearbeat
|
|
306
|
+
yield batched ? [] : null
|
|
307
|
+
} else if (line === ',') {
|
|
308
|
+
// Do nothing. Couch sometimes insert new line between
|
|
309
|
+
// json body and comma.
|
|
310
|
+
} else if (live) {
|
|
311
|
+
const data = JSON.parse(line)
|
|
312
|
+
if (data.last_seq) {
|
|
313
|
+
params.since = data.last_seq
|
|
316
314
|
} else {
|
|
317
|
-
|
|
315
|
+
params.since = data.seq || params.since
|
|
316
|
+
changes.push(data)
|
|
318
317
|
}
|
|
319
|
-
} else
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
318
|
+
} else {
|
|
319
|
+
// NOTE: This makes some assumptions about the format of the JSON.
|
|
320
|
+
if (state === 0) {
|
|
321
|
+
if (line.endsWith('[')) {
|
|
322
|
+
state = 1
|
|
323
|
+
} else {
|
|
324
|
+
assert(false, 'invalid head: ' + line)
|
|
325
|
+
}
|
|
326
|
+
} else if (state === 1) {
|
|
327
|
+
if (line.startsWith(']')) {
|
|
328
|
+
state = 2
|
|
329
|
+
} else {
|
|
330
|
+
const idx = line.lastIndexOf('}') + 1
|
|
331
|
+
try {
|
|
332
|
+
assert(idx >= 0, 'invalid row: ' + idx + ' ' + line)
|
|
333
|
+
const change = JSON.parse(line.slice(0, idx))
|
|
334
|
+
params.since = change.seq || params.since
|
|
335
|
+
changes.push(change)
|
|
336
|
+
} catch (err) {
|
|
337
|
+
throw Object.assign(err, { data: line })
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
} else if (state === 2) {
|
|
341
|
+
state = 3
|
|
342
|
+
params.since = JSON.parse('{' + line).last_seq
|
|
343
|
+
assert(params.since, 'invalid trailer: ' + line)
|
|
328
344
|
}
|
|
329
|
-
} else if (state === 2) {
|
|
330
|
-
state = 3
|
|
331
|
-
params.since = JSON.parse('{' + line).last_seq
|
|
332
|
-
assert(params.since, 'invalid trailer: ' + line)
|
|
333
345
|
}
|
|
334
346
|
}
|
|
335
|
-
} else if (changes.length
|
|
347
|
+
} else if (changes.length) {
|
|
336
348
|
remaining -= changes.length
|
|
337
349
|
assert(remaining >= 0, 'invalid remaining: ' + remaining)
|
|
338
350
|
|
|
@@ -887,141 +899,6 @@ function _normalizeAllDocsOptions({
|
|
|
887
899
|
}
|
|
888
900
|
}
|
|
889
901
|
|
|
890
|
-
class SignalHandler extends undici.DecoratorHandler {
|
|
891
|
-
#signal
|
|
892
|
-
#handler
|
|
893
|
-
#abort
|
|
894
|
-
|
|
895
|
-
constructor({ signal, handler }) {
|
|
896
|
-
super(handler)
|
|
897
|
-
this.#signal = signal
|
|
898
|
-
this.#handler = handler
|
|
899
|
-
}
|
|
900
|
-
|
|
901
|
-
onConnect(abort) {
|
|
902
|
-
if (this.#signal?.aborted) {
|
|
903
|
-
abort(this.#signal.reason)
|
|
904
|
-
} else {
|
|
905
|
-
if (this.#signal) {
|
|
906
|
-
this.#abort = () => abort(this.#signal.reason)
|
|
907
|
-
this.#signal.addEventListener('abort', this.#abort)
|
|
908
|
-
}
|
|
909
|
-
this.#handler.onConnect?.(abort)
|
|
910
|
-
}
|
|
911
|
-
}
|
|
912
|
-
|
|
913
|
-
onComplete(...args) {
|
|
914
|
-
this.#signal?.removeEventListener('abort', this.#abort)
|
|
915
|
-
this.#handler.onComplete?.(...args)
|
|
916
|
-
}
|
|
917
|
-
|
|
918
|
-
onError(...args) {
|
|
919
|
-
this.#signal?.removeEventListener('abort', this.#abort)
|
|
920
|
-
this.#handler.onError?.(...args)
|
|
921
|
-
}
|
|
922
|
-
}
|
|
923
|
-
|
|
924
|
-
class ErrorHandler extends undici.DecoratorHandler {
|
|
925
|
-
#str
|
|
926
|
-
#decoder
|
|
927
|
-
#statusCode
|
|
928
|
-
#contentType
|
|
929
|
-
#opts
|
|
930
|
-
#handler
|
|
931
|
-
#error
|
|
932
|
-
#headers
|
|
933
|
-
|
|
934
|
-
constructor({ opts, handler }) {
|
|
935
|
-
super(handler)
|
|
936
|
-
|
|
937
|
-
this.#handler = handler
|
|
938
|
-
this.#opts = opts
|
|
939
|
-
}
|
|
940
|
-
|
|
941
|
-
onConnect(...args) {
|
|
942
|
-
this.#str = ''
|
|
943
|
-
this.#decoder = null
|
|
944
|
-
this.#handler.onConnect?.(...args)
|
|
945
|
-
}
|
|
946
|
-
|
|
947
|
-
onHeaders(statusCode, headers, resume, statusText) {
|
|
948
|
-
this.#statusCode = statusCode
|
|
949
|
-
|
|
950
|
-
if (this.#statusCode < 200 || this.#statusCode > 300) {
|
|
951
|
-
this.#headers = Array.isArray(headers) ? undiciUtil.parseHeaders(headers) : headers
|
|
952
|
-
|
|
953
|
-
this.#error = new Error(statusText ?? statusCode)
|
|
954
|
-
|
|
955
|
-
this.#contentType = this.#headers['content-type']
|
|
956
|
-
? parseContentType(this.#headers['content-type'] ?? '')?.type
|
|
957
|
-
: null
|
|
958
|
-
|
|
959
|
-
if (this.#contentType !== 'application/json' && this.#contentType !== 'plain/text') {
|
|
960
|
-
throw this.#error
|
|
961
|
-
}
|
|
962
|
-
|
|
963
|
-
this.#decoder = new TextDecoder()
|
|
964
|
-
} else {
|
|
965
|
-
return this.#handler.onHeaders?.(statusCode, headers, resume, statusText)
|
|
966
|
-
}
|
|
967
|
-
}
|
|
968
|
-
|
|
969
|
-
onData(data) {
|
|
970
|
-
if (this.#error) {
|
|
971
|
-
this.#str += this.#decoder?.decode(data, { stream: true }) ?? ''
|
|
972
|
-
} else {
|
|
973
|
-
return this.#handler?.onData(data)
|
|
974
|
-
}
|
|
975
|
-
}
|
|
976
|
-
|
|
977
|
-
onComplete(...args) {
|
|
978
|
-
if (this.#error) {
|
|
979
|
-
this.#str += this.#decoder?.decode(undefined, { stream: false }) ?? ''
|
|
980
|
-
|
|
981
|
-
if (this.#contentType === 'application/json') {
|
|
982
|
-
let body
|
|
983
|
-
let reason
|
|
984
|
-
let error
|
|
985
|
-
try {
|
|
986
|
-
body = JSON.parse(this.#str)
|
|
987
|
-
reason = body.reason
|
|
988
|
-
error = body.error
|
|
989
|
-
} catch {
|
|
990
|
-
body = this.#str
|
|
991
|
-
// Do nothing...
|
|
992
|
-
}
|
|
993
|
-
|
|
994
|
-
throw Object.assign(this.#error, {
|
|
995
|
-
reason,
|
|
996
|
-
error,
|
|
997
|
-
data: {
|
|
998
|
-
req: this.#opts,
|
|
999
|
-
res: {
|
|
1000
|
-
body,
|
|
1001
|
-
statusCode: this.#statusCode,
|
|
1002
|
-
},
|
|
1003
|
-
},
|
|
1004
|
-
})
|
|
1005
|
-
} else if (this.#contentType === 'plain/text') {
|
|
1006
|
-
throw Object.assign(this.#error, {
|
|
1007
|
-
data: {
|
|
1008
|
-
ureq: this.#opts,
|
|
1009
|
-
ures: {
|
|
1010
|
-
body: this.#str,
|
|
1011
|
-
statusCode: this.#statusCode,
|
|
1012
|
-
headers: this.#headers,
|
|
1013
|
-
},
|
|
1014
|
-
},
|
|
1015
|
-
})
|
|
1016
|
-
}
|
|
1017
|
-
|
|
1018
|
-
assert(false)
|
|
1019
|
-
} else {
|
|
1020
|
-
this.#handler.onComplete?.(...args)
|
|
1021
|
-
}
|
|
1022
|
-
}
|
|
1023
|
-
}
|
|
1024
|
-
|
|
1025
902
|
class StreamOutput extends stream.Readable {
|
|
1026
903
|
#str
|
|
1027
904
|
#resume
|
|
@@ -1036,8 +913,8 @@ class StreamOutput extends stream.Readable {
|
|
|
1036
913
|
ttfb: -1,
|
|
1037
914
|
}
|
|
1038
915
|
|
|
1039
|
-
constructor({ highWaterMark = 256 }) {
|
|
1040
|
-
super({ objectMode: true, highWaterMark })
|
|
916
|
+
constructor({ signal, highWaterMark = 256 }) {
|
|
917
|
+
super({ objectMode: true, highWaterMark, signal })
|
|
1041
918
|
}
|
|
1042
919
|
|
|
1043
920
|
get headers() {
|
|
@@ -1136,6 +1013,8 @@ class PromiseOutput {
|
|
|
1136
1013
|
#decoder
|
|
1137
1014
|
#headers
|
|
1138
1015
|
#startTime = performance.now()
|
|
1016
|
+
#signal
|
|
1017
|
+
#abort
|
|
1139
1018
|
#stats = {
|
|
1140
1019
|
connect: -1,
|
|
1141
1020
|
headers: -1,
|
|
@@ -1144,15 +1023,23 @@ class PromiseOutput {
|
|
|
1144
1023
|
error: -1,
|
|
1145
1024
|
}
|
|
1146
1025
|
|
|
1147
|
-
constructor({ resolve, reject }) {
|
|
1026
|
+
constructor({ resolve, reject, signal }) {
|
|
1148
1027
|
this.#resolve = resolve
|
|
1149
1028
|
this.#reject = reject
|
|
1029
|
+
this.#signal = signal
|
|
1150
1030
|
}
|
|
1151
1031
|
|
|
1152
|
-
onConnect() {
|
|
1032
|
+
onConnect(abort) {
|
|
1153
1033
|
this.#stats.connect = performance.now() - this.#startTime
|
|
1154
1034
|
this.#decoder = new TextDecoder()
|
|
1155
1035
|
this.#str = ''
|
|
1036
|
+
|
|
1037
|
+
if (this.#signal?.aborted) {
|
|
1038
|
+
abort()
|
|
1039
|
+
} else {
|
|
1040
|
+
this.#abort = abort
|
|
1041
|
+
this.#signal?.addEventListener('abort', this.#abort)
|
|
1042
|
+
}
|
|
1156
1043
|
}
|
|
1157
1044
|
|
|
1158
1045
|
onHeaders(statusCode, rawHeaders, resume, statusText) {
|
|
@@ -1181,9 +1068,8 @@ class PromiseOutput {
|
|
|
1181
1068
|
|
|
1182
1069
|
this.#str += this.#decoder.decode(undefined, { stream: false })
|
|
1183
1070
|
|
|
1184
|
-
this.#
|
|
1185
|
-
|
|
1186
|
-
)
|
|
1071
|
+
const val = Object.assign(JSON.parse(this.#str), { headers: this.#headers, stats: this.#stats })
|
|
1072
|
+
this.#onDone(null, val)
|
|
1187
1073
|
}
|
|
1188
1074
|
|
|
1189
1075
|
onError(err) {
|
|
@@ -1191,10 +1077,23 @@ class PromiseOutput {
|
|
|
1191
1077
|
this.#stats.error = performance.now() - this.#startTime - this.#stats.data
|
|
1192
1078
|
}
|
|
1193
1079
|
|
|
1194
|
-
this.#
|
|
1080
|
+
this.#onDone(err)
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1083
|
+
#onDone(err, val) {
|
|
1084
|
+
if (err) {
|
|
1085
|
+
this.#reject(err)
|
|
1086
|
+
} else {
|
|
1087
|
+
this.#resolve(val)
|
|
1088
|
+
}
|
|
1089
|
+
|
|
1090
|
+
if (this.#abort) {
|
|
1091
|
+
this.#signal?.removeEventListener('abort', this.#abort)
|
|
1092
|
+
}
|
|
1195
1093
|
}
|
|
1196
1094
|
}
|
|
1197
1095
|
|
|
1096
|
+
const dispatcherCache = new WeakMap()
|
|
1198
1097
|
export function request(
|
|
1199
1098
|
url,
|
|
1200
1099
|
{
|
|
@@ -1204,6 +1103,7 @@ export function request(
|
|
|
1204
1103
|
headers,
|
|
1205
1104
|
dispatcher = undici.getGlobalDispatcher(),
|
|
1206
1105
|
signal,
|
|
1106
|
+
logger,
|
|
1207
1107
|
stream,
|
|
1208
1108
|
},
|
|
1209
1109
|
) {
|
|
@@ -1221,26 +1121,33 @@ export function request(
|
|
|
1221
1121
|
headers: {
|
|
1222
1122
|
'content-type': body != null && typeof body === 'object' ? 'application/json' : 'plain/text',
|
|
1223
1123
|
'user-agent': globalThis.userAgent ?? 'nxt-lib',
|
|
1224
|
-
'request-id': genReqId(),
|
|
1225
1124
|
accept: 'application/json',
|
|
1226
1125
|
...headers,
|
|
1227
1126
|
},
|
|
1127
|
+
logger,
|
|
1228
1128
|
body: body != null && typeof body === 'object' ? JSON.stringify(body) : body,
|
|
1229
1129
|
}
|
|
1230
1130
|
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1131
|
+
let wrappedDispatcher = dispatcherCache.get(dispatcher)
|
|
1132
|
+
if (!wrappedDispatcher) {
|
|
1133
|
+
wrappedDispatcher = dispatcher.compose(
|
|
1134
|
+
interceptors.responseError,
|
|
1135
|
+
interceptors.log,
|
|
1136
|
+
interceptors.requestId,
|
|
1137
|
+
interceptors.responseRetry,
|
|
1138
|
+
interceptors.responseVerify,
|
|
1139
|
+
)
|
|
1140
|
+
dispatcherCache.set(dispatcher, wrappedDispatcher)
|
|
1141
|
+
}
|
|
1235
1142
|
|
|
1236
1143
|
if (stream) {
|
|
1237
|
-
const handler = new StreamOutput(stream)
|
|
1238
|
-
|
|
1144
|
+
const handler = new StreamOutput({ signal, ...stream })
|
|
1145
|
+
wrappedDispatcher.dispatch(opts, handler)
|
|
1239
1146
|
return handler
|
|
1240
1147
|
} else {
|
|
1241
1148
|
return new Promise((resolve, reject) => {
|
|
1242
|
-
const handler = new PromiseOutput({ resolve, reject })
|
|
1243
|
-
|
|
1149
|
+
const handler = new PromiseOutput({ resolve, reject, signal })
|
|
1150
|
+
wrappedDispatcher.dispatch(opts, handler)
|
|
1244
1151
|
})
|
|
1245
1152
|
}
|
|
1246
1153
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nxtedition/lib",
|
|
3
|
-
"version": "19.8.
|
|
3
|
+
"version": "19.8.3",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": "Robert Nagy <robert.nagy@boffins.se>",
|
|
6
6
|
"type": "module",
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
"timers.js",
|
|
27
27
|
"trace.js",
|
|
28
28
|
"weakCache.js",
|
|
29
|
+
"weakCache.d.ts",
|
|
29
30
|
"couch.js",
|
|
30
31
|
"app.js",
|
|
31
32
|
"errors.js",
|
|
@@ -74,13 +75,14 @@
|
|
|
74
75
|
}
|
|
75
76
|
},
|
|
76
77
|
"eslintIgnore": [
|
|
77
|
-
"/__tests__"
|
|
78
|
+
"/__tests__",
|
|
79
|
+
"**/*.d.ts"
|
|
78
80
|
],
|
|
79
81
|
"dependencies": {
|
|
80
|
-
"@aws-sdk/client-s3": "^3.
|
|
81
|
-
"@elastic/elasticsearch": "^8.
|
|
82
|
-
"@elastic/transport": "^8.
|
|
83
|
-
"@nxtedition/nxt-undici": "^2.
|
|
82
|
+
"@aws-sdk/client-s3": "^3.600.0",
|
|
83
|
+
"@elastic/elasticsearch": "^8.14.0",
|
|
84
|
+
"@elastic/transport": "^8.6.0",
|
|
85
|
+
"@nxtedition/nxt-undici": "^2.2.7",
|
|
84
86
|
"content-type": "^1.0.5",
|
|
85
87
|
"date-fns": "^3.6.0",
|
|
86
88
|
"fast-querystring": "^1.1.1",
|
|
@@ -95,31 +97,30 @@
|
|
|
95
97
|
"nested-error-stacks": "^2.1.1",
|
|
96
98
|
"object-hash": "^3.0.0",
|
|
97
99
|
"p-queue": "^8.0.1",
|
|
98
|
-
"pino": "^
|
|
100
|
+
"pino": "^9.2.0",
|
|
99
101
|
"qs": "^6.12.1",
|
|
100
102
|
"request-target": "^1.0.2",
|
|
101
|
-
"smpte-timecode": "^1.3.
|
|
103
|
+
"smpte-timecode": "^1.3.6",
|
|
102
104
|
"split-string": "^6.0.0",
|
|
103
|
-
"split2": "^4.2.0",
|
|
104
105
|
"toobusy-js": "^0.5.1",
|
|
105
|
-
"undici": "^6.
|
|
106
|
+
"undici": "^6.19.2",
|
|
106
107
|
"url-join": "^5.0.0"
|
|
107
108
|
},
|
|
108
109
|
"devDependencies": {
|
|
109
|
-
"@nxtedition/deepstream.io-client-js": ">=24.
|
|
110
|
-
"@types/lodash": "^4.17.
|
|
111
|
-
"@types/node": "^20.
|
|
110
|
+
"@nxtedition/deepstream.io-client-js": ">=24.2.4",
|
|
111
|
+
"@types/lodash": "^4.17.5",
|
|
112
|
+
"@types/node": "^20.14.6",
|
|
112
113
|
"eslint": "^8.0.0",
|
|
113
114
|
"eslint-config-prettier": "^9.1.0",
|
|
114
115
|
"eslint-config-standard": "^17.0.0",
|
|
115
116
|
"eslint-plugin-import": "^2.29.1",
|
|
116
|
-
"eslint-plugin-n": "^17.
|
|
117
|
+
"eslint-plugin-n": "^17.9.0",
|
|
117
118
|
"eslint-plugin-node": "^11.1.0",
|
|
118
|
-
"eslint-plugin-promise": "^6.
|
|
119
|
+
"eslint-plugin-promise": "^6.2.0",
|
|
119
120
|
"husky": "^9.0.11",
|
|
120
|
-
"lint-staged": "^15.2.
|
|
121
|
+
"lint-staged": "^15.2.7",
|
|
121
122
|
"pinst": "^3.0.0",
|
|
122
|
-
"prettier": "^3.2
|
|
123
|
+
"prettier": "^3.3.2",
|
|
123
124
|
"rxjs": "^7.5.6",
|
|
124
125
|
"send": "^0.18.0"
|
|
125
126
|
},
|
package/weakCache.d.ts
ADDED