@dwtechs/antity 0.16.0 → 0.18.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 +4 -1
- package/dist/antity.d.ts +4 -1
- package/dist/antity.js +111 -79
- package/package.json +14 -17
package/README.md
CHANGED
package/dist/antity.d.ts
CHANGED
package/dist/antity.js
CHANGED
|
@@ -24,8 +24,9 @@ SOFTWARE.
|
|
|
24
24
|
https://github.com/DWTechs/Antity.js
|
|
25
25
|
*/
|
|
26
26
|
|
|
27
|
-
import { isBoolean, isStringOfLength, isValidNumber, isValidInteger, isValidFloat, isEven, isOdd, isPositive, isNegative, isPowerOfTwo, isAscii, isArrayOfLength,
|
|
27
|
+
import { isBoolean, isStringOfLength, isValidNumber, isValidInteger, isValidFloat, isEven, isOdd, isPositive, isNegative, isPowerOfTwo, isAscii, isArrayOfLength, isEmail, isRegex, isJson, isJWT, isSymbol, isIpAddress, isSlug, isHexadecimal, isValidDate, isValidTimestamp, isFunction, isHtmlElement, isHtmlEventAttribute, isNode, isObject, isAnsiEscapeCode, isLocale, isTimeZone, isString, isProperty, isArray, isIn, isDate, isNumber, isInteger, isNil } from '@dwtechs/checkard';
|
|
28
28
|
import { log } from '@dwtechs/winstan';
|
|
29
|
+
import { isValidPassword } from '@dwtechs/passken';
|
|
29
30
|
|
|
30
31
|
const LOGS_PREFIX = "Antity: ";
|
|
31
32
|
const METHODS = ["PATCH", "PUT", "POST"];
|
|
@@ -48,7 +49,7 @@ const Types = {
|
|
|
48
49
|
validate: (v, min, max, typeCheck) => isValidNumber(v, min || undefined, max || undefined, typeCheck || undefined, true)
|
|
49
50
|
},
|
|
50
51
|
integer: {
|
|
51
|
-
validate: (v, min, max, typeCheck) => isValidInteger(v, min
|
|
52
|
+
validate: (v, min, max, typeCheck) => isValidInteger(v, min ?? undefined, max ?? undefined, typeCheck || undefined, true)
|
|
52
53
|
},
|
|
53
54
|
float: {
|
|
54
55
|
validate: (v, min, max, typeCheck) => isValidFloat(v, min || undefined, max || undefined, typeCheck || undefined, true)
|
|
@@ -77,12 +78,12 @@ const Types = {
|
|
|
77
78
|
password: {
|
|
78
79
|
validate: (v, min, max, _typeCheck) => {
|
|
79
80
|
const o = {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
81
|
+
minLen: min || PWD_MIN_LENGTH,
|
|
82
|
+
maxLen: max || PWD_MAX_LENGTH,
|
|
83
|
+
lcase: PWD_LOWERCASE,
|
|
84
|
+
ucase: PWD_UPPERCASE,
|
|
85
|
+
num: PWD_NUMBERS,
|
|
86
|
+
sym: PWD_SYMBOLS,
|
|
86
87
|
};
|
|
87
88
|
return isValidPassword(v, o, true);
|
|
88
89
|
}
|
|
@@ -131,10 +132,29 @@ const Types = {
|
|
|
131
132
|
},
|
|
132
133
|
object: {
|
|
133
134
|
validate: (v, _min, _max, _typeCheck) => isObject(v, true)
|
|
135
|
+
},
|
|
136
|
+
ansiEscapeCode: {
|
|
137
|
+
validate: (v, _min, _max, _typeCheck) => isAnsiEscapeCode(v, true)
|
|
138
|
+
},
|
|
139
|
+
locale: {
|
|
140
|
+
validate: (v, _min, _max, typeCheck) => isLocale(v, typeCheck || undefined, true)
|
|
141
|
+
},
|
|
142
|
+
timeZone: {
|
|
143
|
+
validate: (v, _min, _max, _typeCheck) => isTimeZone(v, true)
|
|
134
144
|
}
|
|
135
145
|
};
|
|
136
146
|
|
|
137
147
|
class Property {
|
|
148
|
+
key;
|
|
149
|
+
type;
|
|
150
|
+
min;
|
|
151
|
+
max;
|
|
152
|
+
isPrivate;
|
|
153
|
+
requiredFor;
|
|
154
|
+
isTypeChecked;
|
|
155
|
+
sanitizer;
|
|
156
|
+
normalizer;
|
|
157
|
+
validator;
|
|
138
158
|
constructor(key, type, min, max, isPrivate, requiredFor, isTypeChecked, sanitizer, normalizer, validator) {
|
|
139
159
|
try {
|
|
140
160
|
isString(key, "!0", null, true);
|
|
@@ -180,8 +200,8 @@ function sanitize(v, cb) {
|
|
|
180
200
|
if (cb)
|
|
181
201
|
return cb(v);
|
|
182
202
|
if (isArray(v, null, null)) {
|
|
183
|
-
for (let
|
|
184
|
-
|
|
203
|
+
for (let i = 0; i < v.length; i++) {
|
|
204
|
+
v[i] = trim(v[i]);
|
|
185
205
|
}
|
|
186
206
|
return v;
|
|
187
207
|
}
|
|
@@ -191,12 +211,11 @@ function trim(v) {
|
|
|
191
211
|
if (isString(v, "!0"))
|
|
192
212
|
return v.trim();
|
|
193
213
|
if (isObject(v, true)) {
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
}
|
|
214
|
+
const obj = v;
|
|
215
|
+
for (const k of Object.keys(obj)) {
|
|
216
|
+
const o = obj[k];
|
|
217
|
+
if (isString(o, "!0", null))
|
|
218
|
+
obj[k] = o.trim();
|
|
200
219
|
}
|
|
201
220
|
}
|
|
202
221
|
return v;
|
|
@@ -208,7 +227,7 @@ function normalize(record, properties) {
|
|
|
208
227
|
if (v) {
|
|
209
228
|
log.debug(`sanitize ${key}: ${type} = ${v}`);
|
|
210
229
|
v = sanitize(v, sanitizer);
|
|
211
|
-
if (
|
|
230
|
+
if (normalizer) {
|
|
212
231
|
log.debug(`normalize ${key}: ${type} = ${v}`);
|
|
213
232
|
v = normalizer(v);
|
|
214
233
|
}
|
|
@@ -247,7 +266,7 @@ function require(v, key, type) {
|
|
|
247
266
|
function validate(record, properties, method) {
|
|
248
267
|
for (const { key, type, min, max, requiredFor, isTypeChecked, validator } of properties) {
|
|
249
268
|
const v = record[key];
|
|
250
|
-
if (
|
|
269
|
+
if (requiredFor.includes(method)) {
|
|
251
270
|
const rq = require(v, key, type);
|
|
252
271
|
if (rq)
|
|
253
272
|
return rq;
|
|
@@ -261,71 +280,27 @@ function validate(record, properties, method) {
|
|
|
261
280
|
return null;
|
|
262
281
|
}
|
|
263
282
|
|
|
283
|
+
const STANDARD_PROP_KEYS = new Set(['key', 'type', 'min', 'max', 'isPrivate', 'requiredFor', 'isTypeChecked', 'sanitizer', 'normalizer', 'validator']);
|
|
264
284
|
class Entity {
|
|
285
|
+
_name;
|
|
286
|
+
_privateProps;
|
|
287
|
+
_properties;
|
|
288
|
+
_propsByMethod;
|
|
265
289
|
constructor(name, properties) {
|
|
266
|
-
this.normalizeArray = (req, _res, next) => {
|
|
267
|
-
var _a;
|
|
268
|
-
log.debug(`normalizeArray ${this.name}`);
|
|
269
|
-
const rows = (_a = req.body) === null || _a === void 0 ? void 0 : _a.rows;
|
|
270
|
-
if (!isArray(rows, ">", 0))
|
|
271
|
-
return next({ statusCode: 400, message: `${LOGS_PREFIX}Normalize: no rows found in request body` });
|
|
272
|
-
for (const r of rows) {
|
|
273
|
-
normalize(r, this._properties);
|
|
274
|
-
}
|
|
275
|
-
next();
|
|
276
|
-
};
|
|
277
|
-
this.normalizeOne = (req, _res, next) => {
|
|
278
|
-
log.debug(`normalizeOne ${this.name}`);
|
|
279
|
-
const r = req.body;
|
|
280
|
-
if (!isObject(r, true))
|
|
281
|
-
return next({ statusCode: 400, message: `${LOGS_PREFIX}Normalize: no data found in request body` });
|
|
282
|
-
normalize(r, this._properties);
|
|
283
|
-
next();
|
|
284
|
-
};
|
|
285
|
-
this.validateArray = (req, _res, next) => {
|
|
286
|
-
var _a;
|
|
287
|
-
log.debug(`validateArray ${this.name}`);
|
|
288
|
-
const rows = (_a = req.body) === null || _a === void 0 ? void 0 : _a.rows;
|
|
289
|
-
const method = req.method;
|
|
290
|
-
if (!isArray(rows, ">", 0))
|
|
291
|
-
return next({ statusCode: 400, message: `${LOGS_PREFIX}Validate: no rows found in request body` });
|
|
292
|
-
if (!isIn(METHODS, method))
|
|
293
|
-
return next({
|
|
294
|
-
statusCode: 400,
|
|
295
|
-
message: `${LOGS_PREFIX}Invalid REST method. Received: ${method}. Must be one of: ${METHODS.toString()}`
|
|
296
|
-
});
|
|
297
|
-
for (const r of rows) {
|
|
298
|
-
const error = validate(r, this._properties, method);
|
|
299
|
-
if (error)
|
|
300
|
-
return next(error);
|
|
301
|
-
}
|
|
302
|
-
next();
|
|
303
|
-
};
|
|
304
|
-
this.validateOne = (req, _res, next) => {
|
|
305
|
-
log.debug(`validateOne ${this.name}`);
|
|
306
|
-
const record = req.body;
|
|
307
|
-
const method = req.method;
|
|
308
|
-
if (!isObject(record, true))
|
|
309
|
-
return next({ statusCode: 400, message: `${LOGS_PREFIX}Validate: no data found in request body` });
|
|
310
|
-
if (!isIn(METHODS, method))
|
|
311
|
-
return next({
|
|
312
|
-
statusCode: 400,
|
|
313
|
-
message: `${LOGS_PREFIX}Invalid REST method. Received: ${method}. Must be one of: ${METHODS.toString()}`
|
|
314
|
-
});
|
|
315
|
-
const error = validate(record, this._properties, method);
|
|
316
|
-
if (error)
|
|
317
|
-
return next(error);
|
|
318
|
-
next();
|
|
319
|
-
};
|
|
320
290
|
this._name = name;
|
|
321
291
|
this._properties = [];
|
|
322
292
|
this._privateProps = [];
|
|
293
|
+
this._propsByMethod = new Map(METHODS.map(m => [m, []]));
|
|
323
294
|
for (const p of properties) {
|
|
324
295
|
const prop = new Property(p.key, p.type, p.min, p.max, p.isPrivate, p.requiredFor, p.isTypeChecked, p.sanitizer, p.normalizer, p.validator);
|
|
325
|
-
Object.
|
|
296
|
+
for (const k of Object.keys(p))
|
|
297
|
+
if (!STANDARD_PROP_KEYS.has(k))
|
|
298
|
+
prop[k] = p[k];
|
|
326
299
|
this._properties.push(prop);
|
|
327
300
|
if (prop.isPrivate)
|
|
328
301
|
this._privateProps.push(prop.key);
|
|
302
|
+
for (const m of prop.requiredFor)
|
|
303
|
+
this._propsByMethod.get(m)?.push(prop);
|
|
329
304
|
}
|
|
330
305
|
}
|
|
331
306
|
get name() {
|
|
@@ -346,13 +321,70 @@ class Entity {
|
|
|
346
321
|
return this.properties.find(p => p.key === key);
|
|
347
322
|
}
|
|
348
323
|
getPropsByMethod(method) {
|
|
349
|
-
|
|
350
|
-
for (const p of this.properties) {
|
|
351
|
-
if (isIn(p.requiredFor, method, 0))
|
|
352
|
-
props.push(p);
|
|
353
|
-
}
|
|
354
|
-
return props;
|
|
324
|
+
return this._propsByMethod.get(method) ?? [];
|
|
355
325
|
}
|
|
326
|
+
normalizeArray = (req, _res, next) => {
|
|
327
|
+
log.debug(`normalizeArray ${this.name}`);
|
|
328
|
+
const rows = req.body?.rows;
|
|
329
|
+
if (!isArray(rows, ">", 0)) {
|
|
330
|
+
next({ statusCode: 400, message: `${LOGS_PREFIX}Normalize: no rows found in request body` });
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
333
|
+
for (const r of rows) {
|
|
334
|
+
normalize(r, this._properties);
|
|
335
|
+
}
|
|
336
|
+
next();
|
|
337
|
+
};
|
|
338
|
+
normalizeOne = (req, _res, next) => {
|
|
339
|
+
log.debug(`normalizeOne ${this.name}`);
|
|
340
|
+
const r = req.body;
|
|
341
|
+
if (!isObject(r, true)) {
|
|
342
|
+
next({ statusCode: 400, message: `${LOGS_PREFIX}Normalize: no data found in request body` });
|
|
343
|
+
return;
|
|
344
|
+
}
|
|
345
|
+
normalize(r, this._properties);
|
|
346
|
+
next();
|
|
347
|
+
};
|
|
348
|
+
validateArray = (req, _res, next) => {
|
|
349
|
+
log.debug(`validateArray ${this.name}`);
|
|
350
|
+
const rows = req.body?.rows;
|
|
351
|
+
const method = req.method;
|
|
352
|
+
if (!isArray(rows, ">", 0)) {
|
|
353
|
+
next({ statusCode: 400, message: `${LOGS_PREFIX}Validate: no rows found in request body` });
|
|
354
|
+
return;
|
|
355
|
+
}
|
|
356
|
+
if (!METHODS.includes(method)) {
|
|
357
|
+
next({ statusCode: 400, message: `${LOGS_PREFIX}Invalid REST method. Received: ${method}. Must be one of: ${METHODS.toString()}` });
|
|
358
|
+
return;
|
|
359
|
+
}
|
|
360
|
+
for (const r of rows) {
|
|
361
|
+
const error = validate(r, this._properties, method);
|
|
362
|
+
if (error) {
|
|
363
|
+
next(error);
|
|
364
|
+
return;
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
next();
|
|
368
|
+
};
|
|
369
|
+
validateOne = (req, _res, next) => {
|
|
370
|
+
log.debug(`validateOne ${this.name}`);
|
|
371
|
+
const record = req.body;
|
|
372
|
+
const method = req.method;
|
|
373
|
+
if (!isObject(record, true)) {
|
|
374
|
+
next({ statusCode: 400, message: `${LOGS_PREFIX}Validate: no data found in request body` });
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
if (!METHODS.includes(method)) {
|
|
378
|
+
next({ statusCode: 400, message: `${LOGS_PREFIX}Invalid REST method. Received: ${method}. Must be one of: ${METHODS.toString()}` });
|
|
379
|
+
return;
|
|
380
|
+
}
|
|
381
|
+
const error = validate(record, this._properties, method);
|
|
382
|
+
if (error) {
|
|
383
|
+
next(error);
|
|
384
|
+
return;
|
|
385
|
+
}
|
|
386
|
+
next();
|
|
387
|
+
};
|
|
356
388
|
}
|
|
357
389
|
|
|
358
390
|
export { Entity };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dwtechs/antity",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.18.0",
|
|
4
4
|
"description": "Open source library for easy entity management",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"entities"
|
|
@@ -13,8 +13,7 @@
|
|
|
13
13
|
"url": "https://github.com/DWTechs/Antity.js"
|
|
14
14
|
},
|
|
15
15
|
"bugs": {
|
|
16
|
-
"url": "https://github.com/DWTechs/Antity.js/issues"
|
|
17
|
-
"email": ""
|
|
16
|
+
"url": "https://github.com/DWTechs/Antity.js/issues"
|
|
18
17
|
},
|
|
19
18
|
"license": "MIT",
|
|
20
19
|
"author": {
|
|
@@ -22,36 +21,34 @@
|
|
|
22
21
|
"email": "http://www.lcluber.com/contact",
|
|
23
22
|
"url": "http://www.lcluber.com"
|
|
24
23
|
},
|
|
25
|
-
"contributors": [],
|
|
26
24
|
"scripts": {
|
|
27
|
-
"start": "",
|
|
28
25
|
"prebuild": "npm install",
|
|
29
26
|
"build": "node ./scripts/clear && tsc && npm run rollup && node ./scripts/copy && npm run test",
|
|
30
|
-
"rollup
|
|
31
|
-
"
|
|
32
|
-
"rollup": "npm run rollup:mjs",
|
|
33
|
-
"test": "jest --coverage --config jest.config.js"
|
|
27
|
+
"rollup": "rollup --config rollup.config.mjs",
|
|
28
|
+
"test": "jest --coverage"
|
|
34
29
|
},
|
|
35
30
|
"files": [
|
|
36
31
|
"dist/"
|
|
37
32
|
],
|
|
33
|
+
"engines": {
|
|
34
|
+
"node": ">= 22"
|
|
35
|
+
},
|
|
38
36
|
"dependencies": {
|
|
39
|
-
"@dwtechs/checkard": "3.
|
|
40
|
-
"@dwtechs/
|
|
41
|
-
"@dwtechs/sparray": "0.2.1"
|
|
37
|
+
"@dwtechs/checkard": "3.6.0",
|
|
38
|
+
"@dwtechs/passken": "0.6.1",
|
|
39
|
+
"@dwtechs/sparray": "0.2.1",
|
|
40
|
+
"@dwtechs/winstan": "0.7.0"
|
|
42
41
|
},
|
|
43
42
|
"devDependencies": {
|
|
44
43
|
"@babel/core": "7.26.0",
|
|
45
44
|
"@babel/preset-env": "7.26.0",
|
|
46
|
-
"@
|
|
47
|
-
"@rollup/plugin-node-resolve": "15.3.0",
|
|
45
|
+
"@types/express": "5.0.6",
|
|
48
46
|
"@types/jest": "29.5.14",
|
|
49
|
-
"@types/node": "
|
|
50
|
-
"@types/express": "5.0.0",
|
|
47
|
+
"@types/node": "25.6.0",
|
|
51
48
|
"babel-jest": "29.7.0",
|
|
52
49
|
"core-js": "3.33.0",
|
|
53
50
|
"jest": "29.7.0",
|
|
54
51
|
"rollup": "4.24.0",
|
|
55
|
-
"typescript": "
|
|
52
|
+
"typescript": "6.0.3"
|
|
56
53
|
}
|
|
57
54
|
}
|