aerocoding 0.1.23 → 0.1.24

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.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.23\");\r\n\r\n// ============================================\r\n// Authentication Commands\r\n// ============================================\r\n\r\nprogram\r\n .command(\"login\")\r\n .description(\"Authenticate with AeroCoding\")\r\n .action(loginCommand);\r\n\r\nprogram\r\n .command(\"logout\")\r\n .description(\"Logout and clear stored credentials\")\r\n .action(logoutCommand);\r\n\r\nprogram\r\n .command(\"whoami\")\r\n .description(\"Show current authenticated user\")\r\n .action(whoamiCommand);\r\n\r\n// ============================================\r\n// Project Commands\r\n// ============================================\r\n\r\nprogram\r\n .command(\"init\")\r\n .description(\"Initialize AeroCoding in current directory\")\r\n .option(\"-p, --project <id>\", \"Project ID (skip selection)\")\r\n .option(\"-f, --force\", \"Overwrite existing config without asking\")\r\n .action(initCommand);\r\n\r\nprogram\r\n .command(\"pull\")\r\n .description(\"Pull schema from cloud\")\r\n .option(\"-p, --project <id>\", \"Project ID\")\r\n .action(pullCommand);\r\n\r\nprogram\r\n .command(\"status\")\r\n .description(\"Show local schema status\")\r\n .action(statusCommand);\r\n\r\n// ============================================\r\n// Generation Commands\r\n// ============================================\r\n\r\nprogram\r\n .command(\"generate\")\r\n .alias(\"gen\")\r\n .description(\"Generate code from schema\")\r\n // Identification\r\n .option(\"-p, --project <id>\", \"Project ID\")\r\n .option(\"-t, --targets <targets...>\", \"Generation targets (e.g., dotnet-entity)\")\r\n .option(\"-e, --entities <entities...>\", \"Filter by entity names\")\r\n .option(\"-o, --output <dir>\", \"Output directory\", \"./.aerocoding\")\r\n // Presets & Layers\r\n .option(\"--backend-preset <preset>\", \"Backend architecture preset\")\r\n .option(\"--frontend-preset <preset>\", \"Frontend architecture preset\")\r\n .option(\"--backend-layers <layers...>\", \"Backend layers to generate\")\r\n .option(\"--frontend-layers <layers...>\", \"Frontend layers to generate\")\r\n // Code style toggles (optimistic defaults - all enabled by default)\r\n .option(\"--no-validations\", \"Exclude validations\")\r\n .option(\"--no-comments\", \"Exclude comments\")\r\n .option(\"--no-annotations\", \"Exclude annotations\")\r\n .option(\"--no-logging\", \"Exclude logging statements\")\r\n .option(\"--no-testing\", \"Exclude test files\")\r\n // Validation library (framework-agnostic)\r\n .option(\"--validation-lib <framework>\", \"Validation library (e.g., fluentvalidation, zod, formz)\")\r\n // Control\r\n .option(\"-v, --verbose\", \"Show all generated file paths\")\r\n .option(\"-y, --yes\", \"Skip confirmation prompt\")\r\n .option(\"-a, --all\", \"Generate all bounded contexts and targets without prompting\")\r\n .action(generateCommand);\r\n\r\n// ============================================\r\n// Parse and Execute\r\n// ============================================\r\n\r\nprogram.parse();\r\n","import chalk from \"chalk\";\r\nimport { DeviceFlow } from \"../auth/device-flow.js\";\r\nimport { TokenManager } from \"../auth/token-manager.js\";\r\nimport { createApiClientWithAutoLogout } from \"./_shared/create-api-client.js\";\r\nimport { handleUnauthorized } from \"./_shared/unauthorized.js\";\r\n\r\n/**\r\n * Login Command\r\n *\r\n * Authenticates user via OAuth Device Flow\r\n * Stores tokens securely in OS credential manager\r\n */\r\nexport async function loginCommand() {\r\n console.log(chalk.bold(\"\\nAeroCoding CLI Login\\n\"));\r\n\r\n const tokenManager = new TokenManager();\r\n\r\n // Check if already logged in\r\n const existingToken = await tokenManager.getAccessToken();\r\n if (existingToken) {\r\n const metadata = await tokenManager.getUserMetadata();\r\n console.log(\r\n chalk.yellow(\"Already logged in as:\"),\r\n chalk.white(metadata?.email || \"unknown\")\r\n );\r\n console.log(\r\n chalk.gray(\r\n \" Run 'aerocoding logout' to login with a different account\\n\"\r\n )\r\n );\r\n return;\r\n }\r\n\r\n try {\r\n // Initiate device flow\r\n const deviceFlow = new DeviceFlow();\r\n const tokens = await deviceFlow.initiateAuth();\r\n\r\n // Get user info\r\n const apiClient = createApiClientWithAutoLogout(\r\n tokens.access_token,\r\n tokenManager\r\n );\r\n let user;\r\n try {\r\n user = await apiClient.getCurrentUser();\r\n } catch (error: any) {\r\n if (error.response?.status === 401) {\r\n await handleUnauthorized(tokenManager);\r\n }\r\n throw error;\r\n }\r\n\r\n // Save tokens\r\n await tokenManager.saveTokens(tokens.access_token, tokens.refresh_token, {\r\n id: user.id,\r\n email: user.email,\r\n name: user.name || undefined,\r\n tier: user.tier,\r\n });\r\n\r\n console.log(\"\");\r\n console.log(\r\n chalk.green(\"Successfully logged in as:\"),\r\n chalk.white(user.email)\r\n );\r\n console.log(chalk.gray(\" Run 'aerocoding whoami' to verify\\n\"));\r\n } catch (error: any) {\r\n console.error(\r\n chalk.red(\"\\nLogin failed:\"),\r\n error.message || \"Unknown error\"\r\n );\r\n process.exit(1);\r\n }\r\n}\r\n","import axios from \"axios\";\r\nimport chalk from \"chalk\";\r\nimport ora from \"ora\";\r\nimport open from \"open\";\r\n\r\nconst API_URL = process.env.API_URL || \"https://aerocoding.dev\";\r\nconst MAX_POLL_TIME = 15 * 60 * 1000; // 15 minutes\r\n\r\ninterface DeviceAuthResponse {\r\n device_code: string;\r\n user_code: string;\r\n confirmation_code: string;\r\n verification_uri: string;\r\n verification_uri_complete: string;\r\n expires_in: number;\r\n interval: number;\r\n}\r\n\r\ninterface TokenResponse {\r\n access_token: string;\r\n refresh_token: string;\r\n token_type: string;\r\n expires_in: number;\r\n}\r\n\r\n/**\r\n * DeviceFlow\r\n *\r\n * Implements OAuth 2.0 Device Authorization Grant (RFC 8628)\r\n * Used for CLI authentication without browser-based redirects\r\n */\r\nexport class DeviceFlow {\r\n /**\r\n * Initiate the complete device authorization flow\r\n */\r\n async initiateAuth(): Promise<TokenResponse> {\r\n // Step 1: Request device code\r\n const deviceAuth = await this.requestDeviceCode();\r\n\r\n // Step 2: Display user code and open browser\r\n this.displayUserCode(deviceAuth);\r\n await this.openBrowser(deviceAuth.verification_uri);\r\n\r\n // Step 3: Poll for authorization\r\n const tokens = await this.pollForToken(deviceAuth);\r\n\r\n return tokens;\r\n }\r\n\r\n /**\r\n * Step 1: Request device code from server\r\n */\r\n private async requestDeviceCode(): Promise<DeviceAuthResponse> {\r\n try {\r\n const response = await axios.post(`${API_URL}/api/device/authorize`, {\r\n client_id: \"aerocoding-cli\",\r\n scope: \"generate:code projects:read\",\r\n });\r\n\r\n return response.data;\r\n } catch (error: any) {\r\n console.error(chalk.red(\"Failed to initiate device authorization\"));\r\n if (error.response) {\r\n console.error(\r\n chalk.red(`Error: ${error.response.data.error_description}`)\r\n );\r\n }\r\n throw new Error(\"Failed to initiate device authorization\");\r\n }\r\n }\r\n\r\n /**\r\n * Step 2: Display user code and instructions\r\n */\r\n private displayUserCode(auth: DeviceAuthResponse): void {\r\n console.log(\"\\n\");\r\n console.log(chalk.cyan(\"━\".repeat(60)));\r\n console.log(chalk.bold.white(\" AeroCoding CLI - Device Activation\"));\r\n console.log(chalk.cyan(\"━\".repeat(60)));\r\n console.log(\"\");\r\n console.log(chalk.white(\" 1. Open this URL in your browser:\"));\r\n console.log(chalk.cyan.bold(` ${auth.verification_uri}`));\r\n console.log(\"\");\r\n console.log(chalk.white(\" 2. Enter this code:\"));\r\n console.log(chalk.green.bold(` ${auth.user_code}`));\r\n console.log(\"\");\r\n console.log(\r\n chalk.gray(` Code expires in ${auth.expires_in / 60} minutes`)\r\n );\r\n console.log(chalk.cyan(\"━\".repeat(60)));\r\n console.log(\"\");\r\n }\r\n\r\n /**\r\n * Step 2.5: Open browser automatically\r\n */\r\n private async openBrowser(url: string): Promise<void> {\r\n try {\r\n await open(url);\r\n console.log(chalk.gray(\" Opening browser...\"));\r\n } catch {\r\n console.log(chalk.yellow(\" Could not open browser automatically\"));\r\n console.log(chalk.gray(\" Please open the URL manually\\n\"));\r\n }\r\n }\r\n\r\n /**\r\n * Step 3: Poll for token\r\n */\r\n private async pollForToken(auth: DeviceAuthResponse): Promise<TokenResponse> {\r\n const spinner = ora({\r\n text: \"Waiting for authorization...\",\r\n color: \"cyan\",\r\n }).start();\r\n\r\n const startTime = Date.now();\r\n let currentInterval = auth.interval * 1000;\r\n\r\n while (true) {\r\n // Check timeout\r\n if (Date.now() - startTime > MAX_POLL_TIME) {\r\n spinner.fail(chalk.red(\"Authorization timeout\"));\r\n throw new Error(\"Device authorization timed out\");\r\n }\r\n\r\n try {\r\n const response = await axios.post(`${API_URL}/api/device/token`, {\r\n device_code: auth.device_code,\r\n client_id: \"aerocoding-cli\",\r\n });\r\n\r\n spinner.succeed(chalk.green(\"Successfully authenticated!\"));\r\n return response.data;\r\n } catch (error: any) {\r\n const errorCode = error.response?.data?.error;\r\n const errorDescription = error.response?.data?.error_description;\r\n\r\n if (errorCode === \"authorization_pending\") {\r\n // Keep polling\r\n await this.sleep(currentInterval);\r\n continue;\r\n }\r\n\r\n if (errorCode === \"slow_down\") {\r\n // Increase poll interval by 5 seconds\r\n currentInterval += 5000;\r\n spinner.text = \"Polling... (slowed down to avoid spam)\";\r\n await this.sleep(currentInterval);\r\n continue;\r\n }\r\n\r\n if (errorCode === \"expired_token\") {\r\n spinner.fail(chalk.red(\"Authorization code expired\"));\r\n throw new Error(\"Device code expired. Please try again.\");\r\n }\r\n\r\n if (errorCode === \"access_denied\") {\r\n spinner.fail(chalk.red(\"Authorization denied\"));\r\n throw new Error(\"You denied the authorization request\");\r\n }\r\n\r\n // Unknown error\r\n spinner.fail(chalk.red(\"Authorization failed\"));\r\n console.error(\r\n chalk.red(`Error: ${errorDescription || \"Unknown error\"}`)\r\n );\r\n throw new Error(errorDescription || \"Unknown error\");\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Helper: Sleep for specified milliseconds\r\n */\r\n private sleep(ms: number): Promise<void> {\r\n return new Promise((resolve) => setTimeout(resolve, ms));\r\n }\r\n}\r\n","import { Entry } from \"@napi-rs/keyring\";\r\nimport { createClient, SupabaseClient } from \"@supabase/supabase-js\";\r\n\r\nconst SERVICE_NAME = \"aerocoding-cli\";\r\n\r\n// Public Supabase credentials (anon key is safe to expose)\r\nconst SUPABASE_URL = \"https://peqpttkvdpjgmduzacwl.supabase.co\";\r\nconst SUPABASE_ANON_KEY = \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InBlcXB0dGt2ZHBqZ21kdXphY3dsIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NjQyNjUxNzMsImV4cCI6MjA3OTg0MTE3M30.WAzqgZusGoOEHxidfHc1e4daBglG4DJG5LOXbqldWQA\";\r\n\r\ninterface UserMetadata {\r\n id: string;\r\n email: string;\r\n name?: string;\r\n tier?: string;\r\n}\r\n\r\n/**\r\n * Helper functions for keyring operations using Entry class\r\n */\r\nfunction getPassword(service: string, account: string): string | null {\r\n try {\r\n const entry = new Entry(service, account);\r\n return entry.getPassword();\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\nfunction setPassword(service: string, account: string, password: string): void {\r\n const entry = new Entry(service, account);\r\n entry.setPassword(password);\r\n}\r\n\r\nfunction deletePassword(service: string, account: string): void {\r\n try {\r\n const entry = new Entry(service, account);\r\n entry.deletePassword();\r\n } catch {\r\n // Ignore if entry doesn't exist\r\n }\r\n}\r\n\r\n/**\r\n * TokenManager\r\n *\r\n * Manages secure storage and automatic refresh of authentication tokens\r\n * Uses OS-level credential managers (Keychain/Credential Manager/Secret Service)\r\n */\r\nexport class TokenManager {\r\n private supabase: SupabaseClient;\r\n\r\n constructor() {\r\n this.supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY, {\r\n auth: {\r\n autoRefreshToken: false,\r\n persistSession: false,\r\n },\r\n });\r\n }\r\n\r\n /**\r\n * Get access token, automatically refreshing if expired\r\n */\r\n async getAccessToken(): Promise<string | null> {\r\n try {\r\n let accessToken = getPassword(SERVICE_NAME, \"access_token\");\r\n\r\n if (!accessToken) {\r\n return null;\r\n }\r\n\r\n // Check if expired\r\n if (this.isTokenExpired(accessToken)) {\r\n accessToken = await this.refreshTokens();\r\n }\r\n\r\n return accessToken;\r\n } catch {\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * Refresh tokens using stored refresh token\r\n */\r\n private async refreshTokens(): Promise<string | null> {\r\n try {\r\n const refreshToken = getPassword(SERVICE_NAME, \"refresh_token\");\r\n\r\n if (!refreshToken) {\r\n throw new Error(\"No refresh token available\");\r\n }\r\n\r\n const { data, error } = await this.supabase.auth.refreshSession({\r\n refresh_token: refreshToken,\r\n });\r\n\r\n if (error || !data.session) {\r\n throw new Error(\"Failed to refresh session\");\r\n }\r\n\r\n // Store new tokens (single-use refresh token rotation)\r\n setPassword(SERVICE_NAME, \"access_token\", data.session.access_token);\r\n setPassword(SERVICE_NAME, \"refresh_token\", data.session.refresh_token);\r\n\r\n return data.session.access_token;\r\n } catch {\r\n await this.logout();\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * Check if JWT token is expired (or expires in < 5 min)\r\n */\r\n private isTokenExpired(token: string): boolean {\r\n try {\r\n const payload = JSON.parse(\r\n Buffer.from(token.split(\".\")[1]!, \"base64\").toString()\r\n );\r\n const expiresAt = payload.exp * 1000;\r\n const now = Date.now();\r\n\r\n // Refresh 5 minutes before expiration\r\n return expiresAt - now < 5 * 60 * 1000;\r\n } catch {\r\n return true; // Treat invalid tokens as expired\r\n }\r\n }\r\n\r\n /**\r\n * Save tokens and user metadata after successful login\r\n */\r\n async saveTokens(\r\n accessToken: string,\r\n refreshToken: string,\r\n user: UserMetadata\r\n ): Promise<void> {\r\n setPassword(SERVICE_NAME, \"access_token\", accessToken);\r\n setPassword(SERVICE_NAME, \"refresh_token\", refreshToken);\r\n setPassword(SERVICE_NAME, \"user_metadata\", JSON.stringify(user));\r\n }\r\n\r\n /**\r\n * Get stored user metadata\r\n */\r\n async getUserMetadata(): Promise<UserMetadata | null> {\r\n try {\r\n const metadata = getPassword(SERVICE_NAME, \"user_metadata\");\r\n return metadata ? JSON.parse(metadata) : null;\r\n } catch {\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * Logout - clear all stored credentials\r\n */\r\n async logout(): Promise<void> {\r\n try {\r\n deletePassword(SERVICE_NAME, \"access_token\");\r\n deletePassword(SERVICE_NAME, \"refresh_token\");\r\n deletePassword(SERVICE_NAME, \"user_metadata\");\r\n } catch (error) {\r\n // Ignore errors during logout\r\n }\r\n }\r\n\r\n /**\r\n * Check if user is currently authenticated\r\n */\r\n async isAuthenticated(): Promise<boolean> {\r\n const token = await this.getAccessToken();\r\n return token !== null;\r\n }\r\n}\r\n","import axios, { AxiosInstance } from \"axios\";\r\n\r\n// Production API URL (can be overridden via API_URL env for local dev)\r\nconst API_URL = process.env.API_URL || \"https://aerocoding.dev\";\r\n\r\ninterface User {\r\n id: string;\r\n email: string;\r\n name: string | null;\r\n tier: string;\r\n}\r\n\r\ninterface Organization {\r\n id: string;\r\n name: string;\r\n slug: string;\r\n planTier: string;\r\n}\r\n\r\ninterface Project {\r\n id: string;\r\n name: string;\r\n slug: string;\r\n schema: any;\r\n organizationId: string;\r\n backendFramework?: string;\r\n frontendFramework?: string;\r\n createdAt: string;\r\n updatedAt: string;\r\n}\r\n\r\ninterface GeneratePayload {\r\n projectId: string;\r\n // NEW: Use templateId for full architecture generation\r\n templateId?: string;\r\n // Legacy: Use targets for simple generation\r\n targets?: string[];\r\n options?: {\r\n includeValidations?: boolean;\r\n includeComments?: boolean;\r\n includeAnnotations?: boolean;\r\n includeLogging?: boolean;\r\n includeTesting?: boolean;\r\n outputDir?: string;\r\n backendPreset?: string;\r\n frontendPreset?: string;\r\n backendLayers?: string[];\r\n frontendLayers?: string[];\r\n validationLib?: string;\r\n // NEW: Feature flags for template generation\r\n featureFlags?: Record<string, boolean>;\r\n // Architecture style: bounded-contexts vs flat\r\n useContexts?: boolean;\r\n // Filter by diagram/bounded context IDs\r\n diagramIds?: string[];\r\n };\r\n}\r\n\r\ninterface GeneratedFile {\r\n path: string;\r\n content: string;\r\n language: string;\r\n entityId?: string;\r\n}\r\n\r\ninterface GenerateResult {\r\n files: GeneratedFile[];\r\n stats?: {\r\n totalFiles?: number;\r\n totalEntities?: number;\r\n languages?: string[];\r\n };\r\n cliCommand?: string;\r\n warnings?: string[];\r\n creditsUsed?: number;\r\n creditsRemaining?: number;\r\n}\r\n\r\ninterface CreditUsage {\r\n used: number;\r\n limit: number;\r\n bonusCredits: number;\r\n remaining: number;\r\n}\r\n\r\ninterface ArchitectureLayer {\r\n id: string;\r\n name: string;\r\n category: string;\r\n description?: string;\r\n}\r\n\r\ninterface Architecture {\r\n id: string;\r\n name: string;\r\n description: string;\r\n layers: ArchitectureLayer[];\r\n}\r\n\r\n// New Template Registry Types\r\ninterface TemplateMetadata {\r\n id: string;\r\n name: string;\r\n description: string;\r\n category: \"backend\" | \"frontend\" | \"database\" | \"infra\";\r\n language: string;\r\n framework: string;\r\n tier: \"starter\" | \"standard\" | \"enterprise\";\r\n tags: string[];\r\n version: string;\r\n author: string;\r\n isLegacy?: boolean;\r\n isOfficial?: boolean;\r\n isPremium?: boolean;\r\n /** Architecture style: \"bounded-contexts\" for DDD modules, \"flat\" for single structure */\r\n architectureStyle?: \"bounded-contexts\" | \"flat\";\r\n}\r\n\r\ninterface TemplateLayer {\r\n id: string;\r\n name: string;\r\n description: string;\r\n category: string;\r\n enabled: boolean;\r\n}\r\n\r\ninterface TemplateFeatureFlag {\r\n id: string;\r\n name: string;\r\n label: string;\r\n description?: string;\r\n defaultValue: boolean;\r\n}\r\n\r\ninterface FullTemplate extends TemplateMetadata {\r\n layers: TemplateLayer[];\r\n featureFlags: TemplateFeatureFlag[];\r\n enabledModules: string[];\r\n}\r\n\r\ninterface TemplateFilter {\r\n category?: \"backend\" | \"frontend\" | \"database\" | \"infra\";\r\n language?: string;\r\n framework?: string;\r\n tier?: \"starter\" | \"standard\" | \"enterprise\";\r\n tags?: string[];\r\n}\r\n\r\ninterface TemplateSearchResult {\r\n templates: TemplateMetadata[];\r\n total: number;\r\n page: number;\r\n pageSize: number;\r\n}\r\n\r\ninterface TemplateCombination {\r\n id: string;\r\n name: string;\r\n description: string;\r\n backend: string;\r\n frontend: string;\r\n sharedTypes?: boolean;\r\n apiContract?: \"rest\" | \"graphql\" | \"grpc\";\r\n}\r\n\r\ninterface CreditEstimate {\r\n estimatedCredits: number;\r\n totalFiles: number;\r\n files: string[];\r\n entities: number;\r\n}\r\n\r\ninterface EstimatePayload {\r\n projectId: string;\r\n // Template mode (new)\r\n templateId?: string;\r\n // Legacy targets mode\r\n targets?: string[];\r\n options?: {\r\n outputDir?: string;\r\n backendPreset?: string;\r\n frontendPreset?: string;\r\n backendLayers?: string[];\r\n frontendLayers?: string[];\r\n featureFlags?: Record<string, boolean>;\r\n // Architecture style: bounded-contexts vs flat\r\n useContexts?: boolean;\r\n // Filter by diagram/bounded context IDs\r\n diagramIds?: string[];\r\n };\r\n}\r\n\r\n/**\r\n * ApiClient\r\n *\r\n * Authenticated HTTP client for AeroCoding API\r\n * All requests include Bearer token authentication\r\n */\r\nexport class ApiClient {\r\n private client: AxiosInstance;\r\n\r\n constructor(\r\n accessToken: string,\r\n options?: {\r\n onUnauthorized?: () => Promise<void> | void;\r\n }\r\n ) {\r\n this.client = axios.create({\r\n baseURL: API_URL,\r\n headers: {\r\n Authorization: `Bearer ${accessToken}`,\r\n \"Content-Type\": \"application/json\",\r\n \"X-Requested-With\": \"XMLHttpRequest\", // Required for CSRF validation bypass\r\n },\r\n timeout: 30000, // 30 seconds\r\n });\r\n\r\n this.client.interceptors.response.use(\r\n (response) => response,\r\n async (error) => {\r\n if (error?.response?.status === 401) {\r\n await options?.onUnauthorized?.();\r\n }\r\n\r\n return Promise.reject(error);\r\n }\r\n );\r\n }\r\n\r\n /**\r\n * Get current authenticated user\r\n */\r\n async getCurrentUser(): Promise<User> {\r\n const response = await this.client.get(\"/api/user/me\");\r\n return response.data;\r\n }\r\n\r\n /**\r\n * List user's organizations\r\n */\r\n async listOrganizations(): Promise<Organization[]> {\r\n const response = await this.client.get(\"/api/organizations\");\r\n return response.data;\r\n }\r\n\r\n /**\r\n * List user's projects\r\n */\r\n async listProjects(organizationId?: string): Promise<Project[]> {\r\n const response = await this.client.get(\"/api/projects\", {\r\n params: { organizationId },\r\n });\r\n return response.data;\r\n }\r\n\r\n /**\r\n * Get project by ID\r\n */\r\n async getProject(projectId: string): Promise<Project> {\r\n const response = await this.client.get(`/api/projects/${projectId}`);\r\n return response.data;\r\n }\r\n\r\n /**\r\n * Generate code from project schema\r\n */\r\n async generateCode(payload: GeneratePayload): Promise<GenerateResult> {\r\n const response = await this.client.post(\"/api/generate\", payload);\r\n return response.data.data;\r\n }\r\n\r\n /**\r\n * Get credit usage for organization\r\n */\r\n async getCreditUsage(organizationId: string): Promise<CreditUsage> {\r\n const response = await this.client.get(\"/api/credits/usage\", {\r\n params: { organizationId },\r\n });\r\n return response.data;\r\n }\r\n\r\n /**\r\n * Get available architectures for a framework\r\n */\r\n async getArchitectures(framework: string): Promise<Architecture[]> {\r\n const response = await this.client.get(\"/api/architectures\", {\r\n params: { framework },\r\n });\r\n return response.data;\r\n }\r\n\r\n /**\r\n * Estimate credit cost for a generation request\r\n */\r\n async estimateCreditCost(payload: EstimatePayload): Promise<CreditEstimate> {\r\n const response = await this.client.post(\"/api/generate/estimate\", payload);\r\n return response.data.data;\r\n }\r\n\r\n // ============================================\r\n // Template Registry API\r\n // ============================================\r\n\r\n /**\r\n * Search templates with filters\r\n */\r\n async getTemplates(filter: TemplateFilter = {}): Promise<TemplateSearchResult> {\r\n const params = new URLSearchParams();\r\n if (filter.category) params.set(\"category\", filter.category);\r\n if (filter.language) params.set(\"language\", filter.language);\r\n if (filter.framework) params.set(\"framework\", filter.framework);\r\n if (filter.tier) params.set(\"tier\", filter.tier);\r\n if (filter.tags?.length) params.set(\"tags\", filter.tags.join(\",\"));\r\n\r\n const response = await this.client.get(`/api/templates?${params.toString()}`);\r\n return response.data;\r\n }\r\n\r\n /**\r\n * Get full template by ID (includes layers and feature flags)\r\n */\r\n async getTemplate(id: string): Promise<FullTemplate> {\r\n const response = await this.client.get(`/api/templates/${id}?full=true`);\r\n return response.data.template;\r\n }\r\n\r\n /**\r\n * Get template combinations (backend + frontend pairs)\r\n */\r\n async getTemplateCombinations(): Promise<TemplateCombination[]> {\r\n const response = await this.client.get(\"/api/templates/combinations\");\r\n return response.data.combinations;\r\n }\r\n\r\n /**\r\n * Get templates compatible with a given template\r\n */\r\n async getCompatibleTemplates(templateId: string): Promise<TemplateMetadata[]> {\r\n const response = await this.client.get(`/api/templates/${templateId}?compatible=true`);\r\n return response.data.compatible || [];\r\n }\r\n}\r\n","import { ApiClient } from \"../../api/client.js\";\r\nimport { TokenManager } from \"../../auth/token-manager.js\";\r\n\r\nexport function createApiClientWithAutoLogout(\r\n accessToken: string,\r\n tokenManager: TokenManager\r\n): ApiClient {\r\n return new ApiClient(accessToken, {\r\n onUnauthorized: async () => {\r\n await tokenManager.logout();\r\n },\r\n });\r\n}\r\n","import chalk from \"chalk\";\r\nimport { TokenManager } from \"../../auth/token-manager.js\";\r\n\r\nexport async function handleUnauthorized(\r\n tokenManager: TokenManager\r\n): Promise<never> {\r\n await tokenManager.logout();\r\n\r\n console.error(\r\n chalk.yellow(\r\n \" Your session is invalid or expired. You have been logged out.\"\r\n )\r\n );\r\n console.error(chalk.gray(\" Run 'aerocoding login' to authenticate.\"));\r\n\r\n process.exit(1);\r\n}\r\n","import chalk from \"chalk\";\r\nimport { TokenManager } from \"../auth/token-manager.js\";\r\n\r\n/**\r\n * Logout Command\r\n *\r\n * Clears stored credentials from OS credential manager\r\n */\r\nexport async function logoutCommand() {\r\n const tokenManager = new TokenManager();\r\n\r\n const metadata = await tokenManager.getUserMetadata();\r\n if (!metadata) {\r\n console.log(chalk.yellow(\"Not logged in\"));\r\n return;\r\n }\r\n\r\n const email = metadata.email;\r\n\r\n await tokenManager.logout();\r\n\r\n console.log(chalk.green(\"Logged out successfully\"));\r\n console.log(chalk.gray(` Cleared credentials for ${email}\\n`));\r\n}\r\n","import chalk from \"chalk\";\r\nimport { TokenManager } from \"../auth/token-manager.js\";\r\nimport { createApiClientWithAutoLogout } from \"./_shared/create-api-client.js\";\r\nimport { handleUnauthorized } from \"./_shared/unauthorized.js\";\r\n\r\n/**\r\n * Whoami Command\r\n *\r\n * Shows current authenticated user information\r\n */\r\nexport async function whoamiCommand() {\r\n const tokenManager = new TokenManager();\r\n const token = await tokenManager.getAccessToken();\r\n\r\n if (!token) {\r\n console.log(chalk.red(\"Not logged in\"));\r\n console.log(chalk.gray(\" Run 'aerocoding login' to authenticate\\n\"));\r\n return;\r\n }\r\n\r\n try {\r\n const apiClient = createApiClientWithAutoLogout(token, tokenManager);\r\n const user = await apiClient.getCurrentUser();\r\n\r\n console.log(\"\");\r\n console.log(chalk.white(\"Logged in as:\"), chalk.cyan.bold(user.email));\r\n if (user.name) {\r\n console.log(chalk.gray(\" Name:\"), user.name);\r\n }\r\n console.log(\"\");\r\n } catch (error: any) {\r\n console.error(chalk.red(\"Failed to get user info\"));\r\n if (error.response?.status === 401) {\r\n await handleUnauthorized(tokenManager);\r\n }\r\n process.exit(1);\r\n }\r\n}\r\n","import chalk from \"chalk\";\r\nimport ora from \"ora\";\r\nimport * as p from \"@clack/prompts\";\r\nimport { TokenManager } from \"../auth/token-manager.js\";\r\nimport { createApiClientWithAutoLogout } from \"./_shared/create-api-client.js\";\r\nimport { handleUnauthorized } from \"./_shared/unauthorized.js\";\r\nimport { writeGeneratedFiles, categorizeFilePaths } from \"../utils/file-writer.js\";\r\nimport { promptConfirm } from \"../utils/prompt.js\";\r\nimport { loadConfig } from \"../config/loader.js\";\r\nimport type { AerocodingConfig } from \"../config/schema.js\";\r\n\r\n/**\r\n * Map preset name to template ID for full architecture generation\r\n * Uses the new template system that generates all layers (DTOs, UseCases, Controllers, etc.)\r\n */\r\nfunction mapPresetToTemplateId(preset: string): string | null {\r\n const presetLower = preset.toLowerCase();\r\n\r\n // Clean Architecture presets → full template IDs\r\n if (presetLower.includes(\"clean\") && presetLower.includes(\"dotnet\")) {\r\n return \"clean-arch-dotnet\";\r\n }\r\n if (presetLower.includes(\"clean\") && (presetLower.includes(\"dart\") || presetLower.includes(\"flutter\"))) {\r\n return \"flutter-clean-dart-test\"; // Update when production template available\r\n }\r\n if (presetLower.includes(\"clean\") && presetLower.includes(\"typescript\")) {\r\n return \"minimal-typescript-test\"; // Update when production template available\r\n }\r\n\r\n // Direct template ID (if preset matches a template ID pattern)\r\n if (presetLower.startsWith(\"clean-arch-\")) {\r\n return preset;\r\n }\r\n\r\n return null;\r\n}\r\n\r\n/**\r\n * Map preset name to legacy generator target (fallback)\r\n * Used when no template ID is available for the preset\r\n */\r\nfunction mapPresetToTarget(preset: string): string | null {\r\n const presetLower = preset.toLowerCase();\r\n\r\n // .NET presets\r\n if (presetLower.includes(\"dotnet\") || presetLower.includes(\"aspnet\") || presetLower.includes(\"csharp\")) {\r\n return \"dotnet-entity\";\r\n }\r\n\r\n // Dart/Flutter presets\r\n if (presetLower.includes(\"dart\") || presetLower.includes(\"flutter\")) {\r\n return \"dart-entity\";\r\n }\r\n\r\n // TypeScript presets\r\n if (presetLower.includes(\"typescript\") || presetLower.includes(\"nextjs\") || presetLower.includes(\"react\")) {\r\n return \"typescript-interface\";\r\n }\r\n\r\n return null;\r\n}\r\n\r\n\r\n/**\r\n * Build feature flags from config for template generation\r\n */\r\nfunction buildFeatureFlagsFromConfig(config: AerocodingConfig | null): Record<string, boolean> {\r\n const flags: Record<string, boolean> = {\r\n // Default all feature flags to true for full architecture\r\n includeDtos: true,\r\n includeUseCases: true,\r\n includeMappers: true,\r\n includeControllers: true,\r\n includeEfConfig: true,\r\n includeValidation: true,\r\n includeDtoValidation: true, // Data Annotations on Input records ([Required], [MaxLength], etc.)\r\n // Test flags\r\n includeUnitTests: true,\r\n includeIntegrationTests: true,\r\n // Starter files (disabled by default - user adds their own Program.cs)\r\n includeStarterFiles: false,\r\n };\r\n\r\n if (!config) return flags;\r\n\r\n // Map codeStyle options to feature flags\r\n if (config.codeStyle?.includeValidations !== undefined) {\r\n flags.includeValidation = config.codeStyle.includeValidations;\r\n }\r\n // Map includeTesting to both unit and integration tests\r\n if (config.codeStyle?.includeTesting !== undefined) {\r\n flags.includeUnitTests = config.codeStyle.includeTesting;\r\n flags.includeIntegrationTests = config.codeStyle.includeTesting;\r\n }\r\n\r\n return flags;\r\n}\r\n\r\ninterface GenerateOptions {\r\n project?: string;\r\n targets?: string[];\r\n entities?: string[];\r\n output: string;\r\n // Presets\r\n backendPreset?: string;\r\n frontendPreset?: string;\r\n // Style toggles (commander inverts for --no-X, all default to true)\r\n validations?: boolean;\r\n comments?: boolean;\r\n logging?: boolean;\r\n testing?: boolean;\r\n // Validation library (framework-agnostic)\r\n validationLib?: string;\r\n // Control\r\n verbose?: boolean;\r\n yes?: boolean;\r\n all?: boolean; // Generate all diagrams and targets without prompting\r\n}\r\n\r\n/**\r\n * Generate Command\r\n *\r\n * Generates code from project schema via API\r\n * Consumes credits based on generated files and entity complexity\r\n *\r\n * Config file (.aerocodingrc.json) provides defaults, CLI args override\r\n */\r\nexport async function generateCommand(options: GenerateOptions) {\r\n // 1. Check authentication\r\n const tokenManager = new TokenManager();\r\n const token = await tokenManager.getAccessToken();\r\n\r\n if (!token) {\r\n console.log(chalk.red(\"\\n Not authenticated\"));\r\n console.log(chalk.gray(\" Run 'aerocoding login' to get started\\n\"));\r\n process.exit(1);\r\n }\r\n\r\n // 2. Load config file (optional)\r\n const config = await loadConfig();\r\n\r\n // 3. Merge config with CLI options (CLI overrides config)\r\n const projectId = options.project || config?.project;\r\n\r\n if (!projectId) {\r\n console.log(chalk.red(\"\\n Project ID required\"));\r\n console.log(chalk.gray(\" Run 'aerocoding init' to create a config file\"));\r\n console.log(chalk.gray(\" Or use --project <id> to specify a project\\n\"));\r\n process.exit(1);\r\n }\r\n\r\n // Merge other options with config defaults (templateId will be determined after target selection)\r\n const output = options.output || config?.output || \"./.aerocoding\";\r\n const validationLib = options.validationLib || config?.libraries?.validation;\r\n\r\n // Style options: CLI --no-X overrides config, config overrides default (true)\r\n const includeValidations = options.validations ?? config?.codeStyle?.includeValidations ?? true;\r\n const includeComments = options.comments ?? config?.codeStyle?.includeComments ?? true;\r\n const includeLogging = options.logging ?? config?.codeStyle?.includeLogging ?? true;\r\n const includeTesting = options.testing ?? config?.codeStyle?.includeTesting ?? true;\r\n\r\n const apiClient = createApiClientWithAutoLogout(token, tokenManager);\r\n\r\n let spinner = ora({ text: \"Fetching project...\", color: \"cyan\" }).start();\r\n\r\n try {\r\n // 4. Fetch project to get organizationId\r\n const project = await apiClient.getProject(projectId);\r\n spinner.succeed(chalk.gray(\"Project loaded\"));\r\n\r\n // 4a. Target selection (backend/frontend) - only if both configured\r\n const hasBackendConfig = !!config?.backend?.preset;\r\n const hasFrontendConfig = !!config?.frontend?.preset;\r\n const hasBothTargets = hasBackendConfig && hasFrontendConfig;\r\n\r\n let selectedTarget: \"backend\" | \"frontend\" | \"both\" = \"both\";\r\n\r\n if (hasBothTargets && !options.all) {\r\n const targetChoice = await p.select({\r\n message: \"Which target do you want to generate?\",\r\n options: [\r\n {\r\n value: \"backend\",\r\n label: `Backend (${config?.backend?.preset})`,\r\n hint: \"Recommended\",\r\n },\r\n {\r\n value: \"frontend\",\r\n label: `Frontend (${config?.frontend?.preset})`,\r\n },\r\n {\r\n value: \"both\",\r\n label: \"Both\",\r\n },\r\n ],\r\n initialValue: \"backend\",\r\n });\r\n\r\n if (p.isCancel(targetChoice)) {\r\n console.log(chalk.yellow(\"\\n Generation cancelled\\n\"));\r\n process.exit(0);\r\n }\r\n\r\n selectedTarget = targetChoice as \"backend\" | \"frontend\" | \"both\";\r\n } else if (hasBackendConfig && !hasFrontendConfig) {\r\n selectedTarget = \"backend\";\r\n } else if (hasFrontendConfig && !hasBackendConfig) {\r\n selectedTarget = \"frontend\";\r\n }\r\n\r\n // 4b. Diagram selection - only if multiple diagrams exist\r\n interface Diagram {\r\n id?: string;\r\n name?: string;\r\n entities?: unknown[];\r\n }\r\n const diagrams: Diagram[] = (project.schema as { diagrams?: Diagram[] })?.diagrams || [];\r\n const hasMultipleDiagrams = diagrams.length > 1;\r\n\r\n let selectedDiagramIds: string[] = diagrams.map((d) => d.id || d.name || \"unknown\");\r\n\r\n if (hasMultipleDiagrams && !options.all) {\r\n const diagramChoices = await p.multiselect({\r\n message: \"Which bounded contexts do you want to generate?\",\r\n options: diagrams.map((d) => ({\r\n value: d.id || d.name || \"unknown\",\r\n label: `${d.name || \"Unnamed\"} (${d.entities?.length || 0} entities)`,\r\n })),\r\n initialValues: diagrams.map((d) => d.id || d.name || \"unknown\"),\r\n required: true,\r\n });\r\n\r\n if (p.isCancel(diagramChoices)) {\r\n console.log(chalk.yellow(\"\\n Generation cancelled\\n\"));\r\n process.exit(0);\r\n }\r\n\r\n selectedDiagramIds = diagramChoices as string[];\r\n }\r\n\r\n // 4c. Build templateId, targets, featureFlags based on selected target\r\n let templateId: string | null = null;\r\n let targets: string[] = [];\r\n let backendPreset: string | undefined;\r\n let frontendPreset: string | undefined;\r\n\r\n if (selectedTarget === \"backend\" || selectedTarget === \"both\") {\r\n backendPreset = options.backendPreset || config?.backend?.preset;\r\n if (backendPreset) {\r\n const tid = mapPresetToTemplateId(backendPreset);\r\n if (tid) templateId = tid;\r\n const target = mapPresetToTarget(backendPreset);\r\n if (target) targets.push(target);\r\n }\r\n }\r\n\r\n if (selectedTarget === \"frontend\" || selectedTarget === \"both\") {\r\n frontendPreset = options.frontendPreset || config?.frontend?.preset;\r\n if (frontendPreset) {\r\n const tid = mapPresetToTemplateId(frontendPreset);\r\n if (tid && !templateId) templateId = tid; // Only if backend didn't set one\r\n const target = mapPresetToTarget(frontendPreset);\r\n if (target) targets.push(target);\r\n }\r\n }\r\n\r\n // Fallback: if no config, try CLI options for targets\r\n if (!templateId && (!targets || targets.length === 0)) {\r\n targets = options.targets || [];\r\n }\r\n\r\n // Build feature flags from config\r\n const featureFlags = buildFeatureFlagsFromConfig(config);\r\n\r\n // 5. Fetch credit usage and estimate cost in parallel\r\n spinner = ora({ text: \"Checking credits...\", color: \"cyan\" }).start();\r\n\r\n const credits = await apiClient.getCreditUsage(project.organizationId);\r\n\r\n // Try to get cost estimate (includes file paths for preview)\r\n // Determine architecture style early for estimate\r\n const useContexts = config?.architectureStyle !== \"flat\";\r\n\r\n // Include diagramIds to filter estimate by selected bounded contexts\r\n const estimateDiagramIds = selectedDiagramIds.length < diagrams.length ? selectedDiagramIds : undefined;\r\n\r\n let estimate: { estimatedCredits: number; totalFiles: number; entities: number; files: string[] } | null = null;\r\n try {\r\n if (templateId) {\r\n // Template mode: estimate using templateId\r\n estimate = await apiClient.estimateCreditCost({\r\n projectId,\r\n templateId,\r\n options: {\r\n featureFlags,\r\n useContexts,\r\n diagramIds: estimateDiagramIds,\r\n },\r\n });\r\n } else if (targets && targets.length > 0) {\r\n // Legacy mode: estimate using targets\r\n estimate = await apiClient.estimateCreditCost({\r\n projectId,\r\n targets,\r\n options: {\r\n outputDir: output,\r\n backendPreset,\r\n frontendPreset,\r\n useContexts,\r\n diagramIds: estimateDiagramIds,\r\n },\r\n });\r\n }\r\n } catch {\r\n // Estimate endpoint may not be available yet - continue without estimate\r\n }\r\n\r\n spinner.succeed(chalk.gray(\"Credits verified\"));\r\n\r\n // Check if project has entities (required for generation)\r\n if (estimate && estimate.entities === 0) {\r\n console.log(chalk.yellow(\"\\n ⚠ No entities found in this project.\"));\r\n console.log(chalk.gray(\" Create entities in the diagram editor and save (Ctrl+S) before generating.\\n\"));\r\n process.exit(1);\r\n }\r\n\r\n // Check if enough credits before showing summary (skip if no estimate)\r\n const hasEnoughCredits = estimate ? credits.remaining >= estimate.estimatedCredits : true;\r\n\r\n // 6. Show summary\r\n console.log(\"\");\r\n console.log(chalk.bold(\" Generation Summary\"));\r\n console.log(chalk.gray(\" ─────────────────────────────────\"));\r\n console.log(chalk.gray(\" Project:\"), chalk.white(project.name));\r\n if (config) {\r\n console.log(chalk.gray(\" Config:\"), chalk.cyan(\".aerocodingrc.json\"));\r\n }\r\n // Show generation mode\r\n if (templateId) {\r\n console.log(chalk.gray(\" Mode:\"), chalk.green(\"Full Architecture\"));\r\n console.log(chalk.gray(\" Template:\"), chalk.cyan(templateId));\r\n } else if (targets && targets.length > 0) {\r\n console.log(chalk.gray(\" Mode:\"), chalk.yellow(\"Simple (legacy)\"));\r\n console.log(chalk.gray(\" Targets:\"), chalk.cyan(targets.join(\", \")));\r\n } else {\r\n console.log(chalk.gray(\" Mode:\"), chalk.gray(\"default\"));\r\n }\r\n\r\n // Show selected target (if user had a choice)\r\n if (hasBothTargets) {\r\n const targetLabel =\r\n selectedTarget === \"backend\"\r\n ? \"Backend only\"\r\n : selectedTarget === \"frontend\"\r\n ? \"Frontend only\"\r\n : \"Backend + Frontend\";\r\n console.log(chalk.gray(\" Target:\"), chalk.cyan(targetLabel));\r\n }\r\n\r\n if (backendPreset && (selectedTarget === \"backend\" || selectedTarget === \"both\")) {\r\n console.log(chalk.gray(\" Backend Preset:\"), chalk.cyan(backendPreset));\r\n }\r\n if (frontendPreset && (selectedTarget === \"frontend\" || selectedTarget === \"both\")) {\r\n console.log(chalk.gray(\" Frontend Preset:\"), chalk.cyan(frontendPreset));\r\n }\r\n\r\n // Show selected diagrams (if user had a choice)\r\n if (hasMultipleDiagrams) {\r\n const selectedCount = selectedDiagramIds.length;\r\n const totalCount = diagrams.length;\r\n if (selectedCount === totalCount) {\r\n console.log(chalk.gray(\" Bounded Contexts:\"), chalk.cyan(`All (${totalCount})`));\r\n } else {\r\n const selectedNames = diagrams\r\n .filter((d) => selectedDiagramIds.includes(d.id || d.name || \"unknown\"))\r\n .map((d) => d.name || \"Unnamed\")\r\n .join(\", \");\r\n console.log(chalk.gray(\" Bounded Contexts:\"), chalk.cyan(`${selectedCount}/${totalCount} (${selectedNames})`));\r\n }\r\n }\r\n\r\n // Show architecture style\r\n const archStyle = config?.architectureStyle || \"bounded-contexts\";\r\n console.log(\r\n chalk.gray(\" Architecture:\"),\r\n archStyle === \"bounded-contexts\"\r\n ? chalk.cyan(\"Bounded Contexts\")\r\n : chalk.yellow(\"Flat Structure\")\r\n );\r\n\r\n // Show style options if different from defaults (all default to true)\r\n const disabledOptions: string[] = [];\r\n if (!includeValidations) disabledOptions.push(\"validations\");\r\n if (!includeComments) disabledOptions.push(\"comments\");\r\n if (!includeLogging) disabledOptions.push(\"logging\");\r\n if (!includeTesting) disabledOptions.push(\"testing\");\r\n\r\n if (disabledOptions.length > 0) {\r\n console.log(chalk.gray(\" Disabled:\"), chalk.yellow(disabledOptions.join(\", \")));\r\n }\r\n\r\n if (validationLib) {\r\n console.log(chalk.gray(\" Validation Lib:\"), chalk.cyan(validationLib));\r\n }\r\n\r\n console.log(chalk.gray(\" Output:\"), chalk.cyan(output));\r\n\r\n // Show categorized file preview (if available)\r\n if (estimate && estimate.files && estimate.files.length > 0) {\r\n console.log(\"\");\r\n console.log(chalk.bold(\" Files to Generate\"));\r\n console.log(chalk.gray(\" ─────────────────────────────────\"));\r\n\r\n const categories = categorizeFilePaths(estimate.files);\r\n const maxNameLength = Math.max(...categories.map((c) => c.name.length));\r\n\r\n for (const category of categories) {\r\n const padding = \" \".repeat(maxNameLength - category.name.length + 2);\r\n const countStr = category.count.toString().padStart(3, \" \");\r\n console.log(\r\n chalk.gray(` ${category.name}${padding}`),\r\n chalk.cyan(`${countStr} files`)\r\n );\r\n }\r\n\r\n console.log(chalk.gray(\" ─────────────────────────────────\"));\r\n const totalPadding = \" \".repeat(maxNameLength - 5 + 2);\r\n const totalStr = estimate.totalFiles.toString().padStart(3, \" \");\r\n console.log(\r\n chalk.white(` Total${totalPadding}`),\r\n chalk.bold.cyan(`${totalStr} files`)\r\n );\r\n console.log(chalk.gray(` Entities:`), chalk.cyan(estimate.entities));\r\n }\r\n\r\n // Show credits section\r\n console.log(\"\");\r\n console.log(chalk.bold(\" Credits\"));\r\n console.log(chalk.gray(\" ─────────────────────────────────\"));\r\n if (estimate) {\r\n console.log(\r\n chalk.white(\" Cost:\"),\r\n hasEnoughCredits\r\n ? chalk.bold.yellow(`${estimate.estimatedCredits} credits`)\r\n : chalk.bold.red(`${estimate.estimatedCredits} credits`)\r\n );\r\n }\r\n console.log(\r\n chalk.white(\" Available:\"),\r\n hasEnoughCredits\r\n ? chalk.bold.green(`${credits.remaining} credits`)\r\n : chalk.bold.red(`${credits.remaining} credits (insufficient)`)\r\n );\r\n console.log(\"\");\r\n\r\n // Warn if not enough credits\r\n if (!hasEnoughCredits && estimate) {\r\n console.log(chalk.red(\" ⚠ Not enough credits for this generation.\"));\r\n console.log(chalk.gray(` Need ${estimate.estimatedCredits - credits.remaining} more credits.\\n`));\r\n process.exit(1);\r\n }\r\n\r\n // 7. Confirmation (unless --yes)\r\n if (!options.yes) {\r\n const confirmed = await promptConfirm(\" Proceed with generation?\");\r\n if (!confirmed) {\r\n console.log(chalk.yellow(\"\\n Generation cancelled\\n\"));\r\n process.exit(0);\r\n }\r\n }\r\n\r\n // 8. Call API\r\n console.log(\"\");\r\n spinner = ora({ text: \"Generating code...\", color: \"cyan\" }).start();\r\n\r\n // Build API request based on mode (useContexts already determined above)\r\n // Include diagramIds to filter which bounded contexts to generate\r\n const diagramIds = selectedDiagramIds.length < diagrams.length ? selectedDiagramIds : undefined;\r\n\r\n const generatePayload = templateId\r\n ? {\r\n // NEW: Full architecture mode using template\r\n projectId,\r\n templateId,\r\n options: {\r\n includeValidations,\r\n includeComments,\r\n featureFlags,\r\n useContexts,\r\n diagramIds, // Filter by selected bounded contexts\r\n },\r\n }\r\n : {\r\n // Legacy mode using targets\r\n projectId,\r\n targets,\r\n options: {\r\n includeValidations,\r\n includeComments,\r\n includeLogging,\r\n includeTesting,\r\n outputDir: output,\r\n backendPreset,\r\n frontendPreset,\r\n validationLib,\r\n useContexts,\r\n diagramIds, // Filter by selected bounded contexts\r\n },\r\n };\r\n\r\n const result = await apiClient.generateCode(generatePayload);\r\n\r\n spinner.succeed(chalk.green(\"Code generated successfully!\"));\r\n\r\n // 9. Show results with credits\r\n console.log(\"\");\r\n console.log(chalk.bold(\" Results\"));\r\n console.log(chalk.gray(\" ─────────────────────────────────\"));\r\n console.log(chalk.gray(\" Files:\"), chalk.cyan(result.stats?.totalFiles ?? result.files?.length ?? 0));\r\n if (result.stats?.totalEntities) {\r\n console.log(chalk.gray(\" Entities:\"), chalk.cyan(result.stats.totalEntities));\r\n }\r\n if (result.stats?.languages && result.stats.languages.length > 0) {\r\n console.log(\r\n chalk.gray(\" Languages:\"),\r\n chalk.cyan(result.stats.languages.join(\", \"))\r\n );\r\n }\r\n\r\n if (result.creditsUsed !== undefined) {\r\n console.log(\"\");\r\n console.log(chalk.bold(\" Credits\"));\r\n console.log(chalk.gray(\" ─────────────────────────────────\"));\r\n console.log(chalk.gray(\" Used:\"), chalk.yellow(result.creditsUsed));\r\n console.log(\r\n chalk.gray(\" Remaining:\"),\r\n result.creditsRemaining !== undefined && result.creditsRemaining > 50\r\n ? chalk.green(result.creditsRemaining)\r\n : chalk.yellow(result.creditsRemaining)\r\n );\r\n }\r\n\r\n // Show warnings if any\r\n if (result.warnings && result.warnings.length > 0) {\r\n console.log(\"\");\r\n console.log(chalk.yellow(\" Warnings:\"));\r\n for (const warning of result.warnings) {\r\n console.log(chalk.yellow(` - ${warning}`));\r\n }\r\n }\r\n\r\n console.log(\"\");\r\n\r\n // 10. Write files to disk\r\n await writeGeneratedFiles(result.files, output, options.verbose);\r\n\r\n console.log(chalk.green(` Files written to ${chalk.white(output)}`));\r\n console.log(\"\");\r\n } catch (error: any) {\r\n spinner.fail(chalk.red(\"Generation failed\"));\r\n\r\n if (error.response?.status === 401) {\r\n await handleUnauthorized(tokenManager);\r\n } else if (error.response?.status === 403) {\r\n console.log(chalk.yellow(\"\\n You don't have permission to access this project.\"));\r\n console.log(chalk.gray(\" Check if you're part of the organization.\\n\"));\r\n } else if (error.response?.status === 404) {\r\n console.log(chalk.yellow(\"\\n Project not found.\"));\r\n console.log(chalk.gray(\" Check if the project ID is correct.\\n\"));\r\n } else if (error.response?.status === 429) {\r\n // Insufficient credits\r\n const data = error.response.data;\r\n console.log(chalk.red(\"\\n Insufficient credits\"));\r\n if (data.requiredCredits) {\r\n console.log(chalk.yellow(` Required: ${data.requiredCredits} credits`));\r\n }\r\n console.log(chalk.yellow(` Available: ${data.remaining ?? 0} credits`));\r\n console.log(chalk.gray(\"\\n Upgrade your plan or wait for credit reset.\\n\"));\r\n } else if (error.response?.data?.message) {\r\n console.log(chalk.red(`\\n ${error.response.data.message}\\n`));\r\n } else {\r\n console.log(chalk.red(`\\n ${error.message}\\n`));\r\n }\r\n\r\n process.exit(1);\r\n }\r\n}\r\n","import fs from \"fs/promises\";\r\nimport path from \"path\";\r\nimport chalk from \"chalk\";\r\n\r\ninterface GeneratedFile {\r\n path: string;\r\n content: string;\r\n language: string;\r\n entityId?: string;\r\n /**\r\n * If true, file should only be written if it doesn't already exist.\r\n * Used for starter files (Program.cs, appsettings.json) that users may customize.\r\n */\r\n generateOnce?: boolean;\r\n}\r\n\r\nexport interface FileCategory {\r\n name: string;\r\n count: number;\r\n files: string[];\r\n}\r\n\r\n/**\r\n * Validate that a file path is safe and doesn't escape the output directory.\r\n * SECURITY: Prevents path traversal attacks (e.g., ../../../etc/passwd)\r\n */\r\nfunction isPathSafe(outputDir: string, filePath: string): boolean {\r\n // Resolve both paths to absolute paths\r\n const resolvedOutput = path.resolve(outputDir);\r\n const resolvedFile = path.resolve(outputDir, filePath);\r\n\r\n // Check if the resolved file path starts with the output directory\r\n // Also ensure there's a path separator after the base to prevent\r\n // matching \"output\" when file is in \"output-malicious\"\r\n return (\r\n resolvedFile.startsWith(resolvedOutput + path.sep) ||\r\n resolvedFile === resolvedOutput\r\n );\r\n}\r\n\r\n/**\r\n * Get category name from file path\r\n * Analyzes path segments to determine file type\r\n * @public Exported for use in preview/estimate display\r\n */\r\nexport function getCategoryFromPath(filePath: string): string {\r\n const lowerPath = filePath.toLowerCase();\r\n\r\n // Order matters - more specific first\r\n if (lowerPath.includes(\"/controllers/\")) return \"Controllers\";\r\n if (lowerPath.includes(\"/usecases/\") || lowerPath.includes(\"/use-cases/\"))\r\n return \"UseCases\";\r\n if (lowerPath.includes(\"/dtos/\") || lowerPath.includes(\"/dto/\")) return \"DTOs\";\r\n if (lowerPath.includes(\"/entities/\")) return \"Entities\";\r\n if (\r\n lowerPath.includes(\"/repositories/\") ||\r\n lowerPath.includes(\"/repositoriesimpl/\")\r\n )\r\n return \"Repositories\";\r\n if (\r\n lowerPath.includes(\"/configurations/\") ||\r\n lowerPath.includes(\"/config/\")\r\n )\r\n return \"Configurations\";\r\n if (\r\n lowerPath.includes(\"/validators/\") ||\r\n lowerPath.includes(\"/validation/\")\r\n )\r\n return \"Validators\";\r\n if (lowerPath.includes(\"/mappers/\")) return \"Mappers\";\r\n if (lowerPath.includes(\"/interfaces/\")) return \"Interfaces\";\r\n if (lowerPath.includes(\"/exceptions/\")) return \"Exceptions\";\r\n if (lowerPath.includes(\"/vos/\") || lowerPath.includes(\"/valueobjects/\"))\r\n return \"ValueObjects\";\r\n if (lowerPath.includes(\"/ioc/\") || lowerPath.includes(\"/di/\"))\r\n return \"DependencyInjection\";\r\n if (\r\n lowerPath.includes(\"/tests/\") ||\r\n lowerPath.includes(\".test.\") ||\r\n lowerPath.includes(\".spec.\")\r\n )\r\n return \"Tests\";\r\n if (lowerPath.includes(\"/database/\")) return \"Database\";\r\n\r\n return \"Other\";\r\n}\r\n\r\n/**\r\n * Categorize file paths into categories\r\n * Used for preview/estimate display before generation\r\n * @public Exported for use in generate command preview\r\n */\r\nexport function categorizeFilePaths(filePaths: string[]): FileCategory[] {\r\n const categories = new Map<string, string[]>();\r\n\r\n for (const filePath of filePaths) {\r\n const category = getCategoryFromPath(filePath);\r\n const existing = categories.get(category) || [];\r\n existing.push(filePath);\r\n categories.set(category, existing);\r\n }\r\n\r\n return Array.from(categories.entries())\r\n .map(([name, fileList]) => ({ name, count: fileList.length, files: fileList }))\r\n .sort((a, b) => b.count - a.count); // Most files first\r\n}\r\n\r\n/**\r\n * Categorize files by their path\r\n * Groups files into categories like Entities, DTOs, UseCases, etc.\r\n */\r\nfunction categorizeFiles(files: GeneratedFile[]): FileCategory[] {\r\n return categorizeFilePaths(files.map((f) => f.path));\r\n}\r\n\r\n/**\r\n * Display categorized summary of generated files\r\n */\r\nfunction displayCategorizedSummary(files: GeneratedFile[]): void {\r\n const categories = categorizeFiles(files);\r\n\r\n console.log(\"\");\r\n console.log(chalk.bold(\" Generated Files\"));\r\n console.log(chalk.gray(\" ─────────────────────────────────\"));\r\n\r\n // Find max name length for alignment\r\n const maxNameLength = Math.max(...categories.map((c) => c.name.length));\r\n\r\n for (const category of categories) {\r\n const padding = \" \".repeat(maxNameLength - category.name.length + 2);\r\n const countStr = category.count.toString().padStart(3, \" \");\r\n console.log(\r\n chalk.gray(` ${category.name}${padding}`),\r\n chalk.cyan(`${countStr} files`)\r\n );\r\n }\r\n\r\n console.log(chalk.gray(\" ─────────────────────────────────\"));\r\n const totalPadding = \" \".repeat(maxNameLength - 5 + 2);\r\n const totalStr = files.length.toString().padStart(3, \" \");\r\n console.log(\r\n chalk.white(` Total${totalPadding}`),\r\n chalk.bold.cyan(`${totalStr} files`)\r\n );\r\n}\r\n\r\n/**\r\n * Write generated files to disk\r\n *\r\n * Creates directories as needed and writes files\r\n * Shows categorized summary by default, or full list with verbose=true\r\n */\r\nexport async function writeGeneratedFiles(\r\n files: GeneratedFile[],\r\n outputDir: string,\r\n verbose: boolean = false\r\n): Promise<void> {\r\n // Track written files for summary\r\n const writtenFiles: GeneratedFile[] = [];\r\n\r\n // Track skipped generateOnce files for summary\r\n const skippedOnceFiles: string[] = [];\r\n\r\n for (const file of files) {\r\n // SECURITY: Validate path doesn't escape output directory\r\n if (!isPathSafe(outputDir, file.path)) {\r\n console.error(chalk.red(` Skipping unsafe path: ${file.path}`));\r\n console.error(\r\n chalk.gray(\r\n ` Path traversal detected - file path must be within output directory`\r\n )\r\n );\r\n continue;\r\n }\r\n\r\n const fullPath = path.resolve(outputDir, file.path);\r\n const dir = path.dirname(fullPath);\r\n\r\n // Check if file has generateOnce flag and already exists\r\n if (file.generateOnce) {\r\n try {\r\n await fs.access(fullPath);\r\n // File exists - skip it\r\n skippedOnceFiles.push(file.path);\r\n continue;\r\n } catch {\r\n // File doesn't exist - proceed with generation\r\n }\r\n }\r\n\r\n try {\r\n // Create directory if doesn't exist\r\n await fs.mkdir(dir, { recursive: true });\r\n\r\n // Write file\r\n await fs.writeFile(fullPath, file.content, \"utf-8\");\r\n\r\n // Show file path in verbose mode\r\n if (verbose) {\r\n console.log(chalk.gray(` ${file.path}`));\r\n }\r\n\r\n writtenFiles.push(file);\r\n } catch (error: any) {\r\n console.error(chalk.red(` Failed to write ${file.path}`));\r\n console.error(chalk.gray(` ${error.message}`));\r\n }\r\n }\r\n\r\n // Show categorized summary (unless verbose)\r\n if (!verbose && writtenFiles.length > 0) {\r\n displayCategorizedSummary(writtenFiles);\r\n }\r\n\r\n // Show skipped generateOnce files\r\n if (skippedOnceFiles.length > 0) {\r\n console.log(\"\");\r\n console.log(\r\n chalk.gray(` Skipped ${skippedOnceFiles.length} existing file(s) (generateOnce):`)\r\n );\r\n for (const filePath of skippedOnceFiles) {\r\n console.log(chalk.gray(` - ${filePath}`));\r\n }\r\n }\r\n}\r\n","import readline from \"readline\";\r\nimport chalk from \"chalk\";\r\n\r\n/**\r\n * Prompt user for confirmation\r\n * Returns true if user confirms (Y/yes/enter), false if they decline (n/no)\r\n */\r\nexport function promptConfirm(message: string): Promise<boolean> {\r\n return new Promise((resolve) => {\r\n const rl = readline.createInterface({\r\n input: process.stdin,\r\n output: process.stdout,\r\n });\r\n\r\n rl.question(chalk.yellow(`${message} [Y/n] `), (answer) => {\r\n rl.close();\r\n const normalized = answer.trim().toLowerCase();\r\n // Empty input (just pressing Enter) means \"yes\"\r\n resolve(normalized !== \"n\" && normalized !== \"no\");\r\n });\r\n });\r\n}\r\n","import fs from \"fs/promises\";\r\nimport path from \"path\";\r\nimport { configSchema, CONFIG_FILENAME, type AerocodingConfig } from \"./schema.js\";\r\n\r\nexport async function loadConfig(\r\n dir: string = process.cwd()\r\n): Promise<AerocodingConfig | null> {\r\n const configPath = path.join(dir, CONFIG_FILENAME);\r\n\r\n try {\r\n const content = await fs.readFile(configPath, \"utf-8\");\r\n const parsed = JSON.parse(content);\r\n return configSchema.parse(parsed);\r\n } catch (error) {\r\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") {\r\n return null;\r\n }\r\n throw error;\r\n }\r\n}\r\n\r\nexport async function saveConfig(\r\n config: AerocodingConfig,\r\n dir: string = process.cwd()\r\n): Promise<void> {\r\n const configPath = path.join(dir, CONFIG_FILENAME);\r\n const content = JSON.stringify(\r\n {\r\n $schema: \"https://aerocoding.dev/schemas/aerocodingrc.json\",\r\n ...config,\r\n },\r\n null,\r\n 2\r\n );\r\n await fs.writeFile(configPath, content, \"utf-8\");\r\n}\r\n\r\nexport async function configExists(dir: string = process.cwd()): Promise<boolean> {\r\n const configPath = path.join(dir, CONFIG_FILENAME);\r\n try {\r\n await fs.access(configPath);\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\nexport { type AerocodingConfig, CONFIG_FILENAME } from \"./schema.js\";\r\n","import { z } from \"zod\";\r\n\r\nexport const configSchema = z.object({\r\n $schema: z.string().optional(),\r\n project: z.string().uuid(),\r\n output: z.string().default(\"./.aerocoding\"),\r\n\r\n // Architecture style: how to organize generated code\r\n architectureStyle: z\r\n .enum([\"bounded-contexts\", \"flat\"])\r\n .optional()\r\n .default(\"bounded-contexts\"),\r\n\r\n backend: z\r\n .object({\r\n preset: z.string(),\r\n })\r\n .optional(),\r\n\r\n frontend: z\r\n .object({\r\n preset: z.string(),\r\n })\r\n .optional(),\r\n\r\n codeStyle: z\r\n .object({\r\n includeValidations: z.boolean().default(true),\r\n includeComments: z.boolean().default(true),\r\n includeLogging: z.boolean().default(true),\r\n includeTesting: z.boolean().default(true),\r\n })\r\n .optional(),\r\n\r\n libraries: z\r\n .object({\r\n validation: z.string().optional(),\r\n logging: z.string().optional(),\r\n })\r\n .optional(),\r\n\r\n excludePatterns: z.array(z.string()).optional(),\r\n});\r\n\r\nexport type AerocodingConfig = z.infer<typeof configSchema>;\r\n\r\nexport const CONFIG_FILENAME = \".aerocodingrc.json\";\r\n","import * as p from \"@clack/prompts\";\r\nimport chalk from \"chalk\";\r\nimport { TokenManager } from \"../auth/token-manager.js\";\r\nimport { createApiClientWithAutoLogout } from \"./_shared/create-api-client.js\";\r\nimport { handleUnauthorized } from \"./_shared/unauthorized.js\";\r\nimport { saveConfig, configExists } from \"../config/loader.js\";\r\nimport type { AerocodingConfig } from \"../config/schema.js\";\r\n\r\ninterface InitOptions {\r\n project?: string;\r\n force?: boolean;\r\n}\r\n\r\n/**\r\n * Init Command\r\n *\r\n * Interactive wizard to initialize AeroCoding in current directory\r\n * Creates .aerocodingrc.json config file\r\n */\r\nexport async function initCommand(options: InitOptions) {\r\n p.intro(chalk.bgCyan.black(\" AeroCoding CLI \"));\r\n\r\n // Check if config already exists\r\n if (!options.force && (await configExists())) {\r\n const overwrite = await p.confirm({\r\n message: \"Config file already exists. Overwrite?\",\r\n initialValue: false,\r\n });\r\n\r\n if (p.isCancel(overwrite) || !overwrite) {\r\n p.cancel(\"Operation cancelled.\");\r\n process.exit(0);\r\n }\r\n }\r\n\r\n // 1. Check authentication\r\n const tokenManager = new TokenManager();\r\n const token = await tokenManager.getAccessToken();\r\n\r\n if (!token) {\r\n p.cancel(\"Not logged in. Run 'aerocoding login' first.\");\r\n process.exit(1);\r\n }\r\n\r\n const apiClient = createApiClientWithAutoLogout(token, tokenManager);\r\n\r\n try {\r\n // 2. Select organization first\r\n const orgSpinner = p.spinner();\r\n orgSpinner.start(\"Loading organizations...\");\r\n\r\n const organizations = await apiClient.listOrganizations();\r\n orgSpinner.stop(\"Organizations loaded\");\r\n\r\n if (organizations.length === 0) {\r\n p.cancel(\"No organizations found. Create one on aerocoding.dev first.\");\r\n process.exit(1);\r\n }\r\n\r\n let organizationId: string;\r\n\r\n if (organizations.length === 1 && organizations[0]) {\r\n // Auto-select if only one org\r\n organizationId = organizations[0].id;\r\n p.log.info(`Organization: ${organizations[0].name}`);\r\n } else {\r\n const selectedOrg = await p.select({\r\n message: \"Select organization\",\r\n options: organizations.map((org) => ({\r\n value: org.id,\r\n label: org.name,\r\n hint: org.planTier.toUpperCase(),\r\n })),\r\n });\r\n\r\n if (p.isCancel(selectedOrg)) {\r\n p.cancel(\"Operation cancelled.\");\r\n process.exit(0);\r\n }\r\n\r\n organizationId = selectedOrg as string;\r\n }\r\n\r\n // 3. Select project from organization\r\n let projectId = options.project;\r\n\r\n if (!projectId) {\r\n const spinner = p.spinner();\r\n spinner.start(\"Loading projects...\");\r\n\r\n const projects = await apiClient.listProjects(organizationId);\r\n spinner.stop(\"Projects loaded\");\r\n\r\n if (projects.length === 0) {\r\n p.cancel(\"No projects in this organization. Create one on aerocoding.dev first.\");\r\n process.exit(1);\r\n }\r\n\r\n const selectedProject = await p.select({\r\n message: \"Select project\",\r\n options: projects.map((proj) => ({\r\n value: proj.id,\r\n label: proj.name,\r\n hint: [proj.backendFramework, proj.frontendFramework].filter(Boolean).join(\" + \"),\r\n })),\r\n });\r\n\r\n if (p.isCancel(selectedProject)) {\r\n p.cancel(\"Operation cancelled.\");\r\n process.exit(0);\r\n }\r\n\r\n projectId = selectedProject as string;\r\n }\r\n\r\n // 4. Fetch project details\r\n const spinner = p.spinner();\r\n spinner.start(\"Fetching project details...\");\r\n const project = await apiClient.getProject(projectId);\r\n spinner.stop(`Project: ${project.name}`);\r\n\r\n // Detect frameworks from project settings (no longer asking user)\r\n const hasBackend = !!project.backendFramework;\r\n const hasFrontend = !!project.frontendFramework;\r\n\r\n if (!hasBackend && !hasFrontend) {\r\n p.cancel(\"Project has no frameworks configured. Update it on aerocoding.dev first.\");\r\n process.exit(1);\r\n }\r\n\r\n // Show detected frameworks\r\n if (hasBackend) {\r\n p.log.success(`Backend: ${project.backendFramework?.toUpperCase()} detected`);\r\n }\r\n if (hasFrontend) {\r\n p.log.success(`Frontend: ${project.frontendFramework?.toUpperCase()} detected`);\r\n }\r\n\r\n // Initialize config (architectureStyle will be set later based on template or user choice)\r\n const config: AerocodingConfig = {\r\n project: projectId,\r\n output: \"./.aerocoding\",\r\n architectureStyle: \"flat\", // Default, will be updated based on template or user choice\r\n codeStyle: {\r\n includeValidations: true,\r\n includeComments: true,\r\n includeLogging: true,\r\n includeTesting: true,\r\n },\r\n };\r\n\r\n // Track selected templates to determine architecture style later\r\n let selectedBackendTemplate: { architectureStyle?: \"bounded-contexts\" | \"flat\" } | null = null;\r\n let selectedFrontendTemplate: { architectureStyle?: \"bounded-contexts\" | \"flat\" } | null = null;\r\n\r\n // 5. Backend configuration (if project has backend framework)\r\n if (hasBackend && project.backendFramework) {\r\n const archSpinner = p.spinner();\r\n archSpinner.start(\"Loading backend templates...\");\r\n\r\n // Use new template registry API\r\n const templateResult = await apiClient.getTemplates({\r\n category: \"backend\",\r\n language: project.backendFramework,\r\n });\r\n archSpinner.stop(\"Templates loaded\");\r\n\r\n if (templateResult.templates.length > 0) {\r\n const preset = await p.select({\r\n message: \"Backend template\",\r\n options: templateResult.templates.map((tmpl) => ({\r\n value: tmpl.id,\r\n label: tmpl.name,\r\n hint: tmpl.description || `${tmpl.tier} tier`,\r\n })),\r\n });\r\n\r\n if (p.isCancel(preset)) {\r\n p.cancel(\"Operation cancelled.\");\r\n process.exit(0);\r\n }\r\n\r\n // Fetch full template to get architectureStyle recommendation\r\n const fullTemplate = await apiClient.getTemplate(preset as string);\r\n selectedBackendTemplate = fullTemplate;\r\n\r\n config.backend = {\r\n preset: preset as string,\r\n };\r\n }\r\n }\r\n\r\n // 6. Frontend configuration (if project has frontend framework)\r\n if (hasFrontend && project.frontendFramework) {\r\n const archSpinner = p.spinner();\r\n archSpinner.start(\"Loading frontend templates...\");\r\n\r\n // Use new template registry API\r\n const templateResult = await apiClient.getTemplates({\r\n category: \"frontend\",\r\n framework: project.frontendFramework,\r\n });\r\n archSpinner.stop(\"Templates loaded\");\r\n\r\n if (templateResult.templates.length > 0) {\r\n const preset = await p.select({\r\n message: \"Frontend template\",\r\n options: templateResult.templates.map((tmpl) => ({\r\n value: tmpl.id,\r\n label: tmpl.name,\r\n hint: tmpl.description || `${tmpl.tier} tier`,\r\n })),\r\n });\r\n\r\n if (p.isCancel(preset)) {\r\n p.cancel(\"Operation cancelled.\");\r\n process.exit(0);\r\n }\r\n\r\n // Fetch full template to get architectureStyle recommendation\r\n const fullTemplate = await apiClient.getTemplate(preset as string);\r\n selectedFrontendTemplate = fullTemplate;\r\n\r\n config.frontend = {\r\n preset: preset as string,\r\n };\r\n }\r\n }\r\n\r\n // 7. Architecture style\r\n // Always ask user, but use template recommendation as default\r\n const templateArchStyle =\r\n selectedBackendTemplate?.architectureStyle ||\r\n selectedFrontendTemplate?.architectureStyle;\r\n\r\n const recommendedStyle = templateArchStyle || \"flat\";\r\n\r\n const architectureStyle = await p.select({\r\n message: \"How would you like to organize your code?\",\r\n options: [\r\n {\r\n value: \"bounded-contexts\",\r\n label:\r\n recommendedStyle === \"bounded-contexts\"\r\n ? \"Bounded Contexts (Recommended)\"\r\n : \"Bounded Contexts\",\r\n hint: \"Each module has its own Domain, Application, Infrastructure\",\r\n },\r\n {\r\n value: \"flat\",\r\n label:\r\n recommendedStyle === \"flat\"\r\n ? \"Flat Structure (Recommended)\"\r\n : \"Flat Structure\",\r\n hint: \"Single Domain, Application, Infrastructure for the entire project\",\r\n },\r\n ],\r\n initialValue: recommendedStyle,\r\n });\r\n\r\n if (p.isCancel(architectureStyle)) {\r\n p.cancel(\"Operation cancelled.\");\r\n process.exit(0);\r\n }\r\n\r\n config.architectureStyle = architectureStyle as \"bounded-contexts\" | \"flat\";\r\n\r\n // 8. Code style options\r\n const codeStyleOptions = await p.multiselect({\r\n message: \"Code style options\",\r\n options: [\r\n { value: \"validations\", label: \"Include validations (Recommended)\", hint: \"Add validation rules\" },\r\n { value: \"comments\", label: \"Include comments (Recommended)\", hint: \"Add code documentation\" },\r\n { value: \"logging\", label: \"Include logging (Recommended)\", hint: \"Add log statements\" },\r\n { value: \"testing\", label: \"Include tests (Recommended)\", hint: \"Generate test files\" },\r\n ],\r\n initialValues: [\"validations\", \"comments\", \"logging\", \"testing\"],\r\n });\r\n\r\n if (p.isCancel(codeStyleOptions)) {\r\n p.cancel(\"Operation cancelled.\");\r\n process.exit(0);\r\n }\r\n\r\n const selectedStyles = codeStyleOptions as string[];\r\n config.codeStyle = {\r\n includeValidations: selectedStyles.includes(\"validations\"),\r\n includeComments: selectedStyles.includes(\"comments\"),\r\n includeLogging: selectedStyles.includes(\"logging\"),\r\n includeTesting: selectedStyles.includes(\"testing\"),\r\n };\r\n\r\n // 9. Use default output directory (user can edit .aerocodingrc.json if needed)\r\n config.output = \"./.aerocoding\";\r\n\r\n // 10. Configuration Summary\r\n p.log.step(chalk.bold(\"Configuration Summary:\"));\r\n if (config.backend) {\r\n p.log.info(` Backend: ${config.backend.preset}`);\r\n }\r\n if (config.frontend) {\r\n p.log.info(` Frontend: ${config.frontend.preset}`);\r\n }\r\n p.log.info(\r\n ` Architecture: ${\r\n config.architectureStyle === \"bounded-contexts\"\r\n ? \"Bounded Contexts\"\r\n : \"Flat Structure\"\r\n }`\r\n );\r\n p.log.info(` Output: ${config.output}`);\r\n\r\n // 11. Save config\r\n await saveConfig(config);\r\n\r\n p.outro(\r\n chalk.green(\"Config saved to .aerocodingrc.json\") +\r\n \"\\n\\n\" +\r\n chalk.gray(\" Run \") +\r\n chalk.cyan(\"aerocoding generate\") +\r\n chalk.gray(\" to generate code!\")\r\n );\r\n } catch (error: any) {\r\n if (error.response?.status === 401) {\r\n await handleUnauthorized(tokenManager);\r\n } else if (error.response?.data?.message) {\r\n p.cancel(error.response.data.message);\r\n } else {\r\n p.cancel(error.message || \"An unexpected error occurred\");\r\n }\r\n process.exit(1);\r\n }\r\n}\r\n","import chalk from \"chalk\";\r\n\r\ninterface PullOptions {\r\n project?: string;\r\n}\r\n\r\n/**\r\n * Pull Command (Stub)\r\n *\r\n * TODO: Pull schema from cloud\r\n * - Download project schema\r\n * - Save to .aerocoding/schema.json\r\n */\r\nexport async function pullCommand(options: PullOptions) {\r\n console.log(chalk.yellow(\"Command not yet implemented\"));\r\n if (options.project) {\r\n console.log(chalk.gray(` Requested project: ${options.project}`));\r\n }\r\n console.log(chalk.gray(\" Coming soon in v0.2.0\\n\"));\r\n}\r\n","import chalk from \"chalk\";\r\n\r\n/**\r\n * Status Command (Stub)\r\n *\r\n * TODO: Show local schema status\r\n * - Show current project\r\n * - Show schema stats\r\n * - Show sync status\r\n */\r\nexport async function statusCommand() {\r\n console.log(chalk.yellow(\"Command not yet implemented\"));\r\n console.log(chalk.gray(\" Coming soon in v0.2.0\\n\"));\r\n}\r\n"],"mappings":"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","names":["chalk","spinner","axios","API_URL","chalk","chalk","chalk","chalk","chalk","chalk","chalk","ora","chalk","chalk","fs","path","path","fs","chalk","spinner","ora","p","chalk","chalk","spinner","chalk","chalk"]}
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/manifest/index.ts","../src/manifest/types.ts","../src/manifest/hash-utils.ts","../src/merge/merger.ts","../src/merge/conflict-writer.ts","../src/utils/prompt.ts","../src/config/loader.ts","../src/config/schema.ts","../src/commands/init.ts","../src/commands/create.ts","../src/config/project-config.ts","../src/utils/cloud-sync.ts","../src/commands/update.ts","../src/commands/resolve.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 { createCommand } from \"./commands/create.js\";\r\nimport { updateCommand } from \"./commands/update.js\";\r\nimport { resolveCommand } from \"./commands/resolve.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.24\");\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(\"create <name>\")\r\n .description(\"Create a new AeroCoding project with full architecture\")\r\n .option(\"-t, --template <id>\", \"Template ID (skip selection)\")\r\n .option(\"-p, --project <id>\", \"Project ID (skip selection)\")\r\n .option(\"-f, --force\", \"Overwrite existing directory without asking\")\r\n .action(createCommand);\r\n\r\nprogram\r\n .command(\"update\")\r\n .description(\"Update generated code incrementally (preserves your changes)\")\r\n .option(\"-f, --force\", \"Overwrite modified files without merging\")\r\n .option(\"-v, --verbose\", \"Show detailed file operations\")\r\n .option(\"--dry-run\", \"Preview changes without writing files\")\r\n .action(updateCommand);\r\n\r\nprogram\r\n .command(\"resolve\")\r\n .description(\"Clean up conflict files after manual resolution\")\r\n .option(\"-v, --verbose\", \"Show detailed resolution info\")\r\n .option(\"-a, --all\", \"Resolve all conflicts without confirmation\")\r\n .action(resolveCommand);\r\n\r\nprogram\r\n .command(\"pull\")\r\n .description(\"Pull schema from cloud\")\r\n .option(\"-p, --project <id>\", \"Project ID\")\r\n .action(pullCommand);\r\n\r\nprogram\r\n .command(\"status\")\r\n .description(\"Show local schema status\")\r\n .action(statusCommand);\r\n\r\n// ============================================\r\n// Generation Commands\r\n// ============================================\r\n\r\nprogram\r\n .command(\"generate\")\r\n .alias(\"gen\")\r\n .description(\"Generate code from schema\")\r\n // Identification\r\n .option(\"-p, --project <id>\", \"Project ID\")\r\n .option(\"-t, --targets <targets...>\", \"Generation targets (e.g., dotnet-entity)\")\r\n .option(\"-e, --entities <entities...>\", \"Filter by entity names\")\r\n .option(\"-o, --output <dir>\", \"Output directory\", \"./.aerocoding\")\r\n // Presets & Layers\r\n .option(\"--backend-preset <preset>\", \"Backend architecture preset\")\r\n .option(\"--frontend-preset <preset>\", \"Frontend architecture preset\")\r\n .option(\"--backend-layers <layers...>\", \"Backend layers to generate\")\r\n .option(\"--frontend-layers <layers...>\", \"Frontend layers to generate\")\r\n // Code style toggles (optimistic defaults - all enabled by default)\r\n .option(\"--no-validations\", \"Exclude validations\")\r\n .option(\"--no-comments\", \"Exclude comments\")\r\n .option(\"--no-annotations\", \"Exclude annotations\")\r\n .option(\"--no-logging\", \"Exclude logging statements\")\r\n .option(\"--no-testing\", \"Exclude test files\")\r\n // Validation library (framework-agnostic)\r\n .option(\"--validation-lib <framework>\", \"Validation library (e.g., fluentvalidation, zod, formz)\")\r\n // Control\r\n .option(\"-v, --verbose\", \"Show all generated file paths\")\r\n .option(\"-y, --yes\", \"Skip confirmation prompt\")\r\n .option(\"-a, --all\", \"Generate all bounded contexts and targets without prompting\")\r\n .action(generateCommand);\r\n\r\n// ============================================\r\n// Parse and Execute\r\n// ============================================\r\n\r\nprogram.parse();\r\n","import chalk from \"chalk\";\r\nimport { DeviceFlow } from \"../auth/device-flow.js\";\r\nimport { TokenManager } from \"../auth/token-manager.js\";\r\nimport { createApiClientWithAutoLogout } from \"./_shared/create-api-client.js\";\r\nimport { handleUnauthorized } from \"./_shared/unauthorized.js\";\r\n\r\n/**\r\n * Login Command\r\n *\r\n * Authenticates user via OAuth Device Flow\r\n * Stores tokens securely in OS credential manager\r\n */\r\nexport async function loginCommand() {\r\n console.log(chalk.bold(\"\\nAeroCoding CLI Login\\n\"));\r\n\r\n const tokenManager = new TokenManager();\r\n\r\n // Check if already logged in\r\n const existingToken = await tokenManager.getAccessToken();\r\n if (existingToken) {\r\n const metadata = await tokenManager.getUserMetadata();\r\n console.log(\r\n chalk.yellow(\"Already logged in as:\"),\r\n chalk.white(metadata?.email || \"unknown\")\r\n );\r\n console.log(\r\n chalk.gray(\r\n \" Run 'aerocoding logout' to login with a different account\\n\"\r\n )\r\n );\r\n return;\r\n }\r\n\r\n try {\r\n // Initiate device flow\r\n const deviceFlow = new DeviceFlow();\r\n const tokens = await deviceFlow.initiateAuth();\r\n\r\n // Get user info\r\n const apiClient = createApiClientWithAutoLogout(\r\n tokens.access_token,\r\n tokenManager\r\n );\r\n let user;\r\n try {\r\n user = await apiClient.getCurrentUser();\r\n } catch (error: any) {\r\n if (error.response?.status === 401) {\r\n await handleUnauthorized(tokenManager);\r\n }\r\n throw error;\r\n }\r\n\r\n // Save tokens\r\n await tokenManager.saveTokens(tokens.access_token, tokens.refresh_token, {\r\n id: user.id,\r\n email: user.email,\r\n name: user.name || undefined,\r\n tier: user.tier,\r\n });\r\n\r\n console.log(\"\");\r\n console.log(\r\n chalk.green(\"Successfully logged in as:\"),\r\n chalk.white(user.email)\r\n );\r\n console.log(chalk.gray(\" Run 'aerocoding whoami' to verify\\n\"));\r\n } catch (error: any) {\r\n console.error(\r\n chalk.red(\"\\nLogin failed:\"),\r\n error.message || \"Unknown error\"\r\n );\r\n process.exit(1);\r\n }\r\n}\r\n","import axios from \"axios\";\r\nimport chalk from \"chalk\";\r\nimport ora from \"ora\";\r\nimport open from \"open\";\r\n\r\nconst API_URL = process.env.API_URL || \"https://aerocoding.dev\";\r\nconst MAX_POLL_TIME = 15 * 60 * 1000; // 15 minutes\r\n\r\ninterface DeviceAuthResponse {\r\n device_code: string;\r\n user_code: string;\r\n confirmation_code: string;\r\n verification_uri: string;\r\n verification_uri_complete: string;\r\n expires_in: number;\r\n interval: number;\r\n}\r\n\r\ninterface TokenResponse {\r\n access_token: string;\r\n refresh_token: string;\r\n token_type: string;\r\n expires_in: number;\r\n}\r\n\r\n/**\r\n * DeviceFlow\r\n *\r\n * Implements OAuth 2.0 Device Authorization Grant (RFC 8628)\r\n * Used for CLI authentication without browser-based redirects\r\n */\r\nexport class DeviceFlow {\r\n /**\r\n * Initiate the complete device authorization flow\r\n */\r\n async initiateAuth(): Promise<TokenResponse> {\r\n // Step 1: Request device code\r\n const deviceAuth = await this.requestDeviceCode();\r\n\r\n // Step 2: Display user code and open browser\r\n this.displayUserCode(deviceAuth);\r\n await this.openBrowser(deviceAuth.verification_uri);\r\n\r\n // Step 3: Poll for authorization\r\n const tokens = await this.pollForToken(deviceAuth);\r\n\r\n return tokens;\r\n }\r\n\r\n /**\r\n * Step 1: Request device code from server\r\n */\r\n private async requestDeviceCode(): Promise<DeviceAuthResponse> {\r\n try {\r\n const response = await axios.post(`${API_URL}/api/device/authorize`, {\r\n client_id: \"aerocoding-cli\",\r\n scope: \"generate:code projects:read\",\r\n });\r\n\r\n return response.data;\r\n } catch (error: any) {\r\n console.error(chalk.red(\"Failed to initiate device authorization\"));\r\n if (error.response) {\r\n console.error(\r\n chalk.red(`Error: ${error.response.data.error_description}`)\r\n );\r\n }\r\n throw new Error(\"Failed to initiate device authorization\");\r\n }\r\n }\r\n\r\n /**\r\n * Step 2: Display user code and instructions\r\n */\r\n private displayUserCode(auth: DeviceAuthResponse): void {\r\n console.log(\"\\n\");\r\n console.log(chalk.cyan(\"━\".repeat(60)));\r\n console.log(chalk.bold.white(\" AeroCoding CLI - Device Activation\"));\r\n console.log(chalk.cyan(\"━\".repeat(60)));\r\n console.log(\"\");\r\n console.log(chalk.white(\" 1. Open this URL in your browser:\"));\r\n console.log(chalk.cyan.bold(` ${auth.verification_uri}`));\r\n console.log(\"\");\r\n console.log(chalk.white(\" 2. Enter this code:\"));\r\n console.log(chalk.green.bold(` ${auth.user_code}`));\r\n console.log(\"\");\r\n console.log(\r\n chalk.gray(` Code expires in ${auth.expires_in / 60} minutes`)\r\n );\r\n console.log(chalk.cyan(\"━\".repeat(60)));\r\n console.log(\"\");\r\n }\r\n\r\n /**\r\n * Step 2.5: Open browser automatically\r\n */\r\n private async openBrowser(url: string): Promise<void> {\r\n try {\r\n await open(url);\r\n console.log(chalk.gray(\" Opening browser...\"));\r\n } catch {\r\n console.log(chalk.yellow(\" Could not open browser automatically\"));\r\n console.log(chalk.gray(\" Please open the URL manually\\n\"));\r\n }\r\n }\r\n\r\n /**\r\n * Step 3: Poll for token\r\n */\r\n private async pollForToken(auth: DeviceAuthResponse): Promise<TokenResponse> {\r\n const spinner = ora({\r\n text: \"Waiting for authorization...\",\r\n color: \"cyan\",\r\n }).start();\r\n\r\n const startTime = Date.now();\r\n let currentInterval = auth.interval * 1000;\r\n\r\n while (true) {\r\n // Check timeout\r\n if (Date.now() - startTime > MAX_POLL_TIME) {\r\n spinner.fail(chalk.red(\"Authorization timeout\"));\r\n throw new Error(\"Device authorization timed out\");\r\n }\r\n\r\n try {\r\n const response = await axios.post(`${API_URL}/api/device/token`, {\r\n device_code: auth.device_code,\r\n client_id: \"aerocoding-cli\",\r\n });\r\n\r\n spinner.succeed(chalk.green(\"Successfully authenticated!\"));\r\n return response.data;\r\n } catch (error: any) {\r\n const errorCode = error.response?.data?.error;\r\n const errorDescription = error.response?.data?.error_description;\r\n\r\n if (errorCode === \"authorization_pending\") {\r\n // Keep polling\r\n await this.sleep(currentInterval);\r\n continue;\r\n }\r\n\r\n if (errorCode === \"slow_down\") {\r\n // Increase poll interval by 5 seconds\r\n currentInterval += 5000;\r\n spinner.text = \"Polling... (slowed down to avoid spam)\";\r\n await this.sleep(currentInterval);\r\n continue;\r\n }\r\n\r\n if (errorCode === \"expired_token\") {\r\n spinner.fail(chalk.red(\"Authorization code expired\"));\r\n throw new Error(\"Device code expired. Please try again.\");\r\n }\r\n\r\n if (errorCode === \"access_denied\") {\r\n spinner.fail(chalk.red(\"Authorization denied\"));\r\n throw new Error(\"You denied the authorization request\");\r\n }\r\n\r\n // Unknown error\r\n spinner.fail(chalk.red(\"Authorization failed\"));\r\n console.error(\r\n chalk.red(`Error: ${errorDescription || \"Unknown error\"}`)\r\n );\r\n throw new Error(errorDescription || \"Unknown error\");\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Helper: Sleep for specified milliseconds\r\n */\r\n private sleep(ms: number): Promise<void> {\r\n return new Promise((resolve) => setTimeout(resolve, ms));\r\n }\r\n}\r\n","import { Entry } from \"@napi-rs/keyring\";\r\nimport { createClient, SupabaseClient } from \"@supabase/supabase-js\";\r\n\r\nconst SERVICE_NAME = \"aerocoding-cli\";\r\n\r\n// Public Supabase credentials (anon key is safe to expose)\r\nconst SUPABASE_URL = \"https://peqpttkvdpjgmduzacwl.supabase.co\";\r\nconst SUPABASE_ANON_KEY = \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InBlcXB0dGt2ZHBqZ21kdXphY3dsIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NjQyNjUxNzMsImV4cCI6MjA3OTg0MTE3M30.WAzqgZusGoOEHxidfHc1e4daBglG4DJG5LOXbqldWQA\";\r\n\r\ninterface UserMetadata {\r\n id: string;\r\n email: string;\r\n name?: string;\r\n tier?: string;\r\n}\r\n\r\n/**\r\n * Helper functions for keyring operations using Entry class\r\n */\r\nfunction getPassword(service: string, account: string): string | null {\r\n try {\r\n const entry = new Entry(service, account);\r\n return entry.getPassword();\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\nfunction setPassword(service: string, account: string, password: string): void {\r\n const entry = new Entry(service, account);\r\n entry.setPassword(password);\r\n}\r\n\r\nfunction deletePassword(service: string, account: string): void {\r\n try {\r\n const entry = new Entry(service, account);\r\n entry.deletePassword();\r\n } catch {\r\n // Ignore if entry doesn't exist\r\n }\r\n}\r\n\r\n/**\r\n * TokenManager\r\n *\r\n * Manages secure storage and automatic refresh of authentication tokens\r\n * Uses OS-level credential managers (Keychain/Credential Manager/Secret Service)\r\n */\r\nexport class TokenManager {\r\n private supabase: SupabaseClient;\r\n\r\n constructor() {\r\n this.supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY, {\r\n auth: {\r\n autoRefreshToken: false,\r\n persistSession: false,\r\n },\r\n });\r\n }\r\n\r\n /**\r\n * Get access token, automatically refreshing if expired\r\n */\r\n async getAccessToken(): Promise<string | null> {\r\n try {\r\n let accessToken = getPassword(SERVICE_NAME, \"access_token\");\r\n\r\n if (!accessToken) {\r\n return null;\r\n }\r\n\r\n // Check if expired\r\n if (this.isTokenExpired(accessToken)) {\r\n accessToken = await this.refreshTokens();\r\n }\r\n\r\n return accessToken;\r\n } catch {\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * Refresh tokens using stored refresh token\r\n */\r\n private async refreshTokens(): Promise<string | null> {\r\n try {\r\n const refreshToken = getPassword(SERVICE_NAME, \"refresh_token\");\r\n\r\n if (!refreshToken) {\r\n throw new Error(\"No refresh token available\");\r\n }\r\n\r\n const { data, error } = await this.supabase.auth.refreshSession({\r\n refresh_token: refreshToken,\r\n });\r\n\r\n if (error || !data.session) {\r\n throw new Error(\"Failed to refresh session\");\r\n }\r\n\r\n // Store new tokens (single-use refresh token rotation)\r\n setPassword(SERVICE_NAME, \"access_token\", data.session.access_token);\r\n setPassword(SERVICE_NAME, \"refresh_token\", data.session.refresh_token);\r\n\r\n return data.session.access_token;\r\n } catch {\r\n await this.logout();\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * Check if JWT token is expired (or expires in < 5 min)\r\n */\r\n private isTokenExpired(token: string): boolean {\r\n try {\r\n const payload = JSON.parse(\r\n Buffer.from(token.split(\".\")[1]!, \"base64\").toString()\r\n );\r\n const expiresAt = payload.exp * 1000;\r\n const now = Date.now();\r\n\r\n // Refresh 5 minutes before expiration\r\n return expiresAt - now < 5 * 60 * 1000;\r\n } catch {\r\n return true; // Treat invalid tokens as expired\r\n }\r\n }\r\n\r\n /**\r\n * Save tokens and user metadata after successful login\r\n */\r\n async saveTokens(\r\n accessToken: string,\r\n refreshToken: string,\r\n user: UserMetadata\r\n ): Promise<void> {\r\n setPassword(SERVICE_NAME, \"access_token\", accessToken);\r\n setPassword(SERVICE_NAME, \"refresh_token\", refreshToken);\r\n setPassword(SERVICE_NAME, \"user_metadata\", JSON.stringify(user));\r\n }\r\n\r\n /**\r\n * Get stored user metadata\r\n */\r\n async getUserMetadata(): Promise<UserMetadata | null> {\r\n try {\r\n const metadata = getPassword(SERVICE_NAME, \"user_metadata\");\r\n return metadata ? JSON.parse(metadata) : null;\r\n } catch {\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * Logout - clear all stored credentials\r\n */\r\n async logout(): Promise<void> {\r\n try {\r\n deletePassword(SERVICE_NAME, \"access_token\");\r\n deletePassword(SERVICE_NAME, \"refresh_token\");\r\n deletePassword(SERVICE_NAME, \"user_metadata\");\r\n } catch (error) {\r\n // Ignore errors during logout\r\n }\r\n }\r\n\r\n /**\r\n * Check if user is currently authenticated\r\n */\r\n async isAuthenticated(): Promise<boolean> {\r\n const token = await this.getAccessToken();\r\n return token !== null;\r\n }\r\n}\r\n","import axios, { AxiosInstance } from \"axios\";\r\n\r\n// Production API URL (can be overridden via API_URL env for local dev)\r\nconst API_URL = process.env.API_URL || \"https://aerocoding.dev\";\r\n\r\ninterface User {\r\n id: string;\r\n email: string;\r\n name: string | null;\r\n tier: string;\r\n}\r\n\r\ninterface Organization {\r\n id: string;\r\n name: string;\r\n slug: string;\r\n planTier: string;\r\n}\r\n\r\ninterface Project {\r\n id: string;\r\n name: string;\r\n slug: string;\r\n schema: any;\r\n organizationId: string;\r\n backendFramework?: string;\r\n frontendFramework?: string;\r\n createdAt: string;\r\n updatedAt: string;\r\n}\r\n\r\ninterface GeneratePayload {\r\n projectId: string;\r\n // NEW: Use templateId for full architecture generation\r\n templateId?: string;\r\n // Legacy: Use targets for simple generation\r\n targets?: string[];\r\n options?: {\r\n includeValidations?: boolean;\r\n includeComments?: boolean;\r\n includeAnnotations?: boolean;\r\n includeLogging?: boolean;\r\n includeTesting?: boolean;\r\n outputDir?: string;\r\n backendPreset?: string;\r\n frontendPreset?: string;\r\n backendLayers?: string[];\r\n frontendLayers?: string[];\r\n validationLib?: string;\r\n // NEW: Feature flags for template generation\r\n featureFlags?: Record<string, boolean>;\r\n // Architecture style: bounded-contexts vs flat\r\n useContexts?: boolean;\r\n // Filter by diagram/bounded context IDs\r\n diagramIds?: string[];\r\n };\r\n}\r\n\r\ninterface GeneratedFile {\r\n path: string;\r\n content: string;\r\n language: string;\r\n entityId?: string;\r\n}\r\n\r\ninterface GenerateResult {\r\n files: GeneratedFile[];\r\n stats?: {\r\n totalFiles?: number;\r\n totalEntities?: number;\r\n languages?: string[];\r\n };\r\n cliCommand?: string;\r\n warnings?: string[];\r\n creditsUsed?: number;\r\n creditsRemaining?: number;\r\n}\r\n\r\ninterface CreditUsage {\r\n used: number;\r\n limit: number;\r\n bonusCredits: number;\r\n remaining: number;\r\n}\r\n\r\ninterface ArchitectureLayer {\r\n id: string;\r\n name: string;\r\n category: string;\r\n description?: string;\r\n}\r\n\r\ninterface Architecture {\r\n id: string;\r\n name: string;\r\n description: string;\r\n layers: ArchitectureLayer[];\r\n}\r\n\r\n// New Template Registry Types\r\ninterface TemplateMetadata {\r\n id: string;\r\n name: string;\r\n description: string;\r\n category: \"backend\" | \"frontend\" | \"database\" | \"infra\";\r\n language: string;\r\n framework: string;\r\n tier: \"starter\" | \"standard\" | \"enterprise\";\r\n tags: string[];\r\n version: string;\r\n author: string;\r\n isLegacy?: boolean;\r\n isOfficial?: boolean;\r\n isPremium?: boolean;\r\n /** Architecture style: \"bounded-contexts\" for DDD modules, \"flat\" for single structure */\r\n architectureStyle?: \"bounded-contexts\" | \"flat\";\r\n}\r\n\r\ninterface TemplateLayer {\r\n id: string;\r\n name: string;\r\n description: string;\r\n category: string;\r\n enabled: boolean;\r\n}\r\n\r\ninterface TemplateFeatureFlag {\r\n id: string;\r\n name: string;\r\n label: string;\r\n description?: string;\r\n defaultValue: boolean;\r\n}\r\n\r\ninterface FullTemplate extends TemplateMetadata {\r\n layers: TemplateLayer[];\r\n featureFlags: TemplateFeatureFlag[];\r\n enabledModules: string[];\r\n}\r\n\r\ninterface TemplateFilter {\r\n category?: \"backend\" | \"frontend\" | \"database\" | \"infra\";\r\n language?: string;\r\n framework?: string;\r\n tier?: \"starter\" | \"standard\" | \"enterprise\";\r\n tags?: string[];\r\n}\r\n\r\ninterface TemplateSearchResult {\r\n templates: TemplateMetadata[];\r\n total: number;\r\n page: number;\r\n pageSize: number;\r\n}\r\n\r\ninterface TemplateCombination {\r\n id: string;\r\n name: string;\r\n description: string;\r\n backend: string;\r\n frontend: string;\r\n sharedTypes?: boolean;\r\n apiContract?: \"rest\" | \"graphql\" | \"grpc\";\r\n}\r\n\r\ninterface CreditEstimate {\r\n estimatedCredits: number;\r\n totalFiles: number;\r\n files: string[];\r\n entities: number;\r\n}\r\n\r\ninterface EstimatePayload {\r\n projectId: string;\r\n // Template mode (new)\r\n templateId?: string;\r\n // Legacy targets mode\r\n targets?: string[];\r\n options?: {\r\n outputDir?: string;\r\n backendPreset?: string;\r\n frontendPreset?: string;\r\n backendLayers?: string[];\r\n frontendLayers?: string[];\r\n featureFlags?: Record<string, boolean>;\r\n // Architecture style: bounded-contexts vs flat\r\n useContexts?: boolean;\r\n // Filter by diagram/bounded context IDs\r\n diagramIds?: string[];\r\n };\r\n}\r\n\r\n/**\r\n * ApiClient\r\n *\r\n * Authenticated HTTP client for AeroCoding API\r\n * All requests include Bearer token authentication\r\n */\r\nexport class ApiClient {\r\n private client: AxiosInstance;\r\n\r\n constructor(\r\n accessToken: string,\r\n options?: {\r\n onUnauthorized?: () => Promise<void> | void;\r\n }\r\n ) {\r\n this.client = axios.create({\r\n baseURL: API_URL,\r\n headers: {\r\n Authorization: `Bearer ${accessToken}`,\r\n \"Content-Type\": \"application/json\",\r\n \"X-Requested-With\": \"XMLHttpRequest\", // Required for CSRF validation bypass\r\n },\r\n timeout: 30000, // 30 seconds\r\n });\r\n\r\n this.client.interceptors.response.use(\r\n (response) => response,\r\n async (error) => {\r\n if (error?.response?.status === 401) {\r\n await options?.onUnauthorized?.();\r\n }\r\n\r\n return Promise.reject(error);\r\n }\r\n );\r\n }\r\n\r\n /**\r\n * Get current authenticated user\r\n */\r\n async getCurrentUser(): Promise<User> {\r\n const response = await this.client.get(\"/api/user/me\");\r\n return response.data;\r\n }\r\n\r\n /**\r\n * List user's organizations\r\n */\r\n async listOrganizations(): Promise<Organization[]> {\r\n const response = await this.client.get(\"/api/organizations\");\r\n return response.data;\r\n }\r\n\r\n /**\r\n * List user's projects\r\n */\r\n async listProjects(organizationId?: string): Promise<Project[]> {\r\n const response = await this.client.get(\"/api/projects\", {\r\n params: { organizationId },\r\n });\r\n return response.data;\r\n }\r\n\r\n /**\r\n * Get project by ID\r\n */\r\n async getProject(projectId: string): Promise<Project> {\r\n const response = await this.client.get(`/api/projects/${projectId}`);\r\n return response.data;\r\n }\r\n\r\n /**\r\n * Generate code from project schema\r\n */\r\n async generateCode(payload: GeneratePayload): Promise<GenerateResult> {\r\n const response = await this.client.post(\"/api/generate\", payload);\r\n return response.data.data;\r\n }\r\n\r\n /**\r\n * Get credit usage for organization\r\n */\r\n async getCreditUsage(organizationId: string): Promise<CreditUsage> {\r\n const response = await this.client.get(\"/api/credits/usage\", {\r\n params: { organizationId },\r\n });\r\n return response.data;\r\n }\r\n\r\n /**\r\n * Get available architectures for a framework\r\n */\r\n async getArchitectures(framework: string): Promise<Architecture[]> {\r\n const response = await this.client.get(\"/api/architectures\", {\r\n params: { framework },\r\n });\r\n return response.data;\r\n }\r\n\r\n /**\r\n * Estimate credit cost for a generation request\r\n */\r\n async estimateCreditCost(payload: EstimatePayload): Promise<CreditEstimate> {\r\n const response = await this.client.post(\"/api/generate/estimate\", payload);\r\n return response.data.data;\r\n }\r\n\r\n // ============================================\r\n // Template Registry API\r\n // ============================================\r\n\r\n /**\r\n * Search templates with filters\r\n */\r\n async getTemplates(filter: TemplateFilter = {}): Promise<TemplateSearchResult> {\r\n const params = new URLSearchParams();\r\n if (filter.category) params.set(\"category\", filter.category);\r\n if (filter.language) params.set(\"language\", filter.language);\r\n if (filter.framework) params.set(\"framework\", filter.framework);\r\n if (filter.tier) params.set(\"tier\", filter.tier);\r\n if (filter.tags?.length) params.set(\"tags\", filter.tags.join(\",\"));\r\n\r\n const response = await this.client.get(`/api/templates?${params.toString()}`);\r\n return response.data;\r\n }\r\n\r\n /**\r\n * Get full template by ID (includes layers and feature flags)\r\n */\r\n async getTemplate(id: string): Promise<FullTemplate> {\r\n const response = await this.client.get(`/api/templates/${id}?full=true`);\r\n return response.data.template;\r\n }\r\n\r\n /**\r\n * Get template combinations (backend + frontend pairs)\r\n */\r\n async getTemplateCombinations(): Promise<TemplateCombination[]> {\r\n const response = await this.client.get(\"/api/templates/combinations\");\r\n return response.data.combinations;\r\n }\r\n\r\n /**\r\n * Get templates compatible with a given template\r\n */\r\n async getCompatibleTemplates(templateId: string): Promise<TemplateMetadata[]> {\r\n const response = await this.client.get(`/api/templates/${templateId}?compatible=true`);\r\n return response.data.compatible || [];\r\n }\r\n\r\n // ============================================\r\n // Manifest Cloud Sync API\r\n // ============================================\r\n\r\n /**\r\n * Get manifest from cloud storage\r\n * @returns Manifest or null if not found\r\n */\r\n async getManifest(projectId: string): Promise<CloudManifest | null> {\r\n try {\r\n const response = await this.client.get(`/api/projects/${projectId}/manifest`);\r\n return response.data;\r\n } catch (error: any) {\r\n if (error?.response?.status === 404) {\r\n return null;\r\n }\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Save manifest to cloud storage\r\n */\r\n async saveManifest(\r\n projectId: string,\r\n manifest: CloudManifest\r\n ): Promise<{ success: boolean; fileCount: number; removedPaths: number }> {\r\n const response = await this.client.put(\r\n `/api/projects/${projectId}/manifest`,\r\n manifest\r\n );\r\n return response.data;\r\n }\r\n}\r\n\r\n// ============================================\r\n// Cloud Manifest Types\r\n// ============================================\r\n\r\nexport interface CloudManifestFileEntry {\r\n hash: string;\r\n mtime: number;\r\n size: number;\r\n entityId?: string;\r\n type?: \"entity\" | \"usecase\" | \"repository\" | \"controller\" | \"dto\" | \"config\" | \"test\" | \"other\";\r\n contextName?: string;\r\n}\r\n\r\nexport interface CloudManifest {\r\n version: string;\r\n lastSync?: string;\r\n templateVersion?: string;\r\n files: Record<string, CloudManifestFileEntry>;\r\n}\r\n","import { ApiClient } from \"../../api/client.js\";\r\nimport { TokenManager } from \"../../auth/token-manager.js\";\r\n\r\nexport function createApiClientWithAutoLogout(\r\n accessToken: string,\r\n tokenManager: TokenManager\r\n): ApiClient {\r\n return new ApiClient(accessToken, {\r\n onUnauthorized: async () => {\r\n await tokenManager.logout();\r\n },\r\n });\r\n}\r\n","import chalk from \"chalk\";\r\nimport { TokenManager } from \"../../auth/token-manager.js\";\r\n\r\nexport async function handleUnauthorized(\r\n tokenManager: TokenManager\r\n): Promise<never> {\r\n await tokenManager.logout();\r\n\r\n console.error(\r\n chalk.yellow(\r\n \" Your session is invalid or expired. You have been logged out.\"\r\n )\r\n );\r\n console.error(chalk.gray(\" Run 'aerocoding login' to authenticate.\"));\r\n\r\n process.exit(1);\r\n}\r\n","import chalk from \"chalk\";\r\nimport { TokenManager } from \"../auth/token-manager.js\";\r\n\r\n/**\r\n * Logout Command\r\n *\r\n * Clears stored credentials from OS credential manager\r\n */\r\nexport async function logoutCommand() {\r\n const tokenManager = new TokenManager();\r\n\r\n const metadata = await tokenManager.getUserMetadata();\r\n if (!metadata) {\r\n console.log(chalk.yellow(\"Not logged in\"));\r\n return;\r\n }\r\n\r\n const email = metadata.email;\r\n\r\n await tokenManager.logout();\r\n\r\n console.log(chalk.green(\"Logged out successfully\"));\r\n console.log(chalk.gray(` Cleared credentials for ${email}\\n`));\r\n}\r\n","import chalk from \"chalk\";\r\nimport { TokenManager } from \"../auth/token-manager.js\";\r\nimport { createApiClientWithAutoLogout } from \"./_shared/create-api-client.js\";\r\nimport { handleUnauthorized } from \"./_shared/unauthorized.js\";\r\n\r\n/**\r\n * Whoami Command\r\n *\r\n * Shows current authenticated user information\r\n */\r\nexport async function whoamiCommand() {\r\n const tokenManager = new TokenManager();\r\n const token = await tokenManager.getAccessToken();\r\n\r\n if (!token) {\r\n console.log(chalk.red(\"Not logged in\"));\r\n console.log(chalk.gray(\" Run 'aerocoding login' to authenticate\\n\"));\r\n return;\r\n }\r\n\r\n try {\r\n const apiClient = createApiClientWithAutoLogout(token, tokenManager);\r\n const user = await apiClient.getCurrentUser();\r\n\r\n console.log(\"\");\r\n console.log(chalk.white(\"Logged in as:\"), chalk.cyan.bold(user.email));\r\n if (user.name) {\r\n console.log(chalk.gray(\" Name:\"), user.name);\r\n }\r\n console.log(\"\");\r\n } catch (error: any) {\r\n console.error(chalk.red(\"Failed to get user info\"));\r\n if (error.response?.status === 401) {\r\n await handleUnauthorized(tokenManager);\r\n }\r\n process.exit(1);\r\n }\r\n}\r\n","import chalk from \"chalk\";\r\nimport ora from \"ora\";\r\nimport * as p from \"@clack/prompts\";\r\nimport { TokenManager } from \"../auth/token-manager.js\";\r\nimport { createApiClientWithAutoLogout } from \"./_shared/create-api-client.js\";\r\nimport { handleUnauthorized } from \"./_shared/unauthorized.js\";\r\nimport { writeGeneratedFiles, categorizeFilePaths } from \"../utils/file-writer.js\";\r\nimport { promptConfirm } from \"../utils/prompt.js\";\r\nimport { loadConfig } from \"../config/loader.js\";\r\nimport type { AerocodingConfig } from \"../config/schema.js\";\r\n\r\n/**\r\n * Map preset name to template ID for full architecture generation\r\n * Uses the new template system that generates all layers (DTOs, UseCases, Controllers, etc.)\r\n */\r\nfunction mapPresetToTemplateId(preset: string): string | null {\r\n const presetLower = preset.toLowerCase();\r\n\r\n // Clean Architecture presets → full template IDs\r\n if (presetLower.includes(\"clean\") && presetLower.includes(\"dotnet\")) {\r\n return \"clean-arch-dotnet\";\r\n }\r\n if (presetLower.includes(\"clean\") && (presetLower.includes(\"dart\") || presetLower.includes(\"flutter\"))) {\r\n return \"flutter-clean-dart-test\"; // Update when production template available\r\n }\r\n if (presetLower.includes(\"clean\") && presetLower.includes(\"typescript\")) {\r\n return \"minimal-typescript-test\"; // Update when production template available\r\n }\r\n\r\n // Direct template ID (if preset matches a template ID pattern)\r\n if (presetLower.startsWith(\"clean-arch-\")) {\r\n return preset;\r\n }\r\n\r\n return null;\r\n}\r\n\r\n/**\r\n * Map preset name to legacy generator target (fallback)\r\n * Used when no template ID is available for the preset\r\n */\r\nfunction mapPresetToTarget(preset: string): string | null {\r\n const presetLower = preset.toLowerCase();\r\n\r\n // .NET presets\r\n if (presetLower.includes(\"dotnet\") || presetLower.includes(\"aspnet\") || presetLower.includes(\"csharp\")) {\r\n return \"dotnet-entity\";\r\n }\r\n\r\n // Dart/Flutter presets\r\n if (presetLower.includes(\"dart\") || presetLower.includes(\"flutter\")) {\r\n return \"dart-entity\";\r\n }\r\n\r\n // TypeScript presets\r\n if (presetLower.includes(\"typescript\") || presetLower.includes(\"nextjs\") || presetLower.includes(\"react\")) {\r\n return \"typescript-interface\";\r\n }\r\n\r\n return null;\r\n}\r\n\r\n\r\n/**\r\n * Build feature flags from config for template generation\r\n */\r\nfunction buildFeatureFlagsFromConfig(config: AerocodingConfig | null): Record<string, boolean> {\r\n const flags: Record<string, boolean> = {\r\n // Default all feature flags to true for full architecture\r\n includeDtos: true,\r\n includeUseCases: true,\r\n includeMappers: true,\r\n includeControllers: true,\r\n includeEfConfig: true,\r\n includeValidation: true,\r\n includeDtoValidation: true, // Data Annotations on Input records ([Required], [MaxLength], etc.)\r\n // Test flags\r\n includeUnitTests: true,\r\n includeIntegrationTests: true,\r\n // Starter files (disabled by default - user adds their own Program.cs)\r\n includeStarterFiles: false,\r\n };\r\n\r\n if (!config) return flags;\r\n\r\n // Map codeStyle options to feature flags\r\n if (config.codeStyle?.includeValidations !== undefined) {\r\n flags.includeValidation = config.codeStyle.includeValidations;\r\n }\r\n // Map includeTesting to both unit and integration tests\r\n if (config.codeStyle?.includeTesting !== undefined) {\r\n flags.includeUnitTests = config.codeStyle.includeTesting;\r\n flags.includeIntegrationTests = config.codeStyle.includeTesting;\r\n }\r\n\r\n return flags;\r\n}\r\n\r\n/**\r\n * Categorize files by target (backend vs frontend) based on file extension\r\n */\r\nfunction categorizeFilesByTarget(files: string[]): { backend: string[]; frontend: string[] } {\r\n const backend: string[] = [];\r\n const frontend: string[] = [];\r\n\r\n for (const file of files) {\r\n const ext = file.split(\".\").pop()?.toLowerCase();\r\n\r\n // .NET backend\r\n if (ext === \"cs\" || ext === \"csproj\" || ext === \"sln\") {\r\n backend.push(file);\r\n }\r\n // Flutter/Dart frontend\r\n else if (ext === \"dart\" || file.includes(\"pubspec.yaml\")) {\r\n frontend.push(file);\r\n }\r\n // TypeScript (check path for hints)\r\n else if (ext === \"ts\" || ext === \"tsx\" || ext === \"js\" || ext === \"jsx\") {\r\n if (file.toLowerCase().includes(\"frontend\") || file.includes(\".tsx\")) {\r\n frontend.push(file);\r\n } else {\r\n backend.push(file);\r\n }\r\n }\r\n // Default: check for framework hints in path\r\n else {\r\n if (file.toLowerCase().includes(\"flutter\") || file.toLowerCase().includes(\"dart\")) {\r\n frontend.push(file);\r\n } else {\r\n backend.push(file);\r\n }\r\n }\r\n }\r\n\r\n return { backend, frontend };\r\n}\r\n\r\n/**\r\n * Display file categories with aligned counts\r\n */\r\nfunction displayFileCategories(files: string[]): void {\r\n const categories = categorizeFilePaths(files);\r\n const maxNameLength = Math.max(...categories.map((c) => c.name.length));\r\n\r\n for (const category of categories) {\r\n const padding = \" \".repeat(maxNameLength - category.name.length + 2);\r\n const countStr = category.count.toString().padStart(3, \" \");\r\n console.log(\r\n chalk.gray(` ${category.name}${padding}`),\r\n chalk.cyan(`${countStr} files`)\r\n );\r\n }\r\n}\r\n\r\n/**\r\n * Check if a file belongs to backend based on extension\r\n */\r\nfunction isBackendFile(filePath: string): boolean {\r\n const ext = filePath.split(\".\").pop()?.toLowerCase();\r\n // .NET backend files\r\n if (ext === \"cs\" || ext === \"csproj\" || ext === \"sln\") {\r\n return true;\r\n }\r\n // TypeScript backend (check path for hints)\r\n if (ext === \"ts\" || ext === \"js\") {\r\n if (filePath.toLowerCase().includes(\"frontend\") || filePath.includes(\".tsx\")) {\r\n return false;\r\n }\r\n return true;\r\n }\r\n return false;\r\n}\r\n\r\n/**\r\n * Check if a file belongs to frontend based on extension\r\n */\r\nfunction isFrontendFile(filePath: string): boolean {\r\n const ext = filePath.split(\".\").pop()?.toLowerCase();\r\n // Flutter/Dart frontend\r\n if (ext === \"dart\" || filePath.includes(\"pubspec.yaml\")) {\r\n return true;\r\n }\r\n // React/TypeScript frontend\r\n if (ext === \"tsx\" || ext === \"jsx\") {\r\n return true;\r\n }\r\n // TypeScript with frontend hints\r\n if ((ext === \"ts\" || ext === \"js\") && filePath.toLowerCase().includes(\"frontend\")) {\r\n return true;\r\n }\r\n // Flutter/Dart hints in path\r\n if (filePath.toLowerCase().includes(\"flutter\") || filePath.toLowerCase().includes(\"dart\")) {\r\n return true;\r\n }\r\n return false;\r\n}\r\n\r\ninterface GeneratedFileWithPath {\r\n path: string;\r\n content: string;\r\n language: string;\r\n entityId?: string;\r\n generateOnce?: boolean;\r\n}\r\n\r\n/**\r\n * Organize files into backend/frontend folders based on selected target\r\n */\r\nfunction organizeFilesIntoFolders(\r\n files: GeneratedFileWithPath[],\r\n selectedTarget: \"backend\" | \"frontend\" | \"both\"\r\n): GeneratedFileWithPath[] {\r\n return files.map((file) => {\r\n let newPath = file.path;\r\n\r\n if (selectedTarget === \"both\") {\r\n // When generating both, separate into folders\r\n if (isBackendFile(file.path)) {\r\n newPath = `backend/${file.path}`;\r\n } else if (isFrontendFile(file.path)) {\r\n newPath = `frontend/${file.path}`;\r\n } else {\r\n // Default to backend for unknown files\r\n newPath = `backend/${file.path}`;\r\n }\r\n } else if (selectedTarget === \"backend\") {\r\n // Backend only - put in backend folder\r\n newPath = `backend/${file.path}`;\r\n } else if (selectedTarget === \"frontend\") {\r\n // Frontend only - put in frontend folder\r\n newPath = `frontend/${file.path}`;\r\n }\r\n\r\n return { ...file, path: newPath };\r\n });\r\n}\r\n\r\ninterface GenerateOptions {\r\n project?: string;\r\n targets?: string[];\r\n entities?: string[];\r\n output: string;\r\n // Presets\r\n backendPreset?: string;\r\n frontendPreset?: string;\r\n // Style toggles (commander inverts for --no-X, all default to true)\r\n validations?: boolean;\r\n comments?: boolean;\r\n logging?: boolean;\r\n testing?: boolean;\r\n // Validation library (framework-agnostic)\r\n validationLib?: string;\r\n // Control\r\n verbose?: boolean;\r\n yes?: boolean;\r\n all?: boolean; // Generate all diagrams and targets without prompting\r\n}\r\n\r\n/**\r\n * Generate Command\r\n *\r\n * Generates code from project schema via API\r\n * Consumes credits based on generated files and entity complexity\r\n *\r\n * Config file (.aerocodingrc.json) provides defaults, CLI args override\r\n */\r\nexport async function generateCommand(options: GenerateOptions) {\r\n // 1. Check authentication\r\n const tokenManager = new TokenManager();\r\n const token = await tokenManager.getAccessToken();\r\n\r\n if (!token) {\r\n console.log(chalk.red(\"\\n Not authenticated\"));\r\n console.log(chalk.gray(\" Run 'aerocoding login' to get started\\n\"));\r\n process.exit(1);\r\n }\r\n\r\n // 2. Load config file (optional)\r\n const config = await loadConfig();\r\n\r\n // 3. Merge config with CLI options (CLI overrides config)\r\n const projectId = options.project || config?.project;\r\n\r\n if (!projectId) {\r\n console.log(chalk.red(\"\\n Project ID required\"));\r\n console.log(chalk.gray(\" Run 'aerocoding init' to create a config file\"));\r\n console.log(chalk.gray(\" Or use --project <id> to specify a project\\n\"));\r\n process.exit(1);\r\n }\r\n\r\n // Merge other options with config defaults (templateId will be determined after target selection)\r\n const output = options.output || config?.output || \"./.aerocoding\";\r\n const validationLib = options.validationLib || config?.libraries?.validation;\r\n\r\n // Style options: CLI --no-X overrides config, config overrides default (true)\r\n const includeValidations = options.validations ?? config?.codeStyle?.includeValidations ?? true;\r\n const includeComments = options.comments ?? config?.codeStyle?.includeComments ?? true;\r\n const includeLogging = options.logging ?? config?.codeStyle?.includeLogging ?? true;\r\n const includeTesting = options.testing ?? config?.codeStyle?.includeTesting ?? true;\r\n\r\n const apiClient = createApiClientWithAutoLogout(token, tokenManager);\r\n\r\n let spinner = ora({ text: \"Fetching project...\", color: \"cyan\" }).start();\r\n\r\n try {\r\n // 4. Fetch project to get organizationId\r\n const project = await apiClient.getProject(projectId);\r\n spinner.succeed(chalk.gray(\"Project loaded\"));\r\n\r\n // 4a. Validate config against project settings\r\n const hasBackendConfig = !!config?.backend?.preset;\r\n const hasFrontendConfig = !!config?.frontend?.preset;\r\n const projectHasBackend = !!project.backendFramework;\r\n const projectHasFrontend = !!project.frontendFramework;\r\n\r\n // Check for mismatches between config and project settings\r\n if (hasBackendConfig && !projectHasBackend) {\r\n console.log(\"\");\r\n console.log(chalk.yellow(\" ⚠ Backend is configured but disabled in project settings.\"));\r\n console.log(chalk.gray(\" Enable backend framework at aerocoding.dev or run 'aerocoding init' to reconfigure.\"));\r\n }\r\n\r\n if (hasFrontendConfig && !projectHasFrontend) {\r\n console.log(\"\");\r\n console.log(chalk.yellow(\" ⚠ Frontend is configured but disabled in project settings.\"));\r\n console.log(chalk.gray(\" Enable frontend framework at aerocoding.dev or run 'aerocoding init' to reconfigure.\"));\r\n }\r\n\r\n // Determine available targets (must be in both config AND project settings)\r\n const backendAvailable = hasBackendConfig && projectHasBackend;\r\n const frontendAvailable = hasFrontendConfig && projectHasFrontend;\r\n\r\n if (!backendAvailable && !frontendAvailable) {\r\n console.log(chalk.red(\"\\n No valid targets available.\"));\r\n console.log(chalk.gray(\" Check your project settings at aerocoding.dev and run 'aerocoding init'.\"));\r\n console.log(\"\");\r\n process.exit(1);\r\n }\r\n\r\n // 4b. Target selection (backend/frontend) - only if both available\r\n const hasBothTargets = backendAvailable && frontendAvailable;\r\n\r\n let selectedTarget: \"backend\" | \"frontend\" | \"both\" = \"both\";\r\n\r\n if (hasBothTargets && !options.all) {\r\n const targetChoice = await p.select({\r\n message: \"Which target do you want to generate?\",\r\n options: [\r\n {\r\n value: \"both\",\r\n label: \"Both\",\r\n },\r\n {\r\n value: \"backend\",\r\n label: `Backend (${config?.backend?.preset})`,\r\n },\r\n {\r\n value: \"frontend\",\r\n label: `Frontend (${config?.frontend?.preset})`,\r\n },\r\n ],\r\n initialValue: \"both\",\r\n });\r\n\r\n if (p.isCancel(targetChoice)) {\r\n console.log(chalk.yellow(\"\\n Generation cancelled\\n\"));\r\n process.exit(0);\r\n }\r\n\r\n selectedTarget = targetChoice as \"backend\" | \"frontend\" | \"both\";\r\n } else if (backendAvailable && !frontendAvailable) {\r\n selectedTarget = \"backend\";\r\n } else if (frontendAvailable && !backendAvailable) {\r\n selectedTarget = \"frontend\";\r\n }\r\n\r\n // 4b. Diagram selection - only if multiple diagrams exist\r\n interface Diagram {\r\n id?: string;\r\n name?: string;\r\n entities?: unknown[];\r\n }\r\n const diagrams: Diagram[] = (project.schema as { diagrams?: Diagram[] })?.diagrams || [];\r\n const hasMultipleDiagrams = diagrams.length > 1;\r\n\r\n let selectedDiagramIds: string[] = diagrams.map((d) => d.id || d.name || \"unknown\");\r\n\r\n if (hasMultipleDiagrams && !options.all) {\r\n const diagramChoices = await p.multiselect({\r\n message: \"Which bounded contexts do you want to generate?\",\r\n options: diagrams.map((d) => ({\r\n value: d.id || d.name || \"unknown\",\r\n label: `${d.name || \"Unnamed\"} (${d.entities?.length || 0} entities)`,\r\n })),\r\n initialValues: diagrams.map((d) => d.id || d.name || \"unknown\"),\r\n required: true,\r\n });\r\n\r\n if (p.isCancel(diagramChoices)) {\r\n console.log(chalk.yellow(\"\\n Generation cancelled\\n\"));\r\n process.exit(0);\r\n }\r\n\r\n selectedDiagramIds = diagramChoices as string[];\r\n }\r\n\r\n // 4c. Build templateId, targets, featureFlags based on selected target\r\n let templateId: string | null = null;\r\n let targets: string[] = [];\r\n let backendPreset: string | undefined;\r\n let frontendPreset: string | undefined;\r\n\r\n if (selectedTarget === \"backend\" || selectedTarget === \"both\") {\r\n backendPreset = options.backendPreset || config?.backend?.preset;\r\n if (backendPreset) {\r\n const tid = mapPresetToTemplateId(backendPreset);\r\n if (tid) templateId = tid;\r\n const target = mapPresetToTarget(backendPreset);\r\n if (target) targets.push(target);\r\n }\r\n }\r\n\r\n if (selectedTarget === \"frontend\" || selectedTarget === \"both\") {\r\n frontendPreset = options.frontendPreset || config?.frontend?.preset;\r\n if (frontendPreset) {\r\n const tid = mapPresetToTemplateId(frontendPreset);\r\n if (tid && !templateId) templateId = tid; // Only if backend didn't set one\r\n const target = mapPresetToTarget(frontendPreset);\r\n if (target) targets.push(target);\r\n }\r\n }\r\n\r\n // Fallback: if no config, try CLI options for targets\r\n if (!templateId && (!targets || targets.length === 0)) {\r\n targets = options.targets || [];\r\n }\r\n\r\n // Build feature flags from config\r\n const featureFlags = buildFeatureFlagsFromConfig(config);\r\n\r\n // 5. Fetch credit usage and estimate cost in parallel\r\n spinner = ora({ text: \"Checking credits...\", color: \"cyan\" }).start();\r\n\r\n const credits = await apiClient.getCreditUsage(project.organizationId);\r\n\r\n // Try to get cost estimate (includes file paths for preview)\r\n // Determine architecture style early for estimate\r\n const useContexts = config?.architectureStyle !== \"flat\";\r\n\r\n // Include diagramIds to filter estimate by selected bounded contexts\r\n const estimateDiagramIds = selectedDiagramIds.length < diagrams.length ? selectedDiagramIds : undefined;\r\n\r\n let estimate: { estimatedCredits: number; totalFiles: number; entities: number; files: string[] } | null = null;\r\n try {\r\n if (templateId) {\r\n // Template mode: estimate using templateId\r\n estimate = await apiClient.estimateCreditCost({\r\n projectId,\r\n templateId,\r\n options: {\r\n featureFlags,\r\n useContexts,\r\n diagramIds: estimateDiagramIds,\r\n },\r\n });\r\n } else if (targets && targets.length > 0) {\r\n // Legacy mode: estimate using targets\r\n estimate = await apiClient.estimateCreditCost({\r\n projectId,\r\n targets,\r\n options: {\r\n outputDir: output,\r\n backendPreset,\r\n frontendPreset,\r\n useContexts,\r\n diagramIds: estimateDiagramIds,\r\n },\r\n });\r\n }\r\n } catch {\r\n // Estimate endpoint may not be available yet - continue without estimate\r\n }\r\n\r\n spinner.succeed(chalk.gray(\"Credits verified\"));\r\n\r\n // Check if project has entities (required for generation)\r\n if (estimate && estimate.entities === 0) {\r\n console.log(chalk.yellow(\"\\n ⚠ No entities found in this project.\"));\r\n console.log(chalk.gray(\" Create entities in the diagram editor and save (Ctrl+S) before generating.\\n\"));\r\n process.exit(1);\r\n }\r\n\r\n // Check if enough credits before showing summary (skip if no estimate)\r\n const hasEnoughCredits = estimate ? credits.remaining >= estimate.estimatedCredits : true;\r\n\r\n // 6. Show summary\r\n console.log(\"\");\r\n console.log(chalk.bold(\" Generation Summary\"));\r\n console.log(chalk.gray(\" ─────────────────────────────────\"));\r\n console.log(chalk.gray(\" Project:\"), chalk.white(project.name));\r\n if (config) {\r\n console.log(chalk.gray(\" Config:\"), chalk.cyan(\".aerocodingrc.json\"));\r\n }\r\n // Show generation mode\r\n if (templateId) {\r\n console.log(chalk.gray(\" Mode:\"), chalk.green(\"Full Architecture\"));\r\n console.log(chalk.gray(\" Template:\"), chalk.cyan(templateId));\r\n } else if (targets && targets.length > 0) {\r\n console.log(chalk.gray(\" Mode:\"), chalk.yellow(\"Simple (legacy)\"));\r\n console.log(chalk.gray(\" Targets:\"), chalk.cyan(targets.join(\", \")));\r\n } else {\r\n console.log(chalk.gray(\" Mode:\"), chalk.gray(\"default\"));\r\n }\r\n\r\n // Show selected target (if user had a choice)\r\n if (hasBothTargets) {\r\n const targetLabel =\r\n selectedTarget === \"backend\"\r\n ? \"Backend only\"\r\n : selectedTarget === \"frontend\"\r\n ? \"Frontend only\"\r\n : \"Backend + Frontend\";\r\n console.log(chalk.gray(\" Target:\"), chalk.cyan(targetLabel));\r\n }\r\n\r\n if (backendPreset && (selectedTarget === \"backend\" || selectedTarget === \"both\")) {\r\n console.log(chalk.gray(\" Backend Preset:\"), chalk.cyan(backendPreset));\r\n }\r\n if (frontendPreset && (selectedTarget === \"frontend\" || selectedTarget === \"both\")) {\r\n console.log(chalk.gray(\" Frontend Preset:\"), chalk.cyan(frontendPreset));\r\n }\r\n\r\n // Show selected diagrams (if user had a choice)\r\n if (hasMultipleDiagrams) {\r\n const selectedCount = selectedDiagramIds.length;\r\n const totalCount = diagrams.length;\r\n if (selectedCount === totalCount) {\r\n console.log(chalk.gray(\" Bounded Contexts:\"), chalk.cyan(`All (${totalCount})`));\r\n } else {\r\n const selectedNames = diagrams\r\n .filter((d) => selectedDiagramIds.includes(d.id || d.name || \"unknown\"))\r\n .map((d) => d.name || \"Unnamed\")\r\n .join(\", \");\r\n console.log(chalk.gray(\" Bounded Contexts:\"), chalk.cyan(`${selectedCount}/${totalCount} (${selectedNames})`));\r\n }\r\n }\r\n\r\n // Show architecture style\r\n const archStyle = config?.architectureStyle || \"bounded-contexts\";\r\n console.log(\r\n chalk.gray(\" Architecture:\"),\r\n archStyle === \"bounded-contexts\"\r\n ? chalk.cyan(\"Bounded Contexts\")\r\n : chalk.yellow(\"Flat Structure\")\r\n );\r\n\r\n // Show style options if different from defaults (all default to true)\r\n const disabledOptions: string[] = [];\r\n if (!includeValidations) disabledOptions.push(\"validations\");\r\n if (!includeComments) disabledOptions.push(\"comments\");\r\n if (!includeLogging) disabledOptions.push(\"logging\");\r\n if (!includeTesting) disabledOptions.push(\"testing\");\r\n\r\n if (disabledOptions.length > 0) {\r\n console.log(chalk.gray(\" Disabled:\"), chalk.yellow(disabledOptions.join(\", \")));\r\n }\r\n\r\n if (validationLib) {\r\n console.log(chalk.gray(\" Validation Lib:\"), chalk.cyan(validationLib));\r\n }\r\n\r\n console.log(chalk.gray(\" Output:\"), chalk.cyan(output));\r\n\r\n // Show categorized file preview (if available)\r\n if (estimate && estimate.files && estimate.files.length > 0) {\r\n const { backend: backendFiles, frontend: frontendFiles } = categorizeFilesByTarget(estimate.files);\r\n\r\n // Show Backend files (if generating backend and has backend files)\r\n if ((selectedTarget === \"backend\" || selectedTarget === \"both\") && backendFiles.length > 0) {\r\n console.log(\"\");\r\n console.log(chalk.bold(\" Files to Generate (Backend)\"));\r\n console.log(chalk.gray(\" ─────────────────────────────────\"));\r\n displayFileCategories(backendFiles);\r\n console.log(chalk.gray(\" ─────────────────────────────────\"));\r\n console.log(chalk.gray(\" Subtotal:\"), chalk.cyan(`${backendFiles.length} files`));\r\n }\r\n\r\n // Show Frontend files (if generating frontend and has frontend files)\r\n if ((selectedTarget === \"frontend\" || selectedTarget === \"both\") && frontendFiles.length > 0) {\r\n console.log(\"\");\r\n console.log(chalk.bold(\" Files to Generate (Frontend)\"));\r\n console.log(chalk.gray(\" ─────────────────────────────────\"));\r\n displayFileCategories(frontendFiles);\r\n console.log(chalk.gray(\" ─────────────────────────────────\"));\r\n console.log(chalk.gray(\" Subtotal:\"), chalk.cyan(`${frontendFiles.length} files`));\r\n }\r\n\r\n // Show Total (only if generating both and has files from both)\r\n if (selectedTarget === \"both\" && backendFiles.length > 0 && frontendFiles.length > 0) {\r\n console.log(\"\");\r\n console.log(chalk.bold(\" Total\"));\r\n console.log(chalk.gray(\" ─────────────────────────────────\"));\r\n console.log(chalk.gray(\" Backend:\"), chalk.cyan(`${backendFiles.length} files`));\r\n console.log(chalk.gray(\" Frontend:\"), chalk.cyan(`${frontendFiles.length} files`));\r\n console.log(chalk.gray(\" ─────────────────────────────────\"));\r\n console.log(chalk.white(\" Total:\"), chalk.bold.cyan(`${estimate.totalFiles} files`));\r\n }\r\n\r\n console.log(chalk.gray(` Entities:`), chalk.cyan(estimate.entities));\r\n }\r\n\r\n // Show credits section\r\n console.log(\"\");\r\n console.log(chalk.bold(\" Credits\"));\r\n console.log(chalk.gray(\" ─────────────────────────────────\"));\r\n if (estimate) {\r\n console.log(\r\n chalk.white(\" Cost:\"),\r\n hasEnoughCredits\r\n ? chalk.bold.yellow(`${estimate.estimatedCredits} credits`)\r\n : chalk.bold.red(`${estimate.estimatedCredits} credits`)\r\n );\r\n }\r\n console.log(\r\n chalk.white(\" Available:\"),\r\n hasEnoughCredits\r\n ? chalk.bold.green(`${credits.remaining} credits`)\r\n : chalk.bold.red(`${credits.remaining} credits (insufficient)`)\r\n );\r\n console.log(\"\");\r\n\r\n // Warn if not enough credits\r\n if (!hasEnoughCredits && estimate) {\r\n console.log(chalk.red(\" ⚠ Not enough credits for this generation.\"));\r\n console.log(chalk.gray(` Need ${estimate.estimatedCredits - credits.remaining} more credits.\\n`));\r\n process.exit(1);\r\n }\r\n\r\n // 7. Confirmation (unless --yes)\r\n if (!options.yes) {\r\n const confirmed = await promptConfirm(\" Proceed with generation?\");\r\n if (!confirmed) {\r\n console.log(chalk.yellow(\"\\n Generation cancelled\\n\"));\r\n process.exit(0);\r\n }\r\n }\r\n\r\n // 8. Call API\r\n console.log(\"\");\r\n spinner = ora({ text: \"Generating code...\", color: \"cyan\" }).start();\r\n\r\n // Build API request based on mode (useContexts already determined above)\r\n // Include diagramIds to filter which bounded contexts to generate\r\n const diagramIds = selectedDiagramIds.length < diagrams.length ? selectedDiagramIds : undefined;\r\n\r\n const generatePayload = templateId\r\n ? {\r\n // NEW: Full architecture mode using template\r\n projectId,\r\n templateId,\r\n options: {\r\n includeValidations,\r\n includeComments,\r\n featureFlags,\r\n useContexts,\r\n diagramIds, // Filter by selected bounded contexts\r\n },\r\n }\r\n : {\r\n // Legacy mode using targets\r\n projectId,\r\n targets,\r\n options: {\r\n includeValidations,\r\n includeComments,\r\n includeLogging,\r\n includeTesting,\r\n outputDir: output,\r\n backendPreset,\r\n frontendPreset,\r\n validationLib,\r\n useContexts,\r\n diagramIds, // Filter by selected bounded contexts\r\n },\r\n };\r\n\r\n const result = await apiClient.generateCode(generatePayload);\r\n\r\n spinner.succeed(chalk.green(\"Code generated successfully!\"));\r\n\r\n // 9. Show results with credits\r\n console.log(\"\");\r\n console.log(chalk.bold(\" Results\"));\r\n console.log(chalk.gray(\" ─────────────────────────────────\"));\r\n console.log(chalk.gray(\" Files:\"), chalk.cyan(result.stats?.totalFiles ?? result.files?.length ?? 0));\r\n if (result.stats?.totalEntities) {\r\n console.log(chalk.gray(\" Entities:\"), chalk.cyan(result.stats.totalEntities));\r\n }\r\n if (result.stats?.languages && result.stats.languages.length > 0) {\r\n console.log(\r\n chalk.gray(\" Languages:\"),\r\n chalk.cyan(result.stats.languages.join(\", \"))\r\n );\r\n }\r\n\r\n if (result.creditsUsed !== undefined) {\r\n console.log(\"\");\r\n console.log(chalk.bold(\" Credits\"));\r\n console.log(chalk.gray(\" ─────────────────────────────────\"));\r\n console.log(chalk.gray(\" Used:\"), chalk.yellow(result.creditsUsed));\r\n console.log(\r\n chalk.gray(\" Remaining:\"),\r\n result.creditsRemaining !== undefined && result.creditsRemaining > 50\r\n ? chalk.green(result.creditsRemaining)\r\n : chalk.yellow(result.creditsRemaining)\r\n );\r\n }\r\n\r\n // Show warnings if any\r\n if (result.warnings && result.warnings.length > 0) {\r\n console.log(\"\");\r\n console.log(chalk.yellow(\" Warnings:\"));\r\n for (const warning of result.warnings) {\r\n console.log(chalk.yellow(` - ${warning}`));\r\n }\r\n }\r\n\r\n console.log(\"\");\r\n\r\n // 10. Organize files into backend/frontend folders and write to disk\r\n const organizedFiles = organizeFilesIntoFolders(result.files, selectedTarget);\r\n await writeGeneratedFiles(organizedFiles, output, options.verbose);\r\n\r\n // Show output path(s)\r\n if (selectedTarget === \"both\") {\r\n console.log(chalk.green(` Files written to ${chalk.white(output)}/backend and ${chalk.white(output)}/frontend`));\r\n } else {\r\n console.log(chalk.green(` Files written to ${chalk.white(output)}/${selectedTarget}`));\r\n }\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\nimport type { AeroManifest, ManifestFileEntry } from \"../manifest/index.js\";\r\nimport {\r\n createEmptyManifest,\r\n setManifestFile,\r\n writeManifest,\r\n readManifest,\r\n detectFileChange,\r\n hashString,\r\n} from \"../manifest/index.js\";\r\nimport {\r\n performMerge,\r\n writeConflictFiles,\r\n} from \"../merge/index.js\";\r\n\r\ninterface GeneratedFile {\r\n path: string;\r\n content: string;\r\n language: string;\r\n entityId?: string;\r\n /**\r\n * If true, file should only be written if it doesn't already exist.\r\n * Used for starter files (Program.cs, appsettings.json) that users may customize.\r\n */\r\n generateOnce?: boolean;\r\n /**\r\n * File type for manifest categorization\r\n */\r\n type?: ManifestFileEntry['type'];\r\n /**\r\n * Bounded context name for DDD organization\r\n */\r\n contextName?: string;\r\n}\r\n\r\n/**\r\n * Result of writing files with manifest tracking\r\n */\r\nexport interface WriteResult {\r\n created: string[];\r\n updated: string[];\r\n merged: string[];\r\n skipped: string[];\r\n conflicts: Array<{\r\n path: string;\r\n reason: string;\r\n newPath?: string;\r\n conflictPath?: string;\r\n }>;\r\n manifest: AeroManifest;\r\n}\r\n\r\nexport interface FileCategory {\r\n name: string;\r\n count: number;\r\n files: string[];\r\n}\r\n\r\n/**\r\n * Validate that a file path is safe and doesn't escape the output directory.\r\n * SECURITY: Prevents path traversal attacks (e.g., ../../../etc/passwd)\r\n */\r\nfunction isPathSafe(outputDir: string, filePath: string): boolean {\r\n // Resolve both paths to absolute paths\r\n const resolvedOutput = path.resolve(outputDir);\r\n const resolvedFile = path.resolve(outputDir, filePath);\r\n\r\n // Check if the resolved file path starts with the output directory\r\n // Also ensure there's a path separator after the base to prevent\r\n // matching \"output\" when file is in \"output-malicious\"\r\n return (\r\n resolvedFile.startsWith(resolvedOutput + path.sep) ||\r\n resolvedFile === resolvedOutput\r\n );\r\n}\r\n\r\n/**\r\n * Get category name from file path\r\n * Analyzes path segments to determine file type\r\n * @public Exported for use in preview/estimate display\r\n */\r\nexport function getCategoryFromPath(filePath: string): string {\r\n const lowerPath = filePath.toLowerCase();\r\n\r\n // Order matters - more specific first\r\n if (lowerPath.includes(\"/controllers/\")) return \"Controllers\";\r\n if (lowerPath.includes(\"/usecases/\") || lowerPath.includes(\"/use-cases/\"))\r\n return \"UseCases\";\r\n if (lowerPath.includes(\"/dtos/\") || lowerPath.includes(\"/dto/\")) return \"DTOs\";\r\n if (lowerPath.includes(\"/entities/\")) return \"Entities\";\r\n if (\r\n lowerPath.includes(\"/repositories/\") ||\r\n lowerPath.includes(\"/repositoriesimpl/\")\r\n )\r\n return \"Repositories\";\r\n if (\r\n lowerPath.includes(\"/configurations/\") ||\r\n lowerPath.includes(\"/config/\")\r\n )\r\n return \"Configurations\";\r\n if (\r\n lowerPath.includes(\"/validators/\") ||\r\n lowerPath.includes(\"/validation/\")\r\n )\r\n return \"Validators\";\r\n if (lowerPath.includes(\"/mappers/\")) return \"Mappers\";\r\n if (lowerPath.includes(\"/interfaces/\")) return \"Interfaces\";\r\n if (lowerPath.includes(\"/exceptions/\")) return \"Exceptions\";\r\n if (lowerPath.includes(\"/vos/\") || lowerPath.includes(\"/valueobjects/\"))\r\n return \"ValueObjects\";\r\n if (lowerPath.includes(\"/ioc/\") || lowerPath.includes(\"/di/\"))\r\n return \"DependencyInjection\";\r\n if (\r\n lowerPath.includes(\"/tests/\") ||\r\n lowerPath.includes(\".test.\") ||\r\n lowerPath.includes(\".spec.\")\r\n )\r\n return \"Tests\";\r\n if (lowerPath.includes(\"/database/\")) return \"Database\";\r\n\r\n return \"Other\";\r\n}\r\n\r\n/**\r\n * Categorize file paths into categories\r\n * Used for preview/estimate display before generation\r\n * @public Exported for use in generate command preview\r\n */\r\nexport function categorizeFilePaths(filePaths: string[]): FileCategory[] {\r\n const categories = new Map<string, string[]>();\r\n\r\n for (const filePath of filePaths) {\r\n const category = getCategoryFromPath(filePath);\r\n const existing = categories.get(category) || [];\r\n existing.push(filePath);\r\n categories.set(category, existing);\r\n }\r\n\r\n return Array.from(categories.entries())\r\n .map(([name, fileList]) => ({ name, count: fileList.length, files: fileList }))\r\n .sort((a, b) => b.count - a.count); // Most files first\r\n}\r\n\r\n/**\r\n * Categorize files by their path\r\n * Groups files into categories like Entities, DTOs, UseCases, etc.\r\n */\r\nfunction categorizeFiles(files: GeneratedFile[]): FileCategory[] {\r\n return categorizeFilePaths(files.map((f) => f.path));\r\n}\r\n\r\n/**\r\n * Display categorized summary of generated files\r\n */\r\nfunction displayCategorizedSummary(files: GeneratedFile[]): void {\r\n const categories = categorizeFiles(files);\r\n\r\n console.log(\"\");\r\n console.log(chalk.bold(\" Generated Files\"));\r\n console.log(chalk.gray(\" ─────────────────────────────────\"));\r\n\r\n // Find max name length for alignment\r\n const maxNameLength = Math.max(...categories.map((c) => c.name.length));\r\n\r\n for (const category of categories) {\r\n const padding = \" \".repeat(maxNameLength - category.name.length + 2);\r\n const countStr = category.count.toString().padStart(3, \" \");\r\n console.log(\r\n chalk.gray(` ${category.name}${padding}`),\r\n chalk.cyan(`${countStr} files`)\r\n );\r\n }\r\n\r\n console.log(chalk.gray(\" ─────────────────────────────────\"));\r\n const totalPadding = \" \".repeat(maxNameLength - 5 + 2);\r\n const totalStr = files.length.toString().padStart(3, \" \");\r\n console.log(\r\n chalk.white(` Total${totalPadding}`),\r\n chalk.bold.cyan(`${totalStr} files`)\r\n );\r\n}\r\n\r\n/**\r\n * Write generated files to disk\r\n *\r\n * Creates directories as needed and writes files\r\n * Shows categorized summary by default, or full list with verbose=true\r\n */\r\nexport async function writeGeneratedFiles(\r\n files: GeneratedFile[],\r\n outputDir: string,\r\n verbose: boolean = false\r\n): Promise<void> {\r\n // Track written files for summary\r\n const writtenFiles: GeneratedFile[] = [];\r\n\r\n // Track skipped generateOnce files for summary\r\n const skippedOnceFiles: string[] = [];\r\n\r\n for (const file of files) {\r\n // SECURITY: Validate path doesn't escape output directory\r\n if (!isPathSafe(outputDir, file.path)) {\r\n console.error(chalk.red(` Skipping unsafe path: ${file.path}`));\r\n console.error(\r\n chalk.gray(\r\n ` Path traversal detected - file path must be within output directory`\r\n )\r\n );\r\n continue;\r\n }\r\n\r\n const fullPath = path.resolve(outputDir, file.path);\r\n const dir = path.dirname(fullPath);\r\n\r\n // Check if file has generateOnce flag and already exists\r\n if (file.generateOnce) {\r\n try {\r\n await fs.access(fullPath);\r\n // File exists - skip it\r\n skippedOnceFiles.push(file.path);\r\n continue;\r\n } catch {\r\n // File doesn't exist - proceed with generation\r\n }\r\n }\r\n\r\n try {\r\n // Create directory if doesn't exist\r\n await fs.mkdir(dir, { recursive: true });\r\n\r\n // Write file\r\n await fs.writeFile(fullPath, file.content, \"utf-8\");\r\n\r\n // Show file path in verbose mode\r\n if (verbose) {\r\n console.log(chalk.gray(` ${file.path}`));\r\n }\r\n\r\n writtenFiles.push(file);\r\n } catch (error: any) {\r\n console.error(chalk.red(` Failed to write ${file.path}`));\r\n console.error(chalk.gray(` ${error.message}`));\r\n }\r\n }\r\n\r\n // Show categorized summary (unless verbose)\r\n if (!verbose && writtenFiles.length > 0) {\r\n displayCategorizedSummary(writtenFiles);\r\n }\r\n\r\n // Show skipped generateOnce files\r\n if (skippedOnceFiles.length > 0) {\r\n console.log(\"\");\r\n console.log(\r\n chalk.gray(` Skipped ${skippedOnceFiles.length} existing file(s) (generateOnce):`)\r\n );\r\n for (const filePath of skippedOnceFiles) {\r\n console.log(chalk.gray(` - ${filePath}`));\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Infer file type from path for manifest categorization\r\n */\r\nfunction inferFileType(filePath: string): ManifestFileEntry['type'] {\r\n const lowerPath = filePath.toLowerCase();\r\n\r\n if (lowerPath.includes('/entities/')) return 'entity';\r\n if (lowerPath.includes('/usecases/') || lowerPath.includes('/use-cases/')) return 'usecase';\r\n if (lowerPath.includes('/repositories/')) return 'repository';\r\n if (lowerPath.includes('/controllers/')) return 'controller';\r\n if (lowerPath.includes('/dtos/') || lowerPath.includes('/dto/')) return 'dto';\r\n if (lowerPath.includes('/tests/') || lowerPath.includes('.test.') || lowerPath.includes('.spec.')) return 'test';\r\n if (lowerPath.includes('/config') || lowerPath.includes('appsettings')) return 'config';\r\n\r\n return 'other';\r\n}\r\n\r\n/**\r\n * Write generated files to disk with manifest tracking\r\n *\r\n * This is the incremental-aware version that:\r\n * 1. Checks if files have been modified by user (via manifest)\r\n * 2. Only overwrites unmodified files\r\n * 3. Flags conflicts for user-modified files\r\n * 4. Updates manifest with new file hashes\r\n */\r\nexport async function writeGeneratedFilesWithManifest(\r\n files: GeneratedFile[],\r\n outputDir: string,\r\n templateVersion: string,\r\n options: {\r\n verbose?: boolean;\r\n forceOverwrite?: boolean;\r\n } = {}\r\n): Promise<WriteResult> {\r\n const { verbose = false, forceOverwrite = false } = options;\r\n\r\n // Load existing manifest or create new one\r\n let manifest = await readManifest(outputDir) || createEmptyManifest(templateVersion);\r\n\r\n const result: WriteResult = {\r\n created: [],\r\n updated: [],\r\n merged: [],\r\n skipped: [],\r\n conflicts: [],\r\n manifest,\r\n };\r\n\r\n for (const file of files) {\r\n // SECURITY: Validate path doesn't escape output directory\r\n if (!isPathSafe(outputDir, file.path)) {\r\n console.error(chalk.red(` Skipping unsafe path: ${file.path}`));\r\n continue;\r\n }\r\n\r\n const fullPath = path.resolve(outputDir, file.path);\r\n const dir = path.dirname(fullPath);\r\n const manifestEntry = manifest.files[file.path];\r\n\r\n // Detect if file has changed\r\n const changeStatus = await detectFileChange(fullPath, manifestEntry);\r\n\r\n let shouldWrite = false;\r\n let action: 'create' | 'update' | 'skip' | 'conflict' = 'skip';\r\n\r\n switch (changeStatus.status) {\r\n case 'new':\r\n // File doesn't exist - create it\r\n shouldWrite = true;\r\n action = 'create';\r\n break;\r\n\r\n case 'unchanged':\r\n // File exists but wasn't modified by user - safe to overwrite\r\n shouldWrite = true;\r\n action = 'update';\r\n break;\r\n\r\n case 'modified':\r\n // File was modified by user - try three-way merge\r\n if (forceOverwrite) {\r\n shouldWrite = true;\r\n action = 'update';\r\n } else {\r\n // Perform three-way merge\r\n const currentContent = await fs.readFile(fullPath, 'utf-8');\r\n\r\n // Get base content from what we last generated (stored hash matches original)\r\n // We need to regenerate base from the hash... but we only have the hash.\r\n // For now, use the generated content as base if this is an update scenario.\r\n // In a proper implementation, we'd store the original content or retrieve it.\r\n //\r\n // Since we don't have the original base content stored, we'll use a simplified approach:\r\n // - If the generated content is the same as before (hash matches), skip\r\n // - Otherwise, try merge with empty base (essentially a diff)\r\n\r\n // For Phase 2, we use the manifest hash to detect changes but can't do true 3-way merge\r\n // without storing base content. For now, generate conflict files.\r\n const mergeResult = performMerge(\r\n manifestEntry?.hash ? '' : '', // We don't have base content stored\r\n currentContent,\r\n file.content\r\n );\r\n\r\n if (mergeResult.success) {\r\n // Merge succeeded - write merged content\r\n shouldWrite = true;\r\n action = 'update';\r\n // Override file.content with merged result\r\n (file as any)._mergedContent = mergeResult.content;\r\n result.merged.push(file.path);\r\n } else {\r\n // Merge has conflicts - write .new and .conflict files\r\n action = 'conflict';\r\n\r\n // Create directory if needed\r\n await fs.mkdir(dir, { recursive: true });\r\n\r\n // Write conflict files\r\n const { newPath, conflictPath } = await writeConflictFiles(\r\n fullPath,\r\n file.content,\r\n mergeResult.conflicts,\r\n currentContent\r\n );\r\n\r\n result.conflicts.push({\r\n path: file.path,\r\n reason: 'Merge conflict - manual resolution required',\r\n newPath: path.relative(outputDir, newPath),\r\n conflictPath: path.relative(outputDir, conflictPath),\r\n });\r\n }\r\n }\r\n break;\r\n\r\n case 'deleted':\r\n // File was in manifest but deleted by user - skip it\r\n action = 'skip';\r\n result.skipped.push(file.path);\r\n break;\r\n\r\n case 'unknown':\r\n // File exists but not in manifest (user created it outside AeroCoding)\r\n action = 'skip';\r\n result.skipped.push(file.path);\r\n break;\r\n }\r\n\r\n // Handle generateOnce files\r\n if (file.generateOnce && changeStatus.status !== 'new') {\r\n shouldWrite = false;\r\n action = 'skip';\r\n if (!result.skipped.includes(file.path)) {\r\n result.skipped.push(file.path);\r\n }\r\n }\r\n\r\n if (shouldWrite) {\r\n try {\r\n // Create directory if doesn't exist\r\n await fs.mkdir(dir, { recursive: true });\r\n\r\n // Use merged content if available, otherwise original\r\n const contentToWrite = (file as any)._mergedContent || file.content;\r\n\r\n // Write file\r\n await fs.writeFile(fullPath, contentToWrite, \"utf-8\");\r\n\r\n // Get file stats for manifest\r\n const stats = await fs.stat(fullPath);\r\n\r\n // Update manifest entry\r\n const entry: ManifestFileEntry = {\r\n hash: hashString(contentToWrite),\r\n mtime: Math.floor(stats.mtimeMs),\r\n size: stats.size,\r\n entityId: file.entityId,\r\n type: file.type || inferFileType(file.path),\r\n contextName: file.contextName,\r\n };\r\n\r\n manifest = setManifestFile(manifest, file.path, entry);\r\n\r\n // Track result based on action\r\n const isMerged = result.merged.includes(file.path);\r\n if (action === 'create') {\r\n result.created.push(file.path);\r\n if (verbose) {\r\n console.log(chalk.green(` ✓ Created ${file.path}`));\r\n }\r\n } else if (isMerged) {\r\n // Already added to merged array\r\n if (verbose) {\r\n console.log(chalk.magenta(` ✓ Merged ${file.path}`));\r\n }\r\n } else {\r\n result.updated.push(file.path);\r\n if (verbose) {\r\n console.log(chalk.blue(` ✓ Updated ${file.path}`));\r\n }\r\n }\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 } else if (action === 'conflict' && verbose) {\r\n console.log(chalk.yellow(` ⚠ Conflict ${file.path}`));\r\n }\r\n }\r\n\r\n // Update manifest timestamp and save\r\n manifest = {\r\n ...manifest,\r\n lastSync: new Date().toISOString(),\r\n templateVersion,\r\n };\r\n\r\n await writeManifest(outputDir, manifest);\r\n result.manifest = manifest;\r\n\r\n // Show summary\r\n if (!verbose) {\r\n displayIncrementalSummary(result);\r\n }\r\n\r\n return result;\r\n}\r\n\r\n/**\r\n * Display summary of incremental write operation\r\n */\r\nfunction displayIncrementalSummary(result: WriteResult): void {\r\n console.log(\"\");\r\n console.log(chalk.bold(\" Update Results\"));\r\n console.log(chalk.gray(\" ─────────────────────────────────\"));\r\n\r\n if (result.created.length > 0) {\r\n console.log(chalk.green(` ✓ Created: ${result.created.length} files`));\r\n }\r\n if (result.updated.length > 0) {\r\n console.log(chalk.blue(` ✓ Updated: ${result.updated.length} files`));\r\n }\r\n if (result.merged.length > 0) {\r\n console.log(chalk.magenta(` ✓ Merged: ${result.merged.length} files`));\r\n }\r\n if (result.skipped.length > 0) {\r\n console.log(chalk.gray(` ○ Skipped: ${result.skipped.length} files`));\r\n }\r\n if (result.conflicts.length > 0) {\r\n console.log(chalk.yellow(` ⚠ Conflicts: ${result.conflicts.length} files`));\r\n }\r\n\r\n console.log(chalk.gray(\" ─────────────────────────────────\"));\r\n const total = result.created.length + result.updated.length + result.merged.length;\r\n console.log(chalk.white(` Total written: ${total} files`));\r\n\r\n // Show conflict details with file paths\r\n if (result.conflicts.length > 0) {\r\n console.log(\"\");\r\n console.log(chalk.yellow(\" ⚠ Conflicts need manual resolution:\"));\r\n console.log(\"\");\r\n\r\n for (const conflict of result.conflicts.slice(0, 5)) {\r\n console.log(chalk.yellow(` ${conflict.path}`));\r\n if (conflict.newPath) {\r\n console.log(chalk.gray(` → ${conflict.newPath}`));\r\n }\r\n if (conflict.conflictPath) {\r\n console.log(chalk.gray(` → ${conflict.conflictPath}`));\r\n }\r\n }\r\n\r\n if (result.conflicts.length > 5) {\r\n console.log(chalk.gray(` ... and ${result.conflicts.length - 5} more`));\r\n }\r\n\r\n console.log(\"\");\r\n console.log(chalk.gray(\" Run 'aerocoding resolve' after fixing conflicts.\"));\r\n }\r\n}\r\n","// ============================================\r\n// Manifest Module\r\n// Public code for tracking generated files\r\n// ============================================\r\n\r\nimport * as fs from 'fs/promises';\r\nimport * as path from 'path';\r\nimport type { AeroManifest, ManifestFileEntry } from './types.js';\r\nimport { MANIFEST_VERSION, MANIFEST_FILENAME } from './types.js';\r\n\r\n// Re-export types\r\nexport type { AeroManifest, ManifestFileEntry, FileChangeStatus } from './types.js';\r\nexport { MANIFEST_VERSION, MANIFEST_FILENAME } from './types.js';\r\n\r\n// Re-export hash utilities\r\nexport { hashString, hashFile, detectFileChange } from './hash-utils.js';\r\n\r\n/**\r\n * Read manifest from a directory\r\n */\r\nexport async function readManifest(projectDir: string): Promise<AeroManifest | null> {\r\n const manifestPath = path.join(projectDir, MANIFEST_FILENAME);\r\n\r\n try {\r\n const content = await fs.readFile(manifestPath, 'utf-8');\r\n return JSON.parse(content) as AeroManifest;\r\n } catch (error: any) {\r\n if (error.code === 'ENOENT') {\r\n return null;\r\n }\r\n throw error;\r\n }\r\n}\r\n\r\n/**\r\n * Write manifest to a directory\r\n */\r\nexport async function writeManifest(projectDir: string, manifest: AeroManifest): Promise<void> {\r\n const manifestPath = path.join(projectDir, MANIFEST_FILENAME);\r\n await fs.writeFile(manifestPath, JSON.stringify(manifest, null, 2) + '\\n', 'utf-8');\r\n}\r\n\r\n/**\r\n * Create a new empty manifest\r\n */\r\nexport function createEmptyManifest(templateVersion: string): AeroManifest {\r\n return {\r\n version: MANIFEST_VERSION,\r\n lastSync: new Date().toISOString(),\r\n templateVersion,\r\n files: {},\r\n entities: [],\r\n };\r\n}\r\n\r\n/**\r\n * Add or update a file entry in the manifest\r\n */\r\nexport function setManifestFile(\r\n manifest: AeroManifest,\r\n filePath: string,\r\n entry: ManifestFileEntry\r\n): AeroManifest {\r\n return {\r\n ...manifest,\r\n files: {\r\n ...manifest.files,\r\n [filePath]: entry,\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * Check if manifest exists in a directory\r\n */\r\nexport async function hasManifest(projectDir: string): Promise<boolean> {\r\n const manifest = await readManifest(projectDir);\r\n return manifest !== null;\r\n}\r\n","// ============================================\r\n// Manifest Types for Incremental Generation\r\n// Public code - safe to distribute with CLI\r\n// ============================================\r\n\r\n/**\r\n * aerocoding-manifest.json entry for a single file\r\n */\r\nexport interface ManifestFileEntry {\r\n /** SHA-256 hash of file content */\r\n hash: string;\r\n /** File modification time in milliseconds */\r\n mtime: number;\r\n /** File size in bytes */\r\n size: number;\r\n /** Related entity ID (if applicable) */\r\n entityId?: string;\r\n /** File type for categorization */\r\n type?: 'entity' | 'usecase' | 'repository' | 'controller' | 'dto' | 'config' | 'test' | 'other';\r\n /** Bounded context name */\r\n contextName?: string;\r\n}\r\n\r\n/**\r\n * aerocoding-manifest.json structure\r\n * Tracks all generated files and their hashes\r\n */\r\nexport interface AeroManifest {\r\n /** Manifest format version */\r\n version: string;\r\n /** Last sync timestamp */\r\n lastSync: string;\r\n /** Template version at last generation */\r\n templateVersion: string;\r\n /** Map of file paths to their metadata */\r\n files: Record<string, ManifestFileEntry>;\r\n /** Entities that were generated */\r\n entities?: Array<{\r\n id: string;\r\n name: string;\r\n hash: string;\r\n contextName?: string;\r\n }>;\r\n}\r\n\r\n/**\r\n * Result of comparing a file with its manifest entry\r\n */\r\nexport type FileChangeStatus =\r\n | { status: 'new' }\r\n | { status: 'unchanged' }\r\n | { status: 'modified'; currentHash: string }\r\n | { status: 'deleted' }\r\n | { status: 'unknown' };\r\n\r\n// Constants\r\nexport const MANIFEST_VERSION = '1.0.0';\r\nexport const MANIFEST_FILENAME = 'aerocoding-manifest.json';\r\n","// ============================================\r\n// Hash Utilities for Incremental Generation\r\n// Public code - safe to distribute with CLI\r\n// ============================================\r\n\r\nimport * as crypto from 'crypto';\r\nimport * as fs from 'fs/promises';\r\nimport { createReadStream } from 'fs';\r\nimport type { ManifestFileEntry, FileChangeStatus } from './types.js';\r\n\r\n/**\r\n * Compute SHA-256 hash of a string\r\n */\r\nexport function hashString(content: string): string {\r\n return crypto.createHash('sha256').update(content, 'utf-8').digest('hex');\r\n}\r\n\r\n/**\r\n * Compute SHA-256 hash of a file using streaming (memory efficient)\r\n */\r\nexport async function hashFile(filePath: string): Promise<string> {\r\n return new Promise((resolve, reject) => {\r\n const hash = crypto.createHash('sha256');\r\n const stream = createReadStream(filePath);\r\n\r\n stream.on('data', (chunk) => hash.update(chunk));\r\n stream.on('end', () => resolve(hash.digest('hex')));\r\n stream.on('error', reject);\r\n });\r\n}\r\n\r\n/**\r\n * Get file stats (mtime and size) for quick comparison\r\n */\r\nexport async function getFileStats(filePath: string): Promise<{ mtime: number; size: number } | null> {\r\n try {\r\n const stats = await fs.stat(filePath);\r\n return {\r\n mtime: Math.floor(stats.mtimeMs),\r\n size: stats.size,\r\n };\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Quick check if file might have changed based on mtime and size\r\n * Returns true if file MIGHT have changed (need hash verification)\r\n */\r\nexport function mightHaveChanged(\r\n currentStats: { mtime: number; size: number },\r\n manifestEntry: ManifestFileEntry\r\n): boolean {\r\n return currentStats.mtime !== manifestEntry.mtime || currentStats.size !== manifestEntry.size;\r\n}\r\n\r\n/**\r\n * Detect if a file has been modified by the user\r\n * Uses optimized two-phase check: mtime/size first, then hash if needed\r\n */\r\nexport async function detectFileChange(\r\n filePath: string,\r\n manifestEntry: ManifestFileEntry | undefined\r\n): Promise<FileChangeStatus> {\r\n const stats = await getFileStats(filePath);\r\n\r\n if (!stats) {\r\n if (manifestEntry) {\r\n return { status: 'deleted' };\r\n }\r\n return { status: 'new' };\r\n }\r\n\r\n if (!manifestEntry) {\r\n return { status: 'unknown' };\r\n }\r\n\r\n // Quick check with mtime/size\r\n if (!mightHaveChanged(stats, manifestEntry)) {\r\n return { status: 'unchanged' };\r\n }\r\n\r\n // Verify with hash\r\n const currentHash = await hashFile(filePath);\r\n\r\n if (currentHash === manifestEntry.hash) {\r\n return { status: 'unchanged' };\r\n }\r\n\r\n return { status: 'modified', currentHash };\r\n}\r\n","// ============================================\r\n// Three-Way Merge Implementation\r\n// ============================================\r\n\r\nimport diff3Merge from \"diff3\";\r\n\r\n/**\r\n * Result of a three-way merge operation\r\n */\r\nexport interface MergeResult {\r\n /** Whether the merge completed without conflicts */\r\n success: boolean;\r\n /** The merged content (may contain conflict markers if success=false) */\r\n content: string;\r\n /** Conflict regions if merge had conflicts */\r\n conflicts: ConflictRegion[];\r\n}\r\n\r\n/**\r\n * A region of conflict between user's changes and generated changes\r\n */\r\nexport interface ConflictRegion {\r\n /** Starting line number in the merged output */\r\n startLine: number;\r\n /** Ending line number in the merged output */\r\n endLine: number;\r\n /** User's version of the conflicting section */\r\n yours: string;\r\n /** Generated version of the conflicting section */\r\n generated: string;\r\n}\r\n\r\n/**\r\n * Perform a three-way merge between base, current (user's), and generated content.\r\n *\r\n * @param base - The original content (what was last generated/synced)\r\n * @param current - The current content on disk (may have user modifications)\r\n * @param generated - The newly generated content from the API\r\n * @returns MergeResult with success status, merged content, and any conflicts\r\n *\r\n * @example\r\n * ```typescript\r\n * const result = performMerge(\r\n * \"class Customer { }\", // base\r\n * \"class Customer { IsVip() }\", // current (user added method)\r\n * \"class Customer { Phone; }\" // generated (API added property)\r\n * );\r\n *\r\n * if (result.success) {\r\n * // Merged: class Customer { IsVip(); Phone; }\r\n * await writeFile(path, result.content);\r\n * } else {\r\n * // Has conflicts, need manual resolution\r\n * await writeConflictFiles(path, current, generated, result.conflicts);\r\n * }\r\n * ```\r\n */\r\nexport function performMerge(\r\n base: string,\r\n current: string,\r\n generated: string\r\n): MergeResult {\r\n // Split content into lines for diff3\r\n const baseLines = base.split(\"\\n\");\r\n const currentLines = current.split(\"\\n\");\r\n const generatedLines = generated.split(\"\\n\");\r\n\r\n // Perform three-way merge\r\n // diff3 returns array of regions: either string[] (clean) or { ok: string[] } or { conflict: { a, o, b } }\r\n const merged = diff3Merge(currentLines, baseLines, generatedLines);\r\n\r\n const conflicts: ConflictRegion[] = [];\r\n const outputLines: string[] = [];\r\n let lineNumber = 1;\r\n\r\n for (const region of merged) {\r\n if (Array.isArray(region)) {\r\n // Clean region - lines that merged without conflict\r\n outputLines.push(...region);\r\n lineNumber += region.length;\r\n } else if (\"ok\" in region && region.ok) {\r\n // OK region - also clean\r\n const okLines = region.ok;\r\n outputLines.push(...okLines);\r\n lineNumber += okLines.length;\r\n } else if (\"conflict\" in region && region.conflict) {\r\n // Conflict region\r\n const conflictData = region.conflict;\r\n const yoursLines = conflictData.a || [];\r\n const generatedLines = conflictData.b || [];\r\n const yours = yoursLines.join(\"\\n\");\r\n const generatedStr = generatedLines.join(\"\\n\");\r\n\r\n // Add conflict markers to output\r\n const conflictLines = [\r\n \"<<<<<<< YOURS\",\r\n ...yoursLines,\r\n \"=======\",\r\n ...generatedLines,\r\n \">>>>>>> GENERATED\",\r\n ];\r\n\r\n const startLine = lineNumber;\r\n outputLines.push(...conflictLines);\r\n lineNumber += conflictLines.length;\r\n\r\n conflicts.push({\r\n startLine,\r\n endLine: lineNumber - 1,\r\n yours,\r\n generated: generatedStr,\r\n });\r\n }\r\n }\r\n\r\n return {\r\n success: conflicts.length === 0,\r\n content: outputLines.join(\"\\n\"),\r\n conflicts,\r\n };\r\n}\r\n\r\n/**\r\n * Check if content has any conflict markers\r\n */\r\nexport function hasConflictMarkers(content: string): boolean {\r\n return (\r\n content.includes(\"<<<<<<< YOURS\") ||\r\n content.includes(\"=======\") ||\r\n content.includes(\">>>>>>> GENERATED\")\r\n );\r\n}\r\n\r\n/**\r\n * Extract clean content by removing conflict markers (for preview purposes)\r\n * Takes the \"YOURS\" side of each conflict\r\n */\r\nexport function extractYoursSide(content: string): string {\r\n const lines = content.split(\"\\n\");\r\n const output: string[] = [];\r\n let inConflict = false;\r\n let inGenerated = false;\r\n\r\n for (const line of lines) {\r\n if (line === \"<<<<<<< YOURS\") {\r\n inConflict = true;\r\n inGenerated = false;\r\n continue;\r\n }\r\n if (line === \"=======\") {\r\n inGenerated = true;\r\n continue;\r\n }\r\n if (line === \">>>>>>> GENERATED\") {\r\n inConflict = false;\r\n inGenerated = false;\r\n continue;\r\n }\r\n\r\n if (!inConflict || !inGenerated) {\r\n output.push(line);\r\n }\r\n }\r\n\r\n return output.join(\"\\n\");\r\n}\r\n\r\n/**\r\n * Extract clean content by removing conflict markers\r\n * Takes the \"GENERATED\" side of each conflict\r\n */\r\nexport function extractGeneratedSide(content: string): string {\r\n const lines = content.split(\"\\n\");\r\n const output: string[] = [];\r\n let inConflict = false;\r\n let inYours = false;\r\n\r\n for (const line of lines) {\r\n if (line === \"<<<<<<< YOURS\") {\r\n inConflict = true;\r\n inYours = true;\r\n continue;\r\n }\r\n if (line === \"=======\") {\r\n inYours = false;\r\n continue;\r\n }\r\n if (line === \">>>>>>> GENERATED\") {\r\n inConflict = false;\r\n continue;\r\n }\r\n\r\n if (!inConflict || !inYours) {\r\n output.push(line);\r\n }\r\n }\r\n\r\n return output.join(\"\\n\");\r\n}\r\n","// ============================================\r\n// Conflict File Writer\r\n// ============================================\r\n\r\nimport { writeFile, unlink, access } from \"node:fs/promises\";\r\nimport { basename, extname } from \"node:path\";\r\nimport type { ConflictRegion } from \"./merger.js\";\r\n\r\n/**\r\n * Extensions for conflict files\r\n */\r\nexport const CONFLICT_NEW_EXT = \".new\";\r\nexport const CONFLICT_DIFF_EXT = \".conflict\";\r\n\r\n/**\r\n * Write conflict files when merge fails\r\n *\r\n * Creates two files:\r\n * - `file.ext.new` - The newly generated version (complete)\r\n * - `file.ext.conflict` - A diff showing the conflicts with context\r\n *\r\n * The original file is left untouched.\r\n *\r\n * @param filePath - Path to the original file\r\n * @param generatedContent - The newly generated content\r\n * @param conflicts - The conflict regions from merge\r\n * @param currentContent - The current user content (for context in .conflict)\r\n */\r\nexport async function writeConflictFiles(\r\n filePath: string,\r\n generatedContent: string,\r\n conflicts: ConflictRegion[],\r\n currentContent: string\r\n): Promise<{ newPath: string; conflictPath: string }> {\r\n const newPath = `${filePath}${CONFLICT_NEW_EXT}`;\r\n const conflictPath = `${filePath}${CONFLICT_DIFF_EXT}`;\r\n\r\n // Write .new file with complete generated content\r\n await writeFile(newPath, generatedContent, \"utf-8\");\r\n\r\n // Write .conflict file with diff format\r\n const conflictContent = generateConflictFile(\r\n filePath,\r\n currentContent,\r\n generatedContent,\r\n conflicts\r\n );\r\n await writeFile(conflictPath, conflictContent, \"utf-8\");\r\n\r\n return { newPath, conflictPath };\r\n}\r\n\r\n/**\r\n * Generate the content of a .conflict file\r\n */\r\nfunction generateConflictFile(\r\n filePath: string,\r\n _currentContent: string,\r\n _generatedContent: string,\r\n conflicts: ConflictRegion[]\r\n): string {\r\n const fileName = basename(filePath);\r\n const ext = extname(filePath);\r\n const commentStyle = getCommentStyle(ext);\r\n\r\n const header = `${commentStyle.start}\r\n${commentStyle.prefix} ${fileName} - MERGE CONFLICT\r\n${commentStyle.prefix}\r\n${commentStyle.prefix} This file has ${conflicts.length} conflict(s) that need manual resolution.\r\n${commentStyle.prefix}\r\n${commentStyle.prefix} Resolution options:\r\n${commentStyle.prefix} 1. Edit ${fileName} to include both your changes and the generated changes\r\n${commentStyle.prefix} 2. Copy desired parts from ${fileName}${CONFLICT_NEW_EXT}\r\n${commentStyle.prefix} 3. Run 'aerocoding resolve' when done\r\n${commentStyle.prefix}\r\n${commentStyle.prefix} Your file: ${fileName} (unchanged)\r\n${commentStyle.prefix} Generated: ${fileName}${CONFLICT_NEW_EXT} (new version)\r\n${commentStyle.end}\r\n\r\n`;\r\n\r\n const conflictSections = conflicts\r\n .map((conflict, index) => {\r\n return `${commentStyle.start}\r\n${commentStyle.prefix} CONFLICT ${index + 1} of ${conflicts.length} (lines ${conflict.startLine}-${conflict.endLine})\r\n${commentStyle.end}\r\n\r\n<<<<<<< YOURS (keep your changes)\r\n${conflict.yours}\r\n=======\r\n${conflict.generated}\r\n>>>>>>> GENERATED (from template)\r\n`;\r\n })\r\n .join(\"\\n\");\r\n\r\n return header + conflictSections;\r\n}\r\n\r\n/**\r\n * Get comment style based on file extension\r\n */\r\nfunction getCommentStyle(ext: string): {\r\n start: string;\r\n prefix: string;\r\n end: string;\r\n} {\r\n switch (ext.toLowerCase()) {\r\n case \".cs\":\r\n case \".ts\":\r\n case \".tsx\":\r\n case \".js\":\r\n case \".jsx\":\r\n case \".java\":\r\n case \".kt\":\r\n case \".dart\":\r\n case \".go\":\r\n case \".swift\":\r\n case \".rs\":\r\n case \".c\":\r\n case \".cpp\":\r\n case \".h\":\r\n return { start: \"/*\", prefix: \" *\", end: \" */\" };\r\n\r\n case \".py\":\r\n case \".rb\":\r\n case \".sh\":\r\n case \".yaml\":\r\n case \".yml\":\r\n return { start: \"#\", prefix: \"#\", end: \"#\" };\r\n\r\n case \".html\":\r\n case \".xml\":\r\n case \".xaml\":\r\n case \".svg\":\r\n return { start: \"<!--\", prefix: \" \", end: \"-->\" };\r\n\r\n case \".sql\":\r\n return { start: \"--\", prefix: \"--\", end: \"--\" };\r\n\r\n case \".css\":\r\n case \".scss\":\r\n case \".less\":\r\n return { start: \"/*\", prefix: \" *\", end: \" */\" };\r\n\r\n default:\r\n return { start: \"//\", prefix: \"//\", end: \"//\" };\r\n }\r\n}\r\n\r\n/**\r\n * Check if a file has pending conflict files\r\n */\r\nexport async function hasConflictFiles(filePath: string): Promise<boolean> {\r\n const newPath = `${filePath}${CONFLICT_NEW_EXT}`;\r\n const conflictPath = `${filePath}${CONFLICT_DIFF_EXT}`;\r\n\r\n try {\r\n await access(newPath);\r\n return true;\r\n } catch {\r\n // .new doesn't exist\r\n }\r\n\r\n try {\r\n await access(conflictPath);\r\n return true;\r\n } catch {\r\n // .conflict doesn't exist\r\n }\r\n\r\n return false;\r\n}\r\n\r\n/**\r\n * Remove conflict files after resolution\r\n */\r\nexport async function removeConflictFiles(\r\n filePath: string\r\n): Promise<{ removedNew: boolean; removedConflict: boolean }> {\r\n const newPath = `${filePath}${CONFLICT_NEW_EXT}`;\r\n const conflictPath = `${filePath}${CONFLICT_DIFF_EXT}`;\r\n\r\n let removedNew = false;\r\n let removedConflict = false;\r\n\r\n try {\r\n await unlink(newPath);\r\n removedNew = true;\r\n } catch {\r\n // File didn't exist, that's fine\r\n }\r\n\r\n try {\r\n await unlink(conflictPath);\r\n removedConflict = true;\r\n } catch {\r\n // File didn't exist, that's fine\r\n }\r\n\r\n return { removedNew, removedConflict };\r\n}\r\n\r\n/**\r\n * Find all conflict files in a directory\r\n */\r\nexport function getConflictFilePaths(originalPath: string): {\r\n newPath: string;\r\n conflictPath: string;\r\n} {\r\n return {\r\n newPath: `${originalPath}${CONFLICT_NEW_EXT}`,\r\n conflictPath: `${originalPath}${CONFLICT_DIFF_EXT}`,\r\n };\r\n}\r\n","import readline from \"readline\";\r\nimport chalk from \"chalk\";\r\n\r\n/**\r\n * Prompt user for confirmation\r\n * Returns true if user confirms (Y/yes/enter), false if they decline (n/no)\r\n */\r\nexport function promptConfirm(message: string): Promise<boolean> {\r\n return new Promise((resolve) => {\r\n const rl = readline.createInterface({\r\n input: process.stdin,\r\n output: process.stdout,\r\n });\r\n\r\n rl.question(chalk.yellow(`${message} [Y/n] `), (answer) => {\r\n rl.close();\r\n const normalized = answer.trim().toLowerCase();\r\n // Empty input (just pressing Enter) means \"yes\"\r\n resolve(normalized !== \"n\" && normalized !== \"no\");\r\n });\r\n });\r\n}\r\n","import fs from \"fs/promises\";\r\nimport path from \"path\";\r\nimport { configSchema, CONFIG_FILENAME, type AerocodingConfig } from \"./schema.js\";\r\n\r\nexport async function loadConfig(\r\n dir: string = process.cwd()\r\n): Promise<AerocodingConfig | null> {\r\n const configPath = path.join(dir, CONFIG_FILENAME);\r\n\r\n try {\r\n const content = await fs.readFile(configPath, \"utf-8\");\r\n const parsed = JSON.parse(content);\r\n return configSchema.parse(parsed);\r\n } catch (error) {\r\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") {\r\n return null;\r\n }\r\n throw error;\r\n }\r\n}\r\n\r\nexport async function saveConfig(\r\n config: AerocodingConfig,\r\n dir: string = process.cwd()\r\n): Promise<void> {\r\n const configPath = path.join(dir, CONFIG_FILENAME);\r\n const content = JSON.stringify(\r\n {\r\n $schema: \"https://aerocoding.dev/schemas/aerocodingrc.json\",\r\n ...config,\r\n },\r\n null,\r\n 2\r\n );\r\n await fs.writeFile(configPath, content, \"utf-8\");\r\n}\r\n\r\nexport async function configExists(dir: string = process.cwd()): Promise<boolean> {\r\n const configPath = path.join(dir, CONFIG_FILENAME);\r\n try {\r\n await fs.access(configPath);\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\nexport { type AerocodingConfig, CONFIG_FILENAME } from \"./schema.js\";\r\n","import { z } from \"zod\";\r\n\r\nexport const configSchema = z.object({\r\n $schema: z.string().optional(),\r\n project: z.string().uuid(),\r\n output: z.string().default(\"./.aerocoding\"),\r\n\r\n // Architecture style: how to organize generated code\r\n architectureStyle: z\r\n .enum([\"bounded-contexts\", \"flat\"])\r\n .optional()\r\n .default(\"bounded-contexts\"),\r\n\r\n backend: z\r\n .object({\r\n preset: z.string(),\r\n })\r\n .optional(),\r\n\r\n frontend: z\r\n .object({\r\n preset: z.string(),\r\n })\r\n .optional(),\r\n\r\n codeStyle: z\r\n .object({\r\n includeValidations: z.boolean().default(true),\r\n includeComments: z.boolean().default(true),\r\n includeLogging: z.boolean().default(true),\r\n includeTesting: z.boolean().default(true),\r\n })\r\n .optional(),\r\n\r\n libraries: z\r\n .object({\r\n validation: z.string().optional(),\r\n logging: z.string().optional(),\r\n })\r\n .optional(),\r\n\r\n excludePatterns: z.array(z.string()).optional(),\r\n});\r\n\r\nexport type AerocodingConfig = z.infer<typeof configSchema>;\r\n\r\nexport const CONFIG_FILENAME = \".aerocodingrc.json\";\r\n","import * as p from \"@clack/prompts\";\r\nimport chalk from \"chalk\";\r\nimport { TokenManager } from \"../auth/token-manager.js\";\r\nimport { createApiClientWithAutoLogout } from \"./_shared/create-api-client.js\";\r\nimport { handleUnauthorized } from \"./_shared/unauthorized.js\";\r\nimport { saveConfig, configExists } from \"../config/loader.js\";\r\nimport type { AerocodingConfig } from \"../config/schema.js\";\r\n\r\ninterface InitOptions {\r\n project?: string;\r\n force?: boolean;\r\n}\r\n\r\n/**\r\n * Init Command\r\n *\r\n * Interactive wizard to initialize AeroCoding in current directory\r\n * Creates .aerocodingrc.json config file\r\n */\r\nexport async function initCommand(options: InitOptions) {\r\n p.intro(chalk.bgCyan.black(\" AeroCoding CLI \"));\r\n\r\n // Check if config already exists\r\n if (!options.force && (await configExists())) {\r\n const overwrite = await p.confirm({\r\n message: \"Config file already exists. Overwrite?\",\r\n initialValue: false,\r\n });\r\n\r\n if (p.isCancel(overwrite) || !overwrite) {\r\n p.cancel(\"Operation cancelled.\");\r\n process.exit(0);\r\n }\r\n }\r\n\r\n // 1. Check authentication\r\n const tokenManager = new TokenManager();\r\n const token = await tokenManager.getAccessToken();\r\n\r\n if (!token) {\r\n p.cancel(\"Not logged in. Run 'aerocoding login' first.\");\r\n process.exit(1);\r\n }\r\n\r\n const apiClient = createApiClientWithAutoLogout(token, tokenManager);\r\n\r\n try {\r\n // 2. Select organization first\r\n const orgSpinner = p.spinner();\r\n orgSpinner.start(\"Loading organizations...\");\r\n\r\n const organizations = await apiClient.listOrganizations();\r\n orgSpinner.stop(\"Organizations loaded\");\r\n\r\n if (organizations.length === 0) {\r\n p.cancel(\"No organizations found. Create one on aerocoding.dev first.\");\r\n process.exit(1);\r\n }\r\n\r\n let organizationId: string;\r\n\r\n if (organizations.length === 1 && organizations[0]) {\r\n // Auto-select if only one org\r\n organizationId = organizations[0].id;\r\n p.log.info(`Organization: ${organizations[0].name}`);\r\n } else {\r\n const selectedOrg = await p.select({\r\n message: \"Select organization\",\r\n options: organizations.map((org) => ({\r\n value: org.id,\r\n label: org.name,\r\n hint: org.planTier.toUpperCase(),\r\n })),\r\n });\r\n\r\n if (p.isCancel(selectedOrg)) {\r\n p.cancel(\"Operation cancelled.\");\r\n process.exit(0);\r\n }\r\n\r\n organizationId = selectedOrg as string;\r\n }\r\n\r\n // 3. Select project from organization\r\n let projectId = options.project;\r\n\r\n if (!projectId) {\r\n const spinner = p.spinner();\r\n spinner.start(\"Loading projects...\");\r\n\r\n const projects = await apiClient.listProjects(organizationId);\r\n spinner.stop(\"Projects loaded\");\r\n\r\n if (projects.length === 0) {\r\n p.cancel(\"No projects in this organization. Create one on aerocoding.dev first.\");\r\n process.exit(1);\r\n }\r\n\r\n const selectedProject = await p.select({\r\n message: \"Select project\",\r\n options: projects.map((proj) => ({\r\n value: proj.id,\r\n label: proj.name,\r\n hint: [proj.backendFramework, proj.frontendFramework].filter(Boolean).join(\" + \"),\r\n })),\r\n });\r\n\r\n if (p.isCancel(selectedProject)) {\r\n p.cancel(\"Operation cancelled.\");\r\n process.exit(0);\r\n }\r\n\r\n projectId = selectedProject as string;\r\n }\r\n\r\n // 4. Fetch project details\r\n const spinner = p.spinner();\r\n spinner.start(\"Fetching project details...\");\r\n const project = await apiClient.getProject(projectId);\r\n spinner.stop(`Project: ${project.name}`);\r\n\r\n // Detect frameworks from project settings (no longer asking user)\r\n const hasBackend = !!project.backendFramework;\r\n const hasFrontend = !!project.frontendFramework;\r\n\r\n if (!hasBackend && !hasFrontend) {\r\n p.cancel(\"Project has no frameworks configured. Update it on aerocoding.dev first.\");\r\n process.exit(1);\r\n }\r\n\r\n // Show detected frameworks\r\n if (hasBackend) {\r\n p.log.success(`Backend: ${project.backendFramework?.toUpperCase()} detected`);\r\n }\r\n if (hasFrontend) {\r\n p.log.success(`Frontend: ${project.frontendFramework?.toUpperCase()} detected`);\r\n }\r\n\r\n // Initialize config (architectureStyle will be set later based on template or user choice)\r\n const config: AerocodingConfig = {\r\n project: projectId,\r\n output: \"./.aerocoding\",\r\n architectureStyle: \"flat\", // Default, will be updated based on template or user choice\r\n codeStyle: {\r\n includeValidations: true,\r\n includeComments: true,\r\n includeLogging: true,\r\n includeTesting: true,\r\n },\r\n };\r\n\r\n // Track selected templates to determine architecture style later\r\n let selectedBackendTemplate: { architectureStyle?: \"bounded-contexts\" | \"flat\" } | null = null;\r\n let selectedFrontendTemplate: { architectureStyle?: \"bounded-contexts\" | \"flat\" } | null = null;\r\n\r\n // 5. Backend configuration (if project has backend framework)\r\n if (hasBackend && project.backendFramework) {\r\n const archSpinner = p.spinner();\r\n archSpinner.start(\"Loading backend templates...\");\r\n\r\n // Use new template registry API\r\n const templateResult = await apiClient.getTemplates({\r\n category: \"backend\",\r\n language: project.backendFramework,\r\n });\r\n archSpinner.stop(\"Templates loaded\");\r\n\r\n if (templateResult.templates.length > 0) {\r\n const preset = await p.select({\r\n message: \"Backend template\",\r\n options: templateResult.templates.map((tmpl) => ({\r\n value: tmpl.id,\r\n label: tmpl.name,\r\n hint: tmpl.description || `${tmpl.tier} tier`,\r\n })),\r\n });\r\n\r\n if (p.isCancel(preset)) {\r\n p.cancel(\"Operation cancelled.\");\r\n process.exit(0);\r\n }\r\n\r\n // Fetch full template to get architectureStyle recommendation\r\n const fullTemplate = await apiClient.getTemplate(preset as string);\r\n selectedBackendTemplate = fullTemplate;\r\n\r\n config.backend = {\r\n preset: preset as string,\r\n };\r\n }\r\n }\r\n\r\n // 6. Frontend configuration (if project has frontend framework)\r\n if (hasFrontend && project.frontendFramework) {\r\n const archSpinner = p.spinner();\r\n archSpinner.start(\"Loading frontend templates...\");\r\n\r\n // Use new template registry API\r\n const templateResult = await apiClient.getTemplates({\r\n category: \"frontend\",\r\n framework: project.frontendFramework,\r\n });\r\n archSpinner.stop(\"Templates loaded\");\r\n\r\n if (templateResult.templates.length > 0) {\r\n const preset = await p.select({\r\n message: \"Frontend template\",\r\n options: templateResult.templates.map((tmpl) => ({\r\n value: tmpl.id,\r\n label: tmpl.name,\r\n hint: tmpl.description || `${tmpl.tier} tier`,\r\n })),\r\n });\r\n\r\n if (p.isCancel(preset)) {\r\n p.cancel(\"Operation cancelled.\");\r\n process.exit(0);\r\n }\r\n\r\n // Fetch full template to get architectureStyle recommendation\r\n const fullTemplate = await apiClient.getTemplate(preset as string);\r\n selectedFrontendTemplate = fullTemplate;\r\n\r\n config.frontend = {\r\n preset: preset as string,\r\n };\r\n }\r\n }\r\n\r\n // 7. Architecture style\r\n // Always ask user, but use template recommendation as default\r\n const templateArchStyle =\r\n selectedBackendTemplate?.architectureStyle ||\r\n selectedFrontendTemplate?.architectureStyle;\r\n\r\n const recommendedStyle = templateArchStyle || \"flat\";\r\n\r\n const architectureStyle = await p.select({\r\n message: \"How would you like to organize your code?\",\r\n options: [\r\n {\r\n value: \"bounded-contexts\",\r\n label:\r\n recommendedStyle === \"bounded-contexts\"\r\n ? \"Bounded Contexts (Recommended)\"\r\n : \"Bounded Contexts\",\r\n hint: \"Each module has its own Domain, Application, Infrastructure\",\r\n },\r\n {\r\n value: \"flat\",\r\n label:\r\n recommendedStyle === \"flat\"\r\n ? \"Flat Structure (Recommended)\"\r\n : \"Flat Structure\",\r\n hint: \"Single Domain, Application, Infrastructure for the entire project\",\r\n },\r\n ],\r\n initialValue: recommendedStyle,\r\n });\r\n\r\n if (p.isCancel(architectureStyle)) {\r\n p.cancel(\"Operation cancelled.\");\r\n process.exit(0);\r\n }\r\n\r\n config.architectureStyle = architectureStyle as \"bounded-contexts\" | \"flat\";\r\n\r\n // 8. Code style options\r\n const codeStyleOptions = await p.multiselect({\r\n message: \"Code style options\",\r\n options: [\r\n { value: \"validations\", label: \"Include validations (Recommended)\", hint: \"Add validation rules\" },\r\n { value: \"comments\", label: \"Include comments (Recommended)\", hint: \"Add code documentation\" },\r\n { value: \"logging\", label: \"Include logging (Recommended)\", hint: \"Add log statements\" },\r\n { value: \"testing\", label: \"Include tests (Recommended)\", hint: \"Generate test files\" },\r\n ],\r\n initialValues: [\"validations\", \"comments\", \"logging\", \"testing\"],\r\n });\r\n\r\n if (p.isCancel(codeStyleOptions)) {\r\n p.cancel(\"Operation cancelled.\");\r\n process.exit(0);\r\n }\r\n\r\n const selectedStyles = codeStyleOptions as string[];\r\n config.codeStyle = {\r\n includeValidations: selectedStyles.includes(\"validations\"),\r\n includeComments: selectedStyles.includes(\"comments\"),\r\n includeLogging: selectedStyles.includes(\"logging\"),\r\n includeTesting: selectedStyles.includes(\"testing\"),\r\n };\r\n\r\n // 9. Use default output directory (user can edit .aerocodingrc.json if needed)\r\n config.output = \"./.aerocoding\";\r\n\r\n // 10. Configuration Summary\r\n p.log.step(chalk.bold(\"Configuration Summary:\"));\r\n if (config.backend) {\r\n p.log.info(` Backend: ${config.backend.preset}`);\r\n }\r\n if (config.frontend) {\r\n p.log.info(` Frontend: ${config.frontend.preset}`);\r\n }\r\n p.log.info(\r\n ` Architecture: ${\r\n config.architectureStyle === \"bounded-contexts\"\r\n ? \"Bounded Contexts\"\r\n : \"Flat Structure\"\r\n }`\r\n );\r\n p.log.info(` Output: ${config.output}`);\r\n\r\n // 11. Save config\r\n await saveConfig(config);\r\n\r\n p.outro(\r\n chalk.green(\"Config saved to .aerocodingrc.json\") +\r\n \"\\n\\n\" +\r\n chalk.gray(\" Run \") +\r\n chalk.cyan(\"aerocoding generate\") +\r\n chalk.gray(\" to generate code!\")\r\n );\r\n } catch (error: any) {\r\n if (error.response?.status === 401) {\r\n await handleUnauthorized(tokenManager);\r\n } else if (error.response?.data?.message) {\r\n p.cancel(error.response.data.message);\r\n } else {\r\n p.cancel(error.message || \"An unexpected error occurred\");\r\n }\r\n process.exit(1);\r\n }\r\n}\r\n","import * as p from \"@clack/prompts\";\r\nimport chalk from \"chalk\";\r\nimport ora from \"ora\";\r\nimport { mkdir, access } from \"node:fs/promises\";\r\nimport { resolve } from \"node:path\";\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 {\r\n createProjectConfig,\r\n saveProjectConfig,\r\n PROJECT_CONFIG_FILENAME,\r\n} from \"../config/project-config.js\";\r\nimport {\r\n createEmptyManifest,\r\n writeManifest,\r\n setManifestFile,\r\n hashString,\r\n MANIFEST_FILENAME,\r\n type AeroManifest,\r\n} from \"../manifest/index.js\";\r\nimport { syncToCloud } from \"../utils/cloud-sync.js\";\r\n\r\ninterface CreateOptions {\r\n template?: string;\r\n project?: string;\r\n force?: boolean;\r\n}\r\n\r\n/**\r\n * Create Command\r\n *\r\n * Creates a new AeroCoding project with full architecture generation.\r\n * Combines init + generate into a single command for the meta-framework approach.\r\n *\r\n * Flow:\r\n * 1. Create project directory\r\n * 2. Interactive setup (select org, project, template)\r\n * 3. Generate full architecture\r\n * 4. Create aerocoding.json + aerocoding-manifest.json\r\n */\r\nexport async function createCommand(projectName: string, options: CreateOptions) {\r\n p.intro(chalk.bgCyan.black(\" AeroCoding Create \"));\r\n\r\n // Validate project name\r\n if (!projectName || projectName.trim() === \"\") {\r\n p.cancel(\"Project name is required\");\r\n process.exit(1);\r\n }\r\n\r\n // Sanitize project name for directory\r\n const safeName = projectName\r\n .toLowerCase()\r\n .replace(/[^a-z0-9-]/g, \"-\")\r\n .replace(/-+/g, \"-\")\r\n .replace(/^-|-$/g, \"\");\r\n\r\n if (!safeName) {\r\n p.cancel(\"Invalid project name. Use alphanumeric characters and hyphens.\");\r\n process.exit(1);\r\n }\r\n\r\n const projectDir = resolve(process.cwd(), safeName);\r\n\r\n // Check if directory already exists\r\n try {\r\n await access(projectDir);\r\n if (!options.force) {\r\n const overwrite = await p.confirm({\r\n message: `Directory '${safeName}' 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 } catch {\r\n // Directory doesn't exist, good\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\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 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 (or use provided --project)\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 to generate from\",\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 projectSpinner = p.spinner();\r\n projectSpinner.start(\"Fetching project details...\");\r\n const project = await apiClient.getProject(projectId);\r\n projectSpinner.stop(`Project: ${project.name}`);\r\n\r\n // 5. Select template\r\n let templateId = options.template;\r\n\r\n if (!templateId) {\r\n const templateSpinner = p.spinner();\r\n templateSpinner.start(\"Loading templates...\");\r\n\r\n // Get backend templates if project has backend\r\n const templateResult = await apiClient.getTemplates({\r\n category: \"backend\",\r\n language: project.backendFramework || undefined,\r\n });\r\n\r\n templateSpinner.stop(\"Templates loaded\");\r\n\r\n if (templateResult.templates.length === 0) {\r\n p.cancel(\"No templates available for this project's framework.\");\r\n process.exit(1);\r\n }\r\n\r\n const selectedTemplate = await p.select({\r\n message: \"Select architecture 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(selectedTemplate)) {\r\n p.cancel(\"Operation cancelled.\");\r\n process.exit(0);\r\n }\r\n\r\n templateId = selectedTemplate as string;\r\n }\r\n\r\n // 6. Get namespace\r\n const namespace = await p.text({\r\n message: \"Root namespace/package name\",\r\n placeholder: \"MegaStore\",\r\n initialValue: toPascalCase(project.name),\r\n validate: (value) => {\r\n if (!value || value.trim() === \"\") return \"Namespace is required\";\r\n if (!/^[A-Za-z][A-Za-z0-9]*$/.test(value)) {\r\n return \"Namespace must start with a letter and contain only alphanumeric characters\";\r\n }\r\n return undefined;\r\n },\r\n });\r\n\r\n if (p.isCancel(namespace)) {\r\n p.cancel(\"Operation cancelled.\");\r\n process.exit(0);\r\n }\r\n\r\n // 7. Show summary\r\n p.log.step(chalk.bold(\"Configuration Summary:\"));\r\n p.log.info(` Directory: ${safeName}/`);\r\n p.log.info(` Project: ${project.name}`);\r\n p.log.info(` Template: ${templateId}`);\r\n p.log.info(` Namespace: ${namespace}`);\r\n\r\n const proceed = await p.confirm({\r\n message: \"Create project with these settings?\",\r\n initialValue: true,\r\n });\r\n\r\n if (p.isCancel(proceed) || !proceed) {\r\n p.cancel(\"Operation cancelled.\");\r\n process.exit(0);\r\n }\r\n\r\n // 8. Create directory\r\n const dirSpinner = p.spinner();\r\n dirSpinner.start(`Creating ${safeName}/...`);\r\n await mkdir(projectDir, { recursive: true });\r\n dirSpinner.stop(`Created ${safeName}/`);\r\n\r\n // 9. Generate code\r\n const genSpinner = ora({ text: \"Generating architecture...\", color: \"cyan\" }).start();\r\n\r\n const result = await apiClient.generateCode({\r\n projectId,\r\n templateId,\r\n options: {\r\n includeValidations: true,\r\n includeComments: true,\r\n featureFlags: {\r\n includeDtos: true,\r\n includeUseCases: true,\r\n includeMappers: true,\r\n includeControllers: true,\r\n includeEfConfig: true,\r\n includeValidation: true,\r\n includeDtoValidation: true,\r\n includeUnitTests: true,\r\n includeIntegrationTests: true,\r\n includeStarterFiles: false,\r\n },\r\n useContexts: true,\r\n },\r\n });\r\n\r\n genSpinner.succeed(chalk.green(`Generated ${result.files?.length || 0} files`));\r\n\r\n // 10. Write files to project directory\r\n const writeSpinner = p.spinner();\r\n writeSpinner.start(\"Writing files...\");\r\n\r\n // Organize files into backend folder\r\n const organizedFiles = result.files.map((file: { path: string; content: string; language: string }) => ({\r\n ...file,\r\n path: `backend/${file.path}`,\r\n }));\r\n\r\n await writeGeneratedFiles(organizedFiles, projectDir, false);\r\n writeSpinner.stop(`Wrote ${organizedFiles.length} files`);\r\n\r\n // 11. Create aerocoding.json\r\n const configSpinner = p.spinner();\r\n configSpinner.start(\"Creating config files...\");\r\n\r\n const projectConfig = createProjectConfig({\r\n projectId,\r\n templateId,\r\n templateVersion: \"1.0.0\", // TODO: get from template\r\n namespace: namespace as string,\r\n organizationId,\r\n output: { backend: \"./backend\", frontend: \"./frontend\" },\r\n });\r\n\r\n await saveProjectConfig(projectConfig, projectDir);\r\n\r\n // 12. Create aerocoding-manifest.json\r\n let manifest: AeroManifest = createEmptyManifest(\"1.0.0\");\r\n\r\n // Track all generated files in manifest\r\n for (const file of organizedFiles) {\r\n const hash = hashString(file.content);\r\n manifest = setManifestFile(manifest, file.path, {\r\n hash,\r\n mtime: Date.now(),\r\n size: Buffer.byteLength(file.content, \"utf-8\"),\r\n type: detectFileType(file.path),\r\n });\r\n }\r\n\r\n await writeManifest(projectDir, manifest);\r\n configSpinner.stop(\"Config files created\");\r\n\r\n // 13. Sync manifest to cloud\r\n try {\r\n const syncResult = await syncToCloud(apiClient, projectId, manifest);\r\n if (syncResult.success) {\r\n console.log(\r\n chalk.gray(\" ✓ Manifest synced to cloud\") +\r\n chalk.gray(` (${syncResult.fileCount} files)`)\r\n );\r\n }\r\n } catch {\r\n // Non-fatal - just log warning\r\n console.log(chalk.yellow(\" ⚠ Could not sync manifest to cloud\"));\r\n }\r\n\r\n // 14. Show results\r\n console.log(\"\");\r\n console.log(chalk.bold(\" Project Created Successfully!\"));\r\n console.log(chalk.gray(\" ─────────────────────────────────\"));\r\n console.log(chalk.gray(\" Directory:\"), chalk.cyan(safeName + \"/\"));\r\n console.log(chalk.gray(\" Files:\"), chalk.cyan(organizedFiles.length));\r\n console.log(chalk.gray(\" Config:\"), chalk.cyan(PROJECT_CONFIG_FILENAME));\r\n console.log(chalk.gray(\" Manifest:\"), chalk.cyan(MANIFEST_FILENAME));\r\n\r\n if (result.creditsUsed !== undefined) {\r\n console.log(\"\");\r\n console.log(chalk.gray(\" Credits used:\"), chalk.yellow(result.creditsUsed));\r\n console.log(chalk.gray(\" Credits remaining:\"), chalk.green(result.creditsRemaining));\r\n }\r\n\r\n p.outro(\r\n chalk.green(\"Project ready!\") +\r\n \"\\n\\n\" +\r\n chalk.gray(\" Next steps:\\n\") +\r\n chalk.cyan(` cd ${safeName}\\n`) +\r\n chalk.gray(\" # Make changes in the diagram editor\\n\") +\r\n chalk.cyan(\" aerocoding update\") +\r\n chalk.gray(\" # Sync changes incrementally\")\r\n );\r\n } catch (error: unknown) {\r\n const err = error as { response?: { status?: number; data?: { message?: string } }; message?: string };\r\n if (err.response?.status === 401) {\r\n await handleUnauthorized(tokenManager);\r\n } else if (err.response?.data?.message) {\r\n p.cancel(err.response.data.message);\r\n } else {\r\n p.cancel(err.message || \"An unexpected error occurred\");\r\n }\r\n process.exit(1);\r\n }\r\n}\r\n\r\n/**\r\n * Convert string to PascalCase for .NET namespaces\r\n * \"mega-store\" → \"MegaStore\"\r\n * \"mega_store\" → \"MegaStore\"\r\n * \"mega store\" → \"MegaStore\"\r\n */\r\nfunction toPascalCase(str: string): string {\r\n return str\r\n .split(/[-_\\s]+/) // Split by hyphen, underscore, or space\r\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\r\n .join(\"\")\r\n .replace(/[^a-zA-Z0-9]/g, \"\"); // Remove any remaining special chars\r\n}\r\n\r\n/**\r\n * Detect file type from path for manifest categorization\r\n */\r\nfunction detectFileType(\r\n filePath: string\r\n): \"entity\" | \"usecase\" | \"repository\" | \"controller\" | \"dto\" | \"config\" | \"test\" | \"other\" {\r\n const lower = filePath.toLowerCase();\r\n\r\n if (lower.includes(\"/entities/\") || lower.includes(\"/domain/\")) return \"entity\";\r\n if (lower.includes(\"/usecases/\") || lower.includes(\"/application/\")) return \"usecase\";\r\n if (lower.includes(\"/repositories/\")) return \"repository\";\r\n if (lower.includes(\"/controllers/\") || lower.includes(\"/api/\")) return \"controller\";\r\n if (lower.includes(\"/dtos/\") || lower.includes(\"/dto/\")) return \"dto\";\r\n if (lower.includes(\".test.\") || lower.includes(\".spec.\") || lower.includes(\"/tests/\")) return \"test\";\r\n if (lower.includes(\"/config/\") || lower.includes(\"appsettings\") || lower.includes(\".csproj\")) return \"config\";\r\n\r\n return \"other\";\r\n}\r\n","import { z } from \"zod\";\r\nimport { readFile, writeFile, access } from \"node:fs/promises\";\r\nimport { join } from \"node:path\";\r\n\r\n// ============================================\r\n// aerocoding.json - Project Configuration\r\n// New format for incremental generation\r\n// ============================================\r\n\r\nexport const PROJECT_CONFIG_FILENAME = \"aerocoding.json\";\r\n\r\n/**\r\n * Schema for aerocoding.json\r\n * This is the user-editable config for the meta-framework approach\r\n */\r\nexport const projectConfigSchema = z.object({\r\n $schema: z.string().optional().default(\"https://aerocoding.dev/schema.json\"),\r\n\r\n /** Project UUID from aerocoding.dev */\r\n projectId: z.string().uuid(),\r\n\r\n /** Template ID for architecture generation */\r\n templateId: z.string().min(1),\r\n\r\n /** Template version at project creation */\r\n templateVersion: z.string().optional(),\r\n\r\n /** Root namespace/package name */\r\n namespace: z.string().min(1),\r\n\r\n /** Output directories */\r\n output: z.object({\r\n backend: z.string().default(\"./backend\"),\r\n frontend: z.string().default(\"./frontend\"),\r\n }).optional().default({ backend: \"./backend\", frontend: \"./frontend\" }),\r\n\r\n /** Organization ID (for cloud sync) */\r\n organizationId: z.string().uuid().optional(),\r\n});\r\n\r\nexport type ProjectConfig = z.infer<typeof projectConfigSchema>;\r\n\r\n/**\r\n * Check if aerocoding.json exists in a directory\r\n */\r\nexport async function projectConfigExists(dir: string = process.cwd()): Promise<boolean> {\r\n try {\r\n await access(join(dir, PROJECT_CONFIG_FILENAME));\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * Load aerocoding.json from a directory\r\n */\r\nexport async function loadProjectConfig(dir: string = process.cwd()): Promise<ProjectConfig | null> {\r\n try {\r\n const configPath = join(dir, PROJECT_CONFIG_FILENAME);\r\n const content = await readFile(configPath, \"utf-8\");\r\n const parsed = JSON.parse(content);\r\n return projectConfigSchema.parse(parsed);\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Save aerocoding.json to a directory\r\n */\r\nexport async function saveProjectConfig(config: ProjectConfig, dir: string = process.cwd()): Promise<void> {\r\n const configPath = join(dir, PROJECT_CONFIG_FILENAME);\r\n const content = JSON.stringify(config, null, 2);\r\n await writeFile(configPath, content, \"utf-8\");\r\n}\r\n\r\n/**\r\n * Create a new project config\r\n */\r\nexport function createProjectConfig(options: {\r\n projectId: string;\r\n templateId: string;\r\n templateVersion?: string;\r\n namespace: string;\r\n organizationId?: string;\r\n output?: { backend?: string; frontend?: string };\r\n}): ProjectConfig {\r\n return {\r\n $schema: \"https://aerocoding.dev/schema.json\",\r\n projectId: options.projectId,\r\n templateId: options.templateId,\r\n templateVersion: options.templateVersion,\r\n namespace: options.namespace,\r\n organizationId: options.organizationId,\r\n output: {\r\n backend: options.output?.backend || \"./backend\",\r\n frontend: options.output?.frontend || \"./frontend\",\r\n },\r\n };\r\n}\r\n","// ============================================\r\n// Cloud Sync - Manifest Backup/Recovery\r\n// ============================================\r\n\r\nimport { ApiClient, CloudManifest } from \"../api/client.js\";\r\nimport type { AeroManifest } from \"../manifest/types.js\";\r\n\r\n/**\r\n * Convert local manifest to cloud format\r\n * Strips entities array (not needed for cloud backup)\r\n */\r\nexport function toCloudManifest(manifest: AeroManifest): CloudManifest {\r\n return {\r\n version: manifest.version,\r\n lastSync: manifest.lastSync,\r\n templateVersion: manifest.templateVersion,\r\n files: manifest.files,\r\n };\r\n}\r\n\r\n/**\r\n * Convert cloud manifest back to local format\r\n */\r\nexport function fromCloudManifest(\r\n cloudManifest: CloudManifest,\r\n templateVersion: string\r\n): AeroManifest {\r\n return {\r\n version: cloudManifest.version,\r\n lastSync: cloudManifest.lastSync || new Date().toISOString(),\r\n templateVersion: cloudManifest.templateVersion || templateVersion,\r\n files: cloudManifest.files,\r\n entities: [], // Will be rebuilt on next generation\r\n };\r\n}\r\n\r\n/**\r\n * Sync local manifest to cloud\r\n *\r\n * @returns Success status and file count\r\n */\r\nexport async function syncToCloud(\r\n apiClient: ApiClient,\r\n projectId: string,\r\n manifest: AeroManifest\r\n): Promise<{ success: boolean; fileCount: number }> {\r\n const cloudManifest = toCloudManifest(manifest);\r\n const result = await apiClient.saveManifest(projectId, cloudManifest);\r\n\r\n return {\r\n success: result.success,\r\n fileCount: result.fileCount,\r\n };\r\n}\r\n\r\n/**\r\n * Fetch manifest from cloud\r\n *\r\n * @returns Manifest or null if not found\r\n */\r\nexport async function fetchFromCloud(\r\n apiClient: ApiClient,\r\n projectId: string,\r\n templateVersion: string\r\n): Promise<AeroManifest | null> {\r\n const cloudManifest = await apiClient.getManifest(projectId);\r\n\r\n if (!cloudManifest) {\r\n return null;\r\n }\r\n\r\n return fromCloudManifest(cloudManifest, templateVersion);\r\n}\r\n\r\n/**\r\n * Check if cloud has a more recent manifest\r\n *\r\n * @returns Object with comparison info\r\n */\r\nexport async function compareWithCloud(\r\n apiClient: ApiClient,\r\n projectId: string,\r\n localManifest: AeroManifest | null\r\n): Promise<{\r\n hasCloudBackup: boolean;\r\n cloudLastSync: string | null;\r\n localLastSync: string | null;\r\n isCloudNewer: boolean;\r\n cloudFileCount: number;\r\n localFileCount: number;\r\n}> {\r\n const cloudManifest = await apiClient.getManifest(projectId);\r\n\r\n const cloudLastSync = cloudManifest?.lastSync || null;\r\n const localLastSync = localManifest?.lastSync || null;\r\n const cloudFileCount = cloudManifest ? Object.keys(cloudManifest.files).length : 0;\r\n const localFileCount = localManifest ? Object.keys(localManifest.files).length : 0;\r\n\r\n // Determine if cloud is newer\r\n let isCloudNewer = false;\r\n if (cloudLastSync && localLastSync) {\r\n isCloudNewer = new Date(cloudLastSync) > new Date(localLastSync);\r\n } else if (cloudLastSync && !localLastSync) {\r\n isCloudNewer = true;\r\n }\r\n\r\n return {\r\n hasCloudBackup: cloudManifest !== null,\r\n cloudLastSync,\r\n localLastSync,\r\n isCloudNewer,\r\n cloudFileCount,\r\n localFileCount,\r\n };\r\n}\r\n\r\n/**\r\n * Format a date for display\r\n */\r\nexport function formatSyncDate(isoDate: string | null): string {\r\n if (!isoDate) return \"never\";\r\n\r\n const date = new Date(isoDate);\r\n const now = new Date();\r\n const diffMs = now.getTime() - date.getTime();\r\n const diffMins = Math.floor(diffMs / 60000);\r\n const diffHours = Math.floor(diffMs / 3600000);\r\n const diffDays = Math.floor(diffMs / 86400000);\r\n\r\n if (diffMins < 1) return \"just now\";\r\n if (diffMins < 60) return `${diffMins}m ago`;\r\n if (diffHours < 24) return `${diffHours}h ago`;\r\n if (diffDays < 7) return `${diffDays}d ago`;\r\n\r\n return date.toLocaleDateString();\r\n}\r\n","// ============================================\r\n// Update Command - Incremental Code Generation\r\n// ============================================\r\n\r\nimport * as p from \"@clack/prompts\";\r\nimport 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 { writeGeneratedFilesWithManifest } from \"../utils/file-writer.js\";\r\nimport { loadProjectConfig, PROJECT_CONFIG_FILENAME } from \"../config/project-config.js\";\r\nimport { readManifest, writeManifest } from \"../manifest/index.js\";\r\nimport {\r\n syncToCloud,\r\n fetchFromCloud,\r\n compareWithCloud,\r\n formatSyncDate,\r\n} from \"../utils/cloud-sync.js\";\r\n\r\ninterface UpdateOptions {\r\n force?: boolean;\r\n verbose?: boolean;\r\n dryRun?: boolean;\r\n}\r\n\r\n/**\r\n * Update Command\r\n *\r\n * Incrementally updates generated code by:\r\n * 1. Reading aerocoding.json config\r\n * 2. Fetching latest schema from aerocoding.dev\r\n * 3. Regenerating code with current template\r\n * 4. Using three-way merge to preserve user changes\r\n * 5. Creating .new/.conflict files for manual resolution\r\n *\r\n * @ai-critical Core command for incremental generation workflow\r\n */\r\nexport async function updateCommand(options: UpdateOptions) {\r\n p.intro(chalk.bgCyan.black(\" AeroCoding Update \"));\r\n\r\n // 1. Load project config\r\n const config = await loadProjectConfig();\r\n\r\n if (!config) {\r\n p.cancel(\r\n `No ${PROJECT_CONFIG_FILENAME} found. Run 'aerocoding create' first.`\r\n );\r\n process.exit(1);\r\n }\r\n\r\n // 2. 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 // 3. Load existing manifest (if any)\r\n let manifest = await readManifest(process.cwd());\r\n let fileCount = manifest ? Object.keys(manifest.files).length : 0;\r\n\r\n if (manifest) {\r\n p.log.info(\r\n `Found manifest with ${fileCount} tracked files (last sync: ${manifest.lastSync || \"unknown\"})`\r\n );\r\n } else {\r\n // No local manifest - check cloud for backup\r\n p.log.warn(\"No local manifest found.\");\r\n\r\n const cloudCheck = await compareWithCloud(apiClient, config.projectId, null);\r\n\r\n if (cloudCheck.hasCloudBackup) {\r\n p.log.info(\r\n chalk.cyan(\r\n ` Cloud backup available (${cloudCheck.cloudFileCount} files, synced ${formatSyncDate(cloudCheck.cloudLastSync)})`\r\n )\r\n );\r\n\r\n const recovery = await p.select({\r\n message: \"How would you like to proceed?\",\r\n options: [\r\n {\r\n value: \"restore\",\r\n label: \"Restore from cloud backup\",\r\n hint: \"recommended\",\r\n },\r\n {\r\n value: \"continue\",\r\n label: \"Continue anyway\",\r\n hint: \"all files will be treated as new\",\r\n },\r\n { value: \"cancel\", label: \"Cancel\" },\r\n ],\r\n });\r\n\r\n if (p.isCancel(recovery) || recovery === \"cancel\") {\r\n p.cancel(\"Update cancelled.\");\r\n process.exit(0);\r\n }\r\n\r\n if (recovery === \"restore\") {\r\n const restoreSpinner = p.spinner();\r\n restoreSpinner.start(\"Restoring manifest from cloud...\");\r\n\r\n const cloudManifest = await fetchFromCloud(\r\n apiClient,\r\n config.projectId,\r\n config.templateVersion || \"1.0.0\"\r\n );\r\n\r\n if (cloudManifest) {\r\n await writeManifest(process.cwd(), cloudManifest);\r\n manifest = cloudManifest;\r\n fileCount = Object.keys(manifest.files).length;\r\n restoreSpinner.stop(\r\n chalk.green(`Restored ${fileCount} files from cloud backup`)\r\n );\r\n } else {\r\n restoreSpinner.stop(chalk.yellow(\"Cloud backup not found\"));\r\n }\r\n }\r\n } else {\r\n p.log.info(\r\n chalk.gray(\" No cloud backup available. All generated files will be created as new.\")\r\n );\r\n }\r\n }\r\n\r\n // 4. Fetch project details\r\n const projectSpinner = p.spinner();\r\n projectSpinner.start(\"Fetching project details...\");\r\n const project = await apiClient.getProject(config.projectId);\r\n projectSpinner.stop(`Project: ${project.name}`);\r\n\r\n // 5. Show update summary\r\n p.log.step(chalk.bold(\"Update Configuration:\"));\r\n p.log.info(` Project: ${project.name}`);\r\n p.log.info(` Template: ${config.templateId}`);\r\n p.log.info(` Namespace: ${config.namespace}`);\r\n p.log.info(` Output: ${config.output.backend}`);\r\n\r\n if (options.dryRun) {\r\n p.log.info(chalk.yellow(\" Mode: DRY RUN (no files will be written)\"));\r\n }\r\n if (options.force) {\r\n p.log.info(chalk.yellow(\" Mode: FORCE (will overwrite modified files)\"));\r\n }\r\n\r\n // 6. Confirm update\r\n if (!options.dryRun) {\r\n const proceed = await p.confirm({\r\n message: \"Proceed with update?\",\r\n initialValue: true,\r\n });\r\n\r\n if (p.isCancel(proceed) || !proceed) {\r\n p.cancel(\"Update cancelled.\");\r\n process.exit(0);\r\n }\r\n }\r\n\r\n // 7. Generate code\r\n const genSpinner = ora({\r\n text: \"Generating code from latest schema...\",\r\n color: \"cyan\",\r\n }).start();\r\n\r\n const result = await apiClient.generateCode({\r\n projectId: config.projectId,\r\n templateId: config.templateId,\r\n options: {\r\n includeValidations: true,\r\n includeComments: true,\r\n featureFlags: {\r\n includeDtos: true,\r\n includeUseCases: true,\r\n includeMappers: true,\r\n includeControllers: true,\r\n includeEfConfig: true,\r\n includeValidation: true,\r\n includeDtoValidation: true,\r\n includeUnitTests: true,\r\n includeIntegrationTests: true,\r\n includeStarterFiles: false, // Don't regenerate starter files\r\n },\r\n useContexts: true,\r\n },\r\n });\r\n\r\n genSpinner.succeed(\r\n chalk.green(`Generated ${result.files?.length || 0} files from schema`)\r\n );\r\n\r\n if (options.dryRun) {\r\n // Dry run - just show what would happen\r\n p.log.info(\"\");\r\n p.log.info(chalk.bold(\" Dry Run Results:\"));\r\n p.log.info(chalk.gray(\" ─────────────────────────────────\"));\r\n p.log.info(` Files to process: ${result.files?.length || 0}`);\r\n p.log.info(` Tracked files: ${fileCount}`);\r\n p.log.info(\"\");\r\n p.log.info(chalk.gray(\" Run without --dry-run to apply changes.\"));\r\n\r\n p.outro(chalk.green(\"Dry run complete!\"));\r\n return;\r\n }\r\n\r\n // 8. Apply updates with merge\r\n const updateSpinner = p.spinner();\r\n updateSpinner.start(\"Applying updates...\");\r\n\r\n // Organize files into backend folder (matching create command structure)\r\n const organizedFiles = result.files.map(\r\n (file: { path: string; content: string; language: string }) => ({\r\n ...file,\r\n path: `${config.output.backend.replace(/^\\.\\//, \"\")}/${file.path}`,\r\n })\r\n );\r\n\r\n const writeResult = await writeGeneratedFilesWithManifest(\r\n organizedFiles,\r\n process.cwd(),\r\n config.templateVersion || \"1.0.0\",\r\n {\r\n verbose: options.verbose,\r\n forceOverwrite: options.force,\r\n }\r\n );\r\n\r\n updateSpinner.stop(\"Update complete\");\r\n\r\n // 9. Show credits\r\n if (result.creditsUsed !== undefined) {\r\n console.log(\"\");\r\n console.log(chalk.gray(\" Credits used:\"), chalk.yellow(result.creditsUsed));\r\n console.log(\r\n chalk.gray(\" Credits remaining:\"),\r\n chalk.green(result.creditsRemaining)\r\n );\r\n }\r\n\r\n // 10. Sync manifest to cloud\r\n try {\r\n const syncResult = await syncToCloud(\r\n apiClient,\r\n config.projectId,\r\n writeResult.manifest\r\n );\r\n if (syncResult.success) {\r\n console.log(\r\n chalk.gray(\" ✓ Manifest synced to cloud\") +\r\n chalk.gray(` (${syncResult.fileCount} files)`)\r\n );\r\n }\r\n } catch (syncError) {\r\n // Non-fatal - just log warning\r\n console.log(chalk.yellow(\" ⚠ Could not sync manifest to cloud\"));\r\n if (options.verbose) {\r\n console.log(chalk.gray(` ${(syncError as Error).message}`));\r\n }\r\n }\r\n\r\n // 11. Show final message\r\n if (writeResult.conflicts.length > 0) {\r\n p.outro(\r\n chalk.yellow(`Update complete with ${writeResult.conflicts.length} conflict(s).`) +\r\n \"\\n\" +\r\n chalk.gray(\" Run 'aerocoding resolve' after fixing conflicts.\")\r\n );\r\n } else {\r\n const totalWritten =\r\n writeResult.created.length +\r\n writeResult.updated.length +\r\n writeResult.merged.length;\r\n\r\n p.outro(\r\n chalk.green(`Update complete! ${totalWritten} file(s) written.`)\r\n );\r\n }\r\n } catch (error: unknown) {\r\n const err = error as {\r\n response?: { status?: number; data?: { message?: string } };\r\n message?: string;\r\n };\r\n if (err.response?.status === 401) {\r\n await handleUnauthorized(tokenManager);\r\n } else if (err.response?.data?.message) {\r\n p.cancel(err.response.data.message);\r\n } else {\r\n p.cancel(err.message || \"An unexpected error occurred\");\r\n }\r\n process.exit(1);\r\n }\r\n}\r\n","// ============================================\r\n// Resolve Command - Clean up merge conflicts\r\n// ============================================\r\n\r\nimport * as p from \"@clack/prompts\";\r\nimport chalk from \"chalk\";\r\nimport { readdir, stat } from \"node:fs/promises\";\r\nimport { join, relative } from \"node:path\";\r\nimport {\r\n removeConflictFiles,\r\n CONFLICT_NEW_EXT,\r\n CONFLICT_DIFF_EXT,\r\n} from \"../merge/index.js\";\r\nimport {\r\n readManifest,\r\n writeManifest,\r\n setManifestFile,\r\n hashFile,\r\n} from \"../manifest/index.js\";\r\nimport { loadProjectConfig, PROJECT_CONFIG_FILENAME } from \"../config/project-config.js\";\r\n\r\ninterface ResolveOptions {\r\n verbose?: boolean;\r\n all?: boolean;\r\n}\r\n\r\ninterface ConflictFile {\r\n originalPath: string;\r\n newPath: string;\r\n conflictPath: string;\r\n}\r\n\r\n/**\r\n * Resolve Command\r\n *\r\n * Cleans up conflict files after user has manually resolved merge conflicts.\r\n *\r\n * Flow:\r\n * 1. Find all .new and .conflict files\r\n * 2. For each conflict:\r\n * - Verify original file exists (user resolved it)\r\n * - Remove .new and .conflict files\r\n * - Update manifest with new hash\r\n *\r\n * @ai-critical Part of incremental generation workflow\r\n */\r\nexport async function resolveCommand(options: ResolveOptions) {\r\n p.intro(chalk.bgCyan.black(\" AeroCoding Resolve \"));\r\n\r\n // 1. Load project config\r\n const config = await loadProjectConfig();\r\n\r\n if (!config) {\r\n p.cancel(\r\n `No ${PROJECT_CONFIG_FILENAME} found. Run 'aerocoding create' first.`\r\n );\r\n process.exit(1);\r\n }\r\n\r\n // 2. Find all conflict files\r\n const spinner = p.spinner();\r\n spinner.start(\"Scanning for conflict files...\");\r\n\r\n const conflicts = await findConflictFiles(process.cwd());\r\n spinner.stop(`Found ${conflicts.length} conflict(s)`);\r\n\r\n if (conflicts.length === 0) {\r\n p.log.success(\"No conflicts to resolve!\");\r\n p.outro(chalk.green(\"All clear!\"));\r\n return;\r\n }\r\n\r\n // 3. Show conflicts\r\n p.log.info(\"\");\r\n p.log.info(chalk.bold(\" Pending Conflicts:\"));\r\n p.log.info(chalk.gray(\" ─────────────────────────────────\"));\r\n\r\n for (const conflict of conflicts) {\r\n const relPath = relative(process.cwd(), conflict.originalPath);\r\n p.log.info(chalk.yellow(` ⚠ ${relPath}`));\r\n if (options.verbose) {\r\n p.log.info(chalk.gray(` → ${relative(process.cwd(), conflict.newPath)}`));\r\n p.log.info(\r\n chalk.gray(` → ${relative(process.cwd(), conflict.conflictPath)}`)\r\n );\r\n }\r\n }\r\n\r\n p.log.info(chalk.gray(\" ─────────────────────────────────\"));\r\n p.log.info(\"\");\r\n\r\n // 4. Confirm resolution\r\n if (!options.all) {\r\n const proceed = await p.confirm({\r\n message: `Remove ${conflicts.length} conflict file(s)? (This assumes you've resolved them)`,\r\n initialValue: true,\r\n });\r\n\r\n if (p.isCancel(proceed) || !proceed) {\r\n p.cancel(\"Resolution cancelled.\");\r\n process.exit(0);\r\n }\r\n }\r\n\r\n // 5. Load manifest\r\n let manifest = await readManifest(process.cwd());\r\n\r\n if (!manifest) {\r\n p.cancel(\"No manifest found. Cannot update file hashes.\");\r\n process.exit(1);\r\n }\r\n\r\n // 6. Resolve each conflict\r\n const resolveSpinner = p.spinner();\r\n resolveSpinner.start(\"Resolving conflicts...\");\r\n\r\n let resolved = 0;\r\n let failed = 0;\r\n\r\n for (const conflict of conflicts) {\r\n try {\r\n const relPath = relative(process.cwd(), conflict.originalPath);\r\n\r\n // Verify original file exists\r\n try {\r\n await stat(conflict.originalPath);\r\n } catch {\r\n if (options.verbose) {\r\n console.log(\r\n chalk.red(` ✗ ${relPath} - original file not found`)\r\n );\r\n }\r\n failed++;\r\n continue;\r\n }\r\n\r\n // Remove conflict files\r\n const { removedNew, removedConflict } = await removeConflictFiles(\r\n conflict.originalPath\r\n );\r\n\r\n // Update manifest with new hash\r\n const newHash = await hashFile(conflict.originalPath);\r\n const stats = await stat(conflict.originalPath);\r\n\r\n // Get path relative to project root for manifest\r\n const manifestPath = relPath.replace(/\\\\/g, \"/\");\r\n const existingEntry = manifest.files[manifestPath];\r\n\r\n manifest = setManifestFile(manifest, manifestPath, {\r\n hash: newHash,\r\n mtime: Math.floor(stats.mtimeMs),\r\n size: stats.size,\r\n entityId: existingEntry?.entityId,\r\n type: existingEntry?.type || \"other\",\r\n contextName: existingEntry?.contextName,\r\n });\r\n\r\n if (options.verbose) {\r\n const removed = [];\r\n if (removedNew) removed.push(\".new\");\r\n if (removedConflict) removed.push(\".conflict\");\r\n console.log(\r\n chalk.green(` ✓ ${relPath}`) +\r\n chalk.gray(` (removed ${removed.join(\", \")})`)\r\n );\r\n }\r\n\r\n resolved++;\r\n } catch (error) {\r\n failed++;\r\n if (options.verbose) {\r\n const relPath = relative(process.cwd(), conflict.originalPath);\r\n console.log(chalk.red(` ✗ ${relPath} - ${error}`));\r\n }\r\n }\r\n }\r\n\r\n // 7. Save updated manifest\r\n manifest = {\r\n ...manifest,\r\n lastSync: new Date().toISOString(),\r\n };\r\n\r\n await writeManifest(process.cwd(), manifest);\r\n resolveSpinner.stop(\"Conflicts resolved\");\r\n\r\n // 8. Show results\r\n console.log(\"\");\r\n console.log(chalk.bold(\" Resolution Results\"));\r\n console.log(chalk.gray(\" ─────────────────────────────────\"));\r\n\r\n if (resolved > 0) {\r\n console.log(chalk.green(` ✓ Resolved: ${resolved} files`));\r\n }\r\n if (failed > 0) {\r\n console.log(chalk.red(` ✗ Failed: ${failed} files`));\r\n }\r\n\r\n console.log(chalk.gray(\" ─────────────────────────────────\"));\r\n\r\n if (failed > 0) {\r\n p.outro(\r\n chalk.yellow(\r\n `Resolved ${resolved} conflict(s), ${failed} failed.`\r\n )\r\n );\r\n } else {\r\n p.outro(chalk.green(`All ${resolved} conflict(s) resolved!`));\r\n }\r\n}\r\n\r\n/**\r\n * Recursively find all conflict files in a directory\r\n */\r\nasync function findConflictFiles(dir: string): Promise<ConflictFile[]> {\r\n const conflicts: ConflictFile[] = [];\r\n\r\n async function scan(currentDir: string) {\r\n try {\r\n const entries = await readdir(currentDir, { withFileTypes: true });\r\n\r\n for (const entry of entries) {\r\n const fullPath = join(currentDir, entry.name);\r\n\r\n // Skip node_modules and hidden directories\r\n if (entry.isDirectory()) {\r\n if (\r\n entry.name === \"node_modules\" ||\r\n entry.name === \".git\" ||\r\n entry.name.startsWith(\".\")\r\n ) {\r\n continue;\r\n }\r\n await scan(fullPath);\r\n } else if (entry.isFile()) {\r\n // Check for .new files\r\n if (entry.name.endsWith(CONFLICT_NEW_EXT)) {\r\n const originalPath = fullPath.slice(\r\n 0,\r\n -CONFLICT_NEW_EXT.length\r\n );\r\n const conflictPath = originalPath + CONFLICT_DIFF_EXT;\r\n\r\n // Only add if we haven't already found this conflict\r\n const existing = conflicts.find(\r\n (c) => c.originalPath === originalPath\r\n );\r\n if (!existing) {\r\n conflicts.push({\r\n originalPath,\r\n newPath: fullPath,\r\n conflictPath,\r\n });\r\n }\r\n }\r\n // Check for .conflict files (in case .new was deleted)\r\n else if (entry.name.endsWith(CONFLICT_DIFF_EXT)) {\r\n const originalPath = fullPath.slice(\r\n 0,\r\n -CONFLICT_DIFF_EXT.length\r\n );\r\n const newPath = originalPath + CONFLICT_NEW_EXT;\r\n\r\n // Only add if we haven't already found this conflict\r\n const existing = conflicts.find(\r\n (c) => c.originalPath === originalPath\r\n );\r\n if (!existing) {\r\n conflicts.push({\r\n originalPath,\r\n newPath,\r\n conflictPath: fullPath,\r\n });\r\n }\r\n }\r\n }\r\n }\r\n } catch {\r\n // Ignore directories we can't read\r\n }\r\n }\r\n\r\n await scan(dir);\r\n return conflicts;\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","resolve","axios","API_URL","chalk","chalk","chalk","chalk","chalk","chalk","chalk","ora","fs","path","chalk","fs","resolve","generatedLines","writeFile","path","chalk","fs","chalk","resolve","fs","path","path","fs","chalk","spinner","ora","p","chalk","chalk","spinner","p","chalk","ora","access","z","readFile","writeFile","access","join","join","readFile","writeFile","chalk","access","spinner","ora","p","chalk","ora","chalk","ora","p","chalk","stat","join","chalk","spinner","stat","join","chalk","chalk"]}