import type { Generated, Kysely } from 'kysely'; import type { CheckCallback, DeferMode, Dictionary, EntityName, EntityProperty, EntitySchemaWithMeta, FilterQuery, GroupOperator, IndexColumnOptions, InferEntityName, Opt, Primary, PrimaryProperty, QueryFlag, QueryOrderMap, RawQueryFragment, Scalar, Type, } from '@mikro-orm/core'; import type { JoinType, QueryType } from './query/enums.js'; import type { DatabaseSchema } from './schema/DatabaseSchema.js'; import type { DatabaseTable } from './schema/DatabaseTable.js'; import type { AnyQueryBuilder } from './query/QueryBuilder.js'; import type { CteOptions, NativeQueryBuilder } from './query/NativeQueryBuilder.js'; import type { MikroKyselyPluginOptions } from './plugin/index.js'; export interface Table { table_name: string; schema_name?: string; table_comment?: string; } /** @internal */ export type InternalField = string | RawQueryFragment | AnyQueryBuilder | NativeQueryBuilder; export interface JoinOptions { table: string; schema?: string; type: JoinType; alias: string; ownerAlias: string; inverseAlias?: string; joinColumns?: string[]; inverseJoinColumns?: string[]; primaryKeys?: string[]; path?: string; prop: EntityProperty; cond: Dictionary; cond_?: Dictionary; subquery?: string; nested?: Set; parent?: JoinOptions; } export interface Column { name: string; type: string; mappedType: Type; unsigned?: boolean; autoincrement?: boolean; nullable?: boolean; length?: number; precision?: number; scale?: number; default?: string | null; defaultConstraint?: string; comment?: string; generated?: string; nativeEnumName?: string; enumItems?: string[]; primary?: boolean; unique?: boolean; /** mysql only */ extra?: string; ignoreSchemaChanges?: ('type' | 'extra' | 'default')[]; } export interface ForeignKey { columnNames: string[]; constraintName: string; localTableName: string; referencedTableName: string; referencedColumnNames: string[]; updateRule?: string; deleteRule?: string; deferMode?: DeferMode; } export interface IndexDef { columnNames: string[]; keyName: string; unique: boolean; constraint: boolean; primary: boolean; composite?: boolean; expression?: string; options?: Dictionary; type?: | string | Readonly<{ indexType?: string; storageEngineIndexType?: 'hash' | 'btree'; predicate?: string; }>; deferMode?: DeferMode | `${DeferMode}`; /** * Advanced column options for the index. * When specified, these options override the simple columnNames for index generation. */ columns?: IndexColumnOptions[]; /** * Columns to include in the index but not as part of the key (PostgreSQL, MSSQL). */ include?: string[]; /** Fill factor for the index as a percentage 0-100 (PostgreSQL, MSSQL). */ fillFactor?: number; /** * Whether the index is invisible/hidden from the query optimizer (MySQL 8+, MariaDB 10.6+, MongoDB). */ invisible?: boolean; /** * Whether the index is disabled (MSSQL only). */ disabled?: boolean; /** * Whether the index should be clustered (MariaDB, MSSQL). */ clustered?: boolean; } export interface CheckDef { name: string; expression: string | CheckCallback; definition?: string; columnName?: string; } export interface ColumnDifference { oldColumnName: string; column: Column; fromColumn: Column; changedProperties: Set; } export interface TableDifference { name: string; changedComment?: string; fromTable: DatabaseTable; toTable: DatabaseTable; addedColumns: Dictionary; changedColumns: Dictionary; removedColumns: Dictionary; renamedColumns: Dictionary; addedIndexes: Dictionary; changedIndexes: Dictionary; removedIndexes: Dictionary; renamedIndexes: Dictionary; addedChecks: Dictionary; changedChecks: Dictionary; removedChecks: Dictionary; addedForeignKeys: Dictionary; changedForeignKeys: Dictionary; removedForeignKeys: Dictionary; } export interface DatabaseView { name: string; schema?: string; definition: string; /** True if this is a materialized view (PostgreSQL only). */ materialized?: boolean; /** For materialized views, whether data was populated on creation. */ withData?: boolean; } export interface SchemaDifference { newNamespaces: Set; newNativeEnums: { name: string; schema?: string; items: string[]; }[]; newTables: Dictionary; changedTables: Dictionary; removedTables: Dictionary; newViews: Dictionary; changedViews: Dictionary<{ from: DatabaseView; to: DatabaseView; }>; removedViews: Dictionary; removedNamespaces: Set; removedNativeEnums: { name: string; schema?: string; }[]; orphanedForeignKeys: ForeignKey[]; fromSchema: DatabaseSchema; } export interface IQueryBuilder { readonly alias: string; readonly type: QueryType; /** @internal */ state: { fields?: InternalField[]; [key: string]: any; }; /** @internal */ helper: any; select(fields: string | RawQueryFragment | (string | RawQueryFragment)[], distinct?: boolean): this; addSelect(fields: string | string[]): this; from(target: EntityName | IQueryBuilder, aliasName?: string): IQueryBuilder; insert(data: any): this; update(data: any): this; delete(cond?: FilterQuery): this; truncate(): this; count(field?: string | string[], distinct?: boolean): this; join(field: string, alias: string, cond?: FilterQuery, type?: JoinType, path?: string): this; innerJoin(field: string, alias: string, cond?: FilterQuery): this; leftJoin(field: string, alias: string, cond?: FilterQuery): this; joinAndSelect(field: any, alias: string, cond?: FilterQuery): this; leftJoinAndSelect(field: any, alias: string, cond?: FilterQuery, fields?: string[]): this; innerJoinAndSelect(field: any, alias: string, cond?: FilterQuery, fields?: string[]): this; withSubQuery(subQuery: RawQueryFragment | NativeQueryBuilder, alias: string): this; where( cond: FilterQuery | string | RawQueryFragment | Dictionary, operator?: keyof typeof GroupOperator | any[], operator2?: keyof typeof GroupOperator, ): this; andWhere(cond: FilterQuery | string | RawQueryFragment | Dictionary, params?: any[]): this; orWhere(cond: FilterQuery | string | RawQueryFragment | Dictionary, params?: any[]): this; orderBy(orderBy: QueryOrderMap): this; groupBy(fields: (string | keyof T) | (string | keyof T)[]): this; having(cond?: FilterQuery | string, params?: any[]): this; getAliasForJoinPath(path: string, options?: ICriteriaNodeProcessOptions): string | undefined; getJoinForPath(path?: string, options?: ICriteriaNodeProcessOptions): JoinOptions | undefined; getNextAlias(entityName?: string | EntityName): string; clone(reset?: boolean | string[], preserve?: string[]): IQueryBuilder; setFlag(flag: QueryFlag): this; unsetFlag(flag: QueryFlag): this; hasFlag(flag: QueryFlag): boolean; with(name: string, query: AnyQueryBuilder | NativeQueryBuilder | RawQueryFragment, options?: CteOptions): this; withRecursive( name: string, query: AnyQueryBuilder | NativeQueryBuilder | RawQueryFragment, options?: CteOptions, ): this; scheduleFilterCheck(path: string): void; withSchema(schema: string): this; } export interface ICriteriaNodeProcessOptions { alias?: string; matchPopulateJoins?: boolean; ignoreBranching?: boolean; preferNoBranch?: boolean; type?: 'orderBy' | 'having'; filter?: boolean; parentPath?: string; } export interface ICriteriaNode { readonly entityName: EntityName; readonly parent?: ICriteriaNode | undefined; readonly key?: string | symbol | undefined; readonly strict?: boolean; payload: any; prop?: EntityProperty; index?: number; process(qb: IQueryBuilder, options?: ICriteriaNodeProcessOptions): any; shouldInline(payload: any): boolean; willAutoJoin(qb: IQueryBuilder, alias?: string, options?: ICriteriaNodeProcessOptions): boolean; shouldRename(payload: any): boolean; renameFieldToPK(qb: IQueryBuilder, ownerAlias?: string): string; getPath(opts?: { addIndex?: boolean }): string; getPivotPath(path: string): string; } export type MaybeReturnType = T extends (...args: any[]) => infer R ? R : T; export type InferEntityProperties = Schema extends EntitySchemaWithMeta ? Properties : never; export type InferKyselyDB< TEntities extends { name: string; }, TOptions extends MikroKyselyPluginOptions = {}, > = MapValueAsTable, TOptions>; export type InferDBFromKysely> = TKysely extends Kysely ? TDB : never; type PreferStringLiteral = [TCandidate] extends [never] ? TFallback : string extends TCandidate ? TFallback : TCandidate extends string ? TCandidate : TFallback; export type MapTableName< T extends { name: string; tableName?: string; }, TOptions extends MikroKyselyPluginOptions = {}, > = { [P in T as TOptions['tableNamingStrategy'] extends 'entity' ? P['name'] : PreferStringLiteral, P['name']>]: P; }; export type MapValueAsTable, TOptions extends MikroKyselyPluginOptions = {}> = { [K in keyof TMap as TransformName< K, TOptions['tableNamingStrategy'] extends 'entity' ? 'entity' : 'underscore' >]: InferKyselyTable; }; export type InferKyselyTable< TSchema extends EntitySchemaWithMeta, TOptions extends MikroKyselyPluginOptions = {}, > = ExcludeNever<{ -readonly [K in keyof InferEntityProperties as TransformColumnName< K, TOptions['columnNamingStrategy'] extends 'property' ? 'property' : 'underscore', MaybeReturnType[K]> >]: InferColumnValue< MaybeReturnType[K]>, TOptions['processOnCreateHooks'] extends true ? true : false >; }>; type TransformName = TNamingStrategy extends 'underscore' ? TName extends string ? SnakeCase : TName : TName; type TransformColumnName< TName, TNamingStrategy extends 'underscore' | 'property', TBuilder, > = TNamingStrategy extends 'property' ? TName : TBuilder extends { '~options': { fieldName: string; }; } ? TBuilder['~options']['fieldName'] : TName extends string ? MaybeJoinColumnName, TBuilder> : never; type MaybeJoinColumnName = TBuilder extends { '~type'?: { value: infer Value; }; '~options': { kind: 'm:1'; }; } ? PrimaryProperty extends string ? `${TName}_${SnakeCase>}` : never : TBuilder extends { '~type'?: { value: infer Value; }; '~options': { kind: '1:1'; owner: true; }; } ? PrimaryProperty extends string ? `${TName}_${SnakeCase>}` : never : TName; export type SnakeCase = TName extends `${infer A}${infer B}${infer Rest}` ? IsUpperLetter extends never ? `${Lowercase}${SnakeCase<`${B}${Rest}`>}` : IsLowerLetter extends never ? `${Lowercase}${SnakeCase<`${B}${Rest}`>}` : `${Lowercase}_${SnakeCase<`${B}${Rest}`>}` : Lowercase; type IsLowerLetter = C extends Lowercase ? (C extends Uppercase ? never : C) : never; type IsUpperLetter = C extends Uppercase ? (C extends Lowercase ? never : C) : never; type InferColumnValue = TBuilder extends { '~type'?: { value: infer Value; }; '~options': infer TOptions; } ? MaybeNever, TOptions, TProcessOnCreate>, TOptions> : never; type MaybeGenerated = TOptions extends { nullable: true; } ? TValue | null : TOptions extends { autoincrement: true; } ? Generated : TOptions extends { default: true; } ? Generated : TOptions extends { defaultRaw: true; } ? Generated : TProcessOnCreate extends false ? TValue : TOptions extends { onCreate: Function; } ? Generated : TValue; type MaybeJoinKey = TOptions extends { kind: 'm:1'; } ? UnwrapOpt> : TOptions extends { kind: '1:1'; } ? TOptions extends { owner: true; } ? UnwrapOpt> : never : TValue; type UnwrapOpt = TValue extends Opt ? OriginalValue : TValue; type MaybeNever = TOptions extends | { persist: false; } | { kind: 'm:n' | '1:m'; } ? never : TValue; type ExcludeNever> = { [K in keyof TMap as TMap[K] extends never ? never : K]: TMap[K]; }; export type InferClassEntityDB = ClassEntityDBMap extends infer R ? ([keyof R] extends [never] ? unknown : R) : never; type ClassEntityDBMap = { [T in TEntities as ClassEntityTableName]: ClassEntityColumns; }; type ClassEntityTableName = T extends abstract new ( ...args: any[] ) => infer Instance ? TransformName, TOptions['tableNamingStrategy'] extends 'entity' ? 'entity' : 'underscore'> : never; type ClassEntityColumns = T extends abstract new (...args: any[]) => infer Instance ? { [K in keyof Instance as IsClassEntityColumn]: Instance[K]; } : never; type IsClassEntityColumn = K extends symbol ? never : NonNullable extends Scalar ? K : never; export {};