@palmares/schemas 0.0.1 → 0.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.
Files changed (174) hide show
  1. package/.turbo/turbo-build$colon$watch.log +12 -410
  2. package/CHANGELOG.md +17 -0
  3. package/__tests__/.drizzle/migrations/0000_skinny_harrier.sql +22 -0
  4. package/__tests__/.drizzle/migrations/meta/0000_snapshot.json +156 -0
  5. package/__tests__/.drizzle/migrations/meta/_journal.json +13 -0
  6. package/__tests__/.drizzle/schema.ts +35 -0
  7. package/__tests__/drizzle.config.ts +11 -0
  8. package/__tests__/eslint.config.js +10 -0
  9. package/__tests__/manage.ts +5 -0
  10. package/__tests__/node_modules/.bin/drizzle-kit +17 -0
  11. package/__tests__/node_modules/.bin/esbuild +14 -0
  12. package/__tests__/node_modules/.bin/tsc +17 -0
  13. package/__tests__/node_modules/.bin/tsserver +17 -0
  14. package/__tests__/node_modules/.bin/tsx +17 -0
  15. package/__tests__/package.json +36 -0
  16. package/__tests__/sqlite.db +0 -0
  17. package/__tests__/src/core/array.test.ts +130 -0
  18. package/__tests__/src/core/boolean.test.ts +66 -0
  19. package/__tests__/src/core/datetime.test.ts +102 -0
  20. package/__tests__/src/core/index.ts +35 -0
  21. package/__tests__/src/core/model.test.ts +260 -0
  22. package/__tests__/src/core/models.ts +50 -0
  23. package/__tests__/src/core/numbers.test.ts +177 -0
  24. package/__tests__/src/core/object.test.ts +198 -0
  25. package/__tests__/src/core/string.test.ts +222 -0
  26. package/__tests__/src/core/test.test.ts +59 -0
  27. package/__tests__/src/core/types.test.ts +97 -0
  28. package/__tests__/src/core/union.test.ts +99 -0
  29. package/__tests__/src/settings.ts +71 -0
  30. package/__tests__/tsconfig.json +11 -0
  31. package/dist/cjs/src/adapter/fields/index.js +2 -2
  32. package/dist/cjs/src/adapter/fields/object.js +9 -0
  33. package/dist/cjs/src/adapter/index.js +1 -0
  34. package/dist/cjs/src/constants.js +1 -7
  35. package/dist/cjs/src/domain.js +146 -1
  36. package/dist/cjs/src/index.js +69 -74
  37. package/dist/cjs/src/model.js +206 -206
  38. package/dist/cjs/src/schema/array.js +185 -58
  39. package/dist/cjs/src/schema/boolean.js +105 -44
  40. package/dist/cjs/src/schema/datetime.js +104 -38
  41. package/dist/cjs/src/schema/number.js +134 -114
  42. package/dist/cjs/src/schema/object.js +106 -43
  43. package/dist/cjs/src/schema/schema.js +123 -75
  44. package/dist/cjs/src/schema/string.js +152 -58
  45. package/dist/cjs/src/schema/union.js +412 -290
  46. package/dist/cjs/src/utils.js +42 -15
  47. package/dist/cjs/src/validators/array.js +6 -1
  48. package/dist/cjs/src/validators/boolean.js +2 -0
  49. package/dist/cjs/src/validators/datetime.js +4 -0
  50. package/dist/cjs/src/validators/number.js +12 -40
  51. package/dist/cjs/src/validators/object.js +1 -0
  52. package/dist/cjs/src/validators/schema.js +5 -1
  53. package/dist/cjs/src/validators/string.js +30 -2
  54. package/dist/cjs/src/validators/union.js +5 -4
  55. package/dist/cjs/src/validators/utils.js +99 -27
  56. package/dist/cjs/tsconfig.types.tsbuildinfo +1 -1
  57. package/dist/cjs/types/adapter/fields/array.d.ts +2 -2
  58. package/dist/cjs/types/adapter/fields/array.d.ts.map +1 -1
  59. package/dist/cjs/types/adapter/fields/boolean.d.ts.map +1 -1
  60. package/dist/cjs/types/adapter/fields/datetime.d.ts.map +1 -1
  61. package/dist/cjs/types/adapter/fields/index.d.ts +2 -2
  62. package/dist/cjs/types/adapter/fields/index.d.ts.map +1 -1
  63. package/dist/cjs/types/adapter/fields/number.d.ts.map +1 -1
  64. package/dist/cjs/types/adapter/fields/object.d.ts +2 -1
  65. package/dist/cjs/types/adapter/fields/object.d.ts.map +1 -1
  66. package/dist/cjs/types/adapter/fields/string.d.ts.map +1 -1
  67. package/dist/cjs/types/adapter/fields/union.d.ts.map +1 -1
  68. package/dist/cjs/types/adapter/index.d.ts +1 -0
  69. package/dist/cjs/types/adapter/index.d.ts.map +1 -1
  70. package/dist/cjs/types/adapter/types.d.ts +28 -18
  71. package/dist/cjs/types/adapter/types.d.ts.map +1 -1
  72. package/dist/cjs/types/constants.d.ts +0 -1
  73. package/dist/cjs/types/constants.d.ts.map +1 -1
  74. package/dist/cjs/types/domain.d.ts +5 -4
  75. package/dist/cjs/types/domain.d.ts.map +1 -1
  76. package/dist/cjs/types/index.d.ts +78 -55
  77. package/dist/cjs/types/index.d.ts.map +1 -1
  78. package/dist/cjs/types/model.d.ts +17 -17
  79. package/dist/cjs/types/model.d.ts.map +1 -1
  80. package/dist/cjs/types/schema/array.d.ts +168 -47
  81. package/dist/cjs/types/schema/array.d.ts.map +1 -1
  82. package/dist/cjs/types/schema/boolean.d.ts +103 -44
  83. package/dist/cjs/types/schema/boolean.d.ts.map +1 -1
  84. package/dist/cjs/types/schema/datetime.d.ts +90 -30
  85. package/dist/cjs/types/schema/datetime.d.ts.map +1 -1
  86. package/dist/cjs/types/schema/number.d.ts +133 -125
  87. package/dist/cjs/types/schema/number.d.ts.map +1 -1
  88. package/dist/cjs/types/schema/object.d.ts +104 -35
  89. package/dist/cjs/types/schema/object.d.ts.map +1 -1
  90. package/dist/cjs/types/schema/schema.d.ts +62 -44
  91. package/dist/cjs/types/schema/schema.d.ts.map +1 -1
  92. package/dist/cjs/types/schema/string.d.ts +152 -65
  93. package/dist/cjs/types/schema/string.d.ts.map +1 -1
  94. package/dist/cjs/types/schema/types.d.ts +11 -2
  95. package/dist/cjs/types/schema/types.d.ts.map +1 -1
  96. package/dist/cjs/types/schema/union.d.ts +133 -40
  97. package/dist/cjs/types/schema/union.d.ts.map +1 -1
  98. package/dist/cjs/types/types.d.ts +35 -0
  99. package/dist/cjs/types/types.d.ts.map +1 -1
  100. package/dist/cjs/types/utils.d.ts +41 -27
  101. package/dist/cjs/types/utils.d.ts.map +1 -1
  102. package/dist/cjs/types/validators/array.d.ts.map +1 -1
  103. package/dist/cjs/types/validators/boolean.d.ts.map +1 -1
  104. package/dist/cjs/types/validators/datetime.d.ts.map +1 -1
  105. package/dist/cjs/types/validators/number.d.ts +5 -6
  106. package/dist/cjs/types/validators/number.d.ts.map +1 -1
  107. package/dist/cjs/types/validators/object.d.ts.map +1 -1
  108. package/dist/cjs/types/validators/schema.d.ts +2 -2
  109. package/dist/cjs/types/validators/schema.d.ts.map +1 -1
  110. package/dist/cjs/types/validators/string.d.ts +9 -9
  111. package/dist/cjs/types/validators/string.d.ts.map +1 -1
  112. package/dist/cjs/types/validators/utils.d.ts +44 -27
  113. package/dist/cjs/types/validators/utils.d.ts.map +1 -1
  114. package/dist/esm/src/adapter/fields/index.js +2 -2
  115. package/dist/esm/src/adapter/fields/object.js +6 -0
  116. package/dist/esm/src/adapter/index.js +1 -0
  117. package/dist/esm/src/constants.js +1 -2
  118. package/dist/esm/src/domain.js +11 -1
  119. package/dist/esm/src/index.js +38 -73
  120. package/dist/esm/src/model.js +83 -78
  121. package/dist/esm/src/schema/array.js +136 -54
  122. package/dist/esm/src/schema/boolean.js +98 -44
  123. package/dist/esm/src/schema/datetime.js +91 -38
  124. package/dist/esm/src/schema/number.js +127 -110
  125. package/dist/esm/src/schema/object.js +98 -43
  126. package/dist/esm/src/schema/schema.js +102 -67
  127. package/dist/esm/src/schema/string.js +147 -59
  128. package/dist/esm/src/schema/union.js +119 -40
  129. package/dist/esm/src/types.js +14 -1
  130. package/dist/esm/src/utils.js +56 -27
  131. package/dist/esm/src/validators/array.js +6 -1
  132. package/dist/esm/src/validators/boolean.js +2 -0
  133. package/dist/esm/src/validators/datetime.js +4 -0
  134. package/dist/esm/src/validators/number.js +9 -23
  135. package/dist/esm/src/validators/object.js +1 -0
  136. package/dist/esm/src/validators/schema.js +5 -1
  137. package/dist/esm/src/validators/string.js +30 -2
  138. package/dist/esm/src/validators/union.js +5 -4
  139. package/dist/esm/src/validators/utils.js +62 -36
  140. package/package.json +3 -3
  141. package/src/adapter/fields/array.ts +2 -2
  142. package/src/adapter/fields/boolean.ts +3 -8
  143. package/src/adapter/fields/datetime.ts +3 -9
  144. package/src/adapter/fields/index.ts +11 -11
  145. package/src/adapter/fields/number.ts +3 -9
  146. package/src/adapter/fields/object.ts +13 -10
  147. package/src/adapter/fields/string.ts +3 -9
  148. package/src/adapter/fields/union.ts +3 -9
  149. package/src/adapter/index.ts +1 -0
  150. package/src/adapter/types.ts +60 -45
  151. package/src/constants.ts +1 -3
  152. package/src/domain.ts +15 -1
  153. package/src/index.ts +189 -211
  154. package/src/model.ts +119 -115
  155. package/src/schema/array.ts +274 -90
  156. package/src/schema/boolean.ts +145 -60
  157. package/src/schema/datetime.ts +133 -49
  158. package/src/schema/number.ts +210 -173
  159. package/src/schema/object.ts +167 -74
  160. package/src/schema/schema.ts +205 -126
  161. package/src/schema/string.ts +221 -94
  162. package/src/schema/types.ts +44 -16
  163. package/src/schema/union.ts +193 -68
  164. package/src/types.ts +53 -0
  165. package/src/utils.ts +115 -57
  166. package/src/validators/array.ts +46 -27
  167. package/src/validators/boolean.ts +13 -7
  168. package/src/validators/datetime.ts +24 -16
  169. package/src/validators/number.ts +53 -63
  170. package/src/validators/object.ts +6 -5
  171. package/src/validators/schema.ts +33 -25
  172. package/src/validators/string.ts +122 -59
  173. package/src/validators/union.ts +8 -8
  174. package/src/validators/utils.ts +67 -42
