pols-validator 1.0.1 → 1.1.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/dist/index.d.ts CHANGED
@@ -1,15 +1,6 @@
1
1
  import { Rules } from "./rules";
2
- import { RulesEngine, RulesParams } from "./rulesEngine";
2
+ import { RulesParams } from "./rulesEngine";
3
3
  export { RulesEngine } from './rulesEngine';
4
- export type EvaluateResponse<T> = {
5
- error: false;
6
- success: true;
7
- result: T;
8
- } | {
9
- error: true;
10
- success: false;
11
- messages: string[];
12
- };
13
- export declare const validate: <T>(target: unknown, rules: RulesEngine) => EvaluateResponse<T>;
4
+ export { EvaluateResponse, validate } from './validate';
14
5
  export declare const rules: (params?: RulesParams) => Rules;
15
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAC/B,OAAO,EAAE,WAAW,EAAE,WAAW,EAAW,MAAM,eAAe,CAAA;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAE3C,MAAM,MAAM,gBAAgB,CAAC,CAAC,IAAI;IACjC,KAAK,EAAE,KAAK,CAAA;IACZ,OAAO,EAAE,IAAI,CAAA;IACb,MAAM,EAAE,CAAC,CAAA;CACT,GAAG;IACH,KAAK,EAAE,IAAI,CAAA;IACX,OAAO,EAAE,KAAK,CAAA;IACd,QAAQ,EAAE,MAAM,EAAE,CAAA;CAClB,CAAA;AAED,eAAO,MAAM,QAAQ,GAAI,CAAC,UAAU,OAAO,SAAS,WAAW,KAAG,gBAAgB,CAAC,CAAC,CAqEnF,CAAA;AAED,eAAO,MAAM,KAAK,YAAa,WAAW,UAAsB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAC/B,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAE3C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAE3C,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAEvD,eAAO,MAAM,KAAK,YAAa,WAAW,UAAsB,CAAA"}
package/dist/index.js CHANGED
@@ -1,77 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.rules = exports.validate = exports.RulesEngine = void 0;
4
- const pols_utils_1 = require("pols-utils");
5
4
  const rules_1 = require("./rules");
6
5
  var rulesEngine_1 = require("./rulesEngine");
7
6
  Object.defineProperty(exports, "RulesEngine", { enumerable: true, get: function () { return rulesEngine_1.RulesEngine; } });
8
- const validate = (target, rules) => {
9
- const errorMessages = [];
10
- if (typeof target == 'string')
11
- target = target.trim();
12
- const isEmpty = target == null || (typeof target == 'string' && !target);
13
- const label = rules.label ?? 'Este valor';
14
- if (rules.required && isEmpty) {
15
- return {
16
- error: true,
17
- success: false,
18
- messages: [`'${label}' es requerido`]
19
- };
20
- }
21
- if (isEmpty) {
22
- return {
23
- error: false,
24
- success: true,
25
- result: rules.default
26
- };
27
- }
28
- const wrapper = {
29
- value: pols_utils_1.PUtils.clone(target),
30
- label
31
- };
32
- for (const validationFunction of Object.values(rules.collection)) {
33
- const result = validationFunction(wrapper);
34
- if (!result)
35
- continue;
36
- if (typeof result == 'string') {
37
- errorMessages.push(result);
38
- break;
39
- }
40
- else {
41
- if (wrapper.value == null || typeof wrapper.value != 'object')
42
- throw new Error(`El valor no es un objeto para ser validado contra un esquema: ${wrapper.value}`);
43
- const newResult = {};
44
- for (const key in result.schema) {
45
- const rulesInside = result.schema[key];
46
- const labelIndise = rulesInside.label ?? key;
47
- rulesInside.label = `${result.prefix ? `${result.prefix} ` : ''}${labelIndise}`;
48
- newResult[key] = wrapper.value[key];
49
- const result2 = (0, exports.validate)(newResult[key], rulesInside);
50
- if (result2.error == true) {
51
- errorMessages.push(...result2.messages);
52
- }
53
- else {
54
- newResult[key] = result2.result;
55
- }
56
- }
57
- wrapper.value = newResult;
58
- }
59
- }
60
- if (errorMessages.length) {
61
- return {
62
- error: true,
63
- success: false,
64
- messages: errorMessages
65
- };
66
- }
67
- else {
68
- return {
69
- error: false,
70
- success: true,
71
- result: wrapper.value
72
- };
73
- }
74
- };
75
- exports.validate = validate;
7
+ var validate_1 = require("./validate");
8
+ Object.defineProperty(exports, "validate", { enumerable: true, get: function () { return validate_1.validate; } });
76
9
  const rules = (params) => new rules_1.Rules(params);
77
10
  exports.rules = rules;
