@palmares/schemas 0.0.1 → 0.1.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.
- package/.turbo/turbo-build$colon$watch.log +12 -410
- package/.turbo/turbo-build.log +13 -4
- package/CHANGELOG.md +26 -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/schema/schema.ts
CHANGED
@@ -4,7 +4,7 @@ import { formatErrorFromParseMethod } from '../utils';
|
|
4
4
|
import type {
|
5
5
|
DefinitionsOfSchemaType,
|
6
6
|
OnlyFieldAdaptersFromSchemaAdapter,
|
7
|
-
ValidationFallbackCallbackReturnType
|
7
|
+
ValidationFallbackCallbackReturnType
|
8
8
|
} from './types';
|
9
9
|
import type SchemaAdapter from '../adapter';
|
10
10
|
import type FieldAdapter from '../adapter/fields';
|
@@ -25,13 +25,17 @@ export default class Schema<
|
|
25
25
|
output: any;
|
26
26
|
representation: any;
|
27
27
|
},
|
28
|
-
TDefinitions extends DefinitionsOfSchemaType = DefinitionsOfSchemaType
|
28
|
+
TDefinitions extends DefinitionsOfSchemaType = DefinitionsOfSchemaType
|
29
29
|
> {
|
30
|
-
// Those functions will assume control of the validation process on adapters, instead of the schema.
|
31
|
-
//
|
32
|
-
//
|
33
|
-
//
|
34
|
-
//
|
30
|
+
// Those functions will assume control of the validation process on adapters, instead of the schema.
|
31
|
+
// Why this is used? The idea is that the Schema has NO idea
|
32
|
+
// that one of it's children might be an UnionSchema for example. The adapter might not support unions,
|
33
|
+
// so then we give control to the union. The parent schema will already have an array of translated
|
34
|
+
// adapter schemas. This means for a union with Number and String it'll generate two schemas, one for number
|
35
|
+
// and one for the value as String. Of course this gets multiplied. So if we have a union with Number and String.
|
36
|
+
// We should take those two schemas from the array and validate them individually. This logic is
|
37
|
+
// handled by the union schema. If we have an intersection type for example, instead of validating
|
38
|
+
// One schema OR the other, we validate one schema AND the other. This will be handled
|
35
39
|
// by the schema that contains that intersection logic.
|
36
40
|
protected __beforeValidationCallbacks: Map<
|
37
41
|
string,
|
@@ -48,16 +52,16 @@ export default class Schema<
|
|
48
52
|
) => ReturnType<Schema['__validateByAdapter']>
|
49
53
|
> = new Map();
|
50
54
|
|
51
|
-
protected __cachedGetParent?: (
|
52
|
-
protected set __getParent(value: (
|
55
|
+
protected __cachedGetParent?: () => Schema<any, any>;
|
56
|
+
protected set __getParent(value: () => Schema<any, any>) {
|
53
57
|
this.__cachedGetParent = value;
|
54
58
|
}
|
55
59
|
protected get __getParent(): (() => Schema<any, any>) | undefined {
|
56
|
-
return this.__cachedGetParent
|
60
|
+
return this.__cachedGetParent;
|
57
61
|
}
|
58
62
|
|
59
|
-
protected __alreadyAppliedModel
|
60
|
-
protected __runBeforeParseAndData?: (self: any) => Promise<void
|
63
|
+
protected __alreadyAppliedModel?: Promise<any>;
|
64
|
+
protected __runBeforeParseAndData?: (self: any) => Promise<void>;
|
61
65
|
protected __rootFallbacksValidator!: Validator;
|
62
66
|
protected __saveCallback?: (value: any) => Promise<any | void> | any | void;
|
63
67
|
protected __modelOmitCallback?: () => void;
|
@@ -79,29 +83,35 @@ export default class Schema<
|
|
79
83
|
high: new Map(),
|
80
84
|
medium: new Map(),
|
81
85
|
low: new Map(),
|
82
|
-
_fallbacks: new Set()
|
86
|
+
_fallbacks: new Set()
|
83
87
|
};
|
84
|
-
protected __refinements: ((
|
88
|
+
protected __refinements: ((
|
89
|
+
value: any
|
90
|
+
) =>
|
91
|
+
| Promise<void | undefined | { code: string; message: string }>
|
92
|
+
| void
|
93
|
+
| undefined
|
94
|
+
| { code: string; message: string })[] = [];
|
85
95
|
protected __nullable: {
|
86
96
|
message: string;
|
87
97
|
allow: boolean;
|
88
98
|
} = {
|
89
99
|
message: 'Cannot be null',
|
90
|
-
allow: false
|
100
|
+
allow: false
|
91
101
|
};
|
92
102
|
protected __optional: {
|
93
103
|
message: string;
|
94
104
|
allow: boolean;
|
95
105
|
} = {
|
96
106
|
message: 'Required',
|
97
|
-
allow: false
|
107
|
+
allow: false
|
98
108
|
};
|
99
|
-
protected __extends:
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
109
|
+
protected __extends:
|
110
|
+
| {
|
111
|
+
callback: (schema: any) => any;
|
112
|
+
toStringCallback?: (schemaAsString: string) => string;
|
113
|
+
}
|
114
|
+
| undefined = undefined;
|
105
115
|
|
106
116
|
protected __transformedSchemas: Record<
|
107
117
|
string,
|
@@ -120,11 +130,24 @@ export default class Schema<
|
|
120
130
|
check: (value: TType['input']) => boolean;
|
121
131
|
} = {
|
122
132
|
message: 'Invalid type',
|
123
|
-
check: () => true
|
133
|
+
check: () => true
|
124
134
|
};
|
125
135
|
|
136
|
+
protected __getDefaultTransformedSchemas() {
|
137
|
+
const adapterInstance = getDefaultAdapter();
|
138
|
+
|
139
|
+
// eslint-disable-next-line ts/no-unnecessary-condition
|
140
|
+
if (this.__transformedSchemas[adapterInstance.constructor.name] === undefined)
|
141
|
+
this.__transformedSchemas[adapterInstance.constructor.name] = {
|
142
|
+
transformed: false,
|
143
|
+
adapter: adapterInstance,
|
144
|
+
schemas: []
|
145
|
+
};
|
146
|
+
}
|
147
|
+
|
126
148
|
/**
|
127
|
-
* This will validate the data with the fallbacks, so internally, without relaying on the schema adapter.
|
149
|
+
* This will validate the data with the fallbacks, so internally, without relaying on the schema adapter.
|
150
|
+
* This is nice because we can support things that the schema adapter is not able to support by default.
|
128
151
|
*
|
129
152
|
* @param errorsAsHashedSet - The errors as a hashed set. This is used to prevent duplicate errors.
|
130
153
|
* @param path - The path of the error.
|
@@ -140,15 +163,17 @@ export default class Schema<
|
|
140
163
|
) {
|
141
164
|
// eslint-disable-next-line ts/no-unnecessary-condition
|
142
165
|
if (this.__rootFallbacksValidator)
|
143
|
-
return this.__rootFallbacksValidator.validate(options.errorsAsHashedSet
|
166
|
+
return this.__rootFallbacksValidator.validate(options.errorsAsHashedSet as Set<any>, path, parseResult, options);
|
144
167
|
|
145
168
|
return parseResult;
|
146
169
|
}
|
147
170
|
|
148
171
|
/**
|
149
|
-
* This will validate by the adapter. In other words, we send the data to the schema adapter and then we validate
|
150
|
-
*
|
151
|
-
*
|
172
|
+
* This will validate by the adapter. In other words, we send the data to the schema adapter and then we validate
|
173
|
+
* that data.
|
174
|
+
* So understand that, first we send the data to the adapter, the adapter validates it, then, after we validate
|
175
|
+
* from the adapter we validate with the fallbacks so we can do all of the extra validations not handled by
|
176
|
+
* the adapter.
|
152
177
|
*
|
153
178
|
* @param value - The value to be validated.
|
154
179
|
* @param errorsAsHashedSet - The errors as a hashed set. This is used to prevent duplicate errors on the validator.
|
@@ -167,7 +192,7 @@ export default class Schema<
|
|
167
192
|
) {
|
168
193
|
const parseResult: Awaited<ReturnType<Schema['__parse']>> = {
|
169
194
|
errors: [],
|
170
|
-
parsed: value
|
195
|
+
parsed: value
|
171
196
|
};
|
172
197
|
// On the next iteration we will reset the errors and the parsed value
|
173
198
|
parseResult.errors = [];
|
@@ -176,7 +201,13 @@ export default class Schema<
|
|
176
201
|
// eslint-disable-next-line ts/no-unnecessary-condition
|
177
202
|
if (fieldAdapter === undefined || typeof fieldAdapter.parse !== 'function') return parseResult;
|
178
203
|
|
179
|
-
const adapterParseResult = await fieldAdapter.parse(
|
204
|
+
const adapterParseResult = await fieldAdapter.parse(
|
205
|
+
adapter,
|
206
|
+
adapter.field,
|
207
|
+
schema.transformed,
|
208
|
+
value,
|
209
|
+
options.args
|
210
|
+
);
|
180
211
|
|
181
212
|
parseResult.parsed = adapterParseResult.parsed;
|
182
213
|
|
@@ -184,7 +215,15 @@ export default class Schema<
|
|
184
215
|
if (Array.isArray(adapterParseResult.errors))
|
185
216
|
parseResult.errors = await Promise.all(
|
186
217
|
adapterParseResult.errors.map(async (error) =>
|
187
|
-
formatErrorFromParseMethod(
|
218
|
+
formatErrorFromParseMethod(
|
219
|
+
adapter,
|
220
|
+
fieldAdapter,
|
221
|
+
error,
|
222
|
+
value,
|
223
|
+
schema.transformed,
|
224
|
+
path,
|
225
|
+
options.errorsAsHashedSet || new Set()
|
226
|
+
)
|
188
227
|
)
|
189
228
|
);
|
190
229
|
else
|
@@ -193,24 +232,28 @@ export default class Schema<
|
|
193
232
|
adapter,
|
194
233
|
fieldAdapter,
|
195
234
|
parseResult.errors,
|
235
|
+
value,
|
236
|
+
schema.transformed,
|
196
237
|
path,
|
197
238
|
options.errorsAsHashedSet || new Set()
|
198
|
-
)
|
239
|
+
)
|
199
240
|
];
|
200
241
|
}
|
242
|
+
parseResult.errors = parseResult.errors.filter((error) => typeof error !== 'undefined');
|
201
243
|
return parseResult;
|
202
244
|
}
|
203
245
|
|
204
246
|
// eslint-disable-next-line ts/require-await
|
205
247
|
protected async __transformToAdapter(_options: {
|
206
248
|
// force to transform
|
207
|
-
args: Omit<ValidationDataBasedOnType<any>, 'withFallback'
|
249
|
+
args: Omit<ValidationDataBasedOnType<any>, 'withFallback'>;
|
208
250
|
force?: boolean;
|
209
251
|
toInternalToBubbleUp?: (() => Promise<void>)[];
|
210
252
|
schemaAdapter?: SchemaAdapter;
|
211
253
|
errorsAsHashedSet?: Set<string>;
|
212
254
|
shouldAddStringVersion?: boolean;
|
213
255
|
appendFallbacksBeforeAdapterValidation?: (
|
256
|
+
schema: Schema<any, any>,
|
214
257
|
uniqueNameOfFallback: string,
|
215
258
|
fallbackValidationBeforeAdapter: (
|
216
259
|
adapterToUse: SchemaAdapter,
|
@@ -236,6 +279,7 @@ export default class Schema<
|
|
236
279
|
/** */
|
237
280
|
protected async __parsersToTransformValue(value: any, parsersToUse?: Set<string>) {
|
238
281
|
let shouldStop = false;
|
282
|
+
|
239
283
|
for (const [parserName, parser] of this.__parsers.high.entries()) {
|
240
284
|
if (parsersToUse instanceof Set === false || parsersToUse.has(parserName)) {
|
241
285
|
const result = await Promise.resolve(parser(value));
|
@@ -270,11 +314,16 @@ export default class Schema<
|
|
270
314
|
path: ValidationFallbackCallbackReturnType['errors'][number]['path'] = [],
|
271
315
|
options: Parameters<Schema['__transformToAdapter']>[0]
|
272
316
|
): Promise<{ errors: any[]; parsed: TType['internal'] }> {
|
317
|
+
this.__getDefaultTransformedSchemas();
|
273
318
|
if (typeof this.__runBeforeParseAndData === 'function') await this.__runBeforeParseAndData(this);
|
274
|
-
|
275
|
-
//
|
276
|
-
// the
|
277
|
-
//
|
319
|
+
|
320
|
+
// This is used to run the toInternal command. If we didn't do this, we would need to parse through all of
|
321
|
+
// the schemas to run the toInternal command, from the leafs (ObjectSchemas) to the root schema. This is not
|
322
|
+
// a good idea, so what we do is that during validation the leafs attach a function to the
|
323
|
+
// options.toInternalToBubbleUp like
|
324
|
+
// `options.toInternalToBubbleUp.push(async () => (value[key] = await (schema as any).__toInternal(parsed)));``
|
325
|
+
// This way, when the root schema finishes the validation, it will run all of the functions in the
|
326
|
+
// toInternalToBubbleUp array, modifying the parsed value.
|
278
327
|
const shouldRunToInternalToBubbleUp = options.toInternalToBubbleUp === undefined;
|
279
328
|
if (shouldRunToInternalToBubbleUp) options.toInternalToBubbleUp = [];
|
280
329
|
if (options.errorsAsHashedSet instanceof Set === false) options.errorsAsHashedSet = new Set();
|
@@ -292,17 +341,21 @@ export default class Schema<
|
|
292
341
|
errors: ValidationFallbackCallbackReturnType['errors'];
|
293
342
|
parsed: TType['input'];
|
294
343
|
} = { errors: [], parsed: value };
|
344
|
+
value = await this.__parsersToTransformValue(value, this.__parsers._fallbacks);
|
295
345
|
|
296
346
|
if (options.appendFallbacksBeforeAdapterValidation === undefined)
|
297
|
-
options.appendFallbacksBeforeAdapterValidation = (name, callback) => {
|
298
|
-
this.
|
347
|
+
options.appendFallbacksBeforeAdapterValidation = (schema, name, callback) => {
|
348
|
+
// We just need this if the union adapter is net defined but the parent is not of the same type.
|
349
|
+
// For example, it's a union child of o object schema
|
350
|
+
if (this !== schema) this.__beforeValidationCallbacks.set(name, callback);
|
299
351
|
};
|
300
352
|
|
301
|
-
if (
|
353
|
+
if (
|
354
|
+
this.__transformedSchemas[options.schemaAdapter?.constructor.name || getDefaultAdapter().constructor.name]
|
355
|
+
.transformed === false
|
356
|
+
)
|
302
357
|
await this.__transformToAdapter(options);
|
303
358
|
|
304
|
-
value = await this.__parsersToTransformValue(value, this.__parsers._fallbacks);
|
305
|
-
|
306
359
|
const adapterToUse = options.schemaAdapter
|
307
360
|
? options.schemaAdapter
|
308
361
|
: Object.values(this.__transformedSchemas)[0].adapter;
|
@@ -310,8 +363,8 @@ export default class Schema<
|
|
310
363
|
const parsedResultsAfterFallbacks = await this.__validateByFallbacks(
|
311
364
|
path,
|
312
365
|
{
|
313
|
-
errors:
|
314
|
-
parsed: value
|
366
|
+
errors: parseResult.errors,
|
367
|
+
parsed: value
|
315
368
|
},
|
316
369
|
options
|
317
370
|
);
|
@@ -319,7 +372,8 @@ export default class Schema<
|
|
319
372
|
parseResult.parsed = parsedResultsAfterFallbacks.parsed;
|
320
373
|
// eslint-disable-next-line ts/no-unnecessary-condition
|
321
374
|
parseResult.errors = (parseResult.errors || []).concat(parsedResultsAfterFallbacks.errors || []);
|
322
|
-
// With this, the children takes control of validating by the adapter. For example on a union schema we
|
375
|
+
// With this, the children takes control of validating by the adapter. For example on a union schema we
|
376
|
+
// want to validate all of the schemas and choose the one that has no errors.
|
323
377
|
if (this.__beforeValidationCallbacks.size > 0) {
|
324
378
|
for (const callback of this.__beforeValidationCallbacks.values()) {
|
325
379
|
const parsedValuesAfterValidationCallbacks = await callback(
|
@@ -332,7 +386,13 @@ export default class Schema<
|
|
332
386
|
options
|
333
387
|
);
|
334
388
|
parseResult.parsed = parsedValuesAfterValidationCallbacks.parsed;
|
335
|
-
|
389
|
+
|
390
|
+
parseResult.errors =
|
391
|
+
Array.isArray(parseResult.errors) && Array.isArray(parsedValuesAfterValidationCallbacks.errors)
|
392
|
+
? [...parseResult.errors, ...parsedValuesAfterValidationCallbacks.errors]
|
393
|
+
: Array.isArray(parseResult.errors)
|
394
|
+
? parseResult.errors
|
395
|
+
: parsedValuesAfterValidationCallbacks.errors;
|
336
396
|
}
|
337
397
|
} else {
|
338
398
|
const parsedValuesAfterValidatingByAdapter = await this.__validateByAdapter(
|
@@ -343,30 +403,33 @@ export default class Schema<
|
|
343
403
|
path,
|
344
404
|
options
|
345
405
|
);
|
406
|
+
|
346
407
|
parseResult.parsed = parsedValuesAfterValidatingByAdapter.parsed;
|
347
408
|
// eslint-disable-next-line ts/no-unnecessary-condition
|
348
409
|
parseResult.errors = (parseResult.errors || []).concat(parsedValuesAfterValidatingByAdapter.errors);
|
349
410
|
}
|
350
411
|
|
351
|
-
|
352
|
-
const doesNotHaveErrors = !Array.isArray(parseResult.errors) || parseResult.errors.length === 0;
|
353
412
|
const hasToInternalCallback = typeof this.__toInternal === 'function';
|
354
413
|
const shouldCallToInternalDuringParse =
|
355
|
-
|
414
|
+
hasToInternalCallback &&
|
415
|
+
(options.toInternalToBubbleUp?.length === 0 || Array.isArray(options.toInternalToBubbleUp) === false);
|
356
416
|
// eslint-disable-next-line ts/no-unnecessary-condition
|
357
417
|
const hasNoErrors = parseResult.errors === undefined || (parseResult.errors || []).length === 0;
|
358
418
|
|
359
|
-
await Promise.all(
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
419
|
+
await Promise.all(
|
420
|
+
this.__refinements.map(async (refinement) => {
|
421
|
+
const errorOrNothing = await Promise.resolve(refinement(parseResult.parsed));
|
422
|
+
|
423
|
+
if (typeof errorOrNothing === 'undefined') return;
|
424
|
+
parseResult.errors.push({
|
425
|
+
isValid: false,
|
426
|
+
code: errorOrNothing.code as any,
|
427
|
+
message: errorOrNothing.message,
|
428
|
+
received: parseResult.parsed,
|
429
|
+
path
|
430
|
+
});
|
431
|
+
})
|
432
|
+
);
|
370
433
|
|
371
434
|
if (shouldCallToInternalDuringParse && hasNoErrors) parseResult.parsed = await (this.__toInternal as any)(value);
|
372
435
|
if (shouldRunToInternalToBubbleUp && hasNoErrors)
|
@@ -376,7 +439,8 @@ export default class Schema<
|
|
376
439
|
}
|
377
440
|
|
378
441
|
/**
|
379
|
-
* This let's you refine the schema with custom validations. This is useful when you want to validate something
|
442
|
+
* This let's you refine the schema with custom validations. This is useful when you want to validate something
|
443
|
+
* that is not supported by default by the schema adapter.
|
380
444
|
*
|
381
445
|
* @example
|
382
446
|
* ```typescript
|
@@ -388,7 +452,8 @@ export default class Schema<
|
|
388
452
|
*
|
389
453
|
* const { errors, parsed } = await numberSchema.parse(-1);
|
390
454
|
*
|
391
|
-
* console.log(errors);
|
455
|
+
* console.log(errors);
|
456
|
+
* // [{ isValid: false, code: 'invalid_number', message: 'The number should be greater than 0', path: [] }]
|
392
457
|
* ```
|
393
458
|
*
|
394
459
|
* @param refinementCallback - The callback that will be called to validate the value.
|
@@ -396,7 +461,13 @@ export default class Schema<
|
|
396
461
|
* @param options.isAsync - Whether the callback is async or not. Defaults to true.
|
397
462
|
*/
|
398
463
|
refine(
|
399
|
-
refinementCallback: (
|
464
|
+
refinementCallback: (
|
465
|
+
value: TType['input']
|
466
|
+
) =>
|
467
|
+
| Promise<void | undefined | { code: string; message: string }>
|
468
|
+
| void
|
469
|
+
| undefined
|
470
|
+
| { code: string; message: string }
|
400
471
|
) {
|
401
472
|
this.__refinements.push(refinementCallback);
|
402
473
|
|
@@ -407,7 +478,8 @@ export default class Schema<
|
|
407
478
|
internal: TType['internal'];
|
408
479
|
output: TType['output'];
|
409
480
|
representation: TType['representation'];
|
410
|
-
},
|
481
|
+
},
|
482
|
+
TDefinitions
|
411
483
|
>;
|
412
484
|
}
|
413
485
|
|
@@ -438,7 +510,7 @@ export default class Schema<
|
|
438
510
|
optional(options?: { message?: string; allow?: false }) {
|
439
511
|
this.__optional = {
|
440
512
|
message: typeof options?.message === 'string' ? options.message : 'Required',
|
441
|
-
allow: typeof options?.allow === 'boolean' ? options.allow : true
|
513
|
+
allow: typeof options?.allow === 'boolean' ? options.allow : true
|
442
514
|
};
|
443
515
|
|
444
516
|
return this as unknown as Schema<
|
@@ -454,8 +526,8 @@ export default class Schema<
|
|
454
526
|
}
|
455
527
|
|
456
528
|
/**
|
457
|
-
* Allows the value to be null and ONLY null. You can also use this function to set a custom message when
|
458
|
-
* the { message: 'Your custom message', allow: false } on the options.
|
529
|
+
* Allows the value to be null and ONLY null. You can also use this function to set a custom message when
|
530
|
+
* the value is NULL by setting the { message: 'Your custom message', allow: false } on the options.
|
459
531
|
*
|
460
532
|
* @example
|
461
533
|
* ```typescript
|
@@ -481,7 +553,7 @@ export default class Schema<
|
|
481
553
|
nullable(options?: { message: string; allow: false }) {
|
482
554
|
this.__nullable = {
|
483
555
|
message: typeof options?.message === 'string' ? options.message : 'Cannot be null',
|
484
|
-
allow: typeof options?.allow === 'boolean' ? options.allow : true
|
556
|
+
allow: typeof options?.allow === 'boolean' ? options.allow : true
|
485
557
|
};
|
486
558
|
|
487
559
|
return this as unknown as Schema<
|
@@ -499,8 +571,8 @@ export default class Schema<
|
|
499
571
|
/**
|
500
572
|
* Appends a custom schema to the schema, this way it will bypass the creation of the schema in runtime.
|
501
573
|
*
|
502
|
-
* By default when validating, on the first validation we create the schema. Just during the first validation.
|
503
|
-
* so you can speed up the validation process.
|
574
|
+
* By default when validating, on the first validation we create the schema. Just during the first validation.
|
575
|
+
* With this function, you bypass that, so you can speed up the validation process.
|
504
576
|
*
|
505
577
|
* @example
|
506
578
|
* ```typescript
|
@@ -524,7 +596,7 @@ export default class Schema<
|
|
524
596
|
this.__transformedSchemas[adapter.constructor.name] = {
|
525
597
|
transformed: true,
|
526
598
|
adapter: adapter,
|
527
|
-
schemas: [schema]
|
599
|
+
schemas: [schema]
|
528
600
|
};
|
529
601
|
|
530
602
|
return this as unknown as Schema<
|
@@ -540,14 +612,15 @@ export default class Schema<
|
|
540
612
|
}
|
541
613
|
|
542
614
|
/**
|
543
|
-
* This method will remove the value from the representation of the schema. If the value is undefined it will keep
|
544
|
-
* otherwise it will set the value to undefined after it's validated.
|
615
|
+
* This method will remove the value from the representation of the schema. If the value is undefined it will keep
|
616
|
+
* that way otherwise it will set the value to undefined after it's validated.
|
545
617
|
* This is used in conjunction with the {@link data} function, the {@link parse} function or {@link validate}
|
546
618
|
* function. This will remove the value from the representation of the schema.
|
547
619
|
*
|
548
|
-
* By default, the value will be removed just from the representation, in other words, when you call the {@link data}
|
549
|
-
* But if you want to remove the value from the internal representation, you can pass the argument
|
550
|
-
* Then if you still want to remove the value from the representation, you will need to pass
|
620
|
+
* By default, the value will be removed just from the representation, in other words, when you call the {@link data}
|
621
|
+
* function. But if you want to remove the value from the internal representation, you can pass the argument
|
622
|
+
* `toInternal` as true. Then if you still want to remove the value from the representation, you will need to pass
|
623
|
+
* the argument `toRepresentation` as true as well.
|
551
624
|
*
|
552
625
|
* @example
|
553
626
|
* ```typescript
|
@@ -569,18 +642,21 @@ export default class Schema<
|
|
569
642
|
* ```
|
570
643
|
*
|
571
644
|
*
|
572
|
-
* @param args - By default, the value will be removed just from the representation, in other words, when you call
|
573
|
-
*
|
574
|
-
*
|
645
|
+
* @param args - By default, the value will be removed just from the representation, in other words, when you call
|
646
|
+
* the {@link data} function.
|
647
|
+
* But if you want to remove the value from the internal representation, you can pass the argument `toInternal`
|
648
|
+
* as true. Then if you still want to remove the value from the representation, you will need to pass the
|
649
|
+
* argument `toRepresentation` as true as well.
|
575
650
|
*
|
576
651
|
* @returns The schema.
|
577
652
|
*/
|
578
653
|
omit<
|
579
654
|
TToInternal extends boolean,
|
580
655
|
TToRepresentation extends boolean = boolean extends TToInternal ? true : false
|
581
|
-
>(args?: { toInternal?: TToInternal
|
656
|
+
>(args?: { toInternal?: TToInternal; toRepresentation?: TToRepresentation }) {
|
582
657
|
// To representation is true by default, unless to internal is true.
|
583
|
-
const toRepresentation =
|
658
|
+
const toRepresentation =
|
659
|
+
typeof args?.toRepresentation === 'boolean' ? args.toRepresentation : typeof args?.toInternal !== 'boolean';
|
584
660
|
const toInternal = typeof args?.toInternal === 'boolean' ? args.toInternal : false;
|
585
661
|
|
586
662
|
if (toInternal) {
|
@@ -590,7 +666,7 @@ export default class Schema<
|
|
590
666
|
await toInternal(value);
|
591
667
|
return undefined;
|
592
668
|
};
|
593
|
-
|
669
|
+
// eslint-disable-next-line ts/require-await
|
594
670
|
} else this.__toInternal = async () => undefined;
|
595
671
|
} else if (toRepresentation) {
|
596
672
|
if (this.__toRepresentation) {
|
@@ -599,7 +675,7 @@ export default class Schema<
|
|
599
675
|
await toRepresentation(value);
|
600
676
|
return undefined;
|
601
677
|
};
|
602
|
-
|
678
|
+
// eslint-disable-next-line ts/require-await
|
603
679
|
} else this.__toRepresentation = async () => undefined;
|
604
680
|
}
|
605
681
|
|
@@ -616,9 +692,9 @@ export default class Schema<
|
|
616
692
|
}
|
617
693
|
|
618
694
|
/**
|
619
|
-
* This function is used in conjunction with the {@link validate} function. It's used to save a value to an external
|
620
|
-
* like a database. You should always return the schema after you save the value, that way we will always have
|
621
|
-
* of the schema after the save operation.
|
695
|
+
* This function is used in conjunction with the {@link validate} function. It's used to save a value to an external
|
696
|
+
* source like a database. You should always return the schema after you save the value, that way we will always have
|
697
|
+
* the correct type of the schema after the save operation.
|
622
698
|
*
|
623
699
|
* You can use the {@link toRepresentation} function to transform and clean the value it returns after the save.
|
624
700
|
*
|
@@ -678,10 +754,11 @@ export default class Schema<
|
|
678
754
|
* This function is used to validate the schema and save the value to the database. It is used in
|
679
755
|
* conjunction with the {@link onSave} function.
|
680
756
|
*
|
681
|
-
* Different from other validation libraries, palmares schemas is aware that you want to save. On your
|
682
|
-
* we recommend to ALWAYS use this function instead of {@link parse} directly. This is because
|
683
|
-
* will return an object with the property `save` or the `errors`. If the errors are present,
|
684
|
-
* to the user. If the save property is present, you can use to save the value to an
|
757
|
+
* Different from other validation libraries, palmares schemas is aware that you want to save. On your
|
758
|
+
* routes/functions we recommend to ALWAYS use this function instead of {@link parse} directly. This is because
|
759
|
+
* this function by default will return an object with the property `save` or the `errors`. If the errors are present,
|
760
|
+
* you can return the errors to the user. If the save property is present, you can use to save the value to an
|
761
|
+
* external source. e.g. a database.
|
685
762
|
*
|
686
763
|
* @example
|
687
764
|
* ```typescript
|
@@ -765,9 +842,7 @@ export default class Schema<
|
|
765
842
|
*
|
766
843
|
* @returns The parsed value.
|
767
844
|
*/
|
768
|
-
async parse(
|
769
|
-
value: TType['input']
|
770
|
-
): Promise<{ errors?: any[]; parsed: TType['internal'] }> {
|
845
|
+
async parse(value: TType['input']): Promise<{ errors?: any[]; parsed: TType['internal'] }> {
|
771
846
|
return this.__parse(value, [], {} as any);
|
772
847
|
}
|
773
848
|
|
@@ -802,8 +877,9 @@ export default class Schema<
|
|
802
877
|
* ```
|
803
878
|
*/
|
804
879
|
async data(value: TType['output']): Promise<TType['representation']> {
|
880
|
+
this.__getDefaultTransformedSchemas();
|
805
881
|
if (typeof this.__runBeforeParseAndData === 'function') await this.__runBeforeParseAndData(this);
|
806
|
-
value = await this.__parsersToTransformValue(value)
|
882
|
+
value = await this.__parsersToTransformValue(value);
|
807
883
|
|
808
884
|
if (this.__toRepresentation) value = await Promise.resolve(this.__toRepresentation(value));
|
809
885
|
if (this.__defaultFunction && value === undefined) value = await Promise.resolve(this.__defaultFunction());
|
@@ -827,7 +903,8 @@ export default class Schema<
|
|
827
903
|
}
|
828
904
|
|
829
905
|
/**
|
830
|
-
* This function is used to add a default value to the schema. If the value is either undefined or null,
|
906
|
+
* This function is used to add a default value to the schema. If the value is either undefined or null,
|
907
|
+
* the default value will be used.
|
831
908
|
*
|
832
909
|
* @example
|
833
910
|
* ```typescript
|
@@ -861,8 +938,9 @@ export default class Schema<
|
|
861
938
|
}
|
862
939
|
|
863
940
|
/**
|
864
|
-
* This function let's you customize the schema your own way. After we translate the schema on the adapter we call
|
865
|
-
* the custom schema your own way. Our API does not support passthrough?
|
941
|
+
* This function let's you customize the schema your own way. After we translate the schema on the adapter we call
|
942
|
+
* this function to let you customize the custom schema your own way. Our API does not support passthrough?
|
943
|
+
* No problem, you can use this function to customize the zod schema.
|
866
944
|
*
|
867
945
|
* @example
|
868
946
|
* ```typescript
|
@@ -874,12 +952,13 @@ export default class Schema<
|
|
874
952
|
*
|
875
953
|
* const { errors, parsed } = await numberSchema.parse(-1);
|
876
954
|
*
|
877
|
-
* console.log(errors);
|
955
|
+
* console.log(errors);
|
956
|
+
* // [{ isValid: false, code: 'nonnegative', message: 'The number should be nonnegative', path: [] }]
|
878
957
|
* ```
|
879
958
|
*
|
880
959
|
* @param callback - The callback that will be called to customize the schema.
|
881
|
-
* @param toStringCallback - The callback that will be called to transform the schema to a string when you want
|
882
|
-
* to a string so you can save it for future runs.
|
960
|
+
* @param toStringCallback - The callback that will be called to transform the schema to a string when you want
|
961
|
+
* to compile the underlying schema to a string so you can save it for future runs.
|
883
962
|
*
|
884
963
|
* @returns The schema.
|
885
964
|
*/
|
@@ -891,14 +970,15 @@ export default class Schema<
|
|
891
970
|
) {
|
892
971
|
this.__extends = {
|
893
972
|
callback,
|
894
|
-
toStringCallback
|
895
|
-
}
|
896
|
-
return this
|
973
|
+
toStringCallback
|
974
|
+
};
|
975
|
+
return this;
|
897
976
|
}
|
898
977
|
|
899
978
|
/**
|
900
|
-
* This function is used to transform the value to the representation of the schema. When using the {@link data}
|
901
|
-
* control to add data cleaning for example, transforming the data
|
979
|
+
* This function is used to transform the value to the representation of the schema. When using the {@link data}
|
980
|
+
* function. With this function you have full control to add data cleaning for example, transforming the data
|
981
|
+
* and whatever. Another use case is when you want to return deeply nested recursive data.
|
902
982
|
* The schema maps to itself.
|
903
983
|
*
|
904
984
|
* @example
|
@@ -937,25 +1017,31 @@ export default class Schema<
|
|
937
1017
|
* ```
|
938
1018
|
* @param toRepresentationCallback - The callback that will be called to transform the value to the representation.
|
939
1019
|
* @param options - Options for the toRepresentation function.
|
940
|
-
* @param options.after - Whether the toRepresentationCallback should be called after the existing
|
941
|
-
*
|
1020
|
+
* @param options.after - Whether the toRepresentationCallback should be called after the existing
|
1021
|
+
* toRepresentationCallback. Defaults to true.
|
1022
|
+
* @param options.before - Whether the toRepresentationCallback should be called before the existing
|
1023
|
+
* toRepresentationCallback. Defaults to true.
|
942
1024
|
*
|
943
1025
|
* @returns The schema with a new return type
|
944
1026
|
*/
|
945
1027
|
toRepresentation<TRepresentation>(
|
946
|
-
toRepresentationCallback: (value: TType['representation']) => Promise<TRepresentation
|
1028
|
+
toRepresentationCallback: (value: TType['representation']) => Promise<TRepresentation> | TRepresentation,
|
947
1029
|
options?: {
|
948
1030
|
after?: boolean;
|
949
1031
|
before?: boolean;
|
950
1032
|
}
|
951
1033
|
) {
|
952
1034
|
if (this.__toRepresentation) {
|
953
|
-
const before =
|
954
|
-
|
1035
|
+
const before =
|
1036
|
+
typeof options?.before === 'boolean'
|
1037
|
+
? options.before
|
1038
|
+
: typeof options?.after === 'boolean'
|
1039
|
+
? !options.after
|
1040
|
+
: true;
|
955
1041
|
const existingToRepresentation = this.__toRepresentation;
|
956
|
-
|
1042
|
+
|
957
1043
|
this.__toRepresentation = async (value) => {
|
958
|
-
if (before) return toRepresentationCallback(await existingToRepresentation(value))
|
1044
|
+
if (before) return toRepresentationCallback(await existingToRepresentation(value));
|
959
1045
|
else return existingToRepresentation(await toRepresentationCallback(value));
|
960
1046
|
};
|
961
1047
|
} else this.__toRepresentation = toRepresentationCallback;
|
@@ -973,8 +1059,9 @@ export default class Schema<
|
|
973
1059
|
}
|
974
1060
|
|
975
1061
|
/**
|
976
|
-
* This function is used to transform the value to the internal representation of the schema. This is useful
|
977
|
-
* to a type that the schema adapter can understand. For example, you
|
1062
|
+
* This function is used to transform the value to the internal representation of the schema. This is useful
|
1063
|
+
* when you want to transform the value to a type that the schema adapter can understand. For example, you
|
1064
|
+
* might want to transform a string to a date. This is the function you use.
|
978
1065
|
*
|
979
1066
|
* @example
|
980
1067
|
* ```typescript
|
@@ -1026,8 +1113,9 @@ export default class Schema<
|
|
1026
1113
|
}
|
1027
1114
|
|
1028
1115
|
/**
|
1029
|
-
* Called before the validation of the schema. Let's say that you want to validate a date that might receive a
|
1030
|
-
* here BEFORE the validation. This pretty much transforms the value
|
1116
|
+
* Called before the validation of the schema. Let's say that you want to validate a date that might receive a
|
1117
|
+
* string, you can convert that string to a date here BEFORE the validation. This pretty much transforms the value
|
1118
|
+
* to a type that the schema adapter can understand.
|
1031
1119
|
*
|
1032
1120
|
* @example
|
1033
1121
|
* ```
|
@@ -1066,7 +1154,7 @@ export default class Schema<
|
|
1066
1154
|
async compile(adapter: SchemaAdapter) {
|
1067
1155
|
const data = await this.__transformToAdapter({
|
1068
1156
|
shouldAddStringVersion: true,
|
1069
|
-
force: true
|
1157
|
+
force: true
|
1070
1158
|
} as any);
|
1071
1159
|
|
1072
1160
|
const stringVersions = data.map((value) => value.asString);
|
@@ -1077,17 +1165,8 @@ export default class Schema<
|
|
1077
1165
|
..._args: any[]
|
1078
1166
|
): Schema<TType> {
|
1079
1167
|
const result = new Schema<TType>();
|
1080
|
-
|
1081
|
-
const adapterInstance = getDefaultAdapter();
|
1082
|
-
result.__transformedSchemas[adapterInstance.constructor.name] = {
|
1083
|
-
transformed: false,
|
1084
|
-
adapter: adapterInstance,
|
1085
|
-
schemas: [],
|
1086
|
-
};
|
1087
|
-
|
1088
1168
|
return result;
|
1089
1169
|
}
|
1090
1170
|
}
|
1091
1171
|
|
1092
1172
|
export const schema = Schema.new;
|
1093
|
-
|