-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
New
committed
Dec 17, 2021
1 parent
0a5ce5a
commit 9b1306e
Showing
25 changed files
with
485 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,6 @@ | ||
# environment config | ||
.env | ||
|
||
# compiled output | ||
/dist | ||
/node_modules | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,22 @@ | ||
import { Module } from '@nestjs/common'; | ||
import { ConfigModule } from '@nestjs/config'; | ||
import { AppController } from './app.controller'; | ||
import { AllHttpExceptionsFilter } from './common'; | ||
import { configuration } from './config/configuration'; | ||
import { validationSchema } from './config/validation'; | ||
import { FavoriteModule } from './favorite/favorite.module'; | ||
import { ProfileModule } from './profile/profile.module'; | ||
import { SimulatorModule } from './simulator/simulator.module'; | ||
|
||
@Module({ | ||
imports: [FavoriteModule, ProfileModule, SimulatorModule], | ||
imports: [ | ||
ConfigModule.forRoot({ | ||
isGlobal: true, | ||
load: [configuration], | ||
validationSchema: validationSchema, | ||
}), | ||
FavoriteModule, ProfileModule, SimulatorModule], | ||
controllers: [AppController], | ||
providers: [], | ||
providers: [AllHttpExceptionsFilter], | ||
}) | ||
export class AppModule {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import { | ||
HttpException, | ||
HttpStatus, | ||
ValidationError as NestValidationError, | ||
} from '@nestjs/common'; | ||
import { ValidationError } from '../interfaces'; | ||
|
||
export class HttpValidationException extends HttpException { | ||
constructor(validationErrors: NestValidationError[]) { | ||
let errors: ValidationError[] = []; | ||
|
||
for (const error of validationErrors) { | ||
errors = errors.concat(HttpValidationException.exportErrors(error)); | ||
} | ||
|
||
super(errors, HttpStatus.OK); | ||
} | ||
|
||
private static exportErrors( | ||
error: NestValidationError, | ||
propertyPrefix = '', | ||
): ValidationError[] { | ||
let errors: ValidationError[] = []; | ||
|
||
for (const constraint in error.constraints) { | ||
errors.push({ | ||
property: propertyPrefix + error.property, | ||
constraint, | ||
error: error.constraints[constraint], | ||
}); | ||
} | ||
|
||
error.children.forEach((child) => { | ||
const childErrors = this.exportErrors( | ||
child, | ||
propertyPrefix + error.property + '.', | ||
); | ||
errors = errors.concat(childErrors); | ||
}); | ||
|
||
return errors; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './http-validation-exception'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
import { | ||
ArgumentsHost, | ||
Catch, | ||
ExceptionFilter, | ||
HttpException, | ||
} from '@nestjs/common'; | ||
import { Response } from 'express'; | ||
import { HttpValidationException } from '../exceptions'; | ||
import { | ||
JSendErrorResponse, JSendFailResponse, ValidationError | ||
} from '../interfaces'; | ||
|
||
@Catch() | ||
export class AllHttpExceptionsFilter implements ExceptionFilter { | ||
constructor() {} | ||
|
||
catch(exception: unknown, host: ArgumentsHost) { | ||
const response = host.switchToHttp().getResponse<Response>(); | ||
this.handleException(response, exception); | ||
} | ||
|
||
private handleException(response: Response, exception: unknown): void { | ||
if (exception instanceof HttpValidationException) { | ||
// If Validation Error => Respond with JSend Fail | ||
const errors = exception.getResponse() as ValidationError[] | ||
|
||
const result: JSendFailResponse<any> = { | ||
status: 'fail', | ||
data: errors.reduce((previous, current) => { | ||
previous[current.property] = current.error | ||
return previous | ||
}, {}) | ||
}; | ||
|
||
response.status(400).send(result); | ||
} else if (exception instanceof HttpException) { | ||
const result: JSendErrorResponse = { | ||
status: 'error', | ||
code: exception.getStatus(), | ||
message: exception.message, | ||
}; | ||
|
||
// Include stack trace | ||
// result.data = exception.stack | ||
|
||
response.status(exception.getStatus()).send(result); | ||
} else if (typeof (exception as any).message === 'string') { | ||
const result: JSendErrorResponse = { | ||
status: 'error', | ||
message: (exception as any).message, | ||
}; | ||
|
||
// Include stack trace | ||
// result.data = exception | ||
|
||
response.status(500).send(result); | ||
} else { | ||
const result: JSendErrorResponse = { | ||
status: 'error', | ||
message: 'Unhandled error occurred', | ||
data: exception | ||
}; | ||
response.status(500).send(result); | ||
} | ||
|
||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './all-http-exceptions.filter'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
export * from './exceptions' | ||
export * from './filters'; | ||
export * from './interfaces'; | ||
export * from './interceptors' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './jsend.interceptor'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import { JsendInterceptor } from './jsend.interceptor'; | ||
|
||
describe('JsendInterceptor', () => { | ||
it('should be defined', () => { | ||
expect(new JsendInterceptor()).toBeDefined(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import { CallHandler, ExecutionContext, Injectable, NestInterceptor } from '@nestjs/common'; | ||
import { Observable } from 'rxjs'; | ||
import { map } from 'rxjs/operators'; | ||
import { JSendSuccessResponse } from '../interfaces'; | ||
|
||
@Injectable() | ||
export class JsendInterceptor implements NestInterceptor { | ||
intercept(context: ExecutionContext, next: CallHandler): Observable<any> { | ||
return next.handle().pipe(map((data: unknown) => { | ||
if (data === undefined) { | ||
data = null | ||
} | ||
|
||
const response: JSendSuccessResponse<typeof data> = { | ||
status: 'success', | ||
data | ||
} | ||
return response | ||
})); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export * from './responses'; | ||
export * from './validation-error.interface' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export * from './jsend'; | ||
export * from './response-message' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
export * from './jsend-error-response'; | ||
export * from './jsend-fail-response'; | ||
export * from './jsend-response'; | ||
export * from './jsend-success-response'; |
41 changes: 41 additions & 0 deletions
41
src/common/interfaces/responses/jsend/jsend-error-response.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
|
||
/** | ||
* ## Generic JSend Error Response | ||
* | ||
* When an API call fails due to an error on the server. For example: | ||
* #### GET /posts.json: #### | ||
* ``` | ||
* { | ||
* "status" : "error", | ||
* "message" : "Unable to communicate with database" | ||
* } | ||
* ``` | ||
* Required keys: | ||
* * status: Should always be set to "error". | ||
* * message: A meaningful, end-user-readable (or at the least log-worthy) message, explaining what went wrong. | ||
* | ||
* Optional keys: | ||
* * code: A numeric code corresponding to the error, if applicable | ||
* * data: A generic container for any other information about the error, i.e. the conditions that caused the error, stack traces, etc. | ||
*/ | ||
export interface JSendErrorResponse { | ||
/** | ||
* Should always be set to "error" | ||
*/ | ||
status: 'error' | ||
|
||
/** | ||
* A meaningful, end-user-readable (or at the least log-worthy) message, explaining what went wrong. | ||
*/ | ||
message: string | ||
|
||
/** | ||
* A numeric code corresponding to the error, if applicable | ||
*/ | ||
code?: number | ||
|
||
/** | ||
* A generic container for any other information about the error, i.e. the conditions that caused the error, stack traces, etc. | ||
*/ | ||
data?: any | ||
} |
27 changes: 27 additions & 0 deletions
27
src/common/interfaces/responses/jsend/jsend-fail-response.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
/** | ||
* Generic JSend Fail Response | ||
* When an API call is rejected due to invalid data or call conditions, the JSend object's data key contains an object explaining what went wrong, typically a hash of validation errors. For example: | ||
* #### POST /posts.json (with data body: "Trying to creating a blog post"): #### | ||
* ``` | ||
* { | ||
* "status" : "fail", | ||
* "data" : { "title" : "A title is required" } | ||
* } | ||
* ``` | ||
* Required keys: | ||
* | ||
* * status: Should always be set to "fail". | ||
* * data: Provides the wrapper for the details of why the request failed. If the reasons for failure correspond to POST values, the response object's keys SHOULD correspond to those POST values. | ||
*/ | ||
export interface JSendFailResponse<T> { | ||
/** | ||
* Should always be set to "fail". | ||
*/ | ||
status: 'fail' | ||
|
||
/** | ||
* Provides the wrapper for the details of why the request failed. | ||
* If the reasons for failure correspond to POST values, the response object's keys SHOULD correspond to those POST values. | ||
*/ | ||
data: T | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
/** | ||
* Generic JSend Response | ||
* https://github.com/omniti-labs/jsend | ||
*/ | ||
export interface JSendResponse<T> { | ||
/** | ||
* success: All went well, and (usually) some data was returned. | ||
* fail: There was a problem with the data submitted, or some pre-condition of the API call wasn't satisfied | ||
* error: An error occurred in processing the request, i.e. an exception was thrown | ||
*/ | ||
status: 'success' | 'fail' | 'error' | ||
|
||
/** | ||
* Acts as the wrapper for any data returned by the API call. If the call returns no data, data should be set to null. | ||
*/ | ||
data: T | ||
|
||
/** | ||
* Only for error | ||
*/ | ||
code: string | undefined | ||
|
||
/** | ||
* Only for error | ||
*/ | ||
message: string | undefined | ||
} |
45 changes: 45 additions & 0 deletions
45
src/common/interfaces/responses/jsend/jsend-success-response.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
/** | ||
* Generic JSend Success Response | ||
* When an API call is successful, the JSend object is used as a simple envelope for the results, using the data key, as in the following: | ||
* #### GET /posts.json: #### | ||
* ``` | ||
* { | ||
* status : "success", | ||
* data : { | ||
* "posts" : [ | ||
* { "id" : 1, "title" : "A blog post", "body" : "Some useful content" }, | ||
* { "id" : 2, "title" : "Another blog post", "body" : "More content" }, | ||
* ] | ||
* } | ||
* } | ||
* ``` | ||
* #### GET /posts/2.json: #### | ||
* ``` | ||
* { | ||
* status : "success", | ||
* data : { "post" : { "id" : 2, "title" : "Another blog post", "body" : "More content" }} | ||
* } | ||
* ``` | ||
* #### DELETE /posts/2.json: #### | ||
* ``` | ||
* { | ||
* status : "success", | ||
* data : null | ||
* } | ||
* ``` | ||
* Required keys: | ||
* | ||
* * status: Should always be set to "success". | ||
* * data: Acts as the wrapper for any data returned by the API call. If the call returns no data (as in the last example), data should be set to null. | ||
*/ | ||
export interface JSendSuccessResponse<T> { | ||
/** | ||
* Should always be success | ||
*/ | ||
status: 'success' | ||
|
||
/** | ||
* Acts as the wrapper for any data returned by the API call. If the call returns no data, data should be set to null. | ||
*/ | ||
data: T | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export interface ResponseMessage { | ||
message: string | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
export interface ValidationError { | ||
/** | ||
* Property which rejected in validation check | ||
*/ | ||
property: string; | ||
|
||
/** | ||
* Constraint which caused the validation to be rejected | ||
*/ | ||
constraint: string; | ||
|
||
/** | ||
* Error message | ||
*/ | ||
error: string; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
export const configuration = () => { | ||
return { | ||
environment: process.env.NODE_ENV, | ||
port: parseInt(process.env.PORT, 10) || 3000, | ||
db_url: process.env.DB_URL, | ||
cors_origins: process.env.CORS_ORIGINS | ||
} | ||
} |
Oops, something went wrong.