# mysql中间件

# 安装使用

mysql中间件为独立中间件,需要单独安装使用

npm i sener-mysql
import { Mysql } from 'sener-mysql';
new Mysql({
    // ...
});

# 基础使用

import { Sener, Router } from 'sener';
import { Mysql } from 'sener-mysql';

const router = new Router({
    '/demo': async ({ querySql }) => {
        const {results, fields} = await querySql('select * from user')
        return { data: {success: true} };
    },
});

new Sener({
  middlewares: [router, new Mysql({
    host: 'localhost',
    user: 'me',
    password: 'secret',
    database: 'my_db'
  })],
});

# 构造参数

mysql中间件依赖第三方包 mysql (opens new window), 具体构造参数可以参考 mysql.createConnection 的参数

# 自定义的context

interface IMysqlHelper {
  sql: <Model extends Record<string, any> = {
    [prop: string]: string|number|boolean,
  }>(name: string)=>SQL<Model>; // 用于拼接SQL语句
  _: typeof Cond; // 用于拼接sql语句的条件
  table: <T extends keyof (Tables) >(name: T)=> Instanceof<(Tables)[T]>;
  querySql: (sql: string|QueryOptions) => Promise<{
    results: any;
    fields: FieldInfo[];
  }>;
  mysqlConn: Connection;
}

const Cond: {
    eq(v: any): string; // =
    notEq(v: any): string; // <> (!=)
    gt(v: any): string; // >
    lt(v: any): string; // <
    gte(v: any): string; // >=
    lte(v: any): string; // <=
    bt(v1: any, v2: any): string; // between
    in(vs: any[]): string; // in
    like(v: string): string; // like
    null(): string; // is null
    notNull(): string; // is not null
}

QueryOptions、FieldInfo、 Connection 具体使用请参考 mysql (opens new window)

# sql

sql 方法用于快捷拼接sql语句,支持链式调用,简单使用方式如下

const router = new Router({
    '/demo': async ({ sql, _ }) => {
        const sqlStr = sql('user').select().where([
            { age: _.gt(18) }
        ]).sql;
        return { data: {sqlStr} };
    },
});

以下为sql方法的类型声明

interface ISQLPage {
    index?: number;
    size?: number;
}
type ICondition<Model> = ({
    [prop in keyof Model]?: any;
})[];
interface IWhere<Model> {
    where?: ICondition<Model>;
    reverse?: boolean;
}
declare class SQL<Model extends Record<string, any> = {
    [prop: string]: string | number | boolean;
}, Key = keyof Model> {
    private tableName;
    private sql;
    constructor(tableName: string);
    private reset;
    select(...args: Key[]): this;
    selectDistinct(...args: Key[]): this;
    private _select;
    orderBy<T = Key>(...args: T[]): this;
    orderByDesc<T = Key>(...args: T[]): this;
    groupBy(name: Key): this;
    insert(data: Partial<Model>): this;
    update(data: Partial<Model>): this;
    delete(): this;
    where(conditions?: ICondition<Model>, reverse?: boolean): this;
    deleteAll(): this;
    count(): this;
    sum(name: Key): this;
    avg(name: Key): this;
    min(name: Key): this;
    max(name: Key): this;
    get v(): string;
    page({ index, size, }?: ISQLPage): this;
}

where 方法

where([
  {age: 18, height: 170},
  {age: 10, height: 130},
  {age: 12, height: [130, 140]},
])
// 以上语句表示 (age=18 and height=170) or (age=10 and height=130) or (age=12 and (height=130 or 140))

where([
  {age: 18, height: 170},
  {age: 10, height: 130},
  {age: 12, height: [130, 140]},
], true)
// 第二个参数表示反转and和or的逻辑(内部数组不反转)
// 则以上表示 (age=18 or height=170) and (age=10 or height=130) and (age=12 or (height=130 or 140))

# table

Table 为mysql数据表封装的一层数据抽象层,Table是一个类,有许多的封装好的操作表数据的方法,开发者可以直接使用,也可继承自Table封装自己的业务逻辑

  1. 直接使用
const router = new Router({
    '/demo': async ({ table }) => {
        const user = table('user');
        const result = await user.page({
          index: 3,
          size: 20,
        }).exec();
        return { data: {result} };
    },
});

以下为table的类型声明

declare class Table<Model extends Record<string, any> = Record<string, any>> {
    sql: SQL;
    helper: IMysqlHelper$1;
    allKeys: string[];
    constructor(name: string, target: Mysql$1);
    find(...conds: ICondition<Model>): Promise<Model | null>;
    exist(...conds: ICondition<Model>): Promise<boolean>;
    filter(...conds: ICondition<Model>): Promise<Model[]>;
    page(data?: ISQLPage & IWhere<Model> & {
        orderBy?: {
            keys: (keyof Model)[];
            desc?: boolean;
        };
    }): Promise<Model[]>;
    count(where?: ICondition<Model>, reverse?: boolean): Promise<number>;
    update(data: Partial<Model>, conds: ICondition<Model>, reverse?: boolean): Promise<any>;
    add(data: Partial<Model>): Promise<{
        affectedRows: number;
        insertId: number;
    }>;
    exec<T = any>(sql: SQL): Promise<IQuerySqlResult$1>;
}
  1. 继承自定义业务逻辑
interface IUser {
    user_id: number,
    age: number,
    // ...
}
export class User extends Table<IUser> {
    async auth (ukey: string) {
      // todo
    }
    async login (data: any){
      // todo
    }
}

# ts类型声明

通过泛型传入数据类型之后,后续table方法的参数和返回值都会有相应的类型支持

示例如下

interface IUser {
    user_id: number,
    age: number,
    // ...
}
class User extends Table<IUser> {
    async auth (ukey: string) {
      // todo
    }
    async login (data: any){
      // todo
    }
}
const tables = {
    user: User,
    // ...
};

type ITables = typeof tables;

declare module 'sener-extend' {
    interface Table {
        tables: ITables;
    }
}
文档更新时间: 5/29/2024, 12:05:22 AM