import mysql from "mysql2/promise"; import { Decoder } from "@simonbackx/simple-encoding"; //#region src/classes/DatabaseStoredValue.d.ts type DatabaseStoredValue = string | number | Date | null; //#endregion //#region src/classes/Database.d.ts type SQLResultRow = Record; type SQLResultNamespacedRow = Record; type SelectOptions = { connection?: mysql.PoolConnection; nestTables?: boolean; }; type PoolOptions = { debug?: boolean; host?: string; user?: string; password?: string; port?: number; database?: string | null; connectionLimit?: number; multipleStatements?: boolean; charset?: string; useSSL?: boolean; /** Path to the CA certificate file */ ca?: string; /** Path to the client private key file (for mutual TLS) */ key?: string; /** Path to the client certificate file (for mutual TLS) */ cert?: string; }; declare class DatabaseInstance { pool: mysql.Pool; debug: boolean; private transactionStorage; private static instanceStorage; private static defaultInstance; constructor(options?: PoolOptions); static get current(): DatabaseInstance; static get default(): DatabaseInstance; static use(instance: DatabaseInstance, handler: () => Promise): Promise; createPool(options?: PoolOptions): void; reload(options?: PoolOptions): Promise; setDebug(enabled?: boolean): void; getConnection(): Promise; getTransactionConnection(): mysql.PoolConnection | undefined; beginTransaction(transaction: () => Promise): Promise; escapeId(value: string): string; end(): Promise; startQuery(): [number, number]; logQuery(q: any, hrstart: [number, number]): void; finishQuery(q: any, hrstart: [number, number]): void; select(query: string, values?: any, options?: SelectOptions & { nestTables: true; }): Promise<[SQLResultNamespacedRow[], mysql.FieldPacket[] | undefined]>; select(query: string, values?: any, options?: SelectOptions & { nestTables: false; }): Promise<[SQLResultRow[], mysql.FieldPacket[] | undefined]>; insert(query: string, values?: any, useConnection?: mysql.PoolConnection): Promise<[{ insertId: any; affectedRows: number; }, mysql.FieldPacket[] | undefined]>; update(query: string, values?: any, useConnection?: mysql.PoolConnection): Promise<[{ changedRows: number; affectedRows: number; }, mysql.FieldPacket[] | undefined]>; delete(query: string, values?: any, useConnection?: mysql.PoolConnection): Promise<[{ affectedRows: number; }, mysql.FieldPacket[] | undefined]>; statement(query: string, values?: any, useConnection?: mysql.PoolConnection): Promise<[any, any]>; } type DatabaseProxy = DatabaseInstance & { readonly instance: DatabaseInstance; }; /** * The database of the current async context, as set by DatabaseInstance.use() - the default instance * outside of it. * * Reading a member off this object (Database.select, Database.pool, ...) resolves it on that instance * every time. That only exists to keep the calls that were written against the old singleton working: * write Database.instance.select(...) in new code, so the instance the query runs on is visible where * the query is. */ declare const Database: DatabaseProxy; //#endregion //#region src/classes/Factory.d.ts declare abstract class Factory { options: Options; constructor(options: Options); abstract create(): Promise; randomArray(arr: Array): any; randomEnum(e: E): E[keyof E]; randomString(length: number): string; randomFirstName(gender: 'Male' | 'Female' | 'Other'): string; randomLastName(): string; createMultiple(amount?: number): Promise; } //#endregion //#region src/classes/ColumnType.d.ts type ColumnType = 'integer' | 'number' | 'string' | 'date' | 'datetime' | 'boolean' | 'json'; //#endregion //#region src/classes/Column.d.ts declare class Column { type: ColumnType; name: string; nullable: boolean; primary: boolean; /** * Do not save the model if this is the only field that has changed */ skipUpdate: boolean; decoder: Decoder | undefined; beforeSave?: (value?: any) => any | Promise; beforeLoad?: (value?: any) => any; private static jsonVersion; /** * Set the version used for JSON encoding in simple-encoding */ static setJSONVersion(version: number): void; constructor(type: ColumnType, name: string); /** * @deprecated use to instead */ saveProperty(data: unknown): DatabaseStoredValue; isChanged(old: DatabaseStoredValue, now: DatabaseStoredValue): boolean; from(data: DatabaseStoredValue): unknown; to(data: unknown): DatabaseStoredValue; } //#endregion //#region src/classes/ManyToOneRelation.d.ts declare class ManyToOneRelation { model: { new (): M; } & typeof Model; /** * E.g. addressId */ foreignKey: string; /** * E.g. address */ modelKey: Key; constructor(model: { new (): M; } & typeof Model, modelKey: Key); isLoaded(model: Model): boolean; isSet(model: Model): boolean; joinQuery(namespaceA: string, namespaceB: string): string; load(modelsA: A[]): Promise<(A & Record)[]>; } //#endregion //#region src/classes/OneToManyRelation.d.ts declare class OneToManyRelation { modelA: { new (): A; } & typeof Model; modelB: { new (): B; } & typeof Model; /** * Foreign key of the other model that references the current model */ foreignKey: keyof B; /** * E.g. categories */ modelKey: Key; /** * Sort the loading of this relation */ sortKey: keyof B | undefined; sortOrder: 'ASC' | 'DESC'; constructor(modelA: { new (): A; } & typeof Model, modelB: { new (): B; } & typeof Model, modelKey: Key, foreignKey: keyof B); setSort(key: keyof B, order?: 'ASC' | 'DESC'): this; isLoaded(model: T): model is T & Record; /** * Generate a join query * @param namespaceA namespace in the SQL query of modelA * @param namespaceB namespace in the SQL query of modelB */ joinQuery(namespaceA: string, namespaceB: string): string; orderByQuery(namespaceB: string): string; load(modelA: A, sorted?: boolean, where?: object): Promise; } //#endregion //#region src/classes/Model.d.ts type SQLWhere = { sign: string; value: string | Date | number | null | (string | null)[] | (number | null)[]; mode?: string; }; type SQLWhereQuery = { [key: string]: string | Date | number | null | SQLWhere | SQLWhere[]; }; type Listener = (value: Value) => Promise | void; /** * Controls the fetching and decrypting of members */ declare class ModelEventBus { protected listeners: Map; }[]>; addListener(owner: any, listener: Listener): void; removeListener(owner: any): void; sendEvent(value: Value): Promise; } type ModelEventType = 'created' | 'updated' | 'deleted'; type ModelEvent = { type: 'created'; model: M; } | { type: 'updated'; model: M; changedFields: Record; originalFields: Record; /** * Use this method to compare changes */ getOldModel(): M; } | { type: 'deleted'; model: M; }; declare class Model { static primary: Column; static modelEventBus: ModelEventBus>; /** * Properties that are stored in the table (including foreign keys, but without mapped relations!) */ static columns: Map; static debug: boolean; static showWarnings: boolean; static table: string; static relations: ManyToOneRelation[]; existsInDatabase: boolean; savedProperties: Map DatabaseStoredValue; from: () => unknown; }>; /** * Sometimes we have skipUpdate properties that still should get saved on specific occasions. * E.g. update updatedAt field manually if is the only changed field. */ forceSaveProperties: Set; constructor(); /** * Delete the value of a key from memory */ eraseProperty(key: string): void; /** * Make sure this key will get saved on the next save, even when it is not changed or when it is skipUpdate */ forceSaveProperty(key: string): void; /** * Mark all properties as changed, so they will get updated on the next save */ markAllChanged(): void; /** * Returns the default select to select the needed properties of this table * @param namespace: optional namespace of this select */ static getDefaultSelect(namespace?: string): string; static selectColumnsWithout(namespace?: string, ...exclude: string[]): string; /** * Set a relation to undefined, marking it as not loaded (so it won't get saved in the next save) * @param relation */ unloadRelation(this: this & Record, relation: ManyToOneRelation): this & Record; /** * Set a relation to null, deleting it on the next save (unless unloadRelation is called) * @param relation */ unsetRelation(this: this & Record, relation: ManyToOneRelation): this & Record; setOptionalRelation(relation: ManyToOneRelation, value: Value | null): this & Record; setRelation(relation: ManyToOneRelation, value: V): this & Record; /** * Set a many relation. Note that this doesn't save the relation! You'll need to use the methods of the relation instead */ setManyRelation(relation: ManyToManyRelation | OneToManyRelation, value: Value[]): this & Record; /** * Set a many relation. Note that this doesn't save the relation! You'll need to use the methods of the relation instead */ getManyRelation(relation: ManyToManyRelation | OneToManyRelation): Value[] | null; /** * Load the returned properties from a DB response row into the model * If the row's primary key is null, undefined is returned */ static fromRow(this: T, row: Record): InstanceType | undefined; static fromRows(this: T, rows: Record>[], namespace: string): InstanceType[]; markSaved(fields?: Record, options?: { fromMySQL?: boolean; }): void; copyFrom(this: T, from: T): void; get static(): typeof Model; getPrimaryKey(): number | string | null; /** * Get a model by its primary key * @param id primary key */ static getByID(this: T, id: number | string): Promise | undefined>; /** * Get multiple models by their ID * @param ids primary key of the models you want to fetch */ static getByIDs(this: T, ...ids: (number | string)[]): Promise[]>; static buildWhereOperator(key: string, value: SQLWhere): [string, any[]]; static buildWhereQuery(where: SQLWhereQuery): [string, any[]]; /** * @deprecated Use the new SQL package instead * Get multiple models by a simple where */ static where(this: T, where: SQLWhereQuery, extra?: { limit?: number; sort?: (string | { column: string | SQLWhereQuery; direction?: 'ASC' | 'DESC'; })[]; select?: string; }): Promise[]>; /** * Get multiple models by a simple where */ static all(this: T, limit?: number): Promise[]>; /** * Return an object of all the properties that are changed and their database representation */ getChangedDatabaseProperties(): { fields: Record; skipUpdate: number; }; beforeSave(): void; /** * Return original value from the database or undefined if not known */ getOriginalValue(key: string): unknown | undefined; save(options?: { skipMarkSaved?: boolean; skipSendEvents?: boolean; }): Promise; delete(): Promise; } //#endregion //#region src/classes/ManyToManyRelation.d.ts declare class ManyToManyRelation { modelA: { new (): A; } & typeof Model; modelB: { new (): B; } & typeof Model; modelLink?: { new (): Link; } & typeof Model; /** * E.g. parents */ modelKey: Key; /** * Sort the loading of this relation */ sortKey: string | undefined; sortOrder: 'ASC' | 'DESC'; /** * E.g. _models_parents */ get linkTable(): string; /** * e.g. modelsId */ get linkKeyA(): string; /** * e.g. parentsId */ get linkKeyB(): string; constructor(modelA: { new (): A; } & typeof Model, modelB: { new (): B; } & typeof Model, modelKey: Key, modelLink?: { new (): Link; } & typeof Model); reverse(modelKey: Key2): ManyToManyRelation; setSort(key: string, order?: 'ASC' | 'DESC'): this; joinQuery(namespaceA: string, namespaceB: string): string; orderByQuery(namespaceA: string, namespaceB: string): string; load(modelA: A, sorted?: boolean, where?: object, whereLink?: object): Promise<(B & { _link: Link; })[]>; isLoaded(model: T): model is T & Record; setLinkTable(modelA: A, modelB: B, linkTableValues: { [key: string]: any; }): Promise; linkIds(modelA: string | number, modelsB: (string | number)[], linkTableValues?: { [key: string]: any[]; }): Promise; link(modelA: A, modelsB: B[], linkTableValues?: { [key: string]: any[]; }): Promise; /** * Delete all the links from modelA for this relation * @param modelA */ clearId(modelA: string | number): Promise; /** * Delete all the links from modelA for this relation * @param modelA */ clear(modelA: A): Promise; /** * Delete all the links from modelA for this relation * @param modelA */ syncId(modelA: string | number, modelsB: (string | number)[], linkTableValues?: { [key: string]: any[]; }): Promise; unlinkIds(modelA: string | number, ...modelsB: (string | number)[]): Promise<{ affectedRows: number; }>; unlink(modelA: A, ...modelsB: B[]): Promise; } //#endregion //#region src/classes/Migration.d.ts declare function fileExists(file: string): Promise; type MigrationFunction = () => Promise; declare class Migration { up: MigrationFunction; down: MigrationFunction | undefined; constructor(up: MigrationFunction, down?: MigrationFunction); /*** * Given a folder, loop all the folders in that folder and run the migrations in the 'migrations' folder * * The migrations run on the database of the current async context, unless one is passed in * options.database. That database keeps the migration history of the migrations that ran on it, * in its own 'migrations' table. */ static runAll(folder: string, options?: { database?: DatabaseInstance; }): Promise; static getMigration(file: string): Promise; } //#endregion //#region src/decorators/Column.d.ts declare function column(settings: { type: ColumnType; primary?: boolean; nullable?: boolean; decoder?: Decoder; /** * Do not save the model if this is the only field that has changed */ skipUpdate?: boolean; beforeSave?: (value?: any) => any; beforeLoad?: (value?: any) => any; foreignKey?: ManyToOneRelation; }): (target: any, key: string) => void; //#endregion export { Column, Database, DatabaseInstance, DatabaseProxy, Factory, ManyToManyRelation, ManyToOneRelation, Migration, Model, ModelEvent, ModelEventBus, ModelEventType, OneToManyRelation, PoolOptions, SQLResultNamespacedRow, SQLResultRow, column, fileExists }; //# sourceMappingURL=index.d.ts.map