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