@dbcube/schema-builder 1.0.8 → 1.0.10

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/dist/index.cjs CHANGED
@@ -88,7 +88,7 @@ var FileUtils = class {
88
88
  const fullPath = path.join(currentDir, entry.name);
89
89
  if (entry.isDirectory()) {
90
90
  recurse(fullPath);
91
- } else if (entry.isFile() && (entry.name.endsWith(suffix) || entry.name.includes(suffix))) {
91
+ } else if (entry.isFile() && entry.name.endsWith(suffix)) {
92
92
  cubeFiles.push(fullPath);
93
93
  }
94
94
  }
@@ -101,32 +101,189 @@ var FileUtils = class {
101
101
  });
102
102
  return cubeFiles;
103
103
  }
104
+ /**
105
+ * Extrae nombres de tablas reales de archivos .cube
106
+ * @param {string} filePath - String ruta del archivo .cube
107
+ * @returns {object} - Objeto que contiene el estado y el mensaje con el nombre de la tabla
108
+ */
109
+ static extracTableNameFromCube(filePath) {
110
+ try {
111
+ const content = fs.readFileSync(filePath, "utf8");
112
+ const metaMatch = content.match(/@meta\s*\(\s*\{\s*name\s*:\s*["']([^"']+)["']\s*;\s*[^}]*\}\s*\)/s);
113
+ if (metaMatch) {
114
+ return {
115
+ status: 200,
116
+ message: metaMatch[1]
117
+ };
118
+ }
119
+ throw new Error(`Error to execute this file ${filePath} because no exist a name of table.`);
120
+ } catch (error) {
121
+ if (error instanceof Error) {
122
+ return {
123
+ status: 500,
124
+ message: error.message
125
+ };
126
+ }
127
+ return {
128
+ status: 500,
129
+ message: String(error)
130
+ };
131
+ }
132
+ }
104
133
  };
105
134
  var FileUtils_default = FileUtils;
106
135
 
