@whatwg-node/server 0.10.0-alpha-20240726141316-c6ce93b3598457ebe73b3b725986723af8f5e609 → 0.10.0-alpha-20241125124208-52a1220ca8b2a3b86a8338c8f96b80dde432e1bb

Sign up to get free protection for your applications and to get access to all the features.
package/esm/utils.js CHANGED
@@ -1,4 +1,3 @@
1
- import { URL } from '@whatwg-node/fetch';
2
1
  export function isAsyncIterable(body) {
3
2
  return (body != null && typeof body === 'object' && typeof body[Symbol.asyncIterator] === 'function');
4
3
  }
@@ -49,11 +48,9 @@ function isRequestBody(body) {
49
48
  return false;
50
49
  }
51
50
  export class ServerAdapterRequestAbortSignal extends EventTarget {
52
- constructor() {
53
- super(...arguments);
54
- this.aborted = false;
55
- this._onabort = null;
56
- }
51
+ aborted = false;
52
+ _onabort = null;
53
+ reason;
57
54
  throwIfAborted() {
58
55
  if (this.aborted) {
59
56
  throw this.reason;
@@ -81,17 +78,20 @@ export class ServerAdapterRequestAbortSignal extends EventTarget {
81
78
  }
82
79
  }
83
80
  let bunNodeCompatModeWarned = false;
84
- export function normalizeNodeRequest(nodeRequest, nodeResponse, RequestCtor) {
81
+ export const nodeRequestResponseMap = new WeakMap();
82
+ export function normalizeNodeRequest(nodeRequest, fetchAPI, registerSignal) {
85
83
  const rawRequest = nodeRequest.raw || nodeRequest.req || nodeRequest;
86
84
  let fullUrl = buildFullUrl(rawRequest);
87
85
  if (nodeRequest.query) {
88
- const url = new URL(fullUrl);
86
+ const url = new fetchAPI.URL(fullUrl);
89
87
  for (const key in nodeRequest.query) {
90
88
  url.searchParams.set(key, nodeRequest.query[key]);
91
89
  }
92
90
  fullUrl = url.toString();
93
91
  }
94
92
  let signal;
93
+ const nodeResponse = nodeRequestResponseMap.get(nodeRequest);
94
+ nodeRequestResponseMap.delete(nodeRequest);
95
95
  let normalizedHeaders = nodeRequest.headers;
96
96
  if (nodeRequest.headers?.[':method']) {
97
97
  normalizedHeaders = {};
@@ -104,8 +104,10 @@ export function normalizeNodeRequest(nodeRequest, nodeResponse, RequestCtor) {
104
104
  if (nodeResponse?.once) {
105
105
  let sendAbortSignal;
106
106
  // If ponyfilled
107
- if (RequestCtor !== globalThis.Request) {
108
- signal = new ServerAdapterRequestAbortSignal();
107
+ if (fetchAPI.Request !== globalThis.Request) {
108
+ const newSignal = new ServerAdapterRequestAbortSignal();
109
+ registerSignal?.(newSignal);
110
+ signal = newSignal;
109
111
  sendAbortSignal = () => signal.sendAbort();
110
112
  }
111
113
  else {
@@ -126,7 +128,7 @@ export function normalizeNodeRequest(nodeRequest, nodeResponse, RequestCtor) {
126
128
  });
127
129
  }
128
130
  if (nodeRequest.method === 'GET' || nodeRequest.method === 'HEAD') {
129
- return new RequestCtor(fullUrl, {
131
+ return new fetchAPI.Request(fullUrl, {
130
132
  method: nodeRequest.method,
131
133
  headers: normalizedHeaders,
132
134
  signal,
@@ -141,14 +143,14 @@ export function normalizeNodeRequest(nodeRequest, nodeResponse, RequestCtor) {
141
143
  const maybeParsedBody = nodeRequest.body;
142
144
  if (maybeParsedBody != null && Object.keys(maybeParsedBody).length > 0) {
143
145
  if (isRequestBody(maybeParsedBody)) {
144
- return new RequestCtor(fullUrl, {
146
+ return new fetchAPI.Request(fullUrl, {
145
147
  method: nodeRequest.method,
146
148
  headers: normalizedHeaders,
147
149
  body: maybeParsedBody,
148
150
  signal,
149
151
  });
150
152
  }
151
- const request = new RequestCtor(fullUrl, {
153
+ const request = new fetchAPI.Request(fullUrl, {
152
154
  method: nodeRequest.method,
153
155
  headers: normalizedHeaders,
154
156
  signal,
@@ -176,7 +178,7 @@ export function normalizeNodeRequest(nodeRequest, nodeResponse, RequestCtor) {
176
178
  console.warn(`You use Bun Node compatibility mode, which is not recommended!
177
179
  It will affect your performance. Please check our Bun integration recipe, and avoid using 'http' for your server implementation.`);
178
180
  }
179
- return new RequestCtor(fullUrl, {
181
+ return new fetchAPI.Request(fullUrl, {
180
182
  method: nodeRequest.method,
181
183
  headers: normalizedHeaders,
182
184
  duplex: 'half',
@@ -200,7 +202,7 @@ It will affect your performance. Please check our Bun integration recipe, and av
200
202
  });
201
203
  }
202
204
  // perf: instead of spreading the object, we can just pass it as is and it performs better
203
- return new RequestCtor(fullUrl, {
205
+ return new fetchAPI.Request(fullUrl, {
204
206
  method: nodeRequest.method,
205
207
  headers: normalizedHeaders,
206
208
  body: rawRequest,
@@ -238,11 +240,26 @@ function endResponse(serverResponse) {
238
240
  serverResponse.end(null, null, null);
239
241
  }
240
242
  async function sendAsyncIterable(serverResponse, asyncIterable) {
243
+ let closed = false;
244
+ const closeEventListener = () => {
245
+ closed = true;
246
+ };
247
+ serverResponse.once('error', closeEventListener);
248
+ serverResponse.once('close', closeEventListener);
249
+ serverResponse.once('finish', () => {
250
+ serverResponse.removeListener('close', closeEventListener);
251
+ });
241
252
  for await (const chunk of asyncIterable) {
253
+ if (closed) {
254
+ break;
255
+ }
242
256
  if (!serverResponse
243
257
  // @ts-expect-error http and http2 writes are actually compatible
244
258
  .write(chunk)) {
245
- break;
259
+ if (closed) {
260
+ break;
261
+ }
262
+ await new Promise(resolve => serverResponse.once('drain', resolve));
246
263
  }
247
264
  }
248
265
  endResponse(serverResponse);
@@ -253,7 +270,7 @@ export function sendNodeResponse(fetchResponse, serverResponse, nodeRequest) {
253
270
  }
254
271
  if (!fetchResponse) {
255
272
  serverResponse.statusCode = 404;
256
- serverResponse.end();
273
+ endResponse(serverResponse);
257
274
  return;
258
275
  }
259
276
  serverResponse.statusCode = fetchResponse.status;
@@ -302,10 +319,31 @@ export function sendNodeResponse(fetchResponse, serverResponse, nodeRequest) {
302
319
  fetchBody.pipe(serverResponse);
303
320
  return;
304
321
  }
322
+ if (isReadableStream(fetchBody)) {
323
+ return sendReadableStream(serverResponse, fetchBody);
324
+ }
305
325
  if (isAsyncIterable(fetchBody)) {
306
326
  return sendAsyncIterable(serverResponse, fetchBody);
307
327
  }
308
328
  }
329
+ async function sendReadableStream(serverResponse, readableStream) {
330
+ const reader = readableStream.getReader();
331
+ serverResponse.req.once('error', err => {
332
+ reader.cancel(err);
333
+ });
334
+ while (true) {
335
+ const { done, value } = await reader.read();
336
+ if (done) {
337
+ break;
338
+ }
339
+ if (!serverResponse
340
+ // @ts-expect-error http and http2 writes are actually compatible
341
+ .write(value)) {
342
+ await new Promise(resolve => serverResponse.once('drain', resolve));
343
+ }
344
+ }
345
+ endResponse(serverResponse);
346
+ }
309
347
  export function isRequestInit(val) {
310
348
  return (val != null &&
311
349
  typeof val === 'object' &&
@@ -382,77 +420,18 @@ export function handleErrorFromRequestHandler(error, ResponseCtor) {
382
420
  status: error.status || 500,
383
421
  });
384
422
  }
385
- export function isolateObject(originalCtx, waitUntilPromises) {
423
+ export function isolateObject(originalCtx, waitUntilFn) {
386
424
  if (originalCtx == null) {
387
- return {};
388
- }
389
- const extraProps = {};
390
- const deletedProps = new Set();
391
- return new Proxy(originalCtx, {
392
- get(originalCtx, prop) {
393
- if (waitUntilPromises != null && prop === 'waitUntil') {
394
- return function waitUntil(promise) {
395
- waitUntilPromises.push(promise.catch(err => console.error(err)));
396
- };
397
- }
398
- const extraPropVal = extraProps[prop];
399
- if (extraPropVal != null) {
400
- if (typeof extraPropVal === 'function') {
401
- return extraPropVal.bind(extraProps);
402
- }
403
- return extraPropVal;
404
- }
405
- if (deletedProps.has(prop)) {
406
- return undefined;
407
- }
408
- return originalCtx[prop];
409
- },
410
- set(_originalCtx, prop, value) {
411
- extraProps[prop] = value;
412
- return true;
413
- },
414
- has(originalCtx, prop) {
415
- if (waitUntilPromises != null && prop === 'waitUntil') {
416
- return true;
417
- }
418
- if (deletedProps.has(prop)) {
419
- return false;
420
- }
421
- if (prop in extraProps) {
422
- return true;
423
- }
424
- return prop in originalCtx;
425
- },
426
- defineProperty(_originalCtx, prop, descriptor) {
427
- return Reflect.defineProperty(extraProps, prop, descriptor);
428
- },
429
- deleteProperty(_originalCtx, prop) {
430
- if (prop in extraProps) {
431
- return Reflect.deleteProperty(extraProps, prop);
432
- }
433
- deletedProps.add(prop);
434
- return true;
435
- },
436
- ownKeys(originalCtx) {
437
- const extraKeys = Reflect.ownKeys(extraProps);
438
- const originalKeys = Reflect.ownKeys(originalCtx);
439
- const deletedKeys = Array.from(deletedProps);
440
- const allKeys = new Set(extraKeys.concat(originalKeys.filter(keys => !deletedKeys.includes(keys))));
441
- if (waitUntilPromises != null) {
442
- allKeys.add('waitUntil');
443
- }
444
- return Array.from(allKeys);
445
- },
446
- getOwnPropertyDescriptor(originalCtx, prop) {
447
- if (prop in extraProps) {
448
- return Reflect.getOwnPropertyDescriptor(extraProps, prop);
449
- }
450
- if (deletedProps.has(prop)) {
451
- return undefined;
452
- }
453
- return Reflect.getOwnPropertyDescriptor(originalCtx, prop);
454
- },
455
- });
425
+ if (waitUntilFn == null) {
426
+ return {};
427
+ }
428
+ return {
429
+ waitUntil: waitUntilFn,
430
+ };
431
+ }
432
+ return completeAssign(Object.create(originalCtx), {
433
+ waitUntil: waitUntilFn,
434
+ }, originalCtx);
456
435
  }
457
436
  export function createDeferredPromise() {
458
437
  let resolveFn;
@@ -494,22 +473,27 @@ export function getSupportedEncodings(fetchAPI) {
494
473
  let supportedEncodings = supportedEncodingsByFetchAPI.get(fetchAPI);
495
474
  if (!supportedEncodings) {
496
475
  const possibleEncodings = ['deflate', 'gzip', 'deflate-raw', 'br'];
497
- supportedEncodings = possibleEncodings.filter(encoding => {
498
- // deflate-raw is not supported in Node.js >v20
499
- if (globalThis.process?.version?.startsWith('v2') &&
500
- fetchAPI.DecompressionStream === globalThis.DecompressionStream &&
501
- encoding === 'deflate-raw') {
502
- return false;
503
- }
504
- try {
505
- // eslint-disable-next-line no-new
506
- new fetchAPI.DecompressionStream(encoding);
507
- return true;
508
- }
509
- catch {
510
- return false;
511
- }
512
- });
476
+ if (fetchAPI.DecompressionStream?.['supportedFormats']) {
477
+ supportedEncodings = fetchAPI.DecompressionStream['supportedFormats'];
478
+ }
479
+ else {
480
+ supportedEncodings = possibleEncodings.filter(encoding => {
481
+ // deflate-raw is not supported in Node.js >v20
482
+ if (globalThis.process?.version?.startsWith('v2') &&
483
+ fetchAPI.DecompressionStream === globalThis.DecompressionStream &&
484
+ encoding === 'deflate-raw') {
485
+ return false;
486
+ }
487
+ try {
488
+ // eslint-disable-next-line no-new
489
+ new fetchAPI.DecompressionStream(encoding);
490
+ return true;
491
+ }
492
+ catch {
493
+ return false;
494
+ }
495
+ });
496
+ }
513
497
  supportedEncodingsByFetchAPI.set(fetchAPI, supportedEncodings);
514
498
  }
515
499
  return supportedEncodings;
@@ -540,3 +524,31 @@ export function handleResponseDecompression(response, fetchAPI) {
540
524
  }
541
525
  return decompressedResponse;
542
526
  }
527
+ const terminateEvents = ['SIGINT', 'SIGTERM', 'exit'];
528
+ const disposableStacks = new Set();
529
+ let eventListenerRegistered = false;
530
+ function ensureEventListenerForDisposableStacks() {
531
+ if (eventListenerRegistered) {
532
+ return;
533
+ }
534
+ eventListenerRegistered = true;
535
+ for (const event of terminateEvents) {
536
+ globalThis.process.once(event, function terminateHandler() {
537
+ return Promise.allSettled([...disposableStacks].map(stack => !stack.disposed &&
538
+ stack.disposeAsync().catch(e => {
539
+ console.error('Error while disposing:', e);
540
+ })));
541
+ });
542
+ }
543
+ }
544
+ export function ensureDisposableStackRegisteredForTerminateEvents(disposableStack) {
545
+ if (globalThis.process) {
546
+ ensureEventListenerForDisposableStacks();
547
+ if (!disposableStacks.has(disposableStack)) {
548
+ disposableStacks.add(disposableStack);
549
+ disposableStack.defer(() => {
550
+ disposableStacks.delete(disposableStack);
551
+ });
552
+ }
553
+ }
554
+ }
@@ -1,46 +1,69 @@
1
+ import { isPromise } from './utils.js';
1
2
  export function isUWSResponse(res) {
2
3
  return !!res.onData;
3
4
  }
4
5
  export function getRequestFromUWSRequest({ req, res, fetchAPI, signal }) {
5
- let body;
6
6
  const method = req.getMethod();
7
- if (method !== 'get' && method !== 'head') {
8
- let controller;
9
- body = new fetchAPI.ReadableStream({
10
- start(c) {
11
- controller = c;
12
- },
13
- });
14
- const readable = body.readable;
15
- if (readable) {
16
- signal.addEventListener('abort', () => {
17
- readable.push(null);
18
- });
19
- res.onData(function (ab, isLast) {
20
- const chunk = Buffer.from(ab, 0, ab.byteLength);
21
- readable.push(Buffer.from(chunk));
22
- if (isLast) {
23
- readable.push(null);
24
- }
25
- });
7
+ let duplex;
8
+ const chunks = [];
9
+ const pushFns = [
10
+ (chunk) => {
11
+ chunks.push(chunk);
12
+ },
13
+ ];
14
+ const push = (chunk) => {
15
+ for (const pushFn of pushFns) {
16
+ pushFn(chunk);
26
17
  }
27
- else {
28
- let closed = false;
29
- signal.addEventListener('abort', () => {
30
- if (!closed) {
31
- closed = true;
32
- controller.close();
33
- }
34
- });
35
- res.onData(function (ab, isLast) {
36
- const chunk = Buffer.from(ab, 0, ab.byteLength);
37
- controller.enqueue(Buffer.from(chunk));
38
- if (isLast) {
39
- closed = true;
40
- controller.close();
41
- }
42
- });
18
+ };
19
+ let stopped = false;
20
+ const stopFns = [
21
+ () => {
22
+ stopped = true;
23
+ },
24
+ ];
25
+ const stop = () => {
26
+ for (const stopFn of stopFns) {
27
+ stopFn();
43
28
  }
29
+ };
30
+ res.onData(function (ab, isLast) {
31
+ push(Buffer.from(Buffer.from(ab, 0, ab.byteLength)));
32
+ if (isLast) {
33
+ stop();
34
+ }
35
+ });
36
+ let getReadableStream;
37
+ if (method !== 'get' && method !== 'head') {
38
+ duplex = 'half';
39
+ signal.addEventListener('abort', () => {
40
+ stop();
41
+ });
42
+ let readableStream;
43
+ getReadableStream = () => {
44
+ if (!readableStream) {
45
+ readableStream = new fetchAPI.ReadableStream({
46
+ start(controller) {
47
+ for (const chunk of chunks) {
48
+ controller.enqueue(chunk);
49
+ }
50
+ if (stopped) {
51
+ controller.close();
52
+ return;
53
+ }
54
+ pushFns.push((chunk) => {
55
+ controller.enqueue(chunk);
56
+ });
57
+ stopFns.push(() => {
58
+ if (controller.desiredSize) {
59
+ controller.close();
60
+ }
61
+ });
62
+ },
63
+ });
64
+ }
65
+ return readableStream;
66
+ };
44
67
  }
45
68
  const headers = new fetchAPI.Headers();
46
69
  req.forEach((key, value) => {
@@ -51,30 +74,97 @@ export function getRequestFromUWSRequest({ req, res, fetchAPI, signal }) {
51
74
  if (query) {
52
75
  url += `?${query}`;
53
76
  }
54
- return new fetchAPI.Request(url, {
77
+ let buffer;
78
+ function getBody() {
79
+ if (!getReadableStream) {
80
+ return null;
81
+ }
82
+ if (stopped) {
83
+ return getBufferFromChunks();
84
+ }
85
+ return getReadableStream();
86
+ }
87
+ const request = new fetchAPI.Request(url, {
55
88
  method,
56
89
  headers,
57
- body: body,
90
+ get body() {
91
+ return getBody();
92
+ },
58
93
  signal,
59
94
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
60
95
  // @ts-ignore - not in the TS types yet
61
- duplex: 'half',
96
+ duplex,
62
97
  });
63
- }
64
- async function forwardResponseBodyToUWSResponse(uwsResponse, fetchResponse, signal) {
65
- for await (const chunk of fetchResponse.body) {
66
- if (signal.aborted) {
67
- return;
98
+ function getBufferFromChunks() {
99
+ if (!buffer) {
100
+ buffer = chunks.length === 1 ? chunks[0] : Buffer.concat(chunks);
68
101
  }
69
- uwsResponse.cork(() => {
70
- uwsResponse.write(chunk);
102
+ return buffer;
103
+ }
104
+ function collectBuffer() {
105
+ if (stopped) {
106
+ return fakePromise(getBufferFromChunks());
107
+ }
108
+ return new Promise((resolve, reject) => {
109
+ try {
110
+ stopFns.push(() => {
111
+ resolve(getBufferFromChunks());
112
+ });
113
+ }
114
+ catch (e) {
115
+ reject(e);
116
+ }
71
117
  });
72
118
  }
73
- uwsResponse.cork(() => {
74
- uwsResponse.end();
119
+ Object.defineProperties(request, {
120
+ body: {
121
+ get() {
122
+ return getBody();
123
+ },
124
+ configurable: true,
125
+ enumerable: true,
126
+ },
127
+ json: {
128
+ value() {
129
+ return collectBuffer()
130
+ .then(b => b.toString('utf8'))
131
+ .then(t => JSON.parse(t));
132
+ },
133
+ configurable: true,
134
+ enumerable: true,
135
+ },
136
+ text: {
137
+ value() {
138
+ return collectBuffer().then(b => b.toString('utf8'));
139
+ },
140
+ configurable: true,
141
+ enumerable: true,
142
+ },
143
+ arrayBuffer: {
144
+ value() {
145
+ return collectBuffer();
146
+ },
147
+ configurable: true,
148
+ enumerable: true,
149
+ },
75
150
  });
151
+ return request;
76
152
  }
77
- export function sendResponseToUwsOpts(uwsResponse, fetchResponse, signal) {
153
+ export function createWritableFromUWS(uwsResponse, fetchAPI) {
154
+ return new fetchAPI.WritableStream({
155
+ write(chunk) {
156
+ uwsResponse.cork(() => {
157
+ uwsResponse.write(chunk);
158
+ });
159
+ },
160
+ close() {
161
+ uwsResponse.cork(() => {
162
+ uwsResponse.end();
163
+ });
164
+ },
165
+ });
166
+ }
167
+ export function sendResponseToUwsOpts(uwsResponse, fetchResponse, signal, fetchAPI) {
78
168
  if (!fetchResponse) {
79
169
  uwsResponse.writeStatus('404 Not Found');
80
170
  uwsResponse.end();
@@ -104,13 +194,59 @@ export function sendResponseToUwsOpts(uwsResponse, fetchResponse, signal) {
104
194
  if (bufferOfRes) {
105
195
  uwsResponse.end(bufferOfRes);
106
196
  }
197
+ else if (!fetchResponse.body) {
198
+ uwsResponse.end();
199
+ }
107
200
  });
108
- if (bufferOfRes) {
201
+ if (bufferOfRes || !fetchResponse.body) {
109
202
  return;
110
203
  }
111
- if (!fetchResponse.body) {
112
- uwsResponse.end();
113
- return;
204
+ signal.addEventListener('abort', () => {
205
+ if (!fetchResponse.body?.locked) {
206
+ fetchResponse.body?.cancel(signal.reason);
207
+ }
208
+ });
209
+ return fetchResponse.body
210
+ .pipeTo(createWritableFromUWS(uwsResponse, fetchAPI), {
211
+ signal,
212
+ })
213
+ .catch(err => {
214
+ if (signal.aborted) {
215
+ return;
216
+ }
217
+ throw err;
218
+ });
219
+ }
220
+ export function fakePromise(value) {
221
+ if (isPromise(value)) {
222
+ return value;
114
223
  }
115
- return forwardResponseBodyToUWSResponse(uwsResponse, fetchResponse, signal);
224
+ // Write a fake promise to avoid the promise constructor
225
+ // being called with `new Promise` in the browser.
226
+ return {
227
+ then(resolve) {
228
+ if (resolve) {
229
+ const callbackResult = resolve(value);
230
+ if (isPromise(callbackResult)) {
231
+ return callbackResult;
232
+ }
233
+ return fakePromise(callbackResult);
234
+ }
235
+ return this;
236
+ },
237
+ catch() {
238
+ return this;
239
+ },
240
+ finally(cb) {
241
+ if (cb) {
242
+ const callbackResult = cb();
243
+ if (isPromise(callbackResult)) {
244
+ return callbackResult.then(() => value);
245
+ }
246
+ return fakePromise(value);
247
+ }
248
+ return this;
249
+ },
250
+ [Symbol.toStringTag]: 'Promise',
251
+ };
116
252
  }
package/package.json CHANGED
@@ -1,10 +1,11 @@
1
1
  {
2
2
  "name": "@whatwg-node/server",
3
- "version": "0.10.0-alpha-20240726141316-c6ce93b3598457ebe73b3b725986723af8f5e609",
3
+ "version": "0.10.0-alpha-20241125124208-52a1220ca8b2a3b86a8338c8f96b80dde432e1bb",
4
4
  "description": "Fetch API compliant HTTP Server adapter",
5
5
  "sideEffects": false,
6
6
  "dependencies": {
7
- "@whatwg-node/fetch": "^0.9.19",
7
+ "@whatwg-node/disposablestack": "^0.0.5",
8
+ "@whatwg-node/fetch": "^0.10.0",
8
9
  "tslib": "^2.6.3"
9
10
  },
10
11
  "repository": {
@@ -15,7 +16,7 @@
15
16
  "author": "Arda TANRIKULU <ardatanrikulu@gmail.com>",
16
17
  "license": "MIT",
17
18
  "engines": {
18
- "node": ">=16.0.0"
19
+ "node": ">=18.0.0"
19
20
  },
20
21
  "main": "cjs/index.js",
21
22
  "module": "esm/index.js",
@@ -1,4 +1,4 @@
1
- import { ServerAdapterPlugin } from './types.cjs';
1
+ import type { ServerAdapterPlugin } from './types.cjs';
2
2
  export type CORSOptions = {
3
3
  origin?: string[] | string;
4
4
  methods?: string[];
@@ -1,4 +1,4 @@
1
- import { ServerAdapterPlugin } from './types.js';
1
+ import type { ServerAdapterPlugin } from './types.js';
2
2
  export type CORSOptions = {
3
3
  origin?: string[] | string;
4
4
  methods?: string[];
@@ -1,4 +1,4 @@
1
- import { ServerAdapterPlugin } from './types.cjs';
1
+ import type { ServerAdapterPlugin } from './types.cjs';
2
2
  export declare function createDefaultErrorHandler<TServerContext = {}>(ResponseCtor?: typeof Response): ErrorHandler<TServerContext>;
3
3
  export declare class HTTPError extends Error {
4
4
  status: number;
@@ -6,7 +6,7 @@ export declare class HTTPError extends Error {
6
6
  headers: HeadersInit;
7
7
  details?: any;
8
8
  name: string;
9
- constructor(status: number, message: string, headers?: HeadersInit, details?: any);
9
+ constructor(status: number | undefined, message: string, headers?: HeadersInit, details?: any);
10
10
  }
11
11
  export type ErrorHandler<TServerContext> = (e: any, request: Request, ctx: TServerContext) => Response | Promise<Response>;
12
12
  export declare function useErrorHandling<TServerContext>(onError?: ErrorHandler<TServerContext>): ServerAdapterPlugin<TServerContext>;
@@ -1,4 +1,4 @@
1
- import { ServerAdapterPlugin } from './types.js';
1
+ import type { ServerAdapterPlugin } from './types.js';
2
2
  export declare function createDefaultErrorHandler<TServerContext = {}>(ResponseCtor?: typeof Response): ErrorHandler<TServerContext>;
3
3
  export declare class HTTPError extends Error {
4
4
  status: number;
@@ -6,7 +6,7 @@ export declare class HTTPError extends Error {
6
6
  headers: HeadersInit;
7
7
  details?: any;
8
8
  name: string;
9
- constructor(status: number, message: string, headers?: HeadersInit, details?: any);
9
+ constructor(status: number | undefined, message: string, headers?: HeadersInit, details?: any);
10
10
  }
11
11
  export type ErrorHandler<TServerContext> = (e: any, request: Request, ctx: TServerContext) => Response | Promise<Response>;
12
12
  export declare function useErrorHandling<TServerContext>(onError?: ErrorHandler<TServerContext>): ServerAdapterPlugin<TServerContext>;