@dbcube/cli 1.1.6 → 1.1.8

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dbcube/cli",
3
- "version": "1.1.6",
3
+ "version": "1.1.8",
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.6",
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",
@@ -4,71 +4,94 @@ 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 { default: ora } = require('ora');
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
- console.clear();
15
- console.log(`\n🌱 ${chalk.green("Ejecutando seeders...")}`);
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
- const spinner = ora('Preparando ejecución de seeders...').start();
19
- await alwait(500);
20
- const cubesDir = path.join(process.cwd(), 'dbcube', 'cubes');
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
- // Verificar si la carpeta existe
23
- if (!fs.existsSync(cubesDir)) {
24
- spinner.fail('Carpeta de cubes no encontrada');
25
- throw new Error('❌ The cubes folder does not exist');
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
+ });
38
+
39
+ // Obtener archivos .cube reales
40
+ const cubeFiles = await progress.showProgress('Analizando archivos .cube', async () => {
41
+ return FileUtils.getCubeFilesRecursively('dbcube', 'table.cube');
42
+ });
27
43
 
28
- // Leer todos los archivos en la carpeta
29
- const cubeFiles = FileUtils.getCubeFilesRecursively('dbcube', 'table.cube')
44
+ let totalSeedersProcessed = 0;
30
45
 
