import { ConnectionConfig, createPool, MysqlError } from 'mysql'; import { FC } from 'react' // implements export function passwordMath(len: number): string { const s = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; //prompt("请输入密码的长度"); let pass = ""; for (let i = 0; i < len; i++) { const b = Math.random() * 62; const c = Math.floor(b); pass += s[c]; } return pass } export function nxdatetime() { const date = new Date(); let month: string | number = date.getMonth() + 1; let strDate: string | number = date.getDate(); if (month <= 9) { month = "0" + month; } if (strDate <= 9) { strDate = "0" + strDate; } return date.getFullYear() + "-" + month + "-" + strDate + " " + date.getHours() + ":" + date.getMinutes() + ":" + date.getSeconds() } type valSqlUse = string | number// | undefined namespace TS { export type valApiFrom = string | number | boolean | null | undefined export type Tables = { [tablename: string]: { id: number [fieldname: string]: valApiFrom } } export type catchquery = { fun: 'catchquery', data: MysqlError['message'] } export type catchconfig = { fun: 'catchconfig', data: ConnectionConfig } export type BaseCatch = { catchquery: Function, catchconfig: Function } export type BaseApi< Tables extends TS.Tables, Joins extends Record, Join extends 'inner' | 'left' > = { configping: () => Promise configset: (sqlConfigOp: ConnectionConfig) => Promise servecolse: () => Promise insert: (c: { table: T, set: Omit }) => Promise[]>, select: (c: { table: T, join?: Join, where: { [TS in Joins[T] | T]?: Partial } }) => Promise[]>, update: (c: { table: T, join?: Join, set: Omit, where: { [TS in Joins[T] | T]?: Partial } }) => Promise[]>, delete: (c: { table: T, join?: Join, where: { [TS in Joins[T] | T]?: Partial } }) => Promise<{ id: number }[]> } type GetTypeKey = Extract<{ [K in keyof C]: [K, C[K]] }[keyof C], [any, (...args: any[]) => Promise]>[0] type OmitNever = Pick Promise ? P : never }[keyof T]>; // export type getfunParamPromise>=() } export class Base< Tables extends TS.Tables, JOINS extends { [T in keyof Tables]: readonly string[] } >{ constructor(JOINS: JOINS) { this.JOINS = JOINS this.cache = this.cacheInit(JOINS) } protected JOINS cache protected cacheInit = (JOINS: JOINS): { [T in keyof Tables]: Record } => { const c = {} as { [T in keyof Tables]: Record } Object.keys(JOINS).forEach((k: keyof Tables) => c[k] = {}) return c } } export default class Serve< Tables extends TS.Tables, Joins extends Record, Join extends 'inner' | 'left', JOINS extends { [T in keyof Tables]: readonly string[] } > extends Base implements TS.BaseCatch, TS.BaseApi { protected pool constructor(sqlConfigOp: ConnectionConfig, JOINS: JOINS) { super(JOINS) this.pool = createPool({ ...sqlConfigOp, "dateStrings": false }) } on = >(fun: T, op: any) => this[fun](op) .then((success) => ({ ...op, success })) .catch((catchop: TS.catchquery | TS.catchconfig) => ({ ...op, ...catchop })) private binJoin = ({ table, join }: { table: keyof Tables, join?: Join }): string => { const c = this.JOINS[table] if (c && c.length > 0) { return c.map(v => (join || 'inner') + ' ' + v).join(' ') } else { return ' ' } } private binSet = ({ table, set }: { table: T, set: Omit }): [string, Array] => { let kv: { k: Array, v: Array } = { k: [], v: [] } const uptimestamp = nxdatetime() set = { ...set, uptimestamp } Object.entries(set).forEach(([k, v]) => { if (v === null || v === undefined) { kv.k.push(`${table}.${k}=null`) } else if (v === false || v === undefined) { kv.k.push(`${table}.${k}=0`) } else if (v === true) { kv.k.push(`${table}.${k}=1`) } else { kv.k.push(`${table}.${k}=?`) kv.v.push(v) } }) return [' set ' + kv.k.join(' , '), kv.v] } private binWhere({ where }: { where: { [TS in Joins[T] | T]?: Partial } }): [string, Array] { let kv: { k: Array, v: Array } = { k: [], v: [] } Object.entries(where).forEach(([tname, obj]) => { Object.entries(obj as Record).forEach(([k, v]) => { if (v === null || v === undefined) { kv.k.push(`${tname}.${k} is null`) } else if (v === false) { kv.k.push(`${tname}.${k}=0`) } else if (v === true) { kv.k.push(`${tname}.${k}=1`) } else { kv.k.push(`${tname}.${k}=?`) kv.v.push(v) } }) }) const wherek = kv.k.length ? ' where ' + kv.k.join(' and ') : '' return [wherek, kv.v] } catchquery: (op: MysqlError) => TS.catchquery = op => { console.log(op) return { fun: 'catchquery', data: op.message } } catchconfig: (op: any) => TS.catchconfig = op => { console.log(op) return { fun: 'catchconfig', data: {} } } insert: TS.BaseApi['insert'] = (c) => new Promise((ok, err) => { const [sqlstr, values] = this.binSet(c) const sql = [ `insert into ${c.table}`, sqlstr, ].join(' ') this.pool.getConnection((errMsg, conn) => errMsg ? err(this.catchconfig(errMsg)) : conn.query({ sql, values }, (errmsg, data, field) => { conn.release() if (errmsg) { err(this.catchquery(errMsg)) } else { const selectsql = [ `select ${c.table}.* from ${c.table}`, 'where id=?' ].join(' ') conn.query({ sql: selectsql, values: [data.insertId] }, (errmsg, data, field) => { conn.release() if (errmsg) { err(this.catchquery(errMsg)) } else { ok(data) } }) } })) }) select: TS.BaseApi['select'] = (c) => new Promise((ok, err) => { const [sqlstr, values] = this.binWhere(c) const sql = [ `select ${c.table}.* from ${c.table}`, this.binJoin(c), sqlstr, ].join(' ') this.pool.getConnection((errMsg, conn) => errMsg ? err(this.catchconfig(errMsg)) : conn.query({ sql, values }, (errmsg, success, field) => { conn.release() return errmsg ? err(this.catchquery(errMsg)) : ok(success) })) }) update: TS.BaseApi['update'] = (c) => new Promise((ok, err) => { const [setsql, setvalues] = this.binSet(c) const [wheresql, wheresqlvalues] = this.binWhere(c) const updatesql = [ `update ${c.table}`, this.binJoin(c), setsql, wheresql ].join(' ') this.pool.getConnection((errMsg, conn) => errMsg ? err(this.catchconfig(errMsg)) : conn.query({ sql: updatesql, values: setvalues.concat(wheresqlvalues) }, (errmsg, data, field) => { if (errmsg) { err(this.catchquery(errMsg)) } else { const selectsql = [ `select ${c.table}.* from ${c.table}`, this.binJoin(c), wheresql ].join(' ') conn.query({ sql: selectsql, values: wheresqlvalues }, (errmsg, data, field) => { conn.release() if (errmsg) { err(this.catchquery(errMsg)) } else { ok(data) } }) } })) }) delete: TS.BaseApi['delete'] = (c) => new Promise((ok, err) => { const [wheresql, wheresqlvalues] = this.binWhere(c) const updatesql = [ `delete ${c.table} from ${c.table}`, this.binJoin(c), wheresql ].join(' ') this.pool.getConnection((errMsg, conn) => errMsg ? err(this.catchconfig(errMsg)) : conn.query({ sql: updatesql, values: wheresqlvalues }, (errmsg, data, field) => { conn.release() if (errmsg) { err(this.catchquery(errMsg)) } else { const selectsql = [ `select ${c.table}.* from ${c.table}`, this.binJoin(c), wheresql ].join(' ') conn.query({ sql: selectsql, values: wheresqlvalues }, (errmsg, data, field) => { conn.release() if (errmsg) { err(this.catchquery(errMsg)) } else { ok(data) } }) } })) }) configping: TS.BaseApi['configping'] = () => new Promise((ok, err) => { this.pool.getConnection((errMsg) => errMsg ? err(errMsg) : ok(true)) }) configset: TS.BaseApi['configset'] = (sqlConfigOp) => new Promise((ok) => { this.pool = createPool({ ...sqlConfigOp, "dateStrings": false }) ok(true) }) servecolse: TS.BaseApi['servecolse'] = () => new Promise((ok, err) => { this.pool.end((error) => error ? err(error) : ok(true)) }) } const ccc = < Tables extends TS.Tables, Joins extends Record, Join extends 'inner' | 'left', JOINS extends { [T in keyof Tables]: readonly string[] } >(JOINS: JOINS, catchquery: FC, catchconfig: FC): { cache: { [T in keyof Tables]: Record }, catchquery: FC, catchconfig: FC } => { //const c: TS.BaseApi return { cache: new Base(JOINS).cache, catchquery, catchconfig } } // abstract class WebDemo< // Tables extends TS.Tables, // Joins extends Record, // Join extends 'inner' | 'left', // JOINS extends { [T in keyof Tables]: readonly string[] } // > extends Base implements TS.BaseCatch { // constructor(JOINS: JOINS, catchquery: FC, catchconfig: FC) { // super(JOINS) // } // api: TS.BaseApi // abstract catchquery: FC // abstract catchconfig: FC // // on = >(param: { fun: fun } & Parameters[0]) => { // // return this[param.fun](...param) // // .then((success: any) => ({ ...param, success })) // // .catch((catchop: TS.catchOp) => ({ ...param, ...catchop })) // // } // // abstract on: { [K in keyof Serve]: Serve[K] extends (args?: infer P) => Promise ? (param: { fun: K } & P) => Promise<{ fun: K, success: R } & P> : never }[keyof Serve] // }