@dwtechs/antity 0.3.0 → 0.4.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 +51 -22
- package/dist/antity.cjs.js +65 -33
- package/dist/antity.d.ts +17 -13
- package/dist/antity.js +66 -34
- package/package.json +5 -2
package/README.md
CHANGED
|
@@ -50,15 +50,16 @@ $ npm i @dwtechs/antity
|
|
|
50
50
|
import { Entity } from "@dwtechs/antity";
|
|
51
51
|
import { normalizeName, normalizeNickname } from "@dwtechs/checkard";
|
|
52
52
|
|
|
53
|
-
const entity = new Entity("
|
|
53
|
+
const entity = new Entity("consumers", [
|
|
54
54
|
{
|
|
55
55
|
key: "id",
|
|
56
56
|
type: "integer",
|
|
57
57
|
min: 0,
|
|
58
58
|
max: 120,
|
|
59
59
|
typeCheck: true,
|
|
60
|
-
|
|
60
|
+
operations: ["select", "update", "delete"],
|
|
61
61
|
required: true,
|
|
62
|
+
safe: true,
|
|
62
63
|
sanitize: true,
|
|
63
64
|
normalize: true,
|
|
64
65
|
control: true,
|
|
@@ -72,8 +73,9 @@ const entity = new Entity("consumer", "consumers", [
|
|
|
72
73
|
min: 0,
|
|
73
74
|
max: 255,
|
|
74
75
|
typeCheck: true,
|
|
75
|
-
|
|
76
|
+
operations: ["select", "insert", "update", "delete"],
|
|
76
77
|
required: true,
|
|
78
|
+
safe: true,
|
|
77
79
|
sanitize: true,
|
|
78
80
|
normalize: true,
|
|
79
81
|
control: true,
|
|
@@ -87,8 +89,9 @@ const entity = new Entity("consumer", "consumers", [
|
|
|
87
89
|
min: 0,
|
|
88
90
|
max: 255,
|
|
89
91
|
typeCheck: true,
|
|
90
|
-
|
|
92
|
+
operations: ["select", "insert", "update", "delete"],
|
|
91
93
|
required: true,
|
|
94
|
+
safe: true,
|
|
92
95
|
sanitize: true,
|
|
93
96
|
normalize: true,
|
|
94
97
|
control: true,
|
|
@@ -102,8 +105,9 @@ const entity = new Entity("consumer", "consumers", [
|
|
|
102
105
|
min: 0,
|
|
103
106
|
max: 255,
|
|
104
107
|
typeCheck: true,
|
|
105
|
-
|
|
108
|
+
operations: ["select", "insert", "update", "delete"],
|
|
106
109
|
required: true,
|
|
110
|
+
safe: true,
|
|
107
111
|
sanitize: true,
|
|
108
112
|
normalize: true,
|
|
109
113
|
control: true,
|
|
@@ -113,10 +117,9 @@ const entity = new Entity("consumer", "consumers", [
|
|
|
113
117
|
},
|
|
114
118
|
]);
|
|
115
119
|
|
|
116
|
-
req.body = entity.normalize(req.body);
|
|
117
|
-
const check = entity.validate(req.body,
|
|
118
|
-
|
|
119
|
-
|
|
120
|
+
req.body = entity.normalize(req.body); // will also sanitize if true
|
|
121
|
+
const check = entity.validate(req.body, "select");
|
|
122
|
+
const unsafeProps = entity.getUnsafeProps();
|
|
120
123
|
|
|
121
124
|
```
|
|
122
125
|
|
|
@@ -154,6 +157,7 @@ type Type = "boolean" |
|
|
|
154
157
|
"node" |
|
|
155
158
|
"object";
|
|
156
159
|
|
|
160
|
+
type Operation = "select" | "insert" | "update" | "merge" | "delete";
|
|
157
161
|
type Method = "GET" | "PATCH" | "PUT" | "POST" | "DELETE";
|
|
158
162
|
|
|
159
163
|
class Property {
|
|
@@ -162,8 +166,9 @@ class Property {
|
|
|
162
166
|
min: number | Date;
|
|
163
167
|
max: number | Date;
|
|
164
168
|
required: boolean;
|
|
169
|
+
safe: boolean;
|
|
165
170
|
typeCheck: boolean;
|
|
166
|
-
|
|
171
|
+
operations: Operation[];
|
|
167
172
|
sanitize: boolean;
|
|
168
173
|
normalize: boolean;
|
|
169
174
|
control: boolean;
|
|
@@ -173,18 +178,41 @@ class Property {
|
|
|
173
178
|
};
|
|
174
179
|
|
|
175
180
|
class Entity {
|
|
176
|
-
name: string;
|
|
177
181
|
table: string;
|
|
178
|
-
cols: Record<
|
|
182
|
+
cols: Record<Operation, string[]>;
|
|
179
183
|
properties: Property[];
|
|
180
|
-
normalize(rows: Record<string, any>[]): Record<string, any>[];
|
|
181
|
-
validate(rows: Record<string, any>[],
|
|
184
|
+
normalize(rows: Record<string, any>[]): Record<string, any>[]; // will also sanitize if true
|
|
185
|
+
validate(rows: Record<string, any>[], operation: Operation | Method): string | null;
|
|
182
186
|
getTable(): string;
|
|
183
|
-
|
|
187
|
+
// if pagination is true for a select operation, it will return cols + a total column
|
|
188
|
+
getCols(operation: Operation, stringify?: boolean, pagination?: boolean): string[] | string;
|
|
189
|
+
getUnsafeProps(): string[];
|
|
184
190
|
}
|
|
185
191
|
|
|
186
192
|
```
|
|
187
193
|
|
|
194
|
+
### REST Methods mapping
|
|
195
|
+
|
|
196
|
+
When validating request inputs, you can use REST methods or SQL operations as second parameter
|
|
197
|
+
|
|
198
|
+
| REST method | SQL operation |
|
|
199
|
+
| :---------- | :------------ |
|
|
200
|
+
| GET | select |
|
|
201
|
+
| PATCH | update |
|
|
202
|
+
| PUT | update |
|
|
203
|
+
| POST | insert |
|
|
204
|
+
| DELETE | delete |
|
|
205
|
+
|
|
206
|
+
examples :
|
|
207
|
+
|
|
208
|
+
```javascript
|
|
209
|
+
|
|
210
|
+
entity.validate(req.body, "GET"); // will validate "select" properties
|
|
211
|
+
entity.validate(req.body, "PUT"); // will validate "update" properties
|
|
212
|
+
entity.validate(req.body, "DELETE"); // will validate "delete" properties
|
|
213
|
+
|
|
214
|
+
```
|
|
215
|
+
|
|
188
216
|
|
|
189
217
|
### Available options for a property
|
|
190
218
|
|
|
@@ -193,17 +221,18 @@ Any of these can be passed into the options object for each function.
|
|
|
193
221
|
| Name | Type | Description | Default value |
|
|
194
222
|
| :-------------- | :------------------------ | :------------------------------------------------ | :-------------- |
|
|
195
223
|
| key | string | Name of the property |
|
|
196
|
-
| type | Type | Type of the property
|
|
197
|
-
| min | number
|
|
198
|
-
| max | number
|
|
199
|
-
| required | boolean | Is this property required
|
|
224
|
+
| type | Type | Type of the property |
|
|
225
|
+
| min | number \| Date | Minimum value | 0 \| 1900-01-01
|
|
226
|
+
| max | number \| Date | Maximum value | 999999999 \| 2200-12-31
|
|
227
|
+
| required | boolean | Is this property required on insert | false
|
|
228
|
+
| safe | boolean | Is this property safe to send to the client | true
|
|
200
229
|
| typeCheck | boolean | Type is checked if true | false
|
|
201
|
-
|
|
|
230
|
+
| operations | Operation[] | SQL DML operations concerned by the property | [ "select", "insert", "update", "merge", "delete" ]
|
|
202
231
|
| sanitize | boolean | Sanitize the property if true | true
|
|
203
232
|
| normalize | boolean | Normalize the property if true | false
|
|
204
233
|
| control | boolean | Control the property if true | true
|
|
205
|
-
| sanitizer | ((v:any) => any) \| null
|
|
206
|
-
| normalizer | ((v:any) => any) \| null
|
|
234
|
+
| sanitizer | ((v:any) => any) \| null | Sanitizer function if sanitize is true | null
|
|
235
|
+
| normalizer | ((v:any) => any) \| null | Normalizer function if normalize is true | null
|
|
207
236
|
| controller | ((v:any, min:number, max:number, typeCheck:boolean) => any) \| null | Controller function if control is true | null
|
|
208
237
|
|
|
209
238
|
* *Min and max parameters are not used for boolean type*
|
package/dist/antity.cjs.js
CHANGED
|
@@ -331,7 +331,7 @@ function isValidTimestamp(t, min = -2208989361000, max = 7258114800000, type = t
|
|
|
331
331
|
return isTimestamp(t, type) && t >= min && t <= max;
|
|
332
332
|
}
|
|
333
333
|
|
|
334
|
-
const
|
|
334
|
+
const Operations = ["select", "insert", "update", "merge", "delete"];
|
|
335
335
|
|
|
336
336
|
const Types = {
|
|
337
337
|
boolean: {
|
|
@@ -421,24 +421,25 @@ const Required = {
|
|
|
421
421
|
};
|
|
422
422
|
|
|
423
423
|
class Property {
|
|
424
|
-
constructor(key, type, min, max, required, typeCheck,
|
|
424
|
+
constructor(key, type, min, max, required, safe, typeCheck, operations, sanitize, normalize, control, sanitizer, normalizer, controller) {
|
|
425
425
|
if (!isString(key, true))
|
|
426
|
-
throw new Error(`Property
|
|
426
|
+
throw new Error(`Property"key" must be a string. Received ${key}`);
|
|
427
427
|
if (!isProperty(type, Types))
|
|
428
|
-
throw new Error(`Property type must be a valid type. Received ${type}`);
|
|
429
|
-
if (isArray(
|
|
430
|
-
for (const
|
|
431
|
-
if (!isIn(
|
|
432
|
-
throw new Error(`Property
|
|
428
|
+
throw new Error(`Property "type" must be a valid type. Received ${type}`);
|
|
429
|
+
if (isArray(operations)) {
|
|
430
|
+
for (const o of operations) {
|
|
431
|
+
if (!isIn(o, Operations))
|
|
432
|
+
throw new Error(`Property "operations" must be an array of SQL operations. Received ${o}`);
|
|
433
433
|
}
|
|
434
434
|
}
|
|
435
435
|
this.key = key;
|
|
436
436
|
this.type = type;
|
|
437
|
-
this.min =
|
|
438
|
-
this.max =
|
|
437
|
+
this.min = this.interval(min, type, 0, "1900-01-01T00:00:00Z");
|
|
438
|
+
this.max = this.interval(max, type, 999999999, "2200-12-31T00:00:00Z");
|
|
439
439
|
this.required = isBoolean(required) ? required : false;
|
|
440
|
+
this.safe = isBoolean(safe) ? safe : true;
|
|
440
441
|
this.typeCheck = isBoolean(typeCheck) ? typeCheck : false;
|
|
441
|
-
this.
|
|
442
|
+
this.operations = operations || Operations;
|
|
442
443
|
this.sanitize = isBoolean(sanitize) ? sanitize : true;
|
|
443
444
|
this.normalize = isBoolean(normalize) ? normalize : false;
|
|
444
445
|
this.control = isBoolean(control) ? control : true;
|
|
@@ -446,6 +447,11 @@ class Property {
|
|
|
446
447
|
this.normalizer = isFunction(normalizer) ? normalizer : null;
|
|
447
448
|
this.controller = isFunction(controller) ? controller : null;
|
|
448
449
|
}
|
|
450
|
+
interval(val, type, integerDefault, dateDefault) {
|
|
451
|
+
if (type === "date")
|
|
452
|
+
return isDate(val) ? val : new Date(dateDefault);
|
|
453
|
+
return isInteger(val, true) ? val : integerDefault;
|
|
454
|
+
}
|
|
449
455
|
}
|
|
450
456
|
|
|
451
457
|
const Messages = {
|
|
@@ -453,55 +459,67 @@ const Messages = {
|
|
|
453
459
|
invalid: (key, type) => `Invalid ${key}, must be of type ${type}`,
|
|
454
460
|
};
|
|
455
461
|
|
|
462
|
+
const Methods = ["GET", "PATCH", "PUT", "POST", "DELETE"];
|
|
463
|
+
|
|
456
464
|
class Entity {
|
|
457
|
-
constructor(
|
|
458
|
-
this.name = name;
|
|
465
|
+
constructor(table, properties) {
|
|
459
466
|
this.table = table;
|
|
467
|
+
this.properties = [];
|
|
460
468
|
this.cols = {
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
469
|
+
select: [],
|
|
470
|
+
insert: [],
|
|
471
|
+
update: [],
|
|
472
|
+
merge: [],
|
|
473
|
+
delete: []
|
|
466
474
|
};
|
|
467
|
-
this.
|
|
468
|
-
}
|
|
469
|
-
init(properties) {
|
|
470
|
-
const props = [];
|
|
475
|
+
this.unsafeProps = [];
|
|
471
476
|
for (const p of properties) {
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
477
|
+
const prop = new Property(p.key, p.type, p.min, p.max, p.required, p.safe, p.typeCheck, p.operations, p.sanitize, p.normalize, p.control, p.sanitizer, p.normalizer, p.controller);
|
|
478
|
+
this.properties.push(prop);
|
|
479
|
+
for (const o of p.operations) {
|
|
480
|
+
if (o === "update")
|
|
481
|
+
this.cols[o].push(`${p.key} = $${this.cols[o].length + 1}`);
|
|
482
|
+
else
|
|
483
|
+
this.cols[o].push(p.key);
|
|
475
484
|
}
|
|
485
|
+
if (!prop.safe)
|
|
486
|
+
this.unsafeProps.push(prop.key);
|
|
476
487
|
}
|
|
477
|
-
return props;
|
|
478
488
|
}
|
|
479
489
|
getTable() {
|
|
480
490
|
return this.table;
|
|
481
491
|
}
|
|
482
|
-
getCols(
|
|
483
|
-
|
|
492
|
+
getCols(operation, stringify, pagination) {
|
|
493
|
+
const cols = pagination && operation === "select" ? [...this.cols[operation], "COUNT(*) OVER () AS total"] : this.cols[operation];
|
|
494
|
+
return stringify ? cols.join(', ') : cols;
|
|
495
|
+
}
|
|
496
|
+
getUnsafeProps() {
|
|
497
|
+
return this.unsafeProps;
|
|
484
498
|
}
|
|
485
499
|
normalize(rows) {
|
|
486
500
|
for (const r of rows) {
|
|
487
501
|
for (const { key, sanitize, normalize, sanitizer, normalizer, } of this.properties) {
|
|
488
502
|
let v = r[key];
|
|
489
503
|
if (v) {
|
|
490
|
-
if (sanitize)
|
|
504
|
+
if (sanitize) {
|
|
491
505
|
v = this.sanitize(v, sanitizer);
|
|
492
|
-
|
|
506
|
+
}
|
|
507
|
+
if (normalize && normalizer) {
|
|
493
508
|
v = normalizer(v);
|
|
509
|
+
}
|
|
494
510
|
r[key] = v;
|
|
495
511
|
}
|
|
496
512
|
}
|
|
497
513
|
}
|
|
498
514
|
return rows;
|
|
499
515
|
}
|
|
500
|
-
validate(rows,
|
|
516
|
+
validate(rows, operation) {
|
|
517
|
+
if (isIn(operation, Methods))
|
|
518
|
+
operation = this.mapMethods(operation);
|
|
501
519
|
for (const r of rows) {
|
|
502
|
-
for (const { key, type, min, max, required, typeCheck,
|
|
520
|
+
for (const { key, type, min, max, required, typeCheck, operations, control, controller } of this.properties) {
|
|
503
521
|
const v = r[key];
|
|
504
|
-
if (
|
|
522
|
+
if (isIn(operation, operations)) {
|
|
505
523
|
if (required) {
|
|
506
524
|
const rq = this.require(v, key);
|
|
507
525
|
if (rq)
|
|
@@ -551,6 +569,20 @@ class Entity {
|
|
|
551
569
|
return v;
|
|
552
570
|
}
|
|
553
571
|
}
|
|
572
|
+
mapMethods(method) {
|
|
573
|
+
switch (method) {
|
|
574
|
+
case "GET":
|
|
575
|
+
return Operations[0];
|
|
576
|
+
case "PATCH":
|
|
577
|
+
return Operations[2];
|
|
578
|
+
case "PUT":
|
|
579
|
+
return Operations[2];
|
|
580
|
+
case "POST":
|
|
581
|
+
return Operations[1];
|
|
582
|
+
case "DELETE":
|
|
583
|
+
return Operations[4];
|
|
584
|
+
}
|
|
585
|
+
}
|
|
554
586
|
}
|
|
555
587
|
|
|
556
588
|
exports.Entity = Entity;
|
package/dist/antity.d.ts
CHANGED
|
@@ -25,7 +25,9 @@ https://github.com/DWTechs/Antity.js
|
|
|
25
25
|
*/
|
|
26
26
|
|
|
27
27
|
|
|
28
|
+
type Operation = typeof Operations[number];
|
|
28
29
|
type Method = typeof Methods[number];
|
|
30
|
+
|
|
29
31
|
type Type =
|
|
30
32
|
"boolean" |
|
|
31
33
|
"string" |
|
|
@@ -55,7 +57,8 @@ type Type =
|
|
|
55
57
|
"node" |
|
|
56
58
|
"object";
|
|
57
59
|
|
|
58
|
-
declare const
|
|
60
|
+
declare const Operations: readonly [ "select", "insert", "update", "merge", "delete" ];
|
|
61
|
+
declare const Methods: readonly [ "GET", "PATCH", "PUT", "POST", "DELETE" ];
|
|
59
62
|
|
|
60
63
|
declare const Types: Record<Type, {
|
|
61
64
|
validate: (v: any, min: number | Date, max: number | Date, typeCheck: boolean) => boolean;
|
|
@@ -66,16 +69,15 @@ declare const Required: {
|
|
|
66
69
|
};
|
|
67
70
|
|
|
68
71
|
declare class Entity {
|
|
69
|
-
name: string;
|
|
70
72
|
table: string;
|
|
71
|
-
cols: Record<
|
|
73
|
+
cols: Record<Operation, string[]>;
|
|
72
74
|
properties: Property[];
|
|
73
|
-
constructor(
|
|
74
|
-
private init;
|
|
75
|
+
constructor(table: string, properties: Property[]);
|
|
75
76
|
getTable(): string;
|
|
76
|
-
getCols(
|
|
77
|
+
getCols(operation: Operation, stringify?: boolean, pagination?: boolean): string[] | string;
|
|
78
|
+
getUnsafeProps(): string[];
|
|
77
79
|
normalize(rows: Record<string, any>[]): Record<string, any>[];
|
|
78
|
-
validate(rows: Record<string, any>[],
|
|
80
|
+
validate(rows: Record<string, any>[], operation: Operation | Method): string | null;
|
|
79
81
|
private require;
|
|
80
82
|
private control;
|
|
81
83
|
private sanitize;
|
|
@@ -90,11 +92,12 @@ declare const Messages: {
|
|
|
90
92
|
declare class Property {
|
|
91
93
|
key: string;
|
|
92
94
|
type: Type;
|
|
93
|
-
min: number;
|
|
94
|
-
max: number;
|
|
95
|
+
min: number | Date;
|
|
96
|
+
max: number | Date;
|
|
95
97
|
required: boolean;
|
|
98
|
+
safe: boolean;
|
|
96
99
|
typeCheck: boolean;
|
|
97
|
-
|
|
100
|
+
operations: Operation[];
|
|
98
101
|
sanitize: boolean;
|
|
99
102
|
normalize: boolean;
|
|
100
103
|
control: boolean;
|
|
@@ -106,8 +109,9 @@ declare class Property {
|
|
|
106
109
|
min: number | Date,
|
|
107
110
|
max: number | Date,
|
|
108
111
|
required: boolean,
|
|
112
|
+
safe: boolean,
|
|
109
113
|
typeCheck: boolean,
|
|
110
|
-
|
|
114
|
+
operations: Operation[],
|
|
111
115
|
sanitize: boolean,
|
|
112
116
|
normalize: boolean,
|
|
113
117
|
control: boolean,
|
|
@@ -117,13 +121,13 @@ declare class Property {
|
|
|
117
121
|
);
|
|
118
122
|
}
|
|
119
123
|
|
|
120
|
-
export type { Type, Method };
|
|
124
|
+
export type { Type, Operation, Method };
|
|
121
125
|
export {
|
|
122
126
|
Entity,
|
|
123
127
|
Property,
|
|
124
128
|
Messages,
|
|
125
129
|
Types,
|
|
126
130
|
Required,
|
|
127
|
-
|
|
131
|
+
Operations
|
|
128
132
|
};
|
|
129
133
|
|
package/dist/antity.js
CHANGED
|
@@ -24,9 +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, isEmail, isRegex, isJson, isJWT, isSymbol, isIpAddress, isSlug, isHexadecimal, isValidDate, isValidTimestamp, isFunction, isHtmlElement, isHtmlEventAttribute, isNode, isObject, isNil, isString, isProperty, isArray, isIn, isInteger } from '@dwtechs/checkard';
|
|
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, isNil, isString, isProperty, isArray, isIn, isDate, isInteger } from '@dwtechs/checkard';
|
|
28
28
|
|
|
29
|
-
const
|
|
29
|
+
const Operations = ["select", "insert", "update", "merge", "delete"];
|
|
30
30
|
|
|
31
31
|
const Types = {
|
|
32
32
|
boolean: {
|
|
@@ -116,24 +116,25 @@ const Required = {
|
|
|
116
116
|
};
|
|
117
117
|
|
|
118
118
|
class Property {
|
|
119
|
-
constructor(key, type, min, max, required, typeCheck,
|
|
119
|
+
constructor(key, type, min, max, required, safe, typeCheck, operations, sanitize, normalize, control, sanitizer, normalizer, controller) {
|
|
120
120
|
if (!isString(key, true))
|
|
121
|
-
throw new Error(`Property
|
|
121
|
+
throw new Error(`Property"key" must be a string. Received ${key}`);
|
|
122
122
|
if (!isProperty(type, Types))
|
|
123
|
-
throw new Error(`Property type must be a valid type. Received ${type}`);
|
|
124
|
-
if (isArray(
|
|
125
|
-
for (const
|
|
126
|
-
if (!isIn(
|
|
127
|
-
throw new Error(`Property
|
|
123
|
+
throw new Error(`Property "type" must be a valid type. Received ${type}`);
|
|
124
|
+
if (isArray(operations)) {
|
|
125
|
+
for (const o of operations) {
|
|
126
|
+
if (!isIn(o, Operations))
|
|
127
|
+
throw new Error(`Property "operations" must be an array of SQL operations. Received ${o}`);
|
|
128
128
|
}
|
|
129
129
|
}
|
|
130
130
|
this.key = key;
|
|
131
131
|
this.type = type;
|
|
132
|
-
this.min =
|
|
133
|
-
this.max =
|
|
132
|
+
this.min = this.interval(min, type, 0, "1900-01-01T00:00:00Z");
|
|
133
|
+
this.max = this.interval(max, type, 999999999, "2200-12-31T00:00:00Z");
|
|
134
134
|
this.required = isBoolean(required) ? required : false;
|
|
135
|
+
this.safe = isBoolean(safe) ? safe : true;
|
|
135
136
|
this.typeCheck = isBoolean(typeCheck) ? typeCheck : false;
|
|
136
|
-
this.
|
|
137
|
+
this.operations = operations || Operations;
|
|
137
138
|
this.sanitize = isBoolean(sanitize) ? sanitize : true;
|
|
138
139
|
this.normalize = isBoolean(normalize) ? normalize : false;
|
|
139
140
|
this.control = isBoolean(control) ? control : true;
|
|
@@ -141,6 +142,11 @@ class Property {
|
|
|
141
142
|
this.normalizer = isFunction(normalizer) ? normalizer : null;
|
|
142
143
|
this.controller = isFunction(controller) ? controller : null;
|
|
143
144
|
}
|
|
145
|
+
interval(val, type, integerDefault, dateDefault) {
|
|
146
|
+
if (type === "date")
|
|
147
|
+
return isDate(val) ? val : new Date(dateDefault);
|
|
148
|
+
return isInteger(val, true) ? val : integerDefault;
|
|
149
|
+
}
|
|
144
150
|
}
|
|
145
151
|
|
|
146
152
|
const Messages = {
|
|
@@ -148,55 +154,67 @@ const Messages = {
|
|
|
148
154
|
invalid: (key, type) => `Invalid ${key}, must be of type ${type}`,
|
|
149
155
|
};
|
|
150
156
|
|
|
157
|
+
const Methods = ["GET", "PATCH", "PUT", "POST", "DELETE"];
|
|
158
|
+
|
|
151
159
|
class Entity {
|
|
152
|
-
constructor(
|
|
153
|
-
this.name = name;
|
|
160
|
+
constructor(table, properties) {
|
|
154
161
|
this.table = table;
|
|
162
|
+
this.properties = [];
|
|
155
163
|
this.cols = {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
164
|
+
select: [],
|
|
165
|
+
insert: [],
|
|
166
|
+
update: [],
|
|
167
|
+
merge: [],
|
|
168
|
+
delete: []
|
|
161
169
|
};
|
|
162
|
-
this.
|
|
163
|
-
}
|
|
164
|
-
init(properties) {
|
|
165
|
-
const props = [];
|
|
170
|
+
this.unsafeProps = [];
|
|
166
171
|
for (const p of properties) {
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
172
|
+
const prop = new Property(p.key, p.type, p.min, p.max, p.required, p.safe, p.typeCheck, p.operations, p.sanitize, p.normalize, p.control, p.sanitizer, p.normalizer, p.controller);
|
|
173
|
+
this.properties.push(prop);
|
|
174
|
+
for (const o of p.operations) {
|
|
175
|
+
if (o === "update")
|
|
176
|
+
this.cols[o].push(`${p.key} = $${this.cols[o].length + 1}`);
|
|
177
|
+
else
|
|
178
|
+
this.cols[o].push(p.key);
|
|
170
179
|
}
|
|
180
|
+
if (!prop.safe)
|
|
181
|
+
this.unsafeProps.push(prop.key);
|
|
171
182
|
}
|
|
172
|
-
return props;
|
|
173
183
|
}
|
|
174
184
|
getTable() {
|
|
175
185
|
return this.table;
|
|
176
186
|
}
|
|
177
|
-
getCols(
|
|
178
|
-
|
|
187
|
+
getCols(operation, stringify, pagination) {
|
|
188
|
+
const cols = pagination && operation === "select" ? [...this.cols[operation], "COUNT(*) OVER () AS total"] : this.cols[operation];
|
|
189
|
+
return stringify ? cols.join(', ') : cols;
|
|
190
|
+
}
|
|
191
|
+
getUnsafeProps() {
|
|
192
|
+
return this.unsafeProps;
|
|
179
193
|
}
|
|
180
194
|
normalize(rows) {
|
|
181
195
|
for (const r of rows) {
|
|
182
196
|
for (const { key, sanitize, normalize, sanitizer, normalizer, } of this.properties) {
|
|
183
197
|
let v = r[key];
|
|
184
198
|
if (v) {
|
|
185
|
-
if (sanitize)
|
|
199
|
+
if (sanitize) {
|
|
186
200
|
v = this.sanitize(v, sanitizer);
|
|
187
|
-
|
|
201
|
+
}
|
|
202
|
+
if (normalize && normalizer) {
|
|
188
203
|
v = normalizer(v);
|
|
204
|
+
}
|
|
189
205
|
r[key] = v;
|
|
190
206
|
}
|
|
191
207
|
}
|
|
192
208
|
}
|
|
193
209
|
return rows;
|
|
194
210
|
}
|
|
195
|
-
validate(rows,
|
|
211
|
+
validate(rows, operation) {
|
|
212
|
+
if (isIn(operation, Methods))
|
|
213
|
+
operation = this.mapMethods(operation);
|
|
196
214
|
for (const r of rows) {
|
|
197
|
-
for (const { key, type, min, max, required, typeCheck,
|
|
215
|
+
for (const { key, type, min, max, required, typeCheck, operations, control, controller } of this.properties) {
|
|
198
216
|
const v = r[key];
|
|
199
|
-
if (
|
|
217
|
+
if (isIn(operation, operations)) {
|
|
200
218
|
if (required) {
|
|
201
219
|
const rq = this.require(v, key);
|
|
202
220
|
if (rq)
|
|
@@ -246,6 +264,20 @@ class Entity {
|
|
|
246
264
|
return v;
|
|
247
265
|
}
|
|
248
266
|
}
|
|
267
|
+
mapMethods(method) {
|
|
268
|
+
switch (method) {
|
|
269
|
+
case "GET":
|
|
270
|
+
return Operations[0];
|
|
271
|
+
case "PATCH":
|
|
272
|
+
return Operations[2];
|
|
273
|
+
case "PUT":
|
|
274
|
+
return Operations[2];
|
|
275
|
+
case "POST":
|
|
276
|
+
return Operations[1];
|
|
277
|
+
case "DELETE":
|
|
278
|
+
return Operations[4];
|
|
279
|
+
}
|
|
280
|
+
}
|
|
249
281
|
}
|
|
250
282
|
|
|
251
283
|
export { Entity };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dwtechs/antity",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Open source library for easy entity management",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"entities"
|
|
@@ -35,7 +35,9 @@
|
|
|
35
35
|
"dist/"
|
|
36
36
|
],
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@dwtechs/checkard": "2.29.2"
|
|
38
|
+
"@dwtechs/checkard": "2.29.2",
|
|
39
|
+
"@dwtechs/winstan": "0.2.1",
|
|
40
|
+
"pg": "8.13.1"
|
|
39
41
|
},
|
|
40
42
|
"devDependencies": {
|
|
41
43
|
"@babel/core": "7.26.0",
|
|
@@ -43,6 +45,7 @@
|
|
|
43
45
|
"@rollup/plugin-commonjs": "28.0.1",
|
|
44
46
|
"@rollup/plugin-node-resolve": "15.3.0",
|
|
45
47
|
"@types/jest": "29.5.14",
|
|
48
|
+
"@types/node": "22.10.1",
|
|
46
49
|
"babel-jest": "29.7.0",
|
|
47
50
|
"core-js": "3.33.0",
|
|
48
51
|
"jest": "29.7.0",
|