@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.
- package/.turbo/turbo-build$colon$watch.log +12 -410
- package/CHANGELOG.md +17 -0
- package/__tests__/.drizzle/migrations/0000_skinny_harrier.sql +22 -0
- package/__tests__/.drizzle/migrations/meta/0000_snapshot.json +156 -0
- package/__tests__/.drizzle/migrations/meta/_journal.json +13 -0
- package/__tests__/.drizzle/schema.ts +35 -0
- package/__tests__/drizzle.config.ts +11 -0
- package/__tests__/eslint.config.js +10 -0
- package/__tests__/manage.ts +5 -0
- package/__tests__/node_modules/.bin/drizzle-kit +17 -0
- package/__tests__/node_modules/.bin/esbuild +14 -0
- package/__tests__/node_modules/.bin/tsc +17 -0
- package/__tests__/node_modules/.bin/tsserver +17 -0
- package/__tests__/node_modules/.bin/tsx +17 -0
- package/__tests__/package.json +36 -0
- package/__tests__/sqlite.db +0 -0
- package/__tests__/src/core/array.test.ts +130 -0
- package/__tests__/src/core/boolean.test.ts +66 -0
- package/__tests__/src/core/datetime.test.ts +102 -0
- package/__tests__/src/core/index.ts +35 -0
- package/__tests__/src/core/model.test.ts +260 -0
- package/__tests__/src/core/models.ts +50 -0
- package/__tests__/src/core/numbers.test.ts +177 -0
- package/__tests__/src/core/object.test.ts +198 -0
- package/__tests__/src/core/string.test.ts +222 -0
- package/__tests__/src/core/test.test.ts +59 -0
- package/__tests__/src/core/types.test.ts +97 -0
- package/__tests__/src/core/union.test.ts +99 -0
- package/__tests__/src/settings.ts +71 -0
- package/__tests__/tsconfig.json +11 -0
- package/dist/cjs/src/adapter/fields/index.js +2 -2
- package/dist/cjs/src/adapter/fields/object.js +9 -0
- package/dist/cjs/src/adapter/index.js +1 -0
- package/dist/cjs/src/constants.js +1 -7
- package/dist/cjs/src/domain.js +146 -1
- package/dist/cjs/src/index.js +69 -74
- package/dist/cjs/src/model.js +206 -206
- package/dist/cjs/src/schema/array.js +185 -58
- package/dist/cjs/src/schema/boolean.js +105 -44
- package/dist/cjs/src/schema/datetime.js +104 -38
- package/dist/cjs/src/schema/number.js +134 -114
- package/dist/cjs/src/schema/object.js +106 -43
- package/dist/cjs/src/schema/schema.js +123 -75
- package/dist/cjs/src/schema/string.js +152 -58
- package/dist/cjs/src/schema/union.js +412 -290
- package/dist/cjs/src/utils.js +42 -15
- package/dist/cjs/src/validators/array.js +6 -1
- package/dist/cjs/src/validators/boolean.js +2 -0
- package/dist/cjs/src/validators/datetime.js +4 -0
- package/dist/cjs/src/validators/number.js +12 -40
- package/dist/cjs/src/validators/object.js +1 -0
- package/dist/cjs/src/validators/schema.js +5 -1
- package/dist/cjs/src/validators/string.js +30 -2
- package/dist/cjs/src/validators/union.js +5 -4
- package/dist/cjs/src/validators/utils.js +99 -27
- package/dist/cjs/tsconfig.types.tsbuildinfo +1 -1
- package/dist/cjs/types/adapter/fields/array.d.ts +2 -2
- package/dist/cjs/types/adapter/fields/array.d.ts.map +1 -1
- package/dist/cjs/types/adapter/fields/boolean.d.ts.map +1 -1
- package/dist/cjs/types/adapter/fields/datetime.d.ts.map +1 -1
- package/dist/cjs/types/adapter/fields/index.d.ts +2 -2
- package/dist/cjs/types/adapter/fields/index.d.ts.map +1 -1
- package/dist/cjs/types/adapter/fields/number.d.ts.map +1 -1
- package/dist/cjs/types/adapter/fields/object.d.ts +2 -1
- package/dist/cjs/types/adapter/fields/object.d.ts.map +1 -1
- package/dist/cjs/types/adapter/fields/string.d.ts.map +1 -1
- package/dist/cjs/types/adapter/fields/union.d.ts.map +1 -1
- package/dist/cjs/types/adapter/index.d.ts +1 -0
- package/dist/cjs/types/adapter/index.d.ts.map +1 -1
- package/dist/cjs/types/adapter/types.d.ts +28 -18
- package/dist/cjs/types/adapter/types.d.ts.map +1 -1
- package/dist/cjs/types/constants.d.ts +0 -1
- package/dist/cjs/types/constants.d.ts.map +1 -1
- package/dist/cjs/types/domain.d.ts +5 -4
- package/dist/cjs/types/domain.d.ts.map +1 -1
- package/dist/cjs/types/index.d.ts +78 -55
- package/dist/cjs/types/index.d.ts.map +1 -1
- package/dist/cjs/types/model.d.ts +17 -17
- package/dist/cjs/types/model.d.ts.map +1 -1
- package/dist/cjs/types/schema/array.d.ts +168 -47
- package/dist/cjs/types/schema/array.d.ts.map +1 -1
- package/dist/cjs/types/schema/boolean.d.ts +103 -44
- package/dist/cjs/types/schema/boolean.d.ts.map +1 -1
- package/dist/cjs/types/schema/datetime.d.ts +90 -30
- package/dist/cjs/types/schema/datetime.d.ts.map +1 -1
- package/dist/cjs/types/schema/number.d.ts +133 -125
- package/dist/cjs/types/schema/number.d.ts.map +1 -1
- package/dist/cjs/types/schema/object.d.ts +104 -35
- package/dist/cjs/types/schema/object.d.ts.map +1 -1
- package/dist/cjs/types/schema/schema.d.ts +62 -44
- package/dist/cjs/types/schema/schema.d.ts.map +1 -1
- package/dist/cjs/types/schema/string.d.ts +152 -65
- package/dist/cjs/types/schema/string.d.ts.map +1 -1
- package/dist/cjs/types/schema/types.d.ts +11 -2
- package/dist/cjs/types/schema/types.d.ts.map +1 -1
- package/dist/cjs/types/schema/union.d.ts +133 -40
- package/dist/cjs/types/schema/union.d.ts.map +1 -1
- package/dist/cjs/types/types.d.ts +35 -0
- package/dist/cjs/types/types.d.ts.map +1 -1
- package/dist/cjs/types/utils.d.ts +41 -27
- package/dist/cjs/types/utils.d.ts.map +1 -1
- package/dist/cjs/types/validators/array.d.ts.map +1 -1
- package/dist/cjs/types/validators/boolean.d.ts.map +1 -1
- package/dist/cjs/types/validators/datetime.d.ts.map +1 -1
- package/dist/cjs/types/validators/number.d.ts +5 -6
- package/dist/cjs/types/validators/number.d.ts.map +1 -1
- package/dist/cjs/types/validators/object.d.ts.map +1 -1
- package/dist/cjs/types/validators/schema.d.ts +2 -2
- package/dist/cjs/types/validators/schema.d.ts.map +1 -1
- package/dist/cjs/types/validators/string.d.ts +9 -9
- package/dist/cjs/types/validators/string.d.ts.map +1 -1
- package/dist/cjs/types/validators/utils.d.ts +44 -27
- package/dist/cjs/types/validators/utils.d.ts.map +1 -1
- package/dist/esm/src/adapter/fields/index.js +2 -2
- package/dist/esm/src/adapter/fields/object.js +6 -0
- package/dist/esm/src/adapter/index.js +1 -0
- package/dist/esm/src/constants.js +1 -2
- package/dist/esm/src/domain.js +11 -1
- package/dist/esm/src/index.js +38 -73
- package/dist/esm/src/model.js +83 -78
- package/dist/esm/src/schema/array.js +136 -54
- package/dist/esm/src/schema/boolean.js +98 -44
- package/dist/esm/src/schema/datetime.js +91 -38
- package/dist/esm/src/schema/number.js +127 -110
- package/dist/esm/src/schema/object.js +98 -43
- package/dist/esm/src/schema/schema.js +102 -67
- package/dist/esm/src/schema/string.js +147 -59
- package/dist/esm/src/schema/union.js +119 -40
- package/dist/esm/src/types.js +14 -1
- package/dist/esm/src/utils.js +56 -27
- package/dist/esm/src/validators/array.js +6 -1
- package/dist/esm/src/validators/boolean.js +2 -0
- package/dist/esm/src/validators/datetime.js +4 -0
- package/dist/esm/src/validators/number.js +9 -23
- package/dist/esm/src/validators/object.js +1 -0
- package/dist/esm/src/validators/schema.js +5 -1
- package/dist/esm/src/validators/string.js +30 -2
- package/dist/esm/src/validators/union.js +5 -4
- package/dist/esm/src/validators/utils.js +62 -36
- package/package.json +3 -3
- package/src/adapter/fields/array.ts +2 -2
- package/src/adapter/fields/boolean.ts +3 -8
- package/src/adapter/fields/datetime.ts +3 -9
- package/src/adapter/fields/index.ts +11 -11
- package/src/adapter/fields/number.ts +3 -9
- package/src/adapter/fields/object.ts +13 -10
- package/src/adapter/fields/string.ts +3 -9
- package/src/adapter/fields/union.ts +3 -9
- package/src/adapter/index.ts +1 -0
- package/src/adapter/types.ts +60 -45
- package/src/constants.ts +1 -3
- package/src/domain.ts +15 -1
- package/src/index.ts +189 -211
- package/src/model.ts +119 -115
- package/src/schema/array.ts +274 -90
- package/src/schema/boolean.ts +145 -60
- package/src/schema/datetime.ts +133 -49
- package/src/schema/number.ts +210 -173
- package/src/schema/object.ts +167 -74
- package/src/schema/schema.ts +205 -126
- package/src/schema/string.ts +221 -94
- package/src/schema/types.ts +44 -16
- package/src/schema/union.ts +193 -68
- package/src/types.ts +53 -0
- package/src/utils.ts +115 -57
- package/src/validators/array.ts +46 -27
- package/src/validators/boolean.ts +13 -7
- package/src/validators/datetime.ts +24 -16
- package/src/validators/number.ts +53 -63
- package/src/validators/object.ts +6 -5
- package/src/validators/schema.ts +33 -25
- package/src/validators/string.ts +122 -59
- package/src/validators/union.ts +8 -8
- package/src/validators/utils.ts +67 -42
package/src/utils.ts
CHANGED
@@ -1,7 +1,8 @@
|
|
1
|
+
import SchemaAdapter from './adapter';
|
2
|
+
import { getDefaultAdapter } from './conf';
|
1
3
|
import { checkType, nullable, optional } from './validators/schema';
|
2
4
|
import Validator from './validators/utils';
|
3
5
|
|
4
|
-
import type SchemaAdapter from './adapter';
|
5
6
|
import type FieldAdapter from './adapter/fields';
|
6
7
|
import type { ValidationDataBasedOnType } from './adapter/types';
|
7
8
|
import type Schema from './schema/schema';
|
@@ -9,8 +10,9 @@ import type { ValidationFallbackCallbackReturnType, ValidationFallbackReturnType
|
|
9
10
|
import type { FallbackFunctionsType, SupportedSchemas } from './types';
|
10
11
|
|
11
12
|
/**
|
12
|
-
* The usage of this is that imagine that the library doesn't support a specific feature that we support on
|
13
|
-
* of this class and with this instance we are able to
|
13
|
+
* The usage of this is that imagine that the library doesn't support a specific feature that we support on
|
14
|
+
* our schema definition, it can return an instance of this class and with this instance we are able to
|
15
|
+
* fallback to our default implementation of the schema validation.
|
14
16
|
*/
|
15
17
|
export default class WithFallback<TType extends SupportedSchemas> {
|
16
18
|
fallbackFor: Set<
|
@@ -38,8 +40,9 @@ export default class WithFallback<TType extends SupportedSchemas> {
|
|
38
40
|
}
|
39
41
|
|
40
42
|
/**
|
41
|
-
* Factory function for creating a new instance of WithFallback. We call that function when parsing the
|
42
|
-
* to create a new
|
43
|
+
* Factory function for creating a new instance of WithFallback. We call that function when parsing the
|
44
|
+
* schema adapter, and then, inside of the adapter the user will can the inner function to create a new
|
45
|
+
* instance of WithFallback.
|
43
46
|
*
|
44
47
|
* @param adapterType - The type of the adapter that we are using.
|
45
48
|
*
|
@@ -68,18 +71,22 @@ export function parseErrorsFactory(schemaAdapter: SchemaAdapter) {
|
|
68
71
|
}
|
69
72
|
|
70
73
|
/**
|
71
|
-
* The default transform function that we use for the schema adapters. This function tries to abstract away
|
74
|
+
* The default transform function that we use for the schema adapters. This function tries to abstract away
|
75
|
+
* the complexity of translating the schema to the adapter.
|
72
76
|
*
|
73
|
-
* So first things first, WHAT IS a fallback? A fallback is a function that we call when the user defines a
|
74
|
-
*
|
75
|
-
*
|
77
|
+
* So first things first, WHAT IS a fallback? A fallback is a function that we call when the user defines a
|
78
|
+
* validation that is not supported by the adapter. For example, imagine that for some reason the adapter
|
79
|
+
* doesn't support the `max` validation, we can define a fallback for that validation and then, when the
|
80
|
+
* user defines that validation, we call the fallback function. So, even if the adapter doesn't support that
|
81
|
+
* validation our schema will still be able to validate that.
|
76
82
|
*
|
77
|
-
* @param type - The type of the adapter that we are using, can be a number, an object, all of the possible
|
83
|
+
* @param type - The type of the adapter that we are using, can be a number, an object, all of the possible
|
84
|
+
* schema adapters.
|
78
85
|
* @param schema - The schema that we are translating.
|
79
|
-
* @param validationData - The data that we are using to validate the schema. This means for example, the
|
80
|
-
* it is not valid, etc.
|
81
|
-
* @param fallbackFunctions - The fallback functions that we are using to validate the schema. Those are
|
82
|
-
* supported by the adapter.
|
86
|
+
* @param validationData - The data that we are using to validate the schema. This means for example, the
|
87
|
+
* `max` validation, the `min` validation, etc. The message of the validation when it is not valid, etc.
|
88
|
+
* @param fallbackFunctions - The fallback functions that we are using to validate the schema. Those are
|
89
|
+
* the functions we fallback to when the user defines a validation that is not supported by the adapter.
|
83
90
|
*
|
84
91
|
* @returns - The translated schema for something that the adapter is able to understand.
|
85
92
|
*/
|
@@ -93,18 +100,23 @@ export async function defaultTransform<TType extends SupportedSchemas>(
|
|
93
100
|
options: {
|
94
101
|
validatorsIfFallbackOrNotSupported?: ValidationFallbackReturnType | ValidationFallbackReturnType[];
|
95
102
|
/**
|
96
|
-
* If the schema is not supported by the adapter, this means, that the adapter hasn't defined an adapter
|
103
|
+
* If the schema is not supported by the adapter, this means, that the adapter hasn't defined an adapter
|
104
|
+
* for that field type, we can fallback to a custom implementation.
|
97
105
|
* The problem is that, for example: Unions,
|
98
106
|
*
|
99
|
-
* Let's say we have a schema like this:
|
107
|
+
* Let's say we have a schema like this:
|
108
|
+
* ObjectSchema.new({ age: UnionSchema.new([NumberSchema.new(), StringSchema.new()] )});
|
100
109
|
*
|
101
|
-
* The root object will be validated by the adapter so what we need to do is create two schemas on the
|
102
|
-
* value of `age` key is a number and another where the value of `age` key is
|
103
|
-
*
|
104
|
-
*
|
110
|
+
* The root object will be validated by the adapter so what we need to do is create two schemas on the
|
111
|
+
* root object, one where the value of `age` key is a number and another where the value of `age` key is
|
112
|
+
* a string. Now the root object has two schemas memoized on __transformedSchemas, nice, what's the logic
|
113
|
+
* on that case? The ObjectSchema shouldn't take care of that logic. So the Union schema takes control of
|
114
|
+
* validating through the adapter. Is adapter 1 without errors? If yes, return the result, if not, try
|
115
|
+
* the second adapter. If the second adapter is without errors, return the result, if not, return the
|
116
|
+
* errors.
|
105
117
|
*
|
106
|
-
* In other words, the `fallbackIfNotSupported` function on Unions should return the two schemas saved on
|
107
|
-
* create those two schemas on the array.
|
118
|
+
* In other words, the `fallbackIfNotSupported` function on Unions should return the two schemas saved on
|
119
|
+
* it on that case, that way the root ObjectSchema will create those two schemas on the array.
|
108
120
|
*/
|
109
121
|
fallbackIfNotSupported?: () => ReturnType<Schema['__transformToAdapter']>;
|
110
122
|
} & Pick<Parameters<Schema['__transformToAdapter']>[0], 'shouldAddStringVersion'>
|
@@ -124,22 +136,29 @@ export async function defaultTransform<TType extends SupportedSchemas>(
|
|
124
136
|
__extends: Schema['__extends'];
|
125
137
|
};
|
126
138
|
|
127
|
-
const checkIfShouldUseParserAndAppend = (
|
139
|
+
const checkIfShouldUseParserAndAppend = (
|
140
|
+
parser: Parameters<WithFallback<SupportedSchemas>['fallbackFor']['add']>[0]
|
141
|
+
) => {
|
128
142
|
const isValidationDataAParser = (validationData as any).parsers?.[parser] !== undefined;
|
129
|
-
if (isValidationDataAParser)
|
130
|
-
|
131
|
-
|
132
|
-
|
143
|
+
if (isValidationDataAParser)
|
144
|
+
(
|
145
|
+
schema as unknown as {
|
146
|
+
__parsers: Schema['__parsers'];
|
147
|
+
}
|
148
|
+
).__parsers._fallbacks.add(parser);
|
149
|
+
};
|
133
150
|
|
134
151
|
const getExtendedOrNotSchemaAndString = (schema: any, toStringVersion: string) => {
|
135
|
-
const extendedOrNotSchema =
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
152
|
+
const extendedOrNotSchema =
|
153
|
+
typeof schemaWithPrivateFields.__extends?.callback === 'function'
|
154
|
+
? schemaWithPrivateFields.__extends.callback(schema)
|
155
|
+
: schema;
|
156
|
+
const extendedOrNotSchemaString =
|
157
|
+
typeof schemaWithPrivateFields.__extends?.toStringCallback === 'function'
|
158
|
+
? schemaWithPrivateFields.__extends.toStringCallback(toStringVersion)
|
159
|
+
: toStringVersion;
|
141
160
|
return [extendedOrNotSchema, extendedOrNotSchemaString];
|
142
|
-
}
|
161
|
+
};
|
143
162
|
|
144
163
|
const checkIfShouldAppendFallbackAndAppend = (
|
145
164
|
fallback: Parameters<WithFallback<SupportedSchemas>['fallbackFor']['add']>[0]
|
@@ -160,39 +179,46 @@ export async function defaultTransform<TType extends SupportedSchemas>(
|
|
160
179
|
const validatorsIfFallbackOrNotSupported = Array.isArray(options.validatorsIfFallbackOrNotSupported)
|
161
180
|
? options.validatorsIfFallbackOrNotSupported
|
162
181
|
: [options.validatorsIfFallbackOrNotSupported];
|
182
|
+
|
163
183
|
for (const fallback of validatorsIfFallbackOrNotSupported) Validator.createAndAppendFallback(schema, fallback);
|
164
184
|
}
|
165
185
|
};
|
166
186
|
|
167
|
-
const
|
168
|
-
|
187
|
+
const appendRequiredFallbacks = () => {
|
188
|
+
const hasFallbacks = schemaWithPrivateFields.__rootFallbacksValidator instanceof Validator;
|
189
|
+
if (hasFallbacks) {
|
190
|
+
Validator.createAndAppendFallback(schema, optional(schemaWithPrivateFields.__optional));
|
191
|
+
Validator.createAndAppendFallback(schema, nullable(schemaWithPrivateFields.__nullable));
|
192
|
+
Validator.createAndAppendFallback(schema, checkType(schemaWithPrivateFields.__type));
|
193
|
+
}
|
194
|
+
};
|
169
195
|
|
170
|
-
|
171
|
-
Validator.createAndAppendFallback(schema, optional(schemaWithPrivateFields.__optional));
|
172
|
-
Validator.createAndAppendFallback(schema, nullable(schemaWithPrivateFields.__nullable));
|
173
|
-
Validator.createAndAppendFallback(schema, checkType(schemaWithPrivateFields.__type));
|
174
|
-
}
|
196
|
+
const isFieldAdapterNotSupportedForThatFieldType = fieldAdapter === undefined;
|
175
197
|
|
176
198
|
if (options.fallbackIfNotSupported !== undefined && isFieldAdapterNotSupportedForThatFieldType) {
|
177
199
|
const existingFallbacks = Object.keys(fallbackFunctions) as Parameters<
|
178
200
|
WithFallback<SupportedSchemas>['fallbackFor']['add']
|
179
201
|
>[0][];
|
180
|
-
const allParsers = Object.keys(validationData['parsers']) as Parameters<
|
202
|
+
const allParsers = Object.keys(validationData['parsers']) as Parameters<
|
203
|
+
WithFallback<SupportedSchemas>['fallbackFor']['add']
|
204
|
+
>[0][];
|
181
205
|
|
182
206
|
appendRootFallback();
|
183
207
|
|
184
208
|
for (const fallback of existingFallbacks) checkIfShouldAppendFallbackAndAppend(fallback);
|
185
209
|
for (const parser of allParsers) checkIfShouldUseParserAndAppend(parser);
|
210
|
+
appendRequiredFallbacks();
|
211
|
+
|
186
212
|
return options.fallbackIfNotSupported();
|
187
213
|
}
|
188
214
|
if (!fieldAdapter) throw new Error('The field adapter is not supported and no fallback was provided.');
|
189
215
|
|
190
|
-
const translatedSchemaOrWithFallback =
|
216
|
+
const translatedSchemaOrWithFallback = await Promise.resolve(
|
191
217
|
fieldAdapter.translate(adapter.field, {
|
192
218
|
withFallback: withFallbackFactory<SupportedSchemas>(type),
|
193
|
-
...validationData
|
219
|
+
...validationData
|
194
220
|
})
|
195
|
-
)
|
221
|
+
);
|
196
222
|
|
197
223
|
let stringVersion = '';
|
198
224
|
if (options.shouldAddStringVersion)
|
@@ -209,12 +235,13 @@ export async function defaultTransform<TType extends SupportedSchemas>(
|
|
209
235
|
translatedSchemaOrWithFallback.transformedSchema,
|
210
236
|
stringVersion
|
211
237
|
);
|
238
|
+
appendRequiredFallbacks();
|
212
239
|
|
213
240
|
return [
|
214
241
|
{
|
215
242
|
transformed: extendedOrNotSchema,
|
216
|
-
asString: extendedOrNotSchemaString
|
217
|
-
}
|
243
|
+
asString: extendedOrNotSchemaString
|
244
|
+
}
|
218
245
|
];
|
219
246
|
}
|
220
247
|
|
@@ -226,21 +253,33 @@ export async function defaultTransform<TType extends SupportedSchemas>(
|
|
226
253
|
return [
|
227
254
|
{
|
228
255
|
transformed: extendedOrNotSchema,
|
229
|
-
asString: extendedOrNotSchemaString
|
230
|
-
}
|
256
|
+
asString: extendedOrNotSchemaString
|
257
|
+
}
|
231
258
|
];
|
232
259
|
}
|
233
260
|
|
234
261
|
/**
|
235
|
-
* This function is used to transform the schema to the adapter. By default it caches the transformed schemas on
|
236
|
-
* to transform to the schema again.
|
262
|
+
* This function is used to transform the schema to the adapter. By default it caches the transformed schemas on
|
263
|
+
* the schema instance. So on subsequent validations we don't need to transform to the schema again.
|
237
264
|
*/
|
238
265
|
export async function defaultTransformToAdapter(
|
239
266
|
callback: (adapter: SchemaAdapter) => ReturnType<FieldAdapter['translate']>,
|
267
|
+
schema: Schema<any, any>,
|
240
268
|
transformedSchemas: Schema['__transformedSchemas'],
|
241
269
|
options: Parameters<Schema['__transformToAdapter']>[0],
|
242
270
|
type: string
|
243
271
|
) {
|
272
|
+
const isTransformedSchemasEmpty = Object.keys(transformedSchemas).length <= 0;
|
273
|
+
if (isTransformedSchemasEmpty) {
|
274
|
+
const adapterInstanceToUse =
|
275
|
+
options.schemaAdapter instanceof SchemaAdapter ? options.schemaAdapter : getDefaultAdapter();
|
276
|
+
schema['__transformedSchemas'][adapterInstanceToUse.constructor.name] = {
|
277
|
+
transformed: false,
|
278
|
+
adapter: adapterInstanceToUse,
|
279
|
+
schemas: []
|
280
|
+
};
|
281
|
+
}
|
282
|
+
|
244
283
|
const schemaAdapterNameToUse = options.schemaAdapter?.constructor.name || Object.keys(transformedSchemas)[0];
|
245
284
|
const isACustomSchemaAdapterAndNotYetDefined =
|
246
285
|
// eslint-disable-next-line ts/no-unnecessary-condition
|
@@ -250,7 +289,7 @@ export async function defaultTransformToAdapter(
|
|
250
289
|
transformedSchemas[schemaAdapterNameToUse] = {
|
251
290
|
transformed: false,
|
252
291
|
adapter: options.schemaAdapter as SchemaAdapter,
|
253
|
-
schemas: []
|
292
|
+
schemas: []
|
254
293
|
};
|
255
294
|
|
256
295
|
const shouldTranslate = transformedSchemas[schemaAdapterNameToUse].transformed === false || options.force === true;
|
@@ -269,27 +308,36 @@ export async function formatErrorFromParseMethod(
|
|
269
308
|
adapter: SchemaAdapter,
|
270
309
|
fieldAdapter: FieldAdapter,
|
271
310
|
error: any,
|
311
|
+
received: any,
|
312
|
+
schema: any,
|
272
313
|
path: ValidationFallbackCallbackReturnType['errors'][number]['path'],
|
273
314
|
errorsAsHashedSet: Set<string>
|
274
315
|
) {
|
275
|
-
const formattedError = await fieldAdapter.formatError(adapter,
|
316
|
+
const formattedError = await fieldAdapter.formatError(adapter, adapter.field, schema, error);
|
276
317
|
formattedError.path = Array.isArray(formattedError.path) ? [...path, ...formattedError.path] : path;
|
318
|
+
|
277
319
|
const formattedErrorAsParseResultError =
|
278
320
|
formattedError as unknown as ValidationFallbackCallbackReturnType['errors'][number];
|
279
321
|
formattedErrorAsParseResultError.isValid = false;
|
280
|
-
|
322
|
+
const sortedError = Object.fromEntries(
|
323
|
+
Object.entries(formattedErrorAsParseResultError).sort(([a], [b]) => a.localeCompare(b))
|
324
|
+
);
|
325
|
+
const hashedError = JSON.stringify(sortedError);
|
326
|
+
errorsAsHashedSet.add(JSON.stringify(sortedError));
|
327
|
+
formattedErrorAsParseResultError.received = received;
|
281
328
|
return formattedErrorAsParseResultError;
|
282
329
|
}
|
283
330
|
|
284
331
|
/**
|
285
|
-
* Transform the schema and check if we should add a fallback validation for that schema. This is used for complex
|
332
|
+
* Transform the schema and check if we should add a fallback validation for that schema. This is used for complex
|
333
|
+
* schemas like Objects, arrays, unions, etc.
|
286
334
|
*/
|
287
335
|
export async function transformSchemaAndCheckIfShouldBeHandledByFallbackOnComplexSchemas(
|
288
336
|
schema: Schema,
|
289
337
|
options: Parameters<Schema['__transformToAdapter']>[0]
|
290
338
|
) {
|
291
339
|
const schemaWithProtected = schema as Schema & {
|
292
|
-
__runBeforeParseAndData: Schema['__runBeforeParseAndData']
|
340
|
+
__runBeforeParseAndData: Schema['__runBeforeParseAndData'];
|
293
341
|
__toInternal: Schema['__toInternal'];
|
294
342
|
__toValidate: Schema['__toValidate'];
|
295
343
|
__toRepresentation: Schema['__toRepresentation'];
|
@@ -299,7 +347,8 @@ export async function transformSchemaAndCheckIfShouldBeHandledByFallbackOnComple
|
|
299
347
|
__parsers: Schema['__parsers'];
|
300
348
|
};
|
301
349
|
|
302
|
-
|
350
|
+
// This should come first because we will get the fallbacks of the field here.
|
351
|
+
const transformedData = await schemaWithProtected.__transformToAdapter(options);
|
303
352
|
|
304
353
|
// eslint-disable-next-line ts/no-unnecessary-condition
|
305
354
|
const doesKeyHaveFallback = schemaWithProtected.__rootFallbacksValidator !== undefined;
|
@@ -320,3 +369,12 @@ export async function transformSchemaAndCheckIfShouldBeHandledByFallbackOnComple
|
|
320
369
|
|
321
370
|
return [transformedData, shouldAddFallbackValidation] as const;
|
322
371
|
}
|
372
|
+
|
373
|
+
export function shouldRunDataOnComplexSchemas(schema: Schema<any, any>) {
|
374
|
+
return (
|
375
|
+
typeof schema['__parsersToTransformValue'] === 'function' ||
|
376
|
+
typeof schema['__runBeforeParseAndData'] === 'function' ||
|
377
|
+
typeof schema['__toRepresentation'] === 'function' ||
|
378
|
+
typeof schema['__defaultFunction'] === 'function'
|
379
|
+
);
|
380
|
+
}
|
package/src/validators/array.ts
CHANGED
@@ -4,6 +4,7 @@ import type { ValidationFallbackCallbackReturnType, ValidationFallbackReturnType
|
|
4
4
|
|
5
5
|
export function arrayValidation(isTuple: boolean, schemas: Schema<any, any>[]): ValidationFallbackReturnType {
|
6
6
|
return {
|
7
|
+
name: 'array',
|
7
8
|
type: 'medium',
|
8
9
|
callback: async (value: any, path: (string | number)[], options: Parameters<Schema['__transformToAdapter']>[0]) => {
|
9
10
|
const isNotAnArray = Array.isArray(value) === false;
|
@@ -17,9 +18,9 @@ export function arrayValidation(isTuple: boolean, schemas: Schema<any, any>[]):
|
|
17
18
|
code: 'array',
|
18
19
|
// eslint-disable-next-line ts/no-unnecessary-condition
|
19
20
|
path: path || [],
|
20
|
-
message: 'The value must be an array. Received: ' + typeof value
|
21
|
-
}
|
22
|
-
]
|
21
|
+
message: 'The value must be an array. Received: ' + typeof value
|
22
|
+
}
|
23
|
+
]
|
23
24
|
};
|
24
25
|
if (isTuple && value.length !== schemas.length)
|
25
26
|
return {
|
@@ -31,14 +32,15 @@ export function arrayValidation(isTuple: boolean, schemas: Schema<any, any>[]):
|
|
31
32
|
code: 'tuple',
|
32
33
|
// eslint-disable-next-line ts/no-unnecessary-condition
|
33
34
|
path: path || [],
|
34
|
-
message: 'The tuple must have exactly ' + schemas.length + ' elements. Received: ' + value.length
|
35
|
-
}
|
36
|
-
]
|
35
|
+
message: 'The tuple must have exactly ' + schemas.length + ' elements. Received: ' + value.length
|
36
|
+
}
|
37
|
+
]
|
37
38
|
};
|
38
39
|
|
39
40
|
const errorsOfArray: ValidationFallbackCallbackReturnType['errors'] = [];
|
40
41
|
|
41
|
-
// To speed things up, we can do a simple type check, if the value is of type number and
|
42
|
+
// To speed things up, we can do a simple type check, if the value is of type number and
|
43
|
+
// number is on index 1, and on index 0 is a string,
|
42
44
|
// if the value is a number we can skip checking at index 0.
|
43
45
|
const schemaIndexByTypeof = new Map<string, number>();
|
44
46
|
let parsedValues: any[] = [];
|
@@ -52,8 +54,8 @@ export function arrayValidation(isTuple: boolean, schemas: Schema<any, any>[]):
|
|
52
54
|
const schemasToValidateAgainst = isTuple
|
53
55
|
? [schemas[index]]
|
54
56
|
: existsASchemaIndex
|
55
|
-
|
56
|
-
|
57
|
+
? [schemas[schemaIndex]]
|
58
|
+
: schemas;
|
57
59
|
|
58
60
|
for (let indexOfSchema = 0; indexOfSchema < schemasToValidateAgainst.length; indexOfSchema++) {
|
59
61
|
const schemaToValidate = schemasToValidateAgainst[indexOfSchema];
|
@@ -64,7 +66,9 @@ export function arrayValidation(isTuple: boolean, schemas: Schema<any, any>[]):
|
|
64
66
|
const { parsed, errors } = await schemaWithProtected.__parse(element, [...path, index], options);
|
65
67
|
|
66
68
|
if (schemaWithProtected.__toInternal && options.toInternalToBubbleUp)
|
67
|
-
options.toInternalToBubbleUp.push(
|
69
|
+
options.toInternalToBubbleUp.push(
|
70
|
+
async () => (parsedValues[indexOfSchema] = await schemaWithProtected.__toInternal?.(parsed))
|
71
|
+
);
|
68
72
|
|
69
73
|
// eslint-disable-next-line ts/no-unnecessary-condition
|
70
74
|
if ((errors || []).length <= 0) {
|
@@ -82,17 +86,22 @@ export function arrayValidation(isTuple: boolean, schemas: Schema<any, any>[]):
|
|
82
86
|
|
83
87
|
return {
|
84
88
|
parsed: parsedValues,
|
85
|
-
errors: errorsOfArray
|
89
|
+
errors: errorsOfArray
|
86
90
|
};
|
87
|
-
}
|
91
|
+
}
|
88
92
|
};
|
89
93
|
}
|
90
94
|
|
91
95
|
export function minLength(args: ArraySchema['__minLength']): ValidationFallbackReturnType {
|
92
96
|
return {
|
97
|
+
name: 'minLength',
|
93
98
|
type: 'low',
|
94
99
|
// eslint-disable-next-line ts/require-await
|
95
|
-
callback: async (
|
100
|
+
callback: async (
|
101
|
+
value: any,
|
102
|
+
path: (string | number)[],
|
103
|
+
_options: Parameters<Schema['__transformToAdapter']>[0]
|
104
|
+
) => {
|
96
105
|
const isValid = args.inclusive ? value.length >= args.value : value.length > args.value;
|
97
106
|
|
98
107
|
return {
|
@@ -105,19 +114,24 @@ export function minLength(args: ArraySchema['__minLength']): ValidationFallbackR
|
|
105
114
|
code: 'minLength',
|
106
115
|
// eslint-disable-next-line ts/no-unnecessary-condition
|
107
116
|
path: path || [],
|
108
|
-
message: args.message
|
109
|
-
}
|
110
|
-
]
|
117
|
+
message: args.message
|
118
|
+
}
|
119
|
+
]
|
111
120
|
};
|
112
|
-
}
|
121
|
+
}
|
113
122
|
};
|
114
123
|
}
|
115
124
|
|
116
125
|
export function maxLength(args: ArraySchema['__maxLength']): ValidationFallbackReturnType {
|
117
126
|
return {
|
127
|
+
name: 'maxLength',
|
118
128
|
type: 'low',
|
119
129
|
// eslint-disable-next-line ts/require-await
|
120
|
-
callback: async (
|
130
|
+
callback: async (
|
131
|
+
value: any,
|
132
|
+
path: (string | number)[],
|
133
|
+
_options: Parameters<Schema['__transformToAdapter']>[0]
|
134
|
+
) => {
|
121
135
|
const isValid = args.inclusive ? value.length <= args.value : value.length < args.value;
|
122
136
|
|
123
137
|
return {
|
@@ -130,19 +144,24 @@ export function maxLength(args: ArraySchema['__maxLength']): ValidationFallbackR
|
|
130
144
|
code: 'maxLength',
|
131
145
|
// eslint-disable-next-line ts/no-unnecessary-condition
|
132
146
|
path: path || [],
|
133
|
-
message: args.message
|
134
|
-
}
|
135
|
-
]
|
147
|
+
message: args.message
|
148
|
+
}
|
149
|
+
]
|
136
150
|
};
|
137
|
-
}
|
151
|
+
}
|
138
152
|
};
|
139
153
|
}
|
140
154
|
|
141
155
|
export function nonEmpty(args: ArraySchema['__nonEmpty']): ValidationFallbackReturnType {
|
142
156
|
return {
|
157
|
+
name: 'nonEmpty',
|
143
158
|
type: 'low',
|
144
159
|
// eslint-disable-next-line ts/require-await
|
145
|
-
callback: async (
|
160
|
+
callback: async (
|
161
|
+
value: any,
|
162
|
+
path: (string | number)[],
|
163
|
+
_options: Parameters<Schema['__transformToAdapter']>[0]
|
164
|
+
) => {
|
146
165
|
const isValid = value.length > 0;
|
147
166
|
|
148
167
|
return {
|
@@ -155,10 +174,10 @@ export function nonEmpty(args: ArraySchema['__nonEmpty']): ValidationFallbackRet
|
|
155
174
|
code: 'nonEmpty',
|
156
175
|
// eslint-disable-next-line ts/no-unnecessary-condition
|
157
176
|
path: path || [],
|
158
|
-
message: args.message
|
159
|
-
}
|
160
|
-
]
|
177
|
+
message: args.message
|
178
|
+
}
|
179
|
+
]
|
161
180
|
};
|
162
|
-
}
|
181
|
+
}
|
163
182
|
};
|
164
183
|
}
|
@@ -3,9 +3,14 @@ import type { ValidationFallbackReturnType } from '../schema/types';
|
|
3
3
|
|
4
4
|
export function booleanValidation(): ValidationFallbackReturnType {
|
5
5
|
return {
|
6
|
+
name: 'boolean',
|
6
7
|
type: 'medium',
|
7
8
|
// eslint-disable-next-line ts/require-await
|
8
|
-
callback: async (
|
9
|
+
callback: async (
|
10
|
+
value: any,
|
11
|
+
path: (string | number)[],
|
12
|
+
_options: Parameters<Schema['__transformToAdapter']>[0]
|
13
|
+
) => {
|
9
14
|
const isValid = typeof value === 'boolean';
|
10
15
|
|
11
16
|
return {
|
@@ -18,17 +23,18 @@ export function booleanValidation(): ValidationFallbackReturnType {
|
|
18
23
|
code: 'boolean',
|
19
24
|
// eslint-disable-next-line ts/no-unnecessary-condition
|
20
25
|
path: path || [],
|
21
|
-
message: 'Value is not a boolean'
|
22
|
-
}
|
26
|
+
message: 'Value is not a boolean'
|
27
|
+
}
|
23
28
|
],
|
24
|
-
preventChildValidation: true
|
29
|
+
preventChildValidation: true
|
25
30
|
};
|
26
|
-
}
|
31
|
+
}
|
27
32
|
};
|
28
33
|
}
|
29
34
|
|
30
35
|
export function allowStringParser(): ValidationFallbackReturnType {
|
31
36
|
return {
|
37
|
+
name: 'allowString',
|
32
38
|
type: 'high',
|
33
39
|
// eslint-disable-next-line ts/require-await
|
34
40
|
callback: async (
|
@@ -39,8 +45,8 @@ export function allowStringParser(): ValidationFallbackReturnType {
|
|
39
45
|
const parsed = Boolean(value);
|
40
46
|
return {
|
41
47
|
parsed: parsed,
|
42
|
-
errors: []
|
48
|
+
errors: []
|
43
49
|
};
|
44
|
-
}
|
50
|
+
}
|
45
51
|
};
|
46
52
|
}
|
@@ -4,9 +4,14 @@ import type { ValidationFallbackReturnType } from '../schema/types';
|
|
4
4
|
|
5
5
|
export function datetimeValidation(): ValidationFallbackReturnType {
|
6
6
|
return {
|
7
|
+
name: 'datetime',
|
7
8
|
type: 'medium',
|
8
9
|
// eslint-disable-next-line ts/require-await
|
9
|
-
callback: async (
|
10
|
+
callback: async (
|
11
|
+
value: any,
|
12
|
+
path: (string | number)[],
|
13
|
+
_options: Parameters<Schema['__transformToAdapter']>[0]
|
14
|
+
) => {
|
10
15
|
const isValid = value instanceof Date && !isNaN(value.getTime());
|
11
16
|
|
12
17
|
return {
|
@@ -19,17 +24,18 @@ export function datetimeValidation(): ValidationFallbackReturnType {
|
|
19
24
|
code: 'datetime',
|
20
25
|
// eslint-disable-next-line ts/no-unnecessary-condition
|
21
26
|
path: path || [],
|
22
|
-
message: 'Value is not a date'
|
23
|
-
}
|
27
|
+
message: 'Value is not a date'
|
28
|
+
}
|
24
29
|
],
|
25
|
-
preventChildValidation: true
|
30
|
+
preventChildValidation: true
|
26
31
|
};
|
27
|
-
}
|
32
|
+
}
|
28
33
|
};
|
29
34
|
}
|
30
35
|
|
31
36
|
export function allowStringParser(): ValidationFallbackReturnType {
|
32
37
|
return {
|
38
|
+
name: 'allowString',
|
33
39
|
type: 'high',
|
34
40
|
// eslint-disable-next-line ts/require-await
|
35
41
|
callback: async (
|
@@ -42,20 +48,21 @@ export function allowStringParser(): ValidationFallbackReturnType {
|
|
42
48
|
if (parsed instanceof Date && !isNaN(parsed.getTime())) {
|
43
49
|
return {
|
44
50
|
parsed: parsed,
|
45
|
-
errors: []
|
51
|
+
errors: []
|
46
52
|
};
|
47
53
|
}
|
48
54
|
}
|
49
55
|
return {
|
50
56
|
parsed: value,
|
51
|
-
errors: []
|
57
|
+
errors: []
|
52
58
|
};
|
53
|
-
}
|
59
|
+
}
|
54
60
|
};
|
55
61
|
}
|
56
62
|
|
57
63
|
export function below(args: DatetimeSchema['__below']): ValidationFallbackReturnType {
|
58
64
|
return {
|
65
|
+
name: 'below',
|
59
66
|
type: 'low',
|
60
67
|
// eslint-disable-next-line ts/require-await
|
61
68
|
callback: async (
|
@@ -75,16 +82,17 @@ export function below(args: DatetimeSchema['__below']): ValidationFallbackReturn
|
|
75
82
|
code: 'below',
|
76
83
|
// eslint-disable-next-line ts/no-unnecessary-condition
|
77
84
|
path: path || [],
|
78
|
-
message: args.message
|
79
|
-
}
|
80
|
-
]
|
85
|
+
message: args.message
|
86
|
+
}
|
87
|
+
]
|
81
88
|
};
|
82
|
-
}
|
89
|
+
}
|
83
90
|
};
|
84
91
|
}
|
85
92
|
|
86
93
|
export function above(args: DatetimeSchema['__above']): ValidationFallbackReturnType {
|
87
94
|
return {
|
95
|
+
name: 'above',
|
88
96
|
type: 'low',
|
89
97
|
// eslint-disable-next-line ts/require-await
|
90
98
|
callback: async (
|
@@ -104,10 +112,10 @@ export function above(args: DatetimeSchema['__above']): ValidationFallbackReturn
|
|
104
112
|
code: 'above',
|
105
113
|
// eslint-disable-next-line ts/no-unnecessary-condition
|
106
114
|
path: path || [],
|
107
|
-
message: args.message
|
108
|
-
}
|
109
|
-
]
|
115
|
+
message: args.message
|
116
|
+
}
|
117
|
+
]
|
110
118
|
};
|
111
|
-
}
|
119
|
+
}
|
112
120
|
};
|
113
121
|
}
|