@jsenv/server 16.0.6 → 16.0.8

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.
@@ -121,6 +121,9 @@
121
121
  };
122
122
 
123
123
  const initialWebSocket = await connect();
124
+ if (!initialWebSocket) {
125
+ return;
126
+ }
124
127
  initialWebSocket.onclose = async () => {
125
128
  console.info("connection to server lost, trying to reconnect");
126
129
  const retry = async () => {
@@ -165,12 +168,16 @@
165
168
  );
166
169
  }
167
170
 
171
+ const websocketEndpoint =
172
+ document.currentScript.getAttribute("data-ws-endpoint") ||
173
+ "/.internal/alive.websocket";
174
+
168
175
  const jsenvAutoreloadOnServerRestartElement =
169
176
  new JsenvAutoreloadOnServerRestart({
170
177
  url: (() => {
171
178
  const websocketScheme =
172
179
  self.location.protocol === "https:" ? "wss" : "ws";
173
- const websocketUrl = `${websocketScheme}://${self.location.host}/.internal/alive.websocket`;
180
+ const websocketUrl = `${websocketScheme}://${self.location.host}${websocketEndpoint}`;
174
181
  return websocketUrl;
175
182
  })(),
176
183
  });
@@ -278,6 +278,9 @@
278
278
  };
279
279
 
280
280
  const initialWebSocket = await connect();
281
+ if (!initialWebSocket) {
282
+ return;
283
+ }
281
284
  initialWebSocket.onclose = async () => {
282
285
  console.info("connection to server lost, trying to reconnect");
283
286
  const retry = async () => {
@@ -322,12 +325,16 @@
322
325
  );
323
326
  }
324
327
 
328
+ const websocketEndpoint =
329
+ document.currentScript.getAttribute("data-ws-endpoint") ||
330
+ "/.internal/alive.websocket";
331
+
325
332
  const jsenvAutoreloadOnServerRestartElement =
326
333
  new JsenvAutoreloadOnServerRestart({
327
334
  url: (() => {
328
335
  const websocketScheme =
329
336
  self.location.protocol === "https:" ? "wss" : "ws";
330
- const websocketUrl = `${websocketScheme}://${self.location.host}/.internal/alive.websocket`;
337
+ const websocketUrl = `${websocketScheme}://${self.location.host}${websocketEndpoint}`;
331
338
  return websocketUrl;
332
339
  })(),
333
340
  });
@@ -551,6 +551,29 @@ ${
551
551
  return text;
552
552
  };
553
553
 
