chore: add coverage badges (#1023)
* chore: add coverage badges * ci(casbin): fix spellingpull/1025/head
parent
6c8ba4cdcd
commit
783a082c12
|
@ -1,13 +1,13 @@
|
|||
name: ci-cabin
|
||||
name: ci-casbin
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- 'packages/cabin/**'
|
||||
- 'packages/casbin/**'
|
||||
pull_request:
|
||||
branches: ['*']
|
||||
paths:
|
||||
- 'packages/cabin/**'
|
||||
- 'packages/casbin/**'
|
||||
|
||||
jobs:
|
||||
ci:
|
||||
|
@ -17,13 +17,13 @@ jobs:
|
|||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20.x
|
||||
- run: yarn workspaces focus hono-middleware @hono/ci-cabin
|
||||
- run: yarn workspace @hono/ci-cabin build
|
||||
- run: yarn test --coverage --project @hono/ci-cabin
|
||||
- run: yarn workspaces focus hono-middleware @hono/casbin
|
||||
- run: yarn workspace @hono/casbin build
|
||||
- run: yarn test --coverage --project @hono/casbin
|
||||
- uses: codecov/codecov-action@v5
|
||||
with:
|
||||
fail_ci_if_error: true
|
||||
directory: ./coverage
|
||||
flags: ci-cabin
|
||||
flags: casbin
|
||||
env:
|
||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
name: initial-coverage
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
branches: ['*']
|
||||
|
||||
jobs:
|
||||
ci:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20.x
|
||||
- run: yarn install
|
||||
- run: yarn vitest --coverage
|
||||
- uses: codecov/codecov-action@v5
|
||||
with:
|
||||
fail_ci_if_error: true
|
||||
directory: ./coverage
|
||||
env:
|
||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
|
@ -1,5 +1,7 @@
|
|||
# Ajv validator middleware for Hono
|
||||
|
||||
[](https://codecov.io/github/honojs/middleware)
|
||||
|
||||
Validator middleware using [Ajv](https://github.com/ajv-validator/ajv) for [Hono](https://honojs.dev) applications.
|
||||
Define your schema with Ajv and validate incoming requests.
|
||||
|
||||
|
@ -8,8 +10,8 @@ Define your schema with Ajv and validate incoming requests.
|
|||
No Hook:
|
||||
|
||||
```ts
|
||||
import { type JSONSchemaType } from 'ajv';
|
||||
import { ajvValidator } from '@hono/ajv-validator';
|
||||
import { type JSONSchemaType } from 'ajv'
|
||||
import { ajvValidator } from '@hono/ajv-validator'
|
||||
|
||||
const schema: JSONSchemaType<{ name: string; age: number }> = {
|
||||
type: 'object',
|
||||
|
@ -19,19 +21,19 @@ const schema: JSONSchemaType<{ name: string; age: number }> = {
|
|||
},
|
||||
required: ['name', 'age'],
|
||||
additionalProperties: false,
|
||||
} as const;
|
||||
} as const
|
||||
|
||||
const route = app.post('/user', ajvValidator('json', schema), (c) => {
|
||||
const user = c.req.valid('json');
|
||||
return c.json({ success: true, message: `${user.name} is ${user.age}` });
|
||||
});
|
||||
const user = c.req.valid('json')
|
||||
return c.json({ success: true, message: `${user.name} is ${user.age}` })
|
||||
})
|
||||
```
|
||||
|
||||
Hook:
|
||||
|
||||
```ts
|
||||
import { type JSONSchemaType } from 'ajv';
|
||||
import { ajvValidator } from '@hono/ajv-validator';
|
||||
import { type JSONSchemaType } from 'ajv'
|
||||
import { ajvValidator } from '@hono/ajv-validator'
|
||||
|
||||
const schema: JSONSchemaType<{ name: string; age: number }> = {
|
||||
type: 'object',
|
||||
|
@ -41,17 +43,17 @@ const schema: JSONSchemaType<{ name: string; age: number }> = {
|
|||
},
|
||||
required: ['name', 'age'],
|
||||
additionalProperties: false,
|
||||
};
|
||||
}
|
||||
|
||||
app.post(
|
||||
'/user',
|
||||
ajvValidator('json', schema, (result, c) => {
|
||||
if (!result.success) {
|
||||
return c.text('Invalid!', 400);
|
||||
return c.text('Invalid!', 400)
|
||||
}
|
||||
})
|
||||
//...
|
||||
);
|
||||
)
|
||||
```
|
||||
|
||||
## Author
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
# ArkType validator middleware for Hono
|
||||
|
||||
[](https://codecov.io/github/honojs/middleware)
|
||||
|
||||
The validator middleware using [ArkType](https://arktype.io/) for [Hono](https://honojs.dev) applications.
|
||||
You can write a schema with ArkType and validate the incoming values.
|
||||
|
||||
|
@ -11,7 +13,7 @@ import { arktypeValidator } from '@hono/arktype-validator'
|
|||
|
||||
const schema = type({
|
||||
name: 'string',
|
||||
age: 'number'
|
||||
age: 'number',
|
||||
})
|
||||
|
||||
app.post('/author', arktypeValidator('json', schema), (c) => {
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
# Auth.js middleware for Hono
|
||||
|
||||
[](https://codecov.io/github/honojs/middleware)
|
||||
|
||||
This is a [Auth.js](https://authjs.dev) third-party middleware for [Hono](https://github.com/honojs/hono).
|
||||
|
||||
This middleware can be used to inject the Auth.js session into the request context.
|
||||
|
@ -112,6 +114,7 @@ const useSession = () => {
|
|||
return { session: data, status }
|
||||
}
|
||||
```
|
||||
|
||||
For more details on how to Popup Oauth Login see [example](https://github.com/divyam234/next-auth-hono-react)
|
||||
|
||||
## Author
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
# Bun Transpiler middleware for Hono
|
||||
|
||||
[](https://codecov.io/github/honojs/middleware)
|
||||
|
||||
The Bun Transpiler middleware is a Hono middleware designed to transpile content such as TypeScript or TSX. You can place your script written in TypeScript in a directory and serve it using `serveStatic`. When you apply this middleware, your script will automatically be served transpiled into JavaScript code.
|
||||
|
||||
This middleware works only with [Bun](https://bun.sh/).
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
# Casbin Middleware for Hono
|
||||
|
||||
[](https://codecov.io/github/honojs/middleware)
|
||||
|
||||
This is a third-party [Casbin](https://casbin.org) middleware for [Hono](https://github.com/honojs/hono).
|
||||
|
||||
This middleware can be used to enforce authorization policies defined using Casbin in your Hono routes.
|
||||
|
@ -56,7 +58,8 @@ import { casbin } from '@hono/casbin'
|
|||
import { basicAuthorizer } from '@hono/casbin/helper'
|
||||
|
||||
const app = new Hono()
|
||||
app.use('*',
|
||||
app.use(
|
||||
'*',
|
||||
basicAuth(
|
||||
{
|
||||
username: 'alice', // alice has full access to /dataset1/test
|
||||
|
@ -69,7 +72,7 @@ app.use('*',
|
|||
),
|
||||
casbin({
|
||||
newEnforcer: newEnforcer('examples/model.conf', 'examples/policy.csv'),
|
||||
authorizer: basicAuthorizer
|
||||
authorizer: basicAuthorizer,
|
||||
})
|
||||
)
|
||||
app.get('/dataset1/test', (c) => c.text('dataset1 test')) // alice and bob can access /dataset1/test
|
||||
|
@ -89,13 +92,14 @@ import { casbin } from '@hono/casbin'
|
|||
import { jwtAuthorizer } from '@hono/casbin/helper'
|
||||
|
||||
const app = new Hono()
|
||||
app.use('*',
|
||||
app.use(
|
||||
'*',
|
||||
jwt({
|
||||
secret: 'it-is-very-secret',
|
||||
}),
|
||||
casbin({
|
||||
newEnforcer: newEnforcer('examples/model.conf', 'examples/policy.csv'),
|
||||
authorizer: jwtAuthorizer
|
||||
authorizer: jwtAuthorizer,
|
||||
})
|
||||
)
|
||||
app.get('/dataset1/test', (c) => c.text('dataset1 test')) // alice and bob can access /dataset1/test
|
||||
|
@ -112,7 +116,7 @@ const claimMapping = {
|
|||
// ...
|
||||
casbin({
|
||||
newEnforcer: newEnforcer('examples/model.conf', 'examples/policy.csv'),
|
||||
authorizer: (c, e) => jwtAuthorizer(c, e, claimMapping)
|
||||
authorizer: (c, e) => jwtAuthorizer(c, e, claimMapping),
|
||||
})
|
||||
```
|
||||
|
||||
|
@ -126,13 +130,16 @@ import { newEnforcer } from 'casbin'
|
|||
import { casbin } from '@hono/casbin'
|
||||
|
||||
const app = new Hono()
|
||||
app.use('*', casbin({
|
||||
newEnforcer: newEnforcer('path-to-your-model.conf', 'path-to-your-policy.csv'),
|
||||
authorizer: async (c, enforcer) => {
|
||||
const { user, path, method } = c
|
||||
return await enforcer.enforce(user, path, method)
|
||||
}
|
||||
}))
|
||||
app.use(
|
||||
'*',
|
||||
casbin({
|
||||
newEnforcer: newEnforcer('path-to-your-model.conf', 'path-to-your-policy.csv'),
|
||||
authorizer: async (c, enforcer) => {
|
||||
const { user, path, method } = c
|
||||
return await enforcer.enforce(user, path, method)
|
||||
},
|
||||
})
|
||||
)
|
||||
```
|
||||
|
||||
## Author
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
# Class-validator middleware for Hono
|
||||
|
||||
[](https://codecov.io/github/honojs/middleware)
|
||||
|
||||
The validator middleware using [class-validator](https://github.com/typestack/class-validator) for [Hono](https://github.com/honojs/hono) applications.
|
||||
|
||||
## Usage
|
||||
|
@ -10,13 +12,12 @@ import { IsInt, IsString } from 'class-validator'
|
|||
|
||||
class CreateUserDto {
|
||||
@IsString()
|
||||
name!: string;
|
||||
name!: string
|
||||
|
||||
@IsInt()
|
||||
age!: number;
|
||||
age!: number
|
||||
}
|
||||
|
||||
|
||||
const route = app.post('/user', classValidator('json', CreateUserDto), (c) => {
|
||||
const user = c.req.valid('json')
|
||||
return c.json({ success: true, message: `${user.name} is ${user.age}` })
|
||||
|
@ -31,17 +32,18 @@ import { IsInt, IsString } from 'class-validator'
|
|||
|
||||
class CreateUserDto {
|
||||
@IsString()
|
||||
name!: string;
|
||||
name!: string
|
||||
|
||||
@IsInt()
|
||||
age!: number;
|
||||
@IsInt()
|
||||
age!: number
|
||||
}
|
||||
|
||||
app.post(
|
||||
'/user', classValidator('json', CreateUserDto, (result, c) => {
|
||||
'/user',
|
||||
classValidator('json', CreateUserDto, (result, c) => {
|
||||
if (!result.success) {
|
||||
return c.text('Invalid!', 400)
|
||||
}
|
||||
}
|
||||
})
|
||||
//...
|
||||
)
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
# Clerk middleware for Hono
|
||||
|
||||
[](https://codecov.io/github/honojs/middleware)
|
||||
|
||||
This is a [Clerk](https://clerk.com) third-party middleware for [Hono](https://github.com/honojs/hono).
|
||||
|
||||
This middleware can be used to inject the active Clerk session into the request context.
|
||||
|
@ -33,13 +35,13 @@ app.get('/', (c) => {
|
|||
|
||||
if (!auth?.userId) {
|
||||
return c.json({
|
||||
message: 'You are not logged in.'
|
||||
message: 'You are not logged in.',
|
||||
})
|
||||
}
|
||||
|
||||
return c.json({
|
||||
message: 'You are logged in!',
|
||||
userId: auth.userId
|
||||
userId: auth.userId,
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -65,9 +67,12 @@ app.get('/', async (c) => {
|
|||
user,
|
||||
})
|
||||
} catch (e) {
|
||||
return c.json({
|
||||
message: 'User not found.'
|
||||
}, 404)
|
||||
return c.json(
|
||||
{
|
||||
message: 'User not found.',
|
||||
},
|
||||
404
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
# Cloudflare Access middleware for Hono
|
||||
|
||||
[](https://codecov.io/github/honojs/middleware)
|
||||
|
||||
This is a [Cloudflare Access](https://www.cloudflare.com/zero-trust/products/access/) third-party middleware
|
||||
for [Hono](https://github.com/honojs/hono).
|
||||
|
||||
|
@ -48,7 +50,7 @@ export default app
|
|||
## Errors throw by the middleware
|
||||
|
||||
| Error | HTTP Code |
|
||||
|--------------------------------------------------------------------------------------------------------|-----------|
|
||||
| ------------------------------------------------------------------------------------------------------ | --------- |
|
||||
| Authentication error: Missing bearer token | 401 |
|
||||
| Authentication error: Unable to decode Bearer token | 401 |
|
||||
| Authentication error: Token is expired | 401 |
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
# Conform validator middleware for Hono
|
||||
|
||||
[](https://codecov.io/github/honojs/middleware)
|
||||
|
||||
The validator middleware using [conform](https://conform.guide) for [Hono](https://honojs.dev) applications. This middleware allows you to validate submitted FormValue and making better use of [Hono RPC](https://hono.dev/docs/guides/rpc).
|
||||
|
||||
## Usage
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
# Effect Schema Validator Middleware for Hono
|
||||
|
||||
[](https://codecov.io/github/honojs/middleware)
|
||||
|
||||
This package provides a validator middleware using [Effect Schema](https://github.com/Effect-TS/effect/blob/main/packages/schema/README.md) for [Hono](https://honojs.dev) applications. With this middleware, you can define schemas using Effect Schema and validate incoming data in your Hono routes.
|
||||
|
||||
## Why Effect Schema?
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
# esbuild Transpiler Middleware
|
||||
|
||||
[](https://codecov.io/github/honojs/middleware)
|
||||
|
||||
The **esbuild Transpiler Middleware** is a Hono Middleware designed to transpile content such as TypeScript or TSX.
|
||||
You can place your script written in TypeScript in a directory and serve it using `serveStatic`.
|
||||
When you apply this Middleware, the script will be transpiled into JavaScript code.
|
||||
|
|
|
@ -1,23 +1,26 @@
|
|||
# Event Emitter middleware for Hono
|
||||
|
||||
[](https://codecov.io/github/honojs/middleware)
|
||||
|
||||
### Minimal, lightweight and edge compatible Event Emitter middleware for [Hono](https://github.com/honojs/hono).
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Introduction](#introduction)
|
||||
2. [Installation](#installation)
|
||||
3. [Usage Examples](#usage-examples)
|
||||
- [1. As Hono middleware](#1-as-hono-middleware)
|
||||
- [2. Standalone](#2-standalone)
|
||||
- [1. As Hono middleware](#1-as-hono-middleware)
|
||||
- [2. Standalone](#2-standalone)
|
||||
4. [API Reference](#api-reference)
|
||||
- [emitter](#emitter)
|
||||
- [createEmitter](#createemitter)
|
||||
- [defineHandler](#definehandler)
|
||||
- [defineHandlers](#definehandlers)
|
||||
- [Emitter API Documentation](#emitter)
|
||||
- [emitter](#emitter)
|
||||
- [createEmitter](#createemitter)
|
||||
- [defineHandler](#definehandler)
|
||||
- [defineHandlers](#definehandlers)
|
||||
- [Emitter API Documentation](#emitter)
|
||||
5. [Types](#types)
|
||||
|
||||
## Introduction
|
||||
|
||||
|
||||
This library provides an event emitter middleware for Hono, allowing you to easily implement and manage event-driven architectures in your Hono applications.
|
||||
It enables event driven logic flow, allowing you to decouple your code and make it more modular and maintainable.
|
||||
|
||||
|
@ -52,13 +55,13 @@ bun install @hono/event-emitter
|
|||
// Define event handlers
|
||||
export const handlers = {
|
||||
'user:created': [
|
||||
(c, payload) => {} // c is current Context, payload is whatever the emit method passes
|
||||
(c, payload) => {}, // c is current Context, payload is whatever the emit method passes
|
||||
],
|
||||
'user:deleted': [
|
||||
async (c, payload) => {} // c is current Context, payload is whatever the emit method passes
|
||||
async (c, payload) => {}, // c is current Context, payload is whatever the emit method passes
|
||||
],
|
||||
'foo': [
|
||||
(c, payload) => {} // c is current Context, payload is whatever the emit method passes
|
||||
foo: [
|
||||
(c, payload) => {}, // c is current Context, payload is whatever the emit method passes
|
||||
],
|
||||
}
|
||||
|
||||
|
@ -68,7 +71,6 @@ export const handlers = {
|
|||
// // ...
|
||||
// console.log('New foo created:', payload)
|
||||
// }
|
||||
|
||||
```
|
||||
|
||||
```js
|
||||
|
@ -115,7 +117,6 @@ but because middlewares are called on every request, you can only use named func
|
|||
|
||||
### 2 Standalone
|
||||
|
||||
|
||||
```js
|
||||
// events.js
|
||||
|
||||
|
@ -124,11 +125,11 @@ import { createEmitter } from '@hono/event-emitter'
|
|||
// Define event handlers
|
||||
export const handlers = {
|
||||
'user:created': [
|
||||
(c, payload) => {} // c is current Context, payload will be whatever you pass to emit method
|
||||
(c, payload) => {}, // c is current Context, payload will be whatever you pass to emit method
|
||||
],
|
||||
'user:deleted': [
|
||||
async (c, payload) => {} // c is current Context, payload will be whatever you pass to emit method
|
||||
]
|
||||
async (c, payload) => {}, // c is current Context, payload will be whatever you pass to emit method
|
||||
],
|
||||
}
|
||||
|
||||
// Initialize emitter with handlers
|
||||
|
@ -141,7 +142,6 @@ const ee = createEmitter(handlers)
|
|||
// })
|
||||
|
||||
export default ee
|
||||
|
||||
```
|
||||
|
||||
```js
|
||||
|
@ -154,17 +154,17 @@ import ee from './events'
|
|||
const app = new Hono()
|
||||
|
||||
app.post('/users', async (c) => {
|
||||
// ...
|
||||
// Emit event and pass current context plus the payload
|
||||
ee.emit(c, 'user:created', user)
|
||||
// ...
|
||||
// ...
|
||||
// Emit event and pass current context plus the payload
|
||||
ee.emit(c, 'user:created', user)
|
||||
// ...
|
||||
})
|
||||
|
||||
app.delete('/users/:id', async (c) => {
|
||||
// ...
|
||||
// Emit event and pass current context plus the payload
|
||||
await ee.emitAsync(c, 'user:deleted', id )
|
||||
// ...
|
||||
// ...
|
||||
// Emit event and pass current context plus the payload
|
||||
await ee.emitAsync(c, 'user:deleted', id)
|
||||
// ...
|
||||
})
|
||||
|
||||
export default app
|
||||
|
@ -180,27 +180,25 @@ export default app
|
|||
import type { Emitter } from '@hono/event-emitter'
|
||||
|
||||
export type User = {
|
||||
id: string,
|
||||
title: string,
|
||||
role: string
|
||||
id: string
|
||||
title: string
|
||||
role: string
|
||||
}
|
||||
|
||||
export type AvailableEvents = {
|
||||
// event key: payload type
|
||||
'user:created': User;
|
||||
'user:deleted': string;
|
||||
'foo': { bar: number };
|
||||
};
|
||||
// event key: payload type
|
||||
'user:created': User
|
||||
'user:deleted': string
|
||||
foo: { bar: number }
|
||||
}
|
||||
|
||||
export type Env = {
|
||||
Bindings: {};
|
||||
Variables: {
|
||||
// Define emitter variable type
|
||||
emitter: Emitter<AvailableEvents>;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
Bindings: {}
|
||||
Variables: {
|
||||
// Define emitter variable type
|
||||
emitter: Emitter<AvailableEvents>
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```ts
|
||||
|
@ -212,11 +210,11 @@ import { AvailableEvents } from './types'
|
|||
// Define event handlers
|
||||
export const handlers = defineHandlers<AvailableEvents>({
|
||||
'user:created': [
|
||||
(c, user) => {} // c is current Context, payload will be correctly inferred as User
|
||||
(c, user) => {}, // c is current Context, payload will be correctly inferred as User
|
||||
],
|
||||
'user:deleted': [
|
||||
async (c, payload) => {} // c is current Context, payload will be inferred as string
|
||||
]
|
||||
async (c, payload) => {}, // c is current Context, payload will be inferred as string
|
||||
],
|
||||
})
|
||||
|
||||
// You can also define single event handler as named function using defineHandler to leverage typings
|
||||
|
@ -225,7 +223,6 @@ export const handlers = defineHandlers<AvailableEvents>({
|
|||
// // ...
|
||||
// console.log('Foo:', payload)
|
||||
// })
|
||||
|
||||
```
|
||||
|
||||
```ts
|
||||
|
@ -277,35 +274,39 @@ but because middlewares are called on every request, you can only use named func
|
|||
// types.ts
|
||||
|
||||
type User = {
|
||||
id: string,
|
||||
title: string,
|
||||
id: string
|
||||
title: string
|
||||
role: string
|
||||
}
|
||||
|
||||
type AvailableEvents = {
|
||||
// event key: payload type
|
||||
'user:created': User;
|
||||
'user:updated': User;
|
||||
'user:deleted': string,
|
||||
'foo': { bar: number };
|
||||
'user:created': User
|
||||
'user:updated': User
|
||||
'user:deleted': string
|
||||
foo: { bar: number }
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
```ts
|
||||
// events.ts
|
||||
|
||||
import { createEmitter, defineHandlers, type Emitter, type EventHandlers } from '@hono/event-emitter'
|
||||
import {
|
||||
createEmitter,
|
||||
defineHandlers,
|
||||
type Emitter,
|
||||
type EventHandlers,
|
||||
} from '@hono/event-emitter'
|
||||
import { AvailableEvents } from './types'
|
||||
|
||||
// Define event handlers
|
||||
export const handlers = defineHandlers<AvailableEvents>({
|
||||
'user:created': [
|
||||
(c, user) => {} // c is current Context, payload will be correctly inferred as User
|
||||
(c, user) => {}, // c is current Context, payload will be correctly inferred as User
|
||||
],
|
||||
'user:deleted': [
|
||||
async (c, payload) => {} // c is current Context, payload will be inferred as string
|
||||
]
|
||||
async (c, payload) => {}, // c is current Context, payload will be inferred as string
|
||||
],
|
||||
})
|
||||
|
||||
// You can also define single event handler using defineHandler to leverage typings
|
||||
|
@ -318,12 +319,12 @@ const ee = createEmitter(handlers)
|
|||
|
||||
// And you can add more listeners on the fly.
|
||||
// Here you can use anonymous or closure function because .on() is only called once.
|
||||
ee.on('foo', async (c, payload) => { // Payload will be correctly inferred as User
|
||||
console.log('User updated:', payload)
|
||||
ee.on('foo', async (c, payload) => {
|
||||
// Payload will be correctly inferred as User
|
||||
console.log('User updated:', payload)
|
||||
})
|
||||
|
||||
export default ee
|
||||
|
||||
```
|
||||
|
||||
```ts
|
||||
|
@ -345,7 +346,7 @@ app.post('/user', async (c) => {
|
|||
app.delete('/user/:id', async (c) => {
|
||||
// ...
|
||||
// Emit event and pass current context plus the payload (string)
|
||||
ee.emit(c, 'user:deleted', id )
|
||||
ee.emit(c, 'user:deleted', id)
|
||||
// ...
|
||||
})
|
||||
|
||||
|
@ -355,26 +356,29 @@ export default app
|
|||
## API Reference
|
||||
|
||||
### emitter
|
||||
|
||||
Creates a Hono middleware that adds an event emitter to the context.
|
||||
|
||||
```ts
|
||||
function emitter<EPMap extends EventPayloadMap>(
|
||||
eventHandlers?: EventHandlers<EPMap>,
|
||||
options?: EventEmitterOptions
|
||||
eventHandlers?: EventHandlers<EPMap>,
|
||||
options?: EventEmitterOptions
|
||||
): MiddlewareHandler
|
||||
```
|
||||
|
||||
#### Parameters
|
||||
|
||||
- `eventHandlers` - (optional): An object containing initial event handlers. Each key is event name and value is array of event handlers. Use `defineHandlers` function to create fully typed event handlers.
|
||||
- `options` - (optional): An object containing options for the emitter. Currently, the only option is `maxHandlers`, which is the maximum number of handlers that can be added to an event. The default is `10`.
|
||||
|
||||
#### Returns
|
||||
|
||||
A Hono middleware function that adds an `Emitter` instance to the context under the key 'emitter'.
|
||||
|
||||
#### Example
|
||||
|
||||
```ts
|
||||
app.use(emitter(eventHandlers));
|
||||
app.use(emitter(eventHandlers))
|
||||
```
|
||||
|
||||
### createEmitter
|
||||
|
@ -383,12 +387,13 @@ Creates new instance of event emitter with provided handlers. This is usefull wh
|
|||
|
||||
```ts
|
||||
function createEmitter<EPMap extends EventPayloadMap>(
|
||||
eventHandlers?: EventHandlers<EPMap>,
|
||||
options?: EventEmitterOptions
|
||||
eventHandlers?: EventHandlers<EPMap>,
|
||||
options?: EventEmitterOptions
|
||||
): Emitter<EPMap>
|
||||
```
|
||||
|
||||
#### Parameters
|
||||
|
||||
- `eventHandlers` - (optional): An object containing initial event handlers. Each key is event name and value is array of event handlers.
|
||||
- `options` - (optional): An object containing options for the emitter. Currently, the only option is `maxHandlers`, which is the maximum number of handlers that can be added to an event. The default is `10`.
|
||||
|
||||
|
@ -399,7 +404,7 @@ An `Emitter` instance:
|
|||
#### Example
|
||||
|
||||
```ts
|
||||
const ee = createEmitter(eventHandlers);
|
||||
const ee = createEmitter(eventHandlers)
|
||||
```
|
||||
|
||||
### defineHandler
|
||||
|
@ -408,14 +413,16 @@ A utility function to define a typed event handler.
|
|||
|
||||
```ts
|
||||
function defineHandler<EPMap extends EventPayloadMap, Key extends keyof EPMap, E extends Env = Env>(
|
||||
handler: EventHandler<EPMap[Key], E>,
|
||||
handler: EventHandler<EPMap[Key], E>
|
||||
): EventHandler<EPMap[Key], E>
|
||||
```
|
||||
|
||||
#### Parameters
|
||||
|
||||
- `handler`: The event handler function to be defined.
|
||||
|
||||
#### Type parameters
|
||||
|
||||
- `EPMap`: The available event key to payload map i.e.: `type AvailableEvents = { 'user:created': { name: string } };`.
|
||||
- `Key`: The key of the event type.
|
||||
- `E`: (optional) - The Hono environment, so that the context within the handler has the right info.
|
||||
|
@ -428,11 +435,11 @@ The same event handler function with proper type inference.
|
|||
|
||||
```ts
|
||||
type AvailableEvents = {
|
||||
'user:created': { name: string };
|
||||
};
|
||||
'user:created': { name: string }
|
||||
}
|
||||
|
||||
const handler = defineHandler<AvailableEvents, 'user:created'>((c, payload) => {
|
||||
console.log('New user created:', payload)
|
||||
console.log('New user created:', payload)
|
||||
})
|
||||
```
|
||||
|
||||
|
@ -441,15 +448,17 @@ const handler = defineHandler<AvailableEvents, 'user:created'>((c, payload) => {
|
|||
A utility function to define multiple typed event handlers.
|
||||
|
||||
```ts
|
||||
function defineHandlers<EPMap extends EventPayloadMap, E extends Env = Env>(
|
||||
handlers: { [K in keyof EPMap]?: EventHandler<EPMap[K], E>[] },
|
||||
): { [K in keyof EPMap]?: EventHandler<EPMap[K], E>[] }
|
||||
function defineHandlers<EPMap extends EventPayloadMap, E extends Env = Env>(handlers: {
|
||||
[K in keyof EPMap]?: EventHandler<EPMap[K], E>[]
|
||||
}): { [K in keyof EPMap]?: EventHandler<EPMap[K], E>[] }
|
||||
```
|
||||
|
||||
#### Parameters
|
||||
|
||||
- `handlers`: An object containing event handlers for multiple event types/keys.
|
||||
|
||||
#### Type parameters
|
||||
|
||||
- `EPMap`: The available event key to payload map i.e.: `type AvailableEvents = { 'user:created': { name: string } };`.
|
||||
- `E`: (optional) - The Hono environment, so that the context within the handler has the right info.
|
||||
|
||||
|
@ -461,18 +470,20 @@ The same handlers object with proper type inference.
|
|||
|
||||
```ts
|
||||
type AvailableEvents = {
|
||||
'user:created': { name: string };
|
||||
};
|
||||
'user:created': { name: string }
|
||||
}
|
||||
|
||||
const handlers = defineHandlers<AvailableEvents>({
|
||||
'user:created': [
|
||||
(c, payload) => {
|
||||
console.log('New user created:', pyload)
|
||||
}
|
||||
]
|
||||
'user:created': [
|
||||
(c, payload) => {
|
||||
console.log('New user created:', pyload)
|
||||
},
|
||||
],
|
||||
})
|
||||
```
|
||||
|
||||
## Emitter instance methods
|
||||
|
||||
The `Emitter` interface provides methods for managing and triggering events. Here's a detailed look at each method:
|
||||
|
||||
### on
|
||||
|
@ -483,8 +494,8 @@ Adds an event handler for the specified event key.
|
|||
|
||||
```ts
|
||||
function on<Key extends keyof EventPayloadMap>(
|
||||
key: Key,
|
||||
handler: EventHandler<EventPayloadMap[Key]>
|
||||
key: Key,
|
||||
handler: EventHandler<EventPayloadMap[Key]>
|
||||
): void
|
||||
```
|
||||
|
||||
|
@ -493,8 +504,8 @@ function on<Key extends keyof EventPayloadMap>(
|
|||
- `key`: The event key to listen for. Must be a key of `EventHandlerPayloads`.
|
||||
- `handler`: The function to be called when the event is emitted. If using within a Hono middleware or request handler, do not use anonymous or closure functions!
|
||||
It should accept two parameters:
|
||||
- `c`: The current Hono context object.
|
||||
- `payload`: The payload passed when the event is emitted. The type of the payload is inferred from the `EventHandlerPayloads` type.
|
||||
- `c`: The current Hono context object.
|
||||
- `payload`: The payload passed when the event is emitted. The type of the payload is inferred from the `EventHandlerPayloads` type.
|
||||
|
||||
#### Returns
|
||||
|
||||
|
@ -503,33 +514,36 @@ function on<Key extends keyof EventPayloadMap>(
|
|||
#### Example
|
||||
|
||||
Using outside the Hono middleware or request handler:
|
||||
|
||||
```ts
|
||||
type AvailableEvents = {
|
||||
'user:created': { name: string };
|
||||
};
|
||||
const ee = createEmitter<AvailableEvents>();
|
||||
'user:created': { name: string }
|
||||
}
|
||||
const ee = createEmitter<AvailableEvents>()
|
||||
|
||||
// If adding event handler outside of Hono middleware or request handler, you can use both, named or anonymous function.
|
||||
ee.on('user:created', (c, user) => {
|
||||
console.log('New user created:', user)
|
||||
console.log('New user created:', user)
|
||||
})
|
||||
```
|
||||
|
||||
Using within Hono middleware or request handler:
|
||||
|
||||
```ts
|
||||
type AvailableEvents = {
|
||||
'user:created': { name: string };
|
||||
};
|
||||
'user:created': { name: string }
|
||||
}
|
||||
|
||||
// Define event handler as named function, outside of the Hono middleware or request handler to prevent duplicates/memory leaks
|
||||
const namedHandler = defineHandler<AvailableEvents, 'user:created'>((c, user) => {
|
||||
console.log('New user created:', user)
|
||||
console.log('New user created:', user)
|
||||
})
|
||||
|
||||
app.use(emitter<AvailableEvents>());
|
||||
app.use(emitter<AvailableEvents>())
|
||||
|
||||
app.use((c, next) => {
|
||||
c.get('emitter').on('user:created', namedHandler)
|
||||
return next()
|
||||
c.get('emitter').on('user:created', namedHandler)
|
||||
return next()
|
||||
})
|
||||
```
|
||||
|
||||
|
@ -541,41 +555,42 @@ Removes an event handler for the specified event key.
|
|||
|
||||
```ts
|
||||
function off<Key extends keyof EventPayloadMap>(
|
||||
key: Key,
|
||||
handler?: EventHandler<EventPayloadMap[Key]>
|
||||
key: Key,
|
||||
handler?: EventHandler<EventPayloadMap[Key]>
|
||||
): void
|
||||
```
|
||||
|
||||
#### Parameters
|
||||
|
||||
- `key`: The event key to remove the handler from. Must be a key of `EventPayloadMap`.
|
||||
- `handler` (optional): The specific handler function to remove. If not provided, all handlers for the given key will be removed.
|
||||
|
||||
#### Returns
|
||||
|
||||
`void`
|
||||
|
||||
#### Example
|
||||
|
||||
```ts
|
||||
type AvailableEvents = {
|
||||
'user:created': { name: string };
|
||||
};
|
||||
'user:created': { name: string }
|
||||
}
|
||||
|
||||
const ee = createEmitter<AvailableEvents>();
|
||||
const ee = createEmitter<AvailableEvents>()
|
||||
|
||||
const logUser = defineHandler<AvailableEvents, 'user:created'>((c, user) => {
|
||||
console.log(`User: ${user.name}`);
|
||||
});
|
||||
console.log(`User: ${user.name}`)
|
||||
})
|
||||
|
||||
ee.on('user:created', logUser);
|
||||
ee.on('user:created', logUser)
|
||||
|
||||
// Later, to remove the specific handler:
|
||||
ee.off('user:created', logUser);
|
||||
ee.off('user:created', logUser)
|
||||
|
||||
// Or to remove all handlers for 'user:created':
|
||||
ee.off('user:created');
|
||||
ee.off('user:created')
|
||||
```
|
||||
|
||||
|
||||
### emit
|
||||
|
||||
Synchronously emits an event with the specified key and payload.
|
||||
|
@ -591,6 +606,7 @@ emit<Key extends keyof EventPayloadMap>(
|
|||
```
|
||||
|
||||
#### Parameters
|
||||
|
||||
- `c`: The current Hono context object.
|
||||
- `key`: The event key to emit. Must be a key of `EventPayloadMap`.
|
||||
- `payload`: The payload to pass to the event handlers. The type of the payload is inferred from the `EventPayloadMap` type.
|
||||
|
@ -603,9 +619,9 @@ emit<Key extends keyof EventPayloadMap>(
|
|||
|
||||
```ts
|
||||
app.post('/users', (c) => {
|
||||
const user = { name: 'Alice' };
|
||||
c.get('emitter').emit(c, 'user:created', user);
|
||||
});
|
||||
const user = { name: 'Alice' }
|
||||
c.get('emitter').emit(c, 'user:created', user)
|
||||
})
|
||||
```
|
||||
|
||||
### emitAsync
|
||||
|
@ -624,13 +640,14 @@ emitAsync<Key extends keyof EventPayloadMap>(
|
|||
```
|
||||
|
||||
#### Parameters
|
||||
|
||||
- `c`: The current Hono context object.
|
||||
- `key`: The event key to emit. Must be a key of `EventPayloadMap`.
|
||||
- `payload`: The payload to pass to the event handlers. The type of the payload is inferred from the `EventPayloadMap` type.
|
||||
- `options` (optional): An object containing options for the asynchronous emission.
|
||||
Currently, the only option is `mode`, which can be `'concurrent'` (default) or `'sequencial'`.
|
||||
- The `'concurrent'` mode will call all handlers concurrently (at the same time) and resolve or reject (with aggregated errors) after all handlers settle.
|
||||
- The `'sequencial'` mode will call handlers one by one and resolve when all handlers are done or reject when the first error is thrown, not executing rest of the handlers.
|
||||
- The `'concurrent'` mode will call all handlers concurrently (at the same time) and resolve or reject (with aggregated errors) after all handlers settle.
|
||||
- The `'sequencial'` mode will call handlers one by one and resolve when all handlers are done or reject when the first error is thrown, not executing rest of the handlers.
|
||||
|
||||
#### Returns
|
||||
|
||||
|
@ -640,15 +657,16 @@ emitAsync<Key extends keyof EventPayloadMap>(
|
|||
|
||||
```ts
|
||||
app.post('/users', async (c) => {
|
||||
const user = { name: 'Alice' };
|
||||
await c.get('emitter').emitAsync(c, 'user:created', user);
|
||||
// await c.get('emitter').emitAsync(c, 'user:created', user, { mode: 'sequencial' });
|
||||
});
|
||||
const user = { name: 'Alice' }
|
||||
await c.get('emitter').emitAsync(c, 'user:created', user)
|
||||
// await c.get('emitter').emitAsync(c, 'user:created', user, { mode: 'sequencial' });
|
||||
})
|
||||
```
|
||||
|
||||
## Types
|
||||
|
||||
### EventKey
|
||||
|
||||
A string literal type representing an event key.
|
||||
|
||||
```ts
|
||||
|
@ -656,6 +674,7 @@ type EventKey = string | symbol
|
|||
```
|
||||
|
||||
### EventHandler
|
||||
|
||||
A function type that handles an event.
|
||||
|
||||
```ts
|
||||
|
@ -663,6 +682,7 @@ type EventHandler<T, E extends Env = Env> = (c: Context<E>, payload: T) => void
|
|||
```
|
||||
|
||||
### EventHandlers
|
||||
|
||||
An object type containing event handlers for multiple event types/keys.
|
||||
|
||||
```ts
|
||||
|
@ -670,6 +690,7 @@ type EventHandlers<T, E extends Env = Env> = { [K in keyof T]?: EventHandler<T[K
|
|||
```
|
||||
|
||||
### EventPayloadMap
|
||||
|
||||
An object type containing event keys and their corresponding payload types.
|
||||
|
||||
```ts
|
||||
|
@ -681,15 +702,16 @@ type EventPayloadMap = Record<EventKey, any>
|
|||
An object type containing options for the `Emitter` class.
|
||||
|
||||
```ts
|
||||
type EventEmitterOptions = { maxHandlers?: number };
|
||||
type EventEmitterOptions = { maxHandlers?: number }
|
||||
```
|
||||
|
||||
### EmitAsyncOptions
|
||||
|
||||
An object type containing options for the `emitAsync` method.
|
||||
|
||||
```ts
|
||||
type EmitAsyncOptions = {
|
||||
mode?: 'concurrent' | 'sequencial'
|
||||
mode?: 'concurrent' | 'sequencial'
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -699,45 +721,65 @@ An interface representing an event emitter.
|
|||
|
||||
```ts
|
||||
interface Emitter<EventPayloadMap> {
|
||||
on<Key extends keyof EventPayloadMap>(key: Key, handler: EventHandler<EventPayloadMap[Key]>): void;
|
||||
off<Key extends keyof EventPayloadMap>(key: Key, handler?: EventHandler<EventPayloadMap[Key]>): void;
|
||||
emit<Key extends keyof EventPayloadMap>(c: Context, key: Key, payload: EventPayloadMap[Key]): void;
|
||||
emitAsync<Key extends keyof EventPayloadMap>(
|
||||
c: Context,
|
||||
key: Key,
|
||||
payload: EventPayloadMap[Key],
|
||||
options?: EmitAsyncOptions
|
||||
): Promise<void>;
|
||||
on<Key extends keyof EventPayloadMap>(key: Key, handler: EventHandler<EventPayloadMap[Key]>): void
|
||||
off<Key extends keyof EventPayloadMap>(
|
||||
key: Key,
|
||||
handler?: EventHandler<EventPayloadMap[Key]>
|
||||
): void
|
||||
emit<Key extends keyof EventPayloadMap>(c: Context, key: Key, payload: EventPayloadMap[Key]): void
|
||||
emitAsync<Key extends keyof EventPayloadMap>(
|
||||
c: Context,
|
||||
key: Key,
|
||||
payload: EventPayloadMap[Key],
|
||||
options?: EmitAsyncOptions
|
||||
): Promise<void>
|
||||
}
|
||||
```
|
||||
|
||||
For more usage examples, see the [tests](src/index.test.ts) or [Hono REST API starter kit](https://github.com/DavidHavl/hono-rest-api-starter)
|
||||
|
||||
## FAQ
|
||||
|
||||
### What the heck is event emitter and why should I use it?
|
||||
|
||||
Event emitter is a pattern that allows you to decouple your code and make it more modular and maintainable.
|
||||
It's a way to implement the observer pattern in your application.
|
||||
It's especially useful in larger projects or projects with a lot of interactions between features.
|
||||
Just imagine you have a user registration feature, and you want to send a welcome email after the user is created. You can do this by emitting an event `user:created` and then listen to this event in another part of your application (e.g. email service).
|
||||
|
||||
### How is this different to the built-in EventEmitter in Node.js?
|
||||
|
||||
The build-in EventEmitter has huge API surface, weak TypeScript support and does only synchronous event emitting. Hono's event emitter is designed to be minimal, lightweight, edge compatible and fully typed. Additionally, it supports async event handlers.
|
||||
|
||||
### Is there a way to define event handlers with types?
|
||||
|
||||
Yes, you can use `defineHandlers` and `defineHandler` functions to define event handlers with types. This way you can leverage TypeScript's type inference and get better type checking.
|
||||
|
||||
### Does it support async event handlers?
|
||||
|
||||
Yes, it does. You can use async functions as event handlers and emit the events using `emitAsync` method.
|
||||
|
||||
### What happens if I emit an event that has no handlers?
|
||||
|
||||
Nothing. The event will be emitted, but no handlers will be called.
|
||||
|
||||
### Using `emitAsync` function, what happens if one or more of the handlers reject?
|
||||
|
||||
- If using `{ mode = 'concurrent' }` in the options (which is the default), it will call all handlers concurrently (at the same time) and resolve or reject (with aggregated errors) after all handlers settle.
|
||||
- If using `{ mode = 'sequencial' }` in the options, it will call handlers one by one and resolve when all handlers are done or reject when the first error is thrown, not executing rest of the handlers.
|
||||
|
||||
### Is it request scoped?
|
||||
|
||||
No, by design it's not request scoped. The same Emitter instance is shared across all requests.
|
||||
This aproach prevents memory leaks (especially when using closures or dealing with large data structures within the handlers) and additional strain on Javascript garbage collector.
|
||||
|
||||
### Why can't I use anonymous functions or closures as event handlers when adding them inside of middleware?
|
||||
|
||||
This is because middleware or request handlers run repeatedly on every request, and because anonymous functions are created as new unique object in memory every time,
|
||||
you would be instructing the event emitter to add new handler for same key every time the request/middleware runs.
|
||||
Since they are each different objects in memory they can't be checked for equality and would result in memory leaks and duplicate handlers.
|
||||
You should use named functions if you really want to use the `on()` method inside of middleware or request handler.
|
||||
|
||||
## Author
|
||||
|
||||
David Havl <https://github.com/DavidHavl>
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
# Hono Firebase Auth middleware for Cloudflare Workers
|
||||
|
||||
[](https://codecov.io/github/honojs/middleware)
|
||||
|
||||
This is a Firebase Auth middleware library for [Hono](https://github.com/honojs/hono) which is used [firebase-auth-cloudflare-workers](https://github.com/Code-Hex/firebase-auth-cloudflare-workers).
|
||||
|
||||
Currently only Cloudflare Workers are supported officially. However, it may work in other environments as well, so please let us know in an issue if it works.
|
||||
|
@ -106,23 +108,23 @@ If not specified, check the [`FIREBASE_AUTH_EMULATOR_HOST` environment variable
|
|||
|
||||
```ts
|
||||
import { Hono } from 'hono'
|
||||
import { setCookie } from 'hono/cookie';
|
||||
import { csrf } from 'hono/csrf';
|
||||
import { html } from 'hono/html';
|
||||
import { setCookie } from 'hono/cookie'
|
||||
import { csrf } from 'hono/csrf'
|
||||
import { html } from 'hono/html'
|
||||
import {
|
||||
VerifySessionCookieFirebaseAuthConfig,
|
||||
VerifyFirebaseAuthEnv,
|
||||
verifySessionCookieFirebaseAuth,
|
||||
getFirebaseToken,
|
||||
} from '@hono/firebase-auth'
|
||||
import { AdminAuthApiClient, ServiceAccountCredential } from 'firebase-auth-cloudflare-workers';
|
||||
import { AdminAuthApiClient, ServiceAccountCredential } from 'firebase-auth-cloudflare-workers'
|
||||
|
||||
const config: VerifySessionCookieFirebaseAuthConfig = {
|
||||
// specify your firebase project ID.
|
||||
projectId: 'your-project-id',
|
||||
redirects: {
|
||||
signIn: "/login"
|
||||
}
|
||||
signIn: '/login',
|
||||
},
|
||||
}
|
||||
|
||||
// You can specify here the extended VerifyFirebaseAuthEnv type.
|
||||
|
@ -140,7 +142,7 @@ type MyEnv = VerifyFirebaseAuthEnv & {
|
|||
const app = new Hono<{ Bindings: MyEnv }>()
|
||||
|
||||
// set middleware
|
||||
app.get('/login', csrf(), async c => {
|
||||
app.get('/login', csrf(), async (c) => {
|
||||
// You can copy code from here
|
||||
// https://github.com/Code-Hex/firebase-auth-cloudflare-workers/blob/0ce610fff257b0b60e2f8e38d89c8e012497d537/example/index.ts#L63C25-L63C37
|
||||
const content = await html`...`
|
||||
|
@ -148,13 +150,13 @@ app.get('/login', csrf(), async c => {
|
|||
})
|
||||
|
||||
app.post('/login_session', csrf(), (c) => {
|
||||
const json = await c.req.json();
|
||||
const idToken = json.idToken;
|
||||
const json = await c.req.json()
|
||||
const idToken = json.idToken
|
||||
if (!idToken || typeof idToken !== 'string') {
|
||||
return c.json({ message: 'invalid idToken' }, 400);
|
||||
return c.json({ message: 'invalid idToken' }, 400)
|
||||
}
|
||||
// Set session expiration to 5 days.
|
||||
const expiresIn = 60 * 60 * 24 * 5 * 1000;
|
||||
const expiresIn = 60 * 60 * 24 * 5 * 1000
|
||||
|
||||
// Create the session cookie. This will also verify the ID token in the process.
|
||||
// The session cookie will have the same claims as the ID token.
|
||||
|
@ -163,26 +165,22 @@ app.post('/login_session', csrf(), (c) => {
|
|||
const auth = AdminAuthApiClient.getOrInitialize(
|
||||
c.env.PROJECT_ID,
|
||||
new ServiceAccountCredential(c.env.SERVICE_ACCOUNT_JSON)
|
||||
);
|
||||
const sessionCookie = await auth.createSessionCookie(
|
||||
idToken,
|
||||
expiresIn,
|
||||
);
|
||||
)
|
||||
const sessionCookie = await auth.createSessionCookie(idToken, expiresIn)
|
||||
setCookie(c, 'session', sessionCookie, {
|
||||
maxAge: expiresIn,
|
||||
httpOnly: true,
|
||||
secure: true
|
||||
});
|
||||
return c.json({ message: 'success' });
|
||||
secure: true,
|
||||
})
|
||||
return c.json({ message: 'success' })
|
||||
})
|
||||
|
||||
app.use('/admin/*', csrf(), verifySessionCookieFirebaseAuth(config));
|
||||
app.use('/admin/*', csrf(), verifySessionCookieFirebaseAuth(config))
|
||||
app.get('/admin/hello', (c) => {
|
||||
const idToken = getFirebaseToken(c) // get id-token object.
|
||||
return c.json(idToken)
|
||||
})
|
||||
|
||||
|
||||
export default app
|
||||
```
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
# GraphQL Server Middleware
|
||||
|
||||
[](https://codecov.io/github/honojs/middleware)
|
||||
|
||||
## Requirements
|
||||
|
||||
This middleware depends on [GraphQL.js](https://www.npmjs.com/package/graphql).
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
# Hello middleware for Hono
|
||||
|
||||
[](https://codecov.io/github/honojs/middleware)
|
||||
|
||||
An example project of the third-party middleware for [Hono](https://github.com/honojs/hono).
|
||||
This middleware add `X-Message` header to the Response.
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
# Router using @medley/router
|
||||
|
||||
[](https://codecov.io/github/honojs/middleware)
|
||||
|
||||
Just a PoC.
|
||||
|
||||
## Usage
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
# WebSocket helper for Node.js
|
||||
|
||||
[](https://codecov.io/github/honojs/middleware)
|
||||
|
||||
A WebSocket helper for Node.js
|
||||
|
||||
## Usage
|
||||
|
@ -13,9 +15,12 @@ const app = new Hono()
|
|||
|
||||
const { injectWebSocket, upgradeWebSocket } = createNodeWebSocket({ app })
|
||||
|
||||
app.get('/ws', upgradeWebSocket((c) => ({
|
||||
// https://hono.dev/helpers/websocket
|
||||
})))
|
||||
app.get(
|
||||
'/ws',
|
||||
upgradeWebSocket((c) => ({
|
||||
// https://hono.dev/helpers/websocket
|
||||
}))
|
||||
)
|
||||
|
||||
const server = serve(app)
|
||||
injectWebSocket(server)
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
# OAuth Providers Middleware
|
||||
|
||||
[](https://codecov.io/github/honojs/middleware)
|
||||
|
||||
Authentication middleware for [Hono](https://github.com/honojs/hono). This package offers a straightforward API for social login with platforms such as Facebook, GitHub, Google, LinkedIn and X(Twitter).
|
||||
|
||||
## Installation
|
||||
|
@ -1079,7 +1081,6 @@ You can validate a Twitch access token to verify it's still valid or to obtain i
|
|||
|
||||
You can use `validateToken` method, which accepts the `token` to be validated as parameter and returns `TwitchValidateSuccess` if valid or throws `HTTPException` upon failure.
|
||||
|
||||
|
||||
> **IMPORTANT:** Twitch requires applications to validate OAuth tokens when they start and on an hourly basis thereafter. Failure to validate tokens may result in Twitch taking punitive action, such as revoking API keys or throttling performance. When a token becomes invalid, your app should terminate all sessions using that token immediately. [Read more](https://dev.twitch.tv/docs/authentication/validate-tokens)
|
||||
|
||||
The validation endpoint helps your application detect when tokens become invalid for reasons other than expiration, such as when users disconnect your integration from their Twitch account. When a token becomes invalid, your app should terminate all sessions using that token.
|
||||
|
@ -1099,36 +1100,39 @@ This parameters can be useful if
|
|||
3. Or, in need to encode more info into `redirect_uri`.
|
||||
|
||||
```ts
|
||||
const app = new Hono();
|
||||
const app = new Hono()
|
||||
|
||||
const SITE_ORIGIN = `https://my-site.com`;
|
||||
const OAUTH_CALLBACK_PATH = `/oauth/google`;
|
||||
const SITE_ORIGIN = `https://my-site.com`
|
||||
const OAUTH_CALLBACK_PATH = `/oauth/google`
|
||||
|
||||
app.get('/*',
|
||||
app.get(
|
||||
'/*',
|
||||
async (c, next) => {
|
||||
const session = readSession(c);
|
||||
const session = readSession(c)
|
||||
if (!session) {
|
||||
// start oauth flow
|
||||
const redirectUri = `${SITE_ORIGIN}${OAUTH_CALLBACK_PATH}?redirect=${encodeURIComponent(c.req.path)}`;
|
||||
const oauth = googleAuth({ redirect_uri: redirectUri, ...more });
|
||||
const redirectUri = `${SITE_ORIGIN}${OAUTH_CALLBACK_PATH}?redirect=${encodeURIComponent(
|
||||
c.req.path
|
||||
)}`
|
||||
const oauth = googleAuth({ redirect_uri: redirectUri, ...more })
|
||||
return await oauth(c, next)
|
||||
}
|
||||
},
|
||||
async (c, next) => {
|
||||
// if we are here, the req should contain either a valid session or a valid auth code
|
||||
const session = readSession(c);
|
||||
const session = readSession(c)
|
||||
const authedGoogleUser = c.get('user-google')
|
||||
if (authedGoogleUser) {
|
||||
await saveSession(c, authedGoogleUser);
|
||||
await saveSession(c, authedGoogleUser)
|
||||
} else if (!session) {
|
||||
throw new HttpException(401)
|
||||
}
|
||||
return next();
|
||||
return next()
|
||||
},
|
||||
async (c, next) => {
|
||||
// serve protected content
|
||||
}
|
||||
);
|
||||
)
|
||||
```
|
||||
|
||||
## Author
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
# OpenID Connect Authentication middleware for Hono
|
||||
|
||||
[](https://codecov.io/github/honojs/middleware)
|
||||
|
||||
This is an OpenID Connect (OIDC) authentication third-party middleware for [Hono](https://github.com/honojs/hono), which depends on [oauth4webapi](https://www.npmjs.com/package/oauth4webapi).
|
||||
|
||||
This middleware provides storage-less login sessions.
|
||||
|
@ -144,7 +146,7 @@ If the middleware is applied to the callback URL, the default callback handling
|
|||
|
||||
```typescript
|
||||
// Before other oidc-auth APIs are used
|
||||
app.use(initOidcAuthMiddleware(config));
|
||||
app.use(initOidcAuthMiddleware(config))
|
||||
```
|
||||
|
||||
Or to leverage context, use the [`Context access inside Middleware arguments`](https://hono.dev/docs/guides/middleware#context-access-inside-middleware-arguments) pattern.
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
# OpenTelemetry middleware for Hono
|
||||
|
||||
[](https://codecov.io/github/honojs/middleware)
|
||||
|
||||
This package provides a [Hono](https://hono.dev/) middleware that instruments your application with [OpenTelemetry](https://opentelemetry.io/).
|
||||
|
||||
## Usage
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
# Prometheus middleware for Hono
|
||||
|
||||
[](https://codecov.io/github/honojs/middleware)
|
||||
|
||||
This middleware adds basic [RED metrics](https://www.weave.works/blog/the-red-method-key-metrics-for-microservices-architecture/) to your Hono application, and exposes them on the `/metrics` endpoint for Prometheus to scrape.
|
||||
|
||||
## Installation
|
||||
|
@ -81,13 +83,13 @@ An options object can be passed in the `prometheus()` middleware factory to conf
|
|||
|
||||
### `prefix`
|
||||
|
||||
Type: *string*
|
||||
Type: _string_
|
||||
|
||||
Prefix all metrics with this string.
|
||||
|
||||
### `registry`
|
||||
|
||||
Type: *[Registry](https://www.npmjs.com/package/prom-client)*
|
||||
Type: _[Registry](https://www.npmjs.com/package/prom-client)_
|
||||
|
||||
A prom-client Registry instance to store the metrics. If not provided, a new one will be created.
|
||||
|
||||
|
@ -95,7 +97,7 @@ Useful when you want to register some custom metrics while exposing them on the
|
|||
|
||||
### `collectDefaultMetrics`
|
||||
|
||||
Type: *boolean | [CollectDefaultMetricsOptions](https://www.npmjs.com/package/prom-client#default-metrics)*
|
||||
Type: _boolean | [CollectDefaultMetricsOptions](https://www.npmjs.com/package/prom-client#default-metrics)_
|
||||
|
||||
There are some default metrics recommended by prom-client, like event loop delay, garbage collection statistics etc.
|
||||
|
||||
|
@ -103,34 +105,37 @@ To enable these metrics, set this option to `true`. To configure the default met
|
|||
|
||||
### `metricOptions`
|
||||
|
||||
Type: *object (see below)*
|
||||
Type: _object (see below)_
|
||||
|
||||
Modify the standard metrics (*requestDuration* and *requestsTotal*) with any of the [Counter](https://www.npmjs.com/package/prom-client#counter) / [Histogram](https://www.npmjs.com/package/prom-client#histogram) metric options, including:
|
||||
Modify the standard metrics (_requestDuration_ and _requestsTotal_) with any of the [Counter](https://www.npmjs.com/package/prom-client#counter) / [Histogram](https://www.npmjs.com/package/prom-client#histogram) metric options, including:
|
||||
|
||||
#### `disabled`
|
||||
|
||||
Type: *boolean*
|
||||
Type: _boolean_
|
||||
|
||||
Disables the metric.
|
||||
|
||||
#### `customLabels`
|
||||
|
||||
Type: *Record<string, (context) => string>*
|
||||
Type: _Record<string, (context) => string>_
|
||||
|
||||
A record where the keys are the labels to add to the metrics, and the values are functions that receive the Hono context and return the value for that label. This is useful when adding labels to the metrics that are specific to your application or your needs. These functions are executed after all the other middlewares finished.
|
||||
|
||||
The following example adds a label to the *requestsTotal* metric with the `contentType` name where the value is the content type of the response:
|
||||
The following example adds a label to the _requestsTotal_ metric with the `contentType` name where the value is the content type of the response:
|
||||
|
||||
```ts
|
||||
app.use('*', prometheus({
|
||||
metricOptions: {
|
||||
requestsTotal: {
|
||||
customLabels: {
|
||||
content_type: (c) => c.res.headers.get('content-type'),
|
||||
}
|
||||
app.use(
|
||||
'*',
|
||||
prometheus({
|
||||
metricOptions: {
|
||||
requestsTotal: {
|
||||
customLabels: {
|
||||
content_type: (c) => c.res.headers.get('content-type'),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}))
|
||||
})
|
||||
)
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
# Qwik City middleware for Hono
|
||||
|
||||
[](https://codecov.io/github/honojs/middleware)
|
||||
|
||||
**WIP**
|
||||
|
||||
## Usage
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
# Alias of hono/jsx for replacement of React
|
||||
|
||||
[](https://codecov.io/github/honojs/middleware)
|
||||
|
||||
This package is used to install the React compatibility API provided by [Hono](https://github.com/honojs/hono). This package allows you to replace the "react" and "react-dom" entities with "@hono/react-compat".
|
||||
|
||||
## Usage
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
# React Renderer Middleware
|
||||
|
||||
[](https://codecov.io/github/honojs/middleware)
|
||||
|
||||
React Renderer Middleware allows for the easy creation of a renderer based on React for Hono.
|
||||
|
||||
## Installation
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
# Sentry Middleware for Hono
|
||||
|
||||
[](https://codecov.io/github/honojs/middleware)
|
||||
|
||||
This middleware integrates [Hono](https://github.com/honojs/hono) with Sentry. It captures exceptions and sends them to the specified Sentry data source name (DSN) using [toucan-js](https://github.com/robertcepa/toucan-js).
|
||||
|
||||
## Installation
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
# Standard Schema validator middleware for Hono
|
||||
|
||||
[](https://codecov.io/github/honojs/middleware)
|
||||
|
||||
The validator middleware using [Standard Schema Spec](https://github.com/standard-schema/standard-schema) for [Hono](https://honojs.dev) applications.
|
||||
You can write a schema with any validation library supporting Standard Schema and validate the incoming values.
|
||||
|
||||
## Usage
|
||||
|
||||
|
||||
### Basic:
|
||||
|
||||
```ts
|
||||
import { z } from 'zod'
|
||||
import { sValidator } from '@hono/standard-validator'
|
||||
|
@ -14,7 +16,7 @@ import { sValidator } from '@hono/standard-validator'
|
|||
const schema = z.object({
|
||||
name: z.string(),
|
||||
age: z.number(),
|
||||
});
|
||||
})
|
||||
|
||||
app.post('/author', sValidator('json', schema), (c) => {
|
||||
const data = c.req.valid('json')
|
||||
|
@ -26,6 +28,7 @@ app.post('/author', sValidator('json', schema), (c) => {
|
|||
```
|
||||
|
||||
### Hook:
|
||||
|
||||
```ts
|
||||
app.post(
|
||||
'/post',
|
||||
|
@ -39,15 +42,17 @@ app.post(
|
|||
```
|
||||
|
||||
### Headers:
|
||||
|
||||
Headers are internally transformed to lower-case in Hono. Hence, you will have to make them lower-cased in validation object.
|
||||
|
||||
```ts
|
||||
import { object, string } from 'valibot'
|
||||
import { sValidator } from '@hono/standard-validator'
|
||||
|
||||
const schema = object({
|
||||
'content-type': string(),
|
||||
'user-agent': string()
|
||||
});
|
||||
'user-agent': string(),
|
||||
})
|
||||
|
||||
app.post('/author', sValidator('header', schema), (c) => {
|
||||
const headers = c.req.valid('header')
|
||||
|
@ -55,7 +60,6 @@ app.post('/author', sValidator('header', schema), (c) => {
|
|||
})
|
||||
```
|
||||
|
||||
|
||||
## Author
|
||||
|
||||
Rokas Muningis <https://github.com/muningis>
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
# Swagger Editor Middleware for Hono
|
||||
|
||||
[](https://codecov.io/github/honojs/middleware)
|
||||
|
||||
This library, `@hono/swagger-editor` is the middleware for integrating Swagger Editor with Hono applications. The Swagger Editor is an open source editor to design, define and document RESTful APIs in the Swagger Specification.
|
||||
|
||||
## Installation
|
||||
|
@ -14,7 +16,6 @@ yarn add @hono/swagger-editor
|
|||
|
||||
You can use the `swaggerEditor` middleware to serve Swagger Editor on a specific route in your Hono application. Here's how you can do it:
|
||||
|
||||
|
||||
```ts
|
||||
import { Hono } from 'hono'
|
||||
import { swaggerUI } from '@hono/swagger-ui'
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
# Swagger UI Middleware and Component for Hono
|
||||
|
||||
[](https://codecov.io/github/honojs/middleware)
|
||||
|
||||
This library, `@hono/swagger-ui`, provides a middleware and a component for integrating Swagger UI with Hono applications. Swagger UI is an interactive documentation interface for APIs compliant with the OpenAPI Specification, making it easier to understand and test API endpoints.
|
||||
|
||||
## Installation
|
||||
|
@ -83,16 +85,16 @@ app.openapi(
|
|||
content: {
|
||||
'application/json': {
|
||||
schema: z.object({
|
||||
message: z.string()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
message: z.string(),
|
||||
}),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
(c) => {
|
||||
return c.json({
|
||||
message: 'hello'
|
||||
message: 'hello',
|
||||
})
|
||||
}
|
||||
)
|
||||
|
@ -100,16 +102,16 @@ app.openapi(
|
|||
app.get(
|
||||
'/ui',
|
||||
swaggerUI({
|
||||
url: '/doc'
|
||||
url: '/doc',
|
||||
})
|
||||
)
|
||||
|
||||
app.doc('/doc', {
|
||||
info: {
|
||||
title: 'An API',
|
||||
version: 'v1'
|
||||
version: 'v1',
|
||||
},
|
||||
openapi: '3.1.0'
|
||||
openapi: '3.1.0',
|
||||
})
|
||||
|
||||
export default app
|
||||
|
@ -124,11 +126,10 @@ The following options are available:
|
|||
- `version` (string, optional): The version of Swagger UI to use, defaults to `latest`.
|
||||
- `manuallySwaggerUIHtml` (string, optional): If you want to use your own custom HTML, you can specify it here. If this option is specified, the all options except `version` will be ignored.
|
||||
|
||||
and most of options from [Swagger UI](
|
||||
https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/
|
||||
) are supported as well.
|
||||
and most of options from [Swagger UI](https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/) are supported as well.
|
||||
|
||||
such as:
|
||||
|
||||
- `url` (string, optional): The URL pointing to the OpenAPI definition (v2 or v3) that describes the API.
|
||||
- `urls` (array, optional): An array of OpenAPI definitions (v2 or v3) that describe the APIs. Each definition must have a `name` and `url`.
|
||||
- `presets` (array, optional): An array of presets to use for Swagger UI.
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
# tRPC Server Middleware for Hono
|
||||
|
||||
[](https://codecov.io/github/honojs/middleware)
|
||||
|
||||
tRPC Server Middleware adapts a [tRPC](https://trpc.io) server as middleware for Hono.
|
||||
Hono works on almost any JavaScript runtime, including Cloudflare Workers, Deno, and Bun. So, with this middleware, the same code will run as tRPC server.
|
||||
|
||||
|
@ -76,11 +78,11 @@ import { initTRPC } from '@trpc/server'
|
|||
import { z } from 'zod'
|
||||
|
||||
type Env = {
|
||||
DB: D1Database;
|
||||
DB: D1Database
|
||||
}
|
||||
type HonoContext = {
|
||||
env: Env,
|
||||
};
|
||||
env: Env
|
||||
}
|
||||
|
||||
const t = initTRPC.context<HonoContext>().create()
|
||||
|
||||
|
@ -89,8 +91,8 @@ const router = t.router
|
|||
|
||||
export const appRouter = router({
|
||||
usersCount: publicProcedure.query(({ input, ctx }) => {
|
||||
const result = await ctx.env.DB.prepare("SELECT count(*) from user;").all();
|
||||
return result.results[0].count;
|
||||
const result = await ctx.env.DB.prepare('SELECT count(*) from user;').all()
|
||||
return result.results[0].count
|
||||
}),
|
||||
})
|
||||
|
||||
|
@ -108,10 +110,11 @@ app.use(
|
|||
// c is the hono context
|
||||
var1: c.env.MY_VAR1,
|
||||
var2: c.req.header('X-VAR2'),
|
||||
})
|
||||
}),
|
||||
})
|
||||
)
|
||||
```
|
||||
|
||||
## Custom Endpoints
|
||||
|
||||
To set up custom endpoints ensure the endpoint parameter matches the middleware's path. This alignment allows `@trpc/server` to accurately extract your procedure paths.
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
# tsyringe middleware for Hono
|
||||
|
||||
[](https://codecov.io/github/honojs/middleware)
|
||||
|
||||
The [tsyringe](https://github.com/microsoft/tsyringe) middleware provides a way to use dependency injection in [Hono](https://hono.dev/).
|
||||
|
||||
## Usage
|
||||
|
||||
```ts
|
||||
import "reflect-metadata" // tsyringe requires reflect-metadata or polyfill
|
||||
import 'reflect-metadata' // tsyringe requires reflect-metadata or polyfill
|
||||
import { container, inject, injectable } from 'tsyringe'
|
||||
import { tsyringe } from '@hono/tsyringe'
|
||||
import { Hono } from 'hono'
|
||||
|
@ -21,13 +23,16 @@ class Hello {
|
|||
|
||||
const app = new Hono()
|
||||
|
||||
app.use('*', tsyringe((container) => {
|
||||
app.use(
|
||||
'*',
|
||||
tsyringe((container) => {
|
||||
container.register('name', { useValue: 'world' })
|
||||
}))
|
||||
})
|
||||
)
|
||||
|
||||
app.get('/', (c) => {
|
||||
const hello = container.resolve(Hello)
|
||||
return c.text(hello.greet())
|
||||
const hello = container.resolve(Hello)
|
||||
return c.text(hello.greet())
|
||||
})
|
||||
|
||||
export default app
|
||||
|
@ -39,12 +44,12 @@ export default app
|
|||
const app = new Hono()
|
||||
|
||||
app.use('/tenant/:name/*', async (c, next) => {
|
||||
await tsyringe((container) => {
|
||||
// Allowing to inject `c.var` or `c.req.param` in the providers
|
||||
const tenantName = c.req.param('name')
|
||||
await tsyringe((container) => {
|
||||
// Allowing to inject `c.var` or `c.req.param` in the providers
|
||||
const tenantName = c.req.param('name')
|
||||
|
||||
container.register(Config, { useFactory: () => new Config(tenantName) })
|
||||
})(c, next)
|
||||
container.register(Config, { useFactory: () => new Config(tenantName) })
|
||||
})(c, next)
|
||||
})
|
||||
```
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
# TypeBox validator middleware for Hono
|
||||
|
||||
[](https://codecov.io/github/honojs/middleware)
|
||||
|
||||
Validator middleware using [TypeBox](https://github.com/sinclairzx81/typebox) for [Hono](https://honojs.dev) applications.
|
||||
Define your schema with TypeBox and validate incoming requests.
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
# Typia validator middleware for Hono
|
||||
|
||||
[](https://codecov.io/github/honojs/middleware)
|
||||
|
||||
The validator middleware using [Typia](https://typia.io/docs/) for [Hono](https://honojs.dev) applications.
|
||||
|
||||
## Usage
|
||||
|
@ -83,7 +85,8 @@ const validate = typia.createValidate<Author>()
|
|||
const validateQuery = typia.http.createValidateQuery<IQuery>()
|
||||
const validateHeaders = typia.http.createValidateHeaders<IHeaders>()
|
||||
|
||||
app.get('/items',
|
||||
app.get(
|
||||
'/items',
|
||||
typiaValidator('json', validate),
|
||||
typiaValidator('query', validateQuery),
|
||||
typiaValidator('header', validateHeaders),
|
||||
|
@ -98,6 +101,7 @@ app.get('/items',
|
|||
}
|
||||
)
|
||||
```
|
||||
|
||||
## Author
|
||||
|
||||
Patryk Dwórznik <https://github.com/dworznik>
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
# Valibot validator middleware for Hono
|
||||
|
||||
[](https://codecov.io/github/honojs/middleware)
|
||||
|
||||
The validator middleware using [Valibot](https://valibot.dev) for [Hono](https://honojs.dev) applications.
|
||||
You can write a schema with Valibot and validate the incoming values.
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
# Zod OpenAPI Hono
|
||||
|
||||
[](https://codecov.io/github/honojs/middleware)
|
||||
|
||||
**Zod OpenAPI Hono** is an extended Hono class that supports OpenAPI. With it, you can validate values and types using [**Zod**](https://zod.dev/) and generate OpenAPI Swagger documentation. This is based on [**Zod to OpenAPI**](https://github.com/asteasolutions/zod-to-openapi) (thanks a lot!). For details on creating schemas and defining routes, please refer to [the "Zod to OpenAPI" resource](https://github.com/asteasolutions/zod-to-openapi).
|
||||
|
||||
_Note: This is not standalone middleware but is hosted on the monorepo "[github.com/honojs/middleware](https://github.com/honojs/middleware)"._
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
# Zod validator middleware for Hono
|
||||
|
||||
[](https://codecov.io/github/honojs/middleware)
|
||||
|
||||
The validator middleware using [Zod](https://zod.dev) for [Hono](https://honojs.dev) applications.
|
||||
You can write a schema with Zod and validate the incoming values.
|
||||
|
||||
|
@ -43,22 +45,19 @@ throw a zod validate error instead of directly returning an error response.
|
|||
|
||||
```ts
|
||||
// file: validator-wrapper.ts
|
||||
import { ZodSchema } from "zod";
|
||||
import type { ValidationTargets } from "hono";
|
||||
import { zValidator as zv } from "@hono/zod-validator";
|
||||
import { ZodSchema } from 'zod'
|
||||
import type { ValidationTargets } from 'hono'
|
||||
import { zValidator as zv } from '@hono/zod-validator'
|
||||
|
||||
export const zValidator = <
|
||||
T extends ZodSchema,
|
||||
Target extends keyof ValidationTargets
|
||||
>(
|
||||
export const zValidator = <T extends ZodSchema, Target extends keyof ValidationTargets>(
|
||||
target: Target,
|
||||
schema: T
|
||||
) =>
|
||||
zv(target, schema, (result, c) => {
|
||||
if (!result.success) {
|
||||
throw new HTTPException(400, { cause: result.error });
|
||||
throw new HTTPException(400, { cause: result.error })
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
// usage
|
||||
import { zValidator } from './validator-wrapper'
|
||||
|
|
Loading…
Reference in New Issue