@dwtechs/antity 0.10.0 โ†’ 0.11.1

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
@@ -3,13 +3,11 @@
3
3
  [![npm version](https://badge.fury.io/js/%40dwtechs%2Fantity.svg)](https://www.npmjs.com/package/@dwtechs/antity)
4
4
  [![last version release date](https://img.shields.io/github/release-date/DWTechs/Antity.js)](https://www.npmjs.com/package/@dwtechs/antity)
5
5
  ![Jest:coverage](https://img.shields.io/badge/Jest:coverage-100%25-brightgreen.svg)
6
- [![minified size](https://img.shields.io/bundlephobia/min/@dwtechs/antity?color=brightgreen)](https://www.npmjs.com/package/@dwtechs/antity)
7
6
 
8
7
  - [Synopsis](#synopsis)
9
8
  - [Support](#support)
10
9
  - [Installation](#installation)
11
10
  - [Usage](#usage)
12
- - [ES6](#es6)
13
11
  - [API Reference](#api-reference)
14
12
  - [Contributors](#contributors)
15
13
  - [Stack](#stack)
@@ -19,12 +17,10 @@
19
17
 
20
18
  **[Antity.js](https://github.com/DWTechs/Antity.js)** is an Open source library for easy entity management.
21
19
 
22
- - Only 1 small dependency to check inputs variables
23
- - Very lightweight
24
- - Thoroughly tested
25
- - Works in Javascript, Typescript
26
- - Can be used as EcmaScrypt module
27
- - Written in Typescript
20
+ - ๐Ÿชถ Very lightweight
21
+ - ๐Ÿงช Thoroughly tested
22
+ - ๐Ÿšš Shipped as EcmaScrypt module
23
+ - ๐Ÿ“ Written in Typescript
28
24
 
29
25
 
30
26
  ## Support
@@ -44,8 +40,6 @@ $ npm i @dwtechs/antity
44
40
  ## Usage
45
41
 
46
42
 
47
- ### ES6 / TypeScript
48
-
49
43
  ```javascript
50
44
 
51
45
  import { Entity } from "@dwtechs/antity";
@@ -120,6 +114,8 @@ const entity = new Entity("consumers", [
120
114
 
121
115
  // add a consumer. Used when loggin in from user service
122
116
  router.post("/", entity.normalize, entity.validate, ...);
117
+ // or use check method to both normalize and validate at once
118
+ router.put("/", entity.check, ...);
123
119
 
124
120
  ```
125
121
 
@@ -163,8 +159,8 @@ type Method = "GET" | "PATCH" | "PUT" | "POST" | "DELETE";
163
159
  class Property {
164
160
  key: string;
165
161
  type: Type;
166
- min: number | Date;
167
- max: number | Date;
162
+ min: number | Date | null;
163
+ max: number | Date | null;
168
164
  required: boolean;
169
165
  safe: boolean;
170
166
  typeCheck: boolean;
@@ -185,34 +181,143 @@ class Entity {
185
181
  set name(name: string);
186
182
 
187
183
  /**
188
- * Retrieves a property from the `properties` array that matches the specified key.
184
+ * Returns a single property object matching the given key.
185
+ *
186
+ * - Searches the entity's properties for a property with the specified key
187
+ * - Useful for dynamic validation, normalization, or documentation
188
+ *
189
+ * @param {string} key - The property key to look up
190
+ * @returns {Property | undefined} The Property object if found, otherwise undefined
191
+ *
192
+ * **Input Properties Required:**
193
+ * - `key` (string) - Property key to look up
189
194
  *
190
- * @param {string} key - The key of the property to retrieve.
191
- * @returns {Property | undefined} - The property object if found, otherwise `undefined`.
195
+ * **Output Properties:**
196
+ * - Property object matching the key, or undefined if not found
197
+ *
198
+ * @example
199
+ * ```typescript
200
+ * const prop = entity.getProp('firstName');
201
+ * // prop contains the Property object for 'firstName' or undefined
202
+ * ```
192
203
  */
193
204
  getProp(key: string): Property | undefined;
194
205
 
195
206
  /**
196
- * Retrieves a list of properties associated with a specific method.
207
+ * Returns all properties configured for a given REST method.
208
+ *
209
+ * - Filters the entity's properties by the specified method (e.g., 'POST', 'GET')
210
+ * - Useful for dynamic validation, normalization, or documentation
211
+ *
212
+ * @param {Method} method - The REST method to filter properties by (e.g., 'POST', 'GET')
213
+ * @returns {Property[]} Array of Property objects associated with the method
214
+ *
215
+ * **Input Properties Required:**
216
+ * - `method` (string) - REST method to filter by
197
217
  *
198
- * @param {Method} method - The method to filter properties by.
199
- * @returns {Property[]} An array of properties that are associated with the specified method.
218
+ * **Output Properties:**
219
+ * - Array of Property objects matching the method
220
+ *
221
+ * @example
222
+ * ```typescript
223
+ * const postProps = entity.getPropsByMethod('POST');
224
+ * // postProps contains all properties relevant for POST requests
225
+ * ```
200
226
  */
201
227
  getPropsByMethod(method: Method): Property[];
202
228
 
203
229
  /**
204
- * Normalizes an array of records by applying sanitization and normalization
205
- * rules defined in the `properties` of the class.
230
+ * Normalizes each row in req.body.rows according to property config and HTTP method.
231
+ *
232
+ * - Applies sanitization if `sanitize: true` and method matches
233
+ * - Applies normalization if `normalize: true` and method matches
234
+ * - Mutates req.body.rows with sanitized/normalized values
235
+ * - Calls next(error) on failure, next() on success
236
+ *
237
+ * @param {Request} req - Express request object containing rows
238
+ * @param {Response} _res - Express response object (not used)
239
+ * @param {NextFunction} next - Express next function
240
+ *
241
+ * @returns {void}
242
+ *
243
+ * **Input Properties Required:**
244
+ * - `req.body.rows` (array) - Array of objects to normalize
245
+ * - Each property config can specify sanitize, normalize, etc.
246
+ *
247
+ * **Output Properties:**
248
+ * - Mutates `req.body.rows` with sanitized/normalized values
249
+ * - Calls next(error) if any row fails normalization, next() if all pass
250
+ *
251
+ * @example
252
+ * ```typescript
253
+ * router.post('/entity', entity.normalize, (req, res) => {
254
+ * // req.body.rows are now sanitized and normalized
255
+ * res.json({ success: true });
256
+ * });
257
+ * ```
206
258
  */
207
259
  normalize: (req: Request, _res: Response, next: NextFunction) => void;
208
260
 
209
261
  /**
210
- * Validates a set of rows against the defined properties and operation/method.
262
+ * Validates each row in req.body.rows according to property config and HTTP method.
211
263
  *
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.
264
+ * - Checks required properties and validates values
265
+ * - Calls next(error) on failure, next() on success
266
+ *
267
+ * @param {Request} req - Express request object containing rows
268
+ * @param {Response} _res - Express response object (not used)
269
+ * @param {NextFunction} next - Express next function
270
+ *
271
+ * @returns {void}
272
+ *
273
+ * **Input Properties Required:**
274
+ * - `req.body.rows` (array) - Array of objects to validate
275
+ * - Each property config can specify validate, required, etc.
276
+ *
277
+ * **Output Properties:**
278
+ * - Calls next(error) if any row fails validation, next() if all pass
279
+ *
280
+ * @example
281
+ * ```typescript
282
+ * router.post('/entity', entity.validate, (req, res) => {
283
+ * // req.body.rows are now validated
284
+ * res.json({ success: true });
285
+ * });
286
+ * ```
214
287
  */
215
288
  validate: (req: Request, _res: Response, next: NextFunction) => void;
289
+
290
+ /**
291
+ * Checks, sanitizes, normalizes, and validates each row in req.body.rows according to property config and HTTP method.
292
+ *
293
+ * - Applies sanitization if `sanitize: true` and method matches
294
+ * - Applies normalization if `normalize: true` and method matches
295
+ * - Checks required properties and validates values
296
+ * - Calls next(error) on failure, next() on success
297
+ *
298
+ * @param {Request} req - Express request object containing rows
299
+ * @param {Response} _res - Express response object (not used)
300
+ * @param {NextFunction} next - Express next function
301
+ *
302
+ * @returns {void}
303
+ *
304
+ * **Input Properties Required:**
305
+ * - `req.body.rows` (array) - Array of objects to check
306
+ * - Each property config can specify sanitize, normalize, validate, required, etc.
307
+ *
308
+ * **Output Properties:**
309
+ * - Mutates `req.body.rows` with sanitized/normalized values
310
+ * - Calls next(error) if any row fails checks, next() if all pass
311
+ *
312
+ * @example
313
+ * ```typescript
314
+ * router.post('/entity', entity.check, (req, res) => {
315
+ * // req.body.rows are now sanitized, normalized, and validated
316
+ * res.json({ success: true });
317
+ * });
318
+ * ```
319
+ */
320
+ check: (req: Request, _res: Response, next: NextFunction) => void;
216
321
  }
217
322
 
218
323
  ```
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 {
@@ -218,8 +218,9 @@ class Entity {
218
218
  this.normalize = (req, _res, next) => {
219
219
  var _a;
220
220
  const rows = (_a = req.body) === null || _a === void 0 ? void 0 : _a.rows;
221
+ log.debug(`normalize ${this.name}`);
221
222
  if (!isArray(rows, "!0"))
222
- return next({ status: 400, msg: "Normalize: no rows found in request body" });
223
+ return next({ statusCode: 400, message: "Normalize: no rows found in request body" });
223
224
  for (const r of rows) {
224
225
  for (const { key, type, sanitize: sanitize$1, normalize, sanitizer, normalizer, } of this._properties) {
225
226
  let v = r[key];
@@ -242,12 +243,13 @@ class Entity {
242
243
  var _a;
243
244
  const rows = (_a = req.body) === null || _a === void 0 ? void 0 : _a.rows;
244
245
  const method = req.method;
246
+ log.debug(`validate ${this.name}`);
245
247
  if (!isArray(rows, "!0"))
246
- return next({ status: 400, msg: "Sanitize: no rows found in request body" });
248
+ return next({ statusCode: 400, message: "Validate: no rows found in request body" });
247
249
  if (!isIn(Methods, method))
248
250
  return next({
249
- status: 400,
250
- msg: `Invalid REST method. Received: ${method}. Must be one of: ${Methods.toString()}`
251
+ statusCode: 400,
252
+ message: `Invalid REST method. Received: ${method}. Must be one of: ${Methods.toString()}`
251
253
  });
252
254
  for (const r of rows) {
253
255
  for (const { key, type, min, max, required, typeCheck, methods, validate, validator } of this._properties) {
@@ -268,6 +270,48 @@ class Entity {
268
270
  }
269
271
  next();
270
272
  };
273
+ this.check = (req, _res, next) => {
274
+ var _a;
275
+ const rows = (_a = req.body) === null || _a === void 0 ? void 0 : _a.rows;
276
+ const method = req.method;
277
+ log.debug(`check ${this.name}`);
278
+ if (!isArray(rows, "!0"))
279
+ return next({ statusCode: 400, message: "Check: no rows found in request body" });
280
+ if (!isIn(Methods, method))
281
+ return next({
282
+ statusCode: 400,
283
+ message: `Invalid REST method. Received: ${method}. Must be one of: ${Methods.toString()}`
284
+ });
285
+ for (const r of rows) {
286
+ for (const { key, type, min, max, required, typeCheck, methods, validate, sanitize: sanitize$1, normalize, sanitizer, normalizer, validator } of this._properties) {
287
+ let v = r[key];
288
+ if (isIn(methods, method)) {
289
+ if (v) {
290
+ if (sanitize$1) {
291
+ log.debug(`sanitize ${key}: ${type} = ${v}`);
292
+ v = sanitize(v, sanitizer);
293
+ }
294
+ if (normalize && isFunction(normalizer)) {
295
+ log.debug(`normalize ${key}: ${type} = ${v}`);
296
+ v = normalizer(v);
297
+ }
298
+ r[key] = v;
299
+ if (validate) {
300
+ const ct = control(v, key, type, min, max, typeCheck, validator);
301
+ if (ct)
302
+ return next(ct);
303
+ }
304
+ }
305
+ if (required) {
306
+ const rq = require(v, key, type);
307
+ if (rq)
308
+ return next(rq);
309
+ }
310
+ }
311
+ }
312
+ }
313
+ next();
314
+ };
271
315
  this._name = name;
272
316
  this._properties = [];
273
317
  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.1",
4
4
  "description": "Open source library for easy entity management",
5
5
  "keywords": [
6
6
  "entities"
@@ -38,8 +38,7 @@
38
38
  "dependencies": {
39
39
  "@dwtechs/checkard": "3.2.3",
40
40
  "@dwtechs/winstan": "0.4.0",
41
- "@dwtechs/sparray": "0.1.1",
42
- "pg": "8.13.1"
41
+ "@dwtechs/sparray": "0.1.1"
43
42
  },
44
43
  "devDependencies": {
45
44
  "@babel/core": "7.26.0",