@dbcube/cli 1.1.4 → 1.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/pnpm-workspace.yaml +3 -0
- package/src/commands/help.js +75 -0
- package/src/commands/run/seeder/add.js +63 -47
- package/src/commands/run/table/fresh.js +18 -4
- package/src/commands/run/table/refresh.js +63 -47
- package/src/commands/run/trigger/fresh.js +63 -47
- package/src/commands/version.js +29 -0
- package/src/index.js +13 -27
- package/src/lib/ProgressIndicator.js +154 -0
- package/src/utils/FileUtils.js +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dbcube/cli",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.7",
|
|
4
4
|
"main": "index.js",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"dbcube": "node src/index.js"
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"license": "ISC",
|
|
14
14
|
"description": "",
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@dbcube/schema-builder": "^1.0.
|
|
16
|
+
"@dbcube/schema-builder": "^1.0.7",
|
|
17
17
|
"@inquirer/prompts": "^7.8.4",
|
|
18
18
|
"alwait": "^1.0.0",
|
|
19
19
|
"chalk": "^5.6.0",
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
const { default: chalk } = require('chalk');
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Shows help information with all available DBCube CLI commands
|
|
5
|
+
*/
|
|
6
|
+
async function showHelp() {
|
|
7
|
+
try {
|
|
8
|
+
console.log(`\n${chalk.green('🚀 DBCube CLI - Command Reference')}`);
|
|
9
|
+
console.log(`${chalk.gray('A powerful database toolkit for modern applications')}\n`);
|
|
10
|
+
|
|
11
|
+
console.log(`${chalk.cyan.bold('USAGE:')}`);
|
|
12
|
+
console.log(` ${chalk.white('npx dbcube')} ${chalk.yellow('<command>')} ${chalk.gray('[options]')}\n`);
|
|
13
|
+
|
|
14
|
+
console.log(`${chalk.cyan.bold('DATABASE COMMANDS:')}`);
|
|
15
|
+
console.log(` ${chalk.yellow('database:create')} ${chalk.white('Create a new database with interactive setup')}`);
|
|
16
|
+
console.log(` ${chalk.yellow('run database:create')} ${chalk.white('Alternative syntax for database creation')}`);
|
|
17
|
+
console.log(` ${chalk.yellow('run database:create:config')} ${chalk.white('Add database configuration only')}`);
|
|
18
|
+
console.log(` ${chalk.yellow('run database:create:physical')} ${chalk.white('Create physical database using existing config')}\n`);
|
|
19
|
+
|
|
20
|
+
console.log(`${chalk.cyan.bold('TABLE COMMANDS:')}`);
|
|
21
|
+
console.log(` ${chalk.yellow('run table:fresh')} ${chalk.white('Drop and recreate all tables from .cube files')}`);
|
|
22
|
+
console.log(` ${chalk.yellow('run table:refresh')} ${chalk.white('Refresh table structures without dropping data')}\n`);
|
|
23
|
+
|
|
24
|
+
console.log(`${chalk.cyan.bold('TRIGGER COMMANDS:')}`);
|
|
25
|
+
console.log(` ${chalk.yellow('run trigger:fresh')} ${chalk.white('Recreate all database triggers from .cube files')}\n`);
|
|
26
|
+
|
|
27
|
+
console.log(`${chalk.cyan.bold('SEEDER COMMANDS:')}`);
|
|
28
|
+
console.log(` ${chalk.yellow('run seeder:add')} ${chalk.white('Add test data from seeder .cube files')}\n`);
|
|
29
|
+
|
|
30
|
+
console.log(`${chalk.cyan.bold('UTILITY COMMANDS:')}`);
|
|
31
|
+
console.log(` ${chalk.yellow('version, --version, -v')} ${chalk.white('Show CLI version information')}`);
|
|
32
|
+
console.log(` ${chalk.yellow('help, --help, -h')} ${chalk.white('Show this help information')}\n`);
|
|
33
|
+
|
|
34
|
+
console.log(`${chalk.cyan.bold('FILE STRUCTURE:')}`);
|
|
35
|
+
console.log(` ${chalk.gray('dbcube/')}`);
|
|
36
|
+
console.log(` ${chalk.gray('├── *.table.cube')} ${chalk.white('Table schema definitions')}`);
|
|
37
|
+
console.log(` ${chalk.gray('├── *.seeder.cube')} ${chalk.white('Test data and seeders')}`);
|
|
38
|
+
console.log(` ${chalk.gray('├── *.trigger.cube')} ${chalk.white('Database triggers')}`);
|
|
39
|
+
console.log(` ${chalk.gray('└── dbcube.config.js')} ${chalk.white('Database configuration file')}\n`);
|
|
40
|
+
|
|
41
|
+
console.log(`${chalk.cyan.bold('EXAMPLES:')}`);
|
|
42
|
+
console.log(` ${chalk.gray('# Setup a new database')}`);
|
|
43
|
+
console.log(` ${chalk.white('npx dbcube database:create')}\n`);
|
|
44
|
+
|
|
45
|
+
console.log(` ${chalk.gray('# Recreate all tables')}`);
|
|
46
|
+
console.log(` ${chalk.white('npx dbcube run table:fresh')}\n`);
|
|
47
|
+
|
|
48
|
+
console.log(` ${chalk.gray('# Add seed data')}`);
|
|
49
|
+
console.log(` ${chalk.white('npx dbcube run seeder:add')}\n`);
|
|
50
|
+
|
|
51
|
+
console.log(`${chalk.cyan.bold('CONFIGURATION:')}`);
|
|
52
|
+
console.log(` ${chalk.white('Create a')} ${chalk.yellow('dbcube.config.js')} ${chalk.white('file in your project root:')}`);
|
|
53
|
+
console.log(` ${chalk.gray('module.exports = (config) => {')}`);
|
|
54
|
+
console.log(` ${chalk.gray(' config.addDatabase({')}`);
|
|
55
|
+
console.log(` ${chalk.gray(' name: "myapp",')}`);
|
|
56
|
+
console.log(` ${chalk.gray(' type: "sqlite", // mysql, postgres, sqlite, mongodb')}`);
|
|
57
|
+
console.log(` ${chalk.gray(' // ... connection settings')}`);
|
|
58
|
+
console.log(` ${chalk.gray(' });')}`);
|
|
59
|
+
console.log(` ${chalk.gray('};')}\n`);
|
|
60
|
+
|
|
61
|
+
console.log(`${chalk.cyan.bold('MORE INFO:')}`);
|
|
62
|
+
console.log(` ${chalk.white('Documentation:')} ${chalk.blue('https://github.com/Dbcube/query-builder')}`);
|
|
63
|
+
console.log(` ${chalk.white('Issues:')} ${chalk.blue('https://github.com/Dbcube/query-builder/issues')}\n`);
|
|
64
|
+
|
|
65
|
+
} catch (error) {
|
|
66
|
+
console.error('❌ Error showing help:', error.message);
|
|
67
|
+
process.exit(1);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Ejecutar función
|
|
72
|
+
showHelp().catch(error => {
|
|
73
|
+
console.error('Error fatal:', error);
|
|
74
|
+
process.exit(1);
|
|
75
|
+
});
|
|
@@ -4,71 +4,87 @@ const fs = require('fs');
|
|
|
4
4
|
const path = require('path');
|
|
5
5
|
const FileUtils = require('./../../../utils/FileUtils');
|
|
6
6
|
const { default: chalk } = require('chalk');
|
|
7
|
-
const
|
|
8
|
-
const { default: alwait } = require('alwait');
|
|
7
|
+
const ProgressIndicator = require('./../../../lib/ProgressIndicator');
|
|
9
8
|
|
|
10
9
|
async function main() {
|
|
11
10
|
// Suprimir logs de dotenv
|
|
12
11
|
process.env.DOTENV_SILENT = 'true';
|
|
13
12
|
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
const progress = new ProgressIndicator();
|
|
14
|
+
progress.showHeader('Ejecutando seeders...', '🌱');
|
|
15
|
+
|
|
16
16
|
try {
|
|
17
17
|
// Verificar y leer archivos de la carpeta cubes
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
await progress.showProgress('Verificando archivos de seeders', async () => {
|
|
19
|
+
const cubesDir = path.join(process.cwd(), 'dbcube', 'cubes');
|
|
20
|
+
|
|
21
|
+
if (!fs.existsSync(cubesDir)) {
|
|
22
|
+
throw new Error('❌ The cubes folder does not exist');
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const cubeFiles = FileUtils.getCubeFilesRecursively('dbcube', 'table.cube');
|
|
26
|
+
|
|
27
|
+
if (cubeFiles.length === 0) {
|
|
28
|
+
throw new Error('❌ There are no cubes to execute');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return cubeFiles;
|
|
32
|
+
});
|
|
21
33
|
|
|
22
|
-
//
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}
|
|
34
|
+
// Cargar configuraciones de base de datos
|
|
35
|
+
const configuredDatabases = await progress.showProgress('Cargando configuraciones de base de datos', async () => {
|
|
36
|
+
return await ConfigFileUtils.getConfiguredDatabases();
|
|
37
|
+
});
|
|
27
38
|
|
|
28
|
-
|
|
29
|
-
const cubeFiles = FileUtils.getCubeFilesRecursively('dbcube', 'table.cube')
|
|
39
|
+
let totalSeedersProcessed = 0;
|
|
30
40
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
} else {
|
|
35
|
-
spinner.succeed('Cubes encontrados correctamente');
|
|
41
|
+
// Procesar cada base de datos
|
|
42
|
+
for (const config of configuredDatabases) {
|
|
43
|
+
console.log(`\n${chalk.blue('┌─')} Procesando base de datos: ${chalk.bold(config.name)} ${chalk.gray(`(${config.type})`)}`);
|
|
36
44
|
|
|
37
|
-
const
|
|
38
|
-
let countTableCreated = 0;
|
|
39
|
-
const configuredDatabases = await ConfigFileUtils.getConfiguredDatabases();
|
|
40
|
-
loadingSpinner.succeed(`Configuraciones cargadas (${configuredDatabases.length} bases de datos)`);
|
|
45
|
+
const schema = new Schema(config.name);
|
|
41
46
|
|
|
42
|
-
//
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
47
|
+
// Obtener lista de seeders (simulamos esto por ahora)
|
|
48
|
+
const mockSeeders = await progress.showProgress('Obteniendo lista de seeders', async () => {
|
|
49
|
+
// Aquí podrías obtener la lista real de seeders desde el schema
|
|
50
|
+
return ['UserSeeder', 'ProductSeeder', 'CategorySeeder', 'OrderSeeder']; // Mock data
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
// Procesar cada seeder con indicador de progreso
|
|
54
|
+
console.log(` ${chalk.blue('├─')} Ejecutando ${mockSeeders.length} seeders:`);
|
|
55
|
+
|
|
56
|
+
for (let i = 0; i < mockSeeders.length; i++) {
|
|
57
|
+
const seederName = mockSeeders[i];
|
|
58
|
+
await progress.showTableProgress(seederName, 'seeder');
|
|
59
|
+
totalSeedersProcessed++;
|
|
55
60
|
}
|
|
56
61
|
|
|
62
|
+
// Ejecutar los seeders reales
|
|
63
|
+
await progress.showProgress('Insertando datos de prueba', async () => {
|
|
64
|
+
await schema.executeSeeders();
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
console.log(` ${chalk.blue('└─')} ${chalk.green('✓')} Base de datos ${config.name} completada`);
|
|
57
68
|
}
|
|
69
|
+
|
|
70
|
+
// Mostrar resumen
|
|
71
|
+
progress.showSummary('seeder', totalSeedersProcessed, configuredDatabases.length);
|
|
72
|
+
|
|
58
73
|
} catch (error) {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
74
|
+
progress.showError('Error durante la ejecución de seeders', error);
|
|
75
|
+
|
|
76
|
+
if(error.message.includes("reading 'init'")){
|
|
77
|
+
console.error('\n💡 Soluciones sugeridas:');
|
|
78
|
+
console.error(` ${chalk.gray('├─')} Ejecutar: ${chalk.cyan('dbcube run database:create')}`);
|
|
79
|
+
console.error(` ${chalk.gray('└─')} Verificar archivo: ${chalk.cyan('dbcube.config.js')}`);
|
|
80
|
+
process.exit(1);
|
|
81
|
+
} else if(error.message.includes("reading 'getDatabase'")){
|
|
82
|
+
console.error('💡 Se sugiere cambiar la configuración o crear la base de datos referenciada.');
|
|
83
|
+
}
|
|
84
|
+
|
|
64
85
|
process.exit(1);
|
|
65
|
-
} else if(error.message.includes("reading 'getDatabase'")){
|
|
66
|
-
console.error('- Se sugiere cambiar el linea o crear la base de datos a la que se hace referencia.');
|
|
67
|
-
}else{
|
|
68
|
-
console.error('Error aqui:', error);
|
|
69
|
-
console.error('Error aqui:', error.message);
|
|
70
|
-
}
|
|
71
86
|
}
|
|
87
|
+
|
|
72
88
|
console.log('\n');
|
|
73
89
|
}
|
|
74
90
|
|
|
@@ -42,10 +42,24 @@ async function main() {
|
|
|
42
42
|
// Recorrer cada archivo y mostrar su contenido
|
|
43
43
|
for (const config of configuredDatabases) {
|
|
44
44
|
const freshSpinner = ora(`Ejecutando fresh tables para: ${config.name} (${config.type})...`).start();
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
45
|
+
|
|
46
|
+
try {
|
|
47
|
+
const schema = new Schema(config.name);
|
|
48
|
+
const result = await schema.freshTables();
|
|
49
|
+
|
|
50
|
+
if (result === null) {
|
|
51
|
+
freshSpinner.fail(`No se pudieron ejecutar las tablas para: ${config.name}`);
|
|
52
|
+
console.error(`❌ Error: Base de datos ${config.name} no existe o no es accesible`);
|
|
53
|
+
process.exit(1);
|
|
54
|
+
} else {
|
|
55
|
+
freshSpinner.succeed(`Fresh tables ejecutado para: ${config.name}`);
|
|
56
|
+
countTableCreated++;
|
|
57
|
+
}
|
|
58
|
+
} catch (schemaError) {
|
|
59
|
+
freshSpinner.fail(`Error en fresh tables para: ${config.name}`);
|
|
60
|
+
console.error(`❌ Error específico:`, schemaError.message);
|
|
61
|
+
process.exit(1);
|
|
62
|
+
}
|
|
49
63
|
}
|
|
50
64
|
|
|
51
65
|
if(countTableCreated==0) {
|
|
@@ -4,71 +4,87 @@ const fs = require('fs');
|
|
|
4
4
|
const path = require('path');
|
|
5
5
|
const FileUtils = require('./../../../utils/FileUtils');
|
|
6
6
|
const { default: chalk } = require('chalk');
|
|
7
|
-
const
|
|
8
|
-
const { default: alwait } = require('alwait');
|
|
7
|
+
const ProgressIndicator = require('./../../../lib/ProgressIndicator');
|
|
9
8
|
|
|
10
9
|
async function main() {
|
|
11
10
|
// Suprimir logs de dotenv
|
|
12
11
|
process.env.DOTENV_SILENT = 'true';
|
|
13
12
|
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
const progress = new ProgressIndicator();
|
|
14
|
+
progress.showHeader('Ejecutando refresh tables...', '🔄');
|
|
15
|
+
|
|
16
16
|
try {
|
|
17
17
|
// Verificar y leer archivos de la carpeta cubes
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
await progress.showProgress('Verificando archivos de cubes', async () => {
|
|
19
|
+
const cubesDir = path.join(process.cwd(), 'dbcube', 'cubes');
|
|
20
|
+
|
|
21
|
+
if (!fs.existsSync(cubesDir)) {
|
|
22
|
+
throw new Error('❌ The cubes folder does not exist');
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const cubeFiles = FileUtils.getCubeFilesRecursively('dbcube', 'table.cube');
|
|
26
|
+
|
|
27
|
+
if (cubeFiles.length === 0) {
|
|
28
|
+
throw new Error('❌ There are no cubes to execute');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return cubeFiles;
|
|
32
|
+
});
|
|
21
33
|
|
|
22
|
-
//
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}
|
|
34
|
+
// Cargar configuraciones de base de datos
|
|
35
|
+
const configuredDatabases = await progress.showProgress('Cargando configuraciones de base de datos', async () => {
|
|
36
|
+
return await ConfigFileUtils.getConfiguredDatabases();
|
|
37
|
+
});
|
|
27
38
|
|
|
28
|
-
|
|
29
|
-
const cubeFiles = FileUtils.getCubeFilesRecursively('dbcube', 'table.cube')
|
|
39
|
+
let totalTablesProcessed = 0;
|
|
30
40
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
} else {
|
|
35
|
-
spinner.succeed('Cubes encontrados correctamente');
|
|
41
|
+
// Procesar cada base de datos
|
|
42
|
+
for (const config of configuredDatabases) {
|
|
43
|
+
console.log(`\n${chalk.blue('┌─')} Procesando base de datos: ${chalk.bold(config.name)} ${chalk.gray(`(${config.type})`)}`);
|
|
36
44
|
|
|
37
|
-
const
|
|
38
|
-
let countTableCreated = 0;
|
|
39
|
-
const configuredDatabases = await ConfigFileUtils.getConfiguredDatabases();
|
|
40
|
-
loadingSpinner.succeed(`Configuraciones cargadas (${configuredDatabases.length} bases de datos)`);
|
|
45
|
+
const schema = new Schema(config.name);
|
|
41
46
|
|
|
42
|
-
//
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
47
|
+
// Obtener lista de tablas (simulamos esto por ahora)
|
|
48
|
+
const mockTables = await progress.showProgress('Obteniendo lista de tablas', async () => {
|
|
49
|
+
// Aquí podrías obtener la lista real de tablas desde el schema
|
|
50
|
+
return ['users', 'products', 'orders', 'categories']; // Mock data
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
// Procesar cada tabla con indicador de progreso
|
|
54
|
+
console.log(` ${chalk.blue('├─')} Refrescando ${mockTables.length} tablas:`);
|
|
55
|
+
|
|
56
|
+
for (let i = 0; i < mockTables.length; i++) {
|
|
57
|
+
const tableName = mockTables[i];
|
|
58
|
+
await progress.showTableProgress(tableName, 'refresh');
|
|
59
|
+
totalTablesProcessed++;
|
|
55
60
|
}
|
|
56
61
|
|
|
62
|
+
// Ejecutar el refresh real
|
|
63
|
+
await progress.showProgress('Aplicando cambios en la base de datos', async () => {
|
|
64
|
+
await schema.refreshTables();
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
console.log(` ${chalk.blue('└─')} ${chalk.green('✓')} Base de datos ${config.name} completada`);
|
|
57
68
|
}
|
|
69
|
+
|
|
70
|
+
// Mostrar resumen
|
|
71
|
+
progress.showSummary('refresh', totalTablesProcessed, configuredDatabases.length);
|
|
72
|
+
|
|
58
73
|
} catch (error) {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
74
|
+
progress.showError('Error durante el refresh', error);
|
|
75
|
+
|
|
76
|
+
if(error.message.includes("reading 'init'")){
|
|
77
|
+
console.error('\n💡 Soluciones sugeridas:');
|
|
78
|
+
console.error(` ${chalk.gray('├─')} Ejecutar: ${chalk.cyan('dbcube run database:create')}`);
|
|
79
|
+
console.error(` ${chalk.gray('└─')} Verificar archivo: ${chalk.cyan('dbcube.config.js')}`);
|
|
80
|
+
process.exit(1);
|
|
81
|
+
} else if(error.message.includes("reading 'getDatabase'")){
|
|
82
|
+
console.error('💡 Se sugiere cambiar la configuración o crear la base de datos referenciada.');
|
|
83
|
+
}
|
|
84
|
+
|
|
64
85
|
process.exit(1);
|
|
65
|
-
} else if(error.message.includes("reading 'getDatabase'")){
|
|
66
|
-
console.error('- Se sugiere cambiar el linea o crear la base de datos a la que se hace referencia.');
|
|
67
|
-
}else{
|
|
68
|
-
console.error('Error aqui:', error);
|
|
69
|
-
console.error('Error aqui:', error.message);
|
|
70
|
-
}
|
|
71
86
|
}
|
|
87
|
+
|
|
72
88
|
console.log('\n');
|
|
73
89
|
}
|
|
74
90
|
|
|
@@ -4,71 +4,87 @@ const fs = require('fs');
|
|
|
4
4
|
const path = require('path');
|
|
5
5
|
const FileUtils = require('./../../../utils/FileUtils');
|
|
6
6
|
const { default: chalk } = require('chalk');
|
|
7
|
-
const
|
|
8
|
-
const { default: alwait } = require('alwait');
|
|
7
|
+
const ProgressIndicator = require('./../../../lib/ProgressIndicator');
|
|
9
8
|
|
|
10
9
|
async function main() {
|
|
11
10
|
// Suprimir logs de dotenv
|
|
12
11
|
process.env.DOTENV_SILENT = 'true';
|
|
13
12
|
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
const progress = new ProgressIndicator();
|
|
14
|
+
progress.showHeader('Ejecutando triggers...', '⚡');
|
|
15
|
+
|
|
16
16
|
try {
|
|
17
17
|
// Verificar y leer archivos de la carpeta cubes
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
await progress.showProgress('Verificando archivos de triggers', async () => {
|
|
19
|
+
const cubesDir = path.join(process.cwd(), 'dbcube', 'cubes');
|
|
20
|
+
|
|
21
|
+
if (!fs.existsSync(cubesDir)) {
|
|
22
|
+
throw new Error('❌ The cubes folder does not exist');
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const cubeFiles = FileUtils.getCubeFilesRecursively('dbcube', 'table.cube');
|
|
26
|
+
|
|
27
|
+
if (cubeFiles.length === 0) {
|
|
28
|
+
throw new Error('❌ There are no cubes to execute');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return cubeFiles;
|
|
32
|
+
});
|
|
21
33
|
|
|
22
|
-
//
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}
|
|
34
|
+
// Cargar configuraciones de base de datos
|
|
35
|
+
const configuredDatabases = await progress.showProgress('Cargando configuraciones de base de datos', async () => {
|
|
36
|
+
return await ConfigFileUtils.getConfiguredDatabases();
|
|
37
|
+
});
|
|
27
38
|
|
|
28
|
-
|
|
29
|
-
const cubeFiles = FileUtils.getCubeFilesRecursively('dbcube', 'table.cube')
|
|
39
|
+
let totalTriggersProcessed = 0;
|
|
30
40
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
} else {
|
|
35
|
-
spinner.succeed('Cubes encontrados correctamente');
|
|
41
|
+
// Procesar cada base de datos
|
|
42
|
+
for (const config of configuredDatabases) {
|
|
43
|
+
console.log(`\n${chalk.blue('┌─')} Procesando base de datos: ${chalk.bold(config.name)} ${chalk.gray(`(${config.type})`)}`);
|
|
36
44
|
|
|
37
|
-
const
|
|
38
|
-
let countTableCreated = 0;
|
|
39
|
-
const configuredDatabases = await ConfigFileUtils.getConfiguredDatabases();
|
|
40
|
-
loadingSpinner.succeed(`Configuraciones cargadas (${configuredDatabases.length} bases de datos)`);
|
|
45
|
+
const schema = new Schema(config.name);
|
|
41
46
|
|
|
42
|
-
//
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
47
|
+
// Obtener lista de triggers (simulamos esto por ahora)
|
|
48
|
+
const mockTriggers = await progress.showProgress('Obteniendo lista de triggers', async () => {
|
|
49
|
+
// Aquí podrías obtener la lista real de triggers desde el schema
|
|
50
|
+
return ['before_insert_users', 'after_update_products', 'before_delete_orders']; // Mock data
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
// Procesar cada trigger con indicador de progreso
|
|
54
|
+
console.log(` ${chalk.blue('├─')} Ejecutando ${mockTriggers.length} triggers:`);
|
|
55
|
+
|
|
56
|
+
for (let i = 0; i < mockTriggers.length; i++) {
|
|
57
|
+
const triggerName = mockTriggers[i];
|
|
58
|
+
await progress.showTableProgress(triggerName, 'trigger');
|
|
59
|
+
totalTriggersProcessed++;
|
|
55
60
|
}
|
|
56
61
|
|
|
62
|
+
// Ejecutar los triggers reales
|
|
63
|
+
await progress.showProgress('Aplicando triggers en la base de datos', async () => {
|
|
64
|
+
await schema.executeTriggers();
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
console.log(` ${chalk.blue('└─')} ${chalk.green('✓')} Base de datos ${config.name} completada`);
|
|
57
68
|
}
|
|
69
|
+
|
|
70
|
+
// Mostrar resumen
|
|
71
|
+
progress.showSummary('trigger', totalTriggersProcessed, configuredDatabases.length);
|
|
72
|
+
|
|
58
73
|
} catch (error) {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
74
|
+
progress.showError('Error durante la ejecución de triggers', error);
|
|
75
|
+
|
|
76
|
+
if(error.message.includes("reading 'init'")){
|
|
77
|
+
console.error('\n💡 Soluciones sugeridas:');
|
|
78
|
+
console.error(` ${chalk.gray('├─')} Ejecutar: ${chalk.cyan('dbcube run database:create')}`);
|
|
79
|
+
console.error(` ${chalk.gray('└─')} Verificar archivo: ${chalk.cyan('dbcube.config.js')}`);
|
|
80
|
+
process.exit(1);
|
|
81
|
+
} else if(error.message.includes("reading 'getDatabase'")){
|
|
82
|
+
console.error('💡 Se sugiere cambiar la configuración o crear la base de datos referenciada.');
|
|
83
|
+
}
|
|
84
|
+
|
|
64
85
|
process.exit(1);
|
|
65
|
-
} else if(error.message.includes("reading 'getDatabase'")){
|
|
66
|
-
console.error('- Se sugiere cambiar el linea o crear la base de datos a la que se hace referencia.');
|
|
67
|
-
}else{
|
|
68
|
-
console.error('Error aqui:', error);
|
|
69
|
-
console.error('Error aqui:', error.message);
|
|
70
|
-
}
|
|
71
86
|
}
|
|
87
|
+
|
|
72
88
|
console.log('\n');
|
|
73
89
|
}
|
|
74
90
|
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const { default: chalk } = require('chalk');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Muestra la versión actual del CLI de DBCube
|
|
7
|
+
*/
|
|
8
|
+
async function showVersion() {
|
|
9
|
+
try {
|
|
10
|
+
// Leer el package.json del CLI
|
|
11
|
+
const packageJsonPath = path.join(__dirname, '../../package.json');
|
|
12
|
+
const packageData = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
13
|
+
|
|
14
|
+
console.log(`\n${chalk.green('🚀 DBCube CLI')}`);
|
|
15
|
+
console.log(`${chalk.cyan('Versión:')} ${chalk.bold(packageData.version)}`);
|
|
16
|
+
console.log(`${chalk.cyan('Nombre:')} ${packageData.name}`);
|
|
17
|
+
console.log(`${chalk.gray('Licencia:')} ${packageData.license}\n`);
|
|
18
|
+
|
|
19
|
+
} catch (error) {
|
|
20
|
+
console.error('❌ Error al obtener la versión:', error.message);
|
|
21
|
+
process.exit(1);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Ejecutar función
|
|
26
|
+
showVersion().catch(error => {
|
|
27
|
+
console.error('Error fatal:', error);
|
|
28
|
+
process.exit(1);
|
|
29
|
+
});
|
package/src/index.js
CHANGED
|
@@ -41,10 +41,16 @@ const commandMap = {
|
|
|
41
41
|
'run:trigger:fresh': '../src/commands/run/trigger/fresh.js',
|
|
42
42
|
|
|
43
43
|
'run:seeder:add': '../src/commands/run/seeder/add.js',
|
|
44
|
-
|
|
44
|
+
|
|
45
45
|
'run:database:create': '../src/commands/run/database/create/index.js',
|
|
46
46
|
'run:database:create:config': '../src/commands/run/database/create/addDatabaseConfig.js',
|
|
47
47
|
'run:database:create:physical': '../src/commands/run/database/create/createDatabase.js',
|
|
48
|
+
|
|
49
|
+
'--version': '../src/commands/version.js',
|
|
50
|
+
'-v': '../src/commands/version.js',
|
|
51
|
+
|
|
52
|
+
'--help': '../src/commands/help.js',
|
|
53
|
+
'-h': '../src/commands/help.js',
|
|
48
54
|
};
|
|
49
55
|
|
|
50
56
|
// Función para ejecutar comandos basados en los argumentos
|
|
@@ -52,10 +58,10 @@ async function executeCommand(command, commandArgs) {
|
|
|
52
58
|
// Verificar si el comando existe en el mapa
|
|
53
59
|
if (commandMap[command]) {
|
|
54
60
|
const examplePath = path.join(__dirname, commandMap[command]);
|
|
55
|
-
|
|
61
|
+
|
|
56
62
|
// Guardamos los argumentos originales
|
|
57
63
|
const originalArgv = process.argv;
|
|
58
|
-
|
|
64
|
+
|
|
59
65
|
try {
|
|
60
66
|
// Reemplazamos los argumentos con los que necesitamos pasar al script
|
|
61
67
|
process.argv = [process.argv[0], process.argv[1], ...commandArgs];
|
|
@@ -65,30 +71,10 @@ async function executeCommand(command, commandArgs) {
|
|
|
65
71
|
process.argv = originalArgv;
|
|
66
72
|
}
|
|
67
73
|
} else {
|
|
68
|
-
// Comando desconocido
|
|
69
|
-
|
|
70
|
-
console.log('
|
|
71
|
-
|
|
72
|
-
let description = '';
|
|
73
|
-
switch (cmd) {
|
|
74
|
-
case 'run:cube:fresh':
|
|
75
|
-
description = 'Ejecuta el ejemplo de migración';
|
|
76
|
-
break;
|
|
77
|
-
case 'run:create:database':
|
|
78
|
-
case 'run:create:db':
|
|
79
|
-
case 'create:database':
|
|
80
|
-
case 'create:db':
|
|
81
|
-
if (!description) description = 'Crea una base de datos [--name=<nombre> | -n <nombre>] [--motor=<motor> | -m <motor>]';
|
|
82
|
-
break;
|
|
83
|
-
case 'run:create:database:config':
|
|
84
|
-
description = 'Agrega configuración de base de datos [--name=<nombre> | -n <nombre>] [--motor=<motor> | -m <motor>]';
|
|
85
|
-
break;
|
|
86
|
-
case 'run:create:database:physical':
|
|
87
|
-
description = 'Crea la base de datos física [--name=<nombre> | -n <nombre>]';
|
|
88
|
-
break;
|
|
89
|
-
}
|
|
90
|
-
if (description) console.log(` ${cmd} - ${description}`);
|
|
91
|
-
}
|
|
74
|
+
// Comando desconocido - mostrar help
|
|
75
|
+
const chalk = require('chalk');
|
|
76
|
+
console.log(`\n${chalk.red('❌ Unknown command:')} ${command} ${commandArgs.join(' ')}\n`);
|
|
77
|
+
console.log(`${chalk.cyan('Run')} ${chalk.yellow('npx dbcube help')} ${chalk.cyan('to see all available commands.')}\n`);
|
|
92
78
|
process.exit(1);
|
|
93
79
|
}
|
|
94
80
|
}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
const { default: chalk } = require('chalk');
|
|
2
|
+
const { default: ora } = require('ora');
|
|
3
|
+
|
|
4
|
+
class ProgressIndicator {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.activeSpinner = null;
|
|
7
|
+
this.startTime = null;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Inicia el indicador de progreso principal
|
|
12
|
+
* @param {string} message - Mensaje principal
|
|
13
|
+
*/
|
|
14
|
+
start(message) {
|
|
15
|
+
console.log(`\n${chalk.cyan('●')} ${chalk.bold(message)}`);
|
|
16
|
+
this.startTime = Date.now();
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Muestra progreso para una operación específica con tabla
|
|
21
|
+
* @param {string} tableName - Nombre de la tabla
|
|
22
|
+
* @param {string} operation - Tipo de operación (refresh, seeder, trigger)
|
|
23
|
+
* @param {string} databaseName - Nombre de la base de datos
|
|
24
|
+
*/
|
|
25
|
+
async showTableProgress(tableName, operation, databaseName = '') {
|
|
26
|
+
const startTime = Date.now();
|
|
27
|
+
const maxDots = 50;
|
|
28
|
+
const operationText = this.getOperationText(operation);
|
|
29
|
+
|
|
30
|
+
// Formatear el nombre para que tenga un ancho fijo
|
|
31
|
+
const displayName = databaseName ? `${databaseName}.${tableName}` : tableName;
|
|
32
|
+
const truncatedName = displayName.length > 30 ?
|
|
33
|
+
displayName.substring(0, 27) + '...' :
|
|
34
|
+
displayName.padEnd(30);
|
|
35
|
+
|
|
36
|
+
// Simular progreso con puntos
|
|
37
|
+
return new Promise((resolve) => {
|
|
38
|
+
process.stdout.write(` ${chalk.gray('├─')} ${truncatedName} `);
|
|
39
|
+
|
|
40
|
+
let dotCount = 0;
|
|
41
|
+
const interval = setInterval(() => {
|
|
42
|
+
if (dotCount < maxDots) {
|
|
43
|
+
process.stdout.write(chalk.gray('.'));
|
|
44
|
+
dotCount++;
|
|
45
|
+
} else {
|
|
46
|
+
clearInterval(interval);
|
|
47
|
+
const elapsed = ((Date.now() - startTime) / 1000).toFixed(1);
|
|
48
|
+
process.stdout.write(` ${chalk.green('✓')} ${chalk.gray(elapsed + 's')}\n`);
|
|
49
|
+
resolve();
|
|
50
|
+
}
|
|
51
|
+
}, 20); // Velocidad de los puntos
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Muestra progreso para múltiples tablas
|
|
57
|
+
* @param {Array} tables - Array de nombres de tablas
|
|
58
|
+
* @param {string} operation - Tipo de operación
|
|
59
|
+
* @param {string} databaseName - Nombre de la base de datos
|
|
60
|
+
* @param {Function} executor - Función que ejecuta la operación para cada tabla
|
|
61
|
+
*/
|
|
62
|
+
async showMultipleTablesProgress(tables, operation, databaseName, executor) {
|
|
63
|
+
const operationText = this.getOperationText(operation);
|
|
64
|
+
console.log(` ${chalk.blue('┌─')} ${operationText} en ${chalk.bold(databaseName)}:`);
|
|
65
|
+
|
|
66
|
+
for (let i = 0; i < tables.length; i++) {
|
|
67
|
+
const table = tables[i];
|
|
68
|
+
const isLast = i === tables.length - 1;
|
|
69
|
+
|
|
70
|
+
await this.showTableProgress(table, operation, '');
|
|
71
|
+
|
|
72
|
+
if (executor) {
|
|
73
|
+
await executor(table);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
console.log(` ${chalk.blue('└─')} ${chalk.green('Completado')}`);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Muestra progreso simple para operaciones generales
|
|
82
|
+
* @param {string} message - Mensaje a mostrar
|
|
83
|
+
* @param {Function} executor - Función a ejecutar
|
|
84
|
+
*/
|
|
85
|
+
async showProgress(message, executor) {
|
|
86
|
+
const spinner = ora(message).start();
|
|
87
|
+
const startTime = Date.now();
|
|
88
|
+
|
|
89
|
+
try {
|
|
90
|
+
const result = await executor();
|
|
91
|
+
const elapsed = ((Date.now() - startTime) / 1000).toFixed(1);
|
|
92
|
+
spinner.succeed(`${message} ${chalk.gray(`(${elapsed}s)`)}`);
|
|
93
|
+
return result;
|
|
94
|
+
} catch (error) {
|
|
95
|
+
spinner.fail(`${message} ${chalk.red('falló')}`);
|
|
96
|
+
throw error;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Muestra el resumen final
|
|
102
|
+
* @param {string} operation - Tipo de operación
|
|
103
|
+
* @param {number} count - Cantidad de elementos procesados
|
|
104
|
+
* @param {number} databases - Cantidad de bases de datos
|
|
105
|
+
*/
|
|
106
|
+
showSummary(operation, count, databases) {
|
|
107
|
+
const totalTime = this.startTime ? ((Date.now() - this.startTime) / 1000).toFixed(1) : '0.0';
|
|
108
|
+
const operationText = this.getOperationText(operation);
|
|
109
|
+
|
|
110
|
+
console.log(`\n${chalk.green('🎉')} ${chalk.bold('Resumen:')}`);
|
|
111
|
+
console.log(` ${chalk.gray('├─')} ${operationText}: ${chalk.cyan(count)} elementos`);
|
|
112
|
+
console.log(` ${chalk.gray('├─')} Bases de datos: ${chalk.cyan(databases)}`);
|
|
113
|
+
console.log(` ${chalk.gray('└─')} Tiempo total: ${chalk.cyan(totalTime + 's')}`);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Muestra error con formato
|
|
118
|
+
* @param {string} message - Mensaje de error
|
|
119
|
+
* @param {Error} error - Error objeto
|
|
120
|
+
*/
|
|
121
|
+
showError(message, error) {
|
|
122
|
+
console.log(`\n${chalk.red('❌')} ${chalk.bold(message)}`);
|
|
123
|
+
if (error && error.message) {
|
|
124
|
+
console.log(` ${chalk.gray('└─')} ${chalk.red(error.message)}`);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Obtiene el texto de la operación
|
|
130
|
+
* @param {string} operation - Tipo de operación
|
|
131
|
+
* @returns {string}
|
|
132
|
+
*/
|
|
133
|
+
getOperationText(operation) {
|
|
134
|
+
const operations = {
|
|
135
|
+
'refresh': 'Refrescando tablas',
|
|
136
|
+
'seeder': 'Ejecutando seeders',
|
|
137
|
+
'trigger': 'Ejecutando triggers'
|
|
138
|
+
};
|
|
139
|
+
return operations[operation] || operation;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Limpia la pantalla y muestra encabezado
|
|
144
|
+
* @param {string} title - Título principal
|
|
145
|
+
* @param {string} emoji - Emoji a mostrar
|
|
146
|
+
*/
|
|
147
|
+
showHeader(title, emoji = '🔄') {
|
|
148
|
+
console.clear();
|
|
149
|
+
console.log(`\n${emoji} ${chalk.green.bold(title)}`);
|
|
150
|
+
console.log(chalk.gray('─'.repeat(50)));
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
module.exports = ProgressIndicator;
|
package/src/utils/FileUtils.js
CHANGED
|
@@ -51,7 +51,7 @@ class FileUtils {
|
|
|
51
51
|
const fullPath = path.join(currentDir, entry.name);
|
|
52
52
|
if (entry.isDirectory()) {
|
|
53
53
|
recurse(fullPath);
|
|
54
|
-
} else if (entry.isFile() && entry.name.endsWith(suffix)) {
|
|
54
|
+
} else if (entry.isFile() && (entry.name.endsWith(suffix) || entry.name.includes(suffix))) {
|
|
55
55
|
cubeFiles.push(fullPath); // Ya es absoluta
|
|
56
56
|
}
|
|
57
57
|
}
|