1 | <div align="center">
|
2 | <img src="logo.png" alt="worktop" width="620" />
|
3 | </div>
|
4 |
|
5 | <div align="center">
|
6 | <a href="https://npmjs.org/package/worktop">
|
7 | <img src="https://badgen.now.sh/npm/v/worktop" alt="version" />
|
8 | </a>
|
9 | <a href="https://github.com/lukeed/worktop/actions?query=workflow%3ACI">
|
10 | <img src="https://github.com/lukeed/worktop/workflows/CI/badge.svg?event=push" alt="CI" />
|
11 | </a>
|
12 | <a href="https://npmjs.org/package/worktop">
|
13 | <img src="https://badgen.now.sh/npm/dm/worktop" alt="downloads" />
|
14 | </a>
|
15 | <a href="https://packagephobia.now.sh/result?p=worktop">
|
16 | <img src="https://packagephobia.now.sh/badge?p=worktop" alt="install size" />
|
17 | </a>
|
18 | </div>
|
19 |
|
20 | <div align="center">The next generation web framework for Cloudflare Workers</div>
|
21 |
|
22 | ## Features
|
23 |
|
24 | * Super [lightweight](https://npm.anvaka.com/#/view/2d/worktop)
|
25 | * First-class TypeScript support
|
26 | * Custom Middleware Support
|
27 | * Well-organized submodules for à la carte functionality<sup>*</sup>
|
28 | * Includes Router with support for pattern definitions
|
29 | * Familiar Request-Response handler API
|
30 | * Supports `async`/`await` handlers
|
31 | * Fully treeshakable
|
32 |
|
33 | > <sup>*</sup>_More to come!_
|
34 |
|
35 | ## Install
|
36 |
|
37 | ```
|
38 | $ npm install --save worktop
|
39 | ```
|
40 |
|
41 | ## Usage
|
42 |
|
43 | > Check out [`/examples`](/examples) for a list of working demos!
|
44 |
|
45 | ```ts
|
46 | import { Router } from 'worktop';
|
47 | import * as Cache from 'worktop/cache';
|
48 | import { uid as toUID } from 'worktop/utils';
|
49 | import { read, write } from 'worktop/kv';
|
50 | import type { KV } from 'worktop/kv';
|
51 |
|
52 | declare var DATA: KV.Namespace;
|
53 |
|
54 | interface Message {
|
55 | id: string;
|
56 | text: string;
|
57 | // ...
|
58 | }
|
59 |
|
60 | // Initialize
|
61 | const API = new Router();
|
62 |
|
63 |
|
64 | API.add('GET', '/messages/:id', async (req, res) => {
|
65 | // Pre-parsed `req.params` object
|
66 | const key = `messages::${req.params.id}`;
|
67 |
|
68 | // Assumes JSON (can override)
|
69 | const message = await read<Message>(DATA, key);
|
70 |
|
71 | // Alter response headers directly
|
72 | res.setHeader('Cache-Control', 'public, max-age=60');
|
73 |
|
74 | // Smart `res.send()` helper
|
75 | // ~> automatically stringifies JSON objects
|
76 | // ~> auto-sets `Content-Type` & `Content-Length` headers
|
77 | res.send(200, message);
|
78 | });
|
79 |
|
80 |
|
81 | API.add('POST', '/messages', async (req, res) => {
|
82 | try {
|
83 | // Smart `req.body` helper
|
84 | // ~> parses JSON header as JSON
|
85 | // ~> parses form-like header as FormData, ...etc
|
86 | var input = await req.body<Message>();
|
87 | } catch (err) {
|
88 | return res.send(400, 'Error parsing request body');
|
89 | }
|
90 |
|
91 | if (!input || !input.text.trim()) {
|
92 | return res.send(422, { text: 'required' });
|
93 | }
|
94 |
|
95 | const value: Message = {
|
96 | id: toUID(16),
|
97 | text: input.text.trim(),
|
98 | // ...
|
99 | };
|
100 |
|
101 | // Assumes JSON (can override)
|
102 | const key = `messages::${value.id}`;
|
103 | const success = await write<Message>(DATA, key, value);
|
104 | // ^ boolean
|
105 |
|
106 | // Alias for `event.waitUntil`
|
107 | // ~> queues background task (does NOT delay response)
|
108 | req.extend(
|
109 | fetch('https://.../logs', {
|
110 | method: 'POST',
|
111 | headers: { 'content-type': 'application/json '},
|
112 | body: JSON.stringify({ success, value })
|
113 | })
|
114 | );
|
115 |
|
116 | if (success) res.send(201, value);
|
117 | else res.send(500, 'Error creating record');
|
118 | });
|
119 |
|
120 |
|
121 | API.add('GET', '/alive', (req, res) => {
|
122 | res.end('OK'); // Node.js-like `res.end`
|
123 | });
|
124 |
|
125 |
|
126 | // Attach "fetch" event handler
|
127 | // ~> use `Cache` for request-matching, when permitted
|
128 | // ~> store Response in `Cache`, when permitted
|
129 | Cache.listen(API.run);
|
130 | ```
|
131 |
|
132 | ## API
|
133 |
|
134 | ### Module: `worktop`
|
135 |
|
136 | > [View `worktop` API documentation](/src/router.d.ts)
|
137 | [View `worktop` API documentation](/docs/module.router.md) -->
|
138 |
|
139 | The main module – concerned with routing. <br>This is core of most applications. Exports the [`Router`](/src/router.d.ts#L66) class.
|
140 |
|
141 | ### Module: `worktop/kv`
|
142 |
|
143 | > [View `worktop/kv` API documentation](/src/kv.d.ts)
|
144 | [View `worktop/kv` API documentation](/docs/module.kv.md) -->
|
145 |
|
146 | The `worktop/kv` submodule contains all classes and utilities related to [Workers KV](https://www.cloudflare.com/products/workers-kv/).
|
147 |
|
148 | ### Module: `worktop/cache`
|
149 |
|
150 | > [View `worktop/cache` API documentation](/src/cache.d.ts)
|
151 | [View `worktop/cache` API documentation](/docs/module.cache.md) -->
|
152 |
|
153 | The `worktop/cache` submodule contains all utilities related to [Cloudflare's Cache](https://developers.cloudflare.com/workers/learning/how-the-cache-works).
|
154 |
|
155 | ### Module: `worktop/request`
|
156 |
|
157 | > [View `worktop/request` API documentation](/src/request.d.ts)
|
158 | [View `worktop/request` API documentation](/docs/module.request.md) -->
|
159 |
|
160 | The `worktop/request` submodule contains the [`ServerRequest`](/src/request.d.ts#L117) class, which provides an interface similar to the request instance(s) found in most other Node.js frameworks.
|
161 |
|
162 | > **Note:** This module is used internally and will (very likely) never be imported by your application.
|
163 |
|
164 | ### Module: `worktop/response`
|
165 |
|
166 | > [View `worktop/response` API documentation](/src/response.d.ts)
|
167 | [View `worktop/response` API documentation](/docs/module.response.md) -->
|
168 |
|
169 | The `worktop/response` submodule contains the [`ServerResponse`](/src/response.d.ts#L6) class, which provides an interface similar to the [`IncomingMessage`](https://nodejs.org/api/http.html#http_class_http_incomingmessage) (aka, "response") object that Node.js provides.
|
170 |
|
171 | > **Note:** This module is used internally and will (very likely) never be imported by your application.
|
172 |
|
173 | ### Module: `worktop/base64`
|
174 |
|
175 | > [View `worktop/base64` API documentation](/src/base64.d.ts)
|
176 | [View `worktop/base64` API documentation](/docs/module.base64.md) -->
|
177 |
|
178 | The `worktop/base64` submodule contains a few utilities related to the [Base 64 encoding](https://tools.ietf.org/html/rfc4648#section-4).
|
179 |
|
180 | ### Module: `worktop/cookie`
|
181 |
|
182 | > [View `worktop/cookie` API documentation](/src/cookie.d.ts)
|
183 | [View `worktop/cookie` API documentation](/docs/module.cookie.md) -->
|
184 |
|
185 | The `worktop/cookie` submodule contains `parse` and `stringify` utilities for dealing with cookie header(s).
|
186 |
|
187 | ### Module: `worktop/cors`
|
188 |
|
189 | > [View `worktop/cors` API documentation](/src/cors.d.ts)
|
190 | [View `worktop/cors` API documentation](/docs/module.cors.md) -->
|
191 |
|
192 | The `worktop/cors` submodule offers utilities for dealing with [Cross-Origin Resource Sharing (CORS)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) headers.
|
193 |
|
194 | ### Module: `worktop/crypto`
|
195 |
|
196 | > [View `worktop/crypto` API documentation](/src/crypto.d.ts)
|
197 | [View `worktop/crypto` API documentation](/docs/module.crypto.md) -->
|
198 |
|
199 | The `worktop/crypto` submodule is a collection of cryptographic functionalities.
|
200 |
|
201 | ### Module: `worktop/utils`
|
202 |
|
203 | > [View `worktop/utils` API documentation](/src/utils.d.ts)
|
204 | [View `worktop/utils` API documentation](/docs/module.utils.md) -->
|
205 |
|
206 | The `worktop/utils` submodule is a collection of standalone, general-purpose utilities that you may find useful. These may include – but are not limited to – hashing functions and unique identifier generators.
|
207 |
|
208 | ### Module: `worktop/ws`
|
209 |
|
210 | > [View `worktop/ws` API documentation](/src/ws.d.ts)
|
211 | [View `worktop/ws` API documentation](/docs/module.ws.md) -->
|
212 |
|
213 | The `worktop/ws` submodule contains the [`WebSocket`](/src/ws.d.ts#L18) and [`WebSocketPair`](/src/ws.d.ts#L4) class definitions, as well as two middleware handlers for validating and/or setting up a [`SocketHandler`](/src/ws.d.ts#L38) for the WebSocket connection.
|
214 |
|
215 |
|
216 | ## License
|
217 |
|
218 | MIT © [Luke Edwards](https://lukeed.com)
|