@@ -1,11 +1,18 @@
1
+ import { type ValidationFallbackReturnType } from '../schema/types';
2
+
1
3
  import type Schema from '../schema/schema';
2
4
  import type StringSchema from '../schema/string';
3
- import { type ValidationFallbackReturnType } from '../schema/types';
4
5
 
5
6
  export function stringValidation(): ValidationFallbackReturnType {
6
7
  return {
8
+ name: 'string',
7
9
  type: 'medium',
8
- callback: async (value: any, path: (string | number)[], _options: Parameters<Schema['__transformToAdapter']>[0]) => {
10
+ // eslint-disable-next-line ts/require-await
11
+ callback: async (
12
+ value: any,
13
+ path: (string | number)[],
14
+ _options: Parameters<Schema['__transformToAdapter']>[0]
15
+ ) => {
9
16
  return {
10
17
  parsed: value,
11
18
  errors:
@@ -15,20 +22,27 @@ export function stringValidation(): ValidationFallbackReturnType {
15
22
  {
16
23
  isValid: typeof value === 'string',
17
24
  code: 'string',
25
+ // eslint-disable-next-line ts/no-unnecessary-condition
18
26
  path: path || [],
19
- message: 'The value must be a string. Received: ' + typeof value,
20
- },
21
- ],
27
+ message: 'The value must be a string. Received: ' + typeof value
28
+ }
29
+ ]
22
30
  };
23
- },
31
+ }
24
32
  };
