lesgo 0.7.7 → 0.7.8

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.
@@ -12,6 +12,13 @@ const params = {
12
12
  status: 'active',
13
13
  decimalCheck: 1.99,
14
14
  totalRecord: 99,
15
+ functionCheck: () => {},
16
+ jsonCheck: JSON.stringify({
17
+ test: 'json value',
18
+ testArray: ['withvalues', 'here'],
19
+ testNum: 1,
20
+ }),
21
+ statusCollection: ['active', 'inactive', 'active'],
15
22
  };
16
23
 
17
24
  const validFields = [
@@ -26,8 +33,29 @@ const validFields = [
26
33
  enumValues: ['active', 'inactive'],
27
34
  required: true,
28
35
  },
29
- { key: 'decimalCheck', type: 'decimal', required: true },
36
+ {
37
+ key: 'decimalCheck',
38
+ type: 'decimal',
39
+ required: true,
40
+ },
30
41
  { key: 'totalRecord', type: 'number', required: true },
42
+ {
43
+ key: 'functionCheck',
44
+ type: 'function',
45
+ required: true,
46
+ },
47
+ {
48
+ key: 'jsonCheck',
49
+ type: 'json',
50
+ required: true,
51
+ },
52
+ {
53
+ key: 'statusCollection',
54
+ type: 'enum',
55
+ enumValues: ['active', 'inactive'],
56
+ required: true,
57
+ isCollection: true,
58
+ },
31
59
  ];
32
60
 
