tspace-mysql
Version:
Tspace MySQL is a promise-based ORM for Node.js, designed with modern TypeScript and providing type safety for schema databases.
998 lines • 37.6 kB
JavaScript
;
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.DB = void 0;
const sql_formatter_1 = require("sql-formatter");
const AbstractDB_1 = require("./Abstracts/AbstractDB");
const StateManager_1 = require("./StateManager");
const tools_1 = require("../tools");
const Pool_1 = __importStar(require("./Pool"));
/**
* The 'DB' class is a component of the database system
* @param {string?} table table name
* @example
* new DB('users').findMany().then(results => console.log(results))
*/
class DB extends AbstractDB_1.AbstractDB {
constructor(table) {
super();
this._initialDB();
if (table)
this.table(table);
}
/**
* The 'instance' method is used get instance.
* @override
* @static
* @returns {DB} instance of the DB
*/
static get instance() {
return new this();
}
/**
* The 'initialize' method is used to initialize the database,
* and check if it is connected properly.
*
* @returns {promise<void>}
*/
async initialize() {
await this.query(`${this.$constants("SELECT")} 1`);
return;
}
/**
* The 'initialize' method is used to initialize the database,
* and check if it is connected properly.
*
* @returns {promise<void>}
*/
static async initialize() {
return await new this().initialize();
}
/**
* This 'event' method ensures the pool is initialized before attaching
* the given callback to the specified pool event.
*
* @async
* @template TPoolEvent
* @param {TPoolEvent} event - The name of the pool event to listen for.
* @param {(data: any) => any} callback - A callback function invoked when the event is emitted.
* @returns {Promise<void>} A promise that resolves once the event listener is registered.
*/
async event(event, callback) {
await this.initialize();
if (Pool_1.default.instance == null)
return;
Pool_1.default.instance.on(event, callback);
return;
}
/**
*
* This 'event' method ensures the pool is initialized before attaching
* the given callback to the specified pool event.
*
* @async
* @template TPoolEvent
* @param {TPoolEvent} event - The name of the pool event to listen for.
* @param {(data: any) => any} callback - A callback function invoked when the event is emitted.
* @returns {Promise<void>} A promise that resolves once the event listener is registered.
*/
static async event(event, callback) {
return new this().event(event, callback);
}
/**
* The 'query' method is used to execute sql statement
*
* @param {string} sql
* @param {Record<string,any>} parameters
* @returns {promise<any[]>}
*/
async query(sql, parameters = {}) {
if (!Object.keys(parameters).length) {
return await this.rawQuery(sql);
}
let bindSql = sql;
for (const key in parameters) {
const parameter = parameters[key];
if (parameter === null) {
bindSql = bindSql.replace(`:${key}`, this.$constants("NULL"));
continue;
}
if (parameter === true || parameter === false) {
bindSql = bindSql.replace(`:${key}`, `'${parameter === true ? 1 : 0}'`);
continue;
}
bindSql = bindSql.replace(`:${key}`, Array.isArray(parameter)
? `(${parameter.map((p) => `'${this.escape(p)}'`).join(",")})`
: `'${this.escape(parameter)}'`);
}
return await this.rawQuery(bindSql);
}
/**
* The 'query' method is used to execute sql statement
*
* @param {string} sql
* @param {Record<string,any>} parameters
* @returns {promise<any[]>}
*/
static async query(sql, parameters = {}) {
return await new this().query(sql, parameters);
}
/**
* The 'from' method is used to define the from table name.
* @param {string} table table name
* @returns {this} this
*/
static from(table) {
return new this().from(table);
}
/**
* The 'table' method is used to define the table name.
* @param {string} table table name
* @returns {DB} DB
*/
static table(table) {
return new this().table(table);
}
/**
* The 'alias' method is used to set the table name.
*
* @param {string} sql raw sql from make a new alias for this table
* @param {string} alias alias name
* @returns {DB} DB
*/
static alias(sql, alias) {
return new this().alias(sql, alias);
}
/**
* The 'jsonObject' method is used to specify select data to JSON objects.
* @param {string} object table name
* @param {string} alias
* @returns {string} string
*/
jsonObject(object, alias) {
if (!Object.keys(object).length)
throw new Error("The method 'jsonObject' is not supported for empty object");
let maping = [];
for (const [key, value] of Object.entries(object)) {
if (/\./.test(value)) {
const [table, c] = value.split(".");
maping = [...maping, `'${key}'`, `\`${table}\`.\`${c}\``];
continue;
}
maping = [
...maping,
`'${key}'`,
`\`${this.getTableName()}\`.\`${value}\``,
];
}
return `${this.$constants("JSON_OBJECT")}(${maping.join(" , ")}) ${this.$constants("AS")} \`${alias}\``;
}
/**
* The 'jsonObject' method is used to specify select data to JSON objects.
* @static
* @param {string} object table name
* @param {string} alias
* @returns {string} string
*/
static jsonObject(object, alias) {
return new this().jsonObject(object, alias);
}
/**
* The 'JSONObject' method is used to specify select data to JSON objects.
* @param {string} object table name
* @param {string} alias
* @returns {string} string
*/
JSONObject(object, alias) {
return this.jsonObject(object, alias);
}
/**
* The 'JSONObject' method is used to specify select data to JSON objects.
* @static
* @param {string} object table name
* @param {string} alias
* @returns {string} string
*/
static JSONObject(object, alias) {
return new this().jsonObject(object, alias);
}
/**
* The 'constants' method is used to return constants with key or none in 'DB' or 'Model'.
* @param {string} key
* @returns {string | object} string || object
*/
constants(key) {
return this.$constants(key);
}
/**
* The 'constants' method is used to return constants with key or none in 'DB' or 'Model'.
* @static
* @param {string} key
* @returns {string | object} string || object
*/
static constants(key) {
return new this().constants(key);
}
/**
* cases query
* @param {arrayObject} cases array object {when , then }
* @param {string?} final else condition
* @returns {string} string
*/
caseUpdate(cases, final) {
if (!cases.length)
return [];
let query = [];
for (const c of cases) {
if (c.when == null)
throw new Error(`can't find when condition`);
if (c.then == null)
throw new Error(`can't find then condition`);
query = [
...query,
`${this.$constants("WHEN")} ${c.when} ${this.$constants("THEN")} ${c.then}`,
];
}
return [
this.$constants("RAW"),
this.$constants("CASE"),
query.join(" "),
final == null ? "" : `ELSE ${final}`,
this.$constants("END"),
].join(" ");
}
/**
* select by cases
* @static
* @param {arrayObject} cases array object {when , then }
* @param {string?} final else condition
* @returns {this}
*/
static caseUpdate(cases, final) {
return new this().caseUpdate(cases, final);
}
/**
* The 'generateUUID' methid is used to generate a universal unique identifier.
* @returns {string} string
*/
generateUUID() {
return this.$utils.generateUUID();
}
/**
* The 'generateUUID' methid is used to generate a universal unique identifier.
* @static
* @returns {string} string
*/
static generateUUID() {
return new this().generateUUID();
}
/**
* The 'snakeCase' methid is used to covert value to snakeCase pattern.
* @returns {string} string
*/
snakeCase(value) {
return this.$utils.snakeCase(value);
}
/**
* The 'snakeCase' methid is used to covert value to snake_case pattern.
* @returns {string} string
*/
static snakeCase(value) {
return new this().$utils.snakeCase(value);
}
/**
* The 'camelCase' methid is used to covert value to camelCase pattern.
* @returns {string} string
*/
camelCase(value) {
return this.$utils.camelCase(value);
}
/**
* The 'camelCase' methid is used to covert value to camelCase pattern.
* @returns {string} string
*/
static camelCase(value) {
return new this().$utils.camelCase(value);
}
/**
* The 'escape' methid is used to escaping SQL injections.
* @returns {string} string
*/
escape(value) {
return this.$utils.escape(value, true);
}
/**
* The 'escape' methid is used to escaping SQL injections.
* @returns {string} string
*/
static escape(value) {
return new this().escape(value);
}
/**
* The 'escapeXSS' methid is used to escaping XSS characters.
* @returns {string} string
*/
escapeXSS(value) {
return this.$utils.escapeXSS(value);
}
/**
* The 'escapeXSS' methid is used to escaping XSS characters.
* @returns {string} string
*/
static escapeXSS(value) {
return new this().escapeXSS(value);
}
/**
* The 'raw' methid is used to allow for raw sql queries to some method in 'DB' or 'Model'.
* @param {string} sql
* @returns {string} string
*/
raw(sql) {
return `${this.$constants("RAW")}${sql}`;
}
/**
* The 'raw' methid is used to allow for raw sql queries to some method in 'DB' or 'Model'.
* @static
* @param {string} sql
* @returns {string} string
*/
static raw(sql) {
return `${new this().raw(sql)}`;
}
/**
* The 'freeze' methid is used to freeze the column without any pattern.
*
* @param {string} column
* @returns {string} string
*/
freeze(column) {
return `${this.$constants("FREEZE")}${column}`;
}
/**
* The 'freeze' methid is used to freeze the column without any pattern.
*
* @static
* @param {string} column
* @returns {string} string
*/
static freeze(column) {
return new this().freeze(column);
}
/**
* The 'getConnection' method is used to get a pool connection.
* @param {Object} options options for connection database with credentials
* @property {string} option.driver
* @property {string} option.host
* @property {number} option.port
* @property {string} option.database
* @property {string} option.username
* @property {string} option.password
* @returns {Connection}
*/
async getConnection(options) {
if (options == null) {
const pool = await this.$pool.get();
return await pool.newConnection();
}
const { driver, host, port, database, username: user, password, ...others } = options;
const pool = new Pool_1.PoolConnection({
driver,
host,
port,
database,
user,
password,
...others,
});
return pool.connect();
}
/**
* The 'getConnection' method is used to get a pool connection.
* @param {Object} options options for connection database with credentials
* @property {string} option.driver
* @property {string} option.host
* @property {number} option.port
* @property {string} option.database
* @property {string} option.username
* @property {string} option.password
* @returns {Connection}
*/
static async getConnection(options) {
return new this().getConnection(options);
}
/**
* The 'beginTransaction' is a method used to initiate a database transaction within your application's code.
*
* A database transaction is a way to group multiple database operations (such as inserts, updates, or deletes) into a single unit of work.
*
* Transactions are typically used when you want to ensure that a series of database operations either all succeed or all fail together,
* ensuring data integrity.
* @param {object} options
* @property {number | undefined} options.primaryId
* @property {number | undefined} options.nodeId
* @returns {ConnectionTransaction} object - Connection for the transaction
* @type {object} connection
* @property {function} connection.query - execute query sql then release connection to pool
* @property {function} connection.startTransaction - start transaction of query
* @property {function} connection.commit - commit transaction of query
* @property {function} connection.rollback - rollback transaction of query
*/
async beginTransaction(options) {
if (this.$cluster) {
const cluster = new Pool_1.PoolConnection().clusterConnect();
const masters = cluster.masters;
if (!masters.length) {
throw new Error("No Master available in cluster");
}
const length = masters.length;
let selectedIndex = 0;
if (options?.nodeId != null) {
if (options.nodeId > length) {
throw new Error(`Invalid nodeId ${options.nodeId}. Cluster has only ${length} master node(s).`);
}
selectedIndex = options.nodeId - 1;
}
else if (options?.primaryId != null) {
selectedIndex = Math.round(options.primaryId % length);
}
const writer = masters[selectedIndex];
if (writer == null) {
throw new Error("No Master available in cluster");
}
return await writer.connection();
}
const pool = new Pool_1.PoolConnection().connect();
return await pool.connection();
}
/**
* The 'beginTransaction' is a method used to initiate a database transaction within your application's code.
*
* A database transaction is a way to group multiple database operations (such as inserts, updates, or deletes) into a single unit of work.
*
* Transactions are typically used when you want to ensure that a series of database operations either all succeed or all fail together,
* ensuring data integrity.
* @param {object} options
* @property {number | undefined} options.primaryId
* @property {number | undefined} options.nodeId
* @static
* @returns {ConnectionTransaction} object - Connection for the transaction
* @type {object} connection
* @property {function} connection.query - execute query sql then release connection to pool
* @property {function} connection.startTransaction - start transaction of query
* @property {function} connection.commit - commit transaction of query
* @property {function} connection.rollback - rollback transaction of query
*/
static async beginTransaction(options) {
return await new this().beginTransaction(options);
}
/**
* The 'removeProperties' method is used to removed some properties.
*
* @param {Array | Record} data
* @param {string[]} propertiesToRemoves
* @returns {Array | Record} this
*/
removeProperties(data, propertiesToRemoves) {
const setNestedProperty = (obj, path, value) => {
const segments = path.split(".");
let currentObj = obj;
for (let i = 0; i < segments.length - 1; i++) {
const segment = segments[i];
if (!currentObj.hasOwnProperty(segment)) {
currentObj[segment] = {};
}
currentObj = currentObj[segment];
}
const lastSegment = segments[segments.length - 1];
currentObj[lastSegment] = value;
};
const remove = (obj, propertiesToRemoves) => {
const temp = JSON.parse(JSON.stringify(obj));
for (const property of propertiesToRemoves) {
if (property == null)
continue;
const properties = property.split(".");
let current = temp;
let afterProp = "";
const props = [];
for (let i = 0; i < properties.length - 1; i++) {
const prop = properties[i];
if (current[prop] == null)
continue;
props.push(prop);
if (typeof current[prop] === "object" && current[prop] != null) {
current = current[prop];
afterProp = prop;
continue;
}
delete current[prop];
afterProp = prop;
}
const lastProp = properties[properties.length - 1];
if (Array.isArray(current)) {
setNestedProperty(temp, props.join("."), this.removeProperties(current, [afterProp, lastProp]));
continue;
}
if (current[lastProp] == null)
continue;
delete current[lastProp];
}
return temp;
};
if (Array.isArray(data)) {
return data.map((obj) => remove(obj, propertiesToRemoves));
}
return remove(data, propertiesToRemoves);
}
/**
* The 'removeProperties' method is used to removed some properties.
*
* @param {Array | Record} data
* @param {string[]} propertiesToRemoves
* @returns {Array | Record} this
*/
static removeProperties(data, propertiesToRemoves) {
return new this().removeProperties(data, propertiesToRemoves);
}
/**
*
* This 'backup' method is used to backup database intro new database same server or to another server
* @type {Object} backup
* @property {string} backup.database clone current 'db' in connection to this database
* @type {object?} backup.to
* @property {string} backup.to.host
* @property {number} backup.to.port
* @property {string} backup.to.username
* @property {string} backup.to.password
* @returns {Promise<void>}
*/
async backup({ database, to }) {
const tables = await this.getTables();
const backup = await this._backup({ tables, database, to });
const creating = async ({ table, values, }) => {
try {
await table();
await values();
}
catch (e) { }
};
await Promise.all(backup.map((b) => creating({ table: b.table, values: b.values })));
return;
}
/**
*
* This 'backup' method is used to backup database intro new database same server or to another server
* @type {Object} backup
* @property {string} backup.database clone current 'db' in connection to this database
* @type {object?} backup.to
* @property {string} backup.to.host
* @property {number} backup.to.port
* @property {string} backup.to.username
* @property {string} backup.to.password
* @returns {Promise<void>}
*/
static async backup({ database, to }) {
return new this().backup({ database, to });
}
/**
*
* This 'backupToFile' method is used to backup database intro new ${file}.sql
* @type {Object} backup
* @property {string} backup.database
* @property {string} backup.filePath
* @type {object?} backup.connection
* @property {string} backup.connection.host
* @property {number} backup.connection.port
* @property {number} backup.connection.database
* @property {string} backup.connection.username
* @property {string} backup.connection.password
* @returns {Promise<void>}
*/
async backupToFile({ filePath, database = `dump_${+new Date()}`, connection, }) {
await this.$utils.wait(1000 * 5);
const tables = await this.getTables();
const sqlFormatted = (sql) => {
const statements = sql
.split(';')
.map(s => s.trim())
.filter(Boolean);
const formattedStatements = statements.map(stmt => {
if (stmt.includes('(')) {
const firstParen = stmt.indexOf('(');
const lastParen = stmt.lastIndexOf(')');
if (firstParen === -1 || lastParen === -1)
return stmt + ';';
const prefix = stmt.slice(0, firstParen).trim();
let columnsPart = stmt.slice(firstParen + 1, lastParen).trim();
const colArray = [];
let parenCount = 0;
let start = 0;
for (let i = 0; i < columnsPart.length; i++) {
const char = columnsPart[i];
if (char === '(')
parenCount++;
if (char === ')')
parenCount--;
if (char === ',' && parenCount === 0) {
colArray.push(columnsPart.slice(start, i).trim());
start = i + 1;
}
}
colArray.push(columnsPart.slice(start).trim());
const seen = new Set();
const uniqueColumns = colArray.filter(col => {
const colNameMatch = col.match(/"([\w]+)"/) || col.match(/([\w]+)/);
const colName = colNameMatch ? colNameMatch[1] : col;
if (seen.has(colName))
return false;
seen.add(colName);
return true;
});
const formattedColumns = uniqueColumns.map(c => ' ' + c).join(',\n');
return `${prefix} (\n${formattedColumns}\n)`;
}
else {
return stmt;
}
});
return formattedStatements.join(';\n\n');
};
const backup = (await this._backupToString({ tables, database })).map((b) => {
return {
table: [
`\n--`,
`-- Table structure for table '${b.name}'`,
`--\n`,
`${sqlFormatted(b.table())}`,
].join("\n") + ";",
values: b.values().length
? [
`\n--`,
`-- Dumping data for table '${b.name}'`,
`--\n`,
`${b.values().map(v => `${v}`).join(",\n")}`,
].join("\n")
: "",
};
});
if (connection != null && Object.keys(connection)?.length)
this.connection(connection);
let sql = [
`--`,
`-- tspace-mysql SQL Dump`,
`-- https://www.npmjs.com/package/tspace-mysql`,
`--`,
`-- Host: mysql-db`,
`-- Generation Time: ${new Date()}\n`,
`SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";`,
`START TRANSACTION;`,
`--`,
`-- Database: '${database}'`,
`--\n`,
`${this.$constants("CREATE_DATABASE_NOT_EXISTS")} ${database};`,
`USE ${database};`,
`-- --------------------------------------------------------`,
];
for (const b of backup) {
sql = [...sql, b.table];
if (b.values) {
sql = [...sql, b.values];
}
}
tools_1.Tool.fs.writeFileSync(filePath, [...sql, "COMMIT;"].join("\n"));
return;
}
/**
*
* This 'backupToFile' method is used to backup database intro new ${file}.sql
* @type {Object} backup
* @property {string} backup.database
* @property {string} backup.filePath
* @type {object?} backup.connection
* @property {string} backup.connection.host
* @property {number} backup.connection.port
* @property {number} backup.connection.database
* @property {string} backup.connection.username
* @property {string} backup.connection.password
* @returns {Promise<void>}
*/
static async backupToFile({ filePath, database, connection, }) {
return new this().backupToFile({ filePath, database, connection });
}
/**
*
* This 'backupSchemaToFile' method is used to backup database intro new ${file}.sql
* @type {Object} backup
* @property {string} backup.database
* @property {string} backup.filePath
* @type {object?} backup.connection
* @property {string} backup.connection.host
* @property {number} backup.connection.port
* @property {number} backup.connection.database
* @property {string} backup.connection.username
* @property {string} backup.connection.password
* @returns {Promise<void>}
*/
async backupSchemaToFile({ filePath, database = `dump_${+new Date()}`, connection, }) {
if (connection != null && Object.keys(connection)?.length)
this.connection(connection);
await this.$utils.wait(1000 * 3);
const tables = await this.getTables();
const backup = (await this._backupToString({ tables, database })).map((b) => {
return {
table: (0, sql_formatter_1.format)(b.table(), {
language: "spark",
tabWidth: 2,
linesBetweenQueries: 1,
}) + "\n",
};
});
let sql = [
`SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";`,
`START TRANSACTION;`,
`SET time_zone = "+00:00";`,
`${this.$constants("CREATE_DATABASE_NOT_EXISTS")} \`${database}\`;`,
`USE \`${database}\`;`,
];
for (const b of backup)
sql = [...sql, b.table];
tools_1.Tool.fs.writeFileSync(filePath, [...sql, "COMMIT;"].join("\n"));
return;
}
/**
*
* This 'backupSchemaToFile' method is used to backup database intro new ${file}.sql
*
* @type {Object} backup
* @property {string} backup.database
* @property {string} backup.filePath
* @type {object?} backup.connection
* @property {string} backup.connection.host
* @property {number} backup.connection.port
* @property {number} backup.connection.database
* @property {string} backup.connection.username
* @property {string} backup.connection.password
* @returns {Promise<void>}
*/
static async backupSchemaToFile({ filePath, database, connection, }) {
return new this().backupSchemaToFile({ filePath, database, connection });
}
/**
*
* This 'backupTableToFile' method is used to backup database intro new ${file}.sql
*
* @type {Object} backup
* @property {string} backup.database
* @property {string} backup.filePath
* @type {object?} backup.connection
* @property {string} backup.connection.host
* @property {number} backup.connection.port
* @property {number} backup.connection.database
* @property {string} backup.connection.username
* @property {string} backup.connection.password
* @returns {Promise<void>}
*/
async backupTableToFile({ filePath, table, connection, }) {
if (connection != null && Object.keys(connection)?.length)
this.connection(connection);
/**
*
* wait for the connection to new db connected
*/
await this.$utils.wait(1000 * 5);
const schemas = await this.showSchema(table);
const createTableSQL = [
`${this.$constants("CREATE_TABLE_NOT_EXISTS")}`,
`\`${table}\``,
`(${schemas.join(",")})`,
`${this.$constants("ENGINE")};`,
];
const values = await this.showValues(table);
let valueSQL = [];
if (values.length) {
const columns = await this.showColumns(table);
valueSQL = [
`${this.$constants("INSERT")}`,
`\`${table}\``,
`(${columns.map((column) => `\`${column}\``).join(",")})`,
`${this.$constants("VALUES")} ${values.join(",")};`,
];
}
const sql = [
(0, sql_formatter_1.format)(createTableSQL.join(" "), {
language: "mysql",
tabWidth: 2,
linesBetweenQueries: 1,
}) + "\n",
valueSQL.join(" "),
];
tools_1.Tool.fs.writeFileSync(filePath, [...sql, "COMMIT;"].join("\n"));
return;
}
/**
*
* This 'backupTableSchemaToFile' method is used to backup database intro new ${file}.sql
* @type {Object} backup
* @property {string} backup.table
* @property {string} backup.filePath
* @type {object?} backup.connection
* @property {string} backup.connection.host
* @property {number} backup.connection.port
* @property {number} backup.connection.database
* @property {string} backup.connection.username
* @property {string} backup.connection.password
* @returns {Promise<void>}
*/
static async backupTableToFile({ filePath, table, connection, }) {
return new this().backupTableToFile({ filePath, table, connection });
}
/**
*
* This 'backupTableSchemaToFile' method is used to backup database intro new ${file}.sql
* @type {Object} backup
* @property {string} backup.database
* @property {string} backup.filePath
* @type {object?} backup.connection
* @property {string} backup.connection.host
* @property {number} backup.connection.port
* @property {number} backup.connection.database
* @property {string} backup.connection.username
* @property {string} backup.connection.password
* @returns {Promise<void>}
*/
async backupTableSchemaToFile({ filePath, table, connection, }) {
const schemas = await this.showSchema(table);
const createTableSQL = [
`${this.$constants("CREATE_TABLE_NOT_EXISTS")}`,
`\`${table}\``,
`(${schemas.join(",")})`,
`${this.$constants("ENGINE")};`,
];
const sql = [createTableSQL.join(" ")];
if (connection != null && Object.keys(connection)?.length)
this.connection(connection);
await this.$utils.wait(1000 * 5);
tools_1.Tool.fs.writeFileSync(filePath, (0, sql_formatter_1.format)(sql.join("\n"), {
language: "spark",
tabWidth: 2,
linesBetweenQueries: 1,
}));
return;
}
/**
*
* This 'backupTableSchemaToFile' method is used to backup database intro new ${file}.sql
* @type {Object} backup
* @property {string} backup.table
* @property {string} backup.filePath
* @type {object?} backup.connection
* @property {string} backup.connection.host
* @property {number} backup.connection.port
* @property {number} backup.connection.database
* @property {string} backup.connection.username
* @property {string} backup.connection.password
* @returns {Promise<void>}
*/
static async backupTableSchemaToFile({ filePath, table, connection, }) {
return new this().backupTableSchemaToFile({ filePath, table, connection });
}
async _backup({ tables, database, to, }) {
const backup = [];
const conn = await new DB().getConnection({ ...(to ?? this.$credentials) });
const db = await new DB()
.bind(conn)
.query(this._queryBuilder().getDatabase(database));
if (Object.values(db[0] ?? []).length) {
throw new Error(`This database : '${database}' is already exists`);
}
await new DB()
.bind(conn)
.query(`${this.$constants("CREATE_DATABASE")} \`${database}\``);
const connWithDatabase = await new DB().getConnection({
...(to ?? this.$credentials),
database,
});
for (const table of tables) {
const schema = await new DB()
.debug(this.$state.get("DEBUG"))
.showSchema(table);
const values = await new DB(table).debug(this.$state.get("DEBUG")).get();
backup.push({
name: table == null ? "" : table,
table: async () => {
await new DB()
.debug(this.$state.get("DEBUG"))
.bind(connWithDatabase)
.query(this._queryBuilder().createTable({ database, table, schema }));
return;
},
values: async () => {
if (!values.length)
return;
const chunked = this.$utils.chunkArray([...values], 1000);
const promises = [];
for (const data of chunked) {
promises.push(() => {
return new DB(table)
.debug(this.$state.get("DEBUG"))
.createMultiple([...data])
.bind(connWithDatabase)
.void()
.save();
});
}
await Promise.all(promises.map((v) => v()));
return;
},
});
}
return backup;
}
async _backupToString({ tables, database, }) {
const backup = [];
for (const table of tables) {
const schema = await this.showSchema(table);
const values = await this.table(table).get();
// const values :any[] = []
backup.push({
name: table == null ? "" : table,
table: () => {
return this._queryBuilder().createTable({ database, table, schema });
},
values: () => {
if (!values.length)
return [];
const chunked = this.$utils.chunkArray([...values], values.length > 500 ? 500 : 10);
const str = [];
for (const data of chunked) {
const sql = this.table(table)
.createMultiple([...data])
.toString();
str.push(sql);
}
return str;
},
});
}
return backup;
}
_initialDB() {
this.$state = new StateManager_1.StateManager("db");
return this;
}
}
exports.DB = DB;
exports.default = DB;
//# sourceMappingURL=DB.js.map