25
33
  }
26
34
 
27
- export function maxLength(args: StringSchema['__maxLength']): ValidationFallbackReturnType {
35
+ export function maxLength(args: NonNullable<StringSchema['__maxLength']>): ValidationFallbackReturnType {
28
36
  return {
37
+ name: 'maxLength',
29
38
  type: 'low',
30
- callback: async (value: any, path: (string | number)[], _options: Parameters<Schema['__transformToAdapter']>[0]) => {
31
- const isValid = args.inclusive ? value.length <= args.value : value.length < args.value;
39
+ // eslint-disable-next-line ts/require-await
40
+ callback: async (
41
+ value: any,
42
+ path: (string | number)[],
43
+ _options: Parameters<Schema['__transformToAdapter']>[0]
44
+ ) => {
45
+ const isValid = value.length <= args.value;
32
46
 
33
47
  return {
34
48
  parsed: value,
@@ -38,20 +52,27 @@ export function maxLength(args: StringSchema['__maxLength']): ValidationFallback
38
52
  {
39
53
  isValid: false,
40
54
  code: 'maxLength',
55
+ // eslint-disable-next-line ts/no-unnecessary-condition
41
56
  path: path || [],
42
- message: args.message,
43
- },
44
- ],
57
+ message: args.message
58
+ }
59
+ ]
45
60
  };
46
- },
61
+ }
47
62
  };
48
63
  }
49
64
 
