@dbcube/schema-builder 1.0.14 → 1.0.16

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.js CHANGED
@@ -6,7 +6,7 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
6
6
  });
7
7
 
8
8
  // src/lib/Schema.ts
9
- import fs2 from "fs";
9
+ import fs3 from "fs";
10
10
  import { Engine, TableProcessor, Config as ConfigClass } from "@dbcube/core";
11
11
  import path2 from "path";
12
12
 
@@ -132,9 +132,13 @@ var FileUtils = class {
132
132
  };
133
133
  var FileUtils_default = FileUtils;
134
134
 
135
+ // src/lib/Schema.ts
136
+ import chalk2 from "chalk";
137
+
135
138
  // src/lib/UIUtils.ts
136
139
  import chalk from "chalk";
137
- var UIUtils = class {
140
+ import fs2 from "fs";
141
+ var UIUtils = class _UIUtils {
138
142
  /**
139
143
  * Shows animated progress for processing items
140
144
  */
@@ -166,12 +170,11 @@ var UIUtils = class {
166
170
  `);
167
171
  }
168
172
  /**
169
- * Shows error for an item
173
+ * Shows error for an item (simplified - only shows X)
170
174
  */
171
175
  static showItemError(itemName, error) {
172
- process.stdout.write(` ${chalk.red("\u2717")} ${chalk.red("ERROR")}
176
+ process.stdout.write(` ${chalk.red("\u2717")}
173
177
  `);
174
- console.log(`${chalk.red("\u2502 ")} ${chalk.gray("\u2514\u2500")} ${chalk.red(error)}`);
175
178
  }
176
179
  /**
177
180
  * Shows operation header
@@ -209,6 +212,46 @@ ${chalk.cyan("\u{1F4CA}")} ${chalk.bold.green(`SUMMARY OF ${operationName.toUppe
209
212
  }
210
213
  console.log(`${chalk.blue("\u251C\u2500")} ${chalk.gray(`Total time: ${totalTime}s`)}`);
211
214
  console.log(`${chalk.blue("\u2514\u2500")} ${chalk.bold(totalProcessed > 0 ? chalk.green("\u2705 Completed") : chalk.yellow("\u26A0\uFE0F No changes"))}`);
215
+ if (summary.errors && summary.errors.length > 0) {
216
+ console.log(`
217
+ ${chalk.red("\u{1F6AB}")} ${chalk.bold.red("ERRORS FOUND")}`);
218
+ console.log(chalk.red("\u2500".repeat(60)));
219
+ summary.errors.forEach((error, index) => {
220
+ console.log(`${chalk.red("[error]")} ${chalk.red(error.error)}`);
221
+ console.log("");
222
+ if (error.filePath) {
223
+ const location = error.lineNumber ? `${error.filePath}:${error.lineNumber}:7` : error.filePath;
224
+ console.log(`${chalk.cyan("[code]")} ${chalk.yellow(location)}`);
225
+ _UIUtils.showCodeContext(error.filePath, error.lineNumber || 1);
226
+ }
227
+ if (index < summary.errors.length - 1) {
228
+ console.log("");
229
+ }
230
+ });
231
+ }
232
+ }
233
+ /**
234
+ * Shows code context around an error location
235
+ */
236
+ static showCodeContext(filePath, lineNumber, contextLines = 2) {
237
+ try {
238
+ const content = fs2.readFileSync(filePath, "utf8");
239
+ const lines = content.split("\n");
240
+ const startLine = Math.max(0, lineNumber - contextLines - 1);
241
+ const endLine = Math.min(lines.length, lineNumber + contextLines);
242
+ for (let i = startLine; i < endLine; i++) {
243
+ const currentLineNum = i + 1;
244
+ const line = lines[i];
245
+ const lineNumStr = currentLineNum.toString().padStart(4, " ");
246
+ if (currentLineNum === lineNumber) {
247
+ console.log(`${chalk.gray(lineNumStr)} ${chalk.red("<-")} ${chalk.white(line)}`);
248
+ } else {
249
+ console.log(`${chalk.gray(lineNumStr)} ${chalk.white(line)}`);
250
+ }
251
+ }
252
+ } catch (error) {
253
+ console.log(chalk.gray(" (unable to show code context)"));
254
+ }
212
255
  }
213
256
  };
214
257
 
@@ -229,7 +272,15 @@ var Schema = class {
229
272
  try {
230
273
  const dbResult = FileUtils_default.extractDatabaseNameFromCube(filePath);
231
274
  if (dbResult.status !== 200) {
232
- throw new Error(`Error reading database directive from ${filePath}: ${dbResult.message}`);
275
+ return {
276
+ isValid: false,
277
+ error: {
278
+ itemName: path2.basename(filePath, path2.extname(filePath)),
279
+ error: `Error reading database directive: ${dbResult.message}`,
280
+ filePath,
281
+ lineNumber: this.findDatabaseLineNumber(filePath)
282
+ }
283
+ };
233
284
  }
234
285
  const cubeDbName = dbResult.message;
235
286
  const configInstance = new ConfigClass();
@@ -257,13 +308,44 @@ var Schema = class {
257
308
  } catch (e) {
258
309
  }
259
310
  const availableText = availableDbs.length > 0 ? availableDbs.join(", ") : "none found";
260
- throw new Error(`\u274C Database configuration '${cubeDbName}' from cube file '${path2.basename(filePath)}' not found in dbcube.config.js.
261
-
262
- Available databases: ${availableText}`);
311
+ return {
312
+ isValid: false,
313
+ error: {
314
+ itemName: path2.basename(filePath, path2.extname(filePath)),
315
+ error: `Database configuration '${cubeDbName}' not found in dbcube.config.js. Available: ${availableText}`,
316
+ filePath,
317
+ lineNumber: this.findDatabaseLineNumber(filePath)
318
+ }
319
+ };
263
320
  }
264
- return true;
321
+ return { isValid: true };
265
322
  } catch (error) {
266
- throw new Error(`Database configuration validation failed: ${error.message}`);
323
+ return {
324
+ isValid: false,
325
+ error: {
326
+ itemName: path2.basename(filePath, path2.extname(filePath)),
327
+ error: `Database configuration validation failed: ${error.message}`,
328
+ filePath,
329
+ lineNumber: this.findDatabaseLineNumber(filePath)
330
+ }
331
+ };
332
+ }
333
+ }
334
+ /**
335
+ * Finds the line number where @database directive is located
336
+ */
337
+ findDatabaseLineNumber(filePath) {
338
+ try {
339
+ const content = fs3.readFileSync(filePath, "utf8");
340
+ const lines = content.split("\n");
341
+ for (let i = 0; i < lines.length; i++) {
342
+ if (lines[i].includes("@database")) {
343
+ return i + 1;
344
+ }
345
+ }
346
+ return 1;
347
+ } catch {
348
+ return 1;
267
349
  }
268
350
  }
