@dwtechs/antity 0.5.0 → 0.6.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
@@ -57,7 +57,7 @@ const entity = new Entity("consumers", [
57
57
  min: 0,
58
58
  max: 120,
59
59
  typeCheck: true,
60
- operations: ["select", "update", "delete"],
60
+ operations: ["GET", "PUT", "DELETE"],
61
61
  required: true,
62
62
  safe: true,
63
63
  sanitize: true,
@@ -73,7 +73,7 @@ const entity = new Entity("consumers", [
73
73
  min: 0,
74
74
  max: 255,
75
75
  typeCheck: true,
76
- operations: ["select", "insert", "update", "delete"],
76
+ operations: ["GET", "POST", "PUT", "DELETE"],
77
77
  required: true,
78
78
  safe: true,
79
79
  sanitize: true,
@@ -89,7 +89,7 @@ const entity = new Entity("consumers", [
89
89
  min: 0,
90
90
  max: 255,
91
91
  typeCheck: true,
92
- operations: ["select", "insert", "update", "delete"],
92
+ operations: ["GET", "POST", "PUT", "DELETE"],
93
93
  required: true,
94
94
  safe: true,
95
95
  sanitize: true,
@@ -105,7 +105,7 @@ const entity = new Entity("consumers", [
105
105
  min: 0,
106
106
  max: 255,
107
107
  typeCheck: true,
108
- operations: ["select", "insert", "update", "delete"],
108
+ operations: ["GET", "POST", "PUT", "DELETE"],
109
109
  required: true,
110
110
  safe: true,
111
111
  sanitize: true,
@@ -118,7 +118,7 @@ const entity = new Entity("consumers", [
118
118
  ]);
119
119
 
120
120
  req.body = entity.normalize(req.body); // will also sanitize if true
121
- const check = entity.validate(req.body, "select");
121
+ const check = entity.validate(req.body, "GET");
122
122
  const unsafeProps = entity.getUnsafeProps();
123
123
 
124
124
  ```
@@ -129,35 +129,35 @@ const unsafeProps = entity.getUnsafeProps();
129
129
 
130
130
  ```javascript
131
131
 
132
- type Type = "boolean" |
133
- "string" |
134
- "number" |
135
- "integer" |
136
- "float" |
137
- "even" |
138
- "odd" |
139
- "positve" |
140
- "negative" |
141
- "powerOfTwo" |
142
- "ascii" |
143
- "array" |
144
- "jwt" |
145
- "symbol" |
146
- "email" |
147
- "regex" |
148
- "json" |
149
- "ipAddress" |
150
- "slug" |
151
- "hexadecimal" |
152
- "date" |
153
- "timestamp" |
154
- "function" |
155
- "htmlElement" |
156
- "htmlEventAttribute" |
157
- "node" |
158
- "object";
132
+ type Type =
133
+ "boolean" |
134
+ "string" |
135
+ "number" |
136
+ "integer" |
137
+ "float" |
138
+ "even" |
139
+ "odd" |
140
+ "positive" |
141
+ "negative" |
142
+ "powerOfTwo" |
143
+ "ascii" |
144
+ "array" |
145
+ "jwt" |
146
+ "symbol" |
147
+ "email" |
148
+ "regex" |
149
+ "json" |
150
+ "ipAddress" |
151
+ "slug" |
152
+ "hexadecimal" |
153
+ "date" |
154
+ "timestamp" |
155
+ "function" |
156
+ "htmlElement" |
157
+ "htmlEventAttribute" |
158
+ "node" |
159
+ "object";
159
160
 
160
- type Operation = "select" | "insert" | "update" | "merge" | "delete";
161
161
  type Method = "GET" | "PATCH" | "PUT" | "POST" | "DELETE";
162
162
 
163
163
  class Property {
@@ -168,7 +168,7 @@ class Property {
168
168
  required: boolean;
169
169
  safe: boolean;
170
170
  typeCheck: boolean;
171
- operations: Operation[];
171
+ methods: Method[];
172
172
  sanitize: boolean;
173
173
  normalize: boolean;
174
174
  control: boolean;
@@ -178,38 +178,55 @@ class Property {
178
178
  };
179
179
 
180
180
  class Entity {
181
- table: string;
182
- cols: Record<Operation, string[]>;
183
- properties: Property[];
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;
186
- getTable(): string;
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[];
181
+ constructor(name: string, properties: Property[]);
182
+ get name(): string;
183
+ get unsafeProps(): string[];
184
+ get properties(): Property[];
185
+ set name(name: string);
186
+
187
+ /**
188
+ * Retrieves a property from the `properties` array that matches the specified key.
189
+ *
190
+ * @param {string} key - The key of the property to retrieve.
191
+ * @returns {Property | undefined} - The property object if found, otherwise `undefined`.
192
+ */
193
+ getProp(key: string): Property | undefined;
194
+
195
+ /**
196
+ * Normalizes an array of records by applying sanitization and normalization
197
+ * 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
+ */
204
+ normalize(rows: Record<string, unknown>[]): Record<string, unknown>[];
205
+
206
+ /**
207
+ * Validates a set of rows against the defined properties and operation/method.
208
+ *
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
+ * If a property is required and missing, or if it fails the control checks, the function returns an error message.
216
+ * Otherwise, it returns `null` indicating successful validation.
217
+ */
218
+ validate(rows: Record<string, unknown>[], method: Method): string | null;
190
219
  }
191
220
 
192
221
  ```
193
222
 
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
223
  examples :
207
224
 
208
225
  ```javascript
209
226
 
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
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
213
230
 
214
231
  ```
215
232
 
package/dist/antity.d.ts CHANGED
@@ -25,9 +25,7 @@ https://github.com/DWTechs/Antity.js
25
25
  */
26
26
 
27
27
 
28
- type Operation = typeof Operations[number];
29
28
  type Method = typeof Methods[number];
30
-
31
29
  type Type =
32
30
  "boolean" |
33
31
  "string" |
@@ -57,11 +55,15 @@ type Type =
57
55
  "node" |
58
56
  "object";
59
57
 
60
- declare const Operations: readonly [ "select", "insert", "update", "merge", "delete" ];
61
58
  declare const Methods: readonly [ "GET", "PATCH", "PUT", "POST", "DELETE" ];
62
59
 
63
60
  declare const Types: Record<Type, {
64
- validate: (v: any, min: number | Date, max: number | Date, typeCheck: boolean) => boolean;
61
+ validate: (
62
+ v: any,
63
+ min: number | Date,
64
+ max: number | Date,
65
+ typeCheck: boolean
66
+ ) => boolean;
65
67
  }>;
66
68
 
67
69
  declare const Required: {
@@ -69,24 +71,22 @@ declare const Required: {
69
71
  };
70
72
 
71
73
  declare class Entity {
72
- table: string;
73
- cols: Record<Operation, string[]>;
74
- properties: Property[];
75
- constructor(table: string, properties: Property[]);
76
- getTable(): string;
77
- getCols(operation: Operation, stringify?: boolean, pagination?: boolean): string[] | string;
78
- getUnsafeProps(): string[];
79
- normalize(rows: Record<string, any>[]): Record<string, any>[];
80
- validate(rows: Record<string, any>[], operation: Operation | Method): string | null;
81
- private require;
82
- private control;
83
- private sanitize;
84
- private trim;
74
+ private _name;
75
+ private _unsafeProps;
76
+ private _properties;
77
+ constructor(name: string, properties: Property[]);
78
+ get name(): string;
79
+ get unsafeProps(): string[];
80
+ get properties(): Property[];
81
+ set name(name: string);
82
+ getProp(key: string): Property | undefined;
83
+ normalize(rows: Record<string, unknown>[]): Record<string, unknown>[];
84
+ validate(rows: Record<string, unknown>[], method: Method): string | null;
85
85
  }
86
86
 
87
87
  declare const Messages: {
88
- missing: (key: string) => string;
89
- invalid: (key: string, type: Type) => string;
88
+ missing: (key: string) => string;
89
+ invalid: (key: string, type: Type) => string;
90
90
  };
91
91
 
92
92
  declare class Property {
@@ -97,21 +97,22 @@ declare class Property {
97
97
  required: boolean;
98
98
  safe: boolean;
99
99
  typeCheck: boolean;
100
- operations: Operation[];
100
+ methods: Method[];
101
101
  sanitize: boolean;
102
102
  normalize: boolean;
103
103
  control: boolean;
104
104
  sanitizer: ((v: any) => any) | null;
105
105
  normalizer: ((v: any) => any) | null;
106
106
  controller: ((v: any) => any) | null;
107
- constructor(key: string,
107
+ constructor(
108
+ key: string,
108
109
  type: Type,
109
110
  min: number | Date,
110
111
  max: number | Date,
111
112
  required: boolean,
112
113
  safe: boolean,
113
114
  typeCheck: boolean,
114
- operations: Operation[],
115
+ methods: Method[],
115
116
  sanitize: boolean,
116
117
  normalize: boolean,
117
118
  control: boolean,
@@ -121,13 +122,13 @@ declare class Property {
121
122
  );
122
123
  }
123
124
 
124
- export type { Type, Operation, Method };
125
+ export type { Type, Method };
125
126
  export {
126
127
  Entity,
127
128
  Property,
128
129
  Messages,
129
130
  Types,
130
131
  Required,
131
- Operations
132
+ Methods,
132
133
  };
133
134
 
package/dist/antity.js CHANGED
@@ -24,10 +24,10 @@ 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, isDate, 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, isString, isProperty, isArray, isIn, isDate, isNumber, isInteger, isNil } from '@dwtechs/checkard';
28
28
  import { log } from '@dwtechs/winstan';
29
29
 
30
- const Operations = ["select", "insert", "update", "merge", "delete"];
30
+ const Methods = ["GET", "PATCH", "PUT", "POST", "DELETE"];
31
31
 
32
32
  const Types = {
33
33
  boolean: {
@@ -112,20 +112,17 @@ const Types = {
112
112
  validate: (v, _min, _max, _typeCheck) => isObject(v)
113
113
  }
114
114
  };
115
- const Required = {
116
- validate: (v) => !isNil(v)
117
- };
118
115
 
119
116
  class Property {
120
- constructor(key, type, min, max, required, safe, typeCheck, operations, sanitize, normalize, control, sanitizer, normalizer, controller) {
121
- if (!isString(key, true))
122
- throw new Error(`Property"key" must be a string. Received ${key}`);
123
- if (!isProperty(type, Types))
117
+ constructor(key, type, min, max, required, safe, typeCheck, methods, sanitize, normalize, control, sanitizer, normalizer, controller) {
118
+ if (!isString(key, "!0"))
119
+ throw new Error(`Property "key" must be a string. Received ${key}`);
120
+ if (!isProperty(Types, type))
124
121
  throw new Error(`Property "type" must be a valid type. Received ${type}`);
125
- if (isArray(operations)) {
126
- for (const o of operations) {
127
- if (!isIn(o, Operations))
128
- throw new Error(`Property "operations" must be an array of SQL operations. Received ${o}`);
122
+ if (isArray(methods)) {
123
+ for (const m of methods) {
124
+ if (!isIn(Methods, m))
125
+ throw new Error(`Property "methods" must be an array of REST methods. Received ${m}`);
129
126
  }
130
127
  }
131
128
  this.key = key;
@@ -135,7 +132,7 @@ class Property {
135
132
  this.required = isBoolean(required) ? required : false;
136
133
  this.safe = isBoolean(safe) ? safe : true;
137
134
  this.typeCheck = isBoolean(typeCheck) ? typeCheck : false;
138
- this.operations = operations || Operations;
135
+ this.methods = methods || Methods;
139
136
  this.sanitize = isBoolean(sanitize) ? sanitize : true;
140
137
  this.normalize = isBoolean(normalize) ? normalize : false;
141
138
  this.control = isBoolean(control) ? control : true;
@@ -146,7 +143,7 @@ class Property {
146
143
  interval(val, type, integerDefault, dateDefault) {
147
144
  if (type === "date")
148
145
  return isDate(val) ? val : new Date(dateDefault);
149
- return isInteger(val, true) ? val : integerDefault;
146
+ return (isNumber(val, true) && isInteger(val, true)) ? val : integerDefault;
150
147
  }
151
148
  }
152
149
 
@@ -155,42 +152,34 @@ const Messages = {
155
152
  invalid: (key, type) => `Invalid ${key}, must be of type ${type}`,
156
153
  };
157
154
 
158
- const Methods = ["GET", "PATCH", "PUT", "POST", "DELETE"];
159
-
160
155
  class Entity {
161
- constructor(table, properties) {
162
- this.table = table;
163
- this.properties = [];
164
- this.cols = {
165
- select: [],
166
- insert: [],
167
- update: [],
168
- merge: [],
169
- delete: []
170
- };
171
- this.unsafeProps = [];
156
+ constructor(name, properties) {
157
+ this._name = name;
158
+ this._properties = [];
159
+ this._unsafeProps = [];
172
160
  for (const p of properties) {
173
- 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);
174
- this.properties.push(prop);
175
- for (const o of p.operations) {
176
- if (o === "update")
177
- this.cols[o].push(`${p.key} = $${this.cols[o].length + 1}`);
178
- else
179
- this.cols[o].push(p.key);
180
- }
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);
162
+ this._properties.push(prop);
181
163
  if (!prop.safe)
182
- this.unsafeProps.push(prop.key);
164
+ this._unsafeProps.push(prop.key);
183
165
  }
184
166
  }
185
- getTable() {
186
- return this.table;
167
+ get name() {
168
+ return this._name;
169
+ }
170
+ get unsafeProps() {
171
+ return this._unsafeProps;
187
172
  }
188
- getCols(operation, stringify, pagination) {
189
- const cols = pagination && operation === "select" ? [...this.cols[operation], "COUNT(*) OVER () AS total"] : this.cols[operation];
190
- return stringify ? cols.join(', ') : cols;
173
+ get properties() {
174
+ return this._properties;
191
175
  }
192
- getUnsafeProps() {
193
- return this.unsafeProps;
176
+ set name(name) {
177
+ if (!isString(name, "!0"))
178
+ throw new Error('name must be a string of length > 0');
179
+ this._name = name;
180
+ }
181
+ getProp(key) {
182
+ return this.properties.find(p => p.key === key);
194
183
  }
195
184
  normalize(rows) {
196
185
  for (const r of rows) {
@@ -211,13 +200,13 @@ class Entity {
211
200
  }
212
201
  return rows;
213
202
  }
214
- validate(rows, operation) {
215
- if (isIn(operation, Methods))
216
- operation = this.mapMethods(operation);
203
+ validate(rows, method) {
204
+ if (!isIn(Methods, method))
205
+ return `Invalid REST method. Received: ${method}. Must be one of: ${Methods.toString()}`;
217
206
  for (const r of rows) {
218
- for (const { key, type, min, max, required, typeCheck, operations, control, controller } of this.properties) {
207
+ for (const { key, type, min, max, required, typeCheck, methods, control, controller } of this.properties) {
219
208
  const v = r[key];
220
- if (isIn(operation, operations)) {
209
+ if (isIn(methods, method)) {
221
210
  if (required) {
222
211
  const rq = this.require(v, key, type);
223
212
  if (rq)
@@ -235,13 +224,14 @@ class Entity {
235
224
  }
236
225
  require(v, key, type) {
237
226
  log.debug(`require ${key}: ${type} = ${v}`);
238
- return Required.validate(v) ? null : Messages.missing(key);
227
+ return isNil(v) ? Messages.missing(key) : null;
239
228
  }
240
229
  control(v, key, type, min, max, typeCheck, cb) {
241
230
  log.debug(`control ${key}: ${type} = ${v}`);
242
231
  if (cb)
243
232
  return cb(v) ? null : Messages.invalid(key, type);
244
- return Types[type].validate(v, min, max, typeCheck) ? null : Messages.invalid(key, type);
233
+ const val = Types[type].validate(v, min, max, typeCheck);
234
+ return val ? null : Messages.invalid(key, type);
245
235
  }
246
236
  sanitize(v, cb) {
247
237
  if (cb)
@@ -255,33 +245,18 @@ class Entity {
255
245
  return this.trim(v);
256
246
  }
257
247
  trim(v) {
258
- if (isString(v, true))
248
+ if (isString(v, "!0"))
259
249
  return v.trim();
260
250
  if (isObject(v, true)) {
261
- if (v.has)
262
- for (const p in v) {
263
- if (v.prototype.hasOwnProperty.call(p)) {
264
- let o = v[p];
265
- if (isString(o, true))
266
- o = o.trim();
267
- }
251
+ for (const k in v) {
252
+ if (Object.prototype.hasOwnProperty.call(v, k)) {
253
+ let o = v[k];
254
+ if (isString(o, "!0", null))
255
+ o = o.trim();
268
256
  }
269
- return v;
270
- }
271
- }
272
- mapMethods(method) {
273
- switch (method) {
274
- case "GET":
275
- return Operations[0];
276
- case "PATCH":
277
- return Operations[2];
278
- case "PUT":
279
- return Operations[2];
280
- case "POST":
281
- return Operations[1];
282
- case "DELETE":
283
- return Operations[4];
257
+ }
284
258
  }
259
+ return v;
285
260
  }
286
261
  }
287
262
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dwtechs/antity",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "Open source library for easy entity management",
5
5
  "keywords": [
6
6
  "entities"
@@ -25,6 +25,7 @@
25
25
  "contributors": [],
26
26
  "scripts": {
27
27
  "start": "",
28
+ "prebuild": "npm install",
28
29
  "build": "node ./scripts/clear && tsc && npm run rollup && node ./scripts/copy && npm run test",
29
30
  "rollup:mjs": "rollup --config rollup.config.mjs",
30
31
  "rollup:cjs": "rollup --config rollup.config.cjs.mjs",
@@ -35,8 +36,9 @@
35
36
  "dist/"
36
37
  ],
37
38
  "dependencies": {
38
- "@dwtechs/checkard": "2.29.2",
39
- "@dwtechs/winstan": "0.3.0",
39
+ "@dwtechs/checkard": "3.2.3",
40
+ "@dwtechs/winstan": "0.4.0",
41
+ "@dwtechs/sparray": "0.1.1",
40
42
  "pg": "8.13.1"
41
43
  },
42
44
  "devDependencies": {