@dbcube/schema-builder
Advanced tools
+125
-1
@@ -298,3 +298,3 @@ "use strict"; | ||
| validProperties = ["type", "length", "options", "value", "defaultValue", "foreign", "enumValues", "description"]; | ||
| knownAnnotations = ["database", "table", "meta", "columns", "fields", "dataset", "beforeAdd", "afterAdd", "beforeUpdate", "afterUpdate", "beforeDelete", "afterDelete", "compute", "column"]; | ||
| knownAnnotations = ["database", "table", "meta", "columns", "fields", "dataset", "beforeAdd", "afterAdd", "beforeUpdate", "afterUpdate", "beforeDelete", "afterDelete", "compute", "column", "changeName", "addColumn", "deleteColumn", "renameColumn", "changeType", "changeLength", "changeDefault", "changeOptions", "changeEnumValues"]; | ||
| /** | ||
@@ -557,2 +557,24 @@ * Validates a cube file comprehensively | ||
| } | ||
| if (filePath.includes(".alter.cube")) { | ||
| const hasTable = lines.some((line) => line.includes("@table")); | ||
| if (!hasTable) { | ||
| errors.push({ | ||
| itemName: fileName, | ||
| error: "Alter cube files require @table annotation specifying the target table", | ||
| filePath, | ||
| lineNumber: 1 | ||
| }); | ||
| } | ||
| const hasAlterDirective = lines.some( | ||
| (line) => line.includes("@changeName") || line.includes("@addColumn") || line.includes("@deleteColumn") || line.includes("@renameColumn") || line.includes("@changeType") || line.includes("@changeLength") || line.includes("@changeDefault") || line.includes("@changeOptions") || line.includes("@changeEnumValues") | ||
| ); | ||
| if (!hasAlterDirective) { | ||
| errors.push({ | ||
| itemName: fileName, | ||
| error: "Alter cube files must contain at least one alter directive (@changeName, @addColumn, @deleteColumn, @renameColumn, @changeType, @changeLength, @changeDefault, @changeOptions, or @changeEnumValues)", | ||
| filePath, | ||
| lineNumber: 1 | ||
| }); | ||
| } | ||
| } | ||
| } | ||
@@ -1376,2 +1398,104 @@ getColumnTypeForOptions(lines, optionsLineIndex) { | ||
| } | ||
| async executeAlters() { | ||
| const startTime = Date.now(); | ||
| const cubesDir = import_path3.default.join(process.cwd(), "dbcube"); | ||
| if (!import_fs4.default.existsSync(cubesDir)) { | ||
| throw new Error("\u274C The cubes folder does not exist"); | ||
| } | ||
| const cubeFiles = FileUtils_default.getCubeFilesRecursively("dbcube", ".alter.cube"); | ||
| if (cubeFiles.length === 0) { | ||
| throw new Error("\u274C There are no .alter.cube files to execute"); | ||
| } | ||
| UIUtils.showOperationHeader("EXECUTING ALTER TABLES", this.name, "\u{1F527}"); | ||
| let totalAltersProcessed = 0; | ||
| let successCount = 0; | ||
| let errorCount = 0; | ||
| const processedAlters = []; | ||
| const errors = []; | ||
| for (let index = 0; index < cubeFiles.length; index++) { | ||
| const file = cubeFiles[index]; | ||
| const filePath = import_path3.default.isAbsolute(file) ? file : import_path3.default.join(cubesDir, file); | ||
| const stats = import_fs4.default.statSync(filePath); | ||
| if (stats.isFile()) { | ||
| const alterName = import_path3.default.basename(file, ".alter.cube"); | ||
| await UIUtils.showItemProgress(alterName, index + 1, cubeFiles.length); | ||
| try { | ||
| const validation = this.validateDatabaseConfiguration(filePath); | ||
| if (!validation.isValid && validation.error) { | ||
| UIUtils.showItemError(alterName, validation.error.error); | ||
| errors.push(validation.error); | ||
| errorCount++; | ||
| continue; | ||
| } | ||
| const dbResult = FileUtils_default.extractDatabaseNameFromCube(filePath); | ||
| const cubeDbName = dbResult.status === 200 ? dbResult.message : this.name; | ||
| if (cubeDbName !== this.name) { | ||
| continue; | ||
| } | ||
| const dml = await this.engine.run("schema_engine", [ | ||
| "--action", | ||
| "parse_alter", | ||
| "--schema-path", | ||
| filePath | ||
| ]); | ||
| if (dml.status != 200) { | ||
| returnFormattedError(dml.status, dml.message); | ||
| break; | ||
| } | ||
| 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", | ||
| "alter", | ||
| "--dml", | ||
| parseJson | ||
| ]); | ||
| if (queries.status != 200) { | ||
| returnFormattedError(queries.status, queries.message); | ||
| break; | ||
| } | ||
| delete queries.data.database_type; | ||
| const parseJsonQueries = JSON.stringify(queries.data); | ||
| const response = await this.engine.run("schema_engine", [ | ||
| "--action", | ||
| "execute", | ||
| "--mode", | ||
| "alter", | ||
| "--dml", | ||
| parseJsonQueries | ||
| ]); | ||
| if (response.status != 200) { | ||
| returnFormattedError(response.status, response.message); | ||
| break; | ||
| } | ||
| UIUtils.showItemSuccess(alterName); | ||
| successCount++; | ||
| processedAlters.push(alterName); | ||
| totalAltersProcessed++; | ||
| } catch (error) { | ||
| const processError = { | ||
| itemName: alterName, | ||
| error: error.message, | ||
| filePath | ||
| }; | ||
| UIUtils.showItemError(alterName, error.message); | ||
| errors.push(processError); | ||
| errorCount++; | ||
| } | ||
| } | ||
| } | ||
| const summary = { | ||
| startTime, | ||
| totalProcessed: totalAltersProcessed, | ||
| successCount, | ||
| errorCount, | ||
| processedItems: processedAlters, | ||
| operationName: "alter tables", | ||
| databaseName: this.name, | ||
| errors | ||
| }; | ||
| UIUtils.showOperationSummary(summary); | ||
| return totalAltersProcessed > 0 ? { processed: totalAltersProcessed, success: successCount, errors: errorCount } : null; | ||
| } | ||
| async executeTriggers() { | ||
@@ -1378,0 +1502,0 @@ const startTime = Date.now(); |
+1
-0
@@ -31,2 +31,3 @@ /** | ||
| executeSeeders(): Promise<any>; | ||
| executeAlters(): Promise<any>; | ||
| executeTriggers(): Promise<any>; | ||
@@ -33,0 +34,0 @@ } |
+1
-0
@@ -31,2 +31,3 @@ /** | ||
| executeSeeders(): Promise<any>; | ||
| executeAlters(): Promise<any>; | ||
| executeTriggers(): Promise<any>; | ||
@@ -33,0 +34,0 @@ } |
+125
-1
@@ -258,3 +258,3 @@ // src/lib/Schema.ts | ||
| validProperties = ["type", "length", "options", "value", "defaultValue", "foreign", "enumValues", "description"]; | ||
| knownAnnotations = ["database", "table", "meta", "columns", "fields", "dataset", "beforeAdd", "afterAdd", "beforeUpdate", "afterUpdate", "beforeDelete", "afterDelete", "compute", "column"]; | ||
| knownAnnotations = ["database", "table", "meta", "columns", "fields", "dataset", "beforeAdd", "afterAdd", "beforeUpdate", "afterUpdate", "beforeDelete", "afterDelete", "compute", "column", "changeName", "addColumn", "deleteColumn", "renameColumn", "changeType", "changeLength", "changeDefault", "changeOptions", "changeEnumValues"]; | ||
| /** | ||
@@ -517,2 +517,24 @@ * Validates a cube file comprehensively | ||
| } | ||
| if (filePath.includes(".alter.cube")) { | ||
| const hasTable = lines.some((line) => line.includes("@table")); | ||
| if (!hasTable) { | ||
| errors.push({ | ||
| itemName: fileName, | ||
| error: "Alter cube files require @table annotation specifying the target table", | ||
| filePath, | ||
| lineNumber: 1 | ||
| }); | ||
| } | ||
| const hasAlterDirective = lines.some( | ||
| (line) => line.includes("@changeName") || line.includes("@addColumn") || line.includes("@deleteColumn") || line.includes("@renameColumn") || line.includes("@changeType") || line.includes("@changeLength") || line.includes("@changeDefault") || line.includes("@changeOptions") || line.includes("@changeEnumValues") | ||
| ); | ||
| if (!hasAlterDirective) { | ||
| errors.push({ | ||
| itemName: fileName, | ||
| error: "Alter cube files must contain at least one alter directive (@changeName, @addColumn, @deleteColumn, @renameColumn, @changeType, @changeLength, @changeDefault, @changeOptions, or @changeEnumValues)", | ||
| filePath, | ||
| lineNumber: 1 | ||
| }); | ||
| } | ||
| } | ||
| } | ||
@@ -1336,2 +1358,104 @@ getColumnTypeForOptions(lines, optionsLineIndex) { | ||
| } | ||
| async executeAlters() { | ||
| const startTime = Date.now(); | ||
| const cubesDir = path4.join(process.cwd(), "dbcube"); | ||
| if (!fs5.existsSync(cubesDir)) { | ||
| throw new Error("\u274C The cubes folder does not exist"); | ||
| } | ||
| const cubeFiles = FileUtils_default.getCubeFilesRecursively("dbcube", ".alter.cube"); | ||
| if (cubeFiles.length === 0) { | ||
| throw new Error("\u274C There are no .alter.cube files to execute"); | ||
| } | ||
| UIUtils.showOperationHeader("EXECUTING ALTER TABLES", this.name, "\u{1F527}"); | ||
| let totalAltersProcessed = 0; | ||
| let successCount = 0; | ||
| let errorCount = 0; | ||
| const processedAlters = []; | ||
| const errors = []; | ||
| for (let index = 0; index < cubeFiles.length; index++) { | ||
| const file = cubeFiles[index]; | ||
| const filePath = path4.isAbsolute(file) ? file : path4.join(cubesDir, file); | ||
| const stats = fs5.statSync(filePath); | ||
| if (stats.isFile()) { | ||
| const alterName = path4.basename(file, ".alter.cube"); | ||
| await UIUtils.showItemProgress(alterName, index + 1, cubeFiles.length); | ||
| try { | ||
| const validation = this.validateDatabaseConfiguration(filePath); | ||
| if (!validation.isValid && validation.error) { | ||
| UIUtils.showItemError(alterName, validation.error.error); | ||
| errors.push(validation.error); | ||
| errorCount++; | ||
| continue; | ||
| } | ||
| const dbResult = FileUtils_default.extractDatabaseNameFromCube(filePath); | ||
| const cubeDbName = dbResult.status === 200 ? dbResult.message : this.name; | ||
| if (cubeDbName !== this.name) { | ||
| continue; | ||
| } | ||
| const dml = await this.engine.run("schema_engine", [ | ||
| "--action", | ||
| "parse_alter", | ||
| "--schema-path", | ||
| filePath | ||
| ]); | ||
| if (dml.status != 200) { | ||
| returnFormattedError(dml.status, dml.message); | ||
| break; | ||
| } | ||
| 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", | ||
| "alter", | ||
| "--dml", | ||
| parseJson | ||
| ]); | ||
| if (queries.status != 200) { | ||
| returnFormattedError(queries.status, queries.message); | ||
| break; | ||
| } | ||
| delete queries.data.database_type; | ||
| const parseJsonQueries = JSON.stringify(queries.data); | ||
| const response = await this.engine.run("schema_engine", [ | ||
| "--action", | ||
| "execute", | ||
| "--mode", | ||
| "alter", | ||
| "--dml", | ||
| parseJsonQueries | ||
| ]); | ||
| if (response.status != 200) { | ||
| returnFormattedError(response.status, response.message); | ||
| break; | ||
| } | ||
| UIUtils.showItemSuccess(alterName); | ||
| successCount++; | ||
| processedAlters.push(alterName); | ||
| totalAltersProcessed++; | ||
| } catch (error) { | ||
| const processError = { | ||
| itemName: alterName, | ||
| error: error.message, | ||
| filePath | ||
| }; | ||
| UIUtils.showItemError(alterName, error.message); | ||
| errors.push(processError); | ||
| errorCount++; | ||
| } | ||
| } | ||
| } | ||
| const summary = { | ||
| startTime, | ||
| totalProcessed: totalAltersProcessed, | ||
| successCount, | ||
| errorCount, | ||
| processedItems: processedAlters, | ||
| operationName: "alter tables", | ||
| databaseName: this.name, | ||
| errors | ||
| }; | ||
| UIUtils.showOperationSummary(summary); | ||
| return totalAltersProcessed > 0 ? { processed: totalAltersProcessed, success: successCount, errors: errorCount } : null; | ||
| } | ||
| async executeTriggers() { | ||
@@ -1338,0 +1462,0 @@ const startTime = Date.now(); |
+5
-5
| { | ||
| "name": "@dbcube/schema-builder", | ||
| "version": "5.0.13", | ||
| "version": "5.1.1", | ||
| "description": "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. \nIts agnostic design allows you to generate data manipulation (DML) and data definition (DDL) operations with a clean, chainable syntax—without sacrificing power or expressiveness.\nIt’s designed to work seamlessly in both SQL and NoSQL environments, providing a consistent abstraction layer across different storage technologies while still leveraging the native capabilities of each engine.", | ||
@@ -57,3 +57,3 @@ "main": "dist/index.cjs", | ||
| "dependencies": { | ||
| "@dbcube/core": "^5.0.13", | ||
| "@dbcube/core": "^5.1.4", | ||
| "chalk": "^5.6.2", | ||
@@ -67,7 +67,7 @@ "ora": "^9.3.0" | ||
| "devDependencies": { | ||
| "@types/node": "^25.3.2", | ||
| "rollup": "^4.59.0", | ||
| "@types/node": "^25.5.0", | ||
| "rollup": "^4.60.0", | ||
| "tsup": "^8.5.1", | ||
| "typescript": "^5.9.3" | ||
| } | ||
| } | ||
| } |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
Found 1 instance in 1 package
481304
6.55%3340
8.2%12
-7.69%Updated