@dbcube/schema-builder 1.0.7 → 1.0.9

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