扩展上下文
Elysia 提供了一个上下文,它配备了小工具,帮助您入门。
您可以使用以下方式扩展 Elysia 的上下文:
Decorate
单例,且不可变的属性,所有请求共享。
typescript
import { Elysia } from 'elysia'
class Logger {
log(value: string) {
console.log(value)
}
}
new Elysia()
.decorate('logger', new Logger())
.get('/', ({ logger }) => {
logger.log('hi')
return 'hi'
})装饰后的值将在上下文中作为只读属性可用,详见 装饰(Decorate)。
State
一个可变的引用,所有请求共享。
typescript
import { Elysia } from 'elysia'
new Elysia()
.state('count', 0)
.get('/', ({ store }) => {
store.count++
return store.count
})状态将在每个请求共享的 context.store 中可用,详见 状态(State)。
Resolve / Derive
装饰(Decorate) 的值注册为单例。而 解析(Resolve) 和 派生(Derive) 允许您为每个请求抽象一个上下文值。
typescript
import { Elysia } from 'elysia'
new Elysia()
.derive(({ headers: { authorization } }) => ({
authorization
}))
.get('/', ({ authorization }) => authorization)任何返回的值都会在上下文中可用,除了状态(status),它会直接发送给客户端,并中止后续处理器。
两个 解析(resolve) 和 派生(derive) 的语法相似,但使用场景不同。
在底层,两者是一个语法糖 (具有类型安全) 的生命周期:
由于 解析(resolve) 是基于 转换(transform) 的,这意味着数据尚未验证,也未进行强制转换/转换。如果你需要验证过的数据,建议使用 解析(resolve)。
作用域
状态(State) 和 装饰(Decorate) 是跨所有请求和实例共享的。解析(Resolve) 和 派生(Derive) 是每个请求的,且有封装作用域 (因为它们基于生命周期事件)。
如果您想使用来自插件的解析/派生值,您需要声明一个 作用域(Scope)。
typescript
import { Elysia } from 'elysia'
const plugin = new Elysia()
.derive(
{ as: 'scoped' }, // [!代码 ++]
({ headers: { authorization } }) => ({
authorization
})
)
new Elysia()
.use(plugin)
.get('/', ({ authorization }) => authorization)
.listen(3000)练习
让我们尝试扩展 Elysia 的上下文。
Show answer
我们可以使用 解析(resolve) 从查询中提取年龄。
typescript
import { Elysia, t } from 'elysia'
class Logger {
log(info: string) {
console.log(info)
}
}
new Elysia()
.decorate('logger', new Logger())
.onRequest(({ request, logger }) => {
logger.log(`请求地址 ${request.url}`)
})
.guard({
query: t.Optional(
t.Object({
age: t.Number({ min: 15 })
})
)
})
.resolve(({ query: { age }, status }) => {
if(!age) return status(401)
return { age }
})
.get('/profile', ({ age }) => age)
.listen(3000)