@exyconn/common 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/README.md +259 -0
- package/dist/client/http/index.d.mts +85 -0
- package/dist/client/http/index.d.ts +85 -0
- package/dist/client/http/index.js +127 -0
- package/dist/client/http/index.js.map +1 -0
- package/dist/client/http/index.mjs +109 -0
- package/dist/client/http/index.mjs.map +1 -0
- package/dist/client/index.d.mts +7 -0
- package/dist/client/index.d.ts +7 -0
- package/dist/client/index.js +964 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/index.mjs +889 -0
- package/dist/client/index.mjs.map +1 -0
- package/dist/client/logger/index.d.mts +53 -0
- package/dist/client/logger/index.d.ts +53 -0
- package/dist/client/logger/index.js +120 -0
- package/dist/client/logger/index.js.map +1 -0
- package/dist/client/logger/index.mjs +116 -0
- package/dist/client/logger/index.mjs.map +1 -0
- package/dist/client/utils/index.d.mts +285 -0
- package/dist/client/utils/index.d.ts +285 -0
- package/dist/client/utils/index.js +403 -0
- package/dist/client/utils/index.js.map +1 -0
- package/dist/client/utils/index.mjs +362 -0
- package/dist/client/utils/index.mjs.map +1 -0
- package/dist/index-BNdT-2X4.d.ts +229 -0
- package/dist/index-CcrANHAQ.d.mts +59 -0
- package/dist/index-ClWtDfwk.d.ts +833 -0
- package/dist/index-DSW6JfD-.d.mts +833 -0
- package/dist/index-Du0LLt9f.d.mts +229 -0
- package/dist/index-iTKxFa78.d.ts +59 -0
- package/dist/index.d.mts +171 -0
- package/dist/index.d.ts +171 -0
- package/dist/index.js +3806 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +3792 -0
- package/dist/index.mjs.map +1 -0
- package/dist/response.types-D--UhLJq.d.mts +67 -0
- package/dist/response.types-D--UhLJq.d.ts +67 -0
- package/dist/server/db/index.d.mts +38 -0
- package/dist/server/db/index.d.ts +38 -0
- package/dist/server/db/index.js +68 -0
- package/dist/server/db/index.js.map +1 -0
- package/dist/server/db/index.mjs +60 -0
- package/dist/server/db/index.mjs.map +1 -0
- package/dist/server/enums/index.d.mts +46 -0
- package/dist/server/enums/index.d.ts +46 -0
- package/dist/server/enums/index.js +48 -0
- package/dist/server/enums/index.js.map +1 -0
- package/dist/server/enums/index.mjs +43 -0
- package/dist/server/enums/index.mjs.map +1 -0
- package/dist/server/index.d.mts +9 -0
- package/dist/server/index.d.ts +9 -0
- package/dist/server/index.js +569 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/index.mjs +523 -0
- package/dist/server/index.mjs.map +1 -0
- package/dist/server/logger/index.d.mts +34 -0
- package/dist/server/logger/index.d.ts +34 -0
- package/dist/server/logger/index.js +125 -0
- package/dist/server/logger/index.js.map +1 -0
- package/dist/server/logger/index.mjs +113 -0
- package/dist/server/logger/index.mjs.map +1 -0
- package/dist/server/middleware/index.d.mts +56 -0
- package/dist/server/middleware/index.d.ts +56 -0
- package/dist/server/middleware/index.js +128 -0
- package/dist/server/middleware/index.js.map +1 -0
- package/dist/server/middleware/index.mjs +118 -0
- package/dist/server/middleware/index.mjs.map +1 -0
- package/dist/server/response/index.d.mts +86 -0
- package/dist/server/response/index.d.ts +86 -0
- package/dist/server/response/index.js +140 -0
- package/dist/server/response/index.js.map +1 -0
- package/dist/server/response/index.mjs +126 -0
- package/dist/server/response/index.mjs.map +1 -0
- package/dist/server/utils/index.d.mts +69 -0
- package/dist/server/utils/index.d.ts +69 -0
- package/dist/server/utils/index.js +114 -0
- package/dist/server/utils/index.js.map +1 -0
- package/dist/server/utils/index.mjs +106 -0
- package/dist/server/utils/index.mjs.map +1 -0
- package/dist/shared/index.d.mts +4 -0
- package/dist/shared/index.d.ts +4 -0
- package/dist/shared/index.js +933 -0
- package/dist/shared/index.js.map +1 -0
- package/dist/shared/index.mjs +612 -0
- package/dist/shared/index.mjs.map +1 -0
- package/package.json +202 -0
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import jwt from 'jsonwebtoken';
|
|
2
|
+
|
|
3
|
+
// src/server/middleware/auth.middleware.ts
|
|
4
|
+
|
|
5
|
+
// src/server/response/response-object.ts
|
|
6
|
+
var unauthorizedResponse = (res, message = "Unauthorized access") => {
|
|
7
|
+
return res.status(401 /* UNAUTHORIZED */).json({
|
|
8
|
+
message,
|
|
9
|
+
data: null,
|
|
10
|
+
status: "unauthorized" /* UNAUTHORIZED */,
|
|
11
|
+
statusCode: 401 /* UNAUTHORIZED */
|
|
12
|
+
});
|
|
13
|
+
};
|
|
14
|
+
var forbiddenResponse = (res, message = "Access forbidden") => {
|
|
15
|
+
return res.status(403 /* FORBIDDEN */).json({
|
|
16
|
+
message,
|
|
17
|
+
data: null,
|
|
18
|
+
status: "forbidden" /* FORBIDDEN */,
|
|
19
|
+
statusCode: 403 /* FORBIDDEN */
|
|
20
|
+
});
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
// src/server/middleware/auth.middleware.ts
|
|
24
|
+
var authenticateJWT = (secretKey) => {
|
|
25
|
+
return (req, res, next) => {
|
|
26
|
+
const authHeader = req.headers.authorization;
|
|
27
|
+
if (!authHeader || !authHeader.startsWith("Bearer ")) {
|
|
28
|
+
unauthorizedResponse(res, "Authorization header missing or malformed");
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
const token = authHeader.split(" ")[1];
|
|
32
|
+
try {
|
|
33
|
+
const decoded = jwt.verify(token, secretKey);
|
|
34
|
+
req.userId = decoded.userId;
|
|
35
|
+
req.organizationId = decoded.organizationId;
|
|
36
|
+
req.user = decoded;
|
|
37
|
+
if (!decoded.userId) {
|
|
38
|
+
unauthorizedResponse(res, "User ID not found in token");
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
next();
|
|
42
|
+
} catch (err) {
|
|
43
|
+
if (err instanceof jwt.TokenExpiredError) {
|
|
44
|
+
unauthorizedResponse(res, "Token has expired");
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
if (err instanceof jwt.JsonWebTokenError) {
|
|
48
|
+
forbiddenResponse(res, "Invalid token");
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
unauthorizedResponse(res, "Token validation failed");
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
var optionalAuthenticateJWT = (secretKey) => {
|
|
56
|
+
return (req, _res, next) => {
|
|
57
|
+
const authHeader = req.headers.authorization;
|
|
58
|
+
if (!authHeader || !authHeader.startsWith("Bearer ")) {
|
|
59
|
+
next();
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
const token = authHeader.split(" ")[1];
|
|
63
|
+
try {
|
|
64
|
+
const decoded = jwt.verify(token, secretKey);
|
|
65
|
+
req.userId = decoded.userId;
|
|
66
|
+
req.organizationId = decoded.organizationId;
|
|
67
|
+
req.user = decoded;
|
|
68
|
+
} catch {
|
|
69
|
+
}
|
|
70
|
+
next();
|
|
71
|
+
};
|
|
72
|
+
};
|
|
73
|
+
var authenticateApiKey = (validateKeyFn) => {
|
|
74
|
+
return async (req, res, next) => {
|
|
75
|
+
try {
|
|
76
|
+
const apiKey = req.headers["x-api-key"];
|
|
77
|
+
if (!apiKey) {
|
|
78
|
+
unauthorizedResponse(res, "API key is required. Please provide x-api-key header");
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
const validation = await validateKeyFn(apiKey);
|
|
82
|
+
if (!validation.valid) {
|
|
83
|
+
unauthorizedResponse(res, "Invalid or inactive API key");
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
if (validation.organizationId) {
|
|
87
|
+
req.organizationId = validation.organizationId;
|
|
88
|
+
}
|
|
89
|
+
if (validation.keyId && validation.keyName) {
|
|
90
|
+
req.apiKey = {
|
|
91
|
+
_id: validation.keyId,
|
|
92
|
+
name: validation.keyName
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
next();
|
|
96
|
+
} catch {
|
|
97
|
+
unauthorizedResponse(res, "API key validation failed");
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
};
|
|
101
|
+
var extractOrganization = (req, _res, next) => {
|
|
102
|
+
const orgId = req.headers["x-organization-id"];
|
|
103
|
+
if (orgId) {
|
|
104
|
+
req.organizationId = orgId;
|
|
105
|
+
}
|
|
106
|
+
next();
|
|
107
|
+
};
|
|
108
|
+
var requireOrganization = (req, res, next) => {
|
|
109
|
+
if (!req.organizationId) {
|
|
110
|
+
unauthorizedResponse(res, "Organization ID is required");
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
next();
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
export { authenticateApiKey, authenticateJWT, extractOrganization, optionalAuthenticateJWT, requireOrganization };
|
|
117
|
+
//# sourceMappingURL=index.mjs.map
|
|
118
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/server/response/response-object.ts","../../../src/server/middleware/auth.middleware.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["import type { Response } from 'express';\r\nimport { StatusCode, StatusMessage } from '../enums/status';\r\n\r\n/**\r\n * Standard API Response Interface\r\n */\r\nexport interface ApiResponse<T = unknown> {\r\n message: string;\r\n data: T | null;\r\n status: string;\r\n statusCode: number;\r\n paginationData?: PaginationData;\r\n columns?: ColumnMetadata[];\r\n}\r\n\r\n/**\r\n * Pagination Data Interface\r\n */\r\nexport interface PaginationData {\r\n total?: number;\r\n page?: number;\r\n limit?: number;\r\n totalPages?: number;\r\n hasNextPage?: boolean;\r\n hasPrevPage?: boolean;\r\n}\r\n\r\n/**\r\n * Column Metadata Interface (for dynamic tables)\r\n */\r\nexport interface ColumnMetadata {\r\n name: string;\r\n datatype: string;\r\n required: boolean;\r\n}\r\n\r\n/**\r\n * Extract column metadata from data array\r\n */\r\nexport const extractColumns = <T extends Record<string, unknown>>(\r\n data: T[]\r\n): ColumnMetadata[] => {\r\n if (!Array.isArray(data) || data.length === 0) {\r\n return [];\r\n }\r\n\r\n const sample = data[0];\r\n return Object.entries(sample).map(([key, value]) => {\r\n let datatype: string = typeof value;\r\n\r\n if (value === null) {\r\n datatype = 'null';\r\n } else if (Array.isArray(value)) {\r\n datatype = 'array';\r\n } else if (value instanceof Date) {\r\n datatype = 'date';\r\n } else if (typeof value === 'object') {\r\n datatype = 'object';\r\n }\r\n\r\n return {\r\n name: key,\r\n datatype,\r\n required: value !== null && value !== undefined,\r\n };\r\n });\r\n};\r\n\r\n/**\r\n * Success Response (200)\r\n */\r\nexport const successResponse = <T>(\r\n res: Response,\r\n data: T,\r\n message = 'Operation successful'\r\n): Response => {\r\n return res.status(StatusCode.SUCCESS).json({\r\n message,\r\n data,\r\n status: StatusMessage.SUCCESS,\r\n statusCode: StatusCode.SUCCESS,\r\n });\r\n};\r\n\r\n/**\r\n * Success Response with Array & Pagination (200)\r\n */\r\nexport const successResponseArr = <T>(\r\n res: Response,\r\n data: T[],\r\n paginationData: PaginationData = {},\r\n message = 'Operation successful'\r\n): Response => {\r\n return res.status(StatusCode.SUCCESS).json({\r\n message,\r\n data,\r\n columns: extractColumns(data as Record<string, unknown>[]),\r\n paginationData,\r\n status: StatusMessage.SUCCESS,\r\n statusCode: StatusCode.SUCCESS,\r\n });\r\n};\r\n\r\n/**\r\n * Created Response (201)\r\n */\r\nexport const createdResponse = <T>(\r\n res: Response,\r\n data: T,\r\n message = 'Resource created successfully'\r\n): Response => {\r\n return res.status(StatusCode.CREATED).json({\r\n message,\r\n data,\r\n status: StatusMessage.CREATED,\r\n statusCode: StatusCode.CREATED,\r\n });\r\n};\r\n\r\n/**\r\n * No Content Response (204 as 200 with message)\r\n */\r\nexport const noContentResponse = <T = null>(\r\n res: Response,\r\n data: T = null as T,\r\n message = 'No data found'\r\n): Response => {\r\n return res.status(StatusCode.SUCCESS).json({\r\n message,\r\n data,\r\n status: StatusMessage.NO_CONTENT,\r\n statusCode: StatusCode.NO_CONTENT,\r\n });\r\n};\r\n\r\n/**\r\n * Bad Request Response (400)\r\n */\r\nexport const badRequestResponse = (\r\n res: Response,\r\n message = 'Bad request',\r\n errors: unknown = null\r\n): Response => {\r\n return res.status(StatusCode.BAD_REQUEST).json({\r\n message,\r\n data: errors,\r\n status: StatusMessage.BAD_REQUEST,\r\n statusCode: StatusCode.BAD_REQUEST,\r\n });\r\n};\r\n\r\n/**\r\n * Unauthorized Response (401)\r\n */\r\nexport const unauthorizedResponse = (\r\n res: Response,\r\n message = 'Unauthorized access'\r\n): Response => {\r\n return res.status(StatusCode.UNAUTHORIZED).json({\r\n message,\r\n data: null,\r\n status: StatusMessage.UNAUTHORIZED,\r\n statusCode: StatusCode.UNAUTHORIZED,\r\n });\r\n};\r\n\r\n/**\r\n * Forbidden Response (403)\r\n */\r\nexport const forbiddenResponse = (\r\n res: Response,\r\n message = 'Access forbidden'\r\n): Response => {\r\n return res.status(StatusCode.FORBIDDEN).json({\r\n message,\r\n data: null,\r\n status: StatusMessage.FORBIDDEN,\r\n statusCode: StatusCode.FORBIDDEN,\r\n });\r\n};\r\n\r\n/**\r\n * Not Found Response (404)\r\n */\r\nexport const notFoundResponse = (\r\n res: Response,\r\n message = 'Resource not found'\r\n): Response => {\r\n return res.status(StatusCode.NOT_FOUND).json({\r\n message,\r\n data: null,\r\n status: StatusMessage.NOT_FOUND,\r\n statusCode: StatusCode.NOT_FOUND,\r\n });\r\n};\r\n\r\n/**\r\n * Conflict Response (409)\r\n */\r\nexport const conflictResponse = (\r\n res: Response,\r\n message = 'Resource conflict'\r\n): Response => {\r\n return res.status(StatusCode.CONFLICT).json({\r\n message,\r\n data: null,\r\n status: StatusMessage.CONFLICT,\r\n statusCode: StatusCode.CONFLICT,\r\n });\r\n};\r\n\r\n/**\r\n * Validation Error Response (422)\r\n */\r\nexport const validationErrorResponse = (\r\n res: Response,\r\n errors: unknown,\r\n message = 'Validation failed'\r\n): Response => {\r\n return res.status(StatusCode.UNPROCESSABLE_ENTITY).json({\r\n message,\r\n data: errors,\r\n status: StatusMessage.UNPROCESSABLE_ENTITY,\r\n statusCode: StatusCode.UNPROCESSABLE_ENTITY,\r\n });\r\n};\r\n\r\n/**\r\n * Error Response (500)\r\n */\r\nexport const errorResponse = (\r\n res: Response,\r\n error: unknown = null,\r\n message = 'Something went wrong'\r\n): Response => {\r\n return res.status(StatusCode.INTERNAL_ERROR).json({\r\n message,\r\n data: error,\r\n status: StatusMessage.INTERNAL_ERROR,\r\n statusCode: StatusCode.INTERNAL_ERROR,\r\n });\r\n};\r\n\r\n/**\r\n * Rate Limit Response (429)\r\n */\r\nexport const rateLimitResponse = (\r\n res: Response,\r\n message = 'Too many requests, please try again later'\r\n): Response => {\r\n return res.status(StatusCode.TOO_MANY_REQUESTS).json({\r\n message,\r\n data: null,\r\n status: StatusMessage.TOO_MANY_REQUESTS,\r\n statusCode: StatusCode.TOO_MANY_REQUESTS,\r\n });\r\n};\r\n\r\nexport default {\r\n successResponse,\r\n successResponseArr,\r\n createdResponse,\r\n noContentResponse,\r\n badRequestResponse,\r\n unauthorizedResponse,\r\n forbiddenResponse,\r\n notFoundResponse,\r\n conflictResponse,\r\n validationErrorResponse,\r\n errorResponse,\r\n rateLimitResponse,\r\n extractColumns,\r\n};\r\n","import type { Request, Response, NextFunction } from 'express';\r\nimport jwt from 'jsonwebtoken';\r\nimport { unauthorizedResponse, forbiddenResponse } from '../response/response-object';\r\n\r\n/**\r\n * Extended Request with auth information\r\n */\r\nexport interface AuthRequest extends Request {\r\n userId?: string;\r\n organizationId?: string;\r\n apiKey?: { _id: string; name: string };\r\n user?: Record<string, unknown>;\r\n}\r\n\r\n/**\r\n * JWT Payload Interface\r\n */\r\nexport interface JWTPayload {\r\n userId: string;\r\n organizationId?: string;\r\n email?: string;\r\n role?: string;\r\n [key: string]: unknown;\r\n}\r\n\r\n/**\r\n * JWT Authentication Middleware\r\n * Validates Bearer token from Authorization header\r\n */\r\nexport const authenticateJWT = (secretKey: string) => {\r\n return (req: AuthRequest, res: Response, next: NextFunction): void => {\r\n const authHeader = req.headers.authorization;\r\n\r\n if (!authHeader || !authHeader.startsWith('Bearer ')) {\r\n unauthorizedResponse(res, 'Authorization header missing or malformed');\r\n return;\r\n }\r\n\r\n const token = authHeader.split(' ')[1];\r\n\r\n try {\r\n const decoded = jwt.verify(token, secretKey) as JWTPayload;\r\n\r\n req.userId = decoded.userId;\r\n req.organizationId = decoded.organizationId;\r\n req.user = decoded as Record<string, unknown>;\r\n\r\n if (!decoded.userId) {\r\n unauthorizedResponse(res, 'User ID not found in token');\r\n return;\r\n }\r\n\r\n next();\r\n } catch (err) {\r\n if (err instanceof jwt.TokenExpiredError) {\r\n unauthorizedResponse(res, 'Token has expired');\r\n return;\r\n }\r\n if (err instanceof jwt.JsonWebTokenError) {\r\n forbiddenResponse(res, 'Invalid token');\r\n return;\r\n }\r\n unauthorizedResponse(res, 'Token validation failed');\r\n }\r\n };\r\n};\r\n\r\n/**\r\n * Optional JWT Authentication Middleware\r\n * Validates token if present, but doesn't require it\r\n */\r\nexport const optionalAuthenticateJWT = (secretKey: string) => {\r\n return (req: AuthRequest, _res: Response, next: NextFunction): void => {\r\n const authHeader = req.headers.authorization;\r\n\r\n if (!authHeader || !authHeader.startsWith('Bearer ')) {\r\n next();\r\n return;\r\n }\r\n\r\n const token = authHeader.split(' ')[1];\r\n\r\n try {\r\n const decoded = jwt.verify(token, secretKey) as JWTPayload;\r\n req.userId = decoded.userId;\r\n req.organizationId = decoded.organizationId;\r\n req.user = decoded as Record<string, unknown>;\r\n } catch {\r\n // Token invalid, but continue without auth\r\n }\r\n\r\n next();\r\n };\r\n};\r\n\r\n/**\r\n * API Key Authentication Middleware\r\n * Validates x-api-key header\r\n */\r\nexport const authenticateApiKey = (\r\n validateKeyFn: (key: string) => Promise<{\r\n valid: boolean;\r\n organizationId?: string;\r\n keyId?: string;\r\n keyName?: string;\r\n }>\r\n) => {\r\n return async (req: AuthRequest, res: Response, next: NextFunction): Promise<void> => {\r\n try {\r\n const apiKey = req.headers['x-api-key'] as string;\r\n\r\n if (!apiKey) {\r\n unauthorizedResponse(res, 'API key is required. Please provide x-api-key header');\r\n return;\r\n }\r\n\r\n const validation = await validateKeyFn(apiKey);\r\n\r\n if (!validation.valid) {\r\n unauthorizedResponse(res, 'Invalid or inactive API key');\r\n return;\r\n }\r\n\r\n if (validation.organizationId) {\r\n req.organizationId = validation.organizationId;\r\n }\r\n if (validation.keyId && validation.keyName) {\r\n req.apiKey = {\r\n _id: validation.keyId,\r\n name: validation.keyName,\r\n };\r\n }\r\n\r\n next();\r\n } catch {\r\n unauthorizedResponse(res, 'API key validation failed');\r\n }\r\n };\r\n};\r\n\r\n/**\r\n * Organization Header Middleware\r\n * Extracts organization ID from x-organization-id header\r\n */\r\nexport const extractOrganization = (req: AuthRequest, _res: Response, next: NextFunction): void => {\r\n const orgId = req.headers['x-organization-id'] as string;\r\n\r\n if (orgId) {\r\n req.organizationId = orgId;\r\n }\r\n\r\n next();\r\n};\r\n\r\n/**\r\n * Require Organization Middleware\r\n * Ensures organizationId is present in request\r\n */\r\nexport const requireOrganization = (req: AuthRequest, res: Response, next: NextFunction): void => {\r\n if (!req.organizationId) {\r\n unauthorizedResponse(res, 'Organization ID is required');\r\n return;\r\n }\r\n next();\r\n};\r\n\r\nexport default {\r\n authenticateJWT,\r\n optionalAuthenticateJWT,\r\n authenticateApiKey,\r\n extractOrganization,\r\n requireOrganization,\r\n};\r\n"]}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { Response } from 'express';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Standard API Response Interface
|
|
5
|
+
*/
|
|
6
|
+
interface ApiResponse<T = unknown> {
|
|
7
|
+
message: string;
|
|
8
|
+
data: T | null;
|
|
9
|
+
status: string;
|
|
10
|
+
statusCode: number;
|
|
11
|
+
paginationData?: PaginationData;
|
|
12
|
+
columns?: ColumnMetadata[];
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Pagination Data Interface
|
|
16
|
+
*/
|
|
17
|
+
interface PaginationData {
|
|
18
|
+
total?: number;
|
|
19
|
+
page?: number;
|
|
20
|
+
limit?: number;
|
|
21
|
+
totalPages?: number;
|
|
22
|
+
hasNextPage?: boolean;
|
|
23
|
+
hasPrevPage?: boolean;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Column Metadata Interface (for dynamic tables)
|
|
27
|
+
*/
|
|
28
|
+
interface ColumnMetadata {
|
|
29
|
+
name: string;
|
|
30
|
+
datatype: string;
|
|
31
|
+
required: boolean;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Extract column metadata from data array
|
|
35
|
+
*/
|
|
36
|
+
declare const extractColumns: <T extends Record<string, unknown>>(data: T[]) => ColumnMetadata[];
|
|
37
|
+
/**
|
|
38
|
+
* Success Response (200)
|
|
39
|
+
*/
|
|
40
|
+
declare const successResponse: <T>(res: Response, data: T, message?: string) => Response;
|
|
41
|
+
/**
|
|
42
|
+
* Success Response with Array & Pagination (200)
|
|
43
|
+
*/
|
|
44
|
+
declare const successResponseArr: <T>(res: Response, data: T[], paginationData?: PaginationData, message?: string) => Response;
|
|
45
|
+
/**
|
|
46
|
+
* Created Response (201)
|
|
47
|
+
*/
|
|
48
|
+
declare const createdResponse: <T>(res: Response, data: T, message?: string) => Response;
|
|
49
|
+
/**
|
|
50
|
+
* No Content Response (204 as 200 with message)
|
|
51
|
+
*/
|
|
52
|
+
declare const noContentResponse: <T = null>(res: Response, data?: T, message?: string) => Response;
|
|
53
|
+
/**
|
|
54
|
+
* Bad Request Response (400)
|
|
55
|
+
*/
|
|
56
|
+
declare const badRequestResponse: (res: Response, message?: string, errors?: unknown) => Response;
|
|
57
|
+
/**
|
|
58
|
+
* Unauthorized Response (401)
|
|
59
|
+
*/
|
|
60
|
+
declare const unauthorizedResponse: (res: Response, message?: string) => Response;
|
|
61
|
+
/**
|
|
62
|
+
* Forbidden Response (403)
|
|
63
|
+
*/
|
|
64
|
+
declare const forbiddenResponse: (res: Response, message?: string) => Response;
|
|
65
|
+
/**
|
|
66
|
+
* Not Found Response (404)
|
|
67
|
+
*/
|
|
68
|
+
declare const notFoundResponse: (res: Response, message?: string) => Response;
|
|
69
|
+
/**
|
|
70
|
+
* Conflict Response (409)
|
|
71
|
+
*/
|
|
72
|
+
declare const conflictResponse: (res: Response, message?: string) => Response;
|
|
73
|
+
/**
|
|
74
|
+
* Validation Error Response (422)
|
|
75
|
+
*/
|
|
76
|
+
declare const validationErrorResponse: (res: Response, errors: unknown, message?: string) => Response;
|
|
77
|
+
/**
|
|
78
|
+
* Error Response (500)
|
|
79
|
+
*/
|
|
80
|
+
declare const errorResponse: (res: Response, error?: unknown, message?: string) => Response;
|
|
81
|
+
/**
|
|
82
|
+
* Rate Limit Response (429)
|
|
83
|
+
*/
|
|
84
|
+
declare const rateLimitResponse: (res: Response, message?: string) => Response;
|
|
85
|
+
|
|
86
|
+
export { type ApiResponse, type ColumnMetadata, type PaginationData, badRequestResponse, conflictResponse, createdResponse, errorResponse, extractColumns, forbiddenResponse, noContentResponse, notFoundResponse, rateLimitResponse, successResponse, successResponseArr, unauthorizedResponse, validationErrorResponse };
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { Response } from 'express';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Standard API Response Interface
|
|
5
|
+
*/
|
|
6
|
+
interface ApiResponse<T = unknown> {
|
|
7
|
+
message: string;
|
|
8
|
+
data: T | null;
|
|
9
|
+
status: string;
|
|
10
|
+
statusCode: number;
|
|
11
|
+
paginationData?: PaginationData;
|
|
12
|
+
columns?: ColumnMetadata[];
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Pagination Data Interface
|
|
16
|
+
*/
|
|
17
|
+
interface PaginationData {
|
|
18
|
+
total?: number;
|
|
19
|
+
page?: number;
|
|
20
|
+
limit?: number;
|
|
21
|
+
totalPages?: number;
|
|
22
|
+
hasNextPage?: boolean;
|
|
23
|
+
hasPrevPage?: boolean;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Column Metadata Interface (for dynamic tables)
|
|
27
|
+
*/
|
|
28
|
+
interface ColumnMetadata {
|
|
29
|
+
name: string;
|
|
30
|
+
datatype: string;
|
|
31
|
+
required: boolean;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Extract column metadata from data array
|
|
35
|
+
*/
|
|
36
|
+
declare const extractColumns: <T extends Record<string, unknown>>(data: T[]) => ColumnMetadata[];
|
|
37
|
+
/**
|
|
38
|
+
* Success Response (200)
|
|
39
|
+
*/
|
|
40
|
+
declare const successResponse: <T>(res: Response, data: T, message?: string) => Response;
|
|
41
|
+
/**
|
|
42
|
+
* Success Response with Array & Pagination (200)
|
|
43
|
+
*/
|
|
44
|
+
declare const successResponseArr: <T>(res: Response, data: T[], paginationData?: PaginationData, message?: string) => Response;
|
|
45
|
+
/**
|
|
46
|
+
* Created Response (201)
|
|
47
|
+
*/
|
|
48
|
+
declare const createdResponse: <T>(res: Response, data: T, message?: string) => Response;
|
|
49
|
+
/**
|
|
50
|
+
* No Content Response (204 as 200 with message)
|
|
51
|
+
*/
|
|
52
|
+
declare const noContentResponse: <T = null>(res: Response, data?: T, message?: string) => Response;
|
|
53
|
+
/**
|
|
54
|
+
* Bad Request Response (400)
|
|
55
|
+
*/
|
|
56
|
+
declare const badRequestResponse: (res: Response, message?: string, errors?: unknown) => Response;
|
|
57
|
+
/**
|
|
58
|
+
* Unauthorized Response (401)
|
|
59
|
+
*/
|
|
60
|
+
declare const unauthorizedResponse: (res: Response, message?: string) => Response;
|
|
61
|
+
/**
|
|
62
|
+
* Forbidden Response (403)
|
|
63
|
+
*/
|
|
64
|
+
declare const forbiddenResponse: (res: Response, message?: string) => Response;
|
|
65
|
+
/**
|
|
66
|
+
* Not Found Response (404)
|
|
67
|
+
*/
|
|
68
|
+
declare const notFoundResponse: (res: Response, message?: string) => Response;
|
|
69
|
+
/**
|
|
70
|
+
* Conflict Response (409)
|
|
71
|
+
*/
|
|
72
|
+
declare const conflictResponse: (res: Response, message?: string) => Response;
|
|
73
|
+
/**
|
|
74
|
+
* Validation Error Response (422)
|
|
75
|
+
*/
|
|
76
|
+
declare const validationErrorResponse: (res: Response, errors: unknown, message?: string) => Response;
|
|
77
|
+
/**
|
|
78
|
+
* Error Response (500)
|
|
79
|
+
*/
|
|
80
|
+
declare const errorResponse: (res: Response, error?: unknown, message?: string) => Response;
|
|
81
|
+
/**
|
|
82
|
+
* Rate Limit Response (429)
|
|
83
|
+
*/
|
|
84
|
+
declare const rateLimitResponse: (res: Response, message?: string) => Response;
|
|
85
|
+
|
|
86
|
+
export { type ApiResponse, type ColumnMetadata, type PaginationData, badRequestResponse, conflictResponse, createdResponse, errorResponse, extractColumns, forbiddenResponse, noContentResponse, notFoundResponse, rateLimitResponse, successResponse, successResponseArr, unauthorizedResponse, validationErrorResponse };
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/server/response/response-object.ts
|
|
4
|
+
var extractColumns = (data) => {
|
|
5
|
+
if (!Array.isArray(data) || data.length === 0) {
|
|
6
|
+
return [];
|
|
7
|
+
}
|
|
8
|
+
const sample = data[0];
|
|
9
|
+
return Object.entries(sample).map(([key, value]) => {
|
|
10
|
+
let datatype = typeof value;
|
|
11
|
+
if (value === null) {
|
|
12
|
+
datatype = "null";
|
|
13
|
+
} else if (Array.isArray(value)) {
|
|
14
|
+
datatype = "array";
|
|
15
|
+
} else if (value instanceof Date) {
|
|
16
|
+
datatype = "date";
|
|
17
|
+
} else if (typeof value === "object") {
|
|
18
|
+
datatype = "object";
|
|
19
|
+
}
|
|
20
|
+
return {
|
|
21
|
+
name: key,
|
|
22
|
+
datatype,
|
|
23
|
+
required: value !== null && value !== void 0
|
|
24
|
+
};
|
|
25
|
+
});
|
|
26
|
+
};
|
|
27
|
+
var successResponse = (res, data, message = "Operation successful") => {
|
|
28
|
+
return res.status(200 /* SUCCESS */).json({
|
|
29
|
+
message,
|
|
30
|
+
data,
|
|
31
|
+
status: "success" /* SUCCESS */,
|
|
32
|
+
statusCode: 200 /* SUCCESS */
|
|
33
|
+
});
|
|
34
|
+
};
|
|
35
|
+
var successResponseArr = (res, data, paginationData = {}, message = "Operation successful") => {
|
|
36
|
+
return res.status(200 /* SUCCESS */).json({
|
|
37
|
+
message,
|
|
38
|
+
data,
|
|
39
|
+
columns: extractColumns(data),
|
|
40
|
+
paginationData,
|
|
41
|
+
status: "success" /* SUCCESS */,
|
|
42
|
+
statusCode: 200 /* SUCCESS */
|
|
43
|
+
});
|
|
44
|
+
};
|
|
45
|
+
var createdResponse = (res, data, message = "Resource created successfully") => {
|
|
46
|
+
return res.status(201 /* CREATED */).json({
|
|
47
|
+
message,
|
|
48
|
+
data,
|
|
49
|
+
status: "created" /* CREATED */,
|
|
50
|
+
statusCode: 201 /* CREATED */
|
|
51
|
+
});
|
|
52
|
+
};
|
|
53
|
+
var noContentResponse = (res, data = null, message = "No data found") => {
|
|
54
|
+
return res.status(200 /* SUCCESS */).json({
|
|
55
|
+
message,
|
|
56
|
+
data,
|
|
57
|
+
status: "no-data-found" /* NO_CONTENT */,
|
|
58
|
+
statusCode: 204 /* NO_CONTENT */
|
|
59
|
+
});
|
|
60
|
+
};
|
|
61
|
+
var badRequestResponse = (res, message = "Bad request", errors = null) => {
|
|
62
|
+
return res.status(400 /* BAD_REQUEST */).json({
|
|
63
|
+
message,
|
|
64
|
+
data: errors,
|
|
65
|
+
status: "bad-request" /* BAD_REQUEST */,
|
|
66
|
+
statusCode: 400 /* BAD_REQUEST */
|
|
67
|
+
});
|
|
68
|
+
};
|
|
69
|
+
var unauthorizedResponse = (res, message = "Unauthorized access") => {
|
|
70
|
+
return res.status(401 /* UNAUTHORIZED */).json({
|
|
71
|
+
message,
|
|
72
|
+
data: null,
|
|
73
|
+
status: "unauthorized" /* UNAUTHORIZED */,
|
|
74
|
+
statusCode: 401 /* UNAUTHORIZED */
|
|
75
|
+
});
|
|
76
|
+
};
|
|
77
|
+
var forbiddenResponse = (res, message = "Access forbidden") => {
|
|
78
|
+
return res.status(403 /* FORBIDDEN */).json({
|
|
79
|
+
message,
|
|
80
|
+
data: null,
|
|
81
|
+
status: "forbidden" /* FORBIDDEN */,
|
|
82
|
+
statusCode: 403 /* FORBIDDEN */
|
|
83
|
+
});
|
|
84
|
+
};
|
|
85
|
+
var notFoundResponse = (res, message = "Resource not found") => {
|
|
86
|
+
return res.status(404 /* NOT_FOUND */).json({
|
|
87
|
+
message,
|
|
88
|
+
data: null,
|
|
89
|
+
status: "not-found" /* NOT_FOUND */,
|
|
90
|
+
statusCode: 404 /* NOT_FOUND */
|
|
91
|
+
});
|
|
92
|
+
};
|
|
93
|
+
var conflictResponse = (res, message = "Resource conflict") => {
|
|
94
|
+
return res.status(409 /* CONFLICT */).json({
|
|
95
|
+
message,
|
|
96
|
+
data: null,
|
|
97
|
+
status: "conflict" /* CONFLICT */,
|
|
98
|
+
statusCode: 409 /* CONFLICT */
|
|
99
|
+
});
|
|
100
|
+
};
|
|
101
|
+
var validationErrorResponse = (res, errors, message = "Validation failed") => {
|
|
102
|
+
return res.status(422 /* UNPROCESSABLE_ENTITY */).json({
|
|
103
|
+
message,
|
|
104
|
+
data: errors,
|
|
105
|
+
status: "validation-error" /* UNPROCESSABLE_ENTITY */,
|
|
106
|
+
statusCode: 422 /* UNPROCESSABLE_ENTITY */
|
|
107
|
+
});
|
|
108
|
+
};
|
|
109
|
+
var errorResponse = (res, error = null, message = "Something went wrong") => {
|
|
110
|
+
return res.status(500 /* INTERNAL_ERROR */).json({
|
|
111
|
+
message,
|
|
112
|
+
data: error,
|
|
113
|
+
status: "error" /* INTERNAL_ERROR */,
|
|
114
|
+
statusCode: 500 /* INTERNAL_ERROR */
|
|
115
|
+
});
|
|
116
|
+
};
|
|
117
|
+
var rateLimitResponse = (res, message = "Too many requests, please try again later") => {
|
|
118
|
+
return res.status(429 /* TOO_MANY_REQUESTS */).json({
|
|
119
|
+
message,
|
|
120
|
+
data: null,
|
|
121
|
+
status: "rate-limit-exceeded" /* TOO_MANY_REQUESTS */,
|
|
122
|
+
statusCode: 429 /* TOO_MANY_REQUESTS */
|
|
123
|
+
});
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
exports.badRequestResponse = badRequestResponse;
|
|
127
|
+
exports.conflictResponse = conflictResponse;
|
|
128
|
+
exports.createdResponse = createdResponse;
|
|
129
|
+
exports.errorResponse = errorResponse;
|
|
130
|
+
exports.extractColumns = extractColumns;
|
|
131
|
+
exports.forbiddenResponse = forbiddenResponse;
|
|
132
|
+
exports.noContentResponse = noContentResponse;
|
|
133
|
+
exports.notFoundResponse = notFoundResponse;
|
|
134
|
+
exports.rateLimitResponse = rateLimitResponse;
|
|
135
|
+
exports.successResponse = successResponse;
|
|
136
|
+
exports.successResponseArr = successResponseArr;
|
|
137
|
+
exports.unauthorizedResponse = unauthorizedResponse;
|
|
138
|
+
exports.validationErrorResponse = validationErrorResponse;
|
|
139
|
+
//# sourceMappingURL=index.js.map
|
|
140
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/server/response/response-object.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type { Response } from 'express';\r\nimport { StatusCode, StatusMessage } from '../enums/status';\r\n\r\n/**\r\n * Standard API Response Interface\r\n */\r\nexport interface ApiResponse<T = unknown> {\r\n message: string;\r\n data: T | null;\r\n status: string;\r\n statusCode: number;\r\n paginationData?: PaginationData;\r\n columns?: ColumnMetadata[];\r\n}\r\n\r\n/**\r\n * Pagination Data Interface\r\n */\r\nexport interface PaginationData {\r\n total?: number;\r\n page?: number;\r\n limit?: number;\r\n totalPages?: number;\r\n hasNextPage?: boolean;\r\n hasPrevPage?: boolean;\r\n}\r\n\r\n/**\r\n * Column Metadata Interface (for dynamic tables)\r\n */\r\nexport interface ColumnMetadata {\r\n name: string;\r\n datatype: string;\r\n required: boolean;\r\n}\r\n\r\n/**\r\n * Extract column metadata from data array\r\n */\r\nexport const extractColumns = <T extends Record<string, unknown>>(\r\n data: T[]\r\n): ColumnMetadata[] => {\r\n if (!Array.isArray(data) || data.length === 0) {\r\n return [];\r\n }\r\n\r\n const sample = data[0];\r\n return Object.entries(sample).map(([key, value]) => {\r\n let datatype: string = typeof value;\r\n\r\n if (value === null) {\r\n datatype = 'null';\r\n } else if (Array.isArray(value)) {\r\n datatype = 'array';\r\n } else if (value instanceof Date) {\r\n datatype = 'date';\r\n } else if (typeof value === 'object') {\r\n datatype = 'object';\r\n }\r\n\r\n return {\r\n name: key,\r\n datatype,\r\n required: value !== null && value !== undefined,\r\n };\r\n });\r\n};\r\n\r\n/**\r\n * Success Response (200)\r\n */\r\nexport const successResponse = <T>(\r\n res: Response,\r\n data: T,\r\n message = 'Operation successful'\r\n): Response => {\r\n return res.status(StatusCode.SUCCESS).json({\r\n message,\r\n data,\r\n status: StatusMessage.SUCCESS,\r\n statusCode: StatusCode.SUCCESS,\r\n });\r\n};\r\n\r\n/**\r\n * Success Response with Array & Pagination (200)\r\n */\r\nexport const successResponseArr = <T>(\r\n res: Response,\r\n data: T[],\r\n paginationData: PaginationData = {},\r\n message = 'Operation successful'\r\n): Response => {\r\n return res.status(StatusCode.SUCCESS).json({\r\n message,\r\n data,\r\n columns: extractColumns(data as Record<string, unknown>[]),\r\n paginationData,\r\n status: StatusMessage.SUCCESS,\r\n statusCode: StatusCode.SUCCESS,\r\n });\r\n};\r\n\r\n/**\r\n * Created Response (201)\r\n */\r\nexport const createdResponse = <T>(\r\n res: Response,\r\n data: T,\r\n message = 'Resource created successfully'\r\n): Response => {\r\n return res.status(StatusCode.CREATED).json({\r\n message,\r\n data,\r\n status: StatusMessage.CREATED,\r\n statusCode: StatusCode.CREATED,\r\n });\r\n};\r\n\r\n/**\r\n * No Content Response (204 as 200 with message)\r\n */\r\nexport const noContentResponse = <T = null>(\r\n res: Response,\r\n data: T = null as T,\r\n message = 'No data found'\r\n): Response => {\r\n return res.status(StatusCode.SUCCESS).json({\r\n message,\r\n data,\r\n status: StatusMessage.NO_CONTENT,\r\n statusCode: StatusCode.NO_CONTENT,\r\n });\r\n};\r\n\r\n/**\r\n * Bad Request Response (400)\r\n */\r\nexport const badRequestResponse = (\r\n res: Response,\r\n message = 'Bad request',\r\n errors: unknown = null\r\n): Response => {\r\n return res.status(StatusCode.BAD_REQUEST).json({\r\n message,\r\n data: errors,\r\n status: StatusMessage.BAD_REQUEST,\r\n statusCode: StatusCode.BAD_REQUEST,\r\n });\r\n};\r\n\r\n/**\r\n * Unauthorized Response (401)\r\n */\r\nexport const unauthorizedResponse = (\r\n res: Response,\r\n message = 'Unauthorized access'\r\n): Response => {\r\n return res.status(StatusCode.UNAUTHORIZED).json({\r\n message,\r\n data: null,\r\n status: StatusMessage.UNAUTHORIZED,\r\n statusCode: StatusCode.UNAUTHORIZED,\r\n });\r\n};\r\n\r\n/**\r\n * Forbidden Response (403)\r\n */\r\nexport const forbiddenResponse = (\r\n res: Response,\r\n message = 'Access forbidden'\r\n): Response => {\r\n return res.status(StatusCode.FORBIDDEN).json({\r\n message,\r\n data: null,\r\n status: StatusMessage.FORBIDDEN,\r\n statusCode: StatusCode.FORBIDDEN,\r\n });\r\n};\r\n\r\n/**\r\n * Not Found Response (404)\r\n */\r\nexport const notFoundResponse = (\r\n res: Response,\r\n message = 'Resource not found'\r\n): Response => {\r\n return res.status(StatusCode.NOT_FOUND).json({\r\n message,\r\n data: null,\r\n status: StatusMessage.NOT_FOUND,\r\n statusCode: StatusCode.NOT_FOUND,\r\n });\r\n};\r\n\r\n/**\r\n * Conflict Response (409)\r\n */\r\nexport const conflictResponse = (\r\n res: Response,\r\n message = 'Resource conflict'\r\n): Response => {\r\n return res.status(StatusCode.CONFLICT).json({\r\n message,\r\n data: null,\r\n status: StatusMessage.CONFLICT,\r\n statusCode: StatusCode.CONFLICT,\r\n });\r\n};\r\n\r\n/**\r\n * Validation Error Response (422)\r\n */\r\nexport const validationErrorResponse = (\r\n res: Response,\r\n errors: unknown,\r\n message = 'Validation failed'\r\n): Response => {\r\n return res.status(StatusCode.UNPROCESSABLE_ENTITY).json({\r\n message,\r\n data: errors,\r\n status: StatusMessage.UNPROCESSABLE_ENTITY,\r\n statusCode: StatusCode.UNPROCESSABLE_ENTITY,\r\n });\r\n};\r\n\r\n/**\r\n * Error Response (500)\r\n */\r\nexport const errorResponse = (\r\n res: Response,\r\n error: unknown = null,\r\n message = 'Something went wrong'\r\n): Response => {\r\n return res.status(StatusCode.INTERNAL_ERROR).json({\r\n message,\r\n data: error,\r\n status: StatusMessage.INTERNAL_ERROR,\r\n statusCode: StatusCode.INTERNAL_ERROR,\r\n });\r\n};\r\n\r\n/**\r\n * Rate Limit Response (429)\r\n */\r\nexport const rateLimitResponse = (\r\n res: Response,\r\n message = 'Too many requests, please try again later'\r\n): Response => {\r\n return res.status(StatusCode.TOO_MANY_REQUESTS).json({\r\n message,\r\n data: null,\r\n status: StatusMessage.TOO_MANY_REQUESTS,\r\n statusCode: StatusCode.TOO_MANY_REQUESTS,\r\n });\r\n};\r\n\r\nexport default {\r\n successResponse,\r\n successResponseArr,\r\n createdResponse,\r\n noContentResponse,\r\n badRequestResponse,\r\n unauthorizedResponse,\r\n forbiddenResponse,\r\n notFoundResponse,\r\n conflictResponse,\r\n validationErrorResponse,\r\n errorResponse,\r\n rateLimitResponse,\r\n extractColumns,\r\n};\r\n"]}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
// src/server/response/response-object.ts
|
|
2
|
+
var extractColumns = (data) => {
|
|
3
|
+
if (!Array.isArray(data) || data.length === 0) {
|
|
4
|
+
return [];
|
|
5
|
+
}
|
|
6
|
+
const sample = data[0];
|
|
7
|
+
return Object.entries(sample).map(([key, value]) => {
|
|
8
|
+
let datatype = typeof value;
|
|
9
|
+
if (value === null) {
|
|
10
|
+
datatype = "null";
|
|
11
|
+
} else if (Array.isArray(value)) {
|
|
12
|
+
datatype = "array";
|
|
13
|
+
} else if (value instanceof Date) {
|
|
14
|
+
datatype = "date";
|
|
15
|
+
} else if (typeof value === "object") {
|
|
16
|
+
datatype = "object";
|
|
17
|
+
}
|
|
18
|
+
return {
|
|
19
|
+
name: key,
|
|
20
|
+
datatype,
|
|
21
|
+
required: value !== null && value !== void 0
|
|
22
|
+
};
|
|
23
|
+
});
|
|
24
|
+
};
|
|
25
|
+
var successResponse = (res, data, message = "Operation successful") => {
|
|
26
|
+
return res.status(200 /* SUCCESS */).json({
|
|
27
|
+
message,
|
|
28
|
+
data,
|
|
29
|
+
status: "success" /* SUCCESS */,
|
|
30
|
+
statusCode: 200 /* SUCCESS */
|
|
31
|
+
});
|
|
32
|
+
};
|
|
33
|
+
var successResponseArr = (res, data, paginationData = {}, message = "Operation successful") => {
|
|
34
|
+
return res.status(200 /* SUCCESS */).json({
|
|
35
|
+
message,
|
|
36
|
+
data,
|
|
37
|
+
columns: extractColumns(data),
|
|
38
|
+
paginationData,
|
|
39
|
+
status: "success" /* SUCCESS */,
|
|
40
|
+
statusCode: 200 /* SUCCESS */
|
|
41
|
+
});
|
|
42
|
+
};
|
|
43
|
+
var createdResponse = (res, data, message = "Resource created successfully") => {
|
|
44
|
+
return res.status(201 /* CREATED */).json({
|
|
45
|
+
message,
|
|
46
|
+
data,
|
|
47
|
+
status: "created" /* CREATED */,
|
|
48
|
+
statusCode: 201 /* CREATED */
|
|
49
|
+
});
|
|
50
|
+
};
|
|
51
|
+
var noContentResponse = (res, data = null, message = "No data found") => {
|
|
52
|
+
return res.status(200 /* SUCCESS */).json({
|
|
53
|
+
message,
|
|
54
|
+
data,
|
|
55
|
+
status: "no-data-found" /* NO_CONTENT */,
|
|
56
|
+
statusCode: 204 /* NO_CONTENT */
|
|
57
|
+
});
|
|
58
|
+
};
|
|
59
|
+
var badRequestResponse = (res, message = "Bad request", errors = null) => {
|
|
60
|
+
return res.status(400 /* BAD_REQUEST */).json({
|
|
61
|
+
message,
|
|
62
|
+
data: errors,
|
|
63
|
+
status: "bad-request" /* BAD_REQUEST */,
|
|
64
|
+
statusCode: 400 /* BAD_REQUEST */
|
|
65
|
+
});
|
|
66
|
+
};
|
|
67
|
+
var unauthorizedResponse = (res, message = "Unauthorized access") => {
|
|
68
|
+
return res.status(401 /* UNAUTHORIZED */).json({
|
|
69
|
+
message,
|
|
70
|
+
data: null,
|
|
71
|
+
status: "unauthorized" /* UNAUTHORIZED */,
|
|
72
|
+
statusCode: 401 /* UNAUTHORIZED */
|
|
73
|
+
});
|
|
74
|
+
};
|
|
75
|
+
var forbiddenResponse = (res, message = "Access forbidden") => {
|
|
76
|
+
return res.status(403 /* FORBIDDEN */).json({
|
|
77
|
+
message,
|
|
78
|
+
data: null,
|
|
79
|
+
status: "forbidden" /* FORBIDDEN */,
|
|
80
|
+
statusCode: 403 /* FORBIDDEN */
|
|
81
|
+
});
|
|
82
|
+
};
|
|
83
|
+
var notFoundResponse = (res, message = "Resource not found") => {
|
|
84
|
+
return res.status(404 /* NOT_FOUND */).json({
|
|
85
|
+
message,
|
|
86
|
+
data: null,
|
|
87
|
+
status: "not-found" /* NOT_FOUND */,
|
|
88
|
+
statusCode: 404 /* NOT_FOUND */
|
|
89
|
+
});
|
|
90
|
+
};
|
|
91
|
+
var conflictResponse = (res, message = "Resource conflict") => {
|
|
92
|
+
return res.status(409 /* CONFLICT */).json({
|
|
93
|
+
message,
|
|
94
|
+
data: null,
|
|
95
|
+
status: "conflict" /* CONFLICT */,
|
|
96
|
+
statusCode: 409 /* CONFLICT */
|
|
97
|
+
});
|
|
98
|
+
};
|
|
99
|
+
var validationErrorResponse = (res, errors, message = "Validation failed") => {
|
|
100
|
+
return res.status(422 /* UNPROCESSABLE_ENTITY */).json({
|
|
101
|
+
message,
|
|
102
|
+
data: errors,
|
|
103
|
+
status: "validation-error" /* UNPROCESSABLE_ENTITY */,
|
|
104
|
+
statusCode: 422 /* UNPROCESSABLE_ENTITY */
|
|
105
|
+
});
|
|
106
|
+
};
|
|
107
|
+
var errorResponse = (res, error = null, message = "Something went wrong") => {
|
|
108
|
+
return res.status(500 /* INTERNAL_ERROR */).json({
|
|
109
|
+
message,
|
|
110
|
+
data: error,
|
|
111
|
+
status: "error" /* INTERNAL_ERROR */,
|
|
112
|
+
statusCode: 500 /* INTERNAL_ERROR */
|
|
113
|
+
});
|
|
114
|
+
};
|
|
115
|
+
var rateLimitResponse = (res, message = "Too many requests, please try again later") => {
|
|
116
|
+
return res.status(429 /* TOO_MANY_REQUESTS */).json({
|
|
117
|
+
message,
|
|
118
|
+
data: null,
|
|
119
|
+
status: "rate-limit-exceeded" /* TOO_MANY_REQUESTS */,
|
|
120
|
+
statusCode: 429 /* TOO_MANY_REQUESTS */
|
|
121
|
+
});
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
export { badRequestResponse, conflictResponse, createdResponse, errorResponse, extractColumns, forbiddenResponse, noContentResponse, notFoundResponse, rateLimitResponse, successResponse, successResponseArr, unauthorizedResponse, validationErrorResponse };
|
|
125
|
+
//# sourceMappingURL=index.mjs.map
|
|
126
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/server/response/response-object.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["import type { Response } from 'express';\r\nimport { StatusCode, StatusMessage } from '../enums/status';\r\n\r\n/**\r\n * Standard API Response Interface\r\n */\r\nexport interface ApiResponse<T = unknown> {\r\n message: string;\r\n data: T | null;\r\n status: string;\r\n statusCode: number;\r\n paginationData?: PaginationData;\r\n columns?: ColumnMetadata[];\r\n}\r\n\r\n/**\r\n * Pagination Data Interface\r\n */\r\nexport interface PaginationData {\r\n total?: number;\r\n page?: number;\r\n limit?: number;\r\n totalPages?: number;\r\n hasNextPage?: boolean;\r\n hasPrevPage?: boolean;\r\n}\r\n\r\n/**\r\n * Column Metadata Interface (for dynamic tables)\r\n */\r\nexport interface ColumnMetadata {\r\n name: string;\r\n datatype: string;\r\n required: boolean;\r\n}\r\n\r\n/**\r\n * Extract column metadata from data array\r\n */\r\nexport const extractColumns = <T extends Record<string, unknown>>(\r\n data: T[]\r\n): ColumnMetadata[] => {\r\n if (!Array.isArray(data) || data.length === 0) {\r\n return [];\r\n }\r\n\r\n const sample = data[0];\r\n return Object.entries(sample).map(([key, value]) => {\r\n let datatype: string = typeof value;\r\n\r\n if (value === null) {\r\n datatype = 'null';\r\n } else if (Array.isArray(value)) {\r\n datatype = 'array';\r\n } else if (value instanceof Date) {\r\n datatype = 'date';\r\n } else if (typeof value === 'object') {\r\n datatype = 'object';\r\n }\r\n\r\n return {\r\n name: key,\r\n datatype,\r\n required: value !== null && value !== undefined,\r\n };\r\n });\r\n};\r\n\r\n/**\r\n * Success Response (200)\r\n */\r\nexport const successResponse = <T>(\r\n res: Response,\r\n data: T,\r\n message = 'Operation successful'\r\n): Response => {\r\n return res.status(StatusCode.SUCCESS).json({\r\n message,\r\n data,\r\n status: StatusMessage.SUCCESS,\r\n statusCode: StatusCode.SUCCESS,\r\n });\r\n};\r\n\r\n/**\r\n * Success Response with Array & Pagination (200)\r\n */\r\nexport const successResponseArr = <T>(\r\n res: Response,\r\n data: T[],\r\n paginationData: PaginationData = {},\r\n message = 'Operation successful'\r\n): Response => {\r\n return res.status(StatusCode.SUCCESS).json({\r\n message,\r\n data,\r\n columns: extractColumns(data as Record<string, unknown>[]),\r\n paginationData,\r\n status: StatusMessage.SUCCESS,\r\n statusCode: StatusCode.SUCCESS,\r\n });\r\n};\r\n\r\n/**\r\n * Created Response (201)\r\n */\r\nexport const createdResponse = <T>(\r\n res: Response,\r\n data: T,\r\n message = 'Resource created successfully'\r\n): Response => {\r\n return res.status(StatusCode.CREATED).json({\r\n message,\r\n data,\r\n status: StatusMessage.CREATED,\r\n statusCode: StatusCode.CREATED,\r\n });\r\n};\r\n\r\n/**\r\n * No Content Response (204 as 200 with message)\r\n */\r\nexport const noContentResponse = <T = null>(\r\n res: Response,\r\n data: T = null as T,\r\n message = 'No data found'\r\n): Response => {\r\n return res.status(StatusCode.SUCCESS).json({\r\n message,\r\n data,\r\n status: StatusMessage.NO_CONTENT,\r\n statusCode: StatusCode.NO_CONTENT,\r\n });\r\n};\r\n\r\n/**\r\n * Bad Request Response (400)\r\n */\r\nexport const badRequestResponse = (\r\n res: Response,\r\n message = 'Bad request',\r\n errors: unknown = null\r\n): Response => {\r\n return res.status(StatusCode.BAD_REQUEST).json({\r\n message,\r\n data: errors,\r\n status: StatusMessage.BAD_REQUEST,\r\n statusCode: StatusCode.BAD_REQUEST,\r\n });\r\n};\r\n\r\n/**\r\n * Unauthorized Response (401)\r\n */\r\nexport const unauthorizedResponse = (\r\n res: Response,\r\n message = 'Unauthorized access'\r\n): Response => {\r\n return res.status(StatusCode.UNAUTHORIZED).json({\r\n message,\r\n data: null,\r\n status: StatusMessage.UNAUTHORIZED,\r\n statusCode: StatusCode.UNAUTHORIZED,\r\n });\r\n};\r\n\r\n/**\r\n * Forbidden Response (403)\r\n */\r\nexport const forbiddenResponse = (\r\n res: Response,\r\n message = 'Access forbidden'\r\n): Response => {\r\n return res.status(StatusCode.FORBIDDEN).json({\r\n message,\r\n data: null,\r\n status: StatusMessage.FORBIDDEN,\r\n statusCode: StatusCode.FORBIDDEN,\r\n });\r\n};\r\n\r\n/**\r\n * Not Found Response (404)\r\n */\r\nexport const notFoundResponse = (\r\n res: Response,\r\n message = 'Resource not found'\r\n): Response => {\r\n return res.status(StatusCode.NOT_FOUND).json({\r\n message,\r\n data: null,\r\n status: StatusMessage.NOT_FOUND,\r\n statusCode: StatusCode.NOT_FOUND,\r\n });\r\n};\r\n\r\n/**\r\n * Conflict Response (409)\r\n */\r\nexport const conflictResponse = (\r\n res: Response,\r\n message = 'Resource conflict'\r\n): Response => {\r\n return res.status(StatusCode.CONFLICT).json({\r\n message,\r\n data: null,\r\n status: StatusMessage.CONFLICT,\r\n statusCode: StatusCode.CONFLICT,\r\n });\r\n};\r\n\r\n/**\r\n * Validation Error Response (422)\r\n */\r\nexport const validationErrorResponse = (\r\n res: Response,\r\n errors: unknown,\r\n message = 'Validation failed'\r\n): Response => {\r\n return res.status(StatusCode.UNPROCESSABLE_ENTITY).json({\r\n message,\r\n data: errors,\r\n status: StatusMessage.UNPROCESSABLE_ENTITY,\r\n statusCode: StatusCode.UNPROCESSABLE_ENTITY,\r\n });\r\n};\r\n\r\n/**\r\n * Error Response (500)\r\n */\r\nexport const errorResponse = (\r\n res: Response,\r\n error: unknown = null,\r\n message = 'Something went wrong'\r\n): Response => {\r\n return res.status(StatusCode.INTERNAL_ERROR).json({\r\n message,\r\n data: error,\r\n status: StatusMessage.INTERNAL_ERROR,\r\n statusCode: StatusCode.INTERNAL_ERROR,\r\n });\r\n};\r\n\r\n/**\r\n * Rate Limit Response (429)\r\n */\r\nexport const rateLimitResponse = (\r\n res: Response,\r\n message = 'Too many requests, please try again later'\r\n): Response => {\r\n return res.status(StatusCode.TOO_MANY_REQUESTS).json({\r\n message,\r\n data: null,\r\n status: StatusMessage.TOO_MANY_REQUESTS,\r\n statusCode: StatusCode.TOO_MANY_REQUESTS,\r\n });\r\n};\r\n\r\nexport default {\r\n successResponse,\r\n successResponseArr,\r\n createdResponse,\r\n noContentResponse,\r\n badRequestResponse,\r\n unauthorizedResponse,\r\n forbiddenResponse,\r\n notFoundResponse,\r\n conflictResponse,\r\n validationErrorResponse,\r\n errorResponse,\r\n rateLimitResponse,\r\n extractColumns,\r\n};\r\n"]}
|