UNPKG

kitcn

Version:

kitcn - React Query integration and CLI tools for Convex

1,040 lines (1,039 loc) 235 kB
import { a as ReturnTypeOrValue, i as KnownKeysOnly, o as Simplify$1, t as Assume } from "./types-DF2cg_w0.js"; import * as convex_values0 from "convex/values"; import { GenericId, Validator, Value } from "convex/values"; import { DefineSchemaOptions, FilterExpression, GenericDatabaseReader, GenericDatabaseWriter, GenericIndexFields, GenericSchema, GenericTableIndexes, GenericTableSearchIndexes, GenericTableVectorIndexes, IndexRange, IndexRangeBuilder, SchedulableFunctionReference, Scheduler, SchemaDefinition, TableDefinition, VectorFilterBuilder, internalActionGeneric, internalMutationGeneric } from "convex/server"; //#region src/orm/builders/column-builder.d.ts /** * Core data types supported by column builders * Maps to Convex types: string, number (float64), boolean, bigint (int64), vector */ type ColumnDataType = 'string' | 'number' | 'boolean' | 'bigint' | 'bytes' | 'any' | 'vector'; type ForeignKeyAction = 'cascade' | 'restrict' | 'no action' | 'set null' | 'set default'; interface ColumnReferenceConfig { name?: string; onDelete?: ForeignKeyAction; onUpdate?: ForeignKeyAction; } /** * Base configuration for all column builders * Stores type-level metadata extracted by TypeScript * Matches Drizzle's ColumnBuilderBaseConfig structure */ interface ColumnBuilderBaseConfig<TDataType extends ColumnDataType, TColumnType extends string> { columnType: TColumnType; data: unknown; dataType: TDataType; driverParam: unknown; enumValues: string[] | undefined; name: string; } /** * Runtime configuration stored in builder instance * Updated by chaining methods (.notNull(), .default(), etc.) */ interface ColumnBuilderRuntimeConfig<TData> { columnType: string; dataType: string; default: TData | undefined; defaultFn?: (() => unknown) | undefined; foreignKeyConfigs: { ref: () => ColumnBuilderBase; config: ColumnReferenceConfig; }[]; hasDefault: boolean; isUnique: boolean; name: string; notNull: boolean; onUpdateFn?: (() => unknown) | undefined; primaryKey: boolean; referenceTable?: string; table?: unknown; tableName?: string; uniqueName?: string; uniqueNulls?: 'distinct' | 'not distinct'; } /** * Phantom type configuration - never instantiated, just for TypeScript * Tracks type-level state through method chaining * Matches Drizzle's exact structure */ type ColumnBuilderTypeConfig<T extends ColumnBuilderBaseConfig<ColumnDataType, string>, TTypeConfig extends object> = Simplify$1<{ brand: 'ColumnBuilder'; name: T['name']; dataType: T['dataType']; columnType: T['columnType']; data: T['data']; driverParam: T['driverParam']; notNull: T extends { notNull: infer U; } ? U : boolean; hasDefault: T extends { hasDefault: infer U; } ? U : boolean; isPrimaryKey: T extends { isPrimaryKey: infer U; } ? U : boolean; isUnique: T extends { isUnique: infer U; } ? U : boolean; enumValues: T['enumValues']; } & TTypeConfig>; /** * entityKind symbol for runtime type checking * Following Drizzle's pattern for type guards */ declare const entityKind: unique symbol; interface DrizzleEntity { [entityKind]: string; } /** * ColumnBuilderBase interface - defines the phantom _ property * This interface is crucial for proper type intersection with NotNull/HasDefault/etc. */ interface ColumnBuilderBase<T extends ColumnBuilderBaseConfig<ColumnDataType, string> = ColumnBuilderBaseConfig<ColumnDataType, string>, TTypeConfig extends object = object> { _: ColumnBuilderTypeConfig<T, TTypeConfig>; } /** * Use as the return type for self-referencing `.references()` callbacks. * * @example * ```ts * parentId: text().references((): AnyColumn => commentsTable.id, { onDelete: 'cascade' }) * ``` */ type AnyColumn = ColumnBuilderBase; /** * Base ColumnBuilder abstract class * * All column builders inherit from this class. * Implements chaining methods and stores runtime config. */ declare abstract class ColumnBuilder<T extends ColumnBuilderBaseConfig<ColumnDataType, string> = ColumnBuilderBaseConfig<ColumnDataType, string>, TRuntimeConfig extends object = object, TTypeConfig extends object = object> implements ColumnBuilderBase<T, TTypeConfig>, DrizzleEntity { static readonly [entityKind]: string; readonly [entityKind]: string; /** * Phantom property - never instantiated, just for types * Accumulates type info through method chaining */ _: ColumnBuilderTypeConfig<T, TTypeConfig>; /** * Runtime configuration - actual mutable state */ protected config: ColumnBuilderRuntimeConfig<T['data']> & TRuntimeConfig; constructor(name: T['name'], dataType: T['dataType'], columnType: T['columnType']); /** * Mark column as NOT NULL * Returns type-branded instance with notNull: true */ notNull(): NotNull<this>; /** * Override the TypeScript type for this column. * Mirrors Drizzle's $type() (type-only, no runtime validation changes). */ $type<TType>(): $Type<this, TType>; /** * Set default value for column * Makes field optional on insert */ default(value: ColumnData<this>): HasDefault<this>; /** * Set default function for column (runtime evaluated on insert). * Mirrors Drizzle's $defaultFn() / $default(). */ $defaultFn(fn: () => ColumnData<this>): HasDefault<this>; /** * Alias of $defaultFn for Drizzle parity. */ $default(fn: () => ColumnData<this>): HasDefault<this>; /** * Set on-update function for column (runtime evaluated on update). * Mirrors Drizzle's $onUpdateFn() / $onUpdate(). */ $onUpdateFn(fn: () => ColumnData<this>): HasDefault<this>; /** * Alias of $onUpdateFn for Drizzle parity. */ $onUpdate(fn: () => ColumnData<this>): HasDefault<this>; /** * Mark column as primary key * Implies NOT NULL */ primaryKey(): IsPrimaryKey<NotNull<this>>; /** * Mark column as UNIQUE * Mirrors Drizzle column unique API */ unique(name?: string, config?: { nulls: 'distinct' | 'not distinct'; }): IsUnique<this>; /** * Define a foreign key reference * Mirrors Drizzle column references() API */ references(ref: () => ColumnBuilderBase, config?: ColumnReferenceConfig): this; /** * Build method - must be implemented by subclasses * Compiles builder to Convex validator * * @returns Convex validator for this column */ abstract build(): Validator<any, any, any>; } /** * Type utilities for phantom type branding * Drizzle's EXACT pattern - verified working */ /** * Brand a builder as NOT NULL * Removes | null from extracted type */ type NotNull<T extends ColumnBuilderBase> = T & { _: { notNull: true; }; }; /** * Brand a builder with a table name * Used for relation typing (fields/references must match table) */ type ColumnBuilderWithTableName<T extends ColumnBuilderBase, TTableName extends string> = T & { _: { tableName: TTableName; }; }; /** * Brand a builder as UNIQUE */ type IsUnique<T extends ColumnBuilderBase> = T & { _: { isUnique: true; }; }; /** * Brand a builder with a default value * Makes field optional on insert */ type HasDefault<T extends ColumnBuilderBase> = T & { _: { hasDefault: true; }; }; type ColumnData<TBuilder extends ColumnBuilderBase> = TBuilder['_'] extends { $type: infer TType; } ? TType : TBuilder['_']['data']; type $Type<TBuilder extends ColumnBuilderBase, TType> = TBuilder & { _: { $type: TType; }; }; /** * Brand a builder as a primary key * Implies NOT NULL */ type IsPrimaryKey<T extends ColumnBuilderBase> = T & { _: { isPrimaryKey: true; notNull: true; }; }; //#endregion //#region src/orm/filter-expression.d.ts /** * Extract TypeScript type from a column builder * Uses phantom `_` property to get type info */ type ColumnToType<TBuilder extends ColumnBuilder<any, any, any>> = TBuilder['_']['notNull'] extends true ? TBuilder['_']['data'] : TBuilder['_']['data'] | null; /** * Unique symbol for FilterExpression brand * Prevents structural typing - only expressions created by factory functions are valid */ declare const FilterExpressionBrand: unique symbol; /** * Base filter expression interface * All filter expressions (binary, logical, unary) implement this interface * * @template TValue - The TypeScript type this expression evaluates to */ interface FilterExpression$1<_TValue = boolean> { /** Accept visitor for traversal */ accept<R>(visitor: ExpressionVisitor<R>): R; /** Expression operands (FieldReference, values, or nested expressions) */ readonly operands: readonly any[]; /** Operator string (eq, and, not, etc.) */ readonly operator: string; /** Expression type discriminator */ readonly type: 'binary' | 'logical' | 'unary'; /** Brand symbol for nominal typing */ readonly [FilterExpressionBrand]: true; } /** * Binary operator expression (eq, ne, gt, gte, lt, lte, inArray, notInArray) * Compares field to value: field eq value * * @template TField - Field type being compared */ interface BinaryExpression<TField = any> extends FilterExpression$1<boolean> { /** [field, value] or [field, array] for inArray/notInArray */ readonly operands: readonly [FieldReference<TField>, TField | TField[]]; readonly operator: 'eq' | 'ne' | 'gt' | 'gte' | 'lt' | 'lte' | 'inArray' | 'notInArray' | 'arrayContains' | 'arrayContained' | 'arrayOverlaps' | 'like' | 'ilike' | 'notLike' | 'notIlike' | 'startsWith' | 'endsWith' | 'contains'; readonly type: 'binary'; } /** * Logical operator expression (and, or) * Combines multiple filter expressions */ interface LogicalExpression extends FilterExpression$1<boolean> { /** Array of nested filter expressions */ readonly operands: readonly FilterExpression$1<boolean>[]; readonly operator: 'and' | 'or'; readonly type: 'logical'; } /** * Unary operator expression (not, isNull, isNotNull) * Negates or checks null state of an expression */ interface UnaryExpression extends FilterExpression$1<boolean> { /** Single nested filter expression or field reference for null checks */ readonly operands: readonly [FilterExpression$1<boolean> | FieldReference<any>]; readonly operator: 'not' | 'isNull' | 'isNotNull'; readonly type: 'unary'; } /** * CRITICAL: FieldReference abstraction * * Decouples filter expressions from M2 table configuration * Allows filter expressions to reference fields without knowing about validators * * @template TValue - TypeScript type of the field */ interface FieldReference<TValue = unknown> { readonly __brand: 'FieldReference'; /** Phantom type for type inference - not present at runtime */ readonly __type?: TValue; readonly fieldName: string; } /** * Create a field reference * Used internally by operator functions */ declare function fieldRef<T>(fieldName: string): FieldReference<T>; /** * Type guard for FieldReference */ declare function isFieldReference(value: any): value is FieldReference<any>; /** * Column wrapper - combines builder with column name * Used in where clause to pass column objects to operators * Following Drizzle's pattern: operators receive columns, not extracted types * * @template TBuilder - The column builder type * @template TName - The column name (string literal) */ interface Column<TBuilder extends ColumnBuilder<any, any, any> = any, TName extends string = string> { readonly builder: TBuilder; readonly columnName: TName; } type ColumnArgument<TBuilder extends ColumnBuilder<any, any, any>> = Column<TBuilder, string> | TBuilder; /** * Create a column wrapper * Used internally by query builder's _createColumnProxies */ /** * Expression visitor interface for tree traversal * Extensible pattern - add new visit methods without modifying expression classes * * @template R - Return type of visit operations */ interface ExpressionVisitor<R = void> { visitBinary(expr: BinaryExpression): R; visitLogical(expr: LogicalExpression): R; visitUnary(expr: UnaryExpression): R; } /** * Equality operator: field == value * * @example * const filter = eq(cols.name, 'Alice'); */ declare function eq<TBuilder extends ColumnBuilder<any, any, any>>(col: ColumnArgument<TBuilder>, value: ColumnToType<TBuilder>): BinaryExpression<ColumnToType<TBuilder>>; /** * Not equal operator: field != value */ declare function ne<TBuilder extends ColumnBuilder<any, any, any>>(col: ColumnArgument<TBuilder>, value: ColumnToType<TBuilder>): BinaryExpression<ColumnToType<TBuilder>>; /** * Greater than operator: field > value */ declare function gt<TBuilder extends ColumnBuilder<any, any, any>>(col: ColumnArgument<TBuilder>, value: ColumnToType<TBuilder>): BinaryExpression<ColumnToType<TBuilder>>; /** * Greater than or equal operator: field >= value */ declare function gte<TBuilder extends ColumnBuilder<any, any, any>>(col: ColumnArgument<TBuilder>, value: ColumnToType<TBuilder>): BinaryExpression<ColumnToType<TBuilder>>; /** * Less than operator: field < value */ declare function lt<TBuilder extends ColumnBuilder<any, any, any>>(col: ColumnArgument<TBuilder>, value: ColumnToType<TBuilder>): BinaryExpression<ColumnToType<TBuilder>>; /** * Less than or equal operator: field <= value */ declare function lte<TBuilder extends ColumnBuilder<any, any, any>>(col: ColumnArgument<TBuilder>, value: ColumnToType<TBuilder>): BinaryExpression<ColumnToType<TBuilder>>; /** * Between operator: field BETWEEN min AND max (inclusive) * * Sugar for and(gte(field, min), lte(field, max)). */ declare function between<TBuilder extends ColumnBuilder<any, any, any>>(col: ColumnArgument<TBuilder>, min: ColumnToType<TBuilder>, max: ColumnToType<TBuilder>): FilterExpression$1<boolean>; /** * Not between operator: field < min OR field > max * * Sugar for or(lt(field, min), gt(field, max)). */ declare function notBetween<TBuilder extends ColumnBuilder<any, any, any>>(col: ColumnArgument<TBuilder>, min: ColumnToType<TBuilder>, max: ColumnToType<TBuilder>): FilterExpression$1<boolean>; /** * LIKE operator: SQL-style pattern matching with % wildcards * Note: Implemented as post-filter (Convex has no native LIKE) * * @example * const users = await db.query.users.findMany({ * where: like(users.name, '%alice%'), * }); */ declare function like<TBuilder extends ColumnBuilder<any, any, any>>(col: ColumnArgument<TBuilder>, pattern: string): BinaryExpression<string>; /** * ILIKE operator: Case-insensitive LIKE * Note: Implemented as post-filter (Convex has no native LIKE) * * @example * const users = await db.query.users.findMany({ * where: ilike(users.name, '%ALICE%'), * }); */ declare function ilike<TBuilder extends ColumnBuilder<any, any, any>>(col: ColumnArgument<TBuilder>, pattern: string): BinaryExpression<string>; /** * startsWith operator: Check if string starts with prefix * Optimized for prefix matching * * @example * const users = await db.query.users.findMany({ * where: startsWith(users.email, 'admin@'), * }); */ declare function startsWith<TBuilder extends ColumnBuilder<any, any, any>>(col: ColumnArgument<TBuilder>, prefix: string): BinaryExpression<string>; /** * endsWith operator: Check if string ends with suffix * * @example * const users = await db.query.users.findMany({ * where: endsWith(users.email, '@example.com'), * }); */ declare function endsWith<TBuilder extends ColumnBuilder<any, any, any>>(col: ColumnArgument<TBuilder>, suffix: string): BinaryExpression<string>; /** * contains operator: Check if string contains substring * Can use search index for optimization when available * * @example * const posts = await db.query.posts.findMany({ * where: contains(posts.title, 'javascript'), * }); */ declare function contains<TBuilder extends ColumnBuilder<any, any, any>>(col: ColumnArgument<TBuilder>, substring: string): BinaryExpression<string>; /** * Logical AND: all expressions must be true * Filters out undefined expressions (following Drizzle pattern) * * @example * const filter = and( * eq(fieldRef('age'), 25), * eq(fieldRef('name'), 'Alice') * ); */ declare function and(...expressions: (FilterExpression$1<boolean> | undefined)[]): LogicalExpression | undefined; /** * Logical OR: at least one expression must be true * Filters out undefined expressions (following Drizzle pattern) * * @example * const filter = or( * eq(fieldRef('status'), 'active'), * eq(fieldRef('status'), 'pending') * ); */ declare function or(...expressions: (FilterExpression$1<boolean> | undefined)[]): LogicalExpression | undefined; /** * Logical NOT: negates expression * * @example * const filter = not(eq(fieldRef('isDeleted'), true)); */ declare function not(expression: FilterExpression$1<boolean>): UnaryExpression; /** * Array membership operator: field IN array * * @example * const filter = inArray(cols.status, ['active', 'pending']); */ declare function inArray<TBuilder extends ColumnBuilder<any, any, any>>(col: ColumnArgument<TBuilder>, values: readonly ColumnToType<TBuilder>[]): BinaryExpression<ColumnToType<TBuilder>>; /** * Array exclusion operator: field NOT IN array * Validates array is non-empty at construction time * * @example * const filter = notInArray(cols.role, ['admin', 'moderator']); */ declare function notInArray<TBuilder extends ColumnBuilder<any, any, any>>(col: ColumnArgument<TBuilder>, values: readonly ColumnToType<TBuilder>[]): BinaryExpression<ColumnToType<TBuilder>>; /** * Null check operator: field IS NULL * Type validation: Only works with nullable fields * * @example * const filter = isNull(cols.deletedAt); */ declare function isNull<TBuilder extends ColumnBuilder<any, any, any>>(col: ColumnArgument<TBuilder>): UnaryExpression; /** * Not null check operator: field IS NOT NULL * Type validation: Only works with nullable fields * * @example * const filter = isNotNull(cols.deletedAt); */ declare function isNotNull<TBuilder extends ColumnBuilder<any, any, any>>(col: ColumnArgument<TBuilder>): UnaryExpression; //#endregion //#region src/orm/builders/system-fields.d.ts /** * System ID field builder (public id, internal _id) * Always present, always non-null */ type ConvexSystemIdConfig = ColumnBuilderBaseConfig<'string', 'ConvexSystemId'> & { data: string; driverParam: string; enumValues: undefined; }; declare class ConvexSystemIdBuilder<_TTableName extends string> extends ColumnBuilder<ConvexSystemIdConfig, {}, { notNull: true; }> { static readonly [entityKind]: string; readonly [entityKind]: string; constructor(); build(): convex_values0.VString<string, "required">; /** * Convex validator - runtime access * System fields use v.string() for _id */ get convexValidator(): convex_values0.VString<string, "required">; } /** * System creation time field builder (_creationTime) * Always present, always non-null, always a number (milliseconds) */ type ConvexSystemCreationTimeConfig = ColumnBuilderBaseConfig<'number', 'ConvexSystemCreationTime'> & { data: number; driverParam: number; enumValues: undefined; }; declare class ConvexSystemCreationTimeBuilder extends ColumnBuilder<ConvexSystemCreationTimeConfig, {}, { notNull: true; }> { static readonly [entityKind]: string; readonly [entityKind]: string; constructor(); build(): convex_values0.VFloat64<number, "required">; /** * Convex validator - runtime access * System fields use v.number() for _creationTime */ get convexValidator(): convex_values0.VFloat64<number, "required">; } type ConvexSystemCreatedAtConfig = ColumnBuilderBaseConfig<'number', 'ConvexSystemCreatedAt'> & { data: number; driverParam: number; enumValues: undefined; }; declare class ConvexSystemCreatedAtBuilder extends ColumnBuilder<ConvexSystemCreatedAtConfig, {}, { notNull: true; }> { static readonly [entityKind]: string; readonly [entityKind]: string; constructor(); build(): convex_values0.VFloat64<number, "required">; get convexValidator(): convex_values0.VFloat64<number, "required">; } /** * Create system field builders for a table * These are automatically added to every ConvexTable */ type SystemFields<TName extends string> = { id: ColumnBuilderWithTableName<ConvexSystemIdBuilder<TName>, TName>; }; type InternalSystemFields<TName extends string> = { _creationTime: ColumnBuilderWithTableName<ConvexSystemCreationTimeBuilder, TName>; }; type SystemFieldAliases<TName extends string, TColumns extends Record<string, unknown> = {}> = 'createdAt' extends keyof TColumns ? {} : { createdAt: ColumnBuilderWithTableName<ConvexSystemCreatedAtBuilder, TName>; }; type SystemFieldsWithAliases<TName extends string, TColumns extends Record<string, unknown> = {}> = SystemFields<TName> & InternalSystemFields<TName> & SystemFieldAliases<TName, TColumns>; //#endregion //#region src/orm/symbols.d.ts /** * Symbol-based metadata storage for ORM tables * Following Drizzle's pattern for type-safe runtime introspection */ type OrmRuntimeDefaults = { defaultLimit?: number; countBackfillBatchSize?: number; relationFanOutMaxKeys?: number; aggregateCartesianMaxKeys?: number; aggregateWorkBudget?: number; mutationBatchSize?: number; mutationLeafBatchSize?: number; mutationMaxRows?: number; mutationMaxBytesPerBatch?: number; mutationScheduleCallCap?: number; mutationExecutionMode?: 'sync' | 'async'; mutationAsyncDelayMs?: number; }; type OrmDeleteMode = 'hard' | 'soft' | 'scheduled'; type OrmTableDeleteConfig = { mode: OrmDeleteMode; delayMs?: number; }; type TablePolymorphicVariantRuntime = { fieldNames: readonly string[]; requiredFieldNames: readonly string[]; }; type TablePolymorphicConfigRuntime = { discriminator: string; alias: string; generatedFieldNames: readonly string[]; variants: Readonly<Record<string, TablePolymorphicVariantRuntime>>; }; declare const TableName: unique symbol; declare const Columns: unique symbol; declare const Brand: unique symbol; declare const RlsPolicies: unique symbol; declare const EnableRLS: unique symbol; declare const TableDeleteConfig: unique symbol; declare const TablePolymorphic: unique symbol; declare const OrmSchemaDefinition: unique symbol; declare const OrmSchemaExtensionTables: unique symbol; declare const OrmSchemaExtensions: unique symbol; declare const OrmSchemaExtensionRelations: unique symbol; declare const OrmSchemaExtensionTriggers: unique symbol; declare const OrmSchemaRelations: unique symbol; declare const OrmSchemaTriggers: unique symbol; //#endregion //#region src/orm/unset-token.d.ts declare const unsetToken: unique symbol; type UnsetToken = typeof unsetToken; //#endregion //#region src/orm/types.d.ts /** * Value or array helper (Drizzle pattern). */ type ValueOrArray<T> = T | T[]; /** * Type equality check - returns true if X and Y are exactly the same type * Pattern from Drizzle: drizzle-orm/src/utils.ts:172 */ type Equal<X, Y> = (<T>() => T extends X ? 1 : 2) extends (<T>() => T extends Y ? 1 : 2) ? true : false; /** * Merge two object types without using intersection * Intersection can cause TypeScript to lose phantom type brands * This manually combines keys from both types */ type Merge<A, B> = { [K in keyof A | keyof B]: K extends keyof B ? B[K] : K extends keyof A ? A[K] : never }; type IndexKey = (Value | undefined)[]; type FindManyUnionSource<TTableConfig extends TableRelationalConfig = TableRelationalConfig> = { where?: RelationsFilter<TTableConfig, any> | WhereCallback<TTableConfig>; }; type PipelineRelationName<TTableConfig extends TableRelationalConfig> = Extract<keyof TTableConfig['relations'], string>; type FindManyPipelineFlatMapConfig<TTableConfig extends TableRelationalConfig = TableRelationalConfig, TRelationName extends PipelineRelationName<TTableConfig> = PipelineRelationName<TTableConfig>> = { relation: TRelationName; where?: unknown; orderBy?: unknown; limit?: number; includeParent?: boolean; }; type FindManyPipelineFlatMapStage<TTableConfig extends TableRelationalConfig = TableRelationalConfig> = { flatMap: FindManyPipelineFlatMapConfig<TTableConfig>; }; type FindManyPipelineFilterWithStage<TRow = unknown> = { filterWith: (row: TRow) => boolean | Promise<boolean>; }; type FindManyPipelineMapStage<TRow = unknown, TOutput = unknown> = { map: (row: TRow) => TOutput | null | Promise<TOutput | null>; }; type FindManyPipelineDistinctStage = { distinct: { fields: string[]; }; }; type FindManyPipelineStageForInput<TSchema extends TablesRelationalConfig = TablesRelationalConfig, TTableConfig extends TableRelationalConfig = TableRelationalConfig, TRow = BuildQueryResult<TSchema, TTableConfig, true>> = FindManyPipelineFilterWithStage<TRow> | FindManyPipelineMapStage<TRow> | FindManyPipelineDistinctStage | FindManyPipelineFlatMapStage<TTableConfig>; type FindManyPipelineConfig<TSchema extends TablesRelationalConfig = TablesRelationalConfig, TTableConfig extends TableRelationalConfig = TableRelationalConfig, TStages extends readonly unknown[] = readonly FindManyPipelineStageForInput<TSchema, TTableConfig, BuildQueryResult<TSchema, TTableConfig, true>>[]> = { union?: FindManyUnionSource<TTableConfig>[]; interleaveBy?: string[]; stages?: TStages; }; type FindManyPageByKeyConfig = { index?: string; order?: 'asc' | 'desc'; startKey?: IndexKey; startInclusive?: boolean; endKey?: IndexKey; endInclusive?: boolean; targetMaxRows?: number; absoluteMaxRows?: number; }; type KeyPageResult<T> = { page: T[]; indexKeys: IndexKey[]; hasMore: boolean; }; /** * Extract full document type from a ConvexTable (includes system fields) * Uses GetColumnData in 'query' mode to respect notNull brands * * @example * const users = convexTable('users', { name: text().notNull() }); * type User = InferSelectModel<typeof users>; * // → { id: string, createdAt: number, name: string } * * const posts = convexTable('posts', { title: text() }); // nullable * type Post = InferSelectModel<typeof posts>; * // → { id: string, createdAt: number, title: string | null } */ type InferSelectModel<TTable extends ConvexTable<any>> = Simplify$1<Merge<{ id: string; createdAt: number; }, { [K in keyof TTable['_']['columns']]: GetColumnData<TTable['_']['columns'][K], 'query'> }>>; type RequiredKeyOnly<TKey extends string, TColumn extends ColumnBuilderBase> = TColumn['_']['notNull'] extends true ? TColumn['_']['hasDefault'] extends true ? never : TKey : never; type OptionalKeyOnly<TKey extends string, TColumn extends ColumnBuilderBase> = TColumn['_']['notNull'] extends true ? TColumn['_']['hasDefault'] extends true ? TKey : never : TKey; type InferInsertModelFromColumns<TColumns extends Record<string, ColumnBuilderBase>, TExcludeKeys extends string = never> = Simplify$1<{ [K in keyof TColumns & string as K extends TExcludeKeys ? never : RequiredKeyOnly<K, TColumns[K]>]: GetColumnData<TColumns[K], 'query'> } & { [K in keyof TColumns & string as K extends TExcludeKeys ? never : OptionalKeyOnly<K, TColumns[K]>]?: GetColumnData<TColumns[K], 'query'> | undefined }>; type TablePolymorphicInsertMetadata<TTable extends ConvexTable<any>> = { [K in keyof TTable['_']['columns'] & string]: TTable['_']['columns'][K] extends { __polymorphic: infer TMeta; } ? TMeta extends { variants: infer TVariants extends Record<string, Record<string, ColumnBuilderBase>>; } ? { discriminator: K; variants: TVariants; } : never : never }[keyof TTable['_']['columns'] & string]; type PolymorphicVariantFieldNames<TVariants extends Record<string, Record<string, ColumnBuilderBase>>> = Extract<TVariants[keyof TVariants & string] extends infer TVariantColumns ? TVariantColumns extends Record<string, ColumnBuilderBase> ? keyof TVariantColumns : never : never, string>; type PolymorphicVariantInsertCase<TBase extends Record<string, unknown>, TDiscriminator extends string, TCase extends string, TVariantColumns extends Record<string, ColumnBuilderBase>, TAllGeneratedFields extends string> = Simplify$1<TBase & { [K in TDiscriminator]: TCase } & { [K in keyof TVariantColumns & string as RequiredKeyOnly<K, TVariantColumns[K]>]: GetColumnData<TVariantColumns[K], 'query'> } & { [K in keyof TVariantColumns & string as OptionalKeyOnly<K, TVariantColumns[K]>]?: GetColumnData<TVariantColumns[K], 'query'> | undefined } & { [K in Exclude<TAllGeneratedFields, keyof TVariantColumns & string>]?: never }>; type PolymorphicVariantInsertUnion<TBase extends Record<string, unknown>, TMetadata extends { discriminator: string; variants: Record<string, Record<string, ColumnBuilderBase>>; }> = { [TCase in keyof TMetadata['variants'] & string]: PolymorphicVariantInsertCase<TBase, TMetadata['discriminator'], TCase, TMetadata['variants'][TCase], PolymorphicVariantFieldNames<TMetadata['variants']>> }[keyof TMetadata['variants'] & string]; type InferPolymorphicInsertModel<TTable extends ConvexTable<any>, TMetadata extends { discriminator: string; variants: Record<string, Record<string, ColumnBuilderBase>>; }> = PolymorphicVariantInsertUnion<InferInsertModelFromColumns<TTable['_']['columns'], TMetadata['discriminator'] | PolymorphicVariantFieldNames<TMetadata['variants']>>, TMetadata>; /** * Extract insert type from a ConvexTable (excludes system fields). * Mirrors Drizzle behavior: required if notNull && no default, otherwise optional. * * @example * const users = convexTable('users', { name: text().notNull() }); * type NewUser = InferInsertModel<typeof users>; * // → { name: string } */ type InferInsertModel<TTable extends ConvexTable<any>> = Simplify$1<[TablePolymorphicInsertMetadata<TTable>] extends [never] ? InferInsertModelFromColumns<TTable['_']['columns']> : InferPolymorphicInsertModel<TTable, Extract<TablePolymorphicInsertMetadata<TTable>, object>>>; /** * Extract column data type with mode-based handling (Drizzle pattern) * * Following Drizzle's GetColumnData pattern for consistent type extraction: * - 'raw' mode: Returns base data type without null (for inserts, operator comparisons) * - 'query' mode: Respects notNull brand, adds | null for nullable fields (for selects) * * @template TColumn - Column builder type * @template TInferMode - 'query' (default, adds | null) or 'raw' (base type only) * * @example * const name = text().notNull(); * type NameQuery = GetColumnData<typeof name, 'query'>; // string * type NameRaw = GetColumnData<typeof name, 'raw'>; // string * * const age = integer(); // nullable * type AgeQuery = GetColumnData<typeof age, 'query'>; // number | null * type AgeRaw = GetColumnData<typeof age, 'raw'>; // number */ type GetColumnData<TColumn extends ColumnBuilderBase, TInferMode extends 'query' | 'raw' = 'query'> = TInferMode extends 'raw' ? ColumnDataWithOverride<TColumn> : TColumn['_']['notNull'] extends true ? ColumnDataWithOverride<TColumn> : ColumnDataWithOverride<TColumn> | null; type ColumnDataWithOverride<TColumn extends ColumnBuilderBase> = TColumn['_'] extends { $type: infer TType; } ? unknown extends TType ? TColumn['_']['data'] : TType : TColumn['_']['data']; type AggregateIndexMap<TTableConfig extends TableRelationalConfig = TableRelationalConfig> = TTableConfig['table'] extends ConvexTable<any, any, any, any, infer TAggregateIndexes extends Record<string, string>> ? TAggregateIndexes : Record<string, string>; type AggregateIndexedFieldName<TTableConfig extends TableRelationalConfig = TableRelationalConfig> = Extract<{ [K in keyof AggregateIndexMap<TTableConfig>]: AggregateIndexMap<TTableConfig>[K] }[keyof AggregateIndexMap<TTableConfig>], string>; type AggregateScalarFieldName<TTableConfig extends TableRelationalConfig> = Extract<keyof TTableConfig['table']['_']['columns'], string>; type AggregateWhereFieldName<TTableConfig extends TableRelationalConfig = TableRelationalConfig> = AggregateIndexedFieldName<TTableConfig>; type AggregateWhereFieldValue<TTableConfig extends TableRelationalConfig, TFieldName extends string> = TFieldName extends keyof TTableConfig['table']['_']['columns'] ? TTableConfig['table']['_']['columns'][TFieldName] extends ColumnBuilderBase ? GetColumnData<TTableConfig['table']['_']['columns'][TFieldName], 'query'> : unknown : unknown; type AggregateWhereFieldFilter<TValue> = TValue | { eq?: TValue | undefined; in?: readonly TValue[] | undefined; isNull?: true | undefined; gt?: TValue | undefined; gte?: TValue | undefined; lt?: TValue | undefined; lte?: TValue | undefined; }; type AggregateNoScanWhereBase<TTableConfig extends TableRelationalConfig = TableRelationalConfig> = { [K in AggregateWhereFieldName<TTableConfig>]?: AggregateWhereFieldFilter<AggregateWhereFieldValue<TTableConfig, K>> }; type AggregateNoScanWhere<TTableConfig extends TableRelationalConfig = TableRelationalConfig> = Simplify$1<AggregateNoScanWhereBase<TTableConfig> & { AND?: AggregateNoScanWhereBase<TTableConfig>[] | undefined; OR?: AggregateNoScanWhereBase<TTableConfig>[] | undefined; }>; type AggregateNoScanWhereArg<TTableConfig extends TableRelationalConfig = TableRelationalConfig> = [AggregateWhereFieldName<TTableConfig>] extends [never] ? never : AggregateNoScanWhere<TTableConfig>; /** * Query configuration for findMany/findFirst * * @template TRelationType - 'one' or 'many' determines available options * @template TSchema - Full schema configuration * @template TTableConfig - Configuration for the queried table */ type DBQueryConfig<TRelationType extends 'one' | 'many' = 'one' | 'many', _TIsRoot extends boolean = boolean, TSchema extends TablesRelationalConfig = TablesRelationalConfig, TTableConfig extends TableRelationalConfig = TableRelationalConfig> = { /** * Column selection - pick specific columns to return * If omitted, all columns are selected */ columns?: { [K in keyof TableColumns<TTableConfig>]?: boolean } | undefined; /** * Relation loading - specify which relations to include * Can be `true` for default config or nested config object */ with?: KnownKeysOnly<{ [K in keyof TTableConfig['relations']]?: true | DBQueryConfig<TTableConfig['relations'][K] extends One<any, any> ? 'one' : 'many', false, TSchema, FindTableByDBName<TSchema, TTableConfig['relations'][K]['targetTableName']>> | undefined } & { _count?: { [K in keyof TTableConfig['relations']]?: true | { where?: AggregateNoScanWhereArg<FindTableByDBName<TSchema, Extract<TTableConfig['relations'][K]['targetTableName'], string>>> | undefined; } } | undefined; }, TTableConfig['relations'] & { _count?: unknown; }> | undefined; /** * Auto-include one() relations for discriminator-backed tables. */ withVariants?: true | undefined; /** * Extra computed fields (post-fetch, computed in JS at runtime) */ extras?: Record<string, Value | ((row: InferModelFromColumns<TableColumns<TTableConfig>>) => Value)> | ((fields: Simplify$1<[TableColumns<TTableConfig>] extends [never] ? {} : TableColumns<TTableConfig>>) => Record<string, Value | ((row: InferModelFromColumns<TableColumns<TTableConfig>>) => Value)>) | undefined; /** * Order results - callback or object syntax */ orderBy?: DBQueryConfigOrderBy<TTableConfig> | undefined; /** Skip first N results */ offset?: number | undefined; /** * Cursor pagination (Convex native). When `cursor` is provided, `limit` is * required and the result type changes to a paginated shape. * * - First page: cursor: null * - Next page: cursor: previous.continueCursor */ cursor?: _TIsRoot extends true ? string | null : never; /** * Pin the end boundary to a previously returned cursor. * Only valid with cursor pagination. */ endCursor?: _TIsRoot extends true ? string | null : never; /** * Maximum documents to scan during predicate `where(fn)` pagination. * Only valid when `cursor` is provided. */ maxScan?: _TIsRoot extends true ? number : never; /** * Full-text search query configuration. * Only available on tables that declare search indexes. */ search?: SearchQueryConfig<TTableConfig> | undefined; /** * Vector search query configuration. * Only available on tables that declare vector indexes. */ vectorSearch?: VectorQueryConfig<TTableConfig> | undefined; /** * Stream-backed advanced query pipeline. */ pipeline?: _TIsRoot extends true ? FindManyPipelineConfig<TSchema, TTableConfig> : never; /** * Key-based page boundaries. */ pageByKey?: _TIsRoot extends true ? FindManyPageByKeyConfig : never; } & (TRelationType extends 'many' ? { /** Limit number of results */limit?: number | undefined; } : {}) & { /** * Relation-aware filter object (v1) or callback expression. */ where?: RelationsFilter<TTableConfig, TSchema> | WhereCallback<TTableConfig> | undefined; /** * Allow full scans when no index can be used. */ allowFullScan?: boolean | undefined; }; type CountConfig<_TSchema extends TablesRelationalConfig = TablesRelationalConfig, TTableConfig extends TableRelationalConfig = TableRelationalConfig> = { where?: AggregateNoScanWhereArg<TTableConfig> | undefined; orderBy?: DBQueryConfigOrderBy<TTableConfig> | undefined; skip?: number | undefined; take?: number | undefined; cursor?: { [K in Extract<keyof TTableConfig['table']['_']['columns'], string>]?: GetColumnData<TableColumns<TTableConfig>[K], 'query'> | undefined } | undefined; select?: ({ _all?: true | undefined; } & { [K in Extract<keyof TTableConfig['table']['_']['columns'], string>]?: true | undefined }) | undefined; }; type AggregateNumericFieldName<TTableConfig extends TableRelationalConfig> = { [K in AggregateScalarFieldName<TTableConfig>]: NonNullable<GetColumnData<TableColumns<TTableConfig>[K], 'query'>> extends number ? K : never }[AggregateScalarFieldName<TTableConfig>]; type AggregateFieldValue<TTableConfig extends TableRelationalConfig, TField extends AggregateScalarFieldName<TTableConfig>> = GetColumnData<TableColumns<TTableConfig>[TField], 'query'>; type AggregateConfig<_TSchema extends TablesRelationalConfig = TablesRelationalConfig, TTableConfig extends TableRelationalConfig = TableRelationalConfig> = { where?: AggregateNoScanWhereArg<TTableConfig> | undefined; orderBy?: DBQueryConfigOrderBy<TTableConfig> | undefined; skip?: number | undefined; take?: number | undefined; cursor?: { [K in Extract<keyof TTableConfig['table']['_']['columns'], string>]?: GetColumnData<TableColumns<TTableConfig>[K], 'query'> | undefined } | undefined; _count?: true | ({ _all?: true | undefined; } & { [K in AggregateScalarFieldName<TTableConfig>]?: true | undefined }) | undefined; _sum?: { [K in AggregateNumericFieldName<TTableConfig>]?: true | undefined } | undefined; _avg?: { [K in AggregateNumericFieldName<TTableConfig>]?: true | undefined } | undefined; _min?: { [K in AggregateScalarFieldName<TTableConfig>]?: true | undefined } | undefined; _max?: { [K in AggregateScalarFieldName<TTableConfig>]?: true | undefined } | undefined; }; type GroupByByInput<TTableConfig extends TableRelationalConfig = TableRelationalConfig> = AggregateWhereFieldName<TTableConfig> | readonly AggregateWhereFieldName<TTableConfig>[]; type GroupBySelectedFields<TBy> = TBy extends readonly (infer TField)[] ? Extract<TField, string> : Extract<TBy, string>; type GroupByByResult<TTableConfig extends TableRelationalConfig, TBy> = Simplify$1<{ [K in GroupBySelectedFields<TBy> & AggregateScalarFieldName<TTableConfig>]: AggregateFieldValue<TTableConfig, K> }>; type GroupByOrderDirection = 'asc' | 'desc'; type GroupByByOrderBy<TBy> = Partial<Record<GroupBySelectedFields<TBy>, GroupByOrderDirection>>; type GroupByMetricOrderBy<TTableConfig extends TableRelationalConfig> = { _count?: GroupByOrderDirection | ({ _all?: GroupByOrderDirection | undefined; } & { [K in AggregateScalarFieldName<TTableConfig>]?: GroupByOrderDirection | undefined }) | undefined; _sum?: { [K in AggregateNumericFieldName<TTableConfig>]?: GroupByOrderDirection | undefined } | undefined; _avg?: { [K in AggregateNumericFieldName<TTableConfig>]?: GroupByOrderDirection | undefined } | undefined; _min?: { [K in AggregateScalarFieldName<TTableConfig>]?: GroupByOrderDirection | undefined } | undefined; _max?: { [K in AggregateScalarFieldName<TTableConfig>]?: GroupByOrderDirection | undefined } | undefined; }; type GroupByOrderBy<TTableConfig extends TableRelationalConfig, TBy> = ValueOrArray<GroupByByOrderBy<TBy> | GroupByMetricOrderBy<TTableConfig>>; type GroupByHavingValue<TValue> = TValue | { eq?: TValue | undefined; in?: readonly TValue[] | undefined; isNull?: true | undefined; gt?: TValue | undefined; gte?: TValue | undefined; lt?: TValue | undefined; lte?: TValue | undefined; }; type GroupByHaving<TTableConfig extends TableRelationalConfig, TBy> = Simplify$1<{ [K in GroupBySelectedFields<TBy>]?: GroupByHavingValue<AggregateFieldValue<TTableConfig, Extract<K, AggregateScalarFieldName<TTableConfig>>>> } & { _count?: GroupByHavingValue<number> | ({ _all?: GroupByHavingValue<number> | undefined; } & { [K in AggregateScalarFieldName<TTableConfig>]?: GroupByHavingValue<number> | undefined }) | undefined; _sum?: { [K in AggregateNumericFieldName<TTableConfig>]?: GroupByHavingValue<number | null> | undefined } | undefined; _avg?: { [K in AggregateNumericFieldName<TTableConfig>]?: GroupByHavingValue<number | null> | undefined } | undefined; _min?: { [K in AggregateScalarFieldName<TTableConfig>]?: GroupByHavingValue<AggregateFieldValue<TTableConfig, K> | null> | undefined } | undefined; _max?: { [K in AggregateScalarFieldName<TTableConfig>]?: GroupByHavingValue<AggregateFieldValue<TTableConfig, K> | null> | undefined } | undefined; AND?: GroupByHaving<TTableConfig, TBy>[] | undefined; }>; type GroupByConfig<_TSchema extends TablesRelationalConfig = TablesRelationalConfig, TTableConfig extends TableRelationalConfig = TableRelationalConfig> = { by: GroupByByInput<TTableConfig>; where?: AggregateNoScanWhereArg<TTableConfig> | undefined; orderBy?: GroupByOrderBy<TTableConfig, GroupByByInput<TTableConfig>> | undefined; skip?: number | undefined; take?: number | undefined; cursor?: Record<string, unknown> | undefined; having?: GroupByHaving<TTableConfig, GroupByByInput<TTableConfig>> | undefined; _count?: true | ({ _all?: true | undefined; } & { [K in AggregateScalarFieldName<TTableConfig>]?: true | undefined }) | undefined; _sum?: { [K in AggregateNumericFieldName<TTableConfig>]?: true | undefined } | undefined; _avg?: { [K in AggregateNumericFieldName<TTableConfig>]?: true | undefined } | undefined; _min?: { [K in AggregateScalarFieldName<TTableConfig>]?: true | undefined } | undefined; _max?: { [K in AggregateScalarFieldName<TTableConfig>]?: true | undefined } | undefined; }; type SelectedTrueKeys<TSelection> = Extract<{ [K in keyof TSelection]-?: TSelection[K] extends true ? K : never }[keyof TSelection], string>; type CountSelectResult<TTableConfig extends TableRelationalConfig, TSelect extends Record<string, unknown>> = Simplify$1<(TSelect extends { _all: true; } ? { _all: number; } : {}) & { [K in SelectedTrueKeys<TSelect> & AggregateScalarFieldName<TTableConfig>]: number }>; type AggregateCountResult<TTableConfig extends TableRelationalConfig, TCount> = TCount extends true ? number : TCount extends Record<string, unknown> ? CountSelectResult<TTableConfig, TCount> : never; type AggregateNumericNullableResult<TSelect> = Simplify$1<{ [K in SelectedTrueKeys<NonNullable<TSelect>>]: number | null }>; type AggregateComparableResult<TTableConfig extends TableRelationalConfig, TSelect> = Simplify$1<{ [K in SelectedTrueKeys<NonNullable<TSelect>> & AggregateScalarFieldName<TTableConfig>]: AggregateFieldValue<TTableConfig, K> | null }>; type CountResult<TTableConfig extends TableRelationalConfig, TConfig extends CountConfig<any, TTableConfig> | undefined> = TConfig extends { select: infer TSelect extends Record<string, unknown>; } ? CountSelectResult<TTableConfig, TSelect> : number; type AggregateResult<TTableConfig extends TableRelationalConfig, TConfig extends AggregateConfig<any, TTableConfig>> = Simplify$1<(TConfig extends { _count: infer TCount; } ? { _count: AggregateCountResult<TTableConfig, TCount>; } : {}) & (TConfig extends { _sum: infer TSum extends Record<string, unknown>; } ? { _sum: AggregateNumericNullableResult<TSum>; } : {}) & (TConfig extends { _avg: infer TAvg extends Record<string, unknown>; } ? { _avg: AggregateNumericNullableResult<TAvg>; } : {}) & (TConfig extends { _min: infer TMin extends Record<string, unknown>; } ? { _min: AggregateComparableResult<TTableConfig, TMin>; } : {}) & (TConfig extends { _max: infer TMax extends Record<string, unknown>; } ? { _max: AggregateComparableResult<TTableConfig, TMax>; } : {})>; type GroupByRowResult<TTableConfig extends TableRelationalConfig, TConfig extends GroupByConfig<any, TTableConfig>> = Simplify$1<GroupByByResult<TTableConfig, TConfig['by']> & (TConfig extends { _count: infer TCount; } ? { _count: AggregateCountResult<TTableConfig, TCount>; } : {}) & (TConfig extends { _sum: infer TSum extends Record<string, unknown>; } ? { _sum: AggregateNumericNullableResult<TSum>; } : {}) & (TConfig extends { _avg: infer TAvg extends Record<string, unknown>; } ? { _avg: AggregateNumericNullableResult<TAvg>; } : {}) & (TConfig extends { _min: infer TMin extends Record<string, unknown>; } ? { _min: AggregateComparableResult<TTableConfig, TMin>; } : {}) & (TConfig extends { _max: infer TMax extends Record<string, unknown>; } ? { _max: AggregateComparableResult<TTableConfig, TMax>; } : {})>; type GroupByResult<TTableConfig extends TableRelationalConfig, TConfig extends GroupByConfig<any, TTableConfig>> = GroupByRowResult<TTableConfig, TConfig>[]; type PredicateWhereClause<TTableConfig extends TableRelationalConfig> = { readonly __kind: 'predicate'; readonly predicate: (row: InferModelFromColumns<TableColumns<TTableConfig>>) => boolean | Promise<boolean>; }; type WhereCallback<TTableConfig extends TableRelationalConfig> = (table: TTableConfig['table'], operators: FilterOperators<TTableConfig>) => FilterExpression$1<boolean> | PredicateWhereClause<TTableConfig> | undefined; type PredicateWhereIndexMap<TTableConfig extends TableRelationalConfig> = TTableConfig['table'] extends ConvexTable<any, infer TIndexes, any, any> ? TIndexes : Record<string, GenericIndexFields>; type PredicateWhereIndexName<TTableConfig extends TableRelationalConfig> = Extract<keyof PredicateWhereIndexMap<TTableConfig>, string>; type PredicateWhereNamedIndex<TTableConfig extends TableRelationalConfig, TIndexName extends string> = TIndexName extends PredicateWhereIndexName<TTableConfig> ? PredicateWhereIndexMap<TTableConfig>[TIndexName] extends GenericIndexFields ? PredicateWhereIndexMap<TTableConfig>[TIndexName] : GenericIndexFields : GenericIndexFields; type PredicateWhereIndexConfig<TTableConfig extends TableRelationalConfig = TableRelationalConfig> = [PredicateWhereIndexName<TTableConfig>] extends [never] ? { name: string; range?: (q: IndexRangeBuilder<InferModelFromColumns<TableColumns<TTableConfig>>, GenericIndexFields>) => IndexRange; } : { [TIndexName in PredicateWhereIndexName<TTableConfig>]: { name: TIndexName; range?: (q: IndexRangeBuilder<InferModelFromColumns<TableColumns<TTableConfig>>, PredicateWhereNamedIndex<TTableConfig, TIndexName>>) => IndexRange; } }[PredicateWhereIndexName<TTableConfig>]; type SearchIndexMap<TTableConfig extends TableRelationalConfig> = TTableConfig['table'] extends ConvexTable<any, any, infer TSearchIndexes, any> ? TSearchIndexes : Record<string, { searchField: string; filterFields: string; }>; type SearchIndexName<TTableConfig extends TableRelationalConfig> = Extract<keyof SearchIndexMap<TTableConfig>, string>; type SearchIndexConfigByName<TTableConfig extends TableRelationalConfig, TIndexName extends SearchIndexName<TTableConfig>> = SearchIndexMap<TTableConfig>[TIndexName]; type SearchFilterFieldNames<TTableConfig extends TableRelationalConfig, TIndexName extends SearchIndexName<TTableConfig>> = SearchIndexConfigByName<TTableConfig, TIndexName> extends { filterFields: infer TFilterFields extends string; } ? TFilterFields : never; type SearchFilterValueForField<TTableConfig extends TableRelationalConfig, TFieldName extends string> = TFieldName extends keyof TableColumns<TTableConfig> ? TableColumns<TTableConfig>[TFieldName] extends ColumnBuilder<any, any, any> ? GetColumnData<TableColumns<TTableConfig>[TFieldName], 'raw'> : never : never; type SearchFiltersForIndex<TTableConfig extends TableRelationalConfig, TIndexName extends SearchIndexName<TTableConfig>> = Partial<{ [K in SearchFilterFieldNames<TTableConfig, TIndexName>]: SearchFilterValueForField<TTableConfig, K> }>; type SearchQueryConfig<TTableConfig extends TableRelationalConfig = TableRelationalConfig> = [SearchIndexName<TTableConfig>] extends [never] ? never : { [TIndexName in SearchIndexName<TTableConfig>]: { index: TIndexName; query: string; filters?: SearchFiltersForIndex<TTableConfig, TIndexName> | undefined; } }[SearchIndexName<TTableConfig>]; type SearchWhereFilter<TTableConfig extends TableRelationalConfig> = TableFilter<TTableConfig['table']>; type VectorIndexMap<TTableConfig extends TableRelationalConfig> = TTableConfig['table'] extends ConvexTable<any, any, any, infer TVectorIndexes> ? TVectorIndexes : Record<string, { vectorField: string; dimensions: number; filterFields: string; }>; type VectorIndexName<TTableConfig extends TableRelationalConfig> = Extract<keyof VectorIndexMap<TTableConfig>, string>; type VectorIndexConfigByName<TTableConfig extends TableRelationalConfig, TIndexName extends VectorIndexName<TTableConfig>> = VectorIndexMap<TTableConfig>[TIndexName]; type VectorFilterFieldNames<TTableConfig extends TableRelationalConfig, TIndexName extends VectorIndexName<TTableConfig>> = VectorIndexConfigByName<TTableConfig, TIndexName> extends { filterFields: infer TFilterFields extends string; } ? TFilt