response-standardizer 1.0.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.
- package/dist/index.d.ts +15 -0
- package/dist/index.js +69 -0
- package/dist/types.d.ts +34 -0
- package/dist/types.js +1 -0
- package/dist/utils.d.ts +2 -0
- package/dist/utils.js +7 -0
- package/package.json +36 -0
- package/src/index.ts +121 -0
- package/src/types.ts +55 -0
- package/src/utils.ts +9 -0
- package/tsconfig.json +13 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { RestResponseFunctions, RestMiddlewareFunctions } from "./types.js";
|
|
2
|
+
declare global {
|
|
3
|
+
namespace Express {
|
|
4
|
+
interface Response {
|
|
5
|
+
json: (data: any) => Response;
|
|
6
|
+
send: (data?: any) => Response;
|
|
7
|
+
locals: {
|
|
8
|
+
requestId: string;
|
|
9
|
+
[key: string]: any;
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export declare const RestResponse: RestResponseFunctions;
|
|
15
|
+
export declare const RestMiddleware: RestMiddlewareFunctions;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { generateRequestId, getTimestamp } from "./utils.js";
|
|
2
|
+
const success = (req, res, data, message = null) => {
|
|
3
|
+
res.status(200).json({ data, message });
|
|
4
|
+
};
|
|
5
|
+
const paginate = (req, res, data, pagination, message = null) => {
|
|
6
|
+
res.status(200).json({ data, message, pagination });
|
|
7
|
+
};
|
|
8
|
+
const created = (req, res, data, message = "Record created successfully") => {
|
|
9
|
+
res.status(201).json({ data, message });
|
|
10
|
+
};
|
|
11
|
+
const deleted = (req, res) => {
|
|
12
|
+
res.status(204).send();
|
|
13
|
+
};
|
|
14
|
+
const validationError = (req, res, errors, message = "Validation error") => {
|
|
15
|
+
res.status(400).json({ errors, message, data: null });
|
|
16
|
+
};
|
|
17
|
+
const exceptionError = (req, res, errors, message = "Internal server error") => {
|
|
18
|
+
res.status(500).json({
|
|
19
|
+
data: null,
|
|
20
|
+
message,
|
|
21
|
+
errors
|
|
22
|
+
});
|
|
23
|
+
};
|
|
24
|
+
const unauthorized = (req, res, message = "Unauthorized") => {
|
|
25
|
+
res.status(401).json({ message });
|
|
26
|
+
};
|
|
27
|
+
const accessDenied = (req, res, message = "Access denied") => {
|
|
28
|
+
res.status(403).json({ message });
|
|
29
|
+
};
|
|
30
|
+
export const RestResponse = {
|
|
31
|
+
success,
|
|
32
|
+
paginate,
|
|
33
|
+
created,
|
|
34
|
+
deleted,
|
|
35
|
+
validationError,
|
|
36
|
+
exceptionError,
|
|
37
|
+
unauthorized,
|
|
38
|
+
accessDenied
|
|
39
|
+
};
|
|
40
|
+
const responseHandlerMiddleware = (req, res, next) => {
|
|
41
|
+
const oldJson = res.json.bind(res);
|
|
42
|
+
const oldSend = res.send.bind(res);
|
|
43
|
+
res.json = function (data) {
|
|
44
|
+
const response = {
|
|
45
|
+
status: res.statusCode >= 200 && res.statusCode < 300 ? "success" : "error",
|
|
46
|
+
code: res.statusCode,
|
|
47
|
+
message: data?.message || res.locals.message || (res.statusCode < 300 ? "OK" : "Error"),
|
|
48
|
+
data: data?.data ?? null,
|
|
49
|
+
errors: data?.errors ?? null,
|
|
50
|
+
meta: {
|
|
51
|
+
requestId: res.locals.requestId || generateRequestId(),
|
|
52
|
+
timestamp: getTimestamp(),
|
|
53
|
+
pagination: data?.pagination ?? null
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
return oldJson(response);
|
|
57
|
+
};
|
|
58
|
+
res.send = function (data) {
|
|
59
|
+
if (res.statusCode === 204) {
|
|
60
|
+
return oldSend();
|
|
61
|
+
}
|
|
62
|
+
return oldSend(data);
|
|
63
|
+
};
|
|
64
|
+
res.locals.requestId = generateRequestId();
|
|
65
|
+
next();
|
|
66
|
+
};
|
|
67
|
+
export const RestMiddleware = {
|
|
68
|
+
responseHandlerMiddleware
|
|
69
|
+
};
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Request, Response, NextFunction } from "express";
|
|
2
|
+
export interface StandardResponse<T = any> {
|
|
3
|
+
status: "success" | "error";
|
|
4
|
+
code: number;
|
|
5
|
+
message: string;
|
|
6
|
+
data: T | null;
|
|
7
|
+
errors: Record<string, string[]> | null;
|
|
8
|
+
meta: {
|
|
9
|
+
requestId: string;
|
|
10
|
+
timestamp: string;
|
|
11
|
+
pagination: PaginationMeta | null;
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
export interface PaginationMeta {
|
|
15
|
+
total: number;
|
|
16
|
+
page: number;
|
|
17
|
+
perPage: number;
|
|
18
|
+
pageCount: number;
|
|
19
|
+
}
|
|
20
|
+
export type ErrorFields = Record<string, string[]>;
|
|
21
|
+
export type Middleware = (req: Request, res: Response, next: NextFunction) => void;
|
|
22
|
+
export interface RestMiddlewareFunctions {
|
|
23
|
+
responseHandlerMiddleware: <T>(req: Request, res: Response, next: NextFunction) => void;
|
|
24
|
+
}
|
|
25
|
+
export interface RestResponseFunctions {
|
|
26
|
+
success: <T>(req: Request, res: Response, data: T, message?: string | null) => void;
|
|
27
|
+
paginate: <T>(req: Request, res: Response, data: T, pagination: PaginationMeta, message?: string | null) => void;
|
|
28
|
+
created: <T>(req: Request, res: Response, data: T, message?: string) => void;
|
|
29
|
+
deleted: (req: Request, res: Response) => void;
|
|
30
|
+
validationError: (req: Request, res: Response, errors: ErrorFields, message?: string) => void;
|
|
31
|
+
exceptionError: (req: Request, res: Response, errors: any, message?: string) => void;
|
|
32
|
+
unauthorized: (req: Request, res: Response, message?: string) => void;
|
|
33
|
+
accessDenied: (req: Request, res: Response, message?: string) => void;
|
|
34
|
+
}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/utils.d.ts
ADDED
package/dist/utils.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "response-standardizer",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Express middleware to standardize API responses",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsc",
|
|
9
|
+
"prepare": "npm run build"
|
|
10
|
+
},
|
|
11
|
+
"repository": {
|
|
12
|
+
"type": "git",
|
|
13
|
+
"url": "git+https://gitlab.com/dezhnevesht-archive-software/response-standardizer.git"
|
|
14
|
+
},
|
|
15
|
+
"author": "Hamid Atyabi",
|
|
16
|
+
"license": "ISC",
|
|
17
|
+
"bugs": {
|
|
18
|
+
"url": "https://gitlab.com/dezhnevesht-archive-software/response-standardizer/issues"
|
|
19
|
+
},
|
|
20
|
+
"homepage": "https://gitlab.com/dezhnevesht-archive-software/response-standardizer#readme",
|
|
21
|
+
|
|
22
|
+
"peerDependencies": {
|
|
23
|
+
"express": "^4 || ^5"
|
|
24
|
+
},
|
|
25
|
+
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"uuid": "^9.0.1"
|
|
28
|
+
},
|
|
29
|
+
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@types/express": "^5.0.5",
|
|
32
|
+
"@types/uuid": "^10.0.0",
|
|
33
|
+
"ts-node-dev": "^2.0.0",
|
|
34
|
+
"typescript": "^5.9.3"
|
|
35
|
+
}
|
|
36
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { Request, Response, NextFunction } from "express";
|
|
2
|
+
import { ErrorFields, PaginationMeta, StandardResponse, RestResponseFunctions, RestMiddlewareFunctions } from "./types.js";
|
|
3
|
+
import { generateRequestId, getTimestamp } from "./utils.js";
|
|
4
|
+
declare global {
|
|
5
|
+
namespace Express {
|
|
6
|
+
interface Response {
|
|
7
|
+
json: (data: any) => Response;
|
|
8
|
+
send: (data?: any) => Response;
|
|
9
|
+
locals: {
|
|
10
|
+
requestId: string;
|
|
11
|
+
[key: string]: any;
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const success = <T>(req: Request, res: Response, data: T, message: string | null = null) => {
|
|
18
|
+
res.status(200).json({ data, message });
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const paginate = <T>(
|
|
22
|
+
req: Request,
|
|
23
|
+
res: Response,
|
|
24
|
+
data: T,
|
|
25
|
+
pagination: PaginationMeta,
|
|
26
|
+
message: string | null = null
|
|
27
|
+
) => {
|
|
28
|
+
res.status(200).json({ data, message, pagination });
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const created = <T>(req: Request, res: Response, data: T, message = "Record created successfully") => {
|
|
32
|
+
res.status(201).json({ data, message });
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const deleted = (req: Request, res: Response) => {
|
|
36
|
+
res.status(204).send();
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const validationError = (
|
|
40
|
+
req: Request,
|
|
41
|
+
res: Response,
|
|
42
|
+
errors: ErrorFields,
|
|
43
|
+
message = "Validation error"
|
|
44
|
+
) => {
|
|
45
|
+
res.status(400).json({ errors, message, data: null });
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const exceptionError = (
|
|
49
|
+
req: Request,
|
|
50
|
+
res: Response,
|
|
51
|
+
errors: any,
|
|
52
|
+
message = "Internal server error"
|
|
53
|
+
) => {
|
|
54
|
+
res.status(500).json({
|
|
55
|
+
data: null,
|
|
56
|
+
message,
|
|
57
|
+
errors
|
|
58
|
+
});
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const unauthorized = (req: Request, res: Response, message = "Unauthorized") => {
|
|
62
|
+
res.status(401).json({ message });
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const accessDenied = (req: Request, res: Response, message = "Access denied") => {
|
|
66
|
+
res.status(403).json({ message });
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
export const RestResponse: RestResponseFunctions = {
|
|
70
|
+
success,
|
|
71
|
+
paginate,
|
|
72
|
+
created,
|
|
73
|
+
deleted,
|
|
74
|
+
validationError,
|
|
75
|
+
exceptionError,
|
|
76
|
+
unauthorized,
|
|
77
|
+
accessDenied
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
const responseHandlerMiddleware = (
|
|
82
|
+
req: Request,
|
|
83
|
+
res: Response,
|
|
84
|
+
next: NextFunction
|
|
85
|
+
) => {
|
|
86
|
+
|
|
87
|
+
const oldJson = res.json.bind(res);
|
|
88
|
+
const oldSend = res.send.bind(res);
|
|
89
|
+
|
|
90
|
+
res.json = function (data: any) {
|
|
91
|
+
const response: StandardResponse = {
|
|
92
|
+
status: res.statusCode >= 200 && res.statusCode < 300 ? "success" : "error",
|
|
93
|
+
code: res.statusCode,
|
|
94
|
+
message: data?.message || res.locals.message || (res.statusCode < 300 ? "OK" : "Error"),
|
|
95
|
+
data: data?.data ?? null,
|
|
96
|
+
errors: data?.errors ?? null,
|
|
97
|
+
meta: {
|
|
98
|
+
requestId: res.locals.requestId || generateRequestId(),
|
|
99
|
+
timestamp: getTimestamp(),
|
|
100
|
+
pagination: data?.pagination ?? null
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
return oldJson(response);
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
res.send = function (data: any) {
|
|
108
|
+
if (res.statusCode === 204) {
|
|
109
|
+
return oldSend();
|
|
110
|
+
}
|
|
111
|
+
return oldSend(data);
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
res.locals.requestId = generateRequestId();
|
|
115
|
+
next();
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
export const RestMiddleware: RestMiddlewareFunctions = {
|
|
120
|
+
responseHandlerMiddleware
|
|
121
|
+
}
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { Request, Response, NextFunction } from "express";
|
|
2
|
+
|
|
3
|
+
export interface StandardResponse<T = any> {
|
|
4
|
+
status: "success" | "error";
|
|
5
|
+
code: number;
|
|
6
|
+
message: string;
|
|
7
|
+
data: T | null;
|
|
8
|
+
errors: Record<string, string[]> | null;
|
|
9
|
+
meta: {
|
|
10
|
+
requestId: string;
|
|
11
|
+
timestamp: string;
|
|
12
|
+
pagination: PaginationMeta | null;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface PaginationMeta {
|
|
17
|
+
total: number;
|
|
18
|
+
page: number;
|
|
19
|
+
perPage: number;
|
|
20
|
+
pageCount: number;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export type ErrorFields = Record<string, string[]>;
|
|
24
|
+
|
|
25
|
+
export type Middleware = (req: Request, res: Response, next: NextFunction) => void;
|
|
26
|
+
|
|
27
|
+
export interface RestMiddlewareFunctions {
|
|
28
|
+
responseHandlerMiddleware: <T>(req: Request, res: Response, next: NextFunction) => void
|
|
29
|
+
}
|
|
30
|
+
export interface RestResponseFunctions {
|
|
31
|
+
success: <T>(req: Request, res: Response, data: T, message?: string | null) => void;
|
|
32
|
+
paginate: <T>(
|
|
33
|
+
req: Request,
|
|
34
|
+
res: Response,
|
|
35
|
+
data: T,
|
|
36
|
+
pagination: PaginationMeta,
|
|
37
|
+
message?: string | null
|
|
38
|
+
) => void;
|
|
39
|
+
created: <T>(req: Request, res: Response, data: T, message?: string) => void;
|
|
40
|
+
deleted: (req: Request, res: Response) => void;
|
|
41
|
+
validationError: (
|
|
42
|
+
req: Request,
|
|
43
|
+
res: Response,
|
|
44
|
+
errors: ErrorFields,
|
|
45
|
+
message?: string
|
|
46
|
+
) => void;
|
|
47
|
+
exceptionError: (
|
|
48
|
+
req: Request,
|
|
49
|
+
res: Response,
|
|
50
|
+
errors: any,
|
|
51
|
+
message?: string
|
|
52
|
+
) => void;
|
|
53
|
+
unauthorized: (req: Request, res: Response, message?: string) => void;
|
|
54
|
+
accessDenied: (req: Request, res: Response, message?: string) => void;
|
|
55
|
+
}
|
package/src/utils.ts
ADDED
package/tsconfig.json
ADDED