@cleverbrush/schema 1.1.10 → 2.0.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/README.md +1314 -101
- package/dist/builders/AnySchemaBuilder.d.ts +55 -15
- package/dist/builders/AnySchemaBuilder.js +2 -112
- package/dist/builders/AnySchemaBuilder.js.map +1 -0
- package/dist/builders/ArraySchemaBuilder.d.ts +124 -23
- package/dist/builders/ArraySchemaBuilder.js +2 -284
- package/dist/builders/ArraySchemaBuilder.js.map +1 -0
- package/dist/builders/BooleanSchemaBuilder.d.ts +95 -20
- package/dist/builders/BooleanSchemaBuilder.js +2 -150
- package/dist/builders/BooleanSchemaBuilder.js.map +1 -0
- package/dist/builders/DateSchemaBuilder.d.ts +135 -37
- package/dist/builders/DateSchemaBuilder.js +2 -433
- package/dist/builders/DateSchemaBuilder.js.map +1 -0
- package/dist/builders/ExternSchemaBuilder.d.ts +200 -0
- package/dist/builders/ExternSchemaBuilder.js +2 -0
- package/dist/builders/ExternSchemaBuilder.js.map +1 -0
- package/dist/builders/FunctionSchemaBuilder.d.ts +58 -15
- package/dist/builders/FunctionSchemaBuilder.js +2 -113
- package/dist/builders/FunctionSchemaBuilder.js.map +1 -0
- package/dist/builders/LazySchemaBuilder.d.ts +167 -0
- package/dist/builders/NullSchemaBuilder.d.ts +162 -0
- package/dist/builders/NumberSchemaBuilder.d.ts +143 -31
- package/dist/builders/NumberSchemaBuilder.js +2 -386
- package/dist/builders/NumberSchemaBuilder.js.map +1 -0
- package/dist/builders/ObjectSchemaBuilder.d.ts +266 -61
- package/dist/builders/ObjectSchemaBuilder.js +2 -589
- package/dist/builders/ObjectSchemaBuilder.js.map +1 -0
- package/dist/builders/PropertyValidationResult.d.ts +68 -0
- package/dist/builders/RecordSchemaBuilder.d.ts +341 -0
- package/dist/builders/RecordSchemaBuilder.js +2 -0
- package/dist/builders/RecordSchemaBuilder.js.map +1 -0
- package/dist/builders/SchemaBuilder.d.ts +818 -30
- package/dist/builders/StringSchemaBuilder.d.ts +152 -37
- package/dist/builders/StringSchemaBuilder.js +2 -414
- package/dist/builders/StringSchemaBuilder.js.map +1 -0
- package/dist/builders/TupleSchemaBuilder.d.ts +248 -0
- package/dist/builders/TupleSchemaBuilder.js +2 -0
- package/dist/builders/TupleSchemaBuilder.js.map +1 -0
- package/dist/builders/UnionSchemaBuilder.d.ts +133 -39
- package/dist/builders/UnionSchemaBuilder.js +2 -216
- package/dist/builders/UnionSchemaBuilder.js.map +1 -0
- package/dist/chunk-BFCMDDTX.js +2 -0
- package/dist/chunk-BFCMDDTX.js.map +1 -0
- package/dist/chunk-CTP4RHDG.js +2 -0
- package/dist/chunk-CTP4RHDG.js.map +1 -0
- package/dist/chunk-EUQ5AE3H.js +2 -0
- package/dist/chunk-EUQ5AE3H.js.map +1 -0
- package/dist/chunk-FWUEUW2N.js +2 -0
- package/dist/chunk-FWUEUW2N.js.map +1 -0
- package/dist/chunk-IJ6FO37G.js +2 -0
- package/dist/chunk-IJ6FO37G.js.map +1 -0
- package/dist/chunk-KESLT5EE.js +2 -0
- package/dist/chunk-KESLT5EE.js.map +1 -0
- package/dist/chunk-KFTO7TMB.js +2 -0
- package/dist/chunk-KFTO7TMB.js.map +1 -0
- package/dist/chunk-MKAYFPAR.js +2 -0
- package/dist/chunk-MKAYFPAR.js.map +1 -0
- package/dist/chunk-NXPH3ZUW.js +2 -0
- package/dist/chunk-NXPH3ZUW.js.map +1 -0
- package/dist/chunk-S5TC6NSU.js +2 -0
- package/dist/chunk-S5TC6NSU.js.map +1 -0
- package/dist/chunk-YWBNVHR6.js +2 -0
- package/dist/chunk-YWBNVHR6.js.map +1 -0
- package/dist/chunk-Z7QZ7IXT.js +2 -0
- package/dist/chunk-Z7QZ7IXT.js.map +1 -0
- package/dist/chunk-ZAN4ZHCJ.js +2 -0
- package/dist/chunk-ZAN4ZHCJ.js.map +1 -0
- package/dist/chunk-ZUPYV5TI.js +2 -0
- package/dist/chunk-ZUPYV5TI.js.map +1 -0
- package/dist/core.d.ts +23 -0
- package/dist/core.js +2 -0
- package/dist/core.js.map +1 -0
- package/dist/extension.d.ts +413 -0
- package/dist/extensions/array.d.ts +112 -0
- package/dist/extensions/enum.d.ts +190 -0
- package/dist/extensions/index.d.ts +108 -0
- package/dist/extensions/nullable.d.ts +26 -0
- package/dist/extensions/number.d.ts +228 -0
- package/dist/extensions/string.d.ts +332 -0
- package/dist/extensions/util.d.ts +45 -0
- package/dist/index.d.ts +7 -20
- package/dist/index.js +2 -19
- package/dist/index.js.map +1 -0
- package/dist/utils/transaction.d.ts +27 -4
- package/package.json +74 -6
- package/dist/builders/SchemaBuilder.js +0 -275
- package/dist/utils/transaction.js +0 -178
|
@@ -1,14 +1,91 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import type { StandardSchemaV1 } from '@standard-schema/spec';
|
|
2
|
+
import { type Transaction } from '../utils/transaction.js';
|
|
3
|
+
import type { ArraySchemaBuilder } from './ArraySchemaBuilder.js';
|
|
4
|
+
import type { ExternSchemaBuilder } from './ExternSchemaBuilder.js';
|
|
5
|
+
import type { ObjectSchemaBuilder } from './ObjectSchemaBuilder.js';
|
|
6
|
+
/** @internal Symbol used as the key for the type brand on schema builders. */
|
|
7
|
+
declare const __type: unique symbol;
|
|
8
|
+
/** @internal */
|
|
9
|
+
export type SchemaTypeBrand = typeof __type;
|
|
10
|
+
/** @internal Symbol used as the key for the default-value brand on schema builders. */
|
|
11
|
+
declare const __hasDefault: unique symbol;
|
|
12
|
+
/** @internal */
|
|
13
|
+
export type HasDefaultBrand = typeof __hasDefault;
|
|
14
|
+
/** Symbol used as the key for branded/opaque types. */
|
|
15
|
+
declare const __brand: unique symbol;
|
|
16
|
+
/** Symbol used as the key for branded/opaque types. */
|
|
17
|
+
export type BRAND = typeof __brand;
|
|
18
|
+
/**
|
|
19
|
+
* Intersects a base type with a phantom brand tag.
|
|
20
|
+
* The brand exists only at the type level — zero runtime cost.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```ts
|
|
24
|
+
* type Email = Brand<string, 'Email'>;
|
|
25
|
+
* type UserId = Brand<number, 'UserId'>;
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export type Brand<T, TBrand extends string | symbol> = T & {
|
|
29
|
+
readonly [K in BRAND]: TBrand;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Infers the TypeScript type that a `SchemaBuilder` instance validates.
|
|
33
|
+
* Takes into account type optimizations (via `optimize()`) and whether the schema is optional.
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```ts
|
|
37
|
+
* const userSchema = object({ name: string(), age: number().optional() });
|
|
38
|
+
* type User = InferType<typeof userSchema>;
|
|
39
|
+
* // { name: string; age?: number }
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
export type InferType<T> = T extends {
|
|
43
|
+
optimize: (...args: any[]) => {
|
|
44
|
+
readonly [K in SchemaTypeBrand]: infer TOptimized;
|
|
45
|
+
};
|
|
46
|
+
} ? TOptimized : T extends {
|
|
47
|
+
readonly [K in SchemaTypeBrand]: infer TType;
|
|
48
|
+
} ? TType : T;
|
|
49
|
+
/**
|
|
50
|
+
* Represents a single validation error with a human-readable error message.
|
|
51
|
+
*/
|
|
5
52
|
export type ValidationError = {
|
|
6
|
-
path: string;
|
|
7
53
|
message: string;
|
|
8
54
|
};
|
|
55
|
+
/**
|
|
56
|
+
* Used to represent a validation result for nested
|
|
57
|
+
* objects/properties. Contains a list of errors and
|
|
58
|
+
* the value that caused them.
|
|
59
|
+
*/
|
|
60
|
+
export type NestedValidationResult<TSchema, TRootSchema extends ObjectSchemaBuilder<any, any, any, any, any>, TParentPropertyDescriptor> = {
|
|
61
|
+
/**
|
|
62
|
+
* Value that property had and which caused error or errors
|
|
63
|
+
*/
|
|
64
|
+
seenValue?: InferType<TSchema>;
|
|
65
|
+
/**
|
|
66
|
+
* A list of errors, empty if object satisfies a schema
|
|
67
|
+
*/
|
|
68
|
+
errors: ReadonlyArray<string>;
|
|
69
|
+
/**
|
|
70
|
+
* Whether validation passed for this property and all of its children.
|
|
71
|
+
*/
|
|
72
|
+
isValid: boolean;
|
|
73
|
+
get descriptor(): PropertyDescriptorInner<TRootSchema, TSchema, TParentPropertyDescriptor>;
|
|
74
|
+
};
|
|
75
|
+
/**
|
|
76
|
+
* Utility type that makes a value `T` optional (i.e. `T | undefined`).
|
|
77
|
+
* Used internally by {@link InferType} to represent optional schema fields.
|
|
78
|
+
*/
|
|
9
79
|
export type MakeOptional<T> = {
|
|
10
80
|
prop?: T;
|
|
11
81
|
}['prop'];
|
|
82
|
+
/**
|
|
83
|
+
* Type of the function that provides a validation error message for
|
|
84
|
+
* the given `seenValue` and `schema`. Can be a string or a function
|
|
85
|
+
* returning a string or a promise of a string.
|
|
86
|
+
* Should be used to provide a custom validation error message.
|
|
87
|
+
*/
|
|
88
|
+
export type ValidationErrorMessageProvider<TSchema extends SchemaBuilder<any, any, any, any, any> = SchemaBuilder<any, any, any, any, any>> = string | ((seenValue: InferType<TSchema>, schema: TSchema) => string | Promise<string>);
|
|
12
89
|
export type ValidationResult<T> = {
|
|
13
90
|
/**
|
|
14
91
|
* If `true` - object satisfies schema
|
|
@@ -21,33 +98,303 @@ export type ValidationResult<T> = {
|
|
|
21
98
|
object?: T;
|
|
22
99
|
errors?: ValidationError[];
|
|
23
100
|
};
|
|
101
|
+
/**
|
|
102
|
+
* Error thrown by {@link SchemaBuilder.parse | parse()} and
|
|
103
|
+
* {@link SchemaBuilder.parseAsync | parseAsync()} when validation fails.
|
|
104
|
+
* Carries the full array of {@link ValidationError | validation errors}.
|
|
105
|
+
*/
|
|
106
|
+
export declare class SchemaValidationError extends Error {
|
|
107
|
+
readonly errors: ValidationError[];
|
|
108
|
+
constructor(errors: ValidationError[]);
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Internal result returned by the `preValidate` step of `SchemaBuilder`.
|
|
112
|
+
* Contains the validation context, any early errors, and the transaction
|
|
113
|
+
* wrapping the (possibly preprocessed) value.
|
|
114
|
+
*/
|
|
24
115
|
export type PreValidationResult<T, TTransactionType> = Omit<ValidationResult<T>, 'object'> & {
|
|
25
116
|
context: ValidationContext;
|
|
26
117
|
transaction?: Transaction<TTransactionType>;
|
|
118
|
+
rootPropertyDescriptor?: PropertyDescriptor<any, any, undefined>;
|
|
27
119
|
};
|
|
28
120
|
type ValidatorResult<T> = Omit<ValidationResult<T>, 'object' | 'errors'> & {
|
|
29
|
-
errors?:
|
|
121
|
+
errors?: ValidationError[];
|
|
30
122
|
};
|
|
123
|
+
/**
|
|
124
|
+
* A function that transforms the value before validation.
|
|
125
|
+
* Preprocessors run in order before validators and can modify or replace the value.
|
|
126
|
+
*
|
|
127
|
+
* @param object - the current value to preprocess
|
|
128
|
+
* @returns the transformed value, or a Promise resolving to it
|
|
129
|
+
*/
|
|
31
130
|
export type Preprocessor<T> = (object: T) => Promise<T> | T;
|
|
131
|
+
/**
|
|
132
|
+
* A custom validation function that checks a value and returns a result
|
|
133
|
+
* indicating whether the value is valid, along with optional error messages.
|
|
134
|
+
*
|
|
135
|
+
* @param object - the value to validate
|
|
136
|
+
* @returns a result with `valid` boolean and optional `errors` array, or a Promise resolving to it
|
|
137
|
+
*/
|
|
32
138
|
export type Validator<T> = (object: T) => Promise<ValidatorResult<T>> | ValidatorResult<T>;
|
|
139
|
+
/**
|
|
140
|
+
* Internal wrapper that pairs a preprocessor function with metadata
|
|
141
|
+
* indicating whether it may mutate the value.
|
|
142
|
+
*/
|
|
143
|
+
export type PreprocessorEntry<T> = {
|
|
144
|
+
fn: Preprocessor<T>;
|
|
145
|
+
mutates: boolean;
|
|
146
|
+
};
|
|
147
|
+
/**
|
|
148
|
+
* Internal wrapper that pairs a validator function with metadata
|
|
149
|
+
* indicating whether it may mutate the value.
|
|
150
|
+
*/
|
|
151
|
+
export type ValidatorEntry<T> = {
|
|
152
|
+
fn: Validator<T>;
|
|
153
|
+
mutates: boolean;
|
|
154
|
+
};
|
|
155
|
+
/**
|
|
156
|
+
* Configuration properties used to construct a `SchemaBuilder` instance.
|
|
157
|
+
* Contains the schema type identifier, requirement flag, and lists of
|
|
158
|
+
* preprocessors and validators.
|
|
159
|
+
*/
|
|
33
160
|
export type SchemaBuilderProps<T> = {
|
|
34
161
|
type: string;
|
|
35
162
|
isRequired?: boolean;
|
|
36
|
-
|
|
37
|
-
|
|
163
|
+
isNullable?: boolean;
|
|
164
|
+
isReadonly?: boolean;
|
|
165
|
+
preprocessors: PreprocessorEntry<T>[];
|
|
166
|
+
validators: ValidatorEntry<T>[];
|
|
167
|
+
requiredValidationErrorMessageProvider?: ValidationErrorMessageProvider;
|
|
168
|
+
extensions?: Record<string, unknown>;
|
|
169
|
+
defaultValue?: T | (() => T);
|
|
170
|
+
catchValue?: T | (() => T);
|
|
171
|
+
hasCatch?: boolean;
|
|
172
|
+
description?: string;
|
|
38
173
|
};
|
|
39
|
-
export type ValidationContext = {
|
|
40
|
-
/**
|
|
41
|
-
* Path of the field. **Optional**, used to display correct error path in the {@link ValidationError}
|
|
42
|
-
*/
|
|
43
|
-
path?: string;
|
|
174
|
+
export type ValidationContext<TSchema extends SchemaBuilder<any, any, any, any> = SchemaBuilder<any, any, any, any>> = {
|
|
44
175
|
/**
|
|
45
176
|
* Optional. By default validation will stop after the first validation error, in case if
|
|
46
177
|
* you want to receive all validation erors, please set this flag to `true`.
|
|
47
178
|
* You might need it to display validation errors.
|
|
48
179
|
*/
|
|
49
180
|
doNotStopOnFirstError?: boolean;
|
|
181
|
+
/**
|
|
182
|
+
* Optional. If you define a `rootPropertyDescriptor` while validating an object,
|
|
183
|
+
* it will report all validation errors with the path starting from the root property.
|
|
184
|
+
* Normally it's used internally by the library for validation of nested objects and
|
|
185
|
+
* should not be used directly (but who knows, maybe you will find a use case for it).
|
|
186
|
+
*/
|
|
187
|
+
rootPropertyDescriptor?: TSchema extends ObjectSchemaBuilder<any, any, any, any> ? PropertyDescriptor<TSchema, TSchema, undefined> : never;
|
|
188
|
+
/**
|
|
189
|
+
* Optional. This is a property descriptor for the current object being validated.
|
|
190
|
+
* This descriptor is descendant of the `rootPropertyDescriptor` and is used to provide
|
|
191
|
+
* a path to the current object being validated in the root object.
|
|
192
|
+
* Normally it's used internally by the library for validation of nested objects and
|
|
193
|
+
* should not be used directly (but who knows, maybe you will find a use case for it).
|
|
194
|
+
*/
|
|
195
|
+
currentPropertyDescriptor?: TSchema extends ObjectSchemaBuilder<any, any, any> ? PropertyDescriptor<TSchema, TSchema, unknown> : never;
|
|
196
|
+
/**
|
|
197
|
+
* Optional. Used along with `rootPropertyDescriptor` and `currentPropertyDescriptor` to provide
|
|
198
|
+
* a root validation object, this object will be used to retrieve the value of properties
|
|
199
|
+
* using the `rootPropertyDescriptor` because the `rootPropertyDescriptor` is a property descriptor
|
|
200
|
+
* for the root object, and it needs the root object along with the whole structure to get the
|
|
201
|
+
* value of the property.
|
|
202
|
+
*
|
|
203
|
+
* Normally it's used internally by the library for validation of nested objects and
|
|
204
|
+
* should not be used directly (but who knows, maybe you will find a use case for it).
|
|
205
|
+
*/
|
|
206
|
+
rootValidationObject?: InferType<TSchema>;
|
|
207
|
+
};
|
|
208
|
+
/**
|
|
209
|
+
* A symbol to mark property descriptors in the schema.
|
|
210
|
+
* Normally, you should not use it directly unless you want
|
|
211
|
+
* to develop some advanced features or extend the library.
|
|
212
|
+
* In normal conditions it's used internally by the library.
|
|
213
|
+
*/
|
|
214
|
+
export declare const SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR: unique symbol;
|
|
215
|
+
/**
|
|
216
|
+
* A symbol that marks a schema as having sub-properties that can
|
|
217
|
+
* participate in property descriptor trees. When a schema exposes
|
|
218
|
+
* `[SYMBOL_HAS_PROPERTIES] = true` **and** its `introspect()` returns
|
|
219
|
+
* a `properties` record, it will be recursed into by
|
|
220
|
+
* `ObjectSchemaBuilder.getPropertiesFor()` — the same way nested
|
|
221
|
+
* `ObjectSchemaBuilder` instances are.
|
|
222
|
+
*
|
|
223
|
+
* Currently implemented by `ObjectSchemaBuilder` (always) and
|
|
224
|
+
* `ExternSchemaBuilder` (when created with an explicit property map).
|
|
225
|
+
*/
|
|
226
|
+
export declare const SYMBOL_HAS_PROPERTIES: unique symbol;
|
|
227
|
+
/**
|
|
228
|
+
* Describes a property in a schema. And gives you
|
|
229
|
+
* a possibility to access property value and set it.
|
|
230
|
+
* suppose you have a schema like this:
|
|
231
|
+
* ```ts
|
|
232
|
+
* const schema = object({
|
|
233
|
+
* name: string(),
|
|
234
|
+
* address: object({
|
|
235
|
+
* city: string(),
|
|
236
|
+
* country: string()
|
|
237
|
+
* }),
|
|
238
|
+
* id: number()
|
|
239
|
+
* });
|
|
240
|
+
* ```
|
|
241
|
+
* then you can get a property descriptor for the `address.city` property
|
|
242
|
+
* like this:
|
|
243
|
+
* ```ts
|
|
244
|
+
* const addressCityDescriptor = object.getPropertiesFor(schema).address.city;
|
|
245
|
+
* ```
|
|
246
|
+
*
|
|
247
|
+
* And then you can use it to get and set the value of this property having the object:
|
|
248
|
+
* ```ts
|
|
249
|
+
* const obj = {
|
|
250
|
+
* name: 'Leo',
|
|
251
|
+
* address: {
|
|
252
|
+
* city: 'Kozelsk',
|
|
253
|
+
* country: 'Russia'
|
|
254
|
+
* },
|
|
255
|
+
* id: 123
|
|
256
|
+
* };
|
|
257
|
+
*
|
|
258
|
+
* const success = addressCityDescriptor.setValue(obj, 'Venyov');
|
|
259
|
+
* // this returns you a boolean value indicating if the value was set successfully
|
|
260
|
+
* ```
|
|
261
|
+
*/
|
|
262
|
+
export type PropertySetterOptions = {
|
|
263
|
+
/**
|
|
264
|
+
* If set to `true`, the method will create missing structure
|
|
265
|
+
* in the object to set the value. For example, if you have a schema
|
|
266
|
+
* and property descriptor like this:
|
|
267
|
+
* ```ts
|
|
268
|
+
* const schema = object({
|
|
269
|
+
* address: object({
|
|
270
|
+
* city: string(),
|
|
271
|
+
* country: string()
|
|
272
|
+
* }),
|
|
273
|
+
* });
|
|
274
|
+
* const addressCityDescriptor = object.getPropertiesFor(schema).address.city;
|
|
275
|
+
* ```
|
|
276
|
+
* And then you try to set a new value to the `address.city` property on the object
|
|
277
|
+
* which does not have `address` property:
|
|
278
|
+
* ```ts
|
|
279
|
+
* const obj = {
|
|
280
|
+
* name: 'Leo'
|
|
281
|
+
* };
|
|
282
|
+
* const success = addressCityDescriptor.setValue(obj, 'Venyov', { createMissingStructure: true });
|
|
283
|
+
* // success === true
|
|
284
|
+
* // obj === {
|
|
285
|
+
* // name: 'Leo',
|
|
286
|
+
* // address: {
|
|
287
|
+
* // city: 'Venyov'
|
|
288
|
+
* // }
|
|
289
|
+
* // }
|
|
290
|
+
*/
|
|
291
|
+
createMissingStructure?: boolean;
|
|
292
|
+
};
|
|
293
|
+
/**
|
|
294
|
+
* Extracts the inner property descriptor type from a `PropertyDescriptor`.
|
|
295
|
+
* Returns `undefined` if `T` is not a valid `PropertyDescriptor`.
|
|
296
|
+
*/
|
|
297
|
+
export type PropertyDescriptorInnerFromPropertyDescriptor<T> = T extends PropertyDescriptor<infer TSchema, infer TPropertySchema, infer TParentPropertyDescriptor> ? PropertyDescriptorInner<TSchema, TPropertySchema, TParentPropertyDescriptor> : undefined;
|
|
298
|
+
export type PropertyDescriptorInner<TSchema extends ObjectSchemaBuilder<any, any, any, any, any>, TPropertySchema, TParentPropertyDescriptor> = {
|
|
299
|
+
/**
|
|
300
|
+
* Sets a new value to the property. If the process was successful,
|
|
301
|
+
* the method returns `true`, otherwise `false`.
|
|
302
|
+
* It can return `false` if the property could not be set to the object
|
|
303
|
+
* which can happen if the `setValue` method is called with an object
|
|
304
|
+
* which does not comply with the schema.
|
|
305
|
+
* for example, if you have a schema and property descriptopr like this:
|
|
306
|
+
* ```ts
|
|
307
|
+
* const schema = object({
|
|
308
|
+
* name: string(),
|
|
309
|
+
* address: object({
|
|
310
|
+
* city: string(),
|
|
311
|
+
* country: string()
|
|
312
|
+
* }),
|
|
313
|
+
* id: number()
|
|
314
|
+
* });
|
|
315
|
+
*
|
|
316
|
+
* const addressCityDescriptor = object.getPropertiesFor(schema).address.city;
|
|
317
|
+
* ```
|
|
318
|
+
* And then you try to set a new value to the `address.city` property on the object
|
|
319
|
+
* which does not have `address` property:
|
|
320
|
+
* ```ts
|
|
321
|
+
* const obj = {
|
|
322
|
+
* name: 'Leo'
|
|
323
|
+
* };
|
|
324
|
+
*
|
|
325
|
+
* const success = addressCityDescriptor.setValue(obj, 'Venyov');
|
|
326
|
+
* // success === false
|
|
327
|
+
* ```
|
|
328
|
+
*
|
|
329
|
+
* @param obj Object to set the value to
|
|
330
|
+
* @param value a new value to set to the property
|
|
331
|
+
* @param options additional optional parameters to control the process
|
|
332
|
+
* @returns
|
|
333
|
+
*/
|
|
334
|
+
setValue: (obj: InferType<TSchema>, value: InferType<TPropertySchema>, options?: PropertySetterOptions) => boolean;
|
|
335
|
+
/**
|
|
336
|
+
* Gets the value of the property from the object.
|
|
337
|
+
* @param obj object to get the value from
|
|
338
|
+
* @returns an object containing a `value` and `success` properties. `value` is the value of the property
|
|
339
|
+
* if it was found in the object, `success` is a boolean value indicating if the property was found in the object.
|
|
340
|
+
*/
|
|
341
|
+
getValue: (obj: InferType<TSchema>) => {
|
|
342
|
+
value?: InferType<TPropertySchema>;
|
|
343
|
+
success: boolean;
|
|
344
|
+
};
|
|
345
|
+
/**
|
|
346
|
+
* Gets the schema for the property described by the property descriptor.
|
|
347
|
+
* @returns a schema for the property
|
|
348
|
+
*/
|
|
349
|
+
getSchema: () => TPropertySchema;
|
|
350
|
+
parent: PropertyDescriptorInnerFromPropertyDescriptor<TParentPropertyDescriptor>;
|
|
351
|
+
};
|
|
352
|
+
/**
|
|
353
|
+
* A wrapper object keyed by {@link SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR} that
|
|
354
|
+
* holds a {@link PropertyDescriptorInner} for a particular property within
|
|
355
|
+
* an object schema. Used to get/set property values on validated objects.
|
|
356
|
+
*/
|
|
357
|
+
export type PropertyDescriptor<TRootSchema extends ObjectSchemaBuilder<any, any, any, any, any>, TPropertySchema, TParentPropertyDescriptor> = {
|
|
358
|
+
[SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR]: PropertyDescriptorInner<TRootSchema, TPropertySchema, TParentPropertyDescriptor>;
|
|
50
359
|
};
|
|
360
|
+
/**
|
|
361
|
+
* A tree of property descriptors for the schema.
|
|
362
|
+
* Has a possibility to filter properties by the type (`TAssignableTo` type parameter).
|
|
363
|
+
*/
|
|
364
|
+
export type PropertyDescriptorTree<TSchema extends ObjectSchemaBuilder<any, any, any, any, any>, TRootSchema extends ObjectSchemaBuilder<any, any, any, any, any> = TSchema, TAssignableTo = any, TParentPropertyDescriptor = undefined> = PropertyDescriptor<TRootSchema, TSchema, TParentPropertyDescriptor> & (TSchema extends ObjectSchemaBuilder<infer TProperties, any, any> ? {
|
|
365
|
+
[K in keyof TProperties]: TProperties[K] extends ObjectSchemaBuilder<any, any, any> ? PropertyDescriptorTree<TProperties[K], TRootSchema, any, PropertyDescriptor<TRootSchema, TSchema, TParentPropertyDescriptor>> : TProperties[K] extends ExternSchemaBuilder<any, any, any, any, any, any, infer TExternResult> ? PropertyDescriptor<TRootSchema, TProperties[K], PropertyDescriptor<TRootSchema, TSchema, TParentPropertyDescriptor>> & ExternOutputPropertyDescriptors<TExternResult, TRootSchema, PropertyDescriptor<TRootSchema, TProperties[K], PropertyDescriptor<TRootSchema, TSchema, TParentPropertyDescriptor>>> : TProperties[K] extends ArraySchemaBuilder<infer TArrayElement, any, any> ? TArrayElement extends ObjectSchemaBuilder<any, any, any, any, any> ? PropertyDescriptor<TRootSchema, TProperties[K], PropertyDescriptor<TRootSchema, TSchema, TParentPropertyDescriptor>> : InferType<TProperties[K]> extends TAssignableTo ? PropertyDescriptor<TRootSchema, TProperties[K], PropertyDescriptor<TRootSchema, TSchema, TParentPropertyDescriptor>> : never : InferType<TProperties[K]> extends TAssignableTo ? PropertyDescriptor<TRootSchema, TProperties[K], PropertyDescriptor<TRootSchema, TSchema, TParentPropertyDescriptor>> : never;
|
|
366
|
+
} : never);
|
|
367
|
+
/**
|
|
368
|
+
* Recursively maps the keys of an extern schema's output type into
|
|
369
|
+
* property descriptors. When a value is a plain-object type its keys
|
|
370
|
+
* are expanded recursively; primitives, arrays, Dates, and functions
|
|
371
|
+
* are treated as leaves.
|
|
372
|
+
*
|
|
373
|
+
* @internal
|
|
374
|
+
*/
|
|
375
|
+
type ExternOutputPropertyDescriptors<TOutput, TRootSchema extends ObjectSchemaBuilder<any, any, any, any, any>, TParentPropertyDescriptor> = TOutput extends Date | Function | readonly any[] | string | number | boolean | symbol | bigint | null | undefined ? {} : TOutput extends Record<string, any> ? {
|
|
376
|
+
[K in keyof TOutput]: PropertyDescriptor<TRootSchema, SchemaBuilder<TOutput[K], true, false, false, {}>, TParentPropertyDescriptor> & ExternOutputPropertyDescriptors<TOutput[K], TRootSchema, PropertyDescriptor<TRootSchema, SchemaBuilder<TOutput[K], true, false, false, {}>, TParentPropertyDescriptor>>;
|
|
377
|
+
} : {};
|
|
378
|
+
/**
|
|
379
|
+
* Creates an array augmented with non-enumerable NestedValidationResult
|
|
380
|
+
* properties (`seenValue`, `errors`, `isValid`, `descriptor`).
|
|
381
|
+
* Used by UnionSchemaBuilder and ArraySchemaBuilder to return hybrid
|
|
382
|
+
* arrays from `getErrorsFor()`.
|
|
383
|
+
*/
|
|
384
|
+
export declare function createHybridErrorArray<T extends any[]>(items: T, seenValue: () => any, errors: () => ReadonlyArray<string>, descriptor: () => any): T;
|
|
385
|
+
/**
|
|
386
|
+
* Resolves the full output type of a schema, accounting for `TRequired` and
|
|
387
|
+
* `TNullable` modifiers. Mirrors the branded `[__type]` computation so that
|
|
388
|
+
* the `~standard` Standard Schema property carries the correct inferred type.
|
|
389
|
+
*
|
|
390
|
+
* - When `TRequired = true` and `TNullable = false` the result is `TResult`.
|
|
391
|
+
* - When `TRequired = true` and `TNullable = true` the result is `TResult | null`.
|
|
392
|
+
* - When `TRequired = false` the result is wrapped by {@link MakeOptional},
|
|
393
|
+
* adding `| undefined` (and `| null` when also nullable).
|
|
394
|
+
*
|
|
395
|
+
* @internal
|
|
396
|
+
*/
|
|
397
|
+
type ResolvedSchemaType<TResult, TRequired extends boolean, TNullable extends boolean> = TRequired extends true ? TNullable extends true ? TResult | null : TResult : MakeOptional<TNullable extends true ? TResult | null : TResult>;
|
|
51
398
|
/**
|
|
52
399
|
* Base class for all schema builders. Provides basic functionality for schema building.
|
|
53
400
|
*
|
|
@@ -55,45 +402,195 @@ export type ValidationContext = {
|
|
|
55
402
|
* @typeparam TResult Type of the object that will be returned by `validate()` method.
|
|
56
403
|
* @typeparam TRequired If `true`, object will be required. If `false`, object will be optional.
|
|
57
404
|
*/
|
|
58
|
-
export declare abstract class SchemaBuilder<TResult = any, TRequired extends boolean = true> {
|
|
405
|
+
export declare abstract class SchemaBuilder<TResult = any, TRequired extends boolean = true, TNullable extends boolean = false, THasDefault extends boolean = false, TExtensions = {}> {
|
|
59
406
|
#private;
|
|
60
407
|
/**
|
|
61
|
-
*
|
|
408
|
+
* Type-level brand encoding the inferred type of this schema.
|
|
409
|
+
* Not emitted at runtime — used only by {@link InferType}.
|
|
410
|
+
* @internal
|
|
411
|
+
*/
|
|
412
|
+
readonly [__type]: TRequired extends true ? TNullable extends true ? TResult | null : TResult : MakeOptional<TNullable extends true ? TResult | null : TResult>;
|
|
413
|
+
/**
|
|
414
|
+
* Type-level brand encoding whether this schema has a default value.
|
|
415
|
+
* Not emitted at runtime — used by input type inference.
|
|
416
|
+
* @internal
|
|
417
|
+
*/
|
|
418
|
+
readonly [__hasDefault]: THasDefault;
|
|
419
|
+
/**
|
|
420
|
+
* Standard Schema v1 interface.
|
|
421
|
+
*
|
|
422
|
+
* Exposes this schema as a [Standard Schema v1](https://standardschema.dev/)
|
|
423
|
+
* validator, enabling out-of-the-box interoperability with any library that
|
|
424
|
+
* consumes the spec — including tRPC, TanStack Form, React Hook Form, T3 Env,
|
|
425
|
+
* Hono, Elysia, next-safe-action, and 50+ other tools.
|
|
426
|
+
*
|
|
427
|
+
* Every `SchemaBuilder` subclass (all 13 builders) inherits this property
|
|
428
|
+
* automatically — no additional setup required.
|
|
429
|
+
*
|
|
430
|
+
* **Shape of the returned object:**
|
|
431
|
+
* - `version` — always `1` (Standard Schema spec version)
|
|
432
|
+
* - `vendor` — `'@cleverbrush/schema'`
|
|
433
|
+
* - `validate(value)` — synchronous; wraps this builder's own `.validate()`
|
|
434
|
+
* and converts its result to the Standard Schema `Result<Output>` format:
|
|
435
|
+
* - Success: `{ value: <validated output> }`
|
|
436
|
+
* - Failure: `{ issues: [{ message: string }, …] }`
|
|
437
|
+
*
|
|
438
|
+
* The returned object is **cached** after the first access so repeated reads
|
|
439
|
+
* return the same reference (required by the spec).
|
|
440
|
+
*
|
|
441
|
+
* @example
|
|
442
|
+
* ```ts
|
|
443
|
+
* import { object, string, number } from '@cleverbrush/schema';
|
|
444
|
+
*
|
|
445
|
+
* const UserSchema = object({
|
|
446
|
+
* name: string().minLength(2),
|
|
447
|
+
* email: string().email(),
|
|
448
|
+
* age: number().min(18).optional(),
|
|
449
|
+
* });
|
|
450
|
+
*
|
|
451
|
+
* // Grab the Standard Schema interface
|
|
452
|
+
* const std = UserSchema['~standard'];
|
|
453
|
+
* // std.version === 1
|
|
454
|
+
* // std.vendor === '@cleverbrush/schema'
|
|
455
|
+
*
|
|
456
|
+
* const ok = std.validate({ name: 'Alice', email: 'alice@example.com' });
|
|
457
|
+
* // { value: { name: 'Alice', email: 'alice@example.com', age: undefined } }
|
|
458
|
+
*
|
|
459
|
+
* const fail = std.validate({ name: 'A', email: 'not-an-email' });
|
|
460
|
+
* // { issues: [{ message: 'minLength' }, { message: 'email' }] }
|
|
461
|
+
*
|
|
462
|
+
* // Pass directly to TanStack Form, T3 Env, tRPC, etc.:
|
|
463
|
+
* // validators: { onChange: UserSchema, onBlur: UserSchema }
|
|
464
|
+
* ```
|
|
465
|
+
*
|
|
466
|
+
* @see https://standardschema.dev/
|
|
467
|
+
*/
|
|
468
|
+
get ['~standard'](): StandardSchemaV1.Props<ResolvedSchemaType<TResult, TRequired, TNullable>>;
|
|
469
|
+
/**
|
|
470
|
+
* Set type of schema explicitly. `notUsed` param is needed only for case when JS is used. E.g. when you
|
|
62
471
|
* can't call method like `schema.hasType<Date>()`, so instead you can call `schema.hasType(new Date())`
|
|
63
472
|
* with the same result.
|
|
64
473
|
*/
|
|
65
474
|
abstract hasType<T>(notUsed?: T): any;
|
|
66
475
|
/**
|
|
67
476
|
* Clears type set by call to `.hasType<T>()`, default schema type inference will be used
|
|
68
|
-
* for schema
|
|
477
|
+
* for schema returned by this call.
|
|
69
478
|
*/
|
|
70
479
|
abstract clearHasType(): any;
|
|
71
480
|
/**
|
|
72
|
-
* Protected method used to create
|
|
73
|
-
* defined by the `props` object. Should be used to
|
|
481
|
+
* Protected method used to create a new instance of the Builder
|
|
482
|
+
* defined by the `props` object. Should be used to instantiate new
|
|
74
483
|
* builders to keep builder's immutability.
|
|
75
484
|
* @param props arbitrary props object
|
|
76
485
|
*/
|
|
77
486
|
protected abstract createFromProps(props: any): this;
|
|
487
|
+
/**
|
|
488
|
+
* The string identifier of the schema type (e.g. `'string'`, `'number'`, `'object'`).
|
|
489
|
+
*/
|
|
78
490
|
protected get type(): string;
|
|
491
|
+
/**
|
|
492
|
+
* Sets the schema type identifier. Must be a non-empty string.
|
|
493
|
+
*/
|
|
79
494
|
protected set type(value: string);
|
|
80
495
|
/**
|
|
81
496
|
* A list of preprocessors associated with
|
|
82
497
|
* the Builder
|
|
83
498
|
*/
|
|
84
|
-
protected get preprocessors():
|
|
499
|
+
protected get preprocessors(): PreprocessorEntry<TResult>[];
|
|
85
500
|
/**
|
|
86
501
|
* A list of validators associated with
|
|
87
502
|
* the Builder
|
|
88
503
|
*/
|
|
89
|
-
protected get validators():
|
|
504
|
+
protected get validators(): ValidatorEntry<TResult>[];
|
|
505
|
+
/**
|
|
506
|
+
* Whether the schema requires a non-null/non-undefined value.
|
|
507
|
+
*/
|
|
90
508
|
protected get isRequired(): TRequired;
|
|
509
|
+
/**
|
|
510
|
+
* Whether `null` is an accepted value for this schema.
|
|
511
|
+
*/
|
|
512
|
+
protected get isNullable(): boolean;
|
|
513
|
+
/**
|
|
514
|
+
* Sets the requirement flag. Must be a boolean.
|
|
515
|
+
*/
|
|
91
516
|
protected set isRequired(value: boolean);
|
|
92
|
-
protected preValidate(
|
|
93
517
|
/**
|
|
94
|
-
*
|
|
518
|
+
* The error message provider used for the "is required" error.
|
|
519
|
+
* Exposed for fast-path validation in subclasses.
|
|
520
|
+
*/
|
|
521
|
+
protected get requiredErrorMessage(): ValidationErrorMessageProvider;
|
|
522
|
+
/**
|
|
523
|
+
* Whether this schema has a default value configured via `.default()`.
|
|
524
|
+
* Exposed for fast-path validation in subclasses.
|
|
525
|
+
*/
|
|
526
|
+
protected get hasDefault(): boolean;
|
|
527
|
+
/**
|
|
528
|
+
* Whether this schema has a catch/fallback value configured via `.catch()`.
|
|
529
|
+
*/
|
|
530
|
+
protected get hasCatch(): boolean;
|
|
531
|
+
/**
|
|
532
|
+
* Resolves the catch/fallback value. If the stored value is a factory function,
|
|
533
|
+
* it is called to produce the value (useful for mutable fallbacks like `() => []`).
|
|
534
|
+
*/
|
|
535
|
+
protected resolveCatchValue(): TResult;
|
|
536
|
+
/**
|
|
537
|
+
* Whether this schema is marked as readonly.
|
|
538
|
+
* Type-level only — no runtime enforcement.
|
|
539
|
+
*/
|
|
540
|
+
protected get isReadonly(): boolean;
|
|
541
|
+
/**
|
|
542
|
+
* Resolves the default value. If the stored default is a function,
|
|
543
|
+
* it is called to produce the value (useful for mutable defaults).
|
|
544
|
+
*/
|
|
545
|
+
protected resolveDefaultValue(): TResult;
|
|
546
|
+
/**
|
|
547
|
+
* Whether `preValidateSync` can be skipped entirely.
|
|
548
|
+
* True when there are no preprocessors and no validators,
|
|
549
|
+
* so the only work would be the required check and wrapping
|
|
550
|
+
* in a noop transaction — which subclasses can do inline.
|
|
551
|
+
*/
|
|
552
|
+
protected get canSkipPreValidation(): boolean;
|
|
553
|
+
/**
|
|
554
|
+
* Whether `null` should count as a required-constraint violation.
|
|
555
|
+
*
|
|
556
|
+
* By default `null` is treated the same as `undefined` for the purposes
|
|
557
|
+
* of the required check — i.e. a required schema rejects both.
|
|
558
|
+
* Subclasses that may legally receive `null` as a value (e.g.
|
|
559
|
+
* `UnionSchemaBuilder` when a `NullSchemaBuilder` option is present)
|
|
560
|
+
* can override this to `false` so that `null` bypasses the required
|
|
561
|
+
* check and is passed directly to their option-validation logic.
|
|
562
|
+
*
|
|
563
|
+
* @protected
|
|
564
|
+
*/
|
|
565
|
+
protected get isNullRequiredViolation(): boolean;
|
|
566
|
+
/**
|
|
567
|
+
* Synchronous version of {@link preValidateAsync}.
|
|
568
|
+
* Throws at runtime if any preprocessor or validator returns a Promise.
|
|
569
|
+
*
|
|
570
|
+
* @param object - the value to pre-validate
|
|
571
|
+
* @param context - optional validation context settings
|
|
572
|
+
* @returns a `PreValidationResult` containing the preprocessed transaction, context, and any errors
|
|
573
|
+
* @throws Error if a preprocessor or validator returns a Promise (use {@link preValidateAsync} instead)
|
|
95
574
|
*/
|
|
96
|
-
object: any, context?: ValidationContext):
|
|
575
|
+
protected preValidateSync(object: any, context?: ValidationContext): PreValidationResult<any, {
|
|
576
|
+
validatedObject: any;
|
|
577
|
+
}>;
|
|
578
|
+
/**
|
|
579
|
+
* Async version of pre-validation. Runs preprocessors, validators, and the
|
|
580
|
+
* required/optional check on `object`. Supports async preprocessors,
|
|
581
|
+
* validators, and error message providers.
|
|
582
|
+
*
|
|
583
|
+
* @param object - the value to pre-validate
|
|
584
|
+
* @param context - optional validation context settings
|
|
585
|
+
* @returns a `PreValidationResult` containing the preprocessed transaction, context, and any errors
|
|
586
|
+
*/
|
|
587
|
+
protected preValidateAsync(object: any, context?: ValidationContext): Promise<PreValidationResult<any, {
|
|
588
|
+
validatedObject: any;
|
|
589
|
+
}>>;
|
|
590
|
+
/**
|
|
591
|
+
* @deprecated Use {@link preValidateAsync} instead. This alias will be removed in a future version.
|
|
592
|
+
*/
|
|
593
|
+
protected preValidate(object: any, context?: ValidationContext): Promise<PreValidationResult<any, {
|
|
97
594
|
validatedObject: any;
|
|
98
595
|
}>>;
|
|
99
596
|
/**
|
|
@@ -109,27 +606,209 @@ export declare abstract class SchemaBuilder<TResult = any, TRequired extends boo
|
|
|
109
606
|
* will be considered as valid).
|
|
110
607
|
*/
|
|
111
608
|
isRequired: boolean;
|
|
609
|
+
/**
|
|
610
|
+
* If set to `true`, schema values of `null` are considered valid.
|
|
611
|
+
*/
|
|
612
|
+
isNullable: boolean;
|
|
613
|
+
/**
|
|
614
|
+
* If set to `true`, the inferred type is marked as readonly.
|
|
615
|
+
* Type-level only — no runtime enforcement.
|
|
616
|
+
*/
|
|
617
|
+
isReadonly: boolean;
|
|
112
618
|
/**
|
|
113
619
|
* Array of preprocessor functions
|
|
114
620
|
*/
|
|
115
|
-
preprocessors: readonly
|
|
621
|
+
preprocessors: readonly PreprocessorEntry<TResult>[];
|
|
116
622
|
/**
|
|
117
623
|
* Array of validator functions
|
|
118
624
|
*/
|
|
119
|
-
validators: readonly
|
|
625
|
+
validators: readonly ValidatorEntry<TResult>[];
|
|
626
|
+
/**
|
|
627
|
+
* Custom error message provider for the 'is required' validation error.
|
|
628
|
+
*/
|
|
629
|
+
requiredValidationErrorMessageProvider: ValidationErrorMessageProvider<SchemaBuilder<any, any, any, any, any>>;
|
|
630
|
+
/**
|
|
631
|
+
* Extension metadata. Stores custom state set by schema extensions.
|
|
632
|
+
*/
|
|
633
|
+
extensions: {
|
|
634
|
+
[x: string]: unknown;
|
|
635
|
+
};
|
|
636
|
+
/**
|
|
637
|
+
* Whether a default value (or factory) has been set on this schema.
|
|
638
|
+
*/
|
|
639
|
+
hasDefault: boolean;
|
|
640
|
+
/**
|
|
641
|
+
* The default value or factory function.
|
|
642
|
+
*/
|
|
643
|
+
defaultValue: TResult | (() => TResult) | undefined;
|
|
644
|
+
/**
|
|
645
|
+
* The human-readable description attached to this schema via `.describe()`,
|
|
646
|
+
* or `undefined` if none was set.
|
|
647
|
+
*/
|
|
648
|
+
description: string | undefined;
|
|
649
|
+
/**
|
|
650
|
+
* Whether a catch/fallback value has been set on this schema via `.catch()`.
|
|
651
|
+
*/
|
|
652
|
+
hasCatch: boolean;
|
|
653
|
+
/**
|
|
654
|
+
* The catch/fallback value or factory function set via `.catch()`.
|
|
655
|
+
*/
|
|
656
|
+
catchValue: TResult | (() => TResult) | undefined;
|
|
120
657
|
};
|
|
121
658
|
/**
|
|
122
659
|
* Makes schema optional (consider `null` and `undefined` as valid objects for this schema)
|
|
123
660
|
*/
|
|
124
661
|
optional(): any;
|
|
662
|
+
/**
|
|
663
|
+
* Makes schema nullable — `null` is accepted as a valid value.
|
|
664
|
+
*
|
|
665
|
+
* Unlike `.optional()` which accepts `undefined`, `.nullable()` accepts
|
|
666
|
+
* `null`. The inferred type changes from `T` to `T | null`. Combine with
|
|
667
|
+
* `.optional()` to accept both `null` and `undefined`.
|
|
668
|
+
*/
|
|
669
|
+
nullable(): any;
|
|
670
|
+
/**
|
|
671
|
+
* Removes the nullable mark — `null` is no longer accepted as a valid
|
|
672
|
+
* value. This is the counterpart of `.nullable()`.
|
|
673
|
+
*/
|
|
674
|
+
notNullable(): any;
|
|
675
|
+
/**
|
|
676
|
+
* Sets a default value for this schema. When the input is `undefined`,
|
|
677
|
+
* the default value is used instead. The default is still validated
|
|
678
|
+
* against the schema's constraints.
|
|
679
|
+
*
|
|
680
|
+
* Accepts either a static value or a factory function (useful for
|
|
681
|
+
* mutable defaults like `() => new Date()` or `() => []`).
|
|
682
|
+
*
|
|
683
|
+
* @example
|
|
684
|
+
* ```ts
|
|
685
|
+
* const schema = string().default('hello');
|
|
686
|
+
* schema.validate(undefined); // { valid: true, object: 'hello' }
|
|
687
|
+
* schema.validate('world'); // { valid: true, object: 'world' }
|
|
688
|
+
* ```
|
|
689
|
+
*
|
|
690
|
+
* @example
|
|
691
|
+
* ```ts
|
|
692
|
+
* // Factory function for mutable defaults
|
|
693
|
+
* const schema = array(string()).default(() => []);
|
|
694
|
+
* ```
|
|
695
|
+
*/
|
|
696
|
+
default(value: TResult | (() => TResult)): any;
|
|
697
|
+
/**
|
|
698
|
+
* Sets a fallback value for this schema. When validation **fails** for any reason,
|
|
699
|
+
* the fallback value is returned as a successful result instead of validation errors.
|
|
700
|
+
*
|
|
701
|
+
* This is useful for graceful degradation — for example, providing a safe default
|
|
702
|
+
* when parsing untrusted input that might not conform to the schema.
|
|
703
|
+
*
|
|
704
|
+
* Accepts either a static value or a factory function. Factory functions are called
|
|
705
|
+
* each time the fallback is needed (useful for mutable values like `() => []`).
|
|
706
|
+
*
|
|
707
|
+
* Unlike {@link default}, which only fires when the input is `undefined`, `.catch()`
|
|
708
|
+
* fires on **any** validation failure — type mismatch, constraint violation, etc.
|
|
709
|
+
*
|
|
710
|
+
* When `.catch()` is set, {@link parse} and {@link parseAsync} will **never throw**.
|
|
711
|
+
*
|
|
712
|
+
* @param value - the fallback value, or a factory function producing the fallback
|
|
713
|
+
*
|
|
714
|
+
* @example
|
|
715
|
+
* ```ts
|
|
716
|
+
* const schema = string().catch('unknown');
|
|
717
|
+
* schema.validate(42); // { valid: true, object: 'unknown' }
|
|
718
|
+
* schema.validate('hello'); // { valid: true, object: 'hello' }
|
|
719
|
+
* schema.parse(42); // 'unknown' (no throw)
|
|
720
|
+
* ```
|
|
721
|
+
*
|
|
722
|
+
* @example
|
|
723
|
+
* ```ts
|
|
724
|
+
* // Factory function for mutable fallbacks
|
|
725
|
+
* const schema = array(string()).catch(() => []);
|
|
726
|
+
* schema.validate(null); // { valid: true, object: [] }
|
|
727
|
+
* ```
|
|
728
|
+
*
|
|
729
|
+
* @example
|
|
730
|
+
* ```ts
|
|
731
|
+
* // Contrast with .default() — default fires only on undefined
|
|
732
|
+
* const d = string().default('anon');
|
|
733
|
+
* d.validate(undefined); // { valid: true, object: 'anon' } ← fires
|
|
734
|
+
* d.validate(42); // { valid: false, errors: [...] } ← does NOT fire
|
|
735
|
+
*
|
|
736
|
+
* const c = string().catch('anon');
|
|
737
|
+
* c.validate(undefined); // { valid: true, object: 'anon' } ← fires
|
|
738
|
+
* c.validate(42); // { valid: true, object: 'anon' } ← also fires
|
|
739
|
+
* ```
|
|
740
|
+
*/
|
|
741
|
+
catch(value: TResult | (() => TResult)): this;
|
|
742
|
+
/**
|
|
743
|
+
* Removes the default value set by a previous call to `.default()`.
|
|
744
|
+
*/
|
|
745
|
+
clearDefault(): any;
|
|
746
|
+
/**
|
|
747
|
+
* Attaches a human-readable description to this schema as runtime metadata.
|
|
748
|
+
*
|
|
749
|
+
* The description has no effect on validation — it is purely informational.
|
|
750
|
+
* It is accessible via `.introspect().description` and is emitted as the
|
|
751
|
+
* `description` field by `toJsonSchema()` from `@cleverbrush/schema-json`.
|
|
752
|
+
*
|
|
753
|
+
* Useful for documentation generation, form labels, and AI tool descriptions.
|
|
754
|
+
*
|
|
755
|
+
* @example
|
|
756
|
+
* ```ts
|
|
757
|
+
* const schema = object({
|
|
758
|
+
* name: string().describe('The user\'s full name'),
|
|
759
|
+
* age: number().optional().describe('Age in years'),
|
|
760
|
+
* }).describe('A user object');
|
|
761
|
+
*
|
|
762
|
+
* schema.introspect().description; // 'A user object'
|
|
763
|
+
* ```
|
|
764
|
+
*/
|
|
765
|
+
describe(text: string): this;
|
|
766
|
+
/**
|
|
767
|
+
* Brands the schema with a phantom type tag, preventing structural mixing
|
|
768
|
+
* of semantically different values at the type level. Zero runtime cost.
|
|
769
|
+
*
|
|
770
|
+
* The optional `_name` parameter is only needed when using plain JavaScript
|
|
771
|
+
* (where generic type parameters are unavailable). In TypeScript, prefer
|
|
772
|
+
* the generic form: `schema.brand<'Email'>()`.
|
|
773
|
+
*
|
|
774
|
+
* @example
|
|
775
|
+
* ```ts
|
|
776
|
+
* const Email = string().brand<'Email'>();
|
|
777
|
+
* const Username = string().brand<'Username'>();
|
|
778
|
+
* type Email = InferType<typeof Email>; // string & { readonly [BRAND]: 'Email' }
|
|
779
|
+
* type Username = InferType<typeof Username>; // string & { readonly [BRAND]: 'Username' }
|
|
780
|
+
* ```
|
|
781
|
+
*/
|
|
782
|
+
brand<TBrand extends string | symbol>(_name?: TBrand): any;
|
|
783
|
+
/**
|
|
784
|
+
* Marks the inferred type as readonly. For objects, produces `Readonly<T>`.
|
|
785
|
+
* For arrays, produces `ReadonlyArray<T>`. Primitives are unchanged.
|
|
786
|
+
* Type-level only — no runtime enforcement.
|
|
787
|
+
*
|
|
788
|
+
* @example
|
|
789
|
+
* ```ts
|
|
790
|
+
* const schema = object({ name: string(), age: number() }).readonly();
|
|
791
|
+
* type T = InferType<typeof schema>; // Readonly<{ name: string; age: number }>
|
|
792
|
+
* ```
|
|
793
|
+
*
|
|
794
|
+
* @example
|
|
795
|
+
* ```ts
|
|
796
|
+
* const schema = array(string()).readonly();
|
|
797
|
+
* type T = InferType<typeof schema>; // ReadonlyArray<string>
|
|
798
|
+
* ```
|
|
799
|
+
*/
|
|
800
|
+
readonly(): any;
|
|
125
801
|
/**
|
|
126
802
|
* Makes schema required (consider `null` and `undefined` as invalid objects for this schema)
|
|
803
|
+
* @param errorMessage - optional custom error message or provider for the 'is required' validation error
|
|
127
804
|
*/
|
|
128
|
-
required(): any;
|
|
805
|
+
required(errorMessage?: ValidationErrorMessageProvider): any;
|
|
129
806
|
/**
|
|
130
807
|
* Adds a `preprocessor` to a preprocessors list
|
|
131
808
|
*/
|
|
132
|
-
addPreprocessor(preprocessor: Preprocessor<TResult
|
|
809
|
+
addPreprocessor(preprocessor: Preprocessor<TResult>, options?: {
|
|
810
|
+
mutates?: boolean;
|
|
811
|
+
}): this;
|
|
133
812
|
/**
|
|
134
813
|
* Remove all preprocessors for this schema.
|
|
135
814
|
*/
|
|
@@ -137,15 +816,53 @@ export declare abstract class SchemaBuilder<TResult = any, TRequired extends boo
|
|
|
137
816
|
/**
|
|
138
817
|
* Adds a `validator` to validators list.
|
|
139
818
|
*/
|
|
140
|
-
addValidator(validator: Validator<TResult
|
|
819
|
+
addValidator(validator: Validator<TResult>, options?: {
|
|
820
|
+
mutates?: boolean;
|
|
821
|
+
}): this;
|
|
141
822
|
/**
|
|
142
823
|
* Remove all validators for this schema.
|
|
143
824
|
*/
|
|
144
825
|
clearValidators(): this;
|
|
145
826
|
/**
|
|
146
|
-
* Perform schema validation on `object`.
|
|
827
|
+
* Perform synchronous schema validation on `object`.
|
|
828
|
+
* Throws at runtime if any preprocessor, validator, or error message
|
|
829
|
+
* provider returns a Promise — use {@link validateAsync} instead.
|
|
830
|
+
* @internal Override this in subclasses. External callers use {@link validate}.
|
|
831
|
+
*/
|
|
832
|
+
protected abstract _validate(object: any, context?: ValidationContext): ValidationResult<any>;
|
|
833
|
+
/**
|
|
834
|
+
* Perform asynchronous schema validation on `object`.
|
|
835
|
+
* Supports async preprocessors, validators, and error message providers.
|
|
836
|
+
* @internal Override this in subclasses. External callers use {@link validateAsync}.
|
|
837
|
+
*/
|
|
838
|
+
protected abstract _validateAsync(object: any, context?: ValidationContext): Promise<ValidationResult<any>>;
|
|
839
|
+
/**
|
|
840
|
+
* Perform synchronous schema validation on `object`.
|
|
841
|
+
* Throws at runtime if any preprocessor, validator, or error message
|
|
842
|
+
* provider returns a Promise — use {@link validateAsync} instead.
|
|
843
|
+
*
|
|
844
|
+
* If a fallback has been set via {@link catch}, a failed validation result
|
|
845
|
+
* is replaced by a successful result built from the fallback value, preserving
|
|
846
|
+
* the specialized result shape (e.g. `getErrorsFor` / `getNestedErrors` methods).
|
|
847
|
+
*/
|
|
848
|
+
validate(
|
|
849
|
+
/**
|
|
850
|
+
* Object to validate
|
|
851
|
+
*/
|
|
852
|
+
object: any,
|
|
853
|
+
/**
|
|
854
|
+
* Optional `ValidationContext` settings
|
|
855
|
+
*/
|
|
856
|
+
context?: ValidationContext): ValidationResult<any>;
|
|
857
|
+
/**
|
|
858
|
+
* Perform asynchronous schema validation on `object`.
|
|
859
|
+
* Supports async preprocessors, validators, and error message providers.
|
|
860
|
+
*
|
|
861
|
+
* If a fallback has been set via {@link catch}, a failed validation result
|
|
862
|
+
* is replaced by a successful result built from the fallback value, preserving
|
|
863
|
+
* the specialized result shape (e.g. `getErrorsFor` / `getNestedErrors` methods).
|
|
147
864
|
*/
|
|
148
|
-
|
|
865
|
+
validateAsync(
|
|
149
866
|
/**
|
|
150
867
|
* Object to validate
|
|
151
868
|
*/
|
|
@@ -154,6 +871,77 @@ export declare abstract class SchemaBuilder<TResult = any, TRequired extends boo
|
|
|
154
871
|
* Optional `ValidationContext` settings
|
|
155
872
|
*/
|
|
156
873
|
context?: ValidationContext): Promise<ValidationResult<any>>;
|
|
874
|
+
/**
|
|
875
|
+
* Synchronously resolves a `ValidationErrorMessageProvider` to a string.
|
|
876
|
+
* Throws if the provider function returns a Promise.
|
|
877
|
+
*
|
|
878
|
+
* @param provider - the error message provider (string or sync function)
|
|
879
|
+
* @param seenValue - the value that caused the validation error
|
|
880
|
+
* @returns the resolved error message string
|
|
881
|
+
* @throws Error if the provider returns a Promise (use {@link getValidationErrorMessage} with {@link validateAsync})
|
|
882
|
+
*/
|
|
883
|
+
protected getValidationErrorMessageSync(provider: ValidationErrorMessageProvider<any>, seenValue: TResult): string;
|
|
884
|
+
/**
|
|
885
|
+
* Resolves a `ValidationErrorMessageProvider` to a string error message.
|
|
886
|
+
* Handles both string providers and function providers (sync or async).
|
|
887
|
+
*
|
|
888
|
+
* @param provider - the error message provider (string or function)
|
|
889
|
+
* @param seenValue - the value that caused the validation error
|
|
890
|
+
* @returns the resolved error message string
|
|
891
|
+
*/
|
|
892
|
+
protected getValidationErrorMessage(provider: ValidationErrorMessageProvider<any>, seenValue: TResult): Promise<string>;
|
|
893
|
+
/**
|
|
894
|
+
* Ensures a `ValidationErrorMessageProvider` is valid.
|
|
895
|
+
* If `provider` is `undefined`, falls back to `defaultValue`.
|
|
896
|
+
* Function providers are bound to `this` for access to schema state.
|
|
897
|
+
*
|
|
898
|
+
* @param provider - the provider to validate, or `undefined`
|
|
899
|
+
* @param defaultValue - fallback provider when `provider` is not supplied
|
|
900
|
+
* @returns a valid `ValidationErrorMessageProvider`
|
|
901
|
+
*/
|
|
902
|
+
protected assureValidationErrorMessageProvider(provider: ValidationErrorMessageProvider<any> | undefined, defaultValue: ValidationErrorMessageProvider<any>): ValidationErrorMessageProvider<any>;
|
|
903
|
+
/**
|
|
904
|
+
* Sets extension metadata by key. Returns a new schema instance with the
|
|
905
|
+
* extension data stored. The data survives fluent chaining.
|
|
906
|
+
* @internal Used by extension authors inside `defineExtension()` callbacks.
|
|
907
|
+
*/
|
|
908
|
+
withExtension(key: string, value: unknown): this;
|
|
909
|
+
/**
|
|
910
|
+
* Retrieves extension metadata by key.
|
|
911
|
+
* @internal Used by extension authors inside `defineExtension()` callbacks.
|
|
912
|
+
*/
|
|
913
|
+
getExtension(key: string): unknown;
|
|
914
|
+
/**
|
|
915
|
+
* Synchronously validates the value and returns it if valid.
|
|
916
|
+
* Throws a {@link SchemaValidationError} if validation fails.
|
|
917
|
+
*
|
|
918
|
+
* @param object - the value to parse
|
|
919
|
+
* @param context - optional validation context
|
|
920
|
+
* @returns the validated value
|
|
921
|
+
* @throws SchemaValidationError if validation fails
|
|
922
|
+
* @throws Error if the schema contains async preprocessors, validators, or error message providers
|
|
923
|
+
*/
|
|
924
|
+
parse(object: any, context?: ValidationContext): TResult;
|
|
925
|
+
/**
|
|
926
|
+
* Asynchronously validates the value and returns it if valid.
|
|
927
|
+
* Throws a {@link SchemaValidationError} if validation fails.
|
|
928
|
+
*
|
|
929
|
+
* @param object - the value to parse
|
|
930
|
+
* @param context - optional validation context
|
|
931
|
+
* @returns the validated value
|
|
932
|
+
* @throws SchemaValidationError if validation fails
|
|
933
|
+
*/
|
|
934
|
+
parseAsync(object: any, context?: ValidationContext): Promise<TResult>;
|
|
935
|
+
/**
|
|
936
|
+
* Alias for {@link validate}. Synchronously validates and returns a result object.
|
|
937
|
+
* Provided for familiarity with the zod API.
|
|
938
|
+
*/
|
|
939
|
+
safeParse(object: any, context?: ValidationContext): ValidationResult<TResult>;
|
|
940
|
+
/**
|
|
941
|
+
* Alias for {@link validateAsync}. Asynchronously validates and returns a result object.
|
|
942
|
+
* Provided for familiarity with the zod API.
|
|
943
|
+
*/
|
|
944
|
+
safeParseAsync(object: any, context?: ValidationContext): Promise<ValidationResult<TResult>>;
|
|
157
945
|
protected constructor(props: SchemaBuilderProps<TResult>);
|
|
158
946
|
}
|
|
159
947
|
export {};
|