@jsenv/server 12.2.1 → 12.3.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.
Files changed (2) hide show
  1. package/package.json +13 -13
  2. package/src/startServer.js +80 -55
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsenv/server",
3
- "version": "12.2.1",
3
+ "version": "12.3.0",
4
4
  "description": "Write your Node.js server using pure functions",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -13,7 +13,7 @@
13
13
  "url": "https://github.com/jsenv/server"
14
14
  },
15
15
  "engines": {
16
- "node": ">=16.12.0"
16
+ "node": ">=16.13.0"
17
17
  },
18
18
  "publishConfig": {
19
19
  "access": "public"
@@ -38,33 +38,33 @@
38
38
  "test-with-coverage": "npm run test -- --coverage",
39
39
  "generate-html-snapshots": "node ./test/internal_error/generate_html_snapshot_files.mjs",
40
40
  "prettier": "prettier --write .",
41
- "certificate-authority-install": "node ./script/certificate/certificate_authority_install.mjs",
41
+ "certificate-install": "node ./script/certificate/certificate_install.mjs",
42
42
  "playwright-install": "npx playwright install-deps && npx playwright install"
43
43
  },
44
44
  "dependencies": {
45
45
  "@jsenv/abort": "4.1.2",
46
46
  "@jsenv/logger": "4.0.1",
47
- "@jsenv/url-meta": "6.0.1",
47
+ "@jsenv/url-meta": "6.0.3",
48
48
  "node-fetch": "2.6.2",
49
49
  "path-to-regexp": "6.2.0"
50
50
  },
51
51
  "devDependencies": {
52
- "@jsenv/assert": "2.4.0",
53
- "@jsenv/core": "24.5.0",
52
+ "@jsenv/assert": "2.4.1",
53
+ "@jsenv/core": "25.1.0",
54
54
  "@jsenv/eslint-config": "16.0.9",
55
- "@jsenv/filesystem": "2.6.0",
55
+ "@jsenv/filesystem": "2.6.1",
56
56
  "@jsenv/github-release-package": "1.2.3",
57
57
  "@jsenv/https-local": "1.0.3",
58
- "@jsenv/importmap-eslint-resolver": "5.2.1",
59
- "@jsenv/importmap-node-module": "4.0.1",
58
+ "@jsenv/importmap-eslint-resolver": "5.2.2",
59
+ "@jsenv/importmap-node-module": "5.1.0",
60
60
  "@jsenv/package-publish": "1.6.2",
61
61
  "@jsenv/performance-impact": "2.2.1",
62
- "eslint": "8.4.1",
63
- "eslint-plugin-import": "2.25.3",
62
+ "eslint": "8.7.0",
63
+ "eslint-plugin-import": "2.25.4",
64
64
  "eventsource": "1.1.0",
65
- "fastify": "3.25.0",
65
+ "fastify": "3.25.3",
66
66
  "fastify-static": "4.5.0",
67
- "playwright": "1.17.1",
67
+ "playwright": "1.17.2",
68
68
  "prettier": "2.5.1"
69
69
  }
70
70
  }
@@ -472,8 +472,8 @@ export const startServer = async ({
472
472
  }
473
473
  }
474
474
  })