136
+ // src/lib/UIUtils.ts
137
+ var import_chalk = __toESM(require("chalk"));
138
+ var UIUtils = class {
139
+ /**
140
+ * Shows animated progress for processing items
141
+ */
142
+ static async showItemProgress(itemName, current, total) {
143
+ const consoleWidth = process.stdout.columns || 80;
144
+ const prefix = `\u251C\u2500 ${itemName} `;
145
+ const suffix = ` \u2713 OK`;
146
+ const availableSpace = consoleWidth - prefix.length - suffix.length;
147
+ const maxDots = Math.max(10, availableSpace);
148
+ return new Promise((resolve2) => {
149
+ process.stdout.write(`${import_chalk.default.blue("\u251C\u2500")} ${import_chalk.default.cyan(itemName)} `);
150
+ let dotCount = 0;
151
+ const interval = setInterval(() => {
152
+ if (dotCount < maxDots) {
153
+ process.stdout.write(import_chalk.default.gray("."));
154
+ dotCount++;
155
+ } else {
156
+ clearInterval(interval);
157
+ resolve2();
158
+ }
159
+ }, 10);
160
+ });
161
+ }
162
+ /**
163
+ * Shows success for a processed item
164
+ */
165
+ static showItemSuccess(itemName) {
166
+ process.stdout.write(` ${import_chalk.default.green("\u2713")} ${import_chalk.default.gray("OK")}
167
+ `);
168
+ }
169
+ /**
170
+ * Shows error for an item
171
+ */
172
+ static showItemError(itemName, error) {
173
+ process.stdout.write(` ${import_chalk.default.red("\u2717")} ${import_chalk.default.red("ERROR")}
174
+ `);
175
+ console.log(`${import_chalk.default.red("\u2502 ")} ${import_chalk.default.gray("\u2514\u2500")} ${import_chalk.default.red(error)}`);
176
+ }
177
+ /**
178
+ * Shows operation header
179
+ */
180
+ static showOperationHeader(operationName, databaseName, icon = "\u{1F5D1}\uFE0F") {
181
+ console.log(`
182
+ ${import_chalk.default.cyan(icon)} ${import_chalk.default.bold.green(operationName.toUpperCase())}`);
183
+ console.log(import_chalk.default.gray("\u2500".repeat(60)));
184
+ console.log(`${import_chalk.default.blue("\u250C\u2500")} ${import_chalk.default.bold(`Database: ${databaseName}`)}`);
185
+ }
186
+ /**
187
+ * Shows comprehensive operation summary
188
+ */
189
+ static showOperationSummary(summary) {
190
+ const { startTime, totalProcessed, successCount, errorCount, processedItems, operationName, databaseName } = summary;
191
+ const totalTime = ((Date.now() - startTime) / 1e3).toFixed(1);
192
+ console.log(`
193
+ ${import_chalk.default.cyan("\u{1F4CA}")} ${import_chalk.default.bold.green(`SUMMARY OF ${operationName.toUpperCase()}`)}`);
194
+ console.log(import_chalk.default.gray("\u2500".repeat(60)));
195
+ if (successCount > 0) {
196
+ console.log(`${import_chalk.default.green("\u250C\u2500")} ${import_chalk.default.bold("Successful processing:")}`);
197
+ console.log(`${import_chalk.default.green("\u251C\u2500")} ${import_chalk.default.cyan(`Items processed: ${successCount}`)}`);
198
+ console.log(`${import_chalk.default.green("\u251C\u2500")} ${import_chalk.default.gray(`Database: ${databaseName}`)}`);
199
+ if (processedItems.length > 0) {
200
+ console.log(`${import_chalk.default.green("\u251C\u2500")} ${import_chalk.default.yellow("Items updated:")}`);
201
+ processedItems.forEach((item, index) => {
202
+ const isLast = index === processedItems.length - 1;
203
+ const connector = isLast ? "\u2514\u2500" : "\u251C\u2500";
204
+ console.log(`${import_chalk.default.green("\u2502 ")} ${import_chalk.default.gray(connector)} ${import_chalk.default.cyan(item)}`);
205
+ });
206
+ }
207
+ }
208
+ if (errorCount > 0) {
209
+ console.log(`${import_chalk.default.red("\u251C\u2500")} ${import_chalk.default.bold.red(`Errors: ${errorCount}`)}`);
210
+ }
211
+ console.log(`${import_chalk.default.blue("\u251C\u2500")} ${import_chalk.default.gray(`Total time: ${totalTime}s`)}`);
212
+ console.log(`${import_chalk.default.blue("\u2514\u2500")} ${import_chalk.default.bold(totalProcessed > 0 ? import_chalk.default.green("\u2705 Completed") : import_chalk.default.yellow("\u26A0\uFE0F No changes"))}`);
213
+ if (totalProcessed > 0) {
214
+ console.log(`
215
+ ${import_chalk.default.green("\u{1F389}")} ${import_chalk.default.bold(`${operationName} executed successfully!`)}`);
216
+ } else {
217
+ console.log(`
218
+ ${import_chalk.default.yellow("\u26A0\uFE0F ")} ${import_chalk.default.bold("No items were processed.")}`);
219
+ }
220
+ console.log("");
221
+ }
222
+ };
223
+
107
224
  // src/lib/Schema.ts
