@dwtechs/antity 0.6.0 → 0.8.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
@@ -2,6 +2,7 @@
2
2
  [![License: MIT](https://img.shields.io/npm/l/@dwtechs/antity.svg?color=brightgreen)](https://opensource.org/licenses/MIT)
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
+ ![Jest:coverage](https://img.shields.io/badge/Jest:coverage-100%25-brightgreen.svg)
5
6
  [![minified size](https://img.shields.io/bundlephobia/min/@dwtechs/antity?color=brightgreen)](https://www.npmjs.com/package/@dwtechs/antity)
6
7
 
7
8
  - [Synopsis](#synopsis)
@@ -57,15 +58,15 @@ const entity = new Entity("consumers", [
57
58
  min: 0,
58
59
  max: 120,
59
60
  typeCheck: true,
60
- operations: ["GET", "PUT", "DELETE"],
61
+ methods: ["GET", "PUT", "DELETE"],
61
62
  required: true,
62
63
  safe: true,
63
64
  sanitize: true,
64
65
  normalize: true,
65
- control: true,
66
+ validate: true,
66
67
  sanitizer: null,
67
68
  normalizer: null,
68
- controller: null,
69
+ validator: null,
69
70
  },
70
71
  {
71
72
  key: "firstName",
@@ -73,15 +74,15 @@ const entity = new Entity("consumers", [
73
74
  min: 0,
74
75
  max: 255,
75
76
  typeCheck: true,
76
- operations: ["GET", "POST", "PUT", "DELETE"],
77
+ methods: ["GET", "POST", "PUT", "DELETE"],
77
78
  required: true,
78
79
  safe: true,
79
80
  sanitize: true,
80
81
  normalize: true,
81
- control: true,
82
+ validate: true,
82
83
  sanitizer: null,
83
84
  normalizer: normalizeName,
84
- controller: null,
85
+ validator: null,
85
86
  },
86
87
  {
87
88
  key: "lastName",
@@ -89,15 +90,15 @@ const entity = new Entity("consumers", [
89
90
  min: 0,
90
91
  max: 255,
91
92
  typeCheck: true,
92
- operations: ["GET", "POST", "PUT", "DELETE"],
93
+ methods: ["GET", "POST", "PUT", "DELETE"],
93
94
  required: true,
94
95
  safe: true,
95
96
  sanitize: true,
96
97
  normalize: true,
97
- control: true,
98
+ validate: true,
98
99
  sanitizer: null,
99
100
  normalizer: normalizeName,
100
- controller: null,
101
+ validator: null,
101
102
  },
102
103
  {
103
104
  key: "nickname",
@@ -105,25 +106,23 @@ const entity = new Entity("consumers", [
105
106
  min: 0,
106
107
  max: 255,
107
108
  typeCheck: true,
108
- operations: ["GET", "POST", "PUT", "DELETE"],
109
+ methods: ["GET", "POST", "PUT", "DELETE"],
109
110
  required: true,
110
111
  safe: true,
111
112
  sanitize: true,
112
113
  normalize: true,
113
- control: true,
114
+ validate: true,
114
115
  sanitizer: null,
115
116
  normalizer: normalizeNickname,
116
- controller: null,
117
+ validator: null,
117
118
  },
118
119
  ]);
119
120
 
120
- req.body = entity.normalize(req.body); // will also sanitize if true
121
- const check = entity.validate(req.body, "GET");
122
- const unsafeProps = entity.getUnsafeProps();
121
+ // add a consumer. Used when loggin in from user service
122
+ router.post("/", entity.normalize, entity.validate, ...);
123
123
 
124
124
  ```
125
125
 
126
-
127
126
  ## API Reference
128
127
 
129
128
 
@@ -171,10 +170,10 @@ class Property {
171
170
  methods: Method[];
172
171
  sanitize: boolean;
173
172
  normalize: boolean;
174
- control: boolean;
173
+ validate: boolean;
175
174
  sanitizer: Function | null;
176
175
  normalizer: Function | null;
177
- controller: Function | null;
176
+ validator: Function | null;
178
177
  };
179
178
 
180
179
  class Entity {
@@ -195,40 +194,21 @@ class Entity {
195
194
  /**
196
195
  * Normalizes an array of records by applying sanitization and normalization
197
196
  * rules defined in the `properties` of the class.
198
- *
199
- * @param rows - An array of records where each record is a key-value pair.
200
- * The keys represent property names, and the values are the data
201
- * to be sanitized and normalized.
202
- * @returns An array of records with sanitized and normalized values.
203
197
  */
204
- normalize(rows: Record<string, unknown>[]): Record<string, unknown>[];
198
+ normalize(req: Request, _res: Response, next: NextFunction): void;
205
199
 
206
200
  /**
207
201
  * Validates a set of rows against the defined properties and operation/method.
208
202
  *
209
- * @param rows - An array of objects where each object represents a row to validate.
210
- * Each row is a record with string keys and unknown values.
211
- * @param operation - The operation or method to validate against. It can be of type `Operation` or `Method`.
212
- *
213
- * @returns A string containing the validation error message if validation fails, or `null` if validation passes.
214
- *
215
203
  * If a property is required and missing, or if it fails the control checks, the function returns an error message.
216
204
  * Otherwise, it returns `null` indicating successful validation.
217
205
  */
218
- validate(rows: Record<string, unknown>[], method: Method): string | null;
206
+ validate(req: Request, _res: Response, next: NextFunction): void;
219
207
  }
220
208
 
221
209
  ```
222
-
223
- examples :
224
-
225
- ```javascript
226
-
227
- entity.validate(req.body, "GET"); // will validate properties for GET requests
228
- entity.validate(req.body, "PUT"); // will validate properties for PUT requests
229
- entity.validate(req.body, "DELETE"); // will validate properties for DELETE requests
230
-
231
- ```
210
+ normalize() and validate() methods are made to be used as Express.js middlewares.
211
+ Each method will look for data to work on in the **req.body.rows** parmeter.
232
212
 
233
213
 
234
214
  ### Available options for a property
@@ -244,13 +224,13 @@ Any of these can be passed into the options object for each function.
244
224
  | required | boolean | Is this property required on insert | false
245
225
  | safe | boolean | Is this property safe to send to the client | true
246
226
  | typeCheck | boolean | Type is checked if true | false
247
- | operations | Operation[] | SQL DML operations concerned by the property | [ "select", "insert", "update", "merge", "delete" ]
227
+ | methods | Method[] | SQL DML operations concerned by the property | [ "select", "insert", "update", "merge", "delete" ]
248
228
  | sanitize | boolean | Sanitize the property if true | true
249
229
  | normalize | boolean | Normalize the property if true | false
250
- | control | boolean | Control the property if true | true
230
+ | validate | boolean | validate the property if true | true
251
231
  | sanitizer | ((v:any) => any) \| null | Sanitizer function if sanitize is true | null
252
232
  | normalizer | ((v:any) => any) \| null | Normalizer function if normalize is true | null
253
- | controller | ((v:any, min:number, max:number, typeCheck:boolean) => any) \| null | Controller function if control is true | null
233
+ | validator | ((v:any, min:number, max:number, typeCheck:boolean) => any) \| null | validator function if validate is true | null
254
234
 
255
235
  * *Min and max parameters are not used for boolean type*
256
236
  * *TypeCheck Parameter is not used for boolean, string and array types*
package/dist/antity.d.ts CHANGED
@@ -24,7 +24,8 @@ SOFTWARE.
24
24
  https://github.com/DWTechs/Antity.js
25
25
  */
26
26
 
27
-
27
+ import type { Request, Response, NextFunction } from 'express';
28
+ declare const Methods: readonly [ "GET", "PATCH", "PUT", "POST", "DELETE" ];
28
29
  type Method = typeof Methods[number];
29
30
  type Type =
30
31
  "boolean" |
@@ -55,21 +56,6 @@ type Type =
55
56
  "node" |
56
57
  "object";
57
58
 
58
- declare const Methods: readonly [ "GET", "PATCH", "PUT", "POST", "DELETE" ];
59
-
60
- declare const Types: Record<Type, {
61
- validate: (
62
- v: any,
63
- min: number | Date,
64
- max: number | Date,
65
- typeCheck: boolean
66
- ) => boolean;
67
- }>;
68
-
69
- declare const Required: {
70
- validate: (v: any) => boolean;
71
- };
72
-
73
59
  declare class Entity {
74
60
  private _name;
75
61
  private _unsafeProps;
@@ -80,15 +66,10 @@ declare class Entity {
80
66
  get properties(): Property[];
81
67
  set name(name: string);
82
68
  getProp(key: string): Property | undefined;
83
- normalize(rows: Record<string, unknown>[]): Record<string, unknown>[];
84
- validate(rows: Record<string, unknown>[], method: Method): string | null;
69
+ normalize(req: Request, _res: Response, next: NextFunction): void;
70
+ validate(req: Request, _res: Response, next: NextFunction): void;
85
71
  }
86
72
 
87
- declare const Messages: {
88
- missing: (key: string) => string;
89
- invalid: (key: string, type: Type) => string;
90
- };
91
-
92
73
  declare class Property {
93
74
  key: string;
94
75
  type: Type;
@@ -100,10 +81,10 @@ declare class Property {
100
81
  methods: Method[];
101
82
  sanitize: boolean;
102
83
  normalize: boolean;
103
- control: boolean;
84
+ validate: boolean;
104
85
  sanitizer: ((v: any) => any) | null;
105
86
  normalizer: ((v: any) => any) | null;
106
- controller: ((v: any) => any) | null;
87
+ validator: ((v: any) => any) | null;
107
88
  constructor(
108
89
  key: string,
109
90
  type: Type,
@@ -115,10 +96,10 @@ declare class Property {
115
96
  methods: Method[],
116
97
  sanitize: boolean,
117
98
  normalize: boolean,
118
- control: boolean,
99
+ validate: boolean,
119
100
  sanitizer: ((v: any) => any) | null,
120
101
  normalizer: ((v: any) => any) | null,
121
- controller: ((v: any) => any) | null
102
+ validator: ((v: any) => any) | null
122
103
  );
123
104
  }
124
105
 
@@ -126,9 +107,5 @@ export type { Type, Method };
126
107
  export {
127
108
  Entity,
128
109
  Property,
129
- Messages,
130
- Types,
131
- Required,
132
- Methods,
133
110
  };
134
111
 
package/dist/antity.js CHANGED
@@ -40,7 +40,7 @@ const Types = {
40
40
  validate: (v, min, max, typeCheck) => isValidNumber(v, min || undefined, max || undefined, typeCheck || undefined)
41
41
  },
42
42
  integer: {
43
- validate: (v, min, max, typeCheck) => isValidInteger(v, min || undefined, max || undefined, typeCheck || undefined)
43
+ validate: (v, min, max, typeCheck) => isValidInteger(v, min !== null && min !== void 0 ? min : undefined, max !== null && max !== void 0 ? max : undefined, typeCheck || undefined)
44
44
  },
45
45
  float: {
46
46
  validate: (v, min, max, typeCheck) => isValidFloat(v, min || undefined, max || undefined, typeCheck || undefined)
@@ -114,7 +114,7 @@ const Types = {
114
114
  };
115
115
 
116
116
  class Property {
117
- constructor(key, type, min, max, required, safe, typeCheck, methods, sanitize, normalize, control, sanitizer, normalizer, controller) {
117
+ constructor(key, type, min, max, required, safe, typeCheck, methods, sanitize, normalize, validate, sanitizer, normalizer, validator) {
118
118
  if (!isString(key, "!0"))
119
119
  throw new Error(`Property "key" must be a string. Received ${key}`);
120
120
  if (!isProperty(Types, type))
@@ -135,10 +135,10 @@ class Property {
135
135
  this.methods = methods || Methods;
136
136
  this.sanitize = isBoolean(sanitize) ? sanitize : true;
137
137
  this.normalize = isBoolean(normalize) ? normalize : false;
138
- this.control = isBoolean(control) ? control : true;
138
+ this.validate = isBoolean(validate) ? validate : true;
139
139
  this.sanitizer = isFunction(sanitizer) ? sanitizer : null;
140
140
  this.normalizer = isFunction(normalizer) ? normalizer : null;
141
- this.controller = isFunction(controller) ? controller : null;
141
+ this.validator = isFunction(validator) ? validator : null;
142
142
  }
143
143
  interval(val, type, integerDefault, dateDefault) {
144
144
  if (type === "date")
@@ -147,18 +147,13 @@ class Property {
147
147
  }
148
148
  }
149
149
 
150
- const Messages = {
151
- missing: (key) => `Missing ${key}`,
152
- invalid: (key, type) => `Invalid ${key}, must be of type ${type}`,
153
- };
154
-
155
150
  class Entity {
156
151
  constructor(name, properties) {
157
152
  this._name = name;
158
153
  this._properties = [];
159
154
  this._unsafeProps = [];
160
155
  for (const p of properties) {
161
- 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.control, p.sanitizer, p.normalizer, p.controller);
156
+ 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);
162
157
  this._properties.push(prop);
163
158
  if (!prop.safe)
164
159
  this._unsafeProps.push(prop.key);
@@ -181,7 +176,11 @@ class Entity {
181
176
  getProp(key) {
182
177
  return this.properties.find(p => p.key === key);
183
178
  }
184
- normalize(rows) {
179
+ normalize(req, _res, next) {
180
+ var _a;
181
+ const rows = (_a = req.body) === null || _a === void 0 ? void 0 : _a.rows;
182
+ if (!isArray(rows, "!0"))
183
+ return next({ status: 400, msg: "Normalize: no rows found in request body" });
185
184
  for (const r of rows) {
186
185
  for (const { key, type, sanitize, normalize, sanitizer, normalizer, } of this.properties) {
187
186
  let v = r[key];
@@ -190,7 +189,7 @@ class Entity {
190
189
  log.debug(`sanitize ${key}: ${type} = ${v}`);
191
190
  v = this.sanitize(v, sanitizer);
192
191
  }
193
- if (normalize && normalizer) {
192
+ if (normalize && isFunction(normalizer)) {
194
193
  log.debug(`normalize ${key}: ${type} = ${v}`);
195
194
  v = normalizer(v);
196
195
  }
@@ -198,40 +197,55 @@ class Entity {
198
197
  }
199
198
  }
200
199
  }
201
- return rows;
200
+ next();
202
201
  }
203
- validate(rows, method) {
202
+ validate(req, _res, next) {
203
+ var _a;
204
+ const rows = (_a = req.body) === null || _a === void 0 ? void 0 : _a.rows;
205
+ const method = req.method;
206
+ if (!isArray(rows, "!0"))
207
+ return next({ status: 400, msg: "Sanitize: no rows found in request body" });
204
208
  if (!isIn(Methods, method))
205
- return `Invalid REST method. Received: ${method}. Must be one of: ${Methods.toString()}`;
209
+ return next({
210
+ status: 400,
211
+ msg: `Invalid REST method. Received: ${method}. Must be one of: ${Methods.toString()}`
212
+ });
206
213
  for (const r of rows) {
207
- for (const { key, type, min, max, required, typeCheck, methods, control, controller } of this.properties) {
214
+ for (const { key, type, min, max, required, typeCheck, methods, validate, validator } of this.properties) {
208
215
  const v = r[key];
209
216
  if (isIn(methods, method)) {
210
217
  if (required) {
211
218
  const rq = this.require(v, key, type);
212
219
  if (rq)
213
- return rq;
220
+ return next(rq);
214
221
  }
215
- if (v && control) {
216
- const ct = this.control(v, key, type, min, max, typeCheck, controller);
222
+ if (v && validate) {
223
+ const ct = this.control(v, key, type, min, max, typeCheck, validator);
217
224
  if (ct)
218
- return ct;
225
+ return next(ct);
219
226
  }
220
227
  }
221
228
  }
222
229
  }
223
- return null;
230
+ next();
224
231
  }
225
232
  require(v, key, type) {
226
233
  log.debug(`require ${key}: ${type} = ${v}`);
227
- return isNil(v) ? Messages.missing(key) : null;
234
+ return isNil(v) ? { status: 400, msg: `Missing ${key} of type ${type}` } : null;
228
235
  }
229
236
  control(v, key, type, min, max, typeCheck, cb) {
230
237
  log.debug(`control ${key}: ${type} = ${v}`);
238
+ let val;
231
239
  if (cb)
232
- return cb(v) ? null : Messages.invalid(key, type);
233
- const val = Types[type].validate(v, min, max, typeCheck);
234
- return val ? null : Messages.invalid(key, type);
240
+ val = cb(v);
241
+ else
242
+ val = Types[type].validate(v, min, max, typeCheck);
243
+ let c = "";
244
+ if (!isNil(min))
245
+ c += ` and >= ${min}`;
246
+ if (!isNil(max))
247
+ c += ` and <= ${max}`;
248
+ return val ? null : { status: 400, msg: `Invalid ${key}, must be of type ${type}${c}` };
235
249
  }
236
250
  sanitize(v, cb) {
237
251
  if (cb)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dwtechs/antity",
3
- "version": "0.6.0",
3
+ "version": "0.8.0",
4
4
  "description": "Open source library for easy entity management",
5
5
  "keywords": [
6
6
  "entities"
@@ -30,7 +30,7 @@
30
30
  "rollup:mjs": "rollup --config rollup.config.mjs",
31
31
  "rollup:cjs": "rollup --config rollup.config.cjs.mjs",
32
32
  "rollup": "npm run rollup:mjs",
33
- "test": "jest --coverage"
33
+ "test": "jest --coverage --config jest.config.js"
34
34
  },
35
35
  "files": [
36
36
  "dist/"
@@ -48,6 +48,7 @@
48
48
  "@rollup/plugin-node-resolve": "15.3.0",
49
49
  "@types/jest": "29.5.14",
50
50
  "@types/node": "22.10.1",
51
+ "@types/express": "5.0.0",
51
52
  "babel-jest": "29.7.0",
52
53
  "core-js": "3.33.0",
53
54
  "jest": "29.7.0",