@jsenv/server 15.0.2 → 15.0.3

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 (53) hide show
  1. package/README.md +23 -23
  2. package/package.json +3 -3
  3. package/src/content_negotiation/pick_accepted_content.js +13 -13
  4. package/src/content_negotiation/pick_content_encoding.js +25 -25
  5. package/src/content_negotiation/pick_content_language.js +35 -34
  6. package/src/content_negotiation/pick_content_type.js +29 -29
  7. package/src/fetch_filesystem.js +110 -107
  8. package/src/from_fetch_response.js +6 -6
  9. package/src/interfacing_with_node/body.js +22 -22
  10. package/src/interfacing_with_node/observable.js +80 -80
  11. package/src/interfacing_with_node/observable_from_node_stream.js +35 -35
  12. package/src/interfacing_with_node/request_factory.js +26 -26
  13. package/src/interfacing_with_node/write_node_response.js +82 -82
  14. package/src/internal/colorizeResponseStatus.js +26 -26
  15. package/src/internal/convertFileSystemErrorToResponseProperties.js +10 -10
  16. package/src/internal/dns_resolution.js +7 -7
  17. package/src/internal/etag.js +11 -11
  18. package/src/internal/filesystem.js +19 -19
  19. package/src/internal/headersFromObject.js +8 -8
  20. package/src/internal/headersFromString.js +11 -11
  21. package/src/internal/headersToObject.js +5 -5
  22. package/src/internal/headersToString.js +7 -7
  23. package/src/internal/headers_composition.js +9 -9
  24. package/src/internal/hostname_parser.js +9 -9
  25. package/src/internal/listen.js +47 -47
  26. package/src/internal/listenClientError.js +10 -10
  27. package/src/internal/listenEvent.js +5 -5
  28. package/src/internal/listenRequest.js +8 -8
  29. package/src/internal/listenServerConnectionError.js +19 -19
  30. package/src/internal/multiple-header.js +50 -50
  31. package/src/internal/normalizeHeaderName.js +4 -4
  32. package/src/internal/normalizeHeaderValue.js +2 -2
  33. package/src/internal/object_composition.js +41 -39
  34. package/src/internal/response_composition.js +6 -6
  35. package/src/internal/server-polyglot.js +42 -42
  36. package/src/internal/server_ips.js +20 -20
  37. package/src/internal/trackServerPendingConnections.js +23 -23
  38. package/src/internal/trackServerPendingRequests.js +28 -28
  39. package/src/main.js +18 -18
  40. package/src/readRequestBody.js +15 -15
  41. package/src/serve_directory.js +16 -16
  42. package/src/server_timing/timing_header.js +24 -24
  43. package/src/server_timing/timing_measure.js +14 -14
  44. package/src/service_composition/path_to_regexp.js +173 -168
  45. package/src/service_composition/routing.js +12 -12
  46. package/src/service_controller.js +77 -77
  47. package/src/services/cors/jsenv_service_cors.js +29 -29
  48. package/src/services/error_handler/jsenv_service_error_handler.js +18 -18
  49. package/src/services/request_aliases/jsenv_service_request_aliases.js +20 -20
  50. package/src/services/response_acceptance_check/jsenv_service_response_acceptance_check.js +16 -16
  51. package/src/sse/sse_room.js +117 -115
  52. package/src/start_server.js +328 -328
  53. package/src/stopReasons.js +9 -9
@@ -1,10 +1,10 @@
1
1
  if ("observable" in Symbol === false) {
2
- Symbol.observable = Symbol.for("observable")
2
+ Symbol.observable = Symbol.for("observable");
3
3
  }
4
4
 
5
5
  export const createObservable = (producer) => {
6
6
  if (typeof producer !== "function") {
7
- throw new TypeError(`producer must be a function, got ${producer}`)
7
+ throw new TypeError(`producer must be a function, got ${producer}`);
8
8
  }
9
9
 
10
10
  const observable = {
@@ -12,160 +12,160 @@ export const createObservable = (producer) => {
12
12
  subscribe: ({
13
13
  next = () => {},
14
14
  error = (value) => {
15
- throw value
15
+ throw value;
16
16
  },
17
17
  complete = () => {},
18
18
  }) => {
19
- let cleanup = () => {}
19
+ let cleanup = () => {};
20
20
  const subscription = {
21
21
  closed: false,
22
22
  unsubscribe: () => {
23
- subscription.closed = true
24
- cleanup()
23
+ subscription.closed = true;
24
+ cleanup();
25
25
  },
26
- }
26
+ };
27
27
 
28
28
  const producerReturnValue = producer({
29
29
  next: (value) => {
30
- if (subscription.closed) return
31
- next(value)
30
+ if (subscription.closed) return;
31
+ next(value);
32
32
  },
33
33
  error: (value) => {
34
- if (subscription.closed) return
35
- error(value)
34
+ if (subscription.closed) return;
35
+ error(value);
36
36
  },
37
37
  complete: () => {
38
- if (subscription.closed) return
39
- complete()
38
+ if (subscription.closed) return;
39
+ complete();
40
40
  },
41
- })
41
+ });
42
42
  if (typeof producerReturnValue === "function") {
43
- cleanup = producerReturnValue
43
+ cleanup = producerReturnValue;
44
44
  }
45
- return subscription
45
+ return subscription;
46
46
  },