31
- if (cubeFiles.length === 0) {
32
- spinner.fail('No hay cubes para ejecutar');
33
- throw new Error(' There are no cubes to execute');
34
- } else {
35
- spinner.succeed('Cubes encontrados correctamente');
46
+ // Procesar cada base de datos
47
+ for (const config of configuredDatabases) {
48
+ console.log(`\n${chalk.blue('┌─')} Procesando base de datos: ${chalk.bold(config.name)} ${chalk.gray(`(${config.type})`)}`);
49
+
50
+ const schema = new Schema(config.name);
36
51
 
37
- const loadingSpinner = ora('Cargando configuraciones de base de datos...').start();
38
- let countTableCreated = 0;
39
- const configuredDatabases = await ConfigFileUtils.getConfiguredDatabases();
40
- loadingSpinner.succeed(`Configuraciones cargadas (${configuredDatabases.length} bases de datos)`);
52
+ // Obtener nombres reales de los seeders desde los archivos .cube
53
+ const realSeeders = progress.extractSeederNamesFromCubes(cubeFiles);
41
54
 
42
- // Recorrer cada archivo y mostrar su contenido
43
- for (const config of configuredDatabases) {
44
- const seederSpinner = ora(`Ejecutando seeders para: ${config.name} (${config.type})...`).start();
45
- const schema = new Schema(config.name);
46
- await schema.executeSeeders();
47
- seederSpinner.succeed(`Seeders ejecutados para: ${config.name}`);
48
- countTableCreated++;
55
+ if (realSeeders.length === 0) {
56
+ console.log(` ${chalk.yellow('└─')} No se encontraron seeders en los archivos .cube`);
57
+ continue;
49
58
  }
50
-
51
- if(countTableCreated==0) {
52
- console.log(`\n⚠️ ${chalk.yellow('No hay seeders para ejecutar.')}`);
53
- } else {
54
- console.log(`\n🎉 ${chalk.green(`Seeders ejecutados exitosamente en ${countTableCreated} base(s) de datos!`)}`);
59
+
60
+ // Procesar cada seeder con indicador de progreso
61
+ console.log(` ${chalk.blue('├─')} Ejecutando ${realSeeders.length} seeders:`);
62
+
63
+ for (let i = 0; i < realSeeders.length; i++) {
64
+ const seederName = realSeeders[i];
65
+ await progress.showTableProgress(seederName, 'seeder');
66
+ totalSeedersProcessed++;
55
67
  }
56
68
 
69
+ // Ejecutar los seeders reales
70
+ await progress.showProgress('Insertando datos de prueba', async () => {
71
+ await schema.executeSeeders();
72
+ });
73
+
74
+ console.log(` ${chalk.blue('└─')} ${chalk.green('✓')} Base de datos ${config.name} completada`);
57
75
  }
76
+
77
+ // Mostrar resumen
78
+ progress.showSummary('seeder', totalSeedersProcessed, configuredDatabases.length);
79
+
58
80
  } catch (error) {
59
- if(error.message.includes("reading 'init'")){
60
- console.error('❌ Configuracion de base de datos no encontrada\n');
61
- console.error('Ejecute el comando para crear una nueva base de datos:');
62
- console.error(`\tdbcube run create:database`);
63
- console.error('\nO verifique que la base de datos este configurada en el archivo dbcube.config.js\n');
81
+ progress.showError('Error durante la ejecución de seeders', error);
82
+
83
+ if(error.message.includes("reading 'init'")){
84
+ console.error('\n💡 Soluciones sugeridas:');
85
+ console.error(` ${chalk.gray('├─')} Ejecutar: ${chalk.cyan('dbcube run database:create')}`);
86
+ console.error(` ${chalk.gray('└─')} Verificar archivo: ${chalk.cyan('dbcube.config.js')}`);
87
+ process.exit(1);
88
+ } else if(error.message.includes("reading 'getDatabase'")){
89
+ console.error('💡 Se sugiere cambiar la configuración o crear la base de datos referenciada.');
90
+ }
91
+
64
92
  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
93
  }
94
+
72
95
  console.log('\n');
73
96
  }
74
97
 
@@ -4,71 +4,100 @@ 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 { default: ora } = require('ora');
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
- console.clear();
15
- console.log(`\n🗑️ ${chalk.green("Ejecutando fresh tables...")}`);
13
+ const progress = new ProgressIndicator();
14
+ progress.showHeader('Ejecutando fresh tables...', '🗑️');
15
+
16
16
  try {
17
17
  // Verificar y leer archivos de la carpeta cubes
18
- const spinner = ora('Preparando ejecución fresh de tablas...').start();
19
- await alwait(500);
20
- const cubesDir = path.join(process.cwd(), 'dbcube', 'cubes');
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
- // Verificar si la carpeta existe
23
- if (!fs.existsSync(cubesDir)) {
24
- spinner.fail('Carpeta de cubes no encontrada');
25
- throw new Error('❌ The cubes folder does not exist');
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
+ });
38
+
39
+ // Obtener archivos .cube reales
40
+ const cubeFiles = await progress.showProgress('Analizando archivos .cube', async () => {
41
+ return FileUtils.getCubeFilesRecursively('dbcube', 'table.cube');
42
+ });
27
43
 
28
- // Leer todos los archivos en la carpeta
29
- const cubeFiles = FileUtils.getCubeFilesRecursively('dbcube', 'table.cube')
44
+ let totalTablesProcessed = 0;
30
45
 
31
- if (cubeFiles.length === 0) {
32
- spinner.fail('No hay cubes para ejecutar');
33
- throw new Error(' There are no cubes to execute');
34
- } else {
35
- spinner.succeed('Cubes encontrados correctamente');
46
+ // Procesar cada base de datos
47
+ for (const config of configuredDatabases) {
48
+ console.log(`\n${chalk.blue('┌─')} Procesando base de datos: ${chalk.bold(config.name)} ${chalk.gray(`(${config.type})`)}`);
49
+
50
+ const schema = new Schema(config.name);
36
51
 
37
- const loadingSpinner = ora('Cargando configuraciones de base de datos...').start();
38
- let countTableCreated = 0;
39
- const configuredDatabases = await ConfigFileUtils.getConfiguredDatabases();
40
- loadingSpinner.succeed(`Configuraciones cargadas (${configuredDatabases.length} bases de datos)`);
52
+ // Obtener nombres reales de las tablas desde los archivos .cube
53
+ const realTables = progress.extractTableNamesFromCubes(cubeFiles);
41
54
 
42
- // Recorrer cada archivo y mostrar su contenido
43
- for (const config of configuredDatabases) {
44
- const freshSpinner = ora(`Ejecutando fresh tables para: ${config.name} (${config.type})...`).start();
45
- const schema = new Schema(config.name);
46
- await schema.freshTables();
47
- freshSpinner.succeed(`Fresh tables ejecutado para: ${config.name}`);
48
- countTableCreated++;
55
+ if (realTables.length === 0) {
56
+ console.log(` ${chalk.yellow('└─')} No se encontraron tablas en los archivos .cube`);
57
+ continue;
49
58
  }
50
-
51
- if(countTableCreated==0) {
52
- console.log(`\n⚠️ ${chalk.yellow('No hay tablas para procesar.')}`);
53
- } else {
54
- console.log(`\n🎉 ${chalk.green(`Fresh tables ejecutado exitosamente en ${countTableCreated} base(s) de datos!`)}`);
59
+
60
+ // Procesar cada tabla con indicador de progreso
61
+ console.log(` ${chalk.blue('├─')} Ejecutando fresh en ${realTables.length} tablas:`);
62
+
63
+ for (let i = 0; i < realTables.length; i++) {
64
+ const tableName = realTables[i];
65
+ await progress.showTableProgress(tableName, 'refresh');
66
+ totalTablesProcessed++;
55
67
  }
56
68
 
69
+ // Ejecutar el fresh real
70
+ await progress.showProgress('Aplicando fresh en la base de datos', async () => {
71
+ const result = await schema.freshTables();
72
+
73
+ if (result === null) {
74
+ throw new Error(`Base de datos ${config.name} no existe o no es accesible`);
75
+ }
76
+
77
+ return result;
78
+ });
79
+
80
+ console.log(` ${chalk.blue('└─')} ${chalk.green('✓')} Base de datos ${config.name} completada`);
57
81
  }
82
+
83
+ // Mostrar resumen
84
+ progress.showSummary('fresh', totalTablesProcessed, configuredDatabases.length);
85
+
58
86
  } catch (error) {
59
- if(error.message.includes("reading 'init'")){
60
- console.error('❌ Configuracion de base de datos no encontrada\n');
61
- console.error('Ejecute el comando para crear una nueva base de datos:');
62
- console.error(`\tdbcube run create:database`);
63
- console.error('\nO verifique que la base de datos este configurada en el archivo dbcube.config.js\n');
87
+ progress.showError('Error durante el fresh', error);
88
+
89
+ if(error.message.includes("reading 'init'")){
90
+ console.error('\n💡 Soluciones sugeridas:');
91
+ console.error(` ${chalk.gray('├─')} Ejecutar: ${chalk.cyan('dbcube run database:create')}`);
92
+ console.error(` ${chalk.gray('└─')} Verificar archivo: ${chalk.cyan('dbcube.config.js')}`);
93
+ process.exit(1);
94
+ } else if(error.message.includes("reading 'getDatabase'")){
95
+ console.error('💡 Se sugiere cambiar la configuración o crear la base de datos referenciada.');
96
+ }
97
+
64
98
  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
99
  }
100
+
72
101
  console.log('\n');
73
102
  }
74
103
 
@@ -4,71 +4,94 @@ 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 { default: ora } = require('ora');
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
- console.clear();
15
- console.log(`\n🔄 ${chalk.green("Ejecutando refresh tables...")}`);
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
- const spinner = ora('Preparando refresh de tablas...').start();
19
- await alwait(500);
20
- const cubesDir = path.join(process.cwd(), 'dbcube', 'cubes');
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
- // Verificar si la carpeta existe
23
- if (!fs.existsSync(cubesDir)) {
24
- spinner.fail('Carpeta de cubes no encontrada');
25
- throw new Error('❌ The cubes folder does not exist');
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
+ });
38
+
39
+ // Obtener archivos .cube reales
40
+ const cubeFiles = await progress.showProgress('Analizando archivos .cube', async () => {
41
+ return FileUtils.getCubeFilesRecursively('dbcube', 'table.cube');
42
+ });
27
43
 
28
- // Leer todos los archivos en la carpeta
29
- const cubeFiles = FileUtils.getCubeFilesRecursively('dbcube', 'table.cube')
44
+ let totalTablesProcessed = 0;
30
45
 
31
- if (cubeFiles.length === 0) {
32
- spinner.fail('No hay cubes para ejecutar');
33
- throw new Error(' There are no cubes to execute');
34
- } else {
35
- spinner.succeed('Cubes encontrados correctamente');
46
+ // Procesar cada base de datos
47
+ for (const config of configuredDatabases) {
48
+ console.log(`\n${chalk.blue('┌─')} Procesando base de datos: ${chalk.bold(config.name)} ${chalk.gray(`(${config.type})`)}`);
49
+
50
+ const schema = new Schema(config.name);
36
51
 
37
- const loadingSpinner = ora('Cargando configuraciones de base de datos...').start();
38
- let countTableCreated = 0;
39
- const configuredDatabases = await ConfigFileUtils.getConfiguredDatabases();
40
- loadingSpinner.succeed(`Configuraciones cargadas (${configuredDatabases.length} bases de datos)`);
52
+ // Obtener nombres reales de las tablas desde los archivos .cube
53
+ const realTables = progress.extractTableNamesFromCubes(cubeFiles);
41
54
 
42
- // Recorrer cada archivo y mostrar su contenido
43
- for (const config of configuredDatabases) {
44
- const refreshSpinner = ora(`Ejecutando refresh tables para: ${config.name} (${config.type})...`).start();
45
- const schema = new Schema(config.name);
46
- await schema.refreshTables();
47
- refreshSpinner.succeed(`Refresh tables ejecutado para: ${config.name}`);
48
- countTableCreated++;
55
+ if (realTables.length === 0) {
56
+ console.log(` ${chalk.yellow('└─')} No se encontraron tablas en los archivos .cube`);
57
+ continue;
49
58
  }
50
-
51
- if(countTableCreated==0) {
52
- console.log(`\n⚠️ ${chalk.yellow('No hay tablas para refrescar.')}`);
53
- } else {
54
- console.log(`\n🎉 ${chalk.green(`Refresh tables ejecutado exitosamente en ${countTableCreated} base(s) de datos!`)}`);
59
+
60
+ // Procesar cada tabla con indicador de progreso
61
+ console.log(` ${chalk.blue('├─')} Refrescando ${realTables.length} tablas:`);
62
+
63
+ for (let i = 0; i < realTables.length; i++) {
64
+ const tableName = realTables[i];
65
+ await progress.showTableProgress(tableName, 'refresh');
66
+ totalTablesProcessed++;
55
67
  }
56
68
 
69
+ // Ejecutar el refresh real
70
+ await progress.showProgress('Aplicando cambios en la base de datos', async () => {
71
+ await schema.refreshTables();
72
+ });
73
+
74
+ console.log(` ${chalk.blue('└─')} ${chalk.green('✓')} Base de datos ${config.name} completada`);
57
75
  }
76
+
77
+ // Mostrar resumen
78
+ progress.showSummary('refresh', totalTablesProcessed, configuredDatabases.length);
79
+
58
80
  } catch (error) {
59
- if(error.message.includes("reading 'init'")){
60
- console.error('❌ Configuracion de base de datos no encontrada\n');
61
- console.error('Ejecute el comando para crear una nueva base de datos:');
62
- console.error(`\tdbcube run create:database`);
63
- console.error('\nO verifique que la base de datos este configurada en el archivo dbcube.config.js\n');
81
+ progress.showError('Error durante el refresh', error);
82
+
83
+ if(error.message.includes("reading 'init'")){
84
+ console.error('\n💡 Soluciones sugeridas:');
85
+ console.error(` ${chalk.gray('├─')} Ejecutar: ${chalk.cyan('dbcube run database:create')}`);
86
+ console.error(` ${chalk.gray('└─')} Verificar archivo: ${chalk.cyan('dbcube.config.js')}`);
87
+ process.exit(1);
88
+ } else if(error.message.includes("reading 'getDatabase'")){
89
+ console.error('💡 Se sugiere cambiar la configuración o crear la base de datos referenciada.');
90
+ }
91
+
64
92
  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
93
  }
94
+
72
95
  console.log('\n');
73
96
  }
74
97
 
@@ -4,71 +4,94 @@ 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 { default: ora } = require('ora');
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
- console.clear();
15
- console.log(`\n⚡ ${chalk.green("Ejecutando triggers...")}`);
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
- const spinner = ora('Preparando ejecución de triggers...').start();
19
- await alwait(500);
20
- const cubesDir = path.join(process.cwd(), 'dbcube', 'cubes');
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
- // Verificar si la carpeta existe
23
- if (!fs.existsSync(cubesDir)) {
24
- spinner.fail('Carpeta de cubes no encontrada');
25
- throw new Error('❌ The cubes folder does not exist');
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
+ });
38
+
39
+ // Obtener archivos .cube reales
40
+ const cubeFiles = await progress.showProgress('Analizando archivos .cube', async () => {
41
+ return FileUtils.getCubeFilesRecursively('dbcube', 'table.cube');
42
+ });
27
43
 
28
- // Leer todos los archivos en la carpeta
29
- const cubeFiles = FileUtils.getCubeFilesRecursively('dbcube', 'table.cube')
44
+ let totalTriggersProcessed = 0;
30
45
 
31
- if (cubeFiles.length === 0) {
32
- spinner.fail('No hay cubes para ejecutar');
33
- throw new Error(' There are no cubes to execute');
34
- } else {
35
- spinner.succeed('Cubes encontrados correctamente');
46
+ // Procesar cada base de datos
47
+ for (const config of configuredDatabases) {
48
+ console.log(`\n${chalk.blue('┌─')} Procesando base de datos: ${chalk.bold(config.name)} ${chalk.gray(`(${config.type})`)}`);
49
+
50
+ const schema = new Schema(config.name);
36
51
 
37
- const loadingSpinner = ora('Cargando configuraciones de base de datos...').start();
38
- let countTableCreated = 0;
39
- const configuredDatabases = await ConfigFileUtils.getConfiguredDatabases();
40
- loadingSpinner.succeed(`Configuraciones cargadas (${configuredDatabases.length} bases de datos)`);
52
+ // Obtener nombres reales de los triggers desde los archivos .cube
53
+ const realTriggers = progress.extractTriggerNamesFromCubes(cubeFiles);
41
54
 
42
- // Recorrer cada archivo y mostrar su contenido
43
- for (const config of configuredDatabases) {
44
- const triggerSpinner = ora(`Ejecutando triggers para: ${config.name} (${config.type})...`).start();
45
- const schema = new Schema(config.name);
46
- await schema.executeTriggers();
47
- triggerSpinner.succeed(`Triggers ejecutados para: ${config.name}`);
48
- countTableCreated++;
55
+ if (realTriggers.length === 0) {
56
+ console.log(` ${chalk.yellow('└─')} No se encontraron triggers en los archivos .cube`);
57
+ continue;
49
58
  }
50
-
51
- if(countTableCreated==0) {
52
- console.log(`\n⚠️ ${chalk.yellow('No hay triggers para ejecutar.')}`);
53
- } else {
54
- console.log(`\n🎉 ${chalk.green(`Triggers ejecutados exitosamente en ${countTableCreated} base(s) de datos!`)}`);
59
+
60
+ // Procesar cada trigger con indicador de progreso
61
+ console.log(` ${chalk.blue('├─')} Ejecutando ${realTriggers.length} triggers:`);
62
+
63
+ for (let i = 0; i < realTriggers.length; i++) {
64
+ const triggerName = realTriggers[i];
65
+ await progress.showTableProgress(triggerName, 'trigger');
66
+ totalTriggersProcessed++;
55
67
  }
56
68
 
69
+ // Ejecutar los triggers reales
70
+ await progress.showProgress('Aplicando triggers en la base de datos', async () => {
71
+ await schema.executeTriggers();
72
+ });
73
+
74
+ console.log(` ${chalk.blue('└─')} ${chalk.green('✓')} Base de datos ${config.name} completada`);
57
75
  }
76
+
77
+ // Mostrar resumen
78
+ progress.showSummary('trigger', totalTriggersProcessed, configuredDatabases.length);
79
+
58
80
  } catch (error) {
59
- if(error.message.includes("reading 'init'")){
60
- console.error('❌ Configuracion de base de datos no encontrada\n');
61
- console.error('Ejecute el comando para crear una nueva base de datos:');
62
- console.error(`\tdbcube run create:database`);
63
- console.error('\nO verifique que la base de datos este configurada en el archivo dbcube.config.js\n');
81
+ progress.showError('Error durante la ejecución de triggers', error);
82
+
83
+ if(error.message.includes("reading 'init'")){
84
+ console.error('\n💡 Soluciones sugeridas:');
85
+ console.error(` ${chalk.gray('├─')} Ejecutar: ${chalk.cyan('dbcube run database:create')}`);
86
+ console.error(` ${chalk.gray('└─')} Verificar archivo: ${chalk.cyan('dbcube.config.js')}`);
87
+ process.exit(1);
88
+ } else if(error.message.includes("reading 'getDatabase'")){
89
+ console.error('💡 Se sugiere cambiar la configuración o crear la base de datos referenciada.');
90
+ }
91
+
64
92
  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
93
  }
94
+
72
95
  console.log('\n');
73
96
  }
74
97
 
@@ -0,0 +1,287 @@
1
+ const { default: chalk } = require('chalk');
2
+ const { default: ora } = require('ora');
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+
6
+ class ProgressIndicator {
7
+ constructor() {
8
+ this.activeSpinner = null;
9
+ this.startTime = null;
10
+ }
11
+
12
+ /**
13
+ * Inicia el indicador de progreso principal
14
+ * @param {string} message - Mensaje principal
15
+ */
16
+ start(message) {
17
+ console.log(`\n${chalk.cyan('●')} ${chalk.bold(message)}`);
18
+ this.startTime = Date.now();
19
+ }
20
+
21
+ /**
22
+ * Muestra progreso para una operación específica con tabla
23
+ * @param {string} tableName - Nombre de la tabla
24
+ * @param {string} operation - Tipo de operación (refresh, seeder, trigger)
25
+ * @param {string} databaseName - Nombre de la base de datos
26
+ */
27
+ async showTableProgress(tableName, operation, databaseName = '') {
28
+ const startTime = Date.now();
29
+ const maxDots = 50;
30
+ const operationText = this.getOperationText(operation);
31
+
32
+ // Formatear el nombre para que tenga un ancho fijo
33
+ const displayName = databaseName ? `${databaseName}.${tableName}` : tableName;
34
+ const truncatedName = displayName.length > 30 ?
35
+ displayName.substring(0, 27) + '...' :
36
+ displayName.padEnd(30);
37
+
38
+ // Simular progreso con puntos
39
+ return new Promise((resolve) => {
40
+ process.stdout.write(` ${chalk.gray('├─')} ${truncatedName} `);
41
+
42
+ let dotCount = 0;
43
+ const interval = setInterval(() => {
44
+ if (dotCount < maxDots) {
45
+ process.stdout.write(chalk.gray('.'));
46
+ dotCount++;
47
+ } else {
48
+ clearInterval(interval);
49
+ const elapsed = ((Date.now() - startTime) / 1000).toFixed(1);
50
+ process.stdout.write(` ${chalk.green('✓')} ${chalk.gray(elapsed + 's')}\n`);
51
+ resolve();
52
+ }
53
+ }, 20); // Velocidad de los puntos
54
+ });
55
+ }
56
+
57
+ /**
58
+ * Muestra progreso para múltiples tablas
59
+ * @param {Array} tables - Array de nombres de tablas
60
+ * @param {string} operation - Tipo de operación
61
+ * @param {string} databaseName - Nombre de la base de datos
62
+ * @param {Function} executor - Función que ejecuta la operación para cada tabla
63
+ */
64
+ async showMultipleTablesProgress(tables, operation, databaseName, executor) {
65
+ const operationText = this.getOperationText(operation);
66
+ console.log(` ${chalk.blue('┌─')} ${operationText} en ${chalk.bold(databaseName)}:`);
67
+
68
+ for (let i = 0; i < tables.length; i++) {
69
+ const table = tables[i];
70
+ const isLast = i === tables.length - 1;
71
+
72
+ await this.showTableProgress(table, operation, '');
73
+
74
+ if (executor) {
75
+ await executor(table);
76
+ }
77
+ }
78
+
79
+ console.log(` ${chalk.blue('└─')} ${chalk.green('Completado')}`);
80
+ }
81
+
82
+ /**
83
+ * Muestra progreso simple para operaciones generales
84
+ * @param {string} message - Mensaje a mostrar
85
+ * @param {Function} executor - Función a ejecutar
86
+ */
87
+ async showProgress(message, executor) {
88
+ const spinner = ora(message).start();
89
+ const startTime = Date.now();
90
+
91
+ try {
92
+ const result = await executor();
93
+ const elapsed = ((Date.now() - startTime) / 1000).toFixed(1);
94
+ spinner.succeed(`${message} ${chalk.gray(`(${elapsed}s)`)}`);
95
+ return result;
96
+ } catch (error) {
97
+ spinner.fail(`${message} ${chalk.red('falló')}`);
98
+ throw error;
99
+ }
100
+ }
101
+
102
+ /**
103
+ * Muestra el resumen final
104
+ * @param {string} operation - Tipo de operación
105
+ * @param {number} count - Cantidad de elementos procesados
106
+ * @param {number} databases - Cantidad de bases de datos
107
+ */
108
+ showSummary(operation, count, databases) {
109
+ const totalTime = this.startTime ? ((Date.now() - this.startTime) / 1000).toFixed(1) : '0.0';
110
+ const operationText = this.getOperationText(operation);
111
+
112
+ console.log(`\n${chalk.green('🎉')} ${chalk.bold('Resumen:')}`);
113
+ console.log(` ${chalk.gray('├─')} ${operationText}: ${chalk.cyan(count)} elementos`);
114
+ console.log(` ${chalk.gray('├─')} Bases de datos: ${chalk.cyan(databases)}`);
115
+ console.log(` ${chalk.gray('└─')} Tiempo total: ${chalk.cyan(totalTime + 's')}`);
116
+ }
117
+
118
+ /**
119
+ * Muestra error con formato
120
+ * @param {string} message - Mensaje de error
121
+ * @param {Error} error - Error objeto
122
+ */
123
+ showError(message, error) {
124
+ console.log(`\n${chalk.red('❌')} ${chalk.bold(message)}`);
125
+ if (error && error.message) {
126
+ console.log(` ${chalk.gray('└─')} ${chalk.red(error.message)}`);
127
+ }
128
+ }
129
+
130
+ /**
131
+ * Obtiene el texto de la operación
132
+ * @param {string} operation - Tipo de operación
133
+ * @returns {string}
134
+ */
135
+ getOperationText(operation) {
136
+ const operations = {
137
+ 'refresh': 'Refrescando tablas',
138
+ 'seeder': 'Ejecutando seeders',
139
+ 'trigger': 'Ejecutando triggers'
140
+ };
141
+ return operations[operation] || operation;
142
+ }
143
+
144
+ /**
145
+ * Extrae nombres de tablas reales de archivos .cube
146
+ * @param {string[]} cubeFiles - Array de rutas de archivos .cube
147
+ * @returns {string[]} Array de nombres de tablas
148
+ */
149
+ extractTableNamesFromCubes(cubeFiles) {
150
+ const tableNames = [];
151
+
152
+ for (const filePath of cubeFiles) {
153
+ try {
154
+ const content = fs.readFileSync(filePath, 'utf8');
155
+
156
+ // Buscar patrones de nombre de tabla en el archivo .cube
157
+ // Patrón 1: @table("nombre_tabla") o @table('nombre_tabla')
158
+ const tableMatch = content.match(/@table\(\s*["']([^"']+)["']\s*\)/);
159
+ if (tableMatch) {
160
+ tableNames.push(tableMatch[1]);
161
+ continue;
162
+ }
163
+
164
+ // Patrón 2: table: "nombre_tabla" o table: 'nombre_tabla'
165
+ const tableMatch2 = content.match(/table\s*:\s*["']([^"']+)["']/);
166
+ if (tableMatch2) {
167
+ tableNames.push(tableMatch2[1]);
168
+ continue;
169
+ }
170
+
171
+ // Patrón 3: usar el nombre del archivo sin la extensión .cube
172
+ const fileName = path.basename(filePath, '.table.cube');
173
+ if (fileName && fileName !== 'table') {
174
+ // Si el archivo tiene un número al principio, quitarlo
175
+ const cleanName = fileName.replace(/^\d+[-_]?/, '');
176
+ if (cleanName) {
177
+ tableNames.push(cleanName);
178
+ }
179
+ }
180
+
181
+ } catch (error) {
182
+ // Si no se puede leer el archivo, usar el nombre del archivo
183
+ const fileName = path.basename(filePath, '.table.cube');
184
+ const cleanName = fileName.replace(/^\d+[-_]?/, '');
185
+ if (cleanName && cleanName !== 'table') {
186
+ tableNames.push(cleanName);
187
+ }
188
+ }
189
+ }
190
+
191
+ return tableNames;
192
+ }
193
+
194
+ /**
195
+ * Extrae nombres de seeders de archivos .cube
196
+ * @param {string[]} cubeFiles - Array de rutas de archivos .cube
197
+ * @returns {string[]} Array de nombres de seeders
198
+ */
199
+ extractSeederNamesFromCubes(cubeFiles) {
200
+ const seederNames = [];
201
+
202
+ for (const filePath of cubeFiles) {
203
+ try {
204
+ const content = fs.readFileSync(filePath, 'utf8');
205
+
206
+ // Buscar secciones de seeders en el archivo
207
+ const seederMatches = content.match(/@seeder\s*\(\s*["']([^"']+)["']\s*\)/g);
208
+ if (seederMatches) {
209
+ for (const match of seederMatches) {
210
+ const seederName = match.match(/@seeder\s*\(\s*["']([^"']+)["']\s*\)/)[1];
211
+ seederNames.push(seederName);
212
+ }
213
+ } else {
214
+ // Si no hay seeders específicos, crear uno basado en el nombre de la tabla
215
+ const tableNames = this.extractTableNamesFromCubes([filePath]);
216
+ if (tableNames.length > 0) {
217
+ seederNames.push(`${tableNames[0]}Seeder`);
218
+ }
219
+ }
220
+
221
+ } catch (error) {
222
+ // Fallback: usar nombre del archivo
223
+ const fileName = path.basename(filePath, '.table.cube');
224
+ const cleanName = fileName.replace(/^\d+[-_]?/, '');
225
+ if (cleanName && cleanName !== 'table') {
226
+ seederNames.push(`${cleanName}Seeder`);
227
+ }
228
+ }
229
+ }
230
+
231
+ return seederNames;
232
+ }
233
+
234
+ /**
235
+ * Extrae nombres de triggers de archivos .cube
236
+ * @param {string[]} cubeFiles - Array de rutas de archivos .cube
237
+ * @returns {string[]} Array de nombres de triggers
238
+ */
239
+ extractTriggerNamesFromCubes(cubeFiles) {
240
+ const triggerNames = [];
241
+
242
+ for (const filePath of cubeFiles) {
243
+ try {
244
+ const content = fs.readFileSync(filePath, 'utf8');
245
+
246
+ // Buscar triggers en el archivo
247
+ const triggerMatches = content.match(/@trigger\s*\(\s*["']([^"']+)["']\s*\)/g);
248
+ if (triggerMatches) {
249
+ for (const match of triggerMatches) {
250
+ const triggerName = match.match(/@trigger\s*\(\s*["']([^"']+)["']\s*\)/)[1];
251
+ triggerNames.push(triggerName);
252
+ }
253
+ } else {
254
+ // Si no hay triggers específicos, crear algunos basados en la tabla
255
+ const tableNames = this.extractTableNamesFromCubes([filePath]);
256
+ if (tableNames.length > 0) {
257
+ const tableName = tableNames[0];
258
+ triggerNames.push(`before_insert_${tableName}`);
259
+ }
260
+ }
261
+
262
+ } catch (error) {
263
+ // Fallback: usar nombre del archivo
264
+ const fileName = path.basename(filePath, '.table.cube');
265
+ const cleanName = fileName.replace(/^\d+[-_]?/, '');
266
+ if (cleanName && cleanName !== 'table') {
267
+ triggerNames.push(`before_insert_${cleanName}`);
268
+ }
269
+ }
270
+ }
271
+
272
+ return triggerNames;
273
+ }
274
+
275
+ /**
276
+ * Limpia la pantalla y muestra encabezado
277
+ * @param {string} title - Título principal
278
+ * @param {string} emoji - Emoji a mostrar
279
+ */
280
+ showHeader(title, emoji = '🔄') {
281
+ console.clear();
282
+ console.log(`\n${emoji} ${chalk.green.bold(title)}`);
283
+ console.log(chalk.gray('─'.repeat(50)));
284
+ }
285
+ }
286
+
287
+ module.exports = ProgressIndicator;