Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: mysql client class #10

Merged
merged 4 commits into from
Dec 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -253,3 +253,15 @@ export declare class Builder {
values: any[];
constructor(options: QueryOperatorOptions);
}

export declare class MySQLClient extends QueryHandler {
constructor(options?: ConnectionOptions, name?: string | null | undefined);

existDatabase(database?: string): Promise<boolean>;

existTable(database: string, table: string): Promise<boolean>;

exexQuery(query: Query, operator: OperatorType): Promise<QueryResult>;

close(): Promise<void>;
}
10 changes: 8 additions & 2 deletions src/builder.js
Original file line number Diff line number Diff line change
Expand Up @@ -149,10 +149,16 @@ class Builder {
throw new Error('At least one table is required');
}
return tables.map((t) => {
let name = t.tableName.split('.').map((n) => {
if (n[0] === '`' && n[n.length - 1] === '`') {
return n;
}
return `\`${n}\``;
}).join('.');
if (t.alias) {
return `\`${t.tableName}\` AS \`${t.alias}\``;
return `${name} AS \`${t.alias}\``;
}
return `\`${t.tableName}\``;
return name;
}).join(' , ');
}

Expand Down
61 changes: 57 additions & 4 deletions src/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

const mysql = require('mysql2');
const mysqlPromise = require('mysql2/promise');
const { validate } = require('./utils');
const { _validate } = require('./utils');
const { QueryHandler, Query } = require('./operator');
const { _query } = require('./utils');

const clients = {};

Expand All @@ -12,7 +14,7 @@ const clients = {};
* @returns {mysql.Connection}
*/
const createClient = (options, name = null) => {
validate(options, {
_validate(options, {
host: 'required|string',
user: 'required|string',
password: 'required|string',
Expand All @@ -35,7 +37,7 @@ const createClient = (options, name = null) => {
* @returns {mysqlPromise.Connection}
*/
const createPromiseClient = async (options, name = null) => {
validate(options, {
_validate(options, {
host: 'required|string',
user: 'required|string',
password: 'required|string',
Expand All @@ -57,7 +59,7 @@ const createPromiseClient = async (options, name = null) => {
* @returns {mysql.Pool}
*/
const createPool = (options, name = null) => {
validate(options, {
_validate(options, {
host: 'required|string',
user: 'required|string',
password: 'required|string',
Expand Down Expand Up @@ -89,7 +91,58 @@ const getClient = (name) => {
return clients[name];
};

class MySQLClient extends QueryHandler {

/**
* @param {mysql.ConnectionOptions} options
* @param {*} name
*/
constructor(options, name = 'default') {
const conn = createClient(options, name);
super(conn);
}

async existTable(database, table) {
const c = await this.table('information_schema.TABLES')
.where('TABLE_SCHEMA', database)
.where('TABLE_NAME', table)
.count();
return !!c;
}

async existDatabase(database) {
const c = await this.table('information_schema.SCHEMATA')
.where('SCHEMA_NAME', database)
.count();
return !!c;
}

/**
* @param {import('./operator').Query} query
*/
async exexQuery(query, operator = null) {
if (query instanceof Query) {
query.options.operator = operator;
return await _query(this.conn, query.options);
}
}

async close() {
return new Promise((resolve, reject) => {
this.conn.end((err) => {
if (err) {
reject(err);
return;
}
resolve();
});
});
}
}

module.exports = {
MySQLClient,

getClient,
createPool,
createClient,
Expand Down
50 changes: 10 additions & 40 deletions src/operator.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,42 +3,7 @@
const { Builder } = require('./builder');
const Query = require('./query');
const Hook = require('./hook');

const query = async (conn, options, opt = null) => {
switch (options.driver) {
case 'mysql': {
if (opt === null) {
const builder = new Builder(options);
opt = {
sql: builder.sql,
values: builder.values || [],
};
}
return new Promise((resolve, reject) => {
if (options.transaction) {
conn.execute(opt)
.then((res) => resolve(res))
.catch((err) => reject(err));
} else {
conn.query(opt, (err, result) => {
if (err) {
reject(err);
} else {
resolve(result);
}
});
}
});
}
default: {
const promise = options.query_handler(conn, options, opt);
if (!(promise instanceof Promise)) {
throw new Error('query_handler must return a promise');
}
return promise;
}
}
};
const { _query } = require('./utils');

class QueryOperator extends Query {
/**
Expand Down Expand Up @@ -77,17 +42,17 @@ class QueryOperator extends Query {
try {
switch (this.options.operator) {
case 'find': {
const tmp = await query(this.conn, this.options);
const tmp = await _query(this.conn, this.options);
res = tmp[0];
break;
}
case 'count': {
const [tmp] = await query(this.conn, this.options);
const [tmp] = await _query(this.conn, this.options);
res = tmp.count;
break;
}
default:
res = await query(this.conn, this.options);
res = await _query(this.conn, this.options);
}
Hook.listen({ label: 'post', table: from, opt: this.options.operator }, this.options, res);
} catch (err) {
Expand Down Expand Up @@ -143,11 +108,16 @@ class QueryHandler {
this.options = options;
}

/**
*
* @param {import('mysql2').QueryOptions} opt
* @returns
*/
async query(opt) {
if (!opt) {
throw new Error('opt is required');
}
return await query(this.conn, this.options, opt);
return await _query(this.conn, this.options, opt);
}

table(table, alias = null) {
Expand Down
42 changes: 40 additions & 2 deletions src/utils.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
'use strict';

const Validator = require('validatorjs');
const { Builder } = require('./builder');

const validate = (obj, rules) => {
const _validate = (obj, rules) => {
let validation = new Validator(obj, rules);
validation.check();
if (validation.fails()) {
Expand All @@ -12,6 +13,43 @@ const validate = (obj, rules) => {
}
};

const _query = async (conn, options, opt = null) => {
switch (options.driver) {
case 'mysql': {
if (opt === null) {
const builder = new Builder(options);
opt = {
sql: builder.sql,
values: builder.values || [],
};
}
return new Promise((resolve, reject) => {
if (options.transaction) {
conn.execute(opt)
.then((res) => resolve(res))
.catch((err) => reject(err));
} else {
conn.query(opt, (err, result) => {
if (err) {
reject(err);
} else {
resolve(result);
}
});
}
});
}
default: {
const promise = options.query_handler(conn, options, opt);
if (!(promise instanceof Promise)) {
throw new Error('query_handler must return a promise');
}
return promise;
}
}
};

module.exports = {
validate
_validate,
_query
};