@jsenv/server 16.0.7 → 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.
@@ -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.7",
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
  }
@@ -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(