response-kit 1.0.0 → 2.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/package.json CHANGED
@@ -1,51 +1,67 @@
1
- {
2
- "name": "response-kit",
3
- "version": "1.0.0",
4
- "description": "Standardized API response utility for Node.js and Express.js",
5
- "main": "./src/index.js",
6
- "types": "./index.d.ts",
7
- "exports": {
8
- ".": {
9
- "require": "./src/index.js",
10
- "import": "./src/index.js",
11
- "types": "./index.d.ts"
12
- }
13
- },
14
- "files": [
15
- "src",
16
- "docs",
17
- "index.d.ts",
18
- "README.md",
19
- "LICENSE"
20
- ],
21
- "scripts": {
22
- "lint": "eslint .",
23
- "format": "prettier --write ."
24
- },
25
- "keywords": [
26
- "express",
27
- "nodejs",
28
- "api",
29
- "response",
30
- "response-helper",
31
- "api-response",
32
- "backend"
33
- ],
34
- "author": "Piyush Yadav",
35
- "license": "MIT",
36
- "type": "commonjs",
37
- "repository": {
38
- "type": "git",
39
- "url": "git+https://github.com/piyush72yaduvanshi/api-response-kit.git"
40
- },
41
- "bugs": {
42
- "url": "https://github.com/piyush72yaduvanshi/api-response-kit/issues"
43
- },
44
- "homepage": "https://github.com/piyush72yaduvanshi/api-response-kit#readme",
45
- "devDependencies": {
46
- "eslint": "^10.5.0",
47
- "jest": "^30.4.2",
48
- "prettier": "^3.8.4",
49
- "typescript": "^6.0.3"
50
- }
51
- }
1
+ {
2
+ "name": "response-kit",
3
+ "version": "2.0.0",
4
+ "description": "Production-grade API response utility for Node.js and Express.js with middleware support, global configuration, and async handlers",
5
+ "main": "./src/index.js",
6
+ "types": "./index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "require": "./src/index.js",
10
+ "import": "./src/index.js",
11
+ "types": "./index.d.ts"
12
+ }
13
+ },
14
+ "files": [
15
+ "src",
16
+ "docs",
17
+ "index.d.ts",
18
+ "README.md",
19
+ "LICENSE"
20
+ ],
21
+ "scripts": {
22
+ "lint": "eslint .",
23
+ "format": "prettier --write .",
24
+ "test:ts": "tsc -p tsconfig.json"
25
+ },
26
+ "keywords": [
27
+ "express",
28
+ "nodejs",
29
+ "api",
30
+ "response",
31
+ "response-helper",
32
+ "api-response",
33
+ "backend",
34
+ "middleware",
35
+ "async-handler",
36
+ "express-middleware",
37
+ "response-kit",
38
+ "error-handler"
39
+ ],
40
+ "author": "Piyush Yadav",
41
+ "license": "MIT",
42
+ "type": "commonjs",
43
+ "repository": {
44
+ "type": "git",
45
+ "url": "git+https://github.com/piyush72yaduvanshi/api-response-kit.git"
46
+ },
47
+ "bugs": {
48
+ "url": "https://github.com/piyush72yaduvanshi/api-response-kit/issues"
49
+ },
50
+ "homepage": "https://github.com/piyush72yaduvanshi/api-response-kit#readme",
51
+ "peerDependencies": {
52
+ "express": ">=4.0.0"
53
+ },
54
+ "peerDependenciesMeta": {
55
+ "express": {
56
+ "optional": true
57
+ }
58
+ },
59
+ "devDependencies": {
60
+ "@types/express": "^4.17.25",
61
+ "@types/node": "^20.14.5",
62
+ "express": "^4.21.2",
63
+ "jest": "^30.4.2",
64
+ "prettier": "^3.8.4",
65
+ "typescript": "^6.0.3"
66
+ }
67
+ }
@@ -0,0 +1,94 @@
1
+ class Config {
2
+ constructor() {
3
+ this.settings = {
4
+ successKey: 'success',
5
+ dataKey: 'data',
6
+ messageKey: 'message',
7
+ errorKey: 'errors',
8
+ includeTimestamp: false,
9
+ includeRequestId: false,
10
+ includeMeta: false,
11
+ timestampKey: 'timestamp',
12
+ requestIdKey: 'requestId',
13
+ metaKey: 'meta',
14
+ };
15
+ }
16
+
17
+ /**
18
+ * Configure global settings
19
+ * @param {Object} options - Configuration options
20
+ */
21
+ configure(options = {}) {
22
+ this.settings = {
23
+ ...this.settings,
24
+ ...options,
25
+ };
26
+ }
27
+
28
+ /**
29
+ * Get current configuration
30
+ * @returns {Object} Current settings
31
+ */
32
+ getConfig() {
33
+ return { ...this.settings };
34
+ }
35
+
36
+ /**
37
+ * Reset to default configuration
38
+ */
39
+ reset() {
40
+ this.settings = {
41
+ successKey: 'success',
42
+ dataKey: 'data',
43
+ messageKey: 'message',
44
+ errorKey: 'errors',
45
+ includeTimestamp: false,
46
+ includeRequestId: false,
47
+ includeMeta: false,
48
+ timestampKey: 'timestamp',
49
+ requestIdKey: 'requestId',
50
+ metaKey: 'meta',
51
+ };
52
+ }
53
+
54
+ /**
55
+ * Build response object based on configuration
56
+ * @param {Object} baseResponse - Base response object
57
+ * @param {Object} req - Express request object
58
+ * @returns {Object} Configured response object
59
+ */
60
+ buildResponse(baseResponse, req = null) {
61
+ const response = { ...baseResponse };
62
+
63
+ if (this.settings.includeTimestamp) {
64
+ response[this.settings.timestampKey] = new Date().toISOString();
65
+ }
66
+
67
+ if (this.settings.includeRequestId && req) {
68
+ const requestId = req.id || req.headers['x-request-id'] || this.generateRequestId();
69
+ response[this.settings.requestIdKey] = requestId;
70
+ }
71
+
72
+ if (this.settings.includeMeta && req) {
73
+ response[this.settings.metaKey] = {
74
+ method: req.method,
75
+ path: req.path,
76
+ };
77
+ }
78
+
79
+ return response;
80
+ }
81
+
82
+ /**
83
+ * Generate a simple request ID
84
+ * @returns {string} Generated request ID
85
+ */
86
+ generateRequestId() {
87
+ return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
88
+ }
89
+ }
90
+
91
+ // Singleton instance
92
+ const config = new Config();
93
+
94
+ module.exports = config;
@@ -0,0 +1,104 @@
1
+ const config = require('../core/config');
2
+
3
+ /**
4
+ * Send error response
5
+ * @param {Object} res - Express response object
6
+ * @param {number} statusCode - HTTP status code
7
+ * @param {string} message - Error message
8
+ * @param {*} errors - Error details
9
+ * @param {Object} req - Express request object (optional)
10
+ * @returns {Object} Express response
11
+ */
12
+ const sendError = (
13
+ res,
14
+ statusCode,
15
+ message,
16
+ errors = null,
17
+ req = null
18
+ ) => {
19
+ const settings = config.getConfig();
20
+
21
+ const baseResponse = {
22
+ [settings.successKey]: false,
23
+ [settings.messageKey]: message,
24
+ };
25
+
26
+ // Only include errors if they exist
27
+ if (errors !== null) {
28
+ baseResponse[settings.errorKey] = errors;
29
+ }
30
+
31
+ const response = config.buildResponse(baseResponse, req);
32
+
33
+ return res.status(statusCode).json(response);
34
+ };
35
+
36
+ /**
37
+ * Send 400 Bad Request response
38
+ * @param {Object} res - Express response object
39
+ * @param {string} message - Error message
40
+ * @param {Object} req - Express request object (optional)
41
+ * @returns {Object} Express response
42
+ */
43
+ const badRequest = (res, message = 'Bad Request', req = null) =>
44
+ sendError(res, 400, message, null, req);
45
+
46
+ /**
47
+ * Send 401 Unauthorized response
48
+ * @param {Object} res - Express response object
49
+ * @param {string} message - Error message
50
+ * @param {Object} req - Express request object (optional)
51
+ * @returns {Object} Express response
52
+ */
53
+ const unauthorized = (res, message = 'Unauthorized', req = null) =>
54
+ sendError(res, 401, message, null, req);
55
+
56
+ /**
57
+ * Send 403 Forbidden response
58
+ * @param {Object} res - Express response object
59
+ * @param {string} message - Error message
60
+ * @param {Object} req - Express request object (optional)
61
+ * @returns {Object} Express response
62
+ */
63
+ const forbidden = (res, message = 'Forbidden', req = null) =>
64
+ sendError(res, 403, message, null, req);
65
+
66
+ /**
67
+ * Send 404 Not Found response
68
+ * @param {Object} res - Express response object
69
+ * @param {string} message - Error message
70
+ * @param {Object} req - Express request object (optional)
71
+ * @returns {Object} Express response
72
+ */
73
+ const notFound = (res, message = 'Not Found', req = null) =>
74
+ sendError(res, 404, message, null, req);
75
+
76
+ /**
77
+ * Send 409 Conflict response
78
+ * @param {Object} res - Express response object
79
+ * @param {string} message - Error message
80
+ * @param {Object} req - Express request object (optional)
81
+ * @returns {Object} Express response
82
+ */
83
+ const conflict = (res, message = 'Conflict', req = null) =>
84
+ sendError(res, 409, message, null, req);
85
+
86
+ /**
87
+ * Send 500 Internal Server Error response
88
+ * @param {Object} res - Express response object
89
+ * @param {string} message - Error message
90
+ * @param {Object} req - Express request object (optional)
91
+ * @returns {Object} Express response
92
+ */
93
+ const internalError = (res, message = 'Internal Server Error', req = null) =>
94
+ sendError(res, 500, message, null, req);
95
+
96
+ module.exports = {
97
+ sendError,
98
+ badRequest,
99
+ unauthorized,
100
+ forbidden,
101
+ notFound,
102
+ conflict,
103
+ internalError,
104
+ };
@@ -0,0 +1,41 @@
1
+ const config = require('../core/config');
2
+
3
+ /**
4
+ * Send paginated response
5
+ * @param {Object} res - Express response object
6
+ * @param {Array} data - Array of data items
7
+ * @param {number} page - Current page number
8
+ * @param {number} limit - Items per page
9
+ * @param {number} total - Total number of items
10
+ * @param {Object} req - Express request object (optional)
11
+ * @returns {Object} Express response
12
+ */
13
+ const paginate = (
14
+ res,
15
+ data,
16
+ page,
17
+ limit,
18
+ total,
19
+ req = null
20
+ ) => {
21
+ const settings = config.getConfig();
22
+
23
+ const baseResponse = {
24
+ [settings.successKey]: true,
25
+ [settings.dataKey]: data,
26
+ pagination: {
27
+ page: parseInt(page),
28
+ limit: parseInt(limit),
29
+ total: parseInt(total),
30
+ totalPages: Math.ceil(total / limit),
31
+ },
32
+ };
33
+
34
+ const response = config.buildResponse(baseResponse, req);
35
+
36
+ return res.status(200).json(response);
37
+ };
38
+
39
+ module.exports = {
40
+ paginate,
41
+ };
@@ -0,0 +1,52 @@
1
+ const config = require('../core/config');
2
+
3
+ /**
4
+ * Send success response
5
+ * @param {Object} res - Express response object
6
+ * @param {*} data - Response data
7
+ * @param {string} message - Success message
8
+ * @param {number} statusCode - HTTP status code
9
+ * @param {Object} req - Express request object (optional)
10
+ * @returns {Object} Express response
11
+ */
12
+ const success = (
13
+ res,
14
+ data = null,
15
+ message = 'Success',
16
+ statusCode = 200,
17
+ req = null
18
+ ) => {
19
+ const settings = config.getConfig();
20
+
21
+ const baseResponse = {
22
+ [settings.successKey]: true,
23
+ [settings.messageKey]: message,
24
+ [settings.dataKey]: data,
25
+ };
26
+
27
+ const response = config.buildResponse(baseResponse, req);
28
+
29
+ return res.status(statusCode).json(response);
30
+ };
31
+
32
+ /**
33
+ * Send created response (201)
34
+ * @param {Object} res - Express response object
35
+ * @param {*} data - Response data
36
+ * @param {string} message - Success message
37
+ * @param {Object} req - Express request object (optional)
38
+ * @returns {Object} Express response
39
+ */
40
+ const created = (
41
+ res,
42
+ data = null,
43
+ message = 'Created Successfully',
44
+ req = null
45
+ ) => {
46
+ return success(res, data, message, 201, req);
47
+ };
48
+
49
+ module.exports = {
50
+ success,
51
+ created,
52
+ };
@@ -0,0 +1,32 @@
1
+ const config = require('../core/config');
2
+
3
+ /**
4
+ * Send validation error response (422)
5
+ * @param {Object} res - Express response object
6
+ * @param {Object} errors - Validation errors
7
+ * @param {string} message - Error message
8
+ * @param {Object} req - Express request object (optional)
9
+ * @returns {Object} Express response
10
+ */
11
+ const validationError = (
12
+ res,
13
+ errors = {},
14
+ message = 'Validation Failed',
15
+ req = null
16
+ ) => {
17
+ const settings = config.getConfig();
18
+
19
+ const baseResponse = {
20
+ [settings.successKey]: false,
21
+ [settings.messageKey]: message,
22
+ [settings.errorKey]: errors,
23
+ };
24
+
25
+ const response = config.buildResponse(baseResponse, req);
26
+
27
+ return res.status(422).json(response);
28
+ };
29
+
30
+ module.exports = {
31
+ validationError,
32
+ };
package/src/index.js CHANGED
@@ -1,6 +1,83 @@
1
- module.exports = {
2
- ...require("./success"),
3
- ...require("./error"),
4
- ...require("./validation"),
5
- ...require("./pagination"),
6
- };
1
+ /**
2
+ * Response Kit v2.0.0
3
+ * Production-grade API response utility for Express.js
4
+ *
5
+ * Backward compatible with v1.x
6
+ */
7
+
8
+ const config = require('./core/config');
9
+ const responseMiddleware = require('./middleware/response');
10
+ const asyncHandler = require('./middleware/asyncHandler');
11
+
12
+ // Import refactored helpers (v2 - with config support)
13
+ const { success, created } = require('./helpers/success');
14
+ const {
15
+ badRequest,
16
+ unauthorized,
17
+ forbidden,
18
+ notFound,
19
+ conflict,
20
+ internalError,
21
+ } = require('./helpers/error');
22
+ const { validationError } = require('./helpers/validation');
23
+ const { paginate } = require('./helpers/pagination');
24
+
25
+ /**
26
+ * Main response object
27
+ * Provides both v1 (backward compatible) and v2 (new) APIs
28
+ */
29
+ const response = {
30
+ // V1 API - Backward compatible
31
+ // These maintain the original signature: fn(res, ...)
32
+ success,
33
+ created,
34
+ badRequest,
35
+ unauthorized,
36
+ forbidden,
37
+ notFound,
38
+ conflict,
39
+ internalError,
40
+ validationError,
41
+ paginate,
42
+
43
+ // V2 API - New features
44
+ /**
45
+ * Configure global response settings
46
+ * @param {Object} options - Configuration options
47
+ */
48
+ configure: (options) => config.configure(options),
49
+
50
+ /**
51
+ * Get current configuration
52
+ * @returns {Object} Current configuration
53
+ */
54
+ getConfig: () => config.getConfig(),
55
+
56
+ /**
57
+ * Reset configuration to defaults
58
+ */
59
+ resetConfig: () => config.reset(),
60
+
61
+ /**
62
+ * Express middleware factory
63
+ * Attaches response helpers to res object
64
+ * Usage: app.use(response.middleware())
65
+ * @returns {Function} Express middleware
66
+ */
67
+ middleware: responseMiddleware,
68
+
69
+ /**
70
+ * Async handler wrapper
71
+ * Eliminates try-catch blocks in route handlers
72
+ * Usage: router.get('/path', response.asyncHandler(async (req, res) => {...}))
73
+ * @param {Function} fn - Async route handler
74
+ * @returns {Function} Wrapped handler
75
+ */
76
+ asyncHandler,
77
+ };
78
+
79
+ // For CommonJS default export
80
+ module.exports = response;
81
+
82
+ // For ES modules compatibility
83
+ module.exports.default = response;
@@ -0,0 +1,14 @@
1
+
2
+ /**
3
+ * Wraps async route handlers to catch errors
4
+ * @param {Function} fn - Async route handler function
5
+ * @returns {Function} Express middleware function
6
+ */
7
+ function asyncHandler(fn) {
8
+ return function (req, res, next) {
9
+ // Ensure fn returns a promise, then catch any errors
10
+ Promise.resolve(fn(req, res, next)).catch(next);
11
+ };
12
+ }
13
+
14
+ module.exports = asyncHandler;
@@ -0,0 +1,69 @@
1
+ const config = require('../core/config');
2
+ const { success, created } = require('../helpers/success');
3
+ const {
4
+ badRequest,
5
+ unauthorized,
6
+ forbidden,
7
+ notFound,
8
+ conflict,
9
+ internalError,
10
+ } = require('../helpers/error');
11
+ const { validationError } = require('../helpers/validation');
12
+ const { paginate } = require('../helpers/pagination');
13
+
14
+ /**
15
+ * Response middleware factory
16
+ * Attaches all response helpers to Express res object
17
+ * @returns {Function} Express middleware
18
+ */
19
+ function responseMiddleware() {
20
+ return function (req, res, next) {
21
+ // Success responses
22
+ res.success = function (data = null, message = 'Success', statusCode = 200) {
23
+ return success(res, data, message, statusCode, req);
24
+ };
25
+
26
+ res.created = function (data = null, message = 'Created Successfully') {
27
+ return created(res, data, message, req);
28
+ };
29
+
30
+ // Error responses
31
+ res.badRequest = function (message = 'Bad Request') {
32
+ return badRequest(res, message, req);
33
+ };
34
+
35
+ res.unauthorized = function (message = 'Unauthorized') {
36
+ return unauthorized(res, message, req);
37
+ };
38
+
39
+ res.forbidden = function (message = 'Forbidden') {
40
+ return forbidden(res, message, req);
41
+ };
42
+
43
+ res.notFound = function (message = 'Not Found') {
44
+ return notFound(res, message, req);
45
+ };
46
+
47
+ res.conflict = function (message = 'Conflict') {
48
+ return conflict(res, message, req);
49
+ };
50
+
51
+ res.internalError = function (message = 'Internal Server Error') {
52
+ return internalError(res, message, req);
53
+ };
54
+
55
+ // Validation error
56
+ res.validationError = function (errors = {}, message = 'Validation Failed') {
57
+ return validationError(res, errors, message, req);
58
+ };
59
+
60
+ // Pagination
61
+ res.paginate = function (data, page, limit, total) {
62
+ return paginate(res, data, page, limit, total, req);
63
+ };
64
+
65
+ next();
66
+ };
67
+ }
68
+
69
+ module.exports = responseMiddleware;
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Validate if value is a valid HTTP status code
3
+ * @param {number} statusCode - Status code to validate
4
+ * @returns {boolean} True if valid
5
+ */
6
+ function isValidStatusCode(statusCode) {
7
+ return typeof statusCode === 'number' && statusCode >= 100 && statusCode < 600;
8
+ }
9
+
10
+ /**
11
+ * Validate if value is a string
12
+ * @param {*} value - Value to validate
13
+ * @returns {boolean} True if string
14
+ */
15
+ function isString(value) {
16
+ return typeof value === 'string';
17
+ }
18
+
19
+ /**
20
+ * Validate if value is an object
21
+ * @param {*} value - Value to validate
22
+ * @returns {boolean} True if object
23
+ */
24
+ function isObject(value) {
25
+ return value !== null && typeof value === 'object' && !Array.isArray(value);
26
+ }
27
+
28
+ /**
29
+ * Validate if value is an array
30
+ * @param {*} value - Value to validate
31
+ * @returns {boolean} True if array
32
+ */
33
+ function isArray(value) {
34
+ return Array.isArray(value);
35
+ }
36
+
37
+ /**
38
+ * Validate pagination parameters
39
+ * @param {number} page - Page number
40
+ * @param {number} limit - Items per page
41
+ * @param {number} total - Total items
42
+ * @returns {Object} Validation result
43
+ */
44
+ function validatePaginationParams(page, limit, total) {
45
+ const errors = [];
46
+
47
+ if (!Number.isInteger(page) || page < 1) {
48
+ errors.push('Page must be a positive integer');
49
+ }
50
+
51
+ if (!Number.isInteger(limit) || limit < 1) {
52
+ errors.push('Limit must be a positive integer');
53
+ }
54
+
55
+ if (!Number.isInteger(total) || total < 0) {
56
+ errors.push('Total must be a non-negative integer');
57
+ }
58
+
59
+ return {
60
+ valid: errors.length === 0,
61
+ errors,
62
+ };
63
+ }
64
+
65
+ module.exports = {
66
+ isValidStatusCode,
67
+ isString,
68
+ isObject,
69
+ isArray,
70
+ validatePaginationParams,
71
+ };