utn-cli 2.0.51 → 2.0.53

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.
@@ -229,6 +229,7 @@ export async function addServiceBackend(nombreServicio = null, opciones = { cerr
229
229
  // Si tenemos información de la tabla, generamos el CRUD
230
230
  if (tableInfo) {
231
231
  generarCRUDBackend(newServicioPath, newRutaPath, Servicio, tableInfo);
232
+ actualizarArchivoRest(Servicio, tableInfo);
232
233
  }
233
234
 
234
235
  // Reemplazar el título amigable si se proporciona
@@ -392,6 +393,68 @@ Router.get('/reporte', async (solicitud, respuesta, next) => {
392
393
  fs.writeFileSync(rutaPath, contenidoRutas);
393
394
  }
394
395
 
396
+ function actualizarArchivoRest(nombreServicio, tableInfo) {
397
+ const archivos = fs.readdirSync(process.cwd());
398
+ const archivoRest = archivos.find(f => f.endsWith('.rest'));
399
+
400
+ if (!archivoRest) return;
401
+
402
+ const { columns, primaryKey } = tableInfo;
403
+ const nombreServicioLower = nombreServicio.toLowerCase();
404
+
405
+ // Crear objeto de ejemplo para agregar/actualizar
406
+ const ejemploCuerpo = {};
407
+ columns.forEach(col => {
408
+ ejemploCuerpo[col.name] = col.type.includes('INT') ? 1 : 'Ejemplo';
409
+ });
410
+
411
+ const nuevoContenido = `
412
+ #
413
+ # Rutas del servicio ${nombreServicio}
414
+ #
415
+
416
+ ### Listar registros
417
+ GET {{ BASE_URL }}/${nombreServicio}/listar HTTP/1.1
418
+ Authorization: Bearer {{ AUTH_TOKEN }}
419
+ Content-Type: application/json
420
+ Origin: {{ BASE_URL }}
421
+
422
+ ### Agregar registro
423
+ POST {{ BASE_URL }}/${nombreServicio}/agregar HTTP/1.1
424
+ Authorization: Bearer {{ AUTH_TOKEN }}
425
+ Content-Type: application/json
426
+ Origin: {{ BASE_URL }}
427
+
428
+ ${JSON.stringify(ejemploCuerpo, null, 2)}
429
+
430
+ ### Actualizar registro
431
+ POST {{ BASE_URL }}/${nombreServicio}/actualizar HTTP/1.1
432
+ Authorization: Bearer {{ AUTH_TOKEN }}
433
+ Content-Type: application/json
434
+ Origin: {{ BASE_URL }}
435
+
436
+ ${JSON.stringify(ejemploCuerpo, null, 2)}
437
+
438
+ ### Borrar registro
439
+ POST {{ BASE_URL }}/${nombreServicio}/borrar HTTP/1.1
440
+ Authorization: Bearer {{ AUTH_TOKEN }}
441
+ Content-Type: application/json
442
+ Origin: {{ BASE_URL }}
443
+
444
+ {
445
+ "${primaryKey}": ${ejemploCuerpo[primaryKey] ? (typeof ejemploCuerpo[primaryKey] === 'number' ? ejemploCuerpo[primaryKey] : '"' + ejemploCuerpo[primaryKey] + '"') : 1}
446
+ }
447
+
448
+ ### Generar reporte CSV
449
+ GET {{ BASE_URL }}/${nombreServicio}/reporte HTTP/1.1
450
+ Authorization: Bearer {{ AUTH_TOKEN }}
451
+ Content-Type: application/json
452
+ Origin: {{ BASE_URL }}
453
+ `;
454
+
455
+ fs.appendFileSync(archivoRest, nuevoContenido);
456
+ }
457
+
395
458
  export function showBackendVersion() {
396
459
  mostrarVersion(path.join(__dirname, '../package.json'));
397
460
  closeReadLine();
@@ -79,49 +79,71 @@ export async function createComponent() {
79
79
  function findTableByComment(sqlPath, serviceTitle) {
80
80
  const content = fs.readFileSync(sqlPath, 'utf-8');
81
81
 
82
- // Regex para encontrar tablas y sus comentarios
83
- // Buscamos CREATE OR REPLACE TABLE `db`.`table` ... COMMENT = '...serviceTitle...'
84
- const tableRegex = /CREATE OR REPLACE TABLE `(.+?)`\.`(.+?)` \(([\s\S]+?)\) ENGINE = InnoDB.+?COMMENT = '.*?(?:servicio de |almacena los datos del servicio de |almacena los datos del servicio de: )?([\s\S]+?)';/gi;
82
+ // Dividir el archivo por cada definición de tabla
83
+ const tableBlocks = content.split(/CREATE OR REPLACE TABLE/i).slice(1);
85
84
 
86
- let match;
87
- while ((match = tableRegex.exec(content)) !== null) {
88
- const dbName = match[1];
89
- const tableName = match[2];
90
- const tableBody = match[3];
91
- const tableComment = match[4].trim();
85
+ for (const block of tableBlocks) {
86
+ // Reconstruir el inicio para facilitar el regex
87
+ const fullBlock = 'CREATE OR REPLACE TABLE' + block;
88
+
89
+ // Regex para extraer DB, Tabla, Cuerpo y Comentario de este bloque específico
90
+ const tableRegex = /CREATE OR REPLACE TABLE `(.+?)`\.`(.+?)` \(([\s\S]+?)\) ENGINE = InnoDB.+?COMMENT = '([\s\S]+?)';/gi;
91
+ const match = tableRegex.exec(fullBlock);
92
+
93
+ if (match) {
94
+ const dbName = match[1];
95
+ const tableName = match[2];
96
+ const tableBody = match[3];
97
+ const tableComment = match[4].trim();
92
98
 
93
- // Si el comentario coincide con el título del servicio
94
- if (tableComment.toLowerCase().includes(serviceTitle.toLowerCase()) || serviceTitle.toLowerCase().includes(tableComment.toLowerCase())) {
95
- const columns = [];
96
- let primaryKey = '';
99
+ // Verificar si el comentario coincide con el título del servicio
100
+ if (tableComment.toLowerCase().includes(serviceTitle.toLowerCase()) || serviceTitle.toLowerCase().includes(tableComment.toLowerCase())) {
101
+ const columns = [];
102
+ let primaryKey = '';
97
103
 
98
- // Extraer columnas
99
- const colRegex = /`(.+?)` (.+?)(?: COMMENT '(.+?)')?,/g;
100
- let colMatch;
101
- while ((colMatch = colRegex.exec(tableBody)) !== null) {
102
- const colName = colMatch[1];
103
- if (colName !== 'LastUpdate' && colName !== 'LastUser') {
104
- columns.push({
105
- name: colName,
106
- type: colMatch[2],
107
- alias: colMatch[3] || colName
108
- });
104
+ // Limpiar el cuerpo para procesar líneas individualmente
105
+ const lines = tableBody.split('\n').map(l => l.trim()).filter(l => l.length > 0);
106
+
107
+ for (const line of lines) {
108
+ // Ignorar líneas que no definen columnas reales (PRIMARY KEY, KEY, CONSTRAINT)
109
+ if (line.toUpperCase().startsWith('PRIMARY KEY')) {
110
+ const pkMatch = line.match(/PRIMARY KEY \(`(.+?)`\)/i);
111
+ if (pkMatch) primaryKey = pkMatch[1];
112
+ continue;
113
+ }
114
+ if (line.toUpperCase().startsWith('KEY') || line.toUpperCase().startsWith('CONSTRAINT') || line.toUpperCase().startsWith('UNIQUE')) {
115
+ continue;
116
+ }
117
+
118
+ // Regex para extraer nombre de columna, tipo y comentario
119
+ const colMatch = line.match(/^`(.+?)` (.+?)(?: COMMENT '(.+?)')?,?$/i);
120
+ if (colMatch) {
121
+ const colName = colMatch[1];
122
+ // Excluir metadatos automáticos
123
+ if (colName !== 'LastUpdate' && colName !== 'LastUser') {
124
+ columns.push({
125
+ name: colName,
126
+ type: colMatch[2].replace(/,$/, ''), // Limpiar coma final si existe
127
+ alias: colMatch[3] || colName
128
+ });
129
+ }
130
+ }
109
131
  }
110
- }
111
132
 
112
- // Extraer Primary Key
113
- const pkMatch = tableBody.match(/PRIMARY KEY \(`(.+?)`\)/);
114
- if (pkMatch) {
115
- primaryKey = pkMatch[1];
116
- }
133
+ // Si no se encontró PK en las líneas, buscarla de nuevo con un regex más flexible en todo el cuerpo
134
+ if (!primaryKey) {
135
+ const pkMatch = tableBody.match(/PRIMARY KEY \(`(.+?)`\)/i);
136
+ if (pkMatch) primaryKey = pkMatch[1];
137
+ }
117
138
 
118
- return {
119
- dbName,
120
- tableName,
121
- columns,
122
- primaryKey,
123
- serviceTitle
124
- };
139
+ return {
140
+ dbName,
141
+ tableName,
142
+ columns,
143
+ primaryKey,
144
+ serviceTitle
145
+ };
146
+ }
125
147
  }
126
148
  }
127
149
  return null;
@@ -219,18 +219,6 @@ function personalizarComponenteFrontend(contenido, tableInfo, nombreServicioLowe
219
219
  return contenido;
220
220
  }
221
221
 
222
- console.log('Tarjeta agregada exitosamente.');
223
- } else {
224
- console.error('No se encontró un </div> de cierre en el HTML del contenedor principal.');
225
- }
226
- } else {
227
- console.error(`No se encontró el archivo HTML en: ${rutaHtml}`);
228
- }
229
- if (opciones.cerrarAlFinalizar) {
230
- closeReadLine();
231
- }
232
- }
233
-
234
222
  export function showFrontendVersion() {
235
223
  mostrarVersion(path.join(__dirname, '../package.json'));
236
224
  closeReadLine();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "utn-cli",
3
- "version": "2.0.51",
3
+ "version": "2.0.53",
4
4
  "description": "Herramienta CLI unificada para la gestión de plantillas en SIGU.",
5
5
  "main": "index.js",
6
6
  "type": "module",