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