aerocoding 0.1.15 → 0.1.17
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 +260 -165
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import { Command } from "commander";
|
|
5
5
|
|
|
6
6
|
// src/commands/login.ts
|
|
7
|
-
import
|
|
7
|
+
import chalk3 from "chalk";
|
|
8
8
|
|
|
9
9
|
// src/auth/device-flow.ts
|
|
10
10
|
import axios from "axios";
|
|
@@ -139,7 +139,6 @@ var DeviceFlow = class {
|
|
|
139
139
|
// src/auth/token-manager.ts
|
|
140
140
|
import { Entry } from "@napi-rs/keyring";
|
|
141
141
|
import { createClient } from "@supabase/supabase-js";
|
|
142
|
-
import chalk2 from "chalk";
|
|
143
142
|
var SERVICE_NAME = "aerocoding-cli";
|
|
144
143
|
var SUPABASE_URL = "https://peqpttkvdpjgmduzacwl.supabase.co";
|
|
145
144
|
var SUPABASE_ANON_KEY = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InBlcXB0dGt2ZHBqZ21kdXphY3dsIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NjQyNjUxNzMsImV4cCI6MjA3OTg0MTE3M30.WAzqgZusGoOEHxidfHc1e4daBglG4DJG5LOXbqldWQA";
|
|
@@ -182,12 +181,10 @@ var TokenManager = class {
|
|
|
182
181
|
return null;
|
|
183
182
|
}
|
|
184
183
|
if (this.isTokenExpired(accessToken)) {
|
|
185
|
-
console.log(chalk2.yellow("\u23F1\uFE0F Token expired, refreshing..."));
|
|
186
184
|
accessToken = await this.refreshTokens();
|
|
187
185
|
}
|
|
188
186
|
return accessToken;
|
|
189
|
-
} catch
|
|
190
|
-
console.error(chalk2.red("Failed to get access token:"), error);
|
|
187
|
+
} catch {
|
|
191
188
|
return null;
|
|
192
189
|
}
|
|
193
190
|
}
|
|
@@ -208,12 +205,10 @@ var TokenManager = class {
|
|
|
208
205
|
}
|
|
209
206
|
setPassword(SERVICE_NAME, "access_token", data.session.access_token);
|
|
210
207
|
setPassword(SERVICE_NAME, "refresh_token", data.session.refresh_token);
|
|
211
|
-
console.log(chalk2.green("Token refreshed successfully"));
|
|
212
208
|
return data.session.access_token;
|
|
213
|
-
} catch
|
|
214
|
-
console.error(chalk2.red("Token refresh failed. Please login again."));
|
|
209
|
+
} catch {
|
|
215
210
|
await this.logout();
|
|
216
|
-
|
|
211
|
+
return null;
|
|
217
212
|
}
|
|
218
213
|
}
|
|
219
214
|
/**
|
|
@@ -235,14 +230,9 @@ var TokenManager = class {
|
|
|
235
230
|
* Save tokens and user metadata after successful login
|
|
236
231
|
*/
|
|
237
232
|
async saveTokens(accessToken, refreshToken, user) {
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
setPassword(SERVICE_NAME, "user_metadata", JSON.stringify(user));
|
|
242
|
-
} catch (error) {
|
|
243
|
-
console.error(chalk2.red("Failed to save tokens:"), error);
|
|
244
|
-
throw error;
|
|
245
|
-
}
|
|
233
|
+
setPassword(SERVICE_NAME, "access_token", accessToken);
|
|
234
|
+
setPassword(SERVICE_NAME, "refresh_token", refreshToken);
|
|
235
|
+
setPassword(SERVICE_NAME, "user_metadata", JSON.stringify(user));
|
|
246
236
|
}
|
|
247
237
|
/**
|
|
248
238
|
* Get stored user metadata
|
|
@@ -364,6 +354,43 @@ var ApiClient = class {
|
|
|
364
354
|
const response = await this.client.post("/api/generate/estimate", payload);
|
|
365
355
|
return response.data.data;
|
|
366
356
|
}
|
|
357
|
+
// ============================================
|
|
358
|
+
// Template Registry API
|
|
359
|
+
// ============================================
|
|
360
|
+
/**
|
|
361
|
+
* Search templates with filters
|
|
362
|
+
*/
|
|
363
|
+
async getTemplates(filter = {}) {
|
|
364
|
+
const params = new URLSearchParams();
|
|
365
|
+
if (filter.category) params.set("category", filter.category);
|
|
366
|
+
if (filter.language) params.set("language", filter.language);
|
|
367
|
+
if (filter.framework) params.set("framework", filter.framework);
|
|
368
|
+
if (filter.tier) params.set("tier", filter.tier);
|
|
369
|
+
if (filter.tags?.length) params.set("tags", filter.tags.join(","));
|
|
370
|
+
const response = await this.client.get(`/api/templates?${params.toString()}`);
|
|
371
|
+
return response.data;
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* Get full template by ID (includes layers and feature flags)
|
|
375
|
+
*/
|
|
376
|
+
async getTemplate(id) {
|
|
377
|
+
const response = await this.client.get(`/api/templates/${id}?full=true`);
|
|
378
|
+
return response.data.template;
|
|
379
|
+
}
|
|
380
|
+
/**
|
|
381
|
+
* Get template combinations (backend + frontend pairs)
|
|
382
|
+
*/
|
|
383
|
+
async getTemplateCombinations() {
|
|
384
|
+
const response = await this.client.get("/api/templates/combinations");
|
|
385
|
+
return response.data.combinations;
|
|
386
|
+
}
|
|
387
|
+
/**
|
|
388
|
+
* Get templates compatible with a given template
|
|
389
|
+
*/
|
|
390
|
+
async getCompatibleTemplates(templateId) {
|
|
391
|
+
const response = await this.client.get(`/api/templates/${templateId}?compatible=true`);
|
|
392
|
+
return response.data.compatible || [];
|
|
393
|
+
}
|
|
367
394
|
};
|
|
368
395
|
|
|
369
396
|
// src/commands/_shared/create-api-client.ts
|
|
@@ -376,31 +403,31 @@ function createApiClientWithAutoLogout(accessToken, tokenManager) {
|
|
|
376
403
|
}
|
|
377
404
|
|
|
378
405
|
// src/commands/_shared/unauthorized.ts
|
|
379
|
-
import
|
|
406
|
+
import chalk2 from "chalk";
|
|
380
407
|
async function handleUnauthorized(tokenManager) {
|
|
381
408
|
await tokenManager.logout();
|
|
382
409
|
console.error(
|
|
383
|
-
|
|
410
|
+
chalk2.yellow(
|
|
384
411
|
" Your session is invalid or expired. You have been logged out."
|
|
385
412
|
)
|
|
386
413
|
);
|
|
387
|
-
console.error(
|
|
414
|
+
console.error(chalk2.gray(" Run 'aerocoding login' to authenticate."));
|
|
388
415
|
process.exit(1);
|
|
389
416
|
}
|
|
390
417
|
|
|
391
418
|
// src/commands/login.ts
|
|
392
419
|
async function loginCommand() {
|
|
393
|
-
console.log(
|
|
420
|
+
console.log(chalk3.bold("\nAeroCoding CLI Login\n"));
|
|
394
421
|
const tokenManager = new TokenManager();
|
|
395
422
|
const existingToken = await tokenManager.getAccessToken();
|
|
396
423
|
if (existingToken) {
|
|
397
424
|
const metadata = await tokenManager.getUserMetadata();
|
|
398
425
|
console.log(
|
|
399
|
-
|
|
400
|
-
|
|
426
|
+
chalk3.yellow("Already logged in as:"),
|
|
427
|
+
chalk3.white(metadata?.email || "unknown")
|
|
401
428
|
);
|
|
402
429
|
console.log(
|
|
403
|
-
|
|
430
|
+
chalk3.gray(
|
|
404
431
|
" Run 'aerocoding logout' to login with a different account\n"
|
|
405
432
|
)
|
|
406
433
|
);
|
|
@@ -430,13 +457,13 @@ async function loginCommand() {
|
|
|
430
457
|
});
|
|
431
458
|
console.log("");
|
|
432
459
|
console.log(
|
|
433
|
-
|
|
434
|
-
|
|
460
|
+
chalk3.green("Successfully logged in as:"),
|
|
461
|
+
chalk3.white(user.email)
|
|
435
462
|
);
|
|
436
|
-
console.log(
|
|
463
|
+
console.log(chalk3.gray(" Run 'aerocoding whoami' to verify\n"));
|
|
437
464
|
} catch (error) {
|
|
438
465
|
console.error(
|
|
439
|
-
|
|
466
|
+
chalk3.red("\nLogin failed:"),
|
|
440
467
|
error.message || "Unknown error"
|
|
441
468
|
);
|
|
442
469
|
process.exit(1);
|
|
@@ -444,42 +471,42 @@ async function loginCommand() {
|
|
|
444
471
|
}
|
|
445
472
|
|
|
446
473
|
// src/commands/logout.ts
|
|
447
|
-
import
|
|
474
|
+
import chalk4 from "chalk";
|
|
448
475
|
async function logoutCommand() {
|
|
449
476
|
const tokenManager = new TokenManager();
|
|
450
477
|
const metadata = await tokenManager.getUserMetadata();
|
|
451
478
|
if (!metadata) {
|
|
452
|
-
console.log(
|
|
479
|
+
console.log(chalk4.yellow("Not logged in"));
|
|
453
480
|
return;
|
|
454
481
|
}
|
|
455
482
|
const email = metadata.email;
|
|
456
483
|
await tokenManager.logout();
|
|
457
|
-
console.log(
|
|
458
|
-
console.log(
|
|
484
|
+
console.log(chalk4.green("Logged out successfully"));
|
|
485
|
+
console.log(chalk4.gray(` Cleared credentials for ${email}
|
|
459
486
|
`));
|
|
460
487
|
}
|
|
461
488
|
|
|
462
489
|
// src/commands/whoami.ts
|
|
463
|
-
import
|
|
490
|
+
import chalk5 from "chalk";
|
|
464
491
|
async function whoamiCommand() {
|
|
465
492
|
const tokenManager = new TokenManager();
|
|
466
493
|
const token = await tokenManager.getAccessToken();
|
|
467
494
|
if (!token) {
|
|
468
|
-
console.log(
|
|
469
|
-
console.log(
|
|
495
|
+
console.log(chalk5.red("Not logged in"));
|
|
496
|
+
console.log(chalk5.gray(" Run 'aerocoding login' to authenticate\n"));
|
|
470
497
|
return;
|
|
471
498
|
}
|
|
472
499
|
try {
|
|
473
500
|
const apiClient = createApiClientWithAutoLogout(token, tokenManager);
|
|
474
501
|
const user = await apiClient.getCurrentUser();
|
|
475
502
|
console.log("");
|
|
476
|
-
console.log(
|
|
503
|
+
console.log(chalk5.white("Logged in as:"), chalk5.cyan.bold(user.email));
|
|
477
504
|
if (user.name) {
|
|
478
|
-
console.log(
|
|
505
|
+
console.log(chalk5.gray(" Name:"), user.name);
|
|
479
506
|
}
|
|
480
507
|
console.log("");
|
|
481
508
|
} catch (error) {
|
|
482
|
-
console.error(
|
|
509
|
+
console.error(chalk5.red("Failed to get user info"));
|
|
483
510
|
if (error.response?.status === 401) {
|
|
484
511
|
await handleUnauthorized(tokenManager);
|
|
485
512
|
}
|
|
@@ -488,13 +515,13 @@ async function whoamiCommand() {
|
|
|
488
515
|
}
|
|
489
516
|
|
|
490
517
|
// src/commands/generate.ts
|
|
491
|
-
import
|
|
518
|
+
import chalk8 from "chalk";
|
|
492
519
|
import ora2 from "ora";
|
|
493
520
|
|
|
494
521
|
// src/utils/file-writer.ts
|
|
495
522
|
import fs from "fs/promises";
|
|
496
523
|
import path from "path";
|
|
497
|
-
import
|
|
524
|
+
import chalk6 from "chalk";
|
|
498
525
|
function isPathSafe(outputDir, filePath) {
|
|
499
526
|
const resolvedOutput = path.resolve(outputDir);
|
|
500
527
|
const resolvedFile = path.resolve(outputDir, filePath);
|
|
@@ -504,10 +531,10 @@ async function writeGeneratedFiles(files, outputDir) {
|
|
|
504
531
|
for (const file of files) {
|
|
505
532
|
if (!isPathSafe(outputDir, file.path)) {
|
|
506
533
|
console.error(
|
|
507
|
-
|
|
534
|
+
chalk6.red(` Skipping unsafe path: ${file.path}`)
|
|
508
535
|
);
|
|
509
536
|
console.error(
|
|
510
|
-
|
|
537
|
+
chalk6.gray(` Path traversal detected - file path must be within output directory`)
|
|
511
538
|
);
|
|
512
539
|
continue;
|
|
513
540
|
}
|
|
@@ -516,24 +543,24 @@ async function writeGeneratedFiles(files, outputDir) {
|
|
|
516
543
|
try {
|
|
517
544
|
await fs.mkdir(dir, { recursive: true });
|
|
518
545
|
await fs.writeFile(fullPath, file.content, "utf-8");
|
|
519
|
-
console.log(
|
|
546
|
+
console.log(chalk6.gray(` ${file.path}`));
|
|
520
547
|
} catch (error) {
|
|
521
|
-
console.error(
|
|
522
|
-
console.error(
|
|
548
|
+
console.error(chalk6.red(` Failed to write ${file.path}`));
|
|
549
|
+
console.error(chalk6.gray(` ${error.message}`));
|
|
523
550
|
}
|
|
524
551
|
}
|
|
525
552
|
}
|
|
526
553
|
|
|
527
554
|
// src/utils/prompt.ts
|
|
528
555
|
import readline from "readline";
|
|
529
|
-
import
|
|
556
|
+
import chalk7 from "chalk";
|
|
530
557
|
function promptConfirm(message) {
|
|
531
558
|
return new Promise((resolve) => {
|
|
532
559
|
const rl = readline.createInterface({
|
|
533
560
|
input: process.stdin,
|
|
534
561
|
output: process.stdout
|
|
535
562
|
});
|
|
536
|
-
rl.question(
|
|
563
|
+
rl.question(chalk7.yellow(`${message} [Y/n] `), (answer) => {
|
|
537
564
|
rl.close();
|
|
538
565
|
const normalized = answer.trim().toLowerCase();
|
|
539
566
|
resolve(normalized !== "n" && normalized !== "no");
|
|
@@ -565,7 +592,7 @@ var configSchema = z.object({
|
|
|
565
592
|
includeAnnotations: z.boolean().default(true),
|
|
566
593
|
includeLogging: z.boolean().default(true),
|
|
567
594
|
includeTesting: z.boolean().default(true)
|
|
568
|
-
}).
|
|
595
|
+
}).optional(),
|
|
569
596
|
libraries: z.object({
|
|
570
597
|
validation: z.string().optional(),
|
|
571
598
|
logging: z.string().optional()
|
|
@@ -611,6 +638,22 @@ async function configExists(dir = process.cwd()) {
|
|
|
611
638
|
}
|
|
612
639
|
|
|
613
640
|
// src/commands/generate.ts
|
|
641
|
+
function mapPresetToTemplateId(preset) {
|
|
642
|
+
const presetLower = preset.toLowerCase();
|
|
643
|
+
if (presetLower.includes("clean") && presetLower.includes("dotnet")) {
|
|
644
|
+
return "clean-arch-dotnet";
|
|
645
|
+
}
|
|
646
|
+
if (presetLower.includes("clean") && (presetLower.includes("dart") || presetLower.includes("flutter"))) {
|
|
647
|
+
return "flutter-clean-dart-test";
|
|
648
|
+
}
|
|
649
|
+
if (presetLower.includes("clean") && presetLower.includes("typescript")) {
|
|
650
|
+
return "minimal-typescript-test";
|
|
651
|
+
}
|
|
652
|
+
if (presetLower.startsWith("clean-arch-")) {
|
|
653
|
+
return preset;
|
|
654
|
+
}
|
|
655
|
+
return null;
|
|
656
|
+
}
|
|
614
657
|
function mapPresetToTarget(preset) {
|
|
615
658
|
const presetLower = preset.toLowerCase();
|
|
616
659
|
if (presetLower.includes("dotnet") || presetLower.includes("aspnet") || presetLower.includes("csharp")) {
|
|
@@ -624,6 +667,18 @@ function mapPresetToTarget(preset) {
|
|
|
624
667
|
}
|
|
625
668
|
return null;
|
|
626
669
|
}
|
|
670
|
+
function buildTemplateIdFromConfig(config) {
|
|
671
|
+
if (!config) return null;
|
|
672
|
+
if (config.backend?.preset) {
|
|
673
|
+
const templateId = mapPresetToTemplateId(config.backend.preset);
|
|
674
|
+
if (templateId) return templateId;
|
|
675
|
+
}
|
|
676
|
+
if (config.frontend?.preset) {
|
|
677
|
+
const templateId = mapPresetToTemplateId(config.frontend.preset);
|
|
678
|
+
if (templateId) return templateId;
|
|
679
|
+
}
|
|
680
|
+
return null;
|
|
681
|
+
}
|
|
627
682
|
function buildTargetsFromConfig(config) {
|
|
628
683
|
if (!config) return [];
|
|
629
684
|
const targets = [];
|
|
@@ -641,23 +696,44 @@ function buildTargetsFromConfig(config) {
|
|
|
641
696
|
}
|
|
642
697
|
return targets;
|
|
643
698
|
}
|
|
699
|
+
function buildFeatureFlagsFromConfig(config) {
|
|
700
|
+
const flags = {
|
|
701
|
+
// Default all feature flags to true for full architecture
|
|
702
|
+
includeDtos: true,
|
|
703
|
+
includeUseCases: true,
|
|
704
|
+
includeMappers: true,
|
|
705
|
+
includeControllers: true,
|
|
706
|
+
includeEfConfig: true,
|
|
707
|
+
includeValidation: true
|
|
708
|
+
};
|
|
709
|
+
if (!config) return flags;
|
|
710
|
+
if (config.codeStyle?.includeValidations !== void 0) {
|
|
711
|
+
flags.includeValidation = config.codeStyle.includeValidations;
|
|
712
|
+
}
|
|
713
|
+
if (config.codeStyle?.includeTesting !== void 0) {
|
|
714
|
+
flags.includeTests = config.codeStyle.includeTesting;
|
|
715
|
+
}
|
|
716
|
+
return flags;
|
|
717
|
+
}
|
|
644
718
|
async function generateCommand(options) {
|
|
645
719
|
const tokenManager = new TokenManager();
|
|
646
720
|
const token = await tokenManager.getAccessToken();
|
|
647
721
|
if (!token) {
|
|
648
|
-
console.log(
|
|
649
|
-
console.log(
|
|
722
|
+
console.log(chalk8.red("\n Not authenticated"));
|
|
723
|
+
console.log(chalk8.gray(" Run 'aerocoding login' to get started\n"));
|
|
650
724
|
process.exit(1);
|
|
651
725
|
}
|
|
652
726
|
const config = await loadConfig();
|
|
653
727
|
const projectId = options.project || config?.project;
|
|
654
728
|
if (!projectId) {
|
|
655
|
-
console.log(
|
|
656
|
-
console.log(
|
|
657
|
-
console.log(
|
|
729
|
+
console.log(chalk8.red("\n Project ID required"));
|
|
730
|
+
console.log(chalk8.gray(" Run 'aerocoding init' to create a config file"));
|
|
731
|
+
console.log(chalk8.gray(" Or use --project <id> to specify a project\n"));
|
|
658
732
|
process.exit(1);
|
|
659
733
|
}
|
|
660
|
-
const
|
|
734
|
+
const templateId = buildTemplateIdFromConfig(config);
|
|
735
|
+
const featureFlags = templateId ? buildFeatureFlagsFromConfig(config) : void 0;
|
|
736
|
+
const targets = !templateId ? options.targets || buildTargetsFromConfig(config) : void 0;
|
|
661
737
|
const output = options.output || config?.output || "./.aerocoding";
|
|
662
738
|
const backendPreset = options.backendPreset || config?.backend?.preset;
|
|
663
739
|
const frontendPreset = options.frontendPreset || config?.frontend?.preset;
|
|
@@ -673,47 +749,54 @@ async function generateCommand(options) {
|
|
|
673
749
|
let spinner2 = ora2({ text: "Fetching project...", color: "cyan" }).start();
|
|
674
750
|
try {
|
|
675
751
|
const project = await apiClient.getProject(projectId);
|
|
676
|
-
spinner2.succeed(
|
|
752
|
+
spinner2.succeed(chalk8.gray(`Project: ${project.name}`));
|
|
677
753
|
spinner2 = ora2({ text: "Checking credits...", color: "cyan" }).start();
|
|
678
754
|
const credits = await apiClient.getCreditUsage(project.organizationId);
|
|
679
755
|
let estimate = null;
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
756
|
+
if (targets && targets.length > 0) {
|
|
757
|
+
try {
|
|
758
|
+
estimate = await apiClient.estimateCreditCost({
|
|
759
|
+
projectId,
|
|
760
|
+
targets,
|
|
761
|
+
options: {
|
|
762
|
+
outputDir: output,
|
|
763
|
+
backendPreset,
|
|
764
|
+
frontendPreset,
|
|
765
|
+
backendLayers,
|
|
766
|
+
frontendLayers
|
|
767
|
+
}
|
|
768
|
+
});
|
|
769
|
+
} catch {
|
|
770
|
+
}
|
|
693
771
|
}
|
|
694
|
-
spinner2.succeed(
|
|
772
|
+
spinner2.succeed(chalk8.gray(`Credits: ${credits.remaining} / ${credits.limit} available`));
|
|
695
773
|
if (estimate && estimate.entities === 0) {
|
|
696
|
-
console.log(
|
|
697
|
-
console.log(
|
|
774
|
+
console.log(chalk8.yellow("\n \u26A0 No entities found in this project."));
|
|
775
|
+
console.log(chalk8.gray(" Create entities in the diagram editor and save (Ctrl+S) before generating.\n"));
|
|
698
776
|
process.exit(1);
|
|
699
777
|
}
|
|
700
778
|
const hasEnoughCredits = estimate ? credits.remaining >= estimate.estimatedCredits : true;
|
|
701
779
|
console.log("");
|
|
702
|
-
console.log(
|
|
703
|
-
console.log(
|
|
704
|
-
console.log(
|
|
780
|
+
console.log(chalk8.bold(" Generation Summary"));
|
|
781
|
+
console.log(chalk8.gray(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
782
|
+
console.log(chalk8.gray(" Project:"), chalk8.white(project.name));
|
|
705
783
|
if (config) {
|
|
706
|
-
console.log(
|
|
784
|
+
console.log(chalk8.gray(" Config:"), chalk8.cyan(".aerocodingrc.json"));
|
|
785
|
+
}
|
|
786
|
+
if (templateId) {
|
|
787
|
+
console.log(chalk8.gray(" Mode:"), chalk8.green("Full Architecture"));
|
|
788
|
+
console.log(chalk8.gray(" Template:"), chalk8.cyan(templateId));
|
|
789
|
+
} else if (targets && targets.length > 0) {
|
|
790
|
+
console.log(chalk8.gray(" Mode:"), chalk8.yellow("Simple (legacy)"));
|
|
791
|
+
console.log(chalk8.gray(" Targets:"), chalk8.cyan(targets.join(", ")));
|
|
792
|
+
} else {
|
|
793
|
+
console.log(chalk8.gray(" Mode:"), chalk8.gray("default"));
|
|
707
794
|
}
|
|
708
|
-
console.log(
|
|
709
|
-
chalk9.gray(" Targets:"),
|
|
710
|
-
chalk9.cyan(targets.length > 0 ? targets.join(", ") : "default")
|
|
711
|
-
);
|
|
712
795
|
if (backendPreset) {
|
|
713
|
-
console.log(
|
|
796
|
+
console.log(chalk8.gray(" Backend Preset:"), chalk8.cyan(backendPreset));
|
|
714
797
|
}
|
|
715
798
|
if (frontendPreset) {
|
|
716
|
-
console.log(
|
|
799
|
+
console.log(chalk8.gray(" Frontend Preset:"), chalk8.cyan(frontendPreset));
|
|
717
800
|
}
|
|
718
801
|
const disabledOptions = [];
|
|
719
802
|
if (!includeValidations) disabledOptions.push("validations");
|
|
@@ -722,46 +805,56 @@ async function generateCommand(options) {
|
|
|
722
805
|
if (!includeLogging) disabledOptions.push("logging");
|
|
723
806
|
if (!includeTesting) disabledOptions.push("testing");
|
|
724
807
|
if (disabledOptions.length > 0) {
|
|
725
|
-
console.log(
|
|
808
|
+
console.log(chalk8.gray(" Disabled:"), chalk8.yellow(disabledOptions.join(", ")));
|
|
726
809
|
}
|
|
727
810
|
if (validationLib) {
|
|
728
|
-
console.log(
|
|
811
|
+
console.log(chalk8.gray(" Validation Lib:"), chalk8.cyan(validationLib));
|
|
729
812
|
}
|
|
730
813
|
if (estimate) {
|
|
731
|
-
console.log(
|
|
732
|
-
console.log(
|
|
814
|
+
console.log(chalk8.gray(" Entities:"), chalk8.cyan(estimate.entities));
|
|
815
|
+
console.log(chalk8.gray(" Files:"), chalk8.cyan(estimate.totalFiles));
|
|
733
816
|
}
|
|
734
817
|
console.log("");
|
|
735
|
-
console.log(
|
|
736
|
-
console.log(
|
|
818
|
+
console.log(chalk8.bold(" Credits"));
|
|
819
|
+
console.log(chalk8.gray(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
737
820
|
if (estimate) {
|
|
738
821
|
console.log(
|
|
739
|
-
|
|
740
|
-
hasEnoughCredits ?
|
|
822
|
+
chalk8.white(" Cost:"),
|
|
823
|
+
hasEnoughCredits ? chalk8.bold.yellow(`${estimate.estimatedCredits} credits`) : chalk8.bold.red(`${estimate.estimatedCredits} credits`)
|
|
741
824
|
);
|
|
742
825
|
}
|
|
743
826
|
console.log(
|
|
744
|
-
|
|
745
|
-
hasEnoughCredits ?
|
|
827
|
+
chalk8.white(" Available:"),
|
|
828
|
+
hasEnoughCredits ? chalk8.bold.green(`${credits.remaining} credits`) : chalk8.bold.red(`${credits.remaining} credits (insufficient)`)
|
|
746
829
|
);
|
|
747
|
-
console.log(
|
|
830
|
+
console.log(chalk8.gray(" Output:"), chalk8.cyan(output));
|
|
748
831
|
console.log("");
|
|
749
832
|
if (!hasEnoughCredits && estimate) {
|
|
750
|
-
console.log(
|
|
751
|
-
console.log(
|
|
833
|
+
console.log(chalk8.red(" \u26A0 Not enough credits for this generation."));
|
|
834
|
+
console.log(chalk8.gray(` Need ${estimate.estimatedCredits - credits.remaining} more credits.
|
|
752
835
|
`));
|
|
753
836
|
process.exit(1);
|
|
754
837
|
}
|
|
755
838
|
if (!options.yes) {
|
|
756
839
|
const confirmed = await promptConfirm(" Proceed with generation?");
|
|
757
840
|
if (!confirmed) {
|
|
758
|
-
console.log(
|
|
841
|
+
console.log(chalk8.yellow("\n Generation cancelled\n"));
|
|
759
842
|
process.exit(0);
|
|
760
843
|
}
|
|
761
844
|
}
|
|
762
845
|
console.log("");
|
|
763
846
|
spinner2 = ora2({ text: "Generating code...", color: "cyan" }).start();
|
|
764
|
-
const
|
|
847
|
+
const generatePayload = templateId ? {
|
|
848
|
+
// NEW: Full architecture mode using template
|
|
849
|
+
projectId,
|
|
850
|
+
templateId,
|
|
851
|
+
options: {
|
|
852
|
+
includeValidations,
|
|
853
|
+
includeComments,
|
|
854
|
+
featureFlags
|
|
855
|
+
}
|
|
856
|
+
} : {
|
|
857
|
+
// Legacy mode using targets
|
|
765
858
|
projectId,
|
|
766
859
|
targets,
|
|
767
860
|
options: {
|
|
@@ -777,67 +870,63 @@ async function generateCommand(options) {
|
|
|
777
870
|
frontendLayers,
|
|
778
871
|
validationLib
|
|
779
872
|
}
|
|
780
|
-
}
|
|
781
|
-
|
|
873
|
+
};
|
|
874
|
+
const result = await apiClient.generateCode(generatePayload);
|
|
875
|
+
spinner2.succeed(chalk8.green("Code generated successfully!"));
|
|
782
876
|
console.log("");
|
|
783
|
-
console.log(
|
|
784
|
-
console.log(
|
|
785
|
-
console.log(
|
|
786
|
-
console.log(
|
|
877
|
+
console.log(chalk8.bold(" Results"));
|
|
878
|
+
console.log(chalk8.gray(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
879
|
+
console.log(chalk8.gray(" Files:"), chalk8.cyan(result.stats.totalFiles));
|
|
880
|
+
console.log(chalk8.gray(" Entities:"), chalk8.cyan(result.stats.totalEntities));
|
|
787
881
|
console.log(
|
|
788
|
-
|
|
789
|
-
|
|
882
|
+
chalk8.gray(" Languages:"),
|
|
883
|
+
chalk8.cyan(result.stats.languages.join(", "))
|
|
790
884
|
);
|
|
791
885
|
if (result.creditsUsed !== void 0) {
|
|
792
886
|
console.log("");
|
|
793
|
-
console.log(
|
|
794
|
-
console.log(
|
|
795
|
-
console.log(
|
|
887
|
+
console.log(chalk8.bold(" Credits"));
|
|
888
|
+
console.log(chalk8.gray(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
889
|
+
console.log(chalk8.gray(" Used:"), chalk8.yellow(result.creditsUsed));
|
|
796
890
|
console.log(
|
|
797
|
-
|
|
798
|
-
result.creditsRemaining !== void 0 && result.creditsRemaining > 50 ?
|
|
891
|
+
chalk8.gray(" Remaining:"),
|
|
892
|
+
result.creditsRemaining !== void 0 && result.creditsRemaining > 50 ? chalk8.green(result.creditsRemaining) : chalk8.yellow(result.creditsRemaining)
|
|
799
893
|
);
|
|
800
894
|
}
|
|
801
895
|
if (result.warnings && result.warnings.length > 0) {
|
|
802
896
|
console.log("");
|
|
803
|
-
console.log(
|
|
897
|
+
console.log(chalk8.yellow(" Warnings:"));
|
|
804
898
|
for (const warning of result.warnings) {
|
|
805
|
-
console.log(
|
|
899
|
+
console.log(chalk8.yellow(` - ${warning}`));
|
|
806
900
|
}
|
|
807
901
|
}
|
|
808
902
|
console.log("");
|
|
809
903
|
await writeGeneratedFiles(result.files, output);
|
|
810
|
-
console.log(
|
|
904
|
+
console.log(chalk8.green(` Files written to ${chalk8.white(output)}`));
|
|
811
905
|
console.log("");
|
|
812
906
|
} catch (error) {
|
|
813
|
-
spinner2.fail(
|
|
814
|
-
console.log(chalk9.gray(`
|
|
815
|
-
Error: ${error.response?.status || error.code || "unknown"}`));
|
|
816
|
-
if (error.response?.data) {
|
|
817
|
-
console.log(chalk9.gray(` Details: ${JSON.stringify(error.response.data)}`));
|
|
818
|
-
}
|
|
907
|
+
spinner2.fail(chalk8.red("Generation failed"));
|
|
819
908
|
if (error.response?.status === 401) {
|
|
820
909
|
await handleUnauthorized(tokenManager);
|
|
821
910
|
} else if (error.response?.status === 403) {
|
|
822
|
-
console.log(
|
|
823
|
-
console.log(
|
|
911
|
+
console.log(chalk8.yellow("\n You don't have permission to access this project."));
|
|
912
|
+
console.log(chalk8.gray(" Check if you're part of the organization.\n"));
|
|
824
913
|
} else if (error.response?.status === 404) {
|
|
825
|
-
console.log(
|
|
826
|
-
console.log(
|
|
914
|
+
console.log(chalk8.yellow("\n Project not found."));
|
|
915
|
+
console.log(chalk8.gray(" Check if the project ID is correct.\n"));
|
|
827
916
|
} else if (error.response?.status === 429) {
|
|
828
917
|
const data = error.response.data;
|
|
829
|
-
console.log(
|
|
918
|
+
console.log(chalk8.red("\n Insufficient credits"));
|
|
830
919
|
if (data.requiredCredits) {
|
|
831
|
-
console.log(
|
|
920
|
+
console.log(chalk8.yellow(` Required: ${data.requiredCredits} credits`));
|
|
832
921
|
}
|
|
833
|
-
console.log(
|
|
834
|
-
console.log(
|
|
922
|
+
console.log(chalk8.yellow(` Available: ${data.remaining ?? 0} credits`));
|
|
923
|
+
console.log(chalk8.gray("\n Upgrade your plan or wait for credit reset.\n"));
|
|
835
924
|
} else if (error.response?.data?.message) {
|
|
836
|
-
console.log(
|
|
925
|
+
console.log(chalk8.red(`
|
|
837
926
|
${error.response.data.message}
|
|
838
927
|
`));
|
|
839
928
|
} else {
|
|
840
|
-
console.log(
|
|
929
|
+
console.log(chalk8.red(`
|
|
841
930
|
${error.message}
|
|
842
931
|
`));
|
|
843
932
|
}
|
|
@@ -847,9 +936,9 @@ async function generateCommand(options) {
|
|
|
847
936
|
|
|
848
937
|
// src/commands/init.ts
|
|
849
938
|
import * as p from "@clack/prompts";
|
|
850
|
-
import
|
|
939
|
+
import chalk9 from "chalk";
|
|
851
940
|
async function initCommand(options) {
|
|
852
|
-
p.intro(
|
|
941
|
+
p.intro(chalk9.bgCyan.black(" AeroCoding CLI "));
|
|
853
942
|
if (!options.force && await configExists()) {
|
|
854
943
|
const overwrite = await p.confirm({
|
|
855
944
|
message: "Config file already exists. Overwrite?",
|
|
@@ -877,7 +966,7 @@ async function initCommand(options) {
|
|
|
877
966
|
process.exit(1);
|
|
878
967
|
}
|
|
879
968
|
let organizationId;
|
|
880
|
-
if (organizations.length === 1) {
|
|
969
|
+
if (organizations.length === 1 && organizations[0]) {
|
|
881
970
|
organizationId = organizations[0].id;
|
|
882
971
|
p.log.info(`Organization: ${organizations[0].name}`);
|
|
883
972
|
} else {
|
|
@@ -963,32 +1052,35 @@ async function initCommand(options) {
|
|
|
963
1052
|
};
|
|
964
1053
|
if (selectedTargets.includes("backend") && project.backendFramework) {
|
|
965
1054
|
const archSpinner = p.spinner();
|
|
966
|
-
archSpinner.start("Loading backend
|
|
967
|
-
const
|
|
968
|
-
|
|
969
|
-
|
|
1055
|
+
archSpinner.start("Loading backend templates...");
|
|
1056
|
+
const templateResult = await apiClient.getTemplates({
|
|
1057
|
+
category: "backend",
|
|
1058
|
+
language: project.backendFramework
|
|
1059
|
+
});
|
|
1060
|
+
archSpinner.stop("Templates loaded");
|
|
1061
|
+
if (templateResult.templates.length > 0) {
|
|
970
1062
|
const preset = await p.select({
|
|
971
|
-
message: "Backend
|
|
972
|
-
options:
|
|
973
|
-
value:
|
|
974
|
-
label:
|
|
975
|
-
hint:
|
|
1063
|
+
message: "Backend template",
|
|
1064
|
+
options: templateResult.templates.map((tmpl) => ({
|
|
1065
|
+
value: tmpl.id,
|
|
1066
|
+
label: tmpl.name,
|
|
1067
|
+
hint: tmpl.description || `${tmpl.tier} tier`
|
|
976
1068
|
}))
|
|
977
1069
|
});
|
|
978
1070
|
if (p.isCancel(preset)) {
|
|
979
1071
|
p.cancel("Operation cancelled.");
|
|
980
1072
|
process.exit(0);
|
|
981
1073
|
}
|
|
982
|
-
const
|
|
983
|
-
if (
|
|
1074
|
+
const fullTemplate = await apiClient.getTemplate(preset);
|
|
1075
|
+
if (fullTemplate.layers && fullTemplate.layers.length > 0) {
|
|
984
1076
|
const layers = await p.multiselect({
|
|
985
1077
|
message: "Select backend layers to include",
|
|
986
|
-
options:
|
|
1078
|
+
options: fullTemplate.layers.map((layer) => ({
|
|
987
1079
|
value: layer.id,
|
|
988
1080
|
label: layer.name,
|
|
989
1081
|
hint: layer.category
|
|
990
1082
|
})),
|
|
991
|
-
initialValues:
|
|
1083
|
+
initialValues: fullTemplate.layers.filter((l) => l.enabled).map((l) => l.id)
|
|
992
1084
|
});
|
|
993
1085
|
if (p.isCancel(layers)) {
|
|
994
1086
|
p.cancel("Operation cancelled.");
|
|
@@ -1008,32 +1100,35 @@ async function initCommand(options) {
|
|
|
1008
1100
|
}
|
|
1009
1101
|
if (selectedTargets.includes("frontend") && project.frontendFramework) {
|
|
1010
1102
|
const archSpinner = p.spinner();
|
|
1011
|
-
archSpinner.start("Loading frontend
|
|
1012
|
-
const
|
|
1013
|
-
|
|
1014
|
-
|
|
1103
|
+
archSpinner.start("Loading frontend templates...");
|
|
1104
|
+
const templateResult = await apiClient.getTemplates({
|
|
1105
|
+
category: "frontend",
|
|
1106
|
+
framework: project.frontendFramework
|
|
1107
|
+
});
|
|
1108
|
+
archSpinner.stop("Templates loaded");
|
|
1109
|
+
if (templateResult.templates.length > 0) {
|
|
1015
1110
|
const preset = await p.select({
|
|
1016
|
-
message: "Frontend
|
|
1017
|
-
options:
|
|
1018
|
-
value:
|
|
1019
|
-
label:
|
|
1020
|
-
hint:
|
|
1111
|
+
message: "Frontend template",
|
|
1112
|
+
options: templateResult.templates.map((tmpl) => ({
|
|
1113
|
+
value: tmpl.id,
|
|
1114
|
+
label: tmpl.name,
|
|
1115
|
+
hint: tmpl.description || `${tmpl.tier} tier`
|
|
1021
1116
|
}))
|
|
1022
1117
|
});
|
|
1023
1118
|
if (p.isCancel(preset)) {
|
|
1024
1119
|
p.cancel("Operation cancelled.");
|
|
1025
1120
|
process.exit(0);
|
|
1026
1121
|
}
|
|
1027
|
-
const
|
|
1028
|
-
if (
|
|
1122
|
+
const fullTemplate = await apiClient.getTemplate(preset);
|
|
1123
|
+
if (fullTemplate.layers && fullTemplate.layers.length > 0) {
|
|
1029
1124
|
const layers = await p.multiselect({
|
|
1030
1125
|
message: "Select frontend layers to include",
|
|
1031
|
-
options:
|
|
1126
|
+
options: fullTemplate.layers.map((layer) => ({
|
|
1032
1127
|
value: layer.id,
|
|
1033
1128
|
label: layer.name,
|
|
1034
1129
|
hint: layer.category
|
|
1035
1130
|
})),
|
|
1036
|
-
initialValues:
|
|
1131
|
+
initialValues: fullTemplate.layers.filter((l) => l.enabled).map((l) => l.id)
|
|
1037
1132
|
});
|
|
1038
1133
|
if (p.isCancel(layers)) {
|
|
1039
1134
|
p.cancel("Operation cancelled.");
|
|
@@ -1089,7 +1184,7 @@ async function initCommand(options) {
|
|
|
1089
1184
|
config.output = output;
|
|
1090
1185
|
await saveConfig(config);
|
|
1091
1186
|
p.outro(
|
|
1092
|
-
|
|
1187
|
+
chalk9.green("Config saved to .aerocodingrc.json") + "\n\n" + chalk9.gray(" Run ") + chalk9.cyan("aerocoding generate") + chalk9.gray(" to generate code!")
|
|
1093
1188
|
);
|
|
1094
1189
|
} catch (error) {
|
|
1095
1190
|
if (error.response?.status === 401) {
|
|
@@ -1104,20 +1199,20 @@ async function initCommand(options) {
|
|
|
1104
1199
|
}
|
|
1105
1200
|
|
|
1106
1201
|
// src/commands/pull.ts
|
|
1107
|
-
import
|
|
1202
|
+
import chalk10 from "chalk";
|
|
1108
1203
|
async function pullCommand(options) {
|
|
1109
|
-
console.log(
|
|
1204
|
+
console.log(chalk10.yellow("Command not yet implemented"));
|
|
1110
1205
|
if (options.project) {
|
|
1111
|
-
console.log(
|
|
1206
|
+
console.log(chalk10.gray(` Requested project: ${options.project}`));
|
|
1112
1207
|
}
|
|
1113
|
-
console.log(
|
|
1208
|
+
console.log(chalk10.gray(" Coming soon in v0.2.0\n"));
|
|
1114
1209
|
}
|
|
1115
1210
|
|
|
1116
1211
|
// src/commands/status.ts
|
|
1117
|
-
import
|
|
1212
|
+
import chalk11 from "chalk";
|
|
1118
1213
|
async function statusCommand() {
|
|
1119
|
-
console.log(
|
|
1120
|
-
console.log(
|
|
1214
|
+
console.log(chalk11.yellow("Command not yet implemented"));
|
|
1215
|
+
console.log(chalk11.gray(" Coming soon in v0.2.0\n"));
|
|
1121
1216
|
}
|
|
1122
1217
|
|
|
1123
1218
|
// src/index.ts
|
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.15\");\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(\"-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\nimport chalk from \"chalk\";\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 console.log(chalk.yellow(\"⏱️ Token expired, refreshing...\"));\r\n accessToken = await this.refreshTokens();\r\n }\r\n\r\n return accessToken;\r\n } catch (error) {\r\n console.error(chalk.red(\"Failed to get access token:\"), error);\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 console.log(chalk.green(\"Token refreshed successfully\"));\r\n\r\n return data.session.access_token;\r\n } catch (error) {\r\n console.error(chalk.red(\"Token refresh failed. Please login again.\"));\r\n await this.logout();\r\n throw error;\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 try {\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 } catch (error) {\r\n console.error(chalk.red(\"Failed to save tokens:\"), error);\r\n throw error;\r\n }\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 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 };\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\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 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 };\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","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 } 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 generator target\r\n * Presets follow naming convention: {architecture}-{language}-{variant}\r\n * e.g., \"clean-architecture-dotnet-complete\" → \"dotnet-entity\"\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 targets array from config file\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\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 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 // Build targets from config if not provided via CLI\r\n const targets = options.targets || buildTargetsFromConfig(config);\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: ${project.name}`));\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 (may fail if endpoint not deployed yet)\r\n let estimate: { estimatedCredits: number; totalFiles: number; entities: number } | null = null;\r\n try {\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 },\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: ${credits.remaining} / ${credits.limit} available`));\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 console.log(\r\n chalk.gray(\" Targets:\"),\r\n chalk.cyan(targets.length > 0 ? targets.join(\", \") : \"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 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 // Show estimate info (if available)\r\n if (estimate) {\r\n console.log(chalk.gray(\" Entities:\"), chalk.cyan(estimate.entities));\r\n console.log(chalk.gray(\" Files:\"), chalk.cyan(estimate.totalFiles));\r\n }\r\n\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(chalk.gray(\" Output:\"), chalk.cyan(output));\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 const result = await apiClient.generateCode({\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 },\r\n });\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));\r\n console.log(chalk.gray(\" Entities:\"), chalk.cyan(result.stats.totalEntities));\r\n console.log(\r\n chalk.gray(\" Languages:\"),\r\n chalk.cyan(result.stats.languages.join(\", \"))\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);\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 // Show error details for debugging\r\n console.log(chalk.gray(`\\n Error: ${error.response?.status || error.code || 'unknown'}`));\r\n if (error.response?.data) {\r\n console.log(chalk.gray(` Details: ${JSON.stringify(error.response.data)}`));\r\n }\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\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 * Write generated files to disk\r\n *\r\n * Creates directories as needed and writes files\r\n * Shows progress for each file\r\n */\r\nexport async function writeGeneratedFiles(\r\n files: GeneratedFile[],\r\n outputDir: string\r\n): Promise<void> {\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(\r\n chalk.red(` Skipping unsafe path: ${file.path}`)\r\n );\r\n console.error(\r\n chalk.gray(` Path traversal detected - file path must be within output directory`)\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 console.log(chalk.gray(` ${file.path}`));\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","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 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 .default({}),\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) {\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 architectures...\");\r\n const architectures = await apiClient.getArchitectures(project.backendFramework);\r\n archSpinner.stop(\"Architectures loaded\");\r\n\r\n if (architectures.length > 0) {\r\n const preset = await p.select({\r\n message: \"Backend architecture\",\r\n options: architectures.map((arch) => ({\r\n value: arch.id,\r\n label: arch.name,\r\n hint: arch.description,\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 const selectedArch = architectures.find((a) => a.id === preset);\r\n\r\n if (selectedArch && selectedArch.layers.length > 0) {\r\n const layers = await p.multiselect({\r\n message: \"Select backend layers to include\",\r\n options: selectedArch.layers.map((layer) => ({\r\n value: layer.id,\r\n label: layer.name,\r\n hint: layer.category,\r\n })),\r\n initialValues: selectedArch.layers.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 architectures...\");\r\n const architectures = await apiClient.getArchitectures(project.frontendFramework);\r\n archSpinner.stop(\"Architectures loaded\");\r\n\r\n if (architectures.length > 0) {\r\n const preset = await p.select({\r\n message: \"Frontend architecture\",\r\n options: architectures.map((arch) => ({\r\n value: arch.id,\r\n label: arch.name,\r\n hint: arch.description,\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 const selectedArch = architectures.find((a) => a.id === preset);\r\n\r\n if (selectedArch && selectedArch.layers.length > 0) {\r\n const layers = await p.multiselect({\r\n message: \"Select frontend layers to include\",\r\n options: selectedArch.layers.map((layer) => ({\r\n value: layer.id,\r\n label: layer.name,\r\n hint: layer.category,\r\n })),\r\n initialValues: selectedArch.layers.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. 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 // 8. 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 // 9. 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","chalk","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.15\");\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(\"-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 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 };\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 } 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 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: ${project.name}`));\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 (only for legacy mode with targets)\r\n // Template mode estimation not yet implemented on backend\r\n let estimate: { estimatedCredits: number; totalFiles: number; entities: number } | null = null;\r\n if (targets && targets.length > 0) {\r\n try {\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 },\r\n });\r\n } catch {\r\n // Estimate endpoint may not be available yet - continue without estimate\r\n }\r\n }\r\n\r\n spinner.succeed(chalk.gray(`Credits: ${credits.remaining} / ${credits.limit} available`));\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 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 // Show estimate info (if available)\r\n if (estimate) {\r\n console.log(chalk.gray(\" Entities:\"), chalk.cyan(estimate.entities));\r\n console.log(chalk.gray(\" Files:\"), chalk.cyan(estimate.totalFiles));\r\n }\r\n\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(chalk.gray(\" Output:\"), chalk.cyan(output));\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\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 },\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 },\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));\r\n console.log(chalk.gray(\" Entities:\"), chalk.cyan(result.stats.totalEntities));\r\n console.log(\r\n chalk.gray(\" Languages:\"),\r\n chalk.cyan(result.stats.languages.join(\", \"))\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);\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\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 * Write generated files to disk\r\n *\r\n * Creates directories as needed and writes files\r\n * Shows progress for each file\r\n */\r\nexport async function writeGeneratedFiles(\r\n files: GeneratedFile[],\r\n outputDir: string\r\n): Promise<void> {\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(\r\n chalk.red(` Skipping unsafe path: ${file.path}`)\r\n );\r\n console.error(\r\n chalk.gray(` Path traversal detected - file path must be within output directory`)\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 console.log(chalk.gray(` ${file.path}`));\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","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 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. 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 // 8. 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 // 9. Save config\r\n await saveConfig(config);\r\n\r\n p.outro(\r\n chalk.green(\"Config saved to .aerocodingrc.json\") +\r\n \"\\n\\n\" +\r\n chalk.gray(\" Run \") +\r\n chalk.cyan(\"aerocoding generate\") +\r\n chalk.gray(\" to generate code!\")\r\n );\r\n } catch (error: any) {\r\n if (error.response?.status === 401) {\r\n await handleUnauthorized(tokenManager);\r\n } else if (error.response?.data?.message) {\r\n p.cancel(error.response.data.message);\r\n } else {\r\n p.cancel(error.message || \"An unexpected error occurred\");\r\n }\r\n process.exit(1);\r\n }\r\n}\r\n","import chalk from \"chalk\";\r\n\r\ninterface PullOptions {\r\n project?: string;\r\n}\r\n\r\n/**\r\n * Pull Command (Stub)\r\n *\r\n * TODO: Pull schema from cloud\r\n * - Download project schema\r\n * - Save to .aerocoding/schema.json\r\n */\r\nexport async function pullCommand(options: PullOptions) {\r\n console.log(chalk.yellow(\"Command not yet implemented\"));\r\n if (options.project) {\r\n console.log(chalk.gray(` Requested project: ${options.project}`));\r\n }\r\n console.log(chalk.gray(\" Coming soon in v0.2.0\\n\"));\r\n}\r\n","import chalk from \"chalk\";\r\n\r\n/**\r\n * Status Command (Stub)\r\n *\r\n * TODO: Show local schema status\r\n * - Show current project\r\n * - Show schema stats\r\n * - Show sync status\r\n */\r\nexport async function statusCommand() {\r\n console.log(chalk.yellow(\"Command not yet implemented\"));\r\n console.log(chalk.gray(\" Coming soon in v0.2.0\\n\"));\r\n}\r\n"],"mappings":"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","names":["chalk","spinner","axios","API_URL","chalk","chalk","chalk","chalk","chalk","chalk","chalk","ora","chalk","chalk","fs","path","path","fs","chalk","spinner","ora","chalk","chalk","spinner","chalk","chalk"]}
|