269
351
  async createDatabase() {
@@ -289,7 +371,8 @@ Available databases: ${availableText}`);
289
371
  errorCount: 0,
290
372
  processedItems: [this.name],
291
373
  operationName: "create database",
292
- databaseName: this.name
374
+ databaseName: this.name,
375
+ errors: []
293
376
  };
294
377
  UIUtils.showOperationSummary(summary);
295
378
  return response.data;
@@ -302,7 +385,8 @@ Available databases: ${availableText}`);
302
385
  errorCount: 1,
303
386
  processedItems: [],
304
387
  operationName: "create database",
305
- databaseName: this.name
388
+ databaseName: this.name,
389
+ errors: []
306
390
  };
307
391
  UIUtils.showOperationSummary(summary);
308
392
  throw error;
@@ -311,7 +395,7 @@ Available databases: ${availableText}`);
311
395
  async refreshTables() {
312
396
  const startTime = Date.now();
313
397
  const cubesDir = path2.join(process.cwd(), "dbcube", "cubes");
314
- if (!fs2.existsSync(cubesDir)) {
398
+ if (!fs3.existsSync(cubesDir)) {
315
399
  throw new Error("\u274C The cubes folder does not exist");
316
400
  }
317
401
  const cubeFiles = FileUtils_default.getCubeFilesRecursively("dbcube", "table.cube");
@@ -323,16 +407,23 @@ Available databases: ${availableText}`);
323
407
  let successCount = 0;
324
408
  let errorCount = 0;
325
409
  const processedTables = [];
