Skip to content

Releases: honojs/hono

v4.3.9

21 May 00:03
Compare
Choose a tag to compare

What's Changed

  • fix(factory): export CreateHandlersInterface by @yusukebe in #2752
  • feat(aws-lambda): add support for alb multiValueQueryStringParameters by @yiss in #2751

Full Changelog: v4.3.8...v4.3.9

v4.3.8

19 May 11:02
Compare
Choose a tag to compare

What's Changed

  • test(validator): compatibility with Node.js v20.13.1 by @yusukebe in #2682
  • refactor(utils/jwt): remove some any by @fzn0x in #2684
  • refactor(timing): don't use Partial for the options by @yusukebe in #2712
  • refactor(secure-headers): don't use Partial for the options by @yusukebe in #2713
  • fix(context): Retain all cookies when passing ResponseInit to c.body by @codeflows in #2690
  • fix(hono-jsx): make ref unrequried for forward ref by @dygy in #2715

New Contributors

Full Changelog: v4.3.7...v4.3.8

v4.3.7

15 May 13:11
Compare
Choose a tag to compare

What's Changed

  • doc(ssg): Define the default value for Content-Type by @watany-dev in #2666
  • feat(aws-lambda): add alb event processor by @yiss in #2657
  • feat(utils/cookie): allow setting cookie SameSite attribute in lowercase too by @BlankParticle in #2668
  • fix(method-override): remove un-needed import of URLSearchParams in method override middleware by @f5io in #2679

New Contributors

Full Changelog: v4.3.6...v4.3.7

v4.3.6

12 May 22:56
Compare
Choose a tag to compare

What's Changed

New Contributors

Full Changelog: v4.3.5...v4.3.6

v4.3.5

12 May 07:19
Compare
Choose a tag to compare

What's Changed

  • refactor(context): remove some any by @yusukebe in #2658
  • feat(hono-base): tweaks fetch signature for better compatibility with deno serve by @usualoma in #2661
  • perf(types): add type annotations by @yusukebe in #2663

Full Changelog: v4.3.4...v4.3.5

v4.3.4

09 May 13:51
Compare
Choose a tag to compare

What's Changed

  • chore: update the pull request template by @yusukebe in #2647
  • feat(validator): check for json subtypes in validator by @ztiromoritz in #2634
  • feat(jsx/dom): support getServerSnapshot in useSyncExternalStore by @usualoma in #2646

New Contributors

Full Changelog: v4.3.3...v4.3.4

v4.3.3

08 May 05:31
Compare
Choose a tag to compare

What's Changed

  • fix(types): relax the type of c.req.param() by @yusukebe in #2613
  • chore(eslint): enable @typescript-eslint/unbound-method by @yusukebe in #2622
  • fix(factory): support createFactory() destruction by @yusukebe in #2623
  • fix(aws-lambda): avoid duplicating already set headers by @Amorim33 in #2585
  • refactor: improve parseBody function and docs by @mgrithm in #2628
  • fix(validator): form supports multiple values with foo[] by @yusukebe in #2639

New Contributors

Full Changelog: v4.3.2...v4.3.3

v4.3.2

04 May 23:24
Compare
Choose a tag to compare

What's Changed

  • fix(types): correct inferring when Method has Endponts as Union by @yusukebe in #2610

Full Changelog: v4.3.1...v4.3.2

v4.3.1

04 May 09:21
Compare
Choose a tag to compare

What's Changed

Full Changelog: v4.3.0...v4.3.1

v4.3.0

03 May 10:40
Compare
Choose a tag to compare

Hono v4.3.0 is now available! Let's take a look at the new features.

Improve the RPC-mode

Thanks to @kosei28, @nakasyou, and @NamesMT, the RPC mode has been improved!

c.text() is typed

The response of c.text() was just a Response object, not typed.

const routes = app.get('/about/me', (c) => {
  return c.text('Me!') // the response is not typed
})

With this release, it will be a TypedResponse and you can get the type within the client created by hc.

const client = hc<typeof routes>('http://localhost:8787')

const res = await client.about.me.$get()
const text = await res.text() // text is typed as "Me!"
const json = await res.json() // json is never!

Support all JSON primitives

We added the tests for the responses of c.json() to have the correct types and support inferring all primitives. The all tests below are passed!

const app = new Hono()
const route = app
  .get('/api/string', (c) => c.json('a-string'))
  .get('/api/number', (c) => c.json(37))
  .get('/api/boolean', (c) => c.json(true))
  .get('/api/generic', (c) => c.json(Math.random() > 0.5 ? Boolean(Math.random()) : Math.random()))
type AppType = typeof route