33
61
  describe('test Utils/validateFields', () => {
@@ -39,56 +67,92 @@ describe('test Utils/validateFields', () => {
39
67
  const newParams = { ...params };
40
68
  delete newParams.email;
41
69
 
42
- expect(() => validateFields(newParams, validFields)).toThrow(
43
- new LesgoException(
44
- "Missing required 'email'",
45
- `${FILE}::MISSING_REQUIRED_EMAIL}`
46
- )
47
- );
70
+ try {
71
+ const validated = validateFields(newParams, validFields);
72
+
73
+ expect(validated).toThrow();
74
+ } catch (e) {
75
+ expect(e.name).toEqual('LesgoException');
76
+ expect(e.message).toEqual("Missing required 'email'");
77
+ expect(e.code).toEqual(`${FILE}::MISSING_REQUIRED_EMAIL`);
78
+ expect(e.extra).toStrictEqual({
79
+ field: validFields[2],
80
+ });
81
+ }
48
82
  });
49
83
 
50
84
  it('should throw invalid type when non-string value check', () => {
51
85
  const newParams = { ...params, name: 123 };
52
86
 
53
- expect(() => validateFields(newParams, validFields)).toThrow(
54
- new LesgoException(
55
- `Invalid type for 'name', expecting 'string'`,
56
- `${FILE}::INVALID_TYPE_NAME`
57
- )
58
- );
87
+ try {
88
+ const validated = validateFields(newParams, validFields);
89
+
90
+ expect(validated).toThrow();
91
+ } catch (e) {
92
+ expect(e.name).toEqual('LesgoException');
93
+ expect(e.message).toEqual(`Invalid type for 'name', expecting 'string'`);
94
+ expect(e.code).toEqual(`${FILE}::INVALID_TYPE_NAME`);
95
+ expect(e.extra).toStrictEqual({
96
+ field: validFields[1],
97
+ value: 123,
98
+ });
99
+ }
59
100
  });
60
101
 
61
102
  it('should throw invalid type when non-object value check', () => {
62
103
  const newParams = { ...params, roles: 1597929335 };
63
104
 
64
- expect(() => validateFields(newParams, validFields)).toThrow(
65
- new LesgoException(
66
- `Invalid type for 'roles', expecting 'object'`,
67
- `${FILE}::INVALID_TYPE_ROLES`
68
- )
69
- );
105
+ try {
106
+ const validated = validateFields(newParams, validFields);
107
+
108
+ expect(validated).toThrow();
109
+ } catch (e) {
110
+ expect(e.name).toEqual('LesgoException');
111
+ expect(e.message).toEqual(`Invalid type for 'roles', expecting 'object'`);
112
+ expect(e.code).toEqual(`${FILE}::INVALID_TYPE_ROLES`);
113
+ expect(e.extra).toStrictEqual({
114
+ field: validFields[3],
115
+ value: 1597929335,
116
+ });
117
+ }
70
118
  });
71
119
 
72
120
  it('should throw invalid type when non-number value check', () => {
73
121
  const newParams = { ...params, Id: '123' };
74
122
 
75
- expect(() => validateFields(newParams, validFields)).toThrow(
76
- new LesgoException(
77
- `Invalid type for 'Id', expecting 'number'`,
78
- `${FILE}::INVALID_TYPE_ID`
79
- )
80
- );
123
+ try {
124
+ const validated = validateFields(newParams, validFields);
125
+
126
+ expect(validated).toThrow();
127
+ } catch (e) {
128
+ expect(e.name).toEqual('LesgoException');
129
+ expect(e.message).toEqual(`Invalid type for 'Id', expecting 'number'`);
130
+ expect(e.code).toEqual(`${FILE}::INVALID_TYPE_ID`);
131
+ expect(e.extra).toStrictEqual({
132
+ field: validFields[0],
133
+ value: '123',
134
+ });
135
+ }
81
136
  });
82
137
 
83
138
  it('should throw invalid type when non-array value check', () => {
84
139
  const newParams = { ...params, listItem: { created_at: 1597929335 } };
85
140
 
86
- expect(() => validateFields(newParams, validFields)).toThrow(
87
- new LesgoException(
88
- `Invalid type for 'listItem', expecting 'array'`,
89
- `${FILE}::INVALID_TYPE_LISTITEM`
90
- )
91
- );
141
+ try {
142
+ const validated = validateFields(newParams, validFields);
143
+
144
+ expect(validated).toThrow();
145
+ } catch (e) {
146
+ expect(e.name).toEqual('LesgoException');
147
+ expect(e.message).toEqual(
148
+ `Invalid type for 'listItem', expecting 'array'`
149
+ );
150
+ expect(e.code).toEqual(`${FILE}::INVALID_TYPE_LISTITEM`);
151
+ expect(e.extra).toStrictEqual({
152
+ field: validFields[4],
153
+ value: { created_at: 1597929335 },
154
+ });
155
+ }
92
156
  });
93
157
 
94
158
  it('should throw required when array value is empty but required', () => {
@@ -119,9 +183,136 @@ describe('test Utils/validateFields', () => {
119
183
  expect(() => validateFields(newParams, validFields)).toThrow(
120
184
  new LesgoException(
121
185
  `Invalid type for 'status', expecting 'enum'`,
122
- `${FILE}::INVALID_TYPE_STATUS`
186
+ `Invalid type for 'status', expecting 'enum'`
123
187
  )
124
188
  );
189
+
190
+ try {
191
+ const validated = validateFields(newParams, validFields);
192
+
193
+ expect(validated).toThrow();
194
+ } catch (e) {
195
+ expect(e.name).toEqual('LesgoException');
196
+ expect(e.message).toEqual(`Invalid type for 'status', expecting 'enum'`);
197
+ expect(e.code).toEqual(`${FILE}::INVALID_TYPE_STATUS`);
198
+ expect(e.extra).toStrictEqual({
199
+ field: validFields[5],
200
+ value: 'private',
201
+ });
202
+ }
203
+ });
204
+
205
+ it('should throw invalid type when non-function value check', async () => {
206
+ const newParams = {
207
+ ...params,
208
+ functionCheck: { not: 'function' },
209
+ };
210
+
211
+ try {
212
+ const validated = validateFields(newParams, validFields);
213
+
214
+ expect(validated).toThrow();
215
+ } catch (e) {
216
+ expect(e.name).toEqual('LesgoException');
217
+ expect(e.message).toEqual(
218
+ `Invalid type for 'functionCheck', expecting 'function'`
219
+ );
220
+ expect(e.code).toEqual(`${FILE}::INVALID_TYPE_FUNCTIONCHECK`);
221
+ expect(e.extra).toStrictEqual({
222
+ field: validFields[8],
223
+ value: { not: 'function' },
224
+ });
225
+ }
226
+ });
227
+
228
+ it.each`
229
+ value
230
+ ${'not a json'}
231
+ ${3}
232
+ ${'"invalid'}
233
+ ${{ not: 'json' }}
234
+ ${'{"missing":"bracket"}}'}
235
+ `(
236
+ 'should throw invalid type when non-json $value check',
237
+ async ({ value }) => {
238
+ const newParams = {
239
+ ...params,
240
+ jsonCheck: value,
241
+ };
242
+
243
+ try {
244
+ const validated = validateFields(newParams, validFields);
245
+
246
+ expect(validated).toThrow();
247
+ } catch (e) {
248
+ expect(e.name).toEqual('LesgoException');
249
+ expect(e.message).toEqual(
250
+ `Invalid type for 'jsonCheck', expecting 'json'`
251
+ );
252
+ expect(e.code).toEqual(`${FILE}::INVALID_TYPE_JSONCHECK`);
253
+ expect(e.extra).toStrictEqual({
254
+ field: validFields[9],
255
+ value,
256
+ });
257
+ }
258
+ }
259
+ );
260
+
261
+ it('should throw invalid type when non-collection value check', async () => {
262
+ const newParams = {
263
+ ...params,
264
+ statusCollection: 'active',
265
+ };
266
+
267
+ try {
268
+ const validated = validateFields(newParams, validFields);
269
+
270
+ expect(validated).toThrow();
271
+ } catch (e) {
272
+ expect(e.name).toEqual('LesgoException');
273
+ expect(e.message).toEqual(
274
+ `Invalid type for 'statusCollection', expecting collection of 'enum'`
275
+ );
276
+ expect(e.code).toEqual(`${FILE}::INVALID_TYPE_STATUSCOLLECTION`);
277
+ expect(e.extra).toStrictEqual({
278
+ field: validFields[10],
279
+ value: 'active',
280
+ });
281
+ }
282
+ });
283
+
284
+ it('should ignore type when collection value check is non-required', async () => {
285
+ const newParams = { ...params };
286
+ const newValidFields = [...validFields];
287
+ delete newParams.statusCollection;
288
+ newValidFields[10].required = false;
289
+
290
+ const validated = validateFields(newParams, newValidFields);
291
+
292
+ expect(validated).toStrictEqual(newParams);
293
+ });
294
+
295
+ it('should throw invalid type when non-enum collection value check', async () => {
296
+ const newParams = {
297
+ ...params,
298
+ statusCollection: ['archive'],
299
+ };
300
+
301
+ try {
302
+ const validated = validateFields(newParams, validFields);
303
+
304
+ expect(validated).toThrow();
305
+ } catch (e) {
306
+ expect(e.name).toEqual('LesgoException');
307
+ expect(e.message).toEqual(
308
+ `Invalid type for 'statusCollection', expecting collection of 'enum'`
309
+ );
310
+ expect(e.code).toEqual(`${FILE}::INVALID_TYPE_STATUSCOLLECTION`);
311
+ expect(e.extra).toStrictEqual({
312
+ field: validFields[10],
313
+ value: 'archive',
314
+ });
315
+ }
125
316
  });
126
317
 
127
318
  it('should return only valid and allowed fields when other fields are received', () => {
@@ -4,30 +4,44 @@ import isDecimal from './isDecimal';
4
4
 
5
5
  const FILE = 'Utils/validateFields';
6
6
 
7
- export default (params, validFields) => {
7
+ const isValidJSON = json => {
8
+ if (typeof json !== 'string') {
9
+ return false;
10
+ }
11
+
12
+ // Cannot find a regex solution to this
13
+ try {
14
+ JSON.parse(json);
15
+
16
+ return true;
17
+ } catch (_) {
18
+ return false;
19
+ }
20
+ };
21
+
22
+ const validateFields = (params, validFields) => {
8
23
  const validated = {};
9
24
 
10
25
  validFields.forEach(field => {
11
- if (field.required) {
12
- if (typeof params[field.key] === 'object') {
13
- if (
14
- Array.isArray(params[field.key]) &&
15
- params[field.key].length === 0
16
- ) {
26
+ const { required, type, key, isCollection, enumValues = [] } = field;
27
+
28
+ if (required) {
29
+ if (typeof params[key] === 'object') {
30
+ if (Array.isArray(params[key]) && params[key].length === 0) {
17
31
  throw new LesgoException(
18
- `Missing required '${field.key}'`,
19
- `${FILE}::MISSING_REQUIRED_${field.key.toUpperCase()}`,
32
+ `Missing required '${key}'`,
33
+ `${FILE}::MISSING_REQUIRED_${key.toUpperCase()}`,
20
34
  500,
21
35
  { field }
22
36
  );
23
37
  }
24
38
  }
25
39
 
26
- if (!params[field.key]) {
27
- if (typeof params[field.key] !== 'number') {
40
+ if (!params[key]) {
41
+ if (typeof params[key] !== 'number') {
28
42
  throw new LesgoException(
29
- `Missing required '${field.key}'`,
30
- `${FILE}::MISSING_REQUIRED_${field.key.toUpperCase()}`,
43
+ `Missing required '${key}'`,
44
+ `${FILE}::MISSING_REQUIRED_${key.toUpperCase()}`,
31
45
  500,
32
46
  { field }
33
47
  );
@@ -35,41 +49,68 @@ export default (params, validFields) => {
35
49
  }
36
50
  }
37
51
 
38
- if (
39
- (field.type === 'string' &&
40
- typeof params[field.key] !== 'undefined' &&
41
- typeof params[field.key] !== 'string') ||
42
- (field.type === 'object' &&
43
- typeof params[field.key] !== 'undefined' &&
44
- typeof params[field.key] !== 'object') ||
45
- (field.type === 'number' &&
46
- typeof params[field.key] !== 'undefined' &&
47
- typeof params[field.key] !== 'number') ||
48
- (field.type === 'decimal' &&
49
- typeof params[field.key] !== 'undefined' &&
50
- !isDecimal(params[field.key])) ||
51
- (field.type === 'email' &&
52
- typeof params[field.key] !== 'undefined' &&
53
- !isEmail(params[field.key])) ||
54
- (field.type === 'array' &&
55
- typeof params[field.key] !== 'undefined' &&
56
- !Array.isArray(params[field.key])) ||
57
- (field.type === 'enum' &&
58
- typeof params[field.key] !== 'undefined' &&
59
- !field.enumValues.includes(params[field.key]))
60
- ) {
61
- throw new LesgoException(
62
- `Invalid type for '${field.key}', expecting '${field.type}'`,
63
- `${FILE}::INVALID_TYPE_${field.key.toUpperCase()}`,
64
- 500,
65
- { field, value: params[field.key] }
66
- );
52
+ if (isCollection) {
53
+ try {
54
+ validateFields({ [key]: params[key] }, [
55
+ { key, required, type: 'array' },
56
+ ]);
57
+ } catch (_) {
58
+ throw new LesgoException(
59
+ `Invalid type for '${key}', expecting collection of '${type}'`,
60
+ `${FILE}::INVALID_TYPE_${key.toUpperCase()}`,
61
+ 500,
62
+ { field, value: params[key] }
63
+ );
64
+ }
67
65
  }
68
66
 
69
- if (typeof params[field.key] !== 'undefined') {
70
- validated[field.key] = params[field.key];
67
+ (isCollection ? params[key] || [] : [params[key]]).forEach(paramsItem => {
68
+ if (
69
+ (type === 'string' &&
70
+ typeof paramsItem !== 'undefined' &&
71
+ typeof paramsItem !== 'string') ||
72
+ (type === 'object' &&
73
+ typeof paramsItem !== 'undefined' &&
74
+ typeof paramsItem !== 'object') ||
75
+ (type === 'number' &&
76
+ typeof paramsItem !== 'undefined' &&
77
+ typeof paramsItem !== 'number') ||
78
+ (type === 'decimal' &&
79
+ typeof paramsItem !== 'undefined' &&
80
+ !isDecimal(paramsItem)) ||
81
+ (type === 'email' &&
82
+ typeof paramsItem !== 'undefined' &&
83
+ !isEmail(paramsItem)) ||
84
+ (type === 'array' &&
85
+ typeof paramsItem !== 'undefined' &&
86
+ !Array.isArray(paramsItem)) ||
87
+ (type === 'enum' &&
88
+ typeof paramsItem !== 'undefined' &&
89
+ !enumValues.includes(paramsItem)) ||
90
+ (type === 'function' &&
91
+ typeof paramsItem !== 'undefined' &&
92
+ {}.toString.call(paramsItem) !== '[object Function]') ||
93
+ (type === 'json' &&
94
+ typeof paramsItem !== 'undefined' &&
95
+ !isValidJSON(paramsItem))
96
+ ) {
97
+ throw new LesgoException(
98
+ `Invalid type for '${key}', expecting ${
99
+ isCollection ? 'collection of ' : ''
100
+ }'${type}'`,
101
+ `${FILE}::INVALID_TYPE_${key.toUpperCase()}`,
102
+ 500,
103
+ { field, value: paramsItem }
104
+ );
105
+ }
106
+ });
107
+
108
+ if (typeof params[key] !== 'undefined') {
109
+ validated[key] = params[key];
71
110
  }
72
111
  });
73
112
 
74
113
  return validated;
75
114
  };
115
+
116
+ export default validateFields;