Skip to content

Commit

Permalink
refactor: relationships module
Browse files Browse the repository at this point in the history
  • Loading branch information
thetutlage committed Sep 18, 2023
1 parent 532b9cb commit 7af92d9
Show file tree
Hide file tree
Showing 14 changed files with 5,409 additions and 3,852 deletions.
9 changes: 5 additions & 4 deletions adonis-typings/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,9 +149,10 @@ export type CherryPick = {
* List of events for which a model will trigger hooks
*/
export type EventsList = 'save' | 'create' | 'update' | 'delete' | 'fetch' | 'find' | 'paginate'
export type HooksHandler<Data, Event extends EventsList> =
| ((data: Data, event: Event) => Promise<void> | void)
| string
export type HooksHandler<Data, Event extends EventsList> = (
data: Data,
event: Event
) => Promise<void> | void

/**
* ------------------------------------------------------
Expand Down Expand Up @@ -854,7 +855,7 @@ export interface LucidModel {
$getRelation<Model extends LucidModel, Name extends ExtractModelRelations<InstanceType<Model>>>(
this: Model,
name: Name
): InstanceType<Model>[Name] extends ModelRelations<Model, LucidModel>
): InstanceType<Model>[Name] extends ModelRelations<LucidModel, LucidModel>
? InstanceType<Model>[Name]['client']['relation']
: RelationshipsContract
$getRelation<Model extends LucidModel>(this: Model, name: string): RelationshipsContract
Expand Down
15 changes: 11 additions & 4 deletions adonis-typings/relations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,12 @@ export interface BaseRelationContract<
readonly serializeAs: string | null
readonly booted: boolean
readonly model: ParentModel

foreignKey: string
foreignKeyColumnName: string
localKey: string
localKeyColumnName: string

relatedModel(): RelatedModel
boot(): void
clone(parent: LucidModel): this
Expand Down Expand Up @@ -462,6 +468,7 @@ export interface ManyToManyRelationContract<
readonly pivotRelatedForeignKey: string
readonly pivotTable: string
pivotColumns: string[]
relatedKeyColumnName: string

/**
* Set related models as a relationship on the parent model
Expand Down Expand Up @@ -529,6 +536,8 @@ export interface HasManyThroughRelationContract<
readonly foreignKey: string
readonly throughLocalKey: string
readonly throughForeignKey: string
throughLocalKeyColumnName: string
throughForeignKeyColumnName: string

/**
* Set related models as a relationship on the parent model
Expand Down Expand Up @@ -888,10 +897,8 @@ interface WhereNullPivot<Builder> {
interface WhereInPivot<Builder> {
(K: string, value: StrictValues[]): Builder
(K: string[], value: StrictValues[][]): Builder
(
k: string,
subquery: ChainableContract | ((builder: Builder) => void) | RawBuilderContract | RawQuery
): Builder
(k: string, callback: (builder: Builder) => void): Builder
(k: string, subquery: ChainableContract | RawBuilderContract | RawQuery): Builder
(k: string[], subquery: ChainableContract | RawBuilderContract | RawQuery): Builder
}

Expand Down
55 changes: 26 additions & 29 deletions src/database/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import { ReferenceBuilder } from './static_builder/reference.js'
import { SimplePaginator } from './paginator/simple_paginator.js'
import { DatabaseQueryBuilder } from './query_builder/database.js'
import { ModelQueryBuilder } from '../orm/query_builder/index.js'
import { LucidModel } from '../../adonis-typings/model.js'

/**
* Database class exposes the API to manage multiple connections and obtain an instance
Expand Down Expand Up @@ -77,20 +78,10 @@ export class Database extends Macroable {
this.manager = new ConnectionManager(this.logger, this.emitter)
this.primaryConnectionName = this.config.connection

this.validateConfig()
this.registerConnections()
this.findIfHealthChecksAreEnabled()
}

/**
* Validate config at runtime
*/
private validateConfig() {
// const validator = new ManagerConfigValidator(this.config, 'database', 'config/database')
// validator.validateDefault('connection')
// validator.validateList('connections', 'connection')
}

/**
* Compute whether health check is enabled or not after registering the connections.
* There are chances that all pre-registered connections are not using health
Expand Down Expand Up @@ -188,33 +179,33 @@ export class Database extends Macroable {
/**
* Returns query builder. Optionally one can define the mode as well
*/
query(options?: DatabaseClientOptions) {
return this.connection(this.primaryConnectionName, options).query()
query<Result = any>(options?: DatabaseClientOptions) {
return this.connection(this.primaryConnectionName, options).query<Result>()
}

/**
* Returns insert query builder. Always has to be dual or write mode and
* hence it doesn't matter, since in both `dual` and `write` mode,
* the `write` connection is always used.
*/
insertQuery(options?: DatabaseClientOptions) {
return this.connection(this.primaryConnectionName, options).insertQuery()
insertQuery<ReturnColumns = any>(options?: DatabaseClientOptions) {
return this.connection(this.primaryConnectionName, options).insertQuery<ReturnColumns>()
}

/**
* Returns a query builder instance for a given model.
*/
modelQuery(model: any, options?: DatabaseClientOptions) {
return this.connection(this.primaryConnectionName, options).modelQuery(model)
modelQuery<T extends LucidModel, Result = T>(model: any, options?: DatabaseClientOptions) {
return this.connection(this.primaryConnectionName, options).modelQuery<T, Result>(model)
}

/**
* Returns an instance of raw query builder. Optionally one can
* defined the `read/write` mode in which to execute the
* query
*/
rawQuery(sql: string, bindings?: any, options?: DatabaseClientOptions) {
return this.connection(this.primaryConnectionName, options).rawQuery(sql, bindings)
rawQuery<Result = any>(sql: string, bindings?: any, options?: DatabaseClientOptions) {
return this.connection(this.primaryConnectionName, options).rawQuery<Result>(sql, bindings)
}

/**
Expand All @@ -236,31 +227,37 @@ export class Database extends Macroable {
/**
* Returns instance of a query builder and selects the table
*/
from(table: any) {
from: QueryClientContract['from'] = (table) => {
return this.connection().from(table)
}

/**
* Returns insert query builder and selects the table
*/
table(table: any) {
return this.connection().table(table)
table<ReturnColumns = any>(table: any) {
return this.connection().table<ReturnColumns>(table)
}

/**
* Returns a transaction instance on the default
* connection
*/
transaction(
callback?:
| { isolationLevel?: IsolationLevels }
| ((trx: TransactionClientContract) => Promise<any>),
transaction<T>(
callback: (trx: TransactionClientContract) => Promise<T>,
options?: { isolationLevel?: IsolationLevels }
) {
): Promise<T>
transaction(options?: { isolationLevel?: IsolationLevels }): Promise<TransactionClientContract>
transaction<T>(
callbackOrOptions?:
| ((trx: TransactionClientContract) => Promise<T>)
| { isolationLevel?: IsolationLevels },
options?: { isolationLevel?: IsolationLevels }
): Promise<TransactionClientContract | T> {
const client = this.connection()
return typeof callback === 'function'
? client.transaction(callback, options)
: client.transaction(callback)

return typeof callbackOrOptions === 'function'
? client.transaction(callbackOrOptions, options)
: client.transaction(callbackOrOptions)
}

/**
Expand Down
19 changes: 0 additions & 19 deletions src/helpers/scope.ts

This file was deleted.

50 changes: 46 additions & 4 deletions src/orm/base_model/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ import {
ModelAssignOptions,
ModelAdapterOptions,
ModelRelationOptions,
ModelQueryBuilderContract,
ModelPaginatorContract,
QueryScopeCallback,
QueryScope,
} from '../../../adonis-typings/model.js'

import {
Expand Down Expand Up @@ -595,17 +599,46 @@ class BaseModelImpl implements LucidRow {
/**
* Register before hooks
*/
static before(event: EventsList, handler: HooksHandler<any, EventsList>) {
static before<Model extends LucidModel, Event extends 'find' | 'fetch'>(
this: Model,
event: Event,
handler: HooksHandler<ModelQueryBuilderContract<Model>, Event>
): void
static before<Model extends LucidModel>(
this: Model,
event: 'paginate',
handler: HooksHandler<
[ModelQueryBuilderContract<Model>, ModelQueryBuilderContract<Model>],
'paginate'
>
): void
static before<Model extends LucidModel, Event extends EventsList>(
this: Model,
event: Event,
handler: HooksHandler<InstanceType<Model>, Event>
): void {
this.$hooks.add(`before:${event}`, handler)
return this
}

/**
* Register after hooks
*/
static after(event: EventsList, handler: HooksHandler<any, EventsList>) {
static after<Model extends LucidModel>(
this: Model,
event: 'fetch',
handler: HooksHandler<InstanceType<Model>[], 'fetch'>
): void
static after<Model extends LucidModel>(
this: Model,
event: 'paginate',
handler: HooksHandler<ModelPaginatorContract<InstanceType<Model>>, 'paginate'>
): void
static after<Model extends LucidModel, Event extends EventsList>(
this: Model,
event: Event,
handler: HooksHandler<InstanceType<Model>, Event>
): void {
this.$hooks.add(`after:${event}`, handler)
return this
}

/**
Expand Down Expand Up @@ -2038,3 +2071,12 @@ class BaseModelImpl implements LucidRow {
}

export const BaseModel: LucidModel = BaseModelImpl

/**
* Helper to mark a function as query scope
*/
export function scope<Model extends LucidModel, Callback extends QueryScopeCallback<Model>>(
callback: Callback
): QueryScope<Model, Callback> {
return callback as QueryScope<Model, Callback>
}
1 change: 1 addition & 0 deletions test-helpers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,7 @@ export function getDb(eventEmitter?: Emitter<any>) {
test?.cleanup(() => {
return db.manager.closeAll()
})

return db
}

Expand Down

0 comments on commit 7af92d9

Please sign in to comment.