@dwtechs/antity 0.12.0 → 0.14.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 +90 -25
- package/dist/antity.d.ts +5 -2
- package/dist/antity.js +71 -35
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
[](https://opensource.org/licenses/MIT)
|
|
3
3
|
[](https://www.npmjs.com/package/@dwtechs/antity)
|
|
4
4
|
[](https://www.npmjs.com/package/@dwtechs/antity)
|
|
5
|
-

|
|
6
6
|
|
|
7
7
|
- [Synopsis](#synopsis)
|
|
8
8
|
- [Support](#support)
|
|
@@ -112,9 +112,9 @@ const entity = new Entity("consumers", [
|
|
|
112
112
|
},
|
|
113
113
|
]);
|
|
114
114
|
|
|
115
|
-
// add a consumer. Used when
|
|
116
|
-
router.post("/", entity.
|
|
117
|
-
// or use check method to
|
|
115
|
+
// add a consumer. Used when logging in from user service
|
|
116
|
+
router.post("/", entity.normalizeArray, entity.validateArray, ...);
|
|
117
|
+
// or use check method to normalize and validate array at once
|
|
118
118
|
router.put("/", entity.check, ...);
|
|
119
119
|
|
|
120
120
|
```
|
|
@@ -227,11 +227,12 @@ class Entity {
|
|
|
227
227
|
getPropsByMethod(method: Method): Property[];
|
|
228
228
|
|
|
229
229
|
/**
|
|
230
|
-
* Normalizes
|
|
230
|
+
* Normalizes an array of records by applying sanitization and normalization
|
|
231
|
+
* rules defined in the properties of the class.
|
|
231
232
|
*
|
|
232
|
-
* - Applies sanitization if `sanitize: true`
|
|
233
|
-
* - Applies normalization if `normalize: true`
|
|
234
|
-
* - Mutates req.body.rows with sanitized/normalized values
|
|
233
|
+
* - Applies sanitization if `sanitize: true`
|
|
234
|
+
* - Applies normalization if `normalize: true`
|
|
235
|
+
* - Mutates req.body.rows or req.body with sanitized/normalized values
|
|
235
236
|
* - Calls next(error) on failure, next() on success
|
|
236
237
|
*
|
|
237
238
|
* @param {Request} req - Express request object containing rows
|
|
@@ -241,25 +242,58 @@ class Entity {
|
|
|
241
242
|
* @returns {void}
|
|
242
243
|
*
|
|
243
244
|
* **Input Properties Required:**
|
|
244
|
-
* - `req.body.rows` (array) - Array of objects to normalize
|
|
245
|
+
* - `req.body.rows` (array) or `req.body` (array) - Array of objects to normalize
|
|
245
246
|
* - Each property config can specify sanitize, normalize, etc.
|
|
246
247
|
*
|
|
247
248
|
* **Output Properties:**
|
|
248
|
-
* - Mutates
|
|
249
|
-
* - Calls next(error) if
|
|
249
|
+
* - Mutates array with sanitized/normalized values
|
|
250
|
+
* - Calls next(error) if normalization fails, next() if all pass
|
|
250
251
|
*
|
|
251
252
|
* @example
|
|
252
253
|
* ```typescript
|
|
253
|
-
* router.post('/
|
|
254
|
+
* router.post('/entities', entity.normalizeArray, (req, res) => {
|
|
254
255
|
* // req.body.rows are now sanitized and normalized
|
|
255
256
|
* res.json({ success: true });
|
|
256
257
|
* });
|
|
257
258
|
* ```
|
|
258
259
|
*/
|
|
259
|
-
|
|
260
|
+
normalizeArray: (req: Request, _res: Response, next: NextFunction) => void;
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Normalizes a single record by applying sanitization and normalization
|
|
264
|
+
* rules defined in the properties of the class.
|
|
265
|
+
*
|
|
266
|
+
* - Applies sanitization if `sanitize: true`
|
|
267
|
+
* - Applies normalization if `normalize: true`
|
|
268
|
+
* - Mutates req.body with sanitized/normalized values
|
|
269
|
+
* - Calls next(error) on failure, next() on success
|
|
270
|
+
*
|
|
271
|
+
* @param {Request} req - Express request object containing a single record
|
|
272
|
+
* @param {Response} _res - Express response object (not used)
|
|
273
|
+
* @param {NextFunction} next - Express next function
|
|
274
|
+
*
|
|
275
|
+
* @returns {void}
|
|
276
|
+
*
|
|
277
|
+
* **Input Properties Required:**
|
|
278
|
+
* - `req.body` (object) - Single object to normalize
|
|
279
|
+
* - Each property config can specify sanitize, normalize, etc.
|
|
280
|
+
*
|
|
281
|
+
* **Output Properties:**
|
|
282
|
+
* - Mutates `req.body` with sanitized/normalized values
|
|
283
|
+
* - Calls next(error) if normalization fails, next() if success
|
|
284
|
+
*
|
|
285
|
+
* @example
|
|
286
|
+
* ```typescript
|
|
287
|
+
* router.post('/entity', entity.normalizeOne, (req, res) => {
|
|
288
|
+
* // req.body is now sanitized and normalized
|
|
289
|
+
* res.json({ success: true });
|
|
290
|
+
* });
|
|
291
|
+
* ```
|
|
292
|
+
*/
|
|
293
|
+
normalizeOne: (req: Request, _res: Response, next: NextFunction) => void;
|
|
260
294
|
|
|
261
295
|
/**
|
|
262
|
-
* Validates
|
|
296
|
+
* Validates an array of rows according to property config and HTTP method.
|
|
263
297
|
*
|
|
264
298
|
* - Checks required properties and validates values
|
|
265
299
|
* - Calls next(error) on failure, next() on success
|
|
@@ -271,7 +305,7 @@ class Entity {
|
|
|
271
305
|
* @returns {void}
|
|
272
306
|
*
|
|
273
307
|
* **Input Properties Required:**
|
|
274
|
-
* - `req.body.rows` (array) - Array of objects to validate
|
|
308
|
+
* - `req.body.rows` (array) or `req.body` (array) - Array of objects to validate
|
|
275
309
|
* - Each property config can specify validate, required, etc.
|
|
276
310
|
*
|
|
277
311
|
* **Output Properties:**
|
|
@@ -279,13 +313,42 @@ class Entity {
|
|
|
279
313
|
*
|
|
280
314
|
* @example
|
|
281
315
|
* ```typescript
|
|
282
|
-
* router.post('/
|
|
316
|
+
* router.post('/entities', entity.validateArray, (req, res) => {
|
|
283
317
|
* // req.body.rows are now validated
|
|
284
318
|
* res.json({ success: true });
|
|
285
319
|
* });
|
|
286
320
|
* ```
|
|
287
321
|
*/
|
|
288
|
-
|
|
322
|
+
validateArray: (req: Request, _res: Response, next: NextFunction) => void;
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* Validates a single record according to property config and HTTP method.
|
|
326
|
+
*
|
|
327
|
+
* - Checks required properties and validates values
|
|
328
|
+
* - Calls next(error) on failure, next() on success
|
|
329
|
+
*
|
|
330
|
+
* @param {Request} req - Express request object containing a single record
|
|
331
|
+
* @param {Response} _res - Express response object (not used)
|
|
332
|
+
* @param {NextFunction} next - Express next function
|
|
333
|
+
*
|
|
334
|
+
* @returns {void}
|
|
335
|
+
*
|
|
336
|
+
* **Input Properties Required:**
|
|
337
|
+
* - `req.body` (object) - Single object to validate
|
|
338
|
+
* - Each property config can specify validate, required, etc.
|
|
339
|
+
*
|
|
340
|
+
* **Output Properties:**
|
|
341
|
+
* - Calls next(error) if validation fails, next() if success
|
|
342
|
+
*
|
|
343
|
+
* @example
|
|
344
|
+
* ```typescript
|
|
345
|
+
* router.post('/entity', entity.validateOne, (req, res) => {
|
|
346
|
+
* // req.body is now validated
|
|
347
|
+
* res.json({ success: true });
|
|
348
|
+
* });
|
|
349
|
+
* ```
|
|
350
|
+
*/
|
|
351
|
+
validateOne: (req: Request, _res: Response, next: NextFunction) => void;
|
|
289
352
|
|
|
290
353
|
/**
|
|
291
354
|
* Checks, sanitizes, normalizes, and validates each row in req.body.rows according to property config and HTTP method.
|
|
@@ -321,8 +384,10 @@ class Entity {
|
|
|
321
384
|
}
|
|
322
385
|
|
|
323
386
|
```
|
|
324
|
-
|
|
325
|
-
|
|
387
|
+
**normalizeArray()**, **normalizeOne()**, **validateArray()**, and **validateOne()** methods are made to be used as Express.js middlewares.
|
|
388
|
+
|
|
389
|
+
- **normalizeArray()** and **validateArray()** will look for data in the **req.body.rows** parameter or **req.body** as an array.
|
|
390
|
+
- **normalizeOne()** and **validateOne()** will look for data in the **req.body** parameter as a single object.
|
|
326
391
|
|
|
327
392
|
|
|
328
393
|
### Password validation
|
|
@@ -364,15 +429,15 @@ Any of these can be passed into the options object for each function.
|
|
|
364
429
|
| type | Type | Type of the property |
|
|
365
430
|
| min | number \| Date | Minimum value | 0 \| 1900-01-01
|
|
366
431
|
| max | number \| Date | Maximum value | 999999999 \| 2200-12-31
|
|
367
|
-
| required | boolean |
|
|
368
|
-
| safe | boolean |
|
|
369
|
-
| typeCheck | boolean | Type is checked
|
|
370
|
-
| methods | Method[] |
|
|
432
|
+
| required | boolean | Property is required during validation | false
|
|
433
|
+
| safe | boolean | Property is sent in the response | true
|
|
434
|
+
| typeCheck | boolean | Type is checked during validation | false
|
|
435
|
+
| methods | Method[] | property is validated for the listed methods only | [ "GET", "POST", "PUT", "DELETE" ]
|
|
371
436
|
| sanitize | boolean | Sanitize the property if true | true
|
|
372
437
|
| normalize | boolean | Normalize the property if true | false
|
|
373
438
|
| validate | boolean | validate the property if true | true
|
|
374
|
-
| sanitizer | ((v:any) => any) \| null |
|
|
375
|
-
| normalizer | ((v:any) => any) \| null | Normalizer function if normalize is true
|
|
439
|
+
| sanitizer | ((v:any) => any) \| null | Custom sanitizer function if sanitize is true | null
|
|
440
|
+
| normalizer | ((v:any) => any) \| null | Custop Normalizer function if normalize is true | null
|
|
376
441
|
| validator | ((v:any, min:number, max:number, typeCheck:boolean) => any) \| null | validator function if validate is true | null
|
|
377
442
|
|
|
378
443
|
* *Min and max parameters are not used for boolean type*
|
package/dist/antity.d.ts
CHANGED
|
@@ -68,12 +68,15 @@ declare class Entity {
|
|
|
68
68
|
set name(name: string);
|
|
69
69
|
getProp(key: string): Property | undefined;
|
|
70
70
|
getPropsByMethod(method: Method): Property[];
|
|
71
|
-
|
|
72
|
-
|
|
71
|
+
normalizeArray: (req: Request, _res: Response, next: NextFunction) => void;
|
|
72
|
+
normalizeOne: (req: Request, _res: Response, next: NextFunction) => void;
|
|
73
|
+
validateArray: (req: Request, _res: Response, next: NextFunction) => void;
|
|
74
|
+
validateOne: (req: Request, _res: Response, next: NextFunction) => void;
|
|
73
75
|
check: (req: Request, _res: Response, next: NextFunction) => void;
|
|
74
76
|
}
|
|
75
77
|
|
|
76
78
|
declare class Property {
|
|
79
|
+
[key: string]: unknown;
|
|
77
80
|
key: string;
|
|
78
81
|
type: Type;
|
|
79
82
|
min: number | Date | null;
|
package/dist/antity.js
CHANGED
|
@@ -233,38 +233,69 @@ function require(v, key, type) {
|
|
|
233
233
|
return isNil(v) ? { statusCode: 400, message: `${LOGS_PREFIX}Missing ${key} of type ${type}` } : null;
|
|
234
234
|
}
|
|
235
235
|
|
|
236
|
+
function applyNormalization(record, properties) {
|
|
237
|
+
for (const { key, type, sanitize: sanitize$1, normalize, sanitizer, normalizer, } of properties) {
|
|
238
|
+
let v = record[key];
|
|
239
|
+
if (v) {
|
|
240
|
+
if (sanitize$1) {
|
|
241
|
+
log.debug(`sanitize ${key}: ${type} = ${v}`);
|
|
242
|
+
v = sanitize(v, sanitizer);
|
|
243
|
+
}
|
|
244
|
+
if (normalize && isFunction(normalizer)) {
|
|
245
|
+
log.debug(`normalize ${key}: ${type} = ${v}`);
|
|
246
|
+
v = normalizer(v);
|
|
247
|
+
}
|
|
248
|
+
record[key] = v;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
function applyValidation(record, properties, method) {
|
|
254
|
+
for (const { key, type, min, max, required, typeCheck, methods, validate, validator } of properties) {
|
|
255
|
+
const v = record[key];
|
|
256
|
+
if (isIn(methods, method)) {
|
|
257
|
+
if (required) {
|
|
258
|
+
const rq = require(v, key, type);
|
|
259
|
+
if (rq)
|
|
260
|
+
return rq;
|
|
261
|
+
}
|
|
262
|
+
if (v && validate) {
|
|
263
|
+
const ct = control(v, key, type, min, max, typeCheck, validator);
|
|
264
|
+
if (ct)
|
|
265
|
+
return ct;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
return null;
|
|
270
|
+
}
|
|
271
|
+
|
|
236
272
|
class Entity {
|
|
237
273
|
constructor(name, properties) {
|
|
238
|
-
this.
|
|
274
|
+
this.normalizeArray = (req, _res, next) => {
|
|
239
275
|
var _a;
|
|
276
|
+
log.debug(`normalizeArray ${this.name}`);
|
|
240
277
|
const rows = (_a = req.body) === null || _a === void 0 ? void 0 : _a.rows;
|
|
241
|
-
|
|
242
|
-
if (!isArray(rows, "!0"))
|
|
278
|
+
if (!isArray(rows, ">", 0))
|
|
243
279
|
return next({ statusCode: 400, message: `${LOGS_PREFIX}Normalize: no rows found in request body` });
|
|
244
280
|
for (const r of rows) {
|
|
245
|
-
|
|
246
|
-
let v = r[key];
|
|
247
|
-
if (v) {
|
|
248
|
-
if (sanitize$1) {
|
|
249
|
-
log.debug(`sanitize ${key}: ${type} = ${v}`);
|
|
250
|
-
v = sanitize(v, sanitizer);
|
|
251
|
-
}
|
|
252
|
-
if (normalize && isFunction(normalizer)) {
|
|
253
|
-
log.debug(`normalize ${key}: ${type} = ${v}`);
|
|
254
|
-
v = normalizer(v);
|
|
255
|
-
}
|
|
256
|
-
r[key] = v;
|
|
257
|
-
}
|
|
258
|
-
}
|
|
281
|
+
applyNormalization(r, this._properties);
|
|
259
282
|
}
|
|
260
283
|
next();
|
|
261
284
|
};
|
|
262
|
-
this.
|
|
285
|
+
this.normalizeOne = (req, _res, next) => {
|
|
286
|
+
log.debug(`normalizeOne ${this.name}`);
|
|
287
|
+
const record = req.body;
|
|
288
|
+
if (!isObject(record, true))
|
|
289
|
+
return next({ statusCode: 400, message: `${LOGS_PREFIX}Normalize: no data found in request body` });
|
|
290
|
+
applyNormalization(record, this._properties);
|
|
291
|
+
next();
|
|
292
|
+
};
|
|
293
|
+
this.validateArray = (req, _res, next) => {
|
|
263
294
|
var _a;
|
|
295
|
+
log.debug(`validateArray ${this.name}`);
|
|
264
296
|
const rows = (_a = req.body) === null || _a === void 0 ? void 0 : _a.rows;
|
|
265
297
|
const method = req.method;
|
|
266
|
-
|
|
267
|
-
if (!isArray(rows, "!0"))
|
|
298
|
+
if (!isArray(rows, ">", 0))
|
|
268
299
|
return next({ statusCode: 400, message: `${LOGS_PREFIX}Validate: no rows found in request body` });
|
|
269
300
|
if (!isIn(METHODS, method))
|
|
270
301
|
return next({
|
|
@@ -272,24 +303,28 @@ class Entity {
|
|
|
272
303
|
message: `${LOGS_PREFIX}Invalid REST method. Received: ${method}. Must be one of: ${METHODS.toString()}`
|
|
273
304
|
});
|
|
274
305
|
for (const r of rows) {
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
if (required) {
|
|
279
|
-
const rq = require(v, key, type);
|
|
280
|
-
if (rq)
|
|
281
|
-
return next(rq);
|
|
282
|
-
}
|
|
283
|
-
if (v && validate) {
|
|
284
|
-
const ct = control(v, key, type, min, max, typeCheck, validator);
|
|
285
|
-
if (ct)
|
|
286
|
-
return next(ct);
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
}
|
|
306
|
+
const error = applyValidation(r, this._properties, method);
|
|
307
|
+
if (error)
|
|
308
|
+
return next(error);
|
|
290
309
|
}
|
|
291
310
|
next();
|
|
292
311
|
};
|
|
312
|
+
this.validateOne = (req, _res, next) => {
|
|
313
|
+
log.debug(`validateOne ${this.name}`);
|
|
314
|
+
const record = req.body;
|
|
315
|
+
const method = req.method;
|
|
316
|
+
if (!isObject(record, true))
|
|
317
|
+
return next({ statusCode: 400, message: `${LOGS_PREFIX}Validate: no data found in request body` });
|
|
318
|
+
if (!isIn(METHODS, method))
|
|
319
|
+
return next({
|
|
320
|
+
statusCode: 400,
|
|
321
|
+
message: `${LOGS_PREFIX}Invalid REST method. Received: ${method}. Must be one of: ${METHODS.toString()}`
|
|
322
|
+
});
|
|
323
|
+
const error = applyValidation(record, this._properties, method);
|
|
324
|
+
if (error)
|
|
325
|
+
return next(error);
|
|
326
|
+
next();
|
|
327
|
+
};
|
|
293
328
|
this.check = (req, _res, next) => {
|
|
294
329
|
var _a;
|
|
295
330
|
const rows = (_a = req.body) === null || _a === void 0 ? void 0 : _a.rows;
|
|
@@ -348,6 +383,7 @@ class Entity {
|
|
|
348
383
|
this._unsafeProps = [];
|
|
349
384
|
for (const p of properties) {
|
|
350
385
|
const prop = new Property(p.key, p.type, p.min, p.max, p.required, p.safe, p.typeCheck, p.methods, p.sanitize, p.normalize, p.validate, p.sanitizer, p.normalizer, p.validator);
|
|
386
|
+
Object.assign(prop, p);
|
|
351
387
|
this._properties.push(prop);
|
|
352
388
|
if (!prop.safe)
|
|
353
389
|
this._unsafeProps.push(prop.key);
|