47
- }
47
+ };
48
48
 
49
- return observable
50
- }
49
+ return observable;
50
+ };
51
51
 
52
52
  export const isObservable = (value) => {
53
53
  if (value === null || value === undefined) {
54
- return false
54
+ return false;
55
55
  }
56
56
 
57
57
  if (typeof value === "object" || typeof value === "function") {
58
- return Symbol.observable in value
58
+ return Symbol.observable in value;
59
59
  }
60
60
 
61
- return false
62
- }
61
+ return false;
62
+ };
63
63
 
64
64
  export const observableFromValue = (value) => {
65
65
  if (isObservable(value)) {
66
- return value
66
+ return value;
67
67
  }
68
68
 
69
69
  return createObservable(({ next, complete }) => {
70
- next(value)
70
+ next(value);
71
71
  const timer = setTimeout(() => {
72
- complete()
73
- })
72
+ complete();
73
+ });
74
74
  return () => {
75
- clearTimeout(timer)
76
- }
77
- })
78
- }
75
+ clearTimeout(timer);
76
+ };
77
+ });
78
+ };
79
79
 
80
80
  export const createCompositeProducer = ({ cleanup = () => {} } = {}) => {
81
- const observables = new Set()
82
- const observers = new Set()
81
+ const observables = new Set();
82
+ const observers = new Set();
83
83
 
84
84
  const addObservable = (observable) => {
85
85
  if (observables.has(observable)) {
86
- return false
86
+ return false;
87
87
  }
88
88
 
89
- observables.add(observable)
89
+ observables.add(observable);
90
90
  observers.forEach((observer) => {
91
- observer.observe(observable)
92
- })
93
- return true
94
- }
91
+ observer.observe(observable);
92
+ });
93
+ return true;
94
+ };
95
95
 
96
96
  const removeObservable = (observable) => {
97
97
  if (!observables.has(observable)) {
98
- return false
98
+ return false;
99
99
  }
100
100
 
101
- observables.delete(observable)
101
+ observables.delete(observable);
102
102
  observers.forEach((observer) => {
103
- observer.unobserve(observable)
104
- })
105
- return true
106
- }
103
+ observer.unobserve(observable);
104
+ });
105
+ return true;
106
+ };
107
107
 
108
108
  const producer = ({
109
109
  next = () => {},
110
110
  complete = () => {},
111
111
  error = () => {},
112
112
  }) => {
113
- let completeCount = 0
113
+ let completeCount = 0;
114
114
 
115
115
  const checkComplete = () => {
116
116
  if (completeCount === observables.size) {
117
- complete()
117
+ complete();
118
118
  }
119
- }
119
+ };
120
120
 
121
- const subscriptions = new Map()
121
+ const subscriptions = new Map();
122
122
  const observe = (observable) => {
123
123
  const subscription = observable.subscribe({
124
124
  next: (value) => {
125
- next(value)
125
+ next(value);
126
126
  },
127
127
  error: (value) => {
128
- error(value)
128
+ error(value);
129
129
  },
130
130
  complete: () => {
131
- subscriptions.delete(observable)
132
- completeCount++
133
- checkComplete()
131
+ subscriptions.delete(observable);
132
+ completeCount++;
133
+ checkComplete();
134
134
  },
135
- })
136
- subscriptions.set(observable, subscription)
137
- }
135
+ });
136
+ subscriptions.set(observable, subscription);
137
+ };
138
138
  const unobserve = (observable) => {
139
- const subscription = subscriptions.get(observable)
139
+ const subscription = subscriptions.get(observable);
140
140
  if (!subscription) {
141
- return
141
+ return;
142
142
  }
143
143
 
144
- subscription.unsubscribe()
145
- subscriptions.delete(observable)
146
- checkComplete()
147
- }
144
+ subscription.unsubscribe();
145
+ subscriptions.delete(observable);
146
+ checkComplete();
147
+ };
148
148
  const observer = {
149
149
  observe,
150
150
  unobserve,
151
- }
152
- observers.add(observer)
151
+ };
152
+ observers.add(observer);
153
153
  observables.forEach((observable) => {
154
- observe(observable)
155
- })
154
+ observe(observable);
155
+ });
156
156
 
157
157
  return () => {
158
- observers.delete(observer)
158
+ observers.delete(observer);
159
159
  subscriptions.forEach((subscription) => {
160
- subscription.unsubscribe()
161
- })
162
- subscriptions.clear()
163
- cleanup()
164
- }
165
- }
166
-
167
- producer.addObservable = addObservable
168
- producer.removeObservable = removeObservable
169
-
170
- return producer
171
- }
160
+ subscription.unsubscribe();
161
+ });
162
+ subscriptions.clear();
163
+ cleanup();
164
+ };
165
+ };
166
+
167
+ producer.addObservable = addObservable;
168
+ producer.removeObservable = removeObservable;
169
+
170
+ return producer;
171
+ };
@@ -1,6 +1,6 @@
1
1
  // https://github.com/jamestalmage/stream-to-observable/blob/master/index.js
2
- import { Readable } from "node:stream"
3
- import { createObservable } from "./observable.js"
2
+ import { Readable } from "node:stream";
3
+ import { createObservable } from "./observable.js";
4
4
 
5
5
  export const observableFromNodeStream = (
6
6
  nodeStream,
@@ -10,31 +10,31 @@ export const observableFromNodeStream = (
10
10
  ) => {
11
11
  const observable = createObservable(({ next, error, complete }) => {
12
12
  if (nodeStream.isPaused()) {
13
- nodeStream.resume()
13
+ nodeStream.resume();
14
14
  } else if (nodeStream.complete) {
15
- complete()
16
- return null
15
+ complete();
16
+ return null;
17
17
  }
18
18
  const cleanup = () => {
19
- nodeStream.removeListener("data", next)
20
- nodeStream.removeListener("error", error)
21
- nodeStream.removeListener("end", complete)
22
- nodeStream.removeListener("close", cleanup)
23
- nodeStream.destroy()
24
- }
19
+ nodeStream.removeListener("data", next);
20
+ nodeStream.removeListener("error", error);
21
+ nodeStream.removeListener("end", complete);
22
+ nodeStream.removeListener("close", cleanup);
23
+ nodeStream.destroy();
24
+ };
25
25
  // should we do nodeStream.resume() in case the stream was paused ?
26
- nodeStream.once("error", error)
26
+ nodeStream.once("error", error);
27
27
  nodeStream.on("data", (data) => {
28
- next(data)
29
- })
28
+ next(data);
29
+ });
30
30
  nodeStream.once("close", () => {
31
- cleanup()
32
- })
31
+ cleanup();
32
+ });
33
33
  nodeStream.once("end", () => {
34
- complete()
35
- })
36
- return cleanup
37
- })
34
+ complete();
35
+ });
36
+ return cleanup;
37
+ });
38
38
 
39
39
  if (nodeStream instanceof Readable) {
40
40
  // safe measure, ensure the readable stream gets
@@ -49,24 +49,24 @@ export const observableFromNodeStream = (
49
49
  // url is for http client request
50
50
  detail: `path: ${nodeStream.path}, fd: ${nodeStream.fd}, url: ${nodeStream.url}`,
51
51
  },
52
- )
53
- nodeStream.destroy()
54
- }, readableStreamLifetime)
55
- observable.timeout = timeout
52
+ );
53
+ nodeStream.destroy();
54
+ }, readableStreamLifetime);
55
+ observable.timeout = timeout;
56
56
  onceReadableStreamUsedOrClosed(nodeStream, () => {
57
- clearTimeout(timeout)
58
- })
57
+ clearTimeout(timeout);
58
+ });
59
59
  }
60
60
 
61
- return observable
62
- }
61
+ return observable;
62
+ };
63
63
 
64
64
  const onceReadableStreamUsedOrClosed = (readableStream, callback) => {
65
65
  const dataOrCloseCallback = () => {
66
- readableStream.removeListener("data", dataOrCloseCallback)
67
- readableStream.removeListener("close", dataOrCloseCallback)
68
- callback()
69
- }
70
- readableStream.on("data", dataOrCloseCallback)
71
- readableStream.once("close", dataOrCloseCallback)
72
- }
66
+ readableStream.removeListener("data", dataOrCloseCallback);
67
+ readableStream.removeListener("close", dataOrCloseCallback);
68
+ callback();
69
+ };
70
+ readableStream.on("data", dataOrCloseCallback);
71
+ readableStream.once("close", dataOrCloseCallback);
72
+ };
@@ -1,28 +1,28 @@
1
- import { observableFromNodeStream } from "./observable_from_node_stream.js"
2
- import { headersFromObject } from "../internal/headersFromObject.js"
1
+ import { observableFromNodeStream } from "./observable_from_node_stream.js";
2
+ import { headersFromObject } from "../internal/headersFromObject.js";
3
3
 
4
4
  export const fromNodeRequest = (
5
5
  nodeRequest,
6
6
  { serverOrigin, signal, requestBodyLifetime },
7
7
  ) => {
8
- const headers = headersFromObject(nodeRequest.headers)
8
+ const headers = headersFromObject(nodeRequest.headers);
9
9
  const body = observableFromNodeStream(nodeRequest, {
10
10
  readableStreamLifetime: requestBodyLifetime,
11
- })
11
+ });
12
12
 
13
- let requestOrigin
13
+ let requestOrigin;
14
14
  if (nodeRequest.upgrade) {
15
- requestOrigin = serverOrigin
15
+ requestOrigin = serverOrigin;
16
16
  } else if (nodeRequest.authority) {
17
17
  requestOrigin = nodeRequest.connection.encrypted
18
18
  ? `https://${nodeRequest.authority}`
19
- : `http://${nodeRequest.authority}`
19
+ : `http://${nodeRequest.authority}`;
20
20
  } else if (nodeRequest.headers.host) {
21
21
  requestOrigin = nodeRequest.connection.encrypted
22
22
  ? `https://${nodeRequest.headers.host}`
23
- : `http://${nodeRequest.headers.host}`
23
+ : `http://${nodeRequest.headers.host}`;
24
24
  } else {
25
- requestOrigin = serverOrigin
25
+ requestOrigin = serverOrigin;
26
26
  }
27
27
 
28
28
  return Object.freeze({
@@ -36,8 +36,8 @@ export const fromNodeRequest = (
36
36
  method: nodeRequest.method,
37
37
  headers,
38
38
  body,
39
- })
40
- }
39
+ });
40
+ };
41
41
 
42
42
  export const applyRedirectionToRequest = (
43
43
  request,
@@ -57,26 +57,26 @@ export const applyRedirectionToRequest = (
57
57
  })
58
58
  : {}),
59
59
  ...rest,
60
- }
61
- }
60
+ };
61
+ };
62
62
 
63
63
  const getPropertiesFromResource = ({ resource, baseUrl }) => {
64
- const urlObject = new URL(resource, baseUrl)
65
- let pathname = urlObject.pathname
64
+ const urlObject = new URL(resource, baseUrl);
65
+ let pathname = urlObject.pathname;
66
66
 
67
67
  return {
68
68
  url: String(urlObject),
69
69
  pathname,
70
70
  resource,
71
- }
72
- }
71
+ };
72
+ };
73
73
 
74
74
  const getPropertiesFromPathname = ({ pathname, baseUrl }) => {
75
75
  return getPropertiesFromResource({
76
76
  resource: `${pathname}${new URL(baseUrl).search}`,
77
77
  baseUrl,
78
- })
79
- }
78
+ });
79
+ };
80
80
 
81
81
  export const createPushRequest = (request, { signal, pathname, method }) => {
82
82
  const pushRequest = Object.freeze({
@@ -93,12 +93,12 @@ export const createPushRequest = (request, { signal, pathname, method }) => {
93
93
  method: method || request.method,
94
94
  headers: getHeadersInheritedByPushRequest(request),
95
95
  body: undefined,
96
- })
97
- return pushRequest
98
- }
96
+ });
97
+ return pushRequest;
98
+ };
99
99
 
100
100
  const getHeadersInheritedByPushRequest = (request) => {
101
- const headersInherited = { ...request.headers }
101
+ const headersInherited = { ...request.headers };
102
102
  // mtime sent by the client in request headers concerns the main request
103
103
  // Time remains valid for request to other resources so we keep it
104
104
  // in child requests
@@ -106,7 +106,7 @@ const getHeadersInheritedByPushRequest = (request) => {
106
106
 
107
107
  // eTag sent by the client in request headers concerns the main request
108
108
  // A request made to an other resource must not inherit the eTag
109
- delete headersInherited["if-none-match"]
109
+ delete headersInherited["if-none-match"];
110
110
 
111
- return headersInherited
112
- }
111
+ return headersInherited;
112
+ };