50
- export function minLength(args: StringSchema['__maxLength']): ValidationFallbackReturnType {
65
+ export function minLength(args: NonNullable<StringSchema['__maxLength']>): ValidationFallbackReturnType {
51
66
  return {
67
+ name: 'minLength',
52
68
  type: 'low',
53
- callback: async (value: any, path: (string | number)[], _options: Parameters<Schema['__transformToAdapter']>[0]) => {
54
- const isValid = args.inclusive ? value.length >= args.value : value.length > args.value;
69
+ // eslint-disable-next-line ts/require-await
70
+ callback: async (
71
+ value: any,
72
+ path: (string | number)[],
73
+ _options: Parameters<Schema['__transformToAdapter']>[0]
74
+ ) => {
75
+ const isValid = value.length >= args.value;
55
76
 
56
77
  return {
57
78
  parsed: value,
@@ -61,19 +82,26 @@ export function minLength(args: StringSchema['__maxLength']): ValidationFallback
61
82
  {
62
83
  isValid: false,
63
84
  code: 'minLength',
85
+ // eslint-disable-next-line ts/no-unnecessary-condition
64
86
  path: path || [],
65
- message: args.message,
66
- },
67
- ],
87
+ message: args.message
88
+ }
89
+ ]
68
90
  };
69
- },
91
+ }
70
92
  };
71
93
  }
72
94
 
73
- export function endsWith(args: StringSchema['__endsWith']): ValidationFallbackReturnType {
95
+ export function endsWith(args: NonNullable<StringSchema['__endsWith']>): ValidationFallbackReturnType {
74
96
  return {
97
+ name: 'endsWith',
75
98
  type: 'low',
76
- callback: async (value: any, path: (string | number)[], _options: Parameters<Schema['__transformToAdapter']>[0]) => {
99
+ // eslint-disable-next-line ts/require-await
100
+ callback: async (
101
+ value: any,
102
+ path: (string | number)[],
103
+ _options: Parameters<Schema['__transformToAdapter']>[0]
104
+ ) => {
77
105
  const isValid = value.endsWith(args.value);
78
106
 
79
107
  return {
@@ -84,19 +112,26 @@ export function endsWith(args: StringSchema['__endsWith']): ValidationFallbackRe
84
112
  {
85
113
  isValid: false,
86
114
  code: 'endsWith',
115
+ // eslint-disable-next-line ts/no-unnecessary-condition
87
116
  path: path || [],
88
- message: args.message,
89
- },
90
- ],
117
+ message: args.message
118
+ }
119
+ ]
91
120
  };
92
- },
121
+ }
93
122
  };
94
123
  }
95
124
 
96
- export function startsWith(args: StringSchema['__startsWith']): ValidationFallbackReturnType {
125
+ export function startsWith(args: NonNullable<StringSchema['__startsWith']>): ValidationFallbackReturnType {
97
126
  return {
127
+ name: 'startsWith',
98
128
  type: 'low',
99
- callback: async (value: any, path: (string | number)[], _options: Parameters<Schema['__transformToAdapter']>[0]) => {
129
+ // eslint-disable-next-line ts/require-await
130
+ callback: async (
131
+ value: any,
132
+ path: (string | number)[],
133
+ _options: Parameters<Schema['__transformToAdapter']>[0]
134
+ ) => {
100
135
  const isValid = value.startsWith(args.value);
101
136
 
102
137
  return {
@@ -107,19 +142,26 @@ export function startsWith(args: StringSchema['__startsWith']): ValidationFallba
107
142
  {
108
143
  isValid: false,
109
144
  code: 'startsWith',
145
+ // eslint-disable-next-line ts/no-unnecessary-condition
110
146
  path: path || [],
111
- message: args.message,
112
- },
113
- ],
147
+ message: args.message
148
+ }
149
+ ]
114
150
  };
115
- },
151
+ }
116
152
  };
117
153
  }
118
154
 
119
- export function includes(args: StringSchema['__includes']): ValidationFallbackReturnType {
155
+ export function includes(args: NonNullable<StringSchema['__includes']>): ValidationFallbackReturnType {
120
156
  return {
157
+ name: 'includes',
121
158
  type: 'low',
122
- callback: async (value: any, path: (string | number)[], _options: Parameters<Schema['__transformToAdapter']>[0]) => {
159
+ // eslint-disable-next-line ts/require-await
160
+ callback: async (
161
+ value: any,
162
+ path: (string | number)[],
163
+ _options: Parameters<Schema['__transformToAdapter']>[0]
164
+ ) => {
123
165
  const isValid = value.includes(args.value);
124
166
 
125
167
  return {
@@ -130,19 +172,26 @@ export function includes(args: StringSchema['__includes']): ValidationFallbackRe
130
172
  {
131
173
  isValid: false,
132
174
  code: 'includes',
175
+ // eslint-disable-next-line ts/no-unnecessary-condition
133
176
  path: path || [],
134
- message: args.message,
135
- },
136
- ],
177
+ message: args.message
178
+ }
179
+ ]
137
180
  };
138
- },
181
+ }
139
182
  };
