///
declare module '@ioc:Adonis/Lucid/Orm' {
import { DateTime } from 'luxon';
import { Hooks } from '@poppinss/hooks';
import { ProfilerContract, ProfilerRowContract } from '@ioc:Adonis/Core/Profiler';
import { Update, Counter, OneOrMany, Aggregate, Returning, DialectContract, ChainableContract, QueryClientContract, SimplePaginatorMetaKeys, SimplePaginatorContract, TransactionClientContract, ExcutableQueryBuilderContract } from '@ioc:Adonis/Lucid/Database';
/**
* ------------------------------------------------------
* Helpers
* ------------------------------------------------------
*/
/**
* Same as [[Parameters]] but omits the first parameter
*/
type OmitFirst any> = T extends (x: any, ...args: infer P) => any ? P : never;
/**
* Same as [[Pick]] but picks by value and not the key
*/
type PickProperties = Pick;
/**
* Decorator function
*/
type DecoratorFn = (target: any, property: any) => void;
/**
* Typed decorator
*/
type TypedDecorator = (target: TTarget, property: TKey) => void;
/**
* Typed decorator that also represents an optional property
*/
type OptionalTypedDecorator = (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.
*/
type ModelAttributes = 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
*/
type ExtractScopes = {
[Scope in keyof PickProperties>]: (...args: OmitFirst) => ExtractScopes;
};
/**
* Reusable interface to define an object.
*/
interface ModelObject {
[key: string]: any;
}
/**
* Shape of cache node to keep getters optimized
*/
type CacheNode = {
original: any;
resolved: any;
getter: (value: any) => any;
};
/**
* Shape for cherry picking fields
*/
type CherryPickFields = string[] | {
pick?: string[];
omit?: string[];
};
/**
* Shape for cherry picking fields on nested relationships
*/
type CherryPick = {
fields?: CherryPickFields;
relations?: {
[relation: string]: CherryPick;
};
};
/**
* List of events for which a model will trigger hooks
*/
type EventsList = 'save' | 'create' | 'update' | 'delete' | 'fetch' | 'find' | 'paginate';
type HooksHandler = ((data: Data, event: Event) => Promise | void) | string;
/**
* ------------------------------------------------------
* Query Scope
* ------------------------------------------------------
*/
/**
* Generic query scope callback
*/
type QueryScopeCallback = (query: ModelQueryBuilderContract, ...args: any[]) => void;
/**
* Query scope
*/
type QueryScope = Scope & {
readonly isQueryScope: true;
};
/**
* A function to mark a method as query scope
*/
type ScopeFn = >(callback: Scope) => QueryScope;
/**
* ------------------------------------------------------
* Decorators and Options
* ------------------------------------------------------
*/
/**
* Options for defining a column
*/
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
*/
type ModelColumnOptions = ColumnOptions & {
hasGetter: boolean;
hasSetter: boolean;
};
/**
* Represents a computed property on the model
*/
type ComputedOptions = {
serializeAs: string | null;
meta?: any;
};
/**
* Options accepted by the Model.$addRelation method
*/
type ModelRelationOptions = RelationOptions | ManyToManyRelationOptions | ThroughRelationOptions;
/**
* Signature for column decorator function
*/
type ColumnDecorator = (options?: Partial) => DecoratorFn;
/**
* Signature for computed decorator function
*/
type ComputedDecorator = (options?: Partial) => DecoratorFn;
/**
* Decorator for defining date columns
*/
type DateColumnDecorator = (options?: Partial) => OptionalTypedDecorator;
/**
* Decorator for defining date time columns. It is same as
* date column as of now
*/
type DateTimeColumnDecorator = DateColumnDecorator;
/**
* Decorator for defining hooks. The generics enforces that
* decorator is used on static properties only
*/
type HooksDecorator = () => (target: Model, property: string) => void;
/**
* ------------------------------------------------------
* Model Options
* ------------------------------------------------------
*/
/**
* Model options to be used when making queries
*/
type ModelOptions = {
connection?: string;
profiler?: ProfilerContract | ProfilerRowContract;
};
/**
* Adapter also accepts a client directly
*/
type ModelAdapterOptions = ModelOptions & {
client?: QueryClientContract;
};
/**
* Options used by the method that internally invokes
* the merge method.
] */
type ModelAssignOptions = ModelAdapterOptions & {
allowExtraProperties?: boolean;
};
/**
* Preload function on a model instance
*/
interface LucidRowPreload extends Preload> {
(callback: (preloader: PreloaderContract) => void): Promise;
}
interface LucidRowAggregate extends Preload> {
(callback: (preloader: PreloaderContract) => void): Promise;
}
/**
* An extension of the simple paginator with support for serializing models
*/
interface ModelPaginatorContract extends Omit, 'toJSON'> {
serialize(cherryPick?: CherryPick): {
meta: any;
data: ModelObject[];
};
toJSON(): {
meta: any;
data: ModelObject[];
};
}
/**
* Lazy load aggregates for a given model instance
*/
interface LazyLoadAggregatesContract extends Promise {
loadAggregate: WithAggregate;
loadCount: WithCount;
exec(): Promise;
}
/**
* ------------------------------------------------------
* Model Query Builder
* ------------------------------------------------------
*/
/**
* Model query builder will have extras methods on top of the Database query builder
*/
interface ModelQueryBuilderContract> extends ChainableContract, ExcutableQueryBuilderContract {
model: Model;
returning: Returning;
/**
* Define a callback to transform a row
*/
rowTransformer(callback: (row: LucidRow) => void): this;
/**
* Define a custom preloader for the current query
*/
usePreloader(preloader: PreloaderContract): this;
/**
* Whether or not the query is a child query generated for `.where`
* callbacks
*/
isChildQuery: boolean;
/**
* Alias for the @withScopes method
*/
apply>(callback: (scopes: Scopes) => void): this;
/**
* Apply model query scopes on the query bulder
*/
withScopes>(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(): ModelQueryBuilderContract;
/**
* 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;
/**
* Return the first matching row or fail
*/
firstOrFail(): Promise;
/**
* Perform delete operation
*/
del(returning?: OneOrMany): ModelQueryBuilderContract;
delete(returning?: OneOrMany): ModelQueryBuilderContract;
/**
* 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 : SimplePaginatorContract>;
/**
* Mutations (update and increment can be one query aswell)
*/
update: Update>;
increment: Counter>;
decrement: Counter>;
/**
* Fetch relationship count
*/
withCount: WithCount, this>;
/**
* Fetch aggregate value for a given relationship
*/
withAggregate: WithAggregate, this>;
/**
* Add where constraint using the relationship
*/
has: Has, this>;
orHas: Has, this>;
andHas: Has, this>;
doesntHave: Has, this>;
orDoesntHave: Has, this>;
andDoesntHave: Has, this>;
/**
* Add where constraint using the relationship with a custom callback
*/
whereHas: WhereHas, this>;
orWhereHas: WhereHas, this>;
andWhereHas: WhereHas, this>;
whereDoesntHave: WhereHas, this>;
orWhereDoesntHave: WhereHas, this>;
andWhereDoesntHave: WhereHas, this>;
/**
* Define relationships to be preloaded
*/
preload: Preload, this>;
/**
* Aggregates
*/
count: Aggregate;
countDistinct: Aggregate;
min: Aggregate;
max: Aggregate;
sum: Aggregate;
sumDistinct: Aggregate;
avg: Aggregate;
avgDistinct: Aggregate;
/**
* 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(): ModelQueryBuilderContract;
}
/**
* Shape of model keys
*/
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
*/
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;
$getQueryFor(action: 'update' | 'delete' | 'refresh', client: QueryClientContract): ModelQueryBuilderContract;
/**
* 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 | null): void;
$pushRelated(key: string, result: OneOrMany | null): void;
$getRelated(key: string, defaultValue?: any): OneOrMany | undefined | null;
/**
* Consume the adapter result and hydrate the model
*/
$consumeAdapterResult(adapterResult: ModelObject, sideloadAttributes?: ModelObject): void;
$hydrateOriginals(): void;
fill(value: Partial>, allowExtraProperties?: boolean): this;
merge(value: Partial>, allowExtraProperties?: boolean): this;
/**
* Actions to perform on the instance
*/
save(): Promise;
delete(): Promise;
refresh(): Promise;
/**
* Load relationships onto the instance
*/
load: LucidRowPreload;
/**
* Alias for "load"
* @deprecated
*/
preload: LucidRowPreload;
/**
* Load aggregates
*/
loadAggregate: , RelatedBuilder = Self[Name] extends ModelRelations ? Self[Name]['subQuery'] : never>(name: Name, callback: (builder: RelatedBuilder) => void) => LazyLoadAggregatesContract;
/**
* Load count
*/
loadCount: , RelatedBuilder = Self[Name] extends ModelRelations ? Self[Name]['subQuery'] : never>(name: Name, callback?: (builder: RelatedBuilder) => void) => LazyLoadAggregatesContract;
/**
* 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>(relation: Name): this[Name] extends ModelRelations ? 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
*/
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;
/**
* A map of defined relationships
*/
$relationsDefinitions: Map;
/**
* A map of computed properties
*/
$computedDefinitions: Map;
/**
* 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;
/**
* Reference to hooks
*/
$hooks: Hooks;
/**
* 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(this: T, result?: ModelObject, sideloadAttributes?: ModelObject, options?: ModelAdapterOptions): null | InstanceType;
/**
* Creating multiple model instances from an array of adapter
* result
*/
$createMultipleFromAdapterResult(this: T, results: ModelObject[], sideloadAttributes?: ModelObject, options?: ModelAdapterOptions): InstanceType[];
/**
* Managing columns
*/
$addColumn(name: string, options: Partial): ColumnOptions;
$hasColumn(name: string): boolean;
$getColumn(name: string): ModelColumnOptions | undefined;
/**
* Managing computed columns
*/
$addComputed(name: string, options: Partial): 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>>(this: Model, name: Name): InstanceType[Name] extends ModelRelations ? InstanceType[Name]['client']['relation'] : RelationshipsContract;
$getRelation(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(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(this: Model, event: Event, handler: HooksHandler, Event>): void;
before(this: Model, event: 'paginate', handler: HooksHandler<[
ModelQueryBuilderContract,
ModelQueryBuilderContract
], 'paginate'>): void;
before(this: Model, event: Event, handler: HooksHandler, Event>): void;
/**
* Register an after hook
*/
after(this: Model, event: 'fetch', handler: HooksHandler[], 'fetch'>): void;
after(this: Model, event: 'paginate', handler: HooksHandler>, 'paginate'>): void;
after(this: Model, event: Event, handler: HooksHandler, Event>): void;
/**
* Create model and return its instance back
*/
create(this: T, values: Partial>>, options?: ModelAssignOptions): Promise>;
/**
* Create many of model instances
*/
createMany(this: T, values: Partial>>[], options?: ModelAssignOptions): Promise[]>;
/**
* Find one using the primary key
*/
find(this: T, value: any, options?: ModelAdapterOptions): Promise>;
/**
* Find one using the primary key or fail
*/
findOrFail(this: T, value: any, options?: ModelAdapterOptions): Promise>;
/**
* Find one using a key-value pair
*/
findBy(this: T, key: string, value: any, options?: ModelAdapterOptions): Promise>;
/**
* Find one using a key-value pair or fail
*/
findByOrFail(this: T, key: string, value: any, options?: ModelAdapterOptions): Promise>;
/**
* Same as `query().first()`
*/
first(this: T, options?: ModelAdapterOptions): Promise>;
/**
* Same as `query().firstOrFail()`
*/
firstOrFail(this: T, options?: ModelAdapterOptions): Promise>;
/**
* Find many using an array of primary keys
*/
findMany(this: T, value: any[], options?: ModelAdapterOptions): Promise[]>;
/**
* Returns the first row or create a new instance of model without
* persisting it
*/
firstOrNew(this: T, searchPayload: Partial>>, savePayload?: Partial>>, options?: ModelAssignOptions): Promise>;
/**
* Returns the first row or save it to the database
*/
firstOrCreate(this: T, searchPayload: Partial>>, savePayload?: Partial>>, options?: ModelAssignOptions): Promise>;
/**
* Returns the first row or save it to the database
*/
updateOrCreate(this: T, searchPayload: Partial>>, updatePayload: Partial>>, options?: ModelAssignOptions): Promise>;
/**
* Find rows or create in-memory instances of the missing
* one's.
*/
fetchOrNewUpMany(this: T, predicate: keyof ModelAttributes> | (keyof ModelAttributes>)[], payload: Partial>>[], options?: ModelAssignOptions): Promise[]>;
/**
* Find rows or create many when missing. One db call is invoked
* for each create
*/
fetchOrCreateMany(this: T, predicate: keyof ModelAttributes> | (keyof ModelAttributes>)[], payload: Partial>>[], options?: ModelAssignOptions): Promise[]>;
/**
* Update existing rows or create new one's.
*/
updateOrCreateMany(this: T, predicate: keyof ModelAttributes> | (keyof ModelAttributes>)[], payload: Partial>>[], options?: ModelAssignOptions): Promise[]>;
/**
* Fetch all rows
*/
all(this: T, options?: ModelAdapterOptions): Promise[]>;
/**
* Returns the query for fetching a model instance
*/
query>(this: Model, options?: ModelAdapterOptions): ModelQueryBuilderContract;
/**
* Truncate model table
*/
truncate(cascade?: boolean): Promise;
new (): LucidRow;
}
/**
* ------------------------------------------------------
* Database Adapter
* ------------------------------------------------------
*/
/**
* Every adapter must adhere to the Adapter contract
*/
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;
/**
* Refresh model instance to reflect new values
* from the database
*/
refresh(instance: LucidRow): Promise;
/**
* Perform insert
*/
insert(instance: LucidRow, attributes: ModelObject): Promise;
/**
* Perform update
*/
update(instance: LucidRow, attributes: ModelObject): Promise;
/**
* Must return the query builder for the model
*/
query(modelConstructor: LucidModel, options?: ModelAdapterOptions): ModelQueryBuilderContract;
}
/**
* Naming strategy for model
*/
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['__opaque_type'], model: LucidModel, relatedModel: LucidModel, relationName: string): string;
/**
* The foreign key for a given model relationship
*/
relationForeignKey(relation: ModelRelations['__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;
}
}