@palmares/schemas 0.0.1

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