@whatwg-node/server 0.5.9-alpha-20230130162825-1e02017 → 0.5.9

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 (4) hide show
  1. package/README.md +97 -30
  2. package/index.js +12 -4
  3. package/index.mjs +12 -4
  4. package/package.json +2 -2
package/README.md CHANGED
@@ -1,8 +1,10 @@
1
1
  # WHATWG Node Generic Server Adapter
2
2
 
3
- `@whatwg-node/server` helps you to create a generic server implementation by using WHATWG Fetch API for Node.js, AWS Lambda, Cloudflare Workers, Deno, Express, Fastify, Koa, Next.js and Sveltekit.
3
+ `@whatwg-node/server` helps you to create a generic server implementation by using WHATWG Fetch API
4
+ for Node.js, AWS Lambda, Cloudflare Workers, Deno, Express, Fastify, Koa, Next.js and Sveltekit.
4
5
 
5
- Once you create an adapter with `createServerAdapter`, you don't need to install any other platform specific package since the generic adapter will handle it automatically.
6
+ Once you create an adapter with `createServerAdapter`, you don't need to install any other platform
7
+ specific package since the generic adapter will handle it automatically.
6
8
 
7
9
  ## How to start
8
10
 
@@ -26,8 +28,8 @@ You can use your server adapter with the following integrations:
26
28
  [Node.js](https://nodejs.org/api/http.html) is the most popular server side JavaScript runtime.
27
29
 
28
30
  ```ts
29
- import myServerAdapter from './myServerAdapter'
30
31
  import { createServer } from 'http'
32
+ import myServerAdapter from './myServerAdapter'
31
33
 
32
34
  // You can create your Node server instance by using our adapter
33
35
  const nodeServer = createServer(myServerAdapter)
@@ -37,21 +39,71 @@ nodeServer.listen(4000)
37
39
 
38
40
  ### AWS Lambda
39
41
 
40
- AWS Lambda is a serverless computing platform that makes it easy to build applications that run on the AWS cloud. Our adaoter is platform agnostic so they can fit together easily. In order to reduce the boilerplate we prefer to use [Serverless Express from Vendia](https://github.com/vendia/serverless-express).
42
+ AWS Lambda is a serverless computing platform that makes it easy to build applications that run on
43
+ the AWS cloud. Our adaoter is platform agnostic so they can fit together easily. In order to reduce
44
+ the boilerplate we prefer to use
45
+ [Serverless Express from Vendia](https://github.com/vendia/serverless-express).
41
46
 
42
47
  ```ts
43
- import myServerAdapter from './myServerAdapter'
48
+ import { APIGatewayEvent, APIGatewayProxyResult, Context } from 'aws-lambda'
44
49
  import type { Handler } from '@aws-cdk/aws-lambda'
45
- import { configure } from '@vendia/serverless-express'
50
+ import myServerAdapter from './myServerAdapter'
46
51
 
47
- export const handler: Handler = configure({
48
- app: myServerAdapter
49
- })
52
+ interface ServerContext {
53
+ event: APIGatewayEvent
54
+ lambdaContext: Context
55
+ }
56
+
57
+ export async function handler(
58
+ event: APIGatewayEvent,
59
+ lambdaContext: Context
60
+ ): Promise<APIGatewayProxyResult> {
61
+ const url = new URL(event.path, 'http://localhost')
62
+ if (event.queryStringParameters != null) {
63
+ for (const name in event.queryStringParameters) {
64
+ const value = event.queryStringParameters[name]
65
+ if (value != null) {
66
+ url.searchParams.set(name, value)
67
+ }
68
+ }
69
+ }
70
+
71
+ const response = await myServerAdapter.fetch(
72
+ url,
73
+ {
74
+ // For v1.0 you should use event.httpMethod
75
+ method: event.requestContext.http.method,
76
+ headers: event.headers as HeadersInit,
77
+ body: event.body
78
+ ? Buffer.from(event.body, event.isBase64Encoded ? 'base64' : 'utf8')
79
+ : undefined
80
+ },
81
+ {
82
+ event,
83
+ lambdaContext
84
+ }
85
+ )
86
+
87
+ const responseHeaders: Record<string, string> = {}
88
+
89
+ response.headers.forEach((value, name) => {
90
+ responseHeaders[name] = value
91
+ })
92
+
93
+ return {
94
+ statusCode: response.status,
95
+ headers: responseHeaders,
96
+ body: await response.text(),
97
+ isBase64Encoded: false
98
+ }
99
+ }
50
100
  ```
51
101
 
52
102
  ### Cloudflare Workers
53
103
 
54
- Cloudflare Workers provides a serverless execution environment that allows you to create entirely new applications or augment existing ones without configuring or maintaining infrastructure. It uses Fetch API already so we can use our adapter as an event listener like below;
104
+ Cloudflare Workers provides a serverless execution environment that allows you to create entirely
105
+ new applications or augment existing ones without configuring or maintaining infrastructure. It uses
106
+ Fetch API already so we can use our adapter as an event listener like below;
55
107
 
56
108
  ```ts
57
109
  import myServerAdapter from './myServerAdapter'
@@ -65,18 +117,20 @@ self.addEventListener('fetch', myServerAdapter)
65
117
  You can use our adapter as a Deno request handler like below;
66
118
 
67
119
  ```ts
68
- import { serve } from 'https://deno.land/std@0.117.0/http/server.ts'
120
+ import { serve } from 'https://deno.land/std@0.157.0/http/server.ts'
69
121
  import myServerAdapter from './myServerAdapter'
70
122
 
71
123
  serve(myServerAdapter, {
72
- // Listen any port you want
73
- addr: ':4000'
124
+ onListen({ hostname, port }) {
125
+ console.log(`Listening on http://${hostname}:${port}/graphql`)
126
+ }
74
127
  })
75
128
  ```
76
129
 
77
130
  ### Express
78
131
 
79
- [Express is the most popular web framework for Node.js.](https://expressjs.com/) It is a minimalist framework that provides a robust set of features to handle HTTP on Node.js applications.
132
+ [Express is the most popular web framework for Node.js.](https://expressjs.com/) It is a minimalist
133
+ framework that provides a robust set of features to handle HTTP on Node.js applications.
80
134
 
81
135
  You can easily integrate your adapter into your Express application with a few lines of code.
82
136
 
@@ -96,14 +150,15 @@ app.listen(4000, () => {
96
150
 
97
151
  ### Fastify
98
152
 
99
- [Fastify is one of the popular HTTP server frameworks for Node.js.](https://www.fastify.io/). You can use your adapter easily with Fastify.
153
+ [Fastify is one of the popular HTTP server frameworks for Node.js.](https://www.fastify.io/). You
154
+ can use your adapter easily with Fastify.
100
155
 
101
156
  So you can benefit from the powerful plugins of Fastify ecosystem.
102
157
  [See the ecosystem](https://www.fastify.io/docs/latest/Guides/Ecosystem/)
103
158
 
104
159
  ```ts
160
+ import fastify, { FastifyReply, FastifyRequest } from 'fastify'
105
161
  import myServerAdapter from './myServerAdapter'
106
- import fastify, { FastifyRequest, FastifyReply } from 'fastify'
107
162
 
108
163
  // This is the fastify instance you have created
109
164
  const app = fastify({ logger: true })
@@ -127,7 +182,8 @@ app.route({
127
182
 
128
183
  reply.status(response.status)
129
184
 
130
- reply.send(response.body)
185
+ // Fastify doesn't accept `null` as a response body
186
+ reply.send(response.body || undefined)
131
187
 
132
188
  return reply
133
189
  }
@@ -138,7 +194,9 @@ app.listen(4000)
138
194
 
139
195
  ### Koa
140
196
 
141
- [Koa is another Node.js server framework designed by the team behind Express, which aims to be a smaller, more expressive.](https://koajs.com/) You can add your adapter to your Koa application with a few lines of code then [benefit middlewares written for Koa.](https://github.com/koajs/koa/wiki)
197
+ [Koa is another Node.js server framework designed by the team behind Express, which aims to be a smaller, more expressive.](https://koajs.com/)
198
+ You can add your adapter to your Koa application with a few lines of code then
199
+ [benefit middlewares written for Koa.](https://github.com/koajs/koa/wiki)
142
200
 
143
201
  ```ts
144
202
  import Koa from 'koa'
@@ -167,13 +225,14 @@ app.listen(4000, () => {
167
225
 
168
226
  ### Next.js
169
227
 
170
- [Next.js](https://nextjs.org/) is a web framework that allows you to build websites very quickly and our new server adapter can be integrated with Next.js easily as an API Route.
228
+ [Next.js](https://nextjs.org/) is a web framework that allows you to build websites very quickly and
229
+ our new server adapter can be integrated with Next.js easily as an API Route.
171
230
 
172
231
  ```ts
173
232
  // pages/api/myEndpoint.ts
174
233
  // Next.js API route support: https://nextjs.org/docs/api-routes/introduction
175
- import myServerAdapter from './myServerAdapter'
176
234
  import type { NextApiRequest, NextApiResponse } from 'next'
235
+ import myServerAdapter from './myServerAdapter'
177
236
 
178
237
  export const config = {
179
238
  api: {
@@ -187,7 +246,8 @@ export default myServerAdapter
187
246
 
188
247
  ### SvelteKit
189
248
 
190
- [SvelteKit](https://kit.svelte.dev/) is the fastest way to build svelte apps. It is very simple, and let you build frontend & backend in a single place
249
+ [SvelteKit](https://kit.svelte.dev/) is the fastest way to build svelte apps. It is very simple, and
250
+ let you build frontend & backend in a single place
191
251
 
192
252
  ```ts
193
253
  import myServerAdapter from './myServerAdapter'
@@ -197,8 +257,8 @@ export { myServerAdapter as get, myServerAdapter as post }
197
257
 
198
258
  ### Bun
199
259
 
200
- [Bun](https://bun.sh/) is a modern JavaScript runtime like Node or Deno, and it supports Fetch API as a first class citizen.
201
- So the configuration is really simple like any other JS runtime;
260
+ [Bun](https://bun.sh/) is a modern JavaScript runtime like Node or Deno, and it supports Fetch API
261
+ as a first class citizen. So the configuration is really simple like any other JS runtime;
202
262
 
203
263
  ```ts
204
264
  import myServerAdapter from './myServerAdapter'
@@ -212,9 +272,11 @@ console.info(`Server is running on ${server.hostname}`)
212
272
 
213
273
  ## File Uploads / Multipart Requests
214
274
 
215
- Multipart requests are a type of HTTP request that allows you to send blobs together with regular text data which has a mime-type `multipart/form-data`.
275
+ Multipart requests are a type of HTTP request that allows you to send blobs together with regular
276
+ text data which has a mime-type `multipart/form-data`.
216
277
 
217
- For example, if you send a multipart request from a browser with `FormData`, you can get the same `FormData` object in your request handler.
278
+ For example, if you send a multipart request from a browser with `FormData`, you can get the same
279
+ `FormData` object in your request handler.
218
280
 
219
281
  ```ts
220
282
  import { createServerAdapter } from '@whatwg-node/server'
@@ -238,15 +300,21 @@ const myServerAdapter = createServerAdapter(async request => {
238
300
  })
239
301
  ```
240
302
 
241
- You can learn more about [File API](https://developer.mozilla.org/en-US/docs/Web/API/File) on MDN documentation.
303
+ You can learn more about [File API](https://developer.mozilla.org/en-US/docs/Web/API/File) on MDN
304
+ documentation.
242
305
 
243
306
  ## Routing and Middlewares
244
307
 
245
- We'd recommend to use `@whatwg-node/router` to handle routing and middleware approach. It uses `@whatwg-node/server` under the hood.
308
+ We'd recommend to use `@whatwg-node/router` to handle routing and middleware approach. It uses
309
+ `@whatwg-node/server` under the hood.
310
+
311
+ > Learn more about `@whatwg-node/router` [here](../router)
246
312
 
247
313
  ### Basic Routing
248
314
 
249
315
  ```ts
316
+ // Then use it in any environment
317
+ import { createServer } from 'http'
250
318
  import { createRouter, Router } from '@whatwg-node/router'
251
319
 
252
320
  const router = createRouter()
@@ -266,15 +334,14 @@ router.get('/google', () => Response.redirect('http://www.google.com'))
266
334
  // 404 for everything else
267
335
  router.all('*', () => new Response('Not Found.', { status: 404 }))
268
336
 
269
- // Then use it in any environment
270
- import { createServer } from 'http'
271
337
  const httpServer = createServer(router)
272
338
  httpServer.listen(4000)
273
339
  ```
274
340
 
275
341
  ### Middlewares to handle CORS, cookies and more
276
342
 
277
- This package also provides some utilities for your platform agnostic server implementation. The following example shows how to get the cookies as an object from the request.
343
+ This package also provides some utilities for your platform agnostic server implementation. The
344
+ following example shows how to get the cookies as an object from the request.
278
345
 
279
346
  ```ts
280
347
  import { withCookies } from '@whatwg-node/server'
package/index.js CHANGED
@@ -5,7 +5,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
5
5
  const fetch = require('@whatwg-node/fetch');
6
6
 
7
7
  function isAsyncIterable(body) {
8
- return body != null && typeof body === 'object' && typeof body[Symbol.asyncIterator] === 'function';
8
+ return (body != null && typeof body === 'object' && typeof body[Symbol.asyncIterator] === 'function');
9
9
  }
10
10
  function getPort(nodeRequest) {
11
11
  var _a, _b, _c, _d, _e;
@@ -128,7 +128,11 @@ function isNodeRequest(request) {
128
128
  }
129
129
  function isServerResponse(stream) {
130
130
  // Check all used functions are defined
131
- return (stream != null && stream.setHeader != null && stream.end != null && stream.once != null && stream.write != null);
131
+ return (stream != null &&
132
+ stream.setHeader != null &&
133
+ stream.end != null &&
134
+ stream.once != null &&
135
+ stream.write != null);
132
136
  }
133
137
  function isReadableStream(stream) {
134
138
  return stream != null && stream.getReader != null;
@@ -203,7 +207,9 @@ function createServerAdapter(serverAdapterBaseObject,
203
207
  * WHATWG Fetch spec compliant `Request` constructor.
204
208
  */
205
209
  RequestCtor = fetch.Request) {
206
- const handleRequest = typeof serverAdapterBaseObject === 'function' ? serverAdapterBaseObject : serverAdapterBaseObject.handle;
210
+ const handleRequest = typeof serverAdapterBaseObject === 'function'
211
+ ? serverAdapterBaseObject
212
+ : serverAdapterBaseObject.handle;
207
213
  function handleNodeRequest(nodeRequest, ...ctx) {
208
214
  const serverContext = ctx.length > 1 ? completeAssign({}, ...ctx) : ctx[0];
209
215
  const request = normalizeNodeRequest(nodeRequest, RequestCtor);
@@ -372,7 +378,9 @@ function getCORSHeadersByRequestAndOptions(request, corsOptions) {
372
378
  return headers;
373
379
  }
374
380
  // If defined origins have '*' or undefined by any means, we should allow all origins
375
- if (corsOptions.origin == null || corsOptions.origin.length === 0 || corsOptions.origin.includes('*')) {
381
+ if (corsOptions.origin == null ||
382
+ corsOptions.origin.length === 0 ||
383
+ corsOptions.origin.includes('*')) {
376
384
  const currentOrigin = request.headers.get('origin');
377
385
  // If origin is available in the headers, use it
378
386
  if (currentOrigin != null) {
package/index.mjs CHANGED
@@ -2,7 +2,7 @@ import { Request, Response } from '@whatwg-node/fetch';
2
2
  export { Response } from '@whatwg-node/fetch';
3
3
 
4
4
  function isAsyncIterable(body) {
5
- return body != null && typeof body === 'object' && typeof body[Symbol.asyncIterator] === 'function';
5
+ return (body != null && typeof body === 'object' && typeof body[Symbol.asyncIterator] === 'function');
6
6
  }
7
7
  function getPort(nodeRequest) {
8
8
  var _a, _b, _c, _d, _e;
@@ -125,7 +125,11 @@ function isNodeRequest(request) {
125
125
  }
126
126
  function isServerResponse(stream) {
127
127
  // Check all used functions are defined
128
- return (stream != null && stream.setHeader != null && stream.end != null && stream.once != null && stream.write != null);
128
+ return (stream != null &&
129
+ stream.setHeader != null &&
130
+ stream.end != null &&
131
+ stream.once != null &&
132
+ stream.write != null);
129
133
  }
130
134
  function isReadableStream(stream) {
131
135
  return stream != null && stream.getReader != null;
@@ -200,7 +204,9 @@ function createServerAdapter(serverAdapterBaseObject,
200
204
  * WHATWG Fetch spec compliant `Request` constructor.
201
205
  */
202
206
  RequestCtor = Request) {
203
- const handleRequest = typeof serverAdapterBaseObject === 'function' ? serverAdapterBaseObject : serverAdapterBaseObject.handle;
207
+ const handleRequest = typeof serverAdapterBaseObject === 'function'
208
+ ? serverAdapterBaseObject
209
+ : serverAdapterBaseObject.handle;
204
210
  function handleNodeRequest(nodeRequest, ...ctx) {
205
211
  const serverContext = ctx.length > 1 ? completeAssign({}, ...ctx) : ctx[0];
206
212
  const request = normalizeNodeRequest(nodeRequest, RequestCtor);
@@ -369,7 +375,9 @@ function getCORSHeadersByRequestAndOptions(request, corsOptions) {
369
375
  return headers;
370
376
  }
371
377
  // If defined origins have '*' or undefined by any means, we should allow all origins
372
- if (corsOptions.origin == null || corsOptions.origin.length === 0 || corsOptions.origin.includes('*')) {
378
+ if (corsOptions.origin == null ||
379
+ corsOptions.origin.length === 0 ||
380
+ corsOptions.origin.includes('*')) {
373
381
  const currentOrigin = request.headers.get('origin');
374
382
  // If origin is available in the headers, use it
375
383
  if (currentOrigin != null) {
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@whatwg-node/server",
3
- "version": "0.5.9-alpha-20230130162825-1e02017",
3
+ "version": "0.5.9",
4
4
  "description": "Fetch API compliant HTTP Server adapter",
5
5
  "sideEffects": false,
6
6
  "dependencies": {
7
- "@whatwg-node/fetch": "0.6.3-alpha-20230130162825-1e02017",
7
+ "@whatwg-node/fetch": "0.6.3",
8
8
  "tslib": "^2.3.1"
9
9
  },
10
10
  "repository": {