@nxtedition/lib 19.1.1 → 19.1.2
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 +109 -60
- package/package.json +2 -1
package/couch.js
CHANGED
|
@@ -6,9 +6,10 @@ import { makeWeakCache } from './weakCache.js'
|
|
|
6
6
|
import tp from 'timers/promises'
|
|
7
7
|
import { defaultDelay as delay } from './http.js'
|
|
8
8
|
import urljoin from 'url-join'
|
|
9
|
-
import undici from 'undici'
|
|
9
|
+
import undici, { util as undiciUtil } from 'undici'
|
|
10
10
|
import { AbortError } from './errors.js'
|
|
11
11
|
import split2 from 'split2'
|
|
12
|
+
import { parse as parseContentType } from 'content-type'
|
|
12
13
|
|
|
13
14
|
// https://github.com/fastify/fastify/blob/main/lib/reqIdGenFactory.js
|
|
14
15
|
// 2,147,483,647 (2^31 − 1) stands for max SMI value (an internal optimization of V8).
|
|
@@ -886,22 +887,15 @@ function _normalizeAllDocsOptions({
|
|
|
886
887
|
}
|
|
887
888
|
}
|
|
888
889
|
|
|
889
|
-
class
|
|
890
|
-
#str
|
|
891
|
-
#decoder
|
|
892
|
-
#onAbort
|
|
890
|
+
class SignalHandler extends undici.DecoratorHandler {
|
|
893
891
|
#signal
|
|
894
|
-
#statusCode
|
|
895
|
-
#statusText
|
|
896
|
-
#opts
|
|
897
892
|
#handler
|
|
893
|
+
#abort
|
|
898
894
|
|
|
899
|
-
constructor({
|
|
895
|
+
constructor({ signal, handler }) {
|
|
900
896
|
super(handler)
|
|
901
|
-
|
|
902
|
-
this.#handler = handler
|
|
903
|
-
this.#opts = opts
|
|
904
897
|
this.#signal = signal
|
|
898
|
+
this.#handler = handler
|
|
905
899
|
}
|
|
906
900
|
|
|
907
901
|
onConnect(abort) {
|
|
@@ -909,50 +903,93 @@ class Handler extends undici.DecoratorHandler {
|
|
|
909
903
|
abort(this.#signal.reason)
|
|
910
904
|
} else {
|
|
911
905
|
if (this.#signal) {
|
|
912
|
-
this.#
|
|
913
|
-
this.#signal.addEventListener('abort', this.#
|
|
906
|
+
this.#abort = () => abort(this.#signal.reason)
|
|
907
|
+
this.#signal.addEventListener('abort', this.#abort)
|
|
914
908
|
}
|
|
915
|
-
|
|
916
|
-
this.#str = ''
|
|
917
|
-
this.#decoder = null
|
|
918
909
|
this.#handler.onConnect?.(abort)
|
|
919
910
|
}
|
|
920
911
|
}
|
|
921
912
|
|
|
922
|
-
|
|
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
|
+
#statusText
|
|
929
|
+
#contentType
|
|
930
|
+
#opts
|
|
931
|
+
#handler
|
|
932
|
+
#error
|
|
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) {
|
|
923
948
|
this.#statusCode = statusCode
|
|
924
949
|
this.#statusText = statusText
|
|
925
950
|
|
|
926
|
-
if (this.#statusCode
|
|
927
|
-
|
|
928
|
-
|
|
951
|
+
if (this.#statusCode < 200 || this.#statusCode > 300) {
|
|
952
|
+
headers = Array.isArray(headers) ? undiciUtil.parseHeaders(headers) : headers
|
|
953
|
+
|
|
954
|
+
this.#error = new Error(this.#statusText ?? this.#statusCode)
|
|
955
|
+
|
|
956
|
+
this.#contentType = parseContentType(headers['content-type'] ?? '')?.type
|
|
957
|
+
if (this.#contentType !== 'application/json' && this.#contentType !== 'plain/text') {
|
|
958
|
+
throw this.#error
|
|
959
|
+
}
|
|
960
|
+
|
|
929
961
|
this.#decoder = new TextDecoder()
|
|
962
|
+
} else {
|
|
963
|
+
return this.#handler.onHeaders?.(statusCode, headers, resume, statusText)
|
|
930
964
|
}
|
|
931
965
|
}
|
|
932
966
|
|
|
933
967
|
onData(data) {
|
|
934
|
-
if (this.#
|
|
935
|
-
this.#str += this.#decoder
|
|
968
|
+
if (this.#error) {
|
|
969
|
+
this.#str += this.#decoder?.decode(data, { stream: true }) ?? ''
|
|
936
970
|
} else {
|
|
937
971
|
return this.#handler?.onData(data)
|
|
938
972
|
}
|
|
939
973
|
}
|
|
940
974
|
|
|
941
|
-
onComplete(
|
|
942
|
-
if (this.#
|
|
943
|
-
|
|
944
|
-
let reason
|
|
945
|
-
let error
|
|
946
|
-
try {
|
|
947
|
-
body = JSON.parse(this.#str)
|
|
948
|
-
reason = body.reason
|
|
949
|
-
error = body.error
|
|
950
|
-
} catch {
|
|
951
|
-
// Do nothing...
|
|
952
|
-
}
|
|
975
|
+
onComplete(...args) {
|
|
976
|
+
if (this.#error) {
|
|
977
|
+
this.#str += this.#decoder?.decode(undefined, { stream: false }) ?? ''
|
|
953
978
|
|
|
954
|
-
this
|
|
955
|
-
|
|
979
|
+
if (this.#contentType === 'application/json') {
|
|
980
|
+
let body
|
|
981
|
+
let reason
|
|
982
|
+
let error
|
|
983
|
+
try {
|
|
984
|
+
body = JSON.parse(this.#str)
|
|
985
|
+
reason = body.reason
|
|
986
|
+
error = body.error
|
|
987
|
+
} catch {
|
|
988
|
+
body = this.#str
|
|
989
|
+
// Do nothing...
|
|
990
|
+
}
|
|
991
|
+
|
|
992
|
+
throw Object.assign(this.#error, {
|
|
956
993
|
reason,
|
|
957
994
|
error,
|
|
958
995
|
data: {
|
|
@@ -962,26 +999,22 @@ class Handler extends undici.DecoratorHandler {
|
|
|
962
999
|
statusCode: this.#statusCode,
|
|
963
1000
|
},
|
|
964
1001
|
},
|
|
965
|
-
})
|
|
966
|
-
)
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
if (this.#signal) {
|
|
978
|
-
this.#signal.removeEventListener('abort', this.#onAbort)
|
|
979
|
-
}
|
|
1002
|
+
})
|
|
1003
|
+
} else if (this.#contentType === 'plain/text') {
|
|
1004
|
+
throw Object.assign(this.#error, {
|
|
1005
|
+
data: {
|
|
1006
|
+
req: this.#opts,
|
|
1007
|
+
res: {
|
|
1008
|
+
body: this.#str,
|
|
1009
|
+
statusCode: this.#statusCode,
|
|
1010
|
+
},
|
|
1011
|
+
},
|
|
1012
|
+
})
|
|
1013
|
+
}
|
|
980
1014
|
|
|
981
|
-
|
|
982
|
-
this.#handler.onError?.(err)
|
|
1015
|
+
assert(false)
|
|
983
1016
|
} else {
|
|
984
|
-
this.#handler.onComplete?.(
|
|
1017
|
+
this.#handler.onComplete?.(...args)
|
|
985
1018
|
}
|
|
986
1019
|
}
|
|
987
1020
|
}
|
|
@@ -992,10 +1025,12 @@ class StreamOutput extends stream.Readable {
|
|
|
992
1025
|
#abort
|
|
993
1026
|
#state
|
|
994
1027
|
#decoder
|
|
1028
|
+
#batched
|
|
995
1029
|
#didPush = false
|
|
996
1030
|
|
|
997
|
-
constructor({ highWaterMark }) {
|
|
1031
|
+
constructor({ batched = false, highWaterMark = batched ? 2 : 128 }) {
|
|
998
1032
|
super({ objectMode: true, highWaterMark })
|
|
1033
|
+
this.#batched = batched
|
|
999
1034
|
}
|
|
1000
1035
|
|
|
1001
1036
|
_read() {
|
|
@@ -1033,6 +1068,7 @@ class StreamOutput extends stream.Readable {
|
|
|
1033
1068
|
lines[0] = this.#str + lines[0]
|
|
1034
1069
|
this.#str = lines.pop() ?? ''
|
|
1035
1070
|
|
|
1071
|
+
const rows = this.#batched ? [] : null
|
|
1036
1072
|
for (const line of lines) {
|
|
1037
1073
|
if (this.#state === 0) {
|
|
1038
1074
|
if (line.endsWith('[')) {
|
|
@@ -1044,12 +1080,22 @@ class StreamOutput extends stream.Readable {
|
|
|
1044
1080
|
if (line.startsWith(']')) {
|
|
1045
1081
|
this.#state = 2
|
|
1046
1082
|
} else {
|
|
1047
|
-
|
|
1048
|
-
|
|
1083
|
+
const row = JSON.parse(line.slice(0, line.lastIndexOf('}') + 1))
|
|
1084
|
+
if (rows) {
|
|
1085
|
+
rows.push(row)
|
|
1086
|
+
} else {
|
|
1087
|
+
this.push(row)
|
|
1088
|
+
this.#didPush = true
|
|
1089
|
+
}
|
|
1049
1090
|
}
|
|
1050
1091
|
}
|
|
1051
1092
|
}
|
|
1052
1093
|
|
|
1094
|
+
if (rows) {
|
|
1095
|
+
this.push(rows)
|
|
1096
|
+
this.#didPush = true
|
|
1097
|
+
}
|
|
1098
|
+
|
|
1053
1099
|
return this.readableLength < this.readableHighWaterMark
|
|
1054
1100
|
}
|
|
1055
1101
|
|
|
@@ -1121,6 +1167,8 @@ export function request(
|
|
|
1121
1167
|
method,
|
|
1122
1168
|
headers: {
|
|
1123
1169
|
'content-type': body != null && typeof body === 'object' ? 'application/json' : 'plain/text',
|
|
1170
|
+
'user-agent': globalThis.userAgent,
|
|
1171
|
+
'request-id': genReqId(),
|
|
1124
1172
|
accept: 'application/json',
|
|
1125
1173
|
...headers,
|
|
1126
1174
|
},
|
|
@@ -1128,11 +1176,12 @@ export function request(
|
|
|
1128
1176
|
}
|
|
1129
1177
|
|
|
1130
1178
|
dispatcher = dispatcher.compose(
|
|
1131
|
-
(dispatch) => (opts, handler) => dispatch(opts, new
|
|
1179
|
+
(dispatch) => (opts, handler) => dispatch(opts, new ErrorHandler({ opts, handler })),
|
|
1180
|
+
(dispatch) => (opts, handler) => dispatch(opts, new SignalHandler({ signal, handler })),
|
|
1132
1181
|
)
|
|
1133
1182
|
|
|
1134
1183
|
if (stream) {
|
|
1135
|
-
const handler = new StreamOutput(
|
|
1184
|
+
const handler = new StreamOutput(stream)
|
|
1136
1185
|
dispatcher.dispatch(opts, handler)
|
|
1137
1186
|
return handler
|
|
1138
1187
|
} else {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nxtedition/lib",
|
|
3
|
-
"version": "19.1.
|
|
3
|
+
"version": "19.1.2",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": "Robert Nagy <robert.nagy@boffins.se>",
|
|
6
6
|
"type": "module",
|
|
@@ -79,6 +79,7 @@
|
|
|
79
79
|
"@elastic/elasticsearch": "^8.13.1",
|
|
80
80
|
"@elastic/transport": "^8.5.1",
|
|
81
81
|
"@nxtedition/nxt-undici": "^2.0.46",
|
|
82
|
+
"content-type": "^1.0.5",
|
|
82
83
|
"date-fns": "^3.6.0",
|
|
83
84
|
"fast-querystring": "^1.1.1",
|
|
84
85
|
"hasha": "^6.0.0",
|