@whatwg-node/server 0.8.5 → 0.8.6-alpha-20230608092002-31ae5e4

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.
@@ -44,13 +44,35 @@ function createServerAdapter(serverAdapterBaseObject, options) {
44
44
  }
45
45
  }
46
46
  async function handleRequest(request, serverContext) {
47
- const { requestHandler, response = await requestHandler(request, serverContext) } = await (0, utils_js_1.handleOnRequestHook)({
48
- request,
49
- serverContext,
50
- onRequestHooks,
51
- givenHandleRequest,
52
- fetchAPI,
47
+ let url = new Proxy({}, {
48
+ get: (_target, prop, _receiver) => {
49
+ url = new fetchAPI.URL(request.url, 'http://localhost');
50
+ return Reflect.get(url, prop, url);
51
+ },
53
52
  });
53
+ let requestHandler = givenHandleRequest;
54
+ let response;
55
+ for (const onRequestHook of onRequestHooks) {
56
+ await onRequestHook({
57
+ request,
58
+ serverContext,
59
+ fetchAPI,
60
+ url,
61
+ requestHandler,
62
+ setRequestHandler(newRequestHandler) {
63
+ requestHandler = newRequestHandler;
64
+ },
65
+ endResponse(newResponse) {
66
+ response = newResponse;
67
+ },
68
+ });
69
+ if (response) {
70
+ break;
71
+ }
72
+ }
73
+ if (!response) {
74
+ response = await requestHandler(request, serverContext);
75
+ }
54
76
  for (const onResponseHook of onResponseHooks) {
55
77
  await onResponseHook({
56
78
  request,
package/cjs/utils.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.handleOnRequestHook = exports.completeAssign = exports.isRequestInit = exports.sendNodeResponse = exports.getHeadersObj = exports.isFetchEvent = exports.isReadableStream = exports.isServerResponse = exports.isNodeRequest = exports.isReadable = exports.normalizeNodeRequest = exports.isAsyncIterable = void 0;
3
+ exports.completeAssign = exports.isRequestInit = exports.sendNodeResponse = exports.isFetchEvent = exports.isReadableStream = exports.isServerResponse = exports.isNodeRequest = exports.isReadable = exports.normalizeNodeRequest = exports.isAsyncIterable = void 0;
4
4
  const fetch_1 = require("@whatwg-node/fetch");
5
5
  function isAsyncIterable(body) {
6
6
  return (body != null && typeof body === 'object' && typeof body[Symbol.asyncIterator] === 'function');
@@ -145,39 +145,10 @@ function endResponse(serverResponse) {
145
145
  // @ts-expect-error Avoid arguments adaptor trampoline https://v8.dev/blog/adaptor-frame
146
146
  serverResponse.end(null, null, null);
147
147
  }
148
- function getHeadersObj(headers) {
149
- return new Proxy({}, {
150
- get(_target, prop) {
151
- return headers.get(prop) || undefined;
152
- },
153
- set(_target, prop, value) {
154
- headers.set(prop, value);
155
- return true;
156
- },
157
- has(_target, prop) {
158
- return headers.has(prop);
159
- },
160
- deleteProperty(_target, prop) {
161
- headers.delete(prop);
162
- return true;
163
- },
164
- ownKeys() {
165
- const keys = [];
166
- headers.forEach((_, key) => keys.push(key));
167
- return keys;
168
- },
169
- getOwnPropertyDescriptor() {
170
- return {
171
- enumerable: true,
172
- configurable: true,
173
- };
174
- },
175
- });
176
- }
177
- exports.getHeadersObj = getHeadersObj;
178
148
  async function sendNodeResponse(fetchResponse, serverResponse, nodeRequest) {
179
- const headersObj = getHeadersObj(fetchResponse.headers);
180
- serverResponse.writeHead(fetchResponse.status, fetchResponse.statusText, headersObj);
149
+ serverResponse.writeHead(fetchResponse.status, fetchResponse.statusText, [
150
+ ...fetchResponse.headers,
151
+ ]);
181
152
  // eslint-disable-next-line no-async-promise-executor
182
153
  return new Promise(async (resolve) => {
183
154
  serverResponse.once('close', resolve);
@@ -265,36 +236,3 @@ function completeAssign(target, ...sources) {
265
236
  return target;
266
237
  }
267
238
  exports.completeAssign = completeAssign;
268
- async function handleOnRequestHook({ fetchAPI, request, givenHandleRequest, serverContext, onRequestHooks, }) {
269
- let url = new Proxy({}, {
270
- get: (_target, prop, _receiver) => {
271
- url = new fetchAPI.URL(request.url, 'http://localhost');
272
- return Reflect.get(url, prop, url);
273
- },
274
- });
275
- let requestHandler = givenHandleRequest;
276
- let response;
277
- for (const onRequestHook of onRequestHooks) {
278
- await onRequestHook({
279
- request,
280
- serverContext,
281
- fetchAPI,
282
- url,
283
- requestHandler,
284
- setRequestHandler(newRequestHandler) {
285
- requestHandler = newRequestHandler;
286
- },
287
- endResponse(newResponse) {
288
- response = newResponse;
289
- },
290
- });
291
- if (response) {
292
- break;
293
- }
294
- }
295
- return {
296
- response,
297
- requestHandler,
298
- };
299
- }
300
- exports.handleOnRequestHook = handleOnRequestHook;
@@ -1,7 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.sendResponseToUwsOpts = exports.getRequestFromUWSRequest = exports.isUWSResponse = void 0;
4
- const repeater_1 = require("@repeaterjs/repeater");
5
4
  function isUWSResponse(res) {
6
5
  return typeof res === 'object' && typeof res.onData === 'function';
7
6
  }
@@ -10,19 +9,21 @@ function getRequestFromUWSRequest({ req, res, fetchAPI }) {
10
9
  let body;
11
10
  const method = req.getMethod();
12
11
  if (method !== 'get' && method !== 'head') {
13
- body = new repeater_1.Repeater(function (push, stop) {
14
- res.onAborted(stop);
15
- res.onData(function (chunk, isLast) {
16
- push(Buffer.from(chunk, 0, chunk.byteLength));
17
- if (isLast) {
18
- stop();
19
- }
20
- });
12
+ body = new fetchAPI.ReadableStream({});
13
+ const readable = body.readable;
14
+ res.onAborted(() => {
15
+ readable.push(null);
16
+ });
17
+ res.onData(function (chunk, isLast) {
18
+ readable.push(Buffer.from(chunk, 0, chunk.byteLength));
19
+ if (isLast) {
20
+ readable.push(null);
21
+ }
21
22
  });
22
23
  }
23
- const headers = {};
24
+ const headers = new fetchAPI.Headers();
24
25
  req.forEach((key, value) => {
25
- headers[key] = value;
26
+ headers.set(key, value);
26
27
  });
27
28
  const url = `http://localhost${req.getUrl()}`;
28
29
  return new fetchAPI.Request(url, {
@@ -48,17 +49,17 @@ async function sendResponseToUwsOpts({ res, response }) {
48
49
  });
49
50
  }
50
51
  });
51
- if (!response.body) {
52
- res.end();
53
- return;
54
- }
55
52
  if (response.bodyType === 'String' || response.bodyType === 'Uint8Array') {
56
53
  res.cork(() => {
57
54
  res.end(response.bodyInit);
58
55
  });
59
56
  return;
60
57
  }
61
- for await (const chunk of response.body.readable) {
58
+ if (!response.body) {
59
+ res.end();
60
+ return;
61
+ }
62
+ for await (const chunk of response.body) {
62
63
  if (resAborted) {
63
64
  return;
64
65
  }
@@ -1,6 +1,6 @@
1
1
  /* eslint-disable @typescript-eslint/ban-types */
2
2
  import * as DefaultFetchAPI from '@whatwg-node/fetch';
3
- import { completeAssign, handleOnRequestHook, isFetchEvent, isNodeRequest, isRequestInit, isServerResponse, normalizeNodeRequest, sendNodeResponse, } from './utils.js';
3
+ import { completeAssign, isFetchEvent, isNodeRequest, isRequestInit, isServerResponse, normalizeNodeRequest, sendNodeResponse, } from './utils.js';
4
4
  import { getRequestFromUWSRequest, isUWSResponse, sendResponseToUwsOpts, } from './uwebsockets.js';
5
5
  async function handleWaitUntils(waitUntilPromises) {
6
6
  const waitUntils = await Promise.allSettled(waitUntilPromises);
@@ -40,13 +40,35 @@ function createServerAdapter(serverAdapterBaseObject, options) {
40
40
  }
41
41
  }
42
42
  async function handleRequest(request, serverContext) {
43
- const { requestHandler, response = await requestHandler(request, serverContext) } = await handleOnRequestHook({
44
- request,
45
- serverContext,
46
- onRequestHooks,
47
- givenHandleRequest,
48
- fetchAPI,
43
+ let url = new Proxy({}, {
44
+ get: (_target, prop, _receiver) => {
45
+ url = new fetchAPI.URL(request.url, 'http://localhost');
46
+ return Reflect.get(url, prop, url);
47
+ },
49
48
  });
49
+ let requestHandler = givenHandleRequest;
50
+ let response;
51
+ for (const onRequestHook of onRequestHooks) {
52
+ await onRequestHook({
53
+ request,
54
+ serverContext,
55
+ fetchAPI,
56
+ url,
57
+ requestHandler,
58
+ setRequestHandler(newRequestHandler) {
59
+ requestHandler = newRequestHandler;
60
+ },
61
+ endResponse(newResponse) {
62
+ response = newResponse;
63
+ },
64
+ });
65
+ if (response) {
66
+ break;
67
+ }
68
+ }
69
+ if (!response) {
70
+ response = await requestHandler(request, serverContext);
71
+ }
50
72
  for (const onResponseHook of onResponseHooks) {
51
73
  await onResponseHook({
52
74
  request,
package/esm/utils.js CHANGED
@@ -135,38 +135,10 @@ function endResponse(serverResponse) {
135
135
  // @ts-expect-error Avoid arguments adaptor trampoline https://v8.dev/blog/adaptor-frame
136
136
  serverResponse.end(null, null, null);
137
137
  }
138
- export function getHeadersObj(headers) {
139
- return new Proxy({}, {
140
- get(_target, prop) {
141
- return headers.get(prop) || undefined;
142
- },
143
- set(_target, prop, value) {
144
- headers.set(prop, value);
145
- return true;
146
- },
147
- has(_target, prop) {
148
- return headers.has(prop);
149
- },
150
- deleteProperty(_target, prop) {
151
- headers.delete(prop);
152
- return true;
153
- },
154
- ownKeys() {
155
- const keys = [];
156
- headers.forEach((_, key) => keys.push(key));
157
- return keys;
158
- },
159
- getOwnPropertyDescriptor() {
160
- return {
161
- enumerable: true,
162
- configurable: true,
163
- };
164
- },
165
- });
166
- }
167
138
  export async function sendNodeResponse(fetchResponse, serverResponse, nodeRequest) {
168
- const headersObj = getHeadersObj(fetchResponse.headers);
169
- serverResponse.writeHead(fetchResponse.status, fetchResponse.statusText, headersObj);
139
+ serverResponse.writeHead(fetchResponse.status, fetchResponse.statusText, [
140
+ ...fetchResponse.headers,
141
+ ]);
170
142
  // eslint-disable-next-line no-async-promise-executor
171
143
  return new Promise(async (resolve) => {
172
144
  serverResponse.once('close', resolve);
@@ -251,35 +223,3 @@ export function completeAssign(target, ...sources) {
251
223
  });
252
224
  return target;
253
225
  }
254
- export async function handleOnRequestHook({ fetchAPI, request, givenHandleRequest, serverContext, onRequestHooks, }) {
255
- let url = new Proxy({}, {
256
- get: (_target, prop, _receiver) => {
257
- url = new fetchAPI.URL(request.url, 'http://localhost');
258
- return Reflect.get(url, prop, url);
259
- },
260
- });
261
- let requestHandler = givenHandleRequest;
262
- let response;
263
- for (const onRequestHook of onRequestHooks) {
264
- await onRequestHook({
265
- request,
266
- serverContext,
267
- fetchAPI,
268
- url,
269
- requestHandler,
270
- setRequestHandler(newRequestHandler) {
271
- requestHandler = newRequestHandler;
272
- },
273
- endResponse(newResponse) {
274
- response = newResponse;
275
- },
276
- });
277
- if (response) {
278
- break;
279
- }
280
- }
281
- return {
282
- response,
283
- requestHandler,
284
- };
285
- }
@@ -1,4 +1,3 @@
1
- import { Repeater } from '@repeaterjs/repeater';
2
1
  export function isUWSResponse(res) {
3
2
  return typeof res === 'object' && typeof res.onData === 'function';
4
3
  }
@@ -6,19 +5,21 @@ export function getRequestFromUWSRequest({ req, res, fetchAPI }) {
6
5
  let body;
7
6
  const method = req.getMethod();
8
7
  if (method !== 'get' && method !== 'head') {
9
- body = new Repeater(function (push, stop) {
10
- res.onAborted(stop);
11
- res.onData(function (chunk, isLast) {
12
- push(Buffer.from(chunk, 0, chunk.byteLength));
13
- if (isLast) {
14
- stop();
15
- }
16
- });
8
+ body = new fetchAPI.ReadableStream({});
9
+ const readable = body.readable;
10
+ res.onAborted(() => {
11
+ readable.push(null);
12
+ });
13
+ res.onData(function (chunk, isLast) {
14
+ readable.push(Buffer.from(chunk, 0, chunk.byteLength));
15
+ if (isLast) {
16
+ readable.push(null);
17
+ }
17
18
  });
18
19
  }
19
- const headers = {};
20
+ const headers = new fetchAPI.Headers();
20
21
  req.forEach((key, value) => {
21
- headers[key] = value;
22
+ headers.set(key, value);
22
23
  });
23
24
  const url = `http://localhost${req.getUrl()}`;
24
25
  return new fetchAPI.Request(url, {
@@ -43,17 +44,17 @@ export async function sendResponseToUwsOpts({ res, response }) {
43
44
  });
44
45
  }
45
46
  });
46
- if (!response.body) {
47
- res.end();
48
- return;
49
- }
50
47
  if (response.bodyType === 'String' || response.bodyType === 'Uint8Array') {
51
48
  res.cork(() => {
52
49
  res.end(response.bodyInit);
53
50
  });
54
51
  return;
55
52
  }
56
- for await (const chunk of response.body.readable) {
53
+ if (!response.body) {
54
+ res.end();
55
+ return;
56
+ }
57
+ for await (const chunk of response.body) {
57
58
  if (resAborted) {
58
59
  return;
59
60
  }
package/package.json CHANGED
@@ -1,10 +1,9 @@
1
1
  {
2
2
  "name": "@whatwg-node/server",
3
- "version": "0.8.5",
3
+ "version": "0.8.6-alpha-20230608092002-31ae5e4",
4
4
  "description": "Fetch API compliant HTTP Server adapter",
5
5
  "sideEffects": false,
6
6
  "dependencies": {
7
- "@repeaterjs/repeater": "^3.0.4",
8
7
  "@whatwg-node/fetch": "^0.9.3",
9
8
  "tslib": "^2.3.1"
10
9
  },
@@ -3,11 +3,10 @@
3
3
  /// <reference types="node" />
4
4
  /// <reference types="node" />
5
5
  import type { IncomingMessage, ServerResponse } from 'node:http';
6
- import type { Http2ServerRequest, Http2ServerResponse, OutgoingHttpHeaders } from 'node:http2';
6
+ import type { Http2ServerRequest, Http2ServerResponse } from 'node:http2';
7
7
  import type { Socket } from 'node:net';
8
8
  import type { Readable } from 'node:stream';
9
- import type { OnRequestHook } from './plugins/types.cjs';
10
- import type { FetchAPI, FetchEvent, ServerAdapterRequestHandler } from './types.cjs';
9
+ import type { FetchEvent } from './types.cjs';
11
10
  export declare function isAsyncIterable(body: any): body is AsyncIterable<any>;
12
11
  export interface NodeRequest {
13
12
  protocol?: string;
@@ -29,18 +28,6 @@ export declare function isNodeRequest(request: any): request is NodeRequest;
29
28
  export declare function isServerResponse(stream: any): stream is NodeResponse;
30
29
  export declare function isReadableStream(stream: any): stream is ReadableStream;
31
30
  export declare function isFetchEvent(event: any): event is FetchEvent;
32
- export declare function getHeadersObj(headers: Headers): OutgoingHttpHeaders;
33
31
  export declare function sendNodeResponse(fetchResponse: Response, serverResponse: NodeResponse, nodeRequest: NodeRequest): Promise<void>;
34
32
  export declare function isRequestInit(val: unknown): val is RequestInit;
35
33
  export declare function completeAssign(target: any, ...sources: any[]): any;
36
- export interface HandleOnRequestHookOpts {
37
- fetchAPI: FetchAPI;
38
- request: Request;
39
- givenHandleRequest: ServerAdapterRequestHandler<any>;
40
- serverContext: any;
41
- onRequestHooks: OnRequestHook<any>[];
42
- }
43
- export declare function handleOnRequestHook({ fetchAPI, request, givenHandleRequest, serverContext, onRequestHooks, }: HandleOnRequestHookOpts): Promise<{
44
- response?: Response;
45
- requestHandler: ServerAdapterRequestHandler<any>;
46
- }>;
@@ -3,11 +3,10 @@
3
3
  /// <reference types="node" />
4
4
  /// <reference types="node" />
5
5
  import type { IncomingMessage, ServerResponse } from 'node:http';
6
- import type { Http2ServerRequest, Http2ServerResponse, OutgoingHttpHeaders } from 'node:http2';
6
+ import type { Http2ServerRequest, Http2ServerResponse } from 'node:http2';
7
7
  import type { Socket } from 'node:net';
8
8
  import type { Readable } from 'node:stream';
9
- import type { OnRequestHook } from './plugins/types.js';
10
- import type { FetchAPI, FetchEvent, ServerAdapterRequestHandler } from './types.js';
9
+ import type { FetchEvent } from './types.js';
11
10
  export declare function isAsyncIterable(body: any): body is AsyncIterable<any>;
12
11
  export interface NodeRequest {
13
12
  protocol?: string;
@@ -29,18 +28,6 @@ export declare function isNodeRequest(request: any): request is NodeRequest;
29
28
  export declare function isServerResponse(stream: any): stream is NodeResponse;
30
29
  export declare function isReadableStream(stream: any): stream is ReadableStream;
31
30
  export declare function isFetchEvent(event: any): event is FetchEvent;
32
- export declare function getHeadersObj(headers: Headers): OutgoingHttpHeaders;
33
31
  export declare function sendNodeResponse(fetchResponse: Response, serverResponse: NodeResponse, nodeRequest: NodeRequest): Promise<void>;
34
32
  export declare function isRequestInit(val: unknown): val is RequestInit;
35
33
  export declare function completeAssign(target: any, ...sources: any[]): any;
36
- export interface HandleOnRequestHookOpts {
37
- fetchAPI: FetchAPI;
38
- request: Request;
39
- givenHandleRequest: ServerAdapterRequestHandler<any>;
40
- serverContext: any;
41
- onRequestHooks: OnRequestHook<any>[];
42
- }
43
- export declare function handleOnRequestHook({ fetchAPI, request, givenHandleRequest, serverContext, onRequestHooks, }: HandleOnRequestHookOpts): Promise<{
44
- response?: Response;
45
- requestHandler: ServerAdapterRequestHandler<any>;
46
- }>;
@@ -4,6 +4,7 @@ export interface UWSRequest {
4
4
  forEach(callback: (key: string, value: string) => void): void;
5
5
  getUrl(): string;
6
6
  getHeader(key: string): string | undefined;
7
+ setYield(y: boolean): void;
7
8
  }
8
9
  export interface UWSResponse {
9
10
  onData(callback: (chunk: ArrayBuffer, isLast: boolean) => void): void;
@@ -11,6 +12,7 @@ export interface UWSResponse {
11
12
  writeStatus(status: string): void;
12
13
  writeHeader(key: string, value: string): void;
13
14
  end(body?: any): void;
15
+ close(): void;
14
16
  write(body: any): boolean;
15
17
  cork(callback: () => void): void;
16
18
  }
@@ -4,6 +4,7 @@ export interface UWSRequest {
4
4
  forEach(callback: (key: string, value: string) => void): void;
5
5
  getUrl(): string;
6
6
  getHeader(key: string): string | undefined;
7
+ setYield(y: boolean): void;
7
8
  }
8
9
  export interface UWSResponse {
9
10
  onData(callback: (chunk: ArrayBuffer, isLast: boolean) => void): void;
@@ -11,6 +12,7 @@ export interface UWSResponse {
11
12
  writeStatus(status: string): void;
12
13
  writeHeader(key: string, value: string): void;
13
14
  end(body?: any): void;
15
+ close(): void;
14
16
  write(body: any): boolean;
15
17
  cork(callback: () => void): void;
16
18
  }