hono 1.6.4 → 2.0.2

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 (43) hide show
  1. package/README.md +23 -768
  2. package/dist/compose.d.ts +1 -5
  3. package/dist/compose.js +5 -5
  4. package/dist/context.d.ts +30 -5
  5. package/dist/context.js +25 -9
  6. package/dist/hono.d.ts +2 -2
  7. package/dist/hono.js +3 -3
  8. package/dist/index.d.ts +1 -1
  9. package/dist/index.js +2 -3
  10. package/dist/middleware/basic-auth/index.js +0 -9
  11. package/dist/middleware/compress/index.d.ts +8 -0
  12. package/dist/middleware/compress/index.js +19 -0
  13. package/dist/middleware/cors/index.d.ts +1 -1
  14. package/dist/middleware/jsx/index.js +21 -1
  15. package/dist/middleware/jwt/index.js +3 -0
  16. package/dist/middleware/logger/index.d.ts +3 -5
  17. package/dist/middleware/logger/index.js +15 -16
  18. package/dist/middleware/serve-static/bun.d.ts +7 -0
  19. package/dist/middleware/serve-static/bun.js +38 -0
  20. package/dist/middleware/serve-static/module.mjs +1 -0
  21. package/dist/request.d.ts +9 -0
  22. package/dist/request.js +19 -0
  23. package/dist/utils/buffer.d.ts +1 -1
  24. package/dist/utils/cloudflare.d.ts +1 -1
  25. package/dist/utils/cookie.d.ts +13 -0
  26. package/dist/{middleware/cookie/index.js → utils/cookie.js} +3 -22
  27. package/dist/utils/jwt/jwt.js +4 -1
  28. package/dist/utils/jwt/types.d.ts +6 -1
  29. package/dist/utils/jwt/types.js +9 -4
  30. package/package.json +13 -23
  31. package/dist/middleware/body-parse/index.d.ts +0 -8
  32. package/dist/middleware/body-parse/index.js +0 -11
  33. package/dist/middleware/cookie/index.d.ts +0 -27
  34. package/dist/middleware/graphql-server/index.d.ts +0 -28
  35. package/dist/middleware/graphql-server/index.js +0 -174
  36. package/dist/middleware/graphql-server/parse-body.d.ts +0 -1
  37. package/dist/middleware/graphql-server/parse-body.js +0 -31
  38. package/dist/middleware/mustache/index.d.ts +0 -1
  39. package/dist/middleware/mustache/index.js +0 -5
  40. package/dist/middleware/mustache/module.d.mts +0 -5
  41. package/dist/middleware/mustache/module.mjs +0 -12
  42. package/dist/middleware/mustache/mustache.d.ts +0 -14
  43. package/dist/middleware/mustache/mustache.js +0 -53
package/README.md CHANGED
@@ -1,18 +1,25 @@
1
1
  <div align="center">
2
- <a href="https://github.com/honojs/hono">
3
- <img src="https://raw.githubusercontent.com/honojs/hono/master/docs/images/hono-title.png" width="500" height="auto" alt="Hono"/>
2
+ <a href="https://honojs.dev">
3
+ <img src="https://raw.githubusercontent.com/honojs/hono/main/docs/images/hono-title.png" width="500" height="auto" alt="Hono"/>
4
4
  </a>
5
5
  </div>
6
6
 
7
7
  <hr />
8
8
 
9
+ <p align="center">
10
+ <a href="https://honojs.dev"><b>Documentation :point_right: honojs.dev</b></a><br />
11
+ <i>v2.x has been released!</i> <a href="docs/MIGRATION.md">Migration guide</b>
12
+ </p>
13
+
14
+ <hr />
15
+
9
16
  [![GitHub Workflow Status](https://img.shields.io/github/workflow/status/honojs/hono/ci)](https://github.com/honojs/hono/actions)
10
- [![GitHub](https://img.shields.io/github/license/honojs/hono)](https://github.com/honojs/hono/blob/master/LICENSE)
17
+ [![GitHub](https://img.shields.io/github/license/honojs/hono)](https://github.com/honojs/hono/blob/main/LICENSE)
11
18
  [![npm](https://img.shields.io/npm/v/hono)](https://www.npmjs.com/package/hono)
12
19
  [![npm](https://img.shields.io/npm/dm/hono)](https://www.npmjs.com/package/hono)
13
20
  [![npm type definitions](https://img.shields.io/npm/types/hono)](https://www.npmjs.com/package/hono)
14
21
  [![GitHub commit activity](https://img.shields.io/github/commit-activity/m/honojs/hono)](https://github.com/honojs/hono/pulse)
15
- [![GitHub last commit](https://img.shields.io/github/last-commit/honojs/hono)](https://github.com/honojs/hono/commits/master)
22
+ [![GitHub last commit](https://img.shields.io/github/last-commit/honojs/hono)](https://github.com/honojs/hono/commits/main)
16
23
  [![Deno badge](https://img.shields.io/endpoint?url=https%3A%2F%2Fdeno-visualizer.danopia.net%2Fshields%2Flatest-version%2Fx%2Fhono%2Fmod.ts)](https://doc.deno.land/https/deno.land/x/hono/mod.ts)
17
24
 
18
25
  Hono - _**[炎] means flame🔥 in Japanese**_ - is a small, simple, and ultrafast web framework for Cloudflare Workers, Deno, Bun, and others.
@@ -23,24 +30,19 @@ const app = new Hono()
23
30
 
24
31
  app.get('/', (c) => c.text('Hono!!'))
25
32
 
26
- app.fire()
33
+ export default app
27
34
  ```
28
35
 
29
36
  ## Features
30
37
 
31
38
  - **Ultrafast** - the router does not use linear loops.
32
39
  - **Zero-dependencies** - using only Service Worker and Web Standard API.
33
- - **Middleware** - built-in middleware and ability to extend with your own middleware.
40
+ - **Middleware** - built-in middleware, custom middleware, and third-party middleware.
34
41
  - **TypeScript** - first-class TypeScript support.
35
42
  - **Multi-platform** - works on Cloudflare Workers, Fastly Compute@Edge, Deno, or Bun.
36
43
 
37
44
  ## Benchmarks
38
45
 
39
- ### Cloudflare Workers
40
-
41
- - Machine: Apple MacBook Pro, 32 GiB, M1 Pro
42
- - Scripts: [benchmarks/handle-event](https://github.com/honojs/hono/tree/master/benchmarks/handle-event)
43
-
44
46
  **Hono is fastest**, compared to other routers for Cloudflare Workers.
45
47
 
46
48
  ```plain
@@ -53,771 +55,24 @@ Fastest is hono - regexp-router
53
55
  ✨ Done in 43.56s.
54
56
  ```
55
57
 
56
- ### Deno
57
-
58
- - Machine: Apple MacBook Pro, 32 GiB, M1 Pro, Deno v1.22.0
59
- - Scripts: [benchmarks/deno](https://github.com/honojs/hono/tree/master/benchmarks/deno)
60
- - Method: `autocannon -c 100 -d 40 -p 10 'http://127.0.0.1:8000/user/lookup/username/foo'`
61
-
62
- **Hono is fastest**, compared to other frameworks for Deno.
63
-
64
- | Framework | Version | Results |
65
- | ----------------------------- | :-----: | ----------------------------------------: |
66
- | **Hono - RegExpRouter** | 1.6.0 | **5118k requests in 40.02s, 865 MB read** |
67
- | **Hono - TriRouter(default)** | 1.6.0 | **4932k requests in 40.02s, 833 MB read** |
68
- | Faster | 5.7 | 3579k requests in 40.02s, 551 MB read |
69
- | oak | 10.5.1 | 2385k requests in 40.02s, 403 MB read |
70
- | opine | 2.2.0 | 1491k requests in 40.02s, 346 MB read |
71
-
72
- Another benchmark result: [denosaurs/bench](https://github.com/denosaurs/bench)
73
-
74
- ## Why so fast?
75
-
76
- Routers used in Hono are really smart.
77
-
78
- - **TrieRouter**(default) - Implemented with Trie tree structure.
79
- - **RegExpRouter** - Match the route with using one big Regex made before dispatch.
80
-
81
- ## Hono in 1 minute
82
-
83
- A demonstration to create an application for Cloudflare Workers with Hono.
84
-
85
- ![Demo](https://user-images.githubusercontent.com/10682/151973526-342644f9-71c5-4fee-81f4-64a7558bb192.gif)
86
-
87
- ## Not only fast
88
-
89
- Hono is fast. But not only fast.
90
-
91
- ### Write Less, do more
92
-
93
- Built-in middleware make _"**Write Less, do more**"_ in reality. You can use a lot of middleware without writing code from scratch. Below are examples.
94
-
95
- - [Basic Authentication](https://github.com/honojs/hono/tree/master/src/middleware/basic-auth/)
96
- - [Cookie parsing / serializing](https://github.com/honojs/hono/tree/master/src/middleware/cookie/)
97
- - [CORS](https://github.com/honojs/hono/tree/master/src/middleware/cors/)
98
- - [ETag](https://github.com/honojs/hono/tree/master/src/middleware/etag/)
99
- - [GraphQL Server](https://github.com/honojs/hono/tree/master/src/middleware/graphql-server/)
100
- - [html](https://github.com/honojs/hono/tree/master/src/middleware/html/)
101
- - [JSX](https://github.com/honojs/hono/tree/master/src/middleware/jsx/)
102
- - [JWT Authentication](https://github.com/honojs/hono/tree/master/src/middleware/jwt/)
103
- - [Logger](https://github.com/honojs/hono/tree/master/src/middleware/logger/)
104
- - [Mustache template engine](https://github.com/honojs/hono/tree/master/src/middleware/mustache/) (Only for Cloudflare Workers)
105
- - [JSON pretty printing](https://github.com/honojs/hono/tree/master/src/middleware/pretty-json/)
106
- - [Serving static files](https://github.com/honojs/hono/tree/master/src/middleware/serve-static/) (Only for Cloudflare Workers and Deno)
107
-
108
- To enable logger and Etag middleware with just this code.
109
-
110
- ```ts
111
- import { Hono } from 'hono'
112
- import { etag } from 'hono/etag'
113
- import { logger } from 'hono/logger'
114
-
115
- const app = new Hono()
116
- app.use('*', etag(), logger())
117
- ```
118
-
119
- And, the routing of Hono is so flexible. It's easy to construct large web applications.
120
-
121
- ```ts
122
- import { Hono } from 'hono'
123
- import { basicAuth } from 'hono/basic-auth'
124
-
125
- const v1 = new Hono()
126
- v1.get('/posts', (c) => {
127
- return c.text('list posts')
128
- })
129
- .post(basicAuth({ username, password }), (c) => {
130
- return c.text('created!', 201)
131
- })
132
- .get('/posts/:id', (c) => {
133
- const id = c.req.param('id')
134
- return c.text(`your id is ${id}`)
135
- })
136
-
137
- const app = new Hono()
138
- app.route('/v1', v1)
139
- ```
140
-
141
- ### Web Standard
142
-
143
- Request and Response object used in Hono are extensions of the Web Standard [Fetch API](https://developer.mozilla.org/ja/docs/Web/API/Fetch_API). If you are familiar with that, you don't need to know more than that.
144
-
145
- ### Developer Experience
146
-
147
- Hono provides fine _"**Developer Experience**"_. Easy access to Request/Response thanks to the `Context` object.
148
- Above all, Hono is written in TypeScript. So, Hono has _"**Types**"_!
149
-
150
- For example, the named path parameters will be literal types.
151
-
152
- ![Demo](https://user-images.githubusercontent.com/10682/154179671-9e491597-6778-44ac-a8e6-4483d7ad5393.png)
153
-
154
- ## Install
155
-
156
- You can install Hono from the npm registry.
157
-
158
- ```sh
159
- npm install hono
160
- ```
161
-
162
- ## Methods
163
-
164
- An instance of `Hono` has these methods.
165
-
166
- - app.**HTTP_METHOD**(\[path,\]handler|middleware...)
167
- - app.**all**(\[path,\]handler|middleware...)
168
- - app.**route**(path, \[app\])
169
- - app.**use**(\[path,\]middleware)
170
- - app.**notFound**(handler)
171
- - app.**onError**(err, handler)
172
- - app.**fire**()
173
- - app.**fetch**(request, env, event)
174
- - app.**request**(path, options)
175
-
176
- ## Routing
177
-
178
- ### Basic
179
-
180
- ```ts
181
- // HTTP Methods
182
- app.get('/', (c) => c.text('GET /'))
183
- app.post('/', (c) => c.text('POST /'))
184
- app.put('/', (c) => c.text('PUT /'))
185
- app.delete('/', (c) => c.text('DELETE /'))
186
-
187
- // Wildcard
188
- app.get('/wild/*/card', (c) => {
189
- return c.text('GET /wild/*/card')
190
- })
191
-
192
- // Any HTTP methods
193
- app.all('/hello', (c) => c.text('Any Method /hello'))
194
- ```
195
-
196
- ### Named Parameter
197
-
198
- ```ts
199
- app.get('/user/:name', (c) => {
200
- const name = c.req.param('name')
201
- ...
202
- })
203
- ```
204
-
205
- or all parameters at once:
206
-
207
- ```ts
208
- app.get('/posts/:id/comment/:comment_id', (c) => {
209
- const { id, comment_id } = c.req.param()
210
- ...
211
- })
212
- ```
213
-
214
- ### Regexp
215
-
216
- ```ts
217
- app.get('/post/:date{[0-9]+}/:title{[a-z]+}', (c) => {
218
- const { date, title } = c.req.param()
219
- ...
220
- })
221
- ```
222
-
223
- ### Chained route
224
-
225
- ```ts
226
- app
227
- .get('/endpoint', (c) => {
228
- return c.text('GET /endpoint')
229
- })
230
- .post((c) => {
231
- return c.text('POST /endpoint')
232
- })
233
- .delete((c) => {
234
- return c.text('DELETE /endpoint')
235
- })
236
- ```
237
-
238
- ### no strict
239
-
240
- If `strict` is set false, `/hello`and`/hello/` are treated the same.
241
-
242
- ```ts
243
- const app = new Hono({ strict: false }) // Default is true
244
-
245
- app.get('/hello', (c) => c.text('/hello or /hello/'))
246
- ```
247
-
248
- ### async/await
249
-
250
- ```js
251
- app.get('/fetch-url', async (c) => {
252
- const response = await fetch('https://example.com/')
253
- return c.text(`Status is ${response.status}`)
254
- })
255
- ```
256
-
257
- ## Grouping
258
-
259
- Group the routes with `Hono` instance and add them to the main app with `route` method.
260
-
261
- ```ts
262
- const book = new Hono()
263
-
264
- book.get('/', (c) => c.text('List Books')) // GET /book
265
- book.get('/:id', (c) => {
266
- // GET /book/:id
267
- const id = c.req.param('id')
268
- return c.text('Get Book: ' + id)
269
- })
270
- book.post('/', (c) => c.text('Create Book')) // POST /book
271
-
272
- const app = new Hono()
273
- app.route('/book', book)
274
- ```
275
-
276
- ## Middleware
277
-
278
- Middleware works after/before Handler. We can get `Request` before dispatching or manipulate `Response` after dispatching.
279
-
280
- ### Definition of Middleware
281
-
282
- - Handler - should return `Response` object. Only one handler will be called.
283
- - Middleware - should return nothing, will be proceeded to next middleware with `await next()`
284
-
285
- The user can register middleware using `c.use` or using `c.HTTP_METHOD` as well as the handlers. For this feature, it's easy to specify the path and the method.
286
-
287
- ```ts
288
- // match any method, all routes
289
- app.use('*', logger())
290
-
291
- // specify path
292
- app.use('/posts/*', cors())
293
-
294
- // specify method and path
295
- app.post('/posts/*', basicAuth(), bodyParse())
296
- ```
297
-
298
- If the handler returns `Response`, it will be used for the end-user, and stopping the processing.
299
-
300
- ```ts
301
- app.post('/posts', (c) => c.text('Created!', 201))
302
- ```
303
-
304
- In this case, four middleware are processed before dispatching like this:
305
-
306
- ```ts
307
- logger() -> cors() -> basicAuth() -> bodyParse() -> *handler*
308
- ```
309
-
310
- ### Built-in Middleware
311
-
312
- Hono has built-in middleware.
313
-
314
- ```ts
315
- import { Hono } from 'hono'
316
- import { poweredBy } from 'hono/powered-by'
317
- import { logger } from 'hono/logger'
318
- import { basicAuth } from 'hono/basicAuth'
319
-
320
- const app = new Hono()
321
-
322
- app.use('*', poweredBy())
323
- app.use('*', logger())
324
-
325
- app.use(
326
- '/auth/*',
327
- basicAuth({
328
- username: 'hono',
329
- password: 'acoolproject',
330
- })
331
- )
332
- ```
333
-
334
- Available built-in middleware is listed on [src/middleware](https://github.com/honojs/hono/tree/master/src/middleware).
335
-
336
- ### Custom Middleware
337
-
338
- You can write your own middleware.
339
-
340
- ```ts
341
- // Custom logger
342
- app.use('*', async (c, next) => {
343
- console.log(`[${c.req.method}] ${c.req.url}`)
344
- await next()
345
- })
346
-
347
- // Add a custom header
348
- app.use('/message/*', async (c, next) => {
349
- await next()
350
- c.header('x-message', 'This is middleware!')
351
- })
352
-
353
- app.get('/message/hello', (c) => c.text('Hello Middleware!'))
354
- ```
355
-
356
- ## Not Found
357
-
358
- `app.notFound` for customizing Not Found Response.
359
-
360
- ```js
361
- app.notFound((c) => {
362
- return c.text('Custom 404 Message', 404)
363
- })
364
- ```
365
-
366
- ## Error Handling
367
-
368
- `app.onError` handle the error and return the customized Response.
369
-
370
- ```js
371
- app.onError((err, c) => {
372
- console.error(`${err}`)
373
- return c.text('Custom Error Message', 500)
374
- })
375
- ```
376
-
377
- ## Context
378
-
379
- To handle Request and Response, you can use `Context` object.
380
-
381
- ### c.req
382
-
383
- ```ts
384
- // Get Request object
385
- app.get('/hello', (c) => {
386
- const userAgent = c.req.headers.get('User-Agent')
387
- ...
388
- })
389
-
390
- // Shortcut to get a header value
391
- app.get('/shortcut', (c) => {
392
- const userAgent = c.req.header('User-Agent')
393
- ...
394
- })
395
-
396
- // Query params
397
- app.get('/search', (c) => {
398
- const query = c.req.query('q')
399
- ...
400
- })
401
-
402
- // Get all params at once
403
- app.get('/search', (c) => {
404
- const { q, limit, offset } = c.req.query()
405
- ...
406
- })
407
-
408
- // Multiple query values
409
- app.get('/search', (c) => {
410
- const queries = c.req.queries('q')
411
- // ---> GET search?q=foo&q=bar
412
- // queries[0] => foo, queries[1] => bar
413
- ...
414
- })
415
-
416
- // Captured params
417
- app.get('/entry/:id', (c) => {
418
- const id = c.req.param('id')
419
- ...
420
- })
421
- ```
422
-
423
- ### Shortcuts for Response
424
-
425
- ```ts
426
- app.get('/welcome', (c) => {
427
- // Set headers
428
- c.header('X-Message', 'Hello!')
429
- c.header('Content-Type', 'text/plain')
430
-
431
- // Set HTTP status code
432
- c.status(201)
433
-
434
- // Return the response body
435
- return c.body('Thank you for comming')
436
- })
437
- ```
438
-
439
- The Response is the same as below.
440
-
441
- ```ts
442
- new Response('Thank you for comming', {
443
- status: 201,
444
- headers: {
445
- 'X-Message': 'Hello',
446
- 'Content-Type': 'text/plain',
447
- },
448
- })
449
- ```
450
-
451
- ### c.text()
452
-
453
- Render text as `Content-Type:text/plain`.
454
-
455
- ```ts
456
- app.get('/say', (c) => {
457
- return c.text('Hello!')
458
- })
459
- ```
460
-
461
- ### c.json()
462
-
463
- Render JSON as `Content-Type:application/json`.
464
-
465
- ```ts
466
- app.get('/api', (c) => {
467
- return c.json({ message: 'Hello!' })
468
- })
469
- ```
470
-
471
- ### c.html()
472
-
473
- Render HTML as `Content-Type:text/html`.
474
-
475
- ```ts
476
- app.get('/', (c) => {
477
- return c.html('<h1>Hello! Hono!</h1>')
478
- })
479
- ```
480
-
481
- ### c.notFound()
482
-
483
- Return the `Not Found` Response.
484
-
485
- ```ts
486
- app.get('/notfound', (c) => {
487
- return c.notFound()
488
- })
489
- ```
490
-
491
- ### c.redirect()
492
-
493
- Redirect, default status code is `302`.
494
-
495
- ```ts
496
- app.get('/redirect', (c) => c.redirect('/'))
497
- app.get('/redirect-permanently', (c) => c.redirect('/', 301))
498
- ```
499
-
500
- ### c.res
501
-
502
- ```ts
503
- // Response object
504
- app.use('/', async (c, next) => {
505
- await next()
506
- c.res.headers.append('X-Debug', 'Debug message')
507
- })
508
- ```
509
-
510
- ### c.executionCtx
511
-
512
- ```ts
513
- // ExecutionContext object
514
- app.get('/foo', async (c) => {
515
- c.executionCtx.waitUntil(
516
- c.env.KV.put(key, data)
517
- )
518
- ...
519
- })
520
- ```
521
-
522
- ### c.event
523
-
524
- ```ts
525
- // FetchEvent object (only set when using Service Worker syntax)
526
- app.get('/foo', async (c) => {
527
- c.event.waitUntil(
528
- c.env.KV.put(key, data)
529
- )
530
- ...
531
- })
532
- ```
533
-
534
- ### c.env
535
-
536
- Environment variables, secrets, and KV namespaces are known as bindings. Regardless of type, bindings are always available as global variables and can be accessed via the context `c.env.BINDING_KEY`.
537
-
538
- ```ts
539
- // Environment object for Cloudflare Workers
540
- app.get('*', async c => {
541
- const counter = c.env.COUNTER
542
- ...
543
- })
544
- ```
545
-
546
- ## fire
547
-
548
- `app.fire()` do this.
549
-
550
- ```ts
551
- addEventListener('fetch', (event) => {
552
- event.respondWith(this.handleEvent(event))
553
- })
554
- ```
555
-
556
- ## fetch
557
-
558
- `app.fetch` for Cloudflare Module Worker syntax.
559
-
560
- ```ts
561
- export default {
562
- fetch(request: Request, env: Env, ctx: ExecutionContext) {
563
- return app.fetch(request, env, ctx)
564
- },
565
- }
566
- ```
567
-
568
- or just do:
569
-
570
- ```ts
571
- export default app
572
- ```
573
-
574
- ## request
575
-
576
- `request` is a useful method for testing.
577
-
578
- ```js
579
- test('GET /hello is ok', async () => {
580
- const res = await app.request('http://localhost/hello')
581
- expect(res.status).toBe(200)
582
- })
583
- ```
584
-
585
- ## router
586
-
587
- The `router` option specify which router is used inside. The default router is `TrieRouter`. If you want to use `RexExpRouter`, write like this:
588
-
589
- ```ts
590
- import { RegExpRouter } from 'hono/router/reg-exp-router'
591
-
592
- const app = new Hono({ router: new RegExpRouter() })
593
- ```
594
-
595
- ## Routing priority
596
-
597
- Handlers or middleware will be executed in registration order.
598
-
599
- ```ts
600
- app.get('/book/a', (c) => c.text('a')) // a
601
- app.get('/book/:slug', (c) => c.text('common')) // common
602
- ```
603
-
604
- ```http
605
- GET /book/a ---> `a`
606
- GET /book/b ---> `common`
607
- ```
608
-
609
- When a handler is executed, the process will be stopped.
610
-
611
- ```ts
612
- app.get('*', (c) => c.text('common')) // common
613
- app.get('/foo', (c) => c.text('foo')) // foo
614
- ```
615
-
616
- ```http
617
- GET /foo ---> `common` // foo will not be dispatched
618
- ```
619
-
620
- If you have the middleware that you want to execute, write the code above the handler.
621
-
622
- ```ts
623
- app.use('*', logger())
624
- app.get('/foo', (c) => c.text('foo'))
625
- ```
626
-
627
- If you want a "_fallback_" handler, write the code below the other handler.
628
-
629
- ```ts
630
- app.get('/foo', (c) => c.text('foo')) // foo
631
- app.get('*', (c) => c.text('fallback')) // fallback
632
- ```
633
-
634
- ```http
635
- GET /bar ---> `fallback`
636
- ```
637
-
638
- ## Cloudflare Workers with Hono
639
-
640
- Using [Wrangler](https://developers.cloudflare.com/workers/cli-wrangler/), you can develop the application locally and publish it with few commands.
641
-
642
- Let's write your first code for Cloudflare Workers with Hono.
643
-
644
- ### 1. `wrangler init`
645
-
646
- Initialize as a wrangler project.
647
-
648
- ```
649
- mkdir hono-example
650
- cd hono-example
651
- npx wrangler init -y
652
- ```
653
-
654
- ### 2. `npm install hono`
655
-
656
- Install `hono` from the npm registry.
657
-
658
- ```
659
- npm init -y
660
- npm i hono
661
- ```
662
-
663
- ### 3. Write your app
664
-
665
- Edit `src/index.ts`. Only 4 lines!!
666
-
667
- ```ts
668
- // src/index.ts
669
- import { Hono } from 'hono'
670
- const app = new Hono()
671
-
672
- app.get('/', (c) => c.text('Hello! Hono!'))
673
-
674
- app.fire()
675
- ```
676
-
677
- ### 4. Run
678
-
679
- Run the development server locally. Then, access `http://127.0.0.1:8787/` in your Web browser.
680
-
681
- ```
682
- npx wrangler dev
683
- ```
684
-
685
- ### 5. Publish
686
-
687
- Deploy to Cloudflare. That's all!
688
-
689
- ```
690
- npx wrangler publish ./src/index.ts
691
- ```
692
-
693
- ## Starter template
694
-
695
- You can start making your Cloudflare Workers application with [the starter template](https://github.com/honojs/hono-minimal). It is really minimal using TypeScript, esbuild, Miniflare, and Jest.
696
-
697
- To generate a project skeleton, run this command.
698
-
699
- ```
700
- npx create-cloudflare my-app https://github.com/honojs/hono-minimal
701
- ```
702
-
703
- ## Practical Example
704
-
705
- How about writing web API with Hono?
706
-
707
- ```ts
708
- import { Hono } from 'hono'
709
- import { cors } from 'hono/cors'
710
- import { basicAuth } from 'hono/basic-auth'
711
- import { prettyJSON } from 'hono/pretty-json'
712
- import { getPosts, getPost, createPost, Post } from './model'
713
-
714
- const app = new Hono()
715
- app.get('/', (c) => c.text('Pretty Blog API'))
716
- app.use('*', prettyJSON())
717
- app.notFound((c) => c.json({ message: 'Not Found', ok: false }, 404))
718
-
719
- export interface Bindings {
720
- USERNAME: string
721
- PASSWORD: string
722
- }
723
-
724
- const api = new Hono<Bindings>()
725
- api.use('/posts/*', cors())
726
-
727
- api.get('/posts', (c) => {
728
- const { limit, offset } = c.req.query()
729
- const posts = getPosts({ limit, offset })
730
- return c.json({ posts })
731
- })
732
-
733
- api.get('/posts/:id', (c) => {
734
- const id = c.req.param('id')
735
- const post = getPost({ id })
736
- return c.json({ post })
737
- })
738
-
739
- api.post(
740
- '/posts',
741
- async (c, next) => {
742
- const auth = basicAuth({ username: c.env.USERNAME, password: c.env.PASSWORD })
743
- await auth(c, next)
744
- },
745
- async (c) => {
746
- const post = await c.req.json<Post>()
747
- const ok = createPost({ post })
748
- return c.json({ ok })
749
- }
750
- )
751
-
752
- app.route('/api', api)
753
-
754
- export default app
755
- ```
756
-
757
- ## Other Examples
758
-
759
- - Hono Examples - <https://github.com/honojs/examples>
760
-
761
- ## Deno
762
-
763
- Hono also works on Deno. This feature is still experimental.
764
-
765
- ```tsx
766
- /** @jsx jsx */
767
- import { serve } from 'https://deno.land/std/http/server.ts'
768
- import { Hono, logger, poweredBy, serveStatic, jsx } from 'https://deno.land/x/hono/mod.ts'
769
-
770
- const app = new Hono()
771
-
772
- app.use('*', logger(), poweredBy())
773
-
774
- app.get('/favicon.ico', serveStatic({ path: './public/favicon.ico' }))
775
- app.get('/', (c) => {
776
- return c.html(<h1>Hello Deno!</h1>)
777
- })
778
-
779
- serve(app.fetch)
780
- ```
781
-
782
- ## Bun
783
-
784
- Hono also works on Bun. This feature is still experimental.
785
-
786
- ```ts
787
- import { Hono } from 'hono'
788
-
789
- const app = new Hono()
790
-
791
- app.get('/', (c) => {
792
- return c.json({ message: 'Hello Bun!' })
793
- })
794
-
795
- export default {
796
- port: 3000,
797
- fetch: app.fetch,
798
- }
799
- ```
58
+ ## Documentation
800
59
 
801
- ## Related projects
60
+ The documentation is available on [honojs.dev](https://honojs.dev).
802
61
 
803
- Implementation of the original router `TrieRouter` is inspired by [goblin](https://github.com/bmf-san/goblin). `RegExpRouter` is inspired by [Router::Boom](https://github.com/tokuhirom/Router-Boom). API design is inspired by [express](https://github.com/expressjs/express) and [koa](https://github.com/koajs/koa). [itty-router](https://github.com/kwhitley/itty-router), [Sunder](https://github.com/SunderJS/sunder), and [worktop](https://github.com/lukeed/worktop) are the other routers or frameworks for Cloudflare Workers.
62
+ ## Migration
804
63
 
805
- - express - <https://github.com/expressjs/express>
806
- - koa - <https://github.com/koajs/koa>
807
- - itty-router - <https://github.com/kwhitley/itty-router>
808
- - Sunder - <https://github.com/SunderJS/sunder>
809
- - goblin - <https://github.com/bmf-san/goblin>
810
- - worktop - <https://github.com/lukeed/worktop>
811
- - Router::Boom - <https://github.com/tokuhirom/Router-Boom>
64
+ Migration guide is available on [docs/MIGRATION.md](docs/MIGRATION.md)
812
65
 
813
66
  ## Contributing
814
67
 
815
68
  Contributions Welcome! You can contribute in the following ways.
816
69
 
817
- - Write or fix documents
818
- - Write code of middleware
819
- - Fix bugs
820
- - Refactor the code
70
+ - Fix bugs.
71
+ - Create built-in or third-party middleware.
72
+ - Propose new feature.
73
+ - Refactor the code.
74
+ - Write an article about Hono on your Blog.
75
+ - Fix a typo.
821
76
  - etc.
822
77
 
823
78
  ## Contributors