140
183
  }
141
184
 
142
- export function regex(args: StringSchema['__regex']): ValidationFallbackReturnType {
185
+ export function regex(args: NonNullable<StringSchema['__regex']>): ValidationFallbackReturnType {
143
186
  return {
187
+ name: 'regex',
144
188
  type: 'low',
145
- callback: async (value: any, path: (string | number)[], _options: Parameters<Schema['__transformToAdapter']>[0]) => {
189
+ // eslint-disable-next-line ts/require-await
190
+ callback: async (
191
+ value: any,
192
+ path: (string | number)[],
193
+ _options: Parameters<Schema['__transformToAdapter']>[0]
194
+ ) => {
146
195
  const isValid = args.value.test(value);
147
196
 
148
197
  return {
@@ -153,23 +202,29 @@ export function regex(args: StringSchema['__regex']): ValidationFallbackReturnTy
153
202
  {
154
203
  isValid: false,
155
204
  code: 'regex',
205
+ // eslint-disable-next-line ts/no-unnecessary-condition
156
206
  path: path || [],
157
- message: args.message,
158
- },
159
- ],
207
+ message: args.message
208
+ }
209
+ ]
160
210
  };
161
- },
211
+ }
162
212
  };
163
213
  }
164
214
 
165
- export function uuid(args: StringSchema['__uuid']): ValidationFallbackReturnType {
215
+ export function uuid(args: NonNullable<StringSchema['__uuid']>): ValidationFallbackReturnType {
166
216
  // const uuidRegex =
167
217
  // /^([a-f0-9]{8}-[a-f0-9]{4}-[1-5][a-f0-9]{3}-[a-f0-9]{4}-[a-f0-9]{12}|00000000-0000-0000-0000-000000000000)$/i;
168
- const uuidRegex =
169
- /^[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}$/i;
218
+ const uuidRegex = /^[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}$/i;
170
219
  return {
220
+ name: 'uuid',
171
221
  type: 'low',
172
- callback: async (value: any, path: (string | number)[], _options: Parameters<Schema['__transformToAdapter']>[0]) => {
222
+ // eslint-disable-next-line ts/require-await
223
+ callback: async (
224
+ value: any,
225
+ path: (string | number)[],
226
+ _options: Parameters<Schema['__transformToAdapter']>[0]
227
+ ) => {
173
228
  const isValid = uuidRegex.test(value);
174
229
 
175
230
  return {
@@ -180,20 +235,28 @@ export function uuid(args: StringSchema['__uuid']): ValidationFallbackReturnType
180
235
  {
181
236
  isValid: false,
182
237
  code: 'uuid',
238
+ // eslint-disable-next-line ts/no-unnecessary-condition
183
239
  path: path || [],
184
- message: args.message,
185
- },
186
- ],
240
+ message: args.message
241
+ }
242
+ ]
187
243
  };
188
244
  }
189
- }
245
+ };
190
246
  }
191
247
 
192
- export function email(args: StringSchema['__email']): ValidationFallbackReturnType {
248
+ export function email(args: NonNullable<StringSchema['__email']>): ValidationFallbackReturnType {
193
249
  const emailRegex = /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i;
250
+ console.log('aquiiiiii');
194
251
  return {
252
+ name: 'email',
195
253
  type: 'low',
196
- callback: async (value: any, path: (string | number)[], _options: Parameters<Schema['__transformToAdapter']>[0]) => {
254
+ // eslint-disable-next-line ts/require-await
255
+ callback: async (
256
+ value: any,
257
+ path: (string | number)[],
258
+ _options: Parameters<Schema['__transformToAdapter']>[0]
259
+ ) => {
197
260
  const isValid = emailRegex.test(value);
198
261
 
199
262
  return {
@@ -204,12 +267,12 @@ export function email(args: StringSchema['__email']): ValidationFallbackReturnTy
204
267
  {
205
268
  isValid: false,
206
269
  code: 'email',
270
+ // eslint-disable-next-line ts/no-unnecessary-condition
207
271
  path: path || [],
208
- message: args.message,
209
- },
210
- ],
272
+ message: args.message
273
+ }
274
+ ]
211
275
  };
212
276
  }
213
- }
277
+ };
214
278
  }
