node-mysql-query-utils
Version:
A simple MySQL query utils for Node.js
248 lines (212 loc) • 9.21 kB
text/typescript
import { ConnectionOptions } from "mysql2/promise";
/**
* Represents a type that prettifies another type by preserving its keys and values.
* @template T - The type to be prettified.
*/
export type Prettify<T> = {
[K in keyof T]: T[K];
} & unknown;
export type DatabaseConnectionConfig = {
identifierName: string;
config: ConnectionOptions;
options?: DatabaseManagementOptions;
}
export type SQL_CONSTRUCTORS = {
count: { sql: string, params: any[] },
select: { sql: string, params: any[] },
insert: { sql: string, params: any[] },
update: { sql: string, params: any[] },
delete: { sql: string, params: any[] },
from: { sql: string, params: any[] },
where: { sql: string, params: any[] },
join: { sql: string, params: any[] },
set: { sql: string, params: any[] },
groupBy: { sql: string, params: any[] },
orderBy: { sql: string, params: any[] },
offset: { sql: string, params: any[] },
limit: { sql: string, params: any[] },
}
export type TableModelConstructor<ColumnKeys, PrimaryKey> = {
tableName: string,
tableAlias?: string,
primaryKey: PrimaryKey,
columns: ColumnKeys,
enablePrimaryKey?: boolean, // If false, allows tables without primary keys (e.g., junction tables)
centralFields?: CentralFields
queryFn?: QueryFunction
}
export type CentralFields = {
ctimeField?: string;
utimeField?: string;
isActiveField?: string;
isDeletedField?: string;
statusField?: string;
}
export type RawField = {
raw: string;
alias?: string;
params?: any[];
};
export type FieldAlias<T extends string> = { [key in T]?: string }
export type SelectFields<T extends string> =
| '*'
| string & {}
| T
| (T | FieldAlias<T> | RawField | string & {})[]
| { [key in T]?: string } & RawField;
export type Direction = 'ASC' | 'DESC';
export type OrderByField<T> = {
raw?: never,
field: T | (string & {}),
direction?: Direction
} | {
raw: string,
field?: never,
direction?: Direction
};
export type GroupByField<T> = T | (string & {}) | T[];
export type ColumnData<T extends string> = Partial<Record<T, any>>;
export type IncrementDecrementValue =
| { increment: number; decrement?: never }
| { decrement: number; increment?: never };
export type UpdateValue<T extends string> = Partial<Record<T, IncrementDecrementValue | string | number | null>>;
export type InsertValue<T extends string> = ColumnData<T> | ColumnData<T>[];
export type InsertOptions<ColumnKeys extends string = string> = {
insertIgnore?: boolean;
onDuplicateKeyUpdate?: UpdateValue<ColumnKeys>;
enableTimestamps?: boolean;
ctimeField?: string;
ctimeValue?: () => any
utimeField?: string;
utimeValue?: () => any
};
export type UpdateOptions = {
enableTimestamps?: boolean;
primaryKey?: string;
utimeField?: string;
utimeValue?: () => any
};
export type PatchOptions = Prettify<{
// patchField?: string;
} & Omit<UpdateOptions, 'primaryKey'>>;
export type SoftDeleteOptions = Prettify<{
deleteField?: string;
} & UpdateOptions>
export type LimitOffset =
| { limit?: never; offset?: never }
| { limit: Limit; offset?: Offset };
export type Limit = null | number;
export type Offset = null | number;
export type JoinType = 'INNER' | 'LEFT' | 'RIGHT' | 'FULL';
// --------------------------------------------------QUERY BUILDER--------------------------------------------------
export type BuildQueryOptions = { format?: boolean; };
export type BuildQueryResult = { sql: string; params: any[];[Symbol.iterator](): Iterator<any> };
export type QueryFunction = <T>(sql: string, params?: any[]) => Promise<T>
export type QueryAction<QueryReturnType> = {
buildQuery(options?: BuildQueryOptions): BuildQueryResult;
executeQuery<ReturnType = QueryReturnType>(): Promise<ReturnType>;
}
export interface SelectQueryBuilder<ColumnKeys extends string, QueryReturnType> extends QueryAction<QueryReturnType> {
from(table: string, alias?: string): FromQueryBuilder<ColumnKeys, QueryReturnType>;
}
export interface WhereQueryBuilder<ColumnKeys extends string, QueryReturnType> extends QueryAction<QueryReturnType> {
orderBy(fields: OrderByField<ColumnKeys>[]): OrderByQueryBuilder<QueryReturnType>;
limit(limit?: Limit): LimitQueryBuilder<QueryReturnType>;
groupBy(fields: GroupByField<ColumnKeys>): GroupByQueryBuilder<QueryReturnType>;
}
export interface FromQueryBuilder<ColumnKeys extends string, QueryReturnType> extends QueryAction<QueryReturnType> {
join(joinType: JoinType, table: string, onCondition: string): JoinQueryBuilder<ColumnKeys, QueryReturnType>;
join(joinType: JoinType, table: string, alias: string, onCondition: string): JoinQueryBuilder<ColumnKeys, QueryReturnType>;
where(where: WhereCondition<ColumnKeys>): WhereQueryBuilder<ColumnKeys, QueryReturnType>;
groupBy(fields: GroupByField<ColumnKeys>): GroupByQueryBuilder<QueryReturnType>;
orderBy(fields: OrderByField<ColumnKeys>[]): OrderByQueryBuilder<QueryReturnType>;
limit(limit?: Limit): LimitQueryBuilder<QueryReturnType>;
}
export interface JoinQueryBuilder<ColumnKeys extends string, QueryReturnType> extends FromQueryBuilder<ColumnKeys, QueryReturnType> { }
// export interface GroupByQueryBuilder extends FromQueryBuilder { }
export interface OrderByQueryBuilder<QueryReturnType> extends QueryAction<QueryReturnType> {
limit(limit?: Limit): LimitQueryBuilder<QueryReturnType>;
}
export interface GroupByQueryBuilder<QueryReturnType> extends QueryAction<QueryReturnType> { }
export interface LimitQueryBuilder<QueryReturnType> extends QueryAction<QueryReturnType> {
offset(offset?: Offset): OffsetQueryBuilder<QueryReturnType>;
}
export interface OffsetQueryBuilder<QueryReturnType> extends QueryAction<QueryReturnType> { }
export interface UpdateQueryBuilder<ColumnKeys extends string, QueryReturnType> extends QueryAction<QueryReturnType> {
set?(values: UpdateValue<ColumnKeys>): UpdateQueryBuilder<ColumnKeys, QueryReturnType>;
where(conditions: WhereCondition<ColumnKeys>): WhereQueryBuilder<ColumnKeys, QueryReturnType>;
}
export interface UpdateQueryBuilderWithoutSet<ColumnKeys extends string, QueryReturnType> extends QueryAction<QueryReturnType> {
where(conditions: WhereCondition<ColumnKeys>): WhereQueryBuilder<ColumnKeys, QueryReturnType>;
}
export interface SetQueryBuilder<ColumnKeys extends string, QueryReturnType> extends QueryAction<QueryReturnType> {
where(conditions: WhereCondition<ColumnKeys>): WhereQueryBuilder<ColumnKeys, QueryReturnType>;
}
export interface InsertQueryBuilder<QueryReturnType> extends QueryAction<QueryReturnType> {
}
export interface DeleteQueryBuilder<ColumnKeys extends string, QueryReturnType> extends QueryAction<QueryReturnType> {
where(conditions: WhereCondition<ColumnKeys>): WhereQueryBuilder<ColumnKeys, QueryReturnType>;
limit(limit?: Limit): LimitQueryBuilder<QueryReturnType>;
}
// --------------------------------------------------QUERY BUILDER END--------------------------------------------------
type LikePatternType =
| { contains: string; startsWith?: never; endsWith?: never }
| { startsWith: string; contains?: never; endsWith?: never }
| { endsWith: string; contains?: never; startsWith?: never };
type EqualOperator = { '='?: any };
type NotEqualOperator = { '!='?: any };
type LessThanOperator = { '<'?: any };
type LessThanOrEqualOperator = { '<='?: any };
type GreaterThanOperator = { '>'?: any };
type GreaterThanOrEqualOperator = { '>='?: any };
type LikeOperator = { 'LIKE'?: LikePatternType | string };
type NotLikeOperator = { 'NOT_LIKE'?: LikePatternType | string };
type RegexpOperator = { 'REGEXP'?: string };
type InOperator = { 'IN'?: any[] };
type NotInOperator = { 'NOT_IN'?: any[] };
type BetweenOperator = { 'BETWEEN'?: [any, any] };
type NotBetweenOperator = { 'NOT_BETWEEN'?: [any, any] };
type IsNullOperator = { 'IS_NULL'?: true };
type IsNotNullOperator = { 'IS_NOT_NULL'?: true };
type OperatorCondition = Prettify<EqualOperator &
NotEqualOperator &
LessThanOperator &
LessThanOrEqualOperator &
GreaterThanOperator &
GreaterThanOrEqualOperator &
LikeOperator &
NotLikeOperator &
RegexpOperator &
InOperator &
NotInOperator &
BetweenOperator &
NotBetweenOperator &
IsNullOperator &
IsNotNullOperator
>;
type NonEmptyArray<T> = [T, ...T[]];
type RawWhereCondition = {
'RAW'?: {
sql: string;
params?: any[];
}
}
// export type WhereCondition = { [key: string]: OperatorCondition | string | number }
export type SimpleCondition<ColumnKeys extends string> = {
[key in ColumnKeys]?: OperatorCondition | string | number | Array<string> | Array<number>;
} & {
[key: string]: OperatorCondition | string | number | Array<string> | Array<number>;
};
export type NestedCondition<ColumnKeys extends string> = {
AND?: NonEmptyArray<WhereCondition<ColumnKeys>>;
OR?: NonEmptyArray<WhereCondition<ColumnKeys>>;
};
export type WhereCondition<ColumnKeys extends string> = Prettify<
(SimpleCondition<ColumnKeys> & NestedCondition<ColumnKeys>) |
NestedCondition<ColumnKeys> |
(RawWhereCondition & NestedCondition<ColumnKeys>) |
(SimpleCondition<ColumnKeys> & RawWhereCondition & NestedCondition<ColumnKeys>)
>;
export type DatabaseManagementOptions = {
verbose?: boolean;
}