sleepy-serv 0.2.1 → 0.3.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.
package/README.md CHANGED
@@ -73,11 +73,19 @@ The route's logic is implemented in the route definition files. These must `expo
73
73
  Here's an example of a simple handler function:
74
74
 
75
75
  ```js
76
- export default function (req) {
76
+ export default function (req, res) {
77
+ console.log('res:', res)
78
+
77
79
  return new Response('Hello world')
78
80
  }
79
81
  ```
80
82
 
83
+ These functions take two parameters:
84
+ - `req`: a `BunRequest` object
85
+ - `res`: a results object
86
+
87
+ The `res` parameter might seem familiar if coming from ExpressJS, but this parameter has a different purpose. The `res` parameter is meant to act as a dedicated, persistent object that middleware can write their results to. This way, the `req` object stays as a lean `BunRequest`.
88
+
81
89
  These handlers can also be `async` functions and `sleepy-serv` will wait for them to finish before moving on.
82
90
 
83
91
  ### Middleware
@@ -86,13 +94,13 @@ As mentioned earlier, method definition files can also export an array of functi
86
94
 
87
95
  ```js
88
96
  export default [
89
- async req => {
90
- req.parsedBody = await req.json()
97
+ async (req, res) => {
98
+ res.body = await req.json()
91
99
  },
92
- req => {
93
- console.log('JSON body:', req.parsedBody)
100
+ (req, res) => {
101
+ console.log('JSON body:', res.body)
94
102
 
95
- return new Response('Hello world', )
103
+ return new Response('Hello world')
96
104
  },
97
105
  ]
98
106
  ```
@@ -219,6 +227,72 @@ The middleware defined in `/api/users/:userId/meta.js` will be applied the follo
219
227
 
220
228
  At the time of this writing, `meta.js` only exports middleware functions.
221
229
 
230
+ ## Build-In Middleware
231
+
232
+ `sleepy-serv` also comes built-in with a few useful middleware functions that are commonly used.
233
+
234
+ ### parseJson(req, _res)
235
+
236
+ This middleware parses the request's `body` property as a JSON string, and then stores the results in `res.body`. Additional body parsers can be written in the future a accommodate other body encoding schemes.
237
+
238
+ ### validateSchema(schemas)
239
+
240
+ This function takes a `schemas` object. Each property is optional:
241
+ - `headers`: takes a string formatter schema to evaulate `req.headers`
242
+ - `params`: takes a string formatter schema to evaulate `req.params`
243
+ - `query`: takes a string foramtter schema to evaulate `req.query`
244
+ - `body`: takes a JSON validation schema to evaulate `res.body`
245
+
246
+ Here's an example of the schema in action:
247
+
248
+ ```
249
+ PUT /contacts/123/addresses
250
+
251
+ {
252
+ street1: '123 Main St.',
253
+ street2: '#100',
254
+ city: 'Las Vegas',
255
+ state: 'NV',
256
+ postalCode: '12345',
257
+ }
258
+ ```
259
+
260
+ ***
261
+ TODO: add JSON schema example.
262
+
263
+ Please take a look at the `lib/src/middleware.test.js` test file for a far a comprehensive set of examples on how to use this middleware.
264
+ ***
265
+
266
+ The `headers`, `params`, and `query` (querystrings) can only be strings, so they're evaulated using a simplified _string format schema_ instead of a full JSON schema.
267
+
268
+ The string formatter schema looks like this:
269
+
270
+ ```javascript
271
+ {
272
+ type: 'format',
273
+ value: 'email',
274
+ }
275
+ ```
276
+
277
+ **`type`**
278
+
279
+ Can either set to `'format'` or `'pattern'`. The value of `type` determines how the `value` property is used.
280
+
281
+ **`value`**
282
+
283
+ This determines how to evaulate the string based on the `type` parameter. If `type` is set to `'format'`, then `value` can be set to one of the pre-defined formats that's provided by the JSON schema specification. If `type` is set to `'pattern'`, then `value` can be set to a regex pattern instead.
284
+
285
+ Custom formats can also be provided by using the `setValidationFormats()` during app initialization. Here's an example:
286
+
287
+ ```javascript
288
+ middleware.setValidationFormats({
289
+ phone: /^\d{10}$/, /* 10-digit, numeric string */
290
+ postalCode: /^\d{5}$/, /* 5-digit, numeric string */
291
+ })
292
+ ```
293
+
294
+ Calling `setValidationFormats()` extends the possible values that can be passed to the `value` property when evaulating strings in either the string formatter schema, or the `res.body`'s JSON schema.
295
+
222
296
  ## `createApp()` Options
223
297
 
224
298
  ### `hostname`
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "sleepy-serv",
3
3
  "description": "A more opinionated web server for building REST-ful applications",
4
4
  "author": "Travis J True",
5
- "version": "0.2.1",
5
+ "version": "0.3.0",
6
6
  "exports": "./src/index.js",
7
7
  "type": "module",
8
8
  "keywords": [
package/src/index.js CHANGED
@@ -187,14 +187,15 @@ ${route.modulePath}
187
187
 
188
188
  const handler = async req => {
189
189
  const query = req.url.split('?')[1]
190
+ const res = {}
190
191
 
191
192
  req.query = query ? querystring.parse(query) : {}
192
193
 
193
194
  for (const fn of middlewareChain) {
194
- const res = await fn(req)
195
+ const response = await fn(req, res)
195
196
 
196
- if (res) {
197
- return res
197
+ if (response) {
198
+ return response
198
199
  }
199
200
  }
200
201
  }
package/src/middleware.js CHANGED
@@ -46,14 +46,14 @@ function buildFormatterSchema (schema) {
46
46
  }
47
47
  }
48
48
 
49
- export async function parseJson (req) {
49
+ export async function parseJson (req, res) {
50
50
  const contentType = req.headers.get('content-type')
51
51
 
52
52
  if (req.method !== 'GET' && contentType !== 'application/json') {
53
53
  throw new UnsupportedMediaTypeError('content-type')
54
54
  }
55
55
 
56
- req.parsedBody = await req.json()
56
+ res.body = await req.json()
57
57
  }
58
58
 
59
59
  export function setValidationFormats (formats) {
@@ -61,12 +61,12 @@ export function setValidationFormats (formats) {
61
61
  }
62
62
 
63
63
  export function validateSchema (schemas) {
64
- return function (req) {
64
+ return function (req, res) {
65
65
  const formattedSchemas = {
66
66
  headers: buildFormatterSchema(schemas.headers),
67
67
  params: buildFormatterSchema(schemas.params),
68
68
  query: buildFormatterSchema(schemas.query),
69
- parsedBody: schemas.parsedBody || SCHEMA_EMPTY,
69
+ body: schemas.body || SCHEMA_EMPTY,
70
70
  }
71
71
 
72
72
  const ajv = new Ajv({
@@ -83,7 +83,7 @@ export function validateSchema (schemas) {
83
83
  const errors = Object
84
84
  .entries(formattedSchemas)
85
85
  .reduce((accum, [key, schema]) => {
86
- const data = req[key]
86
+ const data = key === 'body' ? res[key] : req[key]
87
87
  const valid = schema ? ajv.validate(schema, data) : true
88
88
 
89
89
  return !valid