215
-
@@ -5,11 +5,12 @@ export function unionValidation(
5
5
  schemas: readonly [Schema<any, any>, Schema<any, any>, ...Schema<any, any>[]]
6
6
  ): ValidationFallbackReturnType {
7
7
  return {
8
- type: 'high',
8
+ name: 'union',
9
+ type: 'medium',
9
10
  callback: async (value, path, options) => {
10
11
  const parsedValues: Awaited<ReturnType<Schema['__parse']>> = {
11
12
  parsed: value,
12
- errors: [],
13
+ errors: []
13
14
  };
14
15
  const startingToInternalBubbleUpLength = options.toInternalToBubbleUp?.length || 0;
15
16
 
@@ -31,22 +32,21 @@ export function unionValidation(
31
32
  if (hasNoErrorsSoItsAValidSchemaAndShouldResetOldErrors) {
32
33
  return {
33
34
  parsed: parsedValues.parsed,
34
- errors: [],
35
+ errors: []
35
36
  };
36
37
  } else if (startingToInternalBubbleUpLength < (options.toInternalToBubbleUp?.length || 0)) {
37
- // If there is a new toInternalToBubbleUp we should remove the ones that we added since this is not a valid schema,
38
- // we shouldn't be calling the `toInternal` on that schemas.
38
+ // If there is a new toInternalToBubbleUp we should remove the ones that we added since this is not a
39
+ // valid schema, we shouldn't be calling the `toInternal` on that schemas.
39
40
  const numberOfElementsToRemove =
40
41
  (options.toInternalToBubbleUp?.length || 0) - startingToInternalBubbleUpLength;
41
42
  options.toInternalToBubbleUp?.splice(startingToInternalBubbleUpLength, numberOfElementsToRemove);
42
43
  }
43
44
  }
44
-
45
45
  return {
46
46
  parsed: parsedValues.parsed,
47
47
  // eslint-disable-next-line ts/no-unnecessary-condition
48
- errors: parsedValues.errors ? parsedValues.errors : [],
48
+ errors: Array.isArray(parsedValues.errors) ? parsedValues.errors : []
49
49
  };
50
- },
50
+ }
51
51
  };
52
52
  }
@@ -4,13 +4,13 @@ import type Schema from '../schema/schema';
4
4
  import type {
5
5
  ValidationFallbackCallbackReturnType,
6
6
  ValidationFallbackCallbackType,
7
- ValidationFallbackReturnType,
7
+ ValidationFallbackReturnType
8
8
  } from '../schema/types';
9
9
 
10
10
  const priorityByType = {
11
11
  low: 0,
12
12
  medium: 1,
13
- high: 2,
13
+ high: 2
14
14
  };
15
15
 