554
+ const errorToHTML = (error) => {
555
+ const errorIsAPrimitive =
556
+ error === null ||
557
+ (typeof error !== "object" && typeof error !== "function");
558
+
559
+ if (errorIsAPrimitive) {
560
+ if (typeof error === "string") {
561
+ return `<pre>${escapeHtml(error)}</pre>`;
562
+ }
563
+ return `<pre>${JSON.stringify(error, null, " ")}</pre>`;
564
+ }
565
+ return `<pre>${escapeHtml(error.stack)}</pre>`;
566
+ };
567
+
568
+ const escapeHtml = (string) => {
569
+ return string
570
+ .replace(/&/g, "&amp;")
571
+ .replace(/</g, "&lt;")
572
+ .replace(/>/g, "&gt;")
573
+ .replace(/"/g, "&quot;")
574
+ .replace(/'/g, "&#039;");
575
+ };
576
+
554
577
  const LOG_LEVEL_OFF = "off";
555
578
 
556
579
  const LOG_LEVEL_DEBUG = "debug";
@@ -3166,8 +3189,11 @@ const getParentDirectoryUrl = (url) => {
3166
3189
  return new URL(url.endsWith("/") ? "../" : "./", url).href;
3167
3190
  };
3168
3191
 
3169
- const findAncestorDirectoryUrl = (url, callback) => {
3192
+ const findSelfOrAncestorDirectoryUrl = (url, callback) => {
3170
3193
  url = String(url);
3194
+ if (!url.endsWith("/")) {
3195
+ url = new URL("./", url).href;
3196
+ }
3171
3197
  while (url !== "file:///") {
3172
3198
  if (callback(url)) {
3173
3199
  return url;
@@ -3178,7 +3204,7 @@ const findAncestorDirectoryUrl = (url, callback) => {
3178
3204
  };
3179
3205
 
3180
3206
  const lookupPackageDirectory = (currentUrl) => {
3181
- return findAncestorDirectoryUrl(currentUrl, (ancestorDirectoryUrl) => {
3207
+ return findSelfOrAncestorDirectoryUrl(currentUrl, (ancestorDirectoryUrl) => {
3182
3208
  const potentialPackageJsonFileUrl = `${ancestorDirectoryUrl}package.json`;
3183
3209
  return existsSync(new URL(potentialPackageJsonFileUrl));
3184
3210
  });
@@ -7477,14 +7503,7 @@ const jsenvServiceErrorHandler = ({ sendErrorDetails = false } = {}) => {
7477
7503
  return `<p>Details not available: to enable them use jsenvServiceErrorHandler({ sendErrorDetails: true }).</p>`;
7478
7504
  };
7479
7505
  const renderHtmlForErrorWithDetails = () => {
7480
- if (serverInternalErrorIsAPrimitive) {
7481
- return `<pre>${JSON.stringify(
7482
- serverInternalError,
7483
- null,
7484
- " ",
7485
- )}</pre>`;
7486
- }
7487
- return `<pre>${serverInternalError.stack}</pre>`;
7506
+ return errorToHTML(serverInternalError);
7488
7507
  };
7489
7508
 
7490
7509
  const internalErrorHtmlTemplate = readFileSync(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsenv/server",
3
- "version": "16.0.6",
3
+ "version": "16.0.8",
4
4
  "description": "A modern Node.js HTTP server with declarative routing, content negotiation, and WebSocket support",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -33,7 +33,9 @@
33
33
  "/dist/",
34
34
  "/src/"
35
35
  ],
36
- "sideEffects": false,
36
+ "sideEffects": [
37
+ "./dist/jsenv_server_node_modules.js"
38
+ ],
37
39
  "scripts": {
38
40
  "build": "node --experimental-import-meta-resolve ./scripts/build.mjs",
39
41
  "prepublishOnly": "npm run build"
@@ -41,14 +43,14 @@
41
43
  "dependencies": {
42
44
  "launch-editor": "2.10.0",
43
45
  "@jsenv/abort": "4.3.1",
44
- "@jsenv/humanize": "1.4.0",
46
+ "@jsenv/humanize": "1.5.0",
45
47
  "@jsenv/url-meta": "8.5.6",
46
48
  "@jsenv/utils": "2.3.0",
47
49
  "ws": "8.18.1",
48
50
  "formidable": "3.5.2"
49
51
  },
50
52
  "devDependencies": {
51
- "eventsource": "3.0.5",
52
- "undici": "7.5.0"
53
+ "eventsource": "3.0.6",
54
+ "undici": "7.8.0"
53
55
  }
54
56
  }
@@ -53,6 +53,9 @@ class JsenvAutoreloadOnServerRestart extends HTMLElement {
53
53
  };
54
54
 
55
55
  const initialWebSocket = await connect();
56
+ if (!initialWebSocket) {
57
+ return;
58
+ }
56
59
  initialWebSocket.onclose = async () => {
57
60
  console.info("connection to server lost, trying to reconnect");
58
61
  const retry = async () => {
@@ -97,12 +100,16 @@ if (!customElements.get("jsenv-autoreload-on-server-restart")) {
97
100
  );
98
101
  }
99
102
 
103
+ const websocketEndpoint =
104
+ document.currentScript.getAttribute("data-ws-endpoint") ||
105
+ "/.internal/alive.websocket";
106
+
100
107
  const jsenvAutoreloadOnServerRestartElement =
101
108
  new JsenvAutoreloadOnServerRestart({
102
109
  url: (() => {
103
110
  const websocketScheme =
104
111
  self.location.protocol === "https:" ? "wss" : "ws";
105
- const websocketUrl = `${websocketScheme}://${self.location.host}/.internal/alive.websocket`;
112
+ const websocketUrl = `${websocketScheme}://${self.location.host}${websocketEndpoint}`;
106
113
  return websocketUrl;
107
114
  })(),
108
115
  });
@@ -1,3 +1,4 @@
1
+ import { errorToHTML } from "@jsenv/humanize";
1
2
  import { readFileSync } from "node:fs";
2
3
  import { pickContentType } from "../../content_negotiation/pick_content_type.js";
3
4
  import { replacePlaceholdersInHtml } from "../../replace_placeholder_in_html.js";
@@ -36,14 +37,7 @@ export const jsenvServiceErrorHandler = ({ sendErrorDetails = false } = {}) => {
36
37
  return `<p>Details not available: to enable them use jsenvServiceErrorHandler({ sendErrorDetails: true }).</p>`;
37
38
  };
38
39
  const renderHtmlForErrorWithDetails = () => {
39
- if (serverInternalErrorIsAPrimitive) {
40
- return `<pre>${JSON.stringify(
41
- serverInternalError,
42
- null,
43
- " ",
44
- )}</pre>`;
45
- }
46
- return `<pre>${serverInternalError.stack}</pre>`;
40
+ return errorToHTML(serverInternalError);
47
41
  };
48
42
 
49
43
  const internalErrorHtmlTemplate = readFileSync(