@urbansolv/create-nestjs-app 1.0.2 → 1.2.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 (51) hide show
  1. package/dist/templates/nestjs-app/.editorconfig +12 -12
  2. package/dist/templates/nestjs-app/.env.example +24 -24
  3. package/dist/templates/nestjs-app/.eslintrc.js +25 -25
  4. package/dist/templates/nestjs-app/package.json +40 -30
  5. package/dist/templates/nestjs-app/prisma/schema.prisma +79 -79
  6. package/dist/templates/nestjs-app/prisma/seed.ts +153 -154
  7. package/dist/templates/nestjs-app/src/app.module.ts +68 -68
  8. package/dist/templates/nestjs-app/src/common/constants/permissions.constant.ts +27 -27
  9. package/dist/templates/nestjs-app/src/common/decorators/api-response.decorator.ts +44 -44
  10. package/dist/templates/nestjs-app/src/common/decorators/get-user.decorator.ts +11 -11
  11. package/dist/templates/nestjs-app/src/common/decorators/permissions.decorator.ts +5 -5
  12. package/dist/templates/nestjs-app/src/common/decorators/public.decorator.ts +4 -4
  13. package/dist/templates/nestjs-app/src/common/dto/api-response.dto.ts +21 -21
  14. package/dist/templates/nestjs-app/src/common/dto/pagination.dto.ts +33 -33
  15. package/dist/templates/nestjs-app/src/common/filters/http-exception.filter.ts +56 -56
  16. package/dist/templates/nestjs-app/src/common/guards/jwt-auth.guard.ts +32 -32
  17. package/dist/templates/nestjs-app/src/common/guards/permissions.guard.ts +53 -53
  18. package/dist/templates/nestjs-app/src/common/interceptors/logging.interceptor.ts +37 -37
  19. package/dist/templates/nestjs-app/src/common/interceptors/transform.interceptor.ts +55 -55
  20. package/dist/templates/nestjs-app/src/common/prisma/prisma.module.ts +9 -9
  21. package/dist/templates/nestjs-app/src/common/prisma/prisma.service.ts +46 -46
  22. package/dist/templates/nestjs-app/src/common/utils/password.util.ts +13 -13
  23. package/dist/templates/nestjs-app/src/config/app.config.ts +10 -10
  24. package/dist/templates/nestjs-app/src/config/database.config.ts +5 -5
  25. package/dist/templates/nestjs-app/src/config/env.validation.ts +30 -30
  26. package/dist/templates/nestjs-app/src/config/jwt.config.ts +8 -8
  27. package/dist/templates/nestjs-app/src/config/swagger.config.ts +6 -6
  28. package/dist/templates/nestjs-app/src/main.ts +94 -91
  29. package/dist/templates/nestjs-app/src/modules/auth/auth.module.ts +28 -27
  30. package/dist/templates/nestjs-app/src/modules/auth/auth.service.ts +180 -54
  31. package/dist/templates/nestjs-app/src/modules/auth/controllers/v1/auth.controller.ts +33 -33
  32. package/dist/templates/nestjs-app/src/modules/auth/{dto → core/dto}/auth-response.dto.ts +19 -19
  33. package/dist/templates/nestjs-app/src/modules/auth/core/dto/login-response.dto.ts +10 -0
  34. package/dist/templates/nestjs-app/src/modules/auth/{dto → core/dto}/login.dto.ts +15 -15
  35. package/dist/templates/nestjs-app/src/modules/auth/{dto → core/dto}/register.dto.ts +30 -30
  36. package/dist/templates/nestjs-app/src/modules/auth/{interfaces → core/interfaces}/jwt-payload.interface.ts +7 -7
  37. package/dist/templates/nestjs-app/src/modules/auth/{strategies → core/strategies}/jwt.strategy.ts +54 -54
  38. package/dist/templates/nestjs-app/src/modules/health/health.controller.ts +29 -29
  39. package/dist/templates/nestjs-app/src/modules/health/health.module.ts +7 -7
  40. package/dist/templates/nestjs-app/src/modules/users/controllers/v1/users.controller.ts +118 -114
  41. package/dist/templates/nestjs-app/src/modules/users/core/dto/change-position.dto.ts +9 -9
  42. package/dist/templates/nestjs-app/src/modules/users/core/dto/create-user.dto.ts +35 -35
  43. package/dist/templates/nestjs-app/src/modules/users/core/dto/manage-permissions.dto.ts +13 -13
  44. package/dist/templates/nestjs-app/src/modules/users/core/dto/update-user.dto.ts +30 -30
  45. package/dist/templates/nestjs-app/src/modules/users/core/dto/user-query.dto.ts +22 -22
  46. package/dist/templates/nestjs-app/src/modules/users/core/dto/user-response.dto.ts +32 -0
  47. package/dist/templates/nestjs-app/src/modules/users/core/entities/user.entity.ts +45 -45
  48. package/dist/templates/nestjs-app/src/modules/users/core/helpers/user-transform.helper.ts +31 -31
  49. package/dist/templates/nestjs-app/src/modules/users/users.module.ts +10 -10
  50. package/dist/templates/nestjs-app/src/modules/users/users.service.ts +340 -340
  51. package/package.json +2 -2
@@ -1,54 +1,180 @@
1
- import { Injectable, UnauthorizedException } from '@nestjs/common';
2
- import { ConfigService } from '@nestjs/config';
3
- import { PassportStrategy } from '@nestjs/passport';
4
- import { ExtractJwt, Strategy } from 'passport-jwt';
5
- import { PrismaService } from '@common/prisma/prisma.service';
6
- import { JwtPayload } from '../interfaces/jwt-payload.interface';
7
-
8
- @Injectable()
9
- export class JwtStrategy extends PassportStrategy(Strategy) {
10
- constructor(
11
- private configService: ConfigService,
12
- private prisma: PrismaService,
13
- ) {
14
- super({
15
- jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
16
- ignoreExpiration: false,
17
- secretOrKey: configService.get<string>('jwt.secret'),
18
- });
19
- }
20
-
21
- async validate(payload: JwtPayload): Promise<JwtPayload> {
22
- const user = await this.prisma.user.findUnique({
23
- where: { id: payload.userId },
24
- include: {
25
- position: {
26
- include: {
27
- position_permissions: {
28
- include: {
29
- permission: true,
30
- },
31
- },
32
- },
33
- },
34
- },
35
- });
36
-
37
- if (!user || !user.is_active) {
38
- throw new UnauthorizedException('User not found or inactive');
39
- }
40
-
41
- // Build permissions array from position
42
- const permissions = user.position.position_permissions.map(
43
- (pp) => pp.permission.name,
44
- );
45
-
46
- return {
47
- userId: user.id,
48
- email: user.email,
49
- positionId: user.position.id,
50
- positionName: user.position.name,
51
- permissions,
52
- };
53
- }
54
- }
1
+ import {
2
+ Injectable,
3
+ UnauthorizedException,
4
+ ConflictException,
5
+ BadRequestException,
6
+ } from '@nestjs/common';
7
+ import { JwtService } from '@nestjs/jwt';
8
+ import { ConfigService } from '@nestjs/config';
9
+ import { PrismaService } from '@common/prisma/prisma.service';
10
+ import { PasswordUtil } from '@common/utils/password.util';
11
+ import { LoginDto } from './core/dto/login.dto';
12
+ import { RegisterDto } from './core/dto/register.dto';
13
+ import { AuthResponseDto } from './core/dto/auth-response.dto';
14
+ import { JwtPayload } from './core/interfaces/jwt-payload.interface';
15
+
16
+ @Injectable()
17
+ export class AuthService {
18
+ constructor(
19
+ private prisma: PrismaService,
20
+ private jwtService: JwtService,
21
+ private configService: ConfigService,
22
+ ) {}
23
+
24
+ async login(loginDto: LoginDto): Promise<AuthResponseDto> {
25
+ const { email, password } = loginDto;
26
+
27
+ // Find user with position and permissions
28
+ const user = await this.prisma.user.findUnique({
29
+ where: { email },
30
+ include: {
31
+ position: {
32
+ include: {
33
+ position_permissions: {
34
+ include: {
35
+ permission: true,
36
+ },
37
+ },
38
+ },
39
+ },
40
+ },
41
+ });
42
+
43
+ if (!user) {
44
+ throw new UnauthorizedException('Invalid credentials');
45
+ }
46
+
47
+ if (!user.is_active) {
48
+ throw new UnauthorizedException('Account is inactive');
49
+ }
50
+
51
+ console.log({
52
+ passwordInput: loginDto.password,
53
+ passwordHash: user.password,
54
+ isActive: user.is_active,
55
+ deletedAt: user.deleted_at,
56
+ });
57
+
58
+ // Verify password
59
+ const isPasswordValid = await PasswordUtil.compare(password, user.password);
60
+ if (!isPasswordValid) {
61
+ throw new UnauthorizedException('Invalid credentials');
62
+ }
63
+
64
+ // Build permissions array
65
+ const permissions = user.position.position_permissions.map(
66
+ (pp) => pp.permission.name,
67
+ );
68
+
69
+ // Generate JWT token
70
+ const payload: JwtPayload = {
71
+ userId: user.id,
72
+ email: user.email,
73
+ positionId: user.position.id,
74
+ positionName: user.position.name,
75
+ permissions,
76
+ };
77
+
78
+ const access_token = this.jwtService.sign(payload);
79
+
80
+ return {
81
+ access_token,
82
+ user: {
83
+ id: user.id,
84
+ email: user.email,
85
+ first_name: user.first_name,
86
+ last_name: user.last_name,
87
+ position: {
88
+ id: user.position.id,
89
+ name: user.position.name,
90
+ },
91
+ permissions,
92
+ },
93
+ };
94
+ }
95
+
96
+ async register(registerDto: RegisterDto): Promise<AuthResponseDto> {
97
+ const { email, password, first_name, last_name, position_id } = registerDto;
98
+
99
+ // Check if user already exists
100
+ const existingUser = await this.prisma.user.findUnique({
101
+ where: { email },
102
+ });
103
+
104
+ if (existingUser) {
105
+ throw new ConflictException('Email already exists');
106
+ }
107
+
108
+ // Validate position exists
109
+ const position = await this.prisma.position.findUnique({
110
+ where: { id: position_id },
111
+ include: {
112
+ position_permissions: {
113
+ include: {
114
+ permission: true,
115
+ },
116
+ },
117
+ },
118
+ });
119
+
120
+ if (!position) {
121
+ throw new BadRequestException('Invalid position ID');
122
+ }
123
+
124
+ // Hash password
125
+ const hashedPassword = await PasswordUtil.hash(password);
126
+
127
+ // Create user
128
+ const user = await this.prisma.user.create({
129
+ data: {
130
+ email,
131
+ password: hashedPassword,
132
+ first_name,
133
+ last_name,
134
+ position_id,
135
+ },
136
+ include: {
137
+ position: {
138
+ include: {
139
+ position_permissions: {
140
+ include: {
141
+ permission: true,
142
+ },
143
+ },
144
+ },
145
+ },
146
+ },
147
+ });
148
+
149
+ // Build permissions array
150
+ const permissions = user.position.position_permissions.map(
151
+ (pp) => pp.permission.name,
152
+ );
153
+
154
+ // Generate JWT token
155
+ const payload: JwtPayload = {
156
+ userId: user.id,
157
+ email: user.email,
158
+ positionId: user.position.id,
159
+ positionName: user.position.name,
160
+ permissions,
161
+ };
162
+
163
+ const access_token = this.jwtService.sign(payload);
164
+
165
+ return {
166
+ access_token,
167
+ user: {
168
+ id: user.id,
169
+ email: user.email,
170
+ first_name: user.first_name,
171
+ last_name: user.last_name,
172
+ position: {
173
+ id: user.position.id,
174
+ name: user.position.name,
175
+ },
176
+ permissions,
177
+ },
178
+ };
179
+ }
180
+ }
@@ -1,33 +1,33 @@
1
- import { Controller, Post, Body, HttpCode, HttpStatus } from '@nestjs/common';
2
- import { ApiTags, ApiOperation, ApiResponse } from '@nestjs/swagger';
3
- import { AuthService } from '../../auth.service';
4
- import { LoginDto } from '../../dto/login.dto';
5
- import { RegisterDto } from '../../dto/register.dto';
6
- import { AuthResponseDto } from '../../dto/auth-response.dto';
7
- import { Public } from '@common/decorators/public.decorator';
8
- import { ApiSuccessResponse } from '@common/decorators/api-response.decorator';
9
-
10
- @ApiTags('Authentication')
11
- @Controller({ path: 'auth', version: '1' })
12
- export class AuthController {
13
- constructor(private readonly authService: AuthService) {}
14
-
15
- @Public()
16
- @Post('login')
17
- @HttpCode(HttpStatus.OK)
18
- @ApiOperation({ summary: 'User login' })
19
- @ApiSuccessResponse(AuthResponseDto)
20
- @ApiResponse({ status: 401, description: 'Invalid credentials' })
21
- async login(@Body() loginDto: LoginDto): Promise<AuthResponseDto> {
22
- return this.authService.login(loginDto);
23
- }
24
-
25
- @Public()
26
- @Post('register')
27
- @ApiOperation({ summary: 'User registration' })
28
- @ApiSuccessResponse(AuthResponseDto)
29
- @ApiResponse({ status: 409, description: 'Email already exists' })
30
- async register(@Body() registerDto: RegisterDto): Promise<AuthResponseDto> {
31
- return this.authService.register(registerDto);
32
- }
33
- }
1
+ import { Controller, Post, Body, HttpCode, HttpStatus } from '@nestjs/common';
2
+ import { ApiTags, ApiOperation, ApiResponse } from '@nestjs/swagger';
3
+ import { AuthService } from '../../auth.service';
4
+ import { LoginDto } from '../../core/dto/login.dto';
5
+ import { RegisterDto } from '../../core/dto/register.dto';
6
+ import { AuthResponseDto } from '../../core/dto/auth-response.dto';
7
+ import { Public } from '@common/decorators/public.decorator';
8
+ import { ApiSuccessResponse } from '@common/decorators/api-response.decorator';
9
+
10
+ @ApiTags('Authentication')
11
+ @Controller({ path: 'auth', version: '1' })
12
+ export class AuthController {
13
+ constructor(private readonly authService: AuthService) {}
14
+
15
+ @Public()
16
+ @Post('login')
17
+ @HttpCode(HttpStatus.OK)
18
+ @ApiOperation({ summary: 'User login' })
19
+ @ApiSuccessResponse(AuthResponseDto)
20
+ @ApiResponse({ status: 401, description: 'Invalid credentials' })
21
+ async login(@Body() loginDto: LoginDto): Promise<AuthResponseDto> {
22
+ return this.authService.login(loginDto);
23
+ }
24
+
25
+ @Public()
26
+ @Post('register')
27
+ @ApiOperation({ summary: 'User registration' })
28
+ @ApiSuccessResponse(AuthResponseDto)
29
+ @ApiResponse({ status: 409, description: 'Email already exists' })
30
+ async register(@Body() registerDto: RegisterDto): Promise<AuthResponseDto> {
31
+ return this.authService.register(registerDto);
32
+ }
33
+ }
@@ -1,19 +1,19 @@
1
- import { ApiProperty } from '@nestjs/swagger';
2
-
3
- export class AuthResponseDto {
4
- @ApiProperty()
5
- access_token: string;
6
-
7
- @ApiProperty()
8
- user: {
9
- id: number;
10
- email: string;
11
- first_name: string;
12
- last_name: string;
13
- position: {
14
- id: number;
15
- name: string;
16
- };
17
- permissions: string[];
18
- };
19
- }
1
+ import { ApiProperty } from '@nestjs/swagger';
2
+
3
+ export class AuthResponseDto {
4
+ @ApiProperty()
5
+ access_token: string;
6
+
7
+ @ApiProperty()
8
+ user: {
9
+ id: number;
10
+ email: string;
11
+ first_name: string;
12
+ last_name: string;
13
+ position: {
14
+ id: number;
15
+ name: string;
16
+ };
17
+ permissions: string[];
18
+ };
19
+ }
@@ -0,0 +1,10 @@
1
+ import { ApiProperty } from '@nestjs/swagger';
2
+ import { UserResponseDto } from '@modules/users/core/dto/user-response.dto';
3
+
4
+ export class LoginResponseDto {
5
+ @ApiProperty()
6
+ access_token: string;
7
+
8
+ @ApiProperty()
9
+ user: UserResponseDto;
10
+ }
@@ -1,15 +1,15 @@
1
- import { ApiProperty } from '@nestjs/swagger';
2
- import { IsEmail, IsNotEmpty, IsString, MinLength } from 'class-validator';
3
-
4
- export class LoginDto {
5
- @ApiProperty({ example: 'admin@urbansolv.co.id' })
6
- @IsEmail({}, { message: 'Please provide a valid email address' })
7
- @IsNotEmpty({ message: 'Email is required' })
8
- email: string;
9
-
10
- @ApiProperty({ example: 'password123' })
11
- @IsString()
12
- @IsNotEmpty({ message: 'Password is required' })
13
- @MinLength(6, { message: 'Password must be at least 6 characters long' })
14
- password: string;
15
- }
1
+ import { ApiProperty } from '@nestjs/swagger';
2
+ import { IsEmail, IsNotEmpty, IsString, MinLength } from 'class-validator';
3
+
4
+ export class LoginDto {
5
+ @ApiProperty({ example: 'admin@urbansolv.co.id' })
6
+ @IsEmail({}, { message: 'Please provide a valid email address' })
7
+ @IsNotEmpty({ message: 'Email is required' })
8
+ email: string;
9
+
10
+ @ApiProperty({ example: 'password123' })
11
+ @IsString()
12
+ @IsNotEmpty({ message: 'Password is required' })
13
+ @MinLength(6, { message: 'Password must be at least 6 characters long' })
14
+ password: string;
15
+ }
@@ -1,30 +1,30 @@
1
- import { ApiProperty } from '@nestjs/swagger';
2
- import { IsEmail, IsNotEmpty, IsString, MinLength, IsInt } from 'class-validator';
3
-
4
- export class RegisterDto {
5
- @ApiProperty({ example: 'bhagaskoro@urbansolv.co.id' })
6
- @IsEmail({}, { message: 'Please provide a valid email address' })
7
- @IsNotEmpty({ message: 'Email is required' })
8
- email: string;
9
-
10
- @ApiProperty({ example: 'password123' })
11
- @IsString()
12
- @IsNotEmpty({ message: 'Password is required' })
13
- @MinLength(6, { message: 'Password must be at least 6 characters long' })
14
- password: string;
15
-
16
- @ApiProperty({ example: 'Bhagas' })
17
- @IsString()
18
- @IsNotEmpty({ message: 'First name is required' })
19
- first_name: string;
20
-
21
- @ApiProperty({ example: 'Koro' })
22
- @IsString()
23
- @IsNotEmpty({ message: 'Last name is required' })
24
- last_name: string;
25
-
26
- @ApiProperty({ example: 2, description: 'Position ID' })
27
- @IsInt({ message: 'Position ID must be an integer' })
28
- @IsNotEmpty({ message: 'Position ID is required' })
29
- position_id: number;
30
- }
1
+ import { ApiProperty } from '@nestjs/swagger';
2
+ import { IsEmail, IsNotEmpty, IsString, MinLength, IsInt } from 'class-validator';
3
+
4
+ export class RegisterDto {
5
+ @ApiProperty({ example: 'bhagaskoro@urbansolv.co.id' })
6
+ @IsEmail({}, { message: 'Please provide a valid email address' })
7
+ @IsNotEmpty({ message: 'Email is required' })
8
+ email: string;
9
+
10
+ @ApiProperty({ example: 'password123' })
11
+ @IsString()
12
+ @IsNotEmpty({ message: 'Password is required' })
13
+ @MinLength(6, { message: 'Password must be at least 6 characters long' })
14
+ password: string;
15
+
16
+ @ApiProperty({ example: 'Bhagas' })
17
+ @IsString()
18
+ @IsNotEmpty({ message: 'First name is required' })
19
+ first_name: string;
20
+
21
+ @ApiProperty({ example: 'Koro' })
22
+ @IsString()
23
+ @IsNotEmpty({ message: 'Last name is required' })
24
+ last_name: string;
25
+
26
+ @ApiProperty({ example: 2, description: 'Position ID' })
27
+ @IsInt({ message: 'Position ID must be an integer' })
28
+ @IsNotEmpty({ message: 'Position ID is required' })
29
+ position_id: number;
30
+ }
@@ -1,7 +1,7 @@
1
- export interface JwtPayload {
2
- userId: number;
3
- email: string;
4
- positionId: number;
5
- positionName: string;
6
- permissions: string[];
7
- }
1
+ export interface JwtPayload {
2
+ userId: number;
3
+ email: string;
4
+ positionId: number;
5
+ positionName: string;
6
+ permissions: string[];
7
+ }
@@ -1,54 +1,54 @@
1
- import { Injectable, UnauthorizedException } from '@nestjs/common';
2
- import { ConfigService } from '@nestjs/config';
3
- import { PassportStrategy } from '@nestjs/passport';
4
- import { ExtractJwt, Strategy } from 'passport-jwt';
5
- import { PrismaService } from '@common/prisma/prisma.service';
6
- import { JwtPayload } from '../interfaces/jwt-payload.interface';
7
-
8
- @Injectable()
9
- export class JwtStrategy extends PassportStrategy(Strategy) {
10
- constructor(
11
- private configService: ConfigService,
12
- private prisma: PrismaService,
13
- ) {
14
- super({
15
- jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
16
- ignoreExpiration: false,
17
- secretOrKey: configService.get<string>('jwt.secret'),
18
- });
19
- }
20
-
21
- async validate(payload: JwtPayload): Promise<JwtPayload> {
22
- const user = await this.prisma.user.findUnique({
23
- where: { id: payload.userId },
24
- include: {
25
- position: {
26
- include: {
27
- position_permissions: {
28
- include: {
29
- permission: true,
30
- },
31
- },
32
- },
33
- },
34
- },
35
- });
36
-
37
- if (!user || !user.is_active) {
38
- throw new UnauthorizedException('User not found or inactive');
39
- }
40
-
41
- // Build permissions array from position
42
- const permissions = user.position.position_permissions.map(
43
- (pp) => pp.permission.name,
44
- );
45
-
46
- return {
47
- userId: user.id,
48
- email: user.email,
49
- positionId: user.position.id,
50
- positionName: user.position.name,
51
- permissions,
52
- };
53
- }
54
- }
1
+ import { Injectable, UnauthorizedException } from '@nestjs/common';
2
+ import { ConfigService } from '@nestjs/config';
3
+ import { PassportStrategy } from '@nestjs/passport';
4
+ import { ExtractJwt, Strategy } from 'passport-jwt';
5
+ import { PrismaService } from '@common/prisma/prisma.service';
6
+ import { JwtPayload } from '../interfaces/jwt-payload.interface';
7
+
8
+ @Injectable()
9
+ export class JwtStrategy extends PassportStrategy(Strategy) {
10
+ constructor(
11
+ private configService: ConfigService,
12
+ private prisma: PrismaService,
13
+ ) {
14
+ super({
15
+ jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
16
+ ignoreExpiration: false,
17
+ secretOrKey: configService.get<string>('jwt.secret'),
18
+ });
19
+ }
20
+
21
+ async validate(payload: JwtPayload): Promise<JwtPayload> {
22
+ const user = await this.prisma.user.findUnique({
23
+ where: { id: payload.userId },
24
+ include: {
25
+ position: {
26
+ include: {
27
+ position_permissions: {
28
+ include: {
29
+ permission: true,
30
+ },
31
+ },
32
+ },
33
+ },
34
+ },
35
+ });
36
+
37
+ if (!user || !user.is_active) {
38
+ throw new UnauthorizedException('User not found or inactive');
39
+ }
40
+
41
+ // Build permissions array from position
42
+ const permissions = user.position.position_permissions.map(
43
+ (pp) => pp.permission.name,
44
+ );
45
+
46
+ return {
47
+ userId: user.id,
48
+ email: user.email,
49
+ positionId: user.position.id,
50
+ positionName: user.position.name,
51
+ permissions,
52
+ };
53
+ }
54
+ }
@@ -1,29 +1,29 @@
1
- import { Controller, Get } from '@nestjs/common';
2
- import { ApiTags, ApiOperation } from '@nestjs/swagger';
3
- import { Public } from '@common/decorators/public.decorator';
4
-
5
- @ApiTags('Health')
6
- @Controller()
7
- export class HealthController {
8
- @Public()
9
- @Get('health')
10
- @ApiOperation({ summary: 'Health check endpoint' })
11
- health() {
12
- return {
13
- status: 'ok',
14
- timestamp: new Date().toISOString(),
15
- uptime: process.uptime(),
16
- environment: process.env.NODE_ENV,
17
- };
18
- }
19
-
20
- @Public()
21
- @Get('ping')
22
- @ApiOperation({ summary: 'Ping endpoint' })
23
- ping() {
24
- return {
25
- message: 'pong',
26
- timestamp: new Date().toISOString(),
27
- };
28
- }
29
- }
1
+ import { Controller, Get } from '@nestjs/common';
2
+ import { ApiTags, ApiOperation } from '@nestjs/swagger';
3
+ import { Public } from '@common/decorators/public.decorator';
4
+
5
+ @ApiTags('Health')
6
+ @Controller()
7
+ export class HealthController {
8
+ @Public()
9
+ @Get('health')
10
+ @ApiOperation({ summary: 'Health check endpoint' })
11
+ health() {
12
+ return {
13
+ status: 'ok',
14
+ timestamp: new Date().toISOString(),
15
+ uptime: process.uptime(),
16
+ environment: process.env.NODE_ENV,
17
+ };
18
+ }
19
+
20
+ @Public()
21
+ @Get('ping')
22
+ @ApiOperation({ summary: 'Ping endpoint' })
23
+ ping() {
24
+ return {
25
+ message: 'pong',
26
+ timestamp: new Date().toISOString(),
27
+ };
28
+ }
29
+ }
@@ -1,7 +1,7 @@
1
- import { Module } from '@nestjs/common';
2
- import { HealthController } from './health.controller';
3
-
4
- @Module({
5
- controllers: [HealthController],
6
- })
7
- export class HealthModule {}
1
+ import { Module } from '@nestjs/common';
2
+ import { HealthController } from './health.controller';
3
+
4
+ @Module({
5
+ controllers: [HealthController],
6
+ })
7
+ export class HealthModule {}