create-hest-app 0.1.5 → 0.1.7

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.
Files changed (25) hide show
  1. package/package.json +1 -1
  2. package/templates/base/bun.lock +683 -0
  3. package/templates/base/package.json +2 -2
  4. package/templates/base/src/app.controller.ts +4 -2
  5. package/templates/base/src/common/middleware/index.ts +66 -0
  6. package/templates/base/src/index.ts +12 -13
  7. package/templates/base_scalar/bun.lock +1194 -0
  8. package/templates/base_scalar/package.json +3 -3
  9. package/templates/base_scalar/src/app.controller.ts +4 -2
  10. package/templates/base_scalar/src/common/middleware/index.ts +68 -0
  11. package/templates/base_scalar/src/index.ts +12 -13
  12. package/templates/cqrs/package.json +2 -2
  13. package/templates/cqrs/src/common/middleware/index.ts +73 -0
  14. package/templates/cqrs/src/index.ts +10 -13
  15. package/templates/cqrs_scalar/package.json +3 -3
  16. package/templates/cqrs_scalar/src/common/middleware/index.ts +59 -0
  17. package/templates/cqrs_scalar/src/index.ts +10 -13
  18. package/templates/base/src/common/filters/http-exception.filter.ts +0 -34
  19. package/templates/base/src/common/interceptors/response.interceptor.ts +0 -38
  20. package/templates/base_scalar/src/common/filters/http-exception.filter.ts +0 -34
  21. package/templates/base_scalar/src/common/interceptors/response.interceptor.ts +0 -38
  22. package/templates/cqrs/src/common/filters/http-exception.filter.ts +0 -34
  23. package/templates/cqrs/src/common/interceptors/response.interceptor.ts +0 -38
  24. package/templates/cqrs_scalar/src/common/filters/http-exception.filter.ts +0 -34
  25. package/templates/cqrs_scalar/src/common/interceptors/response.interceptor.ts +0 -37
@@ -30,10 +30,10 @@
30
30
  "author": "aqz236",
31
31
  "license": "MIT",
32
32
  "dependencies": {
33
- "@hestjs/core": "^0.1.10",
33
+ "@hestjs/core": "^0.2.0",
34
34
  "@hestjs/logger": "^0.1.5",
35
35
  "@hestjs/validation": "^0.1.5",
36
- "hono": "^4.8.9",
36
+ "hono": "^4.8.10",
37
37
  "reflect-metadata": "^0.2.2"
38
38
  },
39
39
  "devDependencies": {
@@ -1,4 +1,4 @@
1
- import { Controller, Get, NotFoundException, Param, Post } from "@hestjs/core";
1
+ import { Controller, Get, Param, Post } from "@hestjs/core";
2
2
 
3
3
  import { Body } from "@hestjs/validation";
4
4
  import { AppService } from "./app.service";
@@ -22,7 +22,9 @@ export class AppController {
22
22
  getUser(@Param("id") id: string) {
23
23
  const user = this.appService.getUser(id);
24
24
  if (!user) {
25
- throw new NotFoundException(`User with id ${id} not found`);
25
+ const error = new Error(`User with id ${id} not found`) as Error & { status: number };
26
+ error.status = 404;
27
+ throw error;
26
28
  }
27
29
  return user;
28
30
  }
@@ -0,0 +1,66 @@
1
+ import type { Context, Next } from 'hono';
2
+ import { logger } from '@hestjs/logger';
3
+
4
+ /**
5
+ * Hono 异常处理中间件
6
+ */
7
+ export const exceptionMiddleware = async (c: Context, next: Next) => {
8
+ try {
9
+ await next();
10
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
11
+ } catch (error: any) {
12
+ const status = error.status || 500;
13
+ const response = {
14
+ statusCode: status,
15
+ timestamp: new Date().toISOString(),
16
+ path: c.req.url,
17
+ message: error.message || 'Internal Server Error',
18
+ error: error.error || 'Exception',
19
+ };
20
+
21
+ logger.error(`🔥 HTTP Exception [${status}]: ${error.message}`, {
22
+ requestUrl: c.req.url,
23
+ stack: error.stack,
24
+ });
25
+
26
+ return c.json(response, status);
27
+ }
28
+ };
29
+
30
+ /**
31
+ * 响应包装中间件
32
+ */
33
+ export const responseMiddleware = async (c: Context, next: Next) => {
34
+ const start = Date.now();
35
+
36
+ await next();
37
+
38
+ // 跳过文档相关的路径
39
+ if (c.req.path === '/openapi.json' || c.req.path === '/docs' || c.req.path.startsWith('/api-docs')) {
40
+ return;
41
+ }
42
+
43
+ // 只包装JSON响应,且响应状态为2xx
44
+ const contentType = c.res.headers.get('content-type');
45
+ if (contentType?.includes('application/json') && c.res.status >= 200 && c.res.status < 300) {
46
+ try {
47
+ const duration = Date.now() - start;
48
+
49
+ // 克隆响应以避免消耗原始响应体
50
+ const responseClone = c.res.clone();
51
+ const originalResponse = await responseClone.json();
52
+
53
+ const wrappedResponse = {
54
+ success: true,
55
+ data: originalResponse,
56
+ timestamp: new Date().toISOString(),
57
+ duration: `${duration}ms`,
58
+ };
59
+
60
+ return c.json(wrappedResponse);
61
+ } catch (error) {
62
+ // 如果无法解析JSON,就保持原响应
63
+ console.warn('Failed to wrap response:', error);
64
+ }
65
+ }
66
+ };
@@ -1,31 +1,30 @@
1
1
  import { HestFactory } from "@hestjs/core";
2
2
  import { logger } from "@hestjs/logger";
3
- import { ValidationInterceptor } from "@hestjs/validation";
3
+ import { Hono } from "hono";
4
4
  import { cors } from "hono/cors";
5
5
  import { AppModule } from "./app.module";
6
- import { HttpExceptionFilter } from "./common/filters/http-exception.filter";
7
- import { ResponseInterceptor } from "./common/interceptors/response.interceptor";
6
+ import { exceptionMiddleware, responseMiddleware } from "./common/middleware";
8
7
 
9
8
  async function bootstrap() {
10
9
  try {
11
10
  logger.info("🚀 Starting HestJS application...");
12
11
 
13
- const app = await HestFactory.create(AppModule);
14
- app.hono().use(cors()); // 使用 Hono 的 CORS 中间件
15
- // app.hono().use('*', log()); // 使用 Hono 的日志中间件
12
+ // 创建 Hono 实例
13
+ const hono = new Hono();
14
+ hono.use(cors()); // 使用 Hono 的 CORS 中间件
15
+ hono.use('*', exceptionMiddleware); // 异常处理中间件
16
+ hono.use('*', responseMiddleware); // 响应包装中间件
17
+ // hono.use('*', log()); // 使用 Hono 的日志中间件
16
18
 
17
- // 全局拦截器 - 验证拦截器应该在响应拦截器之前
18
- app.useGlobalInterceptors(new ValidationInterceptor());
19
- app.useGlobalInterceptors(new ResponseInterceptor());
20
-
21
- // 全局异常过滤器
22
- app.useGlobalFilters(new HttpExceptionFilter());
19
+ await HestFactory.create(hono, AppModule);
23
20
 
24
21
  Bun.serve({
25
22
  port: 3002,
26
- fetch: app.hono().fetch,
23
+ fetch: hono.fetch,
27
24
  reusePort: true, // 启用端口复用
28
25
  });
26
+
27
+ logger.info(`🎉 Server is running on http://localhost:3002`);
29
28
  } catch (error) {
30
29
  logger.error("❌ Failed to start application:", error);
31
30
  process.exit(1);