@cleverbrush/schema 2.0.0 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +412 -8
- package/dist/builders/AnySchemaBuilder.js +1 -1
- package/dist/builders/ArraySchemaBuilder.d.ts +2 -0
- package/dist/builders/ArraySchemaBuilder.js +1 -1
- package/dist/builders/BooleanSchemaBuilder.d.ts +15 -0
- package/dist/builders/BooleanSchemaBuilder.js +1 -1
- package/dist/builders/DateSchemaBuilder.d.ts +20 -0
- package/dist/builders/DateSchemaBuilder.js +1 -1
- package/dist/builders/ExternSchemaBuilder.d.ts +2 -0
- package/dist/builders/ExternSchemaBuilder.js +1 -1
- package/dist/builders/FunctionSchemaBuilder.d.ts +162 -18
- package/dist/builders/FunctionSchemaBuilder.js +1 -1
- package/dist/builders/GenericSchemaBuilder.d.ts +294 -0
- package/dist/builders/LazySchemaBuilder.d.ts +2 -0
- package/dist/builders/NumberSchemaBuilder.d.ts +16 -0
- package/dist/builders/NumberSchemaBuilder.js +1 -1
- package/dist/builders/ObjectSchemaBuilder.d.ts +262 -42
- package/dist/builders/ObjectSchemaBuilder.js +1 -1
- 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/RecordSchemaBuilder.d.ts +2 -0
- package/dist/builders/RecordSchemaBuilder.js +1 -1
- package/dist/builders/SchemaBuilder.d.ts +89 -0
- package/dist/builders/StringSchemaBuilder.d.ts +2 -0
- package/dist/builders/StringSchemaBuilder.js +1 -1
- package/dist/builders/TupleSchemaBuilder.d.ts +2 -0
- package/dist/builders/TupleSchemaBuilder.js +1 -1
- package/dist/builders/UnionSchemaBuilder.d.ts +8 -0
- package/dist/builders/UnionSchemaBuilder.js +1 -1
- package/dist/chunk-3JMDGYDT.js +2 -0
- package/dist/chunk-3JMDGYDT.js.map +1 -0
- package/dist/{chunk-KESLT5EE.js → chunk-BUEVZ3KA.js} +2 -2
- package/dist/{chunk-KESLT5EE.js.map → chunk-BUEVZ3KA.js.map} +1 -1
- package/dist/{chunk-KFTO7TMB.js → chunk-CFIJQ4GP.js} +2 -2
- package/dist/{chunk-KFTO7TMB.js.map → chunk-CFIJQ4GP.js.map} +1 -1
- package/dist/chunk-DY7J6RNN.js +2 -0
- package/dist/chunk-DY7J6RNN.js.map +1 -0
- package/dist/{chunk-YWBNVHR6.js → chunk-EIVZX4ZO.js} +2 -2
- package/dist/{chunk-YWBNVHR6.js.map → chunk-EIVZX4ZO.js.map} +1 -1
- package/dist/chunk-GXPV6UQK.js +2 -0
- package/dist/chunk-GXPV6UQK.js.map +1 -0
- package/dist/{chunk-ZAN4ZHCJ.js → chunk-HN774HD7.js} +2 -2
- 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-MKAYFPAR.js → chunk-PHE4LIAN.js} +2 -2
- 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-FWUEUW2N.js → chunk-YQZHDMRF.js} +2 -2
- package/dist/chunk-ZC6YBKCP.js +2 -0
- package/dist/chunk-ZC6YBKCP.js.map +1 -0
- package/dist/{chunk-IJ6FO37G.js → chunk-ZFI27R3L.js} +2 -2
- package/dist/core.d.ts +7 -2
- package/dist/core.js +1 -1
- package/dist/extension.d.ts +10 -2
- package/dist/extensions/index.d.ts +5 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +12 -4
- package/dist/chunk-BFCMDDTX.js +0 -2
- package/dist/chunk-BFCMDDTX.js.map +0 -1
- package/dist/chunk-CTP4RHDG.js +0 -2
- package/dist/chunk-CTP4RHDG.js.map +0 -1
- package/dist/chunk-EUQ5AE3H.js +0 -2
- package/dist/chunk-EUQ5AE3H.js.map +0 -1
- package/dist/chunk-NXPH3ZUW.js +0 -2
- package/dist/chunk-NXPH3ZUW.js.map +0 -1
- package/dist/chunk-S5TC6NSU.js +0 -2
- package/dist/chunk-S5TC6NSU.js.map +0 -1
- package/dist/chunk-Z7QZ7IXT.js +0 -2
- package/dist/chunk-Z7QZ7IXT.js.map +0 -1
- package/dist/chunk-ZUPYV5TI.js +0 -2
- package/dist/chunk-ZUPYV5TI.js.map +0 -1
- /package/dist/{chunk-ZAN4ZHCJ.js.map → chunk-HN774HD7.js.map} +0 -0
- /package/dist/{chunk-MKAYFPAR.js.map → chunk-PHE4LIAN.js.map} +0 -0
- /package/dist/{chunk-FWUEUW2N.js.map → chunk-YQZHDMRF.js.map} +0 -0
- /package/dist/{chunk-IJ6FO37G.js.map → chunk-ZFI27R3L.js.map} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/builders/LazySchemaBuilder.ts","../src/builders/NullSchemaBuilder.ts","../src/extension.ts"],"sourcesContent":["import {\n type BRAND,\n SchemaBuilder,\n type ValidationContext,\n type ValidationErrorMessageProvider,\n type ValidationResult\n} from './SchemaBuilder.js';\n\ntype LazySchemaBuilderCreateProps<R extends boolean = true> = Partial<\n ReturnType<LazySchemaBuilder<any, R>['introspect']>\n>;\n\n/**\n * Lazy schema builder class. Allows defining recursive/self-referential schemas\n * by wrapping a getter function that returns the target schema. The getter is\n * called once on first validation and the result is cached.\n *\n * This is the primary mechanism for building recursive data structures such as\n * tree nodes, nested menus, and threaded comments.\n *\n * **NOTE** TypeScript cannot infer recursive types automatically, so you must\n * provide an explicit type annotation on the variable holding the schema:\n *\n * @example\n * ```ts\n * type TreeNode = { value: number; children: TreeNode[] };\n *\n * const treeNode: SchemaBuilder<TreeNode, true> = object({\n * value: number(),\n * children: array(lazy(() => treeNode))\n * });\n *\n * treeNode.validate({ value: 1, children: [{ value: 2, children: [] }] });\n * // { valid: true, object: { value: 1, children: [{ value: 2, children: [] }] } }\n * ```\n *\n * @example\n * ```ts\n * type Comment = { text: string; replies: Comment[] };\n *\n * const commentSchema: SchemaBuilder<Comment, true> = object({\n * text: string(),\n * replies: array(lazy(() => commentSchema))\n * });\n * ```\n */\nexport class LazySchemaBuilder<\n TResult = any,\n TRequired extends boolean = true,\n TNullable extends boolean = false,\n THasDefault extends boolean = false,\n TExtensions = {}\n> extends SchemaBuilder<\n TResult,\n TRequired,\n TNullable,\n THasDefault,\n TExtensions\n> {\n #getter: () => SchemaBuilder<TResult, any, any>;\n #resolvedSchema: SchemaBuilder<TResult, any, any> | null = null;\n\n /**\n * @hidden\n */\n public static create(props: LazySchemaBuilderCreateProps<any>) {\n return new LazySchemaBuilder({\n type: 'lazy',\n ...props\n });\n }\n\n protected constructor(props: LazySchemaBuilderCreateProps<TRequired>) {\n super(props as any);\n if (typeof (props as any).getter !== 'function') {\n throw new Error('LazySchemaBuilder: getter must be a function');\n }\n this.#getter = (props as any).getter;\n }\n\n /**\n * Resolves the lazy schema by calling the getter (once; result is cached).\n * After the first call subsequent calls return the cached schema instance.\n */\n public resolve(): SchemaBuilder<TResult, any, any> {\n if (this.#resolvedSchema === null) {\n this.#resolvedSchema = this.#getter();\n }\n return this.#resolvedSchema;\n }\n\n /**\n * @inheritdoc\n */\n public introspect() {\n return {\n ...super.introspect(),\n /**\n * The getter function that returns the lazily-resolved schema.\n * Call {@link LazySchemaBuilder.resolve} to obtain the schema instance.\n */\n getter: this.#getter\n };\n }\n\n #buildResult(\n superResult: ReturnType<LazySchemaBuilder['preValidateSync']>,\n context?: ValidationContext\n ): ValidationResult<TResult> {\n const {\n valid,\n transaction: preValidationTransaction,\n errors\n } = superResult;\n\n if (!valid) {\n return { valid, errors };\n }\n\n const {\n object: { validatedObject: objToValidate }\n } = preValidationTransaction!;\n\n // Value is null/undefined and the schema is optional — skip delegation.\n if (objToValidate == null) {\n return { valid: true, object: objToValidate };\n }\n\n return this.resolve().validate(\n objToValidate,\n context\n ) as ValidationResult<TResult>;\n }\n\n /** {@inheritDoc SchemaBuilder.validate} */\n public validate(\n object: TResult,\n context?: ValidationContext\n ): ValidationResult<TResult> {\n return super.validate(object, context) as ValidationResult<TResult>;\n }\n\n /** {@inheritDoc SchemaBuilder.validateAsync} */\n public async validateAsync(\n object: TResult,\n context?: ValidationContext\n ): Promise<ValidationResult<TResult>> {\n return super.validateAsync(object, context) as Promise<\n ValidationResult<TResult>\n >;\n }\n\n /**\n * Performs synchronous validation of the schema over `object`.\n * Throws if any preprocessor, validator, or error message provider returns a Promise.\n * @param context Optional `ValidationContext` settings.\n */\n protected _validate(\n object: TResult,\n context?: ValidationContext\n ): ValidationResult<TResult> {\n return this.#buildResult(\n this.preValidateSync(object, context),\n context\n );\n }\n\n /**\n * Performs async validation of the schema over `object`.\n * Supports async preprocessors, validators, and error message providers.\n * @param context Optional `ValidationContext` settings.\n */\n protected async _validateAsync(\n object: TResult,\n context?: ValidationContext\n ): Promise<ValidationResult<TResult>> {\n const superResult = await super.preValidateAsync(object, context);\n\n const {\n valid,\n transaction: preValidationTransaction,\n errors\n } = superResult;\n\n if (!valid) {\n return { valid, errors };\n }\n\n const {\n object: { validatedObject: objToValidate }\n } = preValidationTransaction!;\n\n if (objToValidate == null) {\n return { valid: true, object: objToValidate };\n }\n\n return this.resolve().validateAsync(objToValidate, context) as Promise<\n ValidationResult<TResult>\n >;\n }\n\n protected createFromProps<TReq extends boolean>(\n props: LazySchemaBuilderCreateProps<TReq>\n ): this {\n return LazySchemaBuilder.create(props as any) as any;\n }\n\n /**\n * @inheritdoc\n */\n public hasType<T>(\n _notUsed?: T\n ): LazySchemaBuilder<T, true, TNullable, THasDefault, TExtensions> &\n TExtensions {\n return this.createFromProps({\n ...this.introspect()\n } as any) as any;\n }\n\n /**\n * @inheritdoc\n */\n public clearHasType(): LazySchemaBuilder<\n TResult,\n TRequired,\n TNullable,\n THasDefault,\n TExtensions\n > &\n TExtensions {\n return this.createFromProps({\n ...this.introspect()\n } as any) as any;\n }\n\n /**\n * @hidden\n */\n public required(\n errorMessage?: ValidationErrorMessageProvider\n ): LazySchemaBuilder<TResult, true, TNullable, THasDefault, TExtensions> &\n TExtensions {\n return super.required(errorMessage);\n }\n\n /**\n * @hidden\n */\n public optional(): LazySchemaBuilder<\n TResult,\n false,\n TNullable,\n THasDefault,\n TExtensions\n > &\n TExtensions {\n return super.optional();\n }\n\n /**\n * @hidden\n */\n public default(\n value: TResult | (() => TResult)\n ): LazySchemaBuilder<TResult, true, TNullable, true, TExtensions> &\n TExtensions {\n return super.default(value) as any;\n }\n\n /**\n * @hidden\n */\n public clearDefault(): LazySchemaBuilder<\n TResult,\n TRequired,\n TNullable,\n false,\n TExtensions\n > &\n TExtensions {\n return super.clearDefault() as any;\n }\n\n /**\n * @hidden\n */\n public brand<TBrand extends string | symbol>(\n _name?: TBrand\n ): LazySchemaBuilder<\n TResult & { readonly [K in BRAND]: TBrand },\n TRequired,\n TNullable,\n THasDefault,\n TExtensions\n > &\n TExtensions {\n return super.brand(_name);\n }\n\n /**\n * @hidden\n */\n public readonly(): LazySchemaBuilder<\n Readonly<TResult>,\n TRequired,\n TNullable,\n THasDefault,\n TExtensions\n > &\n TExtensions {\n return super.readonly();\n }\n\n /**\n * @hidden\n */\n public nullable(): LazySchemaBuilder<\n TResult,\n TRequired,\n true,\n THasDefault,\n TExtensions\n > &\n TExtensions {\n return super.nullable() as any;\n }\n\n /**\n * @hidden\n */\n public notNullable(): LazySchemaBuilder<\n TResult,\n TRequired,\n false,\n THasDefault,\n TExtensions\n > &\n TExtensions {\n return super.notNullable() as any;\n }\n}\n\n/**\n * Creates a lazy schema that defers the schema definition until first validation.\n * Use this to define recursive/self-referential schemas.\n *\n * The getter function is called **once** on first use and the result is cached.\n * You **must** provide an explicit TypeScript type annotation on the variable\n * holding the outer schema — TypeScript cannot infer recursive types automatically.\n *\n * @param getter - A function that returns the schema to use for validation.\n *\n * @example\n * ```ts\n * // Tree structure\n * type TreeNode = { value: number; children: TreeNode[] };\n *\n * const treeNode: SchemaBuilder<TreeNode, true> = object({\n * value: number(),\n * children: array(lazy(() => treeNode))\n * });\n * ```\n *\n * @example\n * ```ts\n * // Optional recursive field (submenu)\n * type MenuItem = { label: string; submenu?: MenuItem[] };\n *\n * const menuItem: SchemaBuilder<MenuItem, true> = object({\n * label: string(),\n * submenu: array(lazy(() => menuItem)).optional()\n * });\n * ```\n */\nexport function lazy<TResult>(\n getter: () => SchemaBuilder<TResult, any, any>\n): LazySchemaBuilder<TResult, true, false, false, {}> {\n return LazySchemaBuilder.create({\n type: 'lazy',\n isRequired: true,\n preprocessors: [],\n validators: [],\n getter\n } as any);\n}\n","import {\n type BRAND,\n SchemaBuilder,\n type ValidationContext,\n type ValidationErrorMessageProvider,\n type ValidationResult\n} from './SchemaBuilder.js';\n\ntype NullSchemaBuilderCreateProps<R extends boolean = true> = Partial<\n ReturnType<NullSchemaBuilder<R>['introspect']>\n>;\n\n/**\n * Schema builder for `null` values. Validates that the input is exactly `null`.\n *\n * When required (the default), only `null` is accepted. When optional (via\n * `.optional()`), both `null` and `undefined` are accepted; any other value\n * is rejected.\n *\n * This builder is useful when you need to represent an explicitly-null field\n * in a typed schema, for example in discriminated-union branches or when\n * modelling a JSON payload that may carry a JSON `null` value.\n *\n * **NOTE** this class is exported only to give opportunity to extend it\n * by inheriting. It is not recommended to create an instance of this class\n * directly. Use {@link nul | nul()} function instead.\n *\n * @example\n * ```ts\n * import { nul } from '@cleverbrush/schema';\n *\n * const schema = nul();\n *\n * schema.validate(null); // { valid: true, object: null }\n * schema.validate(undefined); // { valid: false }\n * schema.validate(0); // { valid: false }\n * schema.validate(''); // { valid: false }\n * ```\n *\n * @example\n * ```ts\n * // Optional — accepts null or undefined\n * const schema = nul().optional();\n *\n * schema.validate(null); // { valid: true, object: null }\n * schema.validate(undefined); // { valid: true, object: undefined }\n * schema.validate(false); // { valid: false }\n * ```\n *\n * @example\n * ```ts\n * // Use inside a union to model a nullable string field\n * import { union, string, nul, InferType } from '@cleverbrush/schema';\n *\n * const NullableString = union(string()).or(nul());\n * type NullableString = InferType<typeof NullableString>;\n * // string | null\n *\n * NullableString.validate('hello'); // valid\n * NullableString.validate(null); // valid\n * NullableString.validate(42); // invalid\n * ```\n *\n * @see {@link nul}\n */\nexport class NullSchemaBuilder<\n TRequired extends boolean = true,\n TNullable extends boolean = false,\n TExplicitType = undefined,\n THasDefault extends boolean = false,\n TExtensions = {}\n> extends SchemaBuilder<null, TRequired, TNullable, THasDefault, TExtensions> {\n /**\n * @hidden\n */\n public static create(props: NullSchemaBuilderCreateProps<any>) {\n return new NullSchemaBuilder({\n type: 'null',\n ...props\n });\n }\n\n protected constructor(props: NullSchemaBuilderCreateProps<TRequired>) {\n super(props as any);\n }\n\n /**\n * @hidden\n */\n public hasType<T>(\n _notUsed?: T\n ): NullSchemaBuilder<true, TNullable, T, THasDefault, TExtensions> &\n TExtensions {\n return this.createFromProps({\n ...this.introspect()\n } as any) as any;\n }\n\n /**\n * @hidden\n */\n public clearHasType(): NullSchemaBuilder<\n TRequired,\n TNullable,\n undefined,\n THasDefault,\n TExtensions\n > &\n TExtensions {\n return this.createFromProps({\n ...this.introspect()\n } as any) as any;\n }\n\n // The SchemaBuilder base-class preValidateSync/preValidateAsync treats\n // null as an invalid value for required schemas, which would prevent null\n // from ever passing validation here. We therefore bypass preValidateSync\n // entirely and implement the full (and simple) validation inline.\n #buildResult(object: any): ValidationResult<null> {\n if (object === null) return { valid: true, object: null };\n\n if (object === undefined && this.hasDefault) {\n const defaultVal = this.resolveDefaultValue();\n if (defaultVal === null) return { valid: true, object: null };\n return { valid: false, errors: [{ message: 'must be null' }] };\n }\n\n if (object === undefined && !this.isRequired) {\n return { valid: true, object: undefined as any };\n }\n\n return {\n valid: false,\n errors: [{ message: 'must be null' }]\n };\n }\n\n /** {@inheritDoc SchemaBuilder.validate} */\n public validate(\n object: null,\n context?: ValidationContext\n ): ValidationResult<null> {\n return super.validate(object, context) as ValidationResult<null>;\n }\n\n /** {@inheritDoc SchemaBuilder.validateAsync} */\n public async validateAsync(\n object: null,\n context?: ValidationContext\n ): Promise<ValidationResult<null>> {\n return super.validateAsync(object, context) as Promise<\n ValidationResult<null>\n >;\n }\n\n /**\n * Performs synchronous validation of the schema over `object`.\n * @param context Optional `ValidationContext` settings.\n */\n protected _validate(\n object: null,\n _context?: ValidationContext\n ): ValidationResult<null> {\n return this.#buildResult(object);\n }\n\n /**\n * Performs async validation of the schema over `object`.\n * @param context Optional `ValidationContext` settings.\n */\n protected async _validateAsync(\n object: null,\n _context?: ValidationContext\n ): Promise<ValidationResult<null>> {\n return this.#buildResult(object);\n }\n\n protected createFromProps<TReq extends boolean>(\n props: NullSchemaBuilderCreateProps<TReq>\n ): this {\n return NullSchemaBuilder.create(props as any) as any;\n }\n\n /**\n * @hidden\n */\n public required(\n errorMessage?: ValidationErrorMessageProvider\n ): NullSchemaBuilder<\n true,\n TNullable,\n TExplicitType,\n THasDefault,\n TExtensions\n > &\n TExtensions {\n return super.required(errorMessage);\n }\n\n /**\n * @hidden\n */\n public optional(): NullSchemaBuilder<\n false,\n TNullable,\n TExplicitType,\n THasDefault,\n TExtensions\n > &\n TExtensions {\n return super.optional();\n }\n\n /**\n * @hidden\n */\n public default(\n value: null | (() => null)\n ): NullSchemaBuilder<true, TNullable, TExplicitType, true, TExtensions> &\n TExtensions {\n return super.default(value) as any;\n }\n\n /**\n * @hidden\n */\n public clearDefault(): NullSchemaBuilder<\n TRequired,\n TNullable,\n TExplicitType,\n false,\n TExtensions\n > &\n TExtensions {\n return super.clearDefault() as any;\n }\n\n /**\n * @hidden\n */\n public brand<TBrand extends string | symbol>(\n _name?: TBrand\n ): NullSchemaBuilder<\n TRequired,\n TNullable,\n null & { readonly [K in BRAND]: TBrand },\n THasDefault,\n TExtensions\n > &\n TExtensions {\n return super.brand(_name);\n }\n\n /**\n * Marks the inferred type as `Readonly<null>`. Since `null` is already\n * immutable this is an identity operation, but it sets the `isReadonly`\n * introspection flag for tooling consistency.\n *\n * @see {@link SchemaBuilder.readonly}\n */\n public readonly(): NullSchemaBuilder<\n TRequired,\n TNullable,\n Readonly<null>,\n THasDefault,\n TExtensions\n > &\n TExtensions {\n return super.readonly();\n }\n\n /**\n * @hidden\n */\n public nullable(): NullSchemaBuilder<\n TRequired,\n true,\n TExplicitType,\n THasDefault,\n TExtensions\n > &\n TExtensions {\n return super.nullable() as any;\n }\n\n /**\n * @hidden\n */\n public notNullable(): NullSchemaBuilder<\n TRequired,\n false,\n TExplicitType,\n THasDefault,\n TExtensions\n > &\n TExtensions {\n return super.notNullable() as any;\n }\n}\n\n/**\n * Creates a schema that validates the value is exactly `null`.\n *\n * By default the schema is **required** — only `null` is accepted.\n * Call `.optional()` to also allow `undefined`.\n *\n * @example\n * ```ts\n * import { nul } from '@cleverbrush/schema';\n *\n * nul().validate(null); // { valid: true, object: null }\n * nul().validate(undefined); // { valid: false }\n * nul().validate(0); // { valid: false }\n * ```\n *\n * @example\n * ```ts\n * nul().optional().validate(null); // { valid: true, object: null }\n * nul().optional().validate(undefined); // { valid: true, object: undefined }\n * nul().optional().validate(false); // { valid: false }\n * ```\n *\n * @example\n * ```ts\n * // Nullable field in an object schema\n * import { object, string, nul, union, InferType } from '@cleverbrush/schema';\n *\n * const Schema = object({\n * name: string(),\n * deleted: union(nul()).or(string()), // null | string\n * });\n *\n * type T = InferType<typeof Schema>;\n * // { name: string; deleted: null | string }\n * ```\n */\nexport const nul = () =>\n NullSchemaBuilder.create({\n isRequired: true\n }) as NullSchemaBuilder<true>;\n","/**\n * @module extension\n *\n * The **extension system** for `@cleverbrush/schema` allows third-party and\n * first-party code to add custom methods to any schema builder type\n * (`string`, `number`, `date`, `object`, …) without modifying the core\n * library.\n *\n * ## Overview\n *\n * Extensions follow a two-step workflow:\n *\n * 1. **Define** an extension with {@link defineExtension} — declare which\n * builder types it targets and what methods it adds.\n * 2. **Apply** one or more extensions with {@link withExtensions} — get back\n * augmented factory functions (`string()`, `number()`, …) whose return\n * types include the new methods.\n *\n * ## Ergonomic authoring\n *\n * Extension methods do **not** need to call `withExtension()` manually.\n * The system automatically attaches metadata using the method name as the\n * extension key and the method arguments as the value. This keeps extension\n * definitions concise:\n *\n * ```ts\n * const slugExt = defineExtension({\n * string: {\n * slug(this: StringSchemaBuilder) {\n * return this.addValidator((val) => {\n * const valid = /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(val);\n * return { valid, errors: valid ? [] : [{ message: 'must be a valid URL slug' }] };\n * });\n * }\n * }\n * });\n * ```\n *\n * If you need **custom metadata** (e.g. a different key or a transformed\n * value), call `this.withExtension(key, value)` explicitly — the auto-infer\n * logic will detect the existing key and skip the automatic attachment.\n *\n * ## Stacking and composition\n *\n * Multiple extensions can target the same builder type. Pass them all to\n * `withExtensions()` and the methods are merged. A runtime error is thrown\n * if two extensions define the same method name on the same builder type.\n *\n * ```ts\n * const s = withExtensions(emailExt, slugExt, rangeExt);\n * const schema = s.string().email().slug(); // both methods available\n * ```\n *\n * ## Introspection\n *\n * Extension metadata is accessible via `schema.introspect().extensions`.\n * Each key corresponds to an extension method name and its value is whatever\n * was passed (or auto-inferred) as the extension data.\n *\n * @see {@link defineExtension} — define an extension\n * @see {@link withExtensions} — apply extensions to builder factories\n * @see {@link ExtensionConfig} — shape of the configuration object\n * @see {@link ExtensionDescriptor} — branded descriptor returned by `defineExtension`\n */\nimport { AnySchemaBuilder, any } from './builders/AnySchemaBuilder.js';\nimport { ArraySchemaBuilder, array } from './builders/ArraySchemaBuilder.js';\nimport {\n BooleanSchemaBuilder,\n boolean\n} from './builders/BooleanSchemaBuilder.js';\nimport { DateSchemaBuilder, date } from './builders/DateSchemaBuilder.js';\nimport {\n FunctionSchemaBuilder,\n func\n} from './builders/FunctionSchemaBuilder.js';\nimport { NumberSchemaBuilder, number } from './builders/NumberSchemaBuilder.js';\nimport { ObjectSchemaBuilder, object } from './builders/ObjectSchemaBuilder.js';\nimport { RecordSchemaBuilder, record } from './builders/RecordSchemaBuilder.js';\nimport type { SchemaBuilder } from './builders/SchemaBuilder.js';\nimport { StringSchemaBuilder, string } from './builders/StringSchemaBuilder.js';\nimport { TupleSchemaBuilder, tuple } from './builders/TupleSchemaBuilder.js';\nimport { UnionSchemaBuilder, union } from './builders/UnionSchemaBuilder.js';\n\n// ---------------------------------------------------------------------------\n// Builder type name mapping\n// ---------------------------------------------------------------------------\n\n/**\n * Maps each builder type name to the corresponding generic builder class.\n *\n * Used internally to type-check extension method `this` bindings — for\n * example, an extension targeting `\"string\"` receives `this: StringSchemaBuilder`.\n *\n * @internal Not exported — used only by the extension type machinery.\n */\ntype BuilderMap = {\n string: StringSchemaBuilder<any, any, any, any, any>;\n number: NumberSchemaBuilder<any, any, any, any, any>;\n boolean: BooleanSchemaBuilder<any, any, any, any, any, any, any>;\n date: DateSchemaBuilder<any, any, any, any, any>;\n object: ObjectSchemaBuilder<any, any, any, any, any, any>;\n array: ArraySchemaBuilder<any, any, any, any, any, any, any>;\n tuple: TupleSchemaBuilder<any, any, any, any, any, any, any>;\n record: RecordSchemaBuilder<any, any, any, any, any, any, any>;\n union: UnionSchemaBuilder<any, any, any, any, any, any>;\n func: FunctionSchemaBuilder<any, any, any, any, any>;\n any: AnySchemaBuilder<any, any, any, any, any, any>;\n};\n\ntype BuilderTypeName = keyof BuilderMap;\n\n// Runtime mapping from type name to the actual class constructor\nconst builderClasses: Record<BuilderTypeName, typeof SchemaBuilder> = {\n string: StringSchemaBuilder as any,\n number: NumberSchemaBuilder as any,\n boolean: BooleanSchemaBuilder as any,\n date: DateSchemaBuilder as any,\n object: ObjectSchemaBuilder as any,\n array: ArraySchemaBuilder as any,\n tuple: TupleSchemaBuilder as any,\n record: RecordSchemaBuilder as any,\n union: UnionSchemaBuilder as any,\n func: FunctionSchemaBuilder as any,\n any: AnySchemaBuilder as any\n};\n\n// Runtime mapping from type name to factory function\nconst builderFactories: Record<BuilderTypeName, (...args: any[]) => any> = {\n string,\n number,\n boolean,\n date,\n object,\n array,\n tuple,\n record,\n union,\n func,\n any\n};\n\n// ---------------------------------------------------------------------------\n// Extension configuration types\n// ---------------------------------------------------------------------------\n\n/**\n * Defines the shape of an extension configuration object passed to\n * {@link defineExtension}.\n *\n * Each key is a **builder type name** — one of `\"string\"`, `\"number\"`,\n * `\"boolean\"`, `\"date\"`, `\"object\"`, `\"array\"`, `\"union\"`, `\"func\"`, or\n * `\"any\"`. The value is a record of **method implementations** to add to\n * that builder type.\n *\n * Method implementations receive `this` bound to the target builder instance\n * (e.g. `StringSchemaBuilder` for the `\"string\"` key) and **must** return a\n * builder of the same type to support fluent chaining.\n *\n * @remarks\n * Extension methods that only add validators/preprocessors do not need to\n * call `this.withExtension()` — the system will auto-attach metadata using\n * the method name as the key and the arguments as the value. Call\n * `this.withExtension(key, value)` explicitly only when you need custom\n * metadata (e.g. a transformed value or a different key).\n *\n * @example\n * ```ts\n * // Minimal extension config — auto-inferred metadata\n * const config: ExtensionConfig = {\n * string: {\n * slug(this: StringSchemaBuilder) {\n * return this.addValidator((v) => ({ valid: /^[a-z0-9-]+$/.test(v), errors: [] }));\n * }\n * },\n * number: {\n * port(this: NumberSchemaBuilder) {\n * return this.isInteger().min(1).max(65535);\n * }\n * }\n * };\n * ```\n *\n * @see {@link defineExtension}\n */\nexport type ExtensionConfig = {\n [K in BuilderTypeName]?: Record<\n string,\n (this: BuilderMap[K], ...args: any[]) => any\n >;\n};\n\n/**\n * A branded descriptor returned by {@link defineExtension}.\n *\n * The descriptor captures the extension's method signatures at the **type\n * level** so that {@link withExtensions} can produce correctly-typed factory\n * functions. At runtime it holds the (possibly wrapped) configuration object.\n *\n * Extension descriptors are intentionally **opaque** — consumers should not\n * access `config` directly. Instead, pass descriptors to\n * {@link withExtensions} to obtain augmented builder factories.\n *\n * @typeParam T - The concrete {@link ExtensionConfig} shape. Inferred\n * automatically by `defineExtension`; you rarely need to specify it.\n *\n * @example\n * ```ts\n * // The type is inferred — no need to annotate\n * const myExt: ExtensionDescriptor<{ string: { slug: ... } }> = defineExtension({ ... });\n * ```\n *\n * @see {@link defineExtension}\n * @see {@link withExtensions}\n */\nexport type ExtensionDescriptor<T extends ExtensionConfig = ExtensionConfig> = {\n readonly __brand: unique symbol;\n readonly config: T;\n};\n\n// ---------------------------------------------------------------------------\n// Type-level extraction of extension methods per builder type\n// ---------------------------------------------------------------------------\n\n/** Extracts the method signatures an extension adds to a given builder type. */\ntype ExtractMethods<\n TExt extends ExtensionConfig,\n TType extends BuilderTypeName\n> =\n TExt[TType] extends Record<string, (...args: any[]) => any>\n ? TExt[TType]\n : {};\n\n/** Merges the methods from multiple extensions for a given builder type. */\ntype MergeExtensionMethods<\n TExts extends readonly ExtensionDescriptor<any>[],\n TType extends BuilderTypeName\n> = TExts extends readonly [\n ExtensionDescriptor<infer TFirst>,\n ...infer TRest extends readonly ExtensionDescriptor<any>[]\n]\n ? ExtractMethods<TFirst, TType> & MergeExtensionMethods<TRest, TType>\n : {};\n\n// ---------------------------------------------------------------------------\n// Return types for withExtensions()\n// ---------------------------------------------------------------------------\n\n/**\n * Intersected onto consumer-facing builder types to make `withExtension`\n * and `getExtension` uncallable (`never`). Using an intersection instead\n * of `Omit` preserves the class identity so extended builders remain\n * assignable to `SchemaBuilder<any, any, any, any, any>`.\n */\nexport type HiddenExtensionMethods = {\n /** @internal Extension-author only — use inside `defineExtension()`. */\n withExtension: never;\n /** @internal Extension-author only — use inside `defineExtension()`. */\n getExtension: never;\n};\n\n/**\n * Overrides extension method return types so they always return the full\n * extended builder type. This ensures extension methods preserve all other\n * extension methods through chaining (e.g. `s.string().email().slug()`).\n *\n * The self-reference (`FixedMethods` appears in its own mapped return\n * types) is resolved lazily by TypeScript because the recursion sits\n * inside a function-return position within a conditional mapped type.\n */\nexport type FixedMethods<TRawMethods, TBase> = {\n [K in keyof TRawMethods]: TRawMethods[K] extends (\n this: any,\n ...args: infer A\n ) => any\n ? (\n ...args: A\n ) => TBase & FixedMethods<TRawMethods, TBase> & HiddenExtensionMethods\n : TRawMethods[K];\n};\n\n/**\n * Produces the consumer-facing type for an extended builder: the base\n * builder intersected with its fixed extension methods, with\n * `withExtension` / `getExtension` overridden to `never` so they\n * don't appear as callable in consumer code.\n */\nexport type CleanExtended<TBuilder, TExt> = TBuilder &\n FixedMethods<TExt, TBuilder> &\n HiddenExtensionMethods;\n\n// -- Factory types that return builders with corrected extension methods ------\n\ntype ExtendedStringFactory<TExt> = {\n (): CleanExtended<\n StringSchemaBuilder<string, true, false, false, TExt>,\n TExt\n >;\n <T extends string>(\n equals: T\n ): CleanExtended<StringSchemaBuilder<T, true, false, false, TExt>, TExt>;\n};\n\ntype ExtendedNumberFactory<TExt> = {\n (): CleanExtended<\n NumberSchemaBuilder<number, true, false, false, TExt>,\n TExt\n >;\n <T extends number>(\n equals: T\n ): CleanExtended<NumberSchemaBuilder<T, true, false, false, TExt>, TExt>;\n};\n\ntype ExtendedBooleanFactory<TExt> = () => CleanExtended<\n BooleanSchemaBuilder<boolean, true, false, undefined, false, TExt>,\n TExt\n>;\n\ntype ExtendedDateFactory<TExt> = () => CleanExtended<\n DateSchemaBuilder<Date, true, false, false, TExt>,\n TExt\n>;\n\ntype ExtendedObjectFactory<TExt> = <\n P extends Record<string, SchemaBuilder<any, any, any, any, any>>\n>(\n properties?: P\n) => CleanExtended<\n ObjectSchemaBuilder<P, true, false, undefined, false, TExt>,\n TExt\n>;\n\ntype ExtendedArrayFactory<TExt> = <\n TElementSchema extends SchemaBuilder<any, any, any, any, any>\n>(\n elementSchema?: TElementSchema\n) => CleanExtended<\n ArraySchemaBuilder<TElementSchema, true, false, undefined, false, TExt>,\n TExt\n>;\n\ntype ExtendedUnionFactory<TExt> = <\n T extends SchemaBuilder<any, any, any, any, any>\n>(\n schema: T\n) => CleanExtended<\n UnionSchemaBuilder<[T], true, false, undefined, false, TExt>,\n TExt\n>;\n\ntype ExtendedFuncFactory<TExt> = () => CleanExtended<\n FunctionSchemaBuilder<true, false, undefined, false, TExt>,\n TExt\n>;\n\ntype ExtendedAnyFactory<TExt> = () => CleanExtended<\n AnySchemaBuilder<true, false, undefined, false, TExt>,\n TExt\n>;\n\ntype ExtendedTupleFactory<TExt> = <\n const TElements extends readonly SchemaBuilder<any, any, any, any, any>[]\n>(\n elements: [...TElements]\n) => CleanExtended<\n TupleSchemaBuilder<TElements, true, false, undefined, false, TExt>,\n TExt\n>;\n\ntype ExtendedRecordFactory<TExt> = <\n TKeySchema extends StringSchemaBuilder<any, any, any, any>,\n TValueSchema extends SchemaBuilder<any, any, any, any, any>\n>(\n keySchema: TKeySchema,\n valueSchema: TValueSchema\n) => CleanExtended<\n RecordSchemaBuilder<\n TKeySchema,\n TValueSchema,\n true,\n false,\n undefined,\n false,\n TExt\n >,\n TExt\n>;\n\n/**\n * The return type of {@link withExtensions}.\n *\n * Contains a factory function for every builder type (`string`, `number`,\n * `boolean`, `date`, `object`, `array`, `union`, `func`, `any`). Each\n * factory returns a builder whose type includes the methods contributed\n * by all provided extension descriptors.\n *\n * @typeParam TExts - Tuple of extension descriptors passed to `withExtensions`.\n *\n * @see {@link withExtensions}\n */\ntype WithExtensionsResult<TExts extends readonly ExtensionDescriptor<any>[]> = {\n string: ExtendedStringFactory<MergeExtensionMethods<TExts, 'string'>>;\n number: ExtendedNumberFactory<MergeExtensionMethods<TExts, 'number'>>;\n boolean: ExtendedBooleanFactory<MergeExtensionMethods<TExts, 'boolean'>>;\n date: ExtendedDateFactory<MergeExtensionMethods<TExts, 'date'>>;\n object: ExtendedObjectFactory<MergeExtensionMethods<TExts, 'object'>>;\n array: ExtendedArrayFactory<MergeExtensionMethods<TExts, 'array'>>;\n tuple: ExtendedTupleFactory<MergeExtensionMethods<TExts, 'tuple'>>;\n record: ExtendedRecordFactory<MergeExtensionMethods<TExts, 'record'>>;\n union: ExtendedUnionFactory<MergeExtensionMethods<TExts, 'union'>>;\n func: ExtendedFuncFactory<MergeExtensionMethods<TExts, 'func'>>;\n any: ExtendedAnyFactory<MergeExtensionMethods<TExts, 'any'>>;\n};\n\n// ---------------------------------------------------------------------------\n// Reserved method names — cannot be overridden by extensions\n// ---------------------------------------------------------------------------\n\n/**\n * Method names on `SchemaBuilder` that extensions are **not** allowed to\n * override. An error is thrown at definition time if an extension tries\n * to use any of these names.\n *\n * @internal\n */\nconst RESERVED_METHODS = new Set([\n 'validate',\n 'validateAsync',\n 'parse',\n 'parseAsync',\n 'safeParse',\n 'safeParseAsync',\n 'introspect',\n 'optional',\n 'required',\n 'addPreprocessor',\n 'clearPreprocessors',\n 'addValidator',\n 'clearValidators',\n 'hasType',\n 'clearHasType',\n 'createFromProps',\n 'preValidate',\n 'preValidateSync',\n 'preValidateAsync',\n 'getValidationErrorMessage',\n 'getValidationErrorMessageSync',\n 'assureValidationErrorMessageProvider',\n 'withExtension',\n 'getExtension'\n]);\n\n// ---------------------------------------------------------------------------\n// defineExtension()\n// ---------------------------------------------------------------------------\n\n/**\n * Defines an extension targeting one or more schema builder types.\n *\n * Each extension is a plain object keyed by builder type name (`\"string\"`,\n * `\"number\"`, `\"date\"`, …) whose values are method implementations.\n * Methods receive `this` bound to the builder instance and must return a\n * builder to support fluent chaining.\n *\n * ## Ergonomic metadata (auto-infer)\n *\n * Extension methods **do not** have to call `this.withExtension()`. The\n * system wraps each method and automatically attaches\n * `withExtension(methodName, args)` to the returned builder when the key\n * is not already present. This eliminates the most common source of\n * duplication in extension code.\n *\n * - **Zero-arg methods** → metadata value is `true`\n * - **Single-arg methods** → metadata value is the argument itself\n * - **Multi-arg methods** → metadata value is the arguments array\n *\n * If you need **custom metadata** (e.g. a different key, a transformed\n * value, or a structured object), call `this.withExtension(key, value)`\n * explicitly inside the method — the auto-infer logic detects the existing\n * key and skips automatic attachment.\n *\n * ## Validation\n *\n * `defineExtension` validates the configuration eagerly:\n * - Unknown builder type names throw immediately.\n * - {@link RESERVED_METHODS | Reserved method names} (e.g. `validate`,\n * `introspect`) cannot be overridden.\n * - Non-function values in the method record are rejected.\n *\n * @param config - An {@link ExtensionConfig} object mapping builder type\n * names to method records.\n * @returns A branded {@link ExtensionDescriptor} ready to pass to\n * {@link withExtensions}.\n *\n * @example Simple extension (auto-inferred metadata)\n * ```ts\n * const slugExt = defineExtension({\n * string: {\n * slug(this: StringSchemaBuilder) {\n * return this.addValidator((val) => {\n * const valid = /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(val);\n * return { valid, errors: valid ? [] : [{ message: 'invalid slug' }] };\n * });\n * }\n * }\n * });\n *\n * // Usage:\n * const s = withExtensions(slugExt);\n * const schema = s.string().slug();\n * schema.introspect().extensions.slug; // true\n * ```\n *\n * @example Extension with custom metadata\n * ```ts\n * const currencyExt = defineExtension({\n * number: {\n * currency(this: NumberSchemaBuilder, opts?: { maxDecimals?: number }) {\n * const maxDec = opts?.maxDecimals ?? 2;\n * return this.withExtension('currency', { maxDecimals: maxDec })\n * .min(0)\n * .addValidator((val) => {\n * const decimals = (String(val).split('.')[1] ?? '').length;\n * const valid = decimals <= maxDec;\n * return { valid, errors: valid ? [] : [{ message: `max ${maxDec} decimals` }] };\n * });\n * }\n * }\n * });\n * ```\n *\n * @example Multi-builder extension\n * ```ts\n * const myExt = defineExtension({\n * string: {\n * email(this: StringSchemaBuilder) { return this.addValidator(...); }\n * },\n * number: {\n * port(this: NumberSchemaBuilder) { return this.isInteger().min(1).max(65535); }\n * }\n * });\n * ```\n *\n * @throws {Error} If a builder type name is unknown.\n * @throws {Error} If a method name is reserved.\n * @throws {Error} If a method value is not a function.\n *\n * @see {@link withExtensions} — apply the defined extension\n * @see {@link ExtensionConfig} — configuration shape\n */\nexport function defineExtension<T extends ExtensionConfig>(\n config: T\n): ExtensionDescriptor<T> {\n // Validate at definition time and wrap methods for auto-infer extension key\n const wrappedConfig: any = {};\n for (const builderName of Object.keys(config) as BuilderTypeName[]) {\n if (!(builderName in builderClasses)) {\n throw new Error(\n `Unknown builder type \"${builderName}\". Valid types: ${Object.keys(builderClasses).join(', ')}`\n );\n }\n\n const methods = config[builderName];\n if (!methods || typeof methods !== 'object') {\n throw new Error(\n `Extension config for \"${builderName}\" must be an object of methods`\n );\n }\n\n wrappedConfig[builderName] = {};\n for (const methodName of Object.keys(methods)) {\n if (RESERVED_METHODS.has(methodName)) {\n throw new Error(\n `Cannot override reserved method \"${methodName}\" on \"${builderName}\"`\n );\n }\n const origMethod = methods[methodName];\n if (typeof origMethod !== 'function') {\n throw new Error(\n `Extension method \"${builderName}.${methodName}\" must be a function`\n );\n }\n // Wrap the method to auto-infer extension key if not already set\n wrappedConfig[builderName][methodName] = function (\n this: any,\n ...args: any[]\n ) {\n const result = (origMethod as any).apply(this, args);\n // If result is a builder and does not have the extension key, auto-apply withExtension\n if (\n result &&\n typeof result === 'object' &&\n typeof result.withExtension === 'function' &&\n // Only auto-apply if the extension key is not already present\n (typeof result.getExtension !== 'function' ||\n result.getExtension(methodName) === undefined)\n ) {\n // Only auto-apply if the original method did not call withExtension\n return result.withExtension(\n methodName,\n args.length === 1\n ? args[0]\n : args.length === 0\n ? true\n : args\n );\n }\n return result;\n };\n }\n }\n\n return { config: wrappedConfig } as ExtensionDescriptor<T>;\n}\n\n// ---------------------------------------------------------------------------\n// withExtensions()\n// ---------------------------------------------------------------------------\n\n/**\n * Creates a set of schema factory functions with the provided extensions\n * applied.\n *\n * Each factory function (`string()`, `number()`, `date()`, …) returned by\n * `withExtensions` produces builder instances whose prototypes include the\n * extension methods. All built-in builder methods remain available and\n * fully chainable alongside the new ones.\n *\n * ## Stacking multiple extensions\n *\n * Pass any number of {@link ExtensionDescriptor}s — their methods are\n * merged per builder type. If two extensions define the **same** method\n * name on the same builder type, a runtime error is thrown to prevent\n * silent conflicts.\n *\n * ## Type safety\n *\n * The return type is fully inferred: TypeScript knows exactly which\n * extension methods are available on each builder factory. Extension\n * methods return the full extended builder type, so chaining like\n * `s.string().email().slug().minLength(3)` is fully typed.\n *\n * ## Builder types without extensions\n *\n * Builders that have no methods from any of the provided extensions\n * use the standard (unextended) factory, so there is zero overhead.\n *\n * @param extensions - One or more {@link ExtensionDescriptor}s created\n * by {@link defineExtension}.\n * @returns An object with factory functions for all builder types\n * (`string`, `number`, `boolean`, `date`, `object`, `array`, `union`,\n * `func`, `any`), each returning augmented builders.\n *\n * @example Basic usage\n * ```ts\n * const s = withExtensions(emailExt, rangeExt);\n *\n * // string() now has .email()\n * const emailSchema = s.string().email().minLength(5);\n *\n * // number() now has .range()\n * const rangeSchema = s.number().range(0, 100);\n *\n * // builders without targeted extensions work as normal\n * const dateSchema = s.date();\n * ```\n *\n * @example Stacking extensions on the same builder\n * ```ts\n * const s = withExtensions(emailExt, slugExt, trimmedExt);\n * const schema = s.string().email().slug().trimmed();\n * ```\n *\n * @example Using extensions in object schemas\n * ```ts\n * const s = withExtensions(emailExt, portExt);\n * const ServerConfig = s.object({\n * host: s.string().email(),\n * port: s.number().port()\n * });\n * ```\n *\n * @throws {Error} If two extensions define the same method name on the\n * same builder type.\n *\n * @see {@link defineExtension} — create extension descriptors\n * @see {@link ExtensionDescriptor}\n */\nexport function withExtensions<\n const TExts extends readonly ExtensionDescriptor<any>[]\n>(...extensions: TExts): WithExtensionsResult<TExts> {\n // Collect all methods per builder type and check for collisions\n const methodsByBuilder = new Map<BuilderTypeName, Map<string, Function>>();\n\n for (const ext of extensions) {\n for (const builderName of Object.keys(\n ext.config\n ) as BuilderTypeName[]) {\n if (!methodsByBuilder.has(builderName)) {\n methodsByBuilder.set(builderName, new Map());\n }\n const methods = methodsByBuilder.get(builderName)!;\n const extMethods = ext.config[builderName]!;\n\n for (const methodName of Object.keys(extMethods)) {\n if (methods.has(methodName)) {\n throw new Error(\n `Extension method collision: \"${methodName}\" is defined by multiple extensions for \"${builderName}\"`\n );\n }\n methods.set(methodName, extMethods[methodName]);\n }\n }\n }\n\n // For each builder type, create a dynamic subclass if there are extension methods\n const factories: Record<string, (...args: any[]) => any> = {};\n\n for (const builderName of Object.keys(\n builderClasses\n ) as BuilderTypeName[]) {\n const methods = methodsByBuilder.get(builderName);\n\n if (!methods || methods.size === 0) {\n // No extensions for this builder type — use the standard factory\n factories[builderName] = builderFactories[builderName];\n continue;\n }\n\n const BaseClass = builderClasses[builderName] as any;\n\n // Create a dynamic subclass\n const ExtendedClass = class extends BaseClass {\n // biome-ignore lint/complexity/noUselessConstructor: required\n constructor(...args: any[]) {\n super(...args);\n }\n\n static create(props: any) {\n return new ExtendedClass({\n ...props\n });\n }\n\n protected createFromProps(props: any): any {\n return ExtendedClass.create(props);\n }\n };\n\n // Add extension methods to the subclass prototype\n for (const [methodName, methodFn] of methods) {\n Object.defineProperty(ExtendedClass.prototype, methodName, {\n value: methodFn,\n writable: true,\n configurable: true,\n enumerable: false\n });\n }\n\n // Create a factory that uses the extended class\n factories[builderName] = (...args: any[]) => {\n // Delegate to the original factory to get an initialized instance,\n // then upgrade its prototype so it gains the extension methods.\n // Note: Object.setPrototypeOf can cause V8 hidden-class deoptimization\n // on the mutated object, but avoids the double allocation and\n // introspect() round-trip of the previous approach.\n const original = builderFactories[builderName](...args);\n Object.setPrototypeOf(original, ExtendedClass.prototype);\n return original;\n };\n }\n\n return factories as WithExtensionsResult<TExts>;\n}\n"],"mappings":"wiBA8CO,IAAMA,EAAN,MAAMC,UAMHC,CAMR,CACEC,GACAC,GAA2D,KAK3D,OAAc,OAAOC,EAA0C,CAC3D,OAAO,IAAIJ,EAAkB,CACzB,KAAM,OACN,GAAGI,CACP,CAAC,CACL,CAEU,YAAYA,EAAgD,CAElE,GADA,MAAMA,CAAY,EACd,OAAQA,EAAc,QAAW,WACjC,MAAM,IAAI,MAAM,8CAA8C,EAElE,KAAKF,GAAWE,EAAc,MAClC,CAMO,SAA4C,CAC/C,OAAI,KAAKD,KAAoB,OACzB,KAAKA,GAAkB,KAAKD,GAAQ,GAEjC,KAAKC,EAChB,CAKO,YAAa,CAChB,MAAO,CACH,GAAG,MAAM,WAAW,EAKpB,OAAQ,KAAKD,EACjB,CACJ,CAEAG,GACIC,EACAC,EACyB,CACzB,GAAM,CACF,MAAAC,EACA,YAAaC,EACb,OAAAC,CACJ,EAAIJ,EAEJ,GAAI,CAACE,EACD,MAAO,CAAE,MAAAA,EAAO,OAAAE,CAAO,EAG3B,GAAM,CACF,OAAQ,CAAE,gBAAiBC,CAAc,CAC7C,EAAIF,EAGJ,OAAIE,GAAiB,KACV,CAAE,MAAO,GAAM,OAAQA,CAAc,EAGzC,KAAK,QAAQ,EAAE,SAClBA,EACAJ,CACJ,CACJ,CAGO,SACHK,EACAL,EACyB,CACzB,OAAO,MAAM,SAASK,EAAQL,CAAO,CACzC,CAGA,MAAa,cACTK,EACAL,EACkC,CAClC,OAAO,MAAM,cAAcK,EAAQL,CAAO,CAG9C,CAOU,UACNK,EACAL,EACyB,CACzB,OAAO,KAAKF,GACR,KAAK,gBAAgBO,EAAQL,CAAO,EACpCA,CACJ,CACJ,CAOA,MAAgB,eACZK,EACAL,EACkC,CAClC,IAAMD,EAAc,MAAM,MAAM,iBAAiBM,EAAQL,CAAO,EAE1D,CACF,MAAAC,EACA,YAAaC,EACb,OAAAC,CACJ,EAAIJ,EAEJ,GAAI,CAACE,EACD,MAAO,CAAE,MAAAA,EAAO,OAAAE,CAAO,EAG3B,GAAM,CACF,OAAQ,CAAE,gBAAiBC,CAAc,CAC7C,EAAIF,EAEJ,OAAIE,GAAiB,KACV,CAAE,MAAO,GAAM,OAAQA,CAAc,EAGzC,KAAK,QAAQ,EAAE,cAAcA,EAAeJ,CAAO,CAG9D,CAEU,gBACNH,EACI,CACJ,OAAOJ,EAAkB,OAAOI,CAAY,CAChD,CAKO,QACHS,EAEY,CACZ,OAAO,KAAK,gBAAgB,CACxB,GAAG,KAAK,WAAW,CACvB,CAAQ,CACZ,CAKO,cAOS,CACZ,OAAO,KAAK,gBAAgB,CACxB,GAAG,KAAK,WAAW,CACvB,CAAQ,CACZ,CAKO,SACHC,EAEY,CACZ,OAAO,MAAM,SAASA,CAAY,CACtC,CAKO,UAOS,CACZ,OAAO,MAAM,SAAS,CAC1B,CAKO,QACHC,EAEY,CACZ,OAAO,MAAM,QAAQA,CAAK,CAC9B,CAKO,cAOS,CACZ,OAAO,MAAM,aAAa,CAC9B,CAKO,MACHC,EAQY,CACZ,OAAO,MAAM,MAAMA,CAAK,CAC5B,CAKO,UAOS,CACZ,OAAO,MAAM,SAAS,CAC1B,CAKO,UAOS,CACZ,OAAO,MAAM,SAAS,CAC1B,CAKO,aAOS,CACZ,OAAO,MAAM,YAAY,CAC7B,CACJ,EAkCO,SAASC,EACZC,EACkD,CAClD,OAAOnB,EAAkB,OAAO,CAC5B,KAAM,OACN,WAAY,GACZ,cAAe,CAAC,EAChB,WAAY,CAAC,EACb,OAAAmB,CACJ,CAAQ,CACZ,CC/TO,IAAMC,EAAN,MAAMC,UAMHC,CAAoE,CAI1E,OAAc,OAAOC,EAA0C,CAC3D,OAAO,IAAIF,EAAkB,CACzB,KAAM,OACN,GAAGE,CACP,CAAC,CACL,CAEU,YAAYA,EAAgD,CAClE,MAAMA,CAAY,CACtB,CAKO,QACHC,EAEY,CACZ,OAAO,KAAK,gBAAgB,CACxB,GAAG,KAAK,WAAW,CACvB,CAAQ,CACZ,CAKO,cAOS,CACZ,OAAO,KAAK,gBAAgB,CACxB,GAAG,KAAK,WAAW,CACvB,CAAQ,CACZ,CAMAC,GAAaC,EAAqC,CAC9C,OAAIA,IAAW,KAAa,CAAE,MAAO,GAAM,OAAQ,IAAK,EAEpDA,IAAW,QAAa,KAAK,WACV,KAAK,oBAAoB,IACzB,KAAa,CAAE,MAAO,GAAM,OAAQ,IAAK,EACrD,CAAE,MAAO,GAAO,OAAQ,CAAC,CAAE,QAAS,cAAe,CAAC,CAAE,EAG7DA,IAAW,QAAa,CAAC,KAAK,WACvB,CAAE,MAAO,GAAM,OAAQ,MAAiB,EAG5C,CACH,MAAO,GACP,OAAQ,CAAC,CAAE,QAAS,cAAe,CAAC,CACxC,CACJ,CAGO,SACHA,EACAC,EACsB,CACtB,OAAO,MAAM,SAASD,EAAQC,CAAO,CACzC,CAGA,MAAa,cACTD,EACAC,EAC+B,CAC/B,OAAO,MAAM,cAAcD,EAAQC,CAAO,CAG9C,CAMU,UACND,EACAE,EACsB,CACtB,OAAO,KAAKH,GAAaC,CAAM,CACnC,CAMA,MAAgB,eACZA,EACAE,EAC+B,CAC/B,OAAO,KAAKH,GAAaC,CAAM,CACnC,CAEU,gBACNH,EACI,CACJ,OAAOF,EAAkB,OAAOE,CAAY,CAChD,CAKO,SACHM,EAQY,CACZ,OAAO,MAAM,SAASA,CAAY,CACtC,CAKO,UAOS,CACZ,OAAO,MAAM,SAAS,CAC1B,CAKO,QACHC,EAEY,CACZ,OAAO,MAAM,QAAQA,CAAK,CAC9B,CAKO,cAOS,CACZ,OAAO,MAAM,aAAa,CAC9B,CAKO,MACHC,EAQY,CACZ,OAAO,MAAM,MAAMA,CAAK,CAC5B,CASO,UAOS,CACZ,OAAO,MAAM,SAAS,CAC1B,CAKO,UAOS,CACZ,OAAO,MAAM,SAAS,CAC1B,CAKO,aAOS,CACZ,OAAO,MAAM,YAAY,CAC7B,CACJ,EAsCaC,EAAM,IACfZ,EAAkB,OAAO,CACrB,WAAY,EAChB,CAAC,ECnOL,IAAMa,EAAgE,CAClE,OAAQC,EACR,OAAQC,EACR,QAASC,EACT,KAAMC,EACN,OAAQC,EACR,MAAOC,EACP,MAAOC,EACP,OAAQC,EACR,MAAOC,EACP,KAAMC,EACN,IAAKC,CACT,EAGMC,EAAqE,CACvE,OAAAC,EACA,OAAAC,EACA,QAAAC,EACA,KAAAC,EACA,OAAAC,EACA,MAAAC,EACA,MAAAC,EACA,OAAAC,EACA,MAAAC,EACA,KAAAC,EACA,IAAAC,CACJ,EA6RMC,EAAmB,IAAI,IAAI,CAC7B,WACA,gBACA,QACA,aACA,YACA,iBACA,aACA,WACA,WACA,kBACA,qBACA,eACA,kBACA,UACA,eACA,kBACA,cACA,kBACA,mBACA,4BACA,gCACA,uCACA,gBACA,cACJ,CAAC,EAoGM,SAASC,EACZC,EACsB,CAEtB,IAAMC,EAAqB,CAAC,EAC5B,QAAWC,KAAe,OAAO,KAAKF,CAAM,EAAwB,CAChE,GAAI,EAAEE,KAAe5B,GACjB,MAAM,IAAI,MACN,yBAAyB4B,CAAW,mBAAmB,OAAO,KAAK5B,CAAc,EAAE,KAAK,IAAI,CAAC,EACjG,EAGJ,IAAM6B,EAAUH,EAAOE,CAAW,EAClC,GAAI,CAACC,GAAW,OAAOA,GAAY,SAC/B,MAAM,IAAI,MACN,yBAAyBD,CAAW,gCACxC,EAGJD,EAAcC,CAAW,EAAI,CAAC,EAC9B,QAAWE,KAAc,OAAO,KAAKD,CAAO,EAAG,CAC3C,GAAIL,EAAiB,IAAIM,CAAU,EAC/B,MAAM,IAAI,MACN,oCAAoCA,CAAU,SAASF,CAAW,GACtE,EAEJ,IAAMG,EAAaF,EAAQC,CAAU,EACrC,GAAI,OAAOC,GAAe,WACtB,MAAM,IAAI,MACN,qBAAqBH,CAAW,IAAIE,CAAU,sBAClD,EAGJH,EAAcC,CAAW,EAAEE,CAAU,EAAI,YAElCE,EACL,CACE,IAAMC,EAAUF,EAAmB,MAAM,KAAMC,CAAI,EAEnD,OACIC,GACA,OAAOA,GAAW,UAClB,OAAOA,EAAO,eAAkB,aAE/B,OAAOA,EAAO,cAAiB,YAC5BA,EAAO,aAAaH,CAAU,IAAM,QAGjCG,EAAO,cACVH,EACAE,EAAK,SAAW,EACVA,EAAK,CAAC,EACNA,EAAK,SAAW,EACd,GACAA,CACZ,EAEGC,CACX,CACJ,CACJ,CAEA,MAAO,CAAE,OAAQN,CAAc,CACnC,CA2EO,SAASO,KAEXC,EAAgD,CAEjD,IAAMC,EAAmB,IAAI,IAE7B,QAAWC,KAAOF,EACd,QAAWP,KAAe,OAAO,KAC7BS,EAAI,MACR,EAAwB,CACfD,EAAiB,IAAIR,CAAW,GACjCQ,EAAiB,IAAIR,EAAa,IAAI,GAAK,EAE/C,IAAMC,EAAUO,EAAiB,IAAIR,CAAW,EAC1CU,EAAaD,EAAI,OAAOT,CAAW,EAEzC,QAAWE,KAAc,OAAO,KAAKQ,CAAU,EAAG,CAC9C,GAAIT,EAAQ,IAAIC,CAAU,EACtB,MAAM,IAAI,MACN,gCAAgCA,CAAU,4CAA4CF,CAAW,GACrG,EAEJC,EAAQ,IAAIC,EAAYQ,EAAWR,CAAU,CAAC,CAClD,CACJ,CAIJ,IAAMS,EAAqD,CAAC,EAE5D,QAAWX,KAAe,OAAO,KAC7B5B,CACJ,EAAwB,CACpB,IAAM6B,EAAUO,EAAiB,IAAIR,CAAW,EAEhD,GAAI,CAACC,GAAWA,EAAQ,OAAS,EAAG,CAEhCU,EAAUX,CAAW,EAAIhB,EAAiBgB,CAAW,EACrD,QACJ,CAEA,IAAMY,EAAYxC,EAAe4B,CAAW,EAGtCa,EAAgB,cAAcD,CAAU,CAE1C,eAAeR,EAAa,CACxB,MAAM,GAAGA,CAAI,CACjB,CAEA,OAAO,OAAOU,EAAY,CACtB,OAAO,IAAID,EAAc,CACrB,GAAGC,CACP,CAAC,CACL,CAEU,gBAAgBA,EAAiB,CACvC,OAAOD,EAAc,OAAOC,CAAK,CACrC,CACJ,EAGA,OAAW,CAACZ,EAAYa,CAAQ,IAAKd,EACjC,OAAO,eAAeY,EAAc,UAAWX,EAAY,CACvD,MAAOa,EACP,SAAU,GACV,aAAc,GACd,WAAY,EAChB,CAAC,EAILJ,EAAUX,CAAW,EAAI,IAAII,IAAgB,CAMzC,IAAMY,EAAWhC,EAAiBgB,CAAW,EAAE,GAAGI,CAAI,EACtD,cAAO,eAAeY,EAAUH,EAAc,SAAS,EAChDG,CACX,CACJ,CAEA,OAAOL,CACX","names":["LazySchemaBuilder","_LazySchemaBuilder","SchemaBuilder","#getter","#resolvedSchema","props","#buildResult","superResult","context","valid","preValidationTransaction","errors","objToValidate","object","_notUsed","errorMessage","value","_name","lazy","getter","NullSchemaBuilder","_NullSchemaBuilder","SchemaBuilder","props","_notUsed","#buildResult","object","context","_context","errorMessage","value","_name","nul","builderClasses","StringSchemaBuilder","NumberSchemaBuilder","BooleanSchemaBuilder","DateSchemaBuilder","ObjectSchemaBuilder","ArraySchemaBuilder","TupleSchemaBuilder","RecordSchemaBuilder","UnionSchemaBuilder","FunctionSchemaBuilder","AnySchemaBuilder","builderFactories","string","number","boolean","date","object","array","tuple","record","union","func","any","RESERVED_METHODS","defineExtension","config","wrappedConfig","builderName","methods","methodName","origMethod","args","result","withExtensions","extensions","methodsByBuilder","ext","extMethods","factories","BaseClass","ExtendedClass","props","methodFn","original"]}
|
package/dist/chunk-CTP4RHDG.js
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
var y=Symbol("transaction"),P=[Error,RegExp,Date],R={shouldNotWrapWithTransaction:u=>!!P.find(e=>u instanceof e)},h=(u,e)=>{let r={},a=new Map;e=Object.assign({},R,e||{});let{shouldNotWrapWithTransaction:i}=e,l=()=>!!Object.keys(r).find(s=>r[s]?.[y]?r[s][y].isDirty():!0)||a.size>0,c=()=>{let s={};Object.keys(u).forEach(t=>{s[t]=u[t]}),Object.keys(r).forEach(t=>{let o=r[t];if(o[y]){let{commit:d}=o[y];s[t]=d()}else s[t]=r[t]});for(let t of a.keys())delete s[t];return r={},a=new Map,s},p=()=>{for(let s in r){let t=r[s];t&&typeof t=="object"&&t[y]&&t[y].rollback()}return r={},a=new Map,u};if(Array.isArray(u)){let s=u.map(d=>typeof d=="object"&&d&&!i(d)?h(d).object:d),t=()=>s.map(d=>d&&typeof d[y]=="object"?d[y].commit():d),o=()=>!!s.find((d,f)=>d&&typeof d[y]=="object"?d[y].isDirty():s[f]!==u[f]);return Object.defineProperty(s,y,{writable:!1,configurable:!1,value:{initial:u,object:s,commit:t,rollback:()=>u,isDirty:o}}),{object:s,commit:t,rollback:()=>u,isDirty:o}}let n=new Proxy(u,{set:(s,t,o)=>s&&s[t]===o?(delete r[t],!0):(r[t]=o,a.delete(t),!0),ownKeys:s=>[...Object.keys(s).filter(t=>!a.has(t)),...Object.keys(r).filter(t=>!(t in s))],getOwnPropertyDescriptor:(s,t)=>{if(!a.has(t))return t in r?Object.getOwnPropertyDescriptor(r,t):Object.getOwnPropertyDescriptor(s,t)},has:(s,t)=>a.has(t)?!1:t in r?!0:t in s,get:(s,t)=>{if(typeof t=="symbol")return t===y?{initial:u,object:n,commit:c,rollback:p,isDirty:l}:s[t];if(t in r)return r[t];if(!a.has(t)){if(!S(s[t])&&typeof s[t]=="object"&&s[t]&&!i(s[t])){let{object:o}=h(s[t],e);return r[t]=o,o}return s[t]}},deleteProperty:(s,t)=>(t in r&&(r[t]&&typeof r[t][y]=="object"&&r[t][y].rollback(),delete r[t]),t in s&&a.set(t,!0),!0)});return{object:n,commit:c,rollback:p,isDirty:l}},T=u=>({object:u,commit:()=>u,rollback:()=>u,isDirty:()=>!1}),S=u=>u&&typeof u=="object"&&Object.hasOwn(u,y);var m=class extends Error{errors;constructor(e){let r=e.length>0?e.map(a=>a.message).join("; "):"Validation failed";super(r),this.name="SchemaValidationError",this.errors=e}},x=Symbol(),v=Symbol();function E(u,e,r,a){return Object.defineProperties(u,{seenValue:{get:e,enumerable:!1},errors:{get:r,enumerable:!1},isValid:{get:()=>r().length===0,enumerable:!1},descriptor:{get:a,enumerable:!1}}),u}var b=class{#d=!0;#a=!1;#y=!1;#p;#e=[];#t=[];#n=!1;#h=!0;#c={};#T="base";#f="is required";#o="is required";#s=void 0;#i=void 0;#l=!1;#u;get"~standard"(){if(this.#u)return this.#u;let e=this;return this.#u={version:1,vendor:"@cleverbrush/schema",validate(r){let a=e.validate(r);return a.valid?{value:a.object}:{issues:(a.errors??[]).map(i=>({message:i.message}))}}},this.#u}get type(){return this.#T}set type(e){if(typeof e!="string"||!e)throw new Error("value should be non empty string");this.#T=e}get preprocessors(){return this.#e}get validators(){return this.#t}get isRequired(){return this.#d}get isNullable(){return this.#a}set isRequired(e){if(typeof e!="boolean")throw new Error("should be a boolean value");this.#d=e}get requiredErrorMessage(){return this.#o}get hasDefault(){return this.#s!==void 0}get hasCatch(){return this.#l}resolveCatchValue(){return typeof this.#i=="function"?this.#i():this.#i}get isReadonly(){return this.#y}resolveDefaultValue(){return typeof this.#s=="function"?this.#s():this.#s}get canSkipPreValidation(){return this.#h}get isNullRequiredViolation(){return!0}#m(e,r){let a=r?.doNotStopOnFirstError??!1,i={doNotStopOnFirstError:a,rootPropertyDescriptor:r?.rootPropertyDescriptor,currentPropertyDescriptor:r?.currentPropertyDescriptor},l=this.#n;return{doNotStopOnFirstError:a,resultingContext:i,transaction:l?h({validatedObject:e}):T({validatedObject:e}),errors:[]}}#r(e,r){return{valid:!1,errors:[e[0]].filter(a=>a),context:r}}#b(e,r,a){return Array.isArray(a)&&a.length?a:[{message:`Validator #${e}${r?` (${r})`:""} didn't pass.`}]}#P(e,r,a,i){return e.length>0?{valid:!1,errors:e.filter(l=>l).filter((l,c)=>r?!0:c===0),context:a,transaction:i}:{valid:!0,context:a,transaction:i}}preValidateSync(e,r){let a=this.#m(e,r),{doNotStopOnFirstError:i,resultingContext:l,errors:c}=a,p=a.transaction,n=p.object.validatedObject;if(this.#e.length>0){let s=0;for(let t of this.#e)try{let o=t.fn(n);if(o instanceof Promise)throw new Error(`Preprocessor #${s}${t.fn.name?` (${t.fn.name})`:""} returned a Promise. Use validateAsync() for schemas with async preprocessors.`);n=o}catch(o){if(o.message?.includes("Use validateAsync()"))throw o;if(c.push({message:`Preprocessor #${s}${t.fn.name?` (${t.fn.name})`:""} thrown an error: ${o.message}`}),!i)return this.#r(c,l)}finally{s++}p=this.#n?h({validatedObject:n}):T({validatedObject:n})}if(typeof n>"u"&&this.hasDefault&&(n=this.resolveDefaultValue(),p=this.#n?h({validatedObject:n}):T({validatedObject:n})),this.#t.length>0&&!(n==null&&!this.isRequired)&&!(n===null&&this.#a)){let s=0;for(let t of this.#t)try{let o=t.fn(n);if(o instanceof Promise)throw new Error(`Validator #${s}${t.fn.name?` (${t.fn.name})`:""} returned a Promise. Use validateAsync() for schemas with async validators.`);let{valid:d,errors:f}=o;if(!d&&(c.push(...this.#b(s,t.fn.name,f)),!i))return this.#r(c,l)}catch(o){if(o.message?.includes("Use validateAsync()"))throw o;if(c.push({message:`Validator #${s}${t.fn.name?` (${t.fn.name})`:""} thrown an error: ${o.message}`}),!i)return this.#r(c,l)}finally{s++}}return this.isRequired&&(typeof n>"u"||n===null&&this.isNullRequiredViolation&&!this.#a)&&(c.push({message:this.getValidationErrorMessageSync(this.#o,n)}),!i)?(p.rollback(),this.#r(c,l)):this.#P(c,i,l,p)}async preValidateAsync(e,r){let a=this.#m(e,r),{doNotStopOnFirstError:i,resultingContext:l,errors:c}=a,p=a.transaction,n=p.object.validatedObject;if(this.#e.length>0){let s=0;for(let t of this.#e)try{n=await Promise.resolve(t.fn(n))}catch(o){if(c.push({message:`Preprocessor #${s}${t.fn.name?` (${t.fn.name})`:""} thrown an error: ${o.message}`}),!i)return this.#r(c,l)}finally{s++}p=this.#n?h({validatedObject:n}):T({validatedObject:n})}if(typeof n>"u"&&this.hasDefault&&(n=this.resolveDefaultValue(),p=this.#n?h({validatedObject:n}):T({validatedObject:n})),this.#t.length>0&&!(n==null&&!this.isRequired)&&!(n===null&&this.#a)){let s=0;for(let t of this.#t)try{let{valid:o,errors:d}=await Promise.resolve(t.fn(n));if(!o&&(c.push(...this.#b(s,t.fn.name,d)),!i))return this.#r(c,l)}catch(o){if(c.push({message:`Validator #${s}${t.fn.name?` (${t.fn.name})`:""} thrown an error: ${o.message}`}),!i)return this.#r(c,l)}finally{s++}}return this.isRequired&&(typeof n>"u"||n===null&&this.isNullRequiredViolation&&!this.#a)&&(c.push({message:await this.getValidationErrorMessage(this.#o,n)}),!i)?(p.rollback(),this.#r(c,l)):this.#P(c,i,l,p)}preValidate(e,r){return this.preValidateAsync(e,r)}introspect(){return{type:this.type,isRequired:this.#d,isNullable:this.#a,isReadonly:this.#y,preprocessors:[...this.preprocessors],validators:[...this.validators],requiredValidationErrorMessageProvider:this.#o,extensions:{...this.#c},hasDefault:this.#s!==void 0,defaultValue:this.#s,description:this.#p,hasCatch:this.#l,catchValue:this.#i}}optional(){return this.createFromProps({...this.introspect(),isRequired:!1})}nullable(){return this.createFromProps({...this.introspect(),isNullable:!0})}notNullable(){return this.createFromProps({...this.introspect(),isNullable:!1})}default(e){return this.createFromProps({...this.introspect(),defaultValue:e})}catch(e){return this.createFromProps({...this.introspect(),catchValue:e,hasCatch:!0})}clearDefault(){return this.createFromProps({...this.introspect(),defaultValue:void 0})}describe(e){return this.createFromProps({...this.introspect(),description:e})}brand(e){return this.createFromProps({...this.introspect()})}readonly(){return this.createFromProps({...this.introspect(),isReadonly:!0})}required(e){return this.createFromProps({...this.introspect(),isRequired:!0,...e!==void 0?{requiredValidationErrorMessageProvider:this.assureValidationErrorMessageProvider(e,this.#f)}:{}})}addPreprocessor(e,r){if(typeof e!="function")throw new Error("preprocessor must be a function");return this.createFromProps({...this.introspect(),preprocessors:[...this.preprocessors,{fn:e,mutates:r?.mutates??!0}]})}clearPreprocessors(){return this.createFromProps({...this.introspect(),preprocessors:[]})}addValidator(e,r){if(typeof e!="function")throw new Error("validator must be a function");return this.createFromProps({...this.introspect(),validators:[...this.validators,{fn:e,mutates:r?.mutates??!1}]})}clearValidators(){return this.createFromProps({...this.introspect(),validators:[]})}validate(e,r){let a=this._validate(e,r);if(!a.valid&&this.#l){let i=this.resolveCatchValue(),l=this._validate(i,r);return l.valid?l:{valid:!0,object:i}}return a}async validateAsync(e,r){let a=await this._validateAsync(e,r);if(!a.valid&&this.#l){let i=this.resolveCatchValue(),l=await this._validateAsync(i,r);return l.valid?l:{valid:!0,object:i}}return a}getValidationErrorMessageSync(e,r){if(typeof e=="string")return e;if(typeof e=="function"){let a=e(r,this);if(a instanceof Promise)throw new Error("Async error message providers require validateAsync(). Use a string or sync function instead.");return a}throw new Error("Invalid error message provider must be a string or a function returning a string")}async getValidationErrorMessage(e,r){if(typeof e=="string")return e;if(typeof e=="function")return e(r,this);throw new Error("Invalid error message provider must be a string or a function returning a string or a promise of a string")}assureValidationErrorMessageProvider(e,r){return typeof e=="string"?e:typeof e=="function"?e.bind(this):typeof r=="function"?r.bind(this):r}withExtension(e,r){return this.createFromProps({...this.introspect(),extensions:{...this.#c,[e]:r}})}getExtension(e){return this.#c[e]}parse(e,r){let a=this.validate(e,r);if(!a.valid)throw new m(a.errors||[]);return a.object}async parseAsync(e,r){let a=await this.validateAsync(e,r);if(!a.valid)throw new m(a.errors||[]);return a.object}safeParse(e,r){return this.validate(e,r)}safeParseAsync(e,r){return this.validateAsync(e,r)}constructor(e){if(!(typeof e=="object"&&e))throw new Error("SchemaBuilder props must be an object");let{type:r,preprocessors:a,validators:i,isRequired:l}=e;this.type=r,typeof l=="boolean"&&(this.isRequired=l),typeof e.isNullable=="boolean"&&(this.#a=e.isNullable),typeof e.isReadonly=="boolean"&&(this.#y=e.isReadonly),Array.isArray(a)&&(this.#e=[...a]),Array.isArray(i)&&(this.#t=[...i]),this.#n=this.#e.some(c=>c.mutates)||this.#t.some(c=>c.mutates),this.#h=this.#e.length===0&&this.#t.length===0,typeof e.extensions=="object"&&e.extensions&&(this.#c={...e.extensions}),e.defaultValue!==void 0&&(this.#s=e.defaultValue),e.hasCatch&&(this.#l=!0,this.#i=e.catchValue),typeof e.description=="string"&&(this.#p=e.description),this.#o=this.assureValidationErrorMessageProvider(e.requiredValidationErrorMessageProvider,this.#f)}};export{h as a,m as b,x as c,v as d,E as e,b as f};
|
|
2
|
-
//# sourceMappingURL=chunk-CTP4RHDG.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils/transaction.ts","../src/builders/SchemaBuilder.ts"],"sourcesContent":["const TRANSACTION_SYMBOL = Symbol('transaction');\n\nconst defaultNonTransactionalTypes = [Error, RegExp, Date];\n\n/**\n * Options for customizing transaction behavior.\n */\nexport type TransactionOptions = {\n /**\n * An optional callback returning boolean. Called for every\n * nested object's property (recursively) which is not\n * null `Object`. Using this function you can define if `child`\n * should be wrapped with transaction. It is useful for\n * some cases like Error, Map, etc. when you want to preserve a link,\n * instead of creation of the new transaction.\n * By default it's filtering all instances inheriting from Error and RegExp\n * If `true` is returned from this function `child` will not be wrapped with\n * nested transaction object.\n */\n shouldNotWrapWithTransaction?: (child: any) => boolean;\n};\n\nconst defaultTransactionOptions: TransactionOptions = {\n shouldNotWrapWithTransaction: child =>\n !!defaultNonTransactionalTypes.find(t => child instanceof t)\n};\n\n/**\n * A transaction wrapper around an object. Provides copy-on-write semantics:\n * modifications to `object` are isolated from the original until `commit()` is called.\n * Use `rollback()` to discard changes, and `isDirty()` to check for pending modifications.\n */\nexport type Transaction<T> = {\n /**\n * Transaction object you can modify (equals to `initial` right after the call).\n * All changes to `object` will not be reflected to `initial` until `commit`\n * is called.\n */\n object: T;\n /**\n * Commits transaction, all changes to `object` will be reflected to `initial`\n * after the call of this function.\n */\n commit: () => T;\n /**\n * Rollbacks transaction moving it to the initial state (`object` will be equal to `initial`\n * after the call of this function).\n */\n rollback: () => T;\n /**\n * Returns `true` if there are any changes to `object` which make it different from `initial`.\n */\n isDirty: () => boolean;\n};\n\n/**\n * Starts a transaction over the `initial` object. The returned `object` is a\n * proxy (for plain objects) or a shallow copy (for arrays) that tracks mutations\n * without modifying `initial`. Call `commit()` to apply or `rollback()` to discard changes.\n *\n * @param initial - the object or array to wrap in a transaction\n * @param options - optional configuration to control which nested values are wrapped\n * @returns a {@link Transaction} with `object`, `commit`, `rollback`, and `isDirty` members\n */\nexport const transaction = <T extends {}>(\n initial: T,\n options?: TransactionOptions\n): Transaction<T> => {\n let newProperties: Record<string | symbol, any> = {};\n let deletedProperties = new Map<keyof T, true>();\n\n options = Object.assign({}, defaultTransactionOptions, options || {});\n\n const { shouldNotWrapWithTransaction } =\n options as Required<TransactionOptions>;\n\n const isDirty = () =>\n !!Object.keys(newProperties).find(key => {\n if (newProperties[key]?.[TRANSACTION_SYMBOL]) {\n return newProperties[key][TRANSACTION_SYMBOL].isDirty();\n }\n return true;\n }) || ((deletedProperties.size > 0) as any);\n\n const commit = () => {\n const result = {} as Record<string, any>;\n Object.keys(initial).forEach(key => {\n result[key] = (initial as any)[key];\n });\n\n Object.keys(newProperties).forEach(key => {\n const value = newProperties[key];\n if (value[TRANSACTION_SYMBOL]) {\n const { commit: childCommit } = value[TRANSACTION_SYMBOL];\n result[key] = childCommit();\n } else {\n result[key] = newProperties[key];\n }\n });\n\n for (const key of deletedProperties.keys()) {\n delete result[key as string];\n }\n\n newProperties = {};\n deletedProperties = new Map<keyof T, true>();\n\n return result as T;\n };\n\n const rollback = () => {\n for (const key in newProperties) {\n const value = newProperties[key];\n if (\n value &&\n typeof value === 'object' &&\n value[TRANSACTION_SYMBOL]\n ) {\n // this is nested transaction, let's rollback it as well\n value[TRANSACTION_SYMBOL].rollback();\n }\n }\n newProperties = {};\n deletedProperties = new Map<keyof T, true>();\n return initial;\n };\n\n if (Array.isArray(initial)) {\n const result = initial.map(el =>\n typeof el === 'object' && el && !shouldNotWrapWithTransaction(el)\n ? transaction(el).object\n : el\n );\n const commitArray = () =>\n result.map(el =>\n el && typeof el[TRANSACTION_SYMBOL] === 'object'\n ? el[TRANSACTION_SYMBOL].commit()\n : el\n );\n\n const isDirtyArray = () => {\n return !!result.find((val, index) => {\n if (val && typeof val[TRANSACTION_SYMBOL] === 'object') {\n return val[TRANSACTION_SYMBOL].isDirty();\n }\n return result[index] !== initial[index];\n });\n };\n Object.defineProperty(result, TRANSACTION_SYMBOL, {\n writable: false,\n configurable: false,\n value: {\n initial,\n object: result,\n commit: commitArray as any,\n rollback: () => initial,\n isDirty: isDirtyArray\n }\n });\n return {\n object: result as any,\n commit: commitArray as any,\n rollback: () => initial,\n isDirty: isDirtyArray\n };\n }\n\n const proxy = new Proxy<T>(initial, {\n set: (target, property, value) => {\n if (target && (target as any)[property] === value) {\n delete newProperties[property];\n return true;\n }\n newProperties[property] = value;\n deletedProperties.delete(property as any);\n return true;\n },\n ownKeys: target => {\n return [\n ...Object.keys(target).filter(\n (k: any) => !deletedProperties.has(k)\n ),\n ...Object.keys(newProperties).filter((k: any) => !(k in target))\n ];\n },\n getOwnPropertyDescriptor: (target, prop: any) => {\n if (deletedProperties.has(prop)) {\n return undefined;\n }\n\n if (prop in newProperties) {\n return Object.getOwnPropertyDescriptor(newProperties, prop);\n }\n\n return Object.getOwnPropertyDescriptor(target, prop);\n },\n has: (target, prop: any) => {\n if (deletedProperties.has(prop)) {\n return false;\n }\n\n if (prop in newProperties) {\n return true;\n }\n\n return prop in target;\n },\n get: (target, prop) => {\n if (typeof prop === 'symbol') {\n if (prop === TRANSACTION_SYMBOL) {\n return {\n initial,\n object: proxy,\n commit,\n rollback,\n isDirty\n };\n }\n return (target as any)[prop];\n }\n\n if (prop in newProperties) {\n return newProperties[prop];\n }\n\n if (deletedProperties.has(prop as any)) {\n return undefined;\n }\n\n if (\n !isTransaction((target as any)[prop]) &&\n typeof (target as any)[prop] === 'object' &&\n (target as any)[prop] &&\n !shouldNotWrapWithTransaction((target as any)[prop])\n ) {\n const { object } = transaction((target as any)[prop], options);\n newProperties[prop] = object;\n return object;\n }\n\n return (target as any)[prop];\n },\n deleteProperty: (target, p) => {\n if (p in newProperties) {\n if (\n newProperties[p] &&\n typeof newProperties[p][TRANSACTION_SYMBOL] === 'object'\n ) {\n newProperties[p][TRANSACTION_SYMBOL].rollback();\n }\n delete newProperties[p];\n }\n if (p in target) {\n deletedProperties.set(p as any, true);\n }\n return true;\n }\n });\n\n return {\n object: proxy,\n commit,\n rollback,\n isDirty\n };\n};\n\n/**\n * Creates a lightweight no-op transaction that wraps the `initial` value\n * without any Proxy or copy-on-write overhead. `commit()` and `rollback()`\n * simply return the original object, and `isDirty()` is always `false`.\n *\n * Use this when no preprocessors or validators are defined — there is no\n * risk of mutation, so the full transaction machinery can be skipped.\n */\nexport const noopTransaction = <T extends {}>(initial: T): Transaction<T> => ({\n object: initial,\n commit: () => initial,\n rollback: () => initial,\n isDirty: () => false\n});\n\n/**\n * Checks if `obj` is an instance of a transaction.\n * @param obj object to check if it's a transaction\n * @returns `true` if `obj` is a transaction, `false` otherwise\n */\nexport const isTransaction = (obj: any) =>\n obj && typeof obj === 'object' && Object.hasOwn(obj, TRANSACTION_SYMBOL);\n","import type { StandardSchemaV1 } from '@standard-schema/spec';\nimport {\n noopTransaction,\n type Transaction,\n transaction\n} from '../utils/transaction.js';\nimport type { ArraySchemaBuilder } from './ArraySchemaBuilder.js';\nimport type { ExternSchemaBuilder } from './ExternSchemaBuilder.js';\nimport type { ObjectSchemaBuilder } from './ObjectSchemaBuilder.js';\n\n/** @internal Symbol used as the key for the type brand on schema builders. */\ndeclare const __type: unique symbol;\n/** @internal */\nexport type SchemaTypeBrand = typeof __type;\n\n/** @internal Symbol used as the key for the default-value brand on schema builders. */\ndeclare const __hasDefault: unique symbol;\n/** @internal */\nexport type HasDefaultBrand = typeof __hasDefault;\n\n/** Symbol used as the key for branded/opaque types. */\ndeclare const __brand: unique symbol;\n/** Symbol used as the key for branded/opaque types. */\nexport type BRAND = typeof __brand;\n\n/**\n * Intersects a base type with a phantom brand tag.\n * The brand exists only at the type level — zero runtime cost.\n *\n * @example\n * ```ts\n * type Email = Brand<string, 'Email'>;\n * type UserId = Brand<number, 'UserId'>;\n * ```\n */\nexport type Brand<T, TBrand extends string | symbol> = T & {\n readonly [K in BRAND]: TBrand;\n};\n\n/**\n * Infers the TypeScript type that a `SchemaBuilder` instance validates.\n * Takes into account type optimizations (via `optimize()`) and whether the schema is optional.\n *\n * @example\n * ```ts\n * const userSchema = object({ name: string(), age: number().optional() });\n * type User = InferType<typeof userSchema>;\n * // { name: string; age?: number }\n * ```\n */\nexport type InferType<T> = T extends {\n optimize: (...args: any[]) => {\n readonly [K in SchemaTypeBrand]: infer TOptimized;\n };\n}\n ? TOptimized\n : T extends { readonly [K in SchemaTypeBrand]: infer TType }\n ? TType\n : T;\n\n/**\n * Represents a single validation error with a human-readable error message.\n */\nexport type ValidationError = { message: string };\n\n/**\n * Used to represent a validation result for nested\n * objects/properties. Contains a list of errors and\n * the value that caused them.\n */\nexport type NestedValidationResult<\n TSchema,\n TRootSchema extends ObjectSchemaBuilder<any, any, any, any, any>,\n TParentPropertyDescriptor\n> = {\n /**\n * Value that property had and which caused error or errors\n */\n seenValue?: InferType<TSchema>;\n /**\n * A list of errors, empty if object satisfies a schema\n */\n errors: ReadonlyArray<string>;\n\n /**\n * Whether validation passed for this property and all of its children.\n */\n isValid: boolean;\n\n get descriptor(): PropertyDescriptorInner<\n TRootSchema,\n TSchema,\n TParentPropertyDescriptor\n >;\n};\n\n/**\n * Utility type that makes a value `T` optional (i.e. `T | undefined`).\n * Used internally by {@link InferType} to represent optional schema fields.\n */\nexport type MakeOptional<T> = { prop?: T }['prop'];\n\n/**\n * Type of the function that provides a validation error message for\n * the given `seenValue` and `schema`. Can be a string or a function\n * returning a string or a promise of a string.\n * Should be used to provide a custom validation error message.\n */\nexport type ValidationErrorMessageProvider<\n TSchema extends SchemaBuilder<any, any, any, any, any> = SchemaBuilder<\n any,\n any,\n any,\n any,\n any\n >\n> =\n | string\n | ((\n seenValue: InferType<TSchema>,\n schema: TSchema\n ) => string | Promise<string>);\n\nexport type ValidationResult<T> = {\n /**\n * If `true` - object satisfies schema\n */\n valid: boolean;\n /**\n * Contains validated object. Can be different (if there are any preprocessors in the schema) from object\n * passed to the `validate` method of the `SchemaBuilder` class.\n */\n object?: T;\n errors?: ValidationError[];\n};\n\n/**\n * Error thrown by {@link SchemaBuilder.parse | parse()} and\n * {@link SchemaBuilder.parseAsync | parseAsync()} when validation fails.\n * Carries the full array of {@link ValidationError | validation errors}.\n */\nexport class SchemaValidationError extends Error {\n public readonly errors: ValidationError[];\n\n constructor(errors: ValidationError[]) {\n const message =\n errors.length > 0\n ? errors.map(e => e.message).join('; ')\n : 'Validation failed';\n super(message);\n this.name = 'SchemaValidationError';\n this.errors = errors;\n }\n}\n\n/**\n * Internal result returned by the `preValidate` step of `SchemaBuilder`.\n * Contains the validation context, any early errors, and the transaction\n * wrapping the (possibly preprocessed) value.\n */\nexport type PreValidationResult<T, TTransactionType> = Omit<\n ValidationResult<T>,\n 'object'\n> & {\n context: ValidationContext;\n transaction?: Transaction<TTransactionType>;\n rootPropertyDescriptor?: PropertyDescriptor<any, any, undefined>;\n};\n\ntype ValidatorResult<T> = Omit<ValidationResult<T>, 'object' | 'errors'> & {\n errors?: ValidationError[];\n};\n\n/**\n * A function that transforms the value before validation.\n * Preprocessors run in order before validators and can modify or replace the value.\n *\n * @param object - the current value to preprocess\n * @returns the transformed value, or a Promise resolving to it\n */\nexport type Preprocessor<T> = (object: T) => Promise<T> | T;\n\n/**\n * A custom validation function that checks a value and returns a result\n * indicating whether the value is valid, along with optional error messages.\n *\n * @param object - the value to validate\n * @returns a result with `valid` boolean and optional `errors` array, or a Promise resolving to it\n */\nexport type Validator<T> = (\n object: T\n) => Promise<ValidatorResult<T>> | ValidatorResult<T>;\n\n/**\n * Internal wrapper that pairs a preprocessor function with metadata\n * indicating whether it may mutate the value.\n */\nexport type PreprocessorEntry<T> = { fn: Preprocessor<T>; mutates: boolean };\n\n/**\n * Internal wrapper that pairs a validator function with metadata\n * indicating whether it may mutate the value.\n */\nexport type ValidatorEntry<T> = { fn: Validator<T>; mutates: boolean };\n\n/**\n * Configuration properties used to construct a `SchemaBuilder` instance.\n * Contains the schema type identifier, requirement flag, and lists of\n * preprocessors and validators.\n */\nexport type SchemaBuilderProps<T> = {\n type: string;\n isRequired?: boolean;\n isNullable?: boolean;\n isReadonly?: boolean;\n preprocessors: PreprocessorEntry<T>[];\n validators: ValidatorEntry<T>[];\n requiredValidationErrorMessageProvider?: ValidationErrorMessageProvider;\n extensions?: Record<string, unknown>;\n defaultValue?: T | (() => T);\n catchValue?: T | (() => T);\n hasCatch?: boolean;\n description?: string;\n};\n\nexport type ValidationContext<\n TSchema extends SchemaBuilder<any, any, any, any> = SchemaBuilder<\n any,\n any,\n any,\n any\n >\n> = {\n /**\n * Optional. By default validation will stop after the first validation error, in case if\n * you want to receive all validation erors, please set this flag to `true`.\n * You might need it to display validation errors.\n */\n doNotStopOnFirstError?: boolean;\n\n /**\n * Optional. If you define a `rootPropertyDescriptor` while validating an object,\n * it will report all validation errors with the path starting from the root property.\n * Normally it's used internally by the library for validation of nested objects and\n * should not be used directly (but who knows, maybe you will find a use case for it).\n */\n rootPropertyDescriptor?: TSchema extends ObjectSchemaBuilder<\n any,\n any,\n any,\n any\n >\n ? PropertyDescriptor<TSchema, TSchema, undefined>\n : never;\n\n /**\n * Optional. This is a property descriptor for the current object being validated.\n * This descriptor is descendant of the `rootPropertyDescriptor` and is used to provide\n * a path to the current object being validated in the root object.\n * Normally it's used internally by the library for validation of nested objects and\n * should not be used directly (but who knows, maybe you will find a use case for it).\n */\n currentPropertyDescriptor?: TSchema extends ObjectSchemaBuilder<\n any,\n any,\n any\n >\n ? PropertyDescriptor<TSchema, TSchema, unknown>\n : never;\n\n /**\n * Optional. Used along with `rootPropertyDescriptor` and `currentPropertyDescriptor` to provide\n * a root validation object, this object will be used to retrieve the value of properties\n * using the `rootPropertyDescriptor` because the `rootPropertyDescriptor` is a property descriptor\n * for the root object, and it needs the root object along with the whole structure to get the\n * value of the property.\n *\n * Normally it's used internally by the library for validation of nested objects and\n * should not be used directly (but who knows, maybe you will find a use case for it).\n */\n rootValidationObject?: InferType<TSchema>;\n};\n\n/**\n * A symbol to mark property descriptors in the schema.\n * Normally, you should not use it directly unless you want\n * to develop some advanced features or extend the library.\n * In normal conditions it's used internally by the library.\n */\nexport const SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR = Symbol();\n\n/**\n * A symbol that marks a schema as having sub-properties that can\n * participate in property descriptor trees. When a schema exposes\n * `[SYMBOL_HAS_PROPERTIES] = true` **and** its `introspect()` returns\n * a `properties` record, it will be recursed into by\n * `ObjectSchemaBuilder.getPropertiesFor()` — the same way nested\n * `ObjectSchemaBuilder` instances are.\n *\n * Currently implemented by `ObjectSchemaBuilder` (always) and\n * `ExternSchemaBuilder` (when created with an explicit property map).\n */\nexport const SYMBOL_HAS_PROPERTIES = Symbol();\n\n/**\n * Describes a property in a schema. And gives you\n * a possibility to access property value and set it.\n * suppose you have a schema like this:\n * ```ts\n * const schema = object({\n * name: string(),\n * address: object({\n * city: string(),\n * country: string()\n * }),\n * id: number()\n * });\n * ```\n * then you can get a property descriptor for the `address.city` property\n * like this:\n * ```ts\n * const addressCityDescriptor = object.getPropertiesFor(schema).address.city;\n * ```\n *\n * And then you can use it to get and set the value of this property having the object:\n * ```ts\n * const obj = {\n * name: 'Leo',\n * address: {\n * city: 'Kozelsk',\n * country: 'Russia'\n * },\n * id: 123\n * };\n *\n * const success = addressCityDescriptor.setValue(obj, 'Venyov');\n * // this returns you a boolean value indicating if the value was set successfully\n * ```\n */\n\nexport type PropertySetterOptions = {\n /**\n * If set to `true`, the method will create missing structure\n * in the object to set the value. For example, if you have a schema\n * and property descriptor like this:\n * ```ts\n * const schema = object({\n * address: object({\n * city: string(),\n * country: string()\n * }),\n * });\n * const addressCityDescriptor = object.getPropertiesFor(schema).address.city;\n * ```\n * And then you try to set a new value to the `address.city` property on the object\n * which does not have `address` property:\n * ```ts\n * const obj = {\n * name: 'Leo'\n * };\n * const success = addressCityDescriptor.setValue(obj, 'Venyov', { createMissingStructure: true });\n * // success === true\n * // obj === {\n * // name: 'Leo',\n * // address: {\n * // city: 'Venyov'\n * // }\n * // }\n */\n createMissingStructure?: boolean;\n};\n\n/**\n * Extracts the inner property descriptor type from a `PropertyDescriptor`.\n * Returns `undefined` if `T` is not a valid `PropertyDescriptor`.\n */\nexport type PropertyDescriptorInnerFromPropertyDescriptor<T> =\n T extends PropertyDescriptor<\n infer TSchema,\n infer TPropertySchema,\n infer TParentPropertyDescriptor\n >\n ? PropertyDescriptorInner<\n TSchema,\n TPropertySchema,\n TParentPropertyDescriptor\n >\n : undefined;\n\nexport type PropertyDescriptorInner<\n TSchema extends ObjectSchemaBuilder<any, any, any, any, any>,\n TPropertySchema,\n TParentPropertyDescriptor\n> = {\n /**\n * Sets a new value to the property. If the process was successful,\n * the method returns `true`, otherwise `false`.\n * It can return `false` if the property could not be set to the object\n * which can happen if the `setValue` method is called with an object\n * which does not comply with the schema.\n * for example, if you have a schema and property descriptopr like this:\n * ```ts\n * const schema = object({\n * name: string(),\n * address: object({\n * city: string(),\n * country: string()\n * }),\n * id: number()\n * });\n *\n * const addressCityDescriptor = object.getPropertiesFor(schema).address.city;\n * ```\n * And then you try to set a new value to the `address.city` property on the object\n * which does not have `address` property:\n * ```ts\n * const obj = {\n * name: 'Leo'\n * };\n *\n * const success = addressCityDescriptor.setValue(obj, 'Venyov');\n * // success === false\n * ```\n *\n * @param obj Object to set the value to\n * @param value a new value to set to the property\n * @param options additional optional parameters to control the process\n * @returns\n */\n setValue: (\n obj: InferType<TSchema>,\n value: InferType<TPropertySchema>,\n options?: PropertySetterOptions\n ) => boolean;\n /**\n * Gets the value of the property from the object.\n * @param obj object to get the value from\n * @returns an object containing a `value` and `success` properties. `value` is the value of the property\n * if it was found in the object, `success` is a boolean value indicating if the property was found in the object.\n */\n getValue: (obj: InferType<TSchema>) => {\n value?: InferType<TPropertySchema>;\n success: boolean;\n };\n\n /**\n * Gets the schema for the property described by the property descriptor.\n * @returns a schema for the property\n */\n getSchema: () => TPropertySchema;\n\n parent: PropertyDescriptorInnerFromPropertyDescriptor<TParentPropertyDescriptor>;\n // extends PropertyDescriptor<\n // any,\n // any,\n // any\n // >\n // ? TParentPropertyDescriptor\n // : never;\n};\n\n/**\n * A wrapper object keyed by {@link SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR} that\n * holds a {@link PropertyDescriptorInner} for a particular property within\n * an object schema. Used to get/set property values on validated objects.\n */\nexport type PropertyDescriptor<\n TRootSchema extends ObjectSchemaBuilder<any, any, any, any, any>,\n TPropertySchema,\n TParentPropertyDescriptor\n> = {\n [SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR]: PropertyDescriptorInner<\n TRootSchema,\n TPropertySchema,\n TParentPropertyDescriptor\n >;\n};\n\n/**\n * A tree of property descriptors for the schema.\n * Has a possibility to filter properties by the type (`TAssignableTo` type parameter).\n */\nexport type PropertyDescriptorTree<\n TSchema extends ObjectSchemaBuilder<any, any, any, any, any>,\n TRootSchema extends ObjectSchemaBuilder<any, any, any, any, any> = TSchema,\n TAssignableTo = any,\n TParentPropertyDescriptor = undefined\n> = PropertyDescriptor<TRootSchema, TSchema, TParentPropertyDescriptor> &\n (TSchema extends ObjectSchemaBuilder<infer TProperties, any, any>\n ? {\n [K in keyof TProperties]: TProperties[K] extends ObjectSchemaBuilder<\n any,\n any,\n any\n >\n ? PropertyDescriptorTree<\n TProperties[K],\n TRootSchema,\n any,\n PropertyDescriptor<\n TRootSchema,\n TSchema,\n TParentPropertyDescriptor\n >\n >\n : TProperties[K] extends ExternSchemaBuilder<\n any,\n any,\n any,\n any,\n any,\n any,\n infer TExternResult\n >\n ? PropertyDescriptor<\n TRootSchema,\n TProperties[K],\n PropertyDescriptor<\n TRootSchema,\n TSchema,\n TParentPropertyDescriptor\n >\n > &\n ExternOutputPropertyDescriptors<\n TExternResult,\n TRootSchema,\n PropertyDescriptor<\n TRootSchema,\n TProperties[K],\n PropertyDescriptor<\n TRootSchema,\n TSchema,\n TParentPropertyDescriptor\n >\n >\n >\n : TProperties[K] extends ArraySchemaBuilder<\n infer TArrayElement,\n any,\n any\n >\n ? TArrayElement extends ObjectSchemaBuilder<\n any,\n any,\n any,\n any,\n any\n >\n ? PropertyDescriptor<\n TRootSchema,\n TProperties[K],\n PropertyDescriptor<\n TRootSchema,\n TSchema,\n TParentPropertyDescriptor\n >\n >\n : InferType<TProperties[K]> extends TAssignableTo\n ? PropertyDescriptor<\n TRootSchema,\n TProperties[K],\n PropertyDescriptor<\n TRootSchema,\n TSchema,\n TParentPropertyDescriptor\n >\n >\n : never\n : InferType<TProperties[K]> extends TAssignableTo\n ? PropertyDescriptor<\n TRootSchema,\n TProperties[K],\n PropertyDescriptor<\n TRootSchema,\n TSchema,\n TParentPropertyDescriptor\n >\n >\n : never;\n }\n : never);\n\n/**\n * Recursively maps the keys of an extern schema's output type into\n * property descriptors. When a value is a plain-object type its keys\n * are expanded recursively; primitives, arrays, Dates, and functions\n * are treated as leaves.\n *\n * @internal\n */\ntype ExternOutputPropertyDescriptors<\n TOutput,\n TRootSchema extends ObjectSchemaBuilder<any, any, any, any, any>,\n TParentPropertyDescriptor\n> = TOutput extends\n | Date\n | Function\n | readonly any[]\n | string\n | number\n | boolean\n | symbol\n | bigint\n | null\n | undefined\n ? {}\n : TOutput extends Record<string, any>\n ? {\n [K in keyof TOutput]: PropertyDescriptor<\n TRootSchema,\n SchemaBuilder<TOutput[K], true, false, false, {}>,\n TParentPropertyDescriptor\n > &\n ExternOutputPropertyDescriptors<\n TOutput[K],\n TRootSchema,\n PropertyDescriptor<\n TRootSchema,\n SchemaBuilder<TOutput[K], true, false, false, {}>,\n TParentPropertyDescriptor\n >\n >;\n }\n : {};\n\n/**\n * Creates an array augmented with non-enumerable NestedValidationResult\n * properties (`seenValue`, `errors`, `isValid`, `descriptor`).\n * Used by UnionSchemaBuilder and ArraySchemaBuilder to return hybrid\n * arrays from `getErrorsFor()`.\n */\nexport function createHybridErrorArray<T extends any[]>(\n items: T,\n seenValue: () => any,\n errors: () => ReadonlyArray<string>,\n descriptor: () => any\n): T {\n Object.defineProperties(items, {\n seenValue: {\n get: seenValue,\n enumerable: false\n },\n errors: {\n get: errors,\n enumerable: false\n },\n isValid: {\n get: () => errors().length === 0,\n enumerable: false\n },\n descriptor: {\n get: descriptor,\n enumerable: false\n }\n });\n return items;\n}\n\n/**\n * Resolves the full output type of a schema, accounting for `TRequired` and\n * `TNullable` modifiers. Mirrors the branded `[__type]` computation so that\n * the `~standard` Standard Schema property carries the correct inferred type.\n *\n * - When `TRequired = true` and `TNullable = false` the result is `TResult`.\n * - When `TRequired = true` and `TNullable = true` the result is `TResult | null`.\n * - When `TRequired = false` the result is wrapped by {@link MakeOptional},\n * adding `| undefined` (and `| null` when also nullable).\n *\n * @internal\n */\ntype ResolvedSchemaType<\n TResult,\n TRequired extends boolean,\n TNullable extends boolean\n> = TRequired extends true\n ? TNullable extends true\n ? TResult | null\n : TResult\n : MakeOptional<TNullable extends true ? TResult | null : TResult>;\n\n/**\n * Base class for all schema builders. Provides basic functionality for schema building.\n *\n * **Note:** this class is not intended to be used directly, use one of the subclasses instead.\n * @typeparam TResult Type of the object that will be returned by `validate()` method.\n * @typeparam TRequired If `true`, object will be required. If `false`, object will be optional.\n */\nexport abstract class SchemaBuilder<\n TResult = any,\n TRequired extends boolean = true,\n TNullable extends boolean = false,\n THasDefault extends boolean = false,\n // biome-ignore lint/correctness/noUnusedVariables: used in extensions\n TExtensions = {}\n> {\n #isRequired = true;\n #isNullable = false;\n #isReadonly = false;\n #description: string | undefined;\n #preprocessors: PreprocessorEntry<TResult>[] = [];\n #validators: ValidatorEntry<TResult>[] = [];\n #hasMutating = false;\n #canSkipPreValidation = true;\n #extensions: Record<string, unknown> = {};\n #type = 'base';\n #defaultRequiredErrorMessageProvider: ValidationErrorMessageProvider =\n 'is required';\n #requiredErrorMessageProvider: ValidationErrorMessageProvider =\n 'is required';\n #defaultValue: TResult | (() => TResult) | undefined = undefined;\n #catchValue: TResult | (() => TResult) | undefined = undefined;\n #hasCatch = false;\n /**\n * Cached result of the first `['~standard']` access. Stored so that\n * repeated property reads return the exact same object reference, which\n * is required by the Standard Schema spec.\n */\n #standardProps:\n | StandardSchemaV1.Props<\n ResolvedSchemaType<TResult, TRequired, TNullable>\n >\n | undefined;\n\n /**\n * Type-level brand encoding the inferred type of this schema.\n * Not emitted at runtime — used only by {@link InferType}.\n * @internal\n */\n declare readonly [__type]: TRequired extends true\n ? TNullable extends true\n ? TResult | null\n : TResult\n : MakeOptional<TNullable extends true ? TResult | null : TResult>;\n\n /**\n * Type-level brand encoding whether this schema has a default value.\n * Not emitted at runtime — used by input type inference.\n * @internal\n */\n declare readonly [__hasDefault]: THasDefault;\n\n /**\n * Standard Schema v1 interface.\n *\n * Exposes this schema as a [Standard Schema v1](https://standardschema.dev/)\n * validator, enabling out-of-the-box interoperability with any library that\n * consumes the spec — including tRPC, TanStack Form, React Hook Form, T3 Env,\n * Hono, Elysia, next-safe-action, and 50+ other tools.\n *\n * Every `SchemaBuilder` subclass (all 13 builders) inherits this property\n * automatically — no additional setup required.\n *\n * **Shape of the returned object:**\n * - `version` — always `1` (Standard Schema spec version)\n * - `vendor` — `'@cleverbrush/schema'`\n * - `validate(value)` — synchronous; wraps this builder's own `.validate()`\n * and converts its result to the Standard Schema `Result<Output>` format:\n * - Success: `{ value: <validated output> }`\n * - Failure: `{ issues: [{ message: string }, …] }`\n *\n * The returned object is **cached** after the first access so repeated reads\n * return the same reference (required by the spec).\n *\n * @example\n * ```ts\n * import { object, string, number } from '@cleverbrush/schema';\n *\n * const UserSchema = object({\n * name: string().minLength(2),\n * email: string().email(),\n * age: number().min(18).optional(),\n * });\n *\n * // Grab the Standard Schema interface\n * const std = UserSchema['~standard'];\n * // std.version === 1\n * // std.vendor === '@cleverbrush/schema'\n *\n * const ok = std.validate({ name: 'Alice', email: 'alice@example.com' });\n * // { value: { name: 'Alice', email: 'alice@example.com', age: undefined } }\n *\n * const fail = std.validate({ name: 'A', email: 'not-an-email' });\n * // { issues: [{ message: 'minLength' }, { message: 'email' }] }\n *\n * // Pass directly to TanStack Form, T3 Env, tRPC, etc.:\n * // validators: { onChange: UserSchema, onBlur: UserSchema }\n * ```\n *\n * @see https://standardschema.dev/\n */\n get ['~standard'](): StandardSchemaV1.Props<\n ResolvedSchemaType<TResult, TRequired, TNullable>\n > {\n if (this.#standardProps) return this.#standardProps;\n // Capture `this` for the closure so the validate callback can call\n // the schema's own validate method.\n const self = this;\n this.#standardProps = {\n version: 1 as const,\n vendor: '@cleverbrush/schema',\n validate(\n value: unknown\n ): StandardSchemaV1.Result<\n ResolvedSchemaType<TResult, TRequired, TNullable>\n > {\n // Standard Schema validate accepts `unknown`, while the\n // schema's own validate() has a typed parameter. The cast\n // is safe because validate() performs full runtime\n // validation regardless of the compile-time input type.\n const result = self.validate(value as any);\n if (result.valid) {\n return {\n value: result.object as ResolvedSchemaType<\n TResult,\n TRequired,\n TNullable\n >\n };\n }\n return {\n issues: (result.errors ?? []).map(e => ({\n message: e.message\n }))\n };\n }\n };\n return this.#standardProps;\n }\n\n /**\n * Set type of schema explicitly. `notUsed` param is needed only for case when JS is used. E.g. when you\n * can't call method like `schema.hasType<Date>()`, so instead you can call `schema.hasType(new Date())`\n * with the same result.\n */\n public abstract hasType<T>(notUsed?: T): any;\n\n /**\n * Clears type set by call to `.hasType<T>()`, default schema type inference will be used\n * for schema returned by this call.\n */\n public abstract clearHasType(): any;\n\n /**\n * Protected method used to create a new instance of the Builder\n * defined by the `props` object. Should be used to instantiate new\n * builders to keep builder's immutability.\n * @param props arbitrary props object\n */\n protected abstract createFromProps(props: any): this;\n\n /**\n * The string identifier of the schema type (e.g. `'string'`, `'number'`, `'object'`).\n */\n protected get type() {\n return this.#type;\n }\n\n /**\n * Sets the schema type identifier. Must be a non-empty string.\n */\n protected set type(value: string) {\n if (typeof value !== 'string' || !value)\n throw new Error('value should be non empty string');\n this.#type = value;\n }\n\n /**\n * A list of preprocessors associated with\n * the Builder\n */\n protected get preprocessors() {\n return this.#preprocessors;\n }\n\n /**\n * A list of validators associated with\n * the Builder\n */\n protected get validators() {\n return this.#validators;\n }\n\n /**\n * Whether the schema requires a non-null/non-undefined value.\n */\n protected get isRequired(): TRequired {\n return this.#isRequired as TRequired;\n }\n\n /**\n * Whether `null` is an accepted value for this schema.\n */\n protected get isNullable(): boolean {\n return this.#isNullable;\n }\n\n /**\n * Sets the requirement flag. Must be a boolean.\n */\n protected set isRequired(value: boolean) {\n if (typeof value !== 'boolean')\n throw new Error('should be a boolean value');\n this.#isRequired = value as any;\n }\n\n /**\n * The error message provider used for the \"is required\" error.\n * Exposed for fast-path validation in subclasses.\n */\n protected get requiredErrorMessage(): ValidationErrorMessageProvider {\n return this.#requiredErrorMessageProvider;\n }\n\n /**\n * Whether this schema has a default value configured via `.default()`.\n * Exposed for fast-path validation in subclasses.\n */\n protected get hasDefault(): boolean {\n return this.#defaultValue !== undefined;\n }\n\n /**\n * Whether this schema has a catch/fallback value configured via `.catch()`.\n */\n protected get hasCatch(): boolean {\n return this.#hasCatch;\n }\n\n /**\n * Resolves the catch/fallback value. If the stored value is a factory function,\n * it is called to produce the value (useful for mutable fallbacks like `() => []`).\n */\n protected resolveCatchValue(): TResult {\n return typeof this.#catchValue === 'function'\n ? (this.#catchValue as () => TResult)()\n : (this.#catchValue as TResult);\n }\n\n /**\n * Whether this schema is marked as readonly.\n * Type-level only — no runtime enforcement.\n */\n protected get isReadonly(): boolean {\n return this.#isReadonly;\n }\n\n /**\n * Resolves the default value. If the stored default is a function,\n * it is called to produce the value (useful for mutable defaults).\n */\n protected resolveDefaultValue(): TResult {\n return typeof this.#defaultValue === 'function'\n ? (this.#defaultValue as () => TResult)()\n : (this.#defaultValue as TResult);\n }\n\n /**\n * Whether `preValidateSync` can be skipped entirely.\n * True when there are no preprocessors and no validators,\n * so the only work would be the required check and wrapping\n * in a noop transaction — which subclasses can do inline.\n */\n protected get canSkipPreValidation(): boolean {\n return this.#canSkipPreValidation;\n }\n\n /**\n * Whether `null` should count as a required-constraint violation.\n *\n * By default `null` is treated the same as `undefined` for the purposes\n * of the required check — i.e. a required schema rejects both.\n * Subclasses that may legally receive `null` as a value (e.g.\n * `UnionSchemaBuilder` when a `NullSchemaBuilder` option is present)\n * can override this to `false` so that `null` bypasses the required\n * check and is passed directly to their option-validation logic.\n *\n * @protected\n */\n protected get isNullRequiredViolation(): boolean {\n return true;\n }\n\n /**\n * Shared setup for both {@link preValidateSync} and {@link preValidateAsync}.\n * Builds the validation context, creates the initial transaction, and\n * returns mutable state for the caller to drive.\n */\n #initPreValidation(object: any, context?: ValidationContext) {\n const doNotStopOnFirstError = context?.doNotStopOnFirstError ?? false;\n\n const resultingContext: ValidationContext = {\n doNotStopOnFirstError,\n rootPropertyDescriptor: context?.rootPropertyDescriptor,\n currentPropertyDescriptor: context?.currentPropertyDescriptor\n };\n\n const needsTransaction = this.#hasMutating;\n\n return {\n doNotStopOnFirstError,\n resultingContext,\n transaction: needsTransaction\n ? transaction({ validatedObject: object })\n : noopTransaction({ validatedObject: object }),\n errors: [] as ValidationError[]\n };\n }\n\n /**\n * Builds the failed early-return result used when\n * `doNotStopOnFirstError` is false.\n */\n #earlyFailResult(\n errors: ValidationError[],\n resultingContext: ValidationContext\n ): PreValidationResult<any, { validatedObject: any }> {\n return {\n valid: false,\n errors: [errors[0]].filter(e => e),\n context: resultingContext\n };\n }\n\n /**\n * Builds the error entries for a validator that reported `valid: false`.\n */\n #validatorFailureErrors(\n index: number,\n name: string | undefined,\n validatorErrors: ValidationError[] | undefined\n ): ValidationError[] {\n if (Array.isArray(validatorErrors) && validatorErrors.length) {\n return validatorErrors;\n }\n return [\n {\n message: `Validator #${index}${\n name ? ` (${name})` : ''\n } didn't pass.`\n }\n ];\n }\n\n /**\n * Assembles the final {@link PreValidationResult} after all preprocessors,\n * validators, and the required check have run.\n */\n #buildPreValidationResult(\n errors: ValidationError[],\n doNotStopOnFirstError: boolean,\n resultingContext: ValidationContext,\n trans: Transaction<{ validatedObject: any }>\n ): PreValidationResult<any, { validatedObject: any }> {\n if (errors.length > 0) {\n return {\n valid: false,\n errors: errors\n .filter(e => e)\n .filter((_e, i) =>\n doNotStopOnFirstError ? true : i === 0\n ),\n context: resultingContext,\n transaction: trans\n };\n }\n\n return {\n valid: true,\n context: resultingContext,\n transaction: trans\n };\n }\n\n /**\n * Synchronous version of {@link preValidateAsync}.\n * Throws at runtime if any preprocessor or validator returns a Promise.\n *\n * @param object - the value to pre-validate\n * @param context - optional validation context settings\n * @returns a `PreValidationResult` containing the preprocessed transaction, context, and any errors\n * @throws Error if a preprocessor or validator returns a Promise (use {@link preValidateAsync} instead)\n */\n protected preValidateSync(\n object: any,\n context?: ValidationContext\n ): PreValidationResult<any, { validatedObject: any }> {\n const state = this.#initPreValidation(object, context);\n const { doNotStopOnFirstError, resultingContext, errors } = state;\n let preprocessingTransaction = state.transaction;\n let preprocessedObject =\n preprocessingTransaction.object.validatedObject;\n\n if (this.#preprocessors.length > 0) {\n let currentPrepropIndex = 0;\n for (const entry of this.#preprocessors) {\n try {\n const result = entry.fn(preprocessedObject);\n if (result instanceof Promise) {\n throw new Error(\n `Preprocessor #${currentPrepropIndex}${entry.fn.name ? ` (${entry.fn.name})` : ''} returned a Promise. Use validateAsync() for schemas with async preprocessors.`\n );\n }\n preprocessedObject = result;\n } catch (err) {\n if (\n (err as Error).message?.includes('Use validateAsync()')\n ) {\n throw err;\n }\n errors.push({\n message: `Preprocessor #${currentPrepropIndex}${\n entry.fn.name ? ` (${entry.fn.name})` : ''\n } thrown an error: ${(err as Error).message}`\n });\n if (!doNotStopOnFirstError) {\n return this.#earlyFailResult(errors, resultingContext);\n }\n } finally {\n currentPrepropIndex++;\n }\n }\n preprocessingTransaction = this.#hasMutating\n ? transaction({ validatedObject: preprocessedObject })\n : noopTransaction({ validatedObject: preprocessedObject });\n }\n\n if (typeof preprocessedObject === 'undefined' && this.hasDefault) {\n preprocessedObject = this.resolveDefaultValue();\n preprocessingTransaction = this.#hasMutating\n ? transaction({ validatedObject: preprocessedObject })\n : noopTransaction({ validatedObject: preprocessedObject });\n }\n\n if (\n this.#validators.length > 0 &&\n !(preprocessedObject == null && !this.isRequired) &&\n !(preprocessedObject === null && this.#isNullable)\n ) {\n let currentValidatorIndex = 0;\n for (const entry of this.#validators) {\n try {\n const validatorResult = entry.fn(preprocessedObject);\n if (validatorResult instanceof Promise) {\n throw new Error(\n `Validator #${currentValidatorIndex}${entry.fn.name ? ` (${entry.fn.name})` : ''} returned a Promise. Use validateAsync() for schemas with async validators.`\n );\n }\n const { valid, errors: validatorErrors } = validatorResult;\n if (!valid) {\n errors.push(\n ...this.#validatorFailureErrors(\n currentValidatorIndex,\n entry.fn.name,\n validatorErrors\n )\n );\n if (!doNotStopOnFirstError) {\n return this.#earlyFailResult(\n errors,\n resultingContext\n );\n }\n }\n } catch (err) {\n if (\n (err as Error).message?.includes('Use validateAsync()')\n ) {\n throw err;\n }\n errors.push({\n message: `Validator #${currentValidatorIndex}${\n entry.fn.name ? ` (${entry.fn.name})` : ''\n } thrown an error: ${(err as Error).message}`\n });\n if (!doNotStopOnFirstError) {\n return this.#earlyFailResult(errors, resultingContext);\n }\n } finally {\n currentValidatorIndex++;\n }\n }\n }\n\n if (\n this.isRequired &&\n (typeof preprocessedObject === 'undefined' ||\n (preprocessedObject === null &&\n this.isNullRequiredViolation &&\n !this.#isNullable))\n ) {\n errors.push({\n message: this.getValidationErrorMessageSync(\n this.#requiredErrorMessageProvider,\n preprocessedObject\n )\n });\n if (!doNotStopOnFirstError) {\n preprocessingTransaction.rollback();\n return this.#earlyFailResult(errors, resultingContext);\n }\n }\n\n return this.#buildPreValidationResult(\n errors,\n doNotStopOnFirstError,\n resultingContext,\n preprocessingTransaction\n );\n }\n\n /**\n * Async version of pre-validation. Runs preprocessors, validators, and the\n * required/optional check on `object`. Supports async preprocessors,\n * validators, and error message providers.\n *\n * @param object - the value to pre-validate\n * @param context - optional validation context settings\n * @returns a `PreValidationResult` containing the preprocessed transaction, context, and any errors\n */\n protected async preValidateAsync(\n object: any,\n context?: ValidationContext\n ): Promise<PreValidationResult<any, { validatedObject: any }>> {\n const state = this.#initPreValidation(object, context);\n const { doNotStopOnFirstError, resultingContext, errors } = state;\n let preprocessingTransaction = state.transaction;\n let preprocessedObject =\n preprocessingTransaction.object.validatedObject;\n\n if (this.#preprocessors.length > 0) {\n let currentPrepropIndex = 0;\n for (const entry of this.#preprocessors) {\n try {\n preprocessedObject = await Promise.resolve(\n entry.fn(preprocessedObject)\n );\n } catch (err) {\n errors.push({\n message: `Preprocessor #${currentPrepropIndex}${\n entry.fn.name ? ` (${entry.fn.name})` : ''\n } thrown an error: ${(err as Error).message}`\n });\n if (!doNotStopOnFirstError) {\n return this.#earlyFailResult(errors, resultingContext);\n }\n } finally {\n currentPrepropIndex++;\n }\n }\n preprocessingTransaction = this.#hasMutating\n ? transaction({ validatedObject: preprocessedObject })\n : noopTransaction({ validatedObject: preprocessedObject });\n }\n\n if (typeof preprocessedObject === 'undefined' && this.hasDefault) {\n preprocessedObject = this.resolveDefaultValue();\n preprocessingTransaction = this.#hasMutating\n ? transaction({ validatedObject: preprocessedObject })\n : noopTransaction({ validatedObject: preprocessedObject });\n }\n\n if (\n this.#validators.length > 0 &&\n !(preprocessedObject == null && !this.isRequired) &&\n !(preprocessedObject === null && this.#isNullable)\n ) {\n let currentValidatorIndex = 0;\n for (const entry of this.#validators) {\n try {\n const { valid, errors: validatorErrors } =\n await Promise.resolve(entry.fn(preprocessedObject));\n if (!valid) {\n errors.push(\n ...this.#validatorFailureErrors(\n currentValidatorIndex,\n entry.fn.name,\n validatorErrors\n )\n );\n if (!doNotStopOnFirstError) {\n return this.#earlyFailResult(\n errors,\n resultingContext\n );\n }\n }\n } catch (err) {\n errors.push({\n message: `Validator #${currentValidatorIndex}${\n entry.fn.name ? ` (${entry.fn.name})` : ''\n } thrown an error: ${(err as Error).message}`\n });\n if (!doNotStopOnFirstError) {\n return this.#earlyFailResult(errors, resultingContext);\n }\n } finally {\n currentValidatorIndex++;\n }\n }\n }\n\n if (\n this.isRequired &&\n (typeof preprocessedObject === 'undefined' ||\n (preprocessedObject === null &&\n this.isNullRequiredViolation &&\n !this.#isNullable))\n ) {\n errors.push({\n message: await this.getValidationErrorMessage(\n this.#requiredErrorMessageProvider,\n preprocessedObject\n )\n });\n if (!doNotStopOnFirstError) {\n preprocessingTransaction.rollback();\n return this.#earlyFailResult(errors, resultingContext);\n }\n }\n\n return this.#buildPreValidationResult(\n errors,\n doNotStopOnFirstError,\n resultingContext,\n preprocessingTransaction\n );\n }\n\n /**\n * @deprecated Use {@link preValidateAsync} instead. This alias will be removed in a future version.\n */\n protected preValidate(\n object: any,\n context?: ValidationContext\n ): Promise<PreValidationResult<any, { validatedObject: any }>> {\n return this.preValidateAsync(object, context);\n }\n\n /**\n * Generates a serializable object describing the defined schema\n */\n public introspect() {\n return {\n /**\n * String `id` of schema type, e.g. `string', `number` or `object`.\n */\n type: this.type,\n /**\n * If set to `false`, schema will be optional (`null` or `undefined` values\n * will be considered as valid).\n */\n isRequired: this.#isRequired,\n /**\n * If set to `true`, schema values of `null` are considered valid.\n */\n isNullable: this.#isNullable,\n /**\n * If set to `true`, the inferred type is marked as readonly.\n * Type-level only — no runtime enforcement.\n */\n isReadonly: this.#isReadonly,\n /**\n * Array of preprocessor functions\n */\n preprocessors: [\n ...this.preprocessors\n ] as readonly PreprocessorEntry<TResult>[],\n /**\n * Array of validator functions\n */\n validators: [\n ...this.validators\n ] as readonly ValidatorEntry<TResult>[],\n /**\n * Custom error message provider for the 'is required' validation error.\n */\n requiredValidationErrorMessageProvider:\n this.#requiredErrorMessageProvider,\n /**\n * Extension metadata. Stores custom state set by schema extensions.\n */\n extensions: { ...this.#extensions },\n /**\n * Whether a default value (or factory) has been set on this schema.\n */\n hasDefault: this.#defaultValue !== undefined,\n /**\n * The default value or factory function.\n */\n defaultValue: this.#defaultValue,\n /**\n * The human-readable description attached to this schema via `.describe()`,\n * or `undefined` if none was set.\n */\n description: this.#description,\n /**\n * Whether a catch/fallback value has been set on this schema via `.catch()`.\n */\n hasCatch: this.#hasCatch,\n /**\n * The catch/fallback value or factory function set via `.catch()`.\n */\n catchValue: this.#catchValue\n };\n }\n\n /**\n * Makes schema optional (consider `null` and `undefined` as valid objects for this schema)\n */\n public optional() {\n return this.createFromProps({\n ...this.introspect(),\n isRequired: false\n }) as any;\n }\n\n /**\n * Makes schema nullable — `null` is accepted as a valid value.\n *\n * Unlike `.optional()` which accepts `undefined`, `.nullable()` accepts\n * `null`. The inferred type changes from `T` to `T | null`. Combine with\n * `.optional()` to accept both `null` and `undefined`.\n */\n public nullable() {\n return this.createFromProps({\n ...this.introspect(),\n isNullable: true\n }) as any;\n }\n\n /**\n * Removes the nullable mark — `null` is no longer accepted as a valid\n * value. This is the counterpart of `.nullable()`.\n */\n public notNullable() {\n return this.createFromProps({\n ...this.introspect(),\n isNullable: false\n }) as any;\n }\n\n /**\n * Sets a default value for this schema. When the input is `undefined`,\n * the default value is used instead. The default is still validated\n * against the schema's constraints.\n *\n * Accepts either a static value or a factory function (useful for\n * mutable defaults like `() => new Date()` or `() => []`).\n *\n * @example\n * ```ts\n * const schema = string().default('hello');\n * schema.validate(undefined); // { valid: true, object: 'hello' }\n * schema.validate('world'); // { valid: true, object: 'world' }\n * ```\n *\n * @example\n * ```ts\n * // Factory function for mutable defaults\n * const schema = array(string()).default(() => []);\n * ```\n */\n public default(value: TResult | (() => TResult)) {\n return this.createFromProps({\n ...this.introspect(),\n defaultValue: value\n }) as any;\n }\n\n /**\n * Sets a fallback value for this schema. When validation **fails** for any reason,\n * the fallback value is returned as a successful result instead of validation errors.\n *\n * This is useful for graceful degradation — for example, providing a safe default\n * when parsing untrusted input that might not conform to the schema.\n *\n * Accepts either a static value or a factory function. Factory functions are called\n * each time the fallback is needed (useful for mutable values like `() => []`).\n *\n * Unlike {@link default}, which only fires when the input is `undefined`, `.catch()`\n * fires on **any** validation failure — type mismatch, constraint violation, etc.\n *\n * When `.catch()` is set, {@link parse} and {@link parseAsync} will **never throw**.\n *\n * @param value - the fallback value, or a factory function producing the fallback\n *\n * @example\n * ```ts\n * const schema = string().catch('unknown');\n * schema.validate(42); // { valid: true, object: 'unknown' }\n * schema.validate('hello'); // { valid: true, object: 'hello' }\n * schema.parse(42); // 'unknown' (no throw)\n * ```\n *\n * @example\n * ```ts\n * // Factory function for mutable fallbacks\n * const schema = array(string()).catch(() => []);\n * schema.validate(null); // { valid: true, object: [] }\n * ```\n *\n * @example\n * ```ts\n * // Contrast with .default() — default fires only on undefined\n * const d = string().default('anon');\n * d.validate(undefined); // { valid: true, object: 'anon' } ← fires\n * d.validate(42); // { valid: false, errors: [...] } ← does NOT fire\n *\n * const c = string().catch('anon');\n * c.validate(undefined); // { valid: true, object: 'anon' } ← fires\n * c.validate(42); // { valid: true, object: 'anon' } ← also fires\n * ```\n */\n public catch(value: TResult | (() => TResult)): this {\n return this.createFromProps({\n ...this.introspect(),\n catchValue: value,\n hasCatch: true\n }) as unknown as this;\n }\n\n /**\n * Removes the default value set by a previous call to `.default()`.\n */\n public clearDefault() {\n return this.createFromProps({\n ...this.introspect(),\n defaultValue: undefined\n }) as any;\n }\n\n /**\n * Attaches a human-readable description to this schema as runtime metadata.\n *\n * The description has no effect on validation — it is purely informational.\n * It is accessible via `.introspect().description` and is emitted as the\n * `description` field by `toJsonSchema()` from `@cleverbrush/schema-json`.\n *\n * Useful for documentation generation, form labels, and AI tool descriptions.\n *\n * @example\n * ```ts\n * const schema = object({\n * name: string().describe('The user\\'s full name'),\n * age: number().optional().describe('Age in years'),\n * }).describe('A user object');\n *\n * schema.introspect().description; // 'A user object'\n * ```\n */\n public describe(text: string): this {\n return this.createFromProps({\n ...this.introspect(),\n description: text\n }) as unknown as this;\n }\n\n /**\n * Brands the schema with a phantom type tag, preventing structural mixing\n * of semantically different values at the type level. Zero runtime cost.\n *\n * The optional `_name` parameter is only needed when using plain JavaScript\n * (where generic type parameters are unavailable). In TypeScript, prefer\n * the generic form: `schema.brand<'Email'>()`.\n *\n * @example\n * ```ts\n * const Email = string().brand<'Email'>();\n * const Username = string().brand<'Username'>();\n * type Email = InferType<typeof Email>; // string & { readonly [BRAND]: 'Email' }\n * type Username = InferType<typeof Username>; // string & { readonly [BRAND]: 'Username' }\n * ```\n */\n public brand<TBrand extends string | symbol>(_name?: TBrand) {\n return this.createFromProps({\n ...this.introspect()\n }) as any;\n }\n\n /**\n * Marks the inferred type as readonly. For objects, produces `Readonly<T>`.\n * For arrays, produces `ReadonlyArray<T>`. Primitives are unchanged.\n * Type-level only — no runtime enforcement.\n *\n * @example\n * ```ts\n * const schema = object({ name: string(), age: number() }).readonly();\n * type T = InferType<typeof schema>; // Readonly<{ name: string; age: number }>\n * ```\n *\n * @example\n * ```ts\n * const schema = array(string()).readonly();\n * type T = InferType<typeof schema>; // ReadonlyArray<string>\n * ```\n */\n public readonly() {\n return this.createFromProps({\n ...this.introspect(),\n isReadonly: true\n }) as any;\n }\n\n /**\n * Makes schema required (consider `null` and `undefined` as invalid objects for this schema)\n * @param errorMessage - optional custom error message or provider for the 'is required' validation error\n */\n public required(errorMessage?: ValidationErrorMessageProvider) {\n return this.createFromProps({\n ...this.introspect(),\n isRequired: true,\n ...(errorMessage !== undefined\n ? {\n requiredValidationErrorMessageProvider:\n this.assureValidationErrorMessageProvider(\n errorMessage,\n this.#defaultRequiredErrorMessageProvider\n )\n }\n : {})\n }) as any;\n }\n\n /**\n * Adds a `preprocessor` to a preprocessors list\n */\n public addPreprocessor(\n preprocessor: Preprocessor<TResult>,\n options?: { mutates?: boolean }\n ): this {\n if (typeof preprocessor !== 'function') {\n throw new Error('preprocessor must be a function');\n }\n return this.createFromProps({\n ...this.introspect(),\n preprocessors: [\n ...this.preprocessors,\n { fn: preprocessor, mutates: options?.mutates ?? true }\n ]\n });\n }\n\n /**\n * Remove all preprocessors for this schema.\n */\n public clearPreprocessors(): this {\n return this.createFromProps({\n ...this.introspect(),\n preprocessors: []\n });\n }\n\n /**\n * Adds a `validator` to validators list.\n */\n public addValidator(\n validator: Validator<TResult>,\n options?: { mutates?: boolean }\n ): this {\n if (typeof validator !== 'function') {\n throw new Error('validator must be a function');\n }\n return this.createFromProps({\n ...this.introspect(),\n validators: [\n ...this.validators,\n { fn: validator, mutates: options?.mutates ?? false }\n ]\n });\n }\n\n /**\n * Remove all validators for this schema.\n */\n public clearValidators(): this {\n return this.createFromProps({\n ...this.introspect(),\n validators: []\n });\n }\n\n /**\n * Perform synchronous schema validation on `object`.\n * Throws at runtime if any preprocessor, validator, or error message\n * provider returns a Promise — use {@link validateAsync} instead.\n * @internal Override this in subclasses. External callers use {@link validate}.\n */\n protected abstract _validate(\n object: any,\n context?: ValidationContext\n ): ValidationResult<any>;\n\n /**\n * Perform asynchronous schema validation on `object`.\n * Supports async preprocessors, validators, and error message providers.\n * @internal Override this in subclasses. External callers use {@link validateAsync}.\n */\n protected abstract _validateAsync(\n object: any,\n context?: ValidationContext\n ): Promise<ValidationResult<any>>;\n\n /**\n * Perform synchronous schema validation on `object`.\n * Throws at runtime if any preprocessor, validator, or error message\n * provider returns a Promise — use {@link validateAsync} instead.\n *\n * If a fallback has been set via {@link catch}, a failed validation result\n * is replaced by a successful result built from the fallback value, preserving\n * the specialized result shape (e.g. `getErrorsFor` / `getNestedErrors` methods).\n */\n public validate(\n /**\n * Object to validate\n */\n object: any,\n /**\n * Optional `ValidationContext` settings\n */\n context?: ValidationContext\n ): ValidationResult<any> {\n const result = this._validate(object, context);\n if (!result.valid && this.#hasCatch) {\n const catchValue = this.resolveCatchValue();\n // Re-validate the fallback value so the returned result has the same\n // specialized shape as a normal successful result (e.g. getErrorsFor /\n // getNestedErrors helper methods are present and reflect success semantics).\n const catchResult = this._validate(catchValue, context);\n if (catchResult.valid) {\n return catchResult;\n }\n // Fallback value did not pass validation (user error) – return a plain\n // valid result as best-effort so that .catch() still suppresses the error.\n // Note: in this case specialized result methods such as getErrorsFor() /\n // getNestedErrors() will NOT be present on the returned object. This is an\n // edge case caused by the caller supplying a catch value that itself fails\n // schema validation; the type system should prevent this under normal use.\n return { valid: true, object: catchValue };\n }\n return result;\n }\n\n /**\n * Perform asynchronous schema validation on `object`.\n * Supports async preprocessors, validators, and error message providers.\n *\n * If a fallback has been set via {@link catch}, a failed validation result\n * is replaced by a successful result built from the fallback value, preserving\n * the specialized result shape (e.g. `getErrorsFor` / `getNestedErrors` methods).\n */\n public async validateAsync(\n /**\n * Object to validate\n */\n object: any,\n /**\n * Optional `ValidationContext` settings\n */\n context?: ValidationContext\n ): Promise<ValidationResult<any>> {\n const result = await this._validateAsync(object, context);\n if (!result.valid && this.#hasCatch) {\n const catchValue = this.resolveCatchValue();\n // Re-validate the fallback value so the returned result has the same\n // specialized shape as a normal successful result (e.g. getErrorsFor /\n // getNestedErrors helper methods are present and reflect success semantics).\n const catchResult = await this._validateAsync(catchValue, context);\n if (catchResult.valid) {\n return catchResult;\n }\n // Fallback value did not pass validation (user error) – return a plain\n // valid result as best-effort so that .catch() still suppresses the error.\n // Note: in this case specialized result methods such as getErrorsFor() /\n // getNestedErrors() will NOT be present on the returned object. This is an\n // edge case caused by the caller supplying a catch value that itself fails\n // schema validation; the type system should prevent this under normal use.\n return { valid: true, object: catchValue };\n }\n return result;\n }\n\n /**\n * Synchronously resolves a `ValidationErrorMessageProvider` to a string.\n * Throws if the provider function returns a Promise.\n *\n * @param provider - the error message provider (string or sync function)\n * @param seenValue - the value that caused the validation error\n * @returns the resolved error message string\n * @throws Error if the provider returns a Promise (use {@link getValidationErrorMessage} with {@link validateAsync})\n */\n protected getValidationErrorMessageSync(\n provider: ValidationErrorMessageProvider<any>,\n seenValue: TResult\n ): string {\n if (typeof provider === 'string') {\n return provider;\n }\n\n if (typeof provider === 'function') {\n const result = provider(seenValue, this);\n if (result instanceof Promise) {\n throw new Error(\n 'Async error message providers require validateAsync(). Use a string or sync function instead.'\n );\n }\n return result;\n }\n\n throw new Error(\n 'Invalid error message provider must be a string or a function returning a string'\n );\n }\n\n /**\n * Resolves a `ValidationErrorMessageProvider` to a string error message.\n * Handles both string providers and function providers (sync or async).\n *\n * @param provider - the error message provider (string or function)\n * @param seenValue - the value that caused the validation error\n * @returns the resolved error message string\n */\n protected async getValidationErrorMessage(\n provider: ValidationErrorMessageProvider<any>,\n seenValue: TResult\n ): Promise<string> {\n if (typeof provider === 'string') {\n return provider;\n }\n\n if (typeof provider === 'function') {\n return provider(seenValue, this);\n }\n\n throw new Error(\n 'Invalid error message provider must be a string or a function returning a string or a promise of a string'\n );\n }\n\n /**\n * Ensures a `ValidationErrorMessageProvider` is valid.\n * If `provider` is `undefined`, falls back to `defaultValue`.\n * Function providers are bound to `this` for access to schema state.\n *\n * @param provider - the provider to validate, or `undefined`\n * @param defaultValue - fallback provider when `provider` is not supplied\n * @returns a valid `ValidationErrorMessageProvider`\n */\n protected assureValidationErrorMessageProvider(\n provider: ValidationErrorMessageProvider<any> | undefined,\n defaultValue: ValidationErrorMessageProvider<any>\n ): ValidationErrorMessageProvider<any> {\n if (typeof provider === 'string') {\n return provider;\n }\n if (typeof provider === 'function') {\n return provider.bind(this);\n }\n\n if (typeof defaultValue === 'function') {\n return defaultValue.bind(this);\n }\n\n return defaultValue;\n }\n\n /**\n * Sets extension metadata by key. Returns a new schema instance with the\n * extension data stored. The data survives fluent chaining.\n * @internal Used by extension authors inside `defineExtension()` callbacks.\n */\n public withExtension(key: string, value: unknown): this {\n return this.createFromProps({\n ...this.introspect(),\n extensions: {\n ...this.#extensions,\n [key]: value\n }\n });\n }\n\n /**\n * Retrieves extension metadata by key.\n * @internal Used by extension authors inside `defineExtension()` callbacks.\n */\n public getExtension(key: string): unknown {\n return this.#extensions[key];\n }\n\n /**\n * Synchronously validates the value and returns it if valid.\n * Throws a {@link SchemaValidationError} if validation fails.\n *\n * @param object - the value to parse\n * @param context - optional validation context\n * @returns the validated value\n * @throws SchemaValidationError if validation fails\n * @throws Error if the schema contains async preprocessors, validators, or error message providers\n */\n public parse(object: any, context?: ValidationContext): TResult {\n const result = this.validate(object, context);\n if (!result.valid) {\n throw new SchemaValidationError(result.errors || []);\n }\n return result.object as TResult;\n }\n\n /**\n * Asynchronously validates the value and returns it if valid.\n * Throws a {@link SchemaValidationError} if validation fails.\n *\n * @param object - the value to parse\n * @param context - optional validation context\n * @returns the validated value\n * @throws SchemaValidationError if validation fails\n */\n public async parseAsync(\n object: any,\n context?: ValidationContext\n ): Promise<TResult> {\n const result = await this.validateAsync(object, context);\n if (!result.valid) {\n throw new SchemaValidationError(result.errors || []);\n }\n return result.object as TResult;\n }\n\n /**\n * Alias for {@link validate}. Synchronously validates and returns a result object.\n * Provided for familiarity with the zod API.\n */\n public safeParse(\n object: any,\n context?: ValidationContext\n ): ValidationResult<TResult> {\n return this.validate(object, context) as ValidationResult<TResult>;\n }\n\n /**\n * Alias for {@link validateAsync}. Asynchronously validates and returns a result object.\n * Provided for familiarity with the zod API.\n */\n public safeParseAsync(\n object: any,\n context?: ValidationContext\n ): Promise<ValidationResult<TResult>> {\n return this.validateAsync(object, context) as Promise<\n ValidationResult<TResult>\n >;\n }\n\n protected constructor(props: SchemaBuilderProps<TResult>) {\n if (!(typeof props === 'object' && props))\n throw new Error('SchemaBuilder props must be an object');\n const { type, preprocessors, validators, isRequired } = props;\n this.type = type;\n if (typeof isRequired === 'boolean') this.isRequired = isRequired;\n if (typeof props.isNullable === 'boolean')\n this.#isNullable = props.isNullable;\n if (typeof props.isReadonly === 'boolean')\n this.#isReadonly = props.isReadonly;\n if (Array.isArray(preprocessors)) {\n this.#preprocessors = [...preprocessors];\n }\n\n if (Array.isArray(validators)) {\n this.#validators = [...validators];\n }\n\n this.#hasMutating =\n this.#preprocessors.some(p => p.mutates) ||\n this.#validators.some(v => v.mutates);\n\n this.#canSkipPreValidation =\n this.#preprocessors.length === 0 && this.#validators.length === 0;\n\n if (typeof props.extensions === 'object' && props.extensions) {\n this.#extensions = { ...props.extensions };\n }\n\n if (props.defaultValue !== undefined) {\n this.#defaultValue = props.defaultValue;\n }\n\n if (props.hasCatch) {\n this.#hasCatch = true;\n this.#catchValue = props.catchValue;\n }\n\n if (typeof props.description === 'string') {\n this.#description = props.description;\n }\n\n this.#requiredErrorMessageProvider =\n this.assureValidationErrorMessageProvider(\n props.requiredValidationErrorMessageProvider,\n this.#defaultRequiredErrorMessageProvider\n );\n }\n}\n"],"mappings":"AAAA,IAAMA,EAAqB,OAAO,aAAa,EAEzCC,EAA+B,CAAC,MAAO,OAAQ,IAAI,EAoBnDC,EAAgD,CAClD,6BAA8BC,GAC1B,CAAC,CAACF,EAA6B,KAAKG,GAAKD,aAAiBC,CAAC,CACnE,EAuCaC,EAAc,CACvBC,EACAC,IACiB,CACjB,IAAIC,EAA8C,CAAC,EAC/CC,EAAoB,IAAI,IAE5BF,EAAU,OAAO,OAAO,CAAC,EAAGL,EAA2BK,GAAW,CAAC,CAAC,EAEpE,GAAM,CAAE,6BAAAG,CAA6B,EACjCH,EAEEI,EAAU,IACZ,CAAC,CAAC,OAAO,KAAKH,CAAa,EAAE,KAAKI,GAC1BJ,EAAcI,CAAG,IAAIZ,CAAkB,EAChCQ,EAAcI,CAAG,EAAEZ,CAAkB,EAAE,QAAQ,EAEnD,EACV,GAAOS,EAAkB,KAAO,EAE/BI,EAAS,IAAM,CACjB,IAAMC,EAAS,CAAC,EAChB,OAAO,KAAKR,CAAO,EAAE,QAAQM,GAAO,CAChCE,EAAOF,CAAG,EAAKN,EAAgBM,CAAG,CACtC,CAAC,EAED,OAAO,KAAKJ,CAAa,EAAE,QAAQI,GAAO,CACtC,IAAMG,EAAQP,EAAcI,CAAG,EAC/B,GAAIG,EAAMf,CAAkB,EAAG,CAC3B,GAAM,CAAE,OAAQgB,CAAY,EAAID,EAAMf,CAAkB,EACxDc,EAAOF,CAAG,EAAII,EAAY,CAC9B,MACIF,EAAOF,CAAG,EAAIJ,EAAcI,CAAG,CAEvC,CAAC,EAED,QAAWA,KAAOH,EAAkB,KAAK,EACrC,OAAOK,EAAOF,CAAa,EAG/B,OAAAJ,EAAgB,CAAC,EACjBC,EAAoB,IAAI,IAEjBK,CACX,EAEMG,EAAW,IAAM,CACnB,QAAWL,KAAOJ,EAAe,CAC7B,IAAMO,EAAQP,EAAcI,CAAG,EAE3BG,GACA,OAAOA,GAAU,UACjBA,EAAMf,CAAkB,GAGxBe,EAAMf,CAAkB,EAAE,SAAS,CAE3C,CACA,OAAAQ,EAAgB,CAAC,EACjBC,EAAoB,IAAI,IACjBH,CACX,EAEA,GAAI,MAAM,QAAQA,CAAO,EAAG,CACxB,IAAMQ,EAASR,EAAQ,IAAIY,GACvB,OAAOA,GAAO,UAAYA,GAAM,CAACR,EAA6BQ,CAAE,EAC1Db,EAAYa,CAAE,EAAE,OAChBA,CACV,EACMC,EAAc,IAChBL,EAAO,IAAII,GACPA,GAAM,OAAOA,EAAGlB,CAAkB,GAAM,SAClCkB,EAAGlB,CAAkB,EAAE,OAAO,EAC9BkB,CACV,EAEEE,EAAe,IACV,CAAC,CAACN,EAAO,KAAK,CAACO,EAAKC,IACnBD,GAAO,OAAOA,EAAIrB,CAAkB,GAAM,SACnCqB,EAAIrB,CAAkB,EAAE,QAAQ,EAEpCc,EAAOQ,CAAK,IAAMhB,EAAQgB,CAAK,CACzC,EAEL,cAAO,eAAeR,EAAQd,EAAoB,CAC9C,SAAU,GACV,aAAc,GACd,MAAO,CACH,QAAAM,EACA,OAAQQ,EACR,OAAQK,EACR,SAAU,IAAMb,EAChB,QAASc,CACb,CACJ,CAAC,EACM,CACH,OAAQN,EACR,OAAQK,EACR,SAAU,IAAMb,EAChB,QAASc,CACb,CACJ,CAEA,IAAMG,EAAQ,IAAI,MAASjB,EAAS,CAChC,IAAK,CAACkB,EAAQC,EAAUV,IAChBS,GAAWA,EAAeC,CAAQ,IAAMV,GACxC,OAAOP,EAAciB,CAAQ,EACtB,KAEXjB,EAAciB,CAAQ,EAAIV,EAC1BN,EAAkB,OAAOgB,CAAe,EACjC,IAEX,QAASD,GACE,CACH,GAAG,OAAO,KAAKA,CAAM,EAAE,OAClBE,GAAW,CAACjB,EAAkB,IAAIiB,CAAC,CACxC,EACA,GAAG,OAAO,KAAKlB,CAAa,EAAE,OAAQkB,GAAW,EAAEA,KAAKF,EAAO,CACnE,EAEJ,yBAA0B,CAACA,EAAQG,IAAc,CAC7C,GAAI,CAAAlB,EAAkB,IAAIkB,CAAI,EAI9B,OAAIA,KAAQnB,EACD,OAAO,yBAAyBA,EAAemB,CAAI,EAGvD,OAAO,yBAAyBH,EAAQG,CAAI,CACvD,EACA,IAAK,CAACH,EAAQG,IACNlB,EAAkB,IAAIkB,CAAI,EACnB,GAGPA,KAAQnB,EACD,GAGJmB,KAAQH,EAEnB,IAAK,CAACA,EAAQG,IAAS,CACnB,GAAI,OAAOA,GAAS,SAChB,OAAIA,IAAS3B,EACF,CACH,QAAAM,EACA,OAAQiB,EACR,OAAAV,EACA,SAAAI,EACA,QAAAN,CACJ,EAEIa,EAAeG,CAAI,EAG/B,GAAIA,KAAQnB,EACR,OAAOA,EAAcmB,CAAI,EAG7B,GAAI,CAAAlB,EAAkB,IAAIkB,CAAW,EAIrC,IACI,CAACC,EAAeJ,EAAeG,CAAI,CAAC,GACpC,OAAQH,EAAeG,CAAI,GAAM,UAChCH,EAAeG,CAAI,GACpB,CAACjB,EAA8Bc,EAAeG,CAAI,CAAC,EACrD,CACE,GAAM,CAAE,OAAAE,CAAO,EAAIxB,EAAamB,EAAeG,CAAI,EAAGpB,CAAO,EAC7D,OAAAC,EAAcmB,CAAI,EAAIE,EACfA,CACX,CAEA,OAAQL,EAAeG,CAAI,EAC/B,EACA,eAAgB,CAACH,EAAQM,KACjBA,KAAKtB,IAEDA,EAAcsB,CAAC,GACf,OAAOtB,EAAcsB,CAAC,EAAE9B,CAAkB,GAAM,UAEhDQ,EAAcsB,CAAC,EAAE9B,CAAkB,EAAE,SAAS,EAElD,OAAOQ,EAAcsB,CAAC,GAEtBA,KAAKN,GACLf,EAAkB,IAAIqB,EAAU,EAAI,EAEjC,GAEf,CAAC,EAED,MAAO,CACH,OAAQP,EACR,OAAAV,EACA,SAAAI,EACA,QAAAN,CACJ,CACJ,EAUaoB,EAAiCzB,IAAgC,CAC1E,OAAQA,EACR,OAAQ,IAAMA,EACd,SAAU,IAAMA,EAChB,QAAS,IAAM,EACnB,GAOasB,EAAiBI,GAC1BA,GAAO,OAAOA,GAAQ,UAAY,OAAO,OAAOA,EAAKhC,CAAkB,ECnJpE,IAAMiC,EAAN,cAAoC,KAAM,CAC7B,OAEhB,YAAYC,EAA2B,CACnC,IAAMC,EACFD,EAAO,OAAS,EACVA,EAAO,IAAIE,GAAKA,EAAE,OAAO,EAAE,KAAK,IAAI,EACpC,oBACV,MAAMD,CAAO,EACb,KAAK,KAAO,wBACZ,KAAK,OAASD,CAClB,CACJ,EAwIaG,EAAoC,OAAO,EAa3CC,EAAwB,OAAO,EAyUrC,SAASC,EACZC,EACAC,EACAP,EACAQ,EACC,CACD,cAAO,iBAAiBF,EAAO,CAC3B,UAAW,CACP,IAAKC,EACL,WAAY,EAChB,EACA,OAAQ,CACJ,IAAKP,EACL,WAAY,EAChB,EACA,QAAS,CACL,IAAK,IAAMA,EAAO,EAAE,SAAW,EAC/B,WAAY,EAChB,EACA,WAAY,CACR,IAAKQ,EACL,WAAY,EAChB,CACJ,CAAC,EACMF,CACX,CA+BO,IAAeG,EAAf,KAOL,CACEC,GAAc,GACdC,GAAc,GACdC,GAAc,GACdC,GACAC,GAA+C,CAAC,EAChDC,GAAyC,CAAC,EAC1CC,GAAe,GACfC,GAAwB,GACxBC,GAAuC,CAAC,EACxCC,GAAQ,OACRC,GACI,cACJC,GACI,cACJC,GAAuD,OACvDC,GAAqD,OACrDC,GAAY,GAMZC,GAyEA,GAAK,aAEH,CACE,GAAI,KAAKA,GAAgB,OAAO,KAAKA,GAGrC,IAAMC,EAAO,KACb,YAAKD,GAAiB,CAClB,QAAS,EACT,OAAQ,sBACR,SACIE,EAGF,CAKE,IAAMC,EAASF,EAAK,SAASC,CAAY,EACzC,OAAIC,EAAO,MACA,CACH,MAAOA,EAAO,MAKlB,EAEG,CACH,QAASA,EAAO,QAAU,CAAC,GAAG,IAAI1B,IAAM,CACpC,QAASA,EAAE,OACf,EAAE,CACN,CACJ,CACJ,EACO,KAAKuB,EAChB,CA0BA,IAAc,MAAO,CACjB,OAAO,KAAKN,EAChB,CAKA,IAAc,KAAKQ,EAAe,CAC9B,GAAI,OAAOA,GAAU,UAAY,CAACA,EAC9B,MAAM,IAAI,MAAM,kCAAkC,EACtD,KAAKR,GAAQQ,CACjB,CAMA,IAAc,eAAgB,CAC1B,OAAO,KAAKb,EAChB,CAMA,IAAc,YAAa,CACvB,OAAO,KAAKC,EAChB,CAKA,IAAc,YAAwB,CAClC,OAAO,KAAKL,EAChB,CAKA,IAAc,YAAsB,CAChC,OAAO,KAAKC,EAChB,CAKA,IAAc,WAAWgB,EAAgB,CACrC,GAAI,OAAOA,GAAU,UACjB,MAAM,IAAI,MAAM,2BAA2B,EAC/C,KAAKjB,GAAciB,CACvB,CAMA,IAAc,sBAAuD,CACjE,OAAO,KAAKN,EAChB,CAMA,IAAc,YAAsB,CAChC,OAAO,KAAKC,KAAkB,MAClC,CAKA,IAAc,UAAoB,CAC9B,OAAO,KAAKE,EAChB,CAMU,mBAA6B,CACnC,OAAO,OAAO,KAAKD,IAAgB,WAC5B,KAAKA,GAA8B,EACnC,KAAKA,EAChB,CAMA,IAAc,YAAsB,CAChC,OAAO,KAAKX,EAChB,CAMU,qBAA+B,CACrC,OAAO,OAAO,KAAKU,IAAkB,WAC9B,KAAKA,GAAgC,EACrC,KAAKA,EAChB,CAQA,IAAc,sBAAgC,CAC1C,OAAO,KAAKL,EAChB,CAcA,IAAc,yBAAmC,CAC7C,MAAO,EACX,CAOAY,GAAmBC,EAAaC,EAA6B,CACzD,IAAMC,EAAwBD,GAAS,uBAAyB,GAE1DE,EAAsC,CACxC,sBAAAD,EACA,uBAAwBD,GAAS,uBACjC,0BAA2BA,GAAS,yBACxC,EAEMG,EAAmB,KAAKlB,GAE9B,MAAO,CACH,sBAAAgB,EACA,iBAAAC,EACA,YAAaC,EACPC,EAAY,CAAE,gBAAiBL,CAAO,CAAC,EACvCM,EAAgB,CAAE,gBAAiBN,CAAO,CAAC,EACjD,OAAQ,CAAC,CACb,CACJ,CAMAO,GACIrC,EACAiC,EACkD,CAClD,MAAO,CACH,MAAO,GACP,OAAQ,CAACjC,EAAO,CAAC,CAAC,EAAE,OAAOE,GAAKA,CAAC,EACjC,QAAS+B,CACb,CACJ,CAKAK,GACIC,EACAC,EACAC,EACiB,CACjB,OAAI,MAAM,QAAQA,CAAe,GAAKA,EAAgB,OAC3CA,EAEJ,CACH,CACI,QAAS,cAAcF,CAAK,GACxBC,EAAO,KAAKA,CAAI,IAAM,EAC1B,eACJ,CACJ,CACJ,CAMAE,GACI1C,EACAgC,EACAC,EACAU,EACkD,CAClD,OAAI3C,EAAO,OAAS,EACT,CACH,MAAO,GACP,OAAQA,EACH,OAAOE,GAAKA,CAAC,EACb,OAAO,CAAC0C,EAAIC,IACTb,EAAwB,GAAOa,IAAM,CACzC,EACJ,QAASZ,EACT,YAAaU,CACjB,EAGG,CACH,MAAO,GACP,QAASV,EACT,YAAaU,CACjB,CACJ,CAWU,gBACNb,EACAC,EACkD,CAClD,IAAMe,EAAQ,KAAKjB,GAAmBC,EAAQC,CAAO,EAC/C,CAAE,sBAAAC,EAAuB,iBAAAC,EAAkB,OAAAjC,CAAO,EAAI8C,EACxDC,EAA2BD,EAAM,YACjCE,EACAD,EAAyB,OAAO,gBAEpC,GAAI,KAAKjC,GAAe,OAAS,EAAG,CAChC,IAAImC,EAAsB,EAC1B,QAAWC,KAAS,KAAKpC,GACrB,GAAI,CACA,IAAMc,EAASsB,EAAM,GAAGF,CAAkB,EAC1C,GAAIpB,aAAkB,QAClB,MAAM,IAAI,MACN,iBAAiBqB,CAAmB,GAAGC,EAAM,GAAG,KAAO,KAAKA,EAAM,GAAG,IAAI,IAAM,EAAE,gFACrF,EAEJF,EAAqBpB,CACzB,OAASuB,EAAK,CACV,GACKA,EAAc,SAAS,SAAS,qBAAqB,EAEtD,MAAMA,EAOV,GALAnD,EAAO,KAAK,CACR,QAAS,iBAAiBiD,CAAmB,GACzCC,EAAM,GAAG,KAAO,KAAKA,EAAM,GAAG,IAAI,IAAM,EAC5C,qBAAsBC,EAAc,OAAO,EAC/C,CAAC,EACG,CAACnB,EACD,OAAO,KAAKK,GAAiBrC,EAAQiC,CAAgB,CAE7D,QAAE,CACEgB,GACJ,CAEJF,EAA2B,KAAK/B,GAC1BmB,EAAY,CAAE,gBAAiBa,CAAmB,CAAC,EACnDZ,EAAgB,CAAE,gBAAiBY,CAAmB,CAAC,CACjE,CASA,GAPI,OAAOA,EAAuB,KAAe,KAAK,aAClDA,EAAqB,KAAK,oBAAoB,EAC9CD,EAA2B,KAAK/B,GAC1BmB,EAAY,CAAE,gBAAiBa,CAAmB,CAAC,EACnDZ,EAAgB,CAAE,gBAAiBY,CAAmB,CAAC,GAI7D,KAAKjC,GAAY,OAAS,GAC1B,EAAEiC,GAAsB,MAAQ,CAAC,KAAK,aACtC,EAAEA,IAAuB,MAAQ,KAAKrC,IACxC,CACE,IAAIyC,EAAwB,EAC5B,QAAWF,KAAS,KAAKnC,GACrB,GAAI,CACA,IAAMsC,EAAkBH,EAAM,GAAGF,CAAkB,EACnD,GAAIK,aAA2B,QAC3B,MAAM,IAAI,MACN,cAAcD,CAAqB,GAAGF,EAAM,GAAG,KAAO,KAAKA,EAAM,GAAG,IAAI,IAAM,EAAE,6EACpF,EAEJ,GAAM,CAAE,MAAAI,EAAO,OAAQb,CAAgB,EAAIY,EAC3C,GAAI,CAACC,IACDtD,EAAO,KACH,GAAG,KAAKsC,GACJc,EACAF,EAAM,GAAG,KACTT,CACJ,CACJ,EACI,CAACT,GACD,OAAO,KAAKK,GACRrC,EACAiC,CACJ,CAGZ,OAASkB,EAAK,CACV,GACKA,EAAc,SAAS,SAAS,qBAAqB,EAEtD,MAAMA,EAOV,GALAnD,EAAO,KAAK,CACR,QAAS,cAAcoD,CAAqB,GACxCF,EAAM,GAAG,KAAO,KAAKA,EAAM,GAAG,IAAI,IAAM,EAC5C,qBAAsBC,EAAc,OAAO,EAC/C,CAAC,EACG,CAACnB,EACD,OAAO,KAAKK,GAAiBrC,EAAQiC,CAAgB,CAE7D,QAAE,CACEmB,GACJ,CAER,CAEA,OACI,KAAK,aACJ,OAAOJ,EAAuB,KAC1BA,IAAuB,MACpB,KAAK,yBACL,CAAC,KAAKrC,MAEdX,EAAO,KAAK,CACR,QAAS,KAAK,8BACV,KAAKqB,GACL2B,CACJ,CACJ,CAAC,EACG,CAAChB,IACDe,EAAyB,SAAS,EAC3B,KAAKV,GAAiBrC,EAAQiC,CAAgB,GAItD,KAAKS,GACR1C,EACAgC,EACAC,EACAc,CACJ,CACJ,CAWA,MAAgB,iBACZjB,EACAC,EAC2D,CAC3D,IAAMe,EAAQ,KAAKjB,GAAmBC,EAAQC,CAAO,EAC/C,CAAE,sBAAAC,EAAuB,iBAAAC,EAAkB,OAAAjC,CAAO,EAAI8C,EACxDC,EAA2BD,EAAM,YACjCE,EACAD,EAAyB,OAAO,gBAEpC,GAAI,KAAKjC,GAAe,OAAS,EAAG,CAChC,IAAImC,EAAsB,EAC1B,QAAWC,KAAS,KAAKpC,GACrB,GAAI,CACAkC,EAAqB,MAAM,QAAQ,QAC/BE,EAAM,GAAGF,CAAkB,CAC/B,CACJ,OAASG,EAAK,CAMV,GALAnD,EAAO,KAAK,CACR,QAAS,iBAAiBiD,CAAmB,GACzCC,EAAM,GAAG,KAAO,KAAKA,EAAM,GAAG,IAAI,IAAM,EAC5C,qBAAsBC,EAAc,OAAO,EAC/C,CAAC,EACG,CAACnB,EACD,OAAO,KAAKK,GAAiBrC,EAAQiC,CAAgB,CAE7D,QAAE,CACEgB,GACJ,CAEJF,EAA2B,KAAK/B,GAC1BmB,EAAY,CAAE,gBAAiBa,CAAmB,CAAC,EACnDZ,EAAgB,CAAE,gBAAiBY,CAAmB,CAAC,CACjE,CASA,GAPI,OAAOA,EAAuB,KAAe,KAAK,aAClDA,EAAqB,KAAK,oBAAoB,EAC9CD,EAA2B,KAAK/B,GAC1BmB,EAAY,CAAE,gBAAiBa,CAAmB,CAAC,EACnDZ,EAAgB,CAAE,gBAAiBY,CAAmB,CAAC,GAI7D,KAAKjC,GAAY,OAAS,GAC1B,EAAEiC,GAAsB,MAAQ,CAAC,KAAK,aACtC,EAAEA,IAAuB,MAAQ,KAAKrC,IACxC,CACE,IAAIyC,EAAwB,EAC5B,QAAWF,KAAS,KAAKnC,GACrB,GAAI,CACA,GAAM,CAAE,MAAAuC,EAAO,OAAQb,CAAgB,EACnC,MAAM,QAAQ,QAAQS,EAAM,GAAGF,CAAkB,CAAC,EACtD,GAAI,CAACM,IACDtD,EAAO,KACH,GAAG,KAAKsC,GACJc,EACAF,EAAM,GAAG,KACTT,CACJ,CACJ,EACI,CAACT,GACD,OAAO,KAAKK,GACRrC,EACAiC,CACJ,CAGZ,OAASkB,EAAK,CAMV,GALAnD,EAAO,KAAK,CACR,QAAS,cAAcoD,CAAqB,GACxCF,EAAM,GAAG,KAAO,KAAKA,EAAM,GAAG,IAAI,IAAM,EAC5C,qBAAsBC,EAAc,OAAO,EAC/C,CAAC,EACG,CAACnB,EACD,OAAO,KAAKK,GAAiBrC,EAAQiC,CAAgB,CAE7D,QAAE,CACEmB,GACJ,CAER,CAEA,OACI,KAAK,aACJ,OAAOJ,EAAuB,KAC1BA,IAAuB,MACpB,KAAK,yBACL,CAAC,KAAKrC,MAEdX,EAAO,KAAK,CACR,QAAS,MAAM,KAAK,0BAChB,KAAKqB,GACL2B,CACJ,CACJ,CAAC,EACG,CAAChB,IACDe,EAAyB,SAAS,EAC3B,KAAKV,GAAiBrC,EAAQiC,CAAgB,GAItD,KAAKS,GACR1C,EACAgC,EACAC,EACAc,CACJ,CACJ,CAKU,YACNjB,EACAC,EAC2D,CAC3D,OAAO,KAAK,iBAAiBD,EAAQC,CAAO,CAChD,CAKO,YAAa,CAChB,MAAO,CAIH,KAAM,KAAK,KAKX,WAAY,KAAKrB,GAIjB,WAAY,KAAKC,GAKjB,WAAY,KAAKC,GAIjB,cAAe,CACX,GAAG,KAAK,aACZ,EAIA,WAAY,CACR,GAAG,KAAK,UACZ,EAIA,uCACI,KAAKS,GAIT,WAAY,CAAE,GAAG,KAAKH,EAAY,EAIlC,WAAY,KAAKI,KAAkB,OAInC,aAAc,KAAKA,GAKnB,YAAa,KAAKT,GAIlB,SAAU,KAAKW,GAIf,WAAY,KAAKD,EACrB,CACJ,CAKO,UAAW,CACd,OAAO,KAAK,gBAAgB,CACxB,GAAG,KAAK,WAAW,EACnB,WAAY,EAChB,CAAC,CACL,CASO,UAAW,CACd,OAAO,KAAK,gBAAgB,CACxB,GAAG,KAAK,WAAW,EACnB,WAAY,EAChB,CAAC,CACL,CAMO,aAAc,CACjB,OAAO,KAAK,gBAAgB,CACxB,GAAG,KAAK,WAAW,EACnB,WAAY,EAChB,CAAC,CACL,CAuBO,QAAQI,EAAkC,CAC7C,OAAO,KAAK,gBAAgB,CACxB,GAAG,KAAK,WAAW,EACnB,aAAcA,CAClB,CAAC,CACL,CA8CO,MAAMA,EAAwC,CACjD,OAAO,KAAK,gBAAgB,CACxB,GAAG,KAAK,WAAW,EACnB,WAAYA,EACZ,SAAU,EACd,CAAC,CACL,CAKO,cAAe,CAClB,OAAO,KAAK,gBAAgB,CACxB,GAAG,KAAK,WAAW,EACnB,aAAc,MAClB,CAAC,CACL,CAqBO,SAAS4B,EAAoB,CAChC,OAAO,KAAK,gBAAgB,CACxB,GAAG,KAAK,WAAW,EACnB,YAAaA,CACjB,CAAC,CACL,CAkBO,MAAsCC,EAAgB,CACzD,OAAO,KAAK,gBAAgB,CACxB,GAAG,KAAK,WAAW,CACvB,CAAC,CACL,CAmBO,UAAW,CACd,OAAO,KAAK,gBAAgB,CACxB,GAAG,KAAK,WAAW,EACnB,WAAY,EAChB,CAAC,CACL,CAMO,SAASC,EAA+C,CAC3D,OAAO,KAAK,gBAAgB,CACxB,GAAG,KAAK,WAAW,EACnB,WAAY,GACZ,GAAIA,IAAiB,OACf,CACI,uCACI,KAAK,qCACDA,EACA,KAAKrC,EACT,CACR,EACA,CAAC,CACX,CAAC,CACL,CAKO,gBACHsC,EACAC,EACI,CACJ,GAAI,OAAOD,GAAiB,WACxB,MAAM,IAAI,MAAM,iCAAiC,EAErD,OAAO,KAAK,gBAAgB,CACxB,GAAG,KAAK,WAAW,EACnB,cAAe,CACX,GAAG,KAAK,cACR,CAAE,GAAIA,EAAc,QAASC,GAAS,SAAW,EAAK,CAC1D,CACJ,CAAC,CACL,CAKO,oBAA2B,CAC9B,OAAO,KAAK,gBAAgB,CACxB,GAAG,KAAK,WAAW,EACnB,cAAe,CAAC,CACpB,CAAC,CACL,CAKO,aACHC,EACAD,EACI,CACJ,GAAI,OAAOC,GAAc,WACrB,MAAM,IAAI,MAAM,8BAA8B,EAElD,OAAO,KAAK,gBAAgB,CACxB,GAAG,KAAK,WAAW,EACnB,WAAY,CACR,GAAG,KAAK,WACR,CAAE,GAAIA,EAAW,QAASD,GAAS,SAAW,EAAM,CACxD,CACJ,CAAC,CACL,CAKO,iBAAwB,CAC3B,OAAO,KAAK,gBAAgB,CACxB,GAAG,KAAK,WAAW,EACnB,WAAY,CAAC,CACjB,CAAC,CACL,CAgCO,SAIH7B,EAIAC,EACqB,CACrB,IAAMH,EAAS,KAAK,UAAUE,EAAQC,CAAO,EAC7C,GAAI,CAACH,EAAO,OAAS,KAAKJ,GAAW,CACjC,IAAMqC,EAAa,KAAK,kBAAkB,EAIpCC,EAAc,KAAK,UAAUD,EAAY9B,CAAO,EACtD,OAAI+B,EAAY,MACLA,EAQJ,CAAE,MAAO,GAAM,OAAQD,CAAW,CAC7C,CACA,OAAOjC,CACX,CAUA,MAAa,cAITE,EAIAC,EAC8B,CAC9B,IAAMH,EAAS,MAAM,KAAK,eAAeE,EAAQC,CAAO,EACxD,GAAI,CAACH,EAAO,OAAS,KAAKJ,GAAW,CACjC,IAAMqC,EAAa,KAAK,kBAAkB,EAIpCC,EAAc,MAAM,KAAK,eAAeD,EAAY9B,CAAO,EACjE,OAAI+B,EAAY,MACLA,EAQJ,CAAE,MAAO,GAAM,OAAQD,CAAW,CAC7C,CACA,OAAOjC,CACX,CAWU,8BACNmC,EACAxD,EACM,CACN,GAAI,OAAOwD,GAAa,SACpB,OAAOA,EAGX,GAAI,OAAOA,GAAa,WAAY,CAChC,IAAMnC,EAASmC,EAASxD,EAAW,IAAI,EACvC,GAAIqB,aAAkB,QAClB,MAAM,IAAI,MACN,+FACJ,EAEJ,OAAOA,CACX,CAEA,MAAM,IAAI,MACN,kFACJ,CACJ,CAUA,MAAgB,0BACZmC,EACAxD,EACe,CACf,GAAI,OAAOwD,GAAa,SACpB,OAAOA,EAGX,GAAI,OAAOA,GAAa,WACpB,OAAOA,EAASxD,EAAW,IAAI,EAGnC,MAAM,IAAI,MACN,2GACJ,CACJ,CAWU,qCACNwD,EACAC,EACmC,CACnC,OAAI,OAAOD,GAAa,SACbA,EAEP,OAAOA,GAAa,WACbA,EAAS,KAAK,IAAI,EAGzB,OAAOC,GAAiB,WACjBA,EAAa,KAAK,IAAI,EAG1BA,CACX,CAOO,cAAcC,EAAatC,EAAsB,CACpD,OAAO,KAAK,gBAAgB,CACxB,GAAG,KAAK,WAAW,EACnB,WAAY,CACR,GAAG,KAAKT,GACR,CAAC+C,CAAG,EAAGtC,CACX,CACJ,CAAC,CACL,CAMO,aAAasC,EAAsB,CACtC,OAAO,KAAK/C,GAAY+C,CAAG,CAC/B,CAYO,MAAMnC,EAAaC,EAAsC,CAC5D,IAAMH,EAAS,KAAK,SAASE,EAAQC,CAAO,EAC5C,GAAI,CAACH,EAAO,MACR,MAAM,IAAI7B,EAAsB6B,EAAO,QAAU,CAAC,CAAC,EAEvD,OAAOA,EAAO,MAClB,CAWA,MAAa,WACTE,EACAC,EACgB,CAChB,IAAMH,EAAS,MAAM,KAAK,cAAcE,EAAQC,CAAO,EACvD,GAAI,CAACH,EAAO,MACR,MAAM,IAAI7B,EAAsB6B,EAAO,QAAU,CAAC,CAAC,EAEvD,OAAOA,EAAO,MAClB,CAMO,UACHE,EACAC,EACyB,CACzB,OAAO,KAAK,SAASD,EAAQC,CAAO,CACxC,CAMO,eACHD,EACAC,EACkC,CAClC,OAAO,KAAK,cAAcD,EAAQC,CAAO,CAG7C,CAEU,YAAYmC,EAAoC,CACtD,GAAI,EAAE,OAAOA,GAAU,UAAYA,GAC/B,MAAM,IAAI,MAAM,uCAAuC,EAC3D,GAAM,CAAE,KAAAC,EAAM,cAAAC,EAAe,WAAAC,EAAY,WAAAC,CAAW,EAAIJ,EACxD,KAAK,KAAOC,EACR,OAAOG,GAAe,YAAW,KAAK,WAAaA,GACnD,OAAOJ,EAAM,YAAe,YAC5B,KAAKvD,GAAcuD,EAAM,YACzB,OAAOA,EAAM,YAAe,YAC5B,KAAKtD,GAAcsD,EAAM,YACzB,MAAM,QAAQE,CAAa,IAC3B,KAAKtD,GAAiB,CAAC,GAAGsD,CAAa,GAGvC,MAAM,QAAQC,CAAU,IACxB,KAAKtD,GAAc,CAAC,GAAGsD,CAAU,GAGrC,KAAKrD,GACD,KAAKF,GAAe,KAAKyD,GAAKA,EAAE,OAAO,GACvC,KAAKxD,GAAY,KAAKyD,GAAKA,EAAE,OAAO,EAExC,KAAKvD,GACD,KAAKH,GAAe,SAAW,GAAK,KAAKC,GAAY,SAAW,EAEhE,OAAOmD,EAAM,YAAe,UAAYA,EAAM,aAC9C,KAAKhD,GAAc,CAAE,GAAGgD,EAAM,UAAW,GAGzCA,EAAM,eAAiB,SACvB,KAAK5C,GAAgB4C,EAAM,cAG3BA,EAAM,WACN,KAAK1C,GAAY,GACjB,KAAKD,GAAc2C,EAAM,YAGzB,OAAOA,EAAM,aAAgB,WAC7B,KAAKrD,GAAeqD,EAAM,aAG9B,KAAK7C,GACD,KAAK,qCACD6C,EAAM,uCACN,KAAK9C,EACT,CACR,CACJ","names":["TRANSACTION_SYMBOL","defaultNonTransactionalTypes","defaultTransactionOptions","child","t","transaction","initial","options","newProperties","deletedProperties","shouldNotWrapWithTransaction","isDirty","key","commit","result","value","childCommit","rollback","el","commitArray","isDirtyArray","val","index","proxy","target","property","k","prop","isTransaction","object","p","noopTransaction","obj","SchemaValidationError","errors","message","e","SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR","SYMBOL_HAS_PROPERTIES","createHybridErrorArray","items","seenValue","descriptor","SchemaBuilder","#isRequired","#isNullable","#isReadonly","#description","#preprocessors","#validators","#hasMutating","#canSkipPreValidation","#extensions","#type","#defaultRequiredErrorMessageProvider","#requiredErrorMessageProvider","#defaultValue","#catchValue","#hasCatch","#standardProps","self","value","result","#initPreValidation","object","context","doNotStopOnFirstError","resultingContext","needsTransaction","transaction","noopTransaction","#earlyFailResult","#validatorFailureErrors","index","name","validatorErrors","#buildPreValidationResult","trans","_e","i","state","preprocessingTransaction","preprocessedObject","currentPrepropIndex","entry","err","currentValidatorIndex","validatorResult","valid","text","_name","errorMessage","preprocessor","options","validator","catchValue","catchResult","provider","defaultValue","key","props","type","preprocessors","validators","isRequired","p","v"]}
|
package/dist/chunk-EUQ5AE3H.js
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{f as l}from"./chunk-CTP4RHDG.js";var a=class i extends l{static create(e){return new i({type:"function",...e})}constructor(e){super(e)}hasType(e){return this.createFromProps({...this.introspect()})}clearHasType(){return this.createFromProps({...this.introspect()})}#e(e){let{valid:t,transaction:s,errors:u}=e;if(!t)return{valid:t,errors:u};let{object:{validatedObject:n}}=s;return typeof n>"u"&&!this.isRequired||n===null&&(!this.isRequired||this.isNullable)?{valid:!0,object:n}:typeof n!="function"?{valid:!1,errors:[{message:`expected type function, but saw ${typeof n}`}]}:{valid:!0,object:n}}validate(e,t){return super.validate(e,t)}async validateAsync(e,t){return super.validateAsync(e,t)}_validate(e,t){return this.#e(this.preValidateSync(e,t))}async _validateAsync(e,t){return this.#e(await super.preValidateAsync(e,t))}createFromProps(e){return i.create(e)}required(e){return super.required(e)}optional(){return super.optional()}default(e){return super.default(e)}clearDefault(){return super.clearDefault()}brand(e){return super.brand(e)}readonly(){return super.readonly()}nullable(){return super.nullable()}notNullable(){return super.notNullable()}},o=()=>a.create({isRequired:!0});export{a,o as b};
|
|
2
|
-
//# sourceMappingURL=chunk-EUQ5AE3H.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/builders/FunctionSchemaBuilder.ts"],"sourcesContent":["import {\n type BRAND,\n SchemaBuilder,\n type ValidationContext,\n type ValidationErrorMessageProvider,\n type ValidationResult\n} from './SchemaBuilder.js';\n\ntype FunctionSchemaBuilderCreateProps<R extends boolean = true> = Partial<\n ReturnType<FunctionSchemaBuilder<R>['introspect']>\n>;\n\n/**\n * Schema builder for functions. Allows to define a schema for a function.\n * It can be: required or optional.\n *\n * **NOTE** this class is exported only to give opportunity to extend it\n * by inheriting. It is not recommended to create an instance of this class\n * directly. Use {@link func | func()} function instead.\n *\n * @example\n * ```ts\n * const schema = func();\n * const result = schema.validate(() => {});\n * // result.valid === true\n * // result.object === () => {}\n * ```\n *\n * @example\n * ```ts\n * const schema = func().optional();\n * const result = schema.validate(undefined);\n * // result.valid === true\n * // result.object === undefined\n * ```\n *\n * @see {@link func}\n */\nexport class FunctionSchemaBuilder<\n TRequired extends boolean = true,\n TNullable extends boolean = false,\n TExplicitType = undefined,\n THasDefault extends boolean = false,\n TExtensions = {},\n TResult = TExplicitType extends undefined\n ? (...args: any[]) => any\n : TExplicitType\n> extends SchemaBuilder<\n TResult,\n TRequired,\n TNullable,\n THasDefault,\n TExtensions\n> {\n /**\n * @hidden\n */\n public static create(props: FunctionSchemaBuilderCreateProps<any>) {\n return new FunctionSchemaBuilder({\n type: 'function',\n ...props\n });\n }\n\n protected constructor(props: FunctionSchemaBuilderCreateProps<TRequired>) {\n super(props as any);\n }\n\n /**\n * @hidden\n */\n public hasType<T>(\n _notUsed?: T\n ): FunctionSchemaBuilder<true, TNullable, T, THasDefault, TExtensions> &\n TExtensions {\n return this.createFromProps({\n ...this.introspect()\n } as any) as any;\n }\n\n /**\n * @hidden\n */\n public clearHasType(): FunctionSchemaBuilder<\n TRequired,\n TNullable,\n undefined,\n THasDefault,\n TExtensions\n > &\n TExtensions {\n return this.createFromProps({\n ...this.introspect()\n } as any) as any;\n }\n\n #buildResult(\n superResult: ReturnType<FunctionSchemaBuilder['preValidateSync']>\n ): ValidationResult<TResult> {\n const {\n valid,\n transaction: preValidationTransaction,\n errors\n } = superResult;\n\n if (!valid) {\n return { valid, errors };\n }\n\n const {\n object: { validatedObject: objToValidate }\n } = preValidationTransaction!;\n\n if (\n (typeof objToValidate === 'undefined' && !this.isRequired) ||\n (objToValidate === null && (!this.isRequired || this.isNullable))\n ) {\n return {\n valid: true,\n object: objToValidate\n };\n }\n\n if (typeof objToValidate !== 'function') {\n return {\n valid: false,\n errors: [\n {\n message: `expected type function, but saw ${typeof objToValidate}`\n }\n ]\n };\n }\n\n return {\n valid: true,\n object: objToValidate\n };\n }\n\n /** {@inheritDoc SchemaBuilder.validate} */\n public validate(\n object: TResult,\n context?: ValidationContext\n ): ValidationResult<TResult> {\n return super.validate(object, context) as ValidationResult<TResult>;\n }\n\n /** {@inheritDoc SchemaBuilder.validateAsync} */\n public async validateAsync(\n object: TResult,\n context?: ValidationContext\n ): Promise<ValidationResult<TResult>> {\n return super.validateAsync(object, context) as Promise<\n ValidationResult<TResult>\n >;\n }\n\n /**\n * Performs synchronous validation of the schema over `object`.\n * Throws if any preprocessor, validator, or error message provider returns a Promise.\n * @param context Optional `ValidationContext` settings.\n */\n protected _validate(\n object: TResult,\n context?: ValidationContext\n ): ValidationResult<TResult> {\n return this.#buildResult(this.preValidateSync(object, context));\n }\n\n /**\n * Performs async validation of the schema over `object`.\n * Supports async preprocessors, validators, and error message providers.\n * @param context Optional `ValidationContext` settings.\n */\n protected async _validateAsync(\n object: TResult,\n context?: ValidationContext\n ): Promise<ValidationResult<TResult>> {\n return this.#buildResult(await super.preValidateAsync(object, context));\n }\n\n protected createFromProps<TReq extends boolean>(\n props: FunctionSchemaBuilderCreateProps<TReq>\n ): this {\n return FunctionSchemaBuilder.create(props as any) as any;\n }\n\n /**\n * @hidden\n */\n public required(\n errorMessage?: ValidationErrorMessageProvider\n ): FunctionSchemaBuilder<\n true,\n TNullable,\n TExplicitType,\n THasDefault,\n TExtensions\n > &\n TExtensions {\n return super.required(errorMessage);\n }\n\n /**\n * @hidden\n */\n public optional(): FunctionSchemaBuilder<\n false,\n TNullable,\n TExplicitType,\n THasDefault,\n TExtensions\n > &\n TExtensions {\n return super.optional();\n }\n\n /**\n * @hidden\n */\n public default(\n value: TResult | (() => TResult)\n ): FunctionSchemaBuilder<\n true,\n TNullable,\n TExplicitType,\n true,\n TExtensions\n > &\n TExtensions {\n return super.default(value) as any;\n }\n\n /**\n * @hidden\n */\n public clearDefault(): FunctionSchemaBuilder<\n TRequired,\n TNullable,\n TExplicitType,\n false,\n TExtensions\n > &\n TExtensions {\n return super.clearDefault() as any;\n }\n\n /**\n * @hidden\n */\n public brand<TBrand extends string | symbol>(\n _name?: TBrand\n ): FunctionSchemaBuilder<\n TRequired,\n TNullable,\n TResult & { readonly [K in BRAND]: TBrand },\n THasDefault,\n TExtensions\n > &\n TExtensions {\n return super.brand(_name);\n }\n\n /**\n * Marks the inferred type as `Readonly<Function>`. Sets the\n * `isReadonly` introspection flag for tooling consistency.\n *\n * @see {@link SchemaBuilder.readonly}\n */\n public readonly(): FunctionSchemaBuilder<\n TRequired,\n TNullable,\n Readonly<TResult>,\n THasDefault,\n TExtensions\n > &\n TExtensions {\n return super.readonly();\n }\n\n /**\n * @hidden\n */\n public nullable(): FunctionSchemaBuilder<\n TRequired,\n true,\n TExplicitType,\n THasDefault,\n TExtensions\n > &\n TExtensions {\n return super.nullable() as any;\n }\n\n /**\n * @hidden\n */\n public notNullable(): FunctionSchemaBuilder<\n TRequired,\n false,\n TExplicitType,\n THasDefault,\n TExtensions\n > &\n TExtensions {\n return super.notNullable() as any;\n }\n}\n\n/**\n * Creates a `function` schema.\n * @returns {@link FunctionSchemaBuilder}\n */\nexport const func = () =>\n FunctionSchemaBuilder.create({\n isRequired: true\n }) as FunctionSchemaBuilder<true>;\n"],"mappings":"wCAsCO,IAAMA,EAAN,MAAMC,UASHC,CAMR,CAIE,OAAc,OAAOC,EAA8C,CAC/D,OAAO,IAAIF,EAAsB,CAC7B,KAAM,WACN,GAAGE,CACP,CAAC,CACL,CAEU,YAAYA,EAAoD,CACtE,MAAMA,CAAY,CACtB,CAKO,QACHC,EAEY,CACZ,OAAO,KAAK,gBAAgB,CACxB,GAAG,KAAK,WAAW,CACvB,CAAQ,CACZ,CAKO,cAOS,CACZ,OAAO,KAAK,gBAAgB,CACxB,GAAG,KAAK,WAAW,CACvB,CAAQ,CACZ,CAEAC,GACIC,EACyB,CACzB,GAAM,CACF,MAAAC,EACA,YAAaC,EACb,OAAAC,CACJ,EAAIH,EAEJ,GAAI,CAACC,EACD,MAAO,CAAE,MAAAA,EAAO,OAAAE,CAAO,EAG3B,GAAM,CACF,OAAQ,CAAE,gBAAiBC,CAAc,CAC7C,EAAIF,EAEJ,OACK,OAAOE,EAAkB,KAAe,CAAC,KAAK,YAC9CA,IAAkB,OAAS,CAAC,KAAK,YAAc,KAAK,YAE9C,CACH,MAAO,GACP,OAAQA,CACZ,EAGA,OAAOA,GAAkB,WAClB,CACH,MAAO,GACP,OAAQ,CACJ,CACI,QAAS,mCAAmC,OAAOA,CAAa,EACpE,CACJ,CACJ,EAGG,CACH,MAAO,GACP,OAAQA,CACZ,CACJ,CAGO,SACHC,EACAC,EACyB,CACzB,OAAO,MAAM,SAASD,EAAQC,CAAO,CACzC,CAGA,MAAa,cACTD,EACAC,EACkC,CAClC,OAAO,MAAM,cAAcD,EAAQC,CAAO,CAG9C,CAOU,UACND,EACAC,EACyB,CACzB,OAAO,KAAKP,GAAa,KAAK,gBAAgBM,EAAQC,CAAO,CAAC,CAClE,CAOA,MAAgB,eACZD,EACAC,EACkC,CAClC,OAAO,KAAKP,GAAa,MAAM,MAAM,iBAAiBM,EAAQC,CAAO,CAAC,CAC1E,CAEU,gBACNT,EACI,CACJ,OAAOF,EAAsB,OAAOE,CAAY,CACpD,CAKO,SACHU,EAQY,CACZ,OAAO,MAAM,SAASA,CAAY,CACtC,CAKO,UAOS,CACZ,OAAO,MAAM,SAAS,CAC1B,CAKO,QACHC,EAQY,CACZ,OAAO,MAAM,QAAQA,CAAK,CAC9B,CAKO,cAOS,CACZ,OAAO,MAAM,aAAa,CAC9B,CAKO,MACHC,EAQY,CACZ,OAAO,MAAM,MAAMA,CAAK,CAC5B,CAQO,UAOS,CACZ,OAAO,MAAM,SAAS,CAC1B,CAKO,UAOS,CACZ,OAAO,MAAM,SAAS,CAC1B,CAKO,aAOS,CACZ,OAAO,MAAM,YAAY,CAC7B,CACJ,EAMaC,EAAO,IAChBhB,EAAsB,OAAO,CACzB,WAAY,EAChB,CAAC","names":["FunctionSchemaBuilder","_FunctionSchemaBuilder","SchemaBuilder","props","_notUsed","#buildResult","superResult","valid","preValidationTransaction","errors","objToValidate","object","context","errorMessage","value","_name","func"]}
|
package/dist/chunk-NXPH3ZUW.js
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{c as f,d as j,f as R}from"./chunk-CTP4RHDG.js";var E=class{#e;#r;#t=[];#n=[];get seenValue(){let e=this.#e[f].getValue(this.#r);return e.success?e.value:void 0}get errors(){return this.#t}get isValid(){return this.#t.length===0&&this.getChildErrors().length===0}getChildErrors(){return this.#n}get descriptor(){return this.#e[f]}constructor(e,r,t){if(!x.isValidPropertyDescriptor(e))throw new Error("Invalid property descriptor");this.#e=e,this.#t=Array.isArray(t)?[...t]:[],this.#r=r}addError(e){this.#t.push(e)}addChildError(e){this.#n.push(e)}toJSON(){return{isValid:this.isValid,errors:this.errors}}};var B="must be an object",x=class c extends R{#e={};#r=!1;#t=[];[j]=!0;#n=new WeakMap;static create(e){return new c({type:"object",...e})}createFromProps(e){return c.create(e)}constructor(e){super(e),typeof e.properties=="object"&&e.properties&&(this.#e=e.properties,this.#t=Object.keys(e.properties)),typeof e.acceptUnknownProps=="boolean"&&(this.#r=e.acceptUnknownProps)}introspect(){return{...super.introspect(),properties:{...this.#e},acceptUnknownProps:this.#r}}required(e){return super.required(e)}optional(){return super.optional()}default(e){return super.default(e)}clearDefault(){return super.clearDefault()}brand(e){return super.brand(e)}readonly(){return super.readonly()}#a(e){c.isValidPropertyDescriptor(e?.context?.rootPropertyDescriptor)||(e.context.rootPropertyDescriptor=c.getPropertiesFor(this)),c.isValidPropertyDescriptor(e.context.currentPropertyDescriptor)||(e.context.currentPropertyDescriptor=e.context.rootPropertyDescriptor),!e.context.rootValidationObject&&e.transaction?.object?.validatedObject&&(e.context.rootValidationObject=e.transaction.object.validatedObject)}preValidateSync(e,r){let t=super.preValidateSync(e,r);return this.#a(t),t}async preValidateAsync(e,r){let t=await super.preValidateAsync(e,r);return this.#a(t),t}#s(e){let{valid:r,context:t,transaction:n,errors:o}=e,i=new WeakMap,{doNotStopOnFirstError:p,rootValidationObject:y}=t,a=t.rootPropertyDescriptor,s=t.currentPropertyDescriptor,T=(h,m,b)=>{if(!c.isValidPropertyDescriptor(h))throw new Error("invalid property descriptor");let S=i.has(h)?i.get(h):null;if(S||(S=new E(h,y),i.set(h,S)),S.addError(m),b&&c.isValidPropertyDescriptor(b)){let D=i.has(b)?i.get(b):null;D||(D=new E(b,y),i.set(b,D)),D.addChildError(S)}},d=(h=>{let m=typeof h=="function"?h(s):s;if(!c.isValidPropertyDescriptor(m))throw new Error("invalid property descriptor");return i.has(m)||i.set(m,new E(m,y)),i.get(m)}),l=e.errors||[];if(!r&&!p&&o){if(c.isValidPropertyDescriptor(s))for(let h of o)T(s,h.message);return{earlyReturn:!0,result:{valid:r,errors:o,getErrorsFor:d}}}let{object:{validatedObject:u}}=n;if(typeof u>"u"&&!this.isRequired||u===null&&(!this.isRequired||this.isNullable))return{earlyReturn:!0,result:{valid:!0,object:n.commit().validatedObject,getErrorsFor:d}};if(typeof u!="object"&&(l.push({message:B}),T(s,B),!p))return n&&n.rollback(),{earlyReturn:!0,result:{valid:!1,errors:[l[0]],getErrorsFor:d}};let P=this.#t,g=Object.keys(u);if(P.length===0){if(g.length===0)return p&&l.length>0?{earlyReturn:!0,result:{valid:!1,errors:l,getErrorsFor:d}}:(n&&n.commit().validatedObject,{earlyReturn:!0,result:{valid:!0,object:{},getErrorsFor:d}});if(!this.#r){for(let h=0;h<g.length;h++){let m=`unknown property '${g[h]}'`;if(l.push({message:m}),!p)break}return n&&n.rollback(),{earlyReturn:!0,result:{valid:!1,errors:p?l:[l[0]],getErrorsFor:d}}}return n&&n.commit(),{earlyReturn:!0,result:{valid:!0,object:{...u},getErrorsFor:d}}}return{earlyReturn:!1,errors:l,objToValidate:u,propKeys:P,objKeys:g,addErrorFor:T,getErrorsFor:d,doNotStopOnFirstError:!!p,rootPropertyDescriptor:a,currentPropertyDescriptor:s,validationTransaction:n}}#o(e,r){let{objToValidate:t,objKeys:n,addErrorFor:o,getErrorsFor:i,doNotStopOnFirstError:p,currentPropertyDescriptor:y,validationTransaction:a}=e,s=e.errors,T=!1;for(let{result:d}of r)if(!d.valid&&(T=!0,Array.isArray(d.errors)))for(let l of d.errors)s.push(l);for(let d=0;d<n.length;d++){let l=n[d];if(!(l in this.#e)&&!this.#r){let u=`unknown property '${l}'`;if(s.push({message:u}),o(y,u),!p)return a&&a.rollback(),{valid:!1,errors:[s[0]],getErrorsFor:i}}}if(!T&&s.length===0){let d={};for(let{key:l,result:u}of r)d[l]=u.object;if(this.#r)for(let l of n)l in this.#e||(d[l]=t[l]);return{valid:!0,object:d,getErrorsFor:i}}for(let{key:d,result:l}of r)if(!l.valid){let u=y[d];if(typeof l.getErrorsFor=="function"&&c.isValidPropertyDescriptor(u)){if(c.#y(l,u,o),Array.isArray(l.__externErrorPropertyNames)&&Array.isArray(l.errors))for(let P of l.errors)o(u,P.message,y)}else if(Array.isArray(l.errors)&&c.isValidPropertyDescriptor(u))for(let P of l.errors)o(u,P.message)}return a.rollback(),{valid:!1,errors:p?s:s[0]?[s[0]]:[],getErrorsFor:i}}validate(e,r){return super.validate(e,r)}async validateAsync(e,r){return super.validateAsync(e,r)}_validate(e,r){if(this.canSkipPreValidation&&!r?.doNotStopOnFirstError&&!r?.rootPropertyDescriptor){if(typeof e>"u"||e===null)if(typeof e>"u"&&this.hasDefault)e=this.resolveDefaultValue();else if(!this.isRequired||e===null&&this.isNullable){let t=this;return{valid:!0,object:e,getErrorsFor(n){return t.#i(e,r).getErrorsFor(n)}}}else{let t=this;return{valid:!1,errors:[{message:this.getValidationErrorMessageSync(this.requiredErrorMessage,e)}],getErrorsFor(n){return t.#i(e,r).getErrorsFor(n)}}}else if(typeof e=="object"){let t=this.#t;if(!this.#r){let i=Object.keys(e);for(let p=0;p<i.length;p++)if(!(i[p]in this.#e)){let y=this;return{valid:!1,errors:[{message:`unknown property '${i[p]}'`}],getErrorsFor(a){return y.#i(e,r).getErrorsFor(a)}}}}let n={};for(let i=0;i<t.length;i++){let p=t[i],y=this.#e[p].validate(e[p]);if(!y.valid){let a=this;return{valid:!1,errors:y.errors&&y.errors.length>0?[y.errors[0]]:[],getErrorsFor(s){return a.#i(e,r).getErrorsFor(s)}}}n[p]=y.object}if(this.#r){let i=Object.keys(e);for(let p=0;p<i.length;p++)i[p]in this.#e||(n[i[p]]=e[i[p]])}let o=this;return{valid:!0,object:n,getErrorsFor(i){return o.#i(e,r).getErrorsFor(i)}}}}return this.#i(e,r)}#i(e,r){let t=this.#s(this.preValidateSync(e,r));if(t.earlyReturn)return t.result;let{propKeys:n,objToValidate:o,doNotStopOnFirstError:i,rootPropertyDescriptor:p,currentPropertyDescriptor:y}=t,a=[];for(let s of n){let T=this.#e[s].validate(o[s],{...r,rootPropertyDescriptor:p,currentPropertyDescriptor:y[s]});if(a.push({key:s,result:T}),!T.valid&&!i)break}return this.#o(t,a)}async _validateAsync(e,r){let t=this.#s(await this.preValidateAsync(e,r));if(t.earlyReturn)return t.result;let{propKeys:n,objToValidate:o,doNotStopOnFirstError:i,rootPropertyDescriptor:p,currentPropertyDescriptor:y}=t,a=[];if(i){let s=await Promise.all(n.map(async T=>{let d=await this.#e[T].validateAsync(o[T],{...r,rootPropertyDescriptor:p,currentPropertyDescriptor:y[T]});return{key:T,result:d}}));a.push(...s)}else for(let s of n){let T=await this.#e[s].validateAsync(o[s],{...r,rootPropertyDescriptor:p,currentPropertyDescriptor:y[s]});if(a.push({key:s,result:T}),!T.valid)break}return this.#o(t,a)}acceptUnknownProps(){return this.createFromProps({...this.introspect(),acceptUnknownProps:!0})}notAcceptUnknownProps(){return this.createFromProps({...this.introspect(),acceptUnknownProps:!1})}hasType(e){return this.createFromProps({...this.introspect()})}clearHasType(){return this.createFromProps({...this.introspect()})}addProp(e,r){if(typeof e!="string"||!e)throw new Error("propName must be a non empty string");if(e in this.#e)throw new Error(`Property ${e} already exists`);if(!(r instanceof R))throw new Error("schema must be an instance of the SchemaBuilder class");return this.createFromProps({...this.introspect(),properties:{...this.introspect().properties,[e]:r}})}optimize(){return this.createFromProps({...this.introspect()})}addProps(e){if(e instanceof c)return this.addProps(e.introspect().properties);if(typeof e!="object")throw new Error("props should be an object");if(e===null)throw new Error("props should not be null");let r={...this.#e};for(let t in e){if(t in this.#e)throw new Error(`property '${t}' already exists`);if(!(e[t]instanceof R))throw new Error(`${t} is not a SchemaBuilder`);r[t]=e[t]}return this.createFromProps({...this.introspect(),properties:r})}omit(e){if(typeof e=="string"){let r=e;if(!r||!(r in this.#e))throw new Error(`property ${r.toString()} does not exists in the schema`);return this.createFromProps({...this.introspect(),properties:(()=>{let t={...this.#e};return delete t[r],t})()})}else if(Array.isArray(e)){let r=e,t=new Map;if(r.forEach(o=>{if(typeof o!="string"||!o)throw new Error("property name must be a string");if(!(o in this.#e))throw new Error(`property ${o.toString()} does not exists in the schema`);t.set(o.toString(),!0)}),t.size===0)throw new Error("please provide at least one property to omit");let n={...this.introspect()};for(let o of t.keys())delete n.properties[o];return this.createFromProps(n)}else if(e instanceof c){let r={...e.introspect().properties},t={...this.introspect()};for(let n in r)n in t.properties&&delete t.properties[n];return this.createFromProps(t)}throw new Error("this parameter type is not supported")}intersect(e){if(!(e instanceof c))throw new Error("schema must be an instance of the ObjectSchemaBuilder class");let r=e.introspect().properties,t=this.introspect(),n=Object.keys(t.properties).reduce((o,i)=>(o[i]=i in r?r[i]:t.properties[i],o),{});return this.createFromProps({...this.introspect(),properties:n})}partial(e){if(typeof e>"u"||e===null)return this.createFromProps({...this.introspect(),properties:Object.keys(this.#e).reduce((r,t)=>(r[t]=this.#e[t].optional(),r),{})});if(Array.isArray(e)){let r=e;if(r.length===0)throw new Error("properties cannot be empty");let t={...this.introspect()};return r.forEach(n=>{if(typeof n!="string")throw new Error("each propery in property list must be as string value");if(!(n in t.properties))throw new Error(`property ${n} does not exists`);t.properties[n]=t.properties[n].optional()}),this.createFromProps(t)}if(typeof e=="string")return this.modifyPropSchema(e,r=>r.optional());throw new Error("expecting string or string[] parameter")}deepPartial(){let e={};for(let r of Object.keys(this.#e)){let t=this.#e[r];t instanceof c?e[r]=t.deepPartial().optional():e[r]=t.optional()}return this.createFromProps({...this.introspect(),properties:e})}pick(e){if(typeof e=="string"){let r=e;if(!r)throw new Error("property cannot be empty");if(!(r in this.#e))throw new Error(`property ${r} does not exists`);return this.createFromProps({...this.introspect(),properties:{[r]:this.#e[r]}})}if(Array.isArray(e)){if(e.length===0)throw new Error("properties must be a non empty erray");let r=e.reduce((t,n)=>{if(typeof n!="string"||!n)throw new Error("each property name must be a non empty string");if(!(n in this.#e))throw new Error(`property ${n} does not exists`);return t[n]=this.#e[n],t},{});return this.createFromProps({...this.introspect(),properties:r})}if(e instanceof c){let t=Object.keys(e.introspect().properties).filter(n=>typeof this.#e[n]<"u");if(t.length===0)throw new Error("there are no common properties in provided schemas");return this.pick(t)}throw new Error("string, array or ObjectSchemaBuilder is expected")}modifyPropSchema(e,r){if(typeof e!="string"||!e)throw new Error("propName must be a non empty string");if(!(e in this.#e))throw new Error(`property ${e} does not exists in the schema`);if(typeof r!="function")throw new Error("callback must be a function");let t=r(this.#e[e]);if(!(t instanceof R))throw new Error("callback must return a SchemaBuilder object");let n={...this.introspect()};return n.properties={...n.properties,[e]:t},this.createFromProps(n)}makePropOptional(e){return this.modifyPropSchema(e,r=>r.optional())}makePropRequired(e){return this.modifyPropSchema(e,r=>r.required())}makeAllPropsOptional(){return this.createFromProps({...this.introspect(),properties:Object.keys(this.#e).reduce((e,r)=>(e[r]=this.#e[r].optional(),e),{})})}makeAllPropsRequired(){return this.createFromProps({...this.introspect(),properties:Object.keys(this.#e).reduce((e,r)=>(e[r]=this.#e[r].required(),e),{})})}static#p(e,r,t,n,o){let i=e.introspect();if(!i.properties)return{};let p=Object.keys(i.properties);if(p.length===0)return{};typeof r!="function"&&(r=a=>a);let y=O((a,s)=>(t||r)(a,s),n,e,o);for(let a of p){let s=i.properties[a];if(s instanceof c){let T=s.introspect().properties;T&&typeof T=="object"&&Object.keys(T).length>0?y[a]=c.#p(s,(d,l)=>{let u=r(d,l);return u?(l&&!u[a]&&(u[a]={}),u[a]):null},r,a,y[f]):y[a]=O(r,a,s,y[f])}else if(s[j]===!0){let T=O(r,a,s,y[f]),d=(l,u)=>{let P=r(l,u);return P?(u&&!P[a]&&(P[a]={}),P[a]):null};y[a]=w(T,d)}else y[a]=O(r,a,s,y[f])}return y}static getPropertiesFor(e){if(!(e instanceof c))throw new Error("schema must be an instance of the ObjectSchemaBuilder class");if(e.#n.has(e))return e.#n.get(e);let r=c.#p(e);return e.#n.set(e,r),r}static isValidPropertyDescriptor(e){return typeof e=="object"&&e!==null&&typeof e[f]=="object"}static#y(e,r,t){let o=c.#c(r).introspect().properties,i;if(o)i=Object.keys(o);else if(Array.isArray(e.__externErrorPropertyNames))i=e.__externErrorPropertyNames;else return;for(let p of i){let y=r[p];if(!c.isValidPropertyDescriptor(y))continue;let a=e.getErrorsFor(()=>y);if(!a.isValid)for(let s of a.errors)t(y,s,r);if(o){let s=o[p];(s instanceof c||s[j]===!0)&&typeof e.getErrorsFor=="function"&&c.isValidPropertyDescriptor(y)&&c.#y(e,y,t)}}}static#c(e){if(!c.isValidPropertyDescriptor(e))throw new Error("descriptor is not a valid property descriptor");return e[f].getSchema()}nullable(){return super.nullable()}notNullable(){return super.notNullable()}},k=(c=>x.create({isRequired:!0,properties:c})),O=(c,e,r,t)=>({[f]:{setValue:(n,o,i)=>{let p=c(n,!!i?.createMissingStructure);return p?(typeof e=="string"&&(p[e]=o),!0):!1},getValue:n=>{let o=c(n,!1);return o?typeof e!="string"?{success:!0,value:o}:Object.hasOwn(o,e)?{success:!0,value:o[e]}:{success:!1}:{success:!1}},getSchema:()=>r,parent:t}}),w=(c,e)=>new Proxy(c,{get(r,t,n){if(t===f)return r[f];if(typeof t=="string"&&!(t in r)){let o=O(e,t,void 0,r[f]),i=(p,y)=>{let a=e(p,y);return a!=null&&typeof a=="object"?(y&&!(t in a)&&(a[t]={}),a[t]):null};r[t]=w(o,i)}return Reflect.get(r,t,n)}});k.getPropertiesFor=c=>x.getPropertiesFor(c);k.isValidPropertyDescriptor=x.isValidPropertyDescriptor;export{x as a,k as b};
|
|
2
|
-
//# sourceMappingURL=chunk-NXPH3ZUW.js.map
|