Skip to content
Our Sponsors
Open in Anthropic

title: 宏 - Elysia 教程 layout: false search: false authors: [] head: - - meta - property: 'og:title' content: 宏 - Elysia 教程

- - meta
  - name: 'description'
    content: 宏是可复用的路由选项。学习如何在 Elysia 中创建和使用宏来增强您的应用程序。

- - meta
  - property: 'og:description'
    content: 宏是可复用的路由选项。学习如何在 Elysia 中创建和使用宏来增强您的应用程序。

可复用的路由选项。

想象我们有这样一个身份验证检查:

typescript
import { Elysia, t } from 'elysia'

new Elysia()
	.post('/user', ({ body }) => body, {
		cookie: t.Object({
			session: t.String()
		}),
		beforeHandle({ cookie: { session } }) {
			if(!session.value) throw 'Unauthorized'
		}
	})
	.listen(3000)

如果我们有多个路由需要身份验证,我们必须一遍又一遍地重复相同的选项。

相反,我们可以使用宏来复用路由选项:

typescript
import { Elysia, t } from 'elysia'

new Elysia()
	.macro('auth', {
		cookie: t.Object({
			session: t.String()
		}),
		// 伪身份验证检查
		beforeHandle({ cookie: { session }, status }) {
			if(!session.value) return status(401)
		}
	})
	.post('/user', ({ body }) => body, {
		auth: true
	})
	.listen(3000)

auth 然后会内联 cookiebeforeHandle 到路由中。

简而言之, 是可复用的路由选项,类似于函数,但作为具有类型安全的路由选项。

任务

让我们定义一个宏来检查 body 是否是斐波那契数:

typescript
function isFibonacci(n: number) {
	let a = 0, b = 1
	while(b < n) [a, b] = [b, a + b]
	return b === n || n === 0
}
  1. Enforce Body Schema

    Let's enforce a schema as body for POST `/` endpoint that accept a number.

  2. Check if body is in Fibonacci Sequence

    We can use `isFibonacci` function to check if the number is in Fibonacci sequence. If it is not, return 418 status

Show answer
  1. 为了强制类型,我们可以在宏中定义一个 body 属性。
  2. 为了短路请求,我们可以使用 status 函数提前返回。
typescript
import { Elysia, t } from 'elysia'

function isPerfectSquare(x: number) {
    const s = Math.floor(Math.sqrt(x))
    return s * s === x
}

function isFibonacci(n: number) {
    if (n < 0) return false

    return isPerfectSquare(5 * n * n + 4) || isPerfectSquare(5 * n * n - 4)
}

new Elysia()
    .macro('isFibonacci', {
		body: t.Number(),
        beforeHandle({ body, status }) {
            if(!isFibonacci(body)) return status(418)
        }
    })
	.post('/fibo', ({ body }) => body, {
		isFibonacci: true
	})
    .listen(3000)
  • index.ts