aerocoding 0.1.21 → 0.1.23

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
@@ -517,6 +517,7 @@ async function whoamiCommand() {
517
517
  // src/commands/generate.ts
518
518
  import chalk8 from "chalk";
519
519
  import ora2 from "ora";
520
+ import * as p from "@clack/prompts";
520
521
 
521
522
  // src/utils/file-writer.ts
522
523
  import fs from "fs/promises";
@@ -589,6 +590,7 @@ function displayCategorizedSummary(files) {
589
590
  }
590
591
  async function writeGeneratedFiles(files, outputDir, verbose = false) {
591
592
  const writtenFiles = [];
593
+ const skippedOnceFiles = [];
592
594
  for (const file of files) {
593
595
  if (!isPathSafe(outputDir, file.path)) {
594
596
  console.error(chalk6.red(` Skipping unsafe path: ${file.path}`));
@@ -601,6 +603,14 @@ async function writeGeneratedFiles(files, outputDir, verbose = false) {
601
603
  }
602
604
  const fullPath = path.resolve(outputDir, file.path);
603
605
  const dir = path.dirname(fullPath);
606
+ if (file.generateOnce) {
607
+ try {
608
+ await fs.access(fullPath);
609
+ skippedOnceFiles.push(file.path);
610
+ continue;
611
+ } catch {
612
+ }
613
+ }
604
614
  try {
605
615
  await fs.mkdir(dir, { recursive: true });
606
616
  await fs.writeFile(fullPath, file.content, "utf-8");
@@ -616,6 +626,15 @@ async function writeGeneratedFiles(files, outputDir, verbose = false) {
616
626
  if (!verbose && writtenFiles.length > 0) {
617
627
  displayCategorizedSummary(writtenFiles);
618
628
  }
629
+ if (skippedOnceFiles.length > 0) {
630
+ console.log("");
631
+ console.log(
632
+ chalk6.gray(` Skipped ${skippedOnceFiles.length} existing file(s) (generateOnce):`)
633
+ );
634
+ for (const filePath of skippedOnceFiles) {
635
+ console.log(chalk6.gray(` - ${filePath}`));
636
+ }
637
+ }
619
638
  }
620
639
 
621
640
  // src/utils/prompt.ts
@@ -648,17 +667,14 @@ var configSchema = z.object({
648
667
  // Architecture style: how to organize generated code
649
668
  architectureStyle: z.enum(["bounded-contexts", "flat"]).optional().default("bounded-contexts"),
650
669
  backend: z.object({
651
- preset: z.string(),
652
- layers: z.array(z.string())
670
+ preset: z.string()
653
671
  }).optional(),
654
672
  frontend: z.object({
655
- preset: z.string(),
656
- layers: z.array(z.string())
673
+ preset: z.string()
657
674
  }).optional(),
658
675
  codeStyle: z.object({
659
676
  includeValidations: z.boolean().default(true),
660
677
  includeComments: z.boolean().default(true),
661
- includeAnnotations: z.boolean().default(true),
662
678
  includeLogging: z.boolean().default(true),
663
679
  includeTesting: z.boolean().default(true)
664
680
  }).optional(),
@@ -736,35 +752,6 @@ function mapPresetToTarget(preset) {
736
752
  }
737
753
  return null;
738
754
  }
739
- function buildTemplateIdFromConfig(config) {
740
- if (!config) return null;
741
- if (config.backend?.preset) {
742
- const templateId = mapPresetToTemplateId(config.backend.preset);
743
- if (templateId) return templateId;
744
- }
745
- if (config.frontend?.preset) {
746
- const templateId = mapPresetToTemplateId(config.frontend.preset);
747
- if (templateId) return templateId;
748
- }
749
- return null;
750
- }
751
- function buildTargetsFromConfig(config) {
752
- if (!config) return [];
753
- const targets = [];
754
- if (config.backend?.preset) {
755
- const target = mapPresetToTarget(config.backend.preset);
756
- if (target) {
757
- targets.push(target);
758
- }
759
- }
760
- if (config.frontend?.preset) {
761
- const target = mapPresetToTarget(config.frontend.preset);
762
- if (target) {
763
- targets.push(target);
764
- }
765
- }
766
- return targets;
767
- }
768
755
  function buildFeatureFlagsFromConfig(config) {
769
756
  const flags = {
770
757
  // Default all feature flags to true for full architecture
@@ -773,14 +760,22 @@ function buildFeatureFlagsFromConfig(config) {
773
760
  includeMappers: true,
774
761
  includeControllers: true,
775
762
  includeEfConfig: true,
776
- includeValidation: true
763
+ includeValidation: true,
764
+ includeDtoValidation: true,
765
+ // Data Annotations on Input records ([Required], [MaxLength], etc.)
766
+ // Test flags
767
+ includeUnitTests: true,
768
+ includeIntegrationTests: true,
769
+ // Starter files (disabled by default - user adds their own Program.cs)
770
+ includeStarterFiles: false
777
771
  };
778
772
  if (!config) return flags;
779
773
  if (config.codeStyle?.includeValidations !== void 0) {
780
774
  flags.includeValidation = config.codeStyle.includeValidations;
781
775
  }
782
776
  if (config.codeStyle?.includeTesting !== void 0) {
783
- flags.includeTests = config.codeStyle.includeTesting;
777
+ flags.includeUnitTests = config.codeStyle.includeTesting;
778
+ flags.includeIntegrationTests = config.codeStyle.includeTesting;
784
779
  }
785
780
  return flags;
786
781
  }
@@ -800,18 +795,10 @@ async function generateCommand(options) {
800
795
  console.log(chalk8.gray(" Or use --project <id> to specify a project\n"));
801
796
  process.exit(1);
802
797
  }
803
- const templateId = buildTemplateIdFromConfig(config);
804
- const featureFlags = templateId ? buildFeatureFlagsFromConfig(config) : void 0;
805
- const targets = !templateId ? options.targets || buildTargetsFromConfig(config) : void 0;
806
798
  const output = options.output || config?.output || "./.aerocoding";
807
- const backendPreset = options.backendPreset || config?.backend?.preset;
808
- const frontendPreset = options.frontendPreset || config?.frontend?.preset;
809
- const backendLayers = options.backendLayers || config?.backend?.layers;
810
- const frontendLayers = options.frontendLayers || config?.frontend?.layers;
811
799
  const validationLib = options.validationLib || config?.libraries?.validation;
812
800
  const includeValidations = options.validations ?? config?.codeStyle?.includeValidations ?? true;
813
801
  const includeComments = options.comments ?? config?.codeStyle?.includeComments ?? true;
814
- const includeAnnotations = options.annotations ?? config?.codeStyle?.includeAnnotations ?? true;
815
802
  const includeLogging = options.logging ?? config?.codeStyle?.includeLogging ?? true;
816
803
  const includeTesting = options.testing ?? config?.codeStyle?.includeTesting ?? true;
817
804
  const apiClient = createApiClientWithAutoLogout(token, tokenManager);
@@ -819,9 +806,89 @@ async function generateCommand(options) {
819
806
  try {
820
807
  const project = await apiClient.getProject(projectId);
821
808
  spinner2.succeed(chalk8.gray("Project loaded"));
809
+ const hasBackendConfig = !!config?.backend?.preset;
810
+ const hasFrontendConfig = !!config?.frontend?.preset;
811
+ const hasBothTargets = hasBackendConfig && hasFrontendConfig;
812
+ let selectedTarget = "both";
813
+ if (hasBothTargets && !options.all) {
814
+ const targetChoice = await p.select({
815
+ message: "Which target do you want to generate?",
816
+ options: [
817
+ {
818
+ value: "backend",
819
+ label: `Backend (${config?.backend?.preset})`,
820
+ hint: "Recommended"
821
+ },
822
+ {
823
+ value: "frontend",
824
+ label: `Frontend (${config?.frontend?.preset})`
825
+ },
826
+ {
827
+ value: "both",
828
+ label: "Both"
829
+ }
830
+ ],
831
+ initialValue: "backend"
832
+ });
833
+ if (p.isCancel(targetChoice)) {
834
+ console.log(chalk8.yellow("\n Generation cancelled\n"));
835
+ process.exit(0);
836
+ }
837
+ selectedTarget = targetChoice;
838
+ } else if (hasBackendConfig && !hasFrontendConfig) {
839
+ selectedTarget = "backend";
840
+ } else if (hasFrontendConfig && !hasBackendConfig) {
841
+ selectedTarget = "frontend";
842
+ }
843
+ const diagrams = project.schema?.diagrams || [];
844
+ const hasMultipleDiagrams = diagrams.length > 1;
845
+ let selectedDiagramIds = diagrams.map((d) => d.id || d.name || "unknown");
846
+ if (hasMultipleDiagrams && !options.all) {
847
+ const diagramChoices = await p.multiselect({
848
+ message: "Which bounded contexts do you want to generate?",
849
+ options: diagrams.map((d) => ({
850
+ value: d.id || d.name || "unknown",
851
+ label: `${d.name || "Unnamed"} (${d.entities?.length || 0} entities)`
852
+ })),
853
+ initialValues: diagrams.map((d) => d.id || d.name || "unknown"),
854
+ required: true
855
+ });
856
+ if (p.isCancel(diagramChoices)) {
857
+ console.log(chalk8.yellow("\n Generation cancelled\n"));
858
+ process.exit(0);
859
+ }
860
+ selectedDiagramIds = diagramChoices;
861
+ }
862
+ let templateId = null;
863
+ let targets = [];
864
+ let backendPreset;
865
+ let frontendPreset;
866
+ if (selectedTarget === "backend" || selectedTarget === "both") {
867
+ backendPreset = options.backendPreset || config?.backend?.preset;
868
+ if (backendPreset) {
869
+ const tid = mapPresetToTemplateId(backendPreset);
870
+ if (tid) templateId = tid;
871
+ const target = mapPresetToTarget(backendPreset);
872
+ if (target) targets.push(target);
873
+ }
874
+ }
875
+ if (selectedTarget === "frontend" || selectedTarget === "both") {
876
+ frontendPreset = options.frontendPreset || config?.frontend?.preset;
877
+ if (frontendPreset) {
878
+ const tid = mapPresetToTemplateId(frontendPreset);
879
+ if (tid && !templateId) templateId = tid;
880
+ const target = mapPresetToTarget(frontendPreset);
881
+ if (target) targets.push(target);
882
+ }
883
+ }
884
+ if (!templateId && (!targets || targets.length === 0)) {
885
+ targets = options.targets || [];
886
+ }
887
+ const featureFlags = buildFeatureFlagsFromConfig(config);
822
888
  spinner2 = ora2({ text: "Checking credits...", color: "cyan" }).start();
823
889
  const credits = await apiClient.getCreditUsage(project.organizationId);
824
890
  const useContexts = config?.architectureStyle !== "flat";
891
+ const estimateDiagramIds = selectedDiagramIds.length < diagrams.length ? selectedDiagramIds : void 0;
825
892
  let estimate = null;
826
893
  try {
827
894
  if (templateId) {
@@ -830,7 +897,8 @@ async function generateCommand(options) {
830
897
  templateId,
831
898
  options: {
832
899
  featureFlags,
833
- useContexts
900
+ useContexts,
901
+ diagramIds: estimateDiagramIds
834
902
  }
835
903
  });
836
904
  } else if (targets && targets.length > 0) {
@@ -841,9 +909,8 @@ async function generateCommand(options) {
841
909
  outputDir: output,
842
910
  backendPreset,
843
911
  frontendPreset,
844
- backendLayers,
845
- frontendLayers,
846
- useContexts
912
+ useContexts,
913
+ diagramIds: estimateDiagramIds
847
914
  }
848
915
  });
849
916
  }
@@ -872,12 +939,26 @@ async function generateCommand(options) {
872
939
  } else {
873
940
  console.log(chalk8.gray(" Mode:"), chalk8.gray("default"));
874
941
  }
875
- if (backendPreset) {
942
+ if (hasBothTargets) {
943
+ const targetLabel = selectedTarget === "backend" ? "Backend only" : selectedTarget === "frontend" ? "Frontend only" : "Backend + Frontend";
944
+ console.log(chalk8.gray(" Target:"), chalk8.cyan(targetLabel));
945
+ }
946
+ if (backendPreset && (selectedTarget === "backend" || selectedTarget === "both")) {
876
947
  console.log(chalk8.gray(" Backend Preset:"), chalk8.cyan(backendPreset));
877
948
  }
878
- if (frontendPreset) {
949
+ if (frontendPreset && (selectedTarget === "frontend" || selectedTarget === "both")) {
879
950
  console.log(chalk8.gray(" Frontend Preset:"), chalk8.cyan(frontendPreset));
880
951
  }
952
+ if (hasMultipleDiagrams) {
953
+ const selectedCount = selectedDiagramIds.length;
954
+ const totalCount = diagrams.length;
955
+ if (selectedCount === totalCount) {
956
+ console.log(chalk8.gray(" Bounded Contexts:"), chalk8.cyan(`All (${totalCount})`));
957
+ } else {
958
+ const selectedNames = diagrams.filter((d) => selectedDiagramIds.includes(d.id || d.name || "unknown")).map((d) => d.name || "Unnamed").join(", ");
959
+ console.log(chalk8.gray(" Bounded Contexts:"), chalk8.cyan(`${selectedCount}/${totalCount} (${selectedNames})`));
960
+ }
961
+ }
881
962
  const archStyle = config?.architectureStyle || "bounded-contexts";
882
963
  console.log(
883
964
  chalk8.gray(" Architecture:"),
@@ -886,7 +967,6 @@ async function generateCommand(options) {
886
967
  const disabledOptions = [];
887
968
  if (!includeValidations) disabledOptions.push("validations");
888
969
  if (!includeComments) disabledOptions.push("comments");
889
- if (!includeAnnotations) disabledOptions.push("annotations");
890
970
  if (!includeLogging) disabledOptions.push("logging");
891
971
  if (!includeTesting) disabledOptions.push("testing");
892
972
  if (disabledOptions.length > 0) {
@@ -948,6 +1028,7 @@ async function generateCommand(options) {
948
1028
  }
949
1029
  console.log("");
950
1030
  spinner2 = ora2({ text: "Generating code...", color: "cyan" }).start();
1031
+ const diagramIds = selectedDiagramIds.length < diagrams.length ? selectedDiagramIds : void 0;
951
1032
  const generatePayload = templateId ? {
952
1033
  // NEW: Full architecture mode using template
953
1034
  projectId,
@@ -956,7 +1037,9 @@ async function generateCommand(options) {
956
1037
  includeValidations,
957
1038
  includeComments,
958
1039
  featureFlags,
959
- useContexts
1040
+ useContexts,
1041
+ diagramIds
1042
+ // Filter by selected bounded contexts
960
1043
  }
961
1044
  } : {
962
1045
  // Legacy mode using targets
@@ -965,16 +1048,15 @@ async function generateCommand(options) {
965
1048
  options: {
966
1049
  includeValidations,
967
1050
  includeComments,
968
- includeAnnotations,
969
1051
  includeLogging,
970
1052
  includeTesting,
971
1053
  outputDir: output,
972
1054
  backendPreset,
973
1055
  frontendPreset,
974
- backendLayers,
975
- frontendLayers,
976
1056
  validationLib,
977
- useContexts
1057
+ useContexts,
1058
+ diagramIds
1059
+ // Filter by selected bounded contexts
978
1060
  }
979
1061
  };
980
1062
  const result = await apiClient.generateCode(generatePayload);
@@ -1045,42 +1127,42 @@ async function generateCommand(options) {
1045
1127
  }
1046
1128
 
1047
1129
  // src/commands/init.ts
1048
- import * as p from "@clack/prompts";
1130
+ import * as p2 from "@clack/prompts";
1049
1131
  import chalk9 from "chalk";
1050
1132
  async function initCommand(options) {
1051
- p.intro(chalk9.bgCyan.black(" AeroCoding CLI "));
1133
+ p2.intro(chalk9.bgCyan.black(" AeroCoding CLI "));
1052
1134
  if (!options.force && await configExists()) {
1053
- const overwrite = await p.confirm({
1135
+ const overwrite = await p2.confirm({
1054
1136
  message: "Config file already exists. Overwrite?",
1055
1137
  initialValue: false
1056
1138
  });
1057
- if (p.isCancel(overwrite) || !overwrite) {
1058
- p.cancel("Operation cancelled.");
1139
+ if (p2.isCancel(overwrite) || !overwrite) {
1140
+ p2.cancel("Operation cancelled.");
1059
1141
  process.exit(0);
1060
1142
  }
1061
1143
  }
1062
1144
  const tokenManager = new TokenManager();
1063
1145
  const token = await tokenManager.getAccessToken();
1064
1146
  if (!token) {
1065
- p.cancel("Not logged in. Run 'aerocoding login' first.");
1147
+ p2.cancel("Not logged in. Run 'aerocoding login' first.");
1066
1148
  process.exit(1);
1067
1149
  }
1068
1150
  const apiClient = createApiClientWithAutoLogout(token, tokenManager);
1069
1151
  try {
1070
- const orgSpinner = p.spinner();
1152
+ const orgSpinner = p2.spinner();
1071
1153
  orgSpinner.start("Loading organizations...");
1072
1154
  const organizations = await apiClient.listOrganizations();
1073
1155
  orgSpinner.stop("Organizations loaded");
1074
1156
  if (organizations.length === 0) {
1075
- p.cancel("No organizations found. Create one on aerocoding.dev first.");
1157
+ p2.cancel("No organizations found. Create one on aerocoding.dev first.");
1076
1158
  process.exit(1);
1077
1159
  }
1078
1160
  let organizationId;
1079
1161
  if (organizations.length === 1 && organizations[0]) {
1080
1162
  organizationId = organizations[0].id;
1081
- p.log.info(`Organization: ${organizations[0].name}`);
1163
+ p2.log.info(`Organization: ${organizations[0].name}`);
1082
1164
  } else {
1083
- const selectedOrg = await p.select({
1165
+ const selectedOrg = await p2.select({
1084
1166
  message: "Select organization",
1085
1167
  options: organizations.map((org) => ({
1086
1168
  value: org.id,
@@ -1088,23 +1170,23 @@ async function initCommand(options) {
1088
1170
  hint: org.planTier.toUpperCase()
1089
1171
  }))
1090
1172
  });
1091
- if (p.isCancel(selectedOrg)) {
1092
- p.cancel("Operation cancelled.");
1173
+ if (p2.isCancel(selectedOrg)) {
1174
+ p2.cancel("Operation cancelled.");
1093
1175
  process.exit(0);
1094
1176
  }
1095
1177
  organizationId = selectedOrg;
1096
1178
  }
1097
1179
  let projectId = options.project;
1098
1180
  if (!projectId) {
1099
- const spinner3 = p.spinner();
1181
+ const spinner3 = p2.spinner();
1100
1182
  spinner3.start("Loading projects...");
1101
1183
  const projects = await apiClient.listProjects(organizationId);
1102
1184
  spinner3.stop("Projects loaded");
1103
1185
  if (projects.length === 0) {
1104
- p.cancel("No projects in this organization. Create one on aerocoding.dev first.");
1186
+ p2.cancel("No projects in this organization. Create one on aerocoding.dev first.");
1105
1187
  process.exit(1);
1106
1188
  }
1107
- const selectedProject = await p.select({
1189
+ const selectedProject = await p2.select({
1108
1190
  message: "Select project",
1109
1191
  options: projects.map((proj) => ({
1110
1192
  value: proj.id,
@@ -1112,56 +1194,44 @@ async function initCommand(options) {
1112
1194
  hint: [proj.backendFramework, proj.frontendFramework].filter(Boolean).join(" + ")
1113
1195
  }))
1114
1196
  });
1115
- if (p.isCancel(selectedProject)) {
1116
- p.cancel("Operation cancelled.");
1197
+ if (p2.isCancel(selectedProject)) {
1198
+ p2.cancel("Operation cancelled.");
1117
1199
  process.exit(0);
1118
1200
  }
1119
1201
  projectId = selectedProject;
1120
1202
  }
1121
- const spinner2 = p.spinner();
1203
+ const spinner2 = p2.spinner();
1122
1204
  spinner2.start("Fetching project details...");
1123
1205
  const project = await apiClient.getProject(projectId);
1124
1206
  spinner2.stop(`Project: ${project.name}`);
1125
- const targetOptions = [];
1126
- if (project.backendFramework) {
1127
- targetOptions.push({
1128
- value: "backend",
1129
- label: `Backend (${project.backendFramework})`
1130
- });
1131
- }
1132
- if (project.frontendFramework) {
1133
- targetOptions.push({
1134
- value: "frontend",
1135
- label: `Frontend (${project.frontendFramework})`
1136
- });
1137
- }
1138
- if (targetOptions.length === 0) {
1139
- p.cancel("Project has no frameworks configured. Update it on aerocoding.dev first.");
1207
+ const hasBackend = !!project.backendFramework;
1208
+ const hasFrontend = !!project.frontendFramework;
1209
+ if (!hasBackend && !hasFrontend) {
1210
+ p2.cancel("Project has no frameworks configured. Update it on aerocoding.dev first.");
1140
1211
  process.exit(1);
1141
1212
  }
1142
- const targets = await p.multiselect({
1143
- message: "What do you want to generate?",
1144
- options: targetOptions,
1145
- required: true
1146
- });
1147
- if (p.isCancel(targets)) {
1148
- p.cancel("Operation cancelled.");
1149
- process.exit(0);
1213
+ if (hasBackend) {
1214
+ p2.log.success(`Backend: ${project.backendFramework?.toUpperCase()} detected`);
1215
+ }
1216
+ if (hasFrontend) {
1217
+ p2.log.success(`Frontend: ${project.frontendFramework?.toUpperCase()} detected`);
1150
1218
  }
1151
- const selectedTargets = targets;
1152
1219
  const config = {
1153
1220
  project: projectId,
1154
1221
  output: "./.aerocoding",
1222
+ architectureStyle: "flat",
1223
+ // Default, will be updated based on template or user choice
1155
1224
  codeStyle: {
1156
1225
  includeValidations: true,
1157
1226
  includeComments: true,
1158
- includeAnnotations: true,
1159
1227
  includeLogging: true,
1160
1228
  includeTesting: true
1161
1229
  }
1162
1230
  };
1163
- if (selectedTargets.includes("backend") && project.backendFramework) {
1164
- const archSpinner = p.spinner();
1231
+ let selectedBackendTemplate = null;
1232
+ let selectedFrontendTemplate = null;
1233
+ if (hasBackend && project.backendFramework) {
1234
+ const archSpinner = p2.spinner();
1165
1235
  archSpinner.start("Loading backend templates...");
1166
1236
  const templateResult = await apiClient.getTemplates({
1167
1237
  category: "backend",
@@ -1169,7 +1239,7 @@ async function initCommand(options) {
1169
1239
  });
1170
1240
  archSpinner.stop("Templates loaded");
1171
1241
  if (templateResult.templates.length > 0) {
1172
- const preset = await p.select({
1242
+ const preset = await p2.select({
1173
1243
  message: "Backend template",
1174
1244
  options: templateResult.templates.map((tmpl) => ({
1175
1245
  value: tmpl.id,
@@ -1177,39 +1247,19 @@ async function initCommand(options) {
1177
1247
  hint: tmpl.description || `${tmpl.tier} tier`
1178
1248
  }))
1179
1249
  });
1180
- if (p.isCancel(preset)) {
1181
- p.cancel("Operation cancelled.");
1250
+ if (p2.isCancel(preset)) {
1251
+ p2.cancel("Operation cancelled.");
1182
1252
  process.exit(0);
1183
1253
  }
1184
1254
  const fullTemplate = await apiClient.getTemplate(preset);
1185
- if (fullTemplate.layers && fullTemplate.layers.length > 0) {
1186
- const layers = await p.multiselect({
1187
- message: "Select backend layers to include",
1188
- options: fullTemplate.layers.map((layer) => ({
1189
- value: layer.id,
1190
- label: layer.name,
1191
- hint: layer.category
1192
- })),
1193
- initialValues: fullTemplate.layers.filter((l) => l.enabled).map((l) => l.id)
1194
- });
1195
- if (p.isCancel(layers)) {
1196
- p.cancel("Operation cancelled.");
1197
- process.exit(0);
1198
- }
1199
- config.backend = {
1200
- preset,
1201
- layers
1202
- };
1203
- } else {
1204
- config.backend = {
1205
- preset,
1206
- layers: []
1207
- };
1208
- }
1255
+ selectedBackendTemplate = fullTemplate;
1256
+ config.backend = {
1257
+ preset
1258
+ };
1209
1259
  }
1210
1260
  }
1211
- if (selectedTargets.includes("frontend") && project.frontendFramework) {
1212
- const archSpinner = p.spinner();
1261
+ if (hasFrontend && project.frontendFramework) {
1262
+ const archSpinner = p2.spinner();
1213
1263
  archSpinner.start("Loading frontend templates...");
1214
1264
  const templateResult = await apiClient.getTemplates({
1215
1265
  category: "frontend",
@@ -1217,7 +1267,7 @@ async function initCommand(options) {
1217
1267
  });
1218
1268
  archSpinner.stop("Templates loaded");
1219
1269
  if (templateResult.templates.length > 0) {
1220
- const preset = await p.select({
1270
+ const preset = await p2.select({
1221
1271
  message: "Frontend template",
1222
1272
  options: templateResult.templates.map((tmpl) => ({
1223
1273
  value: tmpl.id,
@@ -1225,105 +1275,84 @@ async function initCommand(options) {
1225
1275
  hint: tmpl.description || `${tmpl.tier} tier`
1226
1276
  }))
1227
1277
  });
1228
- if (p.isCancel(preset)) {
1229
- p.cancel("Operation cancelled.");
1278
+ if (p2.isCancel(preset)) {
1279
+ p2.cancel("Operation cancelled.");
1230
1280
  process.exit(0);
1231
1281
  }
1232
1282
  const fullTemplate = await apiClient.getTemplate(preset);
1233
- if (fullTemplate.layers && fullTemplate.layers.length > 0) {
1234
- const layers = await p.multiselect({
1235
- message: "Select frontend layers to include",
1236
- options: fullTemplate.layers.map((layer) => ({
1237
- value: layer.id,
1238
- label: layer.name,
1239
- hint: layer.category
1240
- })),
1241
- initialValues: fullTemplate.layers.filter((l) => l.enabled).map((l) => l.id)
1242
- });
1243
- if (p.isCancel(layers)) {
1244
- p.cancel("Operation cancelled.");
1245
- process.exit(0);
1246
- }
1247
- config.frontend = {
1248
- preset,
1249
- layers
1250
- };
1251
- } else {
1252
- config.frontend = {
1253
- preset,
1254
- layers: []
1255
- };
1256
- }
1283
+ selectedFrontendTemplate = fullTemplate;
1284
+ config.frontend = {
1285
+ preset
1286
+ };
1257
1287
  }
1258
1288
  }
1259
- const architectureStyle = await p.select({
1289
+ const templateArchStyle = selectedBackendTemplate?.architectureStyle || selectedFrontendTemplate?.architectureStyle;
1290
+ const recommendedStyle = templateArchStyle || "flat";
1291
+ const architectureStyle = await p2.select({
1260
1292
  message: "How would you like to organize your code?",
1261
1293
  options: [
1262
1294
  {
1263
1295
  value: "bounded-contexts",
1264
- label: "Bounded Contexts",
1296
+ label: recommendedStyle === "bounded-contexts" ? "Bounded Contexts (Recommended)" : "Bounded Contexts",
1265
1297
  hint: "Each module has its own Domain, Application, Infrastructure"
1266
1298
  },
1267
1299
  {
1268
1300
  value: "flat",
1269
- label: "Flat Structure",
1301
+ label: recommendedStyle === "flat" ? "Flat Structure (Recommended)" : "Flat Structure",
1270
1302
  hint: "Single Domain, Application, Infrastructure for the entire project"
1271
1303
  }
1272
1304
  ],
1273
- initialValue: "bounded-contexts"
1305
+ initialValue: recommendedStyle
1274
1306
  });
1275
- if (p.isCancel(architectureStyle)) {
1276
- p.cancel("Operation cancelled.");
1307
+ if (p2.isCancel(architectureStyle)) {
1308
+ p2.cancel("Operation cancelled.");
1277
1309
  process.exit(0);
1278
1310
  }
1279
1311
  config.architectureStyle = architectureStyle;
1280
- const codeStyleOptions = await p.multiselect({
1312
+ const codeStyleOptions = await p2.multiselect({
1281
1313
  message: "Code style options",
1282
1314
  options: [
1283
- { value: "validations", label: "Include validations", hint: "Add validation rules" },
1284
- { value: "comments", label: "Include comments", hint: "Add code documentation" },
1285
- { value: "annotations", label: "Include annotations", hint: "Add decorators/attributes" },
1286
- { value: "logging", label: "Include logging", hint: "Add log statements" },
1287
- { value: "testing", label: "Include tests", hint: "Generate test files" }
1315
+ { value: "validations", label: "Include validations (Recommended)", hint: "Add validation rules" },
1316
+ { value: "comments", label: "Include comments (Recommended)", hint: "Add code documentation" },
1317
+ { value: "logging", label: "Include logging (Recommended)", hint: "Add log statements" },
1318
+ { value: "testing", label: "Include tests (Recommended)", hint: "Generate test files" }
1288
1319
  ],
1289
- initialValues: ["validations", "comments", "annotations", "logging", "testing"]
1320
+ initialValues: ["validations", "comments", "logging", "testing"]
1290
1321
  });
1291
- if (p.isCancel(codeStyleOptions)) {
1292
- p.cancel("Operation cancelled.");
1322
+ if (p2.isCancel(codeStyleOptions)) {
1323
+ p2.cancel("Operation cancelled.");
1293
1324
  process.exit(0);
1294
1325
  }
1295
1326
  const selectedStyles = codeStyleOptions;
1296
1327
  config.codeStyle = {
1297
1328
  includeValidations: selectedStyles.includes("validations"),
1298
1329
  includeComments: selectedStyles.includes("comments"),
1299
- includeAnnotations: selectedStyles.includes("annotations"),
1300
1330
  includeLogging: selectedStyles.includes("logging"),
1301
1331
  includeTesting: selectedStyles.includes("testing")
1302
1332
  };
1303
- const output = await p.text({
1304
- message: "Output directory",
1305
- initialValue: "./.aerocoding",
1306
- validate: (value) => {
1307
- if (!value) return "Output directory is required";
1308
- return void 0;
1309
- }
1310
- });
1311
- if (p.isCancel(output)) {
1312
- p.cancel("Operation cancelled.");
1313
- process.exit(0);
1333
+ config.output = "./.aerocoding";
1334
+ p2.log.step(chalk9.bold("Configuration Summary:"));
1335
+ if (config.backend) {
1336
+ p2.log.info(` Backend: ${config.backend.preset}`);
1337
+ }
1338
+ if (config.frontend) {
1339
+ p2.log.info(` Frontend: ${config.frontend.preset}`);
1314
1340
  }
1315
- config.output = output;
1341
+ p2.log.info(
1342
+ ` Architecture: ${config.architectureStyle === "bounded-contexts" ? "Bounded Contexts" : "Flat Structure"}`
1343
+ );
1344
+ p2.log.info(` Output: ${config.output}`);
1316
1345
  await saveConfig(config);
1317
- p.outro(
1346
+ p2.outro(
1318
1347
  chalk9.green("Config saved to .aerocodingrc.json") + "\n\n" + chalk9.gray(" Run ") + chalk9.cyan("aerocoding generate") + chalk9.gray(" to generate code!")
1319
1348
  );
1320
1349
  } catch (error) {
1321
1350
  if (error.response?.status === 401) {
1322
1351
  await handleUnauthorized(tokenManager);
1323
1352
  } else if (error.response?.data?.message) {
1324
- p.cancel(error.response.data.message);
1353
+ p2.cancel(error.response.data.message);
1325
1354
  } else {
1326
- p.cancel(error.message || "An unexpected error occurred");
1355
+ p2.cancel(error.message || "An unexpected error occurred");
1327
1356
  }
1328
1357
  process.exit(1);
1329
1358
  }
@@ -1349,13 +1378,13 @@ async function statusCommand() {
1349
1378
  // src/index.ts
1350
1379
  import "dotenv/config";
1351
1380
  var program = new Command();
1352
- program.name("aerocoding").description("AeroCoding CLI - Generate production-ready code from UML diagrams").version("0.1.21");
1381
+ program.name("aerocoding").description("AeroCoding CLI - Generate production-ready code from UML diagrams").version("0.1.23");
1353
1382
  program.command("login").description("Authenticate with AeroCoding").action(loginCommand);
1354
1383
  program.command("logout").description("Logout and clear stored credentials").action(logoutCommand);
1355
1384
  program.command("whoami").description("Show current authenticated user").action(whoamiCommand);
1356
1385
  program.command("init").description("Initialize AeroCoding in current directory").option("-p, --project <id>", "Project ID (skip selection)").option("-f, --force", "Overwrite existing config without asking").action(initCommand);
1357
1386
  program.command("pull").description("Pull schema from cloud").option("-p, --project <id>", "Project ID").action(pullCommand);
1358
1387
  program.command("status").description("Show local schema status").action(statusCommand);
1359
- program.command("generate").alias("gen").description("Generate code from schema").option("-p, --project <id>", "Project ID").option("-t, --targets <targets...>", "Generation targets (e.g., dotnet-entity)").option("-e, --entities <entities...>", "Filter by entity names").option("-o, --output <dir>", "Output directory", "./.aerocoding").option("--backend-preset <preset>", "Backend architecture preset").option("--frontend-preset <preset>", "Frontend architecture preset").option("--backend-layers <layers...>", "Backend layers to generate").option("--frontend-layers <layers...>", "Frontend layers to generate").option("--no-validations", "Exclude validations").option("--no-comments", "Exclude comments").option("--no-annotations", "Exclude annotations").option("--no-logging", "Exclude logging statements").option("--no-testing", "Exclude test files").option("--validation-lib <framework>", "Validation library (e.g., fluentvalidation, zod, formz)").option("-v, --verbose", "Show all generated file paths").option("-y, --yes", "Skip confirmation prompt").action(generateCommand);
1388
+ program.command("generate").alias("gen").description("Generate code from schema").option("-p, --project <id>", "Project ID").option("-t, --targets <targets...>", "Generation targets (e.g., dotnet-entity)").option("-e, --entities <entities...>", "Filter by entity names").option("-o, --output <dir>", "Output directory", "./.aerocoding").option("--backend-preset <preset>", "Backend architecture preset").option("--frontend-preset <preset>", "Frontend architecture preset").option("--backend-layers <layers...>", "Backend layers to generate").option("--frontend-layers <layers...>", "Frontend layers to generate").option("--no-validations", "Exclude validations").option("--no-comments", "Exclude comments").option("--no-annotations", "Exclude annotations").option("--no-logging", "Exclude logging statements").option("--no-testing", "Exclude test files").option("--validation-lib <framework>", "Validation library (e.g., fluentvalidation, zod, formz)").option("-v, --verbose", "Show all generated file paths").option("-y, --yes", "Skip confirmation prompt").option("-a, --all", "Generate all bounded contexts and targets without prompting").action(generateCommand);
1360
1389
  program.parse();
1361
1390
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/commands/login.ts","../src/auth/device-flow.ts","../src/auth/token-manager.ts","../src/api/client.ts","../src/commands/_shared/create-api-client.ts","../src/commands/_shared/unauthorized.ts","../src/commands/logout.ts","../src/commands/whoami.ts","../src/commands/generate.ts","../src/utils/file-writer.ts","../src/utils/prompt.ts","../src/config/loader.ts","../src/config/schema.ts","../src/commands/init.ts","../src/commands/pull.ts","../src/commands/status.ts"],"sourcesContent":["#!/usr/bin/env node\r\n\r\nimport { Command } from \"commander\";\r\nimport { loginCommand } from \"./commands/login.js\";\r\nimport { logoutCommand } from \"./commands/logout.js\";\r\nimport { whoamiCommand } from \"./commands/whoami.js\";\r\nimport { generateCommand } from \"./commands/generate.js\";\r\nimport { initCommand } from \"./commands/init.js\";\r\nimport { pullCommand } from \"./commands/pull.js\";\r\nimport { statusCommand } from \"./commands/status.js\";\r\nimport \"dotenv/config\";\r\n\r\nconst program = new Command();\r\n\r\nprogram\r\n .name(\"aerocoding\")\r\n .description(\"AeroCoding CLI - Generate production-ready code from UML diagrams\")\r\n .version(\"0.1.21\");\r\n\r\n// ============================================\r\n// Authentication Commands\r\n// ============================================\r\n\r\nprogram\r\n .command(\"login\")\r\n .description(\"Authenticate with AeroCoding\")\r\n .action(loginCommand);\r\n\r\nprogram\r\n .command(\"logout\")\r\n .description(\"Logout and clear stored credentials\")\r\n .action(logoutCommand);\r\n\r\nprogram\r\n .command(\"whoami\")\r\n .description(\"Show current authenticated user\")\r\n .action(whoamiCommand);\r\n\r\n// ============================================\r\n// Project Commands\r\n// ============================================\r\n\r\nprogram\r\n .command(\"init\")\r\n .description(\"Initialize AeroCoding in current directory\")\r\n .option(\"-p, --project <id>\", \"Project ID (skip selection)\")\r\n .option(\"-f, --force\", \"Overwrite existing config without asking\")\r\n .action(initCommand);\r\n\r\nprogram\r\n .command(\"pull\")\r\n .description(\"Pull schema from cloud\")\r\n .option(\"-p, --project <id>\", \"Project ID\")\r\n .action(pullCommand);\r\n\r\nprogram\r\n .command(\"status\")\r\n .description(\"Show local schema status\")\r\n .action(statusCommand);\r\n\r\n// ============================================\r\n// Generation Commands\r\n// ============================================\r\n\r\nprogram\r\n .command(\"generate\")\r\n .alias(\"gen\")\r\n .description(\"Generate code from schema\")\r\n // Identification\r\n .option(\"-p, --project <id>\", \"Project ID\")\r\n .option(\"-t, --targets <targets...>\", \"Generation targets (e.g., dotnet-entity)\")\r\n .option(\"-e, --entities <entities...>\", \"Filter by entity names\")\r\n .option(\"-o, --output <dir>\", \"Output directory\", \"./.aerocoding\")\r\n // Presets & Layers\r\n .option(\"--backend-preset <preset>\", \"Backend architecture preset\")\r\n .option(\"--frontend-preset <preset>\", \"Frontend architecture preset\")\r\n .option(\"--backend-layers <layers...>\", \"Backend layers to generate\")\r\n .option(\"--frontend-layers <layers...>\", \"Frontend layers to generate\")\r\n // Code style toggles (optimistic defaults - all enabled by default)\r\n .option(\"--no-validations\", \"Exclude validations\")\r\n .option(\"--no-comments\", \"Exclude comments\")\r\n .option(\"--no-annotations\", \"Exclude annotations\")\r\n .option(\"--no-logging\", \"Exclude logging statements\")\r\n .option(\"--no-testing\", \"Exclude test files\")\r\n // Validation library (framework-agnostic)\r\n .option(\"--validation-lib <framework>\", \"Validation library (e.g., fluentvalidation, zod, formz)\")\r\n // Control\r\n .option(\"-v, --verbose\", \"Show all generated file paths\")\r\n .option(\"-y, --yes\", \"Skip confirmation prompt\")\r\n .action(generateCommand);\r\n\r\n// ============================================\r\n// Parse and Execute\r\n// ============================================\r\n\r\nprogram.parse();\r\n","import chalk from \"chalk\";\r\nimport { DeviceFlow } from \"../auth/device-flow.js\";\r\nimport { TokenManager } from \"../auth/token-manager.js\";\r\nimport { createApiClientWithAutoLogout } from \"./_shared/create-api-client.js\";\r\nimport { handleUnauthorized } from \"./_shared/unauthorized.js\";\r\n\r\n/**\r\n * Login Command\r\n *\r\n * Authenticates user via OAuth Device Flow\r\n * Stores tokens securely in OS credential manager\r\n */\r\nexport async function loginCommand() {\r\n console.log(chalk.bold(\"\\nAeroCoding CLI Login\\n\"));\r\n\r\n const tokenManager = new TokenManager();\r\n\r\n // Check if already logged in\r\n const existingToken = await tokenManager.getAccessToken();\r\n if (existingToken) {\r\n const metadata = await tokenManager.getUserMetadata();\r\n console.log(\r\n chalk.yellow(\"Already logged in as:\"),\r\n chalk.white(metadata?.email || \"unknown\")\r\n );\r\n console.log(\r\n chalk.gray(\r\n \" Run 'aerocoding logout' to login with a different account\\n\"\r\n )\r\n );\r\n return;\r\n }\r\n\r\n try {\r\n // Initiate device flow\r\n const deviceFlow = new DeviceFlow();\r\n const tokens = await deviceFlow.initiateAuth();\r\n\r\n // Get user info\r\n const apiClient = createApiClientWithAutoLogout(\r\n tokens.access_token,\r\n tokenManager\r\n );\r\n let user;\r\n try {\r\n user = await apiClient.getCurrentUser();\r\n } catch (error: any) {\r\n if (error.response?.status === 401) {\r\n await handleUnauthorized(tokenManager);\r\n }\r\n throw error;\r\n }\r\n\r\n // Save tokens\r\n await tokenManager.saveTokens(tokens.access_token, tokens.refresh_token, {\r\n id: user.id,\r\n email: user.email,\r\n name: user.name || undefined,\r\n tier: user.tier,\r\n });\r\n\r\n console.log(\"\");\r\n console.log(\r\n chalk.green(\"Successfully logged in as:\"),\r\n chalk.white(user.email)\r\n );\r\n console.log(chalk.gray(\" Run 'aerocoding whoami' to verify\\n\"));\r\n } catch (error: any) {\r\n console.error(\r\n chalk.red(\"\\nLogin failed:\"),\r\n error.message || \"Unknown error\"\r\n );\r\n process.exit(1);\r\n }\r\n}\r\n","import axios from \"axios\";\r\nimport chalk from \"chalk\";\r\nimport ora from \"ora\";\r\nimport open from \"open\";\r\n\r\nconst API_URL = process.env.API_URL || \"https://aerocoding.dev\";\r\nconst MAX_POLL_TIME = 15 * 60 * 1000; // 15 minutes\r\n\r\ninterface DeviceAuthResponse {\r\n device_code: string;\r\n user_code: string;\r\n confirmation_code: string;\r\n verification_uri: string;\r\n verification_uri_complete: string;\r\n expires_in: number;\r\n interval: number;\r\n}\r\n\r\ninterface TokenResponse {\r\n access_token: string;\r\n refresh_token: string;\r\n token_type: string;\r\n expires_in: number;\r\n}\r\n\r\n/**\r\n * DeviceFlow\r\n *\r\n * Implements OAuth 2.0 Device Authorization Grant (RFC 8628)\r\n * Used for CLI authentication without browser-based redirects\r\n */\r\nexport class DeviceFlow {\r\n /**\r\n * Initiate the complete device authorization flow\r\n */\r\n async initiateAuth(): Promise<TokenResponse> {\r\n // Step 1: Request device code\r\n const deviceAuth = await this.requestDeviceCode();\r\n\r\n // Step 2: Display user code and open browser\r\n this.displayUserCode(deviceAuth);\r\n await this.openBrowser(deviceAuth.verification_uri);\r\n\r\n // Step 3: Poll for authorization\r\n const tokens = await this.pollForToken(deviceAuth);\r\n\r\n return tokens;\r\n }\r\n\r\n /**\r\n * Step 1: Request device code from server\r\n */\r\n private async requestDeviceCode(): Promise<DeviceAuthResponse> {\r\n try {\r\n const response = await axios.post(`${API_URL}/api/device/authorize`, {\r\n client_id: \"aerocoding-cli\",\r\n scope: \"generate:code projects:read\",\r\n });\r\n\r\n return response.data;\r\n } catch (error: any) {\r\n console.error(chalk.red(\"Failed to initiate device authorization\"));\r\n if (error.response) {\r\n console.error(\r\n chalk.red(`Error: ${error.response.data.error_description}`)\r\n );\r\n }\r\n throw new Error(\"Failed to initiate device authorization\");\r\n }\r\n }\r\n\r\n /**\r\n * Step 2: Display user code and instructions\r\n */\r\n private displayUserCode(auth: DeviceAuthResponse): void {\r\n console.log(\"\\n\");\r\n console.log(chalk.cyan(\"━\".repeat(60)));\r\n console.log(chalk.bold.white(\" AeroCoding CLI - Device Activation\"));\r\n console.log(chalk.cyan(\"━\".repeat(60)));\r\n console.log(\"\");\r\n console.log(chalk.white(\" 1. Open this URL in your browser:\"));\r\n console.log(chalk.cyan.bold(` ${auth.verification_uri}`));\r\n console.log(\"\");\r\n console.log(chalk.white(\" 2. Enter this code:\"));\r\n console.log(chalk.green.bold(` ${auth.user_code}`));\r\n console.log(\"\");\r\n console.log(\r\n chalk.gray(` Code expires in ${auth.expires_in / 60} minutes`)\r\n );\r\n console.log(chalk.cyan(\"━\".repeat(60)));\r\n console.log(\"\");\r\n }\r\n\r\n /**\r\n * Step 2.5: Open browser automatically\r\n */\r\n private async openBrowser(url: string): Promise<void> {\r\n try {\r\n await open(url);\r\n console.log(chalk.gray(\" Opening browser...\"));\r\n } catch {\r\n console.log(chalk.yellow(\" Could not open browser automatically\"));\r\n console.log(chalk.gray(\" Please open the URL manually\\n\"));\r\n }\r\n }\r\n\r\n /**\r\n * Step 3: Poll for token\r\n */\r\n private async pollForToken(auth: DeviceAuthResponse): Promise<TokenResponse> {\r\n const spinner = ora({\r\n text: \"Waiting for authorization...\",\r\n color: \"cyan\",\r\n }).start();\r\n\r\n const startTime = Date.now();\r\n let currentInterval = auth.interval * 1000;\r\n\r\n while (true) {\r\n // Check timeout\r\n if (Date.now() - startTime > MAX_POLL_TIME) {\r\n spinner.fail(chalk.red(\"Authorization timeout\"));\r\n throw new Error(\"Device authorization timed out\");\r\n }\r\n\r\n try {\r\n const response = await axios.post(`${API_URL}/api/device/token`, {\r\n device_code: auth.device_code,\r\n client_id: \"aerocoding-cli\",\r\n });\r\n\r\n spinner.succeed(chalk.green(\"Successfully authenticated!\"));\r\n return response.data;\r\n } catch (error: any) {\r\n const errorCode = error.response?.data?.error;\r\n const errorDescription = error.response?.data?.error_description;\r\n\r\n if (errorCode === \"authorization_pending\") {\r\n // Keep polling\r\n await this.sleep(currentInterval);\r\n continue;\r\n }\r\n\r\n if (errorCode === \"slow_down\") {\r\n // Increase poll interval by 5 seconds\r\n currentInterval += 5000;\r\n spinner.text = \"Polling... (slowed down to avoid spam)\";\r\n await this.sleep(currentInterval);\r\n continue;\r\n }\r\n\r\n if (errorCode === \"expired_token\") {\r\n spinner.fail(chalk.red(\"Authorization code expired\"));\r\n throw new Error(\"Device code expired. Please try again.\");\r\n }\r\n\r\n if (errorCode === \"access_denied\") {\r\n spinner.fail(chalk.red(\"Authorization denied\"));\r\n throw new Error(\"You denied the authorization request\");\r\n }\r\n\r\n // Unknown error\r\n spinner.fail(chalk.red(\"Authorization failed\"));\r\n console.error(\r\n chalk.red(`Error: ${errorDescription || \"Unknown error\"}`)\r\n );\r\n throw new Error(errorDescription || \"Unknown error\");\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Helper: Sleep for specified milliseconds\r\n */\r\n private sleep(ms: number): Promise<void> {\r\n return new Promise((resolve) => setTimeout(resolve, ms));\r\n }\r\n}\r\n","import { Entry } from \"@napi-rs/keyring\";\r\nimport { createClient, SupabaseClient } from \"@supabase/supabase-js\";\r\n\r\nconst SERVICE_NAME = \"aerocoding-cli\";\r\n\r\n// Public Supabase credentials (anon key is safe to expose)\r\nconst SUPABASE_URL = \"https://peqpttkvdpjgmduzacwl.supabase.co\";\r\nconst SUPABASE_ANON_KEY = \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InBlcXB0dGt2ZHBqZ21kdXphY3dsIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NjQyNjUxNzMsImV4cCI6MjA3OTg0MTE3M30.WAzqgZusGoOEHxidfHc1e4daBglG4DJG5LOXbqldWQA\";\r\n\r\ninterface UserMetadata {\r\n id: string;\r\n email: string;\r\n name?: string;\r\n tier?: string;\r\n}\r\n\r\n/**\r\n * Helper functions for keyring operations using Entry class\r\n */\r\nfunction getPassword(service: string, account: string): string | null {\r\n try {\r\n const entry = new Entry(service, account);\r\n return entry.getPassword();\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\nfunction setPassword(service: string, account: string, password: string): void {\r\n const entry = new Entry(service, account);\r\n entry.setPassword(password);\r\n}\r\n\r\nfunction deletePassword(service: string, account: string): void {\r\n try {\r\n const entry = new Entry(service, account);\r\n entry.deletePassword();\r\n } catch {\r\n // Ignore if entry doesn't exist\r\n }\r\n}\r\n\r\n/**\r\n * TokenManager\r\n *\r\n * Manages secure storage and automatic refresh of authentication tokens\r\n * Uses OS-level credential managers (Keychain/Credential Manager/Secret Service)\r\n */\r\nexport class TokenManager {\r\n private supabase: SupabaseClient;\r\n\r\n constructor() {\r\n this.supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY, {\r\n auth: {\r\n autoRefreshToken: false,\r\n persistSession: false,\r\n },\r\n });\r\n }\r\n\r\n /**\r\n * Get access token, automatically refreshing if expired\r\n */\r\n async getAccessToken(): Promise<string | null> {\r\n try {\r\n let accessToken = getPassword(SERVICE_NAME, \"access_token\");\r\n\r\n if (!accessToken) {\r\n return null;\r\n }\r\n\r\n // Check if expired\r\n if (this.isTokenExpired(accessToken)) {\r\n accessToken = await this.refreshTokens();\r\n }\r\n\r\n return accessToken;\r\n } catch {\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * Refresh tokens using stored refresh token\r\n */\r\n private async refreshTokens(): Promise<string | null> {\r\n try {\r\n const refreshToken = getPassword(SERVICE_NAME, \"refresh_token\");\r\n\r\n if (!refreshToken) {\r\n throw new Error(\"No refresh token available\");\r\n }\r\n\r\n const { data, error } = await this.supabase.auth.refreshSession({\r\n refresh_token: refreshToken,\r\n });\r\n\r\n if (error || !data.session) {\r\n throw new Error(\"Failed to refresh session\");\r\n }\r\n\r\n // Store new tokens (single-use refresh token rotation)\r\n setPassword(SERVICE_NAME, \"access_token\", data.session.access_token);\r\n setPassword(SERVICE_NAME, \"refresh_token\", data.session.refresh_token);\r\n\r\n return data.session.access_token;\r\n } catch {\r\n await this.logout();\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * Check if JWT token is expired (or expires in < 5 min)\r\n */\r\n private isTokenExpired(token: string): boolean {\r\n try {\r\n const payload = JSON.parse(\r\n Buffer.from(token.split(\".\")[1]!, \"base64\").toString()\r\n );\r\n const expiresAt = payload.exp * 1000;\r\n const now = Date.now();\r\n\r\n // Refresh 5 minutes before expiration\r\n return expiresAt - now < 5 * 60 * 1000;\r\n } catch {\r\n return true; // Treat invalid tokens as expired\r\n }\r\n }\r\n\r\n /**\r\n * Save tokens and user metadata after successful login\r\n */\r\n async saveTokens(\r\n accessToken: string,\r\n refreshToken: string,\r\n user: UserMetadata\r\n ): Promise<void> {\r\n setPassword(SERVICE_NAME, \"access_token\", accessToken);\r\n setPassword(SERVICE_NAME, \"refresh_token\", refreshToken);\r\n setPassword(SERVICE_NAME, \"user_metadata\", JSON.stringify(user));\r\n }\r\n\r\n /**\r\n * Get stored user metadata\r\n */\r\n async getUserMetadata(): Promise<UserMetadata | null> {\r\n try {\r\n const metadata = getPassword(SERVICE_NAME, \"user_metadata\");\r\n return metadata ? JSON.parse(metadata) : null;\r\n } catch {\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * Logout - clear all stored credentials\r\n */\r\n async logout(): Promise<void> {\r\n try {\r\n deletePassword(SERVICE_NAME, \"access_token\");\r\n deletePassword(SERVICE_NAME, \"refresh_token\");\r\n deletePassword(SERVICE_NAME, \"user_metadata\");\r\n } catch (error) {\r\n // Ignore errors during logout\r\n }\r\n }\r\n\r\n /**\r\n * Check if user is currently authenticated\r\n */\r\n async isAuthenticated(): Promise<boolean> {\r\n const token = await this.getAccessToken();\r\n return token !== null;\r\n }\r\n}\r\n","import axios, { AxiosInstance } from \"axios\";\r\n\r\n// Production API URL (can be overridden via API_URL env for local dev)\r\nconst API_URL = process.env.API_URL || \"https://aerocoding.dev\";\r\n\r\ninterface User {\r\n id: string;\r\n email: string;\r\n name: string | null;\r\n tier: string;\r\n}\r\n\r\ninterface Organization {\r\n id: string;\r\n name: string;\r\n slug: string;\r\n planTier: string;\r\n}\r\n\r\ninterface Project {\r\n id: string;\r\n name: string;\r\n slug: string;\r\n schema: any;\r\n organizationId: string;\r\n backendFramework?: string;\r\n frontendFramework?: string;\r\n createdAt: string;\r\n updatedAt: string;\r\n}\r\n\r\ninterface GeneratePayload {\r\n projectId: string;\r\n // NEW: Use templateId for full architecture generation\r\n templateId?: string;\r\n // Legacy: Use targets for simple generation\r\n targets?: string[];\r\n options?: {\r\n includeValidations?: boolean;\r\n includeComments?: boolean;\r\n includeAnnotations?: boolean;\r\n includeLogging?: boolean;\r\n includeTesting?: boolean;\r\n outputDir?: string;\r\n backendPreset?: string;\r\n frontendPreset?: string;\r\n backendLayers?: string[];\r\n frontendLayers?: string[];\r\n validationLib?: string;\r\n // NEW: Feature flags for template generation\r\n featureFlags?: Record<string, boolean>;\r\n };\r\n}\r\n\r\ninterface GeneratedFile {\r\n path: string;\r\n content: string;\r\n language: string;\r\n entityId?: string;\r\n}\r\n\r\ninterface GenerateResult {\r\n files: GeneratedFile[];\r\n stats?: {\r\n totalFiles?: number;\r\n totalEntities?: number;\r\n languages?: string[];\r\n };\r\n cliCommand?: string;\r\n warnings?: string[];\r\n creditsUsed?: number;\r\n creditsRemaining?: number;\r\n}\r\n\r\ninterface CreditUsage {\r\n used: number;\r\n limit: number;\r\n bonusCredits: number;\r\n remaining: number;\r\n}\r\n\r\ninterface ArchitectureLayer {\r\n id: string;\r\n name: string;\r\n category: string;\r\n description?: string;\r\n}\r\n\r\ninterface Architecture {\r\n id: string;\r\n name: string;\r\n description: string;\r\n layers: ArchitectureLayer[];\r\n}\r\n\r\n// New Template Registry Types\r\ninterface TemplateMetadata {\r\n id: string;\r\n name: string;\r\n description: string;\r\n category: \"backend\" | \"frontend\" | \"database\" | \"infra\";\r\n language: string;\r\n framework: string;\r\n tier: \"starter\" | \"standard\" | \"enterprise\";\r\n tags: string[];\r\n version: string;\r\n author: string;\r\n isLegacy?: boolean;\r\n isOfficial?: boolean;\r\n isPremium?: boolean;\r\n}\r\n\r\ninterface TemplateLayer {\r\n id: string;\r\n name: string;\r\n description: string;\r\n category: string;\r\n enabled: boolean;\r\n}\r\n\r\ninterface TemplateFeatureFlag {\r\n id: string;\r\n name: string;\r\n label: string;\r\n description?: string;\r\n defaultValue: boolean;\r\n}\r\n\r\ninterface FullTemplate extends TemplateMetadata {\r\n layers: TemplateLayer[];\r\n featureFlags: TemplateFeatureFlag[];\r\n enabledModules: string[];\r\n}\r\n\r\ninterface TemplateFilter {\r\n category?: \"backend\" | \"frontend\" | \"database\" | \"infra\";\r\n language?: string;\r\n framework?: string;\r\n tier?: \"starter\" | \"standard\" | \"enterprise\";\r\n tags?: string[];\r\n}\r\n\r\ninterface TemplateSearchResult {\r\n templates: TemplateMetadata[];\r\n total: number;\r\n page: number;\r\n pageSize: number;\r\n}\r\n\r\ninterface TemplateCombination {\r\n id: string;\r\n name: string;\r\n description: string;\r\n backend: string;\r\n frontend: string;\r\n sharedTypes?: boolean;\r\n apiContract?: \"rest\" | \"graphql\" | \"grpc\";\r\n}\r\n\r\ninterface CreditEstimate {\r\n estimatedCredits: number;\r\n totalFiles: number;\r\n files: string[];\r\n entities: number;\r\n}\r\n\r\ninterface EstimatePayload {\r\n projectId: string;\r\n // Template mode (new)\r\n templateId?: string;\r\n // Legacy targets mode\r\n targets?: string[];\r\n options?: {\r\n outputDir?: string;\r\n backendPreset?: string;\r\n frontendPreset?: string;\r\n backendLayers?: string[];\r\n frontendLayers?: string[];\r\n featureFlags?: Record<string, boolean>;\r\n // Architecture style: bounded-contexts vs flat\r\n useContexts?: boolean;\r\n };\r\n}\r\n\r\n/**\r\n * ApiClient\r\n *\r\n * Authenticated HTTP client for AeroCoding API\r\n * All requests include Bearer token authentication\r\n */\r\nexport class ApiClient {\r\n private client: AxiosInstance;\r\n\r\n constructor(\r\n accessToken: string,\r\n options?: {\r\n onUnauthorized?: () => Promise<void> | void;\r\n }\r\n ) {\r\n this.client = axios.create({\r\n baseURL: API_URL,\r\n headers: {\r\n Authorization: `Bearer ${accessToken}`,\r\n \"Content-Type\": \"application/json\",\r\n \"X-Requested-With\": \"XMLHttpRequest\", // Required for CSRF validation bypass\r\n },\r\n timeout: 30000, // 30 seconds\r\n });\r\n\r\n this.client.interceptors.response.use(\r\n (response) => response,\r\n async (error) => {\r\n if (error?.response?.status === 401) {\r\n await options?.onUnauthorized?.();\r\n }\r\n\r\n return Promise.reject(error);\r\n }\r\n );\r\n }\r\n\r\n /**\r\n * Get current authenticated user\r\n */\r\n async getCurrentUser(): Promise<User> {\r\n const response = await this.client.get(\"/api/user/me\");\r\n return response.data;\r\n }\r\n\r\n /**\r\n * List user's organizations\r\n */\r\n async listOrganizations(): Promise<Organization[]> {\r\n const response = await this.client.get(\"/api/organizations\");\r\n return response.data;\r\n }\r\n\r\n /**\r\n * List user's projects\r\n */\r\n async listProjects(organizationId?: string): Promise<Project[]> {\r\n const response = await this.client.get(\"/api/projects\", {\r\n params: { organizationId },\r\n });\r\n return response.data;\r\n }\r\n\r\n /**\r\n * Get project by ID\r\n */\r\n async getProject(projectId: string): Promise<Project> {\r\n const response = await this.client.get(`/api/projects/${projectId}`);\r\n return response.data;\r\n }\r\n\r\n /**\r\n * Generate code from project schema\r\n */\r\n async generateCode(payload: GeneratePayload): Promise<GenerateResult> {\r\n const response = await this.client.post(\"/api/generate\", payload);\r\n return response.data.data;\r\n }\r\n\r\n /**\r\n * Get credit usage for organization\r\n */\r\n async getCreditUsage(organizationId: string): Promise<CreditUsage> {\r\n const response = await this.client.get(\"/api/credits/usage\", {\r\n params: { organizationId },\r\n });\r\n return response.data;\r\n }\r\n\r\n /**\r\n * Get available architectures for a framework\r\n */\r\n async getArchitectures(framework: string): Promise<Architecture[]> {\r\n const response = await this.client.get(\"/api/architectures\", {\r\n params: { framework },\r\n });\r\n return response.data;\r\n }\r\n\r\n /**\r\n * Estimate credit cost for a generation request\r\n */\r\n async estimateCreditCost(payload: EstimatePayload): Promise<CreditEstimate> {\r\n const response = await this.client.post(\"/api/generate/estimate\", payload);\r\n return response.data.data;\r\n }\r\n\r\n // ============================================\r\n // Template Registry API\r\n // ============================================\r\n\r\n /**\r\n * Search templates with filters\r\n */\r\n async getTemplates(filter: TemplateFilter = {}): Promise<TemplateSearchResult> {\r\n const params = new URLSearchParams();\r\n if (filter.category) params.set(\"category\", filter.category);\r\n if (filter.language) params.set(\"language\", filter.language);\r\n if (filter.framework) params.set(\"framework\", filter.framework);\r\n if (filter.tier) params.set(\"tier\", filter.tier);\r\n if (filter.tags?.length) params.set(\"tags\", filter.tags.join(\",\"));\r\n\r\n const response = await this.client.get(`/api/templates?${params.toString()}`);\r\n return response.data;\r\n }\r\n\r\n /**\r\n * Get full template by ID (includes layers and feature flags)\r\n */\r\n async getTemplate(id: string): Promise<FullTemplate> {\r\n const response = await this.client.get(`/api/templates/${id}?full=true`);\r\n return response.data.template;\r\n }\r\n\r\n /**\r\n * Get template combinations (backend + frontend pairs)\r\n */\r\n async getTemplateCombinations(): Promise<TemplateCombination[]> {\r\n const response = await this.client.get(\"/api/templates/combinations\");\r\n return response.data.combinations;\r\n }\r\n\r\n /**\r\n * Get templates compatible with a given template\r\n */\r\n async getCompatibleTemplates(templateId: string): Promise<TemplateMetadata[]> {\r\n const response = await this.client.get(`/api/templates/${templateId}?compatible=true`);\r\n return response.data.compatible || [];\r\n }\r\n}\r\n","import { ApiClient } from \"../../api/client.js\";\r\nimport { TokenManager } from \"../../auth/token-manager.js\";\r\n\r\nexport function createApiClientWithAutoLogout(\r\n accessToken: string,\r\n tokenManager: TokenManager\r\n): ApiClient {\r\n return new ApiClient(accessToken, {\r\n onUnauthorized: async () => {\r\n await tokenManager.logout();\r\n },\r\n });\r\n}\r\n","import chalk from \"chalk\";\r\nimport { TokenManager } from \"../../auth/token-manager.js\";\r\n\r\nexport async function handleUnauthorized(\r\n tokenManager: TokenManager\r\n): Promise<never> {\r\n await tokenManager.logout();\r\n\r\n console.error(\r\n chalk.yellow(\r\n \" Your session is invalid or expired. You have been logged out.\"\r\n )\r\n );\r\n console.error(chalk.gray(\" Run 'aerocoding login' to authenticate.\"));\r\n\r\n process.exit(1);\r\n}\r\n","import chalk from \"chalk\";\r\nimport { TokenManager } from \"../auth/token-manager.js\";\r\n\r\n/**\r\n * Logout Command\r\n *\r\n * Clears stored credentials from OS credential manager\r\n */\r\nexport async function logoutCommand() {\r\n const tokenManager = new TokenManager();\r\n\r\n const metadata = await tokenManager.getUserMetadata();\r\n if (!metadata) {\r\n console.log(chalk.yellow(\"Not logged in\"));\r\n return;\r\n }\r\n\r\n const email = metadata.email;\r\n\r\n await tokenManager.logout();\r\n\r\n console.log(chalk.green(\"Logged out successfully\"));\r\n console.log(chalk.gray(` Cleared credentials for ${email}\\n`));\r\n}\r\n","import chalk from \"chalk\";\r\nimport { TokenManager } from \"../auth/token-manager.js\";\r\nimport { createApiClientWithAutoLogout } from \"./_shared/create-api-client.js\";\r\nimport { handleUnauthorized } from \"./_shared/unauthorized.js\";\r\n\r\n/**\r\n * Whoami Command\r\n *\r\n * Shows current authenticated user information\r\n */\r\nexport async function whoamiCommand() {\r\n const tokenManager = new TokenManager();\r\n const token = await tokenManager.getAccessToken();\r\n\r\n if (!token) {\r\n console.log(chalk.red(\"Not logged in\"));\r\n console.log(chalk.gray(\" Run 'aerocoding login' to authenticate\\n\"));\r\n return;\r\n }\r\n\r\n try {\r\n const apiClient = createApiClientWithAutoLogout(token, tokenManager);\r\n const user = await apiClient.getCurrentUser();\r\n\r\n console.log(\"\");\r\n console.log(chalk.white(\"Logged in as:\"), chalk.cyan.bold(user.email));\r\n if (user.name) {\r\n console.log(chalk.gray(\" Name:\"), user.name);\r\n }\r\n console.log(\"\");\r\n } catch (error: any) {\r\n console.error(chalk.red(\"Failed to get user info\"));\r\n if (error.response?.status === 401) {\r\n await handleUnauthorized(tokenManager);\r\n }\r\n process.exit(1);\r\n }\r\n}\r\n","import chalk from \"chalk\";\r\nimport ora from \"ora\";\r\nimport { TokenManager } from \"../auth/token-manager.js\";\r\nimport { createApiClientWithAutoLogout } from \"./_shared/create-api-client.js\";\r\nimport { handleUnauthorized } from \"./_shared/unauthorized.js\";\r\nimport { writeGeneratedFiles, categorizeFilePaths } from \"../utils/file-writer.js\";\r\nimport { promptConfirm } from \"../utils/prompt.js\";\r\nimport { loadConfig } from \"../config/loader.js\";\r\nimport type { AerocodingConfig } from \"../config/schema.js\";\r\n\r\n/**\r\n * Map preset name to template ID for full architecture generation\r\n * Uses the new template system that generates all layers (DTOs, UseCases, Controllers, etc.)\r\n */\r\nfunction mapPresetToTemplateId(preset: string): string | null {\r\n const presetLower = preset.toLowerCase();\r\n\r\n // Clean Architecture presets → full template IDs\r\n if (presetLower.includes(\"clean\") && presetLower.includes(\"dotnet\")) {\r\n return \"clean-arch-dotnet\";\r\n }\r\n if (presetLower.includes(\"clean\") && (presetLower.includes(\"dart\") || presetLower.includes(\"flutter\"))) {\r\n return \"flutter-clean-dart-test\"; // Update when production template available\r\n }\r\n if (presetLower.includes(\"clean\") && presetLower.includes(\"typescript\")) {\r\n return \"minimal-typescript-test\"; // Update when production template available\r\n }\r\n\r\n // Direct template ID (if preset matches a template ID pattern)\r\n if (presetLower.startsWith(\"clean-arch-\")) {\r\n return preset;\r\n }\r\n\r\n return null;\r\n}\r\n\r\n/**\r\n * Map preset name to legacy generator target (fallback)\r\n * Used when no template ID is available for the preset\r\n */\r\nfunction mapPresetToTarget(preset: string): string | null {\r\n const presetLower = preset.toLowerCase();\r\n\r\n // .NET presets\r\n if (presetLower.includes(\"dotnet\") || presetLower.includes(\"aspnet\") || presetLower.includes(\"csharp\")) {\r\n return \"dotnet-entity\";\r\n }\r\n\r\n // Dart/Flutter presets\r\n if (presetLower.includes(\"dart\") || presetLower.includes(\"flutter\")) {\r\n return \"dart-entity\";\r\n }\r\n\r\n // TypeScript presets\r\n if (presetLower.includes(\"typescript\") || presetLower.includes(\"nextjs\") || presetLower.includes(\"react\")) {\r\n return \"typescript-interface\";\r\n }\r\n\r\n return null;\r\n}\r\n\r\n/**\r\n * Build template ID from config file\r\n * Prioritizes full architecture templates over simple targets\r\n */\r\nfunction buildTemplateIdFromConfig(config: AerocodingConfig | null): string | null {\r\n if (!config) return null;\r\n\r\n // Try backend preset first (most common for full architecture)\r\n if (config.backend?.preset) {\r\n const templateId = mapPresetToTemplateId(config.backend.preset);\r\n if (templateId) return templateId;\r\n }\r\n\r\n // Try frontend preset\r\n if (config.frontend?.preset) {\r\n const templateId = mapPresetToTemplateId(config.frontend.preset);\r\n if (templateId) return templateId;\r\n }\r\n\r\n return null;\r\n}\r\n\r\n/**\r\n * Build targets array from config file (fallback for legacy mode)\r\n * Maps backend/frontend presets to appropriate target types\r\n */\r\nfunction buildTargetsFromConfig(config: AerocodingConfig | null): string[] {\r\n if (!config) return [];\r\n\r\n const targets: string[] = [];\r\n\r\n // Add backend targets based on preset\r\n if (config.backend?.preset) {\r\n const target = mapPresetToTarget(config.backend.preset);\r\n if (target) {\r\n targets.push(target);\r\n }\r\n }\r\n\r\n // Add frontend targets based on preset\r\n if (config.frontend?.preset) {\r\n const target = mapPresetToTarget(config.frontend.preset);\r\n if (target) {\r\n targets.push(target);\r\n }\r\n }\r\n\r\n return targets;\r\n}\r\n\r\n/**\r\n * Build feature flags from config for template generation\r\n */\r\nfunction buildFeatureFlagsFromConfig(config: AerocodingConfig | null): Record<string, boolean> {\r\n const flags: Record<string, boolean> = {\r\n // Default all feature flags to true for full architecture\r\n includeDtos: true,\r\n includeUseCases: true,\r\n includeMappers: true,\r\n includeControllers: true,\r\n includeEfConfig: true,\r\n includeValidation: true,\r\n };\r\n\r\n if (!config) return flags;\r\n\r\n // Map codeStyle options to feature flags\r\n if (config.codeStyle?.includeValidations !== undefined) {\r\n flags.includeValidation = config.codeStyle.includeValidations;\r\n }\r\n if (config.codeStyle?.includeTesting !== undefined) {\r\n flags.includeTests = config.codeStyle.includeTesting;\r\n }\r\n\r\n return flags;\r\n}\r\n\r\ninterface GenerateOptions {\r\n project?: string;\r\n targets?: string[];\r\n entities?: string[];\r\n output: string;\r\n // Presets\r\n backendPreset?: string;\r\n frontendPreset?: string;\r\n backendLayers?: string[];\r\n frontendLayers?: string[];\r\n // Style toggles (commander inverts for --no-X, all default to true)\r\n validations?: boolean;\r\n comments?: boolean;\r\n annotations?: boolean;\r\n logging?: boolean;\r\n testing?: boolean;\r\n // Validation library (framework-agnostic)\r\n validationLib?: string;\r\n // Control\r\n verbose?: boolean;\r\n yes?: boolean;\r\n}\r\n\r\n/**\r\n * Generate Command\r\n *\r\n * Generates code from project schema via API\r\n * Consumes credits based on generated files and entity complexity\r\n *\r\n * Config file (.aerocodingrc.json) provides defaults, CLI args override\r\n */\r\nexport async function generateCommand(options: GenerateOptions) {\r\n // 1. Check authentication\r\n const tokenManager = new TokenManager();\r\n const token = await tokenManager.getAccessToken();\r\n\r\n if (!token) {\r\n console.log(chalk.red(\"\\n Not authenticated\"));\r\n console.log(chalk.gray(\" Run 'aerocoding login' to get started\\n\"));\r\n process.exit(1);\r\n }\r\n\r\n // 2. Load config file (optional)\r\n const config = await loadConfig();\r\n\r\n // 3. Merge config with CLI options (CLI overrides config)\r\n const projectId = options.project || config?.project;\r\n\r\n if (!projectId) {\r\n console.log(chalk.red(\"\\n Project ID required\"));\r\n console.log(chalk.gray(\" Run 'aerocoding init' to create a config file\"));\r\n console.log(chalk.gray(\" Or use --project <id> to specify a project\\n\"));\r\n process.exit(1);\r\n }\r\n\r\n // NEW: Try to build templateId first for full architecture generation\r\n const templateId = buildTemplateIdFromConfig(config);\r\n const featureFlags = templateId ? buildFeatureFlagsFromConfig(config) : undefined;\r\n\r\n // Fallback: Build targets from config if not using template mode\r\n const targets = !templateId ? (options.targets || buildTargetsFromConfig(config)) : undefined;\r\n\r\n // Merge other options with config defaults\r\n const output = options.output || config?.output || \"./.aerocoding\";\r\n const backendPreset = options.backendPreset || config?.backend?.preset;\r\n const frontendPreset = options.frontendPreset || config?.frontend?.preset;\r\n const backendLayers = options.backendLayers || config?.backend?.layers;\r\n const frontendLayers = options.frontendLayers || config?.frontend?.layers;\r\n const validationLib = options.validationLib || config?.libraries?.validation;\r\n\r\n // Style options: CLI --no-X overrides config, config overrides default (true)\r\n const includeValidations = options.validations ?? config?.codeStyle?.includeValidations ?? true;\r\n const includeComments = options.comments ?? config?.codeStyle?.includeComments ?? true;\r\n const includeAnnotations = options.annotations ?? config?.codeStyle?.includeAnnotations ?? true;\r\n const includeLogging = options.logging ?? config?.codeStyle?.includeLogging ?? true;\r\n const includeTesting = options.testing ?? config?.codeStyle?.includeTesting ?? true;\r\n\r\n const apiClient = createApiClientWithAutoLogout(token, tokenManager);\r\n\r\n let spinner = ora({ text: \"Fetching project...\", color: \"cyan\" }).start();\r\n\r\n try {\r\n // 4. Fetch project to get organizationId\r\n const project = await apiClient.getProject(projectId);\r\n spinner.succeed(chalk.gray(\"Project loaded\"));\r\n\r\n // 5. Fetch credit usage and estimate cost in parallel\r\n spinner = ora({ text: \"Checking credits...\", color: \"cyan\" }).start();\r\n\r\n const credits = await apiClient.getCreditUsage(project.organizationId);\r\n\r\n // Try to get cost estimate (includes file paths for preview)\r\n // Determine architecture style early for estimate\r\n const useContexts = config?.architectureStyle !== \"flat\";\r\n\r\n let estimate: { estimatedCredits: number; totalFiles: number; entities: number; files: string[] } | null = null;\r\n try {\r\n if (templateId) {\r\n // Template mode: estimate using templateId\r\n estimate = await apiClient.estimateCreditCost({\r\n projectId,\r\n templateId,\r\n options: {\r\n featureFlags,\r\n useContexts,\r\n },\r\n });\r\n } else if (targets && targets.length > 0) {\r\n // Legacy mode: estimate using targets\r\n estimate = await apiClient.estimateCreditCost({\r\n projectId,\r\n targets,\r\n options: {\r\n outputDir: output,\r\n backendPreset,\r\n frontendPreset,\r\n backendLayers,\r\n frontendLayers,\r\n useContexts,\r\n },\r\n });\r\n }\r\n } catch {\r\n // Estimate endpoint may not be available yet - continue without estimate\r\n }\r\n\r\n spinner.succeed(chalk.gray(\"Credits verified\"));\r\n\r\n // Check if project has entities (required for generation)\r\n if (estimate && estimate.entities === 0) {\r\n console.log(chalk.yellow(\"\\n ⚠ No entities found in this project.\"));\r\n console.log(chalk.gray(\" Create entities in the diagram editor and save (Ctrl+S) before generating.\\n\"));\r\n process.exit(1);\r\n }\r\n\r\n // Check if enough credits before showing summary (skip if no estimate)\r\n const hasEnoughCredits = estimate ? credits.remaining >= estimate.estimatedCredits : true;\r\n\r\n // 6. Show summary\r\n console.log(\"\");\r\n console.log(chalk.bold(\" Generation Summary\"));\r\n console.log(chalk.gray(\" ─────────────────────────────────\"));\r\n console.log(chalk.gray(\" Project:\"), chalk.white(project.name));\r\n if (config) {\r\n console.log(chalk.gray(\" Config:\"), chalk.cyan(\".aerocodingrc.json\"));\r\n }\r\n // Show generation mode\r\n if (templateId) {\r\n console.log(chalk.gray(\" Mode:\"), chalk.green(\"Full Architecture\"));\r\n console.log(chalk.gray(\" Template:\"), chalk.cyan(templateId));\r\n } else if (targets && targets.length > 0) {\r\n console.log(chalk.gray(\" Mode:\"), chalk.yellow(\"Simple (legacy)\"));\r\n console.log(chalk.gray(\" Targets:\"), chalk.cyan(targets.join(\", \")));\r\n } else {\r\n console.log(chalk.gray(\" Mode:\"), chalk.gray(\"default\"));\r\n }\r\n\r\n if (backendPreset) {\r\n console.log(chalk.gray(\" Backend Preset:\"), chalk.cyan(backendPreset));\r\n }\r\n if (frontendPreset) {\r\n console.log(chalk.gray(\" Frontend Preset:\"), chalk.cyan(frontendPreset));\r\n }\r\n\r\n // Show architecture style\r\n const archStyle = config?.architectureStyle || \"bounded-contexts\";\r\n console.log(\r\n chalk.gray(\" Architecture:\"),\r\n archStyle === \"bounded-contexts\"\r\n ? chalk.cyan(\"Bounded Contexts\")\r\n : chalk.yellow(\"Flat Structure\")\r\n );\r\n\r\n // Show style options if different from defaults (all default to true)\r\n const disabledOptions: string[] = [];\r\n if (!includeValidations) disabledOptions.push(\"validations\");\r\n if (!includeComments) disabledOptions.push(\"comments\");\r\n if (!includeAnnotations) disabledOptions.push(\"annotations\");\r\n if (!includeLogging) disabledOptions.push(\"logging\");\r\n if (!includeTesting) disabledOptions.push(\"testing\");\r\n\r\n if (disabledOptions.length > 0) {\r\n console.log(chalk.gray(\" Disabled:\"), chalk.yellow(disabledOptions.join(\", \")));\r\n }\r\n\r\n if (validationLib) {\r\n console.log(chalk.gray(\" Validation Lib:\"), chalk.cyan(validationLib));\r\n }\r\n\r\n console.log(chalk.gray(\" Output:\"), chalk.cyan(output));\r\n\r\n // Show categorized file preview (if available)\r\n if (estimate && estimate.files && estimate.files.length > 0) {\r\n console.log(\"\");\r\n console.log(chalk.bold(\" Files to Generate\"));\r\n console.log(chalk.gray(\" ─────────────────────────────────\"));\r\n\r\n const categories = categorizeFilePaths(estimate.files);\r\n const maxNameLength = Math.max(...categories.map((c) => c.name.length));\r\n\r\n for (const category of categories) {\r\n const padding = \" \".repeat(maxNameLength - category.name.length + 2);\r\n const countStr = category.count.toString().padStart(3, \" \");\r\n console.log(\r\n chalk.gray(` ${category.name}${padding}`),\r\n chalk.cyan(`${countStr} files`)\r\n );\r\n }\r\n\r\n console.log(chalk.gray(\" ─────────────────────────────────\"));\r\n const totalPadding = \" \".repeat(maxNameLength - 5 + 2);\r\n const totalStr = estimate.totalFiles.toString().padStart(3, \" \");\r\n console.log(\r\n chalk.white(` Total${totalPadding}`),\r\n chalk.bold.cyan(`${totalStr} files`)\r\n );\r\n console.log(chalk.gray(` Entities:`), chalk.cyan(estimate.entities));\r\n }\r\n\r\n // Show credits section\r\n console.log(\"\");\r\n console.log(chalk.bold(\" Credits\"));\r\n console.log(chalk.gray(\" ─────────────────────────────────\"));\r\n if (estimate) {\r\n console.log(\r\n chalk.white(\" Cost:\"),\r\n hasEnoughCredits\r\n ? chalk.bold.yellow(`${estimate.estimatedCredits} credits`)\r\n : chalk.bold.red(`${estimate.estimatedCredits} credits`)\r\n );\r\n }\r\n console.log(\r\n chalk.white(\" Available:\"),\r\n hasEnoughCredits\r\n ? chalk.bold.green(`${credits.remaining} credits`)\r\n : chalk.bold.red(`${credits.remaining} credits (insufficient)`)\r\n );\r\n console.log(\"\");\r\n\r\n // Warn if not enough credits\r\n if (!hasEnoughCredits && estimate) {\r\n console.log(chalk.red(\" ⚠ Not enough credits for this generation.\"));\r\n console.log(chalk.gray(` Need ${estimate.estimatedCredits - credits.remaining} more credits.\\n`));\r\n process.exit(1);\r\n }\r\n\r\n // 7. Confirmation (unless --yes)\r\n if (!options.yes) {\r\n const confirmed = await promptConfirm(\" Proceed with generation?\");\r\n if (!confirmed) {\r\n console.log(chalk.yellow(\"\\n Generation cancelled\\n\"));\r\n process.exit(0);\r\n }\r\n }\r\n\r\n // 8. Call API\r\n console.log(\"\");\r\n spinner = ora({ text: \"Generating code...\", color: \"cyan\" }).start();\r\n\r\n // Build API request based on mode (useContexts already determined above)\r\n const generatePayload = templateId\r\n ? {\r\n // NEW: Full architecture mode using template\r\n projectId,\r\n templateId,\r\n options: {\r\n includeValidations,\r\n includeComments,\r\n featureFlags,\r\n useContexts,\r\n },\r\n }\r\n : {\r\n // Legacy mode using targets\r\n projectId,\r\n targets,\r\n options: {\r\n includeValidations,\r\n includeComments,\r\n includeAnnotations,\r\n includeLogging,\r\n includeTesting,\r\n outputDir: output,\r\n backendPreset,\r\n frontendPreset,\r\n backendLayers,\r\n frontendLayers,\r\n validationLib,\r\n useContexts,\r\n },\r\n };\r\n\r\n const result = await apiClient.generateCode(generatePayload);\r\n\r\n spinner.succeed(chalk.green(\"Code generated successfully!\"));\r\n\r\n // 9. Show results with credits\r\n console.log(\"\");\r\n console.log(chalk.bold(\" Results\"));\r\n console.log(chalk.gray(\" ─────────────────────────────────\"));\r\n console.log(chalk.gray(\" Files:\"), chalk.cyan(result.stats?.totalFiles ?? result.files?.length ?? 0));\r\n if (result.stats?.totalEntities) {\r\n console.log(chalk.gray(\" Entities:\"), chalk.cyan(result.stats.totalEntities));\r\n }\r\n if (result.stats?.languages && result.stats.languages.length > 0) {\r\n console.log(\r\n chalk.gray(\" Languages:\"),\r\n chalk.cyan(result.stats.languages.join(\", \"))\r\n );\r\n }\r\n\r\n if (result.creditsUsed !== undefined) {\r\n console.log(\"\");\r\n console.log(chalk.bold(\" Credits\"));\r\n console.log(chalk.gray(\" ─────────────────────────────────\"));\r\n console.log(chalk.gray(\" Used:\"), chalk.yellow(result.creditsUsed));\r\n console.log(\r\n chalk.gray(\" Remaining:\"),\r\n result.creditsRemaining !== undefined && result.creditsRemaining > 50\r\n ? chalk.green(result.creditsRemaining)\r\n : chalk.yellow(result.creditsRemaining)\r\n );\r\n }\r\n\r\n // Show warnings if any\r\n if (result.warnings && result.warnings.length > 0) {\r\n console.log(\"\");\r\n console.log(chalk.yellow(\" Warnings:\"));\r\n for (const warning of result.warnings) {\r\n console.log(chalk.yellow(` - ${warning}`));\r\n }\r\n }\r\n\r\n console.log(\"\");\r\n\r\n // 10. Write files to disk\r\n await writeGeneratedFiles(result.files, output, options.verbose);\r\n\r\n console.log(chalk.green(` Files written to ${chalk.white(output)}`));\r\n console.log(\"\");\r\n } catch (error: any) {\r\n spinner.fail(chalk.red(\"Generation failed\"));\r\n\r\n if (error.response?.status === 401) {\r\n await handleUnauthorized(tokenManager);\r\n } else if (error.response?.status === 403) {\r\n console.log(chalk.yellow(\"\\n You don't have permission to access this project.\"));\r\n console.log(chalk.gray(\" Check if you're part of the organization.\\n\"));\r\n } else if (error.response?.status === 404) {\r\n console.log(chalk.yellow(\"\\n Project not found.\"));\r\n console.log(chalk.gray(\" Check if the project ID is correct.\\n\"));\r\n } else if (error.response?.status === 429) {\r\n // Insufficient credits\r\n const data = error.response.data;\r\n console.log(chalk.red(\"\\n Insufficient credits\"));\r\n if (data.requiredCredits) {\r\n console.log(chalk.yellow(` Required: ${data.requiredCredits} credits`));\r\n }\r\n console.log(chalk.yellow(` Available: ${data.remaining ?? 0} credits`));\r\n console.log(chalk.gray(\"\\n Upgrade your plan or wait for credit reset.\\n\"));\r\n } else if (error.response?.data?.message) {\r\n console.log(chalk.red(`\\n ${error.response.data.message}\\n`));\r\n } else {\r\n console.log(chalk.red(`\\n ${error.message}\\n`));\r\n }\r\n\r\n process.exit(1);\r\n }\r\n}\r\n","import fs from \"fs/promises\";\r\nimport path from \"path\";\r\nimport chalk from \"chalk\";\r\n\r\ninterface GeneratedFile {\r\n path: string;\r\n content: string;\r\n language: string;\r\n entityId?: string;\r\n}\r\n\r\nexport interface FileCategory {\r\n name: string;\r\n count: number;\r\n files: string[];\r\n}\r\n\r\n/**\r\n * Validate that a file path is safe and doesn't escape the output directory.\r\n * SECURITY: Prevents path traversal attacks (e.g., ../../../etc/passwd)\r\n */\r\nfunction isPathSafe(outputDir: string, filePath: string): boolean {\r\n // Resolve both paths to absolute paths\r\n const resolvedOutput = path.resolve(outputDir);\r\n const resolvedFile = path.resolve(outputDir, filePath);\r\n\r\n // Check if the resolved file path starts with the output directory\r\n // Also ensure there's a path separator after the base to prevent\r\n // matching \"output\" when file is in \"output-malicious\"\r\n return (\r\n resolvedFile.startsWith(resolvedOutput + path.sep) ||\r\n resolvedFile === resolvedOutput\r\n );\r\n}\r\n\r\n/**\r\n * Get category name from file path\r\n * Analyzes path segments to determine file type\r\n * @public Exported for use in preview/estimate display\r\n */\r\nexport function getCategoryFromPath(filePath: string): string {\r\n const lowerPath = filePath.toLowerCase();\r\n\r\n // Order matters - more specific first\r\n if (lowerPath.includes(\"/controllers/\")) return \"Controllers\";\r\n if (lowerPath.includes(\"/usecases/\") || lowerPath.includes(\"/use-cases/\"))\r\n return \"UseCases\";\r\n if (lowerPath.includes(\"/dtos/\") || lowerPath.includes(\"/dto/\")) return \"DTOs\";\r\n if (lowerPath.includes(\"/entities/\")) return \"Entities\";\r\n if (\r\n lowerPath.includes(\"/repositories/\") ||\r\n lowerPath.includes(\"/repositoriesimpl/\")\r\n )\r\n return \"Repositories\";\r\n if (\r\n lowerPath.includes(\"/configurations/\") ||\r\n lowerPath.includes(\"/config/\")\r\n )\r\n return \"Configurations\";\r\n if (\r\n lowerPath.includes(\"/validators/\") ||\r\n lowerPath.includes(\"/validation/\")\r\n )\r\n return \"Validators\";\r\n if (lowerPath.includes(\"/mappers/\")) return \"Mappers\";\r\n if (lowerPath.includes(\"/interfaces/\")) return \"Interfaces\";\r\n if (lowerPath.includes(\"/exceptions/\")) return \"Exceptions\";\r\n if (lowerPath.includes(\"/vos/\") || lowerPath.includes(\"/valueobjects/\"))\r\n return \"ValueObjects\";\r\n if (lowerPath.includes(\"/ioc/\") || lowerPath.includes(\"/di/\"))\r\n return \"DependencyInjection\";\r\n if (\r\n lowerPath.includes(\"/tests/\") ||\r\n lowerPath.includes(\".test.\") ||\r\n lowerPath.includes(\".spec.\")\r\n )\r\n return \"Tests\";\r\n if (lowerPath.includes(\"/database/\")) return \"Database\";\r\n\r\n return \"Other\";\r\n}\r\n\r\n/**\r\n * Categorize file paths into categories\r\n * Used for preview/estimate display before generation\r\n * @public Exported for use in generate command preview\r\n */\r\nexport function categorizeFilePaths(filePaths: string[]): FileCategory[] {\r\n const categories = new Map<string, string[]>();\r\n\r\n for (const filePath of filePaths) {\r\n const category = getCategoryFromPath(filePath);\r\n const existing = categories.get(category) || [];\r\n existing.push(filePath);\r\n categories.set(category, existing);\r\n }\r\n\r\n return Array.from(categories.entries())\r\n .map(([name, fileList]) => ({ name, count: fileList.length, files: fileList }))\r\n .sort((a, b) => b.count - a.count); // Most files first\r\n}\r\n\r\n/**\r\n * Categorize files by their path\r\n * Groups files into categories like Entities, DTOs, UseCases, etc.\r\n */\r\nfunction categorizeFiles(files: GeneratedFile[]): FileCategory[] {\r\n return categorizeFilePaths(files.map((f) => f.path));\r\n}\r\n\r\n/**\r\n * Display categorized summary of generated files\r\n */\r\nfunction displayCategorizedSummary(files: GeneratedFile[]): void {\r\n const categories = categorizeFiles(files);\r\n\r\n console.log(\"\");\r\n console.log(chalk.bold(\" Generated Files\"));\r\n console.log(chalk.gray(\" ─────────────────────────────────\"));\r\n\r\n // Find max name length for alignment\r\n const maxNameLength = Math.max(...categories.map((c) => c.name.length));\r\n\r\n for (const category of categories) {\r\n const padding = \" \".repeat(maxNameLength - category.name.length + 2);\r\n const countStr = category.count.toString().padStart(3, \" \");\r\n console.log(\r\n chalk.gray(` ${category.name}${padding}`),\r\n chalk.cyan(`${countStr} files`)\r\n );\r\n }\r\n\r\n console.log(chalk.gray(\" ─────────────────────────────────\"));\r\n const totalPadding = \" \".repeat(maxNameLength - 5 + 2);\r\n const totalStr = files.length.toString().padStart(3, \" \");\r\n console.log(\r\n chalk.white(` Total${totalPadding}`),\r\n chalk.bold.cyan(`${totalStr} files`)\r\n );\r\n}\r\n\r\n/**\r\n * Write generated files to disk\r\n *\r\n * Creates directories as needed and writes files\r\n * Shows categorized summary by default, or full list with verbose=true\r\n */\r\nexport async function writeGeneratedFiles(\r\n files: GeneratedFile[],\r\n outputDir: string,\r\n verbose: boolean = false\r\n): Promise<void> {\r\n // Track written files for summary\r\n const writtenFiles: GeneratedFile[] = [];\r\n\r\n for (const file of files) {\r\n // SECURITY: Validate path doesn't escape output directory\r\n if (!isPathSafe(outputDir, file.path)) {\r\n console.error(chalk.red(` Skipping unsafe path: ${file.path}`));\r\n console.error(\r\n chalk.gray(\r\n ` Path traversal detected - file path must be within output directory`\r\n )\r\n );\r\n continue;\r\n }\r\n\r\n const fullPath = path.resolve(outputDir, file.path);\r\n const dir = path.dirname(fullPath);\r\n\r\n try {\r\n // Create directory if doesn't exist\r\n await fs.mkdir(dir, { recursive: true });\r\n\r\n // Write file\r\n await fs.writeFile(fullPath, file.content, \"utf-8\");\r\n\r\n // Show file path in verbose mode\r\n if (verbose) {\r\n console.log(chalk.gray(` ${file.path}`));\r\n }\r\n\r\n writtenFiles.push(file);\r\n } catch (error: any) {\r\n console.error(chalk.red(` Failed to write ${file.path}`));\r\n console.error(chalk.gray(` ${error.message}`));\r\n }\r\n }\r\n\r\n // Show categorized summary (unless verbose)\r\n if (!verbose && writtenFiles.length > 0) {\r\n displayCategorizedSummary(writtenFiles);\r\n }\r\n}\r\n","import readline from \"readline\";\r\nimport chalk from \"chalk\";\r\n\r\n/**\r\n * Prompt user for confirmation\r\n * Returns true if user confirms (Y/yes/enter), false if they decline (n/no)\r\n */\r\nexport function promptConfirm(message: string): Promise<boolean> {\r\n return new Promise((resolve) => {\r\n const rl = readline.createInterface({\r\n input: process.stdin,\r\n output: process.stdout,\r\n });\r\n\r\n rl.question(chalk.yellow(`${message} [Y/n] `), (answer) => {\r\n rl.close();\r\n const normalized = answer.trim().toLowerCase();\r\n // Empty input (just pressing Enter) means \"yes\"\r\n resolve(normalized !== \"n\" && normalized !== \"no\");\r\n });\r\n });\r\n}\r\n","import fs from \"fs/promises\";\r\nimport path from \"path\";\r\nimport { configSchema, CONFIG_FILENAME, type AerocodingConfig } from \"./schema.js\";\r\n\r\nexport async function loadConfig(\r\n dir: string = process.cwd()\r\n): Promise<AerocodingConfig | null> {\r\n const configPath = path.join(dir, CONFIG_FILENAME);\r\n\r\n try {\r\n const content = await fs.readFile(configPath, \"utf-8\");\r\n const parsed = JSON.parse(content);\r\n return configSchema.parse(parsed);\r\n } catch (error) {\r\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") {\r\n return null;\r\n }\r\n throw error;\r\n }\r\n}\r\n\r\nexport async function saveConfig(\r\n config: AerocodingConfig,\r\n dir: string = process.cwd()\r\n): Promise<void> {\r\n const configPath = path.join(dir, CONFIG_FILENAME);\r\n const content = JSON.stringify(\r\n {\r\n $schema: \"https://aerocoding.dev/schemas/aerocodingrc.json\",\r\n ...config,\r\n },\r\n null,\r\n 2\r\n );\r\n await fs.writeFile(configPath, content, \"utf-8\");\r\n}\r\n\r\nexport async function configExists(dir: string = process.cwd()): Promise<boolean> {\r\n const configPath = path.join(dir, CONFIG_FILENAME);\r\n try {\r\n await fs.access(configPath);\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\nexport { type AerocodingConfig, CONFIG_FILENAME } from \"./schema.js\";\r\n","import { z } from \"zod\";\r\n\r\nexport const configSchema = z.object({\r\n $schema: z.string().optional(),\r\n project: z.string().uuid(),\r\n output: z.string().default(\"./.aerocoding\"),\r\n\r\n // Architecture style: how to organize generated code\r\n architectureStyle: z\r\n .enum([\"bounded-contexts\", \"flat\"])\r\n .optional()\r\n .default(\"bounded-contexts\"),\r\n\r\n backend: z\r\n .object({\r\n preset: z.string(),\r\n layers: z.array(z.string()),\r\n })\r\n .optional(),\r\n\r\n frontend: z\r\n .object({\r\n preset: z.string(),\r\n layers: z.array(z.string()),\r\n })\r\n .optional(),\r\n\r\n codeStyle: z\r\n .object({\r\n includeValidations: z.boolean().default(true),\r\n includeComments: z.boolean().default(true),\r\n includeAnnotations: z.boolean().default(true),\r\n includeLogging: z.boolean().default(true),\r\n includeTesting: z.boolean().default(true),\r\n })\r\n .optional(),\r\n\r\n libraries: z\r\n .object({\r\n validation: z.string().optional(),\r\n logging: z.string().optional(),\r\n })\r\n .optional(),\r\n\r\n excludePatterns: z.array(z.string()).optional(),\r\n});\r\n\r\nexport type AerocodingConfig = z.infer<typeof configSchema>;\r\n\r\nexport const CONFIG_FILENAME = \".aerocodingrc.json\";\r\n","import * as p from \"@clack/prompts\";\r\nimport chalk from \"chalk\";\r\nimport { TokenManager } from \"../auth/token-manager.js\";\r\nimport { createApiClientWithAutoLogout } from \"./_shared/create-api-client.js\";\r\nimport { handleUnauthorized } from \"./_shared/unauthorized.js\";\r\nimport { saveConfig, configExists } from \"../config/loader.js\";\r\nimport type { AerocodingConfig } from \"../config/schema.js\";\r\n\r\ninterface InitOptions {\r\n project?: string;\r\n force?: boolean;\r\n}\r\n\r\n/**\r\n * Init Command\r\n *\r\n * Interactive wizard to initialize AeroCoding in current directory\r\n * Creates .aerocodingrc.json config file\r\n */\r\nexport async function initCommand(options: InitOptions) {\r\n p.intro(chalk.bgCyan.black(\" AeroCoding CLI \"));\r\n\r\n // Check if config already exists\r\n if (!options.force && (await configExists())) {\r\n const overwrite = await p.confirm({\r\n message: \"Config file already exists. Overwrite?\",\r\n initialValue: false,\r\n });\r\n\r\n if (p.isCancel(overwrite) || !overwrite) {\r\n p.cancel(\"Operation cancelled.\");\r\n process.exit(0);\r\n }\r\n }\r\n\r\n // 1. Check authentication\r\n const tokenManager = new TokenManager();\r\n const token = await tokenManager.getAccessToken();\r\n\r\n if (!token) {\r\n p.cancel(\"Not logged in. Run 'aerocoding login' first.\");\r\n process.exit(1);\r\n }\r\n\r\n const apiClient = createApiClientWithAutoLogout(token, tokenManager);\r\n\r\n try {\r\n // 2. Select organization first\r\n const orgSpinner = p.spinner();\r\n orgSpinner.start(\"Loading organizations...\");\r\n\r\n const organizations = await apiClient.listOrganizations();\r\n orgSpinner.stop(\"Organizations loaded\");\r\n\r\n if (organizations.length === 0) {\r\n p.cancel(\"No organizations found. Create one on aerocoding.dev first.\");\r\n process.exit(1);\r\n }\r\n\r\n let organizationId: string;\r\n\r\n if (organizations.length === 1 && organizations[0]) {\r\n // Auto-select if only one org\r\n organizationId = organizations[0].id;\r\n p.log.info(`Organization: ${organizations[0].name}`);\r\n } else {\r\n const selectedOrg = await p.select({\r\n message: \"Select organization\",\r\n options: organizations.map((org) => ({\r\n value: org.id,\r\n label: org.name,\r\n hint: org.planTier.toUpperCase(),\r\n })),\r\n });\r\n\r\n if (p.isCancel(selectedOrg)) {\r\n p.cancel(\"Operation cancelled.\");\r\n process.exit(0);\r\n }\r\n\r\n organizationId = selectedOrg as string;\r\n }\r\n\r\n // 3. Select project from organization\r\n let projectId = options.project;\r\n\r\n if (!projectId) {\r\n const spinner = p.spinner();\r\n spinner.start(\"Loading projects...\");\r\n\r\n const projects = await apiClient.listProjects(organizationId);\r\n spinner.stop(\"Projects loaded\");\r\n\r\n if (projects.length === 0) {\r\n p.cancel(\"No projects in this organization. Create one on aerocoding.dev first.\");\r\n process.exit(1);\r\n }\r\n\r\n const selectedProject = await p.select({\r\n message: \"Select project\",\r\n options: projects.map((proj) => ({\r\n value: proj.id,\r\n label: proj.name,\r\n hint: [proj.backendFramework, proj.frontendFramework].filter(Boolean).join(\" + \"),\r\n })),\r\n });\r\n\r\n if (p.isCancel(selectedProject)) {\r\n p.cancel(\"Operation cancelled.\");\r\n process.exit(0);\r\n }\r\n\r\n projectId = selectedProject as string;\r\n }\r\n\r\n // 4. Fetch project details\r\n const spinner = p.spinner();\r\n spinner.start(\"Fetching project details...\");\r\n const project = await apiClient.getProject(projectId);\r\n spinner.stop(`Project: ${project.name}`);\r\n\r\n // Build target options based on project frameworks\r\n const targetOptions: { value: string; label: string }[] = [];\r\n if (project.backendFramework) {\r\n targetOptions.push({\r\n value: \"backend\",\r\n label: `Backend (${project.backendFramework})`,\r\n });\r\n }\r\n if (project.frontendFramework) {\r\n targetOptions.push({\r\n value: \"frontend\",\r\n label: `Frontend (${project.frontendFramework})`,\r\n });\r\n }\r\n\r\n if (targetOptions.length === 0) {\r\n p.cancel(\"Project has no frameworks configured. Update it on aerocoding.dev first.\");\r\n process.exit(1);\r\n }\r\n\r\n // 4. Select what to generate\r\n const targets = await p.multiselect({\r\n message: \"What do you want to generate?\",\r\n options: targetOptions,\r\n required: true,\r\n });\r\n\r\n if (p.isCancel(targets)) {\r\n p.cancel(\"Operation cancelled.\");\r\n process.exit(0);\r\n }\r\n\r\n const selectedTargets = targets as string[];\r\n\r\n // Initialize config\r\n const config: AerocodingConfig = {\r\n project: projectId,\r\n output: \"./.aerocoding\",\r\n codeStyle: {\r\n includeValidations: true,\r\n includeComments: true,\r\n includeAnnotations: true,\r\n includeLogging: true,\r\n includeTesting: true,\r\n },\r\n };\r\n\r\n // 5. Backend configuration\r\n if (selectedTargets.includes(\"backend\") && project.backendFramework) {\r\n const archSpinner = p.spinner();\r\n archSpinner.start(\"Loading backend templates...\");\r\n\r\n // Use new template registry API\r\n const templateResult = await apiClient.getTemplates({\r\n category: \"backend\",\r\n language: project.backendFramework,\r\n });\r\n archSpinner.stop(\"Templates loaded\");\r\n\r\n if (templateResult.templates.length > 0) {\r\n const preset = await p.select({\r\n message: \"Backend template\",\r\n options: templateResult.templates.map((tmpl) => ({\r\n value: tmpl.id,\r\n label: tmpl.name,\r\n hint: tmpl.description || `${tmpl.tier} tier`,\r\n })),\r\n });\r\n\r\n if (p.isCancel(preset)) {\r\n p.cancel(\"Operation cancelled.\");\r\n process.exit(0);\r\n }\r\n\r\n // Fetch full template with layers and feature flags\r\n const fullTemplate = await apiClient.getTemplate(preset as string);\r\n\r\n if (fullTemplate.layers && fullTemplate.layers.length > 0) {\r\n const layers = await p.multiselect({\r\n message: \"Select backend layers to include\",\r\n options: fullTemplate.layers.map((layer) => ({\r\n value: layer.id,\r\n label: layer.name,\r\n hint: layer.category,\r\n })),\r\n initialValues: fullTemplate.layers.filter((l) => l.enabled).map((l) => l.id),\r\n });\r\n\r\n if (p.isCancel(layers)) {\r\n p.cancel(\"Operation cancelled.\");\r\n process.exit(0);\r\n }\r\n\r\n config.backend = {\r\n preset: preset as string,\r\n layers: layers as string[],\r\n };\r\n } else {\r\n config.backend = {\r\n preset: preset as string,\r\n layers: [],\r\n };\r\n }\r\n }\r\n }\r\n\r\n // 6. Frontend configuration\r\n if (selectedTargets.includes(\"frontend\") && project.frontendFramework) {\r\n const archSpinner = p.spinner();\r\n archSpinner.start(\"Loading frontend templates...\");\r\n\r\n // Use new template registry API\r\n const templateResult = await apiClient.getTemplates({\r\n category: \"frontend\",\r\n framework: project.frontendFramework,\r\n });\r\n archSpinner.stop(\"Templates loaded\");\r\n\r\n if (templateResult.templates.length > 0) {\r\n const preset = await p.select({\r\n message: \"Frontend template\",\r\n options: templateResult.templates.map((tmpl) => ({\r\n value: tmpl.id,\r\n label: tmpl.name,\r\n hint: tmpl.description || `${tmpl.tier} tier`,\r\n })),\r\n });\r\n\r\n if (p.isCancel(preset)) {\r\n p.cancel(\"Operation cancelled.\");\r\n process.exit(0);\r\n }\r\n\r\n // Fetch full template with layers and feature flags\r\n const fullTemplate = await apiClient.getTemplate(preset as string);\r\n\r\n if (fullTemplate.layers && fullTemplate.layers.length > 0) {\r\n const layers = await p.multiselect({\r\n message: \"Select frontend layers to include\",\r\n options: fullTemplate.layers.map((layer) => ({\r\n value: layer.id,\r\n label: layer.name,\r\n hint: layer.category,\r\n })),\r\n initialValues: fullTemplate.layers.filter((l) => l.enabled).map((l) => l.id),\r\n });\r\n\r\n if (p.isCancel(layers)) {\r\n p.cancel(\"Operation cancelled.\");\r\n process.exit(0);\r\n }\r\n\r\n config.frontend = {\r\n preset: preset as string,\r\n layers: layers as string[],\r\n };\r\n } else {\r\n config.frontend = {\r\n preset: preset as string,\r\n layers: [],\r\n };\r\n }\r\n }\r\n }\r\n\r\n // 7. Architecture style\r\n const architectureStyle = await p.select({\r\n message: \"How would you like to organize your code?\",\r\n options: [\r\n {\r\n value: \"bounded-contexts\",\r\n label: \"Bounded Contexts\",\r\n hint: \"Each module has its own Domain, Application, Infrastructure\",\r\n },\r\n {\r\n value: \"flat\",\r\n label: \"Flat Structure\",\r\n hint: \"Single Domain, Application, Infrastructure for the entire project\",\r\n },\r\n ],\r\n initialValue: \"bounded-contexts\",\r\n });\r\n\r\n if (p.isCancel(architectureStyle)) {\r\n p.cancel(\"Operation cancelled.\");\r\n process.exit(0);\r\n }\r\n\r\n config.architectureStyle = architectureStyle as \"bounded-contexts\" | \"flat\";\r\n\r\n // 8. Code style options\r\n const codeStyleOptions = await p.multiselect({\r\n message: \"Code style options\",\r\n options: [\r\n { value: \"validations\", label: \"Include validations\", hint: \"Add validation rules\" },\r\n { value: \"comments\", label: \"Include comments\", hint: \"Add code documentation\" },\r\n { value: \"annotations\", label: \"Include annotations\", hint: \"Add decorators/attributes\" },\r\n { value: \"logging\", label: \"Include logging\", hint: \"Add log statements\" },\r\n { value: \"testing\", label: \"Include tests\", hint: \"Generate test files\" },\r\n ],\r\n initialValues: [\"validations\", \"comments\", \"annotations\", \"logging\", \"testing\"],\r\n });\r\n\r\n if (p.isCancel(codeStyleOptions)) {\r\n p.cancel(\"Operation cancelled.\");\r\n process.exit(0);\r\n }\r\n\r\n const selectedStyles = codeStyleOptions as string[];\r\n config.codeStyle = {\r\n includeValidations: selectedStyles.includes(\"validations\"),\r\n includeComments: selectedStyles.includes(\"comments\"),\r\n includeAnnotations: selectedStyles.includes(\"annotations\"),\r\n includeLogging: selectedStyles.includes(\"logging\"),\r\n includeTesting: selectedStyles.includes(\"testing\"),\r\n };\r\n\r\n // 9. Output directory\r\n const output = await p.text({\r\n message: \"Output directory\",\r\n initialValue: \"./.aerocoding\",\r\n validate: (value) => {\r\n if (!value) return \"Output directory is required\";\r\n return undefined;\r\n },\r\n });\r\n\r\n if (p.isCancel(output)) {\r\n p.cancel(\"Operation cancelled.\");\r\n process.exit(0);\r\n }\r\n\r\n config.output = output as string;\r\n\r\n // 10. Save config\r\n await saveConfig(config);\r\n\r\n p.outro(\r\n chalk.green(\"Config saved to .aerocodingrc.json\") +\r\n \"\\n\\n\" +\r\n chalk.gray(\" Run \") +\r\n chalk.cyan(\"aerocoding generate\") +\r\n chalk.gray(\" to generate code!\")\r\n );\r\n } catch (error: any) {\r\n if (error.response?.status === 401) {\r\n await handleUnauthorized(tokenManager);\r\n } else if (error.response?.data?.message) {\r\n p.cancel(error.response.data.message);\r\n } else {\r\n p.cancel(error.message || \"An unexpected error occurred\");\r\n }\r\n process.exit(1);\r\n }\r\n}\r\n","import chalk from \"chalk\";\r\n\r\ninterface PullOptions {\r\n project?: string;\r\n}\r\n\r\n/**\r\n * Pull Command (Stub)\r\n *\r\n * TODO: Pull schema from cloud\r\n * - Download project schema\r\n * - Save to .aerocoding/schema.json\r\n */\r\nexport async function pullCommand(options: PullOptions) {\r\n console.log(chalk.yellow(\"Command not yet implemented\"));\r\n if (options.project) {\r\n console.log(chalk.gray(` Requested project: ${options.project}`));\r\n }\r\n console.log(chalk.gray(\" Coming soon in v0.2.0\\n\"));\r\n}\r\n","import chalk from \"chalk\";\r\n\r\n/**\r\n * Status Command (Stub)\r\n *\r\n * TODO: Show local schema status\r\n * - Show current project\r\n * - Show schema stats\r\n * - Show sync status\r\n */\r\nexport async function statusCommand() {\r\n console.log(chalk.yellow(\"Command not yet implemented\"));\r\n console.log(chalk.gray(\" Coming soon in v0.2.0\\n\"));\r\n}\r\n"],"mappings":"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","names":["chalk","spinner","axios","API_URL","chalk","chalk","chalk","chalk","chalk","chalk","chalk","ora","chalk","chalk","fs","path","path","fs","chalk","spinner","ora","chalk","chalk","spinner","chalk","chalk"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/commands/login.ts","../src/auth/device-flow.ts","../src/auth/token-manager.ts","../src/api/client.ts","../src/commands/_shared/create-api-client.ts","../src/commands/_shared/unauthorized.ts","../src/commands/logout.ts","../src/commands/whoami.ts","../src/commands/generate.ts","../src/utils/file-writer.ts","../src/utils/prompt.ts","../src/config/loader.ts","../src/config/schema.ts","../src/commands/init.ts","../src/commands/pull.ts","../src/commands/status.ts"],"sourcesContent":["#!/usr/bin/env node\r\n\r\nimport { Command } from \"commander\";\r\nimport { loginCommand } from \"./commands/login.js\";\r\nimport { logoutCommand } from \"./commands/logout.js\";\r\nimport { whoamiCommand } from \"./commands/whoami.js\";\r\nimport { generateCommand } from \"./commands/generate.js\";\r\nimport { initCommand } from \"./commands/init.js\";\r\nimport { pullCommand } from \"./commands/pull.js\";\r\nimport { statusCommand } from \"./commands/status.js\";\r\nimport \"dotenv/config\";\r\n\r\nconst program = new Command();\r\n\r\nprogram\r\n .name(\"aerocoding\")\r\n .description(\"AeroCoding CLI - Generate production-ready code from UML diagrams\")\r\n .version(\"0.1.23\");\r\n\r\n// ============================================\r\n// Authentication Commands\r\n// ============================================\r\n\r\nprogram\r\n .command(\"login\")\r\n .description(\"Authenticate with AeroCoding\")\r\n .action(loginCommand);\r\n\r\nprogram\r\n .command(\"logout\")\r\n .description(\"Logout and clear stored credentials\")\r\n .action(logoutCommand);\r\n\r\nprogram\r\n .command(\"whoami\")\r\n .description(\"Show current authenticated user\")\r\n .action(whoamiCommand);\r\n\r\n// ============================================\r\n// Project Commands\r\n// ============================================\r\n\r\nprogram\r\n .command(\"init\")\r\n .description(\"Initialize AeroCoding in current directory\")\r\n .option(\"-p, --project <id>\", \"Project ID (skip selection)\")\r\n .option(\"-f, --force\", \"Overwrite existing config without asking\")\r\n .action(initCommand);\r\n\r\nprogram\r\n .command(\"pull\")\r\n .description(\"Pull schema from cloud\")\r\n .option(\"-p, --project <id>\", \"Project ID\")\r\n .action(pullCommand);\r\n\r\nprogram\r\n .command(\"status\")\r\n .description(\"Show local schema status\")\r\n .action(statusCommand);\r\n\r\n// ============================================\r\n// Generation Commands\r\n// ============================================\r\n\r\nprogram\r\n .command(\"generate\")\r\n .alias(\"gen\")\r\n .description(\"Generate code from schema\")\r\n // Identification\r\n .option(\"-p, --project <id>\", \"Project ID\")\r\n .option(\"-t, --targets <targets...>\", \"Generation targets (e.g., dotnet-entity)\")\r\n .option(\"-e, --entities <entities...>\", \"Filter by entity names\")\r\n .option(\"-o, --output <dir>\", \"Output directory\", \"./.aerocoding\")\r\n // Presets & Layers\r\n .option(\"--backend-preset <preset>\", \"Backend architecture preset\")\r\n .option(\"--frontend-preset <preset>\", \"Frontend architecture preset\")\r\n .option(\"--backend-layers <layers...>\", \"Backend layers to generate\")\r\n .option(\"--frontend-layers <layers...>\", \"Frontend layers to generate\")\r\n // Code style toggles (optimistic defaults - all enabled by default)\r\n .option(\"--no-validations\", \"Exclude validations\")\r\n .option(\"--no-comments\", \"Exclude comments\")\r\n .option(\"--no-annotations\", \"Exclude annotations\")\r\n .option(\"--no-logging\", \"Exclude logging statements\")\r\n .option(\"--no-testing\", \"Exclude test files\")\r\n // Validation library (framework-agnostic)\r\n .option(\"--validation-lib <framework>\", \"Validation library (e.g., fluentvalidation, zod, formz)\")\r\n // Control\r\n .option(\"-v, --verbose\", \"Show all generated file paths\")\r\n .option(\"-y, --yes\", \"Skip confirmation prompt\")\r\n .option(\"-a, --all\", \"Generate all bounded contexts and targets without prompting\")\r\n .action(generateCommand);\r\n\r\n// ============================================\r\n// Parse and Execute\r\n// ============================================\r\n\r\nprogram.parse();\r\n","import chalk from \"chalk\";\r\nimport { DeviceFlow } from \"../auth/device-flow.js\";\r\nimport { TokenManager } from \"../auth/token-manager.js\";\r\nimport { createApiClientWithAutoLogout } from \"./_shared/create-api-client.js\";\r\nimport { handleUnauthorized } from \"./_shared/unauthorized.js\";\r\n\r\n/**\r\n * Login Command\r\n *\r\n * Authenticates user via OAuth Device Flow\r\n * Stores tokens securely in OS credential manager\r\n */\r\nexport async function loginCommand() {\r\n console.log(chalk.bold(\"\\nAeroCoding CLI Login\\n\"));\r\n\r\n const tokenManager = new TokenManager();\r\n\r\n // Check if already logged in\r\n const existingToken = await tokenManager.getAccessToken();\r\n if (existingToken) {\r\n const metadata = await tokenManager.getUserMetadata();\r\n console.log(\r\n chalk.yellow(\"Already logged in as:\"),\r\n chalk.white(metadata?.email || \"unknown\")\r\n );\r\n console.log(\r\n chalk.gray(\r\n \" Run 'aerocoding logout' to login with a different account\\n\"\r\n )\r\n );\r\n return;\r\n }\r\n\r\n try {\r\n // Initiate device flow\r\n const deviceFlow = new DeviceFlow();\r\n const tokens = await deviceFlow.initiateAuth();\r\n\r\n // Get user info\r\n const apiClient = createApiClientWithAutoLogout(\r\n tokens.access_token,\r\n tokenManager\r\n );\r\n let user;\r\n try {\r\n user = await apiClient.getCurrentUser();\r\n } catch (error: any) {\r\n if (error.response?.status === 401) {\r\n await handleUnauthorized(tokenManager);\r\n }\r\n throw error;\r\n }\r\n\r\n // Save tokens\r\n await tokenManager.saveTokens(tokens.access_token, tokens.refresh_token, {\r\n id: user.id,\r\n email: user.email,\r\n name: user.name || undefined,\r\n tier: user.tier,\r\n });\r\n\r\n console.log(\"\");\r\n console.log(\r\n chalk.green(\"Successfully logged in as:\"),\r\n chalk.white(user.email)\r\n );\r\n console.log(chalk.gray(\" Run 'aerocoding whoami' to verify\\n\"));\r\n } catch (error: any) {\r\n console.error(\r\n chalk.red(\"\\nLogin failed:\"),\r\n error.message || \"Unknown error\"\r\n );\r\n process.exit(1);\r\n }\r\n}\r\n","import axios from \"axios\";\r\nimport chalk from \"chalk\";\r\nimport ora from \"ora\";\r\nimport open from \"open\";\r\n\r\nconst API_URL = process.env.API_URL || \"https://aerocoding.dev\";\r\nconst MAX_POLL_TIME = 15 * 60 * 1000; // 15 minutes\r\n\r\ninterface DeviceAuthResponse {\r\n device_code: string;\r\n user_code: string;\r\n confirmation_code: string;\r\n verification_uri: string;\r\n verification_uri_complete: string;\r\n expires_in: number;\r\n interval: number;\r\n}\r\n\r\ninterface TokenResponse {\r\n access_token: string;\r\n refresh_token: string;\r\n token_type: string;\r\n expires_in: number;\r\n}\r\n\r\n/**\r\n * DeviceFlow\r\n *\r\n * Implements OAuth 2.0 Device Authorization Grant (RFC 8628)\r\n * Used for CLI authentication without browser-based redirects\r\n */\r\nexport class DeviceFlow {\r\n /**\r\n * Initiate the complete device authorization flow\r\n */\r\n async initiateAuth(): Promise<TokenResponse> {\r\n // Step 1: Request device code\r\n const deviceAuth = await this.requestDeviceCode();\r\n\r\n // Step 2: Display user code and open browser\r\n this.displayUserCode(deviceAuth);\r\n await this.openBrowser(deviceAuth.verification_uri);\r\n\r\n // Step 3: Poll for authorization\r\n const tokens = await this.pollForToken(deviceAuth);\r\n\r\n return tokens;\r\n }\r\n\r\n /**\r\n * Step 1: Request device code from server\r\n */\r\n private async requestDeviceCode(): Promise<DeviceAuthResponse> {\r\n try {\r\n const response = await axios.post(`${API_URL}/api/device/authorize`, {\r\n client_id: \"aerocoding-cli\",\r\n scope: \"generate:code projects:read\",\r\n });\r\n\r\n return response.data;\r\n } catch (error: any) {\r\n console.error(chalk.red(\"Failed to initiate device authorization\"));\r\n if (error.response) {\r\n console.error(\r\n chalk.red(`Error: ${error.response.data.error_description}`)\r\n );\r\n }\r\n throw new Error(\"Failed to initiate device authorization\");\r\n }\r\n }\r\n\r\n /**\r\n * Step 2: Display user code and instructions\r\n */\r\n private displayUserCode(auth: DeviceAuthResponse): void {\r\n console.log(\"\\n\");\r\n console.log(chalk.cyan(\"━\".repeat(60)));\r\n console.log(chalk.bold.white(\" AeroCoding CLI - Device Activation\"));\r\n console.log(chalk.cyan(\"━\".repeat(60)));\r\n console.log(\"\");\r\n console.log(chalk.white(\" 1. Open this URL in your browser:\"));\r\n console.log(chalk.cyan.bold(` ${auth.verification_uri}`));\r\n console.log(\"\");\r\n console.log(chalk.white(\" 2. Enter this code:\"));\r\n console.log(chalk.green.bold(` ${auth.user_code}`));\r\n console.log(\"\");\r\n console.log(\r\n chalk.gray(` Code expires in ${auth.expires_in / 60} minutes`)\r\n );\r\n console.log(chalk.cyan(\"━\".repeat(60)));\r\n console.log(\"\");\r\n }\r\n\r\n /**\r\n * Step 2.5: Open browser automatically\r\n */\r\n private async openBrowser(url: string): Promise<void> {\r\n try {\r\n await open(url);\r\n console.log(chalk.gray(\" Opening browser...\"));\r\n } catch {\r\n console.log(chalk.yellow(\" Could not open browser automatically\"));\r\n console.log(chalk.gray(\" Please open the URL manually\\n\"));\r\n }\r\n }\r\n\r\n /**\r\n * Step 3: Poll for token\r\n */\r\n private async pollForToken(auth: DeviceAuthResponse): Promise<TokenResponse> {\r\n const spinner = ora({\r\n text: \"Waiting for authorization...\",\r\n color: \"cyan\",\r\n }).start();\r\n\r\n const startTime = Date.now();\r\n let currentInterval = auth.interval * 1000;\r\n\r\n while (true) {\r\n // Check timeout\r\n if (Date.now() - startTime > MAX_POLL_TIME) {\r\n spinner.fail(chalk.red(\"Authorization timeout\"));\r\n throw new Error(\"Device authorization timed out\");\r\n }\r\n\r\n try {\r\n const response = await axios.post(`${API_URL}/api/device/token`, {\r\n device_code: auth.device_code,\r\n client_id: \"aerocoding-cli\",\r\n });\r\n\r\n spinner.succeed(chalk.green(\"Successfully authenticated!\"));\r\n return response.data;\r\n } catch (error: any) {\r\n const errorCode = error.response?.data?.error;\r\n const errorDescription = error.response?.data?.error_description;\r\n\r\n if (errorCode === \"authorization_pending\") {\r\n // Keep polling\r\n await this.sleep(currentInterval);\r\n continue;\r\n }\r\n\r\n if (errorCode === \"slow_down\") {\r\n // Increase poll interval by 5 seconds\r\n currentInterval += 5000;\r\n spinner.text = \"Polling... (slowed down to avoid spam)\";\r\n await this.sleep(currentInterval);\r\n continue;\r\n }\r\n\r\n if (errorCode === \"expired_token\") {\r\n spinner.fail(chalk.red(\"Authorization code expired\"));\r\n throw new Error(\"Device code expired. Please try again.\");\r\n }\r\n\r\n if (errorCode === \"access_denied\") {\r\n spinner.fail(chalk.red(\"Authorization denied\"));\r\n throw new Error(\"You denied the authorization request\");\r\n }\r\n\r\n // Unknown error\r\n spinner.fail(chalk.red(\"Authorization failed\"));\r\n console.error(\r\n chalk.red(`Error: ${errorDescription || \"Unknown error\"}`)\r\n );\r\n throw new Error(errorDescription || \"Unknown error\");\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Helper: Sleep for specified milliseconds\r\n */\r\n private sleep(ms: number): Promise<void> {\r\n return new Promise((resolve) => setTimeout(resolve, ms));\r\n }\r\n}\r\n","import { Entry } from \"@napi-rs/keyring\";\r\nimport { createClient, SupabaseClient } from \"@supabase/supabase-js\";\r\n\r\nconst SERVICE_NAME = \"aerocoding-cli\";\r\n\r\n// Public Supabase credentials (anon key is safe to expose)\r\nconst SUPABASE_URL = \"https://peqpttkvdpjgmduzacwl.supabase.co\";\r\nconst SUPABASE_ANON_KEY = \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InBlcXB0dGt2ZHBqZ21kdXphY3dsIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NjQyNjUxNzMsImV4cCI6MjA3OTg0MTE3M30.WAzqgZusGoOEHxidfHc1e4daBglG4DJG5LOXbqldWQA\";\r\n\r\ninterface UserMetadata {\r\n id: string;\r\n email: string;\r\n name?: string;\r\n tier?: string;\r\n}\r\n\r\n/**\r\n * Helper functions for keyring operations using Entry class\r\n */\r\nfunction getPassword(service: string, account: string): string | null {\r\n try {\r\n const entry = new Entry(service, account);\r\n return entry.getPassword();\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\nfunction setPassword(service: string, account: string, password: string): void {\r\n const entry = new Entry(service, account);\r\n entry.setPassword(password);\r\n}\r\n\r\nfunction deletePassword(service: string, account: string): void {\r\n try {\r\n const entry = new Entry(service, account);\r\n entry.deletePassword();\r\n } catch {\r\n // Ignore if entry doesn't exist\r\n }\r\n}\r\n\r\n/**\r\n * TokenManager\r\n *\r\n * Manages secure storage and automatic refresh of authentication tokens\r\n * Uses OS-level credential managers (Keychain/Credential Manager/Secret Service)\r\n */\r\nexport class TokenManager {\r\n private supabase: SupabaseClient;\r\n\r\n constructor() {\r\n this.supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY, {\r\n auth: {\r\n autoRefreshToken: false,\r\n persistSession: false,\r\n },\r\n });\r\n }\r\n\r\n /**\r\n * Get access token, automatically refreshing if expired\r\n */\r\n async getAccessToken(): Promise<string | null> {\r\n try {\r\n let accessToken = getPassword(SERVICE_NAME, \"access_token\");\r\n\r\n if (!accessToken) {\r\n return null;\r\n }\r\n\r\n // Check if expired\r\n if (this.isTokenExpired(accessToken)) {\r\n accessToken = await this.refreshTokens();\r\n }\r\n\r\n return accessToken;\r\n } catch {\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * Refresh tokens using stored refresh token\r\n */\r\n private async refreshTokens(): Promise<string | null> {\r\n try {\r\n const refreshToken = getPassword(SERVICE_NAME, \"refresh_token\");\r\n\r\n if (!refreshToken) {\r\n throw new Error(\"No refresh token available\");\r\n }\r\n\r\n const { data, error } = await this.supabase.auth.refreshSession({\r\n refresh_token: refreshToken,\r\n });\r\n\r\n if (error || !data.session) {\r\n throw new Error(\"Failed to refresh session\");\r\n }\r\n\r\n // Store new tokens (single-use refresh token rotation)\r\n setPassword(SERVICE_NAME, \"access_token\", data.session.access_token);\r\n setPassword(SERVICE_NAME, \"refresh_token\", data.session.refresh_token);\r\n\r\n return data.session.access_token;\r\n } catch {\r\n await this.logout();\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * Check if JWT token is expired (or expires in < 5 min)\r\n */\r\n private isTokenExpired(token: string): boolean {\r\n try {\r\n const payload = JSON.parse(\r\n Buffer.from(token.split(\".\")[1]!, \"base64\").toString()\r\n );\r\n const expiresAt = payload.exp * 1000;\r\n const now = Date.now();\r\n\r\n // Refresh 5 minutes before expiration\r\n return expiresAt - now < 5 * 60 * 1000;\r\n } catch {\r\n return true; // Treat invalid tokens as expired\r\n }\r\n }\r\n\r\n /**\r\n * Save tokens and user metadata after successful login\r\n */\r\n async saveTokens(\r\n accessToken: string,\r\n refreshToken: string,\r\n user: UserMetadata\r\n ): Promise<void> {\r\n setPassword(SERVICE_NAME, \"access_token\", accessToken);\r\n setPassword(SERVICE_NAME, \"refresh_token\", refreshToken);\r\n setPassword(SERVICE_NAME, \"user_metadata\", JSON.stringify(user));\r\n }\r\n\r\n /**\r\n * Get stored user metadata\r\n */\r\n async getUserMetadata(): Promise<UserMetadata | null> {\r\n try {\r\n const metadata = getPassword(SERVICE_NAME, \"user_metadata\");\r\n return metadata ? JSON.parse(metadata) : null;\r\n } catch {\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * Logout - clear all stored credentials\r\n */\r\n async logout(): Promise<void> {\r\n try {\r\n deletePassword(SERVICE_NAME, \"access_token\");\r\n deletePassword(SERVICE_NAME, \"refresh_token\");\r\n deletePassword(SERVICE_NAME, \"user_metadata\");\r\n } catch (error) {\r\n // Ignore errors during logout\r\n }\r\n }\r\n\r\n /**\r\n * Check if user is currently authenticated\r\n */\r\n async isAuthenticated(): Promise<boolean> {\r\n const token = await this.getAccessToken();\r\n return token !== null;\r\n }\r\n}\r\n","import axios, { AxiosInstance } from \"axios\";\r\n\r\n// Production API URL (can be overridden via API_URL env for local dev)\r\nconst API_URL = process.env.API_URL || \"https://aerocoding.dev\";\r\n\r\ninterface User {\r\n id: string;\r\n email: string;\r\n name: string | null;\r\n tier: string;\r\n}\r\n\r\ninterface Organization {\r\n id: string;\r\n name: string;\r\n slug: string;\r\n planTier: string;\r\n}\r\n\r\ninterface Project {\r\n id: string;\r\n name: string;\r\n slug: string;\r\n schema: any;\r\n organizationId: string;\r\n backendFramework?: string;\r\n frontendFramework?: string;\r\n createdAt: string;\r\n updatedAt: string;\r\n}\r\n\r\ninterface GeneratePayload {\r\n projectId: string;\r\n // NEW: Use templateId for full architecture generation\r\n templateId?: string;\r\n // Legacy: Use targets for simple generation\r\n targets?: string[];\r\n options?: {\r\n includeValidations?: boolean;\r\n includeComments?: boolean;\r\n includeAnnotations?: boolean;\r\n includeLogging?: boolean;\r\n includeTesting?: boolean;\r\n outputDir?: string;\r\n backendPreset?: string;\r\n frontendPreset?: string;\r\n backendLayers?: string[];\r\n frontendLayers?: string[];\r\n validationLib?: string;\r\n // NEW: Feature flags for template generation\r\n featureFlags?: Record<string, boolean>;\r\n // Architecture style: bounded-contexts vs flat\r\n useContexts?: boolean;\r\n // Filter by diagram/bounded context IDs\r\n diagramIds?: string[];\r\n };\r\n}\r\n\r\ninterface GeneratedFile {\r\n path: string;\r\n content: string;\r\n language: string;\r\n entityId?: string;\r\n}\r\n\r\ninterface GenerateResult {\r\n files: GeneratedFile[];\r\n stats?: {\r\n totalFiles?: number;\r\n totalEntities?: number;\r\n languages?: string[];\r\n };\r\n cliCommand?: string;\r\n warnings?: string[];\r\n creditsUsed?: number;\r\n creditsRemaining?: number;\r\n}\r\n\r\ninterface CreditUsage {\r\n used: number;\r\n limit: number;\r\n bonusCredits: number;\r\n remaining: number;\r\n}\r\n\r\ninterface ArchitectureLayer {\r\n id: string;\r\n name: string;\r\n category: string;\r\n description?: string;\r\n}\r\n\r\ninterface Architecture {\r\n id: string;\r\n name: string;\r\n description: string;\r\n layers: ArchitectureLayer[];\r\n}\r\n\r\n// New Template Registry Types\r\ninterface TemplateMetadata {\r\n id: string;\r\n name: string;\r\n description: string;\r\n category: \"backend\" | \"frontend\" | \"database\" | \"infra\";\r\n language: string;\r\n framework: string;\r\n tier: \"starter\" | \"standard\" | \"enterprise\";\r\n tags: string[];\r\n version: string;\r\n author: string;\r\n isLegacy?: boolean;\r\n isOfficial?: boolean;\r\n isPremium?: boolean;\r\n /** Architecture style: \"bounded-contexts\" for DDD modules, \"flat\" for single structure */\r\n architectureStyle?: \"bounded-contexts\" | \"flat\";\r\n}\r\n\r\ninterface TemplateLayer {\r\n id: string;\r\n name: string;\r\n description: string;\r\n category: string;\r\n enabled: boolean;\r\n}\r\n\r\ninterface TemplateFeatureFlag {\r\n id: string;\r\n name: string;\r\n label: string;\r\n description?: string;\r\n defaultValue: boolean;\r\n}\r\n\r\ninterface FullTemplate extends TemplateMetadata {\r\n layers: TemplateLayer[];\r\n featureFlags: TemplateFeatureFlag[];\r\n enabledModules: string[];\r\n}\r\n\r\ninterface TemplateFilter {\r\n category?: \"backend\" | \"frontend\" | \"database\" | \"infra\";\r\n language?: string;\r\n framework?: string;\r\n tier?: \"starter\" | \"standard\" | \"enterprise\";\r\n tags?: string[];\r\n}\r\n\r\ninterface TemplateSearchResult {\r\n templates: TemplateMetadata[];\r\n total: number;\r\n page: number;\r\n pageSize: number;\r\n}\r\n\r\ninterface TemplateCombination {\r\n id: string;\r\n name: string;\r\n description: string;\r\n backend: string;\r\n frontend: string;\r\n sharedTypes?: boolean;\r\n apiContract?: \"rest\" | \"graphql\" | \"grpc\";\r\n}\r\n\r\ninterface CreditEstimate {\r\n estimatedCredits: number;\r\n totalFiles: number;\r\n files: string[];\r\n entities: number;\r\n}\r\n\r\ninterface EstimatePayload {\r\n projectId: string;\r\n // Template mode (new)\r\n templateId?: string;\r\n // Legacy targets mode\r\n targets?: string[];\r\n options?: {\r\n outputDir?: string;\r\n backendPreset?: string;\r\n frontendPreset?: string;\r\n backendLayers?: string[];\r\n frontendLayers?: string[];\r\n featureFlags?: Record<string, boolean>;\r\n // Architecture style: bounded-contexts vs flat\r\n useContexts?: boolean;\r\n // Filter by diagram/bounded context IDs\r\n diagramIds?: string[];\r\n };\r\n}\r\n\r\n/**\r\n * ApiClient\r\n *\r\n * Authenticated HTTP client for AeroCoding API\r\n * All requests include Bearer token authentication\r\n */\r\nexport class ApiClient {\r\n private client: AxiosInstance;\r\n\r\n constructor(\r\n accessToken: string,\r\n options?: {\r\n onUnauthorized?: () => Promise<void> | void;\r\n }\r\n ) {\r\n this.client = axios.create({\r\n baseURL: API_URL,\r\n headers: {\r\n Authorization: `Bearer ${accessToken}`,\r\n \"Content-Type\": \"application/json\",\r\n \"X-Requested-With\": \"XMLHttpRequest\", // Required for CSRF validation bypass\r\n },\r\n timeout: 30000, // 30 seconds\r\n });\r\n\r\n this.client.interceptors.response.use(\r\n (response) => response,\r\n async (error) => {\r\n if (error?.response?.status === 401) {\r\n await options?.onUnauthorized?.();\r\n }\r\n\r\n return Promise.reject(error);\r\n }\r\n );\r\n }\r\n\r\n /**\r\n * Get current authenticated user\r\n */\r\n async getCurrentUser(): Promise<User> {\r\n const response = await this.client.get(\"/api/user/me\");\r\n return response.data;\r\n }\r\n\r\n /**\r\n * List user's organizations\r\n */\r\n async listOrganizations(): Promise<Organization[]> {\r\n const response = await this.client.get(\"/api/organizations\");\r\n return response.data;\r\n }\r\n\r\n /**\r\n * List user's projects\r\n */\r\n async listProjects(organizationId?: string): Promise<Project[]> {\r\n const response = await this.client.get(\"/api/projects\", {\r\n params: { organizationId },\r\n });\r\n return response.data;\r\n }\r\n\r\n /**\r\n * Get project by ID\r\n */\r\n async getProject(projectId: string): Promise<Project> {\r\n const response = await this.client.get(`/api/projects/${projectId}`);\r\n return response.data;\r\n }\r\n\r\n /**\r\n * Generate code from project schema\r\n */\r\n async generateCode(payload: GeneratePayload): Promise<GenerateResult> {\r\n const response = await this.client.post(\"/api/generate\", payload);\r\n return response.data.data;\r\n }\r\n\r\n /**\r\n * Get credit usage for organization\r\n */\r\n async getCreditUsage(organizationId: string): Promise<CreditUsage> {\r\n const response = await this.client.get(\"/api/credits/usage\", {\r\n params: { organizationId },\r\n });\r\n return response.data;\r\n }\r\n\r\n /**\r\n * Get available architectures for a framework\r\n */\r\n async getArchitectures(framework: string): Promise<Architecture[]> {\r\n const response = await this.client.get(\"/api/architectures\", {\r\n params: { framework },\r\n });\r\n return response.data;\r\n }\r\n\r\n /**\r\n * Estimate credit cost for a generation request\r\n */\r\n async estimateCreditCost(payload: EstimatePayload): Promise<CreditEstimate> {\r\n const response = await this.client.post(\"/api/generate/estimate\", payload);\r\n return response.data.data;\r\n }\r\n\r\n // ============================================\r\n // Template Registry API\r\n // ============================================\r\n\r\n /**\r\n * Search templates with filters\r\n */\r\n async getTemplates(filter: TemplateFilter = {}): Promise<TemplateSearchResult> {\r\n const params = new URLSearchParams();\r\n if (filter.category) params.set(\"category\", filter.category);\r\n if (filter.language) params.set(\"language\", filter.language);\r\n if (filter.framework) params.set(\"framework\", filter.framework);\r\n if (filter.tier) params.set(\"tier\", filter.tier);\r\n if (filter.tags?.length) params.set(\"tags\", filter.tags.join(\",\"));\r\n\r\n const response = await this.client.get(`/api/templates?${params.toString()}`);\r\n return response.data;\r\n }\r\n\r\n /**\r\n * Get full template by ID (includes layers and feature flags)\r\n */\r\n async getTemplate(id: string): Promise<FullTemplate> {\r\n const response = await this.client.get(`/api/templates/${id}?full=true`);\r\n return response.data.template;\r\n }\r\n\r\n /**\r\n * Get template combinations (backend + frontend pairs)\r\n */\r\n async getTemplateCombinations(): Promise<TemplateCombination[]> {\r\n const response = await this.client.get(\"/api/templates/combinations\");\r\n return response.data.combinations;\r\n }\r\n\r\n /**\r\n * Get templates compatible with a given template\r\n */\r\n async getCompatibleTemplates(templateId: string): Promise<TemplateMetadata[]> {\r\n const response = await this.client.get(`/api/templates/${templateId}?compatible=true`);\r\n return response.data.compatible || [];\r\n }\r\n}\r\n","import { ApiClient } from \"../../api/client.js\";\r\nimport { TokenManager } from \"../../auth/token-manager.js\";\r\n\r\nexport function createApiClientWithAutoLogout(\r\n accessToken: string,\r\n tokenManager: TokenManager\r\n): ApiClient {\r\n return new ApiClient(accessToken, {\r\n onUnauthorized: async () => {\r\n await tokenManager.logout();\r\n },\r\n });\r\n}\r\n","import chalk from \"chalk\";\r\nimport { TokenManager } from \"../../auth/token-manager.js\";\r\n\r\nexport async function handleUnauthorized(\r\n tokenManager: TokenManager\r\n): Promise<never> {\r\n await tokenManager.logout();\r\n\r\n console.error(\r\n chalk.yellow(\r\n \" Your session is invalid or expired. You have been logged out.\"\r\n )\r\n );\r\n console.error(chalk.gray(\" Run 'aerocoding login' to authenticate.\"));\r\n\r\n process.exit(1);\r\n}\r\n","import chalk from \"chalk\";\r\nimport { TokenManager } from \"../auth/token-manager.js\";\r\n\r\n/**\r\n * Logout Command\r\n *\r\n * Clears stored credentials from OS credential manager\r\n */\r\nexport async function logoutCommand() {\r\n const tokenManager = new TokenManager();\r\n\r\n const metadata = await tokenManager.getUserMetadata();\r\n if (!metadata) {\r\n console.log(chalk.yellow(\"Not logged in\"));\r\n return;\r\n }\r\n\r\n const email = metadata.email;\r\n\r\n await tokenManager.logout();\r\n\r\n console.log(chalk.green(\"Logged out successfully\"));\r\n console.log(chalk.gray(` Cleared credentials for ${email}\\n`));\r\n}\r\n","import chalk from \"chalk\";\r\nimport { TokenManager } from \"../auth/token-manager.js\";\r\nimport { createApiClientWithAutoLogout } from \"./_shared/create-api-client.js\";\r\nimport { handleUnauthorized } from \"./_shared/unauthorized.js\";\r\n\r\n/**\r\n * Whoami Command\r\n *\r\n * Shows current authenticated user information\r\n */\r\nexport async function whoamiCommand() {\r\n const tokenManager = new TokenManager();\r\n const token = await tokenManager.getAccessToken();\r\n\r\n if (!token) {\r\n console.log(chalk.red(\"Not logged in\"));\r\n console.log(chalk.gray(\" Run 'aerocoding login' to authenticate\\n\"));\r\n return;\r\n }\r\n\r\n try {\r\n const apiClient = createApiClientWithAutoLogout(token, tokenManager);\r\n const user = await apiClient.getCurrentUser();\r\n\r\n console.log(\"\");\r\n console.log(chalk.white(\"Logged in as:\"), chalk.cyan.bold(user.email));\r\n if (user.name) {\r\n console.log(chalk.gray(\" Name:\"), user.name);\r\n }\r\n console.log(\"\");\r\n } catch (error: any) {\r\n console.error(chalk.red(\"Failed to get user info\"));\r\n if (error.response?.status === 401) {\r\n await handleUnauthorized(tokenManager);\r\n }\r\n process.exit(1);\r\n }\r\n}\r\n","import chalk from \"chalk\";\r\nimport ora from \"ora\";\r\nimport * as p from \"@clack/prompts\";\r\nimport { TokenManager } from \"../auth/token-manager.js\";\r\nimport { createApiClientWithAutoLogout } from \"./_shared/create-api-client.js\";\r\nimport { handleUnauthorized } from \"./_shared/unauthorized.js\";\r\nimport { writeGeneratedFiles, categorizeFilePaths } from \"../utils/file-writer.js\";\r\nimport { promptConfirm } from \"../utils/prompt.js\";\r\nimport { loadConfig } from \"../config/loader.js\";\r\nimport type { AerocodingConfig } from \"../config/schema.js\";\r\n\r\n/**\r\n * Map preset name to template ID for full architecture generation\r\n * Uses the new template system that generates all layers (DTOs, UseCases, Controllers, etc.)\r\n */\r\nfunction mapPresetToTemplateId(preset: string): string | null {\r\n const presetLower = preset.toLowerCase();\r\n\r\n // Clean Architecture presets → full template IDs\r\n if (presetLower.includes(\"clean\") && presetLower.includes(\"dotnet\")) {\r\n return \"clean-arch-dotnet\";\r\n }\r\n if (presetLower.includes(\"clean\") && (presetLower.includes(\"dart\") || presetLower.includes(\"flutter\"))) {\r\n return \"flutter-clean-dart-test\"; // Update when production template available\r\n }\r\n if (presetLower.includes(\"clean\") && presetLower.includes(\"typescript\")) {\r\n return \"minimal-typescript-test\"; // Update when production template available\r\n }\r\n\r\n // Direct template ID (if preset matches a template ID pattern)\r\n if (presetLower.startsWith(\"clean-arch-\")) {\r\n return preset;\r\n }\r\n\r\n return null;\r\n}\r\n\r\n/**\r\n * Map preset name to legacy generator target (fallback)\r\n * Used when no template ID is available for the preset\r\n */\r\nfunction mapPresetToTarget(preset: string): string | null {\r\n const presetLower = preset.toLowerCase();\r\n\r\n // .NET presets\r\n if (presetLower.includes(\"dotnet\") || presetLower.includes(\"aspnet\") || presetLower.includes(\"csharp\")) {\r\n return \"dotnet-entity\";\r\n }\r\n\r\n // Dart/Flutter presets\r\n if (presetLower.includes(\"dart\") || presetLower.includes(\"flutter\")) {\r\n return \"dart-entity\";\r\n }\r\n\r\n // TypeScript presets\r\n if (presetLower.includes(\"typescript\") || presetLower.includes(\"nextjs\") || presetLower.includes(\"react\")) {\r\n return \"typescript-interface\";\r\n }\r\n\r\n return null;\r\n}\r\n\r\n\r\n/**\r\n * Build feature flags from config for template generation\r\n */\r\nfunction buildFeatureFlagsFromConfig(config: AerocodingConfig | null): Record<string, boolean> {\r\n const flags: Record<string, boolean> = {\r\n // Default all feature flags to true for full architecture\r\n includeDtos: true,\r\n includeUseCases: true,\r\n includeMappers: true,\r\n includeControllers: true,\r\n includeEfConfig: true,\r\n includeValidation: true,\r\n includeDtoValidation: true, // Data Annotations on Input records ([Required], [MaxLength], etc.)\r\n // Test flags\r\n includeUnitTests: true,\r\n includeIntegrationTests: true,\r\n // Starter files (disabled by default - user adds their own Program.cs)\r\n includeStarterFiles: false,\r\n };\r\n\r\n if (!config) return flags;\r\n\r\n // Map codeStyle options to feature flags\r\n if (config.codeStyle?.includeValidations !== undefined) {\r\n flags.includeValidation = config.codeStyle.includeValidations;\r\n }\r\n // Map includeTesting to both unit and integration tests\r\n if (config.codeStyle?.includeTesting !== undefined) {\r\n flags.includeUnitTests = config.codeStyle.includeTesting;\r\n flags.includeIntegrationTests = config.codeStyle.includeTesting;\r\n }\r\n\r\n return flags;\r\n}\r\n\r\ninterface GenerateOptions {\r\n project?: string;\r\n targets?: string[];\r\n entities?: string[];\r\n output: string;\r\n // Presets\r\n backendPreset?: string;\r\n frontendPreset?: string;\r\n // Style toggles (commander inverts for --no-X, all default to true)\r\n validations?: boolean;\r\n comments?: boolean;\r\n logging?: boolean;\r\n testing?: boolean;\r\n // Validation library (framework-agnostic)\r\n validationLib?: string;\r\n // Control\r\n verbose?: boolean;\r\n yes?: boolean;\r\n all?: boolean; // Generate all diagrams and targets without prompting\r\n}\r\n\r\n/**\r\n * Generate Command\r\n *\r\n * Generates code from project schema via API\r\n * Consumes credits based on generated files and entity complexity\r\n *\r\n * Config file (.aerocodingrc.json) provides defaults, CLI args override\r\n */\r\nexport async function generateCommand(options: GenerateOptions) {\r\n // 1. Check authentication\r\n const tokenManager = new TokenManager();\r\n const token = await tokenManager.getAccessToken();\r\n\r\n if (!token) {\r\n console.log(chalk.red(\"\\n Not authenticated\"));\r\n console.log(chalk.gray(\" Run 'aerocoding login' to get started\\n\"));\r\n process.exit(1);\r\n }\r\n\r\n // 2. Load config file (optional)\r\n const config = await loadConfig();\r\n\r\n // 3. Merge config with CLI options (CLI overrides config)\r\n const projectId = options.project || config?.project;\r\n\r\n if (!projectId) {\r\n console.log(chalk.red(\"\\n Project ID required\"));\r\n console.log(chalk.gray(\" Run 'aerocoding init' to create a config file\"));\r\n console.log(chalk.gray(\" Or use --project <id> to specify a project\\n\"));\r\n process.exit(1);\r\n }\r\n\r\n // Merge other options with config defaults (templateId will be determined after target selection)\r\n const output = options.output || config?.output || \"./.aerocoding\";\r\n const validationLib = options.validationLib || config?.libraries?.validation;\r\n\r\n // Style options: CLI --no-X overrides config, config overrides default (true)\r\n const includeValidations = options.validations ?? config?.codeStyle?.includeValidations ?? true;\r\n const includeComments = options.comments ?? config?.codeStyle?.includeComments ?? true;\r\n const includeLogging = options.logging ?? config?.codeStyle?.includeLogging ?? true;\r\n const includeTesting = options.testing ?? config?.codeStyle?.includeTesting ?? true;\r\n\r\n const apiClient = createApiClientWithAutoLogout(token, tokenManager);\r\n\r\n let spinner = ora({ text: \"Fetching project...\", color: \"cyan\" }).start();\r\n\r\n try {\r\n // 4. Fetch project to get organizationId\r\n const project = await apiClient.getProject(projectId);\r\n spinner.succeed(chalk.gray(\"Project loaded\"));\r\n\r\n // 4a. Target selection (backend/frontend) - only if both configured\r\n const hasBackendConfig = !!config?.backend?.preset;\r\n const hasFrontendConfig = !!config?.frontend?.preset;\r\n const hasBothTargets = hasBackendConfig && hasFrontendConfig;\r\n\r\n let selectedTarget: \"backend\" | \"frontend\" | \"both\" = \"both\";\r\n\r\n if (hasBothTargets && !options.all) {\r\n const targetChoice = await p.select({\r\n message: \"Which target do you want to generate?\",\r\n options: [\r\n {\r\n value: \"backend\",\r\n label: `Backend (${config?.backend?.preset})`,\r\n hint: \"Recommended\",\r\n },\r\n {\r\n value: \"frontend\",\r\n label: `Frontend (${config?.frontend?.preset})`,\r\n },\r\n {\r\n value: \"both\",\r\n label: \"Both\",\r\n },\r\n ],\r\n initialValue: \"backend\",\r\n });\r\n\r\n if (p.isCancel(targetChoice)) {\r\n console.log(chalk.yellow(\"\\n Generation cancelled\\n\"));\r\n process.exit(0);\r\n }\r\n\r\n selectedTarget = targetChoice as \"backend\" | \"frontend\" | \"both\";\r\n } else if (hasBackendConfig && !hasFrontendConfig) {\r\n selectedTarget = \"backend\";\r\n } else if (hasFrontendConfig && !hasBackendConfig) {\r\n selectedTarget = \"frontend\";\r\n }\r\n\r\n // 4b. Diagram selection - only if multiple diagrams exist\r\n interface Diagram {\r\n id?: string;\r\n name?: string;\r\n entities?: unknown[];\r\n }\r\n const diagrams: Diagram[] = (project.schema as { diagrams?: Diagram[] })?.diagrams || [];\r\n const hasMultipleDiagrams = diagrams.length > 1;\r\n\r\n let selectedDiagramIds: string[] = diagrams.map((d) => d.id || d.name || \"unknown\");\r\n\r\n if (hasMultipleDiagrams && !options.all) {\r\n const diagramChoices = await p.multiselect({\r\n message: \"Which bounded contexts do you want to generate?\",\r\n options: diagrams.map((d) => ({\r\n value: d.id || d.name || \"unknown\",\r\n label: `${d.name || \"Unnamed\"} (${d.entities?.length || 0} entities)`,\r\n })),\r\n initialValues: diagrams.map((d) => d.id || d.name || \"unknown\"),\r\n required: true,\r\n });\r\n\r\n if (p.isCancel(diagramChoices)) {\r\n console.log(chalk.yellow(\"\\n Generation cancelled\\n\"));\r\n process.exit(0);\r\n }\r\n\r\n selectedDiagramIds = diagramChoices as string[];\r\n }\r\n\r\n // 4c. Build templateId, targets, featureFlags based on selected target\r\n let templateId: string | null = null;\r\n let targets: string[] = [];\r\n let backendPreset: string | undefined;\r\n let frontendPreset: string | undefined;\r\n\r\n if (selectedTarget === \"backend\" || selectedTarget === \"both\") {\r\n backendPreset = options.backendPreset || config?.backend?.preset;\r\n if (backendPreset) {\r\n const tid = mapPresetToTemplateId(backendPreset);\r\n if (tid) templateId = tid;\r\n const target = mapPresetToTarget(backendPreset);\r\n if (target) targets.push(target);\r\n }\r\n }\r\n\r\n if (selectedTarget === \"frontend\" || selectedTarget === \"both\") {\r\n frontendPreset = options.frontendPreset || config?.frontend?.preset;\r\n if (frontendPreset) {\r\n const tid = mapPresetToTemplateId(frontendPreset);\r\n if (tid && !templateId) templateId = tid; // Only if backend didn't set one\r\n const target = mapPresetToTarget(frontendPreset);\r\n if (target) targets.push(target);\r\n }\r\n }\r\n\r\n // Fallback: if no config, try CLI options for targets\r\n if (!templateId && (!targets || targets.length === 0)) {\r\n targets = options.targets || [];\r\n }\r\n\r\n // Build feature flags from config\r\n const featureFlags = buildFeatureFlagsFromConfig(config);\r\n\r\n // 5. Fetch credit usage and estimate cost in parallel\r\n spinner = ora({ text: \"Checking credits...\", color: \"cyan\" }).start();\r\n\r\n const credits = await apiClient.getCreditUsage(project.organizationId);\r\n\r\n // Try to get cost estimate (includes file paths for preview)\r\n // Determine architecture style early for estimate\r\n const useContexts = config?.architectureStyle !== \"flat\";\r\n\r\n // Include diagramIds to filter estimate by selected bounded contexts\r\n const estimateDiagramIds = selectedDiagramIds.length < diagrams.length ? selectedDiagramIds : undefined;\r\n\r\n let estimate: { estimatedCredits: number; totalFiles: number; entities: number; files: string[] } | null = null;\r\n try {\r\n if (templateId) {\r\n // Template mode: estimate using templateId\r\n estimate = await apiClient.estimateCreditCost({\r\n projectId,\r\n templateId,\r\n options: {\r\n featureFlags,\r\n useContexts,\r\n diagramIds: estimateDiagramIds,\r\n },\r\n });\r\n } else if (targets && targets.length > 0) {\r\n // Legacy mode: estimate using targets\r\n estimate = await apiClient.estimateCreditCost({\r\n projectId,\r\n targets,\r\n options: {\r\n outputDir: output,\r\n backendPreset,\r\n frontendPreset,\r\n useContexts,\r\n diagramIds: estimateDiagramIds,\r\n },\r\n });\r\n }\r\n } catch {\r\n // Estimate endpoint may not be available yet - continue without estimate\r\n }\r\n\r\n spinner.succeed(chalk.gray(\"Credits verified\"));\r\n\r\n // Check if project has entities (required for generation)\r\n if (estimate && estimate.entities === 0) {\r\n console.log(chalk.yellow(\"\\n ⚠ No entities found in this project.\"));\r\n console.log(chalk.gray(\" Create entities in the diagram editor and save (Ctrl+S) before generating.\\n\"));\r\n process.exit(1);\r\n }\r\n\r\n // Check if enough credits before showing summary (skip if no estimate)\r\n const hasEnoughCredits = estimate ? credits.remaining >= estimate.estimatedCredits : true;\r\n\r\n // 6. Show summary\r\n console.log(\"\");\r\n console.log(chalk.bold(\" Generation Summary\"));\r\n console.log(chalk.gray(\" ─────────────────────────────────\"));\r\n console.log(chalk.gray(\" Project:\"), chalk.white(project.name));\r\n if (config) {\r\n console.log(chalk.gray(\" Config:\"), chalk.cyan(\".aerocodingrc.json\"));\r\n }\r\n // Show generation mode\r\n if (templateId) {\r\n console.log(chalk.gray(\" Mode:\"), chalk.green(\"Full Architecture\"));\r\n console.log(chalk.gray(\" Template:\"), chalk.cyan(templateId));\r\n } else if (targets && targets.length > 0) {\r\n console.log(chalk.gray(\" Mode:\"), chalk.yellow(\"Simple (legacy)\"));\r\n console.log(chalk.gray(\" Targets:\"), chalk.cyan(targets.join(\", \")));\r\n } else {\r\n console.log(chalk.gray(\" Mode:\"), chalk.gray(\"default\"));\r\n }\r\n\r\n // Show selected target (if user had a choice)\r\n if (hasBothTargets) {\r\n const targetLabel =\r\n selectedTarget === \"backend\"\r\n ? \"Backend only\"\r\n : selectedTarget === \"frontend\"\r\n ? \"Frontend only\"\r\n : \"Backend + Frontend\";\r\n console.log(chalk.gray(\" Target:\"), chalk.cyan(targetLabel));\r\n }\r\n\r\n if (backendPreset && (selectedTarget === \"backend\" || selectedTarget === \"both\")) {\r\n console.log(chalk.gray(\" Backend Preset:\"), chalk.cyan(backendPreset));\r\n }\r\n if (frontendPreset && (selectedTarget === \"frontend\" || selectedTarget === \"both\")) {\r\n console.log(chalk.gray(\" Frontend Preset:\"), chalk.cyan(frontendPreset));\r\n }\r\n\r\n // Show selected diagrams (if user had a choice)\r\n if (hasMultipleDiagrams) {\r\n const selectedCount = selectedDiagramIds.length;\r\n const totalCount = diagrams.length;\r\n if (selectedCount === totalCount) {\r\n console.log(chalk.gray(\" Bounded Contexts:\"), chalk.cyan(`All (${totalCount})`));\r\n } else {\r\n const selectedNames = diagrams\r\n .filter((d) => selectedDiagramIds.includes(d.id || d.name || \"unknown\"))\r\n .map((d) => d.name || \"Unnamed\")\r\n .join(\", \");\r\n console.log(chalk.gray(\" Bounded Contexts:\"), chalk.cyan(`${selectedCount}/${totalCount} (${selectedNames})`));\r\n }\r\n }\r\n\r\n // Show architecture style\r\n const archStyle = config?.architectureStyle || \"bounded-contexts\";\r\n console.log(\r\n chalk.gray(\" Architecture:\"),\r\n archStyle === \"bounded-contexts\"\r\n ? chalk.cyan(\"Bounded Contexts\")\r\n : chalk.yellow(\"Flat Structure\")\r\n );\r\n\r\n // Show style options if different from defaults (all default to true)\r\n const disabledOptions: string[] = [];\r\n if (!includeValidations) disabledOptions.push(\"validations\");\r\n if (!includeComments) disabledOptions.push(\"comments\");\r\n if (!includeLogging) disabledOptions.push(\"logging\");\r\n if (!includeTesting) disabledOptions.push(\"testing\");\r\n\r\n if (disabledOptions.length > 0) {\r\n console.log(chalk.gray(\" Disabled:\"), chalk.yellow(disabledOptions.join(\", \")));\r\n }\r\n\r\n if (validationLib) {\r\n console.log(chalk.gray(\" Validation Lib:\"), chalk.cyan(validationLib));\r\n }\r\n\r\n console.log(chalk.gray(\" Output:\"), chalk.cyan(output));\r\n\r\n // Show categorized file preview (if available)\r\n if (estimate && estimate.files && estimate.files.length > 0) {\r\n console.log(\"\");\r\n console.log(chalk.bold(\" Files to Generate\"));\r\n console.log(chalk.gray(\" ─────────────────────────────────\"));\r\n\r\n const categories = categorizeFilePaths(estimate.files);\r\n const maxNameLength = Math.max(...categories.map((c) => c.name.length));\r\n\r\n for (const category of categories) {\r\n const padding = \" \".repeat(maxNameLength - category.name.length + 2);\r\n const countStr = category.count.toString().padStart(3, \" \");\r\n console.log(\r\n chalk.gray(` ${category.name}${padding}`),\r\n chalk.cyan(`${countStr} files`)\r\n );\r\n }\r\n\r\n console.log(chalk.gray(\" ─────────────────────────────────\"));\r\n const totalPadding = \" \".repeat(maxNameLength - 5 + 2);\r\n const totalStr = estimate.totalFiles.toString().padStart(3, \" \");\r\n console.log(\r\n chalk.white(` Total${totalPadding}`),\r\n chalk.bold.cyan(`${totalStr} files`)\r\n );\r\n console.log(chalk.gray(` Entities:`), chalk.cyan(estimate.entities));\r\n }\r\n\r\n // Show credits section\r\n console.log(\"\");\r\n console.log(chalk.bold(\" Credits\"));\r\n console.log(chalk.gray(\" ─────────────────────────────────\"));\r\n if (estimate) {\r\n console.log(\r\n chalk.white(\" Cost:\"),\r\n hasEnoughCredits\r\n ? chalk.bold.yellow(`${estimate.estimatedCredits} credits`)\r\n : chalk.bold.red(`${estimate.estimatedCredits} credits`)\r\n );\r\n }\r\n console.log(\r\n chalk.white(\" Available:\"),\r\n hasEnoughCredits\r\n ? chalk.bold.green(`${credits.remaining} credits`)\r\n : chalk.bold.red(`${credits.remaining} credits (insufficient)`)\r\n );\r\n console.log(\"\");\r\n\r\n // Warn if not enough credits\r\n if (!hasEnoughCredits && estimate) {\r\n console.log(chalk.red(\" ⚠ Not enough credits for this generation.\"));\r\n console.log(chalk.gray(` Need ${estimate.estimatedCredits - credits.remaining} more credits.\\n`));\r\n process.exit(1);\r\n }\r\n\r\n // 7. Confirmation (unless --yes)\r\n if (!options.yes) {\r\n const confirmed = await promptConfirm(\" Proceed with generation?\");\r\n if (!confirmed) {\r\n console.log(chalk.yellow(\"\\n Generation cancelled\\n\"));\r\n process.exit(0);\r\n }\r\n }\r\n\r\n // 8. Call API\r\n console.log(\"\");\r\n spinner = ora({ text: \"Generating code...\", color: \"cyan\" }).start();\r\n\r\n // Build API request based on mode (useContexts already determined above)\r\n // Include diagramIds to filter which bounded contexts to generate\r\n const diagramIds = selectedDiagramIds.length < diagrams.length ? selectedDiagramIds : undefined;\r\n\r\n const generatePayload = templateId\r\n ? {\r\n // NEW: Full architecture mode using template\r\n projectId,\r\n templateId,\r\n options: {\r\n includeValidations,\r\n includeComments,\r\n featureFlags,\r\n useContexts,\r\n diagramIds, // Filter by selected bounded contexts\r\n },\r\n }\r\n : {\r\n // Legacy mode using targets\r\n projectId,\r\n targets,\r\n options: {\r\n includeValidations,\r\n includeComments,\r\n includeLogging,\r\n includeTesting,\r\n outputDir: output,\r\n backendPreset,\r\n frontendPreset,\r\n validationLib,\r\n useContexts,\r\n diagramIds, // Filter by selected bounded contexts\r\n },\r\n };\r\n\r\n const result = await apiClient.generateCode(generatePayload);\r\n\r\n spinner.succeed(chalk.green(\"Code generated successfully!\"));\r\n\r\n // 9. Show results with credits\r\n console.log(\"\");\r\n console.log(chalk.bold(\" Results\"));\r\n console.log(chalk.gray(\" ─────────────────────────────────\"));\r\n console.log(chalk.gray(\" Files:\"), chalk.cyan(result.stats?.totalFiles ?? result.files?.length ?? 0));\r\n if (result.stats?.totalEntities) {\r\n console.log(chalk.gray(\" Entities:\"), chalk.cyan(result.stats.totalEntities));\r\n }\r\n if (result.stats?.languages && result.stats.languages.length > 0) {\r\n console.log(\r\n chalk.gray(\" Languages:\"),\r\n chalk.cyan(result.stats.languages.join(\", \"))\r\n );\r\n }\r\n\r\n if (result.creditsUsed !== undefined) {\r\n console.log(\"\");\r\n console.log(chalk.bold(\" Credits\"));\r\n console.log(chalk.gray(\" ─────────────────────────────────\"));\r\n console.log(chalk.gray(\" Used:\"), chalk.yellow(result.creditsUsed));\r\n console.log(\r\n chalk.gray(\" Remaining:\"),\r\n result.creditsRemaining !== undefined && result.creditsRemaining > 50\r\n ? chalk.green(result.creditsRemaining)\r\n : chalk.yellow(result.creditsRemaining)\r\n );\r\n }\r\n\r\n // Show warnings if any\r\n if (result.warnings && result.warnings.length > 0) {\r\n console.log(\"\");\r\n console.log(chalk.yellow(\" Warnings:\"));\r\n for (const warning of result.warnings) {\r\n console.log(chalk.yellow(` - ${warning}`));\r\n }\r\n }\r\n\r\n console.log(\"\");\r\n\r\n // 10. Write files to disk\r\n await writeGeneratedFiles(result.files, output, options.verbose);\r\n\r\n console.log(chalk.green(` Files written to ${chalk.white(output)}`));\r\n console.log(\"\");\r\n } catch (error: any) {\r\n spinner.fail(chalk.red(\"Generation failed\"));\r\n\r\n if (error.response?.status === 401) {\r\n await handleUnauthorized(tokenManager);\r\n } else if (error.response?.status === 403) {\r\n console.log(chalk.yellow(\"\\n You don't have permission to access this project.\"));\r\n console.log(chalk.gray(\" Check if you're part of the organization.\\n\"));\r\n } else if (error.response?.status === 404) {\r\n console.log(chalk.yellow(\"\\n Project not found.\"));\r\n console.log(chalk.gray(\" Check if the project ID is correct.\\n\"));\r\n } else if (error.response?.status === 429) {\r\n // Insufficient credits\r\n const data = error.response.data;\r\n console.log(chalk.red(\"\\n Insufficient credits\"));\r\n if (data.requiredCredits) {\r\n console.log(chalk.yellow(` Required: ${data.requiredCredits} credits`));\r\n }\r\n console.log(chalk.yellow(` Available: ${data.remaining ?? 0} credits`));\r\n console.log(chalk.gray(\"\\n Upgrade your plan or wait for credit reset.\\n\"));\r\n } else if (error.response?.data?.message) {\r\n console.log(chalk.red(`\\n ${error.response.data.message}\\n`));\r\n } else {\r\n console.log(chalk.red(`\\n ${error.message}\\n`));\r\n }\r\n\r\n process.exit(1);\r\n }\r\n}\r\n","import fs from \"fs/promises\";\r\nimport path from \"path\";\r\nimport chalk from \"chalk\";\r\n\r\ninterface GeneratedFile {\r\n path: string;\r\n content: string;\r\n language: string;\r\n entityId?: string;\r\n /**\r\n * If true, file should only be written if it doesn't already exist.\r\n * Used for starter files (Program.cs, appsettings.json) that users may customize.\r\n */\r\n generateOnce?: boolean;\r\n}\r\n\r\nexport interface FileCategory {\r\n name: string;\r\n count: number;\r\n files: string[];\r\n}\r\n\r\n/**\r\n * Validate that a file path is safe and doesn't escape the output directory.\r\n * SECURITY: Prevents path traversal attacks (e.g., ../../../etc/passwd)\r\n */\r\nfunction isPathSafe(outputDir: string, filePath: string): boolean {\r\n // Resolve both paths to absolute paths\r\n const resolvedOutput = path.resolve(outputDir);\r\n const resolvedFile = path.resolve(outputDir, filePath);\r\n\r\n // Check if the resolved file path starts with the output directory\r\n // Also ensure there's a path separator after the base to prevent\r\n // matching \"output\" when file is in \"output-malicious\"\r\n return (\r\n resolvedFile.startsWith(resolvedOutput + path.sep) ||\r\n resolvedFile === resolvedOutput\r\n );\r\n}\r\n\r\n/**\r\n * Get category name from file path\r\n * Analyzes path segments to determine file type\r\n * @public Exported for use in preview/estimate display\r\n */\r\nexport function getCategoryFromPath(filePath: string): string {\r\n const lowerPath = filePath.toLowerCase();\r\n\r\n // Order matters - more specific first\r\n if (lowerPath.includes(\"/controllers/\")) return \"Controllers\";\r\n if (lowerPath.includes(\"/usecases/\") || lowerPath.includes(\"/use-cases/\"))\r\n return \"UseCases\";\r\n if (lowerPath.includes(\"/dtos/\") || lowerPath.includes(\"/dto/\")) return \"DTOs\";\r\n if (lowerPath.includes(\"/entities/\")) return \"Entities\";\r\n if (\r\n lowerPath.includes(\"/repositories/\") ||\r\n lowerPath.includes(\"/repositoriesimpl/\")\r\n )\r\n return \"Repositories\";\r\n if (\r\n lowerPath.includes(\"/configurations/\") ||\r\n lowerPath.includes(\"/config/\")\r\n )\r\n return \"Configurations\";\r\n if (\r\n lowerPath.includes(\"/validators/\") ||\r\n lowerPath.includes(\"/validation/\")\r\n )\r\n return \"Validators\";\r\n if (lowerPath.includes(\"/mappers/\")) return \"Mappers\";\r\n if (lowerPath.includes(\"/interfaces/\")) return \"Interfaces\";\r\n if (lowerPath.includes(\"/exceptions/\")) return \"Exceptions\";\r\n if (lowerPath.includes(\"/vos/\") || lowerPath.includes(\"/valueobjects/\"))\r\n return \"ValueObjects\";\r\n if (lowerPath.includes(\"/ioc/\") || lowerPath.includes(\"/di/\"))\r\n return \"DependencyInjection\";\r\n if (\r\n lowerPath.includes(\"/tests/\") ||\r\n lowerPath.includes(\".test.\") ||\r\n lowerPath.includes(\".spec.\")\r\n )\r\n return \"Tests\";\r\n if (lowerPath.includes(\"/database/\")) return \"Database\";\r\n\r\n return \"Other\";\r\n}\r\n\r\n/**\r\n * Categorize file paths into categories\r\n * Used for preview/estimate display before generation\r\n * @public Exported for use in generate command preview\r\n */\r\nexport function categorizeFilePaths(filePaths: string[]): FileCategory[] {\r\n const categories = new Map<string, string[]>();\r\n\r\n for (const filePath of filePaths) {\r\n const category = getCategoryFromPath(filePath);\r\n const existing = categories.get(category) || [];\r\n existing.push(filePath);\r\n categories.set(category, existing);\r\n }\r\n\r\n return Array.from(categories.entries())\r\n .map(([name, fileList]) => ({ name, count: fileList.length, files: fileList }))\r\n .sort((a, b) => b.count - a.count); // Most files first\r\n}\r\n\r\n/**\r\n * Categorize files by their path\r\n * Groups files into categories like Entities, DTOs, UseCases, etc.\r\n */\r\nfunction categorizeFiles(files: GeneratedFile[]): FileCategory[] {\r\n return categorizeFilePaths(files.map((f) => f.path));\r\n}\r\n\r\n/**\r\n * Display categorized summary of generated files\r\n */\r\nfunction displayCategorizedSummary(files: GeneratedFile[]): void {\r\n const categories = categorizeFiles(files);\r\n\r\n console.log(\"\");\r\n console.log(chalk.bold(\" Generated Files\"));\r\n console.log(chalk.gray(\" ─────────────────────────────────\"));\r\n\r\n // Find max name length for alignment\r\n const maxNameLength = Math.max(...categories.map((c) => c.name.length));\r\n\r\n for (const category of categories) {\r\n const padding = \" \".repeat(maxNameLength - category.name.length + 2);\r\n const countStr = category.count.toString().padStart(3, \" \");\r\n console.log(\r\n chalk.gray(` ${category.name}${padding}`),\r\n chalk.cyan(`${countStr} files`)\r\n );\r\n }\r\n\r\n console.log(chalk.gray(\" ─────────────────────────────────\"));\r\n const totalPadding = \" \".repeat(maxNameLength - 5 + 2);\r\n const totalStr = files.length.toString().padStart(3, \" \");\r\n console.log(\r\n chalk.white(` Total${totalPadding}`),\r\n chalk.bold.cyan(`${totalStr} files`)\r\n );\r\n}\r\n\r\n/**\r\n * Write generated files to disk\r\n *\r\n * Creates directories as needed and writes files\r\n * Shows categorized summary by default, or full list with verbose=true\r\n */\r\nexport async function writeGeneratedFiles(\r\n files: GeneratedFile[],\r\n outputDir: string,\r\n verbose: boolean = false\r\n): Promise<void> {\r\n // Track written files for summary\r\n const writtenFiles: GeneratedFile[] = [];\r\n\r\n // Track skipped generateOnce files for summary\r\n const skippedOnceFiles: string[] = [];\r\n\r\n for (const file of files) {\r\n // SECURITY: Validate path doesn't escape output directory\r\n if (!isPathSafe(outputDir, file.path)) {\r\n console.error(chalk.red(` Skipping unsafe path: ${file.path}`));\r\n console.error(\r\n chalk.gray(\r\n ` Path traversal detected - file path must be within output directory`\r\n )\r\n );\r\n continue;\r\n }\r\n\r\n const fullPath = path.resolve(outputDir, file.path);\r\n const dir = path.dirname(fullPath);\r\n\r\n // Check if file has generateOnce flag and already exists\r\n if (file.generateOnce) {\r\n try {\r\n await fs.access(fullPath);\r\n // File exists - skip it\r\n skippedOnceFiles.push(file.path);\r\n continue;\r\n } catch {\r\n // File doesn't exist - proceed with generation\r\n }\r\n }\r\n\r\n try {\r\n // Create directory if doesn't exist\r\n await fs.mkdir(dir, { recursive: true });\r\n\r\n // Write file\r\n await fs.writeFile(fullPath, file.content, \"utf-8\");\r\n\r\n // Show file path in verbose mode\r\n if (verbose) {\r\n console.log(chalk.gray(` ${file.path}`));\r\n }\r\n\r\n writtenFiles.push(file);\r\n } catch (error: any) {\r\n console.error(chalk.red(` Failed to write ${file.path}`));\r\n console.error(chalk.gray(` ${error.message}`));\r\n }\r\n }\r\n\r\n // Show categorized summary (unless verbose)\r\n if (!verbose && writtenFiles.length > 0) {\r\n displayCategorizedSummary(writtenFiles);\r\n }\r\n\r\n // Show skipped generateOnce files\r\n if (skippedOnceFiles.length > 0) {\r\n console.log(\"\");\r\n console.log(\r\n chalk.gray(` Skipped ${skippedOnceFiles.length} existing file(s) (generateOnce):`)\r\n );\r\n for (const filePath of skippedOnceFiles) {\r\n console.log(chalk.gray(` - ${filePath}`));\r\n }\r\n }\r\n}\r\n","import readline from \"readline\";\r\nimport chalk from \"chalk\";\r\n\r\n/**\r\n * Prompt user for confirmation\r\n * Returns true if user confirms (Y/yes/enter), false if they decline (n/no)\r\n */\r\nexport function promptConfirm(message: string): Promise<boolean> {\r\n return new Promise((resolve) => {\r\n const rl = readline.createInterface({\r\n input: process.stdin,\r\n output: process.stdout,\r\n });\r\n\r\n rl.question(chalk.yellow(`${message} [Y/n] `), (answer) => {\r\n rl.close();\r\n const normalized = answer.trim().toLowerCase();\r\n // Empty input (just pressing Enter) means \"yes\"\r\n resolve(normalized !== \"n\" && normalized !== \"no\");\r\n });\r\n });\r\n}\r\n","import fs from \"fs/promises\";\r\nimport path from \"path\";\r\nimport { configSchema, CONFIG_FILENAME, type AerocodingConfig } from \"./schema.js\";\r\n\r\nexport async function loadConfig(\r\n dir: string = process.cwd()\r\n): Promise<AerocodingConfig | null> {\r\n const configPath = path.join(dir, CONFIG_FILENAME);\r\n\r\n try {\r\n const content = await fs.readFile(configPath, \"utf-8\");\r\n const parsed = JSON.parse(content);\r\n return configSchema.parse(parsed);\r\n } catch (error) {\r\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") {\r\n return null;\r\n }\r\n throw error;\r\n }\r\n}\r\n\r\nexport async function saveConfig(\r\n config: AerocodingConfig,\r\n dir: string = process.cwd()\r\n): Promise<void> {\r\n const configPath = path.join(dir, CONFIG_FILENAME);\r\n const content = JSON.stringify(\r\n {\r\n $schema: \"https://aerocoding.dev/schemas/aerocodingrc.json\",\r\n ...config,\r\n },\r\n null,\r\n 2\r\n );\r\n await fs.writeFile(configPath, content, \"utf-8\");\r\n}\r\n\r\nexport async function configExists(dir: string = process.cwd()): Promise<boolean> {\r\n const configPath = path.join(dir, CONFIG_FILENAME);\r\n try {\r\n await fs.access(configPath);\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\nexport { type AerocodingConfig, CONFIG_FILENAME } from \"./schema.js\";\r\n","import { z } from \"zod\";\r\n\r\nexport const configSchema = z.object({\r\n $schema: z.string().optional(),\r\n project: z.string().uuid(),\r\n output: z.string().default(\"./.aerocoding\"),\r\n\r\n // Architecture style: how to organize generated code\r\n architectureStyle: z\r\n .enum([\"bounded-contexts\", \"flat\"])\r\n .optional()\r\n .default(\"bounded-contexts\"),\r\n\r\n backend: z\r\n .object({\r\n preset: z.string(),\r\n })\r\n .optional(),\r\n\r\n frontend: z\r\n .object({\r\n preset: z.string(),\r\n })\r\n .optional(),\r\n\r\n codeStyle: z\r\n .object({\r\n includeValidations: z.boolean().default(true),\r\n includeComments: z.boolean().default(true),\r\n includeLogging: z.boolean().default(true),\r\n includeTesting: z.boolean().default(true),\r\n })\r\n .optional(),\r\n\r\n libraries: z\r\n .object({\r\n validation: z.string().optional(),\r\n logging: z.string().optional(),\r\n })\r\n .optional(),\r\n\r\n excludePatterns: z.array(z.string()).optional(),\r\n});\r\n\r\nexport type AerocodingConfig = z.infer<typeof configSchema>;\r\n\r\nexport const CONFIG_FILENAME = \".aerocodingrc.json\";\r\n","import * as p from \"@clack/prompts\";\r\nimport chalk from \"chalk\";\r\nimport { TokenManager } from \"../auth/token-manager.js\";\r\nimport { createApiClientWithAutoLogout } from \"./_shared/create-api-client.js\";\r\nimport { handleUnauthorized } from \"./_shared/unauthorized.js\";\r\nimport { saveConfig, configExists } from \"../config/loader.js\";\r\nimport type { AerocodingConfig } from \"../config/schema.js\";\r\n\r\ninterface InitOptions {\r\n project?: string;\r\n force?: boolean;\r\n}\r\n\r\n/**\r\n * Init Command\r\n *\r\n * Interactive wizard to initialize AeroCoding in current directory\r\n * Creates .aerocodingrc.json config file\r\n */\r\nexport async function initCommand(options: InitOptions) {\r\n p.intro(chalk.bgCyan.black(\" AeroCoding CLI \"));\r\n\r\n // Check if config already exists\r\n if (!options.force && (await configExists())) {\r\n const overwrite = await p.confirm({\r\n message: \"Config file already exists. Overwrite?\",\r\n initialValue: false,\r\n });\r\n\r\n if (p.isCancel(overwrite) || !overwrite) {\r\n p.cancel(\"Operation cancelled.\");\r\n process.exit(0);\r\n }\r\n }\r\n\r\n // 1. Check authentication\r\n const tokenManager = new TokenManager();\r\n const token = await tokenManager.getAccessToken();\r\n\r\n if (!token) {\r\n p.cancel(\"Not logged in. Run 'aerocoding login' first.\");\r\n process.exit(1);\r\n }\r\n\r\n const apiClient = createApiClientWithAutoLogout(token, tokenManager);\r\n\r\n try {\r\n // 2. Select organization first\r\n const orgSpinner = p.spinner();\r\n orgSpinner.start(\"Loading organizations...\");\r\n\r\n const organizations = await apiClient.listOrganizations();\r\n orgSpinner.stop(\"Organizations loaded\");\r\n\r\n if (organizations.length === 0) {\r\n p.cancel(\"No organizations found. Create one on aerocoding.dev first.\");\r\n process.exit(1);\r\n }\r\n\r\n let organizationId: string;\r\n\r\n if (organizations.length === 1 && organizations[0]) {\r\n // Auto-select if only one org\r\n organizationId = organizations[0].id;\r\n p.log.info(`Organization: ${organizations[0].name}`);\r\n } else {\r\n const selectedOrg = await p.select({\r\n message: \"Select organization\",\r\n options: organizations.map((org) => ({\r\n value: org.id,\r\n label: org.name,\r\n hint: org.planTier.toUpperCase(),\r\n })),\r\n });\r\n\r\n if (p.isCancel(selectedOrg)) {\r\n p.cancel(\"Operation cancelled.\");\r\n process.exit(0);\r\n }\r\n\r\n organizationId = selectedOrg as string;\r\n }\r\n\r\n // 3. Select project from organization\r\n let projectId = options.project;\r\n\r\n if (!projectId) {\r\n const spinner = p.spinner();\r\n spinner.start(\"Loading projects...\");\r\n\r\n const projects = await apiClient.listProjects(organizationId);\r\n spinner.stop(\"Projects loaded\");\r\n\r\n if (projects.length === 0) {\r\n p.cancel(\"No projects in this organization. Create one on aerocoding.dev first.\");\r\n process.exit(1);\r\n }\r\n\r\n const selectedProject = await p.select({\r\n message: \"Select project\",\r\n options: projects.map((proj) => ({\r\n value: proj.id,\r\n label: proj.name,\r\n hint: [proj.backendFramework, proj.frontendFramework].filter(Boolean).join(\" + \"),\r\n })),\r\n });\r\n\r\n if (p.isCancel(selectedProject)) {\r\n p.cancel(\"Operation cancelled.\");\r\n process.exit(0);\r\n }\r\n\r\n projectId = selectedProject as string;\r\n }\r\n\r\n // 4. Fetch project details\r\n const spinner = p.spinner();\r\n spinner.start(\"Fetching project details...\");\r\n const project = await apiClient.getProject(projectId);\r\n spinner.stop(`Project: ${project.name}`);\r\n\r\n // Detect frameworks from project settings (no longer asking user)\r\n const hasBackend = !!project.backendFramework;\r\n const hasFrontend = !!project.frontendFramework;\r\n\r\n if (!hasBackend && !hasFrontend) {\r\n p.cancel(\"Project has no frameworks configured. Update it on aerocoding.dev first.\");\r\n process.exit(1);\r\n }\r\n\r\n // Show detected frameworks\r\n if (hasBackend) {\r\n p.log.success(`Backend: ${project.backendFramework?.toUpperCase()} detected`);\r\n }\r\n if (hasFrontend) {\r\n p.log.success(`Frontend: ${project.frontendFramework?.toUpperCase()} detected`);\r\n }\r\n\r\n // Initialize config (architectureStyle will be set later based on template or user choice)\r\n const config: AerocodingConfig = {\r\n project: projectId,\r\n output: \"./.aerocoding\",\r\n architectureStyle: \"flat\", // Default, will be updated based on template or user choice\r\n codeStyle: {\r\n includeValidations: true,\r\n includeComments: true,\r\n includeLogging: true,\r\n includeTesting: true,\r\n },\r\n };\r\n\r\n // Track selected templates to determine architecture style later\r\n let selectedBackendTemplate: { architectureStyle?: \"bounded-contexts\" | \"flat\" } | null = null;\r\n let selectedFrontendTemplate: { architectureStyle?: \"bounded-contexts\" | \"flat\" } | null = null;\r\n\r\n // 5. Backend configuration (if project has backend framework)\r\n if (hasBackend && project.backendFramework) {\r\n const archSpinner = p.spinner();\r\n archSpinner.start(\"Loading backend templates...\");\r\n\r\n // Use new template registry API\r\n const templateResult = await apiClient.getTemplates({\r\n category: \"backend\",\r\n language: project.backendFramework,\r\n });\r\n archSpinner.stop(\"Templates loaded\");\r\n\r\n if (templateResult.templates.length > 0) {\r\n const preset = await p.select({\r\n message: \"Backend template\",\r\n options: templateResult.templates.map((tmpl) => ({\r\n value: tmpl.id,\r\n label: tmpl.name,\r\n hint: tmpl.description || `${tmpl.tier} tier`,\r\n })),\r\n });\r\n\r\n if (p.isCancel(preset)) {\r\n p.cancel(\"Operation cancelled.\");\r\n process.exit(0);\r\n }\r\n\r\n // Fetch full template to get architectureStyle recommendation\r\n const fullTemplate = await apiClient.getTemplate(preset as string);\r\n selectedBackendTemplate = fullTemplate;\r\n\r\n config.backend = {\r\n preset: preset as string,\r\n };\r\n }\r\n }\r\n\r\n // 6. Frontend configuration (if project has frontend framework)\r\n if (hasFrontend && project.frontendFramework) {\r\n const archSpinner = p.spinner();\r\n archSpinner.start(\"Loading frontend templates...\");\r\n\r\n // Use new template registry API\r\n const templateResult = await apiClient.getTemplates({\r\n category: \"frontend\",\r\n framework: project.frontendFramework,\r\n });\r\n archSpinner.stop(\"Templates loaded\");\r\n\r\n if (templateResult.templates.length > 0) {\r\n const preset = await p.select({\r\n message: \"Frontend template\",\r\n options: templateResult.templates.map((tmpl) => ({\r\n value: tmpl.id,\r\n label: tmpl.name,\r\n hint: tmpl.description || `${tmpl.tier} tier`,\r\n })),\r\n });\r\n\r\n if (p.isCancel(preset)) {\r\n p.cancel(\"Operation cancelled.\");\r\n process.exit(0);\r\n }\r\n\r\n // Fetch full template to get architectureStyle recommendation\r\n const fullTemplate = await apiClient.getTemplate(preset as string);\r\n selectedFrontendTemplate = fullTemplate;\r\n\r\n config.frontend = {\r\n preset: preset as string,\r\n };\r\n }\r\n }\r\n\r\n // 7. Architecture style\r\n // Always ask user, but use template recommendation as default\r\n const templateArchStyle =\r\n selectedBackendTemplate?.architectureStyle ||\r\n selectedFrontendTemplate?.architectureStyle;\r\n\r\n const recommendedStyle = templateArchStyle || \"flat\";\r\n\r\n const architectureStyle = await p.select({\r\n message: \"How would you like to organize your code?\",\r\n options: [\r\n {\r\n value: \"bounded-contexts\",\r\n label:\r\n recommendedStyle === \"bounded-contexts\"\r\n ? \"Bounded Contexts (Recommended)\"\r\n : \"Bounded Contexts\",\r\n hint: \"Each module has its own Domain, Application, Infrastructure\",\r\n },\r\n {\r\n value: \"flat\",\r\n label:\r\n recommendedStyle === \"flat\"\r\n ? \"Flat Structure (Recommended)\"\r\n : \"Flat Structure\",\r\n hint: \"Single Domain, Application, Infrastructure for the entire project\",\r\n },\r\n ],\r\n initialValue: recommendedStyle,\r\n });\r\n\r\n if (p.isCancel(architectureStyle)) {\r\n p.cancel(\"Operation cancelled.\");\r\n process.exit(0);\r\n }\r\n\r\n config.architectureStyle = architectureStyle as \"bounded-contexts\" | \"flat\";\r\n\r\n // 8. Code style options\r\n const codeStyleOptions = await p.multiselect({\r\n message: \"Code style options\",\r\n options: [\r\n { value: \"validations\", label: \"Include validations (Recommended)\", hint: \"Add validation rules\" },\r\n { value: \"comments\", label: \"Include comments (Recommended)\", hint: \"Add code documentation\" },\r\n { value: \"logging\", label: \"Include logging (Recommended)\", hint: \"Add log statements\" },\r\n { value: \"testing\", label: \"Include tests (Recommended)\", hint: \"Generate test files\" },\r\n ],\r\n initialValues: [\"validations\", \"comments\", \"logging\", \"testing\"],\r\n });\r\n\r\n if (p.isCancel(codeStyleOptions)) {\r\n p.cancel(\"Operation cancelled.\");\r\n process.exit(0);\r\n }\r\n\r\n const selectedStyles = codeStyleOptions as string[];\r\n config.codeStyle = {\r\n includeValidations: selectedStyles.includes(\"validations\"),\r\n includeComments: selectedStyles.includes(\"comments\"),\r\n includeLogging: selectedStyles.includes(\"logging\"),\r\n includeTesting: selectedStyles.includes(\"testing\"),\r\n };\r\n\r\n // 9. Use default output directory (user can edit .aerocodingrc.json if needed)\r\n config.output = \"./.aerocoding\";\r\n\r\n // 10. Configuration Summary\r\n p.log.step(chalk.bold(\"Configuration Summary:\"));\r\n if (config.backend) {\r\n p.log.info(` Backend: ${config.backend.preset}`);\r\n }\r\n if (config.frontend) {\r\n p.log.info(` Frontend: ${config.frontend.preset}`);\r\n }\r\n p.log.info(\r\n ` Architecture: ${\r\n config.architectureStyle === \"bounded-contexts\"\r\n ? \"Bounded Contexts\"\r\n : \"Flat Structure\"\r\n }`\r\n );\r\n p.log.info(` Output: ${config.output}`);\r\n\r\n // 11. Save config\r\n await saveConfig(config);\r\n\r\n p.outro(\r\n chalk.green(\"Config saved to .aerocodingrc.json\") +\r\n \"\\n\\n\" +\r\n chalk.gray(\" Run \") +\r\n chalk.cyan(\"aerocoding generate\") +\r\n chalk.gray(\" to generate code!\")\r\n );\r\n } catch (error: any) {\r\n if (error.response?.status === 401) {\r\n await handleUnauthorized(tokenManager);\r\n } else if (error.response?.data?.message) {\r\n p.cancel(error.response.data.message);\r\n } else {\r\n p.cancel(error.message || \"An unexpected error occurred\");\r\n }\r\n process.exit(1);\r\n }\r\n}\r\n","import chalk from \"chalk\";\r\n\r\ninterface PullOptions {\r\n project?: string;\r\n}\r\n\r\n/**\r\n * Pull Command (Stub)\r\n *\r\n * TODO: Pull schema from cloud\r\n * - Download project schema\r\n * - Save to .aerocoding/schema.json\r\n */\r\nexport async function pullCommand(options: PullOptions) {\r\n console.log(chalk.yellow(\"Command not yet implemented\"));\r\n if (options.project) {\r\n console.log(chalk.gray(` Requested project: ${options.project}`));\r\n }\r\n console.log(chalk.gray(\" Coming soon in v0.2.0\\n\"));\r\n}\r\n","import chalk from \"chalk\";\r\n\r\n/**\r\n * Status Command (Stub)\r\n *\r\n * TODO: Show local schema status\r\n * - Show current project\r\n * - Show schema stats\r\n * - Show sync status\r\n */\r\nexport async function statusCommand() {\r\n console.log(chalk.yellow(\"Command not yet implemented\"));\r\n console.log(chalk.gray(\" Coming soon in v0.2.0\\n\"));\r\n}\r\n"],"mappings":"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","names":["chalk","spinner","axios","API_URL","chalk","chalk","chalk","chalk","chalk","chalk","chalk","ora","chalk","chalk","fs","path","path","fs","chalk","spinner","ora","p","chalk","chalk","spinner","chalk","chalk"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aerocoding",
3
- "version": "0.1.21",
3
+ "version": "0.1.23",
4
4
  "description": "AeroCoding CLI - Generate production-ready code from UML diagrams",
5
5
  "author": "AeroCoding Team",
6
6
  "license": "MIT",