@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 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
- * Retrieves a property from the `properties` array that matches the specified key.
190
+ * Returns a single property object matching the given key.
189
191
  *
190
- * @param {string} key - The key of the property to retrieve.
191
- * @returns {Property | undefined} - The property object if found, otherwise `undefined`.
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
- * Retrieves a list of properties associated with a specific method.
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
- * @param {Method} method - The method to filter properties by.
199
- * @returns {Property[]} An array of properties that are associated with the specified method.
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 an array of records by applying sanitization and normalization
205
- * rules defined in the `properties` of the class.
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 a set of rows against the defined properties and operation/method.
268
+ * Validates each row in req.body.rows according to property config and HTTP method.
211
269
  *
212
- * If a property is required and missing, or if it fails the control checks, the function returns an error message.
213
- * Otherwise, it returns `null` indicating successful validation.
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 : { status: 400, msg: `Invalid ${key}, must be of type ${type}${c}` };
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) ? { status: 400, msg: `Missing ${key} of type ${type}` } : null;
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({ status: 400, msg: "Normalize: no rows found in request body" });
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({ status: 400, msg: "Sanitize: no rows found in request body" });
246
+ return next({ statusCode: 400, message: "Validate: no rows found in request body" });
247
247
  if (!isIn(Methods, method))
248
248
  return next({
249
- status: 400,
250
- msg: `Invalid REST method. Received: ${method}. Must be one of: ${Methods.toString()}`
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 = [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dwtechs/antity",
3
- "version": "0.10.0",
3
+ "version": "0.11.0",
4
4
  "description": "Open source library for easy entity management",
5
5
  "keywords": [
6
6
  "entities"