475
- let { aborted, error, responseProperties } = responseFromShortcircuit
476
- ? { responseProperties: responseFromShortcircuit }
475
+ const result = responseFromShortcircuit
476
+ ? { returnValue: responseFromShortcircuit }
477
477
  : await generateResponseDescription({
478
478
  requestToResponse,
479
479
  request,
@@ -533,65 +533,60 @@ export const startServer = async ({
533
533
  },
534
534
  })
535
535
 
536
+ const { aborted } = result
536
537
  if (aborted) {
537
538
  return ABORTED_RESPONSE_PROPERTIES
538
539
  }
539
-
540
- // internal error, create 500 response
541
- if (error) {
542
- if (
543
- // stopOnInternalError stops server only if requestToResponse generated
544
- // a non controlled error (internal error).
545
- // if requestToResponse gracefully produced a 500 response (it did not throw)
546
- // then we can assume we are still in control of what we are doing
547
- stopOnInternalError
548
- ) {
549
- // il faudrais pouvoir stop que les autres response ?
550
- stop(STOP_REASON_INTERNAL_ERROR)
551
- }
552
-
553
- const propertiesFromError = await serverInternalErrorToResponse(error, {
554
- request,
555
- sendServerInternalErrorDetails,
556
- })
557
- responseProperties = composeTwoResponses(
558
- {
559
- status: 500,
560
- statusText: statusToStatusText(500),
561
- headers: {
562
- // ensure error are not cached
563
- "cache-control": "no-store",
564
- "content-type": "text/plain",
540
+ const readResponseProperties = async () => {
541
+ const { error } = result
542
+ // internal error, create 500 response
543
+ if (error) {
544
+ if (
545
+ // stopOnInternalError stops server only if requestToResponse generated
546
+ // a non controlled error (internal error).
547
+ // if requestToResponse gracefully produced a 500 response (it did not throw)
548
+ // then we can assume we are still in control of what we are doing
549
+ stopOnInternalError
550
+ ) {
551
+ // il faudrais pouvoir stop que les autres response ?
552
+ stop(STOP_REASON_INTERNAL_ERROR)
553
+ }
554
+ const propertiesFromError = await serverInternalErrorToResponse(
555
+ error,
556
+ {
557
+ request,
558
+ sendServerInternalErrorDetails,
565
559
  },
566
- },
567
- propertiesFromError,
568
- )
569
- addRequestLog(requestNode, {
570
- type: "error",
571
- value: createDetailedMessage(
572
- `internal error while handling request`,
560
+ )
561
+ addRequestLog(requestNode, {
562
+ type: "error",
563
+ value: createDetailedMessage(
564
+ `internal error while handling request`,
565
+ {
566
+ "error stack": error.stack,
567
+ },
568
+ ),
569
+ })
570
+ return composeTwoResponses(
573
571
  {
574
- "error stack": error.stack,
572
+ status: 500,
573
+ statusText: statusToStatusText(500),
574
+ headers: {
575
+ // ensure error are not cached
576
+ "cache-control": "no-store",
577
+ "content-type": "text/plain",
578
+ },
575
579
  },
576
- ),
577
- })
578
- } else {
579
- const {
580
- status = 501,
581
- statusText = statusToStatusText(status),
582
- headers = {},
583
- body,
584
- ...rest
585
- } = responseProperties || {}
586
- responseProperties = {
587
- status,
588
- statusText,
589
- headers,
590
- body,
591
- ...rest,
580
+ propertiesFromError,
581
+ )
592
582
  }
583
+ const responseProperties = normalizeResponseProperties(
584
+ result.returnValue,
585
+ )
586
+ return responseProperties
593
587
  }
594
588
 
589
+ let responseProperties = await readResponseProperties()
595
590
  // call every plugin "onResponse" hook
596
591
  requestPlugins.forEach((requestPlugin) => {
597
592
  const { onResponse } = requestPlugin
@@ -605,7 +600,6 @@ export const startServer = async ({
605
600
  }
606
601
  }
607
602
  })
608
-
609
603
  if (
610
604
  request.method !== "HEAD" &&
611
605
  responseProperties.headers["content-length"] > 0 &&
@@ -616,7 +610,6 @@ export const startServer = async ({
616
610
  value: `content-length header is ${responseProperties.headers["content-length"]} but body is empty`,
617
611
  })
618
612
  }
619
-
620
613
  return responseProperties
621
614
  }
622
615
 
@@ -749,6 +742,38 @@ const createNodeServer = async ({
749
742
  })
750
743
  }
751
744
 
745
+ const normalizeResponseProperties = (returnValue) => {
746
+ if (returnValue && returnValue.constructor.name === "Response") {
747
+ const responseHeaders = {}
748
+ const headersToIgnore = ["connection"]
749
+ returnValue.headers.forEach((value, name) => {
750
+ if (!headersToIgnore.includes(name)) {
751
+ responseHeaders[name] = value
752
+ }
753
+ })
754
+ return {
755
+ status: returnValue.status,
756
+ statusText: returnValue.statusText,
757
+ headers: responseHeaders,
758
+ body: returnValue.body, // node-fetch assumed
759
+ }
760
+ }
761
+ const {
762
+ status = 501,
763
+ statusText = statusToStatusText(status),
764
+ headers = {},
765
+ body,
766
+ ...rest
767
+ } = returnValue || {}
768
+ return {
769
+ status,
770
+ statusText,
771
+ headers,
772
+ body,
773
+ ...rest,
774
+ }
775
+ }
776
+
752
777
  const generateResponseDescription = async ({
753
778
  requestToResponse,
754
779
  request,
@@ -759,7 +784,7 @@ const generateResponseDescription = async ({
759
784
  pushResponse,
760
785
  })
761
786
  return {
762
- responseProperties: returnValue,
787
+ returnValue,
763
788
  }
764
789
  } catch (error) {
765
790
  if (error.name === "AbortError" && request.signal.aborted) {