410
+ const errors = [];
326
411
  for (let index = 0; index < cubeFiles.length; index++) {
327
412
  const file = cubeFiles[index];
328
413
  const filePath = path2.isAbsolute(file) ? file : path2.join(cubesDir, file);
329
- const stats = fs2.statSync(filePath);
414
+ const stats = fs3.statSync(filePath);
330
415
  if (stats.isFile()) {
331
416
  const getTableName = FileUtils_default.extracTableNameFromCube(filePath);
332
417
  const tableName = getTableName.status === 200 ? getTableName.message : path2.basename(file, ".table.cube");
333
418
  await UIUtils.showItemProgress(tableName, index + 1, cubeFiles.length);
334
419
  try {
335
- this.validateDatabaseConfiguration(filePath);
420
+ const validation = this.validateDatabaseConfiguration(filePath);
421
+ if (!validation.isValid && validation.error) {
422
+ UIUtils.showItemError(tableName, validation.error.error);
423
+ errors.push(validation.error);
424
+ errorCount++;
425
+ continue;
426
+ }
336
427
  const dml = await this.engine.run("schema_engine", [
337
428
  "--action",
338
429
  "parse_table",
@@ -379,7 +470,13 @@ Available databases: ${availableText}`);
379
470
  processedTables.push(tableName);
380
471
  totalTablesProcessed++;
381
472
  } catch (error) {
473
+ const processError = {
474
+ itemName: tableName,
475
+ error: error.message,
476
+ filePath
477
+ };
382
478
  UIUtils.showItemError(tableName, error.message);
479
+ errors.push(processError);
383
480
  errorCount++;
384
481
  }
385
482
  }
@@ -391,7 +488,8 @@ Available databases: ${availableText}`);
391
488
  errorCount,
392
489
  processedItems: processedTables,
393
490
  operationName: "refresh tables",
394
- databaseName: this.name
491
+ databaseName: this.name,
492
+ errors
395
493
  };
396
494
  UIUtils.showOperationSummary(summary);
397
495
  return totalTablesProcessed > 0 ? { processed: totalTablesProcessed, success: successCount, errors: errorCount } : null;
@@ -399,7 +497,7 @@ Available databases: ${availableText}`);
399
497
  async freshTables() {
400
498
  const startTime = Date.now();
401
499
  const cubesDir = path2.join(process.cwd(), "dbcube", "cubes");
402
- if (!fs2.existsSync(cubesDir)) {
500
+ if (!fs3.existsSync(cubesDir)) {
403
501
  throw new Error("\u274C The cubes folder does not exist");
404
502
  }
405
503
  const cubeFiles = FileUtils_default.getCubeFilesRecursively("dbcube", "table.cube");
@@ -411,16 +509,23 @@ Available databases: ${availableText}`);
411
509
  let successCount = 0;
412
510
  let errorCount = 0;
413
511
  const processedTables = [];
512
+ const errors = [];
414
513
  for (let index = 0; index < cubeFiles.length; index++) {
415
514
  const file = cubeFiles[index];
416
515
  const filePath = path2.isAbsolute(file) ? file : path2.join(cubesDir, file);
417
- const stats = fs2.statSync(filePath);
516
+ const stats = fs3.statSync(filePath);
418
517
  if (stats.isFile()) {
419
518
  const getTableName = FileUtils_default.extracTableNameFromCube(filePath);
420
519
  const tableName = getTableName.status === 200 ? getTableName.message : path2.basename(file, ".table.cube");
421
520
  await UIUtils.showItemProgress(tableName, index + 1, cubeFiles.length);
422
521
  try {
423
- this.validateDatabaseConfiguration(filePath);
522
+ const validation = this.validateDatabaseConfiguration(filePath);
523
+ if (!validation.isValid && validation.error) {
524
+ UIUtils.showItemError(tableName, validation.error.error);
525
+ errors.push(validation.error);
526
+ errorCount++;
527
+ continue;
528
+ }
424
529
  const dml = await this.engine.run("schema_engine", [
425
530
  "--action",
426
531
  "parse_table",
@@ -465,7 +570,13 @@ Available databases: ${availableText}`);
465
570
  processedTables.push(tableName);
466
571
  totalTablesProcessed++;
467
572
  } catch (error) {
573
+ const processError = {
574
+ itemName: tableName,
575
+ error: error.message,
576
+ filePath
577
+ };
468
578
  UIUtils.showItemError(tableName, error.message);
579
+ errors.push(processError);
469
580
  errorCount++;
470
581
  }
471
582
  }
@@ -477,7 +588,8 @@ Available databases: ${availableText}`);
477
588
  errorCount,
478
589
  processedItems: processedTables,
479
590
  operationName: "fresh tables",
480
- databaseName: this.name
591
+ databaseName: this.name,
592
+ errors
481
593
  };
482
594
  UIUtils.showOperationSummary(summary);
483
595
  return totalTablesProcessed > 0 ? { processed: totalTablesProcessed, success: successCount, errors: errorCount } : null;
@@ -485,7 +597,7 @@ Available databases: ${availableText}`);
485
597
  async executeSeeders() {
486
598
  const startTime = Date.now();
487
599
  const cubesDir = path2.join(process.cwd(), "dbcube", "cubes");
488
- if (!fs2.existsSync(cubesDir)) {
600
+ if (!fs3.existsSync(cubesDir)) {
489
601
  throw new Error("\u274C The cubes folder does not exist");
490
602
  }
491
603
  const cubeFiles = FileUtils_default.getCubeFilesRecursively("dbcube", "seeder.cube");
@@ -497,16 +609,23 @@ Available databases: ${availableText}`);
497
609
  let successCount = 0;
498
610
  let errorCount = 0;
499
611
  const processedSeeders = [];
612
+ const errors = [];
500
613
  for (let index = 0; index < cubeFiles.length; index++) {
501
614
  const file = cubeFiles[index];
502
615
  const filePath = path2.isAbsolute(file) ? file : path2.join(cubesDir, file);
503
- const stats = fs2.statSync(filePath);
616
+ const stats = fs3.statSync(filePath);
504
617
  if (stats.isFile()) {
505
618
  const getSeederName = FileUtils_default.extracTableNameFromCube(filePath);
506
619
  const seederName = getSeederName.status === 200 ? getSeederName.message : path2.basename(file, ".seeder.cube");
507
620
  await UIUtils.showItemProgress(seederName, index + 1, cubeFiles.length);
508
621
  try {
509
- this.validateDatabaseConfiguration(filePath);
622
+ const validation = this.validateDatabaseConfiguration(filePath);
623
+ if (!validation.isValid && validation.error) {
624
+ UIUtils.showItemError(seederName, validation.error.error);
625
+ errors.push(validation.error);
626
+ errorCount++;
627
+ continue;
628
+ }
510
629
  const response = await this.engine.run("schema_engine", [
511
630
  "--action",
512
631
  "seeder",
@@ -522,7 +641,13 @@ Available databases: ${availableText}`);
522
641
  processedSeeders.push(seederName);
523
642
  totalSeedersProcessed++;
524
643
  } catch (error) {
644
+ const processError = {
645
+ itemName: seederName,
646
+ error: error.message,
647
+ filePath
648
+ };
525
649
  UIUtils.showItemError(seederName, error.message);
650
+ errors.push(processError);
526
651
  errorCount++;
527
652
  }
528
653
  }
@@ -534,7 +659,8 @@ Available databases: ${availableText}`);
534
659
  errorCount,
535
660
  processedItems: processedSeeders,
536
661
  operationName: "seeders",
537
- databaseName: this.name
662
+ databaseName: this.name,
663
+ errors
538
664
  };
539
665
  UIUtils.showOperationSummary(summary);
540
666
  return totalSeedersProcessed > 0 ? { processed: totalSeedersProcessed, success: successCount, errors: errorCount } : null;
@@ -543,7 +669,7 @@ Available databases: ${availableText}`);
543
669
  const startTime = Date.now();
544
670
  const cubesDir = path2.join(process.cwd(), "dbcube", "cubes");
545
671
  const triggersDirExit = path2.join(process.cwd(), "dbcube", "triggers");
546
- if (!fs2.existsSync(cubesDir)) {
672
+ if (!fs3.existsSync(cubesDir)) {
547
673
  throw new Error("\u274C The cubes folder does not exist");
548
674
  }
549
675
  const cubeFiles = FileUtils_default.getCubeFilesRecursively("dbcube", "trigger.cube");
@@ -555,16 +681,23 @@ Available databases: ${availableText}`);
555
681
  let successCount = 0;
556
682
  let errorCount = 0;
557
683
  const processedTriggers = [];
684
+ const errors = [];
558
685
  for (let index = 0; index < cubeFiles.length; index++) {
559
686
  const file = cubeFiles[index];
560
687
  const filePath = path2.isAbsolute(file) ? file : path2.join(cubesDir, file);
561
- const stats = fs2.statSync(filePath);
688
+ const stats = fs3.statSync(filePath);
562
689
  if (stats.isFile()) {
563
690
  const getTriggerName = FileUtils_default.extracTableNameFromCube(filePath);
564
691
  const triggerName = getTriggerName.status === 200 ? getTriggerName.message : path2.basename(file, ".trigger.cube");
565
692
  await UIUtils.showItemProgress(triggerName, index + 1, cubeFiles.length);
566
693
  try {
567
- this.validateDatabaseConfiguration(filePath);
694
+ const validation = this.validateDatabaseConfiguration(filePath);
695
+ if (!validation.isValid && validation.error) {
696
+ UIUtils.showItemError(triggerName, validation.error.error);
697
+ errors.push(validation.error);
698
+ errorCount++;
699
+ continue;
700
+ }
568
701
  const response = await this.engine.run("schema_engine", [
569
702
  "--action",
570
703
  "trigger",
@@ -582,7 +715,13 @@ Available databases: ${availableText}`);
582
715
  processedTriggers.push(triggerName);
583
716
  totalTriggersProcessed++;
584
717
  } catch (error) {
718
+ const processError = {
719
+ itemName: triggerName,
720
+ error: error.message,
721
+ filePath
722
+ };
585
723
  UIUtils.showItemError(triggerName, error.message);
724
+ errors.push(processError);
586
725
  errorCount++;
587
726
  }
588
727
  }
@@ -594,36 +733,19 @@ Available databases: ${availableText}`);
594
733
  errorCount,
595
734
  processedItems: processedTriggers,
596
735
  operationName: "triggers",
597
- databaseName: this.name
736
+ databaseName: this.name,
737
+ errors
598
738
  };
599
739
  UIUtils.showOperationSummary(summary);
600
740
  return totalTriggersProcessed > 0 ? { processed: totalTriggersProcessed, success: successCount, errors: errorCount } : null;
601
741
  }
602
742
  };
603
743
  function returnFormattedError(status, message) {
604
- const RESET = "\x1B[0m";
605
- const RED = "\x1B[31m";
606
- const YELLOW = "\x1B[33m";
607
- const BOLD = "\x1B[1m";
608
- const CYAN = "\x1B[36m";
609
- const GRAY = "\x1B[90m";
610
- const UNDERLINE = "\x1B[4m";
611
- const MAGENTA = "\x1B[35m";
612
- let output = "";
613
- let help = "";
614
- const color = status === 600 ? YELLOW : RED;
615
- if (message.includes("[help]")) {
616
- const parts = message.split("[help]");
617
- output += `
618
- ${RED}${BOLD}${parts[0]}${RESET}`;
619
- help += `
620
- ${MAGENTA}${BOLD}[help]${RESET} ${GRAY}${parts[1]}${RESET}
621
- `;
622
- } else {
623
- output += `
624
- ${color}${BOLD}${message}${RESET}
625
- `;
626
- }
744
+ console.log(`
745
+ ${chalk2.red("\u{1F6AB}")} ${chalk2.bold.red("ERRORS FOUND")}`);
746
+ console.log(chalk2.red("\u2500".repeat(60)));
747
+ console.log(`${chalk2.red("[error]")} ${chalk2.red(message)}`);
748
+ console.log("");
627
749
  const err = new Error();
628
750
  const stackLines = err.stack?.split("\n") || [];
629
751
  const relevantStackLine = stackLines.find(
@@ -635,32 +757,22 @@ ${color}${BOLD}${message}${RESET}
635
757
  const [, filePath, lineStr, columnStr] = match;
636
758
  const lineNum = parseInt(lineStr, 10);
637
759
  const errorLocation = `${filePath}:${lineStr}:${columnStr}`;
760
+ console.log(`${chalk2.cyan("[code]")} ${chalk2.yellow(errorLocation)}`);
638
761
  try {
639
- const codeLines = fs2.readFileSync(filePath, "utf-8").split("\n");
762
+ const codeLines = fs3.readFileSync(filePath, "utf-8").split("\n");
640
763
  const start = Math.max(0, lineNum - 3);
641
764
  const end = Math.min(codeLines.length, lineNum + 2);
642
- output += `
643
- ${CYAN}${BOLD}[code] ${RESET}${YELLOW} ${UNDERLINE}${errorLocation}${RESET}
644
- `;
645
765
  for (let i = start; i < end; i++) {
646
766
  const line = codeLines[i];
647
767
  const lineLabel = `${i + 1}`.padStart(4, " ");
648
- const pointer = i + 1 === lineNum ? `${RED}<-${RESET}` : " ";
649
- output += `${GRAY}${lineLabel}${RESET} ${pointer} ${line}
650
- `;
768
+ const pointer = i + 1 === lineNum ? `${chalk2.red("<-")}` : " ";
769
+ console.log(`${chalk2.gray(lineLabel)} ${pointer} ${chalk2.white(line)}`);
651
770
  }
652
771
  } catch (err2) {
653
- output += `${YELLOW}\u26A0\uFE0F No se pudo leer el archivo de origen: ${filePath}${RESET}
654
- `;
655
- output += `
656
- ${CYAN}${BOLD}Stack Trace:${RESET}
657
- ${stackLines.slice(2).join("\n")}
658
- `;
772
+ console.log(chalk2.gray(" (unable to show code context)"));
659
773
  }
660
774
  }
661
775
  }
662
- output += help;
663
- console.error(output);
664
776
  process.exit(1);
665
777
  }
666
778