UNPKG

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
"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