108
225
  var Schema = class {
109
226
  name;
110
227
  engine;
111
228
  constructor(name) {
112
229
  this.name = name;
113
- const engine = new import_core.Engine(name);
114
- this.engine = engine;
230
+ this.engine = new import_core.Engine(name);
115
231
  }
116
232
  async createDatabase() {
233
+ const startTime = Date.now();
117
234
  const rootPath = import_path.default.resolve(process.cwd());
118
- const response = await this.engine.run("schema_engine", [
119
- "--action",
120
- "create_database",
121
- "--path",
122
- rootPath
123
- ]);
124
- if (response.status != 200) {
125
- returnFormattedError(response.status, response.message);
235
+ UIUtils.showOperationHeader("CREATING DATABASE", this.name, "\u{1F5C4}\uFE0F");
236
+ await UIUtils.showItemProgress("Database", 1, 1);
237
+ try {
238
+ const response = await this.engine.run("schema_engine", [
239
+ "--action",
240
+ "create_database",
241
+ "--path",
242
+ rootPath
243
+ ]);
244
+ if (response.status != 200) {
245
+ UIUtils.showItemError("Database", `Error creating: ${response.message}`);
246
+ const summary2 = {
247
+ startTime,
248
+ totalProcessed: 0,
249
+ successCount: 0,
250
+ errorCount: 1,
251
+ processedItems: [],
252
+ operationName: "create database",
253
+ databaseName: this.name
254
+ };
255
+ UIUtils.showOperationSummary(summary2);
256
+ returnFormattedError(response.status, response.message);
257
+ }
258
+ UIUtils.showItemSuccess("Database");
259
+ const summary = {
260
+ startTime,
261
+ totalProcessed: 1,
262
+ successCount: 1,
263
+ errorCount: 0,
264
+ processedItems: [this.name],
265
+ operationName: "create database",
266
+ databaseName: this.name
267
+ };
268
+ UIUtils.showOperationSummary(summary);
269
+ return response.data;
270
+ } catch (error) {
271
+ UIUtils.showItemError("Database", error.message);
272
+ const summary = {
273
+ startTime,
274
+ totalProcessed: 0,
275
+ successCount: 0,
276
+ errorCount: 1,
277
+ processedItems: [],
278
+ operationName: "create database",
279
+ databaseName: this.name
280
+ };
281
+ UIUtils.showOperationSummary(summary);
282
+ throw error;
126
283
  }
127
- return response.data;
128
284
  }
129
285
  async refreshTables() {
286
+ const startTime = Date.now();
130
287
  const cubesDir = import_path.default.join(process.cwd(), "dbcube", "cubes");
131
288
  if (!import_fs.default.existsSync(cubesDir)) {
132
289
  throw new Error("\u274C The cubes folder does not exist");
@@ -134,11 +291,21 @@ var Schema = class {
134
291
  const cubeFiles = FileUtils_default.getCubeFilesRecursively("dbcube", "table.cube");
135
292
  if (cubeFiles.length === 0) {
136
293
  throw new Error("\u274C There are no cubes to execute");
137
- } else {
138
- for (const file of cubeFiles) {
139
- const filePath = import_path.default.isAbsolute(file) ? file : import_path.default.join(cubesDir, file);
140
- const stats = import_fs.default.statSync(filePath);
141
- if (stats.isFile()) {
294
+ }
295
+ UIUtils.showOperationHeader("EXECUTING REFRESH TABLES", this.name, "\u{1F504}");
296
+ let totalTablesProcessed = 0;
297
+ let successCount = 0;
298
+ let errorCount = 0;
299
+ const processedTables = [];
300
+ for (let index = 0; index < cubeFiles.length; index++) {
301
+ const file = cubeFiles[index];
302
+ const filePath = import_path.default.isAbsolute(file) ? file : import_path.default.join(cubesDir, file);
303
+ const stats = import_fs.default.statSync(filePath);
304
+ if (stats.isFile()) {
305
+ const getTableName = FileUtils_default.extracTableNameFromCube(filePath);
306
+ const tableName = getTableName.status === 200 ? getTableName.message : import_path.default.basename(file, ".table.cube");
307
+ await UIUtils.showItemProgress(tableName, index + 1, cubeFiles.length);
308
+ try {
142
309
  const dml = await this.engine.run("schema_engine", [
143
310
  "--action",
144
311
  "parse_table",
@@ -148,7 +315,9 @@ var Schema = class {
148
315
  filePath
149
316
  ]);
150
317
  if (dml.status != 200) {
151
- returnFormattedError(dml.status, dml.message);
318
+ UIUtils.showItemError(tableName, `Error parsing: ${dml.message}`);
319
+ errorCount++;
320
+ continue;
152
321
  }
153
322
  const parseJson = JSON.stringify(dml.data.actions).replace(/[\r\n\t]/g, "").replace(/\\[rnt]/g, "").replace(/\s{2,}/g, " ");
154
323
  const queries = await this.engine.run("schema_engine", [
@@ -160,7 +329,9 @@ var Schema = class {
160
329
  parseJson
161
330
  ]);
162
331
  if (queries.status != 200) {
163
- returnFormattedError(queries.status, queries.message);
332
+ UIUtils.showItemError(tableName, `Error generating queries: ${queries.message}`);
333
+ errorCount++;
334
+ continue;
164
335
  }
165
336
  delete queries.data.database_type;
166
337
  const parseJsonQueries = JSON.stringify(queries.data);
@@ -173,17 +344,36 @@ var Schema = class {
173
344
  parseJsonQueries
174
345
  ]);
175
346
  if (response.status != 200) {
176
- returnFormattedError(response.status, response.message);
347
+ UIUtils.showItemError(tableName, `Error executing: ${response.message}`);
348
+ errorCount++;
349
+ continue;
177
350
  }
178
351
  const createQuery = queries.data.regular_queries.filter((q) => q.includes("CREATE"))[0];
179
352
  await import_core.TableProcessor.saveQuery(dml.data.table, dml.data.database, createQuery);
180
- return response.data;
353
+ UIUtils.showItemSuccess(tableName);
354
+ successCount++;
355
+ processedTables.push(tableName);
356
+ totalTablesProcessed++;
357
+ } catch (error) {
358
+ UIUtils.showItemError(tableName, error.message);
359
+ errorCount++;
181
360
  }
182
361
  }
183
362
  }
184
- return null;
363
+ const summary = {
364
+ startTime,
365
+ totalProcessed: totalTablesProcessed,
366
+ successCount,
367
+ errorCount,
368
+ processedItems: processedTables,
369
+ operationName: "refresh tables",
370
+ databaseName: this.name
371
+ };
372
+ UIUtils.showOperationSummary(summary);
373
+ return totalTablesProcessed > 0 ? { processed: totalTablesProcessed, success: successCount, errors: errorCount } : null;
185
374
  }
186
375
  async freshTables() {
376
+ const startTime = Date.now();
187
377
  const cubesDir = import_path.default.join(process.cwd(), "dbcube", "cubes");
188
378
  if (!import_fs.default.existsSync(cubesDir)) {
189
379
  throw new Error("\u274C The cubes folder does not exist");
@@ -191,11 +381,21 @@ var Schema = class {
191
381
  const cubeFiles = FileUtils_default.getCubeFilesRecursively("dbcube", "table.cube");
192
382
  if (cubeFiles.length === 0) {
193
383
  throw new Error("\u274C There are no cubes to execute");
194
- } else {
195
- for (const file of cubeFiles) {
196
- const filePath = import_path.default.isAbsolute(file) ? file : import_path.default.join(cubesDir, file);
197
- const stats = import_fs.default.statSync(filePath);
198
- if (stats.isFile()) {
384
+ }
385
+ UIUtils.showOperationHeader("EXECUTING FRESH TABLES", this.name);
386
+ let totalTablesProcessed = 0;
387
+ let successCount = 0;
388
+ let errorCount = 0;
389
+ const processedTables = [];
390
+ for (let index = 0; index < cubeFiles.length; index++) {
391
+ const file = cubeFiles[index];
392
+ const filePath = import_path.default.isAbsolute(file) ? file : import_path.default.join(cubesDir, file);
393
+ const stats = import_fs.default.statSync(filePath);
394
+ if (stats.isFile()) {
395
+ const getTableName = FileUtils_default.extracTableNameFromCube(filePath);
396
+ const tableName = getTableName.status === 200 ? getTableName.message : import_path.default.basename(file, ".table.cube");
397
+ await UIUtils.showItemProgress(tableName, index + 1, cubeFiles.length);
398
+ try {
199
399
  const dml = await this.engine.run("schema_engine", [
200
400
  "--action",
201
401
  "parse_table",
@@ -205,7 +405,9 @@ var Schema = class {
205
405
  "fresh"
206
406
  ]);
207
407
  if (dml.status != 200) {
208
- returnFormattedError(dml.status, dml.message);
408
+ UIUtils.showItemError(tableName, `Error parsing: ${dml.message}`);
409
+ errorCount++;
410
+ continue;
209
411
  }
210
412
  const parseJson = JSON.stringify(dml.data.actions).replace(/[\r\n\t]/g, "").replace(/\\[rnt]/g, "").replace(/\s{2,}/g, " ");
211
413
  const queries = await this.engine.run("schema_engine", [
@@ -215,7 +417,9 @@ var Schema = class {
215
417
  parseJson
216
418
  ]);
217
419
  if (queries.status != 200) {
218
- returnFormattedError(queries.status, queries.message);
420
+ UIUtils.showItemError(tableName, `Error generating queries: ${queries.message}`);
421
+ errorCount++;
422
+ continue;
219
423
  }
220
424
  delete queries.data._type;
221
425
  const createQuery = queries.data.regular_queries.filter((q) => q.includes("CREATE"))[0];
@@ -233,16 +437,35 @@ var Schema = class {
233
437
  parseJsonQueries
234
438
  ]);
235
439
  if (response.status != 200) {
236
- returnFormattedError(response.status, response.message);
440
+ UIUtils.showItemError(tableName, `Error executing: ${response.message}`);
441
+ errorCount++;
442
+ continue;
237
443
  }
238
444
  await import_core.TableProcessor.saveQuery(dml.data.table, dml.data.database, createQuery);
239
- return response.data;
445
+ UIUtils.showItemSuccess(tableName);
446
+ successCount++;
447
+ processedTables.push(tableName);
448
+ totalTablesProcessed++;
449
+ } catch (error) {
450
+ UIUtils.showItemError(tableName, error.message);
451
+ errorCount++;
240
452
  }
241
453
  }
242
454
  }
243
- return null;
455
+ const summary = {
456
+ startTime,
457
+ totalProcessed: totalTablesProcessed,
458
+ successCount,
459
+ errorCount,
460
+ processedItems: processedTables,
461
+ operationName: "fresh tables",
462
+ databaseName: this.name
463
+ };
464
+ UIUtils.showOperationSummary(summary);
465
+ return totalTablesProcessed > 0 ? { processed: totalTablesProcessed, success: successCount, errors: errorCount } : null;
244
466
  }
245
467
  async executeSeeders() {
468
+ const startTime = Date.now();
246
469
  const cubesDir = import_path.default.join(process.cwd(), "dbcube", "cubes");
247
470
  if (!import_fs.default.existsSync(cubesDir)) {
248
471
  throw new Error("\u274C The cubes folder does not exist");
@@ -250,11 +473,21 @@ var Schema = class {
250
473
  const cubeFiles = FileUtils_default.getCubeFilesRecursively("dbcube", "seeder.cube");
251
474
  if (cubeFiles.length === 0) {
252
475
  throw new Error("\u274C There are no cubes to execute");
253
- } else {
254
- for (const file of cubeFiles) {
255
- const filePath = import_path.default.isAbsolute(file) ? file : import_path.default.join(cubesDir, file);
256
- const stats = import_fs.default.statSync(filePath);
257
- if (stats.isFile()) {
476
+ }
477
+ UIUtils.showOperationHeader("EXECUTING SEEDERS", this.name, "\u{1F331}");
478
+ let totalSeedersProcessed = 0;
479
+ let successCount = 0;
480
+ let errorCount = 0;
481
+ const processedSeeders = [];
482
+ for (let index = 0; index < cubeFiles.length; index++) {
483
+ const file = cubeFiles[index];
484
+ const filePath = import_path.default.isAbsolute(file) ? file : import_path.default.join(cubesDir, file);
485
+ const stats = import_fs.default.statSync(filePath);
486
+ if (stats.isFile()) {
487
+ const getSeederName = FileUtils_default.extracTableNameFromCube(filePath);
488
+ const seederName = getSeederName.status === 200 ? getSeederName.message : import_path.default.basename(file, ".seeder.cube");
489
+ await UIUtils.showItemProgress(seederName, index + 1, cubeFiles.length);
490
+ try {
258
491
  const response = await this.engine.run("schema_engine", [
259
492
  "--action",
260
493
  "seeder",
@@ -262,15 +495,34 @@ var Schema = class {
262
495
  filePath
263
496
  ]);
264
497
  if (response.status != 200) {
265
- returnFormattedError(response.status, response.message);
498
+ UIUtils.showItemError(seederName, `Error executing: ${response.message}`);
499
+ errorCount++;
500
+ continue;
266
501
  }
267
- return response.data;
502
+ UIUtils.showItemSuccess(seederName);
503
+ successCount++;
504
+ processedSeeders.push(seederName);
505
+ totalSeedersProcessed++;
506
+ } catch (error) {
507
+ UIUtils.showItemError(seederName, error.message);
508
+ errorCount++;
268
509
  }
269
510
  }
270
511
  }
271
- return null;
512
+ const summary = {
513
+ startTime,
514
+ totalProcessed: totalSeedersProcessed,
515
+ successCount,
516
+ errorCount,
517
+ processedItems: processedSeeders,
518
+ operationName: "seeders",
519
+ databaseName: this.name
520
+ };
521
+ UIUtils.showOperationSummary(summary);
522
+ return totalSeedersProcessed > 0 ? { processed: totalSeedersProcessed, success: successCount, errors: errorCount } : null;
272
523
  }
273
524
  async executeTriggers() {
525
+ const startTime = Date.now();
274
526
  const cubesDir = import_path.default.join(process.cwd(), "dbcube", "cubes");
275
527
  const triggersDirExit = import_path.default.join(process.cwd(), "dbcube", "triggers");
276
528
  if (!import_fs.default.existsSync(cubesDir)) {
@@ -279,11 +531,21 @@ var Schema = class {
279
531
  const cubeFiles = FileUtils_default.getCubeFilesRecursively("dbcube", "trigger.cube");
280
532
  if (cubeFiles.length === 0) {
281
533
  throw new Error("\u274C There are no cubes to execute");
282
- } else {
283
- for (const file of cubeFiles) {
284
- const filePath = import_path.default.isAbsolute(file) ? file : import_path.default.join(cubesDir, file);
285
- const stats = import_fs.default.statSync(filePath);
286
- if (stats.isFile()) {
534
+ }
535
+ UIUtils.showOperationHeader("EXECUTING TRIGGERS", this.name, "\u26A1");
536
+ let totalTriggersProcessed = 0;
537
+ let successCount = 0;
538
+ let errorCount = 0;
539
+ const processedTriggers = [];
540
+ for (let index = 0; index < cubeFiles.length; index++) {
541
+ const file = cubeFiles[index];
542
+ const filePath = import_path.default.isAbsolute(file) ? file : import_path.default.join(cubesDir, file);
543
+ const stats = import_fs.default.statSync(filePath);
544
+ if (stats.isFile()) {
545
+ const getTriggerName = FileUtils_default.extracTableNameFromCube(filePath);
546
+ const triggerName = getTriggerName.status === 200 ? getTriggerName.message : import_path.default.basename(file, ".trigger.cube");
547
+ await UIUtils.showItemProgress(triggerName, index + 1, cubeFiles.length);
548
+ try {
287
549
  const response = await this.engine.run("schema_engine", [
288
550
  "--action",
289
551
  "trigger",
@@ -293,13 +555,31 @@ var Schema = class {
293
555
  filePath
294
556
  ]);
295
557
  if (response.status != 200) {
296
- returnFormattedError(response.status, response.message);
558
+ UIUtils.showItemError(triggerName, `Error executing: ${response.message}`);
559
+ errorCount++;
560
+ continue;
297
561
  }
298
- return response.data;
562
+ UIUtils.showItemSuccess(triggerName);
563
+ successCount++;
564
+ processedTriggers.push(triggerName);
565
+ totalTriggersProcessed++;
566
+ } catch (error) {
567
+ UIUtils.showItemError(triggerName, error.message);
568
+ errorCount++;
299
569
  }
300
570
  }
301
571
  }
302
- return null;
572
+ const summary = {
573
+ startTime,
574
+ totalProcessed: totalTriggersProcessed,
575
+ successCount,
576
+ errorCount,
577
+ processedItems: processedTriggers,
578
+ operationName: "triggers",
579
+ databaseName: this.name
580
+ };
581
+ UIUtils.showOperationSummary(summary);
582
+ return totalTriggersProcessed > 0 ? { processed: totalTriggersProcessed, success: successCount, errors: errorCount } : null;
303
583
  }
304
584
  };
305
585
  function returnFormattedError(status, message) {