import { JoinMethod, Op } from './enums.js'; import { QueryBuilder, RawQuery } from './builders.js'; import { SortOrder, WhereBoolean } from './enums.js'; import { IQueryStatement, Wrap } from './statements.js'; import { ModelData, ModelDataWithRelationData, ModelDataWithRelationDataSearchable, PartialArray, PickRelations, Unbox, WhereFunction } from './types.js'; import { IOrmRelation } from './relations.js'; import { OrmDriver } from './driver.js'; import { Constructor, IContainer } from '@spinajs/di'; import { ModelBase } from './model.js'; import { DateTime } from 'luxon'; import { Relation } from './relation-objects.js'; import { Lazy } from '@spinajs/util'; import { IConnectionResilienceOptions } from './resilience.js'; import type { IModelChange, IModelSnapshot } from './snapshot.js'; export declare enum QueryContext { Insert = 0, Select = 1, Update = 2, Delete = 3, Schema = 4, Transaction = 5, Upsert = 6, /** INSERT that carries a RETURNING clause and therefore resolves with rows, not a status packet. */ InsertReturning = 7 } export declare enum ColumnAlterationType { Add = 0, Modify = 1, Rename = 2 } export interface ISupportedFeature { /** * DB events support * To execute tasks accoriding to schedule in DB. */ events: boolean; /** Can this dialect echo inserted rows back via RETURNING / OUTPUT on a plain INSERT? */ insertReturning: boolean; /** * Does the identity value reported after a multi-row `INSERT ... VALUES` name the key of the * FIRST row of that statement, with the remaining rows following contiguously? * * MySQL: **true**. InnoDB treats a statement whose row count is known before execution — every * `INSERT ... VALUES (…), (…)` the builder can produce — as a *simple insert*, reserves one * contiguous block of auto-increment values under a short mutex, and `LAST_INSERT_ID()` reports * the first of them. This holds under `innodb_autoinc_lock_mode = 2`, the MySQL 8 default; the * documented "values may not be contiguous" caveat is about *bulk* inserts (`INSERT … SELECT`, * row count unknown) and about mixed-mode inserts where some rows carry an explicit key. * * MSSQL: **false**. `SCOPE_IDENTITY()` returns the LAST identity generated in the scope. * SQLite: **false**. `sqlite3_last_insert_rowid()` is likewise the last row, not the first — * SQLite gets its keys from RETURNING instead. * * Optional and defaulting to false, so a custom driver that does not set it simply opts out of * the batch key backfill rather than getting wrong keys. */ insertIdIsFirstOfBatch?: boolean; } export interface IRelation, O extends ModelBase> extends Array { TargetModelDescriptor: IModelDescriptor | null; /** * Indicates if data was fetched from db */ Populated: boolean; /** * Removes all members matching the predicate. In-memory only — the database changes on the * next `sync()` ( orphan delete ) or `save()` ( orphan policy ). * * @param compare - predicate selecting members to remove */ remove(compare: (a: R) => boolean): R[]; /** * Removes the given model or models, matched by primary key ( an unsaved model, having no * key, is matched by reference ). In-memory only — persist with `sync()` / `save()`. * * @param obj - data to remove */ remove(obj: R | R[]): R[]; /** * Delete all objects from relation ( alias for empty ) */ clear(): Promise; /** * Clears relation data */ empty(): void; /** * Synchronize relation data with db * NOTE: it removes data from db that are not in relation * * @param obj - object to add * @param mode - insert mode */ sync(): Promise; /** * Calculates the intersection between this relation and the provided dataset. Pure * computation — apply it with `set()` and persist with `sync()` / `save()`. * * @param dataset - dataset to compare * @param callback - function to compare models, if not set it is compared by primary key value */ intersection(dataset: R[], callback?: (a: R, b: R) => boolean): R[]; /** * Adds the dataset's members to this relation, skipping members already present ( compared * by primary key, or by the callback ). In-memory only — persist with `sync()` / `save()`. * * @param dataset - data to add * @param callback - function to compare models, if not set it is compared by primary key value */ union(dataset: R[], callback?: (a: R, b: R) => boolean): void; /** * Calculates the symmetric difference between this relation and the dataset. Pure * computation — apply it with `set()` and persist with `sync()` / `save()`. * * @param dataset - data to compare * @param callback - function to compare objects, if none provided - primary key value is used */ diff(dataset: R[], callback?: (a: R, b: R) => boolean): R[]; /** * Clears the relation and replaces its members with the new dataset. In-memory only — * persist with `sync()` / `update()` / `save()`. * * @param obj - replacement data, or a closure receiving current members and primary key columns */ set(obj: R[] | ((data: R[], pKey: string[]) => R[])): void; /** * Populates this relation ( loads all data related to owner of this relation) */ populate(callback?: (this: ISelectQueryBuilder) => void): Promise; } export interface DbServerResponse { RowsAffected: number; LastInsertId: number; Returning: any[]; } /** * Normalizes a driver's raw insert response into {@link DbServerResponse}. * * Every driver MUST register an implementation against this token in its container — the * shape of an insert response is dialect-specific and there is no meaningful default. * Declared as a concrete class that throws rather than as an abstract method, so a container * missing the registration reports which contract was not implemented instead of dying with * `read is not a function` several frames deep inside a result middleware. */ export declare class ServerResponseMapper { /** * Normalizes a driver's raw insert response. * * @param response - whatever the driver's executeOnDb resolved with * @param pkNames - primary key column names, used to read a key out of RETURNING rows */ read(_response: any, _pkNames?: string[]): DbServerResponse; } export declare abstract class DefaultValueBuilder { Query: RawQuery; Value: string | number; /** * fills by default with current date */ abstract date(): T; /** * fills by default with current datetime */ abstract dateTime(): T; /** * Fills column with default value * * @param val - value to fill */ abstract value(val: string | number): T; /** * Fills column with result of query provided * * @param query - raw query instance */ abstract raw(query: RawQuery): T; } export declare enum InsertBehaviour { /** * Ignores if primary key exists in db */ InsertOrIgnore = 0, /** * Updates entry if pk exists */ InsertOrUpdate = 1, /** * Replaces entry if pk exists */ InsertOrReplace = 2, None = 3 } /** * Foreign key referential actions */ export declare enum ReferentialAction { Cascade = "CASCADE", SetNull = "SET NULL", Restrict = "RESTRICT", NoAction = "NO ACTION", SetDefault = "SET DEFAULT" } /** * Transaction mode when migration DB */ export declare enum MigrationTransactionMode { /** * Migration is run whithout transaction */ None = 0, /** * On transaction for one migration - every migration has its own */ PerMigration = 1, /** * One transaction wraps the whole per-connection run. Migrations with * `transaction = false` run outside it, splitting the run into segments. */ PerRun = 2 } /** * Connection pool sizing and timeouts. */ export interface IPoolOptions { /** * Connections kept open when idle. Default 0. */ Min?: number; /** * Maximum concurrent connections. Default 10. Overrides the deprecated PoolLimit. * * SQLite: writes always serialize on one handle — SQLite serializes writers at the file level, * so extra writer handles only produce SQLITE_BUSY. `Max` sizes a pool of READ-ONLY handles * instead ( `Max - 1` of them ) so concurrent SELECTs stop queueing behind each other. Ignored * for `:memory:` and anonymous temporary databases, where each handle would open its own * private database. */ Max?: number; /** * Milliseconds an idle connection is kept before being closed. Default 30000. */ IdleTimeout?: number; /** * Milliseconds to wait for a free connection before failing. Default 10000. */ AcquireTimeout?: number; } /** * Configuration options to set in configuration file and used in OrmDriver */ export interface IDriverOptions { /** * Max connections limit. * * @deprecated use `Pool.Max`. Still honoured when `Pool.Max` is absent. */ PoolLimit?: number; /** * Connection pool sizing and timeouts. */ Pool?: IPoolOptions; /** * Reconnect and health-check behaviour. */ Resilience?: IConnectionResilienceOptions; /** * Database name associated with this connection */ Database?: string; /** * User associatet with this connection */ User?: string; /** * Password to database */ Password?: string; /** * DB Host */ Host?: string; /** * Connection port */ Port?: number; /** * Connection encoding eg. utf-8 */ Encoding?: string; /** * Database filename eg. for Sqlite driver */ Filename?: string; /** * Driver name eg. mysql, sqlite, mssql etc. */ Driver: string; /** * Connection name for identification */ Name: string; /** * Additional driver-specific options */ Options?: any; /** * If this is set, database connection will be made by ssh tunnel */ SSH?: { Host: string; Port: number; PrivateKey: string; User: string; }; Migration?: { /** * Should run migration on startup */ OnStartup?: boolean; /** * Migration table name, if not set default is spinajs_migration */ Table?: string; /** * DI token of an OrmMigrationService implementation used for this * connection. Absent = built-in DefaultMigrationService. */ Service?: string; /** * Migration transaction options */ Transaction?: { /** * How to run migration - with or without transaction */ Mode?: MigrationTransactionMode; }; /** * Concurrency guard for migration runs. */ Lock?: { /** * Default true. */ Enabled?: boolean; /** * Ms to wait for the lock before failing. Default 30_000. */ Timeout?: number; /** * Ms after which a held lock counts as stale and is stolen. Default 600_000. */ StaleAfter?: number; }; }; /** * When building queries with auto generated tables & fields * we wrap them in special caharacter eg. $ * Different sql engines allows different characters, * SQLITE & MYSQL allow to use $ in queries, but MSSQL its special characted used to create pseudocolumn * * Example: SELECT $users$.Name FROM users as $users$ */ AliasSeparator?: string; /** * Is this connection default. Later can be referenced under 'default' name * eg. @Connection('default') */ DefaultConnection?: boolean; } /** * Options a migration may declare alongside its connection. */ export interface IMigrationOptions { /** * Environment this migration belongs to, eg. `local`. Absent means every environment. * * This is the declaration for migrations registered by IMPORT, where no file path is in play - * a package re-exporting its migrations from `index.ts`. For migrations discovered from disk the * filename suffix says the same thing, and the two must agree. */ Env?: string; } export interface IMigrationDescriptor { /** * Whitch connection migration will be executed */ Connection: string; /** * Environment this migration belongs to - see IMigrationOptions.Env */ Env?: string; /** * Absolute path of the file `@Migration()` was applied in, captured off the V8 stack at * decoration time. Best-effort: `undefined` under a bundler that mangles paths, in which case * `Env` above is the only env signal the migration has. */ SourceFile?: string; } export interface IValueConverterDescriptor { Class: Constructor; Options?: any; } /** * Describes model, used internally */ /** * How a primary key column gets its value. * - `auto` — the database assigns it ( identity / auto-increment column ). Default. * - `uuid` — generated client-side immediately before insert, so the value is known * without a round-trip. * - `assigned` — the caller supplies it; inserting without one is an error. */ export type PrimaryKeyGeneration = 'auto' | 'uuid' | 'assigned'; export interface IPrimaryKeyOptions { generated?: PrimaryKeyGeneration; } export interface IModelDescriptor { /** * Primary key column names, in declaration order. Empty when the model has no @Primary(). * A single-column key is a one-element array and must compile to exactly the SQL it did * when this field was a plain string. */ PrimaryKey: string[]; /** * Generation strategy per primary key column, keyed by column name. Absent means `auto`. * * A Map rather than an array because `extractModelDescriptorInherited`'s merger has a * dedicated `_.isMap` branch that merges cleanly, unlike the array branch which * concatenates ( the duplication trap fixed in Task 3 ). */ PrimaryKeyGeneration: Map; /** * Connection name, must be avaible in db config */ Connection: string | null; /** * Table name in database for this model */ TableName: string; /** * Optional, describes timestamps in model */ Timestamps: IModelTimestampDescriptor; /** * Optional, describes soft delete */ SoftDelete: IModelSoftDeleteDescriptor; /** * Optional, is archive mode enabled */ Archived: IModelArchivedDescriptor; /** * Column / fields list in model */ Columns: IColumnDescriptor[]; /** * Converters attached to fields */ Converters: Map; /** * List of unique columns ( UNIQUE constraint ) */ JunctionModelProperties: IJunctionProperty[]; /** * List of relations in model */ Relations: Map; /** Name of model */ Name: string; /** * Model discrimination map that allows to create different models based on db field value */ DiscriminationMap: IDiscriminationMap; /** * Orm driver that this model */ Driver: OrmDriver | null; /** * Json schema for validation */ Schema: any; /** * Json schema of what a SELECT of this model hands back: hidden columns removed, no * `required`, driver-specific types applied. Built next to `Schema` at model load. * * Optional so that a descriptor assembled by hand ( tests, tooling ) still type-checks; * absent means "not built yet" and readers fall back to `Schema`. */ ResponseSchema?: any; /** * Property names the model never dehydrates, declared with `@Hidden()`. Written by the * decorator at class-definition time, so it is readable before - and without - any database * connection, which is what lets the response schema and the generated API documentation be * built off a model class alone. * * Holds relation names as well as column names. */ Hidden: string[]; } export interface IDiscriminationMap { /** * DB field that holds inheritance value */ Field: string; /** * Field values mapped for proper models */ Models: Map> | null; } export interface IDiscriminationEntry { Key: string; Value: Constructor; } export declare enum RelationType { One = 0, Many = 1, ManyToMany = 2, Query = 3, Virtual = 4 } /** * What `save()` does with a row that was removed from a relation. * * - `nullify` — clear the child's foreign key, leaving the row. The default. * - `delete` — delete the child row. * - `soft-delete` — stamp the child's `@SoftDelete` column. Requires the target to carry one. * - `disable` — do nothing; the caller manages orphans by hand. */ export declare enum OrphanPolicy { Nullify = "nullify", Delete = "delete", SoftDelete = "soft-delete", Disable = "disable" } export type ForwardRefFunction = () => Constructor; /** * Returns result of last insert or affected rows ( eg. rows affected would be 0 if insert is ignored ) */ export interface IUpdateResult { RowsAffected: number; LastInsertId: number; } /** * Result of an INSERT. Extends IUpdateResult so existing RowsAffected / LastInsertId readers * keep working. `LastInsertId` is 0 when the dialect reports no identity value ( uuid and * assigned keys ); `Returning` holds the rows the dialect echoed back, empty when unsupported. */ export interface IInsertResult extends IUpdateResult { Returning: any[]; } /** * Options for `ModelBase.save()`. */ export interface ISaveOptions { /** * Re-read the current database state of every already-persisted model in the graph inside * the transaction and diff against that, instead of against the snapshot taken at * hydration. Costs one SELECT per involved table; use it when another process may have * changed the same rows since they were loaded. */ reload?: boolean; /** * Maximum number of rows per batched statement — junction inserts and the key lists of * orphan statements. Defaults to 100. Rows whose primary key the database generates are * always inserted one statement at a time so the generated key can be read back exactly. */ chunk?: number; } /** * What one `save()` actually did. */ export interface ISaveResult { Inserted: number; Updated: number; Deleted: number; SoftDeleted: number; JunctionInserted: number; JunctionDeleted: number; } export interface IRelationDescriptor { /** * Name of relations, defaults for property name in model that owns relation */ Name: string; /** * Is it one-to-one, one-to-many or many-to-many */ Type: RelationType; TargetModelType: Constructor | ForwardRefFunction | string; /** * Relation model ( foreign ) */ TargetModel: Constructor & IModelStatic; /** * Relation owner */ SourceModel: (Constructor & IModelStatic) | null; /** * Relation foreign key (one to one, one to many) */ ForeignKey: string; /** * Relation primary key (one to one, one to many) */ PrimaryKey: string; /** * Used in many to many relations, model for join table */ JunctionModel?: Constructor; /** * Join table foreign keys, defaults to auto generated field names. Can be override. */ JunctionModelTargetModelFKey_Name?: string; JunctionModelSourceModelFKey_Name?: string; /** * Callback for returning query for relations. For use as custom relation queries * * @param data fetched data to prepare relation eg. parent model to extract primary key * @returns */ Callback?: (data: ModelBase[]) => ISelectQueryBuilder; /** * When using custom @Quuery relation, this function is used to map retrieved data to model * @param data * @returns */ Mapper?: (owner: ModelBase, data: ModelBase[]) => ModelBase | ModelBase[]; JoinMode?: 'LeftJoin' | 'RightJoin'; /** * Is this relation recursive ? Used for hierarchical / paren one-to-one relations */ Recursive: boolean; /** * What happens to a member removed from this relation during `save()`. * Unset means "decide from the foreign key's nullability" — see `resolveOrphanPolicy`. */ Orphan?: OrphanPolicy; /** * Relation factory, sometimes we dont want to create standard relation object */ Factory?: (model: ModelBase, relation: IRelationDescriptor, container: IContainer, data: any[]) => Relation, ModelBase, typeof ModelBase>>; /** * sometimes we dont want to create standard relation object, so we create type * that is passed in this property */ RelationClass?: Constructor, ModelBase, typeof ModelBase>>> | (() => Constructor, ModelBase, typeof ModelBase>>>); } export interface IModelStatic extends Constructor> { where(val: boolean): ISelectQueryBuilder>>; where(val: PartialArray> | PickRelations): ISelectQueryBuilder>>; where(func: WhereFunction>): ISelectQueryBuilder>>; where(column: string, operator: Op, value: any): ISelectQueryBuilder>>; where(column: string, value: any): ISelectQueryBuilder>>; where(statement: Wrap): ISelectQueryBuilder>>; where(column: string | boolean | WhereFunction> | RawQuery | PartialArray> | Wrap | PickRelations, operator?: Op | any, value?: any): ISelectQueryBuilder>>; where(column: string | boolean | WhereFunction> | RawQuery | PartialArray> | Wrap | PickRelations, _operator?: Op | any, _value?: any): ISelectQueryBuilder>>; destroy(pk?: any | any[]): IDeleteQueryBuilder> & Promise; create(data: Partial>): Promise>; query(): ISelectQueryBuilder>>; count(callback?: (builder: IWhereBuilder) => void): Promise; count(): Promise; update(data: Partial>): IUpdateQueryBuilder>; exists(pk: any): Promise; get(pk: any): Promise>; insert(data: InstanceType | Partial> | Array> | Array>>, insertBehaviour?: InsertBehaviour): Promise; getModelDescriptor(): IModelDescriptor; getRelationDescriptor(relation: string): IRelationDescriptor; whereExists(relation: string, func: WhereFunction>): ISelectQueryBuilder>>; whereExists(query: ISelectQueryBuilder): ISelectQueryBuilder>>; whereNotExists(relation: string, func: WhereFunction>): ISelectQueryBuilder>>; whereNotExists(query: ISelectQueryBuilder): ISelectQueryBuilder>>; /** * Gets schema for filter columns of this model */ filterSchema(): object; /** * Get list of filterable columns */ filterColumns(): { column: string; operators: string[]; }; } export interface IModelBase { ModelDescriptor: IModelDescriptor | null; Container: IContainer; PrimaryKeyName: string[]; PrimaryKeyValue: any; /** Whether save() would write anything. Derived from the snapshot; no setter. */ readonly IsDirty: boolean; /** * Diff baseline captured at hydration, or null for a model that has never been in the database. */ Snapshot: IModelSnapshot | null; /** `true` until the row has been in the database - there is no diff baseline. */ readonly IsNew: boolean; /** Captures the current column values as the diff baseline. */ takeSnapshot(): void; /** Captures relation `name`'s current member primary keys into the baseline. */ snapshotRelation(name: string): void; /** Discards the diff baseline. */ clearSnapshot(): void; /** Column-level differences between the baseline and the current values, old and new. */ changeSet(): IModelChange[]; /** * Persists this model and everything reachable from it in one transaction. */ save(options?: ISaveOptions): Promise; getFlattenRelationModels(): IModelBase[]; /** * Fills model with data. It only fills properties that exists in database * * @param data - data to fill */ hydrate(data: Partial): void; /** * * Attachess model to proper relation an sets foreign key * * @param data - model to attach */ attach(data: ModelBase): void; /** * Extracts all data from model. It takes only properties that exists in DB. Does not dehydrate related data. * * @param omit - fields to omit */ dehydrate(options?: IDehydrateOptions): ModelData; /** * * Extracts all data from model with relation data. Relation data are dehydrated recursively. * * @param omit - fields to omit */ dehydrateWithRelations(options?: IDehydrateOptions): ModelDataWithRelationData; /** * deletes enitt from db. If model have SoftDelete decorator, model is marked as deleted */ destroy(): Promise; /** * If model can be in achived state - sets archived at date and saves it to db */ archive(): Promise; /** * Updates model to db */ update(): Promise; /** * Save all changes to db. It creates new entry id db or updates existing one if * primary key exists */ insert(insertBehaviour: InsertBehaviour): Promise; /** * * Shorthand for inserting model when no primary key exists, or update * its value in db if primary key is set */ insertOrUpdate(): Promise; /** * Gets model data from database and returns as fresh instance. * * If primary key is not fetched, tries to load by columns with unique constraint. * If there is no unique columns or primary key, throws error */ fresh(): Promise; /** * Refresh model from database. * * If no primary key is set, tries to fetch data base on columns * with unique constraints. If none exists, throws exception */ refresh(): Promise; /** * Used for JSON serialization */ toJSON(): any; driver(): OrmDriver; } export interface IJunctionProperty { Name: string; Model: Constructor; } /** * Table column description, used in models to build schema, validate & other stuff */ export interface IColumnDescriptor { /** * Columnt type eg int, varchar, text */ Type: string; /** * Max character lenght handled in column */ MaxLength: number; /** * Column comment, use it for documentation purposes. */ Comment: string; /** * Default column value */ DefaultValue: any; /** * Full database type with size/length info & sign eg. int(10) unsigned if avaible */ NativeType: string; /** * Numeric types sign */ Unsigned: boolean; /** * Is column nullable (can be null) */ Nullable: boolean; /** * Is column primary key */ PrimaryKey: boolean; /** * Is column auto increment */ AutoIncrement: boolean; /** * Column name */ Name: string; /** * Value converter between database & model */ Converter: IValueConverter | null | undefined; /** * JSON schema definition build for this column. Used to automate data validation */ Schema: any; /** * Does have unique constraint */ Unique: boolean; /** * Is uuid generated column */ Uuid: boolean | undefined; Ignore: boolean; /** * Is column generated eg. sum,min,max & group by */ Aggregate: boolean; /** * Is column virtual ( not exists in DB ) */ Virtual: boolean; IsForeignKey: boolean; ForeignKeyDescription: { From: string; To: string; Table: string; } | null | undefined; } /** * Value converter between model & database data types */ export interface IValueConverter { /** * Converts value to database type * * @param value - value to convert */ toDB(value: any, model: ModelBase, column: IColumnDescriptor, options: any, dehydrateOptions?: IDehydrateOptions): any; /** * Converts value from database type eg. mysql timestamp to DateTime * * @param value - value to convert */ fromDB(value: any, rawData: any, options: any): any; /** * Value copy of `value` to hold as the `save()` diff baseline, for a converter whose * runtime type the ORM cannot copy on its own. * * Implement this together with {@link snapshotEquals} whenever `fromDB` returns a MUTABLE * instance of a class the ORM does not own. Without it the baseline can only either alias * the live object — making the diff permanently empty, so edits to the column are silently * never written — or treat the column as always-changed. The ORM takes the second, loud * option; this hook is how a converter opts into a precise diff instead. * * Immutable value types (the column always gets a fresh instance on assignment) need * neither hook: reference equality already answers the question. * * @param value - the converted, in-memory column value */ snapshotValue?(value: any): any; /** * Diff equality for two values produced by this converter — the baseline from * {@link snapshotValue} and the model's current value. * * @param a - baseline value * @param b - current value */ snapshotEquals?(a: any, b: any): boolean; } /** * Model timestamps description */ export interface IModelTimestampDescriptor { /** * Created at column name */ CreatedAt: string; /** * Updated at column name */ UpdatedAt: string; } /** * Model soft delete description */ export interface IModelSoftDeleteDescriptor { /** * Deleted at column name */ DeletedAt: string; } export declare abstract class OrmMigration { /** * * Migrate up - create tables, indices etc. * Be aware that model function are not avaible yet. To fill tables with * data use fill function */ abstract up(connection: OrmDriver): Promise; /** * Migrate down - undo changes made in up */ abstract down(connection: OrmDriver): Promise; /** * Migrate data - execute AFTER orm module has been initialized * * It means that all model & relations are avaible */ data(): Promise; } /** * Model archived description */ export interface IModelArchivedDescriptor { /** * Archived at column name */ ArchivedAt: string; } export interface IQueryLimit { limit?: number; offset?: number; } export interface ISort { column: string; order: SortOrder; /** * Alias of the table the column belongs to, set when the sort was merged in from a joined relation */ tableAlias?: string; } export interface IQueryBuilder { Table: string; TableAlias: string; Database: string; database(database: string): IQueryBuilder; from(table: string, alias?: string): this; setAlias(alias: string): this; Driver: OrmDriver; Container: IContainer; } export interface ILimitBuilder { take(count: number): this; skip(count: number): this; first(): Promise>; takeFirst(): this; firstOrFail(): Promise>; firstOrThrow(error: Error | ((output: ICompilerOutput) => Error)): Promise>; orThrow(error: Error | ((output: ICompilerOutput) => Error)): Promise>; getLimits(): IQueryLimit; } export interface IOrderByBuilder { orderBy(column: string): this; orderByDescending(column: string): this; order(column: string, direction?: SortOrder): this; order(sort: Partial | Array | null | undefined> | null | undefined): this; orderable(...columns: string[]): this; getOrderable(): string[]; getSort(): ISort | null; getSorts(): ISort[]; } export interface IColumnsBuilder { /** * clears selected columns */ clearColumns(): this; /** * * Select columns from db result ( multiple at once ) * * @param names - column names to select */ columns(names: string[]): this; /** * Return selected columns in this query */ getColumns(): IQueryStatement[]; /** * Selects single column from DB result with optional alias * Can be used multiple times * * @param column - column to select * @param alias - column alias ( optional ) */ select(column: string, alias?: string): this; /** * Selects custom values from DB. eg. Count(*) * * @param rawQuery - raw query to be executed */ select(rawQuery: RawQuery): this; /** * Selects multiple columns at once with aliases. Map key property is column name, value is its alias * * @param columns - column list with aliases */ select(columns: Map): this; } export interface IWhereBuilder { Statements: IQueryStatement[]; Op: WhereBoolean; clone

>(parent: P): IWhereBuilder; when(condition: boolean, callback?: WhereFunction, callbackElse?: WhereFunction): this; where(val: boolean): this; where(val: Partial>>): this; where(func: WhereFunction): this; where(func: Lazy): this; where(column: string, operator: Op, value: any): this; where(column: string, value: any): this; where(statement: Wrap): this; where(column: string | boolean | WhereFunction | Lazy | RawQuery | Partial>> | Wrap, operator?: Op | any, value?: any): this; orWhere(val: boolean): this; orWhere(val: Partial>>): this; orWhere(func: WhereFunction): this; orWhere(func: Lazy): this; orWhere(column: string, operator: Op, value: any): this; orWhere(column: string, value: any): this; orWhere(statement: Wrap): this; orWhere(column: string | boolean | WhereFunction | RawQuery | Wrap | Partial>>, operator?: Op | any, value?: any): this; andWhere(val: boolean): this; andWhere(val: Partial>>): this; andWhere(func: WhereFunction): this; andWhere(func: Lazy): this; andWhere(column: string, operator: Op, value: any): this; andWhere(column: string, value: any): this; andWhere(statement: Wrap): this; andWhere(column: string | boolean | Lazy | WhereFunction | RawQuery | Wrap | Partial>>, operator?: Op | any, value?: any): this; whereObject(obj: Partial>>): this; whereNotNull(column: string): this; whereNull(column: string): this; whereNot(column: string, val: unknown): this; whereIn(column: string, val: unknown[] | ISelectQueryBuilder): this; whereNotIn(column: string, val: unknown[] | ISelectQueryBuilder): this; whereExist(query: ISelectQueryBuilder | string, callback?: WhereFunction): this; whereNotExists(query: ISelectQueryBuilder | string, callback?: WhereFunction): this; whereBetween(column: string, val: unknown[]): this; whereNotBetween(column: string, val: unknown[]): this; whereInSet(column: string, val: unknown[]): this; whereNotInSet(column: string, val: unknown[]): this; whereOnJoin(callback: WhereFunction): this; clearWhere(): this; } export interface IWithRecursiveBuilder { CteRecursive: IQueryStatement | undefined; withRecursive(recKeyName: string, pkKeyName: string): this; /** * Drops the recursive CTE, so this builder compiles as a plain SELECT. Used on the clones * that make up the CTE's own anchor and recursive members, which must not be recursive * themselves. */ clearRecursive(): this; } export interface IGroupByBuilder { GroupStatements: IQueryStatement[]; clearGroupBy(): this; groupBy(expression: RawQuery | string): this; } /** * Dummy abstract class for allowing to add extensions for builder via declaration merging & mixins */ export interface ISelectBuilderExtensions { } export interface IJoinBuilder { JoinStatements: IQueryStatement[]; clearJoins(): this; innerJoin(query: RawQuery): this; innerJoin(relation: string, callback?: (this: IWhereBuilder) => void, queryCallback?: (this: ISelectQueryBuilder) => void): this; innerJoin(model: Constructor, callback?: (this: IWhereBuilder, queryCallback?: (this: ISelectQueryBuilder) => void) => void): this; innerJoin(options: IJoinStatementOptions): this; leftJoin(expression: RawQuery): this; leftJoin(options: IJoinStatementOptions): this; leftJoin(relation: string, callback?: (this: IWhereBuilder) => void, queryCallback?: (this: ISelectQueryBuilder) => void): this; leftJoin(model: Constructor, callback?: (this: IWhereBuilder) => void, queryCallback?: (this: ISelectQueryBuilder) => void): this; leftOuterJoin(query: RawQuery): this; leftOuterJoin(options: IJoinStatementOptions): this; leftOuterJoin(relation: string, callback?: (this: IWhereBuilder) => void, queryCallback?: (this: ISelectQueryBuilder) => void): this; leftOuterJoin(model: Constructor, callback?: (this: IWhereBuilder) => void, queryCallback?: (this: ISelectQueryBuilder) => void): this; rightJoin(expression: RawQuery): this; rightJoin(options: IJoinStatementOptions): this; rightJoin(relation: string, callback?: (this: IWhereBuilder) => void, queryCallback?: (this: ISelectQueryBuilder) => void): this; rightJoin(model: Constructor, callback?: (this: IWhereBuilder) => void, queryCallback?: (this: ISelectQueryBuilder) => void): this; rightOuterJoin(expression: RawQuery): this; rightOuterJoin(options: IJoinStatementOptions): this; rightOuterJoin(relation: string, callback?: (this: IWhereBuilder) => void, queryCallback?: (this: ISelectQueryBuilder) => void): this; rightOuterJoin(model: Constructor, callback?: (this: IWhereBuilder) => void, queryCallback?: (this: ISelectQueryBuilder) => void): this; fullOuterJoin(expression: RawQuery): this; fullOuterJoin(options: IJoinStatementOptions): this; fullOuterJoin(relation: string, callback?: (this: IWhereBuilder) => void, queryCallback?: (this: ISelectQueryBuilder) => void): this; fullOuterJoin(model: Constructor, callback?: (this: IWhereBuilder) => void, queryCallback?: (this: ISelectQueryBuilder) => void): this; crossJoin(expression: RawQuery): this; crossJoin(options: IJoinStatementOptions): this; crossJoin(relation: string, callback?: (this: IWhereBuilder) => void, queryCallback?: (this: ISelectQueryBuilder) => void): this; crossJoin(model: Constructor, callback?: (this: IWhereBuilder, queryCallback?: (this: ISelectQueryBuilder) => void) => void): this; join<_R = ModelBase>(method: JoinMethod, expression: RawQuery): this; join(method: JoinMethod, relation: string, callback?: (this: IWhereBuilder, queryCallback?: (this: ISelectQueryBuilder) => void) => void): this; join(method: JoinMethod, model: Constructor, callback?: (this: IWhereBuilder, queryCallback?: (this: ISelectQueryBuilder) => void) => void): this; join(method: JoinMethod, options: IJoinStatementOptions): this; } export interface IBuilder extends PromiseLike { middleware(middleware: IBuilderMiddleware): this; toDB(): ICompilerOutput | ICompilerOutput[]; /** * Executes the query and resolves with its result. * * The single execution entry point — `then()` delegates to it. Execution is memoized: * a builder runs at most once, and awaiting it again resolves with the same result. * Use `clone()` when a second round-trip is intended. */ execute(): Promise; } export interface IUpdateQueryBuilder extends IColumnsBuilder, IWhereBuilder { } export interface IDeleteQueryBuilder extends IWhereBuilder, ILimitBuilder { } export interface ISelectQueryBuilder extends IColumnsBuilder, IOrderByBuilder, ILimitBuilder, IWhereBuilder, IJoinBuilder, IWithRecursiveBuilder, IGroupByBuilder, IQueryBuilder, IBuilder { get Relations(): IOrmRelation[]; min(column: string, as?: string): this; max(column: string, as?: string): this; count(): this; count(column: string, as?: string): this; selectCount(): Promise; selectCount(column: string, as?: string): Promise; sum(column: string, as?: string): this; avg(column: string, as?: string): this; setAlias(alias: string): this; setTable(table: string, alias?: string): this; distinct(): this; clone(): this; /** * The outer builder this query is correlated to when it is the sub-select of a correlated * EXISTS, or `undefined` otherwise. Rebound by `clone()` so a cloned query correlates * against itself rather than against the query it was cloned from. */ get CorrelationSource(): IWhereBuilder | undefined; /** * Marks this query as the correlated sub-select of `builder`. */ correlateWith(builder: IWhereBuilder | undefined): this; /** * Includes soft-deleted rows (@SoftDelete models) that are excluded by default. */ withDeleted(): this; /** * Includes archived rows (@Archived models) that are excluded by default. */ withArchived(): this; /** * Returns true/false if query result exists in db */ resultExists(): Promise; populate<_R = this>(relation: Constructor): this; populate(relation?: string | string[] | null, callback?: (this: ISelectQueryBuilder, relation: IOrmRelation) => void): this; populate(relation: {}, callback?: (this: ISelectQueryBuilder, relation: IOrmRelation) => void): this; asRaw(): Promise; /** * Returns all records. Its for type castin when using with scopes mostly. */ all(): Promise; mergeBuilder(builder: ISelectQueryBuilder, includeStatements?: boolean): void; } export interface ICompilerOutput { expression: string | null; bindings: any[] | null; } export interface IQueryCompiler { compile(): ICompilerOutput | ICompilerOutput[]; } export interface ILimitCompiler { limit(builder: ILimitBuilder): ICompilerOutput; } export interface IGroupByCompiler { group(builder: IGroupByBuilder): ICompilerOutput; } export interface IRecursiveCompiler { recursive(builder: IWithRecursiveBuilder): ICompilerOutput; } export interface IColumnsCompiler { columns(builder: IColumnsBuilder): ICompilerOutput; } export interface IWhereCompiler { where(builder: IWhereBuilder): ICompilerOutput; } export interface IHavingCompiler { having(builder: IWhereBuilder): ICompilerOutput; } export interface IJoinCompiler { join(builder: IJoinBuilder): ICompilerOutput; } /** * Definitions of query compiler are needed for DI resolving * ========================================================== */ export declare abstract class RecursiveQueryCompiler implements IQueryCompiler { abstract compile(): ICompilerOutput; } export declare abstract class SelectQueryCompiler implements IQueryCompiler { abstract compile(): ICompilerOutput; } export declare abstract class JoinQueryCompiler implements IQueryCompiler { abstract compile(): ICompilerOutput; } export declare abstract class IndexQueryCompiler implements IQueryCompiler { abstract compile(): ICompilerOutput; } export declare abstract class LimitQueryCompiler implements IQueryCompiler { abstract compile(): ICompilerOutput; } export declare abstract class ForeignKeyQueryCompiler implements IQueryCompiler { abstract compile(): ICompilerOutput; } export declare abstract class DeleteQueryCompiler implements IQueryCompiler { abstract compile(): ICompilerOutput; } export declare abstract class UpdateQueryCompiler implements IQueryCompiler { abstract compile(): ICompilerOutput; } export declare abstract class InsertQueryCompiler implements IQueryCompiler { abstract compile(): ICompilerOutput; } export declare abstract class OnDuplicateQueryCompiler implements IQueryCompiler { abstract compile(): ICompilerOutput; } export declare abstract class TableQueryCompiler implements IQueryCompiler { abstract compile(): ICompilerOutput[] | ICompilerOutput; } export declare abstract class TableHistoryQueryCompiler implements IQueryCompiler { abstract compile(): ICompilerOutput[]; } export declare abstract class TruncateTableQueryCompiler implements IQueryCompiler { abstract compile(): ICompilerOutput; } export declare abstract class TableCloneQueryCompiler implements IQueryCompiler { abstract compile(): ICompilerOutput[]; } export declare abstract class EventQueryCompiler implements IQueryCompiler { abstract compile(): ICompilerOutput; } export declare abstract class DropEventQueryCompiler implements IQueryCompiler { abstract compile(): ICompilerOutput; } export declare abstract class AlterTableQueryCompiler implements IQueryCompiler { abstract compile(): ICompilerOutput[]; } export declare abstract class TableExistsCompiler implements IQueryCompiler { abstract compile(): ICompilerOutput; } export declare abstract class DropTableCompiler implements IQueryCompiler { abstract compile(): ICompilerOutput; } export declare abstract class DropViewCompiler implements IQueryCompiler { abstract compile(): ICompilerOutput; } export declare abstract class CreateViewCompiler implements IQueryCompiler { abstract compile(): ICompilerOutput; } export declare abstract class CreateDatabaseCompiler implements IQueryCompiler { abstract compile(): ICompilerOutput; } export declare abstract class DropDatabaseCompiler implements IQueryCompiler { abstract compile(): ICompilerOutput; } export declare abstract class ColumnQueryCompiler implements IQueryCompiler { abstract compile(): ICompilerOutput; } export declare abstract class AlterColumnQueryCompiler implements IQueryCompiler { abstract compile(): ICompilerOutput; } export declare abstract class OrderByQueryCompiler implements IQueryCompiler { abstract compile(): ICompilerOutput; } export declare abstract class GroupByQueryCompiler implements IQueryCompiler { abstract compile(): ICompilerOutput; } export declare abstract class RawSchemaQueryCompiler implements IQueryCompiler { abstract compile(): ICompilerOutput; } /** * ========================================================== */ /** * Middlewares for query builders */ export interface IBuilderMiddleware { /** * * Executed AFTER query is executed in DB and raw data is fetched * Use it to transform DB data before everything else * * @param data - raw data fetched from DB */ afterQuery(data: T): T; /** * Executed when model is about to create. Use it to * override model creation logic. If null is returned, default model * is executed * * @param data - raw data to create */ modelCreation(data: any): ModelBase | null; /** * executed after model was created ( all returned data by query is executed) * * @param data - hydrated data. Models are created and hydrated with data */ afterHydration(data: ModelBase[]): Promise; } /** * Hooks into the lifetime of every query builder. Both hooks run for EVERY builder type — * select, insert, update and delete. * * The two differ in what the query is guaranteed to contain, and that difference is * load-bearing rather than stylistic: * * - `afterQueryCreation` runs from the builder's CONSTRUCTOR. The model and the query context * are set; nothing the caller does afterwards has happened yet — no `where()`, no * `update()`, no `values()`. It is the place to ADD a constraint (rbac appends its owner * `WHERE` here) and the wrong place to read or amend the payload, which does not exist yet. * - `beforeQueryExecution` runs once per builder, immediately before the driver is called, so * the query is complete. It is the place to inspect or rewrite what is about to be written * (rbac stamps the owner column of an INSERT here, because a value written at construction * would be overwritten by the caller's own `values()` call). * * A middleware that throws from either hook aborts the query. */ export declare abstract class QueryMiddleware { /** * Called from the builder's constructor, before the caller has added anything to it. * * @param query - the freshly constructed builder */ abstract afterQueryCreation(query: QueryBuilder): void; /** * Called once per builder immediately before execution, with the query fully assembled. * * May be async. Hooks are awaited in registration order, so one that has to consult the * database before deciding — an rbac rule whose ownership lives in another table — can * do so and still abort the query by throwing. * * @param query - the completed builder */ abstract beforeQueryExecution(query: QueryBuilder): void | Promise; } export declare abstract class ModelMiddleware { abstract onDelete(model: ModelBase): Promise; abstract onUpdate(model: ModelBase): Promise; abstract onInsert(model: ModelBase): Promise; abstract onSelect(model: ModelBase): Promise; } export declare class ValueConverter implements IValueConverter { /** * Converts value to database type * * @param value - value to convert */ toDB(_value: any, _model: ModelBase, _column: IColumnDescriptor, _options?: any, _dehydrateOptions?: IDehydrateOptions): any; /** * Converts value from database type eg. mysql timestamp to DateTime * * @param value - value to convert */ fromDB(_value: any, _rawData?: any, _options?: any): any; } /** * Converter for DATETIME field (eg. mysql datetime) */ export declare class DatetimeValueConverter extends ValueConverter { } /** * Converter for TIME field ( eq. mysql datetime into timespan HH:MM:SS ) */ export declare class TimeValueConverter extends ValueConverter { } /** * Convert 0/1 to boolean ( mysql, sqlite etc. use 0/1 for boolean fields and tinyint/bit types ) */ export declare class BooleanValueConverter extends ValueConverter { } /** * Converter for set field (eg. mysql SET) */ export declare class SetValueConverter extends ValueConverter { } export declare abstract class TableAliasCompiler { abstract compile(builder: QueryBuilder, tbl?: string): string; } export interface IUniversalConverterOptions { TypeColumn: string; } /** * base class for select & where builder for defining scopes */ export declare abstract class QueryScope { } export interface IHistoricalModel { readonly __action__: 'insert' | 'update' | 'delete'; readonly __revision__: number; readonly __start__: DateTime; readonly __end__: DateTime; } export declare abstract class ModelToSqlConverter { abstract toSql(model: ModelBase): unknown; } export declare abstract class ObjectToSqlConverter { abstract toSql(model: unknown, descriptor: IModelDescriptor): unknown; } export interface IDehydrateOptions { /** * Fields to not include in dehydrate */ omit?: string[]; /** * Should skip null values in dehydrate */ skipNull?: boolean; /** * Should skip undefined values in dehydrate */ skipUndefined?: boolean; /** * Should skip empty arrays in dehydrate */ skipEmptyArray?: boolean; /** * Do not throw error if model has nullable fields and they are not set */ ignoreNullable?: boolean; /** * Datetime format to use when dehydrate DateTime fields * - iso - ISO 8601 format * - sql - SQL format (YYYY-MM-DD HH:MM:SS) * - unix - Unix timestamp (seconds since epoch) */ dateTimeFormat?: 'iso' | 'sql' | 'unix'; } export interface IJoinStatementOptions { /** * Query builder that is creating this join */ builder?: ISelectQueryBuilder; /** * Join method eg. inner, left, right */ method?: JoinMethod; /** * Joined table name if not using model */ joinTable?: string; /** * Join table alias if not using model */ joinTableAlias?: string; /** * Join table foreign key ( eg. users.id = posts.user_id -> user_id is foreign key ) */ joinTableForeignKey?: string; /** * Joined model. Is used - it searches for relation between source model & joined model * and extract all needed data */ joinModel?: Constructor; /** * */ sourceModel?: Constructor; /** * Source model - model that is creating this join * If not using builder or raw query */ sourceTableAlias?: string; /** * Source table primary key ( eg. users.id = posts.user_id -> id is primary key ) * If not using model, its needed to set this property */ sourceTablePrimaryKey?: string; /** Source table database if not using builder */ sourceTableDatabase?: string; /** Join table database if not using model */ joinTableDatabase?: string; joinTableDriver?: OrmDriver; /** * Raw query join */ query?: RawQuery; /** * Optional callback to further modify join query ( wheres ) * * @param this callback context is where builder for this join. It will preseve aliases etc. */ callback?: ((this: IWhereBuilder) => void) | Lazy<(this: ISelectQueryBuilder) => void>; /** * * Optional callback to modify whole join query builder * * @param this callback context is select query builder for this join * @returns */ queryCallback?: (this: ISelectQueryBuilder) => void; onStatements?: IQueryStatement[]; nestedJoins?: IQueryStatement[]; } export interface ITransaction { commit(): Promise; rollback(): Promise; } /** * SQL standard transaction isolation levels. Which of these a driver actually honours is * declared per driver in `OrmDriver.SupportedIsolationLevels`; requesting one that is not * listed is rejected rather than silently ignored. */ export type IsolationLevel = 'READ UNCOMMITTED' | 'READ COMMITTED' | 'REPEATABLE READ' | 'SERIALIZABLE'; export interface ITransactionOptions { /** * Isolation level for the outermost transaction. Ignored by nested calls, which map onto * savepoints inside the enclosing transaction and therefore inherit its isolation. */ isolation?: IsolationLevel; } /** * Canonicalizes `(model constructor, primary key)` to one instance for the duration of a * `save()` graph walk or a transaction. See `IdentityMap` in `identity-map.ts`. */ export interface IIdentityMap { get(model: Constructor, pk: unknown): ModelBase | undefined; has(model: Constructor, pk: unknown): boolean; /** Registers `model`, returning the canonical instance for its identity. */ add(model: ModelBase): ModelBase; readonly Size: number; clear(): void; } /** * Per-transaction state carried through `AsyncLocalStorage`. * * `connection` is the driver's own connection handle type and is absent for drivers with a * single shared handle (SQLite). `depth` counts savepoints taken so far, 0 at the outermost * transaction; it is used to mint unique savepoint names. */ export interface ITransactionContext { connection?: unknown; depth: number; /** * Identity map shared by every `save()` that runs inside this transaction. Created lazily * by the first `save()` and discarded with the context, so nothing survives the commit. */ IdentityMap?: IIdentityMap; } //# sourceMappingURL=interfaces.d.ts.map