@dbcube/schema-builder 1.0.17 → 1.0.18

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,9 +6,9 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
6
6
  });
7
7
 
8
8
  // src/lib/Schema.ts
9
- import fs4 from "fs";
9
+ import fs5 from "fs";
10
10
  import { Engine, TableProcessor, Config as ConfigClass } from "@dbcube/core";
11
- import path3 from "path";
11
+ import path4 from "path";
12
12
 
13
13
  // src/lib/FileUtils.ts
14
14
  import * as fs from "fs";
@@ -373,7 +373,7 @@ var CubeValidator = class {
373
373
  filePath,
374
374
  lineNumber
375
375
  });
376
- } else if (!this.isOptionCompatibleWithType(option, columnType)) {
376
+ } else if (columnType !== "unknown" && !this.isOptionCompatibleWithType(option, columnType)) {
377
377
  errors.push({
378
378
  itemName: fileName,
379
379
  error: `Option '${option}' is not compatible with type '${columnType}'`,
@@ -392,6 +392,18 @@ var CubeValidator = class {
392
392
  if (/^\s*[a-zA-Z_][a-zA-Z0-9_]*\s*:\s*\{/.test(line)) {
393
393
  return;
394
394
  }
395
+ if (this.isInsideForeignKeyObject(content, lineNumber - 1)) {
396
+ const validForeignKeyProperties = ["table", "column"];
397
+ if (!validForeignKeyProperties.includes(propertyName)) {
398
+ errors.push({
399
+ itemName: fileName,
400
+ error: `Invalid foreign key property '${propertyName}'. Valid foreign key properties: ${validForeignKeyProperties.join(", ")}`,
401
+ filePath,
402
+ lineNumber
403
+ });
404
+ }
405
+ return;
406
+ }
395
407
  if (this.isInsideColumnsBlock(content, lineNumber - 1)) {
396
408
  if (!this.validProperties.includes(propertyName)) {
397
409
  errors.push({
@@ -560,6 +572,231 @@ var CubeValidator = class {
560
572
  }
561
573
  return columnsStartLine !== -1 && columnsEndLine !== -1 && lineIndex > columnsStartLine && lineIndex < columnsEndLine;
562
574
  }
575
+ isInsideForeignKeyObject(content, lineIndex) {
576
+ const lines = content.split("\n");
577
+ for (let i = lineIndex; i >= 0; i--) {
578
+ const line = lines[i];
579
+ if (/foreign\s*:\s*\{/.test(line)) {
580
+ let braceCount = 0;
581
+ for (let j = i; j <= lineIndex; j++) {
582
+ const currentLine = lines[j];
583
+ const openBraces = (currentLine.match(/\{/g) || []).length;
584
+ const closeBraces = (currentLine.match(/\}/g) || []).length;
585
+ braceCount += openBraces - closeBraces;
586
+ if (braceCount === 0 && j > i) {
587
+ return false;
588
+ }
589
+ }
590
+ return braceCount > 0;
591
+ }
592
+ if (line.trim() === "}" || line.includes("};")) {
593
+ break;
594
+ }
595
+ }
596
+ return false;
597
+ }
598
+ };
599
+
600
+ // src/lib/DependencyResolver.ts
601
+ import fs4 from "fs";
602
+ import path3 from "path";
603
+ var DependencyResolver = class {
604
+ /**
605
+ * Resolves table dependencies and creates execution order
606
+ */
607
+ static resolveDependencies(cubeFiles, cubeType = "table") {
608
+ const tableDependencies = this.extractDependencies(cubeFiles, cubeType);
609
+ const orderedTables = this.topologicalSort(tableDependencies);
610
+ const executionOrder = {
611
+ tables: cubeType === "table" ? orderedTables : [],
612
+ seeders: cubeType === "seeder" ? orderedTables : [],
613
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
614
+ };
615
+ this.saveExecutionOrder(executionOrder);
616
+ return executionOrder;
617
+ }
618
+ /**
619
+ * Extracts dependencies from cube files
620
+ */
621
+ static extractDependencies(cubeFiles, cubeType) {
622
+ const dependencies = [];
623
+ for (const file of cubeFiles) {
624
+ let filePath;
625
+ if (path3.isAbsolute(file)) {
626
+ filePath = file;
627
+ } else if (fs4.existsSync(file)) {
628
+ filePath = path3.resolve(file);
629
+ } else {
630
+ filePath = path3.join(process.cwd(), "dbcube", "cubes", file);
631
+ }
632
+ try {
633
+ const tableNameResult = FileUtils_default.extracTableNameFromCube(filePath);
634
+ const tableName = tableNameResult.status === 200 ? tableNameResult.message : path3.basename(file, `.${cubeType}.cube`);
635
+ const deps = this.extractForeignKeyReferences(filePath);
636
+ dependencies.push({
637
+ tableName,
638
+ filePath,
639
+ dependencies: deps
640
+ });
641
+ } catch (error) {
642
+ console.error(`Error processing ${filePath}:`, error);
643
+ }
644
+ }
645
+ return dependencies;
646
+ }
647
+ /**
648
+ * Extracts foreign key references from a cube file
649
+ */
650
+ static extractForeignKeyReferences(filePath) {
651
+ const dependencies = [];
652
+ try {
653
+ const content = fs4.readFileSync(filePath, "utf8");
654
+ const lines = content.split("\n");
655
+ let insideForeignKey = false;
656
+ let braceCount = 0;
657
+ for (const line of lines) {
658
+ if (/foreign\s*:\s*\{/.test(line)) {
659
+ insideForeignKey = true;
660
+ braceCount = 1;
661
+ const sameLineMatch = line.match(/table\s*:\s*["']([^"']+)["']/);
662
+ if (sameLineMatch) {
663
+ dependencies.push(sameLineMatch[1]);
664
+ insideForeignKey = false;
665
+ braceCount = 0;
666
+ }
667
+ continue;
668
+ }
669
+ if (insideForeignKey) {
670
+ braceCount += (line.match(/\{/g) || []).length;
671
+ braceCount -= (line.match(/\}/g) || []).length;
672
+ const tableMatch = line.match(/table\s*:\s*["']([^"']+)["']/);
673
+ if (tableMatch) {
674
+ dependencies.push(tableMatch[1]);
675
+ }
676
+ if (braceCount === 0) {
677
+ insideForeignKey = false;
678
+ }
679
+ }
680
+ }
681
+ } catch (error) {
682
+ console.error(`Error reading file ${filePath}:`, error);
683
+ }
684
+ return dependencies;
685
+ }
686
+ /**
687
+ * Performs topological sort to determine execution order
688
+ */
689
+ static topologicalSort(dependencies) {
690
+ const graph = /* @__PURE__ */ new Map();
691
+ const inDegree = /* @__PURE__ */ new Map();
692
+ const tableMap = /* @__PURE__ */ new Map();
693
+ for (const dep of dependencies) {
694
+ graph.set(dep.tableName, dep.dependencies);
695
+ inDegree.set(dep.tableName, 0);
696
+ tableMap.set(dep.tableName, dep);
697
+ }
698
+ for (const dep of dependencies) {
699
+ for (const dependency of dep.dependencies) {
700
+ if (inDegree.has(dependency)) {
701
+ inDegree.set(dep.tableName, (inDegree.get(dep.tableName) || 0) + 1);
702
+ }
703
+ }
704
+ }
705
+ const queue = [];
706
+ const result = [];
707
+ for (const [table, degree] of inDegree) {
708
+ if (degree === 0) {
709
+ queue.push(table);
710
+ }
711
+ }
712
+ while (queue.length > 0) {
713
+ const current = queue.shift();
714
+ result.push(current);
715
+ const currentDeps = graph.get(current) || [];
716
+ for (const neighbor of currentDeps) {
717
+ if (inDegree.has(neighbor)) {
718
+ const newDegree = (inDegree.get(neighbor) || 0) - 1;
719
+ inDegree.set(neighbor, newDegree);
720
+ if (newDegree === 0) {
721
+ queue.push(neighbor);
722
+ }
723
+ }
724
+ }
725
+ }
726
+ if (result.length !== dependencies.length) {
727
+ console.warn("\u26A0\uFE0F Circular dependencies detected in tables. Some tables may not execute in optimal order.");
728
+ for (const dep of dependencies) {
729
+ if (!result.includes(dep.tableName)) {
730
+ result.push(dep.tableName);
731
+ }
732
+ }
733
+ }
734
+ return result;
735
+ }
736
+ /**
737
+ * Saves the execution order to .dbcube/orderexecute.json
738
+ */
739
+ static saveExecutionOrder(order) {
740
+ try {
741
+ const projectRoot = process.cwd();
742
+ const dbcubeDir = path3.join(projectRoot, ".dbcube");
743
+ const orderFile = path3.join(dbcubeDir, "orderexecute.json");
744
+ if (!fs4.existsSync(dbcubeDir)) {
745
+ fs4.mkdirSync(dbcubeDir, { recursive: true });
746
+ }
747
+ fs4.writeFileSync(orderFile, JSON.stringify(order, null, 2), "utf8");
748
+ console.log(`\u{1F4C4} Execution order saved to: ${path3.relative(projectRoot, orderFile)}`);
749
+ } catch (error) {
750
+ console.error("\u274C Failed to save execution order:", error);
751
+ }
752
+ }
753
+ /**
754
+ * Loads the execution order from .dbcube/orderexecute.json
755
+ */
756
+ static loadExecutionOrder() {
757
+ try {
758
+ const projectRoot = process.cwd();
759
+ const orderFile = path3.join(projectRoot, ".dbcube", "orderexecute.json");
760
+ if (!fs4.existsSync(orderFile)) {
761
+ return null;
762
+ }
763
+ const content = fs4.readFileSync(orderFile, "utf8");
764
+ return JSON.parse(content);
765
+ } catch (error) {
766
+ console.error("\u274C Failed to load execution order:", error);
767
+ return null;
768
+ }
769
+ }
770
+ /**
771
+ * Orders cube files based on saved execution order
772
+ */
773
+ static orderCubeFiles(cubeFiles, cubeType) {
774
+ const executionOrder = this.loadExecutionOrder();
775
+ if (!executionOrder) {
776
+ console.log("\u{1F4C4} No execution order found, processing files in current order");
777
+ return cubeFiles;
778
+ }
779
+ const orderList = cubeType === "table" ? executionOrder.tables : executionOrder.seeders;
780
+ const orderedFiles = [];
781
+ const fileMap = /* @__PURE__ */ new Map();
782
+ for (const file of cubeFiles) {
783
+ const filePath = path3.isAbsolute(file) ? file : path3.join(process.cwd(), "dbcube", "cubes", file);
784
+ const tableNameResult = FileUtils_default.extracTableNameFromCube(filePath);
785
+ const tableName = tableNameResult.status === 200 ? tableNameResult.message : path3.basename(file, `.${cubeType}.cube`);
786
+ fileMap.set(tableName, file);
787
+ }
788
+ for (const tableName of orderList) {
789
+ if (fileMap.has(tableName)) {
790
+ orderedFiles.push(fileMap.get(tableName));
791
+ fileMap.delete(tableName);
792
+ }
793
+ }
794
+ for (const [, file] of fileMap) {
795
+ orderedFiles.push(file);
796
+ }
797
+ console.log(`\u{1F4CB} Using dependency order: ${orderList.join(" \u2192 ")}`);
798
+ return orderedFiles;
799
+ }
563
800
  };
564
801
 
565
802
  // src/lib/Schema.ts
@@ -591,7 +828,7 @@ var Schema = class {
591
828
  return {
592
829
  isValid: false,
593
830
  error: {
594
- itemName: path3.basename(filePath, path3.extname(filePath)),
831
+ itemName: path4.basename(filePath, path4.extname(filePath)),
595
832
  error: `Error reading database directive: ${dbResult.message}`,
596
833
  filePath,
597
834
  lineNumber: this.findDatabaseLineNumber(filePath)
@@ -600,7 +837,7 @@ var Schema = class {
600
837
  }
601
838
  const cubeDbName = dbResult.message;
602
839
  const configInstance = new ConfigClass();
603
- const configFilePath = path3.resolve(process.cwd(), "dbcube.config.js");
840
+ const configFilePath = path4.resolve(process.cwd(), "dbcube.config.js");
604
841
  const configFn = __require(configFilePath);
605
842
  if (typeof configFn === "function") {
606
843
  configFn(configInstance);
@@ -627,7 +864,7 @@ var Schema = class {
627
864
  return {
628
865
  isValid: false,
629
866
  error: {
630
- itemName: path3.basename(filePath, path3.extname(filePath)),
867
+ itemName: path4.basename(filePath, path4.extname(filePath)),
631
868
  error: `Database configuration '${cubeDbName}' not found in dbcube.config.js. Available: ${availableText}`,
632
869
  filePath,
633
870
  lineNumber: this.findDatabaseLineNumber(filePath)
@@ -639,7 +876,7 @@ var Schema = class {
639
876
  return {
640
877
  isValid: false,
641
878
  error: {
642
- itemName: path3.basename(filePath, path3.extname(filePath)),
879
+ itemName: path4.basename(filePath, path4.extname(filePath)),
643
880
  error: `Database configuration validation failed: ${error.message}`,
644
881
  filePath,
645
882
  lineNumber: this.findDatabaseLineNumber(filePath)
@@ -652,7 +889,7 @@ var Schema = class {
652
889
  */
653
890
  findDatabaseLineNumber(filePath) {
654
891
  try {
655
- const content = fs4.readFileSync(filePath, "utf8");
892
+ const content = fs5.readFileSync(filePath, "utf8");
656
893
  const lines = content.split("\n");
657
894
  for (let i = 0; i < lines.length; i++) {
658
895
  if (lines[i].includes("@database")) {
@@ -666,7 +903,7 @@ var Schema = class {
666
903
  }
667
904
  async createDatabase() {
668
905
  const startTime = Date.now();
669
- const rootPath = path3.resolve(process.cwd());
906
+ const rootPath = path4.resolve(process.cwd());
670
907
  UIUtils.showOperationHeader(" CREATING DATABASE", this.name, "\u{1F5C4}\uFE0F");
671
908
  await UIUtils.showItemProgress("Preparando e instalando base de datos", 1, 1);
672
909
  try {
@@ -710,28 +947,31 @@ var Schema = class {
710
947
  }
711
948
  async refreshTables() {
712
949
  const startTime = Date.now();
713
- const cubesDir = path3.join(process.cwd(), "dbcube", "cubes");
714
- if (!fs4.existsSync(cubesDir)) {
950
+ const cubesDir = path4.join(process.cwd(), "dbcube", "cubes");
951
+ if (!fs5.existsSync(cubesDir)) {
715
952
  throw new Error("\u274C The cubes folder does not exist");
716
953
  }
717
954
  const cubeFiles = FileUtils_default.getCubeFilesRecursively("dbcube", "table.cube");
718
955
  if (cubeFiles.length === 0) {
719
956
  throw new Error("\u274C There are no cubes to execute");
720
957
  }
958
+ console.log("\u{1F504} Resolving table dependencies...");
959
+ DependencyResolver.resolveDependencies(cubeFiles, "table");
960
+ const orderedCubeFiles = DependencyResolver.orderCubeFiles(cubeFiles, "table");
721
961
  UIUtils.showOperationHeader("EXECUTING REFRESH TABLES", this.name, "\u{1F504}");
722
962
  let totalTablesProcessed = 0;
723
963
  let successCount = 0;
724
964
  let errorCount = 0;
725
965
  const processedTables = [];
726
966
  const errors = [];
727
- for (let index = 0; index < cubeFiles.length; index++) {
728
- const file = cubeFiles[index];
729
- const filePath = path3.isAbsolute(file) ? file : path3.join(cubesDir, file);
730
- const stats = fs4.statSync(filePath);
967
+ for (let index = 0; index < orderedCubeFiles.length; index++) {
968
+ const file = orderedCubeFiles[index];
969
+ const filePath = path4.isAbsolute(file) ? file : path4.join(cubesDir, file);
970
+ const stats = fs5.statSync(filePath);
731
971
  if (stats.isFile()) {
732
972
  const getTableName = FileUtils_default.extracTableNameFromCube(filePath);
733
- const tableName = getTableName.status === 200 ? getTableName.message : path3.basename(file, ".table.cube");
734
- await UIUtils.showItemProgress(tableName, index + 1, cubeFiles.length);
973
+ const tableName = getTableName.status === 200 ? getTableName.message : path4.basename(file, ".table.cube");
974
+ await UIUtils.showItemProgress(tableName, index + 1, orderedCubeFiles.length);
735
975
  try {
736
976
  const validation = this.validateDatabaseConfiguration(filePath);
737
977
  if (!validation.isValid && validation.error) {
@@ -812,28 +1052,31 @@ var Schema = class {
812
1052
  }
813
1053
  async freshTables() {
814
1054
  const startTime = Date.now();
815
- const cubesDir = path3.join(process.cwd(), "dbcube", "cubes");
816
- if (!fs4.existsSync(cubesDir)) {
1055
+ const cubesDir = path4.join(process.cwd(), "dbcube", "cubes");
1056
+ if (!fs5.existsSync(cubesDir)) {
817
1057
  throw new Error("\u274C The cubes folder does not exist");
818
1058
  }
819
1059
  const cubeFiles = FileUtils_default.getCubeFilesRecursively("dbcube", "table.cube");
820
1060
  if (cubeFiles.length === 0) {
821
1061
  throw new Error("\u274C There are no cubes to execute");
822
1062
  }
1063
+ console.log("\u{1F504} Resolving table dependencies...");
1064
+ DependencyResolver.resolveDependencies(cubeFiles, "table");
1065
+ const orderedCubeFiles = DependencyResolver.orderCubeFiles(cubeFiles, "table");
823
1066
  UIUtils.showOperationHeader("EXECUTING FRESH TABLES", this.name);
824
1067
  let totalTablesProcessed = 0;
825
1068
  let successCount = 0;
826
1069
  let errorCount = 0;
827
1070
  const processedTables = [];
828
1071
  const errors = [];
829
- for (let index = 0; index < cubeFiles.length; index++) {
830
- const file = cubeFiles[index];
831
- const filePath = path3.isAbsolute(file) ? file : path3.join(cubesDir, file);
832
- const stats = fs4.statSync(filePath);
1072
+ for (let index = 0; index < orderedCubeFiles.length; index++) {
1073
+ const file = orderedCubeFiles[index];
1074
+ const filePath = path4.isAbsolute(file) ? file : path4.join(cubesDir, file);
1075
+ const stats = fs5.statSync(filePath);
833
1076
  if (stats.isFile()) {
834
1077
  const getTableName = FileUtils_default.extracTableNameFromCube(filePath);
835
- const tableName = getTableName.status === 200 ? getTableName.message : path3.basename(file, ".table.cube");
836
- await UIUtils.showItemProgress(tableName, index + 1, cubeFiles.length);
1078
+ const tableName = getTableName.status === 200 ? getTableName.message : path4.basename(file, ".table.cube");
1079
+ await UIUtils.showItemProgress(tableName, index + 1, orderedCubeFiles.length);
837
1080
  try {
838
1081
  const validation = this.validateDatabaseConfiguration(filePath);
839
1082
  if (!validation.isValid && validation.error) {
@@ -912,28 +1155,29 @@ var Schema = class {
912
1155
  }
913
1156
  async executeSeeders() {
914
1157
  const startTime = Date.now();
915
- const cubesDir = path3.join(process.cwd(), "dbcube", "cubes");
916
- if (!fs4.existsSync(cubesDir)) {
1158
+ const cubesDir = path4.join(process.cwd(), "dbcube", "cubes");
1159
+ if (!fs5.existsSync(cubesDir)) {
917
1160
  throw new Error("\u274C The cubes folder does not exist");
918
1161
  }
919
1162
  const cubeFiles = FileUtils_default.getCubeFilesRecursively("dbcube", "seeder.cube");
920
1163
  if (cubeFiles.length === 0) {
921
1164
  throw new Error("\u274C There are no cubes to execute");
922
1165
  }
1166
+ const orderedCubeFiles = DependencyResolver.orderCubeFiles(cubeFiles, "seeder");
923
1167
  UIUtils.showOperationHeader("EXECUTING SEEDERS", this.name, "\u{1F331}");
924
1168
  let totalSeedersProcessed = 0;
925
1169
  let successCount = 0;
926
1170
  let errorCount = 0;
927
1171
  const processedSeeders = [];
928
1172
  const errors = [];
929
- for (let index = 0; index < cubeFiles.length; index++) {
930
- const file = cubeFiles[index];
931
- const filePath = path3.isAbsolute(file) ? file : path3.join(cubesDir, file);
932
- const stats = fs4.statSync(filePath);
1173
+ for (let index = 0; index < orderedCubeFiles.length; index++) {
1174
+ const file = orderedCubeFiles[index];
1175
+ const filePath = path4.isAbsolute(file) ? file : path4.join(cubesDir, file);
1176
+ const stats = fs5.statSync(filePath);
933
1177
  if (stats.isFile()) {
934
1178
  const getSeederName = FileUtils_default.extracTableNameFromCube(filePath);
935
- const seederName = getSeederName.status === 200 ? getSeederName.message : path3.basename(file, ".seeder.cube");
936
- await UIUtils.showItemProgress(seederName, index + 1, cubeFiles.length);
1179
+ const seederName = getSeederName.status === 200 ? getSeederName.message : path4.basename(file, ".seeder.cube");
1180
+ await UIUtils.showItemProgress(seederName, index + 1, orderedCubeFiles.length);
937
1181
  try {
938
1182
  const validation = this.validateDatabaseConfiguration(filePath);
939
1183
  if (!validation.isValid && validation.error) {
@@ -983,9 +1227,9 @@ var Schema = class {
983
1227
  }
984
1228
  async executeTriggers() {
985
1229
  const startTime = Date.now();
986
- const cubesDir = path3.join(process.cwd(), "dbcube", "cubes");
987
- const triggersDirExit = path3.join(process.cwd(), "dbcube", "triggers");
988
- if (!fs4.existsSync(cubesDir)) {
1230
+ const cubesDir = path4.join(process.cwd(), "dbcube", "cubes");
1231
+ const triggersDirExit = path4.join(process.cwd(), "dbcube", "triggers");
1232
+ if (!fs5.existsSync(cubesDir)) {
989
1233
  throw new Error("\u274C The cubes folder does not exist");
990
1234
  }
991
1235
  const cubeFiles = FileUtils_default.getCubeFilesRecursively("dbcube", "trigger.cube");
@@ -1000,11 +1244,11 @@ var Schema = class {
1000
1244
  const errors = [];
1001
1245
  for (let index = 0; index < cubeFiles.length; index++) {
1002
1246
  const file = cubeFiles[index];
1003
- const filePath = path3.isAbsolute(file) ? file : path3.join(cubesDir, file);
1004
- const stats = fs4.statSync(filePath);
1247
+ const filePath = path4.isAbsolute(file) ? file : path4.join(cubesDir, file);
1248
+ const stats = fs5.statSync(filePath);
1005
1249
  if (stats.isFile()) {
1006
1250
  const getTriggerName = FileUtils_default.extracTableNameFromCube(filePath);
1007
- const triggerName = getTriggerName.status === 200 ? getTriggerName.message : path3.basename(file, ".trigger.cube");
1251
+ const triggerName = getTriggerName.status === 200 ? getTriggerName.message : path4.basename(file, ".trigger.cube");
1008
1252
  await UIUtils.showItemProgress(triggerName, index + 1, cubeFiles.length);
1009
1253
  try {
1010
1254
  const validation = this.validateDatabaseConfiguration(filePath);
@@ -1075,7 +1319,7 @@ ${chalk2.red("\u{1F6AB}")} ${chalk2.bold.red("ERRORS FOUND")}`);
1075
1319
  const errorLocation = `${filePath}:${lineStr}:${columnStr}`;
1076
1320
  console.log(`${chalk2.cyan("[code]")} ${chalk2.yellow(errorLocation)}`);
1077
1321
  try {
1078
- const codeLines = fs4.readFileSync(filePath, "utf-8").split("\n");
1322
+ const codeLines = fs5.readFileSync(filePath, "utf-8").split("\n");
1079
1323
  const start = Math.max(0, lineNum - 3);
1080
1324
  const end = Math.min(codeLines.length, lineNum + 2);
1081
1325
  for (let i = start; i < end; i++) {
@@ -1097,6 +1341,7 @@ ${chalk2.red("\u{1F6AB}")} ${chalk2.bold.red("ERRORS FOUND")}`);
1097
1341
  var index_default = Schema;
1098
1342
  export {
1099
1343
  CubeValidator,
1344
+ DependencyResolver,
1100
1345
  Schema,
1101
1346
  UIUtils,
1102
1347
  index_default as default