package/dist/rules.d.ts CHANGED
@@ -13,10 +13,13 @@ export declare class Rules extends RulesEngine {
13
13
  onlyNumbers(): this;
14
14
  maxLength(limit: number): this;
15
15
  minLength(limit: number): this;
16
- length(limit: number): this;
16
+ hasFixedLength(limit: number): this;
17
17
  left(limit: number): this;
18
+ isArray(): this;
19
+ isArrayOfObjects(schema?: (index: number) => Record<string, RulesEngine>, prefix?: (index: number) => string): this;
18
20
  isIn(...elements: unknown[]): this;
19
21
  isNotIn(...elements: unknown[]): this;
22
+ hasElements(): this;
20
23
  gt(limit: number): this;
21
24
  gte(limit: number): this;
22
25
  lt(limit: number): this;
@@ -1 +1 @@
1
- {"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../src/rules.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAW,MAAM,eAAe,CAAA;AAEpD,qBAAa,KAAM,SAAQ,WAAW;IACrC,cAAc;IAWd,cAAc;IAQd,UAAU;IAcV,MAAM;IAMN,MAAM;IA4BN,KAAK,CAAC,OAAO,EAAE,MAAM;IAQrB,QAAQ;IAUR,SAAS;IAQT,SAAS;IAIT,eAAe;IAIf,WAAW;IAQX,SAAS,CAAC,KAAK,EAAE,MAAM;IAgBvB,SAAS,CAAC,KAAK,EAAE,MAAM;IAQvB,MAAM,CAAC,KAAK,EAAE,MAAM;IAQpB,IAAI,CAAC,KAAK,EAAE,MAAM;IA0ElB,IAAI,CAAC,GAAG,QAAQ,EAAE,OAAO,EAAE;IAa3B,OAAO,CAAC,GAAG,QAAQ,EAAE,OAAO,EAAE;IAe9B,EAAE,CAAC,KAAK,EAAE,MAAM;IAQhB,GAAG,CAAC,KAAK,EAAE,MAAM;IAQjB,EAAE,CAAC,KAAK,EAAE,MAAM;IAQhB,GAAG,CAAC,KAAK,EAAE,MAAM;IAQjB,iBAAiB;IASjB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,CAAC,EAAE,MAAM;IAqB9D,SAAS;IAgDT,KAAK;IAQL,KAAK;IAQL,SAAS;IAQT,KAAK,CAAC,QAAQ,EAAE,MAAM;IAStB,iBAAiB;IAQjB,QAAQ;IASR,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,CAAC,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,MAAM,CAAC;IAMlG,UAAU;IAQV,KAAK,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;CAKhC"}
1
+ {"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../src/rules.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAW,MAAM,eAAe,CAAA;AA2CpD,qBAAa,KAAM,SAAQ,WAAW;IACrC,cAAc;IAWd,cAAc;IAQd,UAAU;IAcV,MAAM;IAMN,MAAM;IA4BN,KAAK,CAAC,OAAO,EAAE,MAAM;IAQrB,QAAQ;IAUR,SAAS;IAQT,SAAS;IAIT,eAAe;IAIf,WAAW;IAQX,SAAS,CAAC,KAAK,EAAE,MAAM;IAYvB,SAAS,CAAC,KAAK,EAAE,MAAM;IAYvB,cAAc,CAAC,KAAK,EAAE,MAAM;IAY5B,IAAI,CAAC,KAAK,EAAE,MAAM;IAMlB,OAAO;IAiBP,gBAAgB,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM;IAoB5G,IAAI,CAAC,GAAG,QAAQ,EAAE,OAAO,EAAE;IAa3B,OAAO,CAAC,GAAG,QAAQ,EAAE,OAAO,EAAE;IAO9B,WAAW;IAMX,EAAE,CAAC,KAAK,EAAE,MAAM;IAMhB,GAAG,CAAC,KAAK,EAAE,MAAM;IAMjB,EAAE,CAAC,KAAK,EAAE,MAAM;IAMhB,GAAG,CAAC,KAAK,EAAE,MAAM;IAMjB,iBAAiB;IAOjB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,CAAC,EAAE,MAAM;IAM9D,SAAS;IA+CT,KAAK;IAQL,KAAK;IAQL,SAAS;IAQT,KAAK,CAAC,QAAQ,EAAE,MAAM;IAStB,iBAAiB;IAQjB,QAAQ;IASR,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,CAAC,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,MAAM,CAAC;IAMlG,UAAU;IAQV,KAAK,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;CAKhC"}
package/dist/rules.js CHANGED
@@ -3,6 +3,47 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Rules = void 0;
4
4
  const pols_utils_1 = require("pols-utils");
5
5
  const rulesEngine_1 = require("./rulesEngine");
6
+ const validate_1 = require("./validate");
7
+ const isObject = (wrapper, schema, prefix) => {
8
+ const message = `'${wrapper.label}' debe ser un objeto`;
9
+ if (typeof wrapper.value == 'string') {
10
+ try {
11
+ wrapper.value = JSON.parse(wrapper.value);
12
+ }
13
+ catch {
14
+ return message;
15
+ }
16
+ if (pols_utils_1.PUtils.getType(wrapper.value) != 'Object')
17
+ return message;
18
+ }
19
+ else {
20
+ if (pols_utils_1.PUtils.getType(wrapper.value) != 'Object') {
21
+ return message;
22
+ }
23
+ }
24
+ /* Realiza la validación de cada propiedad */
25
+ const newWrapperValue = {};
26
+ const errorMessages = [];
27
+ for (const key in schema) {
28
+ const rulesInside = schema[key];
29
+ const labelIndise = rulesInside.label ?? key;
30
+ rulesInside.label = `${prefix ?? ''}${labelIndise}`;
31
+ newWrapperValue[key] = wrapper.value[key];
32
+ const result2 = (0, validate_1.validate)(newWrapperValue[key], rulesInside);
33
+ if (result2.error == true) {
34
+ errorMessages.push(...result2.messages);
35
+ }
36
+ else {
37
+ newWrapperValue[key] = result2.result;
38
+ }
39
+ }
40
+ if (errorMessages.length) {
41
+ return errorMessages;
42
+ }
43
+ else {
44
+ wrapper.value = newWrapperValue;
45
+ }
46
+ };
6
47
  class Rules extends rulesEngine_1.RulesEngine {
7
48
  isAlphanumeric() {
8
49
  this.add(this.isAlphanumeric.name, (wrapper) => {
@@ -114,107 +155,90 @@ class Rules extends rulesEngine_1.RulesEngine {
114
155
  return this;
115
156
  }
116
157
  maxLength(limit) {
117
- this.isAlphanumeric();
118
- this.add(this.maxLength.name, (wrapper) => {
119
- if (wrapper.value.length > limit)
120
- return `'${wrapper.label}' debe contener '${limit} ${limit == 1 ? 'caracter' : 'caracteres'}' como máximo`;
158
+ return this.add(this.maxLength.name, (wrapper) => {
159
+ if (wrapper.value instanceof Array) {
160
+ return wrapper.value.length > limit ? `'${wrapper.label}' debe contener '${limit} ${limit == 1 ? 'elementos' : 'elementos'}' como máximo` : null;
161
+ }
162
+ else if (typeof wrapper.value == 'string') {
163
+ return wrapper.value.length > limit ? `'${wrapper.label}' debe contener '${limit} ${limit == 1 ? 'caracter' : 'caracteres'}' como máximo` : null;
164
+ }
165
+ else {
166
+ return `'${wrapper.label}' no es de un tipo válido`;
167
+ }
121
168
  });
122
- return this;
123
169
  }
124
- // maxCount(limit: number) {
125
- // this.isArray()
126
- // this.add(this.maxLength.name, (wrapper: Wrapper<unknown[]>) => {
127
- // if (wrapper.value.length > limit) return `'${wrapper.label}' debe contener '${limit} ${limit == 1 ? 'elemento' : 'elementos'}' como máximo`
128
- // })
129
- // return this
130
- // }
131
170
  minLength(limit) {
132
- this.isAlphanumeric();
133
- this.add(this.minLength.name, (wrapper) => {
134
- if (wrapper.value.length < limit)
135
- return `'${wrapper.label}' debe contener '${limit} ${limit == 1 ? 'caracter' : 'caracteres'}' como mínimo`;
171
+ return this.add(this.minLength.name, (wrapper) => {
172
+ if (wrapper.value instanceof Array) {
173
+ return wrapper.value.length < limit ? `'${wrapper.label}' debe contener '${limit} ${limit == 1 ? 'elementos' : 'elementos'}' como mínimo` : null;
174
+ }
175
+ else if (typeof wrapper.value == 'string') {
176
+ return wrapper.value.length < limit ? `'${wrapper.label}' debe contener '${limit} ${limit == 1 ? 'caracter' : 'caracteres'}' como mínimo` : null;
177
+ }
178
+ else {
179
+ return `'${wrapper.label}' no es de un tipo válido`;
180
+ }
136
181
  });
137
- return this;
138
182
  }
139
- length(limit) {
140
- this.isAlphanumeric();
141
- this.add(this.length.name, (wrapper) => {
142
- if (wrapper.value.length != limit)
143
- return `'${wrapper.label}' debe contener sólo '${limit} ${limit == 1 ? 'caracter' : 'caracteres'}'`;
183
+ hasFixedLength(limit) {
184
+ return this.add(this.hasFixedLength.name, (wrapper) => {
185
+ if (wrapper.value instanceof Array) {
186
+ return wrapper.value.length < limit ? `'${wrapper.label}' debe contener sólo '${limit} ${limit == 1 ? 'elementos' : 'elementos'}'` : null;
187
+ }
188
+ else if (typeof wrapper.value == 'string') {
189
+ return wrapper.value.length < limit ? `'${wrapper.label}' debe contener sólo '${limit} ${limit == 1 ? 'caracter' : 'caracteres'}'` : null;
190
+ }
191
+ else {
192
+ return `'${wrapper.label}' no es de un tipo válido`;
193
+ }
144
194
  });
145
- return this;
146
195
  }
147
196
  left(limit) {
148
- this.isAlphanumeric();
149
- this.add(this.length.name, (wrapper) => {
197
+ return this.isAlphanumeric().add(this.left.name, (wrapper) => {
150
198
  wrapper.value = wrapper.value.substring(0, limit);
151
199
  });
152
- return this;
153
200
  }
154
- // isArray(checkingElements?: (i: number) => RulesEngine) {
155
- // this.add(this.isArray.name, (wrapper: Wrapper) => {
156
- // const message = `'${wrapper.label}' debe ser una lista de elementos`
157
- // if (typeof wrapper.value == 'string') {
158
- // try {
159
- // const value = JSON.parse(wrapper.value)
160
- // if (!(value instanceof Array)) return message
161
- // wrapper.value = value
162
- // } catch (err) {
163
- // return message
164
- // }
165
- // } else {
166
- // if (!(wrapper.value instanceof Array)) return message
167
- // }
168
- // if (checkingElements) {
169
- // const value = wrapper.value as unknown[]
170
- // const messageErrors: string[] = []
171
- // const result: unknown[] = []
172
- // for (const [i, t] of value.entries()) {
173
- // const p = wrapper.validator({
174
- // value: t
175
- // }, {
176
- // value: {
177
- // ...checkingElements(i),
178
- // to: undefined,
179
- // }
180
- // })
181
- // if (p.error == true) {
182
- // messageErrors.push(...p.messages)
183
- // } else {
184
- // result.push(p.result['value'])
185
- // }
186
- // }
187
- // if (messageErrors.length) {
188
- // return messageErrors
189
- // } else {
190
- // wrapper.value = result
191
- // }
192
- // }
193
- // })
194
- // return this
195
- // }
196
- // isArrayOfObjects(checkingElements?: (i: number) => FieldsStructure, prefixString?: (i: number) => string) {
197
- // this.isArray()
198
- // this.add(this.isArrayOfObjects.name, (wrapper: Wrapper<unknown[]>) => {
199
- // const message = `'${wrapper.label}' debe ser una lista de objetos`
200
- // const messages: string[] = []
201
- // for (const [i, v] of wrapper.value.entries()) {
202
- // const result = isObject(v)
203
- // if (result.error == true) return message
204
- // wrapper.value[i] = result.result
205
- // if (checkingElements) {
206
- // const v = wrapper.validator(wrapper.value[i], checkingElements(i), prefixString?.(i))
207
- // if (v.error == true) {
208
- // messages.push(...v.messages)
209
- // } else {
210
- // wrapper.value[i] = v.result
211
- // }
212
- // }
213
- // }
214
- // if (messages.length) return messages
215
- // })
216
- // return this
217
- // }
201
+ isArray() {
202
+ return this.add(this.isArray.name, (wrapper) => {
203
+ const message = `'${wrapper.label}' debe ser una lista de elementos`;
204
+ if (typeof wrapper.value == 'string') {
205
+ try {
206
+ const value = JSON.parse(wrapper.value);
207
+ if (!(value instanceof Array))
208
+ return message;
209
+ wrapper.value = value;
210
+ }
211
+ catch (err) {
212
+ return message;
213
+ }
214
+ }
215
+ else {
216
+ if (!(wrapper.value instanceof Array))
217
+ return message;
218
+ }
219
+ });
220
+ }
221
+ isArrayOfObjects(schema, prefix) {
222
+ return this.isArray().add(this.isArrayOfObjects.name, (wrapper) => {
223
+ const messages = [];
224
+ for (const [i, value] of wrapper.value.entries()) {
225
+ const v = isObject({
226
+ label: prefix?.(i) ?? `Item ${i}`,
227
+ value
228
+ }, schema?.(i));
229
+ if (v) {
230
+ if (v instanceof Array) {
231
+ messages.push(...v);
232
+ }
233
+ else {
234
+ messages.push(v);
235
+ }
236
+ }
237
+ }
238
+ if (messages.length)
239
+ return messages;
240
+ });
241
+ }
218
242
  isIn(...elements) {
219
243
  this.add(this.isIn.name, (wrapper) => {
220
244
  if (wrapper.value instanceof Array) {
@@ -237,49 +261,38 @@ class Rules extends rulesEngine_1.RulesEngine {
237
261
  });
238
262
  return this;
239
263
  }
240
- // hasElements(checkingElements?: (i: number) => FieldStructure) {
241
- // this.isArray(checkingElements)
242
- // this.add(this.hasElements.name, (wrapper: Wrapper) => {
243
- // if (!(wrapper.value as unknown[]).length) return `'${wrapper.label}' debe ser una lista con al menos un elemento`
244
- // })
245
- // return this
246
- // }
264
+ hasElements() {
265
+ return this.isArray().add(this.hasElements.name, (wrapper) => {
266
+ if (!wrapper.value.length)
267
+ return `'${wrapper.label}' debe contenedor al menos un elemento`;
268
+ });
269
+ }
247
270
  gt(limit) {
248
- this.isNumber();
249
- this.add(this.gt.name, (wrapper) => {
271
+ return this.isNumber().add(this.gt.name, (wrapper) => {
250
272
  if (wrapper.value <= limit)
251
273
  return `'${wrapper.label}' debe ser mayor a '${limit}'`;
252
274
  });
253
- return this;
254
275
  }
255
276
  gte(limit) {
256
- this.isNumber();
257
- this.add(this.gte.name, (wrapper) => {
277
+ return this.isNumber().add(this.gte.name, (wrapper) => {
258
278
  if (wrapper.value < limit)
259
279
  return `'${wrapper.label}' debe ser mayor o igual a '${limit}'`;
260
280
  });
261
- return this;
262
281
  }
263
282
  lt(limit) {
264
- this.isNumber();
265
- this.add(this.lt.name, (wrapper) => {
283
+ return this.isNumber().add(this.lt.name, (wrapper) => {
266
284
  if (wrapper.value >= limit)
267
285
  return `'${wrapper.label}' debe ser menor a '${limit}'`;
268
286
  });
269
- return this;
270
287
  }
271
288
  lte(limit) {
272
- return this
273
- .isNumber()
274
- .add(this.lte.name, (wrapper) => {
289
+ return this.isNumber().add(this.lte.name, (wrapper) => {
275
290
  if (wrapper.value > limit)
276
291
  return `'${wrapper.label}' debe ser menor o igual a '${limit}'`;
277
292
  });
278
293
  }
279
294
  beforeOrSameAsNow() {
280
- return this
281
- .isDateTime()
282
- .add(this.beforeOrSameAsNow.name, (wrapper) => {
295
+ return this.isDateTime().add(this.beforeOrSameAsNow.name, (wrapper) => {
283
296
  const now = new pols_utils_1.PDate;
284
297
  if (wrapper.value.time > now.time)
285
298
  return `'${wrapper.label}' debe ser anterior o igual a 'ahora'`;
@@ -287,27 +300,11 @@ class Rules extends rulesEngine_1.RulesEngine {
287
300
  }
288
301
  isObject(schema, prefix) {
289
302
  return this.add(this.isObject.name, (wrapper) => {
290
- const message = `'${wrapper.label}' debe ser un objeto`;
291
- if (typeof wrapper.value == 'string') {
292
- try {
293
- wrapper.value = JSON.parse(wrapper.value);
294
- }
295
- catch {
296
- return message;
297
- }
298
- if (pols_utils_1.PUtils.getType(wrapper.value) != 'Object')
299
- return message;
300
- }
301
- else {
302
- if (pols_utils_1.PUtils.getType(wrapper.value) != 'Object') {
303
- return message;
304
- }
305
- }
306
- return { schema, prefix };
303
+ return isObject(wrapper, schema, prefix);
307
304
  });
308
305
  }
309
306
  isBoolean() {
310
- this.add(this.isBoolean.name, (wrapper) => {
307
+ return this.add(this.isBoolean.name, (wrapper) => {
311
308
  const message = `'${wrapper.label}' debe ser de tipo booleano`;
312
309
  if (typeof wrapper.value == 'string') {
313
310
  const value = wrapper.value.trim().toUpperCase();
@@ -355,7 +352,6 @@ class Rules extends rulesEngine_1.RulesEngine {
355
352
  return typeof wrapper.value == 'boolean' ? null : message;
356
353
  }
357
354
  });
358
- return this;
359
355
  }
360
356
  upper() {
361
357
  this.isAlphanumeric();
@@ -5,10 +5,7 @@ export type RulesParams = {
5
5
  } | {
6
6
  default?: unknown;
7
7
  });
8
- export type ValidationFunction = (wrapper: Wrapper, ...args: unknown[]) => string | void | null | undefined | {
9
- schema: Record<string, RulesEngine>;
10
- prefix?: string;
11
- };
8
+ export type ValidationFunction = (wrapper: Wrapper, ...args: unknown[]) => string | string[] | void | null | undefined;
12
9
  export type Wrapper<T = unknown> = {
13
10
  value: T;
14
11
  label: string;
@@ -18,7 +15,7 @@ export declare class RulesEngine {
18
15
  label: string;
19
16
  required: boolean;
20
17
  default: unknown;
21
- collection: Record<string, ValidationFunction>;
22
- protected add(name: string, validationFunction: ValidationFunction): this;
18
+ collection: ValidationFunction[];
19
+ protected add(name: string, validationFunction: ValidationFunction, executeOnce?: boolean): this;
23
20
  }
24
21
  //# sourceMappingURL=rulesEngine.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"rulesEngine.d.ts","sourceRoot":"","sources":["../src/rulesEngine.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,WAAW,GAAG;IACzB,KAAK,CAAC,EAAE,MAAM,CAAA;CACd,GAAG,CAAC;IACJ,QAAQ,CAAC,EAAE,OAAO,CAAA;CAClB,GAAG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;CACjB,CAAC,CAAA;AAEF,MAAM,MAAM,kBAAkB,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,MAAM,GAAG,IAAI,GAAG,IAAI,GAAG,SAAS,GAAG;IAC7G,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAA;IACnC,MAAM,CAAC,EAAE,MAAM,CAAA;CACf,CAAA;AAED,MAAM,MAAM,OAAO,CAAC,CAAC,GAAG,OAAO,IAAI;IAClC,KAAK,EAAE,CAAC,CAAA;IACR,KAAK,EAAE,MAAM,CAAA;CACb,CAAA;AAED,qBAAa,WAAW;gBACX,MAAM,CAAC,EAAE,WAAW;IAOhC,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,OAAO,CAAQ;IACzB,OAAO,EAAE,OAAO,CAAO;IACvB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAK;IAEnD,SAAS,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,kBAAkB,EAAE,kBAAkB;CAIlE"}
1
+ {"version":3,"file":"rulesEngine.d.ts","sourceRoot":"","sources":["../src/rulesEngine.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,WAAW,GAAG;IACzB,KAAK,CAAC,EAAE,MAAM,CAAA;CACd,GAAG,CAAC;IACJ,QAAQ,CAAC,EAAE,OAAO,CAAA;CAClB,GAAG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;CACjB,CAAC,CAAA;AAEF,MAAM,MAAM,kBAAkB,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,GAAG,IAAI,GAAG,SAAS,CAAA;AAEtH,MAAM,MAAM,OAAO,CAAC,CAAC,GAAG,OAAO,IAAI;IAClC,KAAK,EAAE,CAAC,CAAA;IACR,KAAK,EAAE,MAAM,CAAA;CACb,CAAA;AAED,qBAAa,WAAW;gBACX,MAAM,CAAC,EAAE,WAAW;IAOhC,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,OAAO,CAAQ;IACzB,OAAO,EAAE,OAAO,CAAO;IACvB,UAAU,EAAE,kBAAkB,EAAE,CAAK;IAErC,SAAS,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,WAAW,UAAQ;CAIvF"}
@@ -12,10 +12,9 @@ class RulesEngine {
12
12
  label;
13
13
  required = false;
14
14
  default = null;
15
- collection = {};
16
- add(name, validationFunction) {
17
- if (!this.collection[name])
18
- this.collection[name] = validationFunction;
15
+ collection = [];
16
+ add(name, validationFunction, executeOnce = false) {
17
+ this.collection.push(validationFunction);
19
18
  return this;
20
19
  }
21
20
  }
@@ -0,0 +1,12 @@
1
+ import { RulesEngine } from "./rulesEngine";
2
+ export type EvaluateResponse<T> = {
3
+ error: false;
4
+ success: true;
5
+ result: T;
6
+ } | {
7
+ error: true;
8
+ success: false;
9
+ messages: string[];
10
+ };
11
+ export declare const validate: <T>(target: unknown, rules: RulesEngine) => EvaluateResponse<T>;
12
+ //# sourceMappingURL=validate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../src/validate.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAW,MAAM,eAAe,CAAA;AAEpD,MAAM,MAAM,gBAAgB,CAAC,CAAC,IAAI;IACjC,KAAK,EAAE,KAAK,CAAA;IACZ,OAAO,EAAE,IAAI,CAAA;IACb,MAAM,EAAE,CAAC,CAAA;CACT,GAAG;IACH,KAAK,EAAE,IAAI,CAAA;IACX,OAAO,EAAE,KAAK,CAAA;IACd,QAAQ,EAAE,MAAM,EAAE,CAAA;CAClB,CAAA;AAED,eAAO,MAAM,QAAQ,GAAI,CAAC,UAAU,OAAO,SAAS,WAAW,KAAG,gBAAgB,CAAC,CAAC,CAoDnF,CAAA"}
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.validate = void 0;
4
+ const pols_utils_1 = require("pols-utils");
5
+ const validate = (target, rules) => {
6
+ const errorMessages = [];
7
+ if (typeof target == 'string')
8
+ target = target.trim();
9
+ const isEmpty = target == null || (typeof target == 'string' && !target);
10
+ const label = rules.label ?? 'Este valor';
11
+ if (rules.required && isEmpty) {
12
+ return {
13
+ error: true,
14
+ success: false,
15
+ messages: [`'${label}' es requerido`]
16
+ };
17
+ }
18
+ if (isEmpty) {
19
+ return {
20
+ error: false,
21
+ success: true,
22
+ result: rules.default
23
+ };
24
+ }
25
+ const wrapper = {
26
+ value: pols_utils_1.PUtils.clone(target),
27
+ label
28
+ };
29
+ for (const validationFunction of rules.collection) {
30
+ const result = validationFunction(wrapper);
31
+ if (!result)
32
+ continue;
33
+ if (typeof result == 'string') {
34
+ errorMessages.push(result);
35
+ break;
36
+ }
37
+ else {
38
+ errorMessages.push(...result);
39
+ }
40
+ }
41
+ if (errorMessages.length) {
42
+ return {
43
+ error: true,
44
+ success: false,
45
+ messages: errorMessages
46
+ };
47
+ }
48
+ else {
49
+ return {
50
+ error: false,
51
+ success: true,
52
+ result: wrapper.value
53
+ };
54
+ }
55
+ };
56
+ exports.validate = validate;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pols-validator",
3
- "version": "1.0.1",
3
+ "version": "1.1.0",
4
4
  "main": "dist/index.js",
5
5
  "module": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
package/src/index.ts CHANGED
@@ -1,87 +1,8 @@
1
- import { PUtils } from "pols-utils"
2
1
  import { Rules } from "./rules"
3
- import { RulesEngine, RulesParams, Wrapper } from "./rulesEngine"
4
- export { RulesEngine } from './rulesEngine'
5
-
6
- export type EvaluateResponse<T> = {
7
- error: false
8
- success: true
9
- result: T
10
- } | {
11
- error: true
12
- success: false
13
- messages: string[]
14
- }
15
-
16
- export const validate = <T>(target: unknown, rules: RulesEngine): EvaluateResponse<T> => {
17
- const errorMessages: string[] = []
18
-
19
- if (typeof target == 'string') target = target.trim()
20
-
21
- const isEmpty = target == null || (typeof target == 'string' && !target)
22
- const label = rules.label ?? 'Este valor'
23
-
24
- if (rules.required && isEmpty) {
25
- return {
26
- error: true,
27
- success: false,
28
- messages: [`'${label}' es requerido`]
29
- }
30
- }
2
+ import { RulesParams } from "./rulesEngine"
31
3
 
32
- if (isEmpty) {
33
- return {
34
- error: false,
35
- success: true,
36
- result: rules.default as T
37
- }
38
- }
39
-
40
- const wrapper: Wrapper<T> = {
41
- value: PUtils.clone(target) as T,
42
- label
43
- }
44
- for (const validationFunction of Object.values(rules.collection)) {
45
- const result = validationFunction(wrapper)
46
- if (!result) continue
47
- if (typeof result == 'string') {
48
- errorMessages.push(result)
49
- break
50
- } else {
51
- if (wrapper.value == null || typeof wrapper.value != 'object') throw new Error(`El valor no es un objeto para ser validado contra un esquema: ${wrapper.value}`)
52
-
53
- const newResult: Record<string, unknown> = {}
54
- for (const key in result.schema) {
55
- const rulesInside = result.schema[key]
56
- const labelIndise = rulesInside.label ?? key
57
- rulesInside.label = `${result.prefix ? `${result.prefix} ` : ''}${labelIndise}`
58
-
59
- newResult[key] = wrapper.value[key]
60
-
61
- const result2 = validate(newResult[key], rulesInside)
62
- if (result2.error == true) {
63
- errorMessages.push(...result2.messages)
64
- } else {
65
- newResult[key] = result2.result
66
- }
67
- }
68
- wrapper.value = newResult as T
69
- }
70
- }
4
+ export { RulesEngine } from './rulesEngine'
71
5
 
72
- if (errorMessages.length) {
73
- return {
74
- error: true,
75
- success: false,
76
- messages: errorMessages
77
- }
78
- } else {
79
- return {
80
- error: false,
81
- success: true,
82
- result: wrapper.value
83
- }
84
- }
85
- }
6
+ export { EvaluateResponse, validate } from './validate'
86
7
 
87
8
  export const rules = (params?: RulesParams) => new Rules(params)
package/src/rules.ts CHANGED
@@ -1,5 +1,46 @@
1
1
  import { PDate, PUtils } from "pols-utils"
2
2
  import { RulesEngine, Wrapper } from "./rulesEngine"
3
+ import { validate } from "./validate"
4
+
5
+ const isObject = (wrapper: Wrapper, schema?: Record<string, RulesEngine>, prefix?: string) => {
6
+ const message = `'${wrapper.label}' debe ser un objeto`
7
+
8
+ if (typeof wrapper.value == 'string') {
9
+ try {
10
+ wrapper.value = JSON.parse(wrapper.value)
11
+ } catch {
12
+ return message
13
+ }
14
+ if (PUtils.getType(wrapper.value) != 'Object') return message
15
+ } else {
16
+ if (PUtils.getType(wrapper.value) != 'Object') {
17
+ return message
18
+ }
19
+ }
20
+
21
+ /* Realiza la validación de cada propiedad */
22
+ const newWrapperValue: Record<string, unknown> = {}
23
+ const errorMessages: string[] = []
24
+ for (const key in schema) {
25
+ const rulesInside = schema[key]
26
+ const labelIndise = rulesInside.label ?? key
27
+ rulesInside.label = `${prefix ?? ''}${labelIndise}`
28
+
29
+ newWrapperValue[key] = wrapper.value[key]
30
+
31
+ const result2 = validate(newWrapperValue[key], rulesInside)
32
+ if (result2.error == true) {
33
+ errorMessages.push(...result2.messages)
34
+ } else {
35
+ newWrapperValue[key] = result2.result
36
+ }
37
+ }
38
+ if (errorMessages.length) {
39
+ return errorMessages
40
+ } else {
41
+ wrapper.value = newWrapperValue
42
+ }
43
+ }
3
44
 
4
45
  export class Rules extends RulesEngine {
5
46
  isAlphanumeric() {
@@ -112,110 +153,83 @@ export class Rules extends RulesEngine {
112
153
  }
113
154
 
114
155
  maxLength(limit: number) {
115
- this.isAlphanumeric()
116
- this.add(this.maxLength.name, (wrapper: Wrapper) => {
117
- if ((wrapper.value as string).length > limit) return `'${wrapper.label}' debe contener '${limit} ${limit == 1 ? 'caracter' : 'caracteres'}' como máximo`
156
+ return this.add(this.maxLength.name, (wrapper: Wrapper) => {
157
+ if (wrapper.value instanceof Array) {
158
+ return wrapper.value.length > limit ? `'${wrapper.label}' debe contener '${limit} ${limit == 1 ? 'elementos' : 'elementos'}' como máximo` : null
159
+ } else if (typeof wrapper.value == 'string') {
160
+ return wrapper.value.length > limit ? `'${wrapper.label}' debe contener '${limit} ${limit == 1 ? 'caracter' : 'caracteres'}' como máximo` : null
161
+ } else {
162
+ return `'${wrapper.label}' no es de un tipo válido`
163
+ }
118
164
  })
119
- return this
120
165
  }
121
166
 
122
- // maxCount(limit: number) {
123
- // this.isArray()
124
- // this.add(this.maxLength.name, (wrapper: Wrapper<unknown[]>) => {
125
- // if (wrapper.value.length > limit) return `'${wrapper.label}' debe contener '${limit} ${limit == 1 ? 'elemento' : 'elementos'}' como máximo`
126
- // })
127
- // return this
128
- // }
129
-
130
167
  minLength(limit: number) {
131
- this.isAlphanumeric()
132
- this.add(this.minLength.name, (wrapper: Wrapper) => {
133
- if ((wrapper.value as string).length < limit) return `'${wrapper.label}' debe contener '${limit} ${limit == 1 ? 'caracter' : 'caracteres'}' como mínimo`
168
+ return this.add(this.minLength.name, (wrapper: Wrapper) => {
169
+ if (wrapper.value instanceof Array) {
170
+ return wrapper.value.length < limit ? `'${wrapper.label}' debe contener '${limit} ${limit == 1 ? 'elementos' : 'elementos'}' como mínimo` : null
171
+ } else if (typeof wrapper.value == 'string') {
172
+ return wrapper.value.length < limit ? `'${wrapper.label}' debe contener '${limit} ${limit == 1 ? 'caracter' : 'caracteres'}' como mínimo` : null
173
+ } else {
174
+ return `'${wrapper.label}' no es de un tipo válido`
175
+ }
134
176
  })
135
- return this
136
177
  }
137
178
 
138
- length(limit: number) {
139
- this.isAlphanumeric()
140
- this.add(this.length.name, (wrapper: Wrapper) => {
141
- if ((wrapper.value as string).length != limit) return `'${wrapper.label}' debe contener sólo '${limit} ${limit == 1 ? 'caracter' : 'caracteres'}'`
179
+ hasFixedLength(limit: number) {
180
+ return this.add(this.hasFixedLength.name, (wrapper: Wrapper) => {
181
+ if (wrapper.value instanceof Array) {
182
+ return wrapper.value.length < limit ? `'${wrapper.label}' debe contener sólo '${limit} ${limit == 1 ? 'elementos' : 'elementos'}'` : null
183
+ } else if (typeof wrapper.value == 'string') {
184
+ return wrapper.value.length < limit ? `'${wrapper.label}' debe contener sólo '${limit} ${limit == 1 ? 'caracter' : 'caracteres'}'` : null
185
+ } else {
186
+ return `'${wrapper.label}' no es de un tipo válido`
187
+ }
142
188
  })
143
- return this
144
189
  }
145
190
 
146
191
  left(limit: number) {
147
- this.isAlphanumeric()
148
- this.add(this.length.name, (wrapper: Wrapper) => {
192
+ return this.isAlphanumeric().add(this.left.name, (wrapper: Wrapper) => {
149
193
  (wrapper.value as string) = (wrapper.value as string).substring(0, limit)
150
194
  })
151
- return this
152
195
  }
153
196
 
154
- // isArray(checkingElements?: (i: number) => RulesEngine) {
155
- // this.add(this.isArray.name, (wrapper: Wrapper) => {
156
- // const message = `'${wrapper.label}' debe ser una lista de elementos`
157
- // if (typeof wrapper.value == 'string') {
158
- // try {
159
- // const value = JSON.parse(wrapper.value)
160
- // if (!(value instanceof Array)) return message
161
- // wrapper.value = value
162
- // } catch (err) {
163
- // return message
164
- // }
165
- // } else {
166
- // if (!(wrapper.value instanceof Array)) return message
167
- // }
168
- // if (checkingElements) {
169
- // const value = wrapper.value as unknown[]
170
- // const messageErrors: string[] = []
171
- // const result: unknown[] = []
172
- // for (const [i, t] of value.entries()) {
173
- // const p = wrapper.validator({
174
- // value: t
175
- // }, {
176
- // value: {
177
- // ...checkingElements(i),
178
- // to: undefined,
179
- // }
180
- // })
181
- // if (p.error == true) {
182
- // messageErrors.push(...p.messages)
183
- // } else {
184
- // result.push(p.result['value'])
185
- // }
186
- // }
187
- // if (messageErrors.length) {
188
- // return messageErrors
189
- // } else {
190
- // wrapper.value = result
191
- // }
192
- // }
193
- // })
194
- // return this
195
- // }
196
-
197
- // isArrayOfObjects(checkingElements?: (i: number) => FieldsStructure, prefixString?: (i: number) => string) {
198
- // this.isArray()
199
- // this.add(this.isArrayOfObjects.name, (wrapper: Wrapper<unknown[]>) => {
200
- // const message = `'${wrapper.label}' debe ser una lista de objetos`
201
- // const messages: string[] = []
202
- // for (const [i, v] of wrapper.value.entries()) {
203
- // const result = isObject(v)
204
- // if (result.error == true) return message
205
- // wrapper.value[i] = result.result
206
- // if (checkingElements) {
207
- // const v = wrapper.validator(wrapper.value[i], checkingElements(i), prefixString?.(i))
208
- // if (v.error == true) {
209
- // messages.push(...v.messages)
210
- // } else {
211
- // wrapper.value[i] = v.result
212
- // }
213
- // }
214
- // }
215
- // if (messages.length) return messages
216
- // })
217
- // return this
218
- // }
197
+ isArray() {
198
+ return this.add(this.isArray.name, (wrapper: Wrapper) => {
199
+ const message = `'${wrapper.label}' debe ser una lista de elementos`
200
+ if (typeof wrapper.value == 'string') {
201
+ try {
202
+ const value = JSON.parse(wrapper.value)
203
+ if (!(value instanceof Array)) return message
204
+ wrapper.value = value
205
+ } catch (err) {
206
+ return message
207
+ }
208
+ } else {
209
+ if (!(wrapper.value instanceof Array)) return message
210
+ }
211
+ })
212
+ }
213
+
214
+ isArrayOfObjects(schema?: (index: number) => Record<string, RulesEngine>, prefix?: (index: number) => string) {
215
+ return this.isArray().add(this.isArrayOfObjects.name, (wrapper: Wrapper<unknown[]>) => {
216
+ const messages: string[] = []
217
+ for (const [i, value] of wrapper.value.entries()) {
218
+ const v = isObject({
219
+ label: prefix?.(i) ?? `Item ${i}`,
220
+ value
221
+ }, schema?.(i))
222
+ if (v) {
223
+ if (v instanceof Array) {
224
+ messages.push(...v)
225
+ } else {
226
+ messages.push(v)
227
+ }
228
+ }
229
+ }
230
+ if (messages.length) return messages
231
+ })
232
+ }
219
233
 
220
234
  isIn(...elements: unknown[]) {
221
235
  this.add(this.isIn.name, (wrapper: Wrapper) => {
@@ -237,78 +251,51 @@ export class Rules extends RulesEngine {
237
251
  return this
238
252
  }
239
253
 
240
- // hasElements(checkingElements?: (i: number) => FieldStructure) {
241
- // this.isArray(checkingElements)
242
- // this.add(this.hasElements.name, (wrapper: Wrapper) => {
243
- // if (!(wrapper.value as unknown[]).length) return `'${wrapper.label}' debe ser una lista con al menos un elemento`
244
- // })
245
- // return this
246
- // }
254
+ hasElements() {
255
+ return this.isArray().add(this.hasElements.name, (wrapper: Wrapper<unknown[]>) => {
256
+ if (!wrapper.value.length) return `'${wrapper.label}' debe contenedor al menos un elemento`
257
+ })
258
+ }
247
259
 
248
260
  gt(limit: number) {
249
- this.isNumber()
250
- this.add(this.gt.name, (wrapper: Wrapper) => {
261
+ return this.isNumber().add(this.gt.name, (wrapper: Wrapper) => {
251
262
  if (wrapper.value as number <= limit) return `'${wrapper.label}' debe ser mayor a '${limit}'`
252
263
  })
253
- return this
254
264
  }
255
265
 
256
266
  gte(limit: number) {
257
- this.isNumber()
258
- this.add(this.gte.name, (wrapper: Wrapper) => {
267
+ return this.isNumber().add(this.gte.name, (wrapper: Wrapper) => {
259
268
  if (wrapper.value as number < limit) return `'${wrapper.label}' debe ser mayor o igual a '${limit}'`
260
269
  })
261
- return this
262
270
  }
263
271
 
264
272
  lt(limit: number) {
265
- this.isNumber()
266
- this.add(this.lt.name, (wrapper: Wrapper) => {
273
+ return this.isNumber().add(this.lt.name, (wrapper: Wrapper) => {
267
274
  if (wrapper.value as number >= limit) return `'${wrapper.label}' debe ser menor a '${limit}'`
268
275
  })
269
- return this
270
276
  }
271
277
 
272
278
  lte(limit: number) {
273
- return this
274
- .isNumber()
275
- .add(this.lte.name, (wrapper: Wrapper) => {
276
- if (wrapper.value as number > limit) return `'${wrapper.label}' debe ser menor o igual a '${limit}'`
277
- })
279
+ return this.isNumber().add(this.lte.name, (wrapper: Wrapper) => {
280
+ if (wrapper.value as number > limit) return `'${wrapper.label}' debe ser menor o igual a '${limit}'`
281
+ })
278
282
  }
279
283
 
280
284
  beforeOrSameAsNow() {
281
- return this
282
- .isDateTime()
283
- .add(this.beforeOrSameAsNow.name, (wrapper: Wrapper<PDate>) => {
284
- const now = new PDate
285
- if (wrapper.value.time > now.time) return `'${wrapper.label}' debe ser anterior o igual a 'ahora'`
286
- })
285
+ return this.isDateTime().add(this.beforeOrSameAsNow.name, (wrapper: Wrapper<PDate>) => {
286
+ const now = new PDate
287
+ if (wrapper.value.time > now.time) return `'${wrapper.label}' debe ser anterior o igual a 'ahora'`
288
+ })
287
289
  }
288
290
 
289
291
  isObject(schema?: Record<string, RulesEngine>, prefix?: string) {
290
292
  return this.add(this.isObject.name, (wrapper: Wrapper) => {
291
- const message = `'${wrapper.label}' debe ser un objeto`
292
-
293
- if (typeof wrapper.value == 'string') {
294
- try {
295
- wrapper.value = JSON.parse(wrapper.value)
296
- } catch {
297
- return message
298
- }
299
- if (PUtils.getType(wrapper.value) != 'Object') return message
300
- } else {
301
- if (PUtils.getType(wrapper.value) != 'Object') {
302
- return message
303
- }
304
- }
305
-
306
- return { schema, prefix }
293
+ return isObject(wrapper, schema, prefix)
307
294
  })
308
295
  }
309
296
 
310
297
  isBoolean() {
311
- this.add(this.isBoolean.name, (wrapper: Wrapper) => {
298
+ return this.add(this.isBoolean.name, (wrapper: Wrapper) => {
312
299
  const message = `'${wrapper.label}' debe ser de tipo booleano`
313
300
  if (typeof wrapper.value == 'string') {
314
301
  const value = wrapper.value.trim().toUpperCase()
@@ -352,7 +339,6 @@ export class Rules extends RulesEngine {
352
339
  return typeof wrapper.value == 'boolean' ? null : message
353
340
  }
354
341
  })
355
- return this
356
342
  }
357
343
 
358
344
  upper() {
@@ -6,10 +6,7 @@ export type RulesParams = {
6
6
  default?: unknown
7
7
  })
8
8
 
9
- export type ValidationFunction = (wrapper: Wrapper, ...args: unknown[]) => string | void | null | undefined | {
10
- schema: Record<string, RulesEngine>
11
- prefix?: string
12
- }
9
+ export type ValidationFunction = (wrapper: Wrapper, ...args: unknown[]) => string | string[] | void | null | undefined
13
10
 
14
11
  export type Wrapper<T = unknown> = {
15
12
  value: T
@@ -27,10 +24,10 @@ export class RulesEngine {
27
24
  label: string
28
25
  required: boolean = false
29
26
  default: unknown = null
30
- collection: Record<string, ValidationFunction> = {}
27
+ collection: ValidationFunction[] = []
31
28
 
32
- protected add(name: string, validationFunction: ValidationFunction) {
33
- if (!this.collection[name]) this.collection[name] = validationFunction
29
+ protected add(name: string, validationFunction: ValidationFunction, executeOnce = false) {
30
+ this.collection.push(validationFunction)
34
31
  return this
35
32
  }
36
33
  }
@@ -0,0 +1,66 @@
1
+ import { PUtils } from "pols-utils"
2
+ import { RulesEngine, Wrapper } from "./rulesEngine"
3
+
4
+ export type EvaluateResponse<T> = {
5
+ error: false
6
+ success: true
7
+ result: T
8
+ } | {
9
+ error: true
10
+ success: false
11
+ messages: string[]
12
+ }
13
+
14
+ export const validate = <T>(target: unknown, rules: RulesEngine): EvaluateResponse<T> => {
15
+ const errorMessages: string[] = []
16
+
17
+ if (typeof target == 'string') target = target.trim()
18
+
19
+ const isEmpty = target == null || (typeof target == 'string' && !target)
20
+ const label = rules.label ?? 'Este valor'
21
+
22
+ if (rules.required && isEmpty) {
23
+ return {
24
+ error: true,
25
+ success: false,
26
+ messages: [`'${label}' es requerido`]
27
+ }
28
+ }
29
+
30
+ if (isEmpty) {
31
+ return {
32
+ error: false,
33
+ success: true,
34
+ result: rules.default as T
35
+ }
36
+ }
37
+
38
+ const wrapper: Wrapper<T> = {
39
+ value: PUtils.clone(target) as T,
40
+ label
41
+ }
42
+ for (const validationFunction of rules.collection) {
43
+ const result = validationFunction(wrapper)
44
+ if (!result) continue
45
+ if (typeof result == 'string') {
46
+ errorMessages.push(result)
47
+ break
48
+ } else {
49
+ errorMessages.push(...result)
50
+ }
51
+ }
52
+
53
+ if (errorMessages.length) {
54
+ return {
55
+ error: true,
56
+ success: false,
57
+ messages: errorMessages
58
+ }
59
+ } else {
60
+ return {
61
+ error: false,
62
+ success: true,
63
+ result: wrapper.value
64
+ }
65
+ }
66
+ }