@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,241 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.fakePromise = void 0;
4
+ exports.isUWSResponse = isUWSResponse;
5
+ exports.getRequestFromUWSRequest = getRequestFromUWSRequest;
6
+ exports.createWritableFromUWS = createWritableFromUWS;
7
+ exports.sendResponseToUwsOpts = sendResponseToUwsOpts;
8
+ const promise_helpers_1 = require("@whatwg-node/promise-helpers");
9
+ Object.defineProperty(exports, "fakePromise", { enumerable: true, get: function () { return promise_helpers_1.fakePromise; } });
10
+ function isUWSResponse(res) {
11
+ return !!res.onData;
12
+ }
13
+ function getRequestFromUWSRequest({ req, res, fetchAPI, controller, }) {
14
+ const method = req.getMethod();
15
+ let duplex;
16
+ const chunks = [];
17
+ const pushFns = [
18
+ (chunk) => {
19
+ chunks.push(chunk);
20
+ },
21
+ ];
22
+ const push = (chunk) => {
23
+ for (const pushFn of pushFns) {
24
+ pushFn(chunk);
25
+ }
26
+ };
27
+ let stopped = false;
28
+ const stopFns = [
29
+ () => {
30
+ stopped = true;
31
+ },
32
+ ];
33
+ const stop = () => {
34
+ for (const stopFn of stopFns) {
35
+ stopFn();
36
+ }
37
+ };
38
+ res.onData(function (ab, isLast) {
39
+ push(Buffer.from(Buffer.from(ab, 0, ab.byteLength)));
40
+ if (isLast) {
41
+ stop();
42
+ }
43
+ });
44
+ let getReadableStream;
45
+ if (method !== 'get' && method !== 'head') {
46
+ duplex = 'half';
47
+ controller.signal.addEventListener('abort', () => {
48
+ stop();
49
+ }, { once: true });
50
+ let readableStream;
51
+ getReadableStream = () => {
52
+ if (!readableStream) {
53
+ readableStream = new fetchAPI.ReadableStream({
54
+ start(streamCtrl) {
55
+ for (const chunk of chunks) {
56
+ streamCtrl.enqueue(chunk);
57
+ }
58
+ if (stopped) {
59
+ streamCtrl.close();
60
+ return;
61
+ }
62
+ pushFns.push((chunk) => {
63
+ streamCtrl.enqueue(chunk);
64
+ });
65
+ stopFns.push(() => {
66
+ if (controller.signal.reason) {
67
+ streamCtrl.error(controller.signal.reason);
68
+ return;
69
+ }
70
+ if (streamCtrl.desiredSize) {
71
+ streamCtrl.close();
72
+ }
73
+ });
74
+ },
75
+ });
76
+ }
77
+ return readableStream;
78
+ };
79
+ }
80
+ const headers = new fetchAPI.Headers();
81
+ req.forEach((key, value) => {
82
+ headers.append(key, value);
83
+ });
84
+ let url = `http://localhost${req.getUrl()}`;
85
+ const query = req.getQuery();
86
+ if (query) {
87
+ url += `?${query}`;
88
+ }
89
+ let buffer;
90
+ function getBody() {
91
+ if (!getReadableStream) {
92
+ return null;
93
+ }
94
+ if (stopped) {
95
+ return getBufferFromChunks();
96
+ }
97
+ return getReadableStream();
98
+ }
99
+ const request = new fetchAPI.Request(url, {
100
+ method,
101
+ headers,
102
+ get body() {
103
+ return getBody();
104
+ },
105
+ signal: controller.signal,
106
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
107
+ // @ts-ignore - not in the TS types yet
108
+ duplex,
109
+ });
110
+ function getBufferFromChunks() {
111
+ if (!buffer) {
112
+ buffer = chunks.length === 1 ? chunks[0] : Buffer.concat(chunks);
113
+ }
114
+ return buffer;
115
+ }
116
+ function collectBuffer() {
117
+ if (stopped) {
118
+ return (0, promise_helpers_1.fakePromise)(getBufferFromChunks());
119
+ }
120
+ return new Promise((resolve, reject) => {
121
+ try {
122
+ stopFns.push(() => {
123
+ resolve(getBufferFromChunks());
124
+ });
125
+ }
126
+ catch (e) {
127
+ reject(e);
128
+ }
129
+ });
130
+ }
131
+ Object.defineProperties(request, {
132
+ body: {
133
+ get() {
134
+ return getBody();
135
+ },
136
+ configurable: true,
137
+ enumerable: true,
138
+ },
139
+ json: {
140
+ value() {
141
+ return collectBuffer()
142
+ .then(b => b.toString('utf8'))
143
+ .then(t => JSON.parse(t));
144
+ },
145
+ configurable: true,
146
+ enumerable: true,
147
+ },
148
+ text: {
149
+ value() {
150
+ return collectBuffer().then(b => b.toString('utf8'));
151
+ },
152
+ configurable: true,
153
+ enumerable: true,
154
+ },
155
+ arrayBuffer: {
156
+ value() {
157
+ return collectBuffer();
158
+ },
159
+ configurable: true,
160
+ enumerable: true,
161
+ },
162
+ });
163
+ return request;
164
+ }
165
+ function createWritableFromUWS(uwsResponse, fetchAPI) {
166
+ return new fetchAPI.WritableStream({
167
+ write(chunk) {
168
+ uwsResponse.cork(() => {
169
+ uwsResponse.write(chunk);
170
+ });
171
+ },
172
+ close() {
173
+ uwsResponse.cork(() => {
174
+ uwsResponse.end();
175
+ });
176
+ },
177
+ });
178
+ }
179
+ function sendResponseToUwsOpts(uwsResponse, fetchResponse, controller, fetchAPI) {
180
+ if (!fetchResponse) {
181
+ uwsResponse.writeStatus('404 Not Found');
182
+ uwsResponse.end();
183
+ return;
184
+ }
185
+ const bufferOfRes = fetchResponse._buffer;
186
+ // @ts-expect-error - Handle the case where the response is a string
187
+ const strBody = fetchResponse['bodyType'] === 'String' ? fetchResponse.bodyInit : undefined;
188
+ if (controller.signal.aborted) {
189
+ return;
190
+ }
191
+ uwsResponse.cork(() => {
192
+ uwsResponse.writeStatus(`${fetchResponse.status} ${fetchResponse.statusText}`);
193
+ let isSetCookieHandled = false;
194
+ for (const [key, value] of fetchResponse.headers) {
195
+ // content-length causes an error with Node.js's fetch
196
+ if (key !== 'content-length') {
197
+ if (key === 'set-cookie') {
198
+ if (isSetCookieHandled) {
199
+ continue;
200
+ }
201
+ isSetCookieHandled = true;
202
+ const setCookies = fetchResponse.headers.getSetCookie?.();
203
+ if (setCookies) {
204
+ for (const setCookie of setCookies) {
205
+ uwsResponse.writeHeader(key, setCookie);
206
+ }
207
+ continue;
208
+ }
209
+ }
210
+ uwsResponse.writeHeader(key, value);
211
+ }
212
+ }
213
+ if (strBody) {
214
+ uwsResponse.end(strBody);
215
+ }
216
+ else if (bufferOfRes) {
217
+ uwsResponse.end(bufferOfRes);
218
+ }
219
+ else if (!fetchResponse.body) {
220
+ uwsResponse.end();
221
+ }
222
+ });
223
+ if (strBody || bufferOfRes || !fetchResponse.body) {
224
+ return;
225
+ }
226
+ controller.signal.addEventListener('abort', () => {
227
+ if (!fetchResponse.body?.locked) {
228
+ fetchResponse.body?.cancel(controller.signal.reason);
229
+ }
230
+ }, { once: true });
231
+ return fetchResponse.body
232
+ .pipeTo(createWritableFromUWS(uwsResponse, fetchAPI), {
233
+ signal: controller.signal,
234
+ })
235
+ .catch(err => {
236
+ if (controller.signal.aborted) {
237
+ return;
238
+ }
239
+ throw err;
240
+ });
241
+ }
@@ -0,0 +1,365 @@
1
+ import { chain, getInstrumented } from '@envelop/instrumentation';
2
+ import { AsyncDisposableStack, DisposableSymbols } from '@whatwg-node/disposablestack';
3
+ import { handleMaybePromise, unfakePromise } from '@whatwg-node/promise-helpers';
4
+ import { completeAssign, createCustomAbortControllerSignal, ensureDisposableStackRegisteredForTerminateEvents, handleAbortSignalAndPromiseResponse, handleErrorFromRequestHandler, isFetchEvent, isNodeRequest, isolateObject, isPromise, isRequestInit, isServerResponse, iterateAsyncVoid, normalizeNodeRequest, sendNodeResponse, } from './utils.js';
5
+ import { fakePromise, getRequestFromUWSRequest, isUWSResponse, sendResponseToUwsOpts, } from './uwebsockets.js';
6
+ // Required for envs like nextjs edge runtime
7
+ function isRequestAccessible(serverContext) {
8
+ try {
9
+ return !!serverContext?.request;
10
+ }
11
+ catch {
12
+ return false;
13
+ }
14
+ }
15
+ const EMPTY_OBJECT = {};
16
+ function createServerAdapter(serverAdapterBaseObject, options) {
17
+ const useSingleWriteHead = options?.__useSingleWriteHead == null ? true : options.__useSingleWriteHead;
18
+ const fetchAPI = {
19
+ ...options?.fetchAPI,
20
+ };
21
+ const useCustomAbortCtrl = options?.__useCustomAbortCtrl == null
22
+ ? fetchAPI.Request !== globalThis.Request
23
+ : options.__useCustomAbortCtrl;
24
+ const givenHandleRequest = typeof serverAdapterBaseObject === 'function'
25
+ ? serverAdapterBaseObject
26
+ : serverAdapterBaseObject.handle;
27
+ const onRequestHooks = [];
28
+ const onResponseHooks = [];
29
+ let instrumentation;
30
+ const waitUntilPromises = new Set();
31
+ let _disposableStack;
32
+ function ensureDisposableStack() {
33
+ if (!_disposableStack) {
34
+ _disposableStack = new AsyncDisposableStack();
35
+ if (options?.disposeOnProcessTerminate) {
36
+ ensureDisposableStackRegisteredForTerminateEvents(_disposableStack);
37
+ }
38
+ _disposableStack.defer(() => {
39
+ if (waitUntilPromises.size > 0) {
40
+ return Promise.allSettled(waitUntilPromises).then(() => {
41
+ waitUntilPromises.clear();
42
+ }, () => {
43
+ waitUntilPromises.clear();
44
+ });
45
+ }
46
+ });
47
+ }
48
+ return _disposableStack;
49
+ }
50
+ function waitUntil(maybePromise) {
51
+ // Ensure that the disposable stack is created
52
+ if (isPromise(maybePromise)) {
53
+ ensureDisposableStack();
54
+ waitUntilPromises.add(maybePromise);
55
+ maybePromise.then(() => {
56
+ waitUntilPromises.delete(maybePromise);
57
+ }, err => {
58
+ console.error(`Unexpected error while waiting: ${err.message || err}`);
59
+ waitUntilPromises.delete(maybePromise);
60
+ });
61
+ }
62
+ }
63
+ if (options?.plugins != null) {
64
+ for (const plugin of options.plugins) {
65
+ if (plugin.instrumentation) {
66
+ instrumentation = instrumentation
67
+ ? chain(instrumentation, plugin.instrumentation)
68
+ : plugin.instrumentation;
69
+ }
70
+ if (plugin.onRequest) {
71
+ onRequestHooks.push(plugin.onRequest);
72
+ }
73
+ if (plugin.onResponse) {
74
+ onResponseHooks.push(plugin.onResponse);
75
+ }
76
+ const disposeFn = plugin[DisposableSymbols.dispose];
77
+ if (disposeFn) {
78
+ ensureDisposableStack().defer(disposeFn);
79
+ }
80
+ const asyncDisposeFn = plugin[DisposableSymbols.asyncDispose];
81
+ if (asyncDisposeFn) {
82
+ ensureDisposableStack().defer(asyncDisposeFn);
83
+ }
84
+ if (plugin.onDispose) {
85
+ ensureDisposableStack().defer(plugin.onDispose);
86
+ }
87
+ }
88
+ }
89
+ let handleRequest = onRequestHooks.length > 0 || onResponseHooks.length > 0
90
+ ? function handleRequest(request, serverContext) {
91
+ let requestHandler = givenHandleRequest;
92
+ let response;
93
+ if (onRequestHooks.length === 0) {
94
+ return handleEarlyResponse();
95
+ }
96
+ let url = request['parsedUrl'] ||
97
+ new Proxy(EMPTY_OBJECT, {
98
+ get(_target, prop, _receiver) {
99
+ url = new fetchAPI.URL(request.url, 'http://localhost');
100
+ return Reflect.get(url, prop, url);
101
+ },
102
+ });
103
+ function handleResponse(response) {
104
+ if (onResponseHooks.length === 0) {
105
+ return response;
106
+ }
107
+ return handleMaybePromise(() => iterateAsyncVoid(onResponseHooks, onResponseHook => onResponseHook({
108
+ request,
109
+ response,
110
+ serverContext,
111
+ setResponse(newResponse) {
112
+ response = newResponse;
113
+ },
114
+ fetchAPI,
115
+ })), () => response);
116
+ }
117
+ function handleEarlyResponse() {
118
+ if (!response) {
119
+ return handleMaybePromise(() => requestHandler(request, serverContext), handleResponse);
120
+ }
121
+ return handleResponse(response);
122
+ }
123
+ return handleMaybePromise(() => iterateAsyncVoid(onRequestHooks, (onRequestHook, stopEarly) => onRequestHook({
124
+ request,
125
+ setRequest(newRequest) {
126
+ request = newRequest;
127
+ },
128
+ serverContext,
129
+ fetchAPI,
130
+ url,
131
+ requestHandler,
132
+ setRequestHandler(newRequestHandler) {
133
+ requestHandler = newRequestHandler;
134
+ },
135
+ endResponse(newResponse) {
136
+ response = newResponse;
137
+ if (newResponse) {
138
+ stopEarly();
139
+ }
140
+ },
141
+ })), handleEarlyResponse);
142
+ }
143
+ : givenHandleRequest;
144
+ if (instrumentation?.request) {
145
+ const originalRequestHandler = handleRequest;
146
+ handleRequest = (request, initialContext) => {
147
+ return getInstrumented({ request }).asyncFn(instrumentation.request, originalRequestHandler)(request, initialContext);
148
+ };
149
+ }
150
+ // TODO: Remove this on the next major version
151
+ function handleNodeRequest(nodeRequest, ...ctx) {
152
+ const serverContext = ctx.length > 1 ? completeAssign(...ctx) : ctx[0] || {};
153
+ // Ensure `waitUntil` is available in the server context
154
+ if (!serverContext.waitUntil) {
155
+ serverContext.waitUntil = waitUntil;
156
+ }
157
+ const request = normalizeNodeRequest(nodeRequest, fetchAPI, undefined, useCustomAbortCtrl);
158
+ return handleRequest(request, serverContext);
159
+ }
160
+ function handleNodeRequestAndResponse(nodeRequest, nodeResponseOrContainer, ...ctx) {
161
+ const nodeResponse = nodeResponseOrContainer.raw || nodeResponseOrContainer;
162
+ const serverContext = ctx.length > 1 ? completeAssign(...ctx) : ctx[0] || {};
163
+ // Ensure `waitUntil` is available in the server context
164
+ if (!serverContext.waitUntil) {
165
+ serverContext.waitUntil = waitUntil;
166
+ }
167
+ const request = normalizeNodeRequest(nodeRequest, fetchAPI, nodeResponse, useCustomAbortCtrl);
168
+ return handleRequest(request, serverContext);
169
+ }
170
+ function requestListener(nodeRequest, nodeResponse, ...ctx) {
171
+ const defaultServerContext = {
172
+ req: nodeRequest,
173
+ res: nodeResponse,
174
+ waitUntil,
175
+ };
176
+ return unfakePromise(fakePromise()
177
+ .then(() => handleNodeRequestAndResponse(nodeRequest, nodeResponse, defaultServerContext, ...ctx))
178
+ .catch(err => handleErrorFromRequestHandler(err, fetchAPI.Response))
179
+ .then(response => sendNodeResponse(response, nodeResponse, nodeRequest, useSingleWriteHead))
180
+ .catch(err => console.error(`Unexpected error while handling request: ${err.message || err}`)));
181
+ }
182
+ function handleUWS(res, req, ...ctx) {
183
+ const defaultServerContext = {
184
+ res,
185
+ req,
186
+ waitUntil,
187
+ };
188
+ const filteredCtxParts = ctx.filter(partCtx => partCtx != null);
189
+ const serverContext = filteredCtxParts.length > 0
190
+ ? completeAssign(defaultServerContext, ...ctx)
191
+ : defaultServerContext;
192
+ const controller = useCustomAbortCtrl
193
+ ? createCustomAbortControllerSignal()
194
+ : new AbortController();
195
+ const originalResEnd = res.end.bind(res);
196
+ let resEnded = false;
197
+ res.end = function (data) {
198
+ resEnded = true;
199
+ return originalResEnd(data);
200
+ };
201
+ const originalOnAborted = res.onAborted.bind(res);
202
+ originalOnAborted(function () {
203
+ controller.abort();
204
+ });
205
+ res.onAborted = function (cb) {
206
+ controller.signal.addEventListener('abort', cb, { once: true });
207
+ };
208
+ const request = getRequestFromUWSRequest({
209
+ req,
210
+ res,
211
+ fetchAPI,
212
+ controller,
213
+ });
214
+ return handleMaybePromise(() => handleMaybePromise(() => handleRequest(request, serverContext), response => response, err => handleErrorFromRequestHandler(err, fetchAPI.Response)), response => {
215
+ if (!controller.signal.aborted && !resEnded) {
216
+ return handleMaybePromise(() => sendResponseToUwsOpts(res, response, controller, fetchAPI), r => r, err => {
217
+ console.error(`Unexpected error while handling request: ${err.message || err}`);
218
+ });
219
+ }
220
+ });
221
+ }
222
+ function handleEvent(event, ...ctx) {
223
+ if (!event.respondWith || !event.request) {
224
+ throw new TypeError(`Expected FetchEvent, got ${event}`);
225
+ }
226
+ const filteredCtxParts = ctx.filter(partCtx => partCtx != null);
227
+ const serverContext = filteredCtxParts.length > 0
228
+ ? completeAssign({}, event, ...filteredCtxParts)
229
+ : isolateObject(event);
230
+ const response$ = handleRequest(event.request, serverContext);
231
+ event.respondWith(response$);
232
+ }
233
+ function handleRequestWithWaitUntil(request, ...ctx) {
234
+ const filteredCtxParts = ctx.filter(partCtx => partCtx != null);
235
+ const serverContext = filteredCtxParts.length > 1
236
+ ? completeAssign({}, ...filteredCtxParts)
237
+ : isolateObject(filteredCtxParts[0], filteredCtxParts[0] == null || filteredCtxParts[0].waitUntil == null
238
+ ? waitUntil
239
+ : undefined);
240
+ return handleRequest(request, serverContext);
241
+ }
242
+ const fetchFn = (input, ...maybeCtx) => {
243
+ if (typeof input === 'string' || 'href' in input) {
244
+ const [initOrCtx, ...restOfCtx] = maybeCtx;
245
+ if (isRequestInit(initOrCtx)) {
246
+ const request = new fetchAPI.Request(input, initOrCtx);
247
+ const res$ = handleRequestWithWaitUntil(request, ...restOfCtx);
248
+ const signal = initOrCtx.signal;
249
+ if (signal) {
250
+ return handleAbortSignalAndPromiseResponse(res$, signal);
251
+ }
252
+ return res$;
253
+ }
254
+ const request = new fetchAPI.Request(input);
255
+ return handleRequestWithWaitUntil(request, ...maybeCtx);
256
+ }
257
+ const res$ = handleRequestWithWaitUntil(input, ...maybeCtx);
258
+ return handleAbortSignalAndPromiseResponse(res$, input.signal);
259
+ };
260
+ const genericRequestHandler = (input, ...maybeCtx) => {
261
+ // If it is a Node request
262
+ const [initOrCtxOrRes, ...restOfCtx] = maybeCtx;
263
+ if (isNodeRequest(input)) {
264
+ if (!isServerResponse(initOrCtxOrRes)) {
265
+ throw new TypeError(`Expected ServerResponse, got ${initOrCtxOrRes}`);
266
+ }
267
+ return requestListener(input, initOrCtxOrRes, ...restOfCtx);
268
+ }
269
+ if (isUWSResponse(input)) {
270
+ return handleUWS(input, initOrCtxOrRes, ...restOfCtx);
271
+ }
272
+ if (isServerResponse(initOrCtxOrRes)) {
273
+ throw new TypeError('Got Node response without Node request');
274
+ }
275
+ // Is input a container object over Request?
276
+ if (isRequestAccessible(input)) {
277
+ // Is it FetchEvent?
278
+ if (isFetchEvent(input)) {
279
+ return handleEvent(input, ...maybeCtx);
280
+ }
281
+ // In this input is also the context
282
+ return handleRequestWithWaitUntil(input.request, input, ...maybeCtx);
283
+ }
284
+ // Or is it Request itself?
285
+ // Then ctx is present and it is the context
286
+ return fetchFn(input, ...maybeCtx);
287
+ };
288
+ const adapterObj = {
289
+ handleRequest: handleRequestWithWaitUntil,
290
+ fetch: fetchFn,
291
+ handleNodeRequest,
292
+ handleNodeRequestAndResponse,
293
+ requestListener,
294
+ handleEvent,
295
+ handleUWS,
296
+ handle: genericRequestHandler,
297
+ get disposableStack() {
298
+ return ensureDisposableStack();
299
+ },
300
+ [DisposableSymbols.asyncDispose]() {
301
+ if (_disposableStack && !_disposableStack.disposed) {
302
+ return _disposableStack.disposeAsync();
303
+ }
304
+ return fakePromise();
305
+ },
306
+ dispose() {
307
+ if (_disposableStack && !_disposableStack.disposed) {
308
+ return _disposableStack.disposeAsync();
309
+ }
310
+ return fakePromise();
311
+ },
312
+ waitUntil,
313
+ };
314
+ const serverAdapter = new Proxy(genericRequestHandler, {
315
+ // It should have all the attributes of the handler function and the server instance
316
+ has: (_, prop) => {
317
+ return (prop in adapterObj ||
318
+ prop in genericRequestHandler ||
319
+ (serverAdapterBaseObject && prop in serverAdapterBaseObject));
320
+ },
321
+ get: (_, prop) => {
322
+ // Somehow Deno and Node 24 don't like bound dispose functions
323
+ if (globalThis.Deno || prop === Symbol.asyncDispose || prop === Symbol.dispose) {
324
+ const adapterProp = Reflect.get(adapterObj, prop, adapterObj);
325
+ if (adapterProp) {
326
+ return adapterProp;
327
+ }
328
+ }
329
+ const adapterProp = adapterObj[prop];
330
+ if (adapterProp) {
331
+ if (adapterProp.bind) {
332
+ return adapterProp.bind(adapterObj);
333
+ }
334
+ return adapterProp;
335
+ }
336
+ const handleProp = genericRequestHandler[prop];
337
+ if (handleProp) {
338
+ if (handleProp.bind) {
339
+ return handleProp.bind(genericRequestHandler);
340
+ }
341
+ return handleProp;
342
+ }
343
+ if (serverAdapterBaseObject) {
344
+ const serverAdapterBaseObjectProp = serverAdapterBaseObject[prop];
345
+ if (serverAdapterBaseObjectProp) {
346
+ if (serverAdapterBaseObjectProp.bind) {
347
+ return function (...args) {
348
+ const returnedVal = serverAdapterBaseObject[prop](...args);
349
+ if (returnedVal === serverAdapterBaseObject) {
350
+ return serverAdapter;
351
+ }
352
+ return returnedVal;
353
+ };
354
+ }
355
+ return serverAdapterBaseObjectProp;
356
+ }
357
+ }
358
+ },
359
+ apply(_, __, args) {
360
+ return genericRequestHandler(...args);
361
+ },
362
+ });
363
+ return serverAdapter;
364
+ }
365
+ export { createServerAdapter };
@@ -0,0 +1,11 @@
1
+ export * from './createServerAdapter.js';
2
+ export * from './types.js';
3
+ export * from './utils.js';
4
+ export * from './plugins/types.js';
5
+ export * from './plugins/useCors.js';
6
+ export * from './plugins/useErrorHandling.js';
7
+ export * from './plugins/useContentEncoding.js';
8
+ export * from './uwebsockets.js';
9
+ export { Response } from '@whatwg-node/fetch';
10
+ export { DisposableSymbols } from '@whatwg-node/disposablestack';
11
+ export * from '@envelop/instrumentation';
@@ -0,0 +1,70 @@
1
+ import { decompressedResponseMap, getSupportedEncodings } from '../utils.js';
2
+ const emptyEncodings = ['none', 'identity'];
3
+ export function useContentEncoding() {
4
+ return {
5
+ onRequest({ request, setRequest, fetchAPI, endResponse }) {
6
+ const contentEncodingHeader = request.headers.get('content-encoding');
7
+ if (contentEncodingHeader &&
8
+ contentEncodingHeader !== 'none' &&
9
+ contentEncodingHeader !== 'identity' &&
10
+ request.body) {
11
+ const contentEncodings = contentEncodingHeader
12
+ .split(',')
13
+ .filter(encoding => !emptyEncodings.includes(encoding));
14
+ if (contentEncodings.length) {
15
+ if (!contentEncodings.every(encoding => getSupportedEncodings(fetchAPI).includes(encoding))) {
16
+ endResponse(new fetchAPI.Response(`Unsupported 'Content-Encoding': ${contentEncodingHeader}`, {
17
+ status: 415,
18
+ statusText: 'Unsupported Media Type',
19
+ }));
20
+ return;
21
+ }
22
+ let newBody = request.body;
23
+ for (const contentEncoding of contentEncodings) {
24
+ newBody = request.body.pipeThrough(new fetchAPI.DecompressionStream(contentEncoding));
25
+ }
26
+ setRequest(new fetchAPI.Request(request.url, {
27
+ body: newBody,
28
+ cache: request.cache,
29
+ credentials: request.credentials,
30
+ headers: request.headers,
31
+ integrity: request.integrity,
32
+ keepalive: request.keepalive,
33
+ method: request.method,
34
+ mode: request.mode,
35
+ redirect: request.redirect,
36
+ referrer: request.referrer,
37
+ referrerPolicy: request.referrerPolicy,
38
+ signal: request.signal,
39
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
40
+ // @ts-ignore - not in the TS types yet
41
+ duplex: 'half',
42
+ }));
43
+ }
44
+ }
45
+ },
46
+ onResponse({ request, response, setResponse, fetchAPI }) {
47
+ const acceptEncoding = request.headers.get('accept-encoding');
48
+ if (acceptEncoding) {
49
+ const encodings = acceptEncoding.split(',');
50
+ if (encodings.length && response.body) {
51
+ const supportedEncoding = encodings.find(encoding => getSupportedEncodings(fetchAPI).includes(encoding));
52
+ if (supportedEncoding) {
53
+ const compressionStream = new fetchAPI.CompressionStream(supportedEncoding);
54
+ const newHeaders = new fetchAPI.Headers(response.headers);
55
+ newHeaders.set('content-encoding', supportedEncoding);
56
+ newHeaders.delete('content-length');
57
+ const compressedBody = response.body.pipeThrough(compressionStream);
58
+ const compressedResponse = new fetchAPI.Response(compressedBody, {
59
+ status: response.status,
60
+ statusText: response.statusText,
61
+ headers: newHeaders,
62
+ });
63
+ decompressedResponseMap.set(compressedResponse, response);
64
+ setResponse(compressedResponse);
65
+ }
66
+ }
67
+ }
68
+ },
69
+ };
70
+ }