@entro314labs/at3-stack-kit
Version:
Upgrade existing projects to AT3 Stack with intelligent migration
1 lines • 66.4 kB
Source Map (JSON)
{"version":3,"sources":["../src/index.ts","../src/cli.ts","../src/detect.ts","../src/features/add-ai.ts","../src/features/add-i18n.ts","../src/features/add-pwa.ts","../src/features/add-supabase.ts","../src/features/add-testing.ts","../src/utils/cli-styling.ts","../src/utils/integration.ts"],"sourcesContent":["/**\n * AT3 Stack Kit\n * CLI tool to upgrade existing projects to AT3 Stack with AI, edge, and modern features\n */\n\n// CLI utilities\nexport { program } from \"./cli.js\";\n// Core detection and analysis\nexport * from \"./detect.js\";\n// Feature addition modules\nexport * from \"./features/index.js\";\n","#!/usr/bin/env node\n\n/**\n * AT3 Stack Kit CLI\n * Upgrade existing projects to AT3 Stack with AI, edge, and modern features\n */\n\nimport {\n cancel,\n confirm,\n intro,\n isCancel,\n multiselect,\n note,\n outro,\n select,\n spinner,\n} from \"@clack/prompts\";\nimport chalk from \"chalk\";\nimport { program } from \"commander\";\nimport { detect as detectPackageManager } from \"detect-package-manager\";\nimport { existsSync, readFileSync } from \"fs-extra\";\nimport { join } from \"path\";\nimport { detectProjectType, type ProjectType } from \"./detect.js\";\nimport { addAI, addI18n, addPWA, addSupabase, addTesting } from \"./features/index.js\";\nimport { colors, header, style, symbols } from \"./utils/cli-styling.js\";\nimport { getPostMigrationWorkflow, suggestAT3Tools, updateAT3Config } from \"./utils/integration.js\";\n\nconst features = [\n {\n id: \"ai-custom\",\n name: \"AI Integration (Custom)\",\n description: \"Add custom AI integration with multiple providers\",\n value: \"ai-custom\",\n },\n {\n id: \"ai-vercel\",\n name: \"AI Integration (Vercel SDK)\",\n description: \"Add Vercel AI SDK for streaming responses\",\n value: \"ai-vercel\",\n },\n {\n id: \"supabase\",\n name: \"Supabase\",\n description: \"Add Supabase for database, auth, and edge functions\",\n value: \"supabase\",\n },\n {\n id: \"pwa\",\n name: \"PWA Support\",\n description: \"Add Progressive Web App features\",\n value: \"pwa\",\n },\n {\n id: \"i18n\",\n name: \"Internationalization\",\n description: \"Add next-intl for multi-language support\",\n value: \"i18n\",\n },\n {\n id: \"testing\",\n name: \"Testing Suite\",\n description: \"Add Vitest and Playwright for comprehensive testing\",\n value: \"testing\",\n },\n] as const;\n\ntype FeatureId = (typeof features)[number][\"value\"];\n\nasync function main() {\n console.clear();\n\n intro(style.title(\"AT3 Stack Kit\"));\n\n // Detect current project\n const s = spinner();\n s.start(\"Analyzing your project...\");\n\n const projectType = await detectProjectType(process.cwd());\n const packageManager = await detectPackageManager().catch(() => \"npm\");\n\n s.stop(\n `${symbols.success} Detected: ${style.value(getProjectTypeLabel(projectType))} project using ${style.accent(packageManager)}`\n );\n\n if (projectType === \"unknown\") {\n cancel(\n \"This doesn't appear to be a supported project type. AT3 Kit supports Next.js, T3, and React projects.\"\n );\n process.exit(1);\n }\n\n // Show current project info\n note(getProjectInfo(projectType), \"Current Project\");\n\n // Select features to add\n const selectedFeatures = await multiselect({\n message: \"Which features would you like to add?\",\n options: features.map((feature) => ({\n value: feature.value,\n label: feature.name,\n hint: feature.description,\n })),\n required: true,\n });\n\n if (isCancel(selectedFeatures) || selectedFeatures.length === 0) {\n cancel(\"No features selected.\");\n process.exit(0);\n }\n\n // Confirm installation\n const shouldInstall = await confirm({\n message: `Install dependencies with ${packageManager}?`,\n initialValue: true,\n });\n\n if (isCancel(shouldInstall)) {\n cancel(\"Operation cancelled.\");\n process.exit(0);\n }\n\n // Apply features\n const addSpinner = spinner();\n\n try {\n for (const featureId of selectedFeatures as FeatureId[]) {\n addSpinner.start(`Adding ${getFeatureName(featureId)}...`);\n\n switch (featureId) {\n case \"ai-custom\":\n await addAI(\"custom\", process.cwd());\n break;\n case \"ai-vercel\":\n await addAI(\"vercel\", process.cwd());\n break;\n case \"supabase\":\n await addSupabase(process.cwd());\n break;\n case \"pwa\":\n await addPWA(process.cwd());\n break;\n case \"i18n\":\n await addI18n(process.cwd());\n break;\n case \"testing\":\n await addTesting(process.cwd());\n break;\n }\n\n addSpinner.stop(`✓ Added ${getFeatureName(featureId)}`);\n }\n\n if (shouldInstall) {\n addSpinner.start(`Installing dependencies with ${packageManager}...`);\n // TODO: Install dependencies\n addSpinner.stop(\"✓ Dependencies installed\");\n }\n\n // Update AT3 configuration and get suggestions\n const projectInfo = { type: projectType, packageManager } as any; // Simplified for now\n const addedFeatures = selectedFeatures; // This would be the actual added features\n\n updateAT3Config(process.cwd(), addedFeatures);\n const toolSuggestions = suggestAT3Tools(projectInfo, addedFeatures);\n const workflows = getPostMigrationWorkflow(projectInfo, addedFeatures);\n\n outro(style.success(\"🎉 Your project has been upgraded to AT3 Stack!\"));\n\n const nextSteps = [\n \"Review the added files and configurations\",\n \"Update your .env.local with required API keys\",\n `Run ${style.command(packageManager + \" dev\")} to test your upgraded project`,\n ...workflows,\n ];\n\n note(\n `\n${header.section(\"Next steps:\")}\n${nextSteps.map((step, i) => ` ${colors.muted(`${i + 1}.`)} ${step}`).join(\"\\n\")}\n\n${colors.primary(\"Documentation:\")}\n ${colors.muted(\"•\")} AT3 Stack Guide: https://at3-stack.dev/docs\n ${colors.muted(\"•\")} Feature Guides: https://at3-stack.dev/docs/features\n\n${\n toolSuggestions.length > 0\n ? `${colors.primary(\"AT3 Ecosystem:\")}\n ${toolSuggestions.map((s) => `${colors.muted(\"•\")} ${s}`).join(\"\\n \")}\n\n`\n : \"\"\n}${colors.primary(\"Need help?\")}\n ${colors.muted(\"•\")} GitHub Issues: https://github.com/entro314-labs/at3-stack-kit/issues\n ${colors.muted(\"•\")} Discord: https://discord.gg/at3-stack\n `,\n \"Welcome to AT3!\"\n );\n } catch (error) {\n addSpinner.stop(\"Error occurred\");\n console.error(chalk.red(\"Error upgrading project:\"), error);\n process.exit(1);\n }\n}\n\nfunction getProjectTypeLabel(type: ProjectType): string {\n switch (type) {\n case \"nextjs\":\n return \"Next.js\";\n case \"t3\":\n return \"T3 Stack\";\n case \"react\":\n return \"React\";\n case \"unknown\":\n return \"Unknown\";\n default:\n return \"Unknown\";\n }\n}\n\nfunction getProjectInfo(type: ProjectType): string {\n const packageJsonPath = join(process.cwd(), \"package.json\");\n\n if (!existsSync(packageJsonPath)) {\n return \"No package.json found\";\n }\n\n const packageJson = JSON.parse(readFileSync(packageJsonPath, \"utf-8\"));\n const deps = Object.keys({ ...packageJson.dependencies, ...packageJson.devDependencies });\n\n let info = `Project: ${packageJson.name || \"unnamed\"}\\n`;\n info += `Type: ${getProjectTypeLabel(type)}\\n`;\n\n // Show key dependencies\n const keyDeps = [\"next\", \"react\", \"typescript\", \"tailwindcss\"];\n const foundDeps = keyDeps.filter((dep) => deps.some((d) => d.includes(dep)));\n\n if (foundDeps.length > 0) {\n info += `Dependencies: ${foundDeps.join(\", \")}`;\n }\n\n return info;\n}\n\nfunction getFeatureName(id: FeatureId): string {\n return features.find((f) => f.value === id)?.name || id;\n}\n\n// CLI setup\nprogram\n .name(\"at3-kit\")\n .description(\"Upgrade existing projects to AT3 Stack\")\n .version(\"0.1.0\")\n .option(\"-d, --dry-run\", \"Show what would be changed without making changes\")\n .option(\"--no-install\", \"Skip installing dependencies\")\n .action(async (options: { dryRun?: boolean; install?: boolean }) => {\n await main();\n });\n\n// Subcommands\nprogram\n .command(\"add <feature>\")\n .description(\"Add a specific feature to your project\")\n .option(\"--no-install\", \"Skip installing dependencies\")\n .action(async (feature: string, options: { install?: boolean }) => {\n const validFeatures = features.map((f) => f.value);\n\n if (!validFeatures.includes(feature as FeatureId)) {\n console.error(chalk.red(`Unknown feature: ${feature}`));\n console.log(chalk.dim(`Valid features: ${validFeatures.join(\", \")}`));\n process.exit(1);\n }\n\n // Add single feature without prompts\n console.log(chalk.blue(`Adding ${getFeatureName(feature as FeatureId)}...`));\n // TODO: Implement single feature addition\n });\n\nprogram\n .command(\"detect\")\n .description(\"Detect current project type and show available upgrades\")\n .action(async () => {\n const projectType = await detectProjectType(process.cwd());\n const packageManager = await detectPackageManager().catch(() => \"npm\");\n\n console.log(chalk.green(\"Project Analysis:\"));\n console.log(` Type: ${getProjectTypeLabel(projectType)}`);\n console.log(` Package Manager: ${packageManager}`);\n console.log(\"\\n\" + getProjectInfo(projectType));\n });\n\n// Parse command line arguments (run as CLI)\nprogram.parse();\n\nexport { program };\n","/**\n * Project detection utilities for AT3 Stack Kit\n * Aligned with at3-toolkit's sophisticated detection system\n */\n\nimport { detect as detectPackageManager } from \"detect-package-manager\";\nimport { existsSync, readFileSync } from \"fs-extra\";\nimport { join } from \"path\";\n\nexport type ProjectType =\n | \"ait3e\"\n | \"nextjs\"\n | \"t3\"\n | \"react\"\n | \"vue\"\n | \"nuxt\"\n | \"vite\"\n | \"node\"\n | \"webpack\"\n | \"unknown\";\n\nexport interface DependencyInfo {\n name: string;\n version: string;\n type: \"dependency\" | \"devDependency\" | \"peerDependency\";\n}\n\nexport interface ProjectInfo {\n path: string;\n type: ProjectType;\n hasNextjs: boolean;\n hasReact: boolean;\n hasVue: boolean;\n hasTypeScript: boolean;\n hasTailwind: boolean;\n hasTRPC: boolean;\n hasSupabase: boolean;\n hasAI: boolean;\n hasPWA: boolean;\n hasI18n: boolean;\n hasVitest: boolean;\n hasPlaywright: boolean;\n hasEslint: boolean;\n hasPrettier: boolean;\n hasBiome: boolean;\n hasEdgeRuntime: boolean;\n hasVectorDB: boolean;\n packageManager: \"npm\" | \"pnpm\" | \"yarn\" | \"bun\";\n dependencies: DependencyInfo[];\n configFiles: string[];\n}\n\n/**\n * Detect project type based on dependencies and file structure\n * Enhanced with comprehensive type detection from at3-toolkit\n */\nexport async function detectProjectType(projectPath: string): Promise<ProjectType> {\n const packageJsonPath = join(projectPath, \"package.json\");\n\n if (!existsSync(packageJsonPath)) {\n return \"unknown\";\n }\n\n try {\n const packageJson = JSON.parse(readFileSync(packageJsonPath, \"utf-8\"));\n const deps = { ...packageJson.dependencies, ...packageJson.devDependencies };\n\n // Check for AIT3E stack (AI + T3 + Edge)\n const hasAI =\n deps.ai || deps[\"@ai-sdk/openai\"] || deps[\"@ai-sdk/anthropic\"] || deps[\"@ai-sdk/google\"];\n const hasSupabase = deps[\"@supabase/supabase-js\"] || deps[\"@supabase/ssr\"];\n const hasNextJS = deps.next;\n const hasTailwind = deps.tailwindcss;\n const hasTypeScript = deps.typescript || existsSync(join(projectPath, \"tsconfig.json\"));\n\n if (hasAI && hasSupabase && hasNextJS && (hasTailwind || hasTypeScript)) {\n return \"ait3e\";\n }\n\n // Check for T3 stack\n if (deps[\"@t3-oss/create-t3-app\"] || (deps.next && deps[\"@trpc/server\"] && deps.prisma)) {\n return \"t3\";\n }\n\n // Check for Next.js\n if (deps.next) return \"nextjs\";\n\n // Check for Nuxt\n if (deps.nuxt || deps[\"@nuxt/core\"]) return \"nuxt\";\n\n // Check for Vue\n if (deps.vue) return \"vue\";\n\n // Check for React\n if (deps.react) return \"react\";\n\n // Check for Vite\n if (deps.vite) return \"vite\";\n\n // Check for Webpack\n if (deps.webpack) return \"webpack\";\n\n // Default to Node.js\n return \"node\";\n } catch (error) {\n return \"unknown\";\n }\n}\n\n/**\n * Get comprehensive project information\n * Enhanced with sophisticated dependency analysis from at3-toolkit\n */\nexport async function analyzeProject(projectPath: string): Promise<ProjectInfo> {\n if (!existsSync(projectPath)) {\n throw new Error(`Project path does not exist: ${projectPath}`);\n }\n\n const packageJsonPath = join(projectPath, \"package.json\");\n if (!existsSync(packageJsonPath)) {\n throw new Error(\"No package.json found. This does not appear to be a Node.js project.\");\n }\n\n const packageJson = JSON.parse(readFileSync(packageJsonPath, \"utf-8\"));\n\n // Use sophisticated package manager detection with fallback\n let packageManager: ProjectInfo[\"packageManager\"] = \"npm\";\n try {\n packageManager = (await detectPackageManager({ cwd: projectPath })) as any;\n } catch {\n // Fallback to file-based detection\n if (existsSync(join(projectPath, \"pnpm-lock.yaml\"))) packageManager = \"pnpm\";\n else if (existsSync(join(projectPath, \"yarn.lock\"))) packageManager = \"yarn\";\n else if (existsSync(join(projectPath, \"bun.lockb\"))) packageManager = \"bun\";\n }\n\n // Analyze dependencies with detailed structure\n const dependencies = analyzeDependencies(packageJson);\n const configFiles = findConfigFiles(projectPath);\n\n // Feature detection\n const hasTypeScript = hasTypeScriptSupport(projectPath, dependencies);\n const hasNextjs = hasDependency(dependencies, \"next\");\n const hasReact = hasDependency(dependencies, \"react\");\n const hasVue = hasDependency(dependencies, \"vue\");\n const hasTailwind = hasDependency(dependencies, \"tailwindcss\");\n const hasTRPC = dependencies.some((dep) => dep.name.includes(\"@trpc/\"));\n const hasEslint = hasDependency(dependencies, \"eslint\");\n const hasPrettier = hasDependency(dependencies, \"prettier\");\n const hasBiome = hasDependency(dependencies, \"@biomejs/biome\");\n\n // AT3-specific features\n const hasAI =\n hasDependency(dependencies, \"ai\") ||\n hasDependency(dependencies, \"@ai-sdk/openai\") ||\n hasDependency(dependencies, \"@ai-sdk/anthropic\") ||\n hasDependency(dependencies, \"@ai-sdk/google\");\n const hasSupabase =\n hasDependency(dependencies, \"@supabase/supabase-js\") ||\n hasDependency(dependencies, \"@supabase/ssr\");\n const hasEdgeRuntime =\n existsSync(join(projectPath, \"middleware.ts\")) ||\n existsSync(join(projectPath, \"src/middleware.ts\"));\n const hasVectorDB = hasSupabaseVectorConfig(projectPath);\n const hasPWA = dependencies.some(\n (dep) => dep.name.includes(\"workbox\") || dep.name.includes(\"pwa\")\n );\n const hasI18n = dependencies.some(\n (dep) => dep.name.includes(\"next-intl\") || dep.name.includes(\"i18n\")\n );\n const hasVitest = hasDependency(dependencies, \"vitest\");\n const hasPlaywright =\n hasDependency(dependencies, \"playwright\") || hasDependency(dependencies, \"@playwright/test\");\n\n return {\n path: projectPath,\n type: await detectProjectType(projectPath),\n hasNextjs,\n hasReact,\n hasVue,\n hasTypeScript,\n hasTailwind,\n hasTRPC,\n hasSupabase,\n hasAI,\n hasPWA,\n hasI18n,\n hasVitest,\n hasPlaywright,\n hasEslint,\n hasPrettier,\n hasBiome,\n hasEdgeRuntime,\n hasVectorDB,\n packageManager,\n dependencies,\n configFiles,\n };\n}\n\n/**\n * Analyze dependencies with detailed structure\n */\nfunction analyzeDependencies(packageJson: any): DependencyInfo[] {\n const deps: DependencyInfo[] = [];\n\n // Production dependencies\n if (packageJson.dependencies) {\n Object.entries(packageJson.dependencies).forEach(([name, version]) => {\n deps.push({\n name,\n version: version as string,\n type: \"dependency\",\n });\n });\n }\n\n // Development dependencies\n if (packageJson.devDependencies) {\n Object.entries(packageJson.devDependencies).forEach(([name, version]) => {\n deps.push({\n name,\n version: version as string,\n type: \"devDependency\",\n });\n });\n }\n\n // Peer dependencies\n if (packageJson.peerDependencies) {\n Object.entries(packageJson.peerDependencies).forEach(([name, version]) => {\n deps.push({\n name,\n version: version as string,\n type: \"peerDependency\",\n });\n });\n }\n\n return deps;\n}\n\n/**\n * Find configuration files in the project\n */\nfunction findConfigFiles(projectPath: string): string[] {\n const configFiles: string[] = [];\n\n const commonConfigFiles = [\n // TypeScript\n \"tsconfig.json\",\n \"tsconfig.build.json\",\n\n // Next.js\n \"next.config.js\",\n \"next.config.ts\",\n \"next.config.mjs\",\n\n // Tailwind\n \"tailwind.config.js\",\n \"tailwind.config.ts\",\n \"tailwind.config.mjs\",\n \"postcss.config.js\",\n \"postcss.config.mjs\",\n\n // Linting\n \".eslintrc.js\",\n \".eslintrc.json\",\n \".eslintrc.yml\",\n \".eslintrc.yaml\",\n \"eslint.config.js\",\n \"eslint.config.mjs\",\n \".prettierrc\",\n \".prettierrc.js\",\n \".prettierrc.json\",\n \"biome.json\",\n\n // Testing\n \"vitest.config.ts\",\n \"vitest.config.js\",\n \"jest.config.js\",\n \"jest.config.ts\",\n \"playwright.config.ts\",\n\n // Build tools\n \"vite.config.ts\",\n \"vite.config.js\",\n \"webpack.config.js\",\n \"rollup.config.js\",\n\n // Other\n \".gitignore\",\n \".env.example\",\n \".env.local\",\n \"README.md\",\n ];\n\n commonConfigFiles.forEach((file) => {\n if (existsSync(join(projectPath, file))) {\n configFiles.push(file);\n }\n });\n\n return configFiles;\n}\n\n/**\n * Check if TypeScript is supported\n */\nfunction hasTypeScriptSupport(projectPath: string, dependencies: DependencyInfo[]): boolean {\n return (\n existsSync(join(projectPath, \"tsconfig.json\")) || hasDependency(dependencies, \"typescript\")\n );\n}\n\n/**\n * Check if a dependency exists\n */\nfunction hasDependency(dependencies: DependencyInfo[], name: string): boolean {\n return dependencies.some((dep) => dep.name === name);\n}\n\n/**\n * Check for Supabase vector configuration\n */\nfunction hasSupabaseVectorConfig(projectPath: string): boolean {\n // Check for Supabase migration files that might contain vector extensions\n const supabaseMigrationDir = join(projectPath, \"supabase\", \"migrations\");\n if (existsSync(supabaseMigrationDir)) {\n try {\n const { readdirSync } = require(\"fs\");\n const migrationFiles = readdirSync(supabaseMigrationDir);\n\n return migrationFiles.some((file: string) => {\n if (file.endsWith(\".sql\")) {\n const content = readFileSync(join(supabaseMigrationDir, file), \"utf8\");\n return content.includes(\"vector\") || content.includes(\"embedding\");\n }\n return false;\n });\n } catch (error) {\n return false;\n }\n }\n return false;\n}\n\n/**\n * Check what AT3 features are missing from the project\n */\nexport function getMissingFeatures(info: ProjectInfo): string[] {\n const missing: string[] = [];\n\n if (!info.hasSupabase) missing.push(\"supabase\");\n if (!info.hasAI) missing.push(\"ai\");\n if (!info.hasPWA) missing.push(\"pwa\");\n if (!info.hasI18n) missing.push(\"i18n\");\n if (!info.hasVitest) missing.push(\"testing\");\n if (!info.hasTailwind) missing.push(\"tailwind\");\n if (!info.hasTypeScript) missing.push(\"typescript\");\n\n return missing;\n}\n\n/**\n * Check if project is compatible with AT3 stack\n */\nexport function isCompatible(info: ProjectInfo): boolean {\n // Must have Next.js or React\n if (!info.hasNextjs && !info.hasReact) return false;\n\n // Must have a supported package manager\n if (![\"npm\", \"pnpm\", \"yarn\", \"bun\"].includes(info.packageManager)) return false;\n\n return true;\n}\n\n/**\n * Get upgrade recommendations based on current project state\n */\nexport function getRecommendations(info: ProjectInfo): {\n priority: \"high\" | \"medium\" | \"low\";\n feature: string;\n reason: string;\n}[] {\n const recommendations = [];\n\n if (!info.hasTypeScript) {\n recommendations.push({\n priority: \"high\" as const,\n feature: \"typescript\",\n reason: \"TypeScript provides better development experience and type safety\",\n });\n }\n\n if (!info.hasTailwind) {\n recommendations.push({\n priority: \"high\" as const,\n feature: \"tailwind\",\n reason: \"Tailwind CSS is essential for AT3 stack styling\",\n });\n }\n\n if (!info.hasSupabase) {\n recommendations.push({\n priority: \"medium\" as const,\n feature: \"supabase\",\n reason: \"Supabase provides database, auth, and edge functions\",\n });\n }\n\n if (!info.hasAI) {\n recommendations.push({\n priority: \"medium\" as const,\n feature: \"ai\",\n reason: \"AI integration is a core feature of AT3 stack\",\n });\n }\n\n if (!info.hasVitest && !info.hasPlaywright) {\n recommendations.push({\n priority: \"low\" as const,\n feature: \"testing\",\n reason: \"Comprehensive testing improves code quality\",\n });\n }\n\n return recommendations;\n}\n","/**\n * Add AI integration to existing project\n */\n\nimport { join } from \"node:path\";\nimport { ensureDir, pathExists, readFile, writeFile } from \"fs-extra\";\n\nexport async function addAI(type: \"custom\" | \"vercel\", projectPath: string): Promise<void> {\n const srcPath = join(projectPath, \"src\");\n await ensureDir(srcPath);\n\n // Create lib/ai directory\n const aiPath = join(srcPath, \"lib\", \"ai\");\n await ensureDir(aiPath);\n\n if (type === \"custom\") {\n await addCustomAI(aiPath);\n }\n\n if (type === \"vercel\") {\n await addVercelAI(aiPath);\n }\n\n // Create API routes\n const apiPath = join(srcPath, \"app\", \"api\");\n await ensureDir(apiPath);\n\n await addAPIRoutes(apiPath, type);\n\n // Update package.json\n await updatePackageJson(projectPath, type);\n}\n\nasync function addCustomAI(aiPath: string): Promise<void> {\n // AI client configuration\n const clientConfig = `/**\n * Custom AI client configuration\n */\n\nexport interface AIProvider {\n name: string;\n baseURL: string;\n apiKey: string;\n}\n\nexport const AI_PROVIDERS = {\n openai: {\n name: 'OpenAI',\n baseURL: 'https://api.openai.com/v1',\n apiKey: process.env.OPENAI_API_KEY!,\n },\n anthropic: {\n name: 'Anthropic',\n baseURL: 'https://api.anthropic.com',\n apiKey: process.env.ANTHROPIC_API_KEY!,\n },\n google: {\n name: 'Google AI',\n baseURL: 'https://generativelanguage.googleapis.com',\n apiKey: process.env.GOOGLE_AI_API_KEY!,\n },\n} as const;\n\nexport type AIProviderKey = keyof typeof AI_PROVIDERS;\n`;\n\n await writeFile(join(aiPath, \"config.ts\"), clientConfig);\n\n // AI client\n const client = `/**\n * Custom AI client implementation\n */\n\nimport { AI_PROVIDERS, type AIProviderKey } from './config.js';\n\nexport interface ChatMessage {\n role: 'system' | 'user' | 'assistant';\n content: string;\n}\n\nexport interface CompletionOptions {\n model: string;\n temperature?: number;\n maxTokens?: number;\n}\n\nexport class AIClient {\n constructor(\n private provider: AIProviderKey,\n private options: CompletionOptions = {}\n ) {}\n\n async completion(\n messages: ChatMessage[],\n options: Partial<CompletionOptions> = {}\n ): Promise<string> {\n const config = AI_PROVIDERS[this.provider];\n const finalOptions = { ...this.options, ...options };\n\n // Implementation would depend on the provider\n // This is a basic structure\n const response = await fetch(\\`\\${config.baseURL}/chat/completions\\`, {\n method: 'POST',\n headers: {\n 'Authorization': \\`Bearer \\${config.apiKey}\\`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n model: finalOptions.model || 'gpt-3.5-turbo',\n messages,\n temperature: finalOptions.temperature || 0.7,\n max_tokens: finalOptions.maxTokens || 1000,\n }),\n });\n\n const data = await response.json();\n return data.choices[0]?.message?.content || '';\n }\n}\n`;\n\n await writeFile(join(aiPath, \"client.ts\"), client);\n}\n\nasync function addVercelAI(aiPath: string): Promise<void> {\n // Vercel AI client\n const vercelClient = `/**\n * Vercel AI SDK integration\n */\n\nimport { anthropic } from '@ai-sdk/anthropic';\nimport { google } from '@ai-sdk/google'; \nimport { openai } from '@ai-sdk/openai';\nimport { generateText, streamText } from 'ai';\n\nexport const AI_MODELS = {\n 'gpt-4-turbo': openai('gpt-4-turbo'),\n 'gpt-3.5-turbo': openai('gpt-3.5-turbo'),\n 'claude-3-haiku': anthropic('claude-3-haiku-20240307'),\n 'claude-3-sonnet': anthropic('claude-3-sonnet-20240229'),\n 'gemini-pro': google('models/gemini-pro'),\n} as const;\n\nexport type AIModelKey = keyof typeof AI_MODELS;\n\nexport async function generateCompletion(\n model: AIModelKey,\n prompt: string,\n options?: {\n temperature?: number;\n maxTokens?: number;\n }\n) {\n const { text } = await generateText({\n model: AI_MODELS[model],\n prompt,\n temperature: options?.temperature || 0.7,\n maxTokens: options?.maxTokens || 1000,\n });\n\n return text;\n}\n\nexport async function streamCompletion(\n model: AIModelKey,\n prompt: string,\n options?: {\n temperature?: number;\n maxTokens?: number;\n }\n) {\n const { textStream } = await streamText({\n model: AI_MODELS[model],\n prompt,\n temperature: options?.temperature || 0.7,\n maxTokens: options?.maxTokens || 1000,\n });\n\n return textStream;\n}\n`;\n\n await writeFile(join(aiPath, \"vercel-client.ts\"), vercelClient);\n\n // Vercel AI hooks\n const hooks = `/**\n * React hooks for Vercel AI SDK\n */\n\n'use client';\n\nimport { useChat, useCompletion } from 'ai/react';\nimport { type AIModelKey } from './vercel-client.js';\n\nexport function useAIChat(model: AIModelKey = 'gpt-3.5-turbo') {\n return useChat({\n api: '/api/chat',\n body: {\n model,\n },\n });\n}\n\nexport function useAICompletion(model: AIModelKey = 'gpt-3.5-turbo') {\n return useCompletion({\n api: '/api/completion',\n body: {\n model,\n },\n });\n}\n`;\n\n await writeFile(join(aiPath, \"vercel-hooks.ts\"), hooks);\n}\n\nasync function addAPIRoutes(apiPath: string, type: \"custom\" | \"vercel\"): Promise<void> {\n if (type === \"vercel\") {\n // Chat API route\n const chatRoute = `import { AI_MODELS, type AIModelKey } from '@/lib/ai/vercel-client';\nimport { streamText } from 'ai';\n\nexport async function POST(req: Request) {\n const { messages, model = 'gpt-3.5-turbo' } = await req.json();\n\n const result = await streamText({\n model: AI_MODELS[model as AIModelKey],\n messages,\n });\n\n return result.toDataStreamResponse();\n}\n`;\n\n await ensureDir(join(apiPath, \"chat\"));\n await writeFile(join(apiPath, \"chat\", \"route.ts\"), chatRoute);\n\n // Completion API route\n const completionRoute = `import { AI_MODELS, type AIModelKey } from '@/lib/ai/vercel-client';\nimport { generateText } from 'ai';\n\nexport async function POST(req: Request) {\n const { prompt, model = 'gpt-3.5-turbo' } = await req.json();\n\n const { text } = await generateText({\n model: AI_MODELS[model as AIModelKey],\n prompt,\n });\n\n return Response.json({ text });\n}\n`;\n\n await ensureDir(join(apiPath, \"completion\"));\n await writeFile(join(apiPath, \"completion\", \"route.ts\"), completionRoute);\n }\n}\n\nasync function updatePackageJson(projectPath: string, type: \"custom\" | \"vercel\"): Promise<void> {\n const packageJsonPath = join(projectPath, \"package.json\");\n\n if (!(await pathExists(packageJsonPath))) return;\n\n const packageJson = JSON.parse(await readFile(packageJsonPath, \"utf-8\"));\n\n if (!packageJson.dependencies) packageJson.dependencies = {};\n\n if (type === \"vercel\") {\n packageJson.dependencies.ai = \"^5.0.8\";\n packageJson.dependencies[\"@ai-sdk/openai\"] = \"^2.0.7\";\n packageJson.dependencies[\"@ai-sdk/anthropic\"] = \"^2.0.1\";\n packageJson.dependencies[\"@ai-sdk/google\"] = \"^2.0.3\";\n }\n\n await writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2));\n}\n","/**\n * Add internationalization support to existing project\n */\n\nexport function addI18n(_projectPath: string): void {\n console.log(\"✓ i18n support would be added here\");\n // TODO: Implement i18n setup with next-intl\n}\n","/**\n * Add PWA support to existing project\n */\n\nimport { join } from \"node:path\";\nimport { ensureDir, writeFile } from \"fs-extra\";\n\nexport async function addPWA(projectPath: string): Promise<void> {\n // Add manifest.json\n await addManifest(projectPath);\n\n // Add service worker\n await addServiceWorker(projectPath);\n\n // Update package.json\n await updatePackageJson(projectPath);\n\n console.log(\"✓ PWA support added\");\n}\n\nasync function addManifest(projectPath: string): Promise<void> {\n const publicPath = join(projectPath, \"public\");\n await ensureDir(publicPath);\n\n const manifest = {\n name: \"AT3 App\",\n short_name: \"AT3\",\n description: \"AT3 Stack Application\",\n start_url: \"/\",\n display: \"standalone\",\n background_color: \"#ffffff\",\n theme_color: \"#000000\",\n icons: [\n {\n src: \"/icons/icon-192x192.png\",\n sizes: \"192x192\",\n type: \"image/png\",\n },\n {\n src: \"/icons/icon-512x512.png\",\n sizes: \"512x512\",\n type: \"image/png\",\n },\n ],\n };\n\n await writeFile(join(publicPath, \"manifest.json\"), JSON.stringify(manifest, null, 2));\n}\n\nasync function addServiceWorker(projectPath: string): Promise<void> {\n const publicPath = join(projectPath, \"public\");\n\n const sw = `// Basic service worker for PWA\nself.addEventListener('install', (event) => {\n console.log('Service worker installing...');\n self.skipWaiting();\n});\n\nself.addEventListener('activate', (event) => {\n console.log('Service worker activating...');\n event.waitUntil(self.clients.claim());\n});\n\nself.addEventListener('fetch', (event) => {\n // Add caching logic here\n});\n`;\n\n await writeFile(join(publicPath, \"sw.js\"), sw);\n}\n\nfunction updatePackageJson(_projectPath: string): void {\n // Add PWA-related dependencies if needed\n console.log(\"PWA package.json updates would go here\");\n}\n","/**\n * Add Supabase integration to existing project\n */\n\nimport { ensureDir, pathExists, readFile, writeFile } from \"fs-extra\";\nimport { join } from \"path\";\n\nexport async function addSupabase(projectPath: string): Promise<void> {\n const srcPath = join(projectPath, \"src\");\n await ensureDir(srcPath);\n\n // Create lib/supabase directory\n const supabasePath = join(srcPath, \"lib\", \"supabase\");\n await ensureDir(supabasePath);\n\n // Add Supabase clients\n await addSupabaseClients(supabasePath);\n\n // Add auth helpers\n await addAuthHelpers(join(srcPath, \"lib\", \"auth\"));\n\n // Update package.json\n await updatePackageJson(projectPath);\n\n // Add environment variables template\n await addEnvExample(projectPath);\n\n // Initialize Supabase config\n await initSupabaseConfig(projectPath);\n}\n\nasync function addSupabaseClients(supabasePath: string): Promise<void> {\n // Client-side Supabase client\n const clientCode = `import { createBrowserClient } from '@supabase/ssr';\n\nexport function createClient() {\n return createBrowserClient(\n process.env.NEXT_PUBLIC_SUPABASE_URL!,\n process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!\n );\n}\n`;\n\n await writeFile(join(supabasePath, \"client.ts\"), clientCode);\n\n // Server-side Supabase client\n const serverCode = `import { createServerClient } from '@supabase/ssr';\nimport { cookies } from 'next/headers';\n\nexport async function createServerClient() {\n const cookieStore = await cookies();\n\n return createServerClient(\n process.env.NEXT_PUBLIC_SUPABASE_URL!,\n process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,\n {\n cookies: {\n getAll() {\n return cookieStore.getAll();\n },\n setAll(cookiesToSet) {\n try {\n cookiesToSet.forEach(({ name, value, options }) =>\n cookieStore.set(name, value, options)\n );\n } catch {\n // The 'setAll' method was called from a Server Component.\n // This can be ignored if you have middleware refreshing\n // user sessions.\n }\n },\n },\n }\n );\n}\n`;\n\n await writeFile(join(supabasePath, \"server.ts\"), serverCode);\n\n // Middleware helper\n const middlewareCode = `import { createServerClient } from '@supabase/ssr';\nimport { NextResponse, type NextRequest } from 'next/server';\n\nexport async function updateSession(request: NextRequest) {\n let supabaseResponse = NextResponse.next({\n request,\n });\n\n const supabase = createServerClient(\n process.env.NEXT_PUBLIC_SUPABASE_URL!,\n process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,\n {\n cookies: {\n getAll() {\n return request.cookies.getAll();\n },\n setAll(cookiesToSet) {\n cookiesToSet.forEach(({ name, value }) => request.cookies.set(name, value));\n supabaseResponse = NextResponse.next({\n request,\n });\n cookiesToSet.forEach(({ name, value, options }) =>\n supabaseResponse.cookies.set(name, value, options)\n );\n },\n },\n }\n );\n\n // This will refresh session if expired - required for Server Components\n await supabase.auth.getUser();\n\n return supabaseResponse;\n}\n`;\n\n await writeFile(join(supabasePath, \"middleware.ts\"), middlewareCode);\n}\n\nasync function addAuthHelpers(authPath: string): Promise<void> {\n await ensureDir(authPath);\n\n const authHelpersCode = `import { createServerClient } from '@/lib/supabase/server';\nimport { redirect } from 'next/navigation';\n\nexport async function requireAuth() {\n const supabase = await createServerClient();\n const { data: { user }, error } = await supabase.auth.getUser();\n\n if (error || !user) {\n redirect('/auth/sign-in');\n }\n\n return user;\n}\n\nexport async function getUser() {\n const supabase = await createServerClient();\n const { data: { user } } = await supabase.auth.getUser();\n return user;\n}\n\nexport async function signOut() {\n const supabase = await createServerClient();\n await supabase.auth.signOut();\n redirect('/');\n}\n`;\n\n await writeFile(join(authPath, \"auth-helpers.ts\"), authHelpersCode);\n}\n\nasync function updatePackageJson(projectPath: string): Promise<void> {\n const packageJsonPath = join(projectPath, \"package.json\");\n\n if (!(await pathExists(packageJsonPath))) return;\n\n const packageJson = JSON.parse(await readFile(packageJsonPath, \"utf-8\"));\n\n if (!packageJson.dependencies) packageJson.dependencies = {};\n if (!packageJson.devDependencies) packageJson.devDependencies = {};\n\n // Add Supabase dependencies\n packageJson.dependencies[\"@supabase/supabase-js\"] = \"^2.54.0\";\n packageJson.dependencies[\"@supabase/ssr\"] = \"^0.7.0-rc.2\";\n\n // Add Supabase CLI as dev dependency\n packageJson.devDependencies[\"supabase\"] = \"^2.33.9\";\n\n await writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2));\n}\n\nasync function addEnvExample(projectPath: string): Promise<void> {\n const envExamplePath = join(projectPath, \".env.example\");\n\n let envContent = \"\";\n\n // Read existing .env.example if it exists\n if (await pathExists(envExamplePath)) {\n envContent = await readFile(envExamplePath, \"utf-8\");\n }\n\n // Add Supabase variables if not present\n if (!envContent.includes(\"NEXT_PUBLIC_SUPABASE_URL\")) {\n const supabaseVars = `\n# Supabase\nNEXT_PUBLIC_SUPABASE_URL=your_supabase_url\nNEXT_PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key\nSUPABASE_SERVICE_ROLE_KEY=your_service_role_key\n`;\n\n envContent = envContent + supabaseVars;\n await writeFile(envExamplePath, envContent);\n }\n}\n\nasync function initSupabaseConfig(projectPath: string): Promise<void> {\n const supabaseConfigPath = join(projectPath, \"supabase\", \"config.toml\");\n\n if (await pathExists(supabaseConfigPath)) return; // Already exists\n\n await ensureDir(join(projectPath, \"supabase\"));\n\n const config = `# A string used to distinguish different Supabase projects on the same host.\nproject_id = \"your-project-id\"\n\n[api]\nenabled = true\nport = 54321\nschemas = [\"public\", \"graphql_public\"]\nextra_search_path = [\"public\", \"extensions\"]\nmax_rows = 1000\n\n[auth]\nenabled = true\nport = 9999\nsite_url = \"http://localhost:3000\"\nadditional_redirect_urls = [\"https://localhost:3000\"]\njwt_expiry = 3600\nrefresh_token_rotation_enabled = true\nsecurity_update_password_require_reauthentication = true\n\n[auth.email]\nenable_signup = true\ndouble_confirm_changes = true\nenable_confirmations = false\n`;\n\n await writeFile(supabaseConfigPath, config);\n}\n","/**\n * Add testing suite to existing project\n */\n\nexport function addTesting(_projectPath: string): void {\n console.log(\"✓ Testing suite would be added here\");\n // TODO: Implement Vitest + Playwright setup\n}\n","/**\n * CLI styling utilities for AT3 Stack Kit\n * Aligned with at3-toolkit's sophisticated styling system\n */\n\nimport boxen from \"boxen\";\nimport chalk from \"chalk\";\nimport figures from \"figures\";\nimport gradient from \"gradient-string\";\n\n// Color palette\nexport const colors = {\n primary: chalk.hex(\"#2563eb\"), // Blue\n secondary: chalk.hex(\"#7c3aed\"), // Purple\n success: chalk.green,\n error: chalk.red,\n warning: chalk.yellow,\n info: chalk.blue,\n muted: chalk.gray,\n accent: chalk.magenta,\n ai: chalk.hex(\"#10b981\"), // Emerald for AI features\n} as const;\n\n// Gradients\nexport const gradients = {\n at3: gradient(\"#2563eb\", \"#10b981\"), // Blue to Emerald\n ai: gradient(\"#10b981\", \"#059669\"), // Emerald gradient\n success: gradient(\"#22c55e\", \"#16a34a\"), // Green gradient\n warning: gradient(\"#f59e0b\", \"#d97706\"), // Amber gradient\n error: gradient(\"#ef4444\", \"#dc2626\"), // Red gradient\n} as const;\n\n// Icons and symbols\nexport const symbols = {\n success: colors.success(figures.tick),\n error: colors.error(figures.cross),\n warning: colors.warning(figures.warning),\n info: colors.info(figures.info),\n arrow: colors.muted(figures.arrowRight),\n bullet: colors.muted(figures.bullet),\n line: colors.muted(figures.line),\n ai: colors.ai(\"🤖\"),\n stack: colors.primary(\"📚\"),\n edge: colors.secondary(\"⚡\"),\n database: colors.info(\"🗄️\"),\n config: colors.muted(\"⚙️\"),\n} as const;\n\n// Text styling utilities\nexport const style = {\n title: (text: string) => gradients.at3(text),\n subtitle: (text: string) => colors.secondary(text),\n heading: (text: string) => colors.primary.bold(text),\n label: (text: string) => colors.muted(text),\n value: (text: string) => colors.primary(text),\n success: (text: string) => colors.success(text),\n error: (text: string) => colors.error(text),\n warning: (text: string) => colors.warning(text),\n info: (text: string) => colors.info(text),\n muted: (text: string) => colors.muted(text),\n accent: (text: string) => colors.accent(text),\n ai: (text: string) => colors.ai(text),\n code: (text: string) => chalk.cyan.italic(text),\n path: (text: string) => chalk.dim.underline(text),\n command: (text: string) => chalk.bgBlack.white.bold(` ${text} `),\n} as const;\n\n// Box utilities\nexport const box = {\n info: (content: string, title?: string) =>\n boxen(content, {\n ...(title && { title }),\n titleAlignment: \"center\",\n padding: 1,\n margin: 1,\n borderStyle: \"round\",\n borderColor: \"blue\",\n }),\n success: (content: string, title?: string) =>\n boxen(content, {\n ...(title && { title }),\n titleAlignment: \"center\",\n padding: 1,\n margin: 1,\n borderStyle: \"round\",\n borderColor: \"green\",\n }),\n warning: (content: string, title?: string) =>\n boxen(content, {\n ...(title && { title }),\n titleAlignment: \"center\",\n padding: 1,\n margin: 1,\n borderStyle: \"round\",\n borderColor: \"yellow\",\n }),\n error: (content: string, title?: string) =>\n boxen(content, {\n ...(title && { title }),\n titleAlignment: \"center\",\n padding: 1,\n margin: 1,\n borderStyle: \"round\",\n borderColor: \"red\",\n }),\n} as const;\n\n// Progress indicators\nexport const progress = {\n step: (current: number, total: number, description: string) =>\n `${colors.muted(`[${current}/${total}]`)} ${description}`,\n\n percentage: (percent: number) => {\n const filled = Math.floor(percent / 5);\n const empty = 20 - filled;\n const bar = \"█\".repeat(filled) + \"░\".repeat(empty);\n return `${colors.primary(bar)} ${colors.muted(`${percent}%`)}`;\n },\n};\n\n// Header utilities\nexport const header = {\n main: (title: string, subtitle?: string) => {\n const titleText = gradients.at3.multiline(title);\n const subtitleText = subtitle ? `\\n${colors.muted(subtitle)}` : \"\";\n return `${titleText}${subtitleText}`;\n },\n\n section: (title: string) =>\n `\\n${colors.primary.bold(title)}\\n${colors.muted(\"─\".repeat(title.length))}`,\n};\n\n// List utilities\nexport const list = {\n item: (text: string, symbol = symbols.bullet) => `${symbol} ${text}`,\n checkItem: (text: string, checked = false) => {\n const icon = checked ? symbols.success : colors.muted(figures.radioOff);\n return `${icon} ${text}`;\n },\n numbered: (items: string[]) =>\n items.map((item, i) => `${colors.muted(`${i + 1}.`)} ${item}`).join(\"\\n\"),\n};\n","/**\n * Integration utilities for at3-stack-kit\n * Enables smart detection and suggestions for other AT3 tools\n */\n\nimport { existsSync } from \"fs-extra\";\nimport { join } from \"path\";\nimport type { ProjectInfo } from \"../detect.js\";\nimport { colors, style } from \"./cli-styling.js\";\n\nexport interface AT3Config {\n version: string;\n created: string;\n template?: string;\n features: string[];\n toolsUsed: string[];\n suggestedWorkflows?: string[];\n lastMigration?: string;\n}\n\n/**\n * Update AT3 configuration after migration\n */\nexport function updateAT3Config(projectPath: string, addedFeatures: string[]): AT3Config {\n const configPath = join(projectPath, \".at3-config.json\");\n let config: AT3Config;\n\n if (existsSync(configPath)) {\n try {\n config = JSON.parse(require(\"fs\").readFileSync(configPath, \"utf8\"));\n } catch {\n config = createDefaultConfig();\n }\n } else {\n config = createDefaultConfig();\n }\n\n // Update config\n config.features = [...new Set([...config.features, ...addedFeatures])];\n config.toolsUsed = [...new Set([...config.toolsUsed, \"at3-stack-kit\"])];\n config.lastMigration = new Date().toISOString();\n\n // Write config file (optional for integration)\n try {\n require(\"fs\").writeFileSync(configPath, JSON.stringify(config, null, 2));\n } catch {\n // Silently fail - integration is optional\n }\n\n return config;\n}\n\nfunction createDefaultConfig(): AT3Config {\n return {\n version: \"0.1.0\",\n created: new Date().toISOString(),\n features: [],\n toolsUsed: [\"at3-stack-kit\"],\n };\n}\n\n/**\n * Detect if project was created with create-at3-app\n */\nexport function detectCreateAt3App(projectPath: string): boolean {\n const configPath = join(projectPath, \".at3-config.json\");\n\n if (!existsSync(configPath)) {\n return false;\n }\n\n try {\n const config = JSON.parse(require(\"fs\").readFileSync(configPath, \"utf8\"));\n return config.toolsUsed?.includes(\"create-at3-app\") || false;\n } catch {\n return false;\n }\n}\n\n/**\n * Suggest complementary AT3 tools based on project state\n */\nexport function suggestAT3Tools(projectInfo: ProjectInfo, addedFeatures: string[]): string[] {\n const suggestions: string[] = [];\n\n // Suggest at3-toolkit for development workflow optimization\n if (!projectInfo.hasEslint || !projectInfo.hasPrettier || !projectInfo.hasVitest) {\n suggestions.push(\n `${colors.info(\"💡 Tip:\")} Use ${style.command(\"@entro314-labs/at3t\")} for advanced linting, testing, and development workflow optimization`\n );\n }\n\n // Suggest create-at3-app for future projects\n if (addedFeatures.length > 0) {\n suggestions.push(\n `${colors.info(\"💡 Tip:\")} For new projects, use ${style.command(\"create-at3-app\")} to start with the AT3 stack from the beginning`\n );\n }\n\n return suggestions;\n}\n\n/**\n * Get post-migration workflow suggestions\n */\nexport function getPostMigrationWorkflow(\n projectInfo: ProjectInfo,\n addedFeatures: string[]\n): string[] {\n const workflows: string[] = [];\n\n if (addedFeatures.includes(\"ai\")) {\n workflows.push(\"Configure your AI provider API keys in .env.local\");\n workflows.push(\"Explore the AI integration examples in your project\");\n }\n\n if (addedFeatures.includes(\"supabase\")) {\n workflows.push(\"Set up your Supabase project and update connection strings\");\n workflows.push(\"Run database migrations if any were added\");\n }\n\n if (addedFeatures.includes(\"testing\")) {\n workflows.push(\n `Run ${style.command(projectInfo.packageManager + \" test\")} to verify your test setup`\n );\n }\n\n if (projectInfo.type === \"ait3e\") {\n workflows.push(\"Your project now includes the complete AT3 stack!\");\n workflows.push(\"Consider using at3t for advanced development workflow optimization\");\n }\n\n return workflows;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACOA,qBAUO;AACP,IAAAA,gBAAkB;AAClB,uBAAwB;AACxB,IAAAC,iCAA+C;AAC/C,IAAAC,mBAAyC;AACzC,IAAAC,eAAqB;;;ACjBrB,oCAA+C;AAC/C,sBAAyC;AACzC,kBAAqB;AAiDrB,eAAsB,kBAAkB,aAA2C;AACjF,QAAM,sBAAkB,kBAAK,aAAa,cAAc;AAExD,MAAI,KAAC,4BAAW,eAAe,GAAG;AAChC,WAAO;AAAA,EACT;AAEA,MAAI;AACF,UAAM,cAAc,KAAK,UAAM,8BAAa,iBAAiB,OAAO,CAAC;AACrE,UAAM,OAAO,EAAE,GAAG,YAAY,cAAc,GAAG,YAAY,gBAAgB;AAG3E,UAAM,QACJ,KAAK,MAAM,KAAK,gBAAgB,KAAK,KAAK,mBAAmB,KAAK,KAAK,gBAAgB;AACzF,UAAM,cAAc,KAAK,uBAAuB,KAAK,KAAK,eAAe;AACzE,UAAM,YAAY,KAAK;AACvB,UAAM,cAAc,KAAK;AACzB,UAAM,gBAAgB,KAAK,kBAAc,gCAAW,kBAAK,aAAa,eAAe,CAAC;AAEtF,QAAI,SAAS,eAAe,cAAc,eAAe,gBAAgB;AACvE,aAAO;AAAA,IACT;AAGA,QAAI,KAAK,uBAAuB,KAAM,KAAK,QAAQ,KAAK,cAAc,KAAK,KAAK,QAAS;AACvF,aAAO;AAAA,IACT;AAGA,QAAI,KAAK,KAAM,QAAO;AAGtB,QAAI,KAAK,QAAQ,KAAK,YAAY,EAAG,QAAO;AAG5C,QAAI,KAAK,IAAK,QAAO;AAGrB,QAAI,KAAK,MAAO,QAAO;AAGvB,QAAI,KAAK,KAAM,QAAO;AAGtB,QAAI,KAAK,QAAS,QAAO;AAGzB,WAAO;AAAA,EACT,SAAS,OAAO;AACd,WAAO;AAAA,EACT;AACF;AAMA,eAAsB,eAAe,aAA2C;AAC9E,MAAI,KAAC,4BAAW,WAAW,GAAG;AAC5B,UAAM,IAAI,MAAM,gCAAgC,WAAW,EAAE;AAAA,EAC/D;AAEA,QAAM,sBAAkB,kBAAK,aAAa,cAAc;AACxD,MAAI,KAAC,4BAAW,eAAe,GAAG;AAChC,UAAM,IAAI,MAAM,sEAAsE;AAAA,EACxF;AAEA,QAAM,cAAc,KAAK,UAAM,8BAAa,iBAAiB,OAAO,CAAC;AAGrE,MAAI,iBAAgD;AACpD,MAAI;AACF,qBAAkB,UAAM,8BAAAC,QAAqB,EAAE,KAAK,YAAY,CAAC;AAAA,EACnE,QAAQ;AAEN,YAAI,gCAAW,kBAAK,aAAa,gBAAgB,CAAC,EAAG,kBAAiB;AAAA,iBAC7D,gCAAW,kBAAK,aAAa,WAAW,CAAC,EAAG,kBAAiB;AAAA,iBAC7D,gCAAW,kBAAK,aAAa,WAAW,CAAC,EAAG,kBAAiB;AAAA,EACxE;AAGA,QAAM,eAAe,oBAAoB,WAAW;AACpD,QAAM,cAAc,gBAAgB,WAAW;AAG/C,QAAM,gBAAgB,qBAAqB,aAAa,YAAY;AACpE,QAAM,YAAY,cAAc,cAAc,MAAM;AACpD,QAAM,WAAW,cAAc,cAAc,OAAO;AACpD,QAAM,SAAS,cAAc,cAAc,KAAK;AAChD,QAAM,cAAc,cAAc,cAAc,aAAa;AAC7D,QAAM,UAAU,aAAa,KAAK,CAAC,QAAQ,IAAI,KAAK,SAAS,QAAQ,CAAC;AACtE,QAAM,YAAY,cAAc,cAAc,QAAQ;AACtD,QAAM,cAAc,cAAc,cAAc,UAAU;AAC1D,QAAM,WAAW,cAAc,cAAc,gBAAgB;AAG7D,QAAM,QACJ,cAAc,cAAc,IAAI,KAChC,cAAc,cAAc,gBAAgB,KAC5C,cAAc,cAAc,mBAAmB,KAC/C,cAAc,cAAc,gBAAgB;AAC9C,QAAM,cACJ,cAAc,cAAc,uBAAuB,KACnD,cAAc,cAAc,eAAe;AAC7C,QAAM,qBACJ,gCAAW,kBAAK,aAAa,eAAe,CAAC,SAC7C,gCAAW,kBAAK,aAAa,mBAAmB,CAAC;AACnD,QAAM,cAAc,wBAAwB,WAAW;AACvD,QAAM,SAAS,aAAa;AAAA,IAC1B,CAAC,QAAQ,IAAI,KAAK,SAAS,SAAS,KAAK,IAAI,KAAK,SAAS,KAAK;AAAA,EAClE;AACA,QAAM,UAAU,aAAa;AAAA,IAC3B,CAAC,QAAQ,IAAI,KAAK,SAAS,WAAW,KAAK,IAAI,KAAK,SAAS,MAAM;AAAA,EACrE;AACA,QAAM,YAAY,cAAc,cAAc,QAAQ;AACtD,QAAM,gBACJ,cAAc,cAAc,YAAY,KAAK,cAAc,cAAc,kBAAkB;AAE7F,SAAO;AAAA,IACL,MAAM;AAAA,IACN,MAAM,MAAM,kBAAkB,WAAW;AAAA,IACzC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAKA,SAAS,oBAAoB,aAAoC;AAC/D,QAAM,OAAyB,CAAC;AAGhC,MAAI,YAAY,cAAc;AAC5B,WAAO,QAAQ,YAAY,YAAY,EAAE,QAAQ,CAAC,CAAC,MAAM,OAAO,MAAM;AACpE,WAAK,KAAK;AAAA,QACR;AAAA,QACA;AAAA,QACA,MAAM;AAAA,MACR,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AAGA,MAAI,YAAY,iBAAiB;AAC/B,WAAO,QAAQ,YAAY,eAAe,EAAE,QAAQ,CAAC,CAAC,MAAM,OAAO,MAAM;AACvE,WAAK,KAAK;AAAA,QACR;AAAA,QACA;AAAA,QACA,MAAM;AAAA,MACR,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AAGA,MAAI,YAAY,kBAAk