需求
- 不喜欢用nest内置的mysql和缓存模块,自己配置mysql和redis provider
- 但是这些模块的官方api过于原始,要求自己扩展这些模块的api方法。
实现
import { ConfigService } from '@nestjs/config';
import { ConnectionOptions } from 'mysql2/promise';
import * as mysql from 'mysql2/promise';
declare module 'mysql2/promise' {
export interface Connection {
get(tableName: string, whereMap: object): any;
delete(tableName: string, whereMap: object): any;
update(tableName: string, setMap: object, whereMap: object): any;
fetch(sql: string, param: object | (number | string)[] | null): any;
fetch(sql: string): any
first(sql: string, param: object | (number | string)[] | null): any;
first(sql: string): any
insert(tableName: string, setMap: object): any;
}
}
export async function mysqlFactory (configService: ConfigService) {
const access: ConnectionOptions = {
host: configService.get('mysql.host'),
user: configService.get('mysql.user'),
password: configService.get('mysql.pass'),
database: configService.get('mysql.db'),
namedPlaceholders: true,
};
const conn = await mysql.createConnection(access);
conn.fetch = async function (sql: string, param: object | (number | string)[] | null = {} ) {
const [result] = await conn.query(sql, param);
return result;
};
conn.first = async function (sql: string, param: object | (number | string)[] | null = {} ) {
if(!/.*\s+limit\s+1\s*$/.test(sql)) {
sql += ' limit 1';
}
const [result] = await conn.query(sql, param);
return result[0];
};
conn.get = async function (tableName: string, whereMap: object ) {
const param = [];
const whereArr = [];
for(const key of Object.keys(whereMap)) {
whereArr.push(``${key}` = ?`);
param.push(whereMap[key]);
}
const where = whereArr.join(' and ');
const [result] = await conn.query(`select * from ${tableName} where ${where} limit 1`, param);
return result[0];
};
conn.delete = async function (tableName: string, whereMap: object ){
const param = [];
const whereArr = [];
for(const key of Object.keys(whereMap)) {
whereArr.push(``${key}` = ?`);
param.push(whereMap[key]);
}
const where = whereArr.join(' and ');
const [ result ] = await conn.query(`delete from ${tableName} where ${where}`, param);
return result['affectedRows'];
};
conn.update = async function (tableName: string, setMap: object, whereMap: object ) {
const param = [];
const setArr = [];
for(const key of Object.keys(setMap)) {
setArr.push(``${key}` = ?`);
param.push(setMap[key]);
}
const setData = setArr.join(',');
const whereArr = [];
for(const key of Object.keys(whereMap)) {
whereArr.push(`${key} = ?`);
param.push(whereMap[key]);
}
const whereData = whereArr.join(' and ');
const sql = `update ${tableName} set ${setData} where ${whereData}`;
const [ result ] = await conn.query(sql, param);
return result['affectedRows'];
};
conn.insert = async function (tableName: string, setMap: object) {
const param = [];
const setFieldArr = [];
const setValueArr = [];
for(const key of Object.keys(setMap)) {
setFieldArr.push(``${key}``);
setValueArr.push(`?`);
param.push(setMap[key]);
}
const setField = setFieldArr.join(',');
const setValue = setValueArr.join(',');
const sql = `insert into ${tableName} (${setField}) value(${setValue})`;
const [ result ] = await conn.query(sql, param);
return result['insertId'];
};
return conn;
}
import { ConfigService } from '@nestjs/config';
import Redis, { RedisOptions } from 'ioredis';
declare module 'ioredis' {
export interface RedisCommander {
pkeys(key: string): Promise<string[]>;
}
}
declare module 'ioredis' {
export interface Redis {
pkeys(key: string): Promise<string[]>;
}
}
export async function redisFactory(configService: ConfigService) {
const KeyPrefix = configService.get('redis.prefix') || '';
const access: RedisOptions = {
keyPrefix: configService.get('redis.prefix') || '',
username: configService.get('redis.user') || '',
password: configService.get('redis.pass') || '',
db: configService.get('redis.db') || 0,
host: configService.get('redis.host') || 'localhost',
port: configService.get('redis.port') || 6379,
};
const conn = new Redis(access);
conn.pkeys = async function (key: string) {
const rs = await conn.keys(KeyPrefix+key);
return rs.map(item=>item.substring(KeyPrefix.length));
};
return conn;
}
import { mysqlFactory } from '../../factory/mysql2.factory';
import { redisFactory } from '../../factory/ioredis.factory';
import { Module } from '@nestjs/common';
@Module({
imports: [
ConfigModule.forRoot({
load: [loadConfig],
envFilePath: 'src/config/.env',
}),
],
controllers: [],
providers: [
{
provide: 'REDIS',
useFactory: redisFactory,
inject: [ConfigService],
},
{
provide: 'MYSQL',
useFactory: mysqlFactory,
inject: [ConfigService],
},
TokenService,
SettingService,
PermissionService,
],
exports: ['MYSQL', 'REDIS', TokenService, SettingService, PermissionService],
})
export class AppModule {}
疑问