create-hest-app 0.1.0

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 (139) hide show
  1. package/README.md +211 -0
  2. package/dist/index.js +127 -0
  3. package/package.json +50 -0
  4. package/templates/base/.prettierrc +33 -0
  5. package/templates/base/.vscode/extensions.json +79 -0
  6. package/templates/base/.vscode/settings.json +70 -0
  7. package/templates/base/README.md +562 -0
  8. package/templates/base/eslint.config.ts +26 -0
  9. package/templates/base/package.json +62 -0
  10. package/templates/base/src/app.controller.ts +39 -0
  11. package/templates/base/src/app.module.ts +12 -0
  12. package/templates/base/src/app.service.ts +30 -0
  13. package/templates/base/src/common/filters/http-exception.filter.ts +34 -0
  14. package/templates/base/src/common/interceptors/response.interceptor.ts +38 -0
  15. package/templates/base/src/index.ts +35 -0
  16. package/templates/base/src/modules/custom-validation/custom-validation.controller.ts +146 -0
  17. package/templates/base/src/modules/custom-validation/custom-validation.module.ts +10 -0
  18. package/templates/base/src/modules/custom-validation/custom-validation.service.ts +33 -0
  19. package/templates/base/src/modules/custom-validation/dto/custom-validation.dto.ts +132 -0
  20. package/templates/base/src/modules/users/dto/user.dto.ts +64 -0
  21. package/templates/base/src/modules/users/entities/user.entity.ts +9 -0
  22. package/templates/base/src/modules/users/users.controller.ts +68 -0
  23. package/templates/base/src/modules/users/users.module.ts +10 -0
  24. package/templates/base/src/modules/users/users.service.ts +55 -0
  25. package/templates/base/tsconfig.json +19 -0
  26. package/templates/base_scalar/.prettierrc +32 -0
  27. package/templates/base_scalar/.vscode/extensions.json +79 -0
  28. package/templates/base_scalar/.vscode/settings.json +70 -0
  29. package/templates/base_scalar/README.md +562 -0
  30. package/templates/base_scalar/eslint.config.ts +26 -0
  31. package/templates/base_scalar/package.json +63 -0
  32. package/templates/base_scalar/src/app.controller.ts +196 -0
  33. package/templates/base_scalar/src/app.module.ts +12 -0
  34. package/templates/base_scalar/src/app.service.ts +30 -0
  35. package/templates/base_scalar/src/common/filters/http-exception.filter.ts +34 -0
  36. package/templates/base_scalar/src/common/interceptors/response.interceptor.ts +38 -0
  37. package/templates/base_scalar/src/index.ts +67 -0
  38. package/templates/base_scalar/src/modules/custom-validation/custom-validation.controller.ts +146 -0
  39. package/templates/base_scalar/src/modules/custom-validation/custom-validation.module.ts +10 -0
  40. package/templates/base_scalar/src/modules/custom-validation/custom-validation.service.ts +33 -0
  41. package/templates/base_scalar/src/modules/custom-validation/dto/custom-validation.dto.ts +132 -0
  42. package/templates/base_scalar/src/modules/users/dto/user.dto.ts +64 -0
  43. package/templates/base_scalar/src/modules/users/entities/user.entity.ts +9 -0
  44. package/templates/base_scalar/src/modules/users/users.controller.ts +68 -0
  45. package/templates/base_scalar/src/modules/users/users.module.ts +10 -0
  46. package/templates/base_scalar/src/modules/users/users.service.ts +55 -0
  47. package/templates/base_scalar/tsconfig.json +19 -0
  48. package/templates/cqrs/.prettierrc +33 -0
  49. package/templates/cqrs/.vscode/extensions.json +79 -0
  50. package/templates/cqrs/.vscode/settings.json +70 -0
  51. package/templates/cqrs/README.md +234 -0
  52. package/templates/cqrs/eslint.config.ts +26 -0
  53. package/templates/cqrs/package.json +62 -0
  54. package/templates/cqrs/src/app.controller.ts +28 -0
  55. package/templates/cqrs/src/app.module.ts +12 -0
  56. package/templates/cqrs/src/app.service.ts +8 -0
  57. package/templates/cqrs/src/common/filters/http-exception.filter.ts +34 -0
  58. package/templates/cqrs/src/common/interceptors/response.interceptor.ts +38 -0
  59. package/templates/cqrs/src/index.ts +38 -0
  60. package/templates/cqrs/src/modules/custom-validation/custom-validation.controller.ts +146 -0
  61. package/templates/cqrs/src/modules/custom-validation/custom-validation.module.ts +10 -0
  62. package/templates/cqrs/src/modules/custom-validation/custom-validation.service.ts +33 -0
  63. package/templates/cqrs/src/modules/custom-validation/dto/custom-validation.dto.ts +132 -0
  64. package/templates/cqrs/src/modules/users/dto/user.dto.ts +64 -0
  65. package/templates/cqrs/src/modules/users/entities/user.entity.ts +9 -0
  66. package/templates/cqrs/src/modules/users/users.controller.ts +68 -0
  67. package/templates/cqrs/src/modules/users/users.module.ts +10 -0
  68. package/templates/cqrs/src/modules/users/users.service.ts +55 -0
  69. package/templates/cqrs/src/test-error-scenarios.ts +54 -0
  70. package/templates/cqrs/src/users/commands/create-user.command.ts +8 -0
  71. package/templates/cqrs/src/users/commands/index.ts +2 -0
  72. package/templates/cqrs/src/users/commands/update-user.command.ts +11 -0
  73. package/templates/cqrs/src/users/entities/index.ts +1 -0
  74. package/templates/cqrs/src/users/entities/user.entity.ts +22 -0
  75. package/templates/cqrs/src/users/events/index.ts +2 -0
  76. package/templates/cqrs/src/users/events/user-created.event.ts +8 -0
  77. package/templates/cqrs/src/users/events/user-updated.event.ts +8 -0
  78. package/templates/cqrs/src/users/handlers/create-user.handler.ts +26 -0
  79. package/templates/cqrs/src/users/handlers/get-all-users.handler.ts +15 -0
  80. package/templates/cqrs/src/users/handlers/get-user.handler.ts +15 -0
  81. package/templates/cqrs/src/users/handlers/index.ts +6 -0
  82. package/templates/cqrs/src/users/handlers/update-user.handler.ts +33 -0
  83. package/templates/cqrs/src/users/handlers/user-created.handler.ts +15 -0
  84. package/templates/cqrs/src/users/handlers/user-updated.handler.ts +15 -0
  85. package/templates/cqrs/src/users/index.ts +8 -0
  86. package/templates/cqrs/src/users/queries/get-all-users.query.ts +8 -0
  87. package/templates/cqrs/src/users/queries/get-user.query.ts +12 -0
  88. package/templates/cqrs/src/users/queries/index.ts +2 -0
  89. package/templates/cqrs/src/users/repositories/index.ts +1 -0
  90. package/templates/cqrs/src/users/repositories/user.repository.ts +51 -0
  91. package/templates/cqrs/src/users/user.controller.ts +66 -0
  92. package/templates/cqrs/src/users/user.module.ts +30 -0
  93. package/templates/cqrs/tsconfig.json +19 -0
  94. package/templates/cqrs_scalar/.prettierrc +33 -0
  95. package/templates/cqrs_scalar/.vscode/extensions.json +79 -0
  96. package/templates/cqrs_scalar/.vscode/settings.json +70 -0
  97. package/templates/cqrs_scalar/README.md +234 -0
  98. package/templates/cqrs_scalar/eslint.config.ts +26 -0
  99. package/templates/cqrs_scalar/package.json +62 -0
  100. package/templates/cqrs_scalar/src/app.controller.ts +28 -0
  101. package/templates/cqrs_scalar/src/app.module.ts +12 -0
  102. package/templates/cqrs_scalar/src/app.service.ts +8 -0
  103. package/templates/cqrs_scalar/src/common/filters/http-exception.filter.ts +34 -0
  104. package/templates/cqrs_scalar/src/common/interceptors/response.interceptor.ts +38 -0
  105. package/templates/cqrs_scalar/src/index.ts +38 -0
  106. package/templates/cqrs_scalar/src/modules/custom-validation/custom-validation.controller.ts +146 -0
  107. package/templates/cqrs_scalar/src/modules/custom-validation/custom-validation.module.ts +10 -0
  108. package/templates/cqrs_scalar/src/modules/custom-validation/custom-validation.service.ts +33 -0
  109. package/templates/cqrs_scalar/src/modules/custom-validation/dto/custom-validation.dto.ts +132 -0
  110. package/templates/cqrs_scalar/src/modules/users/dto/user.dto.ts +64 -0
  111. package/templates/cqrs_scalar/src/modules/users/entities/user.entity.ts +9 -0
  112. package/templates/cqrs_scalar/src/modules/users/users.controller.ts +68 -0
  113. package/templates/cqrs_scalar/src/modules/users/users.module.ts +10 -0
  114. package/templates/cqrs_scalar/src/modules/users/users.service.ts +55 -0
  115. package/templates/cqrs_scalar/src/test-error-scenarios.ts +54 -0
  116. package/templates/cqrs_scalar/src/users/commands/create-user.command.ts +8 -0
  117. package/templates/cqrs_scalar/src/users/commands/index.ts +2 -0
  118. package/templates/cqrs_scalar/src/users/commands/update-user.command.ts +11 -0
  119. package/templates/cqrs_scalar/src/users/entities/index.ts +1 -0
  120. package/templates/cqrs_scalar/src/users/entities/user.entity.ts +22 -0
  121. package/templates/cqrs_scalar/src/users/events/index.ts +2 -0
  122. package/templates/cqrs_scalar/src/users/events/user-created.event.ts +8 -0
  123. package/templates/cqrs_scalar/src/users/events/user-updated.event.ts +8 -0
  124. package/templates/cqrs_scalar/src/users/handlers/create-user.handler.ts +26 -0
  125. package/templates/cqrs_scalar/src/users/handlers/get-all-users.handler.ts +15 -0
  126. package/templates/cqrs_scalar/src/users/handlers/get-user.handler.ts +15 -0
  127. package/templates/cqrs_scalar/src/users/handlers/index.ts +6 -0
  128. package/templates/cqrs_scalar/src/users/handlers/update-user.handler.ts +33 -0
  129. package/templates/cqrs_scalar/src/users/handlers/user-created.handler.ts +15 -0
  130. package/templates/cqrs_scalar/src/users/handlers/user-updated.handler.ts +15 -0
  131. package/templates/cqrs_scalar/src/users/index.ts +8 -0
  132. package/templates/cqrs_scalar/src/users/queries/get-all-users.query.ts +8 -0
  133. package/templates/cqrs_scalar/src/users/queries/get-user.query.ts +12 -0
  134. package/templates/cqrs_scalar/src/users/queries/index.ts +2 -0
  135. package/templates/cqrs_scalar/src/users/repositories/index.ts +1 -0
  136. package/templates/cqrs_scalar/src/users/repositories/user.repository.ts +51 -0
  137. package/templates/cqrs_scalar/src/users/user.controller.ts +66 -0
  138. package/templates/cqrs_scalar/src/users/user.module.ts +30 -0
  139. package/templates/cqrs_scalar/tsconfig.json +19 -0
@@ -0,0 +1,15 @@
1
+ import { Injectable } from '@hestjs/core';
2
+ import { QueryHandler, IQueryHandler } from '@hestjs/cqrs';
3
+ import { GetAllUsersQuery, GetAllUsersResult } from '../queries';
4
+ import { UserRepository } from '../repositories';
5
+
6
+ @Injectable()
7
+ @QueryHandler(GetAllUsersQuery)
8
+ export class GetAllUsersHandler implements IQueryHandler<GetAllUsersQuery, GetAllUsersResult> {
9
+ constructor(private readonly userRepository: UserRepository) {}
10
+
11
+ async execute(_query: GetAllUsersQuery): Promise<GetAllUsersResult> {
12
+ const users = await this.userRepository.findAll();
13
+ return { users };
14
+ }
15
+ }
@@ -0,0 +1,15 @@
1
+ import { Injectable } from '@hestjs/core';
2
+ import { QueryHandler, IQueryHandler } from '@hestjs/cqrs';
3
+ import { GetUserQuery, GetUserResult } from '../queries';
4
+ import { UserRepository } from '../repositories';
5
+
6
+ @Injectable()
7
+ @QueryHandler(GetUserQuery)
8
+ export class GetUserHandler implements IQueryHandler<GetUserQuery, GetUserResult> {
9
+ constructor(private readonly userRepository: UserRepository) {}
10
+
11
+ async execute(query: GetUserQuery): Promise<GetUserResult> {
12
+ const user = await this.userRepository.findById(query.userId);
13
+ return { user };
14
+ }
15
+ }
@@ -0,0 +1,6 @@
1
+ export * from './create-user.handler';
2
+ export * from './update-user.handler';
3
+ export * from './get-user.handler';
4
+ export * from './get-all-users.handler';
5
+ export * from './user-created.handler';
6
+ export * from './user-updated.handler';
@@ -0,0 +1,33 @@
1
+ import { Injectable } from '@hestjs/core';
2
+ import { CommandHandler, EventBus, ICommandHandler } from '@hestjs/cqrs';
3
+ import { UpdateUserCommand } from '../commands';
4
+ import { User } from '../entities';
5
+ import { UserUpdatedEvent } from '../events';
6
+ import { UserRepository } from '../repositories';
7
+
8
+ @Injectable()
9
+ @CommandHandler(UpdateUserCommand)
10
+ export class UpdateUserHandler
11
+ implements ICommandHandler<UpdateUserCommand, User>
12
+ {
13
+ constructor(
14
+ private readonly userRepository: UserRepository,
15
+ private readonly eventBus: EventBus,
16
+ ) {}
17
+
18
+ async execute(command: UpdateUserCommand): Promise<User> {
19
+ const user = await this.userRepository.update(
20
+ command.userId,
21
+ command.userData,
22
+ );
23
+
24
+ if (!user) {
25
+ throw new Error(`User with id ${command.userId} not found`);
26
+ }
27
+
28
+ // 发布用户更新事件
29
+ await this.eventBus.publish(new UserUpdatedEvent(user));
30
+
31
+ return user;
32
+ }
33
+ }
@@ -0,0 +1,15 @@
1
+ import { Injectable } from '@hestjs/core';
2
+ import { EventsHandler, IEventHandler } from '@hestjs/cqrs';
3
+ import { logger } from '@hestjs/logger';
4
+ import { UserCreatedEvent } from '../events';
5
+
6
+ @Injectable()
7
+ @EventsHandler(UserCreatedEvent)
8
+ export class UserCreatedHandler implements IEventHandler<UserCreatedEvent> {
9
+ async handle(event: UserCreatedEvent): Promise<void> {
10
+ logger.info(`User created: ${event.user.name} (${event.user.email})`);
11
+
12
+ // 这里可以执行其他业务逻辑,比如发送欢迎邮件等
13
+ // await this.emailService.sendWelcomeEmail(event.user);
14
+ }
15
+ }
@@ -0,0 +1,15 @@
1
+ import { Injectable } from '@hestjs/core';
2
+ import { EventsHandler, IEventHandler } from '@hestjs/cqrs';
3
+ import { logger } from '@hestjs/logger';
4
+ import { UserUpdatedEvent } from '../events';
5
+
6
+ @Injectable()
7
+ @EventsHandler(UserUpdatedEvent)
8
+ export class UserUpdatedHandler implements IEventHandler<UserUpdatedEvent> {
9
+ async handle(event: UserUpdatedEvent): Promise<void> {
10
+ logger.info(`User updated: ${event.user.name} (${event.user.email})`);
11
+
12
+ // 这里可以执行其他业务逻辑,比如发送通知等
13
+ // await this.notificationService.sendUpdateNotification(event.user);
14
+ }
15
+ }
@@ -0,0 +1,8 @@
1
+ export * from './entities';
2
+ export * from './commands';
3
+ export * from './queries';
4
+ export * from './events';
5
+ export * from './handlers';
6
+ export * from './repositories';
7
+ export * from './user.controller';
8
+ export * from './user.module';
@@ -0,0 +1,8 @@
1
+ import { Query, IQueryResult } from '@hestjs/cqrs';
2
+ import { User } from '../entities';
3
+
4
+ export interface GetAllUsersResult extends IQueryResult {
5
+ users: User[];
6
+ }
7
+
8
+ export class GetAllUsersQuery extends Query<GetAllUsersResult> {}
@@ -0,0 +1,12 @@
1
+ import { Query, IQueryResult } from '@hestjs/cqrs';
2
+ import { User } from '../entities';
3
+
4
+ export interface GetUserResult extends IQueryResult {
5
+ user: User | null;
6
+ }
7
+
8
+ export class GetUserQuery extends Query<GetUserResult> {
9
+ constructor(public readonly userId: string) {
10
+ super();
11
+ }
12
+ }
@@ -0,0 +1,2 @@
1
+ export * from './get-user.query';
2
+ export * from './get-all-users.query';
@@ -0,0 +1 @@
1
+ export * from './user.repository';
@@ -0,0 +1,51 @@
1
+ import { Injectable } from '@hestjs/core';
2
+ import { User, CreateUserData, UpdateUserData } from '../entities';
3
+
4
+ @Injectable()
5
+ export class UserRepository {
6
+ private users: Map<string, User> = new Map();
7
+ private nextId = 1;
8
+
9
+ async create(userData: CreateUserData): Promise<User> {
10
+ const id = this.nextId.toString();
11
+ this.nextId++;
12
+
13
+ const user: User = {
14
+ id,
15
+ ...userData,
16
+ createdAt: new Date(),
17
+ updatedAt: new Date(),
18
+ };
19
+
20
+ this.users.set(id, user);
21
+ return user;
22
+ }
23
+
24
+ async findById(id: string): Promise<User | null> {
25
+ return this.users.get(id) || null;
26
+ }
27
+
28
+ async findAll(): Promise<User[]> {
29
+ return Array.from(this.users.values());
30
+ }
31
+
32
+ async update(id: string, userData: UpdateUserData): Promise<User | null> {
33
+ const user = this.users.get(id);
34
+ if (!user) {
35
+ return null;
36
+ }
37
+
38
+ const updatedUser: User = {
39
+ ...user,
40
+ ...userData,
41
+ updatedAt: new Date(),
42
+ };
43
+
44
+ this.users.set(id, updatedUser);
45
+ return updatedUser;
46
+ }
47
+
48
+ async delete(id: string): Promise<boolean> {
49
+ return this.users.delete(id);
50
+ }
51
+ }
@@ -0,0 +1,66 @@
1
+ import { Controller, Get, Post, Put, Context } from '@hestjs/core';
2
+ import type { HestContext } from '@hestjs/core';
3
+ import { CommandBus, QueryBus } from '@hestjs/cqrs';
4
+ import { CreateUserCommand, UpdateUserCommand } from './commands';
5
+ import { CreateUserData, UpdateUserData } from './entities';
6
+ import { GetAllUsersQuery, GetUserQuery } from './queries';
7
+
8
+ @Controller('/users')
9
+ export class UserController {
10
+ constructor(
11
+ private readonly commandBus: CommandBus,
12
+ private readonly queryBus: QueryBus,
13
+ ) {}
14
+
15
+ @Post('/')
16
+ async createUser(@Context() c: HestContext) {
17
+ const userData = await c.req.json<CreateUserData>();
18
+
19
+ // 基本验证(可以添加更复杂的验证逻辑)
20
+ if (!userData.name || !userData.email) {
21
+ return c.json(
22
+ { success: false, error: 'Name and email are required' },
23
+ 400,
24
+ );
25
+ }
26
+
27
+ const user = await this.commandBus.execute(new CreateUserCommand(userData));
28
+ return c.json({ success: true, data: user }, 201);
29
+ }
30
+
31
+ @Get('/')
32
+ async getAllUsers(@Context() c: HestContext) {
33
+ const result = await this.queryBus.execute(new GetAllUsersQuery());
34
+ return c.json({ success: true, data: result.users });
35
+ }
36
+
37
+ @Get('/:id')
38
+ async getUserById(@Context() c: HestContext) {
39
+ const id = c.req.param('id');
40
+ const result = await this.queryBus.execute(new GetUserQuery(id));
41
+
42
+ if (!result.user) {
43
+ return c.json({ success: false, error: 'User not found' }, 404);
44
+ }
45
+
46
+ return c.json({ success: true, data: result.user });
47
+ }
48
+
49
+ @Put('/:id')
50
+ async updateUser(@Context() c: HestContext) {
51
+ const id = c.req.param('id');
52
+ const userData = await c.req.json<UpdateUserData>();
53
+
54
+ try {
55
+ const user = await this.commandBus.execute(
56
+ new UpdateUserCommand(id, userData),
57
+ );
58
+ return c.json({ success: true, data: user });
59
+ } catch (error) {
60
+ if (error instanceof Error && error.message.includes('not found')) {
61
+ return c.json({ success: false, error: 'User not found' }, 404);
62
+ }
63
+ throw error;
64
+ }
65
+ }
66
+ }
@@ -0,0 +1,30 @@
1
+ import { Module } from '@hestjs/core';
2
+ import { CqrsModule } from '@hestjs/cqrs';
3
+ import { UserController } from './user.controller';
4
+ import { UserRepository } from './repositories';
5
+ import {
6
+ CreateUserHandler,
7
+ UpdateUserHandler,
8
+ GetUserHandler,
9
+ GetAllUsersHandler,
10
+ UserCreatedHandler,
11
+ UserUpdatedHandler,
12
+ } from './handlers';
13
+
14
+ @Module({
15
+ imports: [CqrsModule],
16
+ controllers: [UserController],
17
+ providers: [
18
+ UserRepository,
19
+ // Command Handlers
20
+ CreateUserHandler,
21
+ UpdateUserHandler,
22
+ // Query Handlers
23
+ GetUserHandler,
24
+ GetAllUsersHandler,
25
+ // Event Handlers
26
+ UserCreatedHandler,
27
+ UserUpdatedHandler,
28
+ ],
29
+ })
30
+ export class UserModule {}
@@ -0,0 +1,19 @@
1
+ {
2
+ "extends": "@hestjs/typescript-config/base.json",
3
+ "compilerOptions": {
4
+ "strict": true,
5
+ "jsx": "react-jsx",
6
+ "jsxImportSource": "hono/jsx",
7
+ "experimentalDecorators": true,
8
+ "emitDecoratorMetadata": true,
9
+ "target": "ES2022",
10
+ "module": "ESNext",
11
+ "moduleResolution": "bundler",
12
+ "outDir": "./dist",
13
+ "declaration": true,
14
+ "sourceMap": true,
15
+ "paths": {
16
+ "@/*": ["./src/*"]
17
+ }
18
+ }
19
+ }