UNPKG

multi-db-orm

Version:

CRUD , Backup , Restore and Migration library for multiple databases

253 lines (232 loc) 7.39 kB
const { MultiDbORM } = require("./multidb"); class MySQLDB extends MultiDbORM { mysql; pool; dataMap = { id: "VARCHAR(50) NOT NULL PRIMARY KEY", string: "VARCHAR(4000)", stringlarge: "TEXT", stringsmall: "VARCHAR(255)", number: "DOUBLE", boolean: "BOOL", array: "TEXT", object: "JSON", }; constructor(credentials) { super(); const mysql = require("mysql"); this.mysql = mysql; this.pool = mysql.createPool({ ...credentials, connectionLimit: credentials.connectionLimit || 10, host: credentials.host, port: credentials.port, user: credentials.username, password: credentials.password, database: credentials.database, waitForConnections: true, queueLimit: 0, connectTimeout: credentials.connectTimeout || 10000, acquireTimeout: credentials.acquireTimeout || 10000, timeout: credentials.timeout || 60000, }); this.db = this.pool; this.pool.on("connection", (connection) => { if (this.loglevel > 1) console.log("MySQLDB: New connection acquired"); }); this.pool.on("error", (err) => { if (this.loglevel > 0) console.error("MySQLDB: Pool error:", err); }); this.dbType = "mysql"; this.reqMade = 0; } async run(query) { var that = this; this.reqMade++; return new Promise(function (resolve, reject) { that.pool.query(query, function (err, results) { if (err) { reject(err); } else { resolve(results); } if (that.loglevel > 3) { console.log("Query ", query, " -> ", results); } }); }); } async get(modelname, filter, options) { this.metrics.get(modelname, filter, options); var where = ""; for (var key in filter) { where = where + `${key} = '${filter[key]}' AND `; } where = where + " 1 "; var sort = ""; if (options) { if (options.apply) { if (options.apply.ineq) { where = where + ` AND '${options.apply.field}' ${options.apply.ineq.op} '${options.apply.ineq.value}'`; } if (options.apply.sort) { sort = `ORDER BY ${options.apply.field} ${options.apply.sort}`; } } else if (options.sort) { sort = `ORDER BY`; for (let i = 0; i < options.sort.length; i++) { sort = sort + ` ${options.sort[i].field} ${options.sort[i].order}`; if (i < options.sort.length - 1) { sort = sort + " , "; } } } } let limit = ""; let offset = ""; if (options?.limit) { limit = `LIMIT ${options.limit}`; } if (options?.offset) { offset = `OFFSET ${options.offset}`; } var query = `SELECT * FROM ${modelname} WHERE ${where} ${sort} ${limit} ${offset};`; return (await this.run(query)) || []; } async getOne(modelname, filter) { this.metrics.getOne(modelname, filter); var where = ""; for (var key in filter) { where = where + `${key} = '${filter[key]}' AND `; } where = where + " 1 "; var query = `SELECT * FROM ${modelname} WHERE ${where} LIMIT 1;`; var row = await this.run(query); return row[0]; } async create(modelname, sampleObject) { this.sync.create(modelname, sampleObject); this.metrics.create(modelname, sampleObject); var cols = ""; for (var key in sampleObject) { var type; if (this.dataMap[sampleObject[key]]) { type = this.dataMap[sampleObject[key]]; } else { type = this.dataMap[typeof sampleObject[key]] || "TEXT"; if (typeof sampleObject[key] == "string") { if (sampleObject[key].length > 4000) { type = this.dataMap["stringlarge"]; } if (sampleObject[key].length <= 255) { type = this.dataMap["stringsmall"]; } } } if (key.toLowerCase().trim() === "id") { cols = cols + `${key} ${type} PRIMARY KEY NOT NULL UNIQUE,`; } else { cols = cols + `${key} ${type},`; } } cols = cols.substring(0, cols.length - 1); var query = `CREATE TABLE IF NOT EXISTS ${modelname} (${cols});`; try { return await this.run(query); } catch (err) { if (this.loglevel > 0) console.log(err); throw err; } } async insert(modelname, object) { this.sync.insert(modelname, object); this.metrics.insert(modelname, object); var cols = ""; var vals = ""; for (var key in object) { cols = cols + `${key},`; let val = object[key]; if (typeof val == "object") val = JSON.stringify(object[key]); val = this.pool.escape(val); if (typeof val == "undefined") vals = vals + `Null,`; else if (typeof val == "boolean") vals = vals + `${val},`; else vals = vals + `${val},`; } cols = cols.substring(0, cols.length - 1); vals = vals.substring(0, vals.length - 1); var query = `INSERT INTO ${modelname} (${cols}) VALUES(${vals});`; try { return await this.run(query); } catch (err) { if (err.code && err.code === "ER_NO_SUCH_TABLE") { await this.create(modelname, object); return await this.run(query); } else { throw err; } } } async update(modelname, filter, object) { this.sync.update(modelname, filter, object); this.metrics.update(modelname, filter, object); var where = ""; var vals = ""; for (var key in filter) { where = where + `${key} = '${filter[key]}' AND `; } for (var key in object) { let val = object[key]; if (typeof val == "object" && val != undefined && val != null) val = JSON.stringify(object[key]); val = this.pool.escape(val); if ( val == "undefined" || val == undefined || val == "null" || val == null ) vals = vals + `${key} = Null,`; else if (typeof val == "boolean") vals = vals + `${key} = ${val},`; else vals = vals + `${key} = ${val},`; } where = where + " 1 "; vals = vals.substring(0, vals.length - 1); var query = `UPDATE ${modelname} SET ${vals} WHERE ${where};`; try { return await this.run(query); } catch (e) { if (this.loglevel > 4) console.log("Error in update", e); throw e; } } async delete(modelname, filter) { this.sync.delete(modelname, filter); this.metrics.delete(modelname, filter); var where = ""; for (var key in filter) { where = where + `${key} = '${filter[key]}' AND `; } where = where + " 1 "; var query = `DELETE FROM ${modelname} WHERE ${where};`; return await this.run(query); } closePool() { return new Promise((res, rej) => { this.pool.end((err) => { if (err) { rej(err); if (this.loglevel > 1) console.error("Error closing connection pool:", err); } else { res(); if (this.loglevel > 1) console.log("MySQLDB: Connection pool closed"); } }); }); } } module.exports = { MySQLDB, };