response-standardizer 1.1.1 → 1.1.3
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/dist/index.d.ts +2 -0
- package/dist/index.js +29 -13
- package/dist/service.exception.d.ts +5 -0
- package/dist/service.exception.js +8 -0
- package/dist/types.d.ts +5 -7
- package/package.json +1 -1
- package/src/index.ts +28 -17
- package/src/service.exception.ts +10 -0
- package/src/types.ts +5 -9
- package/src/utils.ts +2 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Request, Response } from "express";
|
|
1
2
|
import { RestResponseFunctions, RestMiddlewareFunctions } from "./types.js";
|
|
2
3
|
declare global {
|
|
3
4
|
namespace Express {
|
|
@@ -22,3 +23,4 @@ export declare const error: (message: string, meta?: any) => void;
|
|
|
22
23
|
export declare const warn: (message: string, meta?: any) => void;
|
|
23
24
|
export declare const info: (message: string, meta?: any) => void;
|
|
24
25
|
export declare const log: (level: "INFO" | "WARN" | "ERROR", message: string, meta?: any) => void;
|
|
26
|
+
export declare const handleRestException: (req: Request, res: Response, err: Error) => void;
|
package/dist/index.js
CHANGED
|
@@ -2,6 +2,7 @@ import { generateRequestId, getTimestamp } from "./utils.js";
|
|
|
2
2
|
import axios from "axios";
|
|
3
3
|
import jwt from "jsonwebtoken";
|
|
4
4
|
import path from "path";
|
|
5
|
+
import { ServiceException } from "./service.exception.js";
|
|
5
6
|
let KEYCLOAK_PUBLIC_KEY = null;
|
|
6
7
|
export const initKeycloak = async (config) => {
|
|
7
8
|
const KEYCLOAK_SERVICE = config.service ?? "localhost";
|
|
@@ -51,24 +52,23 @@ const role = (req, res, next, allowedRoles) => {
|
|
|
51
52
|
}
|
|
52
53
|
next();
|
|
53
54
|
};
|
|
54
|
-
const success = (req, res, data
|
|
55
|
-
res.status(200).json(
|
|
55
|
+
const success = (req, res, data) => {
|
|
56
|
+
res.status(200).json(data);
|
|
56
57
|
};
|
|
57
|
-
const paginate = (req, res, data
|
|
58
|
-
res.status(200).json(
|
|
58
|
+
const paginate = (req, res, data) => {
|
|
59
|
+
res.status(200).json(data);
|
|
59
60
|
};
|
|
60
|
-
const created = (req, res, data
|
|
61
|
-
res.status(201).json(
|
|
61
|
+
const created = (req, res, data) => {
|
|
62
|
+
res.status(201).json(data);
|
|
62
63
|
};
|
|
63
64
|
const deleted = (req, res) => {
|
|
64
65
|
res.status(204).send();
|
|
65
66
|
};
|
|
66
67
|
const validationError = (req, res, errors, message = "Validation error") => {
|
|
67
|
-
res.status(400).json({ errors, message
|
|
68
|
+
res.status(400).json({ errors, message });
|
|
68
69
|
};
|
|
69
70
|
const exceptionError = (req, res, errors, message = "Internal server error") => {
|
|
70
71
|
res.status(500).json({
|
|
71
|
-
data: null,
|
|
72
72
|
message,
|
|
73
73
|
errors
|
|
74
74
|
});
|
|
@@ -95,20 +95,17 @@ const responseHandlerMiddleware = (req, res, next) => {
|
|
|
95
95
|
res.json = function (data) {
|
|
96
96
|
if (res.statusCode > 204) {
|
|
97
97
|
const response = {
|
|
98
|
-
status: res.statusCode >= 200 && res.statusCode < 300 ? "success" : "error",
|
|
99
98
|
code: res.statusCode,
|
|
100
99
|
message: data?.message || res.locals.message || (res.statusCode < 300 ? "OK" : "Error"),
|
|
101
|
-
data: data?.data ?? null,
|
|
102
100
|
errors: data?.errors ?? null,
|
|
103
101
|
meta: {
|
|
104
102
|
requestId: res.locals.requestId || generateRequestId(),
|
|
105
|
-
timestamp: getTimestamp()
|
|
106
|
-
pagination: data?.pagination ?? null
|
|
103
|
+
timestamp: getTimestamp()
|
|
107
104
|
}
|
|
108
105
|
};
|
|
109
106
|
return oldJson(response);
|
|
110
107
|
}
|
|
111
|
-
return oldJson(data
|
|
108
|
+
return oldJson(data);
|
|
112
109
|
};
|
|
113
110
|
res.send = function (data) {
|
|
114
111
|
if (res.statusCode === 204) {
|
|
@@ -166,3 +163,22 @@ export const log = (level, message, meta) => {
|
|
|
166
163
|
// چاپ لاگ
|
|
167
164
|
console.log(`${color}[${timestamp}][${location}][${level}] ${message}${metaStr}${colors.RESET}`);
|
|
168
165
|
};
|
|
166
|
+
export const handleRestException = (req, res, err) => {
|
|
167
|
+
if (err instanceof ServiceException) {
|
|
168
|
+
if (err?.status === 401) {
|
|
169
|
+
RestResponse.unauthorized(req, res, err.message);
|
|
170
|
+
}
|
|
171
|
+
else if (err?.status === 403) {
|
|
172
|
+
RestResponse.accessDenied(req, res, err.message);
|
|
173
|
+
}
|
|
174
|
+
else if (err?.status === 400) {
|
|
175
|
+
RestResponse.validationError(req, res, err.errors);
|
|
176
|
+
}
|
|
177
|
+
else if (err?.status === 500) {
|
|
178
|
+
RestResponse.exceptionError(req, res, err.message);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
else if (err instanceof Error) {
|
|
182
|
+
RestResponse.exceptionError(req, res, err.message);
|
|
183
|
+
}
|
|
184
|
+
};
|
package/dist/types.d.ts
CHANGED
|
@@ -1,17 +1,15 @@
|
|
|
1
1
|
import { Request, Response, NextFunction } from "express";
|
|
2
2
|
export interface StandardResponse<T = any> {
|
|
3
|
-
status: "success" | "error";
|
|
4
3
|
code: number;
|
|
5
4
|
message: string;
|
|
6
|
-
data: T | null;
|
|
7
5
|
errors: Record<string, string[]> | null;
|
|
8
6
|
meta: {
|
|
9
7
|
requestId: string;
|
|
10
8
|
timestamp: string;
|
|
11
|
-
pagination: PaginationMeta | null;
|
|
12
9
|
};
|
|
13
10
|
}
|
|
14
|
-
export interface
|
|
11
|
+
export interface Pagination<T> {
|
|
12
|
+
data: T[];
|
|
15
13
|
total: number;
|
|
16
14
|
page: number;
|
|
17
15
|
perPage: number;
|
|
@@ -23,9 +21,9 @@ export interface RestMiddlewareFunctions {
|
|
|
23
21
|
responseHandlerMiddleware: <T>(req: Request, res: Response, next: NextFunction) => void;
|
|
24
22
|
}
|
|
25
23
|
export interface RestResponseFunctions {
|
|
26
|
-
success: <T>(req: Request, res: Response, data: T
|
|
27
|
-
paginate: <T>(req: Request, res: Response, data: T
|
|
28
|
-
created: <T>(req: Request, res: Response, data: T
|
|
24
|
+
success: <T>(req: Request, res: Response, data: T) => void;
|
|
25
|
+
paginate: <T>(req: Request, res: Response, data: Pagination<T>) => void;
|
|
26
|
+
created: <T>(req: Request, res: Response, data: T) => void;
|
|
29
27
|
deleted: (req: Request, res: Response) => void;
|
|
30
28
|
validationError: (req: Request, res: Response, errors: ErrorFields, message?: string) => void;
|
|
31
29
|
exceptionError: (req: Request, res: Response, errors: any, message?: string) => void;
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { Request, Response, NextFunction } from "express";
|
|
2
|
-
import { ErrorFields,
|
|
2
|
+
import { ErrorFields, StandardResponse, RestResponseFunctions, RestMiddlewareFunctions, AuthRequest, Pagination } from "./types.js";
|
|
3
3
|
import { generateRequestId, getTimestamp } from "./utils.js";
|
|
4
4
|
import axios from "axios";
|
|
5
5
|
import jwt, { TokenExpiredError } from "jsonwebtoken";
|
|
6
6
|
import path from "path";
|
|
7
|
+
import { ServiceException } from "./service.exception.js";
|
|
7
8
|
declare global {
|
|
8
9
|
namespace Express {
|
|
9
10
|
interface Response {
|
|
@@ -71,22 +72,20 @@ const role = (req: any, res: any, next: any, allowedRoles: string[]) => {
|
|
|
71
72
|
}
|
|
72
73
|
next()
|
|
73
74
|
}
|
|
74
|
-
const success = <T>(req: Request, res: Response, data: T
|
|
75
|
-
res.status(200).json(
|
|
75
|
+
const success = <T>(req: Request, res: Response, data: T) => {
|
|
76
|
+
res.status(200).json(data);
|
|
76
77
|
};
|
|
77
78
|
|
|
78
79
|
const paginate = <T>(
|
|
79
80
|
req: Request,
|
|
80
81
|
res: Response,
|
|
81
|
-
data: T
|
|
82
|
-
pagination: PaginationMeta,
|
|
83
|
-
message: string | null = null
|
|
82
|
+
data: Pagination<T>
|
|
84
83
|
) => {
|
|
85
|
-
res.status(200).json(
|
|
84
|
+
res.status(200).json(data);
|
|
86
85
|
};
|
|
87
86
|
|
|
88
|
-
const created = <T>(req: Request, res: Response, data: T
|
|
89
|
-
res.status(201).json(
|
|
87
|
+
const created = <T>(req: Request, res: Response, data: T) => {
|
|
88
|
+
res.status(201).json(data);
|
|
90
89
|
};
|
|
91
90
|
|
|
92
91
|
const deleted = (req: Request, res: Response) => {
|
|
@@ -99,7 +98,7 @@ const validationError = (
|
|
|
99
98
|
errors: ErrorFields,
|
|
100
99
|
message = "Validation error"
|
|
101
100
|
) => {
|
|
102
|
-
res.status(400).json({ errors, message
|
|
101
|
+
res.status(400).json({ errors, message });
|
|
103
102
|
};
|
|
104
103
|
|
|
105
104
|
const exceptionError = (
|
|
@@ -109,7 +108,6 @@ const exceptionError = (
|
|
|
109
108
|
message = "Internal server error"
|
|
110
109
|
) => {
|
|
111
110
|
res.status(500).json({
|
|
112
|
-
data: null,
|
|
113
111
|
message,
|
|
114
112
|
errors
|
|
115
113
|
});
|
|
@@ -147,21 +145,18 @@ const responseHandlerMiddleware = (
|
|
|
147
145
|
res.json = function (data: any) {
|
|
148
146
|
if(res.statusCode > 204){
|
|
149
147
|
const response: StandardResponse = {
|
|
150
|
-
status: res.statusCode >= 200 && res.statusCode < 300 ? "success" : "error",
|
|
151
148
|
code: res.statusCode,
|
|
152
149
|
message: data?.message || res.locals.message || (res.statusCode < 300 ? "OK" : "Error"),
|
|
153
|
-
data: data?.data ?? null,
|
|
154
150
|
errors: data?.errors ?? null,
|
|
155
151
|
meta: {
|
|
156
152
|
requestId: res.locals.requestId || generateRequestId(),
|
|
157
|
-
timestamp: getTimestamp()
|
|
158
|
-
pagination: data?.pagination ?? null
|
|
153
|
+
timestamp: getTimestamp()
|
|
159
154
|
}
|
|
160
155
|
};
|
|
161
156
|
|
|
162
157
|
return oldJson(response);
|
|
163
158
|
}
|
|
164
|
-
return oldJson(data
|
|
159
|
+
return oldJson(data);
|
|
165
160
|
};
|
|
166
161
|
|
|
167
162
|
res.send = function (data: any) {
|
|
@@ -226,4 +221,20 @@ export const log = (level: "INFO" | "WARN" | "ERROR", message: string, meta?: an
|
|
|
226
221
|
|
|
227
222
|
// چاپ لاگ
|
|
228
223
|
console.log(`${color}[${timestamp}][${location}][${level}] ${message}${metaStr}${colors.RESET}`);
|
|
229
|
-
};
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
export const handleRestException = (req: Request, res: Response, err: Error) => {
|
|
227
|
+
if(err instanceof ServiceException){
|
|
228
|
+
if(err?.status === 401){
|
|
229
|
+
RestResponse.unauthorized(req, res, err.message)
|
|
230
|
+
}else if(err?.status === 403){
|
|
231
|
+
RestResponse.accessDenied(req, res, err.message)
|
|
232
|
+
}else if(err?.status === 400){
|
|
233
|
+
RestResponse.validationError(req, res, err.errors)
|
|
234
|
+
}else if(err?.status === 500){
|
|
235
|
+
RestResponse.exceptionError(req, res, err.message)
|
|
236
|
+
}
|
|
237
|
+
}else if(err instanceof Error){
|
|
238
|
+
RestResponse.exceptionError(req, res, err.message)
|
|
239
|
+
}
|
|
240
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export class ServiceException extends Error {
|
|
2
|
+
status: number;
|
|
3
|
+
errors: any
|
|
4
|
+
constructor(message: string, status: number = 400, errors: any = null) {
|
|
5
|
+
super(message);
|
|
6
|
+
this.name = "ServiceException";
|
|
7
|
+
this.status = status;
|
|
8
|
+
this.errors = errors;
|
|
9
|
+
}
|
|
10
|
+
}
|
package/src/types.ts
CHANGED
|
@@ -1,19 +1,17 @@
|
|
|
1
1
|
import { Request, Response, NextFunction } from "express";
|
|
2
2
|
|
|
3
3
|
export interface StandardResponse<T = any> {
|
|
4
|
-
status: "success" | "error";
|
|
5
4
|
code: number;
|
|
6
5
|
message: string;
|
|
7
|
-
data: T | null;
|
|
8
6
|
errors: Record<string, string[]> | null;
|
|
9
7
|
meta: {
|
|
10
8
|
requestId: string;
|
|
11
9
|
timestamp: string;
|
|
12
|
-
pagination: PaginationMeta | null;
|
|
13
10
|
};
|
|
14
11
|
}
|
|
15
12
|
|
|
16
|
-
export interface
|
|
13
|
+
export interface Pagination<T>{
|
|
14
|
+
data: T[];
|
|
17
15
|
total: number;
|
|
18
16
|
page: number;
|
|
19
17
|
perPage: number;
|
|
@@ -28,15 +26,13 @@ export interface RestMiddlewareFunctions {
|
|
|
28
26
|
responseHandlerMiddleware: <T>(req: Request, res: Response, next: NextFunction) => void
|
|
29
27
|
}
|
|
30
28
|
export interface RestResponseFunctions {
|
|
31
|
-
success: <T>(req: Request, res: Response, data: T
|
|
29
|
+
success: <T>(req: Request, res: Response, data: T) => void;
|
|
32
30
|
paginate: <T>(
|
|
33
31
|
req: Request,
|
|
34
32
|
res: Response,
|
|
35
|
-
data: T
|
|
36
|
-
pagination: PaginationMeta,
|
|
37
|
-
message?: string | null
|
|
33
|
+
data: Pagination<T>
|
|
38
34
|
) => void;
|
|
39
|
-
created: <T>(req: Request, res: Response, data: T
|
|
35
|
+
created: <T>(req: Request, res: Response, data: T) => void;
|
|
40
36
|
deleted: (req: Request, res: Response) => void;
|
|
41
37
|
validationError: (
|
|
42
38
|
req: Request,
|
package/src/utils.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { v4 as uuidv4 } from "uuid";
|
|
2
|
+
import { RestResponse } from ".";
|
|
2
3
|
|
|
3
4
|
export const generateRequestId = () => {
|
|
4
5
|
return uuidv4();
|
|
@@ -6,4 +7,4 @@ export const generateRequestId = () => {
|
|
|
6
7
|
|
|
7
8
|
export const getTimestamp = () => {
|
|
8
9
|
return new Date().toISOString();
|
|
9
|
-
}
|
|
10
|
+
}
|