UNPKG

@adonisjs/lucid

Version:

SQL ORM built on top of Active Record pattern

690 lines (689 loc) 30.7 kB
import { RawQuery, OneOrMany, StrictValues, ChainableContract, RawBuilderContract } from './querybuilder.js'; import { QueryClientContract, TransactionClientContract } from './database.js'; import { LucidModel, LucidRow, ModelAssignOptions, ModelAttributes, ModelObject, ModelQueryBuilderContract, TypedDecorator } from './model.js'; /** * ------------------------------------------------------ * Helpers * ------------------------------------------------------ */ /** * Extracts relationship attributes from the model */ export type ExtractModelRelations<Model extends LucidRow> = { [Key in keyof Model]: Model[Key] extends ModelRelations<LucidModel, LucidModel> ? Key : never; }[keyof Model]; /** * Returns relationship model instance or array of instances based * upon the relationship type */ export type GetRelationModelInstance<Relation extends ModelRelations<LucidModel, LucidModel>> = Relation['__opaque_type'] extends 'hasOne' | 'belongsTo' ? Relation['instance'] : Relation['instance'][]; /** * ------------------------------------------------------ * Options * ------------------------------------------------------ */ /** * Options accepted when defining a new relationship. Certain * relationships like `manyToMany` have their own options */ export type RelationOptions<RelatedModel extends LucidModel, ParentModel extends LucidModel, Related extends ModelRelations<RelatedModel, ParentModel>> = { localKey?: string; foreignKey?: string; serializeAs?: string | null; onQuery?(query: Related['builder'] | Related['subQuery']): void; meta?: any; }; /** * Options accepted by many to many relationship */ export type ManyToManyRelationOptions<Related extends ModelRelations<LucidModel, LucidModel>> = { pivotTable?: string; localKey?: string; pivotForeignKey?: string; relatedKey?: string; pivotRelatedForeignKey?: string; pivotColumns?: string[]; pivotTimestamps?: boolean | { createdAt: string | boolean; updatedAt: string | boolean; }; serializeAs?: string | null; onQuery?(query: Related['builder'] | Related['subQuery']): void; meta?: any; }; /** * Options accepted by through relationships */ export type ThroughRelationOptions<RelatedModel extends LucidModel, ParentModel extends LucidModel, Related extends ModelRelations<RelatedModel, ParentModel>> = RelationOptions<RelatedModel, ParentModel, Related> & { throughLocalKey?: string; throughForeignKey?: string; throughModel: () => LucidModel; meta?: any; }; /** * ------------------------------------------------------ * Decorators * ------------------------------------------------------ */ /** * Decorator signature to define has one relationship */ export type HasOneDecorator = <RelatedModel extends LucidModel>(model: () => RelatedModel, options?: RelationOptions<RelatedModel, LucidModel, HasOne<RelatedModel, LucidModel>>) => TypedDecorator<HasOne<RelatedModel> | null>; /** * Decorator signature to define has many relationship */ export type HasManyDecorator = <RelatedModel extends LucidModel>(model: () => RelatedModel, options?: RelationOptions<RelatedModel, LucidModel, HasOne<RelatedModel, LucidModel>>) => TypedDecorator<HasMany<RelatedModel>>; /** * Decorator signature to define belongs to relationship */ export type BelongsToDecorator = <RelatedModel extends LucidModel>(model: () => RelatedModel, options?: RelationOptions<RelatedModel, LucidModel, HasOne<RelatedModel, LucidModel>>) => TypedDecorator<BelongsTo<RelatedModel> | null>; /** * Decorator signature to define many to many relationship */ export type ManyToManyDecorator = <RelatedModel extends LucidModel>(model: () => RelatedModel, column?: ManyToManyRelationOptions<ManyToMany<RelatedModel>>) => TypedDecorator<ManyToMany<RelatedModel>>; /** * Decorator signature to define has many through relationship */ export type HasManyThroughDecorator = <RelatedModel extends LucidModel>(model: [() => RelatedModel, () => LucidModel], column?: Omit<ThroughRelationOptions<RelatedModel, LucidModel, HasManyThrough<RelatedModel>>, 'throughModel'>) => TypedDecorator<HasManyThrough<RelatedModel>>; /** * ------------------------------------------------------ * Opaque typed relationships * ------------------------------------------------------ * * They have no runtime relevance, just a way to distinguish * between standard model properties and relationships * */ export type ModelRelationTypes = { readonly __opaque_type: 'hasOne' | 'hasMany' | 'belongsTo' | 'manyToMany' | 'hasManyThrough'; }; /** * Opaque type for has one relationship */ export type HasOne<RelatedModel extends LucidModel, ParentModel extends LucidModel = LucidModel> = InstanceType<RelatedModel> & { readonly __opaque_type: 'hasOne'; model: RelatedModel; instance: InstanceType<RelatedModel>; client: HasOneClientContract<HasOneRelationContract<ParentModel, RelatedModel>, RelatedModel>; builder: RelationQueryBuilderContract<RelatedModel, any>; subQuery: RelationSubQueryBuilderContract<RelatedModel>; }; /** * Opaque type for has many relationship */ export type HasMany<RelatedModel extends LucidModel, ParentModel extends LucidModel = LucidModel> = InstanceType<RelatedModel>[] & { readonly __opaque_type: 'hasMany'; model: RelatedModel; instance: InstanceType<RelatedModel>; client: HasManyClientContract<HasManyRelationContract<ParentModel, RelatedModel>, RelatedModel>; builder: HasManyQueryBuilderContract<RelatedModel, any>; subQuery: RelationSubQueryBuilderContract<RelatedModel>; }; /** * Opaque type for has belongs to relationship */ export type BelongsTo<RelatedModel extends LucidModel, ParentModel extends LucidModel = LucidModel> = InstanceType<RelatedModel> & { readonly __opaque_type: 'belongsTo'; model: RelatedModel; instance: InstanceType<RelatedModel>; client: BelongsToClientContract<BelongsToRelationContract<ParentModel, RelatedModel>, RelatedModel>; builder: RelationQueryBuilderContract<RelatedModel, any>; subQuery: RelationSubQueryBuilderContract<RelatedModel>; }; /** * Opaque type for many to many relationship */ export type ManyToMany<RelatedModel extends LucidModel, ParentModel extends LucidModel = LucidModel> = InstanceType<RelatedModel>[] & { readonly __opaque_type: 'manyToMany'; model: RelatedModel; instance: InstanceType<RelatedModel>; client: ManyToManyClientContract<ManyToManyRelationContract<ParentModel, RelatedModel>, RelatedModel>; builder: ManyToManyQueryBuilderContract<RelatedModel, any>; subQuery: ManyToManySubQueryBuilderContract<RelatedModel>; }; /** * Opaque type for many to many relationship */ export type HasManyThrough<RelatedModel extends LucidModel, ParentModel extends LucidModel = LucidModel> = InstanceType<RelatedModel>[] & { readonly __opaque_type: 'hasManyThrough'; model: RelatedModel; instance: InstanceType<RelatedModel>; client: HasManyThroughClientContract<HasManyThroughRelationContract<ParentModel, RelatedModel>, RelatedModel>; builder: HasManyThroughQueryBuilderContract<RelatedModel, any>; subQuery: RelationSubQueryBuilderContract<RelatedModel>; }; /** * These exists on the models directly as a relationship. The idea * is to distinguish relationship properties from other model * properties. */ export type ModelRelations<RelatedModel extends LucidModel, ParentModel extends LucidModel = LucidModel> = HasOne<RelatedModel, ParentModel> | HasMany<RelatedModel, ParentModel> | BelongsTo<RelatedModel, ParentModel> | ManyToMany<RelatedModel, ParentModel> | HasManyThrough<RelatedModel, ParentModel>; /** * ------------------------------------------------------ * Relationships * ------------------------------------------------------ */ /** * Interface to be implemented by all relationship types */ export interface BaseRelationContract<ParentModel extends LucidModel, RelatedModel extends LucidModel> { readonly type: ModelRelationTypes['__opaque_type']; readonly relationName: string; readonly serializeAs: string | null; readonly booted: boolean; readonly model: ParentModel; relatedModel(): RelatedModel; boot(): void; clone(parent: LucidModel): this; /** * Get client */ client(parent: InstanceType<ParentModel>, client: QueryClientContract): unknown; /** * Get eager query for the relationship */ eagerQuery(parent: OneOrMany<InstanceType<ParentModel>>, client: QueryClientContract): RelationQueryBuilderContract<RelatedModel, InstanceType<RelatedModel>>; subQuery(client: QueryClientContract): RelationSubQueryBuilderContract<RelatedModel>; } /** * Has one relationship interface */ export interface HasOneRelationContract<ParentModel extends LucidModel, RelatedModel extends LucidModel> extends BaseRelationContract<ParentModel, RelatedModel> { readonly type: 'hasOne'; readonly localKey: string; readonly foreignKey: string; foreignKeyColumnName: string; localKeyColumnName: string; /** * Set related model as a relationship on the parent model. */ setRelated(parent: InstanceType<ParentModel>, related: InstanceType<RelatedModel> | null): void; /** * Push related model as a relationship on the parent model */ pushRelated(parent: InstanceType<ParentModel>, related: InstanceType<RelatedModel> | null): void; /** * Set multiple related instances on the multiple parent models. * This method is generally invoked during eager load. * * Fetch 10 users and then all profiles for all 10 users and then * call this method to set related instances */ setRelatedForMany(parent: InstanceType<ParentModel>[], related: InstanceType<RelatedModel>[]): void; /** * Returns the query client for one or many model instances. The query * client then be used to fetch and persist relationships. */ client(parent: InstanceType<ParentModel>, client: QueryClientContract): HasOneClientContract<this, RelatedModel>; /** * Hydrates related model attributes for persistance */ hydrateForPersistance(parent: LucidRow, values: ModelObject | LucidRow): void; } /** * Has many relationship interface */ export interface HasManyRelationContract<ParentModel extends LucidModel, RelatedModel extends LucidModel> extends BaseRelationContract<ParentModel, RelatedModel> { readonly type: 'hasMany'; readonly localKey: string; readonly foreignKey: string; foreignKeyColumnName: string; localKeyColumnName: string; /** * Set related models as a relationship on the parent model */ setRelated(parent: InstanceType<ParentModel>, related: InstanceType<RelatedModel>[]): void; /** * Push related model(s) as a relationship on the parent model */ pushRelated(parent: InstanceType<ParentModel>, related: OneOrMany<InstanceType<RelatedModel>>): void; /** * Set multiple related instances on the multiple parent models. * This method is generally invoked during eager load. * * Fetch 10 users and then all posts for all 10 users and then * call this method to set related instances */ setRelatedForMany(parent: InstanceType<ParentModel>[], related: InstanceType<RelatedModel>[]): void; /** * Returns the query client for one or many model instances. The query * client then be used to fetch and persist relationships. */ client(parent: InstanceType<ParentModel>, client: QueryClientContract): HasManyClientContract<this, RelatedModel>; /** * Hydrates related model attributes for persistance */ hydrateForPersistance(parent: LucidRow, values: ModelObject | LucidRow): void; } /** * Belongs to relationship interface */ export interface BelongsToRelationContract<ParentModel extends LucidModel, RelatedModel extends LucidModel> extends BaseRelationContract<ParentModel, RelatedModel> { readonly type: 'belongsTo'; readonly localKey: string; readonly foreignKey: string; foreignKeyColumnName: string; localKeyColumnName: string; /** * Set related model as a relationship on the parent model */ setRelated(parent: InstanceType<ParentModel>, related: InstanceType<RelatedModel> | null): void; /** * Push related model as a relationship on the parent model */ pushRelated(parent: InstanceType<ParentModel>, related: InstanceType<RelatedModel> | null): void; /** * Set multiple related instances on the multiple parent models. * This method is generally invoked during eager load. * * Fetch 10 profiles and then users for all 10 profiles and then * call this method to set related instances */ setRelatedForMany(parent: InstanceType<ParentModel>[], related: InstanceType<RelatedModel>[]): void; /** * Returns the query client for a model instance */ client(parent: InstanceType<ParentModel>, client: QueryClientContract): BelongsToClientContract<this, RelatedModel>; /** * Hydrates parent model attributes for persistance */ hydrateForPersistance(parent: LucidRow, values: ModelObject | LucidRow): void; } /** * Many to many relationship interface */ export interface ManyToManyRelationContract<ParentModel extends LucidModel, RelatedModel extends LucidModel> extends BaseRelationContract<ParentModel, RelatedModel> { type: 'manyToMany'; readonly localKey: string; readonly relatedKey: string; readonly pivotForeignKey: string; readonly pivotRelatedForeignKey: string; readonly pivotTable: string; pivotColumns: string[]; relatedKeyColumnName: string; localKeyColumnName: string; /** * Set related models as a relationship on the parent model */ setRelated(parent: InstanceType<ParentModel>, related: InstanceType<RelatedModel>[]): void; /** * Push related model(s) as a relationship on the parent model */ pushRelated(parent: InstanceType<ParentModel>, related: OneOrMany<InstanceType<RelatedModel>>): void; /** * Set multiple related instances on the multiple parent models. * This method is generally invoked during eager load. */ setRelatedForMany(parent: InstanceType<ParentModel>[], related: InstanceType<RelatedModel>[]): void; /** * Returns the query client for one model instance */ client(parent: InstanceType<ParentModel>, client: QueryClientContract): ManyToManyClientContract<this, RelatedModel>; /** * Get eager query for the relationship */ eagerQuery(parent: OneOrMany<InstanceType<ParentModel>>, client: QueryClientContract): ManyToManyQueryBuilderContract<RelatedModel, InstanceType<RelatedModel>>; /** * Get subquery for the relationships */ subQuery(client: QueryClientContract): ManyToManySubQueryBuilderContract<RelatedModel>; /** * Returns key-value pair for the pivot table in relation to the parent model */ getPivotPair(parent: LucidRow): [string, number | string]; /** * Returns key-value pair for the pivot table in relation to the related model */ getPivotRelatedPair(related: LucidRow): [string, number | string]; } /** * Has many through relationship interface */ export interface HasManyThroughRelationContract<ParentModel extends LucidModel, RelatedModel extends LucidModel> extends BaseRelationContract<ParentModel, RelatedModel> { type: 'hasManyThrough'; readonly localKey: string; readonly foreignKey: string; readonly throughLocalKey: string; readonly throughForeignKey: string; throughLocalKeyColumnName: string; throughForeignKeyColumnName: string; foreignKeyColumnName: string; localKeyColumnName: string; /** * Set related models as a relationship on the parent model */ setRelated(parent: InstanceType<ParentModel>, related: InstanceType<RelatedModel>[]): void; /** * Push related model(s) as a relationship on the parent model */ pushRelated(parent: InstanceType<ParentModel>, related: InstanceType<RelatedModel> | InstanceType<RelatedModel>[]): void; /** * Set multiple related instances on the multiple parent models. * This method is generally invoked during eager load. */ setRelatedForMany(parent: InstanceType<ParentModel>[], related: InstanceType<RelatedModel>[]): void; /** * Returns the query client for a model instance */ client(model: InstanceType<ParentModel>, client: QueryClientContract): RelationQueryClientContract<this, RelatedModel>; } /** * A union of relationships */ export type RelationshipsContract = HasOneRelationContract<LucidModel, LucidModel> | HasManyRelationContract<LucidModel, LucidModel> | BelongsToRelationContract<LucidModel, LucidModel> | ManyToManyRelationContract<LucidModel, LucidModel> | HasManyThroughRelationContract<LucidModel, LucidModel>; /** * ------------------------------------------------------ * Relationships query client * ------------------------------------------------------ */ export interface RelationQueryClientContract<Relation extends RelationshipsContract, RelatedModel extends LucidModel> { relation: Relation; /** * Return a query builder instance of the relationship */ query<Result = InstanceType<RelatedModel>>(): RelationQueryBuilderContract<RelatedModel, Result>; } /** * Query client for has one relationship */ export interface HasOneClientContract<Relation extends RelationshipsContract, RelatedModel extends LucidModel> extends RelationQueryClientContract<Relation, RelatedModel> { /** * Save related instance. Sets up the FK automatically */ save(related: InstanceType<RelatedModel>): Promise<void>; /** * Create related instance. Sets up the FK automatically */ create(values: Partial<ModelAttributes<InstanceType<RelatedModel>>>, options?: ModelAssignOptions): Promise<InstanceType<RelatedModel>>; /** * Return first or create related instance */ firstOrCreate(search: Partial<ModelAttributes<InstanceType<RelatedModel>>>, savePayload?: Partial<ModelAttributes<InstanceType<RelatedModel>>>, options?: ModelAssignOptions): Promise<InstanceType<RelatedModel>>; /** * Update or create related instance */ updateOrCreate(search: Partial<ModelAttributes<InstanceType<RelatedModel>>>, updatePayload: Partial<ModelAttributes<InstanceType<RelatedModel>>>, options?: ModelAssignOptions): Promise<InstanceType<RelatedModel>>; } /** * Query client for has many relationship. Extends hasOne and * adds support for saving many relations */ export interface HasManyClientContract<Relation extends RelationshipsContract, RelatedModel extends LucidModel> extends HasOneClientContract<Relation, RelatedModel> { /** * Save many of related instances. Sets up FK automatically */ saveMany(related: InstanceType<RelatedModel>[]): Promise<void>; /** * Create many of related instances. Sets up FK automatically */ createMany(values: Partial<ModelAttributes<InstanceType<RelatedModel>>>[], options?: ModelAssignOptions): Promise<InstanceType<RelatedModel>[]>; /** * Fetch or create rows. Providers a great API to sync rows */ fetchOrCreateMany(payload: Partial<ModelAttributes<InstanceType<RelatedModel>>>[], predicate?: keyof ModelAttributes<InstanceType<RelatedModel>> | (keyof ModelAttributes<InstanceType<RelatedModel>>)[], options?: ModelAssignOptions): Promise<InstanceType<RelatedModel>[]>; /** * Update or create rows. Providers a great API to sync rows */ updateOrCreateMany(payload: Partial<ModelAttributes<InstanceType<RelatedModel>>>[], predicate?: keyof ModelAttributes<InstanceType<RelatedModel>> | (keyof ModelAttributes<InstanceType<RelatedModel>>)[], options?: ModelAssignOptions): Promise<InstanceType<RelatedModel>[]>; /** * Return a query builder instance of the relationship */ query<Result = InstanceType<RelatedModel>>(): HasManyQueryBuilderContract<RelatedModel, Result>; } /** * Query client for belongs to relationship. Uses `associate` and * `dissociate` over save. */ export interface BelongsToClientContract<Relation extends RelationshipsContract, RelatedModel extends LucidModel> extends RelationQueryClientContract<Relation, RelatedModel> { /** * Associate related instance */ associate(related: InstanceType<RelatedModel>): Promise<void>; /** * Dissociate related instance */ dissociate(): Promise<void>; } /** * Query client for many to many relationship. */ export interface ManyToManyClientContract<Relation extends RelationshipsContract, RelatedModel extends LucidModel> extends RelationQueryClientContract<Relation, RelatedModel> { /** * Returns related model query builder instance */ query<Result = InstanceType<RelatedModel>>(): ManyToManyQueryBuilderContract<RelatedModel, Result>; /** * Pivot query just targets the pivot table without any joins */ pivotQuery<Result = any>(): ManyToManyQueryBuilderContract<RelatedModel, Result>; /** * Save related model instance. Sets up FK automatically */ save(related: InstanceType<RelatedModel>, performSync?: boolean, // defaults to true pivotAttributes?: ModelObject): Promise<void>; /** * Save many of related model instance. Sets up FK automatically */ saveMany(related: InstanceType<RelatedModel>[], performSync?: boolean, // defaults to true pivotAttributes?: (ModelObject | undefined)[]): Promise<void>; /** * Create related model instance. Sets up FK automatically */ create(values: Partial<ModelAttributes<InstanceType<RelatedModel>>>, pivotAttributes?: ModelObject, options?: ModelAssignOptions): Promise<InstanceType<RelatedModel>>; /** * Create many of related model instances. Sets up FK automatically */ createMany(values: Partial<ModelAttributes<InstanceType<RelatedModel>>>[], pivotAttributes?: (ModelObject | undefined)[], options?: ModelAssignOptions): Promise<InstanceType<RelatedModel>[]>; /** * Attach new pivot rows */ attach(ids: (string | number)[] | Record<string, ModelObject>, trx?: TransactionClientContract): Promise<void>; /** * Detach existing pivot rows */ detach(ids?: (string | number)[], trx?: TransactionClientContract): Promise<void>; /** * Sync pivot rows. */ sync(ids: (string | number)[] | Record<string, ModelObject>, detach?: boolean, trx?: TransactionClientContract): Promise<void>; } /** * HasMany through client contract. HasMany through doesn't * allow persisting relationships. Use the direct relation * for that. */ export interface HasManyThroughClientContract<Relation extends RelationshipsContract, RelatedModel extends LucidModel> extends RelationQueryClientContract<Relation, RelatedModel> { /** * Return a query builder instance of the relationship */ query<Result = InstanceType<RelatedModel>>(): HasManyThroughQueryBuilderContract<RelatedModel, Result>; } /** * ------------------------------------------------------ * Relationships query builders * ------------------------------------------------------ */ /** * Interface with query builder options for the many to many pivot * table */ export interface PivotQueryBuilderContract { pivotColumns(columns: string[]): this; wherePivot: WherePivot<this>; orWherePivot: WherePivot<this>; andWherePivot: WherePivot<this>; whereNotPivot: WherePivot<this>; orWhereNotPivot: WherePivot<this>; andWhereNotPivot: WherePivot<this>; whereInPivot: WhereInPivot<this>; orWhereInPivot: WhereInPivot<this>; andWhereInPivot: WhereInPivot<this>; whereNotInPivot: WhereInPivot<this>; orWhereNotInPivot: WhereInPivot<this>; andWhereNotInPivot: WhereInPivot<this>; whereNullPivot: WhereNullPivot<this>; orWhereNullPivot: WhereNullPivot<this>; andWhereNullPivot: WhereNullPivot<this>; whereNotNullPivot: WhereNullPivot<this>; orWhereNotNullPivot: WhereNullPivot<this>; andWhereNotNullPivot: WhereNullPivot<this>; } /** * Base query builder for all relations */ export interface RelationQueryBuilderContract<Related extends LucidModel, Result> extends ModelQueryBuilderContract<Related, Result> { /** * Is query a relationship query obtained using `related('relation').query()` */ isRelatedQuery: true; /** * Is query a relationship query obtained using `related('relation').subQuery()` */ isRelatedSubQuery: false; /** * Is query a relationship query obtained using one of the preload methods. */ isRelatedPreloadQuery: boolean; selectRelationKeys(): this; } /** * Has many query builder contract */ export interface HasManyQueryBuilderContract<Related extends LucidModel, Result> extends RelationQueryBuilderContract<Related, Result> { groupLimit(limit: number): this; groupOrderBy(column: string, direction?: 'asc' | 'desc'): this; } /** * Has many query through builder contract */ export interface HasManyThroughQueryBuilderContract<Related extends LucidModel, Result> extends RelationQueryBuilderContract<Related, Result> { groupLimit(limit: number): this; groupOrderBy(column: string, direction?: 'asc' | 'desc'): this; } /** * Possible signatures for adding a where clause */ interface WherePivot<Builder> { (key: string, value: StrictValues | ChainableContract): Builder; (key: string, operator: string, value: StrictValues | ChainableContract): Builder; } /** * Possible signatures for adding whereNull clause. */ interface WhereNullPivot<Builder> { (key: string): Builder; } /** * Possible signatures for adding where in clause. */ interface WhereInPivot<Builder> { (K: string, value: StrictValues[]): Builder; (K: string[], value: StrictValues[][]): Builder; (k: string, callback: (builder: Builder) => void): Builder; (k: string, subquery: ChainableContract | RawBuilderContract | RawQuery): Builder; (k: string[], subquery: ChainableContract | RawBuilderContract | RawQuery): Builder; } /** * Shape of many to many query builder. It has few methods over the standard * model query builder */ export interface ManyToManyQueryBuilderContract<Related extends LucidModel, Result> extends RelationQueryBuilderContract<Related, Result>, PivotQueryBuilderContract { isPivotOnlyQuery: boolean; groupLimit(limit: number): this; groupOrderBy(column: string, direction?: 'asc' | 'desc'): this; } /** * ------------------------------------------------------ * Sub Queries * ------------------------------------------------------ */ /** * Not in use right now. Since after omitting these types from the * model query builder losses "this" scope. Need to re-think */ export type UnSupportedSubQueryMethods = 'preload' | 'decrement' | 'increment' | 'update' | 'paginate' | 'delete' | 'del' | 'firstOrFail' | 'first' | 'exec' | 'withCount'; /** * SubQuery builder allows creating sub queries targeting a relationship. Sub queries * cannot be executed directly, but can be used as a reference in the parent query * builder. Use cases are: * * - withCount * - whereHas */ export interface RelationSubQueryBuilderContract<Related extends LucidModel> extends ModelQueryBuilderContract<Related, any> { /** * Is query a relationship query obtained using `related('relation').query()` */ isRelatedQuery: false; /** * Is query a relationship query obtained using `related('relation').subQuery()` */ isRelatedSubQuery: true; /** * Is query a relationship query obtained using one of the preload methods. */ isRelatedPreloadQuery: false; selfJoinCounter: number; readonly selfJoinAlias: string; selectRelationKeys(): this; prepare(): this; } /** * SubQuery builder for many to many relationship */ export interface ManyToManySubQueryBuilderContract<Related extends LucidModel> extends RelationSubQueryBuilderContract<Related>, PivotQueryBuilderContract { } /** * The withCount function */ export interface WithCount<Model extends LucidRow, Builder> { <Name extends ExtractModelRelations<Model>, RelatedBuilder = Model[Name] extends ModelRelations<LucidModel, LucidModel> ? Model[Name]['subQuery'] : never>(relation: Name, callback?: (builder: RelatedBuilder) => void): Builder; } /** * The with aggregate function */ export interface WithAggregate<Model extends LucidRow, Builder> { <Name extends ExtractModelRelations<Model>, RelatedBuilder = Model[Name] extends ModelRelations<LucidModel, LucidModel> ? Model[Name]['subQuery'] : never>(relation: Name, callback: (builder: RelatedBuilder) => void): Builder; } /** * The has function */ export interface Has<Model extends LucidRow, Builder> { <Name extends ExtractModelRelations<Model>>(relation: Name, operator?: string, value?: StrictValues | ChainableContract): Builder; } /** * The whereHas function */ export interface WhereHas<Model extends LucidRow, Builder> { <Name extends ExtractModelRelations<Model>, RelatedBuilder = Model[Name] extends ModelRelations<LucidModel, LucidModel> ? Model[Name]['subQuery'] : never>(relation: Name, callback: (builder: RelatedBuilder) => void, operator?: string, value?: StrictValues | ChainableContract): Builder; } /** * ------------------------------------------------------ * Preloader * ------------------------------------------------------ */ /** * The preload function */ export interface Preload<Model extends LucidRow, Builder> { <Name extends ExtractModelRelations<Model>, RelatedBuilder = Model[Name] extends ModelRelations<LucidModel, LucidModel> ? Model[Name]['builder'] : never>(relation: Name, callback?: (builder: RelatedBuilder) => void): Builder; } export interface PreloadWithoutCallback<Model extends LucidRow, Builder> { <Name extends ExtractModelRelations<Model>>(relation: Name): Builder; } export interface PreloadOnce<Model extends LucidRow, Builder> extends PreloadWithoutCallback<Model, Builder> { } /** * Shape of the preloader to preload relationships */ export interface PreloaderContract<Model extends LucidRow> { processAllForOne(parent: Model, client: QueryClientContract): Promise<void>; processAllForMany(parent: Model[], client: QueryClientContract): Promise<void>; load: Preload<Model, this>; preload: Preload<Model, this>; preloadOnce: PreloadOnce<Model, this>; debug(debug: boolean): this; sideload(values: ModelObject): this; clone(): PreloaderContract<Model>; } export {};