UNPKG

tspace-mysql

Version:

Tspace MySQL is a promise-based ORM for Node.js, designed with modern TypeScript and providing type safety for schema databases.

1,319 lines 100 kB
import "reflect-metadata"; import { DB } from "./DB"; import { AbstractModel } from "./Abstracts/AbstractModel"; import { Blueprint } from "./Blueprint"; import { JoinModel } from "./JoinModel"; import { CONSTANTS } from "../constants"; import type { T } from "./UtilityTypes"; import type { TRelationOptions, TValidateSchema, TGlobalSetting, TPattern, TRelationQueryOptions, TModelOrObject, TRelationKeys, TLifecycle, TCacheModel, TRawStringQuery } from "../types"; import { Join } from "./Join"; /** * * The 'Model' class is a representation of a database table * @generic {Type} TS * @generic {Type} TR * @example * import { Model, Blueprint, type T } from 'tspace-mysql' * * const schema = { * id : new Blueprint().int().primary().autoIncrement(), * uuid : new Blueprint().varchar(50).null(), * email : new Blueprint().varchar(50).null(), * name : new Blueprint().varchar(255).null(), * } * * type TS = T.Schema<typeof Schema> * * class User extends Model<TS> { * boot() { * this.useSchema(schema) * } * } * * const users = await new User().findMany() * console.log(users) */ declare class Model<TS extends Record<string, any> = any, TR = unknown> extends AbstractModel { constructor(); /** * The 'global' method is used setting global variables in models. * @static * @param {GlobalSetting} settings * @example * Model.global({ * softDelete : true, * uuid : true, * timestamp : true, * debug : true * logger : { * selected : true, * inserted : true, * updated : true, * deleted : true * }, * }) * @returns {void} void */ static global(settings: TGlobalSetting): void; /** * The 'table' method is used get table name. * @static * @returns {string} name of the table */ static get table(): string | null; /** * The 'formatPattern' method is used to change the format of the pattern. * @param {object} data { data , pattern } * @property {Record | string} data * @property {string} parttern * @returns {Record | string} T */ static formatPattern<T extends Record<string, any> | string>({ data, pattern, }: { data: T; pattern: TPattern; }): T; /** * The 'instance' method is used get instance. * @override * @static * @returns {Model} instance of the Model */ static get instance(): Model; /** * The 'query' method is used to return instance * @static * @example * const user = await User.query().where('id',1).findOne(); * console.log(user); */ static query<T>(this: new () => T): T; /** * * The 'find' method is used to retrieve a single record from a database table by its primary key. * * It allows you to retrieve a single record from a database table that meets the specified criteria. * @type {?object} options * @property {?object} options.select * @property {?object} options.except * @property {?object[]} options.orderBy * @property {?string[]} options.groupBy * @property {?string} options.having * @property {?number} options.limit * @property {?number} options.offset * @property {?object} options.where * @property {?string[]} options.whereRaw * @property {?object} options.whereQuery * @property {?{condition,callback}} options.when * @property {?{localKey , referenceKey}[]} options.join * @property {?{localKey , referenceKey}[]} options.rightJoin * @property {?{localKey , referenceKey}[]} options.leftJoin * @property {?string[]} options.relations * @property {string[]} options.relationExists * @property {?{condition,callback}} options.relationQuery * @property {?boolean} options.debug * @returns {promise<object>[]} * * @example * import { User } from '../Models/User' * * const users = await User.find({ * select : { id: true, name: true }, * where : { * id: 1 * } * }) * */ static find<Self extends Model, M extends Model = Self, S extends T.SelectOptions<M> | undefined = undefined, SR extends T.RelationOptions<M> | undefined = undefined, E extends T.ExceptOptions<M> | undefined = undefined, SRS extends Record<string, TRawStringQuery> | undefined = undefined, G extends Record<string, T.RepositoryGenericTypeOptions> | undefined = {}>(this: new () => Self, primaryKey: number | string, options?: T.RepositoryOptions<M, S, SR, E, SRS, G>): Promise<T.ResultFiltered<M, S, SR, E, SRS, G> | null>; /** * * The 'findOne' method is used to retrieve the get record that matches the query conditions. * * It allows you to retrieve a single record from a database table that meets the specified criteria. * @type {?object} options * @property {?object} options.select * @property {?object} options.except * @property {?object[]} options.orderBy * @property {?string[]} options.groupBy * @property {?string} options.having * @property {?number} options.limit * @property {?number} options.offset * @property {?object} options.where * @property {?string[]} options.whereRaw * @property {?object} options.whereQuery * @property {?{condition,callback}} options.when * @property {?{localKey , referenceKey}[]} options.join * @property {?{localKey , referenceKey}[]} options.rightJoin * @property {?{localKey , referenceKey}[]} options.leftJoin * @property {?string[]} options.relations * @property {string[]} options.relationExists * @property {?{condition,callback}} options.relationQuery * @property {?boolean} options.debug * @returns {promise<object>[]} * * @example * import { User } from '../Models/User' * * const users = await User.findOne({ * select : { id: true, name: true }, * where : { * id: 1 * } * }) * */ static findOne<Self extends Model, M extends Model = Self, S extends T.SelectOptions<M> | undefined = undefined, SR extends T.RelationOptions<M> | undefined = undefined, E extends T.ExceptOptions<M> | undefined = undefined, SRS extends Record<string, TRawStringQuery> | undefined = undefined, G extends Record<string, T.RepositoryGenericTypeOptions> | undefined = {}>(this: new () => Self, options?: T.RepositoryOptions<M, S, SR, E, SRS, G>): Promise<T.ResultFiltered<M, S, SR, E, SRS, G> | null>; /** * * The 'findMany' method is used to retrieve the get record that matches the query conditions. * * It allows you to retrieve a single record from a database table that meets the specified criteria. * @type {?object} options * @property {?object} options.select * @property {?object} options.except * @property {?object[]} options.orderBy * @property {?string[]} options.groupBy * @property {?string} options.having * @property {?number} options.limit * @property {?number} options.offset * @property {?object} options.where * @property {?string[]} options.whereRaw * @property {?object} options.whereQuery * @property {?{condition,callback}} options.when * @property {?{localKey , referenceKey}[]} options.join * @property {?{localKey , referenceKey}[]} options.rightJoin * @property {?{localKey , referenceKey}[]} options.leftJoin * @property {?string[]} options.relations * @property {string[]} options.relationExists * @property {?{condition,callback}} options.relationQuery * @property {?boolean} options.debug * @returns {promise<object>[]} * * @example * import { User } from '../Models/User' * * const users = await User.findMany({ * select : { id: true, name: true }, * where : { * id: 1 * } * }) * */ static findMany<Self extends Model, M extends Model = Self, S extends T.SelectOptions<M> | undefined = undefined, SR extends T.RelationOptions<M> | undefined = undefined, E extends T.ExceptOptions<M> | undefined = undefined, SRS extends Record<string, TRawStringQuery> | undefined = undefined, G extends Record<string, T.RepositoryGenericTypeOptions> | undefined = {}>(this: new () => Self, options?: T.RepositoryOptions<M, S, SR, E, SRS, G>): Promise<T.ResultFiltered<M, S, SR, E, SRS, G>[]>; /** * * The 'paginate' method is used to perform pagination on a set of database query results obtained through the Query Builder. * * It allows you to split a large set of query results into smaller, more manageable pages, * making it easier to display data in a web application and improve user experience. * @type {?object} options * @property {?object} options.select * @property {?object} options.except * @property {?object[]} options.orderBy * @property {?string[]} options.groupBy * @property {?string} options.having * @property {?number} options.limit * @property {?number} options.offset * @property {?object} options.where * @property {?string[]} options.whereRaw * @property {?object} options.whereQuery * @property {?{condition,callback}} options.when * @property {?{localKey , referenceKey}[]} options.join * @property {?{localKey , referenceKey}[]} options.rightJoin * @property {?{localKey , referenceKey}[]} options.leftJoin * @property {?string[]} options.relations * @property {string[]} options.relationExists * @property {?{condition,callback}} options.relationQuery * @property {?boolean} options.debug * @property {?number} options.page * @returns {promise<{ meta , data[]}>} * * @example * import { User } from '../Models/User' * * const users = await User.paginate({ * limit:15, * page: 1, * select : { id: true, name: true }, * where : { * id: 1 * } * }) */ static paginate<Self extends Model, M extends Model = Self, S extends T.SelectOptions<M> | undefined = undefined, SR extends T.RelationOptions<M> | undefined = undefined, E extends T.ExceptOptions<M> | undefined = undefined, SRS extends Record<string, TRawStringQuery> | undefined = undefined, G extends Record<string, T.RepositoryGenericTypeOptions> | undefined = {}>(this: new () => Self, options?: Omit<Partial<T.RepositoryOptions<M, S, SR, E, SRS, G>> & { page?: number; }, 'offset'>): Promise<T.PaginateResultFiltered<M, S, SR, E, SRS, G>>; /** * The 'exists' method is used to determine if any records exist in the database table that match the query conditions. * * It returns a boolean value indicating whether there are any matching records. * @type {?object} options * @property {?object} options.select * @property {?object} options.except * @property {?object[]} options.orderBy * @property {?string[]} options.groupBy * @property {?string} options.having * @property {?number} options.limit * @property {?number} options.offset * @property {?object} options.where * @property {?string[]} options.whereRaw * @property {?object} options.whereQuery * @property {?{condition,callback}} options.when * @property {?{localKey , referenceKey}[]} options.join * @property {?{localKey , referenceKey}[]} options.rightJoin * @property {?{localKey , referenceKey}[]} options.leftJoin * @property {?boolean} options.debug * @property {?number} options.page * * @example * import { User } from '../Models/User' * * const users = await User.exists({ * where : { * id: 1 * } * }) * */ static exists<Self extends Model, M extends Model = Self>(this: new () => Self, options: Partial<Omit<T.RepositoryOptions<M>, "relations" | "relationQuery">>): Promise<boolean>; /** * The 'toQuery' method is used to retrieve the raw SQL query that would be executed by a query builder instance without actually executing it. * * This method is particularly useful for debugging and understanding the SQL queries generated by your application. * @type {?object} options * @property {?object} options.select * @property {?object} options.except * @property {?object[]} options.orderBy * @property {?string[]} options.groupBy * @property {?string} options.having * @property {?number} options.limit * @property {?number} options.offset * @property {?object} options.where * @property {?string[]} options.whereRaw * @property {?object} options.whereQuery * @property {?{condition,callback}} options.when * @property {?{localKey , referenceKey}[]} options.join * @property {?{localKey , referenceKey}[]} options.rightJoin * @property {?{localKey , referenceKey}[]} options.leftJoin * @property {?boolean} options.debug * @property {?number} options.page * * @example * import { User } from '../Models/User' * * const users = await User.exists({ * where : { * id: 1 * } * }) * */ static toQuery<Self extends Model, M extends Model = Self>(this: new () => Self, options: Partial<Omit<T.RepositoryOptions<M>, "relations" | "relationQuery">>): string; /** * The 'create' method is used to insert a new record into a database table associated. * * It simplifies the process of creating and inserting records. * @type {object} options * @property {object} options.data * @property {?boolean} options.debug * @property {?transaction} options.transaction * @return {promise<T.Result<M>>} */ static create<Self extends Model, M extends Model = Self, NR extends boolean | undefined = false>(this: new () => Self, options: T.RepositoryCreate<M, NR>): Promise<NR extends true ? undefined : T.Result<M>>; /** * The 'createMany' method is used to insert a new records into a database table associated. * * It simplifies the process of creating and inserting records with an array. * @type {object} options * @property {object[]} options.data * @property {?boolean} options.debug * @property {?transaction} options.transaction * @return {promise<TS[]>} */ static createMany<Self extends Model, M extends Model = Self, NR extends boolean | undefined = false>(this: new () => Self, options: T.RepositoryCreateMultiple<M, NR>): Promise<NR extends true ? undefined : T.Result<M>[]>; /** * * The 'createOrUpdate' method allows you to update an existing record in a database table if it exists or create a new record if it does not exist. * * This method is particularly useful when you want to update a record based on certain conditions and, * if the record matching those conditions doesn't exist, create a new one with the provided data. * @type {object} options * @property {object} options.data * @property {object} options.where * @property {?boolean} options.debug * @return {promise<NR extends true ? undefined : T.Result<M>[]>} */ static createOrUpdate<Self extends Model, M extends Model = Self, NR extends boolean | undefined = false>(this: new () => Self, options: T.RepositoryCreateOrThings<M, NR>): Promise<NR extends true ? undefined : T.Result<M>[]>; /** * The 'createNotExists' method to insert data into a database table while ignoring any duplicate key constraint violations. * * This method is particularly useful when you want to insert records into a table and ensure that duplicates are not inserted, * but without raising an error or exception if duplicates are encountered. * * @type {object} options * @property {object} options.data * @property {object} options.where * @property {?boolean} options.debug * @property {?transaction} options.transaction * @return {promise<T | null>} */ static createNotExists<Self extends Model, M extends Model = Self, NR extends boolean | undefined = false>(this: new () => Self, options: T.RepositoryCreateOrThings<M, NR>): Promise<NR extends true ? undefined : T.Result<M> | null>; /** * * The 'createOrSelect' method to insert data into a database table while select any duplicate key constraint violations. * * This method is particularly useful when you want to insert records into a table and ensure that duplicates are not inserted, * but if exists should be returns a result. * @type {object} options * @property {object} options.data * @property {object} options.where * @property {?boolean} options.debug * @return {promise<T.Result<M>>} */ static createOrSelect<Self extends Model, M extends Model = Self, NR extends boolean | undefined = false>(this: new () => Self, options: T.RepositoryCreateOrThings<M, NR>): Promise<NR extends true ? undefined : T.Result<M> | null>; /** * The 'update' method is used to update existing records in a database table that are associated. * * It simplifies the process of updating records by allowing you to specify the values to be updated using a single call. * * It allows you to remove one record that match certain criteria. * @type {object} options * @property {object} options.data * @property {object} options.where * @property {?boolean} options.debug * @property {?transaction} options.transaction * @return {promise< NR extends true ? undefined : T.Result<M> | null>} */ static update<Self extends Model, M extends Model = Self, NR extends boolean | undefined = false>(this: new () => Self, options: T.RepositoryUpdate<M, NR>): Promise<NR extends true ? undefined : T.Result<M> | null>; /** * The 'updateMany' method is used to update existing records in a database table that are associated. * * It simplifies the process of updating records by allowing you to specify the values to be updated using a single call. * * It allows you to remove more records that match certain criteria. * @type {object} options * @property {object} options.data * @property {object} options.where * @property {?boolean} options.debug * @property {?transaction} options.transaction * @return {promise<T.Result<M>[]>} */ static updateMany<Self extends Model, M extends Model = Self, NR extends boolean | undefined = false>(this: new () => Self, options: T.RepositoryUpdate<M, NR>): Promise<NR extends true ? undefined : T.Result<M>[]>; /** * The 'cache' method is used get the functions from the Cache * @returns {TCacheModel} cache */ static get cache(): TCacheModel; /** * The 'boot' method is a special method that you can define within a model. * @example * class User extends Model { * boot() { * this.useUUID() * this.usePrimaryKey('id') * this.useTimestamp() * this.useSoftDelete() * } * } * @returns {void} void */ protected boot(): void; /** * The 'globalScope' method is a feature that allows you to apply query constraints to all queries for a given model. * * Suported only methods -> select , except , where , orderBy, GroupBy , limit and offset * @example * class User extends Model { * boot() { * super() * this.globalScope(query => { * return query.where('id' , '>' , 10) * }) * } * } * @returns {void} void */ protected globalScope<M extends Model>(callback: (query: M) => M): this; /** * The 'useGlobalScope' method is a feature that allows you to apply query constraints to all queries for a given model. * * Suported only methods -> select , except , where , orderBy, GroupBy , limit and offset * * @example * class User extends Model { * boot() { * super() * this.useGlobalScope(query => { * return query.where('id' , '>' , 10) * }) * } * } * @returns {void} void */ protected useGlobalScope<M extends Model>(callback: (query: M) => M): this; /** * The "useObserve" method is used to pattern refers to a way of handling model events using observer classes. * Model events are triggered when certain actions occur on models, * such as creating, updating, deleting, or saving a record. * * Observers are used to encapsulate the event-handling logic for these events, * keeping the logic separate from the model itself and promoting cleaner, more maintainable code. * @param {Function} observer * @returns this * @example * * class UserObserve { * public selected(results : unknown) { * console.log({ results , selected : true }) * } * * public created(results : unknown) { * console.log({ results , created : true }) * } * * public updated(results : unknown) { * console.log({ results ,updated : true }) * } * * public deleted(results : unknown) { * console.log({ results ,deleted : true }) * } * } * * class User extends Model { * boot() { * super() * this.useObserver(UserObserve) * } * } */ protected useObserver(observer: new () => { selected: Function; created: Function; updated: Function; deleted: Function; }): this; /** * The "useLogger" method is used to keeping query data and changed in models. * * @type {object} options * @property {boolean} options.selected - default is false * @property {boolean} options.inserted - default is true * @property {boolean} options.updated - default is true * @property {boolean} options.deleted - default is true * @example * class User extends Model { * boot() { * this.useLogger({ * selected : true, * inserted : true, * updated : true, * deleted : true, * }) * } * } * @returns {this} this */ protected useLogger({ selected, inserted, updated, deleted, }?: { selected?: boolean | undefined; inserted?: boolean | undefined; updated?: boolean | undefined; deleted?: boolean | undefined; }): this; /** * The "useSchema" method is used to define the schema. * * It's automatically create, called when not exists table or columns. * @param {object} schema using Blueprint for schema * @example * import { Blueprint } from 'tspace-mysql'; * class User extends Model { * boot() { * this.useSchema ({ * id : new Blueprint().int().notNull().primary().autoIncrement(), * uuid : new Blueprint().varchar(50).null(), * email : new Blueprint().varchar(50).null(), * name : new Blueprint().varchar(255).null(), * created_at : new Blueprint().timestamp().null(), * updated_at : new Blueprint().timestamp().null() * }) * } * } * @returns {this} this */ protected useSchema(schema: Record<string, Blueprint>): this; /** * The "useTransform " method is used to define value transformers for model columns.. * * Each transformer defines how a value is converted: * - `to` : before persisting to the database * - `from` : after retrieving from the database * * Transformers can be synchronous or asynchronous. * * @param {object} transforms * @example * import { Blueprint } from 'tspace-mysql'; * class User extends Model { * boot() { * this.useTransform({ * name : { * to : async (v) => `${v}-> transform@before`, * from : async (v) => `${v}-> transform@after`, * }, * }) * } * } * @returns {this} this */ protected useTransform(transforms: Record<string, { to: (value: unknown) => any | Promise<any>; from: (value: unknown) => any | Promise<any>; }>): this; /** * The "usePrimaryKey" method is add primary keys for database tables. * * @param {string} primary * @returns {this} this * @example * class User extends Model { * boot() { * this.usePrimaryKey() * } * } */ protected usePrimaryKey(primary: string): this; /** * The "useUUID" method is a concept of using UUIDs (Universally Unique Identifiers) as column 'uuid' in table. * * It's automatically genarate when created a result. * @param {string?} column [column=uuid] make new name column for custom column replace uuid with this * @returns {this} this * @example * class User extends Model { * boot() { * this.useUUID() * } * } */ protected useUUID(column?: string): this; /** * The "useDebug" method is viewer raw-sql logs when excute the results. * @returns {this} this */ protected useDebug(): this; /** * The "usePattern" method is used to assign pattern [snake_case , camelCase]. * @param {string} pattern * @returns {this} this * @example * class User extends Model { * boot() { * this.usePattern('camelCase') * } * } */ protected usePattern(pattern: TPattern): this; /** * The "useCamelCase" method is used to assign pattern camelCase. * @returns {this} this * @example * class User extends Model { * boot() { * this.useCamelCase() * } * } */ protected useCamelCase(): this; /** * The "SnakeCase" method is used to assign pattern snake_case. * @returns {this} this * @example * class User extends Model { * boot() { * this.SnakeCase() * } * } */ protected useSnakeCase(): this; /** * The "useSoftDelete" refer to a feature that allows you to "soft delete" records from a database table instead of permanently deleting them. * * Soft deleting means that the records are not physically removed from the database but are instead marked as deleted by setting a timestamp in a dedicated column. * * This feature is particularly useful when you want to retain a record of deleted data and potentially recover it later, * or when you want to maintain referential integrity in your database * @param {string?} column default deleted_at * @returns {this} this * @example * class User extends Model { * boot() { * this.useSoftDelete('deletedAt') * } * } */ protected useSoftDelete(column?: string): this; /** * The "useTimestamp" method is used to assign a timestamp when creating a new record, * or updating a record. * @param {object} timestampFormat * @property {string} timestampFormat.createdAt - change new name column replace by default [created at] * @property {string} timestampFormat.updatedAt - change new name column replace by default updated at * @returns {this} this * @example * class User extends Model { * boot() { * this.useTimestamp({ * createdAt : 'createdAt', * updatedAt : 'updatedAt' * }) * } * } */ protected useTimestamp(timestampFormat?: { createdAt: string; updatedAt: string; }): this; /** * This "useTable" method is used to assign the name of the table. * @param {string} table table name in database * @returns {this} this * @example * class User extends Model { * boot() { * this.useTable('setTableNameIsUser') // => 'setTableNameIsUser' * } * } */ protected useTable(table: string): this; /** * This "useTableSingular" method is used to assign the name of the table with signgular pattern. * @returns {this} this * @example * class User extends Model { * boot() { * this.useTableSingular() // => 'user' * } * } */ protected useTableSingular(): this; /** * This "useTablePlural " method is used to assign the name of the table with pluarl pattern * @returns {this} this * @example * class User extends Model { * boot() { * this.useTablePlural() // => 'users' * } * } */ protected useTablePlural(): this; /** * This 'useValidationSchema' method is used to validate the schema when have some action create or update. * @param {Object<ValidateSchema>} schema types (String Number and Date) * @returns {this} this * @example * class User extends Model { * boot() { * this.useValidationSchema({ * id : Number, * uuid : Number, * name : { * type : String, * require : true * // json : true, * // enum : ["1","2","3"] * }, * email : { * type : String, * require : true, * length : 199, * match: /^[a-zA-Z0-9._]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/, * unique : true, * fn : async (email : string) => /^[a-zA-Z0-9._]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(email) * }, * createdAt : Date, * updatedAt : Date, * deletedAt : Date * }) * } * } */ protected useValidationSchema(schema?: TValidateSchema): this; /** * This 'useValidateSchema' method is used to validate the schema when have some action create or update. * @param {Object<ValidateSchema>} schema types (String Number and Date) * @returns {this} this * @example * class User extends Model { * boot() { * this.useValidationSchema({ * id : Number, * uuid : string, * name : { * type : String, * require : true * }, * email : { * type : String, * require : true, * length : 199, * // json : true, * // enum : ["1","2","3"] * match: /^[a-zA-Z0-9._]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/, * unique : true, * fn : async (email : string) => /^[a-zA-Z0-9._]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(email) * }, * createdAt : Date, * updatedAt : Date, * deletedAt : Date * }) * } * } */ protected useValidateSchema(schema?: TValidateSchema): this; /** * The "useHooks" method is used to assign hook function when execute returned results to callback function. * @param {Function[]} funs functions for callback result * @returns {this} this * @example * class User extends Model { * boot() { * this.useHook([(results) => console.log(results)]) * } * } */ protected useHooks(funs: Function[]): this; /** * The "useMiddleware" method is used to register functions that run before the main handler executes. * * @param {Function} func functions for execute * @returns {this} this * @example * class User extends Model { * boot() { * this.useMiddleware(() => function ...) * } * } */ protected useMiddleware(func: Function): this; /** * * The 'useLifecycle' method is used to register lifecycle hooks for model events. * * Supported lifecycle types: * - "beforeInsert" * - "afterInsert" * - "beforeUpdate" * - "afterUpdate" * - "beforeRemove" * - "afterRemove" * * Each hook is executed in the order they are registered. * * @param {LifecycleType} type * The lifecycle event to register. Determines which hook * collection the function(s) will be stored in. * * @param {Function | Function[]} funcs * A function or array of functions to be executed when the * lifecycle event is triggered. All functions must be valid * JavaScript functions, otherwise an assertion error is thrown. * * @throws {Error} * Throws if any provided item in `funcs` is not a function. * * @returns {this} * Returns the current instance to enable method chaining. * * @example * // Register a single hook * this.useLifecycle("beforeInsert", () => { * console.log("Before insert hook"); * }); * * @example * // Register multiple hooks * this.useLifecycle("afterUpdate", [ * () => console.log("Update #1"), * () => console.log("Update #2"), * ]); * * @example * // Method chaining * this * .useLifecycle("beforeInsert", fnA) * .useLifecycle("afterInsert", fnB); */ protected useLifecycle(type: TLifecycle, funcs: Function | Function[]): this; /** * The "whenCreatingTable" method is used exection function when creating the table. * @param {Function} fn functions for executing when creating the table * @returns {this} this * @example * class User extends Model { * boot() { * this.whenCreatingTable(async () => { * await new User() * .create({ * ...columns * }) * .save() * }) * } * } */ protected whenCreatingTable(fn: () => Promise<any> | any): this; /** * The "onCreatingTable" method is used exection function when creating the table. * @param {Function} fn functions for executing when creating the table * @returns {this} this * @example * class User extends Model { * boot() { * this.onCreatingTable(async () => { * await new User() * .create({ * ...columns * }) * .save() * }) * } * } */ protected onCreatedTable(fn: () => Promise<any> | any): this; /** * The "onSyncTable" method is used exection function when sync the table. * @param {Function} fn functions for executing when sync table * @returns {this} this * @example * class User extends Model { * boot() { * this.onSyncTable(async () => { * console.log('onSyncTable!!') * }) * } * } */ onSyncTable(fn: () => Promise<any> | any): this; /** * exceptColumns for method except * @override * @returns {promise<string>} string */ protected exceptColumns(): Promise<string[]>; /** * Build method for relation in model * @param {string} name name relation registry in your model * @param {Function} callback query callback * @returns {this} this */ protected buildMethodRelation<K extends T.RelationKeys<this>>(name: K, callback?: Function): this; /** * The 'audit' method is used to sets the audit information for the tracking. * * @param {number} userId - The ID of the user performing the audit. * @param {Record<string, any>} [metadata] - Optional metadata to store with the audit. * @returns {this} this */ audit(userId: number, metadata?: Record<string, any>): this; meta(meta: "MAIN" | "SUBORDINATE"): this; /** * The 'typeOfSchema' method is used get type of schema. * @returns {TS} type of schema */ typeOfSchema(): TS; /** * The 'typeOfRelation' method is used get type of relation. * @returns {TR} type of Relation */ typeOfRelation(): TR; /** * The 'cache' method is used get data from cache. * @param {Object} object * @property {string} key key of cache * @property {number} expires ms * @property {boolean} namespace whether to use namespace for cache key, default is false, namespace is `${database}:${table}:${key}` * @returns {this} this */ cache({ key, expires, namespace }: { key: string; expires: number; namespace?: boolean; }): this; /** * * @override * @param {string[]} ...columns * @returns {this} this */ select<K extends T.ColumnKeys<this> | "*">(...columns: K[]): this; addSelect<K extends T.ColumnKeys<this>>(...columns: K[]): this; /** * * @override * @param {...string} columns * @returns {this} this */ except<K extends T.ColumnKeys<this>>(...columns: K[]): this; /** * * @override * @returns {this} this */ exceptTimestamp(): this; /** * * @override * @param {string} column * @param {string?} order by default order = 'asc' but you can used 'asc' or 'desc' * @returns {this} */ orderBy<K extends T.ColumnKeys<this>>(column: K, order?: "ASC" | "asc" | "DESC" | "desc"): this; /** * * @override * @param {string?} columns [column=id] * @returns {this} */ latest<K extends T.ColumnKeys<this>>(...columns: K[]): this; /** * * @override * @param {string?} columns [column=id] * @returns {this} */ oldest<K extends T.ColumnKeys<this>>(...columns: K[]): this; /** * * @override * @param {string?} columns [column=id] * @returns {this} */ groupBy<K extends T.ColumnKeys<this>>(...columns: K[]): this; /** * @override * @param {string} column * @returns {string} return table.column */ bindColumn(column: string, pattern?: boolean): string; /** * * @override * The 'makeSelectStatement' method is used to make select statement. * @returns {Promise<string>} string */ makeSelectStatement(): Promise<string>; /** * * @override * The 'makeInsertStatement' method is used to make insert table statement. * @returns {Promise<string>} string */ makeInsertStatement(): Promise<string>; /** * * @override * The 'makeUpdateStatement' method is used to make update table statement. * @returns {Promise<string>} string */ makeUpdateStatement(): Promise<string>; /** * * @override * The 'makeDeleteStatement' method is used to make delete statement. * @returns {Promise<string>} string */ makeDeleteStatement(): Promise<string>; /** * * @override * The 'makeCreateTableStatement' method is used to make create table statement. * @returns {Promise<string>} string */ makeCreateTableStatement(): Promise<string>; /** * * Clone instance of model * @param {Model} instance instance of model * @returns {this} this */ clone(instance: Model): this; /** * * Copy an instance of model * @param {Model} instance instance of model * @param {Object} options keep data * @returns {Model} Model */ copyModel(instance: Model, options?: { update?: boolean; insert?: boolean; delete?: boolean; where?: boolean; limit?: boolean; orderBy?: boolean; join?: boolean; offset?: boolean; groupBy?: boolean; select?: boolean; having?: boolean; relations?: boolean; }): this; /** * * execute the query using raw sql syntax * @override * @param {string} sql * @returns {this} this */ protected _queryStatement(sql: string, { retry }?: { retry?: boolean | undefined; }): Promise<any[]>; /** * * execute the query using raw sql syntax actions for insert update and delete * @override * @param {string} sql * @returns {this} this */ protected _actionStatement(sql: string, { retry }?: { retry?: boolean | undefined; }): Promise<any>; /** * The 'CTEs' method is used to create common table expressions(CTEs). * * @override * @returns {string} return sql query */ CTEs<M extends Model>(as: string, callback: (query: M) => M, bindModel?: new () => M): this; /** * The 'disableSoftDelete' method is used to disable the soft delete. * * @param {boolean} condition * @returns {this} this */ disableSoftDelete(condition?: boolean): this; /** * The 'disableSoftDelete' method is used to disable the soft delete. * * @param {boolean} condition * @returns {this} this */ disableTransform(condition?: boolean): this; disabledValidateSchema(condition?: boolean): this; /** * The 'ignoreSoftDelete' method is used to disable the soft delete. * @param {boolean} condition * @returns {this} this */ ignoreSoftDelete(condition?: boolean): this; /** * The 'disableVoid' method is used to disable void. * * @returns {this} this */ disableVoid(): this; /** * The 'ignoreVoid' method is used to ignore void. * * @returns {this} this */ ignoreVoid(): this; /** * The 'disabledGlobalScope' method is used to disable globalScope. * * @returns {this} this */ disabledGlobalScope(condition?: boolean): this; /** * The 'ignoreGlobalScope' method is used to disable globalScope. * * @returns {this} this */ ignoreGlobalScope(condition?: boolean): this; /** * The 'with' method is used to eager load related (relations) data when retrieving records from a database. * * Eager loading allows you to retrieve a primary model and its related models in a more efficient. * * @param {...string} nameRelations ...name registry in models using (hasOne , hasMany , belongsTo , belongsToMany) * @returns {this} this * @example * import { Model , TR } from 'tspace-mysql' * * class User extends Model { * constructor(){ * super() * this.hasMany({ name : 'posts' , model : Post }) * } * } * * class Post extends Model { * constructor(){ * super() * this.hasMany({ name : 'comments' , model : Comment }) * this.belongsTo({ name : 'user' , model : User }) * } * } * // use 'with' for results of relationship * await new User().with('posts').findMany() * */ with<K extends T.RelationKeys<this>>(...nameRelations: K[]): this; /** * The 'relations' method is used to eager load related (relations) data when retrieving records from a database. * * Eager loading allows you to retrieve a primary model and its related models in a more efficient. * * @param {...string} nameRelations ...name registry in models using (hasOne , hasMany , belongsTo , belongsToMany) * @returns {this} this * @example * import { Model , TR } from 'tspace-mysql' * * class User extends Model { * constructor(){ * super() * this.hasMany({ name : 'posts' , model : Post }) * } * } * * class Post extends Model { * constructor(){ * super() * this.hasMany({ name : 'comments' , model : Comment }) * this.belongsTo({ name : 'user' , model : User }) * } * } * // use 'with' for results of relationship * await new User().relations('posts').findMany() * */ relations<K extends T.RelationKeys<this>>(...nameRelations: K[]): this; /** * The 'withAll' method is used to eager load related (relations) data when retrieving records from a database. * * Eager loading allows you to retrieve a primary model and its related models in a more efficient * It's method ignore soft delete * @param {...string} nameRelations if data exists return empty * @returns {this} this */ withAll<K extends T.RelationKeys<this>>(...nameRelations: K[]): this; /** * The 'relationsAll' method is used to eager load related (relations) data when retrieving records from a database. * * Eager loading allows you to retrieve a primary model and its related models in a more efficient. * * It's method ignore soft delete * @param {...string} nameRelations if data exists return empty * @returns {this} this */ relationsAll<K extends T.RelationKeys<this>>(...nameRelations: K[]): this; /** * The 'withCount' method is used to eager load related (relations) data and count data in the relation. * * @param {...string} nameRelations if data exists return 0 * @returns {this} this */ withCount<K extends T.RelationKeys<this>>(...nameRelations: K[]): this; /** * The 'relationsCount' method is used to eager load related (relations) data and count data in the relation. * * @param {...string} nameRelations if data exists return 0 * @returns {this} this */ relationsCount<K extends T.RelationKeys<this>>(...nameRelations: K[]): this; /** * The 'withTrashed' method is used to eager load related (relations) data when retrieving records from a database. * * Eager loading allows you to retrieve a primary model and its related models in a more efficient. * * It's method return results only in trash (soft deleted) * @param {...string} nameRelations if data exists return blank * @returns {this} this */ withTrashed<K extends T.RelationKeys<this>>(...nameRelations: K[]): this; /** * The 'relationsTrashed' method is used to eager load related (relations) data when retrieving records from a database. * * Eager loading allows you to retrieve a primary model and its related models in a more efficient. * * It's method return results only in trash (soft deleted) * @param {...string} nameRelations if data exists return blank * @returns {this} this */ relationsTrashed<K extends T.RelationKeys<this>>(...nameRelations: K[]): this; /** * The 'withExists' method is used to eager load related (relations) data when retrieving records from a database. * * Eager loading allows you to retrieve a primary model and its related models in a more efficient * It's method return only exists result of relation query * @param {...string} nameRelations * @returns {this} this * @example * import { Model } from 'tspace-mysql' * class User extends Model { * constructor(){ * super() * this.hasMany({ name : 'posts' , model : Post }) * } * } * * class Post extends Model { * constructor(){ * super() * this.hasMany({ name : 'comments' , model : Comment }) * this.belongsTo({ name : 'user' , model : User }) * } * } * // use with for results of relationship if relations is exists * await new User().withExists('posts').findMany() */ withExists<K extends T.RelationKeys<this>>(...nameRelations: K[]): this; /** * The 'relationsExists' method is used to eager load related (relations) data when retrieving records from a database. * * Eager loading allows you to retrieve a primary model and its related models in a more efficient * It's method return only exists result of relation query * @param {...string} nameRelations * @returns {this} this * @example * import { Model } from 'tspace-mysql' * class User extends Model { * constructor(){ * super() * this.hasMany({ name : 'posts' , model : Post }) * } * } * * class Post extends Model { * constructor(){ * super() * this.hasMany({ name : 'comments' , model : Comment }) * this.belongsTo({ name : 'user' , model : User }) * } * } * // use with for results of relationship if relations is exists * await new User().relationsExists('posts').findMany() */ relationsExists<K extends T.RelationKeys<this>>(...nameRelations: K[]): this; /** * The 'has' method is used to eager load related (relations) data when retrieving records from a database. * * Eager loading allows you to retrieve a primary model and its related models in a more efficient * It's method return only exists result of relation query * @param {...string} nameRelations * @returns {this} this * @example * import { Model } from 'tspace-mysql' * import { TRelationOptions } from '../types'; * class User extends Model { * constructor(){ * super() * this.hasMany({ name : 'posts' , model : Post }) * } * } * * class Post extends Model { * cons