UNPKG

@adonisjs/lucid

Version:

SQL ORM built on top of Active Record pattern

848 lines (847 loc) 32.4 kB
import { DateTime } from 'luxon'; import type Hooks from '@poppinss/hooks'; import { TransactionFn, DialectContract, QueryClientContract, TransactionClientContract } from './database.js'; import { Update, Counter, OneOrMany, Aggregate, Returning, ChainableContract, SimplePaginatorMetaKeys, SimplePaginatorContract, ExcutableQueryBuilderContract } from './querybuilder.js'; import { ExtractModelRelations, Has, ManyToManyRelationOptions, ModelRelationTypes, ModelRelations, Preload, PreloaderContract, RelationOptions, RelationshipsContract, ThroughRelationOptions, WhereHas, WithAggregate, WithCount, PreloadWithoutCallback, PreloadOnce } from './relations.js'; /** * ------------------------------------------------------ * Helpers * ------------------------------------------------------ */ /** * Same as [[Parameters]] but omits the first parameter */ type OmitFirst<T extends (...args: any) => any> = T extends (x: any, ...args: infer P) => any ? P : never; /** * Same as [[Pick]] but picks by value and not the key */ type PickProperties<T, P> = Pick<T, { [K in keyof T]: T[K] extends P ? K : never; }[keyof T]>; /** * Decorator function */ export type DecoratorFn = (target: any, property: any) => void; /** * Typed decorator */ export type TypedDecorator<PropType> = <TKey extends string, TTarget extends { [K in TKey]: PropType; }>(target: TTarget, property: TKey) => void; /** * Typed decorator that also represents an optional property */ export type OptionalTypedDecorator<PropType> = <TKey extends string, TTarget extends { [K in TKey]?: PropType; }>(target: TTarget, property: TKey) => void; /** * A complex type that filters out functions and relationships from the * model attributes and consider all other properties as database * columns. Alternatively, the user can self define a `$columns` * property. */ export type ModelAttributes<Model extends LucidRow> = Model['$columns'] extends undefined ? { [Filtered in { [P in keyof Model]: P extends keyof LucidRow | 'serializeExtras' ? never : Model[P] extends Function | ModelRelationTypes ? never : P; }[keyof Model]]: Model[Filtered]; } : Model['$columns']; /** * Extract the query scopes of a model */ export type ExtractScopes<Model extends LucidModel> = { [Scope in keyof PickProperties<Model, QueryScope<Model, QueryScopeCallback<Model>>>]: (...args: Model[Scope] extends QueryScopeCallback<Model> ? OmitFirst<Model[Scope]> : never) => ExtractScopes<Model>; }; /** * Reusable interface to define an object. */ export interface ModelObject { [key: string]: any; } /** * Shape of cache node to keep getters optimized */ export type CacheNode = { original: any; resolved: any; getter: (value: any) => any; }; /** * Shape for cherry picking fields */ export type CherryPickFields = string[] | { pick?: string[]; omit?: string[]; }; /** * Shape for cherry picking fields on nested relationships */ export type CherryPick = { fields?: CherryPickFields; relations?: { [relation: string]: 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; /** * ------------------------------------------------------ * Query Scope * ------------------------------------------------------ */ /** * Generic query scope callback */ export type QueryScopeCallback<Model extends LucidModel = LucidModel> = (query: ModelQueryBuilderContract<Model>, ...args: any[]) => void; /** * Query scope */ export type QueryScope<Model extends LucidModel, Scope extends QueryScopeCallback<Model>> = Scope & { readonly isQueryScope: true; }; /** * A function to mark a method as query scope */ export type ScopeFn = <Model extends LucidModel, Scope extends QueryScopeCallback<Model> = QueryScopeCallback<Model>>(callback: Scope) => QueryScope<Model, Scope>; /** * ------------------------------------------------------ * Decorators and Options * ------------------------------------------------------ */ /** * Options for defining a column */ export type ColumnOptions = { columnName: string; serializeAs: string | null; isPrimary: boolean; meta?: any; /** * Invoked before serializing process happens */ serialize?: (value: any, attribute: string, model: LucidRow) => any; /** * Invoked before create or update happens */ prepare?: (value: any, attribute: string, model: LucidRow) => any; /** * Invoked when row is fetched from the database */ consume?: (value: any, attribute: string, model: LucidRow) => any; }; /** * Shape of column options after they have set on the model */ export type ModelColumnOptions = ColumnOptions & { hasGetter: boolean; hasSetter: boolean; }; /** * Represents a computed property on the model */ export type ComputedOptions = { serializeAs: string | null; meta?: any; }; /** * Options accepted by the Model.$addRelation method */ export type ModelRelationOptions = RelationOptions<LucidModel, LucidModel, ModelRelations<LucidModel, LucidModel>> | ManyToManyRelationOptions<ModelRelations<LucidModel, LucidModel>> | ThroughRelationOptions<LucidModel, LucidModel, ModelRelations<LucidModel, LucidModel>>; /** * Signature for column decorator function */ export type ColumnDecorator = (options?: Partial<ColumnOptions>) => DecoratorFn; /** * Signature for computed decorator function */ export type ComputedDecorator = (options?: Partial<ComputedOptions>) => DecoratorFn; /** * Decorator for defining date columns */ export type DateColumnDecorator = (options?: Partial<ColumnOptions & { autoCreate: boolean; autoUpdate: boolean; }>) => OptionalTypedDecorator<DateTime | null>; /** * Decorator for defining date time columns. It is same as * date column as of now */ export type DateTimeColumnDecorator = DateColumnDecorator; /** * Decorator for defining hooks. The generics enforces that * decorator is used on static properties only */ export type HooksDecorator = () => <Model extends LucidModel>(target: Model, property: string) => void; /** * ------------------------------------------------------ * Model Options * ------------------------------------------------------ */ /** * Model options to be used when making queries */ export type ModelOptions = { connection?: string; }; /** * Adapter also accepts a client directly */ export type ModelAdapterOptions = ModelOptions & { client?: QueryClientContract; }; /** * Options used by the method that internally invokes * the merge method. ] */ export type ModelAssignOptions = ModelAdapterOptions & { allowExtraProperties?: boolean; }; /** * Preload function on a model instance */ export interface LucidRowPreload<Model extends LucidRow> extends Preload<Model, Promise<void>> { (callback: (preloader: PreloaderContract<Model>) => void): Promise<void>; } export interface LucidRowPreloadOnce<Model extends LucidRow> extends PreloadWithoutCallback<Model, Promise<void>> { } export interface LucidRowAggregate<Model extends LucidRow> extends Preload<Model, Promise<void>> { (callback: (preloader: PreloaderContract<Model>) => void): Promise<void>; } /** * An extension of the simple paginator with support for serializing models */ export interface ModelPaginatorContract<Result extends LucidRow> extends Omit<SimplePaginatorContract<Result>, 'toJSON'> { serialize(cherryPick?: CherryPick): { meta: any; data: ModelObject[]; }; toJSON(): { meta: any; data: ModelObject[]; }; } /** * Lazy load aggregates for a given model instance */ export interface LazyLoadAggregatesContract<Model extends LucidRow> extends Promise<void> { loadAggregate: WithAggregate<Model, this>; loadCount: WithCount<Model, this>; exec(): Promise<void>; } /** * ------------------------------------------------------ * Model Query Builder * ------------------------------------------------------ */ /** * Model query builder will have extras methods on top of the Database query builder */ export interface ModelQueryBuilderContract<Model extends LucidModel, Result = InstanceType<Model>> extends ChainableContract, ExcutableQueryBuilderContract<Result[]> { model: Model; returning: Returning<this>; /** * Define a callback to transform a row */ rowTransformer(callback: (row: LucidRow) => void): this; /** * Define a custom preloader for the current query */ usePreloader(preloader: PreloaderContract<LucidRow>): this; /** * Whether or not the query is a child query generated for `.where` * callbacks */ isChildQuery: boolean; /** * Alias for the @withScopes method */ apply<Scopes extends ExtractScopes<Model>>(callback: (scopes: Scopes) => void): this; /** * Apply model query scopes on the query bulder */ withScopes<Scopes extends ExtractScopes<Model>>(callback: (scopes: Scopes) => void): this; /** * A copy of client options. */ readonly clientOptions: ModelAdapterOptions; /** * Reference to query client used for making queries */ client: QueryClientContract; /** * Clone query builder instance */ clone<ClonedResult = Result>(): ModelQueryBuilderContract<Model, ClonedResult>; /** * A custom set of sideloaded properties defined on the query * builder, this will be passed to the model instance created * by the query builder */ sideload(value: ModelObject): this; /** * Execute and get first result */ first(): Promise<Result | null>; /** * Return the first matching row or fail */ firstOrFail(): Promise<Result>; /** * Perform delete operation */ del(returning?: OneOrMany<string>): ModelQueryBuilderContract<Model, any>; delete(returning?: OneOrMany<string>): ModelQueryBuilderContract<Model, any>; /** * A shorthand to define limit and offset based upon the * current page */ forPage(page: number, perPage?: number): this; /** * Execute query with pagination */ paginate(page: number, perPage?: number): Promise<Result extends LucidRow ? ModelPaginatorContract<Result> : SimplePaginatorContract<Result>>; /** * Mutations (update and increment can be one query aswell) */ update: Update<ModelQueryBuilderContract<Model, any>>; increment: Counter<ModelQueryBuilderContract<Model, any>>; decrement: Counter<ModelQueryBuilderContract<Model, any>>; /** * Fetch relationship count */ withCount: WithCount<InstanceType<Model>, this>; /** * Fetch aggregate value for a given relationship */ withAggregate: WithAggregate<InstanceType<Model>, this>; /** * Add where constraint using the relationship */ has: Has<InstanceType<Model>, this>; orHas: Has<InstanceType<Model>, this>; andHas: Has<InstanceType<Model>, this>; doesntHave: Has<InstanceType<Model>, this>; orDoesntHave: Has<InstanceType<Model>, this>; andDoesntHave: Has<InstanceType<Model>, this>; /** * Add where constraint using the relationship with a custom callback */ whereHas: WhereHas<InstanceType<Model>, this>; orWhereHas: WhereHas<InstanceType<Model>, this>; andWhereHas: WhereHas<InstanceType<Model>, this>; whereDoesntHave: WhereHas<InstanceType<Model>, this>; orWhereDoesntHave: WhereHas<InstanceType<Model>, this>; andWhereDoesntHave: WhereHas<InstanceType<Model>, this>; /** * Define relationships to be preloaded */ preload: Preload<InstanceType<Model>, this>; preloadOnce: PreloadOnce<InstanceType<Model>, this>; /** * Aggregates */ count: Aggregate<this>; countDistinct: Aggregate<this>; min: Aggregate<this>; max: Aggregate<this>; sum: Aggregate<this>; sumDistinct: Aggregate<this>; avg: Aggregate<this>; avgDistinct: Aggregate<this>; /** * Executes the callback when dialect matches one of the mentioned * dialects */ ifDialect(dialect: DialectContract['name'] | DialectContract['name'][], matchCallback: (query: this) => any, noMatchCallback?: (query: this) => any): this; /** * Executes the callback when dialect matches doesn't all the mentioned * dialects */ unlessDialect(dialect: DialectContract['name'] | DialectContract['name'][], matchCallback: (query: this) => any, noMatchCallback?: (query: this) => any): this; /** * Get rows back as a plain javascript object and not an array * of model instances */ pojo<T>(): ModelQueryBuilderContract<Model, T>; } /** * Shape of model keys */ export interface ModelKeysContract { add(key: string, value: string): void; get(key: string, defaultValue: string): string; get(key: string, defaultValue?: string): string | undefined; resolve(key: string): string; all(): ModelObject; } /** * ------------------------------------------------------ * Shape of Model instance * ------------------------------------------------------ */ /** * Shape of the model instance. We prefix the properties with a `$` to * differentiate between special properties provided by the base * model but with exception to `save`, `delete`, `fill`, `merge` * and `toJSON`. * * @note: Since the interface name appears next to the inherited model * methods, we have to choose a succinct name */ export interface LucidRow { $attributes: ModelObject; $extras: ModelObject; $original: ModelObject; $preloaded: { [relation: string]: LucidRow | LucidRow[]; }; /** * Columns is a property to get type information for model * attributes. This must be declared by the end user */ $columns: undefined; $sideloaded: ModelObject; $primaryKeyValue?: number | string; $isPersisted: boolean; $isNew: boolean; $isLocal: boolean; $dirty: ModelObject; $isDirty: boolean; $isDeleted: boolean; $options?: ModelOptions; $trx?: TransactionClientContract; $setOptionsAndTrx(options?: ModelAdapterOptions): void; useTransaction(trx: TransactionClientContract): this; useConnection(connection: string): this; /** * Gives an option to the end user to define constraints for update, insert * and delete queries. Since the query builder for these queries aren't * exposed to the end user, this method opens up the API to build * custom queries. */ $getQueryFor(action: 'insert', client: QueryClientContract): ReturnType<QueryClientContract['insertQuery']>; $getQueryFor(action: 'update' | 'delete' | 'refresh', client: QueryClientContract): ModelQueryBuilderContract<LucidModel>; /** * Read/write attributes. Following methods are intentionally loosely typed, * so that one can bypass the public facing API and type checking for * advanced use cases */ $setAttribute(key: string, value: any): void; $getAttribute(key: string): any; $getAttributeFromCache(key: string, callback: CacheNode['getter']): any; /** * Read/write realtionships. Following methods are intentionally loosely typed, * so that one can bypass the public facing API and type checking for * advanced use cases */ $hasRelated(key: string): boolean; $setRelated(key: string, result: OneOrMany<LucidRow> | null): void; $pushRelated(key: string, result: OneOrMany<LucidRow> | null): void; $getRelated(key: string, defaultValue?: any): OneOrMany<LucidRow> | undefined | null; /** * Consume the adapter result and hydrate the model */ $consumeAdapterResult(adapterResult: ModelObject, sideloadAttributes?: ModelObject): void; $hydrateOriginals(): void; fill(value: Partial<ModelAttributes<this>>, allowExtraProperties?: boolean): this; merge(value: Partial<ModelAttributes<this>>, allowExtraProperties?: boolean): this; isDirty(fields?: keyof ModelAttributes<this> | (keyof ModelAttributes<this>)[]): boolean; /** * Enable force update even when no attributes * are dirty */ enableForceUpdate(): this; /** * Actions to perform on the instance */ save(): Promise<this>; /** * The lockForUpdate method re-fetches the model instance from * the database and locks the row to perform an update. The * provided callback receives a fresh user instance and should * use that to perform an update. */ lockForUpdate<T>(callback: (user: this) => Promise<T> | T): Promise<T>; /** * Perform delete by issuing a delete request on the adapter */ delete(): Promise<void>; /** * Reload/Refresh the model instance */ refresh(): Promise<this>; /** * Load relationships onto the instance */ load: LucidRowPreload<this>; /** * Load relationships onto the instance, but only if they are not * already preloaded */ loadOnce: LucidRowPreloadOnce<this>; /** * Alias for "load" * @deprecated */ preload: LucidRowPreload<this>; /** * Load aggregates */ loadAggregate: <Self extends this, Name extends ExtractModelRelations<Self>, RelatedBuilder = Self[Name] extends ModelRelations<LucidModel, LucidModel> ? Self[Name]['subQuery'] : never>(name: Name, callback: (builder: RelatedBuilder) => void) => LazyLoadAggregatesContract<Self>; /** * Load count */ loadCount: <Self extends this, Name extends ExtractModelRelations<Self>, RelatedBuilder = Self[Name] extends ModelRelations<LucidModel, LucidModel> ? Self[Name]['subQuery'] : never>(name: Name, callback?: (builder: RelatedBuilder) => void) => LazyLoadAggregatesContract<Self>; /** * Serialize attributes to a plain object */ serializeAttributes(fields?: CherryPickFields, raw?: boolean): ModelObject; /** * Serialize computed properties to a plain object */ serializeComputed(fields?: CherryPickFields): ModelObject; /** * Serialize relationships to key-value pair of model instances and * their serializeAs keys */ serializeRelations(fields: undefined, raw: true): { [key: string]: LucidRow | LucidRow[]; }; /** * Serialize relationships to key-value pair of plain nested objects */ serializeRelations(cherryPick: CherryPick['relations'] | undefined, raw: false | undefined): ModelObject; serializeRelations(cherryPick?: CherryPick['relations'], raw?: boolean): ModelObject; /** * Serialize model to a plain object */ serialize(cherryPick?: CherryPick): ModelObject; /** * Converts model to an object. It just returns the properties * of the model, along with preloaded relationships */ toObject(): ModelObject; /** * Serialize everything */ toJSON(): ModelObject; /** * Returns related model for a given relationship */ related<Name extends ExtractModelRelations<this>>(relation: Name): this[Name] extends ModelRelations<LucidModel, LucidModel> ? this[Name]['client'] : never; } /** * ------------------------------------------------------ * Shape of Model constructor * ------------------------------------------------------ */ /** * Shape of the model static properties. The `$` prefix is to denote * special properties from the base model. * * @note: Since the interface name appears next to the inherited model * methods, we have to choose a succinct name */ export interface LucidModel { /** * Whether or not model has been booted. After this model configurations * are ignored */ readonly booted: boolean; /** * A map of defined columns */ $columnsDefinitions: Map<string, ModelColumnOptions>; /** * A map of defined relationships */ $relationsDefinitions: Map<string, RelationshipsContract>; /** * A map of computed properties */ $computedDefinitions: Map<string, ComputedOptions>; /** * The primary key for finding unique referencing to a * model */ primaryKey: string; /** * Custom database connection to use */ connection?: string; /** * Naming strategy to use */ namingStrategy: NamingStrategyContract; /** * Database table to use */ table: string; /** * Self assign the primary instead of relying on the database to * return it back */ selfAssignPrimaryKey: boolean; /** * Adapter to work as a bridge between query builder and the model */ $adapter: AdapterContract; /** * Define an adapter to use for interacting with * the database */ useAdapter(adapter: AdapterContract): void; /** * Reference to hooks */ $hooks: Hooks<any>; /** * A copy of internal keys mapping. One should be able to resolve between * all key versions */ $keys: { attributesToColumns: ModelKeysContract; attributesToSerialized: ModelKeysContract; columnsToAttributes: ModelKeysContract; columnsToSerialized: ModelKeysContract; serializedToColumns: ModelKeysContract; serializedToAttributes: ModelKeysContract; }; /** * Creating model from adapter results */ $createFromAdapterResult<T extends LucidModel>(this: T, result?: ModelObject, sideloadAttributes?: ModelObject, options?: ModelAdapterOptions): null | InstanceType<T>; /** * Creating multiple model instances from an array of adapter * result */ $createMultipleFromAdapterResult<T extends LucidModel>(this: T, results: ModelObject[], sideloadAttributes?: ModelObject, options?: ModelAdapterOptions): InstanceType<T>[]; /** * Managing columns */ $addColumn(name: string, options: Partial<ColumnOptions>): ColumnOptions; $hasColumn(name: string): boolean; $getColumn(name: string): ModelColumnOptions | undefined; /** * Managing computed columns */ $addComputed(name: string, options: Partial<ComputedOptions>): ComputedOptions; $hasComputed(name: string): boolean; $getComputed(name: string): ComputedOptions | undefined; /** * Managing relationships */ $addRelation(name: string, type: ModelRelationTypes['__opaque_type'], relatedModel: () => LucidModel, options: ModelRelationOptions): void; /** * Find if a relationship exists */ $hasRelation(name: string): boolean; /** * Get relationship declaration */ $getRelation<Model extends LucidModel, Name extends ExtractModelRelations<InstanceType<Model>>>(this: Model, name: Name): InstanceType<Model>[Name] extends ModelRelations<LucidModel, LucidModel> ? InstanceType<Model>[Name]['client']['relation'] : RelationshipsContract; $getRelation<Model extends LucidModel>(this: Model, name: string): RelationshipsContract; /** * Define a static property on the model using the inherit or * define strategy. * * Inherit strategy will clone the property from the parent model * and will set it on the current model */ $defineProperty<Model extends LucidModel, Prop extends keyof Model>(this: Model, propertyName: Prop, defaultValue: Model[Prop], strategy: 'inherit' | 'define' | ((value: Model[Prop]) => Model[Prop])): void; /** * Boot model */ boot(): void; /** * Register a before hook */ before<Model extends LucidModel, Event extends 'find' | 'fetch'>(this: Model, event: Event, handler: HooksHandler<ModelQueryBuilderContract<Model>, Event>): void; before<Model extends LucidModel>(this: Model, event: 'paginate', handler: HooksHandler<[ ModelQueryBuilderContract<Model>, ModelQueryBuilderContract<Model> ], 'paginate'>): void; before<Model extends LucidModel, Event extends EventsList>(this: Model, event: Event, handler: HooksHandler<InstanceType<Model>, Event>): void; /** * Register an after hook */ after<Model extends LucidModel>(this: Model, event: 'fetch', handler: HooksHandler<InstanceType<Model>[], 'fetch'>): void; after<Model extends LucidModel>(this: Model, event: 'paginate', handler: HooksHandler<ModelPaginatorContract<InstanceType<Model>>, 'paginate'>): void; after<Model extends LucidModel, Event extends EventsList>(this: Model, event: Event, handler: HooksHandler<InstanceType<Model>, Event>): void; /** * Create model and return its instance back */ create<T extends LucidModel>(this: T, values: Partial<ModelAttributes<InstanceType<T>>>, options?: ModelAssignOptions): Promise<InstanceType<T>>; /** * Create many of model instances */ createMany<T extends LucidModel>(this: T, values: Partial<ModelAttributes<InstanceType<T>>>[], options?: ModelAssignOptions): Promise<InstanceType<T>[]>; /** * Find one using the primary key */ find<T extends LucidModel>(this: T, value: any, options?: ModelAdapterOptions): Promise<null | InstanceType<T>>; /** * Find one using the primary key or fail */ findOrFail<T extends LucidModel>(this: T, value: any, options?: ModelAdapterOptions): Promise<InstanceType<T>>; /** * Find one using a clause */ findBy<T extends LucidModel>(this: T, clause: Record<string, unknown>, options?: ModelAdapterOptions): Promise<null | InstanceType<T>>; /** * Find one using a key-value pair */ findBy<T extends LucidModel>(this: T, key: string, value: any, options?: ModelAdapterOptions): Promise<null | InstanceType<T>>; /** * Find one using a clause or fail */ findByOrFail<T extends LucidModel>(this: T, clause: Record<string, unknown>, options?: ModelAdapterOptions): Promise<InstanceType<T>>; /** * Find one using a key-value pair or fail */ findByOrFail<T extends LucidModel>(this: T, key: string, value: any, options?: ModelAdapterOptions): Promise<InstanceType<T>>; /** * Find multiple models instance using a clause */ findManyBy<T extends LucidModel>(this: T, clause: Record<string, unknown>, options?: ModelAdapterOptions): Promise<InstanceType<T>[]>; /** * Find multiple models instance using a key/value pair */ findManyBy<T extends LucidModel>(this: T, key: string, value: any, options?: ModelAdapterOptions): Promise<InstanceType<T>[]>; /** * Same as `query().first()` */ first<T extends LucidModel>(this: T, options?: ModelAdapterOptions): Promise<null | InstanceType<T>>; /** * Same as `query().firstOrFail()` */ firstOrFail<T extends LucidModel>(this: T, options?: ModelAdapterOptions): Promise<InstanceType<T>>; /** * Find many using an array of primary keys */ findMany<T extends LucidModel>(this: T, value: any[], options?: ModelAdapterOptions): Promise<InstanceType<T>[]>; /** * Returns the first row or create a new instance of model without * persisting it */ firstOrNew<T extends LucidModel>(this: T, searchPayload: Partial<ModelAttributes<InstanceType<T>>>, savePayload?: Partial<ModelAttributes<InstanceType<T>>>, options?: ModelAssignOptions): Promise<InstanceType<T>>; /** * Returns the first row or save it to the database */ firstOrCreate<T extends LucidModel>(this: T, searchPayload: Partial<ModelAttributes<InstanceType<T>>>, savePayload?: Partial<ModelAttributes<InstanceType<T>>>, options?: ModelAssignOptions): Promise<InstanceType<T>>; /** * Returns the first row or save it to the database */ updateOrCreate<T extends LucidModel>(this: T, searchPayload: Partial<ModelAttributes<InstanceType<T>>>, updatePayload: Partial<ModelAttributes<InstanceType<T>>>, options?: ModelAssignOptions): Promise<InstanceType<T>>; /** * Find rows or create in-memory instances of the missing * one's. */ fetchOrNewUpMany<T extends LucidModel>(this: T, predicate: keyof ModelAttributes<InstanceType<T>> | (keyof ModelAttributes<InstanceType<T>>)[], payload: Partial<ModelAttributes<InstanceType<T>>>[], options?: ModelAssignOptions): Promise<InstanceType<T>[]>; /** * Find rows or create many when missing. One db call is invoked * for each create */ fetchOrCreateMany<T extends LucidModel>(this: T, predicate: keyof ModelAttributes<InstanceType<T>> | (keyof ModelAttributes<InstanceType<T>>)[], payload: Partial<ModelAttributes<InstanceType<T>>>[], options?: ModelAssignOptions): Promise<InstanceType<T>[]>; /** * Update existing rows or create new one's. */ updateOrCreateMany<T extends LucidModel>(this: T, predicate: keyof ModelAttributes<InstanceType<T>> | (keyof ModelAttributes<InstanceType<T>>)[], payload: Partial<ModelAttributes<InstanceType<T>>>[], options?: ModelAssignOptions): Promise<InstanceType<T>[]>; /** * Fetch all rows */ all<T extends LucidModel>(this: T, options?: ModelAdapterOptions): Promise<InstanceType<T>[]>; /** * Returns the query for fetching a model instance */ query<Model extends LucidModel, Result = InstanceType<Model>>(this: Model, options?: ModelAdapterOptions): ModelQueryBuilderContract<Model, Result>; /** * Returns transaction client from the model. It is same as * calling "db.transaction" */ transaction: TransactionFn; /** * Truncate model table */ truncate(cascade?: boolean): Promise<void>; new (): LucidRow; } /** * ------------------------------------------------------ * Database Adapter * ------------------------------------------------------ */ /** * Every adapter must adhere to the Adapter contract */ export interface AdapterContract { /** * Returns query client for a model instance by inspecting it's options */ modelClient(instance: LucidRow): QueryClientContract; /** * Returns query client for a model constructor */ modelConstructorClient(modelConstructor: LucidModel, options?: ModelAdapterOptions): QueryClientContract; /** * Delete model instance */ delete(instance: LucidRow): Promise<void>; /** * Refresh model instance to reflect new values * from the database */ refresh(instance: LucidRow): Promise<void>; /** * Perform insert */ insert(instance: LucidRow, attributes: ModelObject): Promise<void>; /** * Perform update */ update(instance: LucidRow, attributes: ModelObject): Promise<void>; /** * Must return the query builder for the model */ query(modelConstructor: LucidModel, options?: ModelAdapterOptions): ModelQueryBuilderContract<LucidModel, LucidRow>; } /** * Naming strategy for model */ export interface NamingStrategyContract { /** * The default table name for the given model */ tableName(model: LucidModel): string; /** * The database column name for a given model attribute */ columnName(model: LucidModel, attributeName: string): string; /** * The post serialization name for a given model attribute */ serializedName(model: LucidModel, attributeName: string): string; /** * The local key for a given model relationship */ relationLocalKey(relation: ModelRelations<LucidModel, LucidModel>['__opaque_type'], model: LucidModel, relatedModel: LucidModel, relationName: string): string; /** * The foreign key for a given model relationship */ relationForeignKey(relation: ModelRelations<LucidModel, LucidModel>['__opaque_type'], model: LucidModel, relatedModel: LucidModel, relationName: string): string; /** * Pivot table name for many to many relationship */ relationPivotTable(relation: 'manyToMany', model: LucidModel, relatedModel: LucidModel, relationName: string): string; /** * Pivot foreign key for many to many relationship */ relationPivotForeignKey(relation: 'manyToMany', model: LucidModel, relatedModel: LucidModel, relationName: string): string; /** * Keys for the pagination meta */ paginationMetaKeys(): SimplePaginatorMetaKeys; } export {};