@hestjs/core 0.1.8 → 0.1.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,387 +1,451 @@
1
- # HestJS 🚀
1
+ # @hestjs/core
2
2
 
3
- 一个基于 **Hono + Bun + TSyringe** 的现代化 TypeScript 后端框架,提供类似 NestJS 的开发体验,但具有更轻量和更高性能的特点。
3
+ <div align="center">
4
4
 
5
+ [![npm version](https://img.shields.io/npm/v/@hestjs/core.svg)](https://www.npmjs.com/package/@hestjs/core)
5
6
  [![TypeScript](https://img.shields.io/badge/TypeScript-5.x-blue.svg)](https://www.typescriptlang.org/)
6
- [![Bun](https://img.shields.io/badge/Bun-latest-orange.svg)](https://bun.sh/)
7
7
  [![Hono](https://img.shields.io/badge/Hono-4.x-green.svg)](https://hono.dev/)
8
- [![License](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
8
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
9
9
 
10
- ## ✨ 特性
10
+ </div>
11
11
 
12
- - 🎯 **装饰器驱动** - 使用装饰器定义控制器、服务、中间件
13
- - 💉 **依赖注入** - 基于 TSyringe 的完整 DI 容器,用户透明
14
- - 🏗️ **模块化架构** - 采用模块系统组织代码
15
- - ⚡ **高性能** - 基于 Hono 和 Bun 获得最佳性能
16
- - 🔒 **类型安全** - 完全的 TypeScript 支持
17
- - 🛡️ **验证系统** - 基于 TypeBox 的强大验证功能
18
- - 🔄 **拦截器** - 灵活的请求/响应拦截机制
19
- - 🚨 **异常处理** - 完善的异常过滤和处理系统
12
+ HestJS 核心包 - 基于 Hono 构建的现代化 TypeScript 后端库,提供装饰器驱动的开发体验和依赖注入系统。
20
13
 
21
- ## 🚀 快速开始
14
+ ## 🎯 核心理念
15
+
16
+ - **🔓 拒绝过度封装**:直接暴露原生 Hono 实例,保留所有底层功能
17
+ - **✈️ 零配置**:你看不到类似 `hestjs.config.ts`这样的配置文件,无需任何配置
18
+ - **🎯 装饰器驱动**:提供熟悉的 NestJS 风格开发体验
19
+ - **💉 轻量依赖注入**:基于 TSyringe 的简洁 DI 容器
20
+ - **⚡ 极致性能**:基于 Hono 和 Bun 的高性能运行时
22
21
 
23
- ### 安装
22
+ ## 📦 安装
24
23
 
25
24
  ```bash
26
- # 克隆项目
27
- git clone https://github.com/aqz236/hest.git
28
- cd HestJS
25
+ npm install @hestjs/core
26
+ #
27
+ yarn add @hestjs/core
28
+ # 或
29
+ bun add @hestjs/core
30
+ ```
31
+
32
+ ## 🚀 快速开始
29
33
 
30
- # 安装依赖
31
- bun install
34
+ ### 1. 创建基础应用
32
35
 
33
- # 构建包
34
- bun run build
36
+ 在此之前你应该在tsconfig中添加以下内容:
35
37
 
36
- # 运行示例应用
37
- cd apps/hest-demo
38
- bun run dev
38
+ ```json
39
+ {
40
+ "compilerOptions": {
41
+ ...
42
+ "experimentalDecorators": true,
43
+ "emitDecoratorMetadata": true,
44
+ "esModuleInterop": true
45
+ }
46
+ }
39
47
  ```
40
48
 
41
- ### 创建你的第一个应用
42
-
43
49
  ```typescript
44
- // app.controller.ts
45
- import { Controller, Get, Post, Body } from "@hestjs/core";
46
- import { IsString, IsEmail, IsNumber } from "@hestjs/validation";
50
+ import { Controller, Get, HestFactory, Module } from "@hestjs/core";
47
51
 
48
- export class CreateUserDto {
49
- @IsString({ minLength: 2, maxLength: 50 })
50
- name!: string;
52
+ @Controller("/")
53
+ export class WelcomeController {
54
+ @Get("/welcome")
55
+ async welcome() {
56
+ return "Welcome to HestJS!";
57
+ }
58
+ }
51
59
 
52
- @IsEmail()
53
- email!: string;
60
+ @Module({
61
+ controllers: [WelcomeController],
62
+ providers: [],
63
+ imports: [],
64
+ exports: [],
65
+ })
66
+ export class AppModule {}
67
+
68
+ async function bootstrap() {
69
+ const app = await HestFactory.create(AppModule);
70
+ const hono = app.hono();
54
71
 
55
- @IsNumber({ minimum: 0, maximum: 120 })
56
- age!: number;
72
+ Bun.serve({
73
+ port: 3000,
74
+ fetch: hono.fetch,
75
+ });
57
76
  }
58
77
 
59
- @Controller("/api")
60
- export class AppController {
61
- @Get("/users")
62
- getUsers() {
63
- return { users: [] };
78
+ bootstrap();
79
+ ```
80
+
81
+ ### 2. 定义控制器
82
+
83
+ ```typescript
84
+ import { Controller, Get, Post, Context, Body, Param } from "@hestjs/core";
85
+ import type { HestContext } from "@hestjs/core";
86
+
87
+ @Controller("/users")
88
+ export class UsersController {
89
+ @Get("/")
90
+ async getAllUsers() {
91
+ return { message: "Get all users" };
64
92
  }
65
93
 
66
- @Post("/users")
67
- createUser(@Body(CreateUserDto) createUserDto: CreateUserDto) {
68
- // createUserDto 已经过验证和类型转换
69
- return { success: true, data: createUserDto };
94
+ @Get("/:id")
95
+ async getUser(@Param("id") id: string, @Context() c: HestContext) {
96
+ return { id, message: `Get user ${id}` };
97
+ }
98
+
99
+ @Post("/")
100
+ async createUser(@Body() body: any, @Context() c: HestContext) {
101
+ return { message: "User created", data: body };
70
102
  }
71
103
  }
72
104
  ```
73
105
 
106
+ ### 3. 创建模块
107
+
74
108
  ```typescript
75
- // app.module.ts
76
109
  import { Module } from "@hestjs/core";
77
- import { AppController } from "./app.controller";
110
+ import { UsersController } from "./users.controller";
111
+ import { UsersService } from "./users.service";
78
112
 
79
113
  @Module({
80
- controllers: [AppController],
114
+ controllers: [UsersController],
115
+ providers: [UsersService],
116
+ exports: [UsersService],
81
117
  })
82
- export class AppModule {}
118
+ export class UsersModule {}
83
119
  ```
84
120
 
85
- ```typescript
86
- // main.ts
87
- import { HestFactory } from "@hestjs/core";
88
- import { ValidationInterceptor } from "@hestjs/validation";
89
- import { AppModule } from "./app.module";
121
+ ### 4. 创建服务
90
122
 
91
- async function bootstrap() {
92
- const app = await HestFactory.create(AppModule);
123
+ ```typescript
124
+ import { injectable } from "@hestjs/core";
93
125
 
94
- // 启用全局验证
95
- app.useGlobalInterceptors(new ValidationInterceptor());
126
+ @injectable()
127
+ export class UsersService {
128
+ findAll() {
129
+ return [
130
+ { id: 1, name: "John" },
131
+ { id: 2, name: "Jane" },
132
+ ];
133
+ }
96
134
 
97
- await app.listen(3000);
98
- console.log("🚀 Application is running on: http://localhost:3000");
135
+ findOne(id: number) {
136
+ return { id, name: `User ${id}` };
137
+ }
99
138
  }
100
-
101
- bootstrap();
102
139
  ```
103
140
 
104
- ## 📁 项目结构
141
+ ## 🏗️ 架构概览
142
+
143
+ ### 核心模块
144
+
145
+ HestJS Core 包含以下主要模块:
105
146
 
106
147
  ```
107
- packages/
108
- ├── core/ # 核心框架包
109
- │ ├── decorators/ # 装饰器定义
110
- ├── interfaces/ # 核心接口
111
- ├── application/ # 应用核心
112
- └── exceptions/ # 异常处理
113
- ├── validation/ # 验证模块
114
- │ ├── decorators/ # 验证装饰器
115
- ├── pipes/ # 验证管道
116
- │ └── interceptors/ # 验证拦截器
117
- └── ...
148
+ @hestjs/core/
149
+ ├── application/ # 应用工厂和实例
150
+ │ ├── HestFactory # 应用工厂
151
+ └── HestApplicationInstance # 应用实例
152
+ ├── decorators/ # 装饰器系统
153
+ ├── @Controller # 控制器装饰器
154
+ ├── @Module # 模块装饰器
155
+ │ ├── @injectable # 可注入装饰器
156
+ └── 路由装饰器 # @Get, @Post, @Put, @Delete, @Patch
157
+ ├── container/ # 依赖注入容器
158
+ ├── router/ # 路由系统
159
+ ├── exceptions/ # 异常处理
160
+ ├── interceptors/ # 拦截器
161
+ ├── interfaces/ # 类型定义
162
+ └── utils/ # 工具函数
118
163
  ```
119
164
 
120
- ## 🎯 核心概念
165
+ ## 📚 API 参考
166
+
167
+ ### 🏭 应用工厂
168
+
169
+ #### `HestFactory.create(moduleClass)`
121
170
 
122
- ### 控制器 (Controllers)
171
+ 创建应用实例的静态方法。
123
172
 
124
173
  ```typescript
125
- @Controller("/users")
126
- export class UserController {
127
- @Get("/")
128
- findAll() {
129
- return { users: [] };
130
- }
174
+ import { HestFactory } from "@hestjs/core";
175
+ import { AppModule } from "./app.module";
131
176
 
132
- @Get("/:id")
133
- findOne(@Param("id") id: string) {
134
- return { user: { id } };
135
- }
177
+ const app = await HestFactory.create(AppModule);
178
+ ```
136
179
 
137
- @Post("/")
138
- create(@Body(CreateUserDto) createUserDto: CreateUserDto) {
139
- return { success: true };
140
- }
180
+ ### 🎮 控制器装饰器
181
+
182
+ #### `@Controller(path?: string)`
183
+
184
+ 定义控制器类和基础路径。
185
+
186
+ ```typescript
187
+ @Controller("/api/users")
188
+ export class UsersController {
189
+ // 控制器方法
141
190
  }
142
191
  ```
143
192
 
144
- ### 服务和依赖注入 (Services & DI)
193
+ ### 🛣️ 路由装饰器
145
194
 
146
- ```typescript
147
- @Injectable()
148
- export class UserService {
149
- async findAll() {
150
- return [];
151
- }
195
+ #### HTTP 方法装饰器
152
196
 
153
- async create(userData: any) {
154
- // 创建用户逻辑
155
- return userData;
156
- }
197
+ - `@Get(path?: string)` - GET 请求
198
+ - `@Post(path?: string)` - POST 请求
199
+ - `@Put(path?: string)` - PUT 请求
200
+ - `@Delete(path?: string)` - DELETE 请求
201
+ - `@Patch(path?: string)` - PATCH 请求
202
+
203
+ ```typescript
204
+ @Controller('/users')
205
+ export class UsersController {
206
+ @Get('/') // GET /users/
207
+ @Get('/:id') // GET /users/:id
208
+ @Post('/') // POST /users/
209
+ @Put('/:id') // PUT /users/:id
210
+ @Delete('/:id') // DELETE /users/:id
211
+ @Patch('/:id') // PATCH /users/:id
157
212
  }
213
+ ```
158
214
 
159
- @Controller("/users")
160
- export class UserController {
161
- constructor(private readonly userService: UserService) {}
215
+ ### 📥 参数装饰器
162
216
 
163
- @Get("/")
164
- async findAll() {
165
- return await this.userService.findAll();
166
- }
217
+ #### `@Context()`
218
+
219
+ 获取完整的 Hono Context 对象。
220
+
221
+ ```typescript
222
+ @Get('/')
223
+ async getUsers(@Context() c: HestContext) {
224
+ // 访问所有 Hono Context 功能
225
+ const userAgent = c.req.header('User-Agent');
226
+ return c.json({ message: 'Hello' });
167
227
  }
168
228
  ```
169
229
 
170
- ### 验证系统 (Validation)
230
+ #### `@Body()`
171
231
 
172
- #### 基础验证装饰器
232
+ 获取请求体数据。
173
233
 
174
234
  ```typescript
175
- export class CreateUserDto {
176
- @IsString({ minLength: 2, maxLength: 50 })
177
- name!: string;
235
+ @Post('/')
236
+ async createUser(@Body() userData: CreateUserDto) {
237
+ return userData;
238
+ }
239
+ ```
178
240
 
179
- @IsEmail()
180
- email!: string;
241
+ #### `@Param(key?: string)`
181
242
 
182
- @IsNumber({ minimum: 18, maximum: 100 })
183
- age!: number;
243
+ 获取路径参数。
184
244
 
185
- @IsOptional()
186
- @IsString()
187
- bio?: string;
245
+ ```typescript
246
+ @Get('/:id')
247
+ async getUser(@Param('id') id: string) {
248
+ return { id };
188
249
  }
189
250
  ```
190
251
 
191
- #### 自定义验证 (TypeBox API)
252
+ #### `@Query(key?: string)`
253
+
254
+ 获取查询参数。
192
255
 
193
256
  ```typescript
194
- import { Type } from "@sinclair/typebox";
195
- import { Custom, CommonValidators, SchemaFactory } from "@hestjs/validation";
196
-
197
- export class AdvancedDto {
198
- // 使用 TypeBox API 自定义验证
199
- @Custom(
200
- Type.String({
201
- minLength: 3,
202
- maxLength: 20,
203
- pattern: "^[a-zA-Z0-9_]+$",
204
- })
205
- )
206
- username!: string;
207
-
208
- // 使用联合类型
209
- @Custom(
210
- Type.Union([
211
- Type.Literal("admin"),
212
- Type.Literal("user"),
213
- Type.Literal("guest"),
214
- ])
215
- )
216
- role!: "admin" | "user" | "guest";
217
-
218
- // 使用常用验证器
219
- @CommonValidators.UUID()
220
- userId!: string;
221
-
222
- // 使用便捷构建器
223
- @Custom(SchemaFactory.chinesePhoneNumber())
224
- phoneNumber!: string;
225
-
226
- // 复杂对象验证
227
- @Custom(
228
- Type.Object({
229
- lat: Type.Number({ minimum: -90, maximum: 90 }),
230
- lng: Type.Number({ minimum: -180, maximum: 180 }),
231
- })
232
- )
233
- location!: { lat: number; lng: number };
257
+ @Get('/')
258
+ async getUsers(@Query('page') page: string) {
259
+ return { page };
234
260
  }
235
261
  ```
236
262
 
237
- ### 拦截器 (Interceptors)
263
+ #### `@Header(key?: string)`
264
+
265
+ 获取请求头。
238
266
 
239
267
  ```typescript
240
- import { Interceptor, ExecutionContext, CallHandler } from "@hestjs/core";
268
+ @Get('/')
269
+ async getUsers(@Header('authorization') auth: string) {
270
+ return { auth };
271
+ }
272
+ ```
241
273
 
242
- export class LoggingInterceptor implements Interceptor {
243
- intercept(context: ExecutionContext, next: CallHandler) {
244
- console.log("Before...");
274
+ ### 🏗️ 模块系统
245
275
 
246
- const now = Date.now();
247
- return next.handle().then(() => {
248
- console.log(`After... ${Date.now() - now}ms`);
249
- });
250
- }
276
+ #### `@Module(options)`
277
+
278
+ 定义模块和依赖关系。
279
+
280
+ ```typescript
281
+ interface ModuleOptions {
282
+ imports?: any[]; // 导入的模块
283
+ controllers?: any[]; // 控制器
284
+ providers?: any[]; // 提供者(服务)
285
+ exports?: any[]; // 导出的提供者
251
286
  }
252
287
 
253
- // 使用拦截器
254
- app.useGlobalInterceptors(new LoggingInterceptor());
288
+ @Module({
289
+ imports: [DatabaseModule],
290
+ controllers: [UsersController],
291
+ providers: [UsersService],
292
+ exports: [UsersService],
293
+ })
294
+ export class UsersModule {}
255
295
  ```
256
296
 
257
- ### 异常处理 (Exception Handling)
297
+ ### 💉 依赖注入
258
298
 
259
- ```typescript
260
- import {
261
- HttpException,
262
- NotFoundException,
263
- BadRequestException,
264
- } from "@hestjs/core";
299
+ #### `@injectable()`
265
300
 
266
- @Controller("/users")
267
- export class UserController {
268
- @Get("/:id")
269
- findOne(@Param("id") id: string) {
270
- const user = this.findUserById(id);
271
- if (!user) {
272
- throw new NotFoundException(`User with id ${id} not found`);
273
- }
274
- return user;
275
- }
301
+ 标记类为可注入的服务。
276
302
 
277
- @Post("/")
278
- create(@Body() userData: any) {
279
- if (!userData.email) {
280
- throw new BadRequestException("Email is required");
281
- }
282
- return this.createUser(userData);
283
- }
303
+ ```typescript
304
+ @injectable()
305
+ export class UsersService {
306
+ constructor(private readonly databaseService: DatabaseService) {}
284
307
  }
285
308
  ```
286
309
 
287
- ## 🔧 开发状态
310
+ ### 🔄 拦截器和过滤器
288
311
 
289
- ### ✅ 已完成功能
312
+ #### 全局拦截器
290
313
 
291
- - **Phase 1: 核心基础设施** ✅
292
- - 装饰器系统 (`@Controller`, `@Injectable`, `@Module`, 路由装饰器)
293
- - 依赖注入容器 (基于 TSyringe)
294
- - 应用工厂 (`HestFactory.create()`)
295
- - 路由系统和参数注入
314
+ ```typescript
315
+ const app = await HestFactory.create(AppModule);
296
316
 
297
- - **Phase 2: 中间件和异常处理** ✅
298
- - 异常处理系统 (HttpException, 异常过滤器)
299
- - 拦截器系统 (Interceptor, ExecutionContext)
300
- - 全局拦截器和异常过滤器支持
317
+ // 添加全局拦截器
318
+ app.useGlobalInterceptors(new ValidationInterceptor());
319
+ app.useGlobalInterceptors(new ResponseInterceptor());
320
+ ```
301
321
 
302
- - **Phase 3: 验证系统** ✅
303
- - 基于 TypeBox 的验证装饰器
304
- - @Custom() 装饰器支持完整 TypeBox API
305
- - ValidationInterceptor 自动验证
306
- - SchemaFactory 和 CommonValidators
307
- - 详细验证错误处理
322
+ #### 全局异常过滤器
308
323
 
309
- ### 🚧 开发中
324
+ ```typescript
325
+ const app = await HestFactory.create(AppModule);
310
326
 
311
- - **Phase 4: 配置和日志系统**
312
- - **Phase 5: 高级拦截器和管道**
313
- - **Phase 6: CLI 工具**
327
+ // 添加全局异常过滤器
328
+ app.useGlobalFilters(new HttpExceptionFilter());
329
+ ```
314
330
 
315
- ## 📊 性能
331
+ ### 🌐 直接访问 Hono
316
332
 
317
- 基于 Bun 运行时和 Hono 框架,HestJS 提供了卓越的性能:
333
+ HestJS 不会封装 Hono,你可以直接使用所有 Hono 功能:
318
334
 
319
- - 🚀 **快速启动** - 得益于 Bun 的快速启动时间
320
- - **高吞吐量** - Hono 的高效路由和中间件系统
321
- - 💾 **低内存占用** - 轻量级架构设计
322
- - 🔧 **编译时优化** - TypeScript 装饰器元数据预处理
335
+ ```typescript
336
+ const app = await HestFactory.create(AppModule);
337
+ const honoApp = app.hono();
338
+
339
+ // 使用 Hono 原生中间件
340
+ honoApp.use(cors());
341
+ honoApp.use("/api/*", async (c, next) => {
342
+ console.log(`${c.req.method} ${c.req.url}`);
343
+ await next();
344
+ });
345
+
346
+ // 添加自定义路由
347
+ honoApp.get("/health", (c) => c.text("OK"));
348
+ ```
323
349
 
324
- ## 🛠️ 开发
350
+ ## 🧪 类型系统
325
351
 
326
- ### 构建项目
352
+ ### HestContext
327
353
 
328
- ```bash
329
- # 安装依赖
330
- bun install
354
+ 提供完整的 Hono Context 类型安全:
331
355
 
332
- # 构建所有包
333
- bun run build
356
+ ```typescript
357
+ import type { HestContext } from '@hestjs/core';
334
358
 
335
- # 运行测试
336
- bun run test
359
+ @Get('/')
360
+ async handler(@Context() c: HestContext) {
361
+ // 完整的 Hono Context API
362
+ const method = c.req.method;
363
+ const url = c.req.url;
364
+ const headers = c.req.header();
337
365
 
338
- # 运行示例应用
339
- cd apps/hest-demo
340
- bun run dev
366
+ return c.json({ method, url });
367
+ }
341
368
  ```
342
369
 
343
- ### 测试验证功能
370
+ ## 🔮 未来路线图
344
371
 
345
- ```bash
346
- # 运行 Phase 3 验证测试
347
- bun test-phase3.ts
348
- ```
372
+ ### v0.2.x - 增强功能
349
373
 
350
- ## 📖 API 参考
374
+ - [ ] **中间件系统** - 完善的中间件装饰器支持
375
+ - [ ] **管道系统** - 数据转换和验证管道
376
+ - [ ] **守卫系统** - 路由级别的访问控制
377
+ - [ ] **元数据增强** - 更丰富的反射元数据支持
351
378
 
352
- ### 装饰器
379
+ ### v0.3.x - 性能优化
353
380
 
354
- - `@Controller(path?)` - 定义控制器
355
- - `@Injectable()` - 标记可注入服务
356
- - `@Module(options)` - 定义模块
357
- - `@Get(path?)`, `@Post(path?)`, `@Put(path?)`, `@Delete(path?)` - HTTP 路由
358
- - `@Body(dtoClass?)`, `@Param(key?)`, `@Query(key?)` - 参数注入
359
- - `@IsString()`, `@IsEmail()`, `@IsNumber()` - 基础验证
360
- - `@Custom(schema, options?)` - 自定义 TypeBox 验证
381
+ - [ ] **路由缓存** - 路由匹配性能优化
382
+ - [ ] **依赖注入优化** - 容器解析性能提升
383
+ - [ ] **热重载支持** - 开发环境下的热重载
384
+ - [ ] **构建优化** - 更小的打包体积
361
385
 
362
- ### 核心类
386
+ ### v0.4.x - 生态系统
363
387
 
364
- - `HestFactory` - 应用工厂
365
- - `HttpException` - HTTP 异常基类
366
- - `ValidationInterceptor` - 验证拦截器
367
- - `Interceptor` - 拦截器接口
368
- - `ExecutionContext` - 执行上下文
388
+ - [ ] **WebSocket 支持** - 实时通信功能
389
+ - [ ] **文件上传** - 内置文件处理能力
390
+ - [ ] **缓存系统** - 多级缓存支持
391
+ - [ ] **任务调度** - 定时任务和队列系统
392
+
393
+ ### v0.5.x - 企业级功能
394
+
395
+ - [ ] **微服务支持** - 服务发现和通信
396
+ - [ ] **配置管理** - 环境配置和动态配置
397
+ - [ ] **健康检查** - 应用监控和诊断
398
+ - [ ] **链路追踪** - 分布式追踪支持
399
+
400
+ ### v1.0.x - 稳定版本
401
+
402
+ - [ ] **API 稳定** - 向后兼容的 API
403
+ - [ ] **完整文档** - 全面的使用指南
404
+ - [ ] **性能基准** - 与其他框架的对比
405
+ - [ ] **生产就绪** - 企业级部署支持
406
+
407
+ ## 📋 当前功能状态
408
+
409
+ ### ✅ 已实现功能
410
+
411
+ - [x] **应用工厂** - `HestFactory.create()`
412
+ - [x] **控制器系统** - `@Controller()` 装饰器
413
+ - [x] **路由装饰器** - `@Get()`, `@Post()`, `@Put()`, `@Delete()`, `@Patch()`
414
+ - [x] **参数装饰器** - `@Context()`, `@Body()`, `@Param()`, `@Query()`, `@Header()`
415
+ - [x] **模块系统** - `@Module()` 装饰器
416
+ - [x] **依赖注入** - 基于 TSyringe 的 DI 容器
417
+ - [x] **异常处理** - 基础异常过滤器
418
+ - [x] **拦截器** - 全局拦截器支持
419
+ - [x] **类型安全** - 完整的 TypeScript 支持
420
+ - [x] **Hono 集成** - 直接访问 Hono 实例
421
+
422
+ ### 🚧 开发中功能
423
+
424
+ - [ ] **装饰器中间件** - `@UseMiddleware()` 装饰器
425
+ - [ ] **路由守卫** - `@UseGuards()` 装饰器
426
+ - [ ] **数据管道** - `@UsePipes()` 装饰器
427
+ - [ ] **OpenAPI 集成** - 自动 API 文档生成
428
+
429
+ ## 💡 设计原则
430
+
431
+ 1. **最小封装** - 不隐藏底层框架的功能
432
+ 2. **类型安全** - 完整的 TypeScript 支持
433
+ 3. **性能优先** - 基于高性能的 Hono 和 Bun
434
+ 4. **开发体验** - 熟悉的装饰器语法
435
+ 5. **渐进式** - 可以逐步采用各种功能
369
436
 
370
437
  ## 🤝 贡献
371
438
 
372
- 欢迎贡献代码!请查看 [贡献指南](CONTRIBUTING.md) 了解详情。
439
+ 欢迎提交 Issue 和 Pull Request!
373
440
 
374
441
  ## 📄 许可证
375
442
 
376
443
  [MIT](LICENSE)
377
444
 
378
- ## 🔗 相关链接
379
-
380
- - [Hono](https://hono.dev/) - 快速、轻量级的 Web 框架
381
- - [Bun](https://bun.sh/) - 快速的 JavaScript 运行时
382
- - [TSyringe](https://github.com/microsoft/tsyringe) - 依赖注入容器
383
- - [TypeBox](https://github.com/sinclairzx81/typebox) - JSON Schema 类型构建器
384
-
385
445
  ---
386
446
 
387
- ⭐ 如果这个项目对你有帮助,请给个 Star!
447
+ **更多信息**:
448
+
449
+ - 📚 [完整文档](https://aqz236.github.io/hestjs-demo)
450
+ - 🎮 [示例项目](https://github.com/aqz236/hestjs-demo)
451
+ - 🐛 [问题反馈](https://github.com/aqz236/hest/issues)
@@ -11,5 +11,9 @@ export declare class HestFactory {
11
11
  * 初始化模块
12
12
  */
13
13
  private static initializeModule;
14
+ /**
15
+ * 递归收集所有模块的控制器
16
+ */
17
+ private static collectAllControllers;
14
18
  }
15
19
  //# sourceMappingURL=application-factory.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"application-factory.d.ts","sourceRoot":"","sources":["../../src/application/application-factory.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAG7D;;GAEG;AACH,qBAAa,WAAW;IACtB;;OAEG;WACU,MAAM,CAAC,WAAW,EAAE,GAAG,GAAG,OAAO,CAAC,uBAAuB,CAAC;IA0BvE;;OAEG;mBACkB,gBAAgB;CAgDtC"}
1
+ {"version":3,"file":"application-factory.d.ts","sourceRoot":"","sources":["../../src/application/application-factory.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAI7D;;GAEG;AACH,qBAAa,WAAW;IACtB;;OAEG;WACU,MAAM,CAAC,WAAW,EAAE,GAAG,GAAG,OAAO,CAAC,uBAAuB,CAAC;IA8BvE;;OAEG;mBACkB,gBAAgB;IAiDrC;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,qBAAqB;CA4BrC"}
@@ -6,6 +6,7 @@ const container_1 = require("../container/container");
6
6
  const metadata_scanner_1 = require("../metadata/metadata-scanner");
7
7
  const router_explorer_1 = require("../router/router-explorer");
8
8
  const hest_application_1 = require("./hest-application");
9
+ const application_hooks_1 = require("./application-hooks");
9
10
  const logger_1 = require("@hestjs/logger");
10
11
  /**
11
12
  * HestJS 应用工厂
@@ -27,10 +28,13 @@ class HestFactory {
27
28
  const routerExplorer = new router_explorer_1.RouterExplorer(app, container);
28
29
  routerExplorer.setGlobalFilters(appInstance.getGlobalFilters());
29
30
  routerExplorer.setGlobalInterceptors(appInstance.getGlobalInterceptors());
30
- const moduleMetadata = metadata_scanner_1.MetadataScanner.scanModule(moduleClass);
31
- if (moduleMetadata?.controllers) {
32
- routerExplorer.explore(moduleMetadata.controllers);
31
+ // 收集所有模块的控制器
32
+ const allControllers = HestFactory.collectAllControllers(moduleClass);
33
+ if (allControllers.length > 0) {
34
+ routerExplorer.explore(allControllers);
33
35
  }
36
+ // 执行所有注册的应用启动钩子
37
+ await application_hooks_1.ApplicationHooks.getInstance().executeHooks(container);
34
38
  return appInstance;
35
39
  }
36
40
  /**
@@ -42,15 +46,15 @@ class HestFactory {
42
46
  throw new Error(`Module metadata not found for ${moduleClass.name}`);
43
47
  }
44
48
  // 注册模块自身
45
- container.register(moduleClass, moduleClass);
49
+ container.register(moduleClass, moduleClass, 'module');
46
50
  // 注册提供者
47
51
  if (moduleMetadata.providers) {
48
52
  for (const provider of moduleMetadata.providers) {
49
53
  if (metadata_scanner_1.MetadataScanner.isInjectable(provider)) {
50
54
  // 注册类本身作为令牌
51
- container.register(provider, provider);
55
+ container.register(provider, provider, 'provider');
52
56
  // 同时注册类名字符串作为令牌,以支持 @Inject('ClassName') 语法
53
- container.register(provider.name, provider);
57
+ container.register(provider.name, provider, 'provider');
54
58
  }
55
59
  else {
56
60
  console.warn(`Provider ${provider.name} is not injectable, skipping registration`);
@@ -61,7 +65,7 @@ class HestFactory {
61
65
  if (moduleMetadata.controllers) {
62
66
  for (const controller of moduleMetadata.controllers) {
63
67
  if (metadata_scanner_1.MetadataScanner.isController(controller)) {
64
- container.register(controller, controller);
68
+ container.register(controller, controller, 'controller');
65
69
  }
66
70
  else {
67
71
  throw new Error(`${controller.name} is not a valid controller`);
@@ -76,6 +80,32 @@ class HestFactory {
76
80
  }
77
81
  logger_1.logger.info(`✅ Module ${moduleClass.name} initialized`);
78
82
  }
83
+ /**
84
+ * 递归收集所有模块的控制器
85
+ */
86
+ static collectAllControllers(moduleClass, visited = new Set()) {
87
+ // 防止循环依赖
88
+ if (visited.has(moduleClass)) {
89
+ return [];
90
+ }
91
+ visited.add(moduleClass);
92
+ const controllers = [];
93
+ const moduleMetadata = metadata_scanner_1.MetadataScanner.scanModule(moduleClass);
94
+ if (!moduleMetadata) {
95
+ return controllers;
96
+ }
97
+ // 收集当前模块的控制器
98
+ if (moduleMetadata.controllers) {
99
+ controllers.push(...moduleMetadata.controllers);
100
+ }
101
+ // 递归收集导入模块的控制器
102
+ if (moduleMetadata.imports) {
103
+ for (const importedModule of moduleMetadata.imports) {
104
+ controllers.push(...HestFactory.collectAllControllers(importedModule, visited));
105
+ }
106
+ }
107
+ return controllers;
108
+ }
79
109
  }
80
110
  exports.HestFactory = HestFactory;
81
111
  //# sourceMappingURL=application-factory.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"application-factory.js","sourceRoot":"","sources":["../../src/application/application-factory.ts"],"names":[],"mappings":";;;AAAA,+BAA4B;AAC5B,sDAAmD;AACnD,mEAA+D;AAC/D,+DAA2D;AAC3D,yDAA6D;AAC7D,2CAAwC;AAExC;;GAEG;AACH,MAAa,WAAW;IACtB;;OAEG;IACH,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,WAAgB;QAClC,aAAa;QACb,MAAM,GAAG,GAAG,IAAI,WAAI,EAAE,CAAC;QAEvB,WAAW;QACX,MAAM,SAAS,GAAG,qBAAS,CAAC,WAAW,EAAE,CAAC;QAE1C,QAAQ;QACR,MAAM,WAAW,CAAC,gBAAgB,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;QAE3D,SAAS;QACT,MAAM,WAAW,GAAG,IAAI,0CAAuB,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QAEhE,OAAO;QACP,MAAM,cAAc,GAAG,IAAI,gCAAc,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QAC1D,cAAc,CAAC,gBAAgB,CAAC,WAAW,CAAC,gBAAgB,EAAE,CAAC,CAAC;QAChE,cAAc,CAAC,qBAAqB,CAAC,WAAW,CAAC,qBAAqB,EAAE,CAAC,CAAC;QAE1E,MAAM,cAAc,GAAG,kCAAe,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;QAC/D,IAAI,cAAc,EAAE,WAAW,EAAE,CAAC;YAChC,cAAc,CAAC,OAAO,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC;QACrD,CAAC;QAED,OAAO,WAAW,CAAC;IACrB,CAAC;IAED;;OAEG;IACK,MAAM,CAAC,KAAK,CAAC,gBAAgB,CACnC,WAAgB,EAChB,SAAoB;QAEpB,MAAM,cAAc,GAAG,kCAAe,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;QAC/D,IAAI,CAAC,cAAc,EAAE,CAAC;YACpB,MAAM,IAAI,KAAK,CAAC,iCAAiC,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC;QACvE,CAAC;QAED,SAAS;QACT,SAAS,CAAC,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;QAE7C,QAAQ;QACR,IAAI,cAAc,CAAC,SAAS,EAAE,CAAC;YAC7B,KAAK,MAAM,QAAQ,IAAI,cAAc,CAAC,SAAS,EAAE,CAAC;gBAChD,IAAI,kCAAe,CAAC,YAAY,CAAC,QAAQ,CAAC,EAAE,CAAC;oBAC3C,YAAY;oBACZ,SAAS,CAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;oBACvC,4CAA4C;oBAC5C,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;gBAC9C,CAAC;qBAAM,CAAC;oBACN,OAAO,CAAC,IAAI,CACV,YAAY,QAAQ,CAAC,IAAI,2CAA2C,CACrE,CAAC;gBACJ,CAAC;YACH,CAAC;QACH,CAAC;QAED,QAAQ;QACR,IAAI,cAAc,CAAC,WAAW,EAAE,CAAC;YAC/B,KAAK,MAAM,UAAU,IAAI,cAAc,CAAC,WAAW,EAAE,CAAC;gBACpD,IAAI,kCAAe,CAAC,YAAY,CAAC,UAAU,CAAC,EAAE,CAAC;oBAC7C,SAAS,CAAC,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;gBAC7C,CAAC;qBAAM,CAAC;oBACN,MAAM,IAAI,KAAK,CAAC,GAAG,UAAU,CAAC,IAAI,4BAA4B,CAAC,CAAC;gBAClE,CAAC;YACH,CAAC;QACH,CAAC;QAED,UAAU;QACV,IAAI,cAAc,CAAC,OAAO,EAAE,CAAC;YAC3B,KAAK,MAAM,cAAc,IAAI,cAAc,CAAC,OAAO,EAAE,CAAC;gBACpD,MAAM,WAAW,CAAC,gBAAgB,CAAC,cAAc,EAAE,SAAS,CAAC,CAAC;YAChE,CAAC;QACH,CAAC;QAED,eAAM,CAAC,IAAI,CAAC,YAAY,WAAW,CAAC,IAAI,cAAc,CAAC,CAAC;IAC1D,CAAC;CACF;AAjFD,kCAiFC"}
1
+ {"version":3,"file":"application-factory.js","sourceRoot":"","sources":["../../src/application/application-factory.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * 应用启动钩子系统
3
+ *
4
+ * 这是一个通用的钩子系统,允许外部包注册自己的初始化逻辑
5
+ * 而不会让 core 包与特定的外部包产生耦合
6
+ */
7
+ export type ApplicationHook = (container: any) => Promise<void> | void;
8
+ /**
9
+ * 应用钩子管理器
10
+ */
11
+ export declare class ApplicationHooks {
12
+ private static instance;
13
+ private hooks;
14
+ private constructor();
15
+ static getInstance(): ApplicationHooks;
16
+ /**
17
+ * 注册应用启动钩子
18
+ */
19
+ registerHook(hook: ApplicationHook): void;
20
+ /**
21
+ * 执行所有注册的钩子
22
+ */
23
+ executeHooks(container: any): Promise<void>;
24
+ /**
25
+ * 清空所有钩子
26
+ */
27
+ clearHooks(): void;
28
+ }
29
+ //# sourceMappingURL=application-hooks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"application-hooks.d.ts","sourceRoot":"","sources":["../../src/application/application-hooks.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,MAAM,eAAe,GAAG,CAAC,SAAS,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;AAEvE;;GAEG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAmB;IAC1C,OAAO,CAAC,KAAK,CAAyB;IAEtC,OAAO;IAEP,MAAM,CAAC,WAAW,IAAI,gBAAgB;IAOtC;;OAEG;IACH,YAAY,CAAC,IAAI,EAAE,eAAe,GAAG,IAAI;IAIzC;;OAEG;IACG,YAAY,CAAC,SAAS,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IAUjD;;OAEG;IACH,UAAU,IAAI,IAAI;CAGnB"}
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ /**
3
+ * 应用启动钩子系统
4
+ *
5
+ * 这是一个通用的钩子系统,允许外部包注册自己的初始化逻辑
6
+ * 而不会让 core 包与特定的外部包产生耦合
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.ApplicationHooks = void 0;
10
+ /**
11
+ * 应用钩子管理器
12
+ */
13
+ class ApplicationHooks {
14
+ static instance;
15
+ hooks = [];
16
+ constructor() { }
17
+ static getInstance() {
18
+ if (!ApplicationHooks.instance) {
19
+ ApplicationHooks.instance = new ApplicationHooks();
20
+ }
21
+ return ApplicationHooks.instance;
22
+ }
23
+ /**
24
+ * 注册应用启动钩子
25
+ */
26
+ registerHook(hook) {
27
+ this.hooks.push(hook);
28
+ }
29
+ /**
30
+ * 执行所有注册的钩子
31
+ */
32
+ async executeHooks(container) {
33
+ for (const hook of this.hooks) {
34
+ try {
35
+ await hook(container);
36
+ }
37
+ catch (error) {
38
+ console.warn('Failed to execute application hook:', error);
39
+ }
40
+ }
41
+ }
42
+ /**
43
+ * 清空所有钩子
44
+ */
45
+ clearHooks() {
46
+ this.hooks = [];
47
+ }
48
+ }
49
+ exports.ApplicationHooks = ApplicationHooks;
50
+ //# sourceMappingURL=application-hooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"application-hooks.js","sourceRoot":"","sources":["../../src/application/application-hooks.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;AAIH;;GAEG;AACH,MAAa,gBAAgB;IACnB,MAAM,CAAC,QAAQ,CAAmB;IAClC,KAAK,GAAsB,EAAE,CAAC;IAEtC,gBAAuB,CAAC;IAExB,MAAM,CAAC,WAAW;QAChB,IAAI,CAAC,gBAAgB,CAAC,QAAQ,EAAE,CAAC;YAC/B,gBAAgB,CAAC,QAAQ,GAAG,IAAI,gBAAgB,EAAE,CAAC;QACrD,CAAC;QACD,OAAO,gBAAgB,CAAC,QAAQ,CAAC;IACnC,CAAC;IAED;;OAEG;IACH,YAAY,CAAC,IAAqB;QAChC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACxB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,YAAY,CAAC,SAAc;QAC/B,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YAC9B,IAAI,CAAC;gBACH,MAAM,IAAI,CAAC,SAAS,CAAC,CAAC;YACxB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,IAAI,CAAC,qCAAqC,EAAE,KAAK,CAAC,CAAC;YAC7D,CAAC;QACH,CAAC;IACH,CAAC;IAED;;OAEG;IACH,UAAU;QACR,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;IAClB,CAAC;CACF;AAvCD,4CAuCC"}
@@ -1,3 +1,4 @@
1
- export * from './hest-application';
2
1
  export * from './application-factory';
2
+ export * from './hest-application';
3
+ export * from './application-hooks';
3
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/application/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/application/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC"}
@@ -14,6 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- __exportStar(require("./hest-application"), exports);
18
17
  __exportStar(require("./application-factory"), exports);
18
+ __exportStar(require("./hest-application"), exports);
19
+ __exportStar(require("./application-hooks"), exports);
19
20
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/application/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,qDAAmC;AACnC,wDAAsC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/application/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,wDAAsC;AACtC,qDAAmC;AACnC,sDAAoC"}
@@ -1,16 +1,37 @@
1
1
  import "reflect-metadata";
2
2
  import { DependencyContainer, InjectionToken } from "tsyringe";
3
+ import type { InjectableMetadata, ControllerMetadata, ModuleMetadata } from "../interfaces/metadata";
4
+ import type { ControllerConstructor } from "../interfaces/router";
5
+ import { Scope } from "../utils/constants";
3
6
  declare global {
4
7
  namespace Reflect {
5
8
  function getMetadata(key: any, target: any, propertyKey?: string | symbol): any;
6
9
  }
7
10
  }
11
+ /**
12
+ * 逻辑容器项类型
13
+ */
14
+ export interface LogicalContainerItem<T = any> {
15
+ token: InjectionToken<T>;
16
+ provider: T;
17
+ type: 'controller' | 'provider' | 'module';
18
+ metadata?: ControllerMetadata | InjectableMetadata | ModuleMetadata;
19
+ scope?: Scope;
20
+ }
21
+ /**
22
+ * 控制器容器项特化类型
23
+ */
24
+ export interface ControllerContainerItem extends LogicalContainerItem<ControllerConstructor> {
25
+ type: 'controller';
26
+ metadata?: ControllerMetadata;
27
+ }
8
28
  /**
9
29
  * HestJS DI 容器封装
10
30
  */
11
31
  export declare class Container {
12
32
  private static instance;
13
33
  private container;
34
+ private logicalContainer;
14
35
  constructor();
15
36
  /**
16
37
  * 获取容器单例
@@ -19,7 +40,7 @@ export declare class Container {
19
40
  /**
20
41
  * 注册服务
21
42
  */
22
- register<T>(token: InjectionToken<T>, provider: any): void;
43
+ register<T>(token: InjectionToken<T>, provider: any, type?: 'controller' | 'provider' | 'module'): void;
23
44
  /**
24
45
  * 注册实例
25
46
  */
@@ -44,5 +65,21 @@ export declare class Container {
44
65
  * 获取底层容器实例
45
66
  */
46
67
  getContainer(): DependencyContainer;
68
+ /**
69
+ * 获取逻辑容器中的所有项
70
+ */
71
+ getLogicalContainer(): Map<InjectionToken<any>, LogicalContainerItem>;
72
+ /**
73
+ * 获取指定类型的所有项
74
+ */
75
+ getItemsByType(type: 'controller' | 'provider' | 'module'): LogicalContainerItem[];
76
+ /**
77
+ * 获取所有控制器
78
+ */
79
+ getAllControllers(): ControllerContainerItem[];
80
+ /**
81
+ * 提取元数据信息
82
+ */
83
+ private extractMetadata;
47
84
  }
48
85
  //# sourceMappingURL=container.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"container.d.ts","sourceRoot":"","sources":["../../src/container/container.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAC1B,OAAO,EACL,mBAAmB,EACnB,cAAc,EAEf,MAAM,UAAU,CAAC;AAKlB,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,OAAO,CAAC;QAChB,SAAS,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,GAAG,CAAC;KACjF;CACF;AAED;;GAEG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAY;IACnC,OAAO,CAAC,SAAS,CAAsB;;IAMvC;;OAEG;IACH,MAAM,CAAC,WAAW,IAAI,SAAS;IAO/B;;OAEG;IACH,QAAQ,CAAC,CAAC,EAAE,KAAK,EAAE,cAAc,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,GAAG,GAAG,IAAI;IAgB1D;;OAEG;IACH,gBAAgB,CAAC,CAAC,EAAE,KAAK,EAAE,cAAc,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI;IAIhE;;OAEG;IACH,OAAO,CAAC,CAAC,EAAE,KAAK,EAAE,cAAc,CAAC,CAAC,CAAC,GAAG,CAAC;IAIvC;;OAEG;IACH,YAAY,CAAC,CAAC,EAAE,KAAK,EAAE,cAAc,CAAC,CAAC,CAAC,GAAG,OAAO;IAIlD;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb;;OAEG;IACH,WAAW,IAAI,SAAS;IAMxB;;OAEG;IACH,YAAY,IAAI,mBAAmB;CAGpC"}
1
+ {"version":3,"file":"container.d.ts","sourceRoot":"","sources":["../../src/container/container.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAC1B,OAAO,EACL,mBAAmB,EACnB,cAAc,EAEf,MAAM,UAAU,CAAC;AAClB,OAAO,KAAK,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACrG,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAClE,OAAO,EAAiB,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAG1D,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,OAAO,CAAC;QAChB,SAAS,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,GAAG,CAAC;KACjF;CACF;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB,CAAC,CAAC,GAAG,GAAG;IAC3C,KAAK,EAAE,cAAc,CAAC,CAAC,CAAC,CAAC;IACzB,QAAQ,EAAE,CAAC,CAAC;IACZ,IAAI,EAAE,YAAY,GAAG,UAAU,GAAG,QAAQ,CAAC;IAC3C,QAAQ,CAAC,EAAE,kBAAkB,GAAG,kBAAkB,GAAG,cAAc,CAAC;IACpE,KAAK,CAAC,EAAE,KAAK,CAAC;CACf;AAED;;GAEG;AACH,MAAM,WAAW,uBAAwB,SAAQ,oBAAoB,CAAC,qBAAqB,CAAC;IAC1F,IAAI,EAAE,YAAY,CAAC;IACnB,QAAQ,CAAC,EAAE,kBAAkB,CAAC;CAC/B;AAED;;GAEG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAY;IACnC,OAAO,CAAC,SAAS,CAAsB;IACvC,OAAO,CAAC,gBAAgB,CAA6D;;IAMrF;;OAEG;IACH,MAAM,CAAC,WAAW,IAAI,SAAS;IAO/B;;OAEG;IACH,QAAQ,CAAC,CAAC,EAAE,KAAK,EAAE,cAAc,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,IAAI,GAAE,YAAY,GAAG,UAAU,GAAG,QAAqB,GAAG,IAAI;IA0BnH;;OAEG;IACH,gBAAgB,CAAC,CAAC,EAAE,KAAK,EAAE,cAAc,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI;IAIhE;;OAEG;IACH,OAAO,CAAC,CAAC,EAAE,KAAK,EAAE,cAAc,CAAC,CAAC,CAAC,GAAG,CAAC;IAIvC;;OAEG;IACH,YAAY,CAAC,CAAC,EAAE,KAAK,EAAE,cAAc,CAAC,CAAC,CAAC,GAAG,OAAO;IAIlD;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb;;OAEG;IACH,WAAW,IAAI,SAAS;IAMxB;;OAEG;IACH,YAAY,IAAI,mBAAmB;IAInC;;OAEG;IACH,mBAAmB,IAAI,GAAG,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE,oBAAoB,CAAC;IAIrE;;OAEG;IACH,cAAc,CAAC,IAAI,EAAE,YAAY,GAAG,UAAU,GAAG,QAAQ,GAAG,oBAAoB,EAAE;IAIlF;;OAEG;IACH,iBAAiB,IAAI,uBAAuB,EAAE;IAI9C;;OAEG;IACH,OAAO,CAAC,eAAe;CAYxB"}
@@ -10,6 +10,7 @@ const constants_1 = require("../utils/constants");
10
10
  class Container {
11
11
  static instance;
12
12
  container;
13
+ logicalContainer = new Map();
13
14
  constructor() {
14
15
  this.container = tsyringe_1.container.createChildContainer();
15
16
  }
@@ -25,8 +26,17 @@ class Container {
25
26
  /**
26
27
  * 注册服务
27
28
  */
28
- register(token, provider) {
29
+ register(token, provider, type = 'provider') {
29
30
  const metadata = Reflect.getMetadata(constants_1.METADATA_KEYS.INJECTABLE, provider) || {};
31
+ // 保存到逻辑容器
32
+ const logicalItem = {
33
+ token,
34
+ provider,
35
+ type,
36
+ metadata: this.extractMetadata(provider, type),
37
+ scope: metadata.scope
38
+ };
39
+ this.logicalContainer.set(token, logicalItem);
30
40
  switch (metadata.scope) {
31
41
  case constants_1.Scope.SINGLETON:
32
42
  this.container.registerSingleton(token, provider);
@@ -76,6 +86,39 @@ class Container {
76
86
  getContainer() {
77
87
  return this.container;
78
88
  }
89
+ /**
90
+ * 获取逻辑容器中的所有项
91
+ */
92
+ getLogicalContainer() {
93
+ return this.logicalContainer;
94
+ }
95
+ /**
96
+ * 获取指定类型的所有项
97
+ */
98
+ getItemsByType(type) {
99
+ return Array.from(this.logicalContainer.values()).filter(item => item.type === type);
100
+ }
101
+ /**
102
+ * 获取所有控制器
103
+ */
104
+ getAllControllers() {
105
+ return this.getItemsByType('controller');
106
+ }
107
+ /**
108
+ * 提取元数据信息
109
+ */
110
+ extractMetadata(provider, type) {
111
+ switch (type) {
112
+ case 'controller':
113
+ return Reflect.getMetadata(constants_1.METADATA_KEYS.CONTROLLER, provider);
114
+ case 'module':
115
+ return Reflect.getMetadata(constants_1.METADATA_KEYS.MODULE, provider);
116
+ case 'provider':
117
+ return Reflect.getMetadata(constants_1.METADATA_KEYS.INJECTABLE, provider);
118
+ default:
119
+ return null;
120
+ }
121
+ }
79
122
  }
80
123
  exports.Container = Container;
81
124
  //# sourceMappingURL=container.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"container.js","sourceRoot":"","sources":["../../src/container/container.ts"],"names":[],"mappings":";;;AAAA,4BAA0B;AAC1B,uCAIkB;AAElB,kDAA0D;AAS1D;;GAEG;AACH,MAAa,SAAS;IACZ,MAAM,CAAC,QAAQ,CAAY;IAC3B,SAAS,CAAsB;IAEvC;QACE,IAAI,CAAC,SAAS,GAAG,oBAAiB,CAAC,oBAAoB,EAAE,CAAC;IAC5D,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,WAAW;QAChB,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAC;YACxB,SAAS,CAAC,QAAQ,GAAG,IAAI,SAAS,EAAE,CAAC;QACvC,CAAC;QACD,OAAO,SAAS,CAAC,QAAQ,CAAC;IAC5B,CAAC;IAED;;OAEG;IACH,QAAQ,CAAI,KAAwB,EAAE,QAAa;QACjD,MAAM,QAAQ,GACZ,OAAO,CAAC,WAAW,CAAC,yBAAa,CAAC,UAAU,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC;QAEhE,QAAQ,QAAQ,CAAC,KAAK,EAAE,CAAC;YACvB,KAAK,iBAAK,CAAC,SAAS;gBAClB,IAAI,CAAC,SAAS,CAAC,iBAAiB,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;gBAClD,MAAM;YACR,KAAK,iBAAK,CAAC,SAAS;gBAClB,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAC;gBACvD,MAAM;YACR;gBACE,IAAI,CAAC,SAAS,CAAC,iBAAiB,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;QACtD,CAAC;IACH,CAAC;IAED;;OAEG;IACH,gBAAgB,CAAI,KAAwB,EAAE,QAAW;QACvD,IAAI,CAAC,SAAS,CAAC,gBAAgB,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IACnD,CAAC;IAED;;OAEG;IACH,OAAO,CAAI,KAAwB;QACjC,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IACvC,CAAC;IAED;;OAEG;IACH,YAAY,CAAI,KAAwB;QACtC,OAAO,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;IAC5C,CAAC;IAED;;OAEG;IACH,KAAK;QACH,IAAI,CAAC,SAAS,CAAC,cAAc,EAAE,CAAC;IAClC,CAAC;IAED;;OAEG;IACH,WAAW;QACT,MAAM,KAAK,GAAG,IAAI,SAAS,EAAE,CAAC;QAC9B,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,oBAAoB,EAAE,CAAC;QACxD,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;OAEG;IACH,YAAY;QACV,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;CACF;AAhFD,8BAgFC"}
1
+ {"version":3,"file":"container.js","sourceRoot":"","sources":["../../src/container/container.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,4 @@
1
- export * from './container';
2
- export * from './injection-token';
1
+ export * from "./container";
2
+ export * from "./injection-token";
3
+ export type { LogicalContainerItem, ControllerContainerItem } from "./container";
3
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/container/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/container/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,mBAAmB,CAAC;AAClC,YAAY,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hestjs/core",
3
- "version": "0.1.8",
3
+ "version": "0.1.10",
4
4
  "description": "HestJS Core Framework - A TypeScript framework built on Hono with dependency injection and decorators",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",