16
16
  const typeByPriority = Object.entries(priorityByType).reduce(
@@ -22,24 +22,30 @@ const typeByPriority = Object.entries(priorityByType).reduce(
22
22
  );
23
23
 
24
24
  /**
25
- * Okay, so what is this? This is a validator class, it represents a Node on a linked list. The linked list has lower priority validators on the end of the list and higher
26
- * priority validators on the start of the list. Maybe in the future we can change that to a binary tree, but for now this is enough.
25
+ * Okay, so what is this? This is a validator class, it represents a Node on a linked list. The linked list
26
+ * has lower priority validators on the end of the list and higher priority validators on the start of the
27
+ * list. Maybe in the future we can change that to a binary tree, but for now this is enough.
27
28
  *
28
- * Why did we choose this approach? Because what i was doing was that i saw myself repeating the same code 3 times on the schema in order to make the validation work. Each validator had
29
- * a different return type, i didn't like that. I wanted to add more power and control on the validator, not on the schema. So i created this class. So pretty much, over here and
30
- * on each validator we can define the type it is. It can actually be three: `low`, `medium` and `high`. The `low` validators are the ones that are going to be executed last, the `high` validators
31
- * are the ones that are going to be executed first. High validators validate if the value is null or undefined, if it allows that. It can stop the execution of the other validators if it wants to.
29
+ * Why did we choose this approach? Because what i was doing was that i saw myself repeating the same code 3
30
+ * times on the schema in order to make the validation work. Each validator had a different return type, i
31
+ * didn't like that. I wanted to add more power and control on the validator, not on the schema. So i created
32
+ * this class. So pretty much, over here and on each validator we can define the type it is. It can actually
33
+ * be three: `low`, `medium` and `high`. The `low` validators are the ones that are going to be executed last,
34
+ * The `high` validators are the ones that are going to be executed first. High validators validate if the value
35
+ * is null or undefined, if it allows that. It can stop the execution of the other validators if it wants to.
32
36
  *
33
- * Example: Let's say that the value is null, if the value is null, is there a reason to check if it's a number? No, right? So the high validator can stop the execution of the other validators.
34
- * Same as before, if the value is not a number, is there a reason to check if it's value is greater than the `max` allowed 10? No, right? So the medium validator can stop the execution of
35
- * the other validators.
37
+ * Example: Let's say that the value is null, if the value is null, is there a reason to check if it's a number?
38
+ * No, right? So the high validator can stop the execution of the other validators.
39
+ * Same as before, if the value is not a number, is there a reason to check if it's value is greater than the
40
+ * `max` allowed 10? No, right? So the medium validator can stop the execution of the other validators.
36
41
  *
37
- * That's what this solve, it's a better approach than repeating the same code 3 times on the schema. It's also more powerful, because if we need to add any extra priorities we can do that easily
38
- * without changing the schema.
42
+ * That's what this solve, it's a better approach than repeating the same code 3 times on the schema. It's also
43
+ * more powerful, because if we need to add any extra priorities we can do that easily without changing the schema.
39
44
  */
40
45
  export default class Validator {
41
46
  child?: Validator;
42
47
  parent?: Validator;
48
+ fallbackNamesAdded = new Set();
43
49
  priority: number;
44
50
  fallbacks: ((
45
51
  value: any,
@@ -57,19 +63,27 @@ export default class Validator {
57
63
  }>)[] = [];
58
64
 
59
65
  constructor(type: ValidatorTypes) {
66
+ this.fallbackNamesAdded = new Set();
67
+ this.fallbacks = [];
60
68
  this.priority = priorityByType[type];
61
69
  }
62
70
 
63
71
  /**
64
- * We create all of the validators on the schema in order, i actually didn't want to go on that route but i found it easier to do so.
72
+ * We create all of the validators on the schema in order, i actually didn't want to go on that route but i
73
+ * found it easier to do so.
65
74
  *
66
- * The logic here is simple, if it's not the same priority we will walk on the linked list until we find a validator that matches the priority we are expecting. If we can't walk anymore, we create
67
- * the next priority validator and append it to the linked list. Be aware that it's a double linked list, so we can walk both ways, from the end to the start and from the start to the end.
68
- * So you don't really need to start from the root, the linked list can start from anywhere and it will find it's way through.
75
+ * The logic here is simple, if it's not the same priority we will walk on the linked list until we find
76
+ * a validator that matches the priority we are expecting. If we can't walk anymore, we create the next
77
+ * priority validator and append it to the linked list. Be aware that it's a double linked list, so we
78
+ * can walk both ways, from the end to the start and from the start to the end.
79
+ * So you don't really need to start from the root, the linked list can start from anywhere and it will
80
+ * find it's way through.
69
81
  *
70
- * I know there are better ways to do this instead of walking through the linked list, but like i explained before, this is enough for now.
82
+ * I know there are better ways to do this instead of walking through the linked list, but like i explained
83
+ * before, this is enough for now.
71
84
  *
72
- * If the priority is higher than the current priority saved on the schema, we should substitute the rootValidator on the schema with the new one.
85
+ * If the priority is higher than the current priority saved on the schema, we should substitute the
86
+ * rootValidator on the schema with the new one.
73
87
  *
74
88
  * @param schema - The schema that we are working on right now, all fallbacks are tied to that specific schema.
75
89
  * @param type - The type of the fallback that we are adding.
@@ -80,14 +94,15 @@ export default class Validator {
80
94
  private checkAppendOrCreate(
81
95
  schema: Schema,
82
96
  type: ValidatorTypes,
97
+ fallbackName: string,
83
98
  fallback: ValidationFallbackCallbackType,
84
99
  childOrParent: 'child' | 'parent',
85
100
  options?: Parameters<(typeof Validator)['createAndAppendFallback']>[2]
86
101
  ) {
87
-
88
102
  const schemaWithProtected = schema as Schema & { __rootFallbacksValidator?: Schema['__rootFallbacksValidator'] };
89
103
 
90
- if (this[childOrParent]) (this as any)[childOrParent].addFallback(schemaWithProtected, type, fallback, options);
104
+ if (this[childOrParent])
105
+ (this as any)[childOrParent].addFallback(schemaWithProtected, type, fallbackName, fallback, options);
91
106
  else {
92
107
  const nextPriority = childOrParent === 'child' ? this.priority - 1 : this.priority + 1;
93
108
  if (Object.keys(typeByPriority).includes(String(nextPriority))) {
@@ -96,7 +111,7 @@ export default class Validator {
96
111
  const validatorInstance = new Validator(nextType);
97
112
  this[childOrParent] = validatorInstance;
98
113
  (this as any)[childOrParent][childOrParent === 'parent' ? 'child' : 'parent'] = this;
99
- (this as any)[childOrParent].addFallback(schemaWithProtected, type, fallback, options);
114
+ (this as any)[childOrParent].addFallback(schemaWithProtected, type, fallbackName, fallback, options);
100
115
  if (nextPriority > schemaWithProtected.__rootFallbacksValidator.priority)
101
116
  schemaWithProtected.__rootFallbacksValidator = validatorInstance;
102
117
  }
@@ -106,23 +121,29 @@ export default class Validator {
106
121
  addFallback(
107
122
  schema: Schema,
108
123
  type: ValidatorTypes,
124
+ fallbackName: string,
109
125
  fallback: ValidationFallbackCallbackType,
110
126
  options?: Parameters<(typeof Validator)['createAndAppendFallback']>[2]
111
127
  ) {
128
+ if (this.fallbackNamesAdded.has(fallbackName) && options?.removeCurrent !== true) return;
129
+ this.fallbackNamesAdded.add(fallbackName);
112
130
  const priority = priorityByType[type];
113
131
  if (this.priority === priority) {
114
132
  if (typeof options?.at === 'number')
115
133
  this.fallbacks.splice(options.at, options.removeCurrent === true ? 1 : 0, fallback);
116
134
  else this.fallbacks.push(fallback);
117
- } else if (priority > this.priority) this.checkAppendOrCreate(schema, type, fallback, 'parent', options);
118
- else if (priority < this.priority) this.checkAppendOrCreate(schema, type, fallback, 'child', options);
135
+ } else if (priority > this.priority)
136
+ this.checkAppendOrCreate(schema, type, fallbackName, fallback, 'parent', options);
137
+ else if (priority < this.priority) this.checkAppendOrCreate(schema, type, fallbackName, fallback, 'child', options);
119
138
  }
120
139
 
121
140
  /**
122
- * Validates the value against all of the fallbacks, the fallbacks are executed in order, from the highest priority to the lowest priority.
123
- * A validator can stop the execution of the other validators if it feels like so. Like on the example of a value being null or undefined.
141
+ * Validates the value against all of the fallbacks, the fallbacks are executed in order, from the highest
142
+ * priority to the lowest priority. A validator can stop the execution of the other validators if it feels
143
+ * like so. Like on the example of a value being null or undefined.
124
144
  *
125
- * @param errorsAsHashedSet - This is a set that contains all of the errors that we already found, this is used to avoid duplicated errors.
145
+ * @param errorsAsHashedSet - This is a set that contains all of the errors that we already found, this is
146
+ * used to avoid duplicated errors.
126
147
  * @param path - The path that we are validating right now.
127
148
  * @param parseResult - The result of the parsing, it contains the parsed value and the errors that we found.
128
149
  * @param options - The options that we are passing to the fallback.
@@ -143,34 +164,38 @@ export default class Validator {
143
164
  parseResult.parsed = parsed;
144
165
  for (const error of errors) {
145
166
  if (error.isValid === false) {
146
- const hashedError = JSON.stringify(error);
167
+ const sortedError = Object.fromEntries(Object.entries(error).sort(([a], [b]) => a.localeCompare(b)));
168
+
169
+ const hashedError = JSON.stringify(sortedError);
147
170
  if (errorsAsHashedSet.has(hashedError)) continue;
171
+ errorsAsHashedSet.add(hashedError);
148
172
  if (!Array.isArray(parseResult.errors)) parseResult.errors = [];
149
- parseResult.errors.push(error);
173
+ parseResult.errors.push({
174
+ ...error,
175
+ received: parseResult.parsed
176
+ });
150
177
  }
151
178
  }
152
179
  doesItShouldPreventChildValidation = doesItShouldPreventChildValidation || preventChildValidation || false;
153
180
  }
154
181
 
155
182
  if (this.child && doesItShouldPreventChildValidation === false)
156
- return this.child.validate(
157
- errorsAsHashedSet,
158
- path,
159
- parseResult,
160
- options
161
- );
183
+ return await this.child.validate(errorsAsHashedSet, path, parseResult, options);
162
184
 
163
185
  return parseResult as unknown as Promise<ValidationFallbackCallbackReturnType>;
164
186
  }
165
187
 
166
188
  /**
167
- * This static method takes care of everything for you. This means that you should only call this method for appending new fallbacks, it takes care of creating the root validator
168
- * and making sure that the rootValidator on the schema is the highest priority one.
189
+ * This static method takes care of everything for you. This means that you should only call this method
190
+ * for appending new fallbacks, it takes care of creating the root validator and making sure that the
191
+ * rootValidator on the schema is the highest priority one.
169
192
  *
170
- * @param schema - The schema that we are working on right now, all fallbacks are tied to that specific schema. We automatically define the rootValidator on the schema
171
- * so you don't need to worry about that.
172
- * @param fallback - The fallback that we are adding. This is an object that contains the type of the fallback and the callback that we are adding.
173
- * @param options - The options that we are passing to the fallback. Options like `at` and `removeCurrent` are passed to the `addFallback` method.
193
+ * @param schema - The schema that we are working on right now, all fallbacks are tied to that specific
194
+ * schema. We automatically define the rootValidator on the schema so you don't need to worry about that.
195
+ * @param fallback - The fallback that we are adding. This is an object that contains the type of the
196
+ * fallback and the callback that we are adding.
197
+ * @param options - The options that we are passing to the fallback. Options like `at` and `removeCurrent`
198
+ * are passed to the `addFallback` method.
174
199
  */
175
200
  static createAndAppendFallback(
176
201
  schema: Schema<any, any>,
@@ -188,7 +213,7 @@ export default class Validator {
188
213
  validatorInstance = new Validator(fallback.type);
189
214
  schemaWithProtected.__rootFallbacksValidator = validatorInstance;
190
215
  }
191
- validatorInstance.addFallback(schema, fallback.type, fallback.callback, options);
216
+ validatorInstance.addFallback(schema, fallback.type, fallback.name, fallback.callback, options);
192
217
  return validatorInstance;
193
218
  }
194
219