Skip to content

Commit d8c1141

Browse files
author
hersveit
authored
Merge pull request #31 from fullstack-development/response-refactor
Response refactor
2 parents a63f882 + 2372cd7 commit d8c1141

26 files changed

+394
-326
lines changed

api/.eslintrc.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,5 +45,6 @@ module.exports = {
4545
hoist: 'all',
4646
},
4747
],
48+
'@typescript-eslint/no-namespace': ['off'],
4849
},
4950
};

api/package.json

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"scripts": {
1010
"buildPrepare": "node buildPrepare.js",
1111
"build": "rimraf dist && yarn buildPrepare && nest build --webpack --webpackPath webpack.references.config.js",
12-
"format": "prettier --write \"src/**/*.ts\"",
12+
"format": "prettier --end-of-line lf --write \"src/**/*.ts\"",
1313
"start:dev": "yarn buildPrepare && cross-env NODE_ENV=development nest start --webpack --webpackPath webpack.references.config.js --watch",
1414
"start:debug": "yarn buildPrepare && cross-env NODE_ENV=development nest start --webpack --webpackPath webpack.references.config.js --debug --watch",
1515
"start:prod": "yarn buildPrepare && cross-env NODE_ENV=production node dist/main",
@@ -19,11 +19,11 @@
1919
},
2020
"dependencies": {
2121
"@medibloc/nestjs-request-context": "^1.0.0",
22-
"@nestjs/common": "^9.0.0",
23-
"@nestjs/core": "^9.0.0",
24-
"@nestjs/jwt": "^9.0.0",
22+
"@nestjs/common": "^9.2.1",
23+
"@nestjs/core": "^9.2.1",
24+
"@nestjs/jwt": "^10.0.1",
2525
"@nestjs/passport": "^9.0.0",
26-
"@nestjs/platform-express": "^9.0.0",
26+
"@nestjs/platform-express": "^9.2.1",
2727
"@nestjs/schedule": "^2.1.0",
2828
"body-parser": "^1.19.0",
2929
"class-transformer": "^0.3.1",
@@ -41,14 +41,15 @@
4141
"rimraf": "^3.0.2",
4242
"rxjs": "^7.2.0",
4343
"swagger-ui-express": "^4.5.0",
44+
"ts-morph": "^17.0.1",
4445
"uuid": "^8.3.2",
4546
"yamljs": "^0.3.0"
4647
},
4748
"devDependencies": {
4849
"@golevelup/ts-jest": "^0.3.2",
49-
"@nestjs/cli": "^9.0.0",
50-
"@nestjs/schematics": "^9.0.0",
51-
"@nestjs/testing": "^9.0.0",
50+
"@nestjs/cli": "^9.1.9",
51+
"@nestjs/schematics": "^9.0.4",
52+
"@nestjs/testing": "^9.2.1",
5253
"@types/cookie-parser": "^1.4.2",
5354
"@types/express": "^4.17.13",
5455
"@types/jest": "28.1.8",

api/src/controllers/app.controller.ts

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,27 @@ import { ControllerResponse } from './../core/controller.core';
44
@Controller('api')
55
export class AppControllerProvider {
66
@Get('echo')
7-
echo(@Query() query: unknown, @Body() body: unknown) {
8-
return ControllerResponse.Success({
9-
headers: {
10-
'Content-Type': 'application/json',
7+
async echo(
8+
@Query() query: unknown,
9+
@Body() body: unknown,
10+
): Promise<
11+
ControllerResponse<
12+
{
13+
query: unknown;
14+
body: unknown;
1115
},
12-
body: {
16+
'Content-Type'
17+
>
18+
> {
19+
return new ControllerResponse(
20+
{
1321
query: query && typeof query === 'object' ? JSON.stringify(query) : query,
1422
body: body && typeof body === 'object' ? JSON.stringify(body) : body,
1523
},
16-
});
24+
{
25+
'Content-Type': 'application/json',
26+
},
27+
);
1728
}
1829
}
1930

api/src/controllers/auth/__tests__/auth.controller.spec.ts

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ describe('AuthController', () => {
124124
password: '123456789',
125125
});
126126
expect(response.statusCode).toEqual(200);
127-
expect(response.body).toEqual({ success: true });
127+
expect(response.body).toEqual({});
128128
});
129129
});
130130

