@whatwg-node/server 0.4.5 → 0.4.6-alpha-20220922124249-c941ae6

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.
package/README.md CHANGED
@@ -117,7 +117,10 @@ app.route({
117
117
  url: '/mypath',
118
118
  method: ['GET', 'POST', 'OPTIONS'],
119
119
  handler: async (req, reply) => {
120
- const response = await myServerAdapter.handleNodeRequest(req)
120
+ const response = await myServerAdapter.handleNodeRequest(req, {
121
+ req,
122
+ reply,
123
+ })
121
124
  response.headers.forEach((value, key) => {
122
125
  reply.header(key, value)
123
126
  })
package/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  /// <reference types="node" />
2
2
  /// <reference lib="webworker" />
3
- import type { RequestListener, ServerResponse } from 'node:http';
3
+ import type { IncomingMessage, ServerResponse } from 'node:http';
4
4
  import { NodeRequest } from './utils';
5
5
  export interface ServerAdapterBaseObject<TServerContext, THandleRequest extends ServerAdapterRequestHandler<TServerContext> = ServerAdapterRequestHandler<TServerContext>> {
6
6
  /**
@@ -17,26 +17,32 @@ export interface ServerAdapterObject<TServerContext, TBaseObject extends ServerA
17
17
  /**
18
18
  * WHATWG Fetch spec compliant `fetch` function that can be used for testing purposes.
19
19
  */
20
- fetch(request: Request, ...ctx: any[]): Promise<Response> | Response;
21
- fetch(urlStr: string, ...ctx: any[]): Promise<Response> | Response;
22
- fetch(urlStr: string, init: RequestInit, ...ctx: any[]): Promise<Response> | Response;
23
- fetch(url: URL, ...ctx: any[]): Promise<Response> | Response;
24
- fetch(url: URL, init: RequestInit, ...ctx: any[]): Promise<Response> | Response;
20
+ fetch(request: Request, ctx: TServerContext): Promise<Response> | Response;
21
+ fetch(request: Request, ...ctx: Partial<TServerContext>[]): Promise<Response> | Response;
22
+ fetch(urlStr: string, ctx: TServerContext): Promise<Response> | Response;
23
+ fetch(urlStr: string, ...ctx: Partial<TServerContext>[]): Promise<Response> | Response;
24
+ fetch(urlStr: string, init: RequestInit, ctx: TServerContext): Promise<Response> | Response;
25
+ fetch(urlStr: string, init: RequestInit, ...ctx: Partial<TServerContext>[]): Promise<Response> | Response;
26
+ fetch(url: URL, ctx: TServerContext): Promise<Response> | Response;
27
+ fetch(url: URL, ...ctx: Partial<TServerContext>[]): Promise<Response> | Response;
28
+ fetch(url: URL, init: RequestInit, ctx: TServerContext): Promise<Response> | Response;
29
+ fetch(url: URL, init: RequestInit, ...ctx: Partial<TServerContext>[]): Promise<Response> | Response;
25
30
  /**
26
31
  * This function takes Node's request object and returns a WHATWG Fetch spec compliant `Response` object.
27
32
  **/
28
- handleNodeRequest(nodeRequest: NodeRequest, serverContext: TServerContext): Promise<Response> | Response;
33
+ handleNodeRequest(nodeRequest: NodeRequest, ctx: TServerContext): Promise<Response> | Response;
29
34
  /**
30
35
  * A request listener function that can be used with any Node server variation.
31
36
  */
32
- requestListener: RequestListener;
37
+ requestListener(req: IncomingMessage, res: ServerResponse, ctx: TServerContext): void;
38
+ requestListener(req: IncomingMessage, res: ServerResponse, ...ctx: Partial<TServerContext>[]): void;
33
39
  /**
34
40
  * Proxy to requestListener to mimic Node middlewares
35
41
  */
36
- handle: RequestListener & ServerAdapterObject<TServerContext, TBaseObject>['fetch'];
42
+ handle: ServerAdapterObject<TServerContext, TBaseObject>['requestListener'] & ServerAdapterObject<TServerContext, TBaseObject>['fetch'];
37
43
  }
38
- export declare type ServerAdapter<TServerContext, TBaseObject extends ServerAdapterBaseObject<TServerContext>> = TBaseObject & RequestListener & ServerAdapterObject<TServerContext, TBaseObject>['fetch'] & ServerAdapterObject<TServerContext, TBaseObject>;
39
- export declare type ServerAdapterRequestHandler<TServerContext> = (request: Request, serverContext: TServerContext) => Promise<Response> | Response;
44
+ export declare type ServerAdapter<TServerContext, TBaseObject extends ServerAdapterBaseObject<TServerContext>> = TBaseObject & ServerAdapterObject<TServerContext, TBaseObject>['requestListener'] & ServerAdapterObject<TServerContext, TBaseObject>['fetch'] & ServerAdapterObject<TServerContext, TBaseObject>;
45
+ export declare type ServerAdapterRequestHandler<TServerContext> = (request: Request, ctx: TServerContext) => Promise<Response> | Response;
40
46
  export declare type DefaultServerAdapterContext = {
41
47
  req: NodeRequest;
42
48
  res: ServerResponse;
package/index.js CHANGED
@@ -154,6 +154,23 @@ async function sendNodeResponse({ headers, status, statusText, body }, serverRes
154
154
  }
155
155
  });
156
156
  }
157
+ function isRequestInit(val) {
158
+ return (val != null &&
159
+ typeof val === 'object' &&
160
+ ('body' in val ||
161
+ 'cache' in val ||
162
+ 'credentials' in val ||
163
+ 'headers' in val ||
164
+ 'integrity' in val ||
165
+ 'keepalive' in val ||
166
+ 'method' in val ||
167
+ 'mode' in val ||
168
+ 'redirect' in val ||
169
+ 'referrer' in val ||
170
+ 'referrerPolicy' in val ||
171
+ 'signal' in val ||
172
+ 'window' in val));
173
+ }
157
174
 
158
175
  /// <reference lib="webworker" />
159
176
  async function handleWaitUntils(waitUntilPromises) {
@@ -170,13 +187,18 @@ function createServerAdapter(serverAdapterBaseObject,
170
187
  */
171
188
  RequestCtor = fetch.Request) {
172
189
  const handleRequest = typeof serverAdapterBaseObject === 'function' ? serverAdapterBaseObject : serverAdapterBaseObject.handle;
173
- function handleNodeRequest(nodeRequest, serverContext) {
190
+ function handleNodeRequest(nodeRequest, ctx) {
174
191
  const request = normalizeNodeRequest(nodeRequest, RequestCtor);
175
- return handleRequest(request, serverContext);
192
+ return handleRequest(request, ctx);
176
193
  }
177
- async function requestListener(nodeRequest, serverResponse) {
194
+ async function requestListener(nodeRequest, serverResponse, ...ctx) {
178
195
  const waitUntilPromises = [];
196
+ let serverContext = {};
197
+ if ((ctx === null || ctx === void 0 ? void 0 : ctx.length) > 0) {
198
+ serverContext = Object.assign({}, serverContext, ...ctx);
199
+ }
179
200
  const response = await handleNodeRequest(nodeRequest, {
201
+ ...serverContext,
180
202
  req: nodeRequest,
181
203
  res: serverResponse,
182
204
  waitUntil(p) {
@@ -195,30 +217,34 @@ RequestCtor = fetch.Request) {
195
217
  if (waitUntilPromises.length > 0) {
196
218
  await handleWaitUntils(waitUntilPromises);
197
219
  }
220
+ return response;
198
221
  }
199
- function handleEvent(event) {
222
+ function handleEvent(event, ...ctx) {
200
223
  if (!event.respondWith || !event.request) {
201
224
  throw new TypeError(`Expected FetchEvent, got ${event}`);
202
225
  }
203
- const response$ = handleRequest(event.request, event);
226
+ let serverContext = {};
227
+ if ((ctx === null || ctx === void 0 ? void 0 : ctx.length) > 0) {
228
+ serverContext = Object.assign({}, serverContext, ...ctx);
229
+ }
230
+ const response$ = handleRequest(event.request, serverContext);
204
231
  event.respondWith(response$);
232
+ return response$;
205
233
  }
206
- function handleRequestWithWaitUntil(request, ctx = {}, ...rest) {
234
+ function handleRequestWithWaitUntil(request, ctx) {
207
235
  var _a;
236
+ const extendedCtx = ctx;
208
237
  if ('process' in globalThis && ((_a = process.versions) === null || _a === void 0 ? void 0 : _a['bun']) != null) {
209
238
  // This is required for bun
210
239
  request.text();
211
240
  }
212
- if ((rest === null || rest === void 0 ? void 0 : rest.length) > 0) {
213
- ctx = Object.assign({}, ctx, ...rest);
214
- }
215
- if (!ctx.waitUntil) {
241
+ if (!extendedCtx.waitUntil) {
216
242
  const waitUntilPromises = [];
217
- ctx.waitUntil = (p) => {
243
+ extendedCtx.waitUntil = (p) => {
218
244
  waitUntilPromises.push(p);
219
245
  };
220
246
  const response$ = handleRequest(request, {
221
- ...ctx,
247
+ ...extendedCtx,
222
248
  waitUntil(p) {
223
249
  waitUntilPromises.push(p);
224
250
  },
@@ -228,32 +254,51 @@ RequestCtor = fetch.Request) {
228
254
  }
229
255
  return response$;
230
256
  }
231
- return handleRequest(request, ctx);
257
+ return handleRequest(request, extendedCtx);
232
258
  }
233
- function genericRequestHandler(input, ctx, ...rest) {
259
+ const fetchFn = (input, initOrCtx, ...ctx) => {
260
+ let init;
261
+ let serverContext = {};
262
+ if (isRequestInit(initOrCtx)) {
263
+ init = initOrCtx;
264
+ }
265
+ else {
266
+ init = {};
267
+ serverContext = Object.assign({}, serverContext, initOrCtx);
268
+ }
269
+ if ((ctx === null || ctx === void 0 ? void 0 : ctx.length) > 0) {
270
+ serverContext = Object.assign({}, serverContext, ...ctx);
271
+ }
272
+ if (typeof input === 'string' || input instanceof URL) {
273
+ return handleRequestWithWaitUntil(new RequestCtor(input, init), serverContext);
274
+ }
275
+ return handleRequestWithWaitUntil(input, serverContext);
276
+ };
277
+ const genericRequestHandler = (input, initOrCtxOrRes, ...ctx) => {
234
278
  // If it is a Node request
235
- if (isReadable(input) && ctx != null && isServerResponse(ctx)) {
236
- return requestListener(input, ctx);
279
+ if (isReadable(input) && isServerResponse(initOrCtxOrRes)) {
280
+ return requestListener(input, initOrCtxOrRes, ...ctx);
281
+ }
282
+ if (isServerResponse(initOrCtxOrRes)) {
283
+ throw new Error('Got Node response without Node request');
237
284
  }
238
285
  // Is input a container object over Request?
239
- if (input.request) {
286
+ if (typeof input === 'object' && 'request' in input) {
240
287
  // Is it FetchEvent?
241
- if (input.respondWith) {
242
- return handleEvent(input);
288
+ if ('respondWith' in input) {
289
+ return handleEvent(input, isRequestInit(initOrCtxOrRes) ? {} : initOrCtxOrRes, ...ctx);
243
290
  }
244
291
  // In this input is also the context
245
- return handleRequestWithWaitUntil(input.request, input, ...rest);
292
+ return fetchFn(
293
+ // @ts-expect-error input can indeed be a Request
294
+ input.request, initOrCtxOrRes, ...ctx);
246
295
  }
247
296
  // Or is it Request itself?
248
297
  // Then ctx is present and it is the context
249
- return handleRequestWithWaitUntil(input, ctx, ...rest);
250
- }
251
- function fetchFn(input, init, ...ctx) {
252
- if (typeof input === 'string' || input instanceof URL) {
253
- return handleRequestWithWaitUntil(new RequestCtor(input, init), ...ctx);
254
- }
255
- return handleRequestWithWaitUntil(input, init, ...ctx);
256
- }
298
+ return fetchFn(
299
+ // @ts-expect-error input can indeed string | Request | URL
300
+ input, initOrCtxOrRes, ...ctx);
301
+ };
257
302
  const adapterObj = {
258
303
  handleRequest,
259
304
  fetch: fetchFn,
@@ -277,12 +322,12 @@ RequestCtor = fetch.Request) {
277
322
  }
278
323
  return adapterProp;
279
324
  }
280
- const genericRequestHandlerProp = genericRequestHandler[prop];
281
- if (genericRequestHandlerProp) {
282
- if (genericRequestHandlerProp.bind) {
283
- return genericRequestHandlerProp.bind(genericRequestHandler);
325
+ const handleProp = genericRequestHandler[prop];
326
+ if (handleProp) {
327
+ if (handleProp.bind) {
328
+ return handleProp.bind(genericRequestHandler);
284
329
  }
285
- return genericRequestHandlerProp;
330
+ return handleProp;
286
331
  }
287
332
  if (serverAdapterBaseObject) {
288
333
  const serverAdapterBaseObjectProp = serverAdapterBaseObject[prop];
@@ -297,7 +342,7 @@ RequestCtor = fetch.Request) {
297
342
  apply(_, __, [input, ctx]) {
298
343
  return genericRequestHandler(input, ctx);
299
344
  },
300
- });
345
+ }); // 😡
301
346
  }
302
347
 
303
348
  exports.createServerAdapter = createServerAdapter;
package/index.mjs CHANGED
@@ -150,6 +150,23 @@ async function sendNodeResponse({ headers, status, statusText, body }, serverRes
150
150
  }
151
151
  });
152
152
  }
153
+ function isRequestInit(val) {
154
+ return (val != null &&
155
+ typeof val === 'object' &&
156
+ ('body' in val ||
157
+ 'cache' in val ||
158
+ 'credentials' in val ||
159
+ 'headers' in val ||
160
+ 'integrity' in val ||
161
+ 'keepalive' in val ||
162
+ 'method' in val ||
163
+ 'mode' in val ||
164
+ 'redirect' in val ||
165
+ 'referrer' in val ||
166
+ 'referrerPolicy' in val ||
167
+ 'signal' in val ||
168
+ 'window' in val));
169
+ }
153
170
 
154
171
  /// <reference lib="webworker" />
155
172
  async function handleWaitUntils(waitUntilPromises) {
@@ -166,13 +183,18 @@ function createServerAdapter(serverAdapterBaseObject,
166
183
  */
167
184
  RequestCtor = Request) {
168
185
  const handleRequest = typeof serverAdapterBaseObject === 'function' ? serverAdapterBaseObject : serverAdapterBaseObject.handle;
169
- function handleNodeRequest(nodeRequest, serverContext) {
186
+ function handleNodeRequest(nodeRequest, ctx) {
170
187
  const request = normalizeNodeRequest(nodeRequest, RequestCtor);
171
- return handleRequest(request, serverContext);
188
+ return handleRequest(request, ctx);
172
189
  }
173
- async function requestListener(nodeRequest, serverResponse) {
190
+ async function requestListener(nodeRequest, serverResponse, ...ctx) {
174
191
  const waitUntilPromises = [];
192
+ let serverContext = {};
193
+ if ((ctx === null || ctx === void 0 ? void 0 : ctx.length) > 0) {
194
+ serverContext = Object.assign({}, serverContext, ...ctx);
195
+ }
175
196
  const response = await handleNodeRequest(nodeRequest, {
197
+ ...serverContext,
176
198
  req: nodeRequest,
177
199
  res: serverResponse,
178
200
  waitUntil(p) {
@@ -191,30 +213,34 @@ RequestCtor = Request) {
191
213
  if (waitUntilPromises.length > 0) {
192
214
  await handleWaitUntils(waitUntilPromises);
193
215
  }
216
+ return response;
194
217
  }
195
- function handleEvent(event) {
218
+ function handleEvent(event, ...ctx) {
196
219
  if (!event.respondWith || !event.request) {
197
220
  throw new TypeError(`Expected FetchEvent, got ${event}`);
198
221
  }
199
- const response$ = handleRequest(event.request, event);
222
+ let serverContext = {};
223
+ if ((ctx === null || ctx === void 0 ? void 0 : ctx.length) > 0) {
224
+ serverContext = Object.assign({}, serverContext, ...ctx);
225
+ }
226
+ const response$ = handleRequest(event.request, serverContext);
200
227
  event.respondWith(response$);
228
+ return response$;
201
229
  }
202
- function handleRequestWithWaitUntil(request, ctx = {}, ...rest) {
230
+ function handleRequestWithWaitUntil(request, ctx) {
203
231
  var _a;
232
+ const extendedCtx = ctx;
204
233
  if ('process' in globalThis && ((_a = process.versions) === null || _a === void 0 ? void 0 : _a['bun']) != null) {
205
234
  // This is required for bun
206
235
  request.text();
207
236
  }
208
- if ((rest === null || rest === void 0 ? void 0 : rest.length) > 0) {
209
- ctx = Object.assign({}, ctx, ...rest);
210
- }
211
- if (!ctx.waitUntil) {
237
+ if (!extendedCtx.waitUntil) {
212
238
  const waitUntilPromises = [];
213
- ctx.waitUntil = (p) => {
239
+ extendedCtx.waitUntil = (p) => {
214
240
  waitUntilPromises.push(p);
215
241
  };
216
242
  const response$ = handleRequest(request, {
217
- ...ctx,
243
+ ...extendedCtx,
218
244
  waitUntil(p) {
219
245
  waitUntilPromises.push(p);
220
246
  },
@@ -224,32 +250,51 @@ RequestCtor = Request) {
224
250
  }
225
251
  return response$;
226
252
  }
227
- return handleRequest(request, ctx);
253
+ return handleRequest(request, extendedCtx);
228
254
  }
229
- function genericRequestHandler(input, ctx, ...rest) {
255
+ const fetchFn = (input, initOrCtx, ...ctx) => {
256
+ let init;
257
+ let serverContext = {};
258
+ if (isRequestInit(initOrCtx)) {
259
+ init = initOrCtx;
260
+ }
261
+ else {
262
+ init = {};
263
+ serverContext = Object.assign({}, serverContext, initOrCtx);
264
+ }
265
+ if ((ctx === null || ctx === void 0 ? void 0 : ctx.length) > 0) {
266
+ serverContext = Object.assign({}, serverContext, ...ctx);
267
+ }
268
+ if (typeof input === 'string' || input instanceof URL) {
269
+ return handleRequestWithWaitUntil(new RequestCtor(input, init), serverContext);
270
+ }
271
+ return handleRequestWithWaitUntil(input, serverContext);
272
+ };
273
+ const genericRequestHandler = (input, initOrCtxOrRes, ...ctx) => {
230
274
  // If it is a Node request
231
- if (isReadable(input) && ctx != null && isServerResponse(ctx)) {
232
- return requestListener(input, ctx);
275
+ if (isReadable(input) && isServerResponse(initOrCtxOrRes)) {
276
+ return requestListener(input, initOrCtxOrRes, ...ctx);
277
+ }
278
+ if (isServerResponse(initOrCtxOrRes)) {
279
+ throw new Error('Got Node response without Node request');
233
280
  }
234
281
  // Is input a container object over Request?
235
- if (input.request) {
282
+ if (typeof input === 'object' && 'request' in input) {
236
283
  // Is it FetchEvent?
237
- if (input.respondWith) {
238
- return handleEvent(input);
284
+ if ('respondWith' in input) {
285
+ return handleEvent(input, isRequestInit(initOrCtxOrRes) ? {} : initOrCtxOrRes, ...ctx);
239
286
  }
240
287
  // In this input is also the context
241
- return handleRequestWithWaitUntil(input.request, input, ...rest);
288
+ return fetchFn(
289
+ // @ts-expect-error input can indeed be a Request
290
+ input.request, initOrCtxOrRes, ...ctx);
242
291
  }
243
292
  // Or is it Request itself?
244
293
  // Then ctx is present and it is the context
245
- return handleRequestWithWaitUntil(input, ctx, ...rest);
246
- }
247
- function fetchFn(input, init, ...ctx) {
248
- if (typeof input === 'string' || input instanceof URL) {
249
- return handleRequestWithWaitUntil(new RequestCtor(input, init), ...ctx);
250
- }
251
- return handleRequestWithWaitUntil(input, init, ...ctx);
252
- }
294
+ return fetchFn(
295
+ // @ts-expect-error input can indeed string | Request | URL
296
+ input, initOrCtxOrRes, ...ctx);
297
+ };
253
298
  const adapterObj = {
254
299
  handleRequest,
255
300
  fetch: fetchFn,
@@ -273,12 +318,12 @@ RequestCtor = Request) {
273
318
  }
274
319
  return adapterProp;
275
320
  }
276
- const genericRequestHandlerProp = genericRequestHandler[prop];
277
- if (genericRequestHandlerProp) {
278
- if (genericRequestHandlerProp.bind) {
279
- return genericRequestHandlerProp.bind(genericRequestHandler);
321
+ const handleProp = genericRequestHandler[prop];
322
+ if (handleProp) {
323
+ if (handleProp.bind) {
324
+ return handleProp.bind(genericRequestHandler);
280
325
  }
281
- return genericRequestHandlerProp;
326
+ return handleProp;
282
327
  }
283
328
  if (serverAdapterBaseObject) {
284
329
  const serverAdapterBaseObjectProp = serverAdapterBaseObject[prop];
@@ -293,7 +338,7 @@ RequestCtor = Request) {
293
338
  apply(_, __, [input, ctx]) {
294
339
  return genericRequestHandler(input, ctx);
295
340
  },
296
- });
341
+ }); // 😡
297
342
  }
298
343
 
299
344
  export { createServerAdapter };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@whatwg-node/server",
3
- "version": "0.4.5",
3
+ "version": "0.4.6-alpha-20220922124249-c941ae6",
4
4
  "description": "Fetch API compliant HTTP Server adapter",
5
5
  "sideEffects": false,
6
6
  "peerDependencies": {
package/utils.d.ts CHANGED
@@ -21,3 +21,4 @@ export declare function normalizeNodeRequest(nodeRequest: NodeRequest, RequestCt
21
21
  export declare function isReadable(stream: any): stream is Readable;
22
22
  export declare function isServerResponse(stream: any): stream is ServerResponse;
23
23
  export declare function sendNodeResponse({ headers, status, statusText, body }: Response, serverResponse: ServerResponse): Promise<void>;
24
+ export declare function isRequestInit(val: unknown): val is RequestInit;