@dwtechs/antity 0.11.1 → 0.13.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,7 +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
+ ![Jest:coverage](https://img.shields.io/badge/Jest:coverage-72%25-brightgreen.svg)
6
6
 
7
7
  - [Synopsis](#synopsis)
8
8
  - [Support](#support)
@@ -364,15 +364,15 @@ Any of these can be passed into the options object for each function.
364
364
  | type | Type | Type of the property |
365
365
  | min | number \| Date | Minimum value | 0 \| 1900-01-01
366
366
  | max | number \| Date | Maximum value | 999999999 \| 2200-12-31
367
- | required | boolean | Is this property required on insert | false
368
- | safe | boolean | Is this property safe to send to the client | true
369
- | typeCheck | boolean | Type is checked if true | false
370
- | methods | Method[] | SQL DML operations concerned by the property | [ "select", "insert", "update", "merge", "delete" ]
367
+ | required | boolean | Property is required during validation | false
368
+ | safe | boolean | Property is sent in the response | true
369
+ | typeCheck | boolean | Type is checked during validation | false
370
+ | methods | Method[] | property is validated for the listed methods only | [ "GET", "POST", "PUT", "DELETE" ]
371
371
  | sanitize | boolean | Sanitize the property if true | true
372
372
  | normalize | boolean | Normalize the property if true | false
373
373
  | validate | boolean | validate the property if true | true
374
- | sanitizer | ((v:any) => any) \| null | Sanitizer function if sanitize is true | null
375
- | normalizer | ((v:any) => any) \| null | Normalizer function if normalize is true | null
374
+ | sanitizer | ((v:any) => any) \| null | Custom sanitizer function if sanitize is true | null
375
+ | normalizer | ((v:any) => any) \| null | Custop Normalizer function if normalize is true | null
376
376
  | validator | ((v:any, min:number, max:number, typeCheck:boolean) => any) \| null | validator function if validate is true | null
377
377
 
378
378
  * *Min and max parameters are not used for boolean type*
package/dist/antity.d.ts CHANGED
@@ -74,6 +74,7 @@ declare class Entity {
74
74
  }
75
75
 
76
76
  declare class Property {
77
+ [key: string]: unknown;
77
78
  key: string;
78
79
  type: Type;
79
80
  min: number | Date | null;
package/dist/antity.js CHANGED
@@ -27,8 +27,8 @@ https://github.com/DWTechs/Antity.js
27
27
  import { isBoolean, isStringOfLength, isValidNumber, isValidInteger, isValidFloat, isEven, isOdd, isPositive, isNegative, isPowerOfTwo, isAscii, isArrayOfLength, isValidPassword, isEmail, isRegex, isJson, isJWT, isSymbol, isIpAddress, isSlug, isHexadecimal, isValidDate, isValidTimestamp, isFunction, isHtmlElement, isHtmlEventAttribute, isNode, isObject, isString, isProperty, isArray, isIn, isDate, isNumber, isInteger, isNil } from '@dwtechs/checkard';
28
28
  import { log } from '@dwtechs/winstan';
29
29
 
30
- const Methods = ["GET", "PATCH", "PUT", "POST", "DELETE"];
31
-
30
+ const LOGS_PREFIX = "Antity: ";
31
+ const METHODS = ["GET", "PATCH", "PUT", "POST", "DELETE"];
32
32
  const { PWD_MIN_LENGTH_POLICY, PWD_MAX_LENGTH_POLICY, PWD_NUMBERS_POLICY, PWD_UPPERCASE_POLICY, PWD_LOWERCASE_POLICY, PWD_SYMBOLS_POLICY } = process.env;
33
33
  const PWD_MIN_LENGTH = PWD_MIN_LENGTH_POLICY ? +PWD_MIN_LENGTH_POLICY : 9;
34
34
  const PWD_MAX_LENGTH = PWD_MAX_LENGTH_POLICY ? +PWD_MAX_LENGTH_POLICY : 20;
@@ -36,42 +36,43 @@ const PWD_NUMBERS = PWD_NUMBERS_POLICY ? true : false;
36
36
  const PWD_UPPERCASE = PWD_UPPERCASE_POLICY ? true : false;
37
37
  const PWD_LOWERCASE = PWD_LOWERCASE_POLICY ? true : false;
38
38
  const PWD_SYMBOLS = PWD_SYMBOLS_POLICY ? true : false;
39
+
39
40
  const Types = {
40
41
  boolean: {
41
- validate: (v, _min, _max, _typeCheck) => isBoolean(v)
42
+ validate: (v, _min, _max, _typeCheck) => isBoolean(v, true)
42
43
  },
43
44
  string: {
44
- validate: (v, min, max, _typeCheck) => isStringOfLength(v, min, max)
45
+ validate: (v, min, max, _typeCheck) => isStringOfLength(v, min, max, true)
45
46
  },
46
47
  number: {
47
- validate: (v, min, max, typeCheck) => isValidNumber(v, min || undefined, max || undefined, typeCheck || undefined)
48
+ validate: (v, min, max, typeCheck) => isValidNumber(v, min || undefined, max || undefined, typeCheck || undefined, true)
48
49
  },
49
50
  integer: {
50
- validate: (v, min, max, typeCheck) => isValidInteger(v, min !== null && min !== void 0 ? min : undefined, max !== null && max !== void 0 ? max : undefined, typeCheck || undefined)
51
+ validate: (v, min, max, typeCheck) => isValidInteger(v, min !== null && min !== void 0 ? min : undefined, max !== null && max !== void 0 ? max : undefined, typeCheck || undefined, true)
51
52
  },
52
53
  float: {
53
- validate: (v, min, max, typeCheck) => isValidFloat(v, min || undefined, max || undefined, typeCheck || undefined)
54
+ validate: (v, min, max, typeCheck) => isValidFloat(v, min || undefined, max || undefined, typeCheck || undefined, true)
54
55
  },
55
56
  even: {
56
- validate: (v, _min, _max, typeCheck) => isEven(v, typeCheck || undefined)
57
+ validate: (v, _min, _max, typeCheck) => isEven(v, typeCheck || undefined, true)
57
58
  },
58
59
  odd: {
59
- validate: (v, _min, _max, typeCheck) => isOdd(v, typeCheck || undefined)
60
+ validate: (v, _min, _max, typeCheck) => isOdd(v, typeCheck || undefined, true)
60
61
  },
61
62
  positive: {
62
- validate: (v, _min, _max, typeCheck) => isPositive(v, typeCheck || undefined)
63
+ validate: (v, _min, _max, typeCheck) => isPositive(v, typeCheck || undefined, true)
63
64
  },
64
65
  negative: {
65
- validate: (v, _min, _max, typeCheck) => isNegative(v, typeCheck || undefined)
66
+ validate: (v, _min, _max, typeCheck) => isNegative(v, typeCheck || undefined, true)
66
67
  },
67
68
  powerOfTwo: {
68
- validate: (v, _min, _max, typeCheck) => isPowerOfTwo(v, typeCheck || undefined)
69
+ validate: (v, _min, _max, typeCheck) => isPowerOfTwo(v, typeCheck || undefined, true)
69
70
  },
70
71
  ascii: {
71
- validate: (v, _min, _max, typeCheck) => isAscii(v, typeCheck || undefined)
72
+ validate: (v, _min, _max, typeCheck) => isAscii(v, typeCheck || undefined, true)
72
73
  },
73
74
  array: {
74
- validate: (v, min, max, _typeCheck) => isArrayOfLength(v, min || undefined, max || undefined)
75
+ validate: (v, min, max, _typeCheck) => isArrayOfLength(v, min || undefined, max || undefined, true)
75
76
  },
76
77
  password: {
77
78
  validate: (v, min, max, _typeCheck) => {
@@ -83,66 +84,78 @@ const Types = {
83
84
  number: PWD_NUMBERS,
84
85
  specialCharacter: PWD_SYMBOLS,
85
86
  };
86
- return isValidPassword(v, o);
87
+ return isValidPassword(v, o, true);
87
88
  }
88
89
  },
89
90
  email: {
90
- validate: (v, _min, _max, _typeCheck) => isEmail(v)
91
+ validate: (v, _min, _max, _typeCheck) => isEmail(v, true)
91
92
  },
92
93
  regex: {
93
- validate: (v, _min, _max, typeCheck) => isRegex(v, typeCheck || undefined)
94
+ validate: (v, _min, _max, typeCheck) => isRegex(v, typeCheck || undefined, true)
94
95
  },
95
96
  json: {
96
- validate: (v, _min, _max, _typeCheck) => isJson(v)
97
+ validate: (v, _min, _max, _typeCheck) => isJson(v, true)
97
98
  },
98
99
  jwt: {
99
- validate: (v, _min, _max, _typeCheck) => isJWT(v)
100
+ validate: (v, _min, _max, _typeCheck) => isJWT(v, true)
100
101
  },
101
102
  symbol: {
102
- validate: (v, _min, _max, _typeCheck) => isSymbol(v)
103
+ validate: (v, _min, _max, _typeCheck) => isSymbol(v, true)
103
104
  },
104
105
  ipAddress: {
105
- validate: (v, _min, _max, _typeCheck) => isIpAddress(v)
106
+ validate: (v, _min, _max, _typeCheck) => isIpAddress(v, true)
106
107
  },
107
108
  slug: {
108
- validate: (v, _min, _max, _typeCheck) => isSlug(v)
109
+ validate: (v, _min, _max, _typeCheck) => isSlug(v, true)
109
110
  },
110
111
  hexadecimal: {
111
- validate: (v, _min, _max, _typeCheck) => isHexadecimal(v)
112
+ validate: (v, _min, _max, _typeCheck) => isHexadecimal(v, true)
112
113
  },
113
114
  date: {
114
- validate: (v, min, max, _typeCheck) => isValidDate(v, min || undefined, max || undefined)
115
+ validate: (v, min, max, _typeCheck) => isValidDate(v, min || undefined, max || undefined, true)
115
116
  },
116
117
  timestamp: {
117
- validate: (v, min, max, typeCheck) => isValidTimestamp(v, min || undefined, max || undefined, typeCheck || undefined)
118
+ validate: (v, min, max, typeCheck) => isValidTimestamp(v, min || undefined, max || undefined, typeCheck || undefined, true)
118
119
  },
119
120
  function: {
120
- validate: (v, _min, _max, _typeCheck) => isFunction(v)
121
+ validate: (v, _min, _max, _typeCheck) => isFunction(v, true)
121
122
  },
122
123
  htmlElement: {
123
- validate: (v, _min, _max, _typeCheck) => isHtmlElement(v)
124
+ validate: (v, _min, _max, _typeCheck) => isHtmlElement(v, true)
124
125
  },
125
126
  htmlEventAttribute: {
126
- validate: (v, _min, _max, _typeCheck) => isHtmlEventAttribute(v)
127
+ validate: (v, _min, _max, _typeCheck) => isHtmlEventAttribute(v, true)
127
128
  },
128
129
  node: {
129
- validate: (v, _min, _max, _typeCheck) => isNode(v)
130
+ validate: (v, _min, _max, _typeCheck) => isNode(v, true)
130
131
  },
131
132
  object: {
132
- validate: (v, _min, _max, _typeCheck) => isObject(v)
133
+ validate: (v, _min, _max, _typeCheck) => isObject(v, true)
133
134
  }
134
135
  };
135
136
 
136
137
  class Property {
137
138
  constructor(key, type, min, max, required, safe, typeCheck, methods, sanitize, normalize, validate, sanitizer, normalizer, validator) {
138
- if (!isString(key, "!0"))
139
- throw new Error(`Property "key" must be a string. Received ${key}`);
140
- if (!isProperty(Types, type))
141
- throw new Error(`Property "type" must be a valid type. Received ${type}`);
139
+ try {
140
+ isString(key, "!0", null, true);
141
+ }
142
+ catch (err) {
143
+ throw new Error(`${LOGS_PREFIX}Property "key" must be a string - caused by: ${err.message}`);
144
+ }
145
+ try {
146
+ isProperty(Types, type, true, true, true);
147
+ }
148
+ catch (err) {
149
+ throw new Error(`${LOGS_PREFIX}Property "type" must be a valid type - caused by: ${err.message}`);
150
+ }
142
151
  if (isArray(methods)) {
143
152
  for (const m of methods) {
144
- if (!isIn(Methods, m))
145
- throw new Error(`Property "methods" must be an array of REST methods. Received ${m}`);
153
+ try {
154
+ isIn(METHODS, m, 0, true);
155
+ }
156
+ catch (err) {
157
+ throw new Error(`${LOGS_PREFIX}Property "methods" must be an array of REST methods - caused by: ${err.message}`);
158
+ }
146
159
  }
147
160
  }
148
161
  this.key = key;
@@ -152,7 +165,7 @@ class Property {
152
165
  this.required = isBoolean(required) ? required : false;
153
166
  this.safe = isBoolean(safe) ? safe : true;
154
167
  this.typeCheck = isBoolean(typeCheck) ? typeCheck : false;
155
- this.methods = methods || Methods;
168
+ this.methods = methods || METHODS;
156
169
  this.sanitize = isBoolean(sanitize) ? sanitize : true;
157
170
  this.normalize = isBoolean(normalize) ? normalize : false;
158
171
  this.validate = isBoolean(validate) ? validate : true;
@@ -195,22 +208,29 @@ function trim(v) {
195
208
 
196
209
  function control(v, key, type, min, max, typeCheck, cb) {
197
210
  log.debug(`control ${key}: ${type} = ${v}`);
198
- let val;
211
+ let errorMessage = "";
199
212
  if (cb)
200
- val = cb(v);
213
+ try {
214
+ cb(v);
215
+ }
216
+ catch (err) {
217
+ errorMessage = `Custom validator callback failed for "${key}" - caused by: ${err.message}`;
218
+ }
201
219
  else
202
- val = Types[type].validate(v, min, max, typeCheck);
203
- let c = "";
204
- if (!isNil(min))
205
- c += ` and >= ${min}`;
206
- if (!isNil(max))
207
- c += ` and <= ${max}`;
208
- return val ? null : { statusCode: 400, message: `Invalid ${key}, must be of type ${type}${c}` };
220
+ try {
221
+ Types[type].validate(v, min, max, typeCheck);
222
+ }
223
+ catch (err) {
224
+ errorMessage = `Invalid "${key}" - caused by: ${err.message}`;
225
+ }
226
+ if (errorMessage)
227
+ return { statusCode: 400, message: `${LOGS_PREFIX}${errorMessage}` };
228
+ return null;
209
229
  }
210
230
 
211
231
  function require(v, key, type) {
212
232
  log.debug(`require ${key}: ${type} = ${v}`);
213
- return isNil(v) ? { statusCode: 400, message: `Missing ${key} of type ${type}` } : null;
233
+ return isNil(v) ? { statusCode: 400, message: `${LOGS_PREFIX}Missing ${key} of type ${type}` } : null;
214
234
  }
215
235
 
216
236
  class Entity {
@@ -220,7 +240,7 @@ class Entity {
220
240
  const rows = (_a = req.body) === null || _a === void 0 ? void 0 : _a.rows;
221
241
  log.debug(`normalize ${this.name}`);
222
242
  if (!isArray(rows, "!0"))
223
- return next({ statusCode: 400, message: "Normalize: no rows found in request body" });
243
+ return next({ statusCode: 400, message: `${LOGS_PREFIX}Normalize: no rows found in request body` });
224
244
  for (const r of rows) {
225
245
  for (const { key, type, sanitize: sanitize$1, normalize, sanitizer, normalizer, } of this._properties) {
226
246
  let v = r[key];
@@ -245,11 +265,11 @@ class Entity {
245
265
  const method = req.method;
246
266
  log.debug(`validate ${this.name}`);
247
267
  if (!isArray(rows, "!0"))
248
- return next({ statusCode: 400, message: "Validate: no rows found in request body" });
249
- if (!isIn(Methods, method))
268
+ return next({ statusCode: 400, message: `${LOGS_PREFIX}Validate: no rows found in request body` });
269
+ if (!isIn(METHODS, method))
250
270
  return next({
251
271
  statusCode: 400,
252
- message: `Invalid REST method. Received: ${method}. Must be one of: ${Methods.toString()}`
272
+ message: `${LOGS_PREFIX}Invalid REST method. Received: ${method}. Must be one of: ${METHODS.toString()}`
253
273
  });
254
274
  for (const r of rows) {
255
275
  for (const { key, type, min, max, required, typeCheck, methods, validate, validator } of this._properties) {
@@ -275,13 +295,24 @@ class Entity {
275
295
  const rows = (_a = req.body) === null || _a === void 0 ? void 0 : _a.rows;
276
296
  const method = req.method;
277
297
  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))
298
+ try {
299
+ isArray(rows, "!0", null, true);
300
+ }
301
+ catch (err) {
302
+ return next({
303
+ statusCode: 400,
304
+ message: `${LOGS_PREFIX}no rows found in request body - caused by: ${err.message}`
305
+ });
306
+ }
307
+ try {
308
+ isIn(METHODS, method, 0, true);
309
+ }
310
+ catch (err) {
281
311
  return next({
282
312
  statusCode: 400,
283
- message: `Invalid REST method. Received: ${method}. Must be one of: ${Methods.toString()}`
313
+ message: `${LOGS_PREFIX}Invalid REST method. Must be one of: ${METHODS.toString()} - caused by: ${err.message}`
284
314
  });
315
+ }
285
316
  for (const r of rows) {
286
317
  for (const { key, type, min, max, required, typeCheck, methods, validate, sanitize: sanitize$1, normalize, sanitizer, normalizer, validator } of this._properties) {
287
318
  let v = r[key];
@@ -317,6 +348,7 @@ class Entity {
317
348
  this._unsafeProps = [];
318
349
  for (const p of properties) {
319
350
  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);
351
+ Object.assign(prop, p);
320
352
  this._properties.push(prop);
321
353
  if (!prop.safe)
322
354
  this._unsafeProps.push(prop.key);
@@ -333,7 +365,7 @@ class Entity {
333
365
  }
334
366
  set name(name) {
335
367
  if (!isString(name, "!0"))
336
- throw new Error('name must be a string of length > 0');
368
+ throw new Error(`${LOGS_PREFIX}name must be a string of length > 0`);
337
369
  this._name = name;
338
370
  }
339
371
  getProp(key) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dwtechs/antity",
3
- "version": "0.11.1",
3
+ "version": "0.13.0",
4
4
  "description": "Open source library for easy entity management",
5
5
  "keywords": [
6
6
  "entities"
@@ -36,9 +36,9 @@
36
36
  "dist/"
37
37
  ],
38
38
  "dependencies": {
39
- "@dwtechs/checkard": "3.2.3",
39
+ "@dwtechs/checkard": "3.5.1",
40
40
  "@dwtechs/winstan": "0.4.0",
41
- "@dwtechs/sparray": "0.1.1"
41
+ "@dwtechs/sparray": "0.2.1"
42
42
  },
43
43
  "devDependencies": {
44
44
  "@babel/core": "7.26.0",