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 +219 -190
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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.
|
|
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
|
-
|
|
845
|
-
|
|
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 (
|
|
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
|
|
1130
|
+
import * as p2 from "@clack/prompts";
|
|
1049
1131
|
import chalk9 from "chalk";
|
|
1050
1132
|
async function initCommand(options) {
|
|
1051
|
-
|
|
1133
|
+
p2.intro(chalk9.bgCyan.black(" AeroCoding CLI "));
|
|
1052
1134
|
if (!options.force && await configExists()) {
|
|
1053
|
-
const overwrite = await
|
|
1135
|
+
const overwrite = await p2.confirm({
|
|
1054
1136
|
message: "Config file already exists. Overwrite?",
|
|
1055
1137
|
initialValue: false
|
|
1056
1138
|
});
|
|
1057
|
-
if (
|
|
1058
|
-
|
|
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
|
-
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
1163
|
+
p2.log.info(`Organization: ${organizations[0].name}`);
|
|
1082
1164
|
} else {
|
|
1083
|
-
const selectedOrg = await
|
|
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 (
|
|
1092
|
-
|
|
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 =
|
|
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
|
-
|
|
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
|
|
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 (
|
|
1116
|
-
|
|
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 =
|
|
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
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
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
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
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
|
-
|
|
1164
|
-
|
|
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
|
|
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 (
|
|
1181
|
-
|
|
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
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
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 (
|
|
1212
|
-
const archSpinner =
|
|
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
|
|
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 (
|
|
1229
|
-
|
|
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
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
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
|
|
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:
|
|
1305
|
+
initialValue: recommendedStyle
|
|
1274
1306
|
});
|
|
1275
|
-
if (
|
|
1276
|
-
|
|
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
|
|
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: "
|
|
1286
|
-
{ value: "
|
|
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", "
|
|
1320
|
+
initialValues: ["validations", "comments", "logging", "testing"]
|
|
1290
1321
|
});
|
|
1291
|
-
if (
|
|
1292
|
-
|
|
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
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1353
|
+
p2.cancel(error.response.data.message);
|
|
1325
1354
|
} else {
|
|
1326
|
-
|
|
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.
|
|
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":";;;AAEA,SAAS,eAAe;;;ACFxB,OAAOA,YAAW;;;ACAlB,OAAO,WAAW;AAClB,OAAO,WAAW;AAClB,OAAO,SAAS;AAChB,OAAO,UAAU;AAEjB,IAAM,UAAU,QAAQ,IAAI,WAAW;AACvC,IAAM,gBAAgB,KAAK,KAAK;AAyBzB,IAAM,aAAN,MAAiB;AAAA;AAAA;AAAA;AAAA,EAItB,MAAM,eAAuC;AAE3C,UAAM,aAAa,MAAM,KAAK,kBAAkB;AAGhD,SAAK,gBAAgB,UAAU;AAC/B,UAAM,KAAK,YAAY,WAAW,gBAAgB;AAGlD,UAAM,SAAS,MAAM,KAAK,aAAa,UAAU;AAEjD,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,oBAAiD;AAC7D,QAAI;AACF,YAAM,WAAW,MAAM,MAAM,KAAK,GAAG,OAAO,yBAAyB;AAAA,QACnE,WAAW;AAAA,QACX,OAAO;AAAA,MACT,CAAC;AAED,aAAO,SAAS;AAAA,IAClB,SAAS,OAAY;AACnB,cAAQ,MAAM,MAAM,IAAI,yCAAyC,CAAC;AAClE,UAAI,MAAM,UAAU;AAClB,gBAAQ;AAAA,UACN,MAAM,IAAI,UAAU,MAAM,SAAS,KAAK,iBAAiB,EAAE;AAAA,QAC7D;AAAA,MACF;AACA,YAAM,IAAI,MAAM,yCAAyC;AAAA,IAC3D;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,gBAAgB,MAAgC;AACtD,YAAQ,IAAI,IAAI;AAChB,YAAQ,IAAI,MAAM,KAAK,SAAI,OAAO,EAAE,CAAC,CAAC;AACtC,YAAQ,IAAI,MAAM,KAAK,MAAM,sCAAsC,CAAC;AACpE,YAAQ,IAAI,MAAM,KAAK,SAAI,OAAO,EAAE,CAAC,CAAC;AACtC,YAAQ,IAAI,EAAE;AACd,YAAQ,IAAI,MAAM,MAAM,qCAAqC,CAAC;AAC9D,YAAQ,IAAI,MAAM,KAAK,KAAK,QAAQ,KAAK,gBAAgB,EAAE,CAAC;AAC5D,YAAQ,IAAI,EAAE;AACd,YAAQ,IAAI,MAAM,MAAM,uBAAuB,CAAC;AAChD,YAAQ,IAAI,MAAM,MAAM,KAAK,QAAQ,KAAK,SAAS,EAAE,CAAC;AACtD,YAAQ,IAAI,EAAE;AACd,YAAQ;AAAA,MACN,MAAM,KAAK,qBAAqB,KAAK,aAAa,EAAE,UAAU;AAAA,IAChE;AACA,YAAQ,IAAI,MAAM,KAAK,SAAI,OAAO,EAAE,CAAC,CAAC;AACtC,YAAQ,IAAI,EAAE;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,YAAY,KAA4B;AACpD,QAAI;AACF,YAAM,KAAK,GAAG;AACd,cAAQ,IAAI,MAAM,KAAK,sBAAsB,CAAC;AAAA,IAChD,QAAQ;AACN,cAAQ,IAAI,MAAM,OAAO,wCAAwC,CAAC;AAClE,cAAQ,IAAI,MAAM,KAAK,kCAAkC,CAAC;AAAA,IAC5D;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,aAAa,MAAkD;AAC3E,UAAMC,WAAU,IAAI;AAAA,MAClB,MAAM;AAAA,MACN,OAAO;AAAA,IACT,CAAC,EAAE,MAAM;AAET,UAAM,YAAY,KAAK,IAAI;AAC3B,QAAI,kBAAkB,KAAK,WAAW;AAEtC,WAAO,MAAM;AAEX,UAAI,KAAK,IAAI,IAAI,YAAY,eAAe;AAC1C,QAAAA,SAAQ,KAAK,MAAM,IAAI,uBAAuB,CAAC;AAC/C,cAAM,IAAI,MAAM,gCAAgC;AAAA,MAClD;AAEA,UAAI;AACF,cAAM,WAAW,MAAM,MAAM,KAAK,GAAG,OAAO,qBAAqB;AAAA,UAC/D,aAAa,KAAK;AAAA,UAClB,WAAW;AAAA,QACb,CAAC;AAED,QAAAA,SAAQ,QAAQ,MAAM,MAAM,6BAA6B,CAAC;AAC1D,eAAO,SAAS;AAAA,MAClB,SAAS,OAAY;AACnB,cAAM,YAAY,MAAM,UAAU,MAAM;AACxC,cAAM,mBAAmB,MAAM,UAAU,MAAM;AAE/C,YAAI,cAAc,yBAAyB;AAEzC,gBAAM,KAAK,MAAM,eAAe;AAChC;AAAA,QACF;AAEA,YAAI,cAAc,aAAa;AAE7B,6BAAmB;AACnB,UAAAA,SAAQ,OAAO;AACf,gBAAM,KAAK,MAAM,eAAe;AAChC;AAAA,QACF;AAEA,YAAI,cAAc,iBAAiB;AACjC,UAAAA,SAAQ,KAAK,MAAM,IAAI,4BAA4B,CAAC;AACpD,gBAAM,IAAI,MAAM,wCAAwC;AAAA,QAC1D;AAEA,YAAI,cAAc,iBAAiB;AACjC,UAAAA,SAAQ,KAAK,MAAM,IAAI,sBAAsB,CAAC;AAC9C,gBAAM,IAAI,MAAM,sCAAsC;AAAA,QACxD;AAGA,QAAAA,SAAQ,KAAK,MAAM,IAAI,sBAAsB,CAAC;AAC9C,gBAAQ;AAAA,UACN,MAAM,IAAI,UAAU,oBAAoB,eAAe,EAAE;AAAA,QAC3D;AACA,cAAM,IAAI,MAAM,oBAAoB,eAAe;AAAA,MACrD;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,MAAM,IAA2B;AACvC,WAAO,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,EAAE,CAAC;AAAA,EACzD;AACF;;;ACjLA,SAAS,aAAa;AACtB,SAAS,oBAAoC;AAE7C,IAAM,eAAe;AAGrB,IAAM,eAAe;AACrB,IAAM,oBAAoB;AAY1B,SAAS,YAAY,SAAiB,SAAgC;AACpE,MAAI;AACF,UAAM,QAAQ,IAAI,MAAM,SAAS,OAAO;AACxC,WAAO,MAAM,YAAY;AAAA,EAC3B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,YAAY,SAAiB,SAAiB,UAAwB;AAC7E,QAAM,QAAQ,IAAI,MAAM,SAAS,OAAO;AACxC,QAAM,YAAY,QAAQ;AAC5B;AAEA,SAAS,eAAe,SAAiB,SAAuB;AAC9D,MAAI;AACF,UAAM,QAAQ,IAAI,MAAM,SAAS,OAAO;AACxC,UAAM,eAAe;AAAA,EACvB,QAAQ;AAAA,EAER;AACF;AAQO,IAAM,eAAN,MAAmB;AAAA,EAChB;AAAA,EAER,cAAc;AACZ,SAAK,WAAW,aAAa,cAAc,mBAAmB;AAAA,MAC5D,MAAM;AAAA,QACJ,kBAAkB;AAAA,QAClB,gBAAgB;AAAA,MAClB;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,iBAAyC;AAC7C,QAAI;AACF,UAAI,cAAc,YAAY,cAAc,cAAc;AAE1D,UAAI,CAAC,aAAa;AAChB,eAAO;AAAA,MACT;AAGA,UAAI,KAAK,eAAe,WAAW,GAAG;AACpC,sBAAc,MAAM,KAAK,cAAc;AAAA,MACzC;AAEA,aAAO;AAAA,IACT,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,gBAAwC;AACpD,QAAI;AACF,YAAM,eAAe,YAAY,cAAc,eAAe;AAE9D,UAAI,CAAC,cAAc;AACjB,cAAM,IAAI,MAAM,4BAA4B;AAAA,MAC9C;AAEA,YAAM,EAAE,MAAM,MAAM,IAAI,MAAM,KAAK,SAAS,KAAK,eAAe;AAAA,QAC9D,eAAe;AAAA,MACjB,CAAC;AAED,UAAI,SAAS,CAAC,KAAK,SAAS;AAC1B,cAAM,IAAI,MAAM,2BAA2B;AAAA,MAC7C;AAGA,kBAAY,cAAc,gBAAgB,KAAK,QAAQ,YAAY;AACnE,kBAAY,cAAc,iBAAiB,KAAK,QAAQ,aAAa;AAErE,aAAO,KAAK,QAAQ;AAAA,IACtB,QAAQ;AACN,YAAM,KAAK,OAAO;AAClB,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,eAAe,OAAwB;AAC7C,QAAI;AACF,YAAM,UAAU,KAAK;AAAA,QACnB,OAAO,KAAK,MAAM,MAAM,GAAG,EAAE,CAAC,GAAI,QAAQ,EAAE,SAAS;AAAA,MACvD;AACA,YAAM,YAAY,QAAQ,MAAM;AAChC,YAAM,MAAM,KAAK,IAAI;AAGrB,aAAO,YAAY,MAAM,IAAI,KAAK;AAAA,IACpC,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,WACJ,aACA,cACA,MACe;AACf,gBAAY,cAAc,gBAAgB,WAAW;AACrD,gBAAY,cAAc,iBAAiB,YAAY;AACvD,gBAAY,cAAc,iBAAiB,KAAK,UAAU,IAAI,CAAC;AAAA,EACjE;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,kBAAgD;AACpD,QAAI;AACF,YAAM,WAAW,YAAY,cAAc,eAAe;AAC1D,aAAO,WAAW,KAAK,MAAM,QAAQ,IAAI;AAAA,IAC3C,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,SAAwB;AAC5B,QAAI;AACF,qBAAe,cAAc,cAAc;AAC3C,qBAAe,cAAc,eAAe;AAC5C,qBAAe,cAAc,eAAe;AAAA,IAC9C,SAAS,OAAO;AAAA,IAEhB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,kBAAoC;AACxC,UAAM,QAAQ,MAAM,KAAK,eAAe;AACxC,WAAO,UAAU;AAAA,EACnB;AACF;;;AC/KA,OAAOC,YAA8B;AAGrC,IAAMC,WAAU,QAAQ,IAAI,WAAW;AA2LhC,IAAM,YAAN,MAAgB;AAAA,EACb;AAAA,EAER,YACE,aACA,SAGA;AACA,SAAK,SAASD,OAAM,OAAO;AAAA,MACzB,SAASC;AAAA,MACT,SAAS;AAAA,QACP,eAAe,UAAU,WAAW;AAAA,QACpC,gBAAgB;AAAA,QAChB,oBAAoB;AAAA;AAAA,MACtB;AAAA,MACA,SAAS;AAAA;AAAA,IACX,CAAC;AAED,SAAK,OAAO,aAAa,SAAS;AAAA,MAChC,CAAC,aAAa;AAAA,MACd,OAAO,UAAU;AACf,YAAI,OAAO,UAAU,WAAW,KAAK;AACnC,gBAAM,SAAS,iBAAiB;AAAA,QAClC;AAEA,eAAO,QAAQ,OAAO,KAAK;AAAA,MAC7B;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,iBAAgC;AACpC,UAAM,WAAW,MAAM,KAAK,OAAO,IAAI,cAAc;AACrD,WAAO,SAAS;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,oBAA6C;AACjD,UAAM,WAAW,MAAM,KAAK,OAAO,IAAI,oBAAoB;AAC3D,WAAO,SAAS;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,aAAa,gBAA6C;AAC9D,UAAM,WAAW,MAAM,KAAK,OAAO,IAAI,iBAAiB;AAAA,MACtD,QAAQ,EAAE,eAAe;AAAA,IAC3B,CAAC;AACD,WAAO,SAAS;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,WAAW,WAAqC;AACpD,UAAM,WAAW,MAAM,KAAK,OAAO,IAAI,iBAAiB,SAAS,EAAE;AACnE,WAAO,SAAS;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,aAAa,SAAmD;AACpE,UAAM,WAAW,MAAM,KAAK,OAAO,KAAK,iBAAiB,OAAO;AAChE,WAAO,SAAS,KAAK;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,eAAe,gBAA8C;AACjE,UAAM,WAAW,MAAM,KAAK,OAAO,IAAI,sBAAsB;AAAA,MAC3D,QAAQ,EAAE,eAAe;AAAA,IAC3B,CAAC;AACD,WAAO,SAAS;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,iBAAiB,WAA4C;AACjE,UAAM,WAAW,MAAM,KAAK,OAAO,IAAI,sBAAsB;AAAA,MAC3D,QAAQ,EAAE,UAAU;AAAA,IACtB,CAAC;AACD,WAAO,SAAS;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,mBAAmB,SAAmD;AAC1E,UAAM,WAAW,MAAM,KAAK,OAAO,KAAK,0BAA0B,OAAO;AACzE,WAAO,SAAS,KAAK;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,aAAa,SAAyB,CAAC,GAAkC;AAC7E,UAAM,SAAS,IAAI,gBAAgB;AACnC,QAAI,OAAO,SAAU,QAAO,IAAI,YAAY,OAAO,QAAQ;AAC3D,QAAI,OAAO,SAAU,QAAO,IAAI,YAAY,OAAO,QAAQ;AAC3D,QAAI,OAAO,UAAW,QAAO,IAAI,aAAa,OAAO,SAAS;AAC9D,QAAI,OAAO,KAAM,QAAO,IAAI,QAAQ,OAAO,IAAI;AAC/C,QAAI,OAAO,MAAM,OAAQ,QAAO,IAAI,QAAQ,OAAO,KAAK,KAAK,GAAG,CAAC;AAEjE,UAAM,WAAW,MAAM,KAAK,OAAO,IAAI,kBAAkB,OAAO,SAAS,CAAC,EAAE;AAC5E,WAAO,SAAS;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,YAAY,IAAmC;AACnD,UAAM,WAAW,MAAM,KAAK,OAAO,IAAI,kBAAkB,EAAE,YAAY;AACvE,WAAO,SAAS,KAAK;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,0BAA0D;AAC9D,UAAM,WAAW,MAAM,KAAK,OAAO,IAAI,6BAA6B;AACpE,WAAO,SAAS,KAAK;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,uBAAuB,YAAiD;AAC5E,UAAM,WAAW,MAAM,KAAK,OAAO,IAAI,kBAAkB,UAAU,kBAAkB;AACrF,WAAO,SAAS,KAAK,cAAc,CAAC;AAAA,EACtC;AACF;;;AC1UO,SAAS,8BACd,aACA,cACW;AACX,SAAO,IAAI,UAAU,aAAa;AAAA,IAChC,gBAAgB,YAAY;AAC1B,YAAM,aAAa,OAAO;AAAA,IAC5B;AAAA,EACF,CAAC;AACH;;;ACZA,OAAOC,YAAW;AAGlB,eAAsB,mBACpB,cACgB;AAChB,QAAM,aAAa,OAAO;AAE1B,UAAQ;AAAA,IACNA,OAAM;AAAA,MACJ;AAAA,IACF;AAAA,EACF;AACA,UAAQ,MAAMA,OAAM,KAAK,2CAA2C,CAAC;AAErE,UAAQ,KAAK,CAAC;AAChB;;;ALJA,eAAsB,eAAe;AACnC,UAAQ,IAAIC,OAAM,KAAK,0BAA0B,CAAC;AAElD,QAAM,eAAe,IAAI,aAAa;AAGtC,QAAM,gBAAgB,MAAM,aAAa,eAAe;AACxD,MAAI,eAAe;AACjB,UAAM,WAAW,MAAM,aAAa,gBAAgB;AACpD,YAAQ;AAAA,MACNA,OAAM,OAAO,uBAAuB;AAAA,MACpCA,OAAM,MAAM,UAAU,SAAS,SAAS;AAAA,IAC1C;AACA,YAAQ;AAAA,MACNA,OAAM;AAAA,QACJ;AAAA,MACF;AAAA,IACF;AACA;AAAA,EACF;AAEA,MAAI;AAEF,UAAM,aAAa,IAAI,WAAW;AAClC,UAAM,SAAS,MAAM,WAAW,aAAa;AAG7C,UAAM,YAAY;AAAA,MAChB,OAAO;AAAA,MACP;AAAA,IACF;AACA,QAAI;AACJ,QAAI;AACF,aAAO,MAAM,UAAU,eAAe;AAAA,IACxC,SAAS,OAAY;AACnB,UAAI,MAAM,UAAU,WAAW,KAAK;AAClC,cAAM,mBAAmB,YAAY;AAAA,MACvC;AACA,YAAM;AAAA,IACR;AAGA,UAAM,aAAa,WAAW,OAAO,cAAc,OAAO,eAAe;AAAA,MACvE,IAAI,KAAK;AAAA,MACT,OAAO,KAAK;AAAA,MACZ,MAAM,KAAK,QAAQ;AAAA,MACnB,MAAM,KAAK;AAAA,IACb,CAAC;AAED,YAAQ,IAAI,EAAE;AACd,YAAQ;AAAA,MACNA,OAAM,MAAM,4BAA4B;AAAA,MACxCA,OAAM,MAAM,KAAK,KAAK;AAAA,IACxB;AACA,YAAQ,IAAIA,OAAM,KAAK,uCAAuC,CAAC;AAAA,EACjE,SAAS,OAAY;AACnB,YAAQ;AAAA,MACNA,OAAM,IAAI,iBAAiB;AAAA,MAC3B,MAAM,WAAW;AAAA,IACnB;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;;;AM1EA,OAAOC,YAAW;AAQlB,eAAsB,gBAAgB;AACpC,QAAM,eAAe,IAAI,aAAa;AAEtC,QAAM,WAAW,MAAM,aAAa,gBAAgB;AACpD,MAAI,CAAC,UAAU;AACb,YAAQ,IAAIC,OAAM,OAAO,eAAe,CAAC;AACzC;AAAA,EACF;AAEA,QAAM,QAAQ,SAAS;AAEvB,QAAM,aAAa,OAAO;AAE1B,UAAQ,IAAIA,OAAM,MAAM,yBAAyB,CAAC;AAClD,UAAQ,IAAIA,OAAM,KAAK,6BAA6B,KAAK;AAAA,CAAI,CAAC;AAChE;;;ACvBA,OAAOC,YAAW;AAUlB,eAAsB,gBAAgB;AACpC,QAAM,eAAe,IAAI,aAAa;AACtC,QAAM,QAAQ,MAAM,aAAa,eAAe;AAEhD,MAAI,CAAC,OAAO;AACV,YAAQ,IAAIC,OAAM,IAAI,eAAe,CAAC;AACtC,YAAQ,IAAIA,OAAM,KAAK,4CAA4C,CAAC;AACpE;AAAA,EACF;AAEA,MAAI;AACF,UAAM,YAAY,8BAA8B,OAAO,YAAY;AACnE,UAAM,OAAO,MAAM,UAAU,eAAe;AAE5C,YAAQ,IAAI,EAAE;AACd,YAAQ,IAAIA,OAAM,MAAM,eAAe,GAAGA,OAAM,KAAK,KAAK,KAAK,KAAK,CAAC;AACrE,QAAI,KAAK,MAAM;AACb,cAAQ,IAAIA,OAAM,KAAK,SAAS,GAAG,KAAK,IAAI;AAAA,IAC9C;AACA,YAAQ,IAAI,EAAE;AAAA,EAChB,SAAS,OAAY;AACnB,YAAQ,MAAMA,OAAM,IAAI,yBAAyB,CAAC;AAClD,QAAI,MAAM,UAAU,WAAW,KAAK;AAClC,YAAM,mBAAmB,YAAY;AAAA,IACvC;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;;;ACrCA,OAAOC,YAAW;AAClB,OAAOC,UAAS;;;ACDhB,OAAO,QAAQ;AACf,OAAO,UAAU;AACjB,OAAOC,YAAW;AAmBlB,SAAS,WAAW,WAAmB,UAA2B;AAEhE,QAAM,iBAAiB,KAAK,QAAQ,SAAS;AAC7C,QAAM,eAAe,KAAK,QAAQ,WAAW,QAAQ;AAKrD,SACE,aAAa,WAAW,iBAAiB,KAAK,GAAG,KACjD,iBAAiB;AAErB;AAOO,SAAS,oBAAoB,UAA0B;AAC5D,QAAM,YAAY,SAAS,YAAY;AAGvC,MAAI,UAAU,SAAS,eAAe,EAAG,QAAO;AAChD,MAAI,UAAU,SAAS,YAAY,KAAK,UAAU,SAAS,aAAa;AACtE,WAAO;AACT,MAAI,UAAU,SAAS,QAAQ,KAAK,UAAU,SAAS,OAAO,EAAG,QAAO;AACxE,MAAI,UAAU,SAAS,YAAY,EAAG,QAAO;AAC7C,MACE,UAAU,SAAS,gBAAgB,KACnC,UAAU,SAAS,oBAAoB;AAEvC,WAAO;AACT,MACE,UAAU,SAAS,kBAAkB,KACrC,UAAU,SAAS,UAAU;AAE7B,WAAO;AACT,MACE,UAAU,SAAS,cAAc,KACjC,UAAU,SAAS,cAAc;AAEjC,WAAO;AACT,MAAI,UAAU,SAAS,WAAW,EAAG,QAAO;AAC5C,MAAI,UAAU,SAAS,cAAc,EAAG,QAAO;AAC/C,MAAI,UAAU,SAAS,cAAc,EAAG,QAAO;AAC/C,MAAI,UAAU,SAAS,OAAO,KAAK,UAAU,SAAS,gBAAgB;AACpE,WAAO;AACT,MAAI,UAAU,SAAS,OAAO,KAAK,UAAU,SAAS,MAAM;AAC1D,WAAO;AACT,MACE,UAAU,SAAS,SAAS,KAC5B,UAAU,SAAS,QAAQ,KAC3B,UAAU,SAAS,QAAQ;AAE3B,WAAO;AACT,MAAI,UAAU,SAAS,YAAY,EAAG,QAAO;AAE7C,SAAO;AACT;AAOO,SAAS,oBAAoB,WAAqC;AACvE,QAAM,aAAa,oBAAI,IAAsB;AAE7C,aAAW,YAAY,WAAW;AAChC,UAAM,WAAW,oBAAoB,QAAQ;AAC7C,UAAM,WAAW,WAAW,IAAI,QAAQ,KAAK,CAAC;AAC9C,aAAS,KAAK,QAAQ;AACtB,eAAW,IAAI,UAAU,QAAQ;AAAA,EACnC;AAEA,SAAO,MAAM,KAAK,WAAW,QAAQ,CAAC,EACnC,IAAI,CAAC,CAAC,MAAM,QAAQ,OAAO,EAAE,MAAM,OAAO,SAAS,QAAQ,OAAO,SAAS,EAAE,EAC7E,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;AACrC;AAMA,SAAS,gBAAgB,OAAwC;AAC/D,SAAO,oBAAoB,MAAM,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC;AACrD;AAKA,SAAS,0BAA0B,OAA8B;AAC/D,QAAM,aAAa,gBAAgB,KAAK;AAExC,UAAQ,IAAI,EAAE;AACd,UAAQ,IAAIA,OAAM,KAAK,mBAAmB,CAAC;AAC3C,UAAQ,IAAIA,OAAM,KAAK,0MAAqC,CAAC;AAG7D,QAAM,gBAAgB,KAAK,IAAI,GAAG,WAAW,IAAI,CAAC,MAAM,EAAE,KAAK,MAAM,CAAC;AAEtE,aAAW,YAAY,YAAY;AACjC,UAAM,UAAU,IAAI,OAAO,gBAAgB,SAAS,KAAK,SAAS,CAAC;AACnE,UAAM,WAAW,SAAS,MAAM,SAAS,EAAE,SAAS,GAAG,GAAG;AAC1D,YAAQ;AAAA,MACNA,OAAM,KAAK,KAAK,SAAS,IAAI,GAAG,OAAO,EAAE;AAAA,MACzCA,OAAM,KAAK,GAAG,QAAQ,QAAQ;AAAA,IAChC;AAAA,EACF;AAEA,UAAQ,IAAIA,OAAM,KAAK,0MAAqC,CAAC;AAC7D,QAAM,eAAe,IAAI,OAAO,gBAAgB,IAAI,CAAC;AACrD,QAAM,WAAW,MAAM,OAAO,SAAS,EAAE,SAAS,GAAG,GAAG;AACxD,UAAQ;AAAA,IACNA,OAAM,MAAM,UAAU,YAAY,EAAE;AAAA,IACpCA,OAAM,KAAK,KAAK,GAAG,QAAQ,QAAQ;AAAA,EACrC;AACF;AAQA,eAAsB,oBACpB,OACA,WACA,UAAmB,OACJ;AAEf,QAAM,eAAgC,CAAC;AAEvC,aAAW,QAAQ,OAAO;AAExB,QAAI,CAAC,WAAW,WAAW,KAAK,IAAI,GAAG;AACrC,cAAQ,MAAMA,OAAM,IAAI,2BAA2B,KAAK,IAAI,EAAE,CAAC;AAC/D,cAAQ;AAAA,QACNA,OAAM;AAAA,UACJ;AAAA,QACF;AAAA,MACF;AACA;AAAA,IACF;AAEA,UAAM,WAAW,KAAK,QAAQ,WAAW,KAAK,IAAI;AAClD,UAAM,MAAM,KAAK,QAAQ,QAAQ;AAEjC,QAAI;AAEF,YAAM,GAAG,MAAM,KAAK,EAAE,WAAW,KAAK,CAAC;AAGvC,YAAM,GAAG,UAAU,UAAU,KAAK,SAAS,OAAO;AAGlD,UAAI,SAAS;AACX,gBAAQ,IAAIA,OAAM,KAAK,KAAK,KAAK,IAAI,EAAE,CAAC;AAAA,MAC1C;AAEA,mBAAa,KAAK,IAAI;AAAA,IACxB,SAAS,OAAY;AACnB,cAAQ,MAAMA,OAAM,IAAI,qBAAqB,KAAK,IAAI,EAAE,CAAC;AACzD,cAAQ,MAAMA,OAAM,KAAK,OAAO,MAAM,OAAO,EAAE,CAAC;AAAA,IAClD;AAAA,EACF;AAGA,MAAI,CAAC,WAAW,aAAa,SAAS,GAAG;AACvC,8BAA0B,YAAY;AAAA,EACxC;AACF;;;ACjMA,OAAO,cAAc;AACrB,OAAOC,YAAW;AAMX,SAAS,cAAc,SAAmC;AAC/D,SAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,UAAM,KAAK,SAAS,gBAAgB;AAAA,MAClC,OAAO,QAAQ;AAAA,MACf,QAAQ,QAAQ;AAAA,IAClB,CAAC;AAED,OAAG,SAASA,OAAM,OAAO,GAAG,OAAO,SAAS,GAAG,CAAC,WAAW;AACzD,SAAG,MAAM;AACT,YAAM,aAAa,OAAO,KAAK,EAAE,YAAY;AAE7C,cAAQ,eAAe,OAAO,eAAe,IAAI;AAAA,IACnD,CAAC;AAAA,EACH,CAAC;AACH;;;ACrBA,OAAOC,SAAQ;AACf,OAAOC,WAAU;;;ACDjB,SAAS,SAAS;AAEX,IAAM,eAAe,EAAE,OAAO;AAAA,EACnC,SAAS,EAAE,OAAO,EAAE,SAAS;AAAA,EAC7B,SAAS,EAAE,OAAO,EAAE,KAAK;AAAA,EACzB,QAAQ,EAAE,OAAO,EAAE,QAAQ,eAAe;AAAA;AAAA,EAG1C,mBAAmB,EAChB,KAAK,CAAC,oBAAoB,MAAM,CAAC,EACjC,SAAS,EACT,QAAQ,kBAAkB;AAAA,EAE7B,SAAS,EACN,OAAO;AAAA,IACN,QAAQ,EAAE,OAAO;AAAA,IACjB,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC;AAAA,EAC5B,CAAC,EACA,SAAS;AAAA,EAEZ,UAAU,EACP,OAAO;AAAA,IACN,QAAQ,EAAE,OAAO;AAAA,IACjB,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC;AAAA,EAC5B,CAAC,EACA,SAAS;AAAA,EAEZ,WAAW,EACR,OAAO;AAAA,IACN,oBAAoB,EAAE,QAAQ,EAAE,QAAQ,IAAI;AAAA,IAC5C,iBAAiB,EAAE,QAAQ,EAAE,QAAQ,IAAI;AAAA,IACzC,oBAAoB,EAAE,QAAQ,EAAE,QAAQ,IAAI;AAAA,IAC5C,gBAAgB,EAAE,QAAQ,EAAE,QAAQ,IAAI;AAAA,IACxC,gBAAgB,EAAE,QAAQ,EAAE,QAAQ,IAAI;AAAA,EAC1C,CAAC,EACA,SAAS;AAAA,EAEZ,WAAW,EACR,OAAO;AAAA,IACN,YAAY,EAAE,OAAO,EAAE,SAAS;AAAA,IAChC,SAAS,EAAE,OAAO,EAAE,SAAS;AAAA,EAC/B,CAAC,EACA,SAAS;AAAA,EAEZ,iBAAiB,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS;AAChD,CAAC;AAIM,IAAM,kBAAkB;;;AD7C/B,eAAsB,WACpB,MAAc,QAAQ,IAAI,GACQ;AAClC,QAAM,aAAaC,MAAK,KAAK,KAAK,eAAe;AAEjD,MAAI;AACF,UAAM,UAAU,MAAMC,IAAG,SAAS,YAAY,OAAO;AACrD,UAAM,SAAS,KAAK,MAAM,OAAO;AACjC,WAAO,aAAa,MAAM,MAAM;AAAA,EAClC,SAAS,OAAO;AACd,QAAK,MAAgC,SAAS,UAAU;AACtD,aAAO;AAAA,IACT;AACA,UAAM;AAAA,EACR;AACF;AAEA,eAAsB,WACpB,QACA,MAAc,QAAQ,IAAI,GACX;AACf,QAAM,aAAaD,MAAK,KAAK,KAAK,eAAe;AACjD,QAAM,UAAU,KAAK;AAAA,IACnB;AAAA,MACE,SAAS;AAAA,MACT,GAAG;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,QAAMC,IAAG,UAAU,YAAY,SAAS,OAAO;AACjD;AAEA,eAAsB,aAAa,MAAc,QAAQ,IAAI,GAAqB;AAChF,QAAM,aAAaD,MAAK,KAAK,KAAK,eAAe;AACjD,MAAI;AACF,UAAMC,IAAG,OAAO,UAAU;AAC1B,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;;;AH/BA,SAAS,sBAAsB,QAA+B;AAC5D,QAAM,cAAc,OAAO,YAAY;AAGvC,MAAI,YAAY,SAAS,OAAO,KAAK,YAAY,SAAS,QAAQ,GAAG;AACnE,WAAO;AAAA,EACT;AACA,MAAI,YAAY,SAAS,OAAO,MAAM,YAAY,SAAS,MAAM,KAAK,YAAY,SAAS,SAAS,IAAI;AACtG,WAAO;AAAA,EACT;AACA,MAAI,YAAY,SAAS,OAAO,KAAK,YAAY,SAAS,YAAY,GAAG;AACvE,WAAO;AAAA,EACT;AAGA,MAAI,YAAY,WAAW,aAAa,GAAG;AACzC,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAMA,SAAS,kBAAkB,QAA+B;AACxD,QAAM,cAAc,OAAO,YAAY;AAGvC,MAAI,YAAY,SAAS,QAAQ,KAAK,YAAY,SAAS,QAAQ,KAAK,YAAY,SAAS,QAAQ,GAAG;AACtG,WAAO;AAAA,EACT;AAGA,MAAI,YAAY,SAAS,MAAM,KAAK,YAAY,SAAS,SAAS,GAAG;AACnE,WAAO;AAAA,EACT;AAGA,MAAI,YAAY,SAAS,YAAY,KAAK,YAAY,SAAS,QAAQ,KAAK,YAAY,SAAS,OAAO,GAAG;AACzG,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAMA,SAAS,0BAA0B,QAAgD;AACjF,MAAI,CAAC,OAAQ,QAAO;AAGpB,MAAI,OAAO,SAAS,QAAQ;AAC1B,UAAM,aAAa,sBAAsB,OAAO,QAAQ,MAAM;AAC9D,QAAI,WAAY,QAAO;AAAA,EACzB;AAGA,MAAI,OAAO,UAAU,QAAQ;AAC3B,UAAM,aAAa,sBAAsB,OAAO,SAAS,MAAM;AAC/D,QAAI,WAAY,QAAO;AAAA,EACzB;AAEA,SAAO;AACT;AAMA,SAAS,uBAAuB,QAA2C;AACzE,MAAI,CAAC,OAAQ,QAAO,CAAC;AAErB,QAAM,UAAoB,CAAC;AAG3B,MAAI,OAAO,SAAS,QAAQ;AAC1B,UAAM,SAAS,kBAAkB,OAAO,QAAQ,MAAM;AACtD,QAAI,QAAQ;AACV,cAAQ,KAAK,MAAM;AAAA,IACrB;AAAA,EACF;AAGA,MAAI,OAAO,UAAU,QAAQ;AAC3B,UAAM,SAAS,kBAAkB,OAAO,SAAS,MAAM;AACvD,QAAI,QAAQ;AACV,cAAQ,KAAK,MAAM;AAAA,IACrB;AAAA,EACF;AAEA,SAAO;AACT;AAKA,SAAS,4BAA4B,QAA0D;AAC7F,QAAM,QAAiC;AAAA;AAAA,IAErC,aAAa;AAAA,IACb,iBAAiB;AAAA,IACjB,gBAAgB;AAAA,IAChB,oBAAoB;AAAA,IACpB,iBAAiB;AAAA,IACjB,mBAAmB;AAAA,EACrB;AAEA,MAAI,CAAC,OAAQ,QAAO;AAGpB,MAAI,OAAO,WAAW,uBAAuB,QAAW;AACtD,UAAM,oBAAoB,OAAO,UAAU;AAAA,EAC7C;AACA,MAAI,OAAO,WAAW,mBAAmB,QAAW;AAClD,UAAM,eAAe,OAAO,UAAU;AAAA,EACxC;AAEA,SAAO;AACT;AAiCA,eAAsB,gBAAgB,SAA0B;AAE9D,QAAM,eAAe,IAAI,aAAa;AACtC,QAAM,QAAQ,MAAM,aAAa,eAAe;AAEhD,MAAI,CAAC,OAAO;AACV,YAAQ,IAAIC,OAAM,IAAI,uBAAuB,CAAC;AAC9C,YAAQ,IAAIA,OAAM,KAAK,2CAA2C,CAAC;AACnE,YAAQ,KAAK,CAAC;AAAA,EAChB;AAGA,QAAM,SAAS,MAAM,WAAW;AAGhC,QAAM,YAAY,QAAQ,WAAW,QAAQ;AAE7C,MAAI,CAAC,WAAW;AACd,YAAQ,IAAIA,OAAM,IAAI,yBAAyB,CAAC;AAChD,YAAQ,IAAIA,OAAM,KAAK,iDAAiD,CAAC;AACzE,YAAQ,IAAIA,OAAM,KAAK,gDAAgD,CAAC;AACxE,YAAQ,KAAK,CAAC;AAAA,EAChB;AAGA,QAAM,aAAa,0BAA0B,MAAM;AACnD,QAAM,eAAe,aAAa,4BAA4B,MAAM,IAAI;AAGxE,QAAM,UAAU,CAAC,aAAc,QAAQ,WAAW,uBAAuB,MAAM,IAAK;AAGpF,QAAM,SAAS,QAAQ,UAAU,QAAQ,UAAU;AACnD,QAAM,gBAAgB,QAAQ,iBAAiB,QAAQ,SAAS;AAChE,QAAM,iBAAiB,QAAQ,kBAAkB,QAAQ,UAAU;AACnE,QAAM,gBAAgB,QAAQ,iBAAiB,QAAQ,SAAS;AAChE,QAAM,iBAAiB,QAAQ,kBAAkB,QAAQ,UAAU;AACnE,QAAM,gBAAgB,QAAQ,iBAAiB,QAAQ,WAAW;AAGlE,QAAM,qBAAqB,QAAQ,eAAe,QAAQ,WAAW,sBAAsB;AAC3F,QAAM,kBAAkB,QAAQ,YAAY,QAAQ,WAAW,mBAAmB;AAClF,QAAM,qBAAqB,QAAQ,eAAe,QAAQ,WAAW,sBAAsB;AAC3F,QAAM,iBAAiB,QAAQ,WAAW,QAAQ,WAAW,kBAAkB;AAC/E,QAAM,iBAAiB,QAAQ,WAAW,QAAQ,WAAW,kBAAkB;AAE/E,QAAM,YAAY,8BAA8B,OAAO,YAAY;AAEnE,MAAIC,WAAUC,KAAI,EAAE,MAAM,uBAAuB,OAAO,OAAO,CAAC,EAAE,MAAM;AAExE,MAAI;AAEF,UAAM,UAAU,MAAM,UAAU,WAAW,SAAS;AACpD,IAAAD,SAAQ,QAAQD,OAAM,KAAK,gBAAgB,CAAC;AAG5C,IAAAC,WAAUC,KAAI,EAAE,MAAM,uBAAuB,OAAO,OAAO,CAAC,EAAE,MAAM;AAEpE,UAAM,UAAU,MAAM,UAAU,eAAe,QAAQ,cAAc;AAIrE,UAAM,cAAc,QAAQ,sBAAsB;AAElD,QAAI,WAAuG;AAC3G,QAAI;AACF,UAAI,YAAY;AAEd,mBAAW,MAAM,UAAU,mBAAmB;AAAA,UAC5C;AAAA,UACA;AAAA,UACA,SAAS;AAAA,YACP;AAAA,YACA;AAAA,UACF;AAAA,QACF,CAAC;AAAA,MACH,WAAW,WAAW,QAAQ,SAAS,GAAG;AAExC,mBAAW,MAAM,UAAU,mBAAmB;AAAA,UAC5C;AAAA,UACA;AAAA,UACA,SAAS;AAAA,YACP,WAAW;AAAA,YACX;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,UACF;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF,QAAQ;AAAA,IAER;AAEA,IAAAD,SAAQ,QAAQD,OAAM,KAAK,kBAAkB,CAAC;AAG9C,QAAI,YAAY,SAAS,aAAa,GAAG;AACvC,cAAQ,IAAIA,OAAM,OAAO,+CAA0C,CAAC;AACpE,cAAQ,IAAIA,OAAM,KAAK,gFAAgF,CAAC;AACxG,cAAQ,KAAK,CAAC;AAAA,IAChB;AAGA,UAAM,mBAAmB,WAAW,QAAQ,aAAa,SAAS,mBAAmB;AAGrF,YAAQ,IAAI,EAAE;AACd,YAAQ,IAAIA,OAAM,KAAK,sBAAsB,CAAC;AAC9C,YAAQ,IAAIA,OAAM,KAAK,0MAAqC,CAAC;AAC7D,YAAQ,IAAIA,OAAM,KAAK,YAAY,GAAGA,OAAM,MAAM,QAAQ,IAAI,CAAC;AAC/D,QAAI,QAAQ;AACV,cAAQ,IAAIA,OAAM,KAAK,WAAW,GAAGA,OAAM,KAAK,oBAAoB,CAAC;AAAA,IACvE;AAEA,QAAI,YAAY;AACd,cAAQ,IAAIA,OAAM,KAAK,SAAS,GAAGA,OAAM,MAAM,mBAAmB,CAAC;AACnE,cAAQ,IAAIA,OAAM,KAAK,aAAa,GAAGA,OAAM,KAAK,UAAU,CAAC;AAAA,IAC/D,WAAW,WAAW,QAAQ,SAAS,GAAG;AACxC,cAAQ,IAAIA,OAAM,KAAK,SAAS,GAAGA,OAAM,OAAO,iBAAiB,CAAC;AAClE,cAAQ,IAAIA,OAAM,KAAK,YAAY,GAAGA,OAAM,KAAK,QAAQ,KAAK,IAAI,CAAC,CAAC;AAAA,IACtE,OAAO;AACL,cAAQ,IAAIA,OAAM,KAAK,SAAS,GAAGA,OAAM,KAAK,SAAS,CAAC;AAAA,IAC1D;AAEA,QAAI,eAAe;AACjB,cAAQ,IAAIA,OAAM,KAAK,mBAAmB,GAAGA,OAAM,KAAK,aAAa,CAAC;AAAA,IACxE;AACA,QAAI,gBAAgB;AAClB,cAAQ,IAAIA,OAAM,KAAK,oBAAoB,GAAGA,OAAM,KAAK,cAAc,CAAC;AAAA,IAC1E;AAGA,UAAM,YAAY,QAAQ,qBAAqB;AAC/C,YAAQ;AAAA,MACNA,OAAM,KAAK,iBAAiB;AAAA,MAC5B,cAAc,qBACVA,OAAM,KAAK,kBAAkB,IAC7BA,OAAM,OAAO,gBAAgB;AAAA,IACnC;AAGA,UAAM,kBAA4B,CAAC;AACnC,QAAI,CAAC,mBAAoB,iBAAgB,KAAK,aAAa;AAC3D,QAAI,CAAC,gBAAiB,iBAAgB,KAAK,UAAU;AACrD,QAAI,CAAC,mBAAoB,iBAAgB,KAAK,aAAa;AAC3D,QAAI,CAAC,eAAgB,iBAAgB,KAAK,SAAS;AACnD,QAAI,CAAC,eAAgB,iBAAgB,KAAK,SAAS;AAEnD,QAAI,gBAAgB,SAAS,GAAG;AAC9B,cAAQ,IAAIA,OAAM,KAAK,aAAa,GAAGA,OAAM,OAAO,gBAAgB,KAAK,IAAI,CAAC,CAAC;AAAA,IACjF;AAEA,QAAI,eAAe;AACjB,cAAQ,IAAIA,OAAM,KAAK,mBAAmB,GAAGA,OAAM,KAAK,aAAa,CAAC;AAAA,IACxE;AAEA,YAAQ,IAAIA,OAAM,KAAK,WAAW,GAAGA,OAAM,KAAK,MAAM,CAAC;AAGvD,QAAI,YAAY,SAAS,SAAS,SAAS,MAAM,SAAS,GAAG;AAC3D,cAAQ,IAAI,EAAE;AACd,cAAQ,IAAIA,OAAM,KAAK,qBAAqB,CAAC;AAC7C,cAAQ,IAAIA,OAAM,KAAK,0MAAqC,CAAC;AAE7D,YAAM,aAAa,oBAAoB,SAAS,KAAK;AACrD,YAAM,gBAAgB,KAAK,IAAI,GAAG,WAAW,IAAI,CAAC,MAAM,EAAE,KAAK,MAAM,CAAC;AAEtE,iBAAW,YAAY,YAAY;AACjC,cAAM,UAAU,IAAI,OAAO,gBAAgB,SAAS,KAAK,SAAS,CAAC;AACnE,cAAM,WAAW,SAAS,MAAM,SAAS,EAAE,SAAS,GAAG,GAAG;AAC1D,gBAAQ;AAAA,UACNA,OAAM,KAAK,KAAK,SAAS,IAAI,GAAG,OAAO,EAAE;AAAA,UACzCA,OAAM,KAAK,GAAG,QAAQ,QAAQ;AAAA,QAChC;AAAA,MACF;AAEA,cAAQ,IAAIA,OAAM,KAAK,0MAAqC,CAAC;AAC7D,YAAM,eAAe,IAAI,OAAO,gBAAgB,IAAI,CAAC;AACrD,YAAM,WAAW,SAAS,WAAW,SAAS,EAAE,SAAS,GAAG,GAAG;AAC/D,cAAQ;AAAA,QACNA,OAAM,MAAM,UAAU,YAAY,EAAE;AAAA,QACpCA,OAAM,KAAK,KAAK,GAAG,QAAQ,QAAQ;AAAA,MACrC;AACA,cAAQ,IAAIA,OAAM,KAAK,aAAa,GAAGA,OAAM,KAAK,SAAS,QAAQ,CAAC;AAAA,IACtE;AAGA,YAAQ,IAAI,EAAE;AACd,YAAQ,IAAIA,OAAM,KAAK,WAAW,CAAC;AACnC,YAAQ,IAAIA,OAAM,KAAK,0MAAqC,CAAC;AAC7D,QAAI,UAAU;AACZ,cAAQ;AAAA,QACNA,OAAM,MAAM,SAAS;AAAA,QACrB,mBACIA,OAAM,KAAK,OAAO,GAAG,SAAS,gBAAgB,UAAU,IACxDA,OAAM,KAAK,IAAI,GAAG,SAAS,gBAAgB,UAAU;AAAA,MAC3D;AAAA,IACF;AACA,YAAQ;AAAA,MACNA,OAAM,MAAM,cAAc;AAAA,MAC1B,mBACIA,OAAM,KAAK,MAAM,GAAG,QAAQ,SAAS,UAAU,IAC/CA,OAAM,KAAK,IAAI,GAAG,QAAQ,SAAS,yBAAyB;AAAA,IAClE;AACA,YAAQ,IAAI,EAAE;AAGd,QAAI,CAAC,oBAAoB,UAAU;AACjC,cAAQ,IAAIA,OAAM,IAAI,kDAA6C,CAAC;AACpE,cAAQ,IAAIA,OAAM,KAAK,UAAU,SAAS,mBAAmB,QAAQ,SAAS;AAAA,CAAkB,CAAC;AACjG,cAAQ,KAAK,CAAC;AAAA,IAChB;AAGA,QAAI,CAAC,QAAQ,KAAK;AAChB,YAAM,YAAY,MAAM,cAAc,4BAA4B;AAClE,UAAI,CAAC,WAAW;AACd,gBAAQ,IAAIA,OAAM,OAAO,4BAA4B,CAAC;AACtD,gBAAQ,KAAK,CAAC;AAAA,MAChB;AAAA,IACF;AAGA,YAAQ,IAAI,EAAE;AACd,IAAAC,WAAUC,KAAI,EAAE,MAAM,sBAAsB,OAAO,OAAO,CAAC,EAAE,MAAM;AAGnE,UAAM,kBAAkB,aACpB;AAAA;AAAA,MAEE;AAAA,MACA;AAAA,MACA,SAAS;AAAA,QACP;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF,IACA;AAAA;AAAA,MAEE;AAAA,MACA;AAAA,MACA,SAAS;AAAA,QACP;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,WAAW;AAAA,QACX;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEJ,UAAM,SAAS,MAAM,UAAU,aAAa,eAAe;AAE3D,IAAAD,SAAQ,QAAQD,OAAM,MAAM,8BAA8B,CAAC;AAG3D,YAAQ,IAAI,EAAE;AACd,YAAQ,IAAIA,OAAM,KAAK,WAAW,CAAC;AACnC,YAAQ,IAAIA,OAAM,KAAK,0MAAqC,CAAC;AAC7D,YAAQ,IAAIA,OAAM,KAAK,UAAU,GAAGA,OAAM,KAAK,OAAO,OAAO,cAAc,OAAO,OAAO,UAAU,CAAC,CAAC;AACrG,QAAI,OAAO,OAAO,eAAe;AAC/B,cAAQ,IAAIA,OAAM,KAAK,aAAa,GAAGA,OAAM,KAAK,OAAO,MAAM,aAAa,CAAC;AAAA,IAC/E;AACA,QAAI,OAAO,OAAO,aAAa,OAAO,MAAM,UAAU,SAAS,GAAG;AAChE,cAAQ;AAAA,QACNA,OAAM,KAAK,cAAc;AAAA,QACzBA,OAAM,KAAK,OAAO,MAAM,UAAU,KAAK,IAAI,CAAC;AAAA,MAC9C;AAAA,IACF;AAEA,QAAI,OAAO,gBAAgB,QAAW;AACpC,cAAQ,IAAI,EAAE;AACd,cAAQ,IAAIA,OAAM,KAAK,WAAW,CAAC;AACnC,cAAQ,IAAIA,OAAM,KAAK,0MAAqC,CAAC;AAC7D,cAAQ,IAAIA,OAAM,KAAK,SAAS,GAAGA,OAAM,OAAO,OAAO,WAAW,CAAC;AACnE,cAAQ;AAAA,QACNA,OAAM,KAAK,cAAc;AAAA,QACzB,OAAO,qBAAqB,UAAa,OAAO,mBAAmB,KAC/DA,OAAM,MAAM,OAAO,gBAAgB,IACnCA,OAAM,OAAO,OAAO,gBAAgB;AAAA,MAC1C;AAAA,IACF;AAGA,QAAI,OAAO,YAAY,OAAO,SAAS,SAAS,GAAG;AACjD,cAAQ,IAAI,EAAE;AACd,cAAQ,IAAIA,OAAM,OAAO,aAAa,CAAC;AACvC,iBAAW,WAAW,OAAO,UAAU;AACrC,gBAAQ,IAAIA,OAAM,OAAO,SAAS,OAAO,EAAE,CAAC;AAAA,MAC9C;AAAA,IACF;AAEA,YAAQ,IAAI,EAAE;AAGd,UAAM,oBAAoB,OAAO,OAAO,QAAQ,QAAQ,OAAO;AAE/D,YAAQ,IAAIA,OAAM,MAAM,sBAAsBA,OAAM,MAAM,MAAM,CAAC,EAAE,CAAC;AACpE,YAAQ,IAAI,EAAE;AAAA,EAChB,SAAS,OAAY;AACnB,IAAAC,SAAQ,KAAKD,OAAM,IAAI,mBAAmB,CAAC;AAE3C,QAAI,MAAM,UAAU,WAAW,KAAK;AAClC,YAAM,mBAAmB,YAAY;AAAA,IACvC,WAAW,MAAM,UAAU,WAAW,KAAK;AACzC,cAAQ,IAAIA,OAAM,OAAO,uDAAuD,CAAC;AACjF,cAAQ,IAAIA,OAAM,KAAK,+CAA+C,CAAC;AAAA,IACzE,WAAW,MAAM,UAAU,WAAW,KAAK;AACzC,cAAQ,IAAIA,OAAM,OAAO,wBAAwB,CAAC;AAClD,cAAQ,IAAIA,OAAM,KAAK,yCAAyC,CAAC;AAAA,IACnE,WAAW,MAAM,UAAU,WAAW,KAAK;AAEzC,YAAM,OAAO,MAAM,SAAS;AAC5B,cAAQ,IAAIA,OAAM,IAAI,0BAA0B,CAAC;AACjD,UAAI,KAAK,iBAAiB;AACxB,gBAAQ,IAAIA,OAAM,OAAO,eAAe,KAAK,eAAe,UAAU,CAAC;AAAA,MACzE;AACA,cAAQ,IAAIA,OAAM,OAAO,gBAAgB,KAAK,aAAa,CAAC,UAAU,CAAC;AACvE,cAAQ,IAAIA,OAAM,KAAK,mDAAmD,CAAC;AAAA,IAC7E,WAAW,MAAM,UAAU,MAAM,SAAS;AACxC,cAAQ,IAAIA,OAAM,IAAI;AAAA,IAAO,MAAM,SAAS,KAAK,OAAO;AAAA,CAAI,CAAC;AAAA,IAC/D,OAAO;AACL,cAAQ,IAAIA,OAAM,IAAI;AAAA,IAAO,MAAM,OAAO;AAAA,CAAI,CAAC;AAAA,IACjD;AAEA,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;;;AK1fA,YAAY,OAAO;AACnB,OAAOG,YAAW;AAkBlB,eAAsB,YAAY,SAAsB;AACtD,EAAE,QAAMC,OAAM,OAAO,MAAM,kBAAkB,CAAC;AAG9C,MAAI,CAAC,QAAQ,SAAU,MAAM,aAAa,GAAI;AAC5C,UAAM,YAAY,MAAQ,UAAQ;AAAA,MAChC,SAAS;AAAA,MACT,cAAc;AAAA,IAChB,CAAC;AAED,QAAM,WAAS,SAAS,KAAK,CAAC,WAAW;AACvC,MAAE,SAAO,sBAAsB;AAC/B,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF;AAGA,QAAM,eAAe,IAAI,aAAa;AACtC,QAAM,QAAQ,MAAM,aAAa,eAAe;AAEhD,MAAI,CAAC,OAAO;AACV,IAAE,SAAO,8CAA8C;AACvD,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,YAAY,8BAA8B,OAAO,YAAY;AAEnE,MAAI;AAEF,UAAM,aAAe,UAAQ;AAC7B,eAAW,MAAM,0BAA0B;AAE3C,UAAM,gBAAgB,MAAM,UAAU,kBAAkB;AACxD,eAAW,KAAK,sBAAsB;AAEtC,QAAI,cAAc,WAAW,GAAG;AAC9B,MAAE,SAAO,6DAA6D;AACtE,cAAQ,KAAK,CAAC;AAAA,IAChB;AAEA,QAAI;AAEJ,QAAI,cAAc,WAAW,KAAK,cAAc,CAAC,GAAG;AAElD,uBAAiB,cAAc,CAAC,EAAE;AAClC,MAAE,MAAI,KAAK,iBAAiB,cAAc,CAAC,EAAE,IAAI,EAAE;AAAA,IACrD,OAAO;AACL,YAAM,cAAc,MAAQ,SAAO;AAAA,QACjC,SAAS;AAAA,QACT,SAAS,cAAc,IAAI,CAAC,SAAS;AAAA,UACnC,OAAO,IAAI;AAAA,UACX,OAAO,IAAI;AAAA,UACX,MAAM,IAAI,SAAS,YAAY;AAAA,QACjC,EAAE;AAAA,MACJ,CAAC;AAED,UAAM,WAAS,WAAW,GAAG;AAC3B,QAAE,SAAO,sBAAsB;AAC/B,gBAAQ,KAAK,CAAC;AAAA,MAChB;AAEA,uBAAiB;AAAA,IACnB;AAGA,QAAI,YAAY,QAAQ;AAExB,QAAI,CAAC,WAAW;AACd,YAAMC,WAAY,UAAQ;AAC1B,MAAAA,SAAQ,MAAM,qBAAqB;AAEnC,YAAM,WAAW,MAAM,UAAU,aAAa,cAAc;AAC5D,MAAAA,SAAQ,KAAK,iBAAiB;AAE9B,UAAI,SAAS,WAAW,GAAG;AACzB,QAAE,SAAO,uEAAuE;AAChF,gBAAQ,KAAK,CAAC;AAAA,MAChB;AAEA,YAAM,kBAAkB,MAAQ,SAAO;AAAA,QACrC,SAAS;AAAA,QACT,SAAS,SAAS,IAAI,CAAC,UAAU;AAAA,UAC/B,OAAO,KAAK;AAAA,UACZ,OAAO,KAAK;AAAA,UACZ,MAAM,CAAC,KAAK,kBAAkB,KAAK,iBAAiB,EAAE,OAAO,OAAO,EAAE,KAAK,KAAK;AAAA,QAClF,EAAE;AAAA,MACJ,CAAC;AAED,UAAM,WAAS,eAAe,GAAG;AAC/B,QAAE,SAAO,sBAAsB;AAC/B,gBAAQ,KAAK,CAAC;AAAA,MAChB;AAEA,kBAAY;AAAA,IACd;AAGA,UAAMA,WAAY,UAAQ;AAC1B,IAAAA,SAAQ,MAAM,6BAA6B;AAC3C,UAAM,UAAU,MAAM,UAAU,WAAW,SAAS;AACpD,IAAAA,SAAQ,KAAK,YAAY,QAAQ,IAAI,EAAE;AAGvC,UAAM,gBAAoD,CAAC;AAC3D,QAAI,QAAQ,kBAAkB;AAC5B,oBAAc,KAAK;AAAA,QACjB,OAAO;AAAA,QACP,OAAO,YAAY,QAAQ,gBAAgB;AAAA,MAC7C,CAAC;AAAA,IACH;AACA,QAAI,QAAQ,mBAAmB;AAC7B,oBAAc,KAAK;AAAA,QACjB,OAAO;AAAA,QACP,OAAO,aAAa,QAAQ,iBAAiB;AAAA,MAC/C,CAAC;AAAA,IACH;AAEA,QAAI,cAAc,WAAW,GAAG;AAC9B,MAAE,SAAO,0EAA0E;AACnF,cAAQ,KAAK,CAAC;AAAA,IAChB;AAGA,UAAM,UAAU,MAAQ,cAAY;AAAA,MAClC,SAAS;AAAA,MACT,SAAS;AAAA,MACT,UAAU;AAAA,IACZ,CAAC;AAED,QAAM,WAAS,OAAO,GAAG;AACvB,MAAE,SAAO,sBAAsB;AAC/B,cAAQ,KAAK,CAAC;AAAA,IAChB;AAEA,UAAM,kBAAkB;AAGxB,UAAM,SAA2B;AAAA,MAC/B,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,WAAW;AAAA,QACT,oBAAoB;AAAA,QACpB,iBAAiB;AAAA,QACjB,oBAAoB;AAAA,QACpB,gBAAgB;AAAA,QAChB,gBAAgB;AAAA,MAClB;AAAA,IACF;AAGA,QAAI,gBAAgB,SAAS,SAAS,KAAK,QAAQ,kBAAkB;AACnE,YAAM,cAAgB,UAAQ;AAC9B,kBAAY,MAAM,8BAA8B;AAGhD,YAAM,iBAAiB,MAAM,UAAU,aAAa;AAAA,QAClD,UAAU;AAAA,QACV,UAAU,QAAQ;AAAA,MACpB,CAAC;AACD,kBAAY,KAAK,kBAAkB;AAEnC,UAAI,eAAe,UAAU,SAAS,GAAG;AACvC,cAAM,SAAS,MAAQ,SAAO;AAAA,UAC5B,SAAS;AAAA,UACT,SAAS,eAAe,UAAU,IAAI,CAAC,UAAU;AAAA,YAC/C,OAAO,KAAK;AAAA,YACZ,OAAO,KAAK;AAAA,YACZ,MAAM,KAAK,eAAe,GAAG,KAAK,IAAI;AAAA,UACxC,EAAE;AAAA,QACJ,CAAC;AAED,YAAM,WAAS,MAAM,GAAG;AACtB,UAAE,SAAO,sBAAsB;AAC/B,kBAAQ,KAAK,CAAC;AAAA,QAChB;AAGA,cAAM,eAAe,MAAM,UAAU,YAAY,MAAgB;AAEjE,YAAI,aAAa,UAAU,aAAa,OAAO,SAAS,GAAG;AACzD,gBAAM,SAAS,MAAQ,cAAY;AAAA,YACjC,SAAS;AAAA,YACT,SAAS,aAAa,OAAO,IAAI,CAAC,WAAW;AAAA,cAC3C,OAAO,MAAM;AAAA,cACb,OAAO,MAAM;AAAA,cACb,MAAM,MAAM;AAAA,YACd,EAAE;AAAA,YACF,eAAe,aAAa,OAAO,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE,EAAE;AAAA,UAC7E,CAAC;AAED,cAAM,WAAS,MAAM,GAAG;AACtB,YAAE,SAAO,sBAAsB;AAC/B,oBAAQ,KAAK,CAAC;AAAA,UAChB;AAEA,iBAAO,UAAU;AAAA,YACf;AAAA,YACA;AAAA,UACF;AAAA,QACF,OAAO;AACL,iBAAO,UAAU;AAAA,YACf;AAAA,YACA,QAAQ,CAAC;AAAA,UACX;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAGA,QAAI,gBAAgB,SAAS,UAAU,KAAK,QAAQ,mBAAmB;AACrE,YAAM,cAAgB,UAAQ;AAC9B,kBAAY,MAAM,+BAA+B;AAGjD,YAAM,iBAAiB,MAAM,UAAU,aAAa;AAAA,QAClD,UAAU;AAAA,QACV,WAAW,QAAQ;AAAA,MACrB,CAAC;AACD,kBAAY,KAAK,kBAAkB;AAEnC,UAAI,eAAe,UAAU,SAAS,GAAG;AACvC,cAAM,SAAS,MAAQ,SAAO;AAAA,UAC5B,SAAS;AAAA,UACT,SAAS,eAAe,UAAU,IAAI,CAAC,UAAU;AAAA,YAC/C,OAAO,KAAK;AAAA,YACZ,OAAO,KAAK;AAAA,YACZ,MAAM,KAAK,eAAe,GAAG,KAAK,IAAI;AAAA,UACxC,EAAE;AAAA,QACJ,CAAC;AAED,YAAM,WAAS,MAAM,GAAG;AACtB,UAAE,SAAO,sBAAsB;AAC/B,kBAAQ,KAAK,CAAC;AAAA,QAChB;AAGA,cAAM,eAAe,MAAM,UAAU,YAAY,MAAgB;AAEjE,YAAI,aAAa,UAAU,aAAa,OAAO,SAAS,GAAG;AACzD,gBAAM,SAAS,MAAQ,cAAY;AAAA,YACjC,SAAS;AAAA,YACT,SAAS,aAAa,OAAO,IAAI,CAAC,WAAW;AAAA,cAC3C,OAAO,MAAM;AAAA,cACb,OAAO,MAAM;AAAA,cACb,MAAM,MAAM;AAAA,YACd,EAAE;AAAA,YACF,eAAe,aAAa,OAAO,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE,EAAE;AAAA,UAC7E,CAAC;AAED,cAAM,WAAS,MAAM,GAAG;AACtB,YAAE,SAAO,sBAAsB;AAC/B,oBAAQ,KAAK,CAAC;AAAA,UAChB;AAEA,iBAAO,WAAW;AAAA,YAChB;AAAA,YACA;AAAA,UACF;AAAA,QACF,OAAO;AACL,iBAAO,WAAW;AAAA,YAChB;AAAA,YACA,QAAQ,CAAC;AAAA,UACX;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAGA,UAAM,oBAAoB,MAAQ,SAAO;AAAA,MACvC,SAAS;AAAA,MACT,SAAS;AAAA,QACP;AAAA,UACE,OAAO;AAAA,UACP,OAAO;AAAA,UACP,MAAM;AAAA,QACR;AAAA,QACA;AAAA,UACE,OAAO;AAAA,UACP,OAAO;AAAA,UACP,MAAM;AAAA,QACR;AAAA,MACF;AAAA,MACA,cAAc;AAAA,IAChB,CAAC;AAED,QAAM,WAAS,iBAAiB,GAAG;AACjC,MAAE,SAAO,sBAAsB;AAC/B,cAAQ,KAAK,CAAC;AAAA,IAChB;AAEA,WAAO,oBAAoB;AAG3B,UAAM,mBAAmB,MAAQ,cAAY;AAAA,MAC3C,SAAS;AAAA,MACT,SAAS;AAAA,QACP,EAAE,OAAO,eAAe,OAAO,uBAAuB,MAAM,uBAAuB;AAAA,QACnF,EAAE,OAAO,YAAY,OAAO,oBAAoB,MAAM,yBAAyB;AAAA,QAC/E,EAAE,OAAO,eAAe,OAAO,uBAAuB,MAAM,4BAA4B;AAAA,QACxF,EAAE,OAAO,WAAW,OAAO,mBAAmB,MAAM,qBAAqB;AAAA,QACzE,EAAE,OAAO,WAAW,OAAO,iBAAiB,MAAM,sBAAsB;AAAA,MAC1E;AAAA,MACA,eAAe,CAAC,eAAe,YAAY,eAAe,WAAW,SAAS;AAAA,IAChF,CAAC;AAED,QAAM,WAAS,gBAAgB,GAAG;AAChC,MAAE,SAAO,sBAAsB;AAC/B,cAAQ,KAAK,CAAC;AAAA,IAChB;AAEA,UAAM,iBAAiB;AACvB,WAAO,YAAY;AAAA,MACjB,oBAAoB,eAAe,SAAS,aAAa;AAAA,MACzD,iBAAiB,eAAe,SAAS,UAAU;AAAA,MACnD,oBAAoB,eAAe,SAAS,aAAa;AAAA,MACzD,gBAAgB,eAAe,SAAS,SAAS;AAAA,MACjD,gBAAgB,eAAe,SAAS,SAAS;AAAA,IACnD;AAGA,UAAM,SAAS,MAAQ,OAAK;AAAA,MAC1B,SAAS;AAAA,MACT,cAAc;AAAA,MACd,UAAU,CAAC,UAAU;AACnB,YAAI,CAAC,MAAO,QAAO;AACnB,eAAO;AAAA,MACT;AAAA,IACF,CAAC;AAED,QAAM,WAAS,MAAM,GAAG;AACtB,MAAE,SAAO,sBAAsB;AAC/B,cAAQ,KAAK,CAAC;AAAA,IAChB;AAEA,WAAO,SAAS;AAGhB,UAAM,WAAW,MAAM;AAEvB,IAAE;AAAA,MACAD,OAAM,MAAM,oCAAoC,IAC9C,SACAA,OAAM,KAAK,QAAQ,IACnBA,OAAM,KAAK,qBAAqB,IAChCA,OAAM,KAAK,oBAAoB;AAAA,IACnC;AAAA,EACF,SAAS,OAAY;AACnB,QAAI,MAAM,UAAU,WAAW,KAAK;AAClC,YAAM,mBAAmB,YAAY;AAAA,IACvC,WAAW,MAAM,UAAU,MAAM,SAAS;AACxC,MAAE,SAAO,MAAM,SAAS,KAAK,OAAO;AAAA,IACtC,OAAO;AACL,MAAE,SAAO,MAAM,WAAW,8BAA8B;AAAA,IAC1D;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;;;ACvXA,OAAOE,aAAW;AAalB,eAAsB,YAAY,SAAsB;AACtD,UAAQ,IAAIA,QAAM,OAAO,6BAA6B,CAAC;AACvD,MAAI,QAAQ,SAAS;AACnB,YAAQ,IAAIA,QAAM,KAAK,wBAAwB,QAAQ,OAAO,EAAE,CAAC;AAAA,EACnE;AACA,UAAQ,IAAIA,QAAM,KAAK,2BAA2B,CAAC;AACrD;;;ACnBA,OAAOC,aAAW;AAUlB,eAAsB,gBAAgB;AACpC,UAAQ,IAAIA,QAAM,OAAO,6BAA6B,CAAC;AACvD,UAAQ,IAAIA,QAAM,KAAK,2BAA2B,CAAC;AACrD;;;AhBHA,OAAO;AAEP,IAAM,UAAU,IAAI,QAAQ;AAE5B,QACG,KAAK,YAAY,EACjB,YAAY,mEAAmE,EAC/E,QAAQ,QAAQ;AAMnB,QACG,QAAQ,OAAO,EACf,YAAY,8BAA8B,EAC1C,OAAO,YAAY;AAEtB,QACG,QAAQ,QAAQ,EAChB,YAAY,qCAAqC,EACjD,OAAO,aAAa;AAEvB,QACG,QAAQ,QAAQ,EAChB,YAAY,iCAAiC,EAC7C,OAAO,aAAa;AAMvB,QACG,QAAQ,MAAM,EACd,YAAY,4CAA4C,EACxD,OAAO,sBAAsB,6BAA6B,EAC1D,OAAO,eAAe,0CAA0C,EAChE,OAAO,WAAW;AAErB,QACG,QAAQ,MAAM,EACd,YAAY,wBAAwB,EACpC,OAAO,sBAAsB,YAAY,EACzC,OAAO,WAAW;AAErB,QACG,QAAQ,QAAQ,EAChB,YAAY,0BAA0B,EACtC,OAAO,aAAa;AAMvB,QACG,QAAQ,UAAU,EAClB,MAAM,KAAK,EACX,YAAY,2BAA2B,EAEvC,OAAO,sBAAsB,YAAY,EACzC,OAAO,8BAA8B,0CAA0C,EAC/E,OAAO,gCAAgC,wBAAwB,EAC/D,OAAO,sBAAsB,oBAAoB,eAAe,EAEhE,OAAO,6BAA6B,6BAA6B,EACjE,OAAO,8BAA8B,8BAA8B,EACnE,OAAO,gCAAgC,4BAA4B,EACnE,OAAO,iCAAiC,6BAA6B,EAErE,OAAO,oBAAoB,qBAAqB,EAChD,OAAO,iBAAiB,kBAAkB,EAC1C,OAAO,oBAAoB,qBAAqB,EAChD,OAAO,gBAAgB,4BAA4B,EACnD,OAAO,gBAAgB,oBAAoB,EAE3C,OAAO,gCAAgC,yDAAyD,EAEhG,OAAO,iBAAiB,+BAA+B,EACvD,OAAO,aAAa,0BAA0B,EAC9C,OAAO,eAAe;AAMzB,QAAQ,MAAM;","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"]}
|