@dwtechs/antity 0.10.0 → 0.11.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 +124 -13
- package/dist/antity.d.ts +1 -0
- package/dist/antity.js +47 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -120,6 +120,8 @@ const entity = new Entity("consumers", [
|
|
|
120
120
|
|
|
121
121
|
// add a consumer. Used when loggin in from user service
|
|
122
122
|
router.post("/", entity.normalize, entity.validate, ...);
|
|
123
|
+
// or use check method to both normalize and validate at once
|
|
124
|
+
router.put("/", entity.check, ...);
|
|
123
125
|
|
|
124
126
|
```
|
|
125
127
|
|
|
@@ -163,8 +165,8 @@ type Method = "GET" | "PATCH" | "PUT" | "POST" | "DELETE";
|
|
|
163
165
|
class Property {
|
|
164
166
|
key: string;
|
|
165
167
|
type: Type;
|
|
166
|
-
min: number | Date;
|
|
167
|
-
max: number | Date;
|
|
168
|
+
min: number | Date | null;
|
|
169
|
+
max: number | Date | null;
|
|
168
170
|
required: boolean;
|
|
169
171
|
safe: boolean;
|
|
170
172
|
typeCheck: boolean;
|
|
@@ -185,34 +187,143 @@ class Entity {
|
|
|
185
187
|
set name(name: string);
|
|
186
188
|
|
|
187
189
|
/**
|
|
188
|
-
*
|
|
190
|
+
* Returns a single property object matching the given key.
|
|
189
191
|
*
|
|
190
|
-
*
|
|
191
|
-
*
|
|
192
|
+
* - Searches the entity's properties for a property with the specified key
|
|
193
|
+
* - Useful for dynamic validation, normalization, or documentation
|
|
194
|
+
*
|
|
195
|
+
* @param {string} key - The property key to look up
|
|
196
|
+
* @returns {Property | undefined} The Property object if found, otherwise undefined
|
|
197
|
+
*
|
|
198
|
+
* **Input Properties Required:**
|
|
199
|
+
* - `key` (string) - Property key to look up
|
|
200
|
+
*
|
|
201
|
+
* **Output Properties:**
|
|
202
|
+
* - Property object matching the key, or undefined if not found
|
|
203
|
+
*
|
|
204
|
+
* @example
|
|
205
|
+
* ```typescript
|
|
206
|
+
* const prop = entity.getProp('firstName');
|
|
207
|
+
* // prop contains the Property object for 'firstName' or undefined
|
|
208
|
+
* ```
|
|
192
209
|
*/
|
|
193
210
|
getProp(key: string): Property | undefined;
|
|
194
211
|
|
|
195
212
|
/**
|
|
196
|
-
*
|
|
213
|
+
* Returns all properties configured for a given REST method.
|
|
214
|
+
*
|
|
215
|
+
* - Filters the entity's properties by the specified method (e.g., 'POST', 'GET')
|
|
216
|
+
* - Useful for dynamic validation, normalization, or documentation
|
|
217
|
+
*
|
|
218
|
+
* @param {Method} method - The REST method to filter properties by (e.g., 'POST', 'GET')
|
|
219
|
+
* @returns {Property[]} Array of Property objects associated with the method
|
|
220
|
+
*
|
|
221
|
+
* **Input Properties Required:**
|
|
222
|
+
* - `method` (string) - REST method to filter by
|
|
197
223
|
*
|
|
198
|
-
*
|
|
199
|
-
*
|
|
224
|
+
* **Output Properties:**
|
|
225
|
+
* - Array of Property objects matching the method
|
|
226
|
+
*
|
|
227
|
+
* @example
|
|
228
|
+
* ```typescript
|
|
229
|
+
* const postProps = entity.getPropsByMethod('POST');
|
|
230
|
+
* // postProps contains all properties relevant for POST requests
|
|
231
|
+
* ```
|
|
200
232
|
*/
|
|
201
233
|
getPropsByMethod(method: Method): Property[];
|
|
202
234
|
|
|
203
235
|
/**
|
|
204
|
-
* Normalizes
|
|
205
|
-
*
|
|
236
|
+
* Normalizes each row in req.body.rows according to property config and HTTP method.
|
|
237
|
+
*
|
|
238
|
+
* - Applies sanitization if `sanitize: true` and method matches
|
|
239
|
+
* - Applies normalization if `normalize: true` and method matches
|
|
240
|
+
* - Mutates req.body.rows with sanitized/normalized values
|
|
241
|
+
* - Calls next(error) on failure, next() on success
|
|
242
|
+
*
|
|
243
|
+
* @param {Request} req - Express request object containing rows
|
|
244
|
+
* @param {Response} _res - Express response object (not used)
|
|
245
|
+
* @param {NextFunction} next - Express next function
|
|
246
|
+
*
|
|
247
|
+
* @returns {void}
|
|
248
|
+
*
|
|
249
|
+
* **Input Properties Required:**
|
|
250
|
+
* - `req.body.rows` (array) - Array of objects to normalize
|
|
251
|
+
* - Each property config can specify sanitize, normalize, etc.
|
|
252
|
+
*
|
|
253
|
+
* **Output Properties:**
|
|
254
|
+
* - Mutates `req.body.rows` with sanitized/normalized values
|
|
255
|
+
* - Calls next(error) if any row fails normalization, next() if all pass
|
|
256
|
+
*
|
|
257
|
+
* @example
|
|
258
|
+
* ```typescript
|
|
259
|
+
* router.post('/entity', entity.normalize, (req, res) => {
|
|
260
|
+
* // req.body.rows are now sanitized and normalized
|
|
261
|
+
* res.json({ success: true });
|
|
262
|
+
* });
|
|
263
|
+
* ```
|
|
206
264
|
*/
|
|
207
265
|
normalize: (req: Request, _res: Response, next: NextFunction) => void;
|
|
208
266
|
|
|
209
267
|
/**
|
|
210
|
-
* Validates
|
|
268
|
+
* Validates each row in req.body.rows according to property config and HTTP method.
|
|
211
269
|
*
|
|
212
|
-
*
|
|
213
|
-
*
|
|
270
|
+
* - Checks required properties and validates values
|
|
271
|
+
* - Calls next(error) on failure, next() on success
|
|
272
|
+
*
|
|
273
|
+
* @param {Request} req - Express request object containing rows
|
|
274
|
+
* @param {Response} _res - Express response object (not used)
|
|
275
|
+
* @param {NextFunction} next - Express next function
|
|
276
|
+
*
|
|
277
|
+
* @returns {void}
|
|
278
|
+
*
|
|
279
|
+
* **Input Properties Required:**
|
|
280
|
+
* - `req.body.rows` (array) - Array of objects to validate
|
|
281
|
+
* - Each property config can specify validate, required, etc.
|
|
282
|
+
*
|
|
283
|
+
* **Output Properties:**
|
|
284
|
+
* - Calls next(error) if any row fails validation, next() if all pass
|
|
285
|
+
*
|
|
286
|
+
* @example
|
|
287
|
+
* ```typescript
|
|
288
|
+
* router.post('/entity', entity.validate, (req, res) => {
|
|
289
|
+
* // req.body.rows are now validated
|
|
290
|
+
* res.json({ success: true });
|
|
291
|
+
* });
|
|
292
|
+
* ```
|
|
214
293
|
*/
|
|
215
294
|
validate: (req: Request, _res: Response, next: NextFunction) => void;
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Checks, sanitizes, normalizes, and validates each row in req.body.rows according to property config and HTTP method.
|
|
298
|
+
*
|
|
299
|
+
* - Applies sanitization if `sanitize: true` and method matches
|
|
300
|
+
* - Applies normalization if `normalize: true` and method matches
|
|
301
|
+
* - Checks required properties and validates values
|
|
302
|
+
* - Calls next(error) on failure, next() on success
|
|
303
|
+
*
|
|
304
|
+
* @param {Request} req - Express request object containing rows
|
|
305
|
+
* @param {Response} _res - Express response object (not used)
|
|
306
|
+
* @param {NextFunction} next - Express next function
|
|
307
|
+
*
|
|
308
|
+
* @returns {void}
|
|
309
|
+
*
|
|
310
|
+
* **Input Properties Required:**
|
|
311
|
+
* - `req.body.rows` (array) - Array of objects to check
|
|
312
|
+
* - Each property config can specify sanitize, normalize, validate, required, etc.
|
|
313
|
+
*
|
|
314
|
+
* **Output Properties:**
|
|
315
|
+
* - Mutates `req.body.rows` with sanitized/normalized values
|
|
316
|
+
* - Calls next(error) if any row fails checks, next() if all pass
|
|
317
|
+
*
|
|
318
|
+
* @example
|
|
319
|
+
* ```typescript
|
|
320
|
+
* router.post('/entity', entity.check, (req, res) => {
|
|
321
|
+
* // req.body.rows are now sanitized, normalized, and validated
|
|
322
|
+
* res.json({ success: true });
|
|
323
|
+
* });
|
|
324
|
+
* ```
|
|
325
|
+
*/
|
|
326
|
+
check: (req: Request, _res: Response, next: NextFunction) => void;
|
|
216
327
|
}
|
|
217
328
|
|
|
218
329
|
```
|
package/dist/antity.d.ts
CHANGED
|
@@ -70,6 +70,7 @@ declare class Entity {
|
|
|
70
70
|
getPropsByMethod(method: Method): Property[];
|
|
71
71
|
normalize: (req: Request, _res: Response, next: NextFunction) => void;
|
|
72
72
|
validate: (req: Request, _res: Response, next: NextFunction) => void;
|
|
73
|
+
check: (req: Request, _res: Response, next: NextFunction) => void;
|
|
73
74
|
}
|
|
74
75
|
|
|
75
76
|
declare class Property {
|
package/dist/antity.js
CHANGED
|
@@ -205,12 +205,12 @@ function control(v, key, type, min, max, typeCheck, cb) {
|
|
|
205
205
|
c += ` and >= ${min}`;
|
|
206
206
|
if (!isNil(max))
|
|
207
207
|
c += ` and <= ${max}`;
|
|
208
|
-
return val ? null : {
|
|
208
|
+
return val ? null : { statusCode: 400, message: `Invalid ${key}, must be of type ${type}${c}` };
|
|
209
209
|
}
|
|
210
210
|
|
|
211
211
|
function require(v, key, type) {
|
|
212
212
|
log.debug(`require ${key}: ${type} = ${v}`);
|
|
213
|
-
return isNil(v) ? {
|
|
213
|
+
return isNil(v) ? { statusCode: 400, message: `Missing ${key} of type ${type}` } : null;
|
|
214
214
|
}
|
|
215
215
|
|
|
216
216
|
class Entity {
|
|
@@ -219,7 +219,7 @@ class Entity {
|
|
|
219
219
|
var _a;
|
|
220
220
|
const rows = (_a = req.body) === null || _a === void 0 ? void 0 : _a.rows;
|
|
221
221
|
if (!isArray(rows, "!0"))
|
|
222
|
-
return next({
|
|
222
|
+
return next({ statusCode: 400, message: "Normalize: no rows found in request body" });
|
|
223
223
|
for (const r of rows) {
|
|
224
224
|
for (const { key, type, sanitize: sanitize$1, normalize, sanitizer, normalizer, } of this._properties) {
|
|
225
225
|
let v = r[key];
|
|
@@ -243,11 +243,11 @@ class Entity {
|
|
|
243
243
|
const rows = (_a = req.body) === null || _a === void 0 ? void 0 : _a.rows;
|
|
244
244
|
const method = req.method;
|
|
245
245
|
if (!isArray(rows, "!0"))
|
|
246
|
-
return next({
|
|
246
|
+
return next({ statusCode: 400, message: "Validate: no rows found in request body" });
|
|
247
247
|
if (!isIn(Methods, method))
|
|
248
248
|
return next({
|
|
249
|
-
|
|
250
|
-
|
|
249
|
+
statusCode: 400,
|
|
250
|
+
message: `Invalid REST method. Received: ${method}. Must be one of: ${Methods.toString()}`
|
|
251
251
|
});
|
|
252
252
|
for (const r of rows) {
|
|
253
253
|
for (const { key, type, min, max, required, typeCheck, methods, validate, validator } of this._properties) {
|
|
@@ -268,6 +268,47 @@ class Entity {
|
|
|
268
268
|
}
|
|
269
269
|
next();
|
|
270
270
|
};
|
|
271
|
+
this.check = (req, _res, next) => {
|
|
272
|
+
var _a;
|
|
273
|
+
const rows = (_a = req.body) === null || _a === void 0 ? void 0 : _a.rows;
|
|
274
|
+
const method = req.method;
|
|
275
|
+
if (!isArray(rows, "!0"))
|
|
276
|
+
return next({ statusCode: 400, message: "Check: no rows found in request body" });
|
|
277
|
+
if (!isIn(Methods, method))
|
|
278
|
+
return next({
|
|
279
|
+
statusCode: 400,
|
|
280
|
+
message: `Invalid REST method. Received: ${method}. Must be one of: ${Methods.toString()}`
|
|
281
|
+
});
|
|
282
|
+
for (const r of rows) {
|
|
283
|
+
for (const { key, type, min, max, required, typeCheck, methods, validate, sanitize: sanitize$1, normalize, sanitizer, normalizer, validator } of this._properties) {
|
|
284
|
+
let v = r[key];
|
|
285
|
+
if (isIn(methods, method)) {
|
|
286
|
+
if (v) {
|
|
287
|
+
if (sanitize$1) {
|
|
288
|
+
log.debug(`sanitize ${key}: ${type} = ${v}`);
|
|
289
|
+
v = sanitize(v, sanitizer);
|
|
290
|
+
}
|
|
291
|
+
if (normalize && isFunction(normalizer)) {
|
|
292
|
+
log.debug(`normalize ${key}: ${type} = ${v}`);
|
|
293
|
+
v = normalizer(v);
|
|
294
|
+
}
|
|
295
|
+
r[key] = v;
|
|
296
|
+
if (validate) {
|
|
297
|
+
const ct = control(v, key, type, min, max, typeCheck, validator);
|
|
298
|
+
if (ct)
|
|
299
|
+
return next(ct);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
if (required) {
|
|
303
|
+
const rq = require(v, key, type);
|
|
304
|
+
if (rq)
|
|
305
|
+
return next(rq);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
next();
|
|
311
|
+
};
|
|
271
312
|
this._name = name;
|
|
272
313
|
this._properties = [];
|
|
273
314
|
this._unsafeProps = [];
|