const client = hc<AppType>('http://localhost')

const stringFetch = await client.api.string.$get()
const stringRes = await stringFetch.json()
const numberFetch = await client.api.number.$get()
const numberRes = await numberFetch.json()
const booleanFetch = await client.api.boolean.$get()
const booleanRes = await booleanFetch.json()
const genericFetch = await client.api.generic.$get()
const genericRes = await genericFetch.json()

type stringVerify = Expect<Equal<'a-string', typeof stringRes>>
expect(stringRes).toBe('a-string')
type numberVerify = Expect<Equal<37, typeof numberRes>>
expect(numberRes).toBe(37)
type booleanVerify = Expect<Equal<true, typeof booleanRes>>
expect(booleanRes).toBe(true)
type genericVerify = Expect<Equal<number | boolean, typeof genericRes>>
expect(typeof genericRes === 'number' || typeof genericRes === 'boolean').toBe(true)

// using .text() on json endpoint should return string
type textTest = Expect<Equal<Promise<string>, ReturnType<typeof genericFetch.text>>>

Status code type

If you explicitly specify the status code, such as 200 or 404, in c.json(). It will be added as a type for passing to the client.

// server.ts
const app = new Hono().get(
  '/posts',
  zValidator(
    'query',
    z.object({
      id: z.string()
    })
  ),
  async (c) => {
    const { id } = c.req.valid('query')
    const post: Post | undefined = await getPost(id)

    if (post === undefined) {
      return c.json({ error: 'not found' }, 404) // Specify 404
    }

    return c.json({ post }, 200) // Specify 200
  }
)

export type AppType = typeof app

You can get the data by the status code.

// client.ts
const client = hc<AppType>('http://localhost:8787/')

const res = await client.posts.$get({
  query: {
    id: '123'
  }
})

if (res.status === 404) {
  const data: { error: string } = await res.json()
  console.log(data.error)
}

if (res.ok) {
  const data: { post: Post } = await res.json()
  console.log(data.post)
}

// { post: Post } | { error: string }
type ResponseType = InferResponseType<typeof client.posts.$get>

// { post: Post }
type ResponseType200 = InferResponseType<typeof client.posts.$get, 200>

Improve compatibility with React

The compatibility of hono/jsx/dom has been improved. Now, these React libraries work with hono/jsx/dom!

The below demo is working with hono/jsx/dom, not React.

Google Chrome

If you want to use React libraries with hono/jsx/dom, set-up tsconfig.json and vite.config.ts like the followings:

tsconfig.json:

{
  "compilerOptions": {
    "paths": {
      "react": ["./node_modules/hono/dist/jsx/dom"],
      "react-dom": ["./node_modules/hono/dist/jsx/dom"]
    }
  }
}

vite.config.ts:

import { defineConfig } from 'vite'

export default defineConfig({
  resolve: {
    alias: {
      react: 'hono/jsx/dom',
      'react-dom': 'hono/jsx/dom'
    }
  }
})

Thanks @usualoma!

createApp() in Factory Helper

createApp() method is added to Factory Helper. If you use this method with createFactory(), you can avoid redundancy in the definition of the Env type.

If your application is like this, you have to set the Env in two places:

import { createMiddleware } from 'hono/factory'

type Env = {
  Variables: {
    myVar: string
  }
}

// 1. Set the `Env` to `new Hono()`
const app = new Hono<Env>()

// 2. Set the `Env` to `createMiddleware()`
const mw = createMiddleware<Env>(async (c, next) => {
  await next()
})

app.use(mw)

By using createFactory() and createApp(), you can set the Env only in one place.

import { createFactory } from 'hono/factory'

// ...

// Set the `Env` to `createFactory()`
const factory = createFactory<Env>()

const app = factory.createApp()

// factory also has `createMiddleware()`
const mw = factory.createMiddleware(async (c, next) => {
  await next()
})

Deprecate serveStatic for Cloudflare Workers

serveStatic exported by hono/cloudflare-workers has been deprecated. If you create an application which serves static asset files, use Cloudflare Pages instead.

Other features

  • Cookie Helper - delete cookie returns the deleted value #2512
  • Bearer Authenticate - add headerName option #2514
  • JSX/DOM - preserve the state of element even if it is repeatedly evaluated by children #2563
  • Mimes utility - expose built-in MIME types #2516
  • Serve Static - expose serve-static builder #2515
  • Secure Headers - enable to set nonce in CSP #2577
  • Server-Timing - allow crossOrigin in TimingOptions to be a function #2359
  • Client - add init option #2592

All Updates

New Contributors

Full Changelog: v4.2.9...v4.3.0