request-guardian 1.0.19 → 2.0.2

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 CHANGED
@@ -1,56 +1,115 @@
1
- # Readme for Request-Guardian
2
-
3
- `request-guardian` is a middleware function that validates incoming requests against a set of validation rules using `express-validator`. It can be used to ensure that data sent to a server is in the expected format and meets certain criteria. If the validation fails, it returns a 400 error response with an array of validation errors.
4
-
5
- ## Installation
6
-
7
- To install `request-guardian`, use `npm` or `yarn`.
8
-
9
- ```bash
10
- npm install request-guardian
11
- ```
12
-
13
- ```bash
14
- yarn add request-guardian
15
- ```
16
-
17
- ## Usage
18
-
19
- `request-guardian` is a middleware function that can be used with `Express` applications. To use it, simply require the module and use it as middleware for your routes.
20
-
21
- ***NOTE: Make sure that you call the validate() method after a middleware to parse incoming requests with JSON payloads.***
22
-
23
- ```javascript
24
- const express = require('express');
25
- const validate = require('request-guardian');
26
-
27
- const app = express();
28
-
29
- // middleware to parse incoming requests with JSON payloads.
30
- app.use(express.json());
31
-
32
- // Use Request Guardian middleware
33
- validate(app);
34
-
35
- // define your routes
36
- app.post('/users', (req, res) => {
37
- // handle validated request
38
- });
39
- ```
40
-
41
- Validation rules are defined in separate files located in the `utils/validations/index.js` directory. `request-guardian` will look for a file with the same name as the current route and load any validation rules defined within that file.
42
-
43
- ```javascript
44
- // utils/validations/index.js
45
-
46
- const { body } = require('express-validator');
47
-
48
- module.exports = {
49
- '/api/authentication/signup': [
50
- body('email').isEmail(),
51
- body('password').isLength({ min: 8 }),
52
- ]
53
- } ;
54
- ```
55
-
56
- If no validation rules are found for the current route, `request-guardian` will simply pass the request to the next middleware function in the stack.
1
+ # Request Guardian
2
+
3
+ `request-guardian` registers [express-validator](https://express-validator.github.io/) rules on an Express app. Rules come from your project's `utils/validations/index.js`. Failed validation returns **422**. Unexpected errors while running validators return **400**.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install request-guardian
9
+ ```
10
+
11
+ ```bash
12
+ yarn add request-guardian
13
+ ```
14
+
15
+ This package depends on `express-validator`. Use it with Express.
16
+
17
+ ## Usage
18
+
19
+ Call `validate(app)` **after** body parsers such as `express.json()`, and **before** you define route handlers. `validate` attaches middleware when it runs, so calling it after `app.post(...)` can skip validation.
20
+
21
+ ```javascript
22
+ const express = require('express');
23
+ const validate = require('request-guardian');
24
+
25
+ const app = express();
26
+
27
+ app.use(express.json());
28
+ validate(app);
29
+
30
+ app.post('/users', (req, res) => {
31
+ // request already passed validation for this path
32
+ });
33
+ ```
34
+
35
+ Put validation rules in `utils/validations/index.js` at the **application root** (the process working directory), not inside `node_modules`. Keys must match the Express paths you register.
36
+
37
+ Each path can be:
38
+
39
+ - An **array** of validation chains: applied to every method (`app.use`).
40
+ - An **object** keyed by HTTP method: different rules for `GET`, `POST`, and other methods on the same path.
41
+
42
+ Supported method keys (case-insensitive): `all`, `get`, `post`, `put`, `delete`, `patch`, `options`, `head`. Unknown keys are ignored.
43
+
44
+ ### Method-specific rules
45
+
46
+ Use this when the same path needs different rules per method:
47
+
48
+ ```javascript
49
+ // utils/validations/index.js
50
+ const { body, query } = require('express-validator');
51
+
52
+ module.exports = {
53
+ '/api/authentication/signup': {
54
+ GET: [
55
+ query('page').optional().isInt({ min: 1 }),
56
+ ],
57
+ POST: [
58
+ body('email').isEmail(),
59
+ body('password').isLength({ min: 8 }),
60
+ ],
61
+ },
62
+ };
63
+ ```
64
+
65
+ `all` applies to every method on that path, the same as a bare array:
66
+
67
+ ```javascript
68
+ module.exports = {
69
+ '/api/reports': {
70
+ all: [
71
+ query('from').optional().isISO8601(),
72
+ ],
73
+ },
74
+ };
75
+ ```
76
+
77
+ ### Same rules for every method
78
+
79
+ ```javascript
80
+ const { body } = require('express-validator');
81
+
82
+ module.exports = {
83
+ '/api/users': [
84
+ body('name').notEmpty(),
85
+ ],
86
+ };
87
+ ```
88
+
89
+ If a path is not listed, no validation middleware is attached for it. If `utils/validations/index.js` is missing, `validate()` logs `Validations rules not found at utils/validations/index.js` and registers nothing.
90
+
91
+ ## Responses
92
+
93
+ Validation failure:
94
+
95
+ ```json
96
+ {
97
+ "data": [],
98
+ "status": "VALIDATION_ERROR",
99
+ "message": "Invalid Data, Validation Failed."
100
+ }
101
+ ```
102
+
103
+ `data` is `express-validator`'s `errors.array()`.
104
+
105
+ Unexpected error while running validators:
106
+
107
+ ```json
108
+ {
109
+ "data": "error message",
110
+ "status": "BAD_REQUEST",
111
+ "message": "error message"
112
+ }
113
+ ```
114
+
115
+ HTTP status codes: **422** for validation errors, **400** for other failures in the validator.
package/index.js CHANGED
@@ -1,45 +1,90 @@
1
- const { validationResult } = require('express-validator');
2
- const path = require('path');
3
-
4
- function runValidator(validations) {
5
- return async function _runValidator(req, res, next) {
6
- try {
7
- if (!validations) return next();
8
- for (let validation of validations) {
9
- const result = await validation.run(req);
10
- if (result.errors.length) break;
11
- }
12
- const errors = validationResult(req);
13
- if (errors.isEmpty()) {
14
- return next();
15
- }
16
- res.status(422).json({
17
- data: errors.array(),
18
- status: 'VALIDATION_ERROR',
19
- message: 'Invalid Data, Validation Failed.',
20
- });
21
- } catch (error) {
22
- let message = error.message;
23
- if (error.code === 'MODULE_NOT_FOUND') {
24
- message = `Validations rules not found for ${req.path}`;
25
- }
26
- res.status(400).json({
27
- data: message,
28
- status: 'BAD_REQUEST',
29
- message: message,
30
- });
31
- }
32
- };
33
- }
34
- function validate(app) {
35
- try {
36
- for (const key in require(path.resolve('utils/validations/index'))) {
37
- app.use(key, runValidator(require(path.resolve('utils/validations/index'))[key]));
38
- }
39
- } catch (error) {
40
- if (error.code === 'MODULE_NOT_FOUND') {
41
- console.log(`Validations rules not found at utils/validations/index.js`)
42
- }
43
- }
44
- }
1
+ const { validationResult } = require('express-validator');
2
+ const path = require('path');
3
+
4
+ const VALID_HTTP_METHODS = new Set([
5
+ 'all',
6
+ 'get',
7
+ 'post',
8
+ 'put',
9
+ 'delete',
10
+ 'patch',
11
+ 'options',
12
+ 'head',
13
+ ]);
14
+
15
+ function runValidator(validations) {
16
+ return async function _runValidator(req, res, next) {
17
+ try {
18
+ if (!validations) return next();
19
+ for (let validation of validations) {
20
+ const result = await validation.run(req);
21
+ if (result.errors.length) break;
22
+ }
23
+ const errors = validationResult(req);
24
+ if (errors.isEmpty()) {
25
+ return next();
26
+ }
27
+ res.status(422).json({
28
+ data: errors.array(),
29
+ status: 'VALIDATION_ERROR',
30
+ message: 'Invalid Data, Validation Failed.',
31
+ });
32
+ } catch (error) {
33
+ let message = error.message;
34
+ if (error.code === 'MODULE_NOT_FOUND') {
35
+ message = `Validations rules not found for ${req.path}`;
36
+ }
37
+ res.status(400).json({
38
+ data: message,
39
+ status: 'BAD_REQUEST',
40
+ message: message,
41
+ });
42
+ }
43
+ };
44
+ }
45
+
46
+ function registerRouteValidation(app, routeName, validationConfig) {
47
+ if (!validationConfig) return;
48
+
49
+ if (Array.isArray(validationConfig)) {
50
+ app.use(routeName, runValidator(validationConfig));
51
+ return;
52
+ }
53
+
54
+ if (typeof validationConfig !== 'object') {
55
+ return;
56
+ }
57
+
58
+ for (const [method, rules] of Object.entries(validationConfig)) {
59
+ const normalizedMethod = method.toLowerCase();
60
+
61
+ if (!VALID_HTTP_METHODS.has(normalizedMethod)) {
62
+ continue;
63
+ }
64
+
65
+ if (Array.isArray(rules)) {
66
+ if (normalizedMethod === 'all') {
67
+ app.use(routeName, runValidator(rules));
68
+ continue;
69
+ }
70
+
71
+ app[normalizedMethod](routeName, runValidator(rules));
72
+ }
73
+ }
74
+ }
75
+
76
+ function validate(app) {
77
+ try {
78
+ const validationRules = require(path.resolve('utils/validations/index'));
79
+
80
+ for (const [key, value] of Object.entries(validationRules || {})) {
81
+ registerRouteValidation(app, key, value);
82
+ }
83
+ } catch (error) {
84
+ if (error.code === 'MODULE_NOT_FOUND') {
85
+ console.log(`Validations rules not found at utils/validations/index.js`);
86
+ }
87
+ }
88
+ }
89
+
45
90
  module.exports = validate;
package/package.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "request-guardian",
3
- "version": "1.0.19",
4
- "description": "",
3
+ "version": "2.0.2",
4
+ "description": "Express middleware that runs express-validator rules from utils/validations/index.js, including per-method rules.",
5
5
  "main": "index.js",
6
6
  "scripts": {
7
7
  "test": "echo \"Error: no test specified\" && exit 1"
8
8
  },
9
9
  "repository": {
10
10
  "type": "git",
11
- "url": "https://github.com/saiyadzaid/request-guardian.git"
11
+ "url": "git+https://github.com/saiyadzaid/request-guardian.git"
12
12
  },
13
13
  "keywords": [
14
14
  "express",
@@ -0,0 +1,13 @@
1
+ const { body, query } = require('express-validator');
2
+
3
+ module.exports = {
4
+ '/api/authentication/signup': {
5
+ GET: [
6
+ query('page').optional().isInt({ min: 1 }),
7
+ ],
8
+ POST: [
9
+ body('email').isEmail(),
10
+ body('password').isLength({ min: 8 }),
11
+ ],
12
+ },
13
+ };