tspace-mysql
Version:
Tspace MySQL is a promise-based ORM for Node.js, designed with modern TypeScript and providing type safety for schema databases.
305 lines • 11 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.Pool = exports.loadOptionsEnv = exports.PoolConnection = void 0;
const tools_1 = require("../tools");
const MysqlDriver_1 = require("./Driver/mysql/MysqlDriver");
const PostgresDriver_1 = require("./Driver/postgres/PostgresDriver");
const MariadbDriver_1 = require("./Driver/mariadb/MariadbDriver");
const config_1 = __importStar(require("../config"));
Object.defineProperty(exports, "loadOptionsEnv", { enumerable: true, get: function () { return config_1.loadOptionsEnv; } });
class PoolConnection {
OPTIONS = this._loadOptions();
POOL = null;
CLUSTER = null;
get instance() {
return this.POOL;
}
/**
*
* @Init a options connection pool
*/
constructor(options) {
if (options) {
this.OPTIONS = new Map(Object.entries({
...Object.fromEntries(this.OPTIONS),
...JSON.parse(JSON.stringify(options)),
}));
}
}
connect(configs) {
if (this.POOL != null) {
return this.POOL;
}
const options = configs ?? Object.fromEntries(this.OPTIONS);
switch (this._driver()) {
case "mysql":
case "mysql2": {
this.POOL = new MysqlDriver_1.MysqlDriver(options).connect();
break;
}
case "pg":
case "postgres": {
this.POOL = new PostgresDriver_1.PostgresDriver(options).connect();
break;
}
case 'mariadb': {
this.POOL = new MariadbDriver_1.MariadbDriver(options).connect();
break;
}
default:
throw new Error("No default driver specified");
}
return this.POOL;
}
disconnect() {
const options = Object.fromEntries(this.OPTIONS);
switch (this._driver()) {
case "mysql":
case "mysql2": {
return new MysqlDriver_1.MysqlDriver(options).disconnect(this.POOL);
}
case 'pg':
case 'postgres': {
return new PostgresDriver_1.PostgresDriver(options).disconnect(this.POOL);
}
case 'mariadb': {
return new MariadbDriver_1.MariadbDriver(options).disconnect(this.POOL);
}
default:
throw new Error("No default driver specified");
}
}
clusterConnect() {
if (this.CLUSTER != null) {
return this.CLUSTER;
}
const options = Object.fromEntries(this.OPTIONS);
const parseList = (value) => String(value).split(',').map(v => v.trim());
const getValue = (arr, index) => arr[index] != null ? arr[index] : arr[arr.length - 1];
const hostList = parseList(options.host);
const hosts = [];
const types = [];
hostList.forEach((h, i) => {
let type = i === 0 ? 'master' : 'slave';
let host = h;
if (h.includes('@')) {
const [_t, _h] = h.split('@');
type = _t === 'master' ? 'master' : 'slave';
host = _h;
}
hosts.push(host);
types.push(type);
});
const usernames = parseList(options.user);
const passwords = parseList(options.password);
const ports = parseList(options.port).map(v => +v);
const writerOptions = hosts
.map((host, i) => {
if (types[i] !== 'master')
return null;
return {
host,
port: getValue(ports, i),
username: getValue(usernames, i),
password: getValue(passwords, i)
};
})
.filter(Boolean);
const writers = writerOptions.map((opt, i) => {
return {
pool: {
type: 'master',
node: +i + 1,
host: opt.host,
port: opt.port,
username: opt.username
},
...new PoolConnection().connect({
...options,
...opt
})
};
});
const readerOptions = hosts
.map((host, i) => {
if (types[i] !== 'slave')
return null;
return {
host,
port: getValue(ports, i),
username: getValue(usernames, i),
password: getValue(passwords, i)
};
})
.filter(Boolean);
const readers = readerOptions.map((opt, i) => {
return {
pool: {
type: 'slave',
node: +i + 1,
host: opt.host,
port: opt.port,
username: opt.username
},
...new PoolConnection().connect({
...options,
...opt
})
};
});
if (!writers.length) {
throw new Error('No master nodes found. Please verify your cluster config.');
}
if (!readers.length) {
throw new Error('No slave nodes found. Please verify your cluster config.');
}
this.CLUSTER = {
masters: writers,
slaves: readers
};
return this.CLUSTER;
}
_defaultOptions() {
return new Map(Object.entries({
connectionLimit: Number(config_1.default.CONNECTION_LIMIT),
dateStrings: Boolean(config_1.default.DATE_STRINGS),
host: String(config_1.default.HOST),
port: Number(config_1.default.PORT),
database: String(config_1.default.DATABASE),
user: String(config_1.default.USERNAME),
password: String(config_1.default.PASSWORD),
// ------------------ custom ----------------------------
driver: String(config_1.default.DRIVER ?? "mysql2"),
cluster: Boolean(config_1.default.CLUSTER ?? false)
}));
}
_loadOptions() {
try {
/**
* @source data
* source db {
* host = localhost
* port = 3306
* database = npm
* user = root
* password =
* connectionLimit =
* dateStrings =
* connectTimeout =
* waitForConnections =
* queueLimit =
* charset =
* }
*/
const dbOptionsPath = tools_1.Tool.path.join(tools_1.Tool.path.resolve(), "db.tspace");
const dbOptionsExists = tools_1.Tool.fs.existsSync(dbOptionsPath);
if (!dbOptionsExists)
return this._defaultOptions();
const dbOptions = tools_1.Tool.fs.readFileSync(dbOptionsPath, "utf8");
const options = this._convertStringToObject(dbOptions);
if (options == null)
return this._defaultOptions();
return new Map(Object.entries(options));
}
catch (e) {
return this._defaultOptions();
}
}
_convertStringToObject(str, target = "db") {
if (str.toLocaleLowerCase().includes("#ignore"))
return null;
str = str.trim();
const sources = str.split("\n\n");
if (!sources.length)
return null;
const lines = sources[0].split("\r\n");
if (!lines.length)
return null;
const sourceObj = {};
let targetKey = "";
for (const line of lines) {
let [key, value] = line.split("=");
const sourceKey = key.match(/source\s+(\w+)/);
const sourceKeyClose = key.match(/}/g);
if (sourceKey != null) {
targetKey = sourceKey[1];
continue;
}
if (sourceKeyClose != null && sourceKeyClose.length) {
targetKey = "";
continue;
}
if (key == null || value == null)
continue;
key = key.trim();
value = value.trim();
if (!sourceObj.hasOwnProperty(targetKey))
sourceObj[targetKey] = {};
sourceObj[targetKey][key] = value;
}
return this._covertKeyTypeToCorrectType(sourceObj[target]) || null;
}
_covertKeyTypeToCorrectType(data) {
for (const [key, value] of Object.entries(data)) {
if (value == null)
continue;
if (typeof value === "string" &&
["true", "false"].some((v) => value.toLowerCase() === v)) {
data[key] = JSON.parse(value.toLowerCase());
continue;
}
if (/^[0-9]+$/.test(value))
data[key] = +value;
}
return data;
}
_driver() {
return String(this.OPTIONS.get("driver") ?? "mysql2");
}
}
exports.PoolConnection = PoolConnection;
/**
*
* Connection to database when service is started
*
* @returns {Connection} Connection
* @property {Function} Connection.query
* @property {Function} Connection.connection
*/
const pool = new PoolConnection();
exports.Pool = pool;
exports.default = pool;
//# sourceMappingURL=Pool.js.map