import type { Schema, Infer } from '../base.ts'; import { success, createParseMethods, SCHEMA_KIND } from '../base.ts'; /** * Schema for optional values (T | undefined). * Accepts undefined or the wrapped schema's type. * * @template T - The wrapped schema type * * @example * ```typescript * const schema = s.optional(s.string()); * schema.parse('hello'); // 'hello' * schema.parse(undefined); // undefined * schema.parse(123); // throws ValidationError * ``` */ // eslint-disable-next-line @typescript-eslint/no-explicit-any export class OptionalSchema> implements Schema | undefined, Infer | undefined> { readonly [SCHEMA_KIND] = 'OptionalSchema'; readonly schema: T; description?: string; readonly '~standard' = { version: 1 as const, vendor: 'agentuity', validate: (value: unknown) => { if (value === undefined) { return success(undefined as Infer | undefined); } return this.schema['~standard'].validate(value); }, types: undefined as unknown as { input: Infer | undefined; output: Infer | undefined }, }; // Type-safe parse methods for this instance private parseMethods = createParseMethods | undefined>(); constructor(schema: T) { this.schema = schema; } describe(description: string): this { this.description = description; return this; } optional() { return this; // Already optional } nullable(): Schema | undefined | null, Infer | undefined | null> { // Import here to avoid circular dependency // eslint-disable-next-line @typescript-eslint/no-require-imports const { nullable } = require('./nullable.js'); return nullable(this); } parse = this.parseMethods.parse; safeParse = this.parseMethods.safeParse; } /** * Make a schema optional (T | undefined). * * @param schema - The schema to make optional * * @example * ```typescript * const userSchema = s.object({ * name: s.string(), * nickname: s.optional(s.string()) * }); * ``` */ // eslint-disable-next-line @typescript-eslint/no-explicit-any export function optional>(schema: T): OptionalSchema { return new OptionalSchema(schema); }