1 | # ⚡ zap [![npm](https://badgen.net/npm/v/zap)](https://www.npmjs.com/package/zap) [![CI](https://github.com/jacobwgillespie/zap/actions/workflows/ci.yml/badge.svg)](https://github.com/jacobwgillespie/zap/actions/workflows/ci.yml)
|
2 |
|
3 | Zap is a lightweight HTTP server framework for Node.
|
4 |
|
5 | - [Installation](#installation)
|
6 | - [Usage](#usage)
|
7 | - [API](#api)
|
8 | - [Recipes](#recipes)
|
9 | - [Credits](#credits)
|
10 | - [License](#license)
|
11 |
|
12 | ## Installation
|
13 |
|
14 | Install with your favorite package manager:
|
15 |
|
16 | ```shell
|
17 | $ pnpm add zap
|
18 | $ yarn add zap
|
19 | $ npm install zap
|
20 | ```
|
21 |
|
22 | ## Usage
|
23 |
|
24 | ```typescript
|
25 | import {route, router, serve} from 'zap'
|
26 |
|
27 | const app = router(
|
28 | route('GET', '/', () => 'Hello World'),
|
29 |
|
30 | route('GET', '/hello/:name', (req) => `Hello ${req.params.name}`),
|
31 | )
|
32 |
|
33 | const server = http.createServer(serve(app))
|
34 | server.listen(3000)
|
35 | ```
|
36 |
|
37 | ## API
|
38 |
|
39 | ### `serve(handler, options)`
|
40 |
|
41 | Constructs a new `http.RequestListener` out of a `Handler`.
|
42 |
|
43 | ### `router(...routes)`
|
44 |
|
45 | Constructs a new `Handler` out of a list of `RouteHandlers`.
|
46 |
|
47 | ### `route(method, path, handler)`
|
48 |
|
49 | Constructs a `RouteHandler` that matches a given method (`GET`, `POST`, etc) and path.
|
50 |
|
51 | ### Body parsers
|
52 |
|
53 | - `buffer(req, options)` - read the request body as a `Buffer`
|
54 | - `text(req, options)` - read the request body as a string
|
55 | - `json(req, options)` - read the request body as parsed JSON
|
56 |
|
57 | ### Request helpers
|
58 |
|
59 | - `getHeader(req, header)` - returns the requested header if it was provided
|
60 | - `fromRequest(fn)` - wraps a function in the form `(req: ServerRequest, ...rest) => any` to return an equivalent function that caches its results for the provided request
|
61 |
|
62 | ### Response helpers
|
63 |
|
64 | - Ordinarily you would return a `ResponseBodyType` from a `Handler` function
|
65 | - `send(res, statusCode, body)` - a response with a given status code
|
66 | - `notFound()` - a 404 response
|
67 | - `redirect(location, statusCode)` - a redirect to another location (default status code 303)
|
68 | - `httpError(code, message, metadata)` - an error response with a given code, message, and optional metadata
|
69 |
|
70 | ## Recipes
|
71 |
|
72 | ### Validating body schema
|
73 |
|
74 | You can use a function that throws an `httpError` to provide type-safe body payload parsing:
|
75 |
|
76 | ```typescript
|
77 | async function parseBody(req: ServerRequest) {
|
78 | const body = await json(req)
|
79 | if (!validate(body)) throw httpError(400, 'invalid body')
|
80 | return body
|
81 | }
|
82 |
|
83 | route('POST', '/example', (req) => {
|
84 | const body = await parseBody(req)
|
85 | // body is now typed according to your parseBody return type
|
86 | })
|
87 | ```
|
88 |
|
89 | ### Error handling
|
90 |
|
91 | The `serve()` function options accept an `errorHandler` that will replace `zap`'s built-in error handler. This allows you to report errors to services like Sentry, format the response sent to the user, etc.
|
92 |
|
93 | ```typescript
|
94 | serve(handler, {
|
95 | errorHandler: (_, res, error) => {
|
96 | send(res, 500, {message: 'Internal server error', details: formatError(error)})
|
97 | },
|
98 | })
|
99 | ```
|
100 |
|
101 | ## Credits
|
102 |
|
103 | Special thanks to [@nornagon](https://github.com/nornagon) for the `zap` package name. For versions of this module published before `v1.0.0`, see [nornagon/node-zap](https://github.com/nornagon/node-zap).
|
104 |
|
105 | ## License
|
106 |
|
107 | MIT License, see `LICENSE`.
|