快速开始
环境要求
- Bun >= 1.2 —— 唯一运行时与包管理器
- TypeScript >= 5.8
- 每个
tsconfig.json必须显式打开experimentalDecorators
一个完整的应用
ts
import type { Context } from 'hono';
import { Inject, Module } from '@hestjs/core';
class Greeting {
hello(name: string): string {
return `hello ${name}`;
}
}
class GreetingController {
constructor(@Inject(Greeting) private readonly greeting: Greeting) {}
say(c: Context<Env, '/greet/:name'>): Response {
return c.json({ message: this.greeting.hello(c.req.param('name')) });
}
}
@Module({ providers: [Greeting, GreetingController] })
export class AppModule {}
export { GreetingController };ts
import { logger } from 'hono/logger';
import { createApp } from '@hestjs/core';
import { AppModule, GreetingController } from './app.module';
const app = createApp(AppModule, {
// middleware 在路由之前执行
middleware: [logger()],
// 路由就是 Hono 的路由
routes: (hono, resolve) => {
const greeting = resolve(GreetingController);
return hono
.get('/health', (c) => c.text('ok'))
.get('/greet/:name', (c) => greeting.say(c));
},
});
await app.start();
export type AppType = typeof app.hono;
export default { port: Number(process.env.PORT ?? 3000), fetch: app.hono.fetch };bash
bun run src/main.ts
curl http://localhost:3000/greet/ada # {"message":"hello ada"}
curl http://localhost:3000/health # ok完整版本见仓库里的 apps/example。
tsconfig 的两条要求
json
{
"extends": "../../packages/typescript-config/base.json",
"compilerOptions": {
"experimentalDecorators": true
}
}extends 必须用相对路径。 Bun 的转译器不解析包名形式的 extends (@hestjs/typescript-config/base.json),读不到 experimentalDecorators 就会把装饰器当成 stage-3 标准装饰器处理,元数据写到别处去了。
不需要
emitDecoratorMetadata。Bun 支持它,但 HestJS 不用它—— 依赖由@Inject()显式声明,不靠编译产物里的类型信息。
目录建议
src/
├── main.ts # 组装、注册路由、启动
├── app.module.ts # 根模块
├── users/
│ ├── users.module.ts
│ ├── users.controller.ts # 普通 provider,方法收 Context
│ ├── users.service.ts
│ └── users.repository.ts
└── shared/
└── database.module.ts模块跟着业务切,一个目录一个模块。apps/example 就是这么放的。