fortify-schema
Version:
TypeScript interface-like schema validation system that's easier to use than Zod
1,591 lines (1,559 loc) • 62.6 kB
TypeScript
/**
* Constant value wrapper to distinguish from string types
*/
interface ConstantValue {
const: string | number | boolean;
}
/**
* Union value wrapper for proper type inference
*/
interface UnionValue<T extends readonly string[] = readonly string[]> {
union: T;
}
/**
* Optional constant value wrapper
*/
interface OptionalConstantValue {
const: string | number | boolean;
optional: true;
}
/**
* Optional schema interface wrapper
*/
interface OptionalSchemaInterface {
optional: true;
schema: SchemaInterface;
}
/**
* Schema definition using TypeScript-like interface syntax
*/
interface SchemaInterface {
[key: string]: SchemaFieldType | ConstantValue | OptionalConstantValue | SchemaInterface | SchemaInterface[] | any;
}
/**
* Field type definitions using string literals and objects
*/
type SchemaFieldType = "string" | "string?" | "number" | "number?" | "boolean" | "boolean?" | "date" | "date?" | "any" | "any?" | "email" | "email?" | "url" | "url?" | "uuid" | "uuid?" | "phone" | "phone?" | "slug" | "slug?" | "username" | "username?" | "int" | "int?" | "positive" | "positive?" | "float" | "float?" | "string[]" | "string[]?" | "number[]" | "number[]?" | "boolean[]" | "boolean[]?" | "int[]" | "int[]?" | "email[]" | "email[]?" | "url[]" | "url[]?" | string | ConstantValue | OptionalConstantValue | UnionValue | SchemaInterface | SchemaInterface[] | OptionalSchemaInterface;
/**
* Schema validation options for fine-tuning
*/
interface SchemaOptions {
minLength?: number;
maxLength?: number;
pattern?: RegExp;
min?: number;
max?: number;
precision?: number;
minItems?: number;
maxItems?: number;
unique?: boolean;
strict?: boolean;
allowUnknown?: boolean;
required?: boolean;
default?: any;
loose?: boolean;
}
/**
* Core types and interfaces for the FortifyJS Schema system
*/
/**
* Schema validation result
*/
interface SchemaValidationResult<T = any> {
success: boolean;
data?: T;
errors: string[];
warnings: string[];
}
/**
* Base schema configuration options
*/
interface BaseSchemaOptions {
optional?: boolean;
nullable?: boolean;
default?: any;
}
/**
* String schema validation options
*/
interface StringSchemaOptions extends BaseSchemaOptions {
minLength?: number;
maxLength?: number;
pattern?: RegExp;
format?: "email" | "url" | "uuid" | "phone" | "slug" | "username";
}
/**
* Number schema validation options
*/
interface NumberSchemaOptions extends BaseSchemaOptions {
min?: number;
max?: number;
integer?: boolean;
positive?: boolean;
precision?: number;
}
/**
* Boolean schema validation options
*/
interface BooleanSchemaOptions extends BaseSchemaOptions {
strict?: boolean;
}
/**
* Array schema validation options
*/
interface ArraySchemaOptions extends BaseSchemaOptions {
minLength?: number;
maxLength?: number;
unique?: boolean;
}
/**
* Object schema validation options
*/
interface ObjectSchemaOptions extends BaseSchemaOptions {
strict?: boolean;
allowUnknown?: boolean;
}
/**
* Schema type definitions
*/
type SchemaType = "string" | "number" | "boolean" | "array" | "object" | "date" | "any";
/**
* Schema definition for object properties
*/
type SchemaDefinition = {
[key: string]: SchemaConfig;
};
/**
* Complete schema configuration
*/
interface SchemaConfig {
type: SchemaType;
options?: BaseSchemaOptions;
elementSchema?: SchemaConfig;
properties?: SchemaDefinition;
validator?: (value: any) => void;
}
/**
* TypeScript Interface-like Schema Definition System
*
* Allows defining schemas using TypeScript-like syntax with string literals
* that feel natural and are much easier to read and write.
*/
/**
* Interface Schema class for TypeScript-like schema definitions
*/
type AllowUnknownSchema<T> = T & Record<string, any>;
declare class InterfaceSchema<T = any> {
private definition;
private options;
constructor(definition: SchemaInterface, options?: SchemaOptions);
/**
* Validate data against the interface schema
*/
validate(data: any): SchemaValidationResult<T>;
/**
* Validate individual field
*/
private validateField;
/**
* Validate string-based field types
*/
private validateStringFieldType;
/**
* Validate basic types with enhanced constraints
*/
private validateBasicType;
/**
* Validate conditional field with full data context
*/
private validateConditionalFieldWithContext;
/**
* Evaluate a condition against a field value
*/
private evaluateCondition;
/**
* Validate conditional field based on other field values (legacy method)
*
* Note: This method is used when conditional validation is called without
* full data context. It provides a fallback validation approach.
*/
private validateConditionalField;
/**
* Helper method to validate a value against a schema type
*/
private validateSchemaType;
/**
* Parse and validate (throws on error)
*/
parse(data: T): T;
/**
* Safe parse (returns result object) - strictly typed input
*/
safeParse(data: T): SchemaValidationResult<T>;
/**
* Safe parse with unknown data (for testing invalid inputs)
* Use this when you need to test data that might not match the schema
*/
safeParseUnknown(data: unknown): SchemaValidationResult<T>;
/**
* Set schema options
*/
withOptions(opts: SchemaOptions): InterfaceSchema<T>;
/**
* Enable strict mode (no unknown properties allowed)
*/
strict(): InterfaceSchema<T>;
/**
* Enable loose mode (allow type coercion)
*/
loose(): InterfaceSchema<T>;
/**
* Allow unknown properties (not strict about extra fields)
* Returns a schema that accepts extra properties beyond the defined interface
*/
allowUnknown(): InterfaceSchema<AllowUnknownSchema<T>>;
/**
* Set minimum constraints
*/
min(value: number): InterfaceSchema<T>;
/**
* Set maximum constraints
*/
max(value: number): InterfaceSchema<T>;
/**
* Require unique array values
*/
unique(): InterfaceSchema<T>;
/**
* Set pattern for string validation
*/
pattern(regex: RegExp): InterfaceSchema<T>;
/**
* Set default value
*/
default(value: any): InterfaceSchema<T>;
}
/**
* Enhanced Type Inference System for Schema Definitions
* Features: design, better extensibility, performance optimizations
*/
interface BaseTypeMap {
string: string;
number: number;
int: number;
integer: number;
float: number;
double: number;
positive: number;
negative: number;
boolean: boolean;
bool: boolean;
date: Date;
datetime: Date;
timestamp: Date;
email: string;
url: string;
uri: string;
uuid: string;
guid: string;
phone: string;
slug: string;
username: string;
password: string;
text: string;
json: any;
object: object;
any: any;
unknown: unknown;
void: void;
null: null;
undefined: undefined;
}
type ParseUnion<T extends string> = T extends `${infer First}|${infer Rest}` ? First extends "" ? ParseUnion<Rest> : Rest extends "" ? First : First | ParseUnion<Rest> : T extends "" ? never : T;
type ParseWhenCondition<T extends string> = T extends `${infer Field}.!exists` ? {
field: Field;
operator: "!exists";
value: true;
} : T extends `${infer Field}.exists` ? {
field: Field;
operator: "exists";
value: true;
} : T extends `${infer Field}.!empty` ? {
field: Field;
operator: "!empty";
value: true;
} : T extends `${infer Field}.empty` ? {
field: Field;
operator: "empty";
value: true;
} : T extends `${infer Field}.!null` ? {
field: Field;
operator: "!null";
value: true;
} : T extends `${infer Field}.null` ? {
field: Field;
operator: "null";
value: true;
} : T extends `${infer Field}.!in(${infer Values})` ? {
field: Field;
operator: "!in";
value: Values;
} : T extends `${infer Field}.in(${infer Values})` ? {
field: Field;
operator: "in";
value: Values;
} : T extends `${infer Field}.!contains(${infer Value})` ? {
field: Field;
operator: "!contains";
value: Value;
} : T extends `${infer Field}.contains(${infer Value})` ? {
field: Field;
operator: "contains";
value: Value;
} : T extends `${infer Field}.startsWith(${infer Value})` ? {
field: Field;
operator: "startsWith";
value: Value;
} : T extends `${infer Field}.endsWith(${infer Value})` ? {
field: Field;
operator: "endsWith";
value: Value;
} : T extends `${infer Field}!~${infer Value}` ? {
field: Field;
operator: "!~";
value: Value;
} : T extends `${infer Field}~${infer Value}` ? {
field: Field;
operator: "~";
value: Value;
} : T extends `${infer Field}!=${infer Value}` ? {
field: Field;
operator: "!=";
value: Value;
} : T extends `${infer Field}>=${infer Value}` ? {
field: Field;
operator: ">=";
value: Value;
} : T extends `${infer Field}<=${infer Value}` ? {
field: Field;
operator: "<=";
value: Value;
} : T extends `${infer Field}>${infer Value}` ? {
field: Field;
operator: ">";
value: Value;
} : T extends `${infer Field}<${infer Value}` ? {
field: Field;
operator: "<";
value: Value;
} : T extends `${infer Field}=${infer Value}` ? {
field: Field;
operator: "=";
value: Value;
} : never;
type InferConstantType<T extends string> = T extends `=${infer ConstValue}` ? ConstValue extends "true" ? true : ConstValue extends "false" ? false : ConstValue extends `${number}` ? number : ConstValue : T extends `=${infer ConstValue}?` ? ConstValue extends "true" ? true | undefined : ConstValue extends "false" ? false | undefined : ConstValue extends `${number}` ? number | undefined : ConstValue | undefined : never;
type InferConditionalType<T extends string> = T extends `when ${infer Condition} *? ${infer ThenType} : ${infer ElseType}` ? InferFieldType$1<ThenType> | InferFieldType$1<ElseType> : T extends `when ${infer Condition} *? ${infer ThenType}` ? InferFieldType$1<ThenType> : T extends `when(${infer Condition}) then(${infer ThenType}) else(${infer ElseType})` ? InferFieldType$1<ThenType> | InferFieldType$1<ElseType> : T extends `when(${infer Condition}) then(${infer ThenType})` ? InferFieldType$1<ThenType> : T extends `${infer Condition} ? ${infer ThenType} : ${infer ElseType}` ? InferFieldType$1<ThenType> | InferFieldType$1<ElseType> : T extends `when:${infer Condition}:${infer ThenType}:${infer ElseType}` ? InferFieldType$1<ThenType> | InferFieldType$1<ElseType> : T extends `when:${infer Condition}:${infer ThenType}` ? InferFieldType$1<ThenType> : never;
type InferBaseType<T extends string> = T extends keyof BaseTypeMap ? BaseTypeMap[T] : T extends `${infer BaseType}?` ? BaseType extends keyof BaseTypeMap ? BaseTypeMap[BaseType] | undefined : never : never;
type InferArrayType<T extends string> = T extends `${infer ElementType}[]` ? ElementType extends keyof BaseTypeMap ? BaseTypeMap[ElementType][] : ElementType extends `${string}|${string}` ? ParseUnion<ElementType>[] : any[] : T extends `${infer ElementType}[]?` ? ElementType extends keyof BaseTypeMap ? BaseTypeMap[ElementType][] | undefined : ElementType extends `${string}|${string}` ? ParseUnion<ElementType>[] | undefined : any[] | undefined : never;
type InferRecordType<T extends string> = T extends `record<${infer KeyType},${infer ValueType}>` ? KeyType extends "string" | "number" | "symbol" ? Record<string, InferFieldType$1<ValueType>> : Record<string, InferFieldType$1<ValueType>> : T extends `record<${infer KeyType},${infer ValueType}>?` ? KeyType extends "string" | "number" | "symbol" ? Record<string, InferFieldType$1<ValueType>> | undefined : Record<string, InferFieldType$1<ValueType>> | undefined : T extends `map<${infer KeyType},${infer ValueType}>` ? Record<string, InferFieldType$1<ValueType>> : T extends `map<${infer KeyType},${infer ValueType}>?` ? Record<string, InferFieldType$1<ValueType>> | undefined : never;
type InferConstrainedType<T extends string> = T extends `${infer BaseType}(${infer Constraints})` ? BaseType extends keyof BaseTypeMap ? BaseTypeMap[BaseType] : BaseType extends `${infer ArrayType}[]` ? ArrayType extends keyof BaseTypeMap ? BaseTypeMap[ArrayType][] : any[] : any : T extends `${infer BaseType}(${infer Constraints})?` ? BaseType extends keyof BaseTypeMap ? BaseTypeMap[BaseType] | undefined : BaseType extends `${infer ArrayType}[]` ? ArrayType extends keyof BaseTypeMap ? BaseTypeMap[ArrayType][] | undefined : any[] | undefined : any | undefined : never;
type InferRegexType<T extends string> = T extends `${infer BaseType}(/${string}/)` ? BaseType extends keyof BaseTypeMap ? BaseTypeMap[BaseType] : string : T extends `${infer BaseType}(/${string}/)?` ? BaseType extends keyof BaseTypeMap ? BaseTypeMap[BaseType] | undefined : string | undefined : never;
type InferFieldType$1<T> = T extends string ? InferConstantType<T> extends never ? InferConditionalType<T> extends never ? T extends `${string}|${string}` ? T extends `${infer UnionType}?` ? ParseUnion<UnionType> | undefined : ParseUnion<T> : InferArrayType<T> extends never ? InferRecordType<T> extends never ? InferConstrainedType<T> extends never ? InferRegexType<T> extends never ? InferBaseType<T> extends never ? any : InferBaseType<T> : InferRegexType<T> : InferConstrainedType<T> : InferRecordType<T> : InferArrayType<T> : InferConditionalType<T> : InferConstantType<T> : any;
type InferConditionalTypeAdvanced<TCondition extends string, TThenType extends string, TElseType extends string, TSchema extends SchemaInterface> = ParseWhenCondition<TCondition> extends {
field: infer Field;
operator: infer Op;
value: infer Value;
} ? Field extends keyof TSchema ? TSchema[Field] extends string ? Op extends "=" ? TSchema[Field] extends `${string}|${string}` ? Value extends ParseUnion<TSchema[Field]> ? InferFieldType$1<TThenType> : InferFieldType$1<TElseType> : TSchema[Field] extends Value ? InferFieldType$1<TThenType> : InferFieldType$1<TElseType> : Op extends "!=" ? TSchema[Field] extends Value ? InferFieldType$1<TElseType> : InferFieldType$1<TThenType> : Op extends "exists" ? InferFieldType$1<TThenType> : Op extends "!exists" ? InferFieldType$1<TElseType> : // For complex operators, use union type
InferFieldType$1<TThenType> | InferFieldType$1<TElseType> : InferFieldType$1<TThenType> | InferFieldType$1<TElseType> : InferFieldType$1<TThenType> | InferFieldType$1<TElseType> : InferFieldType$1<TThenType> | InferFieldType$1<TElseType>;
type InferSchemaFieldType<T, TSchema extends SchemaInterface = {}> = T extends UnionValue<infer U> ? U[number] : T extends ConstantValue ? T["const"] : T extends OptionalConstantValue ? T["const"] | undefined : T extends {
__conditional: true;
__inferredType: infer U;
} ? U : T extends `when ${infer Condition} *? ${infer ThenType} : ${infer ElseType}` ? InferConditionalTypeAdvanced<Condition, ThenType, ElseType, TSchema> : T extends `when ${infer Condition} *? ${infer ThenType}` ? InferFieldType$1<ThenType> : T extends `when(${infer Condition}) then(${infer ThenType}) else(${infer ElseType})` ? InferConditionalTypeAdvanced<Condition, ThenType, ElseType, TSchema> : T extends `when(${infer Condition}) then(${infer ThenType})` ? InferFieldType$1<ThenType> : T extends `${infer Condition} ? ${infer ThenType} : ${infer ElseType}` ? InferConditionalTypeAdvanced<Condition, ThenType, ElseType, TSchema> : T extends `when:${infer Condition}:${infer ThenType}:${infer ElseType}` ? InferConditionalTypeAdvanced<Condition, ThenType, ElseType, TSchema> : T extends `when:${infer Condition}:${infer ThenType}` ? InferFieldType$1<ThenType> : T extends string ? InferFieldType$1<T> : T extends SchemaInterface ? InferSchemaType<T> : T extends OptionalSchemaInterface ? InferSchemaType<T["schema"]> | undefined : T extends readonly [infer U] ? InferSchemaFieldType<U, TSchema>[] : T extends (infer U)[] ? InferSchemaFieldType<U, TSchema>[] : any;
type IsOptionalField<T> = T extends string ? T extends `${string}?` ? true : false : T extends OptionalConstantValue ? true : T extends OptionalSchemaInterface ? true : T extends {
__optional: true;
} ? true : false;
type RequiredFields<T extends SchemaInterface> = {
[K in keyof T]: IsOptionalField<T[K]> extends true ? never : K;
}[keyof T];
type OptionalFields<T extends SchemaInterface> = {
[K in keyof T]: IsOptionalField<T[K]> extends true ? K : never;
}[keyof T];
type InferSchemaType<T extends SchemaInterface> = {
[K in RequiredFields<T>]: InferSchemaFieldType<T[K], T>;
} & {
[K in OptionalFields<T>]?: InferSchemaFieldType<T[K], T>;
};
/**
* Schema modification utilities - transform and combine schemas
*/
declare class Mod {
/**
* Merge multiple schemas into a single schema
* @example
* ```typescript
* const UserSchema = Interface({ id: "number", name: "string" });
* const ProfileSchema = Interface({ bio: "string?", avatar: "url?" });
*
* const MergedSchema = Mod.merge(UserSchema, ProfileSchema);
* // Result: { id: number, name: string, bio?: string, avatar?: string }
* ```
*/
static merge<T, U>(schema1: InterfaceSchema<T>, schema2: InterfaceSchema<U>): InterfaceSchema<T & U>;
/**
* Pick specific fields from a schema
* @example
* ```typescript
* const UserSchema = Interface({
* id: "number",
* name: "string",
* email: "email",
* password: "string"
* });
*
* const PublicUserSchema = Mod.pick(UserSchema, ["id", "name", "email"]);
* // Result: { id: number, name: string, email: string }
* ```
*/
static pick<T, K extends keyof T>(schema: InterfaceSchema<T>, keys: K[]): InterfaceSchema<Pick<T, K>>;
/**
* Omit specific fields from a schema
* @example
* ```typescript
* const UserSchema = Interface({
* id: "number",
* name: "string",
* email: "email",
* password: "string"
* });
*
* const SafeUserSchema = Mod.omit(UserSchema, ["password"]);
* // Result: { id: number, name: string, email: string }
* ```
*/
static omit<T, K extends keyof T>(schema: InterfaceSchema<T>, keys: K[]): InterfaceSchema<Omit<T, K>>;
/**
* Make all fields in a schema optional
* @example
* ```typescript
* const UserSchema = Interface({ id: "number", name: "string" });
* const PartialUserSchema = Mod.partial(UserSchema);
* // Result: { id?: number, name?: string }
* ```
*/
static partial<T>(schema: InterfaceSchema<T>): InterfaceSchema<Partial<T>>;
/**
* Make all fields in a schema required (remove optional markers)
* @example
* ```typescript
* const UserSchema = Interface({ id: "number", name: "string?" });
* const RequiredUserSchema = Mod.required(UserSchema);
* // Result: { id: number, name: string }
* ```
*/
static required<T>(schema: InterfaceSchema<T>): InterfaceSchema<Required<T>>;
/**
* Extend a schema with additional fields
* @example
* ```typescript
* const BaseSchema = Interface({ id: "number", name: "string" });
* const ExtendedSchema = Mod.extend(BaseSchema, {
* email: "email",
* createdAt: "date"
* });
* // Result: { id: number, name: string, email: string, createdAt: Date }
* ```
*/
static extend<T, U extends SchemaInterface>(schema: InterfaceSchema<T>, extension: U): InterfaceSchema<T & InferSchemaType<U>>;
}
/**
* Helper class for creating schema values
*/
declare class Make {
/**
* Create a constant value (safer than using raw values)
* @example
* ```typescript
* const schema = Interface({
* status: Make.const("pending"),
* version: Make.const(1.0),
* enabled: Make.const(true)
* });
* ```
*/
static const<const T extends string | number | boolean>(value: T): ConstantValue & {
const: T;
};
/**
* Create a union type (multiple allowed values) with proper type inference
* @example
* ```typescript
* const schema = Interface({
* status: Make.union("pending", "accepted", "rejected"),
* priority: Make.union("low", "medium", "high")
* });
* ```
*/
static union<const T extends readonly string[]>(...values: T): UnionValue<T>;
/**
* Create an optional union type
* @example
* ```typescript
* const schema = Interface({
* status: Make.unionOptional("pending", "accepted", "rejected")
* });
* ```
*/
static unionOptional(...values: string[]): string;
}
/**
* TypeScript Interface-like Schema System
*
* The most intuitive way to define schemas - just like TypeScript interfaces!
*
* @example
* ```typescript
* import { Interface } from "fortify-schema";
*
* // Define schema like a TypeScript interface
* const UserSchema = Interface({
* id: "number",
* email: "email",
* name: "string",
* age: "number?", // Optional
* isActive: "boolean?", // Optional
* tags: "string[]?", // Optional array
* role: "admin", // Constant value
* profile: { // Nested object
* bio: "string?",
* avatar: "url?"
* }
* });
*
* // Validate data
* const result = UserSchema.safeParse(userData);
* ```
*/
/**
* Create a schema using TypeScript interface-like syntax with full type inference
*
* @param definition - Schema definition using TypeScript-like syntax
* @param options - Optional validation options
* @returns InterfaceSchema instance with inferred types
*
* @example Basic Usage
* ```typescript
* const UserSchema = Interface({
* id: "number",
* email: "email",
* name: "string",
* age: "number?",
* isActive: "boolean?",
* tags: "string[]?"
* });
*
* // result is fully typed as:
* // SchemaValidationResult<{
* // id: number;
* // email: string;
* // name: string;
* // age?: number;
* // isActive?: boolean;
* // tags?: string[];
* // }>
* const result = UserSchema.safeParse(data);
* ```
*
* @example With Constraints
* ```typescript
* const UserSchema = Interface({
* username: "string(3,20)", // 3-20 characters
* age: "number(18,120)", // 18-120 years
* tags: "string[](1,10)?", // 1-10 tags, optional
* });
* ```
*
* @example Nested Objects
* ```typescript
* const OrderSchema = Interface({
* id: "number",
* customer: {
* name: "string",
* email: "email",
* address: {
* street: "string",
* city: "string",
* zipCode: "string"
* }
* },
* items: [{
* name: "string",
* price: "number",
* quantity: "int"
* }]
* });
* ```
*/
declare function Interface<const T extends SchemaInterface>(definition: T, options?: SchemaOptions): InterfaceSchema<InferSchemaType<T>>;
/**
* Type helper for inferring TypeScript types from schema definitions
*
* @example
* ```typescript
* const UserSchema = Interface({
* id: "number",
* email: "email",
* name: "string",
* age: "number?",
* tags: "string[]?"
* });
*
* // Infer the TypeScript type
* type User = InferType<typeof UserSchema>;
* // User = {
* // id: number;
* // email: string;
* // name: string;
* // age?: number;
* // tags?: string[];
* // }
* ```
*/
type InferType<T extends InterfaceSchema<any>> = T extends InterfaceSchema<infer U> ? U : never;
/**
* Available field types for schema definitions
*/
declare const FieldTypes: {
readonly STRING: "string";
readonly STRING_OPTIONAL: "string?";
readonly NUMBER: "number";
readonly NUMBER_OPTIONAL: "number?";
readonly BOOLEAN: "boolean";
readonly BOOLEAN_OPTIONAL: "boolean?";
readonly DATE: "date";
readonly DATE_OPTIONAL: "date?";
readonly ANY: "any";
readonly ANY_OPTIONAL: "any?";
readonly EMAIL: "email";
readonly EMAIL_OPTIONAL: "email?";
readonly URL: "url";
readonly URL_OPTIONAL: "url?";
readonly UUID: "uuid";
readonly UUID_OPTIONAL: "uuid?";
readonly PHONE: "phone";
readonly PHONE_OPTIONAL: "phone?";
readonly SLUG: "slug";
readonly SLUG_OPTIONAL: "slug?";
readonly USERNAME: "username";
readonly USERNAME_OPTIONAL: "username?";
readonly INT: "int";
readonly INT_OPTIONAL: "int?";
readonly POSITIVE: "positive";
readonly POSITIVE_OPTIONAL: "positive?";
readonly FLOAT: "float";
readonly FLOAT_OPTIONAL: "float?";
readonly STRING_ARRAY: "string[]";
readonly STRING_ARRAY_OPTIONAL: "string[]?";
readonly NUMBER_ARRAY: "number[]";
readonly NUMBER_ARRAY_OPTIONAL: "number[]?";
readonly BOOLEAN_ARRAY: "boolean[]";
readonly BOOLEAN_ARRAY_OPTIONAL: "boolean[]?";
readonly INT_ARRAY: "int[]";
readonly INT_ARRAY_OPTIONAL: "int[]?";
readonly EMAIL_ARRAY: "email[]";
readonly EMAIL_ARRAY_OPTIONAL: "email[]?";
readonly URL_ARRAY: "url[]";
readonly URL_ARRAY_OPTIONAL: "url[]?";
readonly RECORD_STRING_ANY: "record<string,any>";
readonly RECORD_STRING_ANY_OPTIONAL: "record<string,any>?";
readonly RECORD_STRING_STRING: "record<string,string>";
readonly RECORD_STRING_STRING_OPTIONAL: "record<string,string>?";
readonly RECORD_STRING_NUMBER: "record<string,number>";
readonly RECORD_STRING_NUMBER_OPTIONAL: "record<string,number>?";
};
/**
* Quick schema creation helpers
*/
declare const QuickSchemas: {
/**
* User schema with common fields
*/
User: InterfaceSchema<InferSchemaType<{
readonly id: "number";
readonly email: "email";
readonly name: "string";
readonly createdAt: "date?";
readonly updatedAt: "date?";
}>>;
/**
* API response schema
*/
APIResponse: InterfaceSchema<InferSchemaType<{
readonly success: "boolean";
readonly data: "any?";
readonly errors: "string[]?";
readonly timestamp: "date?";
}>>;
/**
* Pagination schema
*/
Pagination: InterfaceSchema<InferSchemaType<{
readonly page: "int";
readonly limit: "int";
readonly total: "int";
readonly hasNext: "boolean?";
readonly hasPrev: "boolean?";
}>>;
/**
* Address schema
*/
Address: InterfaceSchema<InferSchemaType<{
readonly street: "string";
readonly city: "string";
readonly state: "string?";
readonly zipCode: "string";
readonly country: "string";
}>>;
/**
* Contact info schema
*/
Contact: InterfaceSchema<InferSchemaType<{
readonly email: "email?";
readonly phone: "phone?";
readonly website: "url?";
}>>;
};
/**
* OpenAPI Converter - Convert schemas to OpenAPI specifications
*
* This module provides utilities to convert Fortify Schema definitions
* to OpenAPI 3.0 specifications for API documentation.
*/
/**
* OpenAPI converter for schema definitions
*/
declare class OpenAPIConverter {
/**
* Convert a schema to OpenAPI format
*/
static convertSchema(schema: SchemaInterface): OpenAPISchemaObject;
/**
* Convert a single field to OpenAPI property
*/
private static convertField;
/**
* Convert string-based field definitions
*/
private static convertStringField;
/**
* Convert object field definitions
*/
private static convertObjectField;
/**
* Parse string constraints from string(min,max) format
*/
private static parseStringConstraints;
/**
* Generate complete OpenAPI specification
*/
static generateOpenAPISpec(schema: SchemaInterface, options: OpenAPISpecOptions): OpenAPISpecification;
/**
* Generate schema reference for use in OpenAPI paths
*/
static generateSchemaReference(schemaName: string): OpenAPIReference;
/**
* Generate request body specification
*/
static generateRequestBody(schema: SchemaInterface, options?: RequestBodyOptions): OpenAPIRequestBody;
/**
* Generate response specification
*/
static generateResponse(schema: SchemaInterface, options?: ResponseOptions): OpenAPIResponse;
}
/**
* Type definitions
*/
interface OpenAPISchemaObject {
type: string;
properties?: Record<string, any>;
required?: string[];
items?: any;
format?: string;
pattern?: string;
minimum?: number;
maximum?: number;
exclusiveMinimum?: boolean;
exclusiveMaximum?: boolean;
minLength?: number;
maxLength?: number;
minItems?: number;
maxItems?: number;
}
interface OpenAPISpecOptions {
title: string;
version: string;
description?: string;
schemaName?: string;
servers?: string[];
paths?: Record<string, any>;
}
interface OpenAPISpecification {
openapi: string;
info: {
title: string;
version: string;
description?: string;
};
servers?: Array<{
url: string;
}>;
components: {
schemas: Record<string, OpenAPISchemaObject>;
};
paths: Record<string, any>;
}
interface OpenAPIReference {
$ref: string;
}
interface RequestBodyOptions {
description?: string;
required?: boolean;
examples?: Record<string, any>;
}
interface OpenAPIRequestBody {
description: string;
required: boolean;
content: Record<string, {
schema: OpenAPISchemaObject;
examples?: Record<string, any>;
}>;
}
interface ResponseOptions {
description?: string;
examples?: Record<string, any>;
headers?: Record<string, any>;
}
interface OpenAPIResponse {
description: string;
content: Record<string, {
schema: OpenAPISchemaObject;
examples?: Record<string, any>;
}>;
headers?: Record<string, any>;
}
/**
* TypeScript Generator - Generate TypeScript type definitions from schemas
*
* This module provides utilities to convert Fortify Schema definitions
* to TypeScript type definitions and interfaces.
*/
/**
* TypeScript code generator for schema definitions
*/
declare class TypeScriptGenerator$1 {
/**
* Generate TypeScript interface from schema
*/
static generateInterface(schema: SchemaInterface, options?: TypeScriptOptions): string;
/**
* Extract field definitions from schema object
*/
private static extractFieldDefinitions;
/**
* Generate interface definition
*/
private static generateInterfaceDefinition;
/**
* Generate type alias definition
*/
private static generateTypeDefinition;
/**
* Convert schema field to TypeScript type
*/
private static convertToTypeScript;
/**
* Convert string-based field to TypeScript type
*/
private static convertStringToTypeScript;
/**
* Convert object to TypeScript type
*/
private static convertObjectToTypeScript;
/**
* Check if field is optional
*/
private static isOptionalField;
/**
* Generate utility types for schema
*/
static generateUtilityTypes(schema: SchemaInterface, baseName: string): string;
/**
* Generate validation function types
*/
static generateValidationTypes(baseName: string): string;
/**
* Generate complete TypeScript module
*/
static generateModule(schema: SchemaInterface, options: ModuleOptions): string;
/**
* Generate JSDoc comments for schema fields
*/
static generateJSDoc(schema: SchemaInterface): Record<string, string>;
/**
* Generate JSDoc for a single field
*/
private static generateFieldJSDoc;
}
/**
* Type definitions
*/
interface TypeScriptOptions {
exportName?: string;
namespace?: string;
exportType?: "interface" | "type";
}
interface ModuleOptions {
moduleName?: string;
exportName?: string;
includeUtilities?: boolean;
includeValidation?: boolean;
header?: string;
}
/**
* Validation Engine - Core validation logic for schema extensions
*
* This module provides the core validation engine that powers all schema extensions.
* It handles type checking, constraint validation, and error reporting.
*/
/**
* Core validation engine for schema validation
*/
declare class ValidationEngine {
/**
* Validate a value against a schema field definition
*/
static validateField(fieldSchema: any, value: any): ValidationFieldResult;
/**
* Validate against string-based schema definitions
*/
private static validateStringSchema;
/**
* Validate against object schema definitions
*/
private static validateObjectSchema;
/**
* Email validation
*/
private static validateEmail;
/**
* URL validation
*/
private static validateUrl;
/**
* UUID validation
*/
private static validateUuid;
/**
* Number validation
*/
private static validateNumber;
/**
* Positive number validation
*/
private static validatePositiveNumber;
/**
* Integer validation
*/
private static validateInteger;
/**
* Boolean validation
*/
private static validateBoolean;
/**
* Date validation
*/
private static validateDate;
/**
* String validation
*/
private static validateString;
/**
* String validation with constraints
*/
private static validateStringWithConstraints;
/**
* Array validation
*/
private static validateArray;
/**
* Validate entire object against schema
*/
static validateObject(schema: SchemaInterface, data: any): ValidationResult$1;
}
/**
* Type definitions
*/
interface ValidationFieldResult {
isValid: boolean;
errors: string[];
}
interface ValidationResult$1 {
isValid: boolean;
data: any;
errors: Record<string, string[]>;
timestamp: Date;
}
/**
* Type definitions
*/
interface DocumentationOptions {
title?: string;
description?: string;
examples?: boolean;
interactive?: boolean;
}
interface InteractiveOptions {
title?: string;
theme?: "light" | "dark";
showExamples?: boolean;
allowTesting?: boolean;
}
interface Documentation {
markdown: string;
html: string;
openapi: OpenAPISpec;
json: any;
examples: any[];
}
interface InteractiveDocumentation {
html: string;
css: string;
javascript: string;
}
interface OpenAPISpec {
openapi: string;
info: {
title: string;
version: string;
};
servers?: Array<{
url: string;
}>;
components: {
schemas: Record<string, any>;
};
}
/**
* Type definitions
*/
interface ValidationResult {
isValid: boolean;
data: any;
errors: Record<string, string[]>;
timestamp: Date;
}
interface FieldValidationResult {
field: string;
value: any;
isValid: boolean;
errors: string[];
}
interface ValidationStats {
totalValidated: number;
validCount: number;
invalidCount: number;
errorRate: number;
startTime: Date;
}
type InferFieldType<T extends string> = T extends "string" ? string : T extends "string?" ? string | undefined : T extends "number" ? number : T extends "number?" ? number | undefined : T extends "boolean" ? boolean : T extends "boolean?" ? boolean | undefined : T extends "string[]" ? string[] : T extends "string[]?" ? string[] | undefined : T extends "number[]" ? number[] : T extends "number[]?" ? number[] | undefined : T extends "boolean[]" ? boolean[] : T extends "boolean[]?" ? boolean[] | undefined : T extends `${string}|${string}` ? string : any;
type ConditionalResult<TThen extends string, TElse extends string> = {
__conditional: true;
__inferredType: InferFieldType<TThen> | InferFieldType<TElse>;
};
/**
* Builder for the "else" part of conditional validation with TypeScript inference
* This class is returned after calling .then() and provides the .else() method
*/
declare class ConditionalElse<TThen extends string = string> {
private builder;
private condition;
private thenSchema;
constructor(builder: ConditionalBuilder, condition: (value: any) => boolean, thenSchema: TThen);
/**
* Specify the schema to use when the condition is false
*/
else<TElse extends string>(elseSchema: TElse): ConditionalResult<TThen, TElse>;
/**
* Alias for else() - for backward compatibility
*/
default<TElse extends string>(defaultSchema: TElse): ConditionalResult<TThen, TElse>;
/**
* Build without else clause (same as calling .else(undefined))
*/
build(): any;
}
/**
* Builder for the "then" part of conditional validation with TypeScript inference
*/
declare class ConditionalThen {
private builder;
private condition;
constructor(builder: ConditionalBuilder, condition: (value: any) => boolean);
then<T extends string>(schema: T): ConditionalElse<T>;
}
/**
* Builder for single field conditional validation with TypeScript inference
*/
declare class ConditionalBuilder {
private fieldName;
private conditions;
private defaultSchema;
constructor(fieldName: string);
/**
* Check if field equals specific value
*/
is(value: any): ConditionalThen;
/**
* Check if field does not equal specific value
*/
isNot(value: any): ConditionalThen;
/**
* Check if field exists (not null/undefined)
*/
exists(): ConditionalThen;
/**
* Check if field matches pattern
*/
matches(pattern: RegExp): ConditionalThen;
/**
* Check if field is in array of values
*/
in(values: any[]): ConditionalThen;
/**
* Custom condition function
*/
when(condition: (value: any) => boolean): ConditionalThen;
addCondition(condition: (value: any) => boolean, schema: any): this;
default(schema: any): any;
build(): any;
}
/**
* Builder for multi-field "then" part
*/
declare class MultiConditionalThen {
private builder;
private conditions;
constructor(builder: MultiConditionalBuilder, conditions: Record<string, any>);
then(schema: any): MultiConditionalElse;
}
/**
* Builder for multi-field "else" part
*/
declare class MultiConditionalElse {
private thenSchema;
private elseSchema;
constructor(thenSchema: any, elseSchema: any);
else(schema: any): any;
}
/**
* Custom validator builder
*/
declare class CustomValidator {
private validator;
constructor(validator: (data: any) => {
valid: true;
} | {
error: string;
});
build(): any;
}
/**
* Builder for multi-field conditional validation
*/
declare class MultiConditionalBuilder {
private fieldNames;
private matchConditions;
constructor(fieldNames: string[]);
match(conditions: Record<string, any>): MultiConditionalThen;
}
/**
* Conditional Validation - Revolutionary dependent field validation
*
* This module provides powerful conditional validation where fields can depend
* on other fields' values, making complex business logic validation simple.
*/
/**
* Conditional validation utilities
*/
declare const When: {
/**
* Create conditional validation based on another field's value
*
* @example
* ```typescript
* const UserSchema = Interface({
* accountType: Make.union("free", "premium", "enterprise"),
* maxProjects: When.field("accountType").is("free").then("int(1,3)")
* .is("premium").then("int(1,50)")
* .is("enterprise").then("int(1,)")
* .default("int(1,1)"),
*
* paymentMethod: When.field("accountType").isNot("free").then("string").else("string?"),
* billingAddress: When.field("paymentMethod").exists().then({
* street: "string",
* city: "string",
* country: "string(2,2)"
* }).else("any?")
* });
* ```
*/
field(fieldName: string): ConditionalBuilder;
/**
* Create validation that depends on multiple fields
*
* @example
* ```typescript
* const OrderSchema = Interface({
* orderType: Make.union("pickup", "delivery"),
* address: "string?",
* deliveryFee: "number?",
*
* // Complex conditional validation
* ...When.fields(["orderType", "address"]).match({
* orderType: "delivery",
* address: (val) => val && val.length > 0
* }).then({
* deliveryFee: "number(0,)" // Required for delivery with address
* }).else({
* deliveryFee: "number?" // Optional otherwise
* })
* });
* ```
*/
fields(fieldNames: string[]): MultiConditionalBuilder;
/**
* Create custom validation logic
*
* @example
* ```typescript
* const EventSchema = Interface({
* startDate: "date",
* endDate: "date",
*
* // Custom validation: endDate must be after startDate
* ...When.custom((data) => {
* if (data.endDate <= data.startDate) {
* return { error: "End date must be after start date" };
* }
* return { valid: true };
* })
* });
* ```
*/
custom(validator: (data: any) => {
valid: true;
} | {
error: string;
}): CustomValidator;
};
/**
* Smart Schema Inference - Revolutionary TypeScript type-to-schema conversion
*
* This module provides automatic schema generation from TypeScript types,
* making schema definition even more seamless.
*/
/**
* Smart inference utilities for automatic schema generation
*/
declare const Smart: {
/**
* Infer schema from TypeScript interface using runtime reflection
*
* @example
* ```typescript
* interface User {
* id: number;
* email: string;
* name?: string;
* }
*
* // Use with sample data that matches your interface
* const UserSchema = Smart.fromType<User>({
* id: 1,
* email: "user@example.com",
* name: "John Doe"
* });
* // Generates: Interface({ id: "positive", email: "email", name: "string?" })
* ```
*/
fromType<T>(sampleData: T): SchemaInterface;
/**
* Infer schema from sample data with intelligent type detection
*
* @example
* ```typescript
* const sampleUser = {
* id: 1,
* email: "user@example.com",
* name: "John Doe",
* tags: ["developer", "typescript"]
* };
*
* const UserSchema = Smart.fromSample(sampleUser);
* // Generates: Interface({ id: "positive", email: "email", name: "string", tags: "string[]" })
* ```
*/
fromSample(sample: any): SchemaInterface;
/**
* Infer field type from value with smart detection
*/
inferFieldType(value: any): string;
/**
* Smart format detection utilities
*/
isEmail(str: string): boolean;
isUrl(str: string): boolean;
isUuid(str: string): boolean;
isPhone(str: string): boolean;
/**
* Generate schema from JSON Schema (migration helper)
*
* @example
* ```typescript
* const jsonSchema = {
* type: "object",
* properties: {
* id: { type: "number" },
* email: { type: "string", format: "email" }
* }
* };
*
* const schema = Smart.fromJsonSchema(jsonSchema);
* ```
*/
fromJsonSchema(jsonSchema: any): SchemaInterface;
convertJsonSchemaProperty(prop: any): string;
};
/**
* Live validator for real-time validation
*/
declare class LiveValidator {
private schema;
private currentData;
private currentErrors;
private listeners;
private fieldListeners;
constructor(schema: SchemaInterface);
/**
* Validate a single field in real-time
*/
validateField(fieldName: string, value: any): FieldValidationResult;
/**
* Validate all current data
*/
validateAll(): ValidationResult;
/**
* Listen for validation changes
*/
onValidation(listener: (result: ValidationResult) => void): void;
/**
* Listen for specific field validation
*/
onFieldValidation(fieldName: string, listener: (result: FieldValidationResult) => void): void;
/**
* Get current validation state
*/
get isValid(): boolean;
get errors(): Record<string, string[]>;
get data(): any;
private notifyListeners;
}
/**
* Form validator with DOM integration
*/
declare class FormValidator extends LiveValidator {
private boundFields;
private autoValidationEnabled;
private submitListeners;
/**
* Bind a form field for automatic validation (Node.js compatible)
*/
bindField(fieldName: string, element: any): void;
/**
* Enable automatic validation on input changes (Node.js compatible)
*/
enableAutoValidation(): void;
/**
* Listen for form submission
*/
onSubmit(listener: (isValid: boolean, data: any, errors: Record<string, string[]>) => void): void;
/**
* Trigger form validation (typically on submit)
*/
submit(): void;
private setupFieldListeners;
}
/**
* Stream validator for continuous data validation
*/
declare class StreamValidator {
private schema;
private validListeners;
private invalidListeners;
private statsListeners;
private stats;
constructor(schema: SchemaInterface);
/**
* Validate streaming data
*/
validate(data: any): void;
/**
* Listen for valid data
*/
onValid(listener: (data: any) => void): void;
/**
* Listen for invalid data
*/
onInvalid(listener: (data: any, errors: Record<string, string[]>) => void): void;
/**
* Listen for validation statistics
*/
onStats(listener: (stats: ValidationStats) => void): void;
/**
* Get current validation statistics
*/
getStats(): ValidationStats;
private updateStats;
}
/**
* Real-time Validation - Revolutionary live validation system
*
* This module provides real-time validation with reactive updates,
* perfect for forms and live data validation.
*
* Uses modular validation engine for consistent validation logic.
*/
/**
* Real-time validation utilities
*/
declare const Live: {
/**
* Create a reactive validator that validates in real-time
*
* @example
* ```typescript
* const UserSchema = Interface({
* email: "email",
* username: "string(3,20)",
* password: "string(8,)"
* });
*
* const liveValidator = Live.validator(UserSchema);
*
* // Listen for validation changes
* liveValidator.onValidation((result) => {
* console.log('Validation result:', result);
* updateUI(result);
* });
*
* // Validate field by field
* liveValidator.validateField('email', 'user@example.com');
* liveValidator.validateField('username', 'johndoe');
*
* // Get current state
* console.log(liveValidator.isValid); // true/false
* console.log(liveValidator.errors); // Current errors
* ```
*/
validator(schema: SchemaInterface): LiveValidator;
/**
* Create a form validator with field-level validation
*
* @example
* ```typescript
* const formValidator = Live.form(UserSchema);
*
* // Bind to form fields
* formValidator.bindField('email', emailInput);
* formValidator.bindField('username', usernameInput);
*
* // Auto-validation on input
* formValidator.enableAutoValidation();
*
* // Submit validation
* formValidator.onSubmit((isValid, data, errors) => {
* if (isValid) {
* submitForm(data);
* } else {
* showErrors(errors);
* }
* });
* ```
*/
form(schema: SchemaInterface): FormValidator;
/**
* Create a stream validator for continuous data validation
*
* @example
* ```typescript
* const streamValidator = Live.stream(DataSchema);
*
* // Validate streaming data
* dataStream.subscribe((data) => {
* streamValidator.validate(data);
* });
*
* // Handle validation results
* streamValidator.onValid((data) => {
* processValidData(data);
* });
*
* streamValidator.onInvalid((data, errors) => {
* logInvalidData(data, errors);
* });
* ```
*/
stream(schema: SchemaInterface): StreamValidator;
};
/**
* Auto documentation utilities
*/
declare const Docs: {
/**
* Generate comprehensive documentation from schema
*
* @example
* ```typescript
* const UserSchema = Interface({
* id: "uuid",
* email: "email",
* name: "string(2,50)",
* age: "int(18,120)?",
* role: Make.union("user", "admin", "moderator")
* });
*
* const documentation = Docs.generate(UserSchema, {
* title: "User API",
* description: "User management endpoints",
* examples: true,
* interactive: true
* });
*
* console.log(documentation.markdown);
* console.log(documentation.html);
* console.log(documentation.openapi);
* ```
*/
generate(schema: SchemaInterface, options?: DocumentationOptions): Documentation;
/**
* Generate OpenAPI specification from schema
*
* @example
* ```typescript
* const openApiSpec = Docs.openapi(UserSchema, {
* title: "User API",
* version: "1.0.0",
* servers: ["https://api.example.com"]
* });
* ```
*/
openapi(schema: Sche