@awesomeness-js/utils 1.1.7 → 1.1.9

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/index.js CHANGED
@@ -6,6 +6,8 @@
6
6
  import _build from './src/build.js';
7
7
  import _clean_array from './src/clean/array.js';
8
8
  import _clean_boolean from './src/clean/boolean.js';
9
+ import _clean_custom from './src/clean/custom.js';
10
+ import _clean_file from './src/clean/file.js';
9
11
  import _clean_integer from './src/clean/integer.js';
10
12
  import _clean_number from './src/clean/number.js';
11
13
  import _clean_object from './src/clean/object.js';
@@ -64,6 +66,8 @@ export { _wait as wait };
64
66
  export const clean = {
65
67
  array: _clean_array,
66
68
  boolean: _clean_boolean,
69
+ custom: _clean_custom,
70
+ file: _clean_file,
67
71
  integer: _clean_integer,
68
72
  number: _clean_number,
69
73
  object: _clean_object,
@@ -141,6 +145,8 @@ export default {
141
145
  clean: {
142
146
  array: _clean_array,
143
147
  boolean: _clean_boolean,
148
+ custom: _clean_custom,
149
+ file: _clean_file,
144
150
  integer: _clean_integer,
145
151
  number: _clean_number,
146
152
  object: _clean_object,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@awesomeness-js/utils",
3
- "version": "1.1.7",
3
+ "version": "1.1.9",
4
4
  "description": "Awesomeness - Utils",
5
5
  "repository": {
6
6
  "type": "git",
@@ -0,0 +1,39 @@
1
+ export default function cleanCustom(value, {
2
+ required = false,
3
+ validate = null, // callback that returns true or cleaned value, throws or returns false if invalid
4
+ } = {}) {
5
+
6
+ try {
7
+ if (value === undefined || value === null) {
8
+ throw {
9
+ message: 'Value is missing',
10
+ value
11
+ };
12
+ }
13
+
14
+ if (typeof validate === 'function') {
15
+ const result = validate(value);
16
+
17
+ // if validator returns false, treat as invalid
18
+ if (result === false) {
19
+ throw {
20
+ message: 'Validation failed',
21
+ value
22
+ };
23
+ }
24
+
25
+ // if validator returns something else, assume cleaned value
26
+ return result === true ? value : result;
27
+ }
28
+
29
+ // no validation callback, just return the value
30
+ return value;
31
+
32
+ } catch (e) {
33
+ if (required) {
34
+ throw e;
35
+ } else {
36
+ return null;
37
+ }
38
+ }
39
+ }
@@ -0,0 +1,62 @@
1
+ export default function cleanFile(file, {
2
+ required = false,
3
+ validTypes = [],
4
+ minSize = false, // bytes
5
+ maxSize = false, // bytes
6
+ } = {}) {
7
+
8
+ try {
9
+ if (!file || typeof file !== 'object') {
10
+ throw {
11
+ message: 'File must be an object (like req.file or File API object)',
12
+ value: file
13
+ };
14
+ }
15
+
16
+ if (typeof file.size !== 'number' || typeof file.type !== 'string') {
17
+ throw {
18
+ message: 'File object missing required fields (size, type)',
19
+ value: file
20
+ };
21
+ }
22
+
23
+ // type validation
24
+ if (Array.isArray(validTypes) && validTypes.length > 0) {
25
+ const isValidType = validTypes.some(t => file.type === t || file.name?.endsWith(t));
26
+ if (!isValidType) {
27
+ throw {
28
+ message: `Invalid file type: ${file.type}`,
29
+ allowed: validTypes,
30
+ value: file.name || null
31
+ };
32
+ }
33
+ }
34
+
35
+ // size validation
36
+ if (minSize !== false && file.size < minSize) {
37
+ throw {
38
+ message: `File is smaller than minimum size (${minSize} bytes)`,
39
+ value: file.size
40
+ };
41
+ }
42
+
43
+ if (maxSize !== false && file.size > maxSize) {
44
+ throw {
45
+ message: `File is larger than maximum size (${maxSize} bytes)`,
46
+ value: file.size
47
+ };
48
+ }
49
+
50
+ // return a normalized safe file info object
51
+ return {
52
+ name: file.name || null,
53
+ type: file.type,
54
+ size: file.size,
55
+ lastModified: file.lastModified ? new Date(file.lastModified).toISOString() : null,
56
+ };
57
+
58
+ } catch (e) {
59
+ if (required) throw e;
60
+ else return null;
61
+ }
62
+ }
@@ -9,7 +9,22 @@ import cleanString from '../clean/string.js';
9
9
  import cleanTimestamp from '../clean/timestamp.js';
10
10
  import cleanUUID from '../clean/uuid.js';
11
11
 
12
- function cleanArray(arr, schema = {}, testMode = false){
12
+ const knownTypesToClean = [
13
+ 'boolean',
14
+ 'integer',
15
+ 'number',
16
+ 'string',
17
+ 'timestamp',
18
+ 'uuid',
19
+ 'object',
20
+ 'array'
21
+ ];
22
+
23
+ function cleanArray(arr, schema = {}, {
24
+ testMode = false,
25
+ allOrNothing = false,
26
+ path = ''
27
+ } = {}){
13
28
 
14
29
  try {
15
30
 
@@ -25,97 +40,153 @@ function cleanArray(arr, schema = {}, testMode = false){
25
40
  validateSchema(schema);
26
41
 
27
42
  const cleanArrayItems = [];
28
-
43
+ const errors = {};
44
+
29
45
  const supposedToBeType = schema.items.type;
30
46
 
31
47
  arr.forEach( (item, key) => {
48
+
49
+ let cleanedItem;
50
+
51
+ try {
52
+
53
+ const itemType = thingType(item);
32
54
 
33
- const itemType = thingType(item);
34
-
35
-
36
- if(itemType !== supposedToBeType){
37
-
38
- throw {
39
- message: 'type invalid',
40
- itemType,
41
- supposedToBeType
42
- };
43
-
44
- }
45
-
46
- let cleanedItem = item;
47
-
48
- if(supposedToBeType === 'boolean'){
55
+ if(itemType !== supposedToBeType){
56
+
57
+ throw {
58
+ message: 'type invalid',
59
+ itemType,
60
+ supposedToBeType
61
+ };
62
+
63
+ }
64
+
65
+ cleanedItem = item;
49
66
 
50
- cleanedItem = cleanBoolean(item);
67
+ if(!knownTypesToClean.includes(supposedToBeType)){
51
68
 
52
- }
69
+ throw {
70
+ message: 'Unknown type to clean in schema',
71
+ supposedToBeType
72
+ };
53
73
 
54
- if(supposedToBeType === 'integer'){
74
+ }
55
75
 
56
- cleanedItem = cleanInteger(item);
57
76
 
58
- }
77
+ if(testMode){ console.log(`cleaning ${supposedToBeType}`, item, schema.items); }
59
78
 
60
- if(supposedToBeType === 'number'){
61
79
 
62
- cleanedItem = cleanNumber(item);
80
+ if(supposedToBeType === 'boolean'){
63
81
 
64
- }
82
+ cleanedItem = cleanBoolean(item);
65
83
 
66
- if(supposedToBeType === 'string'){
84
+ }
67
85
 
68
- cleanedItem = cleanString(item);
86
+ if(supposedToBeType === 'integer'){
69
87
 
70
- }
88
+ cleanedItem = cleanInteger(item);
71
89
 
72
- if(supposedToBeType === 'timestamp'){
90
+ }
73
91
 
74
- cleanedItem = cleanTimestamp(item);
92
+ if(supposedToBeType === 'number'){
75
93
 
76
- }
94
+ cleanedItem = cleanNumber(item);
77
95
 
78
- if(supposedToBeType === 'uuid'){
96
+ }
79
97
 
80
- cleanedItem = cleanUUID(item);
98
+ if(supposedToBeType === 'string'){
81
99
 
82
- }
83
-
84
- if(supposedToBeType === 'array'){
85
-
86
- cleanedItem = cleanArray(item, schema.items);
87
-
88
- }
100
+ cleanedItem = cleanString(item);
89
101
 
90
- if(supposedToBeType === 'object'){
91
-
92
- cleanedItem = cleanObject(item, schema.items);
93
-
94
- }
102
+ }
95
103
 
96
- if(cleanedItem === null){
104
+ if(supposedToBeType === 'timestamp'){
97
105
 
98
- if(schema.required === true){
106
+ cleanedItem = cleanTimestamp(item);
99
107
 
100
- throw {
101
- message: 'required item is null',
102
- item,
103
- key
104
- };
108
+ }
109
+
110
+ if(supposedToBeType === 'uuid'){
111
+
112
+ cleanedItem = cleanUUID(item);
113
+
114
+ }
105
115
 
106
- } else {
116
+ if(supposedToBeType === 'array'){
117
+
118
+ cleanedItem = cleanArray(item, schema.items, {
119
+ testMode,
120
+ allOrNothing,
121
+ path: path ? `${path}.${key}` : key
122
+ });
123
+
124
+ }
107
125
 
108
- return; // skip this item if it's not required and is null
126
+ if(supposedToBeType === 'object'){
127
+
128
+ cleanedItem = cleanObject(item, schema.items, {
129
+ testMode,
130
+ allOrNothing,
131
+ path: path ? `${path}.${key}` : key
132
+ });
109
133
 
110
134
  }
111
-
112
- }
113
135
 
136
+ if(cleanedItem === null){
137
+
138
+ if(schema.required === true){
139
+
140
+ throw {
141
+ message: 'required item is null',
142
+ item,
143
+ key
144
+ };
145
+
146
+ } else {
147
+
148
+ return; // skip this item if it's not required and is null
149
+
150
+ }
151
+
152
+ }
153
+
154
+
155
+ } catch(err){
156
+
157
+ if(allOrNothing){
158
+
159
+ throw err;
160
+
161
+ } else {
162
+
163
+ const errorPath = path ? `${path}[${key}]` : `[${key}]`;
164
+
165
+ errors[errorPath] = {
166
+ error: err,
167
+ value: item,
168
+ requirements: schema.items
169
+ };
170
+
171
+ }
172
+
173
+ return; // skip this item if there's an error
174
+
175
+ }
114
176
 
115
177
  cleanArrayItems.push(cleanedItem);
116
178
 
117
179
  });
118
-
180
+
181
+ if(Object.keys(errors).length > 0){
182
+
183
+ throw {
184
+ message: 'Array not clean',
185
+ errors
186
+ };
187
+
188
+ }
189
+
119
190
  if(cleanArrayItems.length === 0){
120
191
 
121
192
  throw {
@@ -146,7 +217,11 @@ function cleanArray(arr, schema = {}, testMode = false){
146
217
  }
147
218
 
148
219
 
149
- function cleanObject(obj, schema, testMode = false){
220
+ function cleanObject(obj, schema, {
221
+ testMode = false,
222
+ allOrNothing = false,
223
+ path = ''
224
+ } = {}){
150
225
 
151
226
  validateSchema(schema);
152
227
 
@@ -184,111 +259,142 @@ function cleanObject(obj, schema, testMode = false){
184
259
  }
185
260
 
186
261
  const cleanObj = {};
262
+ const errors = {};
187
263
 
188
264
  // Iterate over the schema keys
189
265
  each(obj, (value, key) => {
190
266
 
191
- const valType = thingType(value);
192
- const supposedToBeType = schema.properties[key].type;
267
+ let cleanedValue;
193
268
 
194
- if(testMode){
195
- console.log(`cleaning ${key}`,{
196
- valType,
197
- supposedToBeType,
198
- value,
199
- });
200
- }
269
+ try {
201
270
 
202
- if(valType !== supposedToBeType){
271
+ const valType = thingType(value);
272
+ const supposedToBeType = schema.properties[key].type;
203
273
 
204
- throw {
205
- message: 'type invalid',
206
- valType,
207
- supposedToBeType,
208
- key
209
- };
274
+ if(testMode){
275
+ console.log(`cleaning ${key}`,{
276
+ valType,
277
+ supposedToBeType,
278
+ value,
279
+ });
280
+ }
210
281
 
211
- }
282
+ if(valType !== supposedToBeType){
212
283
 
213
- let cleanedValue;
284
+ throw {
285
+ message: 'type invalid',
286
+ valType,
287
+ supposedToBeType,
288
+ key
289
+ };
214
290
 
215
- const knownTypesToClean = [
216
- 'boolean',
217
- 'integer',
218
- 'number',
219
- 'string',
220
- 'timestamp',
221
- 'uuid',
222
- 'object',
223
- 'array'
224
- ];
291
+ }
225
292
 
226
- if(!knownTypesToClean.includes(supposedToBeType)){
227
293
 
228
- throw {
229
- message: 'Unknown type to clean in schema',
230
- supposedToBeType,
231
- key
232
- };
294
+ if(!knownTypesToClean.includes(supposedToBeType)){
233
295
 
234
- }
296
+ throw {
297
+ message: 'Unknown type to clean in schema',
298
+ supposedToBeType,
299
+ key
300
+ };
235
301
 
236
-
237
- if(testMode){ console.log('cleaning boolean', value); }
302
+ }
238
303
 
304
+
305
+ if(testMode){ console.log(`cleaning ${supposedToBeType}`, value, schema.properties[key]); }
239
306
 
240
- if(supposedToBeType === 'boolean'){
241
307
 
242
- cleanedValue = cleanBoolean(value, schema.properties[key]);
308
+ if(supposedToBeType === 'boolean'){
243
309
 
244
- }
310
+ cleanedValue = cleanBoolean(value, schema.properties[key]);
245
311
 
246
- if(supposedToBeType === 'integer'){
312
+ }
247
313
 
248
- cleanedValue = cleanInteger(value, schema.properties[key]);
314
+ if(supposedToBeType === 'integer'){
249
315
 
250
- }
316
+ cleanedValue = cleanInteger(value, schema.properties[key]);
251
317
 
252
- if(supposedToBeType === 'number'){
318
+ }
253
319
 
254
- cleanedValue = cleanNumber(value, schema.properties[key]);
320
+ if(supposedToBeType === 'number'){
255
321
 
256
- }
322
+ cleanedValue = cleanNumber(value, schema.properties[key]);
257
323
 
258
- if(supposedToBeType === 'string'){
324
+ }
259
325
 
260
- cleanedValue = cleanString(value, schema.properties[key]);
326
+ if(supposedToBeType === 'string'){
261
327
 
262
- }
328
+ cleanedValue = cleanString(value, schema.properties[key]);
263
329
 
264
- if(supposedToBeType === 'timestamp'){
330
+ }
265
331
 
266
- cleanedValue = cleanTimestamp(value, schema.properties[key]);
332
+ if(supposedToBeType === 'timestamp'){
267
333
 
268
- }
334
+ cleanedValue = cleanTimestamp(value, schema.properties[key]);
269
335
 
270
- if(supposedToBeType === 'uuid'){
336
+ }
271
337
 
272
- cleanedValue = cleanUUID(value, schema.properties[key]);
338
+ if(supposedToBeType === 'uuid'){
273
339
 
274
- }
340
+ cleanedValue = cleanUUID(value, schema.properties[key]);
275
341
 
276
- if(supposedToBeType === 'object'){
342
+ }
277
343
 
278
- cleanedValue = cleanObject(value, schema.properties[key]);
279
-
280
- }
344
+ if(supposedToBeType === 'object'){
345
+
346
+ cleanedValue = cleanObject(value, schema.properties[key], {
347
+ testMode,
348
+ allOrNothing,
349
+ path: path ? `${path}.${key}` : key
350
+ });
351
+
352
+ }
353
+
354
+ if(supposedToBeType === 'array'){
355
+
356
+ cleanedValue = cleanArray(value, schema.properties[key], {
357
+ testMode,
358
+ allOrNothing,
359
+ path: path ? `${path}.${key}` : key
360
+ });
361
+
362
+ }
363
+
364
+ } catch (err) {
365
+
366
+ if(allOrNothing){
367
+
368
+ throw err;
369
+
370
+ } else {
371
+
372
+ const errorPath = path ? `${path}.${key}` : key;
373
+
374
+ errors[errorPath] = {
375
+ error: err,
376
+ value: value,
377
+ requirements: schema.properties[key]
378
+ };
379
+
380
+ }
281
381
 
282
- if(supposedToBeType === 'array'){
283
382
 
284
- cleanedValue = cleanArray(value, schema.properties[key]);
285
-
286
383
  }
287
384
 
288
385
  cleanObj[key] = cleanedValue;
289
386
 
290
387
  });
291
388
 
389
+ if(Object.keys(errors).length > 0){
390
+
391
+ throw {
392
+ message: 'Object not clean',
393
+ errors
394
+ };
395
+
396
+ }
397
+
292
398
  return cleanObj;
293
399
 
294
400
  }
@@ -1,2 +1,6 @@
1
- declare const _default: (arr: any, schema?: {}) => any[];
1
+ declare const _default: (arr: any, schema?: {}, { testMode, allOrNothing, path }?: {
2
+ testMode?: boolean;
3
+ allOrNothing?: boolean;
4
+ path?: string;
5
+ }) => any[];
2
6
  export default _default;
@@ -0,0 +1,4 @@
1
+ export default function cleanCustom(value: any, { required, validate, }?: {
2
+ required?: boolean;
3
+ validate?: any;
4
+ }): any;
@@ -0,0 +1,11 @@
1
+ export default function cleanFile(file: any, { required, validTypes, minSize, maxSize, }?: {
2
+ required?: boolean;
3
+ validTypes?: any[];
4
+ minSize?: boolean;
5
+ maxSize?: boolean;
6
+ }): {
7
+ name: any;
8
+ type: any;
9
+ size: any;
10
+ lastModified: string;
11
+ };
@@ -1,2 +1,6 @@
1
- declare const _default: (obj: any, schema: any) => {};
1
+ declare const _default: (obj: any, schema: any, { testMode, allOrNothing, path }?: {
2
+ testMode?: boolean;
3
+ allOrNothing?: boolean;
4
+ path?: string;
5
+ }) => {};
2
6
  export default _default;
package/types/index.d.ts CHANGED
@@ -6,6 +6,8 @@
6
6
  import type _build from './build';
7
7
  import type _clean_array from './clean/array';
8
8
  import type _clean_boolean from './clean/boolean';
9
+ import type _clean_custom from './clean/custom';
10
+ import type _clean_file from './clean/file';
9
11
  import type _clean_integer from './clean/integer';
10
12
  import type _clean_number from './clean/number';
11
13
  import type _clean_object from './clean/object';
@@ -64,6 +66,8 @@ export declare const wait: typeof _wait;
64
66
  export declare const clean: {
65
67
  array: typeof _clean_array;
66
68
  boolean: typeof _clean_boolean;
69
+ custom: typeof _clean_custom;
70
+ file: typeof _clean_file;
67
71
  integer: typeof _clean_integer;
68
72
  number: typeof _clean_number;
69
73
  object: typeof _clean_object;
@@ -141,6 +145,8 @@ declare const _default: {
141
145
  clean: {
142
146
  array: typeof _clean_array,
143
147
  boolean: typeof _clean_boolean,
148
+ custom: typeof _clean_custom,
149
+ file: typeof _clean_file,
144
150
  integer: typeof _clean_integer,
145
151
  number: typeof _clean_number,
146
152
  object: typeof _clean_object,
@@ -9,8 +9,16 @@ declare namespace _default {
9
9
  export { cleanUUID as uuid };
10
10
  }
11
11
  export default _default;
12
- declare function cleanArray(arr: any, schema?: {}): any[];
13
- declare function cleanObject(obj: any, schema: any): {};
12
+ declare function cleanArray(arr: any, schema?: {}, { testMode, allOrNothing, path }?: {
13
+ testMode?: boolean;
14
+ allOrNothing?: boolean;
15
+ path?: string;
16
+ }): any[];
17
+ declare function cleanObject(obj: any, schema: any, { testMode, allOrNothing, path }?: {
18
+ testMode?: boolean;
19
+ allOrNothing?: boolean;
20
+ path?: string;
21
+ }): {};
14
22
  import cleanBoolean from '../clean/boolean.js';
15
23
  import cleanInteger from '../clean/integer.js';
16
24
  import cleanNumber from '../clean/number.js';