@comapeo/map-server 1.0.0-pre.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 (179) hide show
  1. package/README.md +610 -0
  2. package/dist/context.d.ts +46 -0
  3. package/dist/context.d.ts.map +1 -0
  4. package/dist/context.js +181 -0
  5. package/dist/index.d.ts +25 -0
  6. package/dist/index.d.ts.map +1 -0
  7. package/dist/index.js +112 -0
  8. package/dist/lib/constants.d.ts +7 -0
  9. package/dist/lib/constants.d.ts.map +1 -0
  10. package/dist/lib/constants.js +6 -0
  11. package/dist/lib/download-request.d.ts +17 -0
  12. package/dist/lib/download-request.d.ts.map +1 -0
  13. package/dist/lib/download-request.js +113 -0
  14. package/dist/lib/errors.d.ts +88 -0
  15. package/dist/lib/errors.d.ts.map +1 -0
  16. package/dist/lib/errors.js +158 -0
  17. package/dist/lib/event-stream-response.d.ts +17 -0
  18. package/dist/lib/event-stream-response.d.ts.map +1 -0
  19. package/dist/lib/event-stream-response.js +39 -0
  20. package/dist/lib/event-target.d.ts +9 -0
  21. package/dist/lib/event-target.d.ts.map +1 -0
  22. package/dist/lib/event-target.js +4 -0
  23. package/dist/lib/fetch-api.d.ts +3 -0
  24. package/dist/lib/fetch-api.d.ts.map +1 -0
  25. package/dist/lib/fetch-api.js +16 -0
  26. package/dist/lib/map-share.d.ts +52 -0
  27. package/dist/lib/map-share.d.ts.map +1 -0
  28. package/dist/lib/map-share.js +142 -0
  29. package/dist/lib/secret-stream-fetch.d.ts +7 -0
  30. package/dist/lib/secret-stream-fetch.d.ts.map +1 -0
  31. package/dist/lib/secret-stream-fetch.js +34 -0
  32. package/dist/lib/self-evicting-map.d.ts +16 -0
  33. package/dist/lib/self-evicting-map.d.ts.map +1 -0
  34. package/dist/lib/self-evicting-map.js +29 -0
  35. package/dist/lib/state-update-event.d.ts +8 -0
  36. package/dist/lib/state-update-event.d.ts.map +1 -0
  37. package/dist/lib/state-update-event.js +10 -0
  38. package/dist/lib/utils.d.ts +32 -0
  39. package/dist/lib/utils.d.ts.map +1 -0
  40. package/dist/lib/utils.js +96 -0
  41. package/dist/middlewares/localhost-only.d.ts +11 -0
  42. package/dist/middlewares/localhost-only.d.ts.map +1 -0
  43. package/dist/middlewares/localhost-only.js +10 -0
  44. package/dist/middlewares/parse-request.d.ts +11 -0
  45. package/dist/middlewares/parse-request.d.ts.map +1 -0
  46. package/dist/middlewares/parse-request.js +25 -0
  47. package/dist/routes/downloads.d.ts +15 -0
  48. package/dist/routes/downloads.d.ts.map +1 -0
  49. package/dist/routes/downloads.js +60 -0
  50. package/dist/routes/map-shares.d.ts +19 -0
  51. package/dist/routes/map-shares.d.ts.map +1 -0
  52. package/dist/routes/map-shares.js +192 -0
  53. package/dist/routes/maps.d.ts +6 -0
  54. package/dist/routes/maps.d.ts.map +1 -0
  55. package/dist/routes/maps.js +118 -0
  56. package/dist/routes/root.d.ts +6 -0
  57. package/dist/routes/root.d.ts.map +1 -0
  58. package/dist/routes/root.js +29 -0
  59. package/dist/types.d.ts +110 -0
  60. package/dist/types.d.ts.map +1 -0
  61. package/dist/types.js +96 -0
  62. package/node_modules/@envelop/instrumentation/LICENSE +21 -0
  63. package/node_modules/@envelop/instrumentation/README.md +30 -0
  64. package/node_modules/@envelop/instrumentation/cjs/index.js +5 -0
  65. package/node_modules/@envelop/instrumentation/cjs/instrumentation.js +89 -0
  66. package/node_modules/@envelop/instrumentation/cjs/package.json +1 -0
  67. package/node_modules/@envelop/instrumentation/esm/index.js +2 -0
  68. package/node_modules/@envelop/instrumentation/esm/instrumentation.js +82 -0
  69. package/node_modules/@envelop/instrumentation/package.json +57 -0
  70. package/node_modules/@envelop/instrumentation/typings/index.d.cts +1 -0
  71. package/node_modules/@envelop/instrumentation/typings/index.d.ts +1 -0
  72. package/node_modules/@envelop/instrumentation/typings/instrumentation.d.cts +44 -0
  73. package/node_modules/@envelop/instrumentation/typings/instrumentation.d.ts +44 -0
  74. package/node_modules/@whatwg-node/disposablestack/cjs/AsyncDisposableStack.js +73 -0
  75. package/node_modules/@whatwg-node/disposablestack/cjs/DisposableStack.js +62 -0
  76. package/node_modules/@whatwg-node/disposablestack/cjs/SupressedError.js +16 -0
  77. package/node_modules/@whatwg-node/disposablestack/cjs/index.js +11 -0
  78. package/node_modules/@whatwg-node/disposablestack/cjs/package.json +1 -0
  79. package/node_modules/@whatwg-node/disposablestack/cjs/symbols.js +20 -0
  80. package/node_modules/@whatwg-node/disposablestack/cjs/utils.js +11 -0
  81. package/node_modules/@whatwg-node/disposablestack/esm/AsyncDisposableStack.js +69 -0
  82. package/node_modules/@whatwg-node/disposablestack/esm/DisposableStack.js +58 -0
  83. package/node_modules/@whatwg-node/disposablestack/esm/SupressedError.js +12 -0
  84. package/node_modules/@whatwg-node/disposablestack/esm/index.js +7 -0
  85. package/node_modules/@whatwg-node/disposablestack/esm/symbols.js +16 -0
  86. package/node_modules/@whatwg-node/disposablestack/esm/utils.js +7 -0
  87. package/node_modules/@whatwg-node/disposablestack/package.json +44 -0
  88. package/node_modules/@whatwg-node/disposablestack/typings/AsyncDisposableStack.d.cts +15 -0
  89. package/node_modules/@whatwg-node/disposablestack/typings/AsyncDisposableStack.d.ts +15 -0
  90. package/node_modules/@whatwg-node/disposablestack/typings/DisposableStack.d.cts +14 -0
  91. package/node_modules/@whatwg-node/disposablestack/typings/DisposableStack.d.ts +14 -0
  92. package/node_modules/@whatwg-node/disposablestack/typings/SupressedError.d.cts +5 -0
  93. package/node_modules/@whatwg-node/disposablestack/typings/SupressedError.d.ts +5 -0
  94. package/node_modules/@whatwg-node/disposablestack/typings/index.d.cts +4 -0
  95. package/node_modules/@whatwg-node/disposablestack/typings/index.d.ts +4 -0
  96. package/node_modules/@whatwg-node/disposablestack/typings/symbols.d.cts +5 -0
  97. package/node_modules/@whatwg-node/disposablestack/typings/symbols.d.ts +5 -0
  98. package/node_modules/@whatwg-node/disposablestack/typings/utils.d.cts +2 -0
  99. package/node_modules/@whatwg-node/disposablestack/typings/utils.d.ts +2 -0
  100. package/node_modules/@whatwg-node/promise-helpers/cjs/index.js +270 -0
  101. package/node_modules/@whatwg-node/promise-helpers/cjs/package.json +1 -0
  102. package/node_modules/@whatwg-node/promise-helpers/esm/index.js +257 -0
  103. package/node_modules/@whatwg-node/promise-helpers/package.json +43 -0
  104. package/node_modules/@whatwg-node/promise-helpers/typings/index.d.cts +31 -0
  105. package/node_modules/@whatwg-node/promise-helpers/typings/index.d.ts +31 -0
  106. package/node_modules/@whatwg-node/server/README.md +590 -0
  107. package/node_modules/@whatwg-node/server/cjs/createServerAdapter.js +368 -0
  108. package/node_modules/@whatwg-node/server/cjs/index.js +17 -0
  109. package/node_modules/@whatwg-node/server/cjs/package.json +1 -0
  110. package/node_modules/@whatwg-node/server/cjs/plugins/types.js +0 -0
  111. package/node_modules/@whatwg-node/server/cjs/plugins/useContentEncoding.js +73 -0
  112. package/node_modules/@whatwg-node/server/cjs/plugins/useCors.js +124 -0
  113. package/node_modules/@whatwg-node/server/cjs/plugins/useErrorHandling.js +52 -0
  114. package/node_modules/@whatwg-node/server/cjs/types.js +0 -0
  115. package/node_modules/@whatwg-node/server/cjs/utils.js +599 -0
  116. package/node_modules/@whatwg-node/server/cjs/uwebsockets.js +241 -0
  117. package/node_modules/@whatwg-node/server/esm/createServerAdapter.js +365 -0
  118. package/node_modules/@whatwg-node/server/esm/index.js +11 -0
  119. package/node_modules/@whatwg-node/server/esm/plugins/types.js +0 -0
  120. package/node_modules/@whatwg-node/server/esm/plugins/useContentEncoding.js +70 -0
  121. package/node_modules/@whatwg-node/server/esm/plugins/useCors.js +120 -0
  122. package/node_modules/@whatwg-node/server/esm/plugins/useErrorHandling.js +46 -0
  123. package/node_modules/@whatwg-node/server/esm/types.js +0 -0
  124. package/node_modules/@whatwg-node/server/esm/utils.js +588 -0
  125. package/node_modules/@whatwg-node/server/esm/uwebsockets.js +234 -0
  126. package/node_modules/@whatwg-node/server/package.json +46 -0
  127. package/node_modules/@whatwg-node/server/typings/createServerAdapter.d.cts +19 -0
  128. package/node_modules/@whatwg-node/server/typings/createServerAdapter.d.ts +19 -0
  129. package/node_modules/@whatwg-node/server/typings/index.d.cts +11 -0
  130. package/node_modules/@whatwg-node/server/typings/index.d.ts +11 -0
  131. package/node_modules/@whatwg-node/server/typings/plugins/types.d.cts +76 -0
  132. package/node_modules/@whatwg-node/server/typings/plugins/types.d.ts +76 -0
  133. package/node_modules/@whatwg-node/server/typings/plugins/useContentEncoding.d.cts +2 -0
  134. package/node_modules/@whatwg-node/server/typings/plugins/useContentEncoding.d.ts +2 -0
  135. package/node_modules/@whatwg-node/server/typings/plugins/useCors.d.cts +14 -0
  136. package/node_modules/@whatwg-node/server/typings/plugins/useCors.d.ts +14 -0
  137. package/node_modules/@whatwg-node/server/typings/plugins/useErrorHandling.d.cts +13 -0
  138. package/node_modules/@whatwg-node/server/typings/plugins/useErrorHandling.d.ts +13 -0
  139. package/node_modules/@whatwg-node/server/typings/types.d.cts +100 -0
  140. package/node_modules/@whatwg-node/server/typings/types.d.ts +100 -0
  141. package/node_modules/@whatwg-node/server/typings/utils.d.cts +42 -0
  142. package/node_modules/@whatwg-node/server/typings/utils.d.ts +42 -0
  143. package/node_modules/@whatwg-node/server/typings/uwebsockets.d.cts +32 -0
  144. package/node_modules/@whatwg-node/server/typings/uwebsockets.d.ts +32 -0
  145. package/node_modules/tslib/CopyrightNotice.txt +15 -0
  146. package/node_modules/tslib/LICENSE.txt +12 -0
  147. package/node_modules/tslib/README.md +164 -0
  148. package/node_modules/tslib/SECURITY.md +41 -0
  149. package/node_modules/tslib/modules/index.d.ts +38 -0
  150. package/node_modules/tslib/modules/index.js +70 -0
  151. package/node_modules/tslib/modules/package.json +3 -0
  152. package/node_modules/tslib/package.json +47 -0
  153. package/node_modules/tslib/tslib.d.ts +460 -0
  154. package/node_modules/tslib/tslib.es6.html +1 -0
  155. package/node_modules/tslib/tslib.es6.js +402 -0
  156. package/node_modules/tslib/tslib.es6.mjs +401 -0
  157. package/node_modules/tslib/tslib.html +1 -0
  158. package/node_modules/tslib/tslib.js +484 -0
  159. package/package.json +87 -0
  160. package/src/context.ts +203 -0
  161. package/src/index.ts +193 -0
  162. package/src/lib/constants.ts +6 -0
  163. package/src/lib/download-request.ts +142 -0
  164. package/src/lib/errors.ts +187 -0
  165. package/src/lib/event-stream-response.ts +57 -0
  166. package/src/lib/event-target.ts +11 -0
  167. package/src/lib/fetch-api.ts +18 -0
  168. package/src/lib/map-share.ts +185 -0
  169. package/src/lib/secret-stream-fetch.ts +42 -0
  170. package/src/lib/self-evicting-map.ts +35 -0
  171. package/src/lib/state-update-event.ts +14 -0
  172. package/src/lib/utils.ts +110 -0
  173. package/src/middlewares/localhost-only.ts +16 -0
  174. package/src/middlewares/parse-request.ts +34 -0
  175. package/src/routes/downloads.ts +92 -0
  176. package/src/routes/map-shares.ts +246 -0
  177. package/src/routes/maps.ts +146 -0
  178. package/src/routes/root.ts +37 -0
  179. package/src/types.ts +152 -0
@@ -0,0 +1,588 @@
1
+ import { createDeferredPromise, fakePromise, handleMaybePromise, isPromise, } from '@whatwg-node/promise-helpers';
2
+ export { isPromise, createDeferredPromise };
3
+ export function isAsyncIterable(body) {
4
+ return (body != null && typeof body === 'object' && typeof body[Symbol.asyncIterator] === 'function');
5
+ }
6
+ function getPort(nodeRequest) {
7
+ if (nodeRequest.socket?.localPort) {
8
+ return nodeRequest.socket?.localPort;
9
+ }
10
+ const hostInHeader = nodeRequest.headers?.[':authority'] || nodeRequest.headers?.host;
11
+ const portInHeader = hostInHeader?.split(':')?.[1];
12
+ if (portInHeader) {
13
+ return portInHeader;
14
+ }
15
+ return 80;
16
+ }
17
+ function getHostnameWithPort(nodeRequest) {
18
+ if (nodeRequest.headers?.[':authority']) {
19
+ return nodeRequest.headers?.[':authority'];
20
+ }
21
+ if (nodeRequest.headers?.host) {
22
+ return nodeRequest.headers?.host;
23
+ }
24
+ const port = getPort(nodeRequest);
25
+ if (nodeRequest.hostname) {
26
+ return nodeRequest.hostname + ':' + port;
27
+ }
28
+ const localIp = nodeRequest.socket?.localAddress;
29
+ if (localIp && !localIp?.includes('::') && !localIp?.includes('ffff')) {
30
+ return `${localIp}:${port}`;
31
+ }
32
+ return 'localhost';
33
+ }
34
+ function buildFullUrl(nodeRequest) {
35
+ const hostnameWithPort = getHostnameWithPort(nodeRequest);
36
+ const protocol = nodeRequest.protocol || (nodeRequest.socket?.encrypted ? 'https' : 'http');
37
+ const endpoint = nodeRequest.originalUrl || nodeRequest.url || '/graphql';
38
+ return `${protocol}://${hostnameWithPort}${endpoint}`;
39
+ }
40
+ function isRequestBody(body) {
41
+ const stringTag = body[Symbol.toStringTag];
42
+ if (typeof body === 'string' ||
43
+ stringTag === 'Uint8Array' ||
44
+ stringTag === 'Blob' ||
45
+ stringTag === 'FormData' ||
46
+ stringTag === 'URLSearchParams' ||
47
+ isAsyncIterable(body)) {
48
+ return true;
49
+ }
50
+ return false;
51
+ }
52
+ export function normalizeNodeRequest(nodeRequest, fetchAPI, nodeResponse, __useCustomAbortCtrl) {
53
+ const rawRequest = nodeRequest.raw || nodeRequest.req || nodeRequest;
54
+ let fullUrl = buildFullUrl(rawRequest);
55
+ if (nodeRequest.query) {
56
+ const url = new fetchAPI.URL(fullUrl);
57
+ for (const key in nodeRequest.query) {
58
+ url.searchParams.set(key, nodeRequest.query[key]);
59
+ }
60
+ fullUrl = url.toString();
61
+ }
62
+ let normalizedHeaders = nodeRequest.headers;
63
+ if (nodeRequest.headers?.[':method']) {
64
+ normalizedHeaders = {};
65
+ for (const key in nodeRequest.headers) {
66
+ if (!key.startsWith(':')) {
67
+ normalizedHeaders[key] = nodeRequest.headers[key];
68
+ }
69
+ }
70
+ }
71
+ const controller = __useCustomAbortCtrl
72
+ ? createCustomAbortControllerSignal()
73
+ : new AbortController();
74
+ if (nodeResponse?.once) {
75
+ const closeEventListener = () => {
76
+ if (!controller.signal.aborted) {
77
+ Object.defineProperty(rawRequest, 'aborted', { value: true });
78
+ controller.abort(nodeResponse.errored ?? undefined);
79
+ }
80
+ };
81
+ nodeResponse.once('error', closeEventListener);
82
+ nodeResponse.once('close', closeEventListener);
83
+ nodeResponse.once('finish', () => {
84
+ nodeResponse.removeListener('close', closeEventListener);
85
+ });
86
+ }
87
+ if (nodeRequest.method === 'GET' || nodeRequest.method === 'HEAD') {
88
+ return new fetchAPI.Request(fullUrl, {
89
+ method: nodeRequest.method,
90
+ headers: normalizedHeaders,
91
+ signal: controller.signal,
92
+ });
93
+ }
94
+ /**
95
+ * Some Node server frameworks like Serverless Express sends a dummy object with body but as a Buffer not string
96
+ * so we do those checks to see is there something we can use directly as BodyInit
97
+ * because the presence of body means the request stream is already consumed and,
98
+ * rawRequest cannot be used as BodyInit/ReadableStream by Fetch API in this case.
99
+ */
100
+ const maybeParsedBody = nodeRequest.body;
101
+ if (maybeParsedBody != null && Object.keys(maybeParsedBody).length > 0) {
102
+ if (isRequestBody(maybeParsedBody)) {
103
+ return new fetchAPI.Request(fullUrl, {
104
+ method: nodeRequest.method || 'GET',
105
+ headers: normalizedHeaders,
106
+ body: maybeParsedBody,
107
+ signal: controller.signal,
108
+ });
109
+ }
110
+ const request = new fetchAPI.Request(fullUrl, {
111
+ method: nodeRequest.method || 'GET',
112
+ headers: normalizedHeaders,
113
+ signal: controller.signal,
114
+ });
115
+ if (!request.headers.get('content-type')?.includes('json')) {
116
+ request.headers.set('content-type', 'application/json; charset=utf-8');
117
+ }
118
+ return new Proxy(request, {
119
+ get: (target, prop, receiver) => {
120
+ switch (prop) {
121
+ case 'json':
122
+ return () => fakePromise(maybeParsedBody);
123
+ case 'text':
124
+ return () => fakePromise(JSON.stringify(maybeParsedBody));
125
+ default:
126
+ if (globalThis.Bun) {
127
+ // workaround for https://github.com/oven-sh/bun/issues/12368
128
+ // Proxy.get doesn't seem to get `receiver` correctly
129
+ return Reflect.get(target, prop);
130
+ }
131
+ return Reflect.get(target, prop, receiver);
132
+ }
133
+ },
134
+ });
135
+ }
136
+ // perf: instead of spreading the object, we can just pass it as is and it performs better
137
+ return new fetchAPI.Request(fullUrl, {
138
+ method: nodeRequest.method,
139
+ headers: normalizedHeaders,
140
+ signal: controller.signal,
141
+ // @ts-expect-error - AsyncIterable is supported as body
142
+ body: rawRequest,
143
+ duplex: 'half',
144
+ });
145
+ }
146
+ export function isReadable(stream) {
147
+ return stream.read != null;
148
+ }
149
+ export function isNodeRequest(request) {
150
+ return isReadable(request);
151
+ }
152
+ export function isServerResponse(stream) {
153
+ // Check all used functions are defined
154
+ return (stream != null &&
155
+ stream.setHeader != null &&
156
+ stream.end != null &&
157
+ stream.once != null &&
158
+ stream.write != null);
159
+ }
160
+ export function isReadableStream(stream) {
161
+ return stream != null && stream.getReader != null;
162
+ }
163
+ export function isFetchEvent(event) {
164
+ return event != null && event.request != null && event.respondWith != null;
165
+ }
166
+ function configureSocket(rawRequest) {
167
+ rawRequest?.socket?.setTimeout?.(0);
168
+ rawRequest?.socket?.setNoDelay?.(true);
169
+ rawRequest?.socket?.setKeepAlive?.(true);
170
+ }
171
+ function endResponse(serverResponse) {
172
+ // @ts-expect-error Avoid arguments adaptor trampoline https://v8.dev/blog/adaptor-frame
173
+ serverResponse.end(null, null, null);
174
+ }
175
+ function sendAsyncIterable(serverResponse, asyncIterable) {
176
+ let closed = false;
177
+ const closeEventListener = () => {
178
+ closed = true;
179
+ };
180
+ serverResponse.once('error', closeEventListener);
181
+ serverResponse.once('close', closeEventListener);
182
+ serverResponse.once('finish', () => {
183
+ serverResponse.removeListener('close', closeEventListener);
184
+ serverResponse.removeListener('error', closeEventListener);
185
+ });
186
+ const iterator = asyncIterable[Symbol.asyncIterator]();
187
+ const pump = () => iterator.next().then(({ done, value }) => {
188
+ if (closed || done) {
189
+ return;
190
+ }
191
+ return handleMaybePromise(() => safeWrite(value, serverResponse), () => (closed ? endResponse(serverResponse) : pump()));
192
+ });
193
+ return pump();
194
+ }
195
+ function safeWrite(chunk, serverResponse) {
196
+ // @ts-expect-error http and http2 writes are actually compatible
197
+ const result = serverResponse.write(chunk);
198
+ if (!result) {
199
+ return new Promise(resolve => serverResponse.once('drain', resolve));
200
+ }
201
+ }
202
+ const isNode1x = globalThis.process?.versions?.node?.startsWith('1');
203
+ export function sendNodeResponse(fetchResponse, serverResponse, nodeRequest, __useSingleWriteHead) {
204
+ if (serverResponse.closed || serverResponse.destroyed || serverResponse.writableEnded) {
205
+ return;
206
+ }
207
+ if (!fetchResponse) {
208
+ serverResponse.statusCode = 404;
209
+ endResponse(serverResponse);
210
+ return;
211
+ }
212
+ if (__useSingleWriteHead &&
213
+ // @ts-expect-error - headersInit is a private property
214
+ fetchResponse.headers?.headersInit &&
215
+ // @ts-expect-error - headersInit is a private property
216
+ !Array.isArray(fetchResponse.headers.headersInit) &&
217
+ // @ts-expect-error - headersInit is a private property
218
+ !fetchResponse.headers.headersInit.get &&
219
+ // @ts-expect-error - map is a private property
220
+ !fetchResponse.headers._map &&
221
+ // @ts-expect-error - _setCookies is a private property
222
+ !fetchResponse.headers._setCookies?.length) {
223
+ // @ts-expect-error - writeHead accepts headers object
224
+ serverResponse.writeHead(fetchResponse.status, fetchResponse.statusText,
225
+ // @ts-expect-error - headersInit is a private property
226
+ fetchResponse.headers.headersInit);
227
+ }
228
+ else {
229
+ // Avoid using `setHeaders` on Node.js 18 as it is broken with multiple headers with the same name
230
+ // @ts-expect-error - setHeaders exist
231
+ if (serverResponse.setHeaders && !isNode1x) {
232
+ // @ts-expect-error - writeHead bad typings
233
+ serverResponse.setHeaders(fetchResponse.headers);
234
+ }
235
+ else {
236
+ let setCookiesSet = false;
237
+ fetchResponse.headers.forEach((value, key) => {
238
+ if (key === 'set-cookie') {
239
+ if (setCookiesSet) {
240
+ return;
241
+ }
242
+ setCookiesSet = true;
243
+ const setCookies = fetchResponse.headers.getSetCookie?.();
244
+ if (setCookies) {
245
+ serverResponse.setHeader('set-cookie', setCookies);
246
+ return;
247
+ }
248
+ }
249
+ serverResponse.setHeader(key, value);
250
+ });
251
+ }
252
+ // @ts-expect-error - writeHead bad typings
253
+ serverResponse.writeHead(fetchResponse.status, fetchResponse.statusText);
254
+ }
255
+ // @ts-expect-error - Handle the case where the response is a string
256
+ if (fetchResponse['bodyType'] === 'String') {
257
+ return handleMaybePromise(
258
+ // @ts-expect-error - bodyInit is a private property
259
+ () => safeWrite(fetchResponse.bodyInit, serverResponse), () => endResponse(serverResponse));
260
+ }
261
+ // Optimizations for node-fetch
262
+ const bufOfRes =
263
+ // @ts-expect-error - _buffer is a private property
264
+ fetchResponse._buffer;
265
+ if (bufOfRes) {
266
+ return handleMaybePromise(() => safeWrite(bufOfRes, serverResponse), () => endResponse(serverResponse));
267
+ }
268
+ // Other fetch implementations
269
+ const fetchBody = fetchResponse.body;
270
+ if (fetchBody == null) {
271
+ endResponse(serverResponse);
272
+ return;
273
+ }
274
+ if (
275
+ // @ts-expect-error - Uint8Array is a valid body type
276
+ fetchBody[Symbol.toStringTag] === 'Uint8Array') {
277
+ return handleMaybePromise(() => safeWrite(fetchBody, serverResponse), () => endResponse(serverResponse));
278
+ }
279
+ configureSocket(nodeRequest);
280
+ if (isReadable(fetchBody)) {
281
+ serverResponse.once('close', () => {
282
+ fetchBody.destroy();
283
+ });
284
+ fetchBody.pipe(serverResponse, {
285
+ end: true,
286
+ });
287
+ return;
288
+ }
289
+ if (isReadableStream(fetchBody)) {
290
+ return sendReadableStream(nodeRequest, serverResponse, fetchBody);
291
+ }
292
+ if (isAsyncIterable(fetchBody)) {
293
+ return sendAsyncIterable(serverResponse, fetchBody);
294
+ }
295
+ }
296
+ function sendReadableStream(nodeRequest, serverResponse, readableStream) {
297
+ const reader = readableStream.getReader();
298
+ nodeRequest?.once?.('error', err => {
299
+ reader.cancel(err).catch(() => {});
300
+ });
301
+ function pump() {
302
+ return reader
303
+ .read()
304
+ .then(({ done, value }) => done
305
+ ? endResponse(serverResponse)
306
+ : handleMaybePromise(() => safeWrite(value, serverResponse), pump))
307
+ .catch(err => {
308
+ // If stream was aborted (e.g., via cancel()), destroy the socket with RST
309
+ if (err?.name === 'AbortError') {
310
+ if (!serverResponse.destroyed) {
311
+ serverResponse.destroy();
312
+ }
313
+ return;
314
+ }
315
+ // For other errors, re-throw to be handled by the request handler
316
+ throw err;
317
+ });
318
+ }
319
+ return pump();
320
+ }
321
+ export function isRequestInit(val) {
322
+ return (val != null &&
323
+ typeof val === 'object' &&
324
+ ('body' in val ||
325
+ 'cache' in val ||
326
+ 'credentials' in val ||
327
+ 'headers' in val ||
328
+ 'integrity' in val ||
329
+ 'keepalive' in val ||
330
+ 'method' in val ||
331
+ 'mode' in val ||
332
+ 'redirect' in val ||
333
+ 'referrer' in val ||
334
+ 'referrerPolicy' in val ||
335
+ 'signal' in val ||
336
+ 'window' in val));
337
+ }
338
+ // from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign#copying_accessors
339
+ export function completeAssign(...args) {
340
+ const [target, ...sources] = args.filter(arg => arg != null && typeof arg === 'object');
341
+ sources.forEach(source => {
342
+ // modified Object.keys to Object.getOwnPropertyNames
343
+ // because Object.keys only returns enumerable properties
344
+ const descriptors = Object.getOwnPropertyNames(source).reduce((descriptors, key) => {
345
+ const descriptor = Object.getOwnPropertyDescriptor(source, key);
346
+ if (descriptor) {
347
+ descriptors[key] = Object.getOwnPropertyDescriptor(source, key);
348
+ }
349
+ return descriptors;
350
+ }, {});
351
+ // By default, Object.assign copies enumerable Symbols, too
352
+ Object.getOwnPropertySymbols(source).forEach(sym => {
353
+ const descriptor = Object.getOwnPropertyDescriptor(source, sym);
354
+ if (descriptor?.enumerable) {
355
+ descriptors[sym] = descriptor;
356
+ }
357
+ });
358
+ Object.defineProperties(target, descriptors);
359
+ });
360
+ return target;
361
+ }
362
+ export { iterateAsyncVoid } from '@whatwg-node/promise-helpers';
363
+ export function handleErrorFromRequestHandler(error, ResponseCtor) {
364
+ return new ResponseCtor(error.stack || error.message || error.toString(), {
365
+ status: error.status || 500,
366
+ });
367
+ }
368
+ export function isolateObject(originalCtx, waitUntilFn) {
369
+ if (originalCtx == null) {
370
+ if (waitUntilFn == null) {
371
+ return {};
372
+ }
373
+ return {
374
+ waitUntil: waitUntilFn,
375
+ };
376
+ }
377
+ return completeAssign(Object.create(originalCtx), {
378
+ waitUntil: waitUntilFn,
379
+ }, originalCtx);
380
+ }
381
+ export function handleAbortSignalAndPromiseResponse(response$, abortSignal) {
382
+ if (abortSignal?.aborted) {
383
+ throw abortSignal.reason;
384
+ }
385
+ if (isPromise(response$) && abortSignal) {
386
+ const deferred$ = createDeferredPromise();
387
+ function abortSignalFetchErrorHandler() {
388
+ deferred$.reject(abortSignal.reason);
389
+ }
390
+ abortSignal.addEventListener('abort', abortSignalFetchErrorHandler, { once: true });
391
+ response$
392
+ .then(function fetchSuccessHandler(res) {
393
+ deferred$.resolve(res);
394
+ })
395
+ .catch(function fetchErrorHandler(err) {
396
+ deferred$.reject(err);
397
+ })
398
+ .finally(() => {
399
+ abortSignal.removeEventListener('abort', abortSignalFetchErrorHandler);
400
+ });
401
+ return deferred$.promise;
402
+ }
403
+ return response$;
404
+ }
405
+ export const decompressedResponseMap = new WeakMap();
406
+ const supportedEncodingsByFetchAPI = new WeakMap();
407
+ export function getSupportedEncodings(fetchAPI) {
408
+ let supportedEncodings = supportedEncodingsByFetchAPI.get(fetchAPI);
409
+ if (!supportedEncodings) {
410
+ const possibleEncodings = [
411
+ 'deflate',
412
+ 'gzip',
413
+ 'deflate-raw',
414
+ 'br',
415
+ 'zstd',
416
+ ];
417
+ if (fetchAPI.DecompressionStream?.['supportedFormats']) {
418
+ supportedEncodings = fetchAPI.DecompressionStream['supportedFormats'];
419
+ }
420
+ else {
421
+ supportedEncodings = possibleEncodings.filter(encoding => {
422
+ // deflate-raw is not supported in Node.js >v20
423
+ if (globalThis.process?.version?.startsWith('v2') &&
424
+ fetchAPI.DecompressionStream === globalThis.DecompressionStream &&
425
+ encoding === 'deflate-raw') {
426
+ return false;
427
+ }
428
+ try {
429
+ // eslint-disable-next-line no-new
430
+ new fetchAPI.DecompressionStream(encoding);
431
+ return true;
432
+ }
433
+ catch {
434
+ return false;
435
+ }
436
+ });
437
+ }
438
+ supportedEncodingsByFetchAPI.set(fetchAPI, supportedEncodings);
439
+ }
440
+ return supportedEncodings;
441
+ }
442
+ export function handleResponseDecompression(response, fetchAPI) {
443
+ const contentEncodingHeader = response?.headers.get('content-encoding');
444
+ if (!contentEncodingHeader || contentEncodingHeader === 'none') {
445
+ return response;
446
+ }
447
+ if (!response?.body) {
448
+ return response;
449
+ }
450
+ let decompressedResponse = decompressedResponseMap.get(response);
451
+ if (!decompressedResponse || decompressedResponse.bodyUsed) {
452
+ let decompressedBody = response.body;
453
+ const contentEncodings = contentEncodingHeader.split(',');
454
+ if (!contentEncodings.every(encoding => getSupportedEncodings(fetchAPI).includes(encoding))) {
455
+ return new fetchAPI.Response(`Unsupported 'Content-Encoding': ${contentEncodingHeader}`, {
456
+ status: 415,
457
+ statusText: 'Unsupported Media Type',
458
+ });
459
+ }
460
+ for (const contentEncoding of contentEncodings) {
461
+ decompressedBody = decompressedBody.pipeThrough(new fetchAPI.DecompressionStream(contentEncoding));
462
+ }
463
+ decompressedResponse = new fetchAPI.Response(decompressedBody, response);
464
+ decompressedResponseMap.set(response, decompressedResponse);
465
+ }
466
+ return decompressedResponse;
467
+ }
468
+ const terminateEvents = ['SIGINT', 'exit', 'SIGTERM'];
469
+ const disposableStacks = new Set();
470
+ let eventListenerRegistered = false;
471
+ function ensureEventListenerForDisposableStacks() {
472
+ if (eventListenerRegistered) {
473
+ return;
474
+ }
475
+ eventListenerRegistered = true;
476
+ for (const event of terminateEvents) {
477
+ globalThis.process.once(event, function terminateHandler() {
478
+ return Promise.allSettled([...disposableStacks].map(stack => !stack.disposed && stack.disposeAsync()));
479
+ });
480
+ }
481
+ }
482
+ export function ensureDisposableStackRegisteredForTerminateEvents(disposableStack) {
483
+ if (globalThis.process) {
484
+ ensureEventListenerForDisposableStacks();
485
+ if (!disposableStacks.has(disposableStack)) {
486
+ disposableStacks.add(disposableStack);
487
+ disposableStack.defer(() => {
488
+ disposableStacks.delete(disposableStack);
489
+ });
490
+ }
491
+ }
492
+ }
493
+ class CustomAbortControllerSignal extends EventTarget {
494
+ aborted = false;
495
+ _onabort = null;
496
+ _reason;
497
+ constructor() {
498
+ super();
499
+ const nodeEvents = globalThis.process?.getBuiltinModule?.('node:events');
500
+ // @ts-expect-error - We know kMaxEventTargetListeners is available in node:events
501
+ if (nodeEvents?.kMaxEventTargetListeners) {
502
+ // @ts-expect-error - See https://github.com/nodejs/node/pull/55816/files#diff-03bd4f07a1006cb0daaddced702858751b20f5ab7681cb0719c1b1d80d6ca05cR31
503
+ this[nodeEvents.kMaxEventTargetListeners] = 0;
504
+ }
505
+ }
506
+ throwIfAborted() {
507
+ if (this._nativeCtrl?.signal?.throwIfAborted) {
508
+ return this._nativeCtrl.signal.throwIfAborted();
509
+ }
510
+ if (this.aborted) {
511
+ throw this._reason;
512
+ }
513
+ }
514
+ _nativeCtrl;
515
+ ensureNativeCtrl() {
516
+ if (!this._nativeCtrl) {
517
+ const isAborted = this.aborted;
518
+ this._nativeCtrl = new AbortController();
519
+ if (isAborted) {
520
+ this._nativeCtrl.abort(this._reason);
521
+ }
522
+ }
523
+ return this._nativeCtrl;
524
+ }
525
+ abort(reason) {
526
+ if (this._nativeCtrl?.abort) {
527
+ return this._nativeCtrl?.abort(reason);
528
+ }
529
+ this._reason = reason || new DOMException('This operation was aborted', 'AbortError');
530
+ this.aborted = true;
531
+ this.dispatchEvent(new Event('abort'));
532
+ }
533
+ get signal() {
534
+ if (this._nativeCtrl?.signal) {
535
+ return this._nativeCtrl.signal;
536
+ }
537
+ return this;
538
+ }
539
+ get reason() {
540
+ if (this._nativeCtrl?.signal) {
541
+ return this._nativeCtrl.signal.reason;
542
+ }
543
+ return this._reason;
544
+ }
545
+ get onabort() {
546
+ if (this._onabort) {
547
+ return this._onabort;
548
+ }
549
+ return this._onabort;
550
+ }
551
+ set onabort(value) {
552
+ if (this._nativeCtrl?.signal) {
553
+ this._nativeCtrl.signal.onabort = value;
554
+ return;
555
+ }
556
+ if (this._onabort) {
557
+ this.removeEventListener('abort', this._onabort);
558
+ }
559
+ this._onabort = value;
560
+ if (value) {
561
+ this.addEventListener('abort', value);
562
+ }
563
+ }
564
+ }
565
+ export function createCustomAbortControllerSignal() {
566
+ if (globalThis.Bun || globalThis.Deno) {
567
+ return new AbortController();
568
+ }
569
+ return new Proxy(new CustomAbortControllerSignal(), {
570
+ get(target, prop, receiver) {
571
+ if (prop.toString().includes('kDependantSignals')) {
572
+ const nativeCtrl = target.ensureNativeCtrl();
573
+ return Reflect.get(nativeCtrl.signal, prop, nativeCtrl.signal);
574
+ }
575
+ return Reflect.get(target, prop, receiver);
576
+ },
577
+ set(target, prop, value, receiver) {
578
+ if (prop.toString().includes('kDependantSignals')) {
579
+ const nativeCtrl = target.ensureNativeCtrl();
580
+ return Reflect.set(nativeCtrl.signal, prop, value, nativeCtrl.signal);
581
+ }
582
+ return Reflect.set(target, prop, value, receiver);
583
+ },
584
+ getPrototypeOf() {
585
+ return AbortSignal.prototype;
586
+ },
587
+ });
588
+ }