UNPKG

fortify-schema

Version:

TypeScript interface-like schema validation system that's easier to use than Zod

203 lines (188 loc) 4.77 kB
import { StringSchema } from "./StringSchema"; import { NumberSchema } from "./NumberSchema"; import { BooleanSchema } from "./BooleanSchema"; import { ArraySchema } from "./ArraySchema"; import { ObjectSchema } from "./ObjectSchema"; import { BaseSchema } from "./BaseSchema"; /** * Main Schema factory - TypeScript-like schema validation * * Provides a clean, modular API for creating validation schemas without * mixing validation logic with schema definition logic. * * @example * ```typescript * import { Schema } from "fortify-schema"; * * // Define a user schema * const UserSchema = Schema.object({ * id: Schema.number().int().positive(), * email: Schema.string().email(), * name: Schema.string().min(2).max(50), * age: Schema.number().int().min(0).max(120).optional(), * isActive: Schema.boolean().default(true), * tags: Schema.array(Schema.string()).max(10).optional() * }); * * // Validate data * const result = UserSchema.safeParse({ * id: 1, * email: 'user@example.com', * name: 'John Doe', * isActive: true * }); * * if (result.success) { * console.log('Valid user:', result.data); * } else { * console.log('Validation errors:', result.errors); * } * ``` */ export const Schema = { /** * Create a string schema * * @example * ```typescript * const nameSchema = Schema.string().min(2).max(50); * const emailSchema = Schema.string().email(); * const slugSchema = Schema.string().slug(); * ``` */ string(): StringSchema { return new StringSchema(); }, /** * Create a number schema * * @example * ```typescript * const ageSchema = Schema.number().int().min(0).max(120); * const priceSchema = Schema.number().positive().precision(2); * const idSchema = Schema.number().int().positive(); * ``` */ number(): NumberSchema { return new NumberSchema(); }, /** * Create a boolean schema * * @example * ```typescript * const activeSchema = Schema.boolean().default(true); * const strictBoolSchema = Schema.boolean().strict(); * ``` */ boolean(): BooleanSchema { return new BooleanSchema(); }, /** * Create an array schema * * @example * ```typescript * const tagsSchema = Schema.array(Schema.string()).min(1).max(10); * const numbersSchema = Schema.array(Schema.number()).unique(); * const usersSchema = Schema.array(UserSchema); * ``` */ array<T>(elementSchema: BaseSchema<T>): ArraySchema<T> { return new ArraySchema(elementSchema); }, /** * Create an object schema * * @example * ```typescript * const userSchema = Schema.object({ * id: Schema.number().int(), * name: Schema.string(), * email: Schema.string().email() * }); * * const strictSchema = Schema.object({ * id: Schema.number() * }).strict(); // No extra properties * ``` */ object<T extends Record<string, any>>(shape: { [K in keyof T]: BaseSchema<T[K]>; }): ObjectSchema<T> { return new ObjectSchema(shape); }, /** * Create a custom schema with validation function * * @example * ```typescript * const customSchema = Schema.custom<string>((value) => { * if (typeof value !== 'string') { * throw new Error('Expected string'); * } * if (!value.startsWith('custom_')) { * throw new Error('Must start with custom_'); * } * return value; * }); * ``` */ custom<T>(validator: (value: any) => T): BaseSchema<T> { return new CustomSchema(validator); }, }; /** * Custom schema implementation */ class CustomSchema<T> extends BaseSchema<T> { constructor(private validator: (value: any) => T) { super(); } validate(value: any) { // Handle common validation (undefined/null) const commonResult = this.handleCommonValidation(value); if (commonResult) { return commonResult; } const result = { success: true, errors: [] as string[], warnings: [] as string[], data: undefined as T | undefined, }; try { result.data = this.validator(value); } catch (error) { result.success = false; result.errors.push((error as Error).message); } return result; } getConfig() { return { type: "custom", optional: this._optional, nullable: this._nullable, default: this._default, }; } } // Re-export all schema types for convenience export { BaseSchema, StringSchema, NumberSchema, BooleanSchema, ArraySchema, ObjectSchema, }; // Re-export types export type { SchemaValidationResult, StringSchemaOptions, NumberSchemaOptions, BooleanSchemaOptions, ArraySchemaOptions, ObjectSchemaOptions, } from "../../../types/types";