@jsenv/core 29.1.4 → 29.1.6
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/main.js
CHANGED
|
@@ -4450,8 +4450,10 @@ const observableFromValue = value => {
|
|
|
4450
4450
|
};
|
|
4451
4451
|
|
|
4452
4452
|
// https://github.com/jamestalmage/stream-to-observable/blob/master/index.js
|
|
4453
|
-
const
|
|
4454
|
-
|
|
4453
|
+
const observableFromNodeStream = (nodeStream, {
|
|
4454
|
+
readableStreamLifetime = 120_000 // 2s
|
|
4455
|
+
|
|
4456
|
+
} = {}) => {
|
|
4455
4457
|
const observable = createObservable(({
|
|
4456
4458
|
next,
|
|
4457
4459
|
error,
|
|
@@ -4490,13 +4492,13 @@ const nodeStreamToObservable = nodeStream => {
|
|
|
4490
4492
|
// safe measure, ensure the readable stream gets
|
|
4491
4493
|
// used in the next ${readableStreamLifetimeInSeconds} otherwise destroys it
|
|
4492
4494
|
const timeout = setTimeout(() => {
|
|
4493
|
-
process.emitWarning(`Readable stream not used after ${
|
|
4495
|
+
process.emitWarning(`Readable stream not used after ${readableStreamLifetime / 1000} seconds. It will be destroyed to release resources`, {
|
|
4494
4496
|
CODE: "READABLE_STREAM_TIMEOUT",
|
|
4495
4497
|
// url is for http client request
|
|
4496
4498
|
detail: `path: ${nodeStream.path}, fd: ${nodeStream.fd}, url: ${nodeStream.url}`
|
|
4497
4499
|
});
|
|
4498
4500
|
nodeStream.destroy();
|
|
4499
|
-
},
|
|
4501
|
+
}, readableStreamLifetime);
|
|
4500
4502
|
observable.timeout = timeout;
|
|
4501
4503
|
onceReadableStreamUsedOrClosed(nodeStream, () => {
|
|
4502
4504
|
clearTimeout(timeout);
|
|
@@ -4550,10 +4552,13 @@ const headersFromObject = headersObject => {
|
|
|
4550
4552
|
|
|
4551
4553
|
const fromNodeRequest = (nodeRequest, {
|
|
4552
4554
|
serverOrigin,
|
|
4553
|
-
signal
|
|
4555
|
+
signal,
|
|
4556
|
+
requestBodyLifetime
|
|
4554
4557
|
}) => {
|
|
4555
4558
|
const headers = headersFromObject(nodeRequest.headers);
|
|
4556
|
-
const body =
|
|
4559
|
+
const body = observableFromNodeStream(nodeRequest, {
|
|
4560
|
+
readableStreamLifetime: requestBodyLifetime
|
|
4561
|
+
});
|
|
4557
4562
|
let requestOrigin;
|
|
4558
4563
|
|
|
4559
4564
|
if (nodeRequest.upgrade) {
|
|
@@ -4671,7 +4676,7 @@ const normalizeBodyMethods = body => {
|
|
|
4671
4676
|
|
|
4672
4677
|
if (isNodeStream(body)) {
|
|
4673
4678
|
return {
|
|
4674
|
-
asObservable: () =>
|
|
4679
|
+
asObservable: () => observableFromNodeStream(body),
|
|
4675
4680
|
destroy: () => {
|
|
4676
4681
|
body.destroy();
|
|
4677
4682
|
}
|
|
@@ -4702,7 +4707,7 @@ const fileHandleToReadableStream = fileHandle => {
|
|
|
4702
4707
|
};
|
|
4703
4708
|
|
|
4704
4709
|
const fileHandleToObservable = fileHandle => {
|
|
4705
|
-
return
|
|
4710
|
+
return observableFromNodeStream(fileHandleToReadableStream(fileHandle));
|
|
4706
4711
|
};
|
|
4707
4712
|
|
|
4708
4713
|
const isNodeStream = value => {
|
|
@@ -4717,7 +4722,7 @@ const isNodeStream = value => {
|
|
|
4717
4722
|
return false;
|
|
4718
4723
|
};
|
|
4719
4724
|
|
|
4720
|
-
const
|
|
4725
|
+
const writeNodeResponse = async (responseStream, {
|
|
4721
4726
|
status,
|
|
4722
4727
|
statusText,
|
|
4723
4728
|
headers,
|
|
@@ -5487,7 +5492,16 @@ const startServer = async ({
|
|
|
5487
5492
|
"request url": request.url,
|
|
5488
5493
|
"request headers": JSON.stringify(request.headers, null, " ")
|
|
5489
5494
|
}));
|
|
5490
|
-
}
|
|
5495
|
+
},
|
|
5496
|
+
// timeAllocated to start responding to a request
|
|
5497
|
+
// after this delay the server will respond with 504
|
|
5498
|
+
responseTimeout = 60_000 * 10,
|
|
5499
|
+
// 10s
|
|
5500
|
+
// time allocated to server code to start reading the request body
|
|
5501
|
+
// after this delay the underlying stream is destroyed, attempting to read it would throw
|
|
5502
|
+
// if used the stream stays opened, it's only if the stream is not read at all that it gets destroyed
|
|
5503
|
+
requestBodyLifetime = 60_000 * 2 // 2s
|
|
5504
|
+
|
|
5491
5505
|
} = {}) => {
|
|
5492
5506
|
const logger = createLogger({
|
|
5493
5507
|
logLevel
|
|
@@ -5972,7 +5986,7 @@ const startServer = async ({
|
|
|
5972
5986
|
abortController.abort();
|
|
5973
5987
|
} else if (!http2Stream.pushAllowed) {
|
|
5974
5988
|
abortController.abort();
|
|
5975
|
-
} else if (responseProperties
|
|
5989
|
+
} else if (responseProperties.requestAborted) {} else {
|
|
5976
5990
|
const responseLength = responseProperties.headers["content-length"] || 0;
|
|
5977
5991
|
const {
|
|
5978
5992
|
effectiveRecvDataLength,
|
|
@@ -6047,87 +6061,104 @@ const startServer = async ({
|
|
|
6047
6061
|
let handleRequestReturnValue;
|
|
6048
6062
|
let errorWhileHandlingRequest = null;
|
|
6049
6063
|
let handleRequestTimings = serverTiming ? {} : null;
|
|
6064
|
+
let timeout;
|
|
6065
|
+
const timeoutPromise = new Promise(resolve => {
|
|
6066
|
+
timeout = setTimeout(() => {
|
|
6067
|
+
resolve({
|
|
6068
|
+
// the correct status code should be 500 because it's
|
|
6069
|
+
// we don't really know what takes time
|
|
6070
|
+
// in practice it's often because server is trying to reach an other server
|
|
6071
|
+
// that is not responding so 504 is more correct
|
|
6072
|
+
status: 504,
|
|
6073
|
+
statusText: `server timeout after ${responseTimeout / 1000}s waiting to handle request`
|
|
6074
|
+
});
|
|
6075
|
+
}, responseTimeout);
|
|
6076
|
+
});
|
|
6077
|
+
const handleRequestPromise = serviceController.callAsyncHooksUntil("handleRequest", request, {
|
|
6078
|
+
timing: handleRequestTimings,
|
|
6079
|
+
warn,
|
|
6080
|
+
pushResponse: async ({
|
|
6081
|
+
path,
|
|
6082
|
+
method
|
|
6083
|
+
}) => {
|
|
6084
|
+
if (typeof path !== "string" || path[0] !== "/") {
|
|
6085
|
+
addRequestLog(requestNode, {
|
|
6086
|
+
type: "warn",
|
|
6087
|
+
value: `response push ignored because path is invalid (must be a string starting with "/", found ${path})`
|
|
6088
|
+
});
|
|
6089
|
+
return;
|
|
6090
|
+
}
|
|
6050
6091
|
|
|
6051
|
-
|
|
6052
|
-
|
|
6053
|
-
|
|
6054
|
-
|
|
6055
|
-
|
|
6056
|
-
|
|
6057
|
-
|
|
6058
|
-
}) => {
|
|
6059
|
-
if (typeof path !== "string" || path[0] !== "/") {
|
|
6060
|
-
addRequestLog(requestNode, {
|
|
6061
|
-
type: "warn",
|
|
6062
|
-
value: `response push ignored because path is invalid (must be a string starting with "/", found ${path})`
|
|
6063
|
-
});
|
|
6064
|
-
return;
|
|
6065
|
-
}
|
|
6066
|
-
|
|
6067
|
-
if (!request.http2) {
|
|
6068
|
-
addRequestLog(requestNode, {
|
|
6069
|
-
type: "warn",
|
|
6070
|
-
value: `response push ignored because request is not http2`
|
|
6071
|
-
});
|
|
6072
|
-
return;
|
|
6073
|
-
}
|
|
6074
|
-
|
|
6075
|
-
const canPushStream = testCanPushStream(nodeResponse.stream);
|
|
6092
|
+
if (!request.http2) {
|
|
6093
|
+
addRequestLog(requestNode, {
|
|
6094
|
+
type: "warn",
|
|
6095
|
+
value: `response push ignored because request is not http2`
|
|
6096
|
+
});
|
|
6097
|
+
return;
|
|
6098
|
+
}
|
|
6076
6099
|
|
|
6077
|
-
|
|
6078
|
-
addRequestLog(requestNode, {
|
|
6079
|
-
type: "debug",
|
|
6080
|
-
value: `response push ignored because ${canPushStream.reason}`
|
|
6081
|
-
});
|
|
6082
|
-
return;
|
|
6083
|
-
}
|
|
6100
|
+
const canPushStream = testCanPushStream(nodeResponse.stream);
|
|
6084
6101
|
|
|
6085
|
-
|
|
6102
|
+
if (!canPushStream.can) {
|
|
6103
|
+
addRequestLog(requestNode, {
|
|
6104
|
+
type: "debug",
|
|
6105
|
+
value: `response push ignored because ${canPushStream.reason}`
|
|
6106
|
+
});
|
|
6107
|
+
return;
|
|
6108
|
+
}
|
|
6086
6109
|
|
|
6087
|
-
|
|
6088
|
-
preventedByService = serviceController.getCurrentService();
|
|
6089
|
-
};
|
|
6110
|
+
let preventedByService = null;
|
|
6090
6111
|
|
|
6091
|
-
|
|
6092
|
-
|
|
6093
|
-
|
|
6094
|
-
}, {
|
|
6095
|
-
request,
|
|
6096
|
-
warn,
|
|
6097
|
-
prevent
|
|
6098
|
-
}, () => preventedByService);
|
|
6099
|
-
|
|
6100
|
-
if (preventedByService) {
|
|
6101
|
-
addRequestLog(requestNode, {
|
|
6102
|
-
type: "debug",
|
|
6103
|
-
value: `response push prevented by "${preventedByService.name}" service`
|
|
6104
|
-
});
|
|
6105
|
-
return;
|
|
6106
|
-
}
|
|
6112
|
+
const prevent = () => {
|
|
6113
|
+
preventedByService = serviceController.getCurrentService();
|
|
6114
|
+
};
|
|
6107
6115
|
|
|
6108
|
-
|
|
6109
|
-
|
|
6110
|
-
|
|
6111
|
-
|
|
6112
|
-
|
|
6113
|
-
|
|
6114
|
-
|
|
6115
|
-
|
|
6116
|
-
|
|
6117
|
-
|
|
6118
|
-
|
|
6116
|
+
serviceController.callHooksUntil("onResponsePush", {
|
|
6117
|
+
path,
|
|
6118
|
+
method
|
|
6119
|
+
}, {
|
|
6120
|
+
request,
|
|
6121
|
+
warn,
|
|
6122
|
+
prevent
|
|
6123
|
+
}, () => preventedByService);
|
|
6124
|
+
|
|
6125
|
+
if (preventedByService) {
|
|
6126
|
+
addRequestLog(requestNode, {
|
|
6127
|
+
type: "debug",
|
|
6128
|
+
value: `response push prevented by "${preventedByService.name}" service`
|
|
6119
6129
|
});
|
|
6130
|
+
return;
|
|
6120
6131
|
}
|
|
6121
|
-
|
|
6122
|
-
|
|
6123
|
-
|
|
6132
|
+
|
|
6133
|
+
const requestChildNode = {
|
|
6134
|
+
logs: [],
|
|
6135
|
+
children: []
|
|
6136
|
+
};
|
|
6137
|
+
requestNode.children.push(requestChildNode);
|
|
6138
|
+
await pushResponse({
|
|
6139
|
+
path,
|
|
6140
|
+
method
|
|
6141
|
+
}, {
|
|
6142
|
+
requestNode: requestChildNode,
|
|
6143
|
+
parentHttp2Stream: nodeResponse.stream
|
|
6144
|
+
});
|
|
6145
|
+
}
|
|
6146
|
+
});
|
|
6147
|
+
|
|
6148
|
+
try {
|
|
6149
|
+
handleRequestReturnValue = await Promise.race([timeoutPromise, handleRequestPromise]);
|
|
6150
|
+
} catch (e) {
|
|
6151
|
+
errorWhileHandlingRequest = e;
|
|
6124
6152
|
}
|
|
6125
6153
|
|
|
6154
|
+
clearTimeout(timeout);
|
|
6126
6155
|
let responseProperties;
|
|
6127
6156
|
|
|
6128
6157
|
if (errorWhileHandlingRequest) {
|
|
6129
6158
|
if (errorWhileHandlingRequest.name === "AbortError" && request.signal.aborted) {
|
|
6130
|
-
responseProperties =
|
|
6159
|
+
responseProperties = {
|
|
6160
|
+
requestAborted: true
|
|
6161
|
+
};
|
|
6131
6162
|
} else {
|
|
6132
6163
|
// internal error, create 500 response
|
|
6133
6164
|
if ( // stopOnInternalError stops server only if requestToResponse generated
|
|
@@ -6237,7 +6268,7 @@ const startServer = async ({
|
|
|
6237
6268
|
await new Promise(resolve => setTimeout(resolve));
|
|
6238
6269
|
}
|
|
6239
6270
|
|
|
6240
|
-
await
|
|
6271
|
+
await writeNodeResponse(responseStream, responseProperties, {
|
|
6241
6272
|
signal,
|
|
6242
6273
|
ignoreBody,
|
|
6243
6274
|
onAbort: () => {
|
|
@@ -6348,7 +6379,8 @@ const startServer = async ({
|
|
|
6348
6379
|
});
|
|
6349
6380
|
const request = fromNodeRequest(nodeRequest, {
|
|
6350
6381
|
serverOrigin: websocketOrigin,
|
|
6351
|
-
signal: new AbortController().signal
|
|
6382
|
+
signal: new AbortController().signal,
|
|
6383
|
+
requestBodyLifetime
|
|
6352
6384
|
});
|
|
6353
6385
|
serviceController.callAsyncHooksUntil("handleWebsocket", websocket, {
|
|
6354
6386
|
request
|
|
@@ -6456,7 +6488,6 @@ const testCanPushStream = http2Stream => {
|
|
|
6456
6488
|
};
|
|
6457
6489
|
};
|
|
6458
6490
|
|
|
6459
|
-
const ABORTED_RESPONSE_PROPERTIES = {};
|
|
6460
6491
|
const PROCESS_TEARDOWN_EVENTS_MAP = {
|
|
6461
6492
|
SIGHUP: STOP_REASON_PROCESS_SIGHUP,
|
|
6462
6493
|
SIGTERM: STOP_REASON_PROCESS_SIGTERM,
|
|
@@ -19843,7 +19874,7 @@ const jsenvPluginUrlResolution = ({
|
|
|
19843
19874
|
|
|
19844
19875
|
let urlType;
|
|
19845
19876
|
|
|
19846
|
-
if (reference.
|
|
19877
|
+
if (reference.injected) {
|
|
19847
19878
|
urlType = reference.expectedType;
|
|
19848
19879
|
} else {
|
|
19849
19880
|
const parentUrlInfo = context.urlGraph.getUrlInfo(reference.parentUrl);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jsenv/core",
|
|
3
|
-
"version": "29.1.
|
|
3
|
+
"version": "29.1.6",
|
|
4
4
|
"description": "Tool to develop, test and build js projects",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": {
|
|
@@ -73,7 +73,7 @@
|
|
|
73
73
|
"@jsenv/integrity": "0.0.1",
|
|
74
74
|
"@jsenv/log": "3.3.0",
|
|
75
75
|
"@jsenv/node-esm-resolution": "0.1.0",
|
|
76
|
-
"@jsenv/server": "14.1.
|
|
76
|
+
"@jsenv/server": "14.1.5",
|
|
77
77
|
"@jsenv/sourcemap": "1.0.5",
|
|
78
78
|
"@jsenv/uneval": "1.6.0",
|
|
79
79
|
"@jsenv/url-meta": "7.0.0",
|
|
@@ -102,7 +102,7 @@ export const jsenvPluginUrlResolution = ({
|
|
|
102
102
|
return resolveUrlUsingWebResolution(reference, context)
|
|
103
103
|
}
|
|
104
104
|
let urlType
|
|
105
|
-
if (reference.
|
|
105
|
+
if (reference.injected) {
|
|
106
106
|
urlType = reference.expectedType
|
|
107
107
|
} else {
|
|
108
108
|
const parentUrlInfo = context.urlGraph.getUrlInfo(reference.parentUrl)
|