@lenne.tech/nest-server 10.8.6 → 10.8.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lenne.tech/nest-server",
3
- "version": "10.8.6",
3
+ "version": "10.8.7",
4
4
  "description": "Modern, fast, powerful Node.js web framework in TypeScript based on Nest with a GraphQL API and a connection to MongoDB (or other databases).",
5
5
  "keywords": [
6
6
  "node",
@@ -0,0 +1,28 @@
1
+ import { applyDecorators } from '@nestjs/common';
2
+ import { ApiBadRequestResponse, ApiNotFoundResponse, ApiUnauthorizedResponse } from '@nestjs/swagger';
3
+
4
+ export const commonErrorSchema = {
5
+ properties: {
6
+ message: { type: 'string' },
7
+ name: { type: 'string' },
8
+ options: { type: 'object' },
9
+ response: {
10
+ properties: {
11
+ error: { type: 'string' },
12
+ message: { type: 'string' },
13
+ statusCode: { type: 'number' },
14
+ },
15
+ type: 'object',
16
+ },
17
+ status: { type: 'number' },
18
+ },
19
+ type: 'object',
20
+ };
21
+
22
+ export function ApiCommonErrorResponses() {
23
+ return applyDecorators(
24
+ ApiUnauthorizedResponse({ schema: commonErrorSchema }),
25
+ ApiNotFoundResponse({ schema: commonErrorSchema }),
26
+ ApiBadRequestResponse({ schema: commonErrorSchema }),
27
+ );
28
+ }
@@ -1,5 +1,6 @@
1
1
  import { Field, ID, ObjectType } from '@nestjs/graphql';
2
2
  import { Prop, Schema } from '@nestjs/mongoose';
3
+ import { ApiProperty } from '@nestjs/swagger';
3
4
  import { Types } from 'mongoose';
4
5
 
5
6
  import { Restricted } from '../decorators/restricted.decorator';
@@ -47,6 +48,7 @@ export abstract class CorePersistenceModel extends CoreModel {
47
48
  description: 'ID of the persistence object',
48
49
  nullable: true,
49
50
  })
51
+ @ApiProperty({ type: String })
50
52
  id: string = undefined;
51
53
 
52
54
  /**
@@ -55,6 +57,7 @@ export abstract class CorePersistenceModel extends CoreModel {
55
57
  @Restricted(RoleEnum.S_EVERYONE)
56
58
  @Field({ description: 'Created date', nullable: true })
57
59
  @Prop({ onCreate: () => new Date() })
60
+ @ApiProperty({ example: 1740037703939, format: 'int64', type: Date })
58
61
  createdAt: Date = undefined;
59
62
 
60
63
  /**
@@ -63,6 +66,7 @@ export abstract class CorePersistenceModel extends CoreModel {
63
66
  @Restricted(RoleEnum.S_EVERYONE)
64
67
  @Field({ description: 'Updated date', nullable: true })
65
68
  @Prop({ onUpdate: () => new Date() })
69
+ @ApiProperty({ example: 1740037703939, format: 'int64', type: String })
66
70
  updatedAt: Date = undefined;
67
71
 
68
72
  // ===========================================================================
@@ -1,7 +1,13 @@
1
1
  import { Body, Controller, Get, ParseBoolPipe, Post, Query, Res, UseGuards } from '@nestjs/common';
2
- import { ApiBody, ApiOperation, ApiResponse } from '@nestjs/swagger';
2
+ import {
3
+ ApiBody, ApiCreatedResponse,
4
+ ApiOkResponse,
5
+ ApiOperation,
6
+ ApiQuery,
7
+ } from '@nestjs/swagger';
3
8
  import { Response as ResponseType } from 'express';
4
9
 
10
+ import { ApiCommonErrorResponses } from '../../common/decorators/common-error.decorator';
5
11
  import { CurrentUser } from '../../common/decorators/current-user.decorator';
6
12
  import { Roles } from '../../common/decorators/roles.decorator';
7
13
  import { RoleEnum } from '../../common/enums/role.enum';
@@ -17,6 +23,7 @@ import { Tokens } from './tokens.decorator';
17
23
 
18
24
  @Roles(RoleEnum.ADMIN)
19
25
  @Controller('auth')
26
+ @ApiCommonErrorResponses()
20
27
  export class CoreAuthController {
21
28
  /**
22
29
  * Import services
@@ -30,6 +37,8 @@ export class CoreAuthController {
30
37
  * Logout user (from specific device)
31
38
  */
32
39
  @ApiOperation({ description: 'Logs a user out from a specific device' })
40
+ @ApiQuery({ description: 'If all devices should be logged out,', name: 'allDevices', required: false, type: Boolean })
41
+ @ApiOkResponse({ type: Boolean })
33
42
  @Get('logout')
34
43
  @Roles(RoleEnum.S_EVERYONE)
35
44
  @UseGuards(AuthGuard(AuthGuardStrategy.JWT))
@@ -37,7 +46,7 @@ export class CoreAuthController {
37
46
  @CurrentUser() currentUser: ICoreAuthUser,
38
47
  @Tokens('token') token: string,
39
48
  @Res({ passthrough: true }) res: ResponseType,
40
- @Query('allDevices', ParseBoolPipe) allDevices?: boolean,
49
+ @Query('allDevices', new ParseBoolPipe({ optional: true })) allDevices?: boolean,
41
50
  ): Promise<boolean> {
42
51
  const result = await this.authService.logout(token, { allDevices, currentUser });
43
52
  return this.processCookies(res, result);
@@ -46,7 +55,8 @@ export class CoreAuthController {
46
55
  /**
47
56
  * Refresh token (for specific device)
48
57
  */
49
- @ApiResponse({ type: CoreAuthModel })
58
+ @ApiOperation({ description: 'Refresh token (for specific device)' })
59
+ @ApiOkResponse({ type: CoreAuthModel })
50
60
  @Get('refresh-token')
51
61
  @Roles(RoleEnum.S_EVERYONE)
52
62
  @UseGuards(AuthGuard(AuthGuardStrategy.JWT_REFRESH))
@@ -63,6 +73,7 @@ export class CoreAuthController {
63
73
  * Sign in user via email and password (on specific device)
64
74
  */
65
75
  @ApiOperation({ description: 'Sign in via email and password' })
76
+ @ApiCreatedResponse({ description: 'Signed in successfully', type: CoreAuthModel })
66
77
  @Post('signin')
67
78
  @Roles(RoleEnum.S_EVERYONE)
68
79
  async signIn(@Res({ passthrough: true }) res: ResponseType, @Body() input: CoreAuthSignInInput): Promise<CoreAuthModel> {
@@ -75,9 +86,10 @@ export class CoreAuthController {
75
86
  */
76
87
  @ApiBody({ type: CoreAuthSignUpInput })
77
88
  @ApiOperation({ description: 'Sign up via email and password' })
89
+ @ApiCreatedResponse({ type: CoreAuthSignUpInput })
78
90
  @Post('signup')
79
91
  @Roles(RoleEnum.S_EVERYONE)
80
- async signUp(@Res() res: ResponseType, @Body() input: CoreAuthSignUpInput): Promise<CoreAuthModel> {
92
+ async signUp(@Res({ passthrough: true }) res: ResponseType, @Body() input: CoreAuthSignUpInput): Promise<CoreAuthModel> {
81
93
  const result = await this.authService.signUp(input);
82
94
  return this.processCookies(res, result);
83
95
  }
@@ -1,6 +1,6 @@
1
1
  import { Field, ObjectType } from '@nestjs/graphql';
2
2
  import { Schema as MongooseSchema, Prop, raw } from '@nestjs/mongoose';
3
- import { ApiProperty } from '@nestjs/swagger';
3
+ import { ApiExtraModels, ApiProperty } from '@nestjs/swagger';
4
4
  import { IsOptional } from 'class-validator';
5
5
  import { Document } from 'mongoose';
6
6
 
@@ -17,6 +17,7 @@ export type CoreUserModelDocument = CoreUserModel & Document;
17
17
  @Restricted(RoleEnum.S_EVERYONE)
18
18
  @ObjectType({ description: 'User', isAbstract: true })
19
19
  @MongooseSchema({ timestamps: true })
20
+ @ApiExtraModels(CorePersistenceModel)
20
21
  export abstract class CoreUserModel extends CorePersistenceModel {
21
22
  // ===================================================================================================================
22
23
  // Properties
package/src/index.ts CHANGED
@@ -9,6 +9,7 @@ export * from './core.module';
9
9
  // =====================================================================================================================
10
10
  export * from './core/common/args/filter.args';
11
11
  export * from './core/common/args/pagination.args';
12
+ export * from './core/common/decorators/common-error.decorator';
12
13
  export * from './core/common/decorators/current-user.decorator';
13
14
  export * from './core/common/decorators/graphql-populate.decorator';
14
15
  export * from './core/common/decorators/graphql-service-options.decorator';
@@ -1,5 +1,6 @@
1
1
  import { Field, ObjectType } from '@nestjs/graphql';
2
2
  import { Prop } from '@nestjs/mongoose';
3
+ import { ApiExtraModels, ApiProperty } from '@nestjs/swagger';
3
4
  import { Types } from 'mongoose';
4
5
 
5
6
  import { Restricted } from '../../../core/common/decorators/restricted.decorator';
@@ -19,6 +20,7 @@ import mongoose = require('mongoose');
19
20
  description: 'Persistence model which will be saved in DB',
20
21
  isAbstract: true,
21
22
  })
23
+ @ApiExtraModels(CorePersistenceModel)
22
24
  export abstract class PersistenceModel extends CorePersistenceModel {
23
25
  // ===================================================================================================================
24
26
  // Properties
@@ -35,6 +37,7 @@ export abstract class PersistenceModel extends CorePersistenceModel {
35
37
  nullable: true,
36
38
  })
37
39
  @Prop({ ref: 'User', type: mongoose.Schema.Types.ObjectId })
40
+ @ApiProperty({ type: String })
38
41
  createdBy?: Types.ObjectId | string = undefined;
39
42
 
40
43
  /**
@@ -48,6 +51,7 @@ export abstract class PersistenceModel extends CorePersistenceModel {
48
51
  nullable: true,
49
52
  })
50
53
  @Prop({ ref: 'User', type: mongoose.Schema.Types.ObjectId })
54
+ @ApiProperty({ type: User })
51
55
  updatedBy?: Types.ObjectId | string = undefined;
52
56
 
53
57
  // ===================================================================================================================