@jsenv/server 16.4.0 → 17.0.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.
- package/dist/jsenv_server.js +3384 -3214
- package/index.js +12 -9
- package/package.json +1 -1
- package/src/{services/autoreload_on_server_restart/jsenv_service_autoreload_on_server_restart.js → plugins/autoreload_on_server_restart/server_plugin_autoreload_on_server_restart.js} +1 -1
- package/src/{services/cors/jsenv_service_cors.js → plugins/cors/server_plugin_cors.js} +1 -1
- package/src/{services → plugins}/default_body_4xx_5xx/client/4xx.html +1 -1
- package/src/{services/default_body_4xx_5xx/jsenv_service_default_body_4xx_5xx.js → plugins/default_body_4xx_5xx/server_plugin_default_body_4xx_5xx.js} +2 -1
- package/src/{services/error_handler/jsenv_service_error_handler.js → plugins/error_handler/server_plugin_error_handler.js} +1 -1
- package/src/{services/filesystem/jsenv_service_static_files.js → plugins/filesystem/server_plugin_static_files.js} +2 -2
- package/src/{services/internal_client_files/jsenv_service_internal_client_files.js → plugins/internal_client_files/server_plugin_internal_client_files.js} +1 -1
- package/src/{services/open_file/jsenv_service_open_file.js → plugins/open_file/server_plugin_open_file.js} +1 -1
- package/src/{services/request_aliases/jsenv_service_request_aliases.js → plugins/request_aliases/server_plugin_request_aliases.js} +1 -1
- package/src/{services/response_acceptance_check/jsenv_service_response_acceptance_check.js → plugins/response_acceptance_check/server_plugin_response_acceptance_check.js} +1 -1
- package/src/{services → plugins}/route_inspector/client/route_inspector.html +2 -2
- package/src/{services/route_inspector/jsenv_service_route_inspector.js → plugins/route_inspector/server_plugin_route_inspector.js} +1 -1
- package/src/plugins/server_plugins_controller.js +21 -0
- package/src/plugins_controller.js +341 -0
- package/src/router/router.js +8 -5
- package/src/start_server.js +34 -38
- package/src/service_controller.js +0 -193
- /package/src/{services → plugins}/autoreload_on_server_restart/client/autoreload_on_server_restart.js +0 -0
- /package/src/{services → plugins}/error_handler/client/500.html +0 -0
- /package/src/{services → plugins}/filesystem/etag.js +0 -0
- /package/src/{services → plugins}/filesystem/fetch_filesystem.js +0 -0
- /package/src/{services → plugins}/filesystem/filesystem_error_to_response.js +0 -0
- /package/src/{services → plugins}/filesystem/filesystem_path_and_url.js +0 -0
- /package/src/{services → plugins}/filesystem/serve_directory.js +0 -0
- /package/src/{services → plugins}/route_inspector/client/code_block.js +0 -0
- /package/src/{stopReasons.js → stop_reasons.js} +0 -0
package/src/start_server.js
CHANGED
|
@@ -23,17 +23,14 @@ import { composeTwoResponses } from "./internal/response_composition.js";
|
|
|
23
23
|
import { createPolyglotServer } from "./internal/server-polyglot.js";
|
|
24
24
|
import { trackServerPendingConnections } from "./internal/trackServerPendingConnections.js";
|
|
25
25
|
import { trackServerPendingRequests } from "./internal/trackServerPendingRequests.js";
|
|
26
|
+
import { serverPluginAutoreloadOnRestart } from "./plugins/autoreload_on_server_restart/server_plugin_autoreload_on_server_restart.js";
|
|
27
|
+
import { serverPluginDefaultBody4xx5xx } from "./plugins/default_body_4xx_5xx/server_plugin_default_body_4xx_5xx.js";
|
|
28
|
+
import { serverPluginInternalClientFiles } from "./plugins/internal_client_files/server_plugin_internal_client_files.js";
|
|
29
|
+
import { serverPluginOpenFile } from "./plugins/open_file/server_plugin_open_file.js";
|
|
30
|
+
import { serverPluginRouteInspector } from "./plugins/route_inspector/server_plugin_route_inspector.js";
|
|
31
|
+
import { createServerPluginsController } from "./plugins/server_plugins_controller.js";
|
|
26
32
|
import { createRouter } from "./router/router.js";
|
|
27
33
|
import { timingToServerTimingResponseHeaders } from "./server_timing/timing_header.js";
|
|
28
|
-
import {
|
|
29
|
-
createServiceController,
|
|
30
|
-
flattenAndFilterServices,
|
|
31
|
-
} from "./service_controller.js";
|
|
32
|
-
import { jsenvServiceAutoreloadOnRestart } from "./services/autoreload_on_server_restart/jsenv_service_autoreload_on_server_restart.js";
|
|
33
|
-
import { jsenvServiceDefaultBody4xx5xx } from "./services/default_body_4xx_5xx/jsenv_service_default_body_4xx_5xx.js";
|
|
34
|
-
import { jsenvServiceInternalClientFiles } from "./services/internal_client_files/jsenv_service_internal_client_files.js";
|
|
35
|
-
import { jsenvServiceOpenFile } from "./services/open_file/jsenv_service_open_file.js";
|
|
36
|
-
import { jsenvServiceRouteInspector } from "./services/route_inspector/jsenv_service_route_inspector.js";
|
|
37
34
|
import {
|
|
38
35
|
STOP_REASON_INTERNAL_ERROR,
|
|
39
36
|
STOP_REASON_NOT_SPECIFIED,
|
|
@@ -42,7 +39,7 @@ import {
|
|
|
42
39
|
STOP_REASON_PROCESS_SIGHUP,
|
|
43
40
|
STOP_REASON_PROCESS_SIGINT,
|
|
44
41
|
STOP_REASON_PROCESS_SIGTERM,
|
|
45
|
-
} from "./
|
|
42
|
+
} from "./stop_reasons.js";
|
|
46
43
|
import { getWebSocketHandler } from "./web_socket_response.js";
|
|
47
44
|
|
|
48
45
|
import { applyDnsResolution } from "./internal/dns_resolution.js";
|
|
@@ -81,7 +78,7 @@ export const startServer = async ({
|
|
|
81
78
|
stopOnInternalError = false,
|
|
82
79
|
keepProcessAlive = true,
|
|
83
80
|
routes = [],
|
|
84
|
-
|
|
81
|
+
plugins = [],
|
|
85
82
|
nagle = true,
|
|
86
83
|
serverTiming = false,
|
|
87
84
|
requestWaitingMs = 0,
|
|
@@ -155,25 +152,26 @@ export const startServer = async ({
|
|
|
155
152
|
}
|
|
156
153
|
}
|
|
157
154
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
...
|
|
155
|
+
plugins = [
|
|
156
|
+
serverPluginOpenFile(),
|
|
157
|
+
serverPluginDefaultBody4xx5xx(),
|
|
158
|
+
serverPluginRouteInspector(),
|
|
159
|
+
serverPluginInternalClientFiles(),
|
|
160
|
+
serverPluginAutoreloadOnRestart(),
|
|
161
|
+
...plugins,
|
|
165
162
|
];
|
|
166
163
|
|
|
164
|
+
const serverPluginsController = await createServerPluginsController(plugins);
|
|
167
165
|
const allRouteArray = [];
|
|
168
166
|
for (const route of routes) {
|
|
169
167
|
allRouteArray.push(route);
|
|
170
168
|
}
|
|
171
|
-
for (const
|
|
172
|
-
const
|
|
173
|
-
if (
|
|
174
|
-
for (const
|
|
175
|
-
|
|
176
|
-
allRouteArray.push(
|
|
169
|
+
for (const serverPlugin of serverPluginsController.activePlugins) {
|
|
170
|
+
const routes = serverPlugin.routes;
|
|
171
|
+
if (routes) {
|
|
172
|
+
for (const route of routes) {
|
|
173
|
+
route.serverPlugin = serverPlugin;
|
|
174
|
+
allRouteArray.push(route);
|
|
177
175
|
}
|
|
178
176
|
}
|
|
179
177
|
}
|
|
@@ -184,8 +182,6 @@ export const startServer = async ({
|
|
|
184
182
|
});
|
|
185
183
|
|
|
186
184
|
const server = {};
|
|
187
|
-
|
|
188
|
-
const serviceController = createServiceController(services);
|
|
189
185
|
const processTeardownEvents = {
|
|
190
186
|
SIGHUP: stopOnExit,
|
|
191
187
|
SIGTERM: stopOnExit,
|
|
@@ -296,7 +292,7 @@ export const startServer = async ({
|
|
|
296
292
|
serverOrigins[key] = new URL(`${serverOrigins[key]}:${port}`).origin;
|
|
297
293
|
});
|
|
298
294
|
|
|
299
|
-
|
|
295
|
+
serverPluginsController.callHooks("serverListening", { port });
|
|
300
296
|
startServerOperation.addAbortCallback(async () => {
|
|
301
297
|
await stopListening(nodeServer);
|
|
302
298
|
});
|
|
@@ -341,7 +337,7 @@ export const startServer = async ({
|
|
|
341
337
|
}
|
|
342
338
|
stopCallbackSet.clear();
|
|
343
339
|
await Promise.all(promises);
|
|
344
|
-
|
|
340
|
+
serverPluginsController.callHooks("serverStopped", { reason });
|
|
345
341
|
status = "stopped";
|
|
346
342
|
stoppedResolve(reason);
|
|
347
343
|
});
|
|
@@ -396,7 +392,7 @@ export const startServer = async ({
|
|
|
396
392
|
});
|
|
397
393
|
|
|
398
394
|
const applyRequestInternalRedirection = (request) => {
|
|
399
|
-
|
|
395
|
+
serverPluginsController.callHooks(
|
|
400
396
|
"redirectRequest",
|
|
401
397
|
request,
|
|
402
398
|
{},
|
|
@@ -501,7 +497,7 @@ export const startServer = async ({
|
|
|
501
497
|
headersToInject,
|
|
502
498
|
);
|
|
503
499
|
}
|
|
504
|
-
|
|
500
|
+
serverPluginsController.callHooks(
|
|
505
501
|
"injectResponseProperties",
|
|
506
502
|
request,
|
|
507
503
|
responseProperties,
|
|
@@ -559,7 +555,7 @@ export const startServer = async ({
|
|
|
559
555
|
);
|
|
560
556
|
},
|
|
561
557
|
};
|
|
562
|
-
await
|
|
558
|
+
await serverPluginsController.callAsyncHooks(
|
|
563
559
|
"augmentRouteFetchSecondArg",
|
|
564
560
|
request,
|
|
565
561
|
fetchSecondArg,
|
|
@@ -599,7 +595,7 @@ export const startServer = async ({
|
|
|
599
595
|
stop(STOP_REASON_INTERNAL_ERROR);
|
|
600
596
|
}
|
|
601
597
|
const handleErrorReturnValue =
|
|
602
|
-
await
|
|
598
|
+
await serverPluginsController.callAsyncHooksUntil("handleError", e, {
|
|
603
599
|
request,
|
|
604
600
|
});
|
|
605
601
|
if (!handleErrorReturnValue) {
|
|
@@ -718,19 +714,19 @@ export const startServer = async ({
|
|
|
718
714
|
return;
|
|
719
715
|
}
|
|
720
716
|
|
|
721
|
-
let
|
|
717
|
+
let preventedByPlugin = null;
|
|
722
718
|
const prevent = () => {
|
|
723
|
-
|
|
719
|
+
preventedByPlugin = serverPluginsController.getCurrentPlugin();
|
|
724
720
|
};
|
|
725
|
-
|
|
721
|
+
serverPluginsController.callHooksUntil(
|
|
726
722
|
"onResponsePush",
|
|
727
723
|
{ path, method },
|
|
728
724
|
{ request, prevent },
|
|
729
|
-
() =>
|
|
725
|
+
() => preventedByPlugin,
|
|
730
726
|
);
|
|
731
|
-
if (
|
|
727
|
+
if (preventedByPlugin) {
|
|
732
728
|
pushRequestLogger.debug(
|
|
733
|
-
`response push prevented by "${
|
|
729
|
+
`response push prevented by "${preventedByPlugin.name}" plugin`,
|
|
734
730
|
);
|
|
735
731
|
return;
|
|
736
732
|
}
|
|
@@ -1,193 +0,0 @@
|
|
|
1
|
-
const HOOK_NAMES = [
|
|
2
|
-
"serverListening",
|
|
3
|
-
"redirectRequest",
|
|
4
|
-
"augmentRouteFetchSecondArg",
|
|
5
|
-
"routes",
|
|
6
|
-
"handleError",
|
|
7
|
-
"onResponsePush",
|
|
8
|
-
"injectResponseProperties",
|
|
9
|
-
"serverStopped",
|
|
10
|
-
];
|
|
11
|
-
|
|
12
|
-
export const createServiceController = (services) => {
|
|
13
|
-
const hookSetMap = new Map();
|
|
14
|
-
|
|
15
|
-
const addHook = (hook) => {
|
|
16
|
-
let hookSet = hookSetMap.get(hook.name);
|
|
17
|
-
if (!hookSet) {
|
|
18
|
-
hookSet = new Set();
|
|
19
|
-
hookSetMap.set(hook.name, hookSet);
|
|
20
|
-
}
|
|
21
|
-
hookSet.add(hook);
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
const addService = (service) => {
|
|
25
|
-
for (const key of Object.keys(service)) {
|
|
26
|
-
if (key === "name") continue;
|
|
27
|
-
const isHook = HOOK_NAMES.includes(key);
|
|
28
|
-
if (!isHook) {
|
|
29
|
-
console.warn(
|
|
30
|
-
`Unexpected "${key}" property on "${service.name}" service`,
|
|
31
|
-
);
|
|
32
|
-
}
|
|
33
|
-
const hookName = key;
|
|
34
|
-
const hookValue = service[hookName];
|
|
35
|
-
if (!hookValue) {
|
|
36
|
-
continue;
|
|
37
|
-
}
|
|
38
|
-
if (hookName === "routes") {
|
|
39
|
-
} else {
|
|
40
|
-
addHook({
|
|
41
|
-
service,
|
|
42
|
-
name: hookName,
|
|
43
|
-
value: hookValue,
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
for (const service of services) {
|
|
50
|
-
addService(service);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
let currentService = null;
|
|
54
|
-
let currentHookName = null;
|
|
55
|
-
const callHook = (hook, info, context) => {
|
|
56
|
-
const hookFn = getHookFunction(hook, info);
|
|
57
|
-
if (!hookFn) {
|
|
58
|
-
return null;
|
|
59
|
-
}
|
|
60
|
-
currentService = hook.service;
|
|
61
|
-
currentHookName = hook.name;
|
|
62
|
-
let valueReturned = hookFn(info, context);
|
|
63
|
-
currentService = null;
|
|
64
|
-
currentHookName = null;
|
|
65
|
-
return valueReturned;
|
|
66
|
-
};
|
|
67
|
-
const callAsyncHook = async (hook, info, context) => {
|
|
68
|
-
const hookFn = getHookFunction(hook, info);
|
|
69
|
-
if (!hookFn) {
|
|
70
|
-
return null;
|
|
71
|
-
}
|
|
72
|
-
currentService = hook.service;
|
|
73
|
-
currentHookName = hook.name;
|
|
74
|
-
let valueReturned = await hookFn(info, context);
|
|
75
|
-
currentService = null;
|
|
76
|
-
currentHookName = null;
|
|
77
|
-
return valueReturned;
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
const callHooks = (hookName, info, context, callback = () => {}) => {
|
|
81
|
-
const hookSet = hookSetMap.get(hookName);
|
|
82
|
-
if (!hookSet) {
|
|
83
|
-
return;
|
|
84
|
-
}
|
|
85
|
-
for (const hook of hookSet) {
|
|
86
|
-
const returnValue = callHook(hook, info, context);
|
|
87
|
-
if (returnValue) {
|
|
88
|
-
callback(returnValue);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
};
|
|
92
|
-
const callAsyncHooks = async (hookName, info, context, callback) => {
|
|
93
|
-
const hookSet = hookSetMap.get(hookName);
|
|
94
|
-
if (!hookSet) {
|
|
95
|
-
return;
|
|
96
|
-
}
|
|
97
|
-
for (const hook of hookSet) {
|
|
98
|
-
const returnValue = await callAsyncHook(hook, info, context);
|
|
99
|
-
if (returnValue && callback) {
|
|
100
|
-
await callback(returnValue, hook.plugin);
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
};
|
|
104
|
-
const callHooksUntil = (
|
|
105
|
-
hookName,
|
|
106
|
-
info,
|
|
107
|
-
context,
|
|
108
|
-
until = (returnValue) => returnValue,
|
|
109
|
-
) => {
|
|
110
|
-
const hookSet = hookSetMap.get(hookName);
|
|
111
|
-
if (!hookSet) {
|
|
112
|
-
return null;
|
|
113
|
-
}
|
|
114
|
-
for (const hook of hookSet) {
|
|
115
|
-
const returnValue = callHook(hook, info, context);
|
|
116
|
-
const untilReturnValue = until(returnValue);
|
|
117
|
-
if (untilReturnValue) {
|
|
118
|
-
return untilReturnValue;
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
return null;
|
|
122
|
-
};
|
|
123
|
-
const callAsyncHooksUntil = async (hookName, info, context) => {
|
|
124
|
-
const hookSet = hookSetMap.get(hookName);
|
|
125
|
-
if (!hookSet) {
|
|
126
|
-
return null;
|
|
127
|
-
}
|
|
128
|
-
if (hookSet.size === 0) {
|
|
129
|
-
return null;
|
|
130
|
-
}
|
|
131
|
-
const iterator = hookSet.values()[Symbol.iterator]();
|
|
132
|
-
let result;
|
|
133
|
-
const visit = async () => {
|
|
134
|
-
const { done, value: hook } = iterator.next();
|
|
135
|
-
if (done) {
|
|
136
|
-
return;
|
|
137
|
-
}
|
|
138
|
-
const returnValue = await callAsyncHook(hook, info, context);
|
|
139
|
-
if (returnValue) {
|
|
140
|
-
result = returnValue;
|
|
141
|
-
return;
|
|
142
|
-
}
|
|
143
|
-
await visit();
|
|
144
|
-
};
|
|
145
|
-
await visit();
|
|
146
|
-
return result;
|
|
147
|
-
};
|
|
148
|
-
|
|
149
|
-
return {
|
|
150
|
-
services,
|
|
151
|
-
|
|
152
|
-
callHooks,
|
|
153
|
-
callHooksUntil,
|
|
154
|
-
callAsyncHooks,
|
|
155
|
-
callAsyncHooksUntil,
|
|
156
|
-
|
|
157
|
-
getCurrentService: () => currentService,
|
|
158
|
-
getCurrentHookName: () => currentHookName,
|
|
159
|
-
};
|
|
160
|
-
};
|
|
161
|
-
|
|
162
|
-
const getHookFunction = (hook, info) => {
|
|
163
|
-
const hookValue = hook.value;
|
|
164
|
-
if (hook.name === "handleRequest" && typeof hookValue === "object") {
|
|
165
|
-
const request = info;
|
|
166
|
-
const hookForMethod = hookValue[request.method] || hookValue["*"];
|
|
167
|
-
if (!hookForMethod) {
|
|
168
|
-
return null;
|
|
169
|
-
}
|
|
170
|
-
return hookForMethod;
|
|
171
|
-
}
|
|
172
|
-
return hookValue;
|
|
173
|
-
};
|
|
174
|
-
|
|
175
|
-
export const flattenAndFilterServices = (services) => {
|
|
176
|
-
const flatServices = [];
|
|
177
|
-
const visitServiceEntry = (serviceEntry) => {
|
|
178
|
-
if (Array.isArray(serviceEntry)) {
|
|
179
|
-
serviceEntry.forEach((value) => visitServiceEntry(value));
|
|
180
|
-
return;
|
|
181
|
-
}
|
|
182
|
-
if (typeof serviceEntry === "object" && serviceEntry !== null) {
|
|
183
|
-
if (!serviceEntry.name) {
|
|
184
|
-
serviceEntry.name = "anonymous";
|
|
185
|
-
}
|
|
186
|
-
flatServices.push(serviceEntry);
|
|
187
|
-
return;
|
|
188
|
-
}
|
|
189
|
-
throw new Error(`services must be objects, got ${serviceEntry}`);
|
|
190
|
-
};
|
|
191
|
-
services.forEach((serviceEntry) => visitServiceEntry(serviceEntry));
|
|
192
|
-
return flatServices;
|
|
193
|
-
};
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|