UNPKG

@wearesage/schema

Version:

A flexible schema definition and validation system for TypeScript with multi-database support

326 lines (276 loc) 7.99 kB
export type Type<T> = new (...args: any[]) => T; export type EntityOptions = { name?: string; description?: string; }; export type PropertyOptions = { name?: string; type?: any; required?: boolean; unique?: boolean; default?: any; description?: string; readOnly?: boolean; writeOnly?: boolean; }; export type RelationshipOptions = { name?: string; target: any; inverse?: string; required?: boolean; cardinality?: "one" | "many"; }; export type RelationshipTypeFunc<T> = () => Type<T> | string; // New relationship options using type function approach // Database-specific relationship options export type Neo4jRelationshipOptions = { direction?: 'IN' | 'OUT'; type?: string; properties?: Record<string, any>; }; export type MongoDBRelationshipOptions = { embedded?: boolean; collection?: string; }; export type PostgreSQLRelationshipOptions = { joinTable?: string; foreignKeyColumn?: string; inverse_foreignKeyColumn?: string; }; export type OneToOneOptions<T> = { target: RelationshipTypeFunc<T>; inverse?: string; name?: string; required?: boolean; neo4j?: Neo4jRelationshipOptions; mongodb?: MongoDBRelationshipOptions; postgresql?: PostgreSQLRelationshipOptions; }; export type OneToManyOptions<T> = { target: RelationshipTypeFunc<T>; inverse?: string; name?: string; required?: boolean; neo4j?: Neo4jRelationshipOptions; mongodb?: MongoDBRelationshipOptions; postgresql?: PostgreSQLRelationshipOptions; }; export type ManyToOneOptions<T> = { target: RelationshipTypeFunc<T>; inverse?: string; name?: string; required?: boolean; neo4j?: Neo4jRelationshipOptions; mongodb?: MongoDBRelationshipOptions; postgresql?: PostgreSQLRelationshipOptions; }; export type ManyToManyOptions<T> = { target: RelationshipTypeFunc<T>; inverse?: string; name?: string; required?: boolean; neo4j?: Neo4jRelationshipOptions; mongodb?: MongoDBRelationshipOptions; postgresql?: PostgreSQLRelationshipOptions; }; // Validation decorator types export type ValidationRule = { type: string; options?: any; message?: string; }; export type CustomValidatorFunction = (value: any) => boolean | Promise<boolean>; export type MinMaxOptions = { value: number; message?: string; }; export type PatternOptions = { pattern: RegExp; message?: string; }; export type EmailOptions = { message?: string; }; export type URLOptions = { message?: string; protocols?: string[]; }; export type CustomValidationOptions = { validator: CustomValidatorFunction; message?: string; }; export type LengthOptions = { min?: number; max?: number; message?: string; }; export type IndexOptions = { unique?: boolean; sparse?: boolean; background?: boolean; name?: string; direction?: 'asc' | 'desc'; ttl?: number; }; export type TimestampOptions = { onCreate?: boolean; onUpdate?: boolean; precision?: 'milliseconds' | 'seconds'; }; // Validation result types export type ValidationError = { property: string; value: any; message: string; rule: string; target: string; }; export type ValidationResult = { isValid: boolean; errors: ValidationError[]; }; export type ValidatorFunction = (value: any, options?: any) => boolean | Promise<boolean>; // Query Builder Types export type QueryCondition = { property: string; operator: QueryOperator; value: any; async?: boolean; }; export type QueryOperator = | 'equals' | 'eq' | 'not_equals' | 'ne' | 'not' | 'greater_than' | 'gt' | 'greater_than_or_equal' | 'gte' | 'less_than' | 'lt' | 'less_than_or_equal' | 'lte' | 'in' | 'not_in' | 'like' | 'ilike' | 'contains' | 'starts_with' | 'ends_with' | 'is_null' | 'is_not_null' | 'between' | 'not_between' | 'regex' | 'not_regex'; export type QueryLogicalOperator = 'and' | 'or' | 'not'; export type QuerySort = { property: string; direction: 'asc' | 'desc'; }; export type QueryInclude = { relationship: string; nested?: QueryInclude[]; }; export type QueryOptions = { limit?: number; offset?: number; sort?: QuerySort[]; include?: QueryInclude[]; }; export type QueryResult<T> = { data: T[]; total: number; hasMore: boolean; metadata: { query: string; executionTime: number; database: string; cached?: boolean; }; }; // Async condition function type - for agents to use external data in queries export type AsyncConditionFunction<T> = (entity: T) => Promise<boolean>; // Type-safe query builder interface export interface IQueryBuilder<T> { // Basic conditions where(property: keyof T): IQueryConditionBuilder<T>; // Logical operators and(property: keyof T): IQueryConditionBuilder<T>; or(property: keyof T): IQueryConditionBuilder<T>; not(property: keyof T): IQueryConditionBuilder<T>; // Async conditions for AI agents whereAsync(condition: AsyncConditionFunction<T>): IQueryBuilder<T>; andAsync(condition: AsyncConditionFunction<T>): IQueryBuilder<T>; orAsync(condition: AsyncConditionFunction<T>): IQueryBuilder<T>; // Relationships include(relationship: string): IQueryBuilder<T>; includeNested(relationship: string, nested: QueryInclude[]): IQueryBuilder<T>; // Sorting & Pagination orderBy(property: keyof T, direction?: 'asc' | 'desc'): IQueryBuilder<T>; limit(count: number): IQueryBuilder<T>; offset(count: number): IQueryBuilder<T>; // Execution execute(): Promise<QueryResult<T>>; first(): Promise<T | null>; count(): Promise<number>; exists(): Promise<boolean>; // Introspection for AI agents getAvailableProperties(): (keyof T)[]; getAvailableRelationships(): string[]; getAvailableOperators(): QueryOperator[]; describeProperty(property: keyof T): PropertyMetadata; describeRelationship(relationship: string): RelationshipMetadata; // Internal methods (for testing and compiler) addCondition(condition: QueryCondition): void; addAsyncCondition(condition: AsyncConditionFunction<T>): void; getConditions(): QueryCondition[]; getAsyncConditions(): AsyncConditionFunction<T>[]; getSorts(): QuerySort[]; getIncludes(): QueryInclude[]; getLimit(): number | undefined; getOffset(): number | undefined; } export interface IQueryConditionBuilder<T> { // Comparison operators equals(value: any): IQueryBuilder<T>; eq(value: any): IQueryBuilder<T>; not(value: any): IQueryBuilder<T>; ne(value: any): IQueryBuilder<T>; // Numeric operators gt(value: number): IQueryBuilder<T>; gte(value: number): IQueryBuilder<T>; lt(value: number): IQueryBuilder<T>; lte(value: number): IQueryBuilder<T>; between(min: number, max: number): IQueryBuilder<T>; // Array operators in(values: any[]): IQueryBuilder<T>; notIn(values: any[]): IQueryBuilder<T>; // String operators like(pattern: string): IQueryBuilder<T>; ilike(pattern: string): IQueryBuilder<T>; contains(value: string): IQueryBuilder<T>; startsWith(value: string): IQueryBuilder<T>; endsWith(value: string): IQueryBuilder<T>; regex(pattern: RegExp): IQueryBuilder<T>; // Null operators isNull(): IQueryBuilder<T>; isNotNull(): IQueryBuilder<T>; // Async operators for AI agents equalsAsync(valueProvider: () => Promise<any>): IQueryBuilder<T>; matchesAsync(condition: AsyncConditionFunction<T>): IQueryBuilder<T>; } // Metadata types for AI agent discovery export type PropertyMetadata = { name: string; type: string; required: boolean; unique: boolean; indexed: boolean; description?: string; validationRules: ValidationRule[]; examples?: any[]; }; export type RelationshipMetadata = { name: string; type: 'one-to-one' | 'one-to-many' | 'many-to-one' | 'many-to-many'; target: string; inverse?: string; required: boolean; description?: string; }; // Query compilation for different databases export type CompiledQuery = { sql?: string; mongodb?: any; neo4j?: string; redis?: string[]; parameters: Record<string, any>; };