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