@@ -163,10 +163,7 @@ describe('AuthController', () => {
163163
password: '123456789',
164164
});
165165
expect(response.statusCode).toEqual(200);
166-
expect(response.body).toEqual({
167-
success: true,
168-
data: '1',
169-
});
166+
expect(response.body).toEqual({ token: '1' });
170167
expect(response.headers['set-cookie']).toEqual(['2']);
171168
});
172169
});
@@ -196,10 +193,7 @@ describe('AuthController', () => {
196193

197194
expect(authService.confirmEmail).toBeCalledWith(confirmUuid);
198195
expect(response.statusCode).toEqual(200);
199-
expect(response.body).toEqual({
200-
success: true,
201-
data: '1',
202-
});
196+
expect(response.body).toEqual({ token: '1' });
203197
expect(response.headers['set-cookie']).toEqual(['2']);
204198
});
205199
});

api/src/controllers/auth/auth.controller.ts

Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,15 @@ import { JwtUserRefreshGuard } from '../../services/auth/guards/jwt-user-refresh
55
import { UserType } from '../../services/token/token.model';
66
import { UseValidationPipe } from '../../utils/validation.utils';
77
import { TokenService, TokenServiceProvider } from './../../services/token/token.service';
8-
import { ConfirmEmailInput, SignInInput, SignUpInput } from './auth.model';
8+
import {
9+
ConfirmEmailInput,
10+
ConfirmEmailResponse,
11+
HandleRefreshTokenResponse,
12+
SignInInput,
13+
SignInResponse,
14+
SignUpInput,
15+
SignUpResponse,
16+
} from './auth.model';
917

1018
@Controller('api/auth')
1119
export class AuthControllerProvider {
@@ -16,42 +24,40 @@ export class AuthControllerProvider {
1624

1725
@Post('sign-up')
1826
@UseValidationPipe()
19-
async signUp(@Body() body: SignUpInput) {
20-
return mapResponse(await this.authService.signUp(body))(() => ControllerResponse.Success());
27+
async signUp(@Body() body: SignUpInput): Promise<SignUpResponse> {
28+
return mapResponse(
29+
await this.authService.signUp(body),
30+
() => new ControllerResponse<never, never>(),
31+
);
2132
}
2233

2334
@Post('sign-in')
2435
@UseValidationPipe()
25-
async signIn(@Body() body: SignInInput) {
26-
return mapResponse(await this.authService.signIn(body))(({ accessToken, refreshCookie }) =>
27-
ControllerResponse.Success({
28-
body: accessToken,
29-
headers: { 'Set-Cookie': refreshCookie },
30-
}),
36+
async signIn(@Body() body: SignInInput): Promise<SignInResponse> {
37+
return mapResponse(
38+
await this.authService.signIn(body),
39+
({ accessToken, refreshCookie }) =>
40+
new ControllerResponse({ token: accessToken }, { 'Set-Cookie': refreshCookie }),
3141
);
3242
}
3343

3444
@Post('confirm-email')
3545
@UseValidationPipe()
36-
async confirmEmail(@Body() { confirmUuid }: ConfirmEmailInput) {
37-
return mapResponse(await this.authService.confirmEmail(confirmUuid))(
46+
async confirmEmail(@Body() { confirmUuid }: ConfirmEmailInput): Promise<ConfirmEmailResponse> {
47+
return mapResponse(
48+
await this.authService.confirmEmail(confirmUuid),
3849
({ accessToken, refreshCookie }) =>
39-
ControllerResponse.Success({
40-
body: accessToken,
41-
headers: { 'Set-Cookie': refreshCookie },
42-
}),
50+
new ControllerResponse({ token: accessToken }, { 'Set-Cookie': refreshCookie }),
4351
);
4452
}
4553

4654
@Get('refresh')
4755
@UseGuards(JwtUserRefreshGuard)
48-
async handleRefreshToken(@User() user: RequestUser) {
49-
return mapResponse(await this.tokenService.generate(user.id, UserType.USER, user.email))(
56+
async handleRefreshToken(@User() user: RequestUser): Promise<HandleRefreshTokenResponse> {
57+
return mapResponse(
58+
await this.tokenService.generate(user.id, UserType.USER, user.email),
5059
({ accessToken, refreshCookie }) =>
51-
ControllerResponse.Success({
52-
body: accessToken,
53-
headers: { 'Set-Cookie': refreshCookie },
54-
}),
60+
new ControllerResponse({ token: accessToken }, { 'Set-Cookie': refreshCookie }),
5561
);
5662
}
5763
}

api/src/controllers/auth/auth.model.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,12 @@
11
import { IsEmail, IsString, IsUUID, MaxLength, MinLength } from 'class-validator';
2+
import { ControllerResponse } from '../../core/controller.core';
3+
import { CannotFindEmailConfirm, CannotFindUser } from '../../core/database/database.model';
4+
import {
5+
CannotSendEmailConfirmation,
6+
EmailAlreadyConfirmed,
7+
EmailNotConfirmed,
8+
} from '../../services/auth/auth.model';
9+
import { EmailOrPasswordIncorrect, UserAlreadyExist } from '../../services/user/user.model';
210

311
export class SignUpInput {
412
@IsEmail()
@@ -24,3 +32,24 @@ export class ConfirmEmailInput {
2432
@IsUUID('4')
2533
confirmUuid: string;
2634
}
35+
36+
export type SignUpResponse =
37+
| ControllerResponse<never, never>
38+
| UserAlreadyExist
39+
| CannotSendEmailConfirmation;
40+
41+
export type SignInResponse =
42+
| CannotFindUser
43+
| EmailOrPasswordIncorrect
44+
| EmailNotConfirmed
45+
| ControllerResponse<{ token: string }, 'Set-Cookie'>;
46+
47+
export type ConfirmEmailResponse =
48+
| ControllerResponse<{ token: string }, 'Set-Cookie'>
49+
| CannotFindUser
50+
| EmailAlreadyConfirmed
51+
| CannotFindEmailConfirm;
52+
53+
export type HandleRefreshTokenResponse =
54+
| ControllerResponse<{ token: string }, 'Set-Cookie'>
55+
| CannotFindUser;

api/src/controllers/user/__tests__/user.controller.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ describe('UserController', () => {
121121
.send();
122122

123123
expect(response.statusCode).toEqual(200);
124-
expect(omit(['created'], response.body.data)).toEqual(
124+
expect(omit(['created'], response.body)).toEqual(
125125
omit(['refreshToken', 'created', 'emailConfirm', 'hash'], user),
126126
);
127127
});

api/src/controllers/user/user.controller.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,20 @@ import * as R from 'ramda';
33
import { ControllerResponse, mapResponse, RequestUser, User } from '../../core/controller.core';
44
import { JwtUserGuard } from '../../services/auth/guards/jwt-user.guard';
55
import { UserService, UserServiceProvider } from '../../services/user/user.service';
6+
import { MeResponse as MRS } from './user.model';
67

78
@Controller('api/user')
89
export class UserControllerProvider {
910
constructor(private users: UserServiceProvider) {}
1011

1112
@Get('me')
1213
@UseGuards(JwtUserGuard)
13-
async me(@User() { id }: RequestUser) {
14-
return mapResponse(await this.users.findUser({ id }))((user) => {
15-
return ControllerResponse.Success({
16-
body: R.omit(['refreshToken', 'emailConfirm', 'hash'], user),
17-
});
18-
});
14+
async me(@User() { id }: RequestUser): Promise<MRS> {
15+
return mapResponse(
16+
await this.users.findUser({ id }),
17+
(user) =>
18+
new ControllerResponse(R.omit(['refreshToken', 'emailConfirm', 'hash'], user)),
19+
);
1920
}
2021
}
2122

api/src/controllers/user/user.model.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1+
import { EmailConfirm, RefreshToken, User } from '@lib/repository';
12
import { plainToClass, Transform, Type } from 'class-transformer';
23
import { IsOptional, ValidateNested } from 'class-validator';
4+
import { ControllerResponse } from '../../core/controller.core';
5+
import { CannotFindUser as CFU } from '../../core/database/database.model';
36
import { CompareDateQuery, CompareNumberQuery, IsSafeInteger } from '../../utils/validation.utils';
47

58
export class QueryParams {
@@ -49,3 +52,16 @@ export class QueryParams {
4952
@IsSafeInteger()
5053
pageSize = 50;
5154
}
55+
56+
export type MeResponse =
57+
| CFU
58+
| ControllerResponse<
59+
Omit<
60+
User & {
61+
refreshToken: RefreshToken | null;
62+
emailConfirm: EmailConfirm | null;
63+
},
64+
'refreshToken' | 'emailConfirm' | 'hash'
65+
>,
66+
never
67+
>;

0 commit comments

Comments
 (0)