UNPKG

@dbcube/schema-builder

Version:

The DBCube Query Builder is a lightweight, flexible, and fluent library for building queries across multiple database engines, including MySQL, PostgreSQL, SQLite, and MongoDB, using JavaScript/Node.js. Its agnostic design allows you to generate data man

375 lines (370 loc) 13.4 kB
"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/index.ts var index_exports = {}; __export(index_exports, { Schema: () => Schema, default: () => index_default }); module.exports = __toCommonJS(index_exports); // src/lib/Schema.ts var import_fs = __toESM(require("fs")); var import_core = require("@dbcube/core"); var import_path = __toESM(require("path")); // src/lib/FileUtils.ts var fs = __toESM(require("fs")); var path = __toESM(require("path")); var FileUtils = class { /** * Verifica si un archivo existe (asincrónico). * @param filePath - Ruta del archivo. * @returns True si el archivo existe, false si no. */ static async fileExists(filePath) { return new Promise((resolve2) => { fs.access(path.resolve(filePath), fs.constants.F_OK, (err) => { resolve2(!err); }); }); } /** * Verifica si un archivo existe (sincrónico). * @param filePath - Ruta del archivo. * @returns True si el archivo existe, false si no. */ static fileExistsSync(filePath) { try { fs.accessSync(path.resolve(filePath), fs.constants.F_OK); return true; } catch { return false; } } static extractDatabaseName(input) { const match = input.match(/@database\(["']?([\w-]+)["']?\)/); return match ? match[1] : null; } /** * Lee recursivamente archivos que terminan en un sufijo dado y los ordena numéricamente. * @param dir - Directorio base (relativo o absoluto). * @param suffix - Sufijo de archivo (como 'table.cube'). * @returns Rutas absolutas de los archivos encontrados y ordenados. */ static getCubeFilesRecursively(dir, suffix) { const baseDir = path.resolve(dir); const cubeFiles = []; function recurse(currentDir) { const entries = fs.readdirSync(currentDir, { withFileTypes: true }); for (const entry of entries) { const fullPath = path.join(currentDir, entry.name); if (entry.isDirectory()) { recurse(fullPath); } else if (entry.isFile() && entry.name.endsWith(suffix)) { cubeFiles.push(fullPath); } } } recurse(baseDir); cubeFiles.sort((a, b) => { const aNum = parseInt(path.basename(a)); const bNum = parseInt(path.basename(b)); return (isNaN(aNum) ? 0 : aNum) - (isNaN(bNum) ? 0 : bNum); }); return cubeFiles; } }; var FileUtils_default = FileUtils; // src/lib/Schema.ts var Schema = class { name; engine; constructor(name) { this.name = name; const engine = new import_core.Engine(name); this.engine = engine; } async createDatabase() { const rootPath = import_path.default.resolve(process.cwd()); const response = await this.engine.run("schema_engine", [ "--action", "create_database", "--path", rootPath ]); if (response.status != 200) { returnFormattedError(response.status, response.message); } return response.data; } async refreshTables() { const cubesDir = import_path.default.join(process.cwd(), "dbcube", "cubes"); if (!import_fs.default.existsSync(cubesDir)) { throw new Error("\u274C The cubes folder does not exist"); } const cubeFiles = FileUtils_default.getCubeFilesRecursively("dbcube", "table.cube"); if (cubeFiles.length === 0) { throw new Error("\u274C There are no cubes to execute"); } else { for (const file of cubeFiles) { const filePath = import_path.default.isAbsolute(file) ? file : import_path.default.join(cubesDir, file); const stats = import_fs.default.statSync(filePath); if (stats.isFile()) { const dml = await this.engine.run("schema_engine", [ "--action", "parse_table", "--mode", "refresh", "--schema-path", filePath ]); if (dml.status != 200) { returnFormattedError(dml.status, dml.message); } const parseJson = JSON.stringify(dml.data.actions).replace(/[\r\n\t]/g, "").replace(/\\[rnt]/g, "").replace(/\s{2,}/g, " "); const queries = await this.engine.run("schema_engine", [ "--action", "generate", "--mode", "refresh", "--dml", parseJson ]); if (queries.status != 200) { returnFormattedError(queries.status, queries.message); } delete queries.data.database_type; const parseJsonQueries = JSON.stringify(queries.data); const response = await this.engine.run("schema_engine", [ "--action", "execute", "--mode", "refresh", "--dml", parseJsonQueries ]); if (response.status != 200) { returnFormattedError(response.status, response.message); } const createQuery = queries.data.regular_queries.filter((q) => q.includes("CREATE"))[0]; await import_core.TableProcessor.saveQuery(dml.data.table, dml.data.database, createQuery); return response.data; } } } return null; } async freshTables() { const cubesDir = import_path.default.join(process.cwd(), "dbcube", "cubes"); if (!import_fs.default.existsSync(cubesDir)) { throw new Error("\u274C The cubes folder does not exist"); } const cubeFiles = FileUtils_default.getCubeFilesRecursively("dbcube", "table.cube"); if (cubeFiles.length === 0) { throw new Error("\u274C There are no cubes to execute"); } else { for (const file of cubeFiles) { const filePath = import_path.default.isAbsolute(file) ? file : import_path.default.join(cubesDir, file); const stats = import_fs.default.statSync(filePath); if (stats.isFile()) { const dml = await this.engine.run("schema_engine", [ "--action", "parse_table", "--schema-path", filePath, "--mode", "fresh" ]); if (dml.status != 200) { returnFormattedError(dml.status, dml.message); } const parseJson = JSON.stringify(dml.data.actions).replace(/[\r\n\t]/g, "").replace(/\\[rnt]/g, "").replace(/\s{2,}/g, " "); const queries = await this.engine.run("schema_engine", [ "--action", "generate", "--dml", parseJson ]); if (queries.status != 200) { returnFormattedError(queries.status, queries.message); } delete queries.data._type; const createQuery = queries.data.regular_queries.filter((q) => q.includes("CREATE"))[0]; if (queries.data.regular_queries.length > 0) { const nowQueries = await import_core.TableProcessor.generateAlterQueries(queries.data.regular_queries[0], dml.data.motor, dml.data.table, dml.data.database); queries.data.regular_queries = nowQueries; } const parseJsonQueries = JSON.stringify(queries.data); const response = await this.engine.run("schema_engine", [ "--action", "execute", "--mode", "fresh", "--dml", parseJsonQueries ]); if (response.status != 200) { returnFormattedError(response.status, response.message); } await import_core.TableProcessor.saveQuery(dml.data.table, dml.data.database, createQuery); return response.data; } } } return null; } async executeSeeders() { const cubesDir = import_path.default.join(process.cwd(), "dbcube", "cubes"); if (!import_fs.default.existsSync(cubesDir)) { throw new Error("\u274C The cubes folder does not exist"); } const cubeFiles = FileUtils_default.getCubeFilesRecursively("dbcube", "seeder.cube"); if (cubeFiles.length === 0) { throw new Error("\u274C There are no cubes to execute"); } else { for (const file of cubeFiles) { const filePath = import_path.default.isAbsolute(file) ? file : import_path.default.join(cubesDir, file); const stats = import_fs.default.statSync(filePath); if (stats.isFile()) { const response = await this.engine.run("schema_engine", [ "--action", "seeder", "--schema-path", filePath ]); if (response.status != 200) { returnFormattedError(response.status, response.message); } return response.data; } } } return null; } async executeTriggers() { const cubesDir = import_path.default.join(process.cwd(), "dbcube", "cubes"); const triggersDirExit = import_path.default.join(process.cwd(), "dbcube", "triggers"); if (!import_fs.default.existsSync(cubesDir)) { throw new Error("\u274C The cubes folder does not exist"); } const cubeFiles = FileUtils_default.getCubeFilesRecursively("dbcube", "trigger.cube"); if (cubeFiles.length === 0) { throw new Error("\u274C There are no cubes to execute"); } else { for (const file of cubeFiles) { const filePath = import_path.default.isAbsolute(file) ? file : import_path.default.join(cubesDir, file); const stats = import_fs.default.statSync(filePath); if (stats.isFile()) { const response = await this.engine.run("schema_engine", [ "--action", "trigger", "--path-exit", triggersDirExit, "--schema-path", filePath ]); if (response.status != 200) { returnFormattedError(response.status, response.message); } return response.data; } } } return null; } }; function returnFormattedError(status, message) { const RESET = "\x1B[0m"; const RED = "\x1B[31m"; const YELLOW = "\x1B[33m"; const BOLD = "\x1B[1m"; const CYAN = "\x1B[36m"; const GRAY = "\x1B[90m"; const UNDERLINE = "\x1B[4m"; const MAGENTA = "\x1B[35m"; let output = ""; let help = ""; const color = status === 600 ? YELLOW : RED; if (message.includes("[help]")) { const parts = message.split("[help]"); output += ` ${RED}${BOLD}${parts[0]}${RESET}`; help += ` ${MAGENTA}${BOLD}[help]${RESET} ${GRAY}${parts[1]}${RESET} `; } else { output += ` ${color}${BOLD}${message}${RESET} `; } const err = new Error(); const stackLines = err.stack?.split("\n") || []; const relevantStackLine = stackLines.find( (line) => line.includes(".js:") && !line.includes("node_modules") ); if (relevantStackLine) { const match = relevantStackLine.match(/\((.*):(\d+):(\d+)\)/) || relevantStackLine.match(/at (.*):(\d+):(\d+)/); if (match) { const [, filePath, lineStr, columnStr] = match; const lineNum = parseInt(lineStr, 10); const errorLocation = `${filePath}:${lineStr}:${columnStr}`; try { const codeLines = import_fs.default.readFileSync(filePath, "utf-8").split("\n"); const start = Math.max(0, lineNum - 3); const end = Math.min(codeLines.length, lineNum + 2); output += ` ${CYAN}${BOLD}[code] ${RESET}${YELLOW} ${UNDERLINE}${errorLocation}${RESET} `; for (let i = start; i < end; i++) { const line = codeLines[i]; const lineLabel = `${i + 1}`.padStart(4, " "); const pointer = i + 1 === lineNum ? `${RED}<-${RESET}` : " "; output += `${GRAY}${lineLabel}${RESET} ${pointer} ${line} `; } } catch (err2) { output += `${YELLOW}\u26A0\uFE0F No se pudo leer el archivo de origen: ${filePath}${RESET} `; output += ` ${CYAN}${BOLD}Stack Trace:${RESET} ${stackLines.slice(2).join("\n")} `; } } } output += help; console.error(output); process.exit(1); } // src/index.ts var index_default = Schema; // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { Schema }); //# sourceMappingURL=index.cjs.map