|
1 | 1 | # acorn |
2 | 2 |
|
3 | | -[](https://github.com/oakserver/acorn) |
4 | | - |
5 | | -Rapidly develop and iterate on RESTful APIs using a strongly typed router |
6 | | -designed for Deno CLI, Deno Deploy and Bun. |
7 | | - |
8 | | -## Usage |
9 | | - |
10 | | -### Under Deno runtime or Deploy |
11 | | - |
12 | | -Add the package to your project: |
13 | | - |
14 | | -``` |
15 | | -deno add @oak/acorn |
16 | | -``` |
17 | | - |
18 | | -### Under Node.js and Cloudflare Workers |
19 | | - |
20 | | -Install the package using your chosen package manager: |
21 | | - |
22 | | -#### npm |
23 | | - |
24 | | -``` |
25 | | -npx jsr add @oak/acorn |
26 | | -``` |
27 | | - |
28 | | -#### Yarn |
29 | | - |
30 | | -``` |
31 | | -yarn dlx jsr add @oak/acorn |
32 | | -``` |
33 | | - |
34 | | -#### pnpm |
35 | | - |
36 | | -``` |
37 | | -pnpm dlx jsr add @oak/acorn |
38 | | -``` |
39 | | - |
40 | | -### Under Bun |
41 | | - |
42 | | -``` |
43 | | -bunx jsr add @oak/acorn |
44 | | -``` |
45 | | - |
46 | | -### Listening |
47 | | - |
48 | | -For Deno, Node.js, and Bun the router needs to be configured and then start |
49 | | -listening for requests: |
50 | | - |
51 | | -```ts |
52 | | -import { Router } from "@oak/acorn"; |
53 | | - |
54 | | -const BOOKS = { |
55 | | - "1": { id: 1, title: "The Hound of the Baskervilles" }, |
56 | | - "2": { id: 2, title: "It" }, |
57 | | -}; |
58 | | - |
59 | | -const router = new Router(); |
60 | | - |
61 | | -router.get("/", () => ({ hello: "world" })); |
62 | | -router.get("/books/:id", (ctx) => BOOKS[ctx.params.id]); |
63 | | - |
64 | | -router.listen({ port: 5000 }); |
65 | | -``` |
66 | | - |
67 | | -### Fetch handlers |
68 | | - |
69 | | -For Cloudflare Workers the router needs to be configured and router needs to be |
70 | | -the default export: |
71 | | - |
72 | | -```ts |
73 | | -import { Router } from "@oak/acorn"; |
74 | | - |
75 | | -const BOOKS = { |
76 | | - "1": { id: 1, title: "The Hound of the Baskervilles" }, |
77 | | - "2": { id: 2, title: "It" }, |
78 | | -}; |
79 | | - |
80 | | -const router = new Router(); |
81 | | - |
82 | | -router.get("/", () => ({ hello: "world" })); |
83 | | -router.get("/books/:id", (ctx) => BOOKS[ctx.params.id]); |
84 | | - |
85 | | -router.listen({ port: 5000 }); |
86 | | - |
87 | | -export default router; |
88 | | -``` |
89 | | - |
90 | | -## Philosophy |
91 | | - |
92 | | -After having spent years working on [oak](https://jsr.io/@oak/oak) and extensive |
93 | | -experience with building Deno, that really when people were looking at |
94 | | -middleware type of solution, really what they were looking fore was a straight |
95 | | -forward router that made it easy to handle JSON payloads. |
96 | | - |
97 | | -Also, oak was created in the early days of Deno, before it even had a native |
98 | | -HTTP server, and that server supported the web standard `Request` and |
99 | | -`Response`. |
100 | | - |
101 | | -Acorn was the culmination of that need. It makes it easy to have route handlers |
102 | | -that are straight forward and focuses on staying closer to the native |
103 | | -implementations of Deno constructs that have evolved over time. |
104 | | - |
105 | | -## Routes |
106 | | - |
107 | | -An instance of a router has several methods for registering a handler for a |
108 | | -route. The methods correspond to one or many HTTP methods or verbs. When a |
109 | | -request is handled by the router that matches a route and the HTTP method(s), it |
110 | | -will invoke the registered handler. |
111 | | - |
112 | | -The handler is provided with a context which contains information about the |
113 | | -request: |
114 | | - |
115 | | -```ts |
116 | | -interface Context<Params extends Record<string, string>, BodyType> { |
117 | | - readonly addr: Addr; |
118 | | - readonly cookies: SecureCookieMap; |
119 | | - readonly params: Params; |
120 | | - readonly request: Request; |
121 | | - readonly searchParams: Record<string, string>; |
122 | | - body(): Promise<BodyType | undefined>; |
123 | | - url(): URL; |
124 | | -} |
125 | | -``` |
126 | | - |
127 | | -The `.params` property provides any parameters (named captures) parsed out when |
128 | | -matching the route string. |
129 | | - |
130 | | -The `.searchParams` property provides any search parameters associated with the |
131 | | -request. |
132 | | - |
133 | | -The `.addr` property provides the remote address associated with the request. |
134 | | - |
135 | | -The `.url()` method returns an instance of URL associated with the request. |
136 | | - |
137 | | -The `.body()` method is a convenience method to deal with decoding a JSON string |
138 | | -body. It can be used with an optional |
139 | | -[deserializer ](https://deno.land/x/[email protected]/mod.ts?s=Deserializer) which can |
140 | | -do advanced decoding of the body, or it will attempted to be decoded from the |
141 | | -JSON string. |
142 | | - |
143 | | -More advanced request body handling can be handled via the `.request` property. |
144 | | - |
145 | | -The handler is then expected to have a return value which can be a `Request` |
146 | | -instance, a value that is a [`BodyInit`](https://deno.land/api?s=BodyInit), or |
147 | | -any other value. If an optional |
148 | | -[serializer ](https://deno.land/x/[email protected]/mod.ts?s=Serializer) is provided |
149 | | -and the response is not a `Request` instance or of the type `BodyInit`, the |
150 | | -value will be passed to the serializer. If no serializer is present then |
151 | | -[`JSON.stringify()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify) |
152 | | -will be used to attempt to convert the value to a JSON string. If `undefined` is |
153 | | -returned, then a `404 NotFound` response will be generated. |
154 | | - |
155 | | -The handling of the request differs significantly from middleware solutions like |
156 | | -[oak](https://oakserver.github.io/oak/). In most cases you will want only one |
157 | | -handler per route and HTTP method combination. There is nothing that prevents |
158 | | -multiple registrations, but the first handler registered that returns a non |
159 | | -`undefined` value will be used and any remaining handlers will not be called. |
160 | | - |
161 | | -Underneath, the router matches route strings using the browser standard |
162 | | -[URL Pattern API](https://developer.mozilla.org/en-US/docs/Web/API/URL_Pattern_API) |
163 | | -and matches the pathname part of the URL. |
| 3 | +A focused Javascript/TypeScript framework for creating RESTful services. |
164 | 4 |
|
165 | 5 | --- |
166 | 6 |
|
|
0 commit comments