@fragments-sdk/cli 0.14.3 → 0.15.0
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/README.md +0 -3
- package/dist/bin.js +4290 -3754
- package/dist/bin.js.map +1 -1
- package/dist/{chunk-TXFCEDOC.js → chunk-2WXKALIG.js} +2 -2
- package/dist/{chunk-I34BC3CU.js → chunk-32LIWN2P.js} +1006 -3
- package/dist/chunk-32LIWN2P.js.map +1 -0
- package/dist/{chunk-55KERLWL.js → chunk-65WSVDV5.js} +314 -89
- package/dist/chunk-65WSVDV5.js.map +1 -0
- package/dist/chunk-7DZC4YEV.js +294 -0
- package/dist/chunk-7DZC4YEV.js.map +1 -0
- package/dist/{chunk-LOYS64QS.js → chunk-7WHVW72L.js} +230 -19
- package/dist/chunk-7WHVW72L.js.map +1 -0
- package/dist/{chunk-PJT5IZ37.js → chunk-BJE3425I.js} +19 -52
- package/dist/{chunk-PJT5IZ37.js.map → chunk-BJE3425I.js.map} +1 -1
- package/dist/{chunk-5A6X2Y73.js → chunk-CZD3AD4Q.js} +12 -11
- package/dist/chunk-CZD3AD4Q.js.map +1 -0
- package/dist/{chunk-EYXVAMEX.js → chunk-MN3TJ3D5.js} +72 -3
- package/dist/chunk-MN3TJ3D5.js.map +1 -0
- package/dist/chunk-QCN35LJU.js +630 -0
- package/dist/chunk-QCN35LJU.js.map +1 -0
- package/dist/chunk-T47OLCSF.js +36 -0
- package/dist/chunk-T47OLCSF.js.map +1 -0
- package/dist/{chunk-APTQIBS5.js → chunk-XJQ5BIWI.js} +144 -1049
- package/dist/chunk-XJQ5BIWI.js.map +1 -0
- package/dist/codebase-scanner-VOTPXRYW.js +22 -0
- package/dist/converter-JLINP7CJ.js +34 -0
- package/dist/converter-JLINP7CJ.js.map +1 -0
- package/dist/core/index.js +43 -1
- package/dist/{generate-RYWIPDN2.js → generate-A4FP5426.js} +3 -4
- package/dist/{generate-RYWIPDN2.js.map → generate-A4FP5426.js.map} +1 -1
- package/dist/govern-scan-UCBZR6D6.js +280 -0
- package/dist/govern-scan-UCBZR6D6.js.map +1 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +11 -11
- package/dist/{init-WRUSW7R5.js → init-HGSM35XA.js} +131 -128
- package/dist/init-HGSM35XA.js.map +1 -0
- package/dist/{init-cloud-REQ3XLHO.js → init-cloud-MQ6GRJAZ.js} +2 -2
- package/dist/mcp-bin.js +5 -36
- package/dist/mcp-bin.js.map +1 -1
- package/dist/scan-VNNKACG2.js +15 -0
- package/dist/{scan-generate-TFZVL3BT.js → scan-generate-TWRHNU5M.js} +335 -46
- package/dist/scan-generate-TWRHNU5M.js.map +1 -0
- package/dist/scanner-7LAZYPWZ.js +13 -0
- package/dist/{service-HKJ6B7P7.js → service-FHQU7YS7.js} +27 -23
- package/dist/{snapshot-C5DYIGIV.js → snapshot-KQEQ6XHL.js} +2 -2
- package/dist/{static-viewer-DUVC4UIM.js → static-viewer-63PG6FWY.js} +3 -3
- package/dist/static-viewer-63PG6FWY.js.map +1 -0
- package/dist/{test-JW7JIDFG.js → test-UQYUCZIS.js} +4 -6
- package/dist/{test-JW7JIDFG.js.map → test-UQYUCZIS.js.map} +1 -1
- package/dist/{tokens-KE73G5JC.js → tokens-6GYKDV6U.js} +6 -5
- package/dist/{tokens-KE73G5JC.js.map → tokens-6GYKDV6U.js.map} +1 -1
- package/dist/tokens-generate-VTZV5EEW.js +86 -0
- package/dist/tokens-generate-VTZV5EEW.js.map +1 -0
- package/package.json +6 -6
- package/src/bin.ts +210 -48
- package/src/build.ts +130 -6
- package/src/commands/__fixtures__/shadcn-label-wrapper/package.json +7 -0
- package/src/commands/__fixtures__/shadcn-label-wrapper/src/components/ui/label.contract.json +42 -0
- package/src/commands/__fixtures__/shadcn-label-wrapper/src/components/ui/label.tsx +11 -0
- package/src/commands/__fixtures__/shadcn-label-wrapper/src/components/ui/primitive.contract.json +20 -0
- package/src/commands/__fixtures__/shadcn-label-wrapper/src/components/ui/primitive.tsx +14 -0
- package/src/commands/__fixtures__/shadcn-label-wrapper/tsconfig.app.json +23 -0
- package/src/commands/__tests__/init.test.ts +113 -0
- package/src/commands/__tests__/scan-generate.test.ts +188 -69
- package/src/commands/__tests__/verify.test.ts +91 -0
- package/src/commands/discover.ts +151 -0
- package/src/commands/enhance.ts +3 -1
- package/src/commands/govern-scan.ts +386 -0
- package/src/commands/govern.ts +2 -2
- package/src/commands/init.ts +152 -28
- package/src/commands/inspect.ts +290 -0
- package/src/commands/migrate-contract.ts +85 -0
- package/src/commands/scan-generate.ts +438 -50
- package/src/commands/scan.ts +1 -0
- package/src/commands/setup.ts +27 -50
- package/src/commands/tokens-generate.ts +113 -0
- package/src/commands/verify.ts +195 -1
- package/src/core/__fixtures__/shadcn-input/input.tsx +7 -0
- package/src/core/__fixtures__/shadcn-input/tsconfig.json +14 -0
- package/src/core/__fixtures__/shadcn-label/label.tsx +11 -0
- package/src/core/__fixtures__/shadcn-label/primitive.tsx +14 -0
- package/src/core/__fixtures__/shadcn-label/tsconfig.json +14 -0
- package/src/core/__fixtures__/shadcn-radix-label/label.tsx +11 -0
- package/src/core/__fixtures__/shadcn-radix-label/node_modules/radix-ui/index.d.ts +12 -0
- package/src/core/__fixtures__/shadcn-radix-label/tsconfig.json +14 -0
- package/src/core/__tests__/contract-parity.test.ts +316 -0
- package/src/core/component-extractor.test.ts +39 -0
- package/src/core/component-extractor.ts +92 -1
- package/src/core/config.ts +2 -1
- package/src/core/discovery.ts +13 -2
- package/src/core/drift-verifier.ts +123 -0
- package/src/core/extractor-adapter.ts +80 -0
- package/src/mcp/__tests__/projectFields.test.ts +1 -1
- package/src/mcp/utils.ts +1 -50
- package/src/migrate/converter.ts +3 -3
- package/src/migrate/fragment-to-contract.ts +253 -0
- package/src/migrate/report.ts +1 -1
- package/src/scripts/token-benchmark.ts +121 -0
- package/src/service/__tests__/props-extractor.test.ts +94 -0
- package/src/service/__tests__/token-normalizer.test.ts +690 -0
- package/src/service/ast-utils.ts +4 -23
- package/src/service/babel-config.ts +23 -0
- package/src/service/enhance/converter.ts +61 -0
- package/src/service/enhance/props-extractor.ts +25 -8
- package/src/service/enhance/scanner.ts +5 -24
- package/src/service/snippet-validation.ts +9 -3
- package/src/service/token-normalizer.ts +510 -0
- package/src/shared/index.ts +1 -0
- package/src/shared/project-fields.ts +46 -0
- package/src/viewer/__tests__/viewer-integration.test.ts +8 -8
- package/src/viewer/preview-adapter.ts +116 -0
- package/src/viewer/style-utils.ts +27 -412
- package/src/viewer/vite-plugin.ts +2 -2
- package/dist/chunk-55KERLWL.js.map +0 -1
- package/dist/chunk-5A6X2Y73.js.map +0 -1
- package/dist/chunk-APTQIBS5.js.map +0 -1
- package/dist/chunk-EYXVAMEX.js.map +0 -1
- package/dist/chunk-I34BC3CU.js.map +0 -1
- package/dist/chunk-LOYS64QS.js.map +0 -1
- package/dist/chunk-ZKTFKHWN.js +0 -324
- package/dist/chunk-ZKTFKHWN.js.map +0 -1
- package/dist/discovery-VDANZAJ2.js +0 -28
- package/dist/init-WRUSW7R5.js.map +0 -1
- package/dist/scan-YJHQIRKG.js +0 -14
- package/dist/scan-generate-TFZVL3BT.js.map +0 -1
- package/dist/viewer-2TZS3NDL.js +0 -2730
- package/dist/viewer-2TZS3NDL.js.map +0 -1
- package/src/commands/dev.ts +0 -107
- /package/dist/{chunk-TXFCEDOC.js.map → chunk-2WXKALIG.js.map} +0 -0
- /package/dist/{discovery-VDANZAJ2.js.map → codebase-scanner-VOTPXRYW.js.map} +0 -0
- /package/dist/{init-cloud-REQ3XLHO.js.map → init-cloud-MQ6GRJAZ.js.map} +0 -0
- /package/dist/{scan-YJHQIRKG.js.map → scan-VNNKACG2.js.map} +0 -0
- /package/dist/{service-HKJ6B7P7.js.map → scanner-7LAZYPWZ.js.map} +0 -0
- /package/dist/{static-viewer-DUVC4UIM.js.map → service-FHQU7YS7.js.map} +0 -0
- /package/dist/{snapshot-C5DYIGIV.js.map → snapshot-KQEQ6XHL.js.map} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/commands/setup.ts"],"sourcesContent":["/**\n * fragments setup - Configure @fragments-sdk/ui in a consumer project\n *\n * Auto-detects framework (Next.js, Vite, etc.) and scaffolds:\n * - Styles import in entry file\n * - ThemeProvider wrapper in layout/app\n * - transpilePackages for Next.js\n * - SCSS seeds file (optional)\n */\n\nimport { readFile, writeFile, access, mkdir } from 'node:fs/promises';\nimport { join, resolve, dirname } from 'node:path';\nimport pc from 'picocolors';\nimport { BRAND } from '../core/index.js';\n\n// ============================================\n// Types\n// ============================================\n\nexport interface SetupOptions {\n /** Project root directory (defaults to cwd) */\n root?: string;\n /** Skip interactive prompts */\n yes?: boolean;\n /** Brand color hex (e.g., #6366f1) */\n brand?: string;\n /** Include SCSS seed file */\n scss?: boolean;\n /** Configure MCP server for AI tooling */\n mcp?: boolean;\n}\n\nexport interface SetupResult {\n success: boolean;\n actions: string[];\n errors: string[];\n}\n\nexport type Framework = 'nextjs-app' | 'nextjs-pages' | 'vite' | 'remix' | 'astro' | 'unknown';\n\n// ============================================\n// Detection\n// ============================================\n\nexport async function fileExists(path: string): Promise<boolean> {\n try {\n await access(path);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function detectSetupFramework(root: string): Promise<Framework> {\n // Next.js App Router\n if (\n await fileExists(join(root, 'app/layout.tsx')) ||\n await fileExists(join(root, 'src/app/layout.tsx'))\n ) {\n return 'nextjs-app';\n }\n\n // Next.js Pages Router\n if (\n await fileExists(join(root, 'pages/_app.tsx')) ||\n await fileExists(join(root, 'pages/_app.ts'))\n ) {\n return 'nextjs-pages';\n }\n\n // Next.js (config exists but no router detected yet)\n if (\n await fileExists(join(root, 'next.config.ts')) ||\n await fileExists(join(root, 'next.config.js')) ||\n await fileExists(join(root, 'next.config.mjs'))\n ) {\n return 'nextjs-app';\n }\n\n // Remix\n if (\n await fileExists(join(root, 'app/root.tsx')) ||\n await fileExists(join(root, 'app/root.ts'))\n ) {\n return 'remix';\n }\n\n // Astro\n if (\n await fileExists(join(root, 'astro.config.mjs')) ||\n await fileExists(join(root, 'astro.config.ts'))\n ) {\n return 'astro';\n }\n\n // Vite (check after Remix/Astro since they also use Vite under the hood)\n if (\n await fileExists(join(root, 'vite.config.ts')) ||\n await fileExists(join(root, 'vite.config.js'))\n ) {\n return 'vite';\n }\n\n // Fallback: check package.json for framework deps\n try {\n const pkgPath = join(root, 'package.json');\n const pkgContent = await readFile(pkgPath, 'utf-8');\n const pkg = JSON.parse(pkgContent);\n const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };\n\n if (allDeps['next']) return 'nextjs-app';\n if (allDeps['@remix-run/react']) return 'remix';\n if (allDeps['astro']) return 'astro';\n if (allDeps['vite']) return 'vite';\n } catch {\n // No package.json or parse error\n }\n\n return 'unknown';\n}\n\nexport async function findEntryFile(root: string, framework: Framework): Promise<string | null> {\n const candidates: string[] = [];\n\n switch (framework) {\n case 'nextjs-app':\n candidates.push(\n 'src/app/layout.tsx', 'app/layout.tsx',\n 'src/app/layout.ts', 'app/layout.ts'\n );\n break;\n case 'nextjs-pages':\n candidates.push('pages/_app.tsx', 'pages/_app.ts');\n break;\n case 'remix':\n candidates.push('app/root.tsx', 'app/root.ts');\n break;\n case 'astro':\n candidates.push(\n 'src/layouts/Layout.astro',\n 'src/layouts/BaseLayout.astro',\n 'src/pages/index.astro'\n );\n break;\n case 'vite':\n candidates.push(\n 'src/main.tsx', 'src/main.ts',\n 'src/index.tsx', 'src/index.ts'\n );\n break;\n default:\n candidates.push(\n 'src/main.tsx', 'src/main.ts',\n 'src/index.tsx', 'src/index.ts',\n 'src/App.tsx', 'src/App.ts'\n );\n }\n\n for (const candidate of candidates) {\n if (await fileExists(join(root, candidate))) {\n return candidate;\n }\n }\n\n return null;\n}\n\nasync function findNextConfig(root: string): Promise<string | null> {\n const candidates = ['next.config.ts', 'next.config.mjs', 'next.config.js'];\n for (const candidate of candidates) {\n if (await fileExists(join(root, candidate))) {\n return candidate;\n }\n }\n return null;\n}\n\n// ============================================\n// Actions\n// ============================================\n\nexport async function addStylesImport(root: string, entryFile: string): Promise<{ modified: boolean; message: string }> {\n const fullPath = join(root, entryFile);\n const content = await readFile(fullPath, 'utf-8');\n\n if (content.includes('@fragments-sdk/ui/styles')) {\n return { modified: false, message: `Styles already imported in ${entryFile}` };\n }\n\n const stylesImport = \"import '@fragments-sdk/ui/styles';\";\n let newContent: string;\n\n // Astro files: insert inside frontmatter block (between --- fences)\n if (entryFile.endsWith('.astro')) {\n const fenceStart = content.indexOf('---');\n if (fenceStart !== -1) {\n const insertPos = fenceStart + 4; // after \"---\\n\"\n newContent = content.slice(0, insertPos) + stylesImport + '\\n' + content.slice(insertPos);\n } else {\n // No frontmatter — add one\n newContent = `---\\n${stylesImport}\\n---\\n${content}`;\n }\n } else {\n const useClientMatch = content.match(/^(?:\\uFEFF)?[ \\t]*['\"]use client['\"]\\s*;?[ \\t]*$/m);\n\n if (useClientMatch && useClientMatch.index != null) {\n const directiveLineEnd = content.indexOf('\\n', useClientMatch.index);\n const directiveEnd = directiveLineEnd === -1 ? content.length : directiveLineEnd + 1;\n const separator = directiveLineEnd === -1 ? '\\n' : '';\n newContent = content.slice(0, directiveEnd) + separator + stylesImport + '\\n' + content.slice(directiveEnd);\n } else {\n newContent = stylesImport + '\\n' + content;\n }\n }\n\n await writeFile(fullPath, newContent, 'utf-8');\n return { modified: true, message: `Added styles import to ${entryFile}` };\n}\n\nexport async function addThemeProvider(root: string, entryFile: string, framework: Framework): Promise<{ modified: boolean; message: string }> {\n const fullPath = join(root, entryFile);\n const content = await readFile(fullPath, 'utf-8');\n\n if (content.includes('ThemeProvider')) {\n return { modified: false, message: `ThemeProvider already present in ${entryFile}` };\n }\n\n // Astro uses .astro files — can't inject React imports\n if (framework === 'astro') {\n return { modified: false, message: 'Add ThemeProvider in your React island — see https://usefragments.com/getting-started#astro' };\n }\n\n // Add provider import after the last import line\n const providerImport = \"import { ThemeProvider, TooltipProvider, ToastProvider } from '@fragments-sdk/ui';\";\n\n let newContent = content;\n const lines = content.split('\\n');\n\n // Prefer placing right after the @fragments-sdk/ui/styles import if it exists\n let insertIdx = -1;\n for (let i = 0; i < lines.length; i++) {\n if (lines[i].includes('@fragments-sdk/ui/styles')) {\n insertIdx = i;\n break;\n }\n }\n\n // Otherwise, place after the last import line\n if (insertIdx === -1) {\n for (let i = 0; i < lines.length; i++) {\n if (lines[i].startsWith('import ') || lines[i].startsWith(\"import '\") || lines[i].startsWith('import \"')) {\n insertIdx = i;\n }\n }\n }\n\n if (insertIdx >= 0) {\n lines.splice(insertIdx + 1, 0, providerImport);\n newContent = lines.join('\\n');\n } else {\n newContent = providerImport + '\\n' + content;\n }\n\n await writeFile(fullPath, newContent, 'utf-8');\n\n // Framework-specific wrap instructions\n if (framework === 'nextjs-app') {\n const hint = !content.includes('suppressHydrationWarning')\n ? `\\n Add suppressHydrationWarning to your <html> tag`\n : '';\n return {\n modified: true,\n message: `Added provider imports to ${entryFile}. Wrap {children} with:\\n` +\n ` <ThemeProvider defaultMode=\"system\"><TooltipProvider><ToastProvider>{children}</ToastProvider></TooltipProvider></ThemeProvider>${hint}`,\n };\n }\n\n if (framework === 'nextjs-pages') {\n return {\n modified: true,\n message: `Added provider imports to ${entryFile}. Wrap <Component {...pageProps} /> with:\\n` +\n ` <ThemeProvider defaultMode=\"system\"><TooltipProvider><ToastProvider>...</ToastProvider></TooltipProvider></ThemeProvider>`,\n };\n }\n\n if (framework === 'remix') {\n return {\n modified: true,\n message: `Added provider imports to ${entryFile}. Wrap <Outlet /> with:\\n` +\n ` <ThemeProvider defaultMode=\"system\"><TooltipProvider><ToastProvider>...</ToastProvider></TooltipProvider></ThemeProvider>`,\n };\n }\n\n // Vite and unknown — generic instruction\n return {\n modified: true,\n message: `Added provider imports to ${entryFile}. Wrap your app root with:\\n` +\n ` <ThemeProvider defaultMode=\"system\"><TooltipProvider><ToastProvider>...</ToastProvider></TooltipProvider></ThemeProvider>`,\n };\n}\n\nexport async function addTranspilePackages(root: string): Promise<{ modified: boolean; message: string }> {\n const configFile = await findNextConfig(root);\n if (!configFile) {\n return { modified: false, message: 'No next.config found' };\n }\n\n const fullPath = join(root, configFile);\n const content = await readFile(fullPath, 'utf-8');\n\n if (content.includes('transpilePackages') && content.includes('@fragments-sdk/ui')) {\n return { modified: false, message: `transpilePackages already configured in ${configFile}` };\n }\n\n if (content.includes('transpilePackages')) {\n // transpilePackages exists but without @fragments-sdk/ui — need manual addition\n return {\n modified: false,\n message: `transpilePackages found in ${configFile} but missing '@fragments-sdk/ui'. Please add it manually.`,\n };\n }\n\n // Add transpilePackages to the config\n // Try to find the config object and add the property\n const patterns = [\n // const nextConfig: NextConfig = { ... } (with optional type annotation)\n { search: /const\\s+\\w+\\s*(?::\\s*\\w+)?\\s*=\\s*\\{/, replacement: (match: string) => `${match}\\n transpilePackages: ['@fragments-sdk/ui'],` },\n // module.exports = { ... }\n { search: /module\\.exports\\s*=\\s*\\{/, replacement: (match: string) => `${match}\\n transpilePackages: ['@fragments-sdk/ui'],` },\n // export default { ... }\n { search: /export\\s+default\\s*\\{/, replacement: (match: string) => `${match}\\n transpilePackages: ['@fragments-sdk/ui'],` },\n ];\n\n for (const pattern of patterns) {\n if (pattern.search.test(content)) {\n const newContent = content.replace(pattern.search, pattern.replacement);\n await writeFile(fullPath, newContent, 'utf-8');\n return { modified: true, message: `Added transpilePackages to ${configFile}` };\n }\n }\n\n return {\n modified: false,\n message: `Could not auto-modify ${configFile}. Add transpilePackages: ['@fragments-sdk/ui'] manually.`,\n };\n}\n\nasync function createScssSeeds(root: string, brand?: string): Promise<{ modified: boolean; message: string }> {\n // Try common SCSS locations\n const scssLocations = [\n 'src/app/globals.scss',\n 'app/globals.scss',\n 'src/styles/globals.scss',\n 'src/globals.scss',\n 'styles/globals.scss',\n ];\n\n // Check if any exists already\n for (const loc of scssLocations) {\n const fullPath = join(root, loc);\n if (await fileExists(fullPath)) {\n const content = await readFile(fullPath, 'utf-8');\n if (content.includes('@fragments-sdk/ui/styles')) {\n return { modified: false, message: `SCSS seeds already configured in ${loc}` };\n }\n\n // Prepend @use to existing file\n const seedContent = generateScssSeedImport(brand);\n const newContent = seedContent + '\\n' + content;\n await writeFile(fullPath, newContent, 'utf-8');\n return { modified: true, message: `Added SCSS seed import to ${loc}` };\n }\n }\n\n // Create new globals.scss in the most common location\n const targetDir = await fileExists(join(root, 'src/app'))\n ? 'src/app'\n : await fileExists(join(root, 'src'))\n ? 'src/styles'\n : 'styles';\n\n const targetPath = join(targetDir, 'globals.scss');\n const fullPath = join(root, targetPath);\n\n await mkdir(dirname(fullPath), { recursive: true });\n await writeFile(fullPath, generateScssSeedImport(brand), 'utf-8');\n return { modified: true, message: `Created ${targetPath} with SCSS seed configuration` };\n}\n\nasync function setupMcpConfig(root: string): Promise<{ modified: boolean; message: string }> {\n // Check common MCP config locations\n const mcpConfigPaths = [\n '.cursor/mcp.json',\n '.vscode/mcp.json',\n ];\n\n for (const configPath of mcpConfigPaths) {\n const fullPath = join(root, configPath);\n if (await fileExists(fullPath)) {\n try {\n const content = await readFile(fullPath, 'utf-8');\n const config = JSON.parse(content);\n const servers = config.mcpServers || {};\n\n // Check if fragments is already configured\n const hasFragments = Object.values(servers).some((server: unknown) => {\n const s = server as { command?: string; args?: string[] };\n return s.args?.some((arg: string) => arg.includes('@fragments-sdk/mcp'));\n });\n\n if (hasFragments) {\n return { modified: false, message: `MCP server already configured in ${configPath}` };\n }\n\n // Add fragments MCP server\n servers.fragments = {\n command: 'npx',\n args: ['@fragments-sdk/mcp'],\n };\n config.mcpServers = servers;\n\n await writeFile(fullPath, JSON.stringify(config, null, 2) + '\\n', 'utf-8');\n return { modified: true, message: `Added Fragments MCP server to ${configPath}` };\n } catch {\n return { modified: false, message: `Could not parse ${configPath}` };\n }\n }\n }\n\n // No existing MCP config — create one for Cursor (most common)\n const cursorDir = join(root, '.cursor');\n const cursorMcpPath = join(cursorDir, 'mcp.json');\n\n await mkdir(cursorDir, { recursive: true });\n const mcpConfig = {\n mcpServers: {\n fragments: {\n command: 'npx',\n args: ['@fragments-sdk/mcp'],\n },\n },\n };\n\n await writeFile(cursorMcpPath, JSON.stringify(mcpConfig, null, 2) + '\\n', 'utf-8');\n return { modified: true, message: 'Created .cursor/mcp.json with Fragments MCP server' };\n}\n\nfunction generateScssSeedImport(brand?: string): string {\n const brandColor = brand || '#0066ff';\n return `@use '@fragments-sdk/ui/styles' with (\n $fui-brand: ${brandColor},\n $fui-neutral: \"stone\",\n $fui-density: \"default\",\n $fui-radius-style: \"rounded\"\n);\n`;\n}\n\n// ============================================\n// Main Setup Function\n// ============================================\n\nexport async function setup(options: SetupOptions = {}): Promise<SetupResult> {\n const root = resolve(options.root ?? process.cwd());\n const actions: string[] = [];\n const errors: string[] = [];\n\n console.log(pc.cyan(`\\n${BRAND.name} Setup\\n`));\n\n // 1. Detect framework\n const framework = await detectSetupFramework(root);\n const frameworkLabels: Record<string, string> = {\n 'nextjs-app': 'Next.js (App Router)',\n 'nextjs-pages': 'Next.js (Pages Router)',\n 'vite': 'Vite',\n 'remix': 'Remix',\n 'astro': 'Astro',\n };\n const frameworkLabel = frameworkLabels[framework] || 'Unknown';\n\n console.log(` ${pc.dim('Framework:')} ${frameworkLabel}`);\n\n // 2. Find entry file\n const entryFile = await findEntryFile(root, framework);\n if (entryFile) {\n console.log(` ${pc.dim('Entry:')} ${entryFile}`);\n } else {\n console.log(` ${pc.yellow('!')} Could not detect entry file`);\n }\n console.log();\n\n // 3. Add styles import\n if (entryFile) {\n try {\n const result = await addStylesImport(root, entryFile);\n const icon = result.modified ? pc.green('+') : pc.dim('·');\n console.log(` ${icon} ${result.message}`);\n if (result.modified) actions.push(result.message);\n } catch (error) {\n const msg = `Failed to add styles import: ${error instanceof Error ? error.message : error}`;\n console.log(` ${pc.red('✗')} ${msg}`);\n errors.push(msg);\n }\n }\n\n // 4. Add ThemeProvider imports\n if (entryFile) {\n try {\n const result = await addThemeProvider(root, entryFile, framework);\n const icon = result.modified ? pc.green('+') : pc.dim('·');\n console.log(` ${icon} ${result.message}`);\n if (result.modified) actions.push(result.message);\n } catch (error) {\n const msg = `Failed to add ThemeProvider: ${error instanceof Error ? error.message : error}`;\n console.log(` ${pc.red('✗')} ${msg}`);\n errors.push(msg);\n }\n }\n\n // 5. Next.js: add transpilePackages\n if (framework === 'nextjs-app' || framework === 'nextjs-pages') {\n try {\n const result = await addTranspilePackages(root);\n const icon = result.modified ? pc.green('+') : pc.dim('·');\n console.log(` ${icon} ${result.message}`);\n if (result.modified) actions.push(result.message);\n } catch (error) {\n const msg = `Failed to update next.config: ${error instanceof Error ? error.message : error}`;\n console.log(` ${pc.red('✗')} ${msg}`);\n errors.push(msg);\n }\n }\n\n // 6. Create SCSS seeds file (if --scss flag or brand color specified)\n if (options.scss || options.brand) {\n try {\n const result = await createScssSeeds(root, options.brand);\n const icon = result.modified ? pc.green('+') : pc.dim('·');\n console.log(` ${icon} ${result.message}`);\n if (result.modified) actions.push(result.message);\n } catch (error) {\n const msg = `Failed to create SCSS seeds: ${error instanceof Error ? error.message : error}`;\n console.log(` ${pc.red('✗')} ${msg}`);\n errors.push(msg);\n }\n }\n\n // 7. Configure MCP server (if --mcp flag)\n if (options.mcp) {\n try {\n const result = await setupMcpConfig(root);\n const icon = result.modified ? pc.green('+') : pc.dim('·');\n console.log(` ${icon} ${result.message}`);\n if (result.modified) actions.push(result.message);\n } catch (error) {\n const msg = `Failed to configure MCP: ${error instanceof Error ? error.message : error}`;\n console.log(` ${pc.red('✗')} ${msg}`);\n errors.push(msg);\n }\n }\n\n // Summary\n console.log();\n if (errors.length > 0) {\n console.log(pc.red(` ${errors.length} error(s) occurred during setup`));\n } else if (actions.length > 0) {\n console.log(pc.green(` ✓ Setup complete — ${actions.length} file(s) modified`));\n } else {\n console.log(pc.green(' ✓ Already configured — no changes needed'));\n }\n\n // Next steps\n console.log();\n console.log(pc.dim(' Next steps:'));\n if (!options.scss && !options.brand) {\n console.log(pc.dim(' • Run with --scss to add build-time theme seeds'));\n }\n if (!options.mcp) {\n console.log(pc.dim(' • Run with --mcp to configure AI tooling (MCP server)'));\n }\n console.log(pc.dim(' • Run `fragments doctor` to verify your setup'));\n console.log(pc.dim(' • Visit https://usefragments.com/getting-started'));\n console.log();\n\n return {\n success: errors.length === 0,\n actions,\n errors,\n };\n}\n"],"mappings":"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","names":["fullPath"]}
|
|
1
|
+
{"version":3,"sources":["../src/commands/setup.ts"],"sourcesContent":["/**\n * fragments setup - Configure @fragments-sdk/ui in a consumer project\n *\n * Auto-detects framework (Next.js, Vite, etc.) and scaffolds:\n * - Styles import in entry file\n * - ThemeProvider wrapper in layout/app\n * - transpilePackages for Next.js\n * - SCSS seeds file (optional)\n */\n\nimport { readFile, writeFile, access, mkdir } from 'node:fs/promises';\nimport { join, resolve, dirname } from 'node:path';\nimport pc from 'picocolors';\nimport { BRAND } from '../core/index.js';\n\n// ============================================\n// Types\n// ============================================\n\nexport interface SetupOptions {\n /** Project root directory (defaults to cwd) */\n root?: string;\n /** Skip interactive prompts */\n yes?: boolean;\n /** Brand color hex (e.g., #6366f1) */\n brand?: string;\n /** Include SCSS seed file */\n scss?: boolean;\n /** Configure MCP server for AI tooling */\n mcp?: boolean;\n}\n\nexport interface SetupResult {\n success: boolean;\n actions: string[];\n errors: string[];\n}\n\nexport type Framework = 'nextjs-app' | 'nextjs-pages' | 'vite' | 'remix' | 'astro' | 'unknown';\n\n// ============================================\n// Detection\n// ============================================\n\nexport async function fileExists(path: string): Promise<boolean> {\n try {\n await access(path);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function detectSetupFramework(root: string): Promise<Framework> {\n // Next.js App Router\n if (\n await fileExists(join(root, 'app/layout.tsx')) ||\n await fileExists(join(root, 'src/app/layout.tsx'))\n ) {\n return 'nextjs-app';\n }\n\n // Next.js Pages Router\n if (\n await fileExists(join(root, 'pages/_app.tsx')) ||\n await fileExists(join(root, 'pages/_app.ts'))\n ) {\n return 'nextjs-pages';\n }\n\n // Next.js (config exists but no router detected yet)\n if (\n await fileExists(join(root, 'next.config.ts')) ||\n await fileExists(join(root, 'next.config.js')) ||\n await fileExists(join(root, 'next.config.mjs'))\n ) {\n return 'nextjs-app';\n }\n\n // Remix\n if (\n await fileExists(join(root, 'app/root.tsx')) ||\n await fileExists(join(root, 'app/root.ts'))\n ) {\n return 'remix';\n }\n\n // Astro\n if (\n await fileExists(join(root, 'astro.config.mjs')) ||\n await fileExists(join(root, 'astro.config.ts'))\n ) {\n return 'astro';\n }\n\n // Vite (check after Remix/Astro since they also use Vite under the hood)\n if (\n await fileExists(join(root, 'vite.config.ts')) ||\n await fileExists(join(root, 'vite.config.js'))\n ) {\n return 'vite';\n }\n\n // Fallback: check package.json for framework deps\n try {\n const pkgPath = join(root, 'package.json');\n const pkgContent = await readFile(pkgPath, 'utf-8');\n const pkg = JSON.parse(pkgContent);\n const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };\n\n if (allDeps['next']) return 'nextjs-app';\n if (allDeps['@remix-run/react']) return 'remix';\n if (allDeps['astro']) return 'astro';\n if (allDeps['vite']) return 'vite';\n } catch {\n // No package.json or parse error\n }\n\n return 'unknown';\n}\n\nexport async function findEntryFile(root: string, framework: Framework): Promise<string | null> {\n const candidates: string[] = [];\n\n switch (framework) {\n case 'nextjs-app':\n candidates.push(\n 'src/app/layout.tsx', 'app/layout.tsx',\n 'src/app/layout.ts', 'app/layout.ts'\n );\n break;\n case 'nextjs-pages':\n candidates.push('pages/_app.tsx', 'pages/_app.ts');\n break;\n case 'remix':\n candidates.push('app/root.tsx', 'app/root.ts');\n break;\n case 'astro':\n candidates.push(\n 'src/layouts/Layout.astro',\n 'src/layouts/BaseLayout.astro',\n 'src/pages/index.astro'\n );\n break;\n case 'vite':\n candidates.push(\n 'src/main.tsx', 'src/main.ts',\n 'src/index.tsx', 'src/index.ts'\n );\n break;\n default:\n candidates.push(\n 'src/main.tsx', 'src/main.ts',\n 'src/index.tsx', 'src/index.ts',\n 'src/App.tsx', 'src/App.ts'\n );\n }\n\n for (const candidate of candidates) {\n if (await fileExists(join(root, candidate))) {\n return candidate;\n }\n }\n\n return null;\n}\n\nasync function findNextConfig(root: string): Promise<string | null> {\n const candidates = ['next.config.ts', 'next.config.mjs', 'next.config.js'];\n for (const candidate of candidates) {\n if (await fileExists(join(root, candidate))) {\n return candidate;\n }\n }\n return null;\n}\n\n// ============================================\n// Actions\n// ============================================\n\nexport async function addStylesImport(root: string, entryFile: string): Promise<{ modified: boolean; message: string }> {\n const fullPath = join(root, entryFile);\n const content = await readFile(fullPath, 'utf-8');\n\n if (content.includes('@fragments-sdk/ui/styles')) {\n return { modified: false, message: `Styles already imported in ${entryFile}` };\n }\n\n const stylesImport = \"import '@fragments-sdk/ui/styles';\";\n let newContent: string;\n\n // Astro files: insert inside frontmatter block (between --- fences)\n if (entryFile.endsWith('.astro')) {\n const fenceStart = content.indexOf('---');\n if (fenceStart !== -1) {\n const insertPos = fenceStart + 4; // after \"---\\n\"\n newContent = content.slice(0, insertPos) + stylesImport + '\\n' + content.slice(insertPos);\n } else {\n // No frontmatter — add one\n newContent = `---\\n${stylesImport}\\n---\\n${content}`;\n }\n } else {\n const useClientMatch = content.match(/^(?:\\uFEFF)?[ \\t]*['\"]use client['\"]\\s*;?[ \\t]*$/m);\n\n if (useClientMatch && useClientMatch.index != null) {\n const directiveLineEnd = content.indexOf('\\n', useClientMatch.index);\n const directiveEnd = directiveLineEnd === -1 ? content.length : directiveLineEnd + 1;\n const separator = directiveLineEnd === -1 ? '\\n' : '';\n newContent = content.slice(0, directiveEnd) + separator + stylesImport + '\\n' + content.slice(directiveEnd);\n } else {\n newContent = stylesImport + '\\n' + content;\n }\n }\n\n await writeFile(fullPath, newContent, 'utf-8');\n return { modified: true, message: `Added styles import to ${entryFile}` };\n}\n\nexport async function addThemeProvider(root: string, entryFile: string, framework: Framework): Promise<{ modified: boolean; message: string }> {\n const fullPath = join(root, entryFile);\n const content = await readFile(fullPath, 'utf-8');\n\n if (content.includes('ThemeProvider')) {\n return { modified: false, message: `ThemeProvider already present in ${entryFile}` };\n }\n\n // Astro uses .astro files — can't inject React imports\n if (framework === 'astro') {\n return { modified: false, message: 'Add ThemeProvider in your React island — see https://usefragments.com/getting-started#astro' };\n }\n\n // Add provider import after the last import line\n const providerImport = \"import { ThemeProvider, TooltipProvider, ToastProvider } from '@fragments-sdk/ui';\";\n\n let newContent = content;\n const lines = content.split('\\n');\n\n // Prefer placing right after the @fragments-sdk/ui/styles import if it exists\n let insertIdx = -1;\n for (let i = 0; i < lines.length; i++) {\n if (lines[i].includes('@fragments-sdk/ui/styles')) {\n insertIdx = i;\n break;\n }\n }\n\n // Otherwise, place after the last import line\n if (insertIdx === -1) {\n for (let i = 0; i < lines.length; i++) {\n if (lines[i].startsWith('import ') || lines[i].startsWith(\"import '\") || lines[i].startsWith('import \"')) {\n insertIdx = i;\n }\n }\n }\n\n if (insertIdx >= 0) {\n lines.splice(insertIdx + 1, 0, providerImport);\n newContent = lines.join('\\n');\n } else {\n newContent = providerImport + '\\n' + content;\n }\n\n await writeFile(fullPath, newContent, 'utf-8');\n\n // Framework-specific wrap instructions\n if (framework === 'nextjs-app') {\n const hint = !content.includes('suppressHydrationWarning')\n ? `\\n Add suppressHydrationWarning to your <html> tag`\n : '';\n return {\n modified: true,\n message: `Added provider imports to ${entryFile}. Wrap {children} with:\\n` +\n ` <ThemeProvider defaultMode=\"system\"><TooltipProvider><ToastProvider>{children}</ToastProvider></TooltipProvider></ThemeProvider>${hint}`,\n };\n }\n\n if (framework === 'nextjs-pages') {\n return {\n modified: true,\n message: `Added provider imports to ${entryFile}. Wrap <Component {...pageProps} /> with:\\n` +\n ` <ThemeProvider defaultMode=\"system\"><TooltipProvider><ToastProvider>...</ToastProvider></TooltipProvider></ThemeProvider>`,\n };\n }\n\n if (framework === 'remix') {\n return {\n modified: true,\n message: `Added provider imports to ${entryFile}. Wrap <Outlet /> with:\\n` +\n ` <ThemeProvider defaultMode=\"system\"><TooltipProvider><ToastProvider>...</ToastProvider></TooltipProvider></ThemeProvider>`,\n };\n }\n\n // Vite and unknown — generic instruction\n return {\n modified: true,\n message: `Added provider imports to ${entryFile}. Wrap your app root with:\\n` +\n ` <ThemeProvider defaultMode=\"system\"><TooltipProvider><ToastProvider>...</ToastProvider></TooltipProvider></ThemeProvider>`,\n };\n}\n\nexport async function addTranspilePackages(root: string): Promise<{ modified: boolean; message: string }> {\n const configFile = await findNextConfig(root);\n if (!configFile) {\n return { modified: false, message: 'No next.config found' };\n }\n\n const fullPath = join(root, configFile);\n const content = await readFile(fullPath, 'utf-8');\n\n if (content.includes('transpilePackages') && content.includes('@fragments-sdk/ui')) {\n return { modified: false, message: `transpilePackages already configured in ${configFile}` };\n }\n\n if (content.includes('transpilePackages')) {\n // transpilePackages exists but without @fragments-sdk/ui — need manual addition\n return {\n modified: false,\n message: `transpilePackages found in ${configFile} but missing '@fragments-sdk/ui'. Please add it manually.`,\n };\n }\n\n // Add transpilePackages to the config\n // Try to find the config object and add the property\n const patterns = [\n // const nextConfig: NextConfig = { ... } (with optional type annotation)\n { search: /const\\s+\\w+\\s*(?::\\s*\\w+)?\\s*=\\s*\\{/, replacement: (match: string) => `${match}\\n transpilePackages: ['@fragments-sdk/ui'],` },\n // module.exports = { ... }\n { search: /module\\.exports\\s*=\\s*\\{/, replacement: (match: string) => `${match}\\n transpilePackages: ['@fragments-sdk/ui'],` },\n // export default { ... }\n { search: /export\\s+default\\s*\\{/, replacement: (match: string) => `${match}\\n transpilePackages: ['@fragments-sdk/ui'],` },\n ];\n\n for (const pattern of patterns) {\n if (pattern.search.test(content)) {\n const newContent = content.replace(pattern.search, pattern.replacement);\n await writeFile(fullPath, newContent, 'utf-8');\n return { modified: true, message: `Added transpilePackages to ${configFile}` };\n }\n }\n\n return {\n modified: false,\n message: `Could not auto-modify ${configFile}. Add transpilePackages: ['@fragments-sdk/ui'] manually.`,\n };\n}\n\nasync function createScssSeeds(root: string, brand?: string): Promise<{ modified: boolean; message: string }> {\n // Try common SCSS locations\n const scssLocations = [\n 'src/app/globals.scss',\n 'app/globals.scss',\n 'src/styles/globals.scss',\n 'src/globals.scss',\n 'styles/globals.scss',\n ];\n\n // Check if any exists already\n for (const loc of scssLocations) {\n const fullPath = join(root, loc);\n if (await fileExists(fullPath)) {\n const content = await readFile(fullPath, 'utf-8');\n if (content.includes('@fragments-sdk/ui/styles')) {\n return { modified: false, message: `SCSS seeds already configured in ${loc}` };\n }\n\n // Prepend @use to existing file\n const seedContent = generateScssSeedImport(brand);\n const newContent = seedContent + '\\n' + content;\n await writeFile(fullPath, newContent, 'utf-8');\n return { modified: true, message: `Added SCSS seed import to ${loc}` };\n }\n }\n\n // Create new globals.scss in the most common location\n const targetDir = await fileExists(join(root, 'src/app'))\n ? 'src/app'\n : await fileExists(join(root, 'src'))\n ? 'src/styles'\n : 'styles';\n\n const targetPath = join(targetDir, 'globals.scss');\n const fullPath = join(root, targetPath);\n\n await mkdir(dirname(fullPath), { recursive: true });\n await writeFile(fullPath, generateScssSeedImport(brand), 'utf-8');\n return { modified: true, message: `Created ${targetPath} with SCSS seed configuration` };\n}\n\nasync function setupMcpConfig(root: string): Promise<{ modified: boolean; message: string }> {\n // Check common MCP config locations\n const mcpConfigPaths = [\n '.cursor/mcp.json',\n '.vscode/mcp.json',\n ];\n\n for (const configPath of mcpConfigPaths) {\n const fullPath = join(root, configPath);\n if (await fileExists(fullPath)) {\n try {\n const content = await readFile(fullPath, 'utf-8');\n const config = JSON.parse(content);\n const servers = config.mcpServers || {};\n\n // Check if fragments is already configured\n const hasFragments = Object.values(servers).some((server: unknown) => {\n const s = server as { command?: string; args?: string[] };\n return s.args?.some((arg: string) => arg.includes('@fragments-sdk/mcp'));\n });\n\n if (hasFragments) {\n return { modified: false, message: `MCP server already configured in ${configPath}` };\n }\n\n // Add fragments MCP server\n servers.fragments = {\n command: 'npx',\n args: ['@fragments-sdk/mcp'],\n };\n config.mcpServers = servers;\n\n await writeFile(fullPath, JSON.stringify(config, null, 2) + '\\n', 'utf-8');\n return { modified: true, message: `Added Fragments MCP server to ${configPath}` };\n } catch {\n return { modified: false, message: `Could not parse ${configPath}` };\n }\n }\n }\n\n // No existing MCP config — create one for Cursor (most common)\n const cursorDir = join(root, '.cursor');\n const cursorMcpPath = join(cursorDir, 'mcp.json');\n\n await mkdir(cursorDir, { recursive: true });\n const mcpConfig = {\n mcpServers: {\n fragments: {\n command: 'npx',\n args: ['@fragments-sdk/mcp'],\n },\n },\n };\n\n await writeFile(cursorMcpPath, JSON.stringify(mcpConfig, null, 2) + '\\n', 'utf-8');\n return { modified: true, message: 'Created .cursor/mcp.json with Fragments MCP server' };\n}\n\nfunction generateScssSeedImport(brand?: string): string {\n const brandColor = brand || '#0066ff';\n return `@use '@fragments-sdk/ui/styles' with (\n $fui-brand: ${brandColor},\n $fui-neutral: \"stone\",\n $fui-density: \"default\",\n $fui-radius-style: \"rounded\"\n);\n`;\n}\n\n// ============================================\n// Step runner\n// ============================================\n\nasync function runSetupStep(\n fn: () => Promise<{ modified: boolean; message: string }>,\n failureLabel: string,\n actions: string[],\n errors: string[],\n): Promise<void> {\n try {\n const result = await fn();\n const icon = result.modified ? pc.green('+') : pc.dim('·');\n console.log(` ${icon} ${result.message}`);\n if (result.modified) actions.push(result.message);\n } catch (error) {\n const msg = `${failureLabel}: ${error instanceof Error ? error.message : error}`;\n console.log(` ${pc.red('✗')} ${msg}`);\n errors.push(msg);\n }\n}\n\n// ============================================\n// Main Setup Function\n// ============================================\n\nexport async function setup(options: SetupOptions = {}): Promise<SetupResult> {\n const root = resolve(options.root ?? process.cwd());\n const actions: string[] = [];\n const errors: string[] = [];\n\n console.log(pc.cyan(`\\n${BRAND.name} Setup\\n`));\n\n // 1. Detect framework\n const framework = await detectSetupFramework(root);\n const frameworkLabels: Record<string, string> = {\n 'nextjs-app': 'Next.js (App Router)',\n 'nextjs-pages': 'Next.js (Pages Router)',\n 'vite': 'Vite',\n 'remix': 'Remix',\n 'astro': 'Astro',\n };\n const frameworkLabel = frameworkLabels[framework] || 'Unknown';\n\n console.log(` ${pc.dim('Framework:')} ${frameworkLabel}`);\n\n // 2. Find entry file\n const entryFile = await findEntryFile(root, framework);\n if (entryFile) {\n console.log(` ${pc.dim('Entry:')} ${entryFile}`);\n } else {\n console.log(` ${pc.yellow('!')} Could not detect entry file`);\n }\n console.log();\n\n // 3. Add styles import\n if (entryFile) {\n await runSetupStep(() => addStylesImport(root, entryFile), 'Failed to add styles import', actions, errors);\n }\n\n // 4. Add ThemeProvider imports\n if (entryFile) {\n await runSetupStep(() => addThemeProvider(root, entryFile, framework), 'Failed to add ThemeProvider', actions, errors);\n }\n\n // 5. Next.js: add transpilePackages\n if (framework === 'nextjs-app' || framework === 'nextjs-pages') {\n await runSetupStep(() => addTranspilePackages(root), 'Failed to update next.config', actions, errors);\n }\n\n // 6. Create SCSS seeds file (if --scss flag or brand color specified)\n if (options.scss || options.brand) {\n await runSetupStep(() => createScssSeeds(root, options.brand), 'Failed to create SCSS seeds', actions, errors);\n }\n\n // 7. Configure MCP server (if --mcp flag)\n if (options.mcp) {\n await runSetupStep(() => setupMcpConfig(root), 'Failed to configure MCP', actions, errors);\n }\n\n // Summary\n console.log();\n if (errors.length > 0) {\n console.log(pc.red(` ${errors.length} error(s) occurred during setup`));\n } else if (actions.length > 0) {\n console.log(pc.green(` ✓ Setup complete — ${actions.length} file(s) modified`));\n } else {\n console.log(pc.green(' ✓ Already configured — no changes needed'));\n }\n\n // Next steps\n console.log();\n console.log(pc.dim(' Next steps:'));\n if (!options.scss && !options.brand) {\n console.log(pc.dim(' • Run with --scss to add build-time theme seeds'));\n }\n if (!options.mcp) {\n console.log(pc.dim(' • Run with --mcp to configure AI tooling (MCP server)'));\n }\n console.log(pc.dim(' • Run `fragments doctor` to verify your setup'));\n console.log(pc.dim(' • Visit https://usefragments.com/getting-started'));\n console.log();\n\n return {\n success: errors.length === 0,\n actions,\n errors,\n };\n}\n"],"mappings":"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","names":["fullPath"]}
|
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
import { createRequire as __banner_createRequire } from 'module'; const require = __banner_createRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
|
+
discoverAllComponents,
|
|
3
4
|
loadConfig
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import {
|
|
6
|
-
discoverAllComponents
|
|
7
|
-
} from "./chunk-ZKTFKHWN.js";
|
|
5
|
+
} from "./chunk-65WSVDV5.js";
|
|
8
6
|
import {
|
|
9
7
|
convertToFragmentProps,
|
|
10
8
|
extractPropsFromFile,
|
|
11
9
|
filterBoilerplate,
|
|
12
10
|
generateComponentContext,
|
|
13
11
|
generateEnhancementSuggestions,
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
scanCodebase
|
|
17
|
-
} from "./chunk-APTQIBS5.js";
|
|
12
|
+
parseAllStories
|
|
13
|
+
} from "./chunk-XJQ5BIWI.js";
|
|
18
14
|
import {
|
|
19
15
|
BRAND
|
|
20
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-32LIWN2P.js";
|
|
17
|
+
import {
|
|
18
|
+
inferAllRelations,
|
|
19
|
+
scanCodebase
|
|
20
|
+
} from "./chunk-QCN35LJU.js";
|
|
21
21
|
|
|
22
22
|
// src/commands/scan.ts
|
|
23
23
|
import { writeFile, mkdir } from "fs/promises";
|
|
@@ -82,7 +82,8 @@ ${BRAND.name} Scan
|
|
|
82
82
|
for (const comp of components) {
|
|
83
83
|
try {
|
|
84
84
|
const extraction = await extractPropsFromFile(comp.sourcePath, {
|
|
85
|
-
propsTypeName: `${comp.name}Props
|
|
85
|
+
propsTypeName: `${comp.name}Props`,
|
|
86
|
+
componentName: comp.name
|
|
86
87
|
});
|
|
87
88
|
propsResults.set(comp.name, extraction);
|
|
88
89
|
if (extraction.success && extraction.props.length > 0) {
|
|
@@ -370,4 +371,4 @@ function calculateConfidence(props, usageAnalysis, storyFile) {
|
|
|
370
371
|
export {
|
|
371
372
|
scan
|
|
372
373
|
};
|
|
373
|
-
//# sourceMappingURL=chunk-
|
|
374
|
+
//# sourceMappingURL=chunk-CZD3AD4Q.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/scan.ts"],"sourcesContent":["/**\n * fragments scan - Zero-config fragments.json generation from source code\n *\n * Automatically extracts component documentation by:\n * 1. Discovering components from source files and barrel exports\n * 2. Extracting props from TypeScript interfaces\n * 3. Scanning codebase for usage patterns\n * 4. Parsing Storybook stories for examples\n * 5. Inferring component relationships from usage data\n * 6. Generating complete fragments.json without manual documentation\n */\n\nimport { writeFile, mkdir } from \"node:fs/promises\";\nimport { resolve, join, dirname, relative } from \"node:path\";\nimport pc from \"picocolors\";\nimport {\n BRAND,\n type CompiledFragmentsFile,\n type CompiledFragment,\n type PropDefinition,\n} from \"../core/index.js\";\nimport {\n loadConfig,\n discoverAllComponents,\n type DiscoveredComponent,\n} from \"../core/node.js\";\nimport {\n scanCodebase,\n extractPropsFromFile,\n parseAllStories,\n inferAllRelations,\n generateComponentContext,\n generateEnhancementSuggestions,\n filterBoilerplate,\n convertToFragmentProps,\n type UsageAnalysis,\n type ComponentRelation,\n type PropsExtractionResult,\n type ParsedStoryFile,\n} from \"../service/index.js\";\n\nexport interface ScanOptions {\n /** Path to config file */\n config?: string;\n /** Output file path (default: fragments.json) */\n output?: string;\n /** Component patterns to scan */\n componentPatterns?: string[];\n /** Barrel export files to parse */\n barrelFiles?: string[];\n /** Directory to scan for usage patterns */\n usageDir?: string;\n /** Skip usage analysis */\n skipUsage?: boolean;\n /** Skip Storybook parsing */\n skipStorybook?: boolean;\n /** Verbose output */\n verbose?: boolean;\n /** Suppress all console output (for use as a sub-step) */\n quiet?: boolean;\n}\n\nexport interface ScanResult {\n success: boolean;\n outputPath: string;\n componentCount: number;\n propsExtracted: number;\n usagesFound: number;\n relationsInferred: number;\n storiesParsed: number;\n errors: Array<{ component: string; error: string }>;\n warnings: Array<{ component: string; warning: string }>;\n}\n\n/**\n * Scan codebase and generate fragments.json directly from source\n */\nexport async function scan(options: ScanOptions = {}): Promise<ScanResult> {\n const startTime = Date.now();\n const errors: Array<{ component: string; error: string }> = [];\n const warnings: Array<{ component: string; warning: string }> = [];\n\n // In quiet mode, suppress all console output\n const log = options.quiet ? (() => {}) : console.log.bind(console);\n\n // Load config or use defaults\n let configDir: string;\n let outputFile: string;\n let componentPatterns: string[] | undefined;\n\n try {\n const loaded = await loadConfig(options.config);\n configDir = loaded.configDir;\n outputFile = options.output || loaded.config.outFile || \"fragments.json\";\n componentPatterns = options.componentPatterns || loaded.config.components;\n } catch {\n // No config file, use defaults\n configDir = process.cwd();\n outputFile = options.output || \"fragments.json\";\n componentPatterns = options.componentPatterns;\n }\n\n log(pc.cyan(`\\n${BRAND.name} Scan\\n`));\n log(pc.dim(\"Zero-config fragments.json generation from source code\\n\"));\n\n // Phase 1: Discover components\n log(pc.dim(\"Phase 1: Discovering components...\"));\n const components = await discoverAllComponents(configDir, {\n patterns: componentPatterns,\n exclude: [\"**/*.test.*\", \"**/*.spec.*\", \"**/__tests__/**\"],\n barrelFiles: options.barrelFiles,\n });\n\n if (components.length === 0) {\n log(pc.yellow(\"No components found. Check your patterns or config.\"));\n return {\n success: false,\n outputPath: resolve(configDir, outputFile),\n componentCount: 0,\n propsExtracted: 0,\n usagesFound: 0,\n relationsInferred: 0,\n storiesParsed: 0,\n errors: [{ component: \"*\", error: \"No components found\" }],\n warnings: [],\n };\n }\n\n log(pc.green(` Found ${components.length} components`));\n if (options.verbose) {\n for (const comp of components.slice(0, 10)) {\n log(pc.dim(` - ${comp.name}: ${comp.relativePath}`));\n }\n if (components.length > 10) {\n log(pc.dim(` ... and ${components.length - 10} more`));\n }\n }\n\n // Phase 2: Extract props from TypeScript\n log(pc.dim(\"\\nPhase 2: Extracting props from TypeScript...\"));\n const propsMap = new Map<string, ReturnType<typeof convertToFragmentProps>>();\n const propsResults = new Map<string, PropsExtractionResult>();\n let propsExtracted = 0;\n\n for (const comp of components) {\n try {\n const extraction = await extractPropsFromFile(comp.sourcePath, {\n propsTypeName: `${comp.name}Props`,\n componentName: comp.name,\n });\n\n propsResults.set(comp.name, extraction);\n\n if (extraction.success && extraction.props.length > 0) {\n propsMap.set(comp.name, convertToFragmentProps(extraction.props));\n propsExtracted++;\n }\n } catch (e) {\n if (options.verbose) {\n warnings.push({\n component: comp.name,\n warning: `Props extraction failed: ${e instanceof Error ? e.message : String(e)}`,\n });\n }\n }\n }\n\n log(pc.green(` Extracted props for ${propsExtracted} components`));\n\n // Phase 3: Scan for usage patterns\n let usageAnalysis: UsageAnalysis | undefined;\n let usagesFound = 0;\n let allRelations = new Map<string, ComponentRelation[]>();\n\n if (!options.skipUsage) {\n log(pc.dim(\"\\nPhase 3: Scanning for usage patterns...\"));\n const usageDir = options.usageDir || configDir;\n\n try {\n // Get component names for filtering\n const componentNames = components.map((c) => c.name);\n\n usageAnalysis = await scanCodebase({\n rootDir: usageDir,\n include: [\"**/*.tsx\", \"**/*.ts\", \"**/*.jsx\", \"**/*.js\"],\n exclude: [\n \"**/node_modules/**\",\n \"**/dist/**\",\n \"**/*.stories.*\",\n \"**/*.test.*\",\n \"**/*.spec.*\",\n ],\n componentNames,\n useCache: true,\n });\n\n // Count total usages across all components\n usagesFound = Object.values(usageAnalysis.components).reduce(\n (sum, comp) => sum + comp.totalUsages,\n 0\n );\n\n // Infer relations\n allRelations = inferAllRelations(usageAnalysis);\n log(pc.green(` Found ${usagesFound} usages across ${usageAnalysis.totalFiles} files`));\n log(pc.green(` Inferred relations for ${allRelations.size} components`));\n } catch (e) {\n warnings.push({\n component: \"*\",\n warning: `Usage scanning failed: ${e instanceof Error ? e.message : String(e)}`,\n });\n log(pc.yellow(` Usage scanning failed: ${e instanceof Error ? e.message : \"unknown error\"}`));\n }\n } else {\n log(pc.dim(\"\\nPhase 3: Skipping usage analysis\"));\n }\n\n // Phase 4: Parse Storybook stories\n const storiesMap = new Map<string, ParsedStoryFile>();\n let storiesParsed = 0;\n\n if (!options.skipStorybook) {\n log(pc.dim(\"\\nPhase 4: Parsing Storybook stories...\"));\n\n try {\n const allStories = await parseAllStories(configDir);\n\n for (const [name, stories] of Object.entries(allStories)) {\n if (stories && stories.stories.length > 0) {\n storiesMap.set(name, stories);\n storiesParsed++;\n }\n }\n\n log(pc.green(` Parsed stories for ${storiesParsed} components`));\n } catch (e) {\n warnings.push({\n component: \"*\",\n warning: `Storybook parsing failed: ${e instanceof Error ? e.message : String(e)}`,\n });\n log(pc.yellow(` Storybook parsing failed: ${e instanceof Error ? e.message : \"unknown error\"}`));\n }\n } else {\n log(pc.dim(\"\\nPhase 4: Skipping Storybook parsing\"));\n }\n\n // Phase 5: Generate fragments\n log(pc.dim(\"\\nPhase 5: Generating fragments...\"));\n const fragments: Record<string, CompiledFragment> = {};\n\n for (const comp of components) {\n try {\n const fragment = generateFragmentFromData(\n comp,\n configDir,\n propsMap.get(comp.name),\n usageAnalysis?.components[comp.name],\n allRelations.get(comp.name),\n storiesMap.get(comp.name)\n );\n\n fragments[comp.name] = fragment;\n } catch (e) {\n errors.push({\n component: comp.name,\n error: e instanceof Error ? e.message : String(e),\n });\n }\n }\n\n // Write output\n const outputPath = resolve(configDir, outputFile);\n await mkdir(dirname(outputPath), { recursive: true });\n\n const output: CompiledFragmentsFile = {\n version: \"1.0.0\",\n generatedAt: new Date().toISOString(),\n fragments,\n };\n\n await writeFile(outputPath, JSON.stringify(output, null, 2));\n\n const elapsed = ((Date.now() - startTime) / 1000).toFixed(1);\n\n // Summary\n log(pc.dim(\"\\n────────────────────────────────────────\"));\n log(pc.green(`\\n✓ Generated fragments.json in ${elapsed}s`));\n log(pc.dim(` Output: ${relative(process.cwd(), outputPath)}`));\n log(pc.dim(` Components: ${Object.keys(fragments).length}`));\n log(pc.dim(` Props extracted: ${propsExtracted}`));\n log(pc.dim(` Usages found: ${usagesFound}`));\n log(pc.dim(` Relations inferred: ${allRelations.size}`));\n log(pc.dim(` Stories parsed: ${storiesParsed}`));\n\n if (warnings.length > 0) {\n log(pc.yellow(`\\n ${warnings.length} warning(s)`));\n if (options.verbose) {\n for (const w of warnings) {\n log(pc.dim(` ${w.component}: ${w.warning}`));\n }\n }\n }\n\n if (errors.length > 0) {\n log(pc.red(`\\n ${errors.length} error(s)`));\n for (const e of errors) {\n log(pc.dim(` ${e.component}: ${e.error}`));\n }\n }\n\n log();\n\n return {\n success: errors.length === 0,\n outputPath,\n componentCount: Object.keys(fragments).length,\n propsExtracted,\n usagesFound,\n relationsInferred: allRelations.size,\n storiesParsed,\n errors,\n warnings,\n };\n}\n\n/**\n * Generate a CompiledFragment from extracted data\n */\nfunction generateFragmentFromData(\n comp: DiscoveredComponent,\n configDir: string,\n props: Record<string, PropDefinition> | undefined,\n usageAnalysis: UsageAnalysis[\"components\"][string] | undefined,\n relations: ComponentRelation[] | undefined,\n storyFile: ParsedStoryFile | undefined\n): CompiledFragment {\n // Generate context for AI suggestions\n const context = generateComponentContext(\n comp.name,\n usageAnalysis,\n undefined, // No extracted docs yet\n storyFile,\n undefined, // No props extraction result (we have the converted props already)\n relations\n );\n\n // Generate enhancement suggestions from context\n const suggestions = generateEnhancementSuggestions(context);\n\n // Filter boilerplate from suggestions\n const when = filterBoilerplate(suggestions.suggestions.when);\n const whenNot = filterBoilerplate(suggestions.suggestions.whenNot);\n\n // Infer category from path\n const category = inferCategory(comp.relativePath);\n\n // Infer status from path\n const status = inferStatus(comp.relativePath);\n\n // Build variants from stories\n const variants: CompiledFragment[\"variants\"] = [];\n if (storyFile?.stories) {\n for (const story of storyFile.stories) {\n variants.push({\n name: story.name,\n description: story.description || `${story.displayName} variant`,\n code: story.code,\n });\n }\n }\n\n // Build relations\n const compiledRelations: CompiledFragment[\"relations\"] = [];\n if (relations && relations.length > 0) {\n for (const rel of relations.slice(0, 10)) {\n compiledRelations.push({\n component: rel.component,\n relationship: rel.relationship,\n note: `Appears together ${rel.frequency} times`,\n });\n }\n }\n\n // Generate description\n const description = generateDescription(comp.name, props, usageAnalysis);\n\n return {\n filePath: comp.relativePath,\n meta: {\n name: comp.name,\n description,\n category,\n status,\n },\n usage: {\n when: when.length > 0 ? when : [`Use ${comp.name} for its intended purpose`],\n whenNot: whenNot,\n },\n props: props || {},\n relations: compiledRelations.length > 0 ? compiledRelations : undefined,\n variants,\n _generated: {\n source: \"ai\",\n sourceFile: comp.relativePath,\n confidence: calculateConfidence(props, usageAnalysis, storyFile),\n timestamp: new Date().toISOString(),\n },\n };\n}\n\n/**\n * Infer category from file path\n */\nfunction inferCategory(relativePath: string): string {\n const parts = relativePath.toLowerCase().split(\"/\");\n\n // Common category patterns\n const categoryPatterns: Record<string, string[]> = {\n \"Actions\": [\"button\", \"action\", \"cta\"],\n \"Forms\": [\"form\", \"input\", \"select\", \"checkbox\", \"radio\", \"textarea\", \"field\"],\n \"Layout\": [\"layout\", \"container\", \"grid\", \"flex\", \"stack\", \"box\", \"divider\", \"spacer\"],\n \"Navigation\": [\"nav\", \"menu\", \"breadcrumb\", \"tab\", \"link\", \"pagination\"],\n \"Feedback\": [\"alert\", \"toast\", \"notification\", \"message\", \"badge\", \"indicator\", \"progress\", \"spinner\", \"loading\"],\n \"Data Display\": [\"table\", \"list\", \"card\", \"avatar\", \"stat\", \"timeline\", \"tree\"],\n \"Overlays\": [\"modal\", \"dialog\", \"drawer\", \"popover\", \"tooltip\", \"dropdown\"],\n \"Typography\": [\"text\", \"heading\", \"title\", \"label\", \"paragraph\"],\n \"Media\": [\"image\", \"video\", \"icon\", \"avatar\"],\n };\n\n for (const [category, patterns] of Object.entries(categoryPatterns)) {\n for (const pattern of patterns) {\n if (parts.some((part) => part.includes(pattern))) {\n return category;\n }\n }\n }\n\n // Check path structure for category\n const componentIdx = parts.findIndex((p) => p === \"components\");\n if (componentIdx !== -1 && parts.length > componentIdx + 1) {\n const categoryPart = parts[componentIdx + 1];\n return categoryPart.charAt(0).toUpperCase() + categoryPart.slice(1);\n }\n\n return \"Components\";\n}\n\n/**\n * Infer status from file path\n */\nfunction inferStatus(\n relativePath: string\n): \"stable\" | \"beta\" | \"experimental\" | \"deprecated\" {\n const lowerPath = relativePath.toLowerCase();\n\n if (lowerPath.includes(\"/experimental/\") || lowerPath.includes(\"/labs/\")) {\n return \"experimental\";\n }\n if (lowerPath.includes(\"/beta/\")) {\n return \"beta\";\n }\n if (lowerPath.includes(\"/deprecated/\") || lowerPath.includes(\"/legacy/\")) {\n return \"deprecated\";\n }\n\n return \"stable\";\n}\n\n/**\n * Generate component description\n */\nfunction generateDescription(\n name: string,\n props: Record<string, PropDefinition> | undefined,\n usageAnalysis: UsageAnalysis[\"components\"][string] | undefined\n): string {\n // Convert name to readable form\n const words = name\n .replace(/([A-Z])/g, \" $1\")\n .trim()\n .toLowerCase();\n\n // Check props for hints\n const hasOnClick = props && (\"onClick\" in props || \"onPress\" in props);\n const hasValue = props && (\"value\" in props || \"defaultValue\" in props);\n const hasChildren = props && \"children\" in props;\n const hasHref = props && \"href\" in props;\n\n // Check usage contexts\n const topContext = usageAnalysis?.contexts[0]?.type;\n\n if (hasHref) {\n return `Navigational ${words} for linking to other pages or resources`;\n }\n\n if (hasOnClick && !hasValue) {\n return `Interactive ${words} for triggering actions`;\n }\n\n if (hasValue) {\n return `Form ${words} for user input`;\n }\n\n if (topContext && topContext !== \"unknown\") {\n return `${words.charAt(0).toUpperCase() + words.slice(1)} commonly used in ${topContext} contexts`;\n }\n\n if (hasChildren) {\n return `Container ${words} for composing UI`;\n }\n\n return `${words.charAt(0).toUpperCase() + words.slice(1)} component`;\n}\n\n/**\n * Calculate confidence score based on available data\n */\nfunction calculateConfidence(\n props: Record<string, PropDefinition> | undefined,\n usageAnalysis: UsageAnalysis[\"components\"][string] | undefined,\n storyFile: ParsedStoryFile | undefined\n): number {\n let confidence = 0;\n\n // Props give +30 confidence\n if (props && Object.keys(props).length > 0) {\n confidence += 30;\n }\n\n // Usage data gives up to +40 confidence\n if (usageAnalysis) {\n if (usageAnalysis.totalUsages > 10) confidence += 40;\n else if (usageAnalysis.totalUsages > 5) confidence += 30;\n else if (usageAnalysis.totalUsages > 0) confidence += 20;\n }\n\n // Stories give +30 confidence\n if (storyFile && storyFile.stories.length > 0) {\n confidence += 30;\n }\n\n return Math.min(confidence, 100);\n}\n"],"mappings":"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","names":[]}
|
|
@@ -35,7 +35,23 @@ function createComponentExtractor(tsconfigPath) {
|
|
|
35
35
|
readFile: ts.sys.readFile,
|
|
36
36
|
readDirectory: ts.sys.readDirectory,
|
|
37
37
|
directoryExists: ts.sys.directoryExists,
|
|
38
|
-
getDirectories: ts.sys.getDirectories
|
|
38
|
+
getDirectories: ts.sys.getDirectories,
|
|
39
|
+
resolveModuleNames: (moduleNames, containingFile) => moduleNames.map((moduleName) => {
|
|
40
|
+
const resolved = ts.resolveModuleName(
|
|
41
|
+
moduleName,
|
|
42
|
+
containingFile,
|
|
43
|
+
parsedCommandLine.options,
|
|
44
|
+
{
|
|
45
|
+
fileExists: ts.sys.fileExists,
|
|
46
|
+
readFile: ts.sys.readFile,
|
|
47
|
+
realpath: ts.sys.realpath,
|
|
48
|
+
directoryExists: ts.sys.directoryExists,
|
|
49
|
+
getDirectories: ts.sys.getDirectories,
|
|
50
|
+
getCurrentDirectory: () => rootDir
|
|
51
|
+
}
|
|
52
|
+
);
|
|
53
|
+
return resolved.resolvedModule;
|
|
54
|
+
})
|
|
39
55
|
};
|
|
40
56
|
const languageService = ts.createLanguageService(host, ts.createDocumentRegistry());
|
|
41
57
|
function ensureFile(filePath) {
|
|
@@ -349,7 +365,23 @@ function extractPropsFromFunctionLike(checker, func) {
|
|
|
349
365
|
const firstParam = func.parameters[0];
|
|
350
366
|
if (!firstParam) return null;
|
|
351
367
|
if (firstParam.type) {
|
|
352
|
-
|
|
368
|
+
const directType = checker.getTypeFromTypeNode(firstParam.type);
|
|
369
|
+
if (checker.getPropertiesOfType(directType).length > 0) {
|
|
370
|
+
return directType;
|
|
371
|
+
}
|
|
372
|
+
const apparentType = checker.getApparentType(directType);
|
|
373
|
+
if (checker.getPropertiesOfType(apparentType).length > 0) {
|
|
374
|
+
return apparentType;
|
|
375
|
+
}
|
|
376
|
+
const paramType = checker.getTypeAtLocation(firstParam);
|
|
377
|
+
if (checker.getPropertiesOfType(paramType).length > 0) {
|
|
378
|
+
return paramType;
|
|
379
|
+
}
|
|
380
|
+
const constrainedType = checker.getBaseConstraintOfType(directType);
|
|
381
|
+
if (constrainedType && checker.getPropertiesOfType(constrainedType).length > 0) {
|
|
382
|
+
return constrainedType;
|
|
383
|
+
}
|
|
384
|
+
return directType;
|
|
353
385
|
}
|
|
354
386
|
const paramSymbol = checker.getSymbolAtLocation(firstParam.name);
|
|
355
387
|
if (paramSymbol) {
|
|
@@ -362,6 +394,24 @@ function buildComponentMeta(checker, component, filePath, sourceFile, moduleExpo
|
|
|
362
394
|
const sourceFilePath = toPosixPath(sourceFile.fileName);
|
|
363
395
|
if (component.propsType) {
|
|
364
396
|
extractPropsFromType(checker, component.propsType, props, sourceFilePath);
|
|
397
|
+
if (Object.keys(props).length === 0) {
|
|
398
|
+
const apparentPropsType = checker.getApparentType(component.propsType);
|
|
399
|
+
if (apparentPropsType !== component.propsType) {
|
|
400
|
+
extractPropsFromType(checker, apparentPropsType, props, sourceFilePath);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
if (Object.keys(props).length === 0) {
|
|
404
|
+
const constrainedPropsType = checker.getBaseConstraintOfType(component.propsType);
|
|
405
|
+
if (constrainedPropsType) {
|
|
406
|
+
extractPropsFromType(checker, constrainedPropsType, props, sourceFilePath);
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
const destructuredProps = component.componentNode ? extractDestructuredPropNames(component.componentNode) : /* @__PURE__ */ new Set();
|
|
411
|
+
for (const propName of destructuredProps) {
|
|
412
|
+
if (props[propName]) {
|
|
413
|
+
props[propName].source = "local";
|
|
414
|
+
}
|
|
365
415
|
}
|
|
366
416
|
const defaults = component.componentNode ? extractDefaultValues(component.componentNode) : {};
|
|
367
417
|
for (const [propName, defaultVal] of Object.entries(defaults)) {
|
|
@@ -518,6 +568,25 @@ function extractDefaultValues(node) {
|
|
|
518
568
|
}
|
|
519
569
|
return defaults;
|
|
520
570
|
}
|
|
571
|
+
function extractDestructuredPropNames(node) {
|
|
572
|
+
const names = /* @__PURE__ */ new Set();
|
|
573
|
+
let funcNode = null;
|
|
574
|
+
if (ts.isFunctionDeclaration(node) || ts.isArrowFunction(node) || ts.isFunctionExpression(node)) {
|
|
575
|
+
funcNode = node;
|
|
576
|
+
}
|
|
577
|
+
if (!funcNode?.parameters?.length) return names;
|
|
578
|
+
const firstParam = funcNode.parameters[0];
|
|
579
|
+
if (!ts.isObjectBindingPattern(firstParam.name)) return names;
|
|
580
|
+
for (const element of firstParam.name.elements) {
|
|
581
|
+
if (element.dotDotDotToken || !ts.isIdentifier(element.name)) continue;
|
|
582
|
+
const propName = element.propertyName ? element.propertyName.getText() : element.name.text;
|
|
583
|
+
if (propName === "className" || propName === "children" || propName === "ref") {
|
|
584
|
+
continue;
|
|
585
|
+
}
|
|
586
|
+
names.add(propName);
|
|
587
|
+
}
|
|
588
|
+
return names;
|
|
589
|
+
}
|
|
521
590
|
function readLiteralValue(expression) {
|
|
522
591
|
if (ts.isStringLiteral(expression) || ts.isNoSubstitutionTemplateLiteral(expression)) {
|
|
523
592
|
return expression.text;
|
|
@@ -623,4 +692,4 @@ function toPosixPath(filePath) {
|
|
|
623
692
|
export {
|
|
624
693
|
createComponentExtractor
|
|
625
694
|
};
|
|
626
|
-
//# sourceMappingURL=chunk-
|
|
695
|
+
//# sourceMappingURL=chunk-MN3TJ3D5.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/component-extractor.ts"],"sourcesContent":["/**\n * ComponentExtractor — persistent LanguageService-based prop extraction.\n *\n * Replaces auto-props.ts with:\n * - Persistent ts.LanguageService (not throwaway ts.createProgram())\n * - Incremental invalidation via projectVersion\n * - Compound component (Object.assign) sub-component prop extraction\n * - Full type serialization to PropMeta format\n *\n * Zero additional dependencies — uses raw TypeScript APIs.\n */\n\nimport ts from 'typescript';\nimport { existsSync, readFileSync, statSync, readdirSync } from 'node:fs';\nimport { resolve, dirname, join } from 'node:path';\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\nexport interface ComponentExtractor {\n /** Extract metadata for a single component by export name */\n extract(filePath: string, exportName?: string): ComponentMeta | null;\n\n /** Extract all exported components found in a file */\n extractAll(filePath: string): ComponentMeta[];\n\n /** Notify extractor that a file changed (incremental) */\n invalidate(filePath: string): void;\n\n /** Clean up resources */\n dispose(): void;\n}\n\nexport interface ComponentMeta {\n name: string;\n filePath: string;\n description: string;\n props: Record<string, PropMeta>;\n composition: CompositionMeta | null;\n exports: string[];\n dependencies: string[];\n}\n\nexport interface PropMeta {\n name: string;\n type: string;\n typeKind: PropTypeKind;\n values?: string[];\n default?: string;\n description?: string;\n required: boolean;\n source: 'local' | 'inherited';\n}\n\nexport type PropTypeKind =\n | 'string' | 'number' | 'boolean'\n | 'enum'\n | 'function'\n | 'node'\n | 'element'\n | 'object' | 'array'\n | 'union'\n | 'custom';\n\nexport interface CompositionMeta {\n pattern: 'compound' | 'controlled' | 'simple';\n parts: PartMeta[];\n required: string[];\n}\n\nexport interface PartMeta {\n name: string;\n props: Record<string, PropMeta>;\n}\n\n// ---------------------------------------------------------------------------\n// Internal types\n// ---------------------------------------------------------------------------\n\ninterface ResolvedComponent {\n name: string;\n propsType: ts.Type | null;\n componentNode: ts.Node | null;\n compoundParts: Map<string, ts.Type> | null;\n}\n\n// ---------------------------------------------------------------------------\n// Factory\n// ---------------------------------------------------------------------------\n\nexport function createComponentExtractor(tsconfigPath?: string): ComponentExtractor {\n let projectVersion = 0;\n const fileVersions = new Map<string, number>();\n const fileSnapshots = new Map<string, ts.IScriptSnapshot>();\n\n // Parse tsconfig or use inferred settings\n const rootDir = tsconfigPath ? dirname(resolve(tsconfigPath)) : process.cwd();\n const parsedCommandLine = tsconfigPath\n ? parseTsConfig(tsconfigPath)\n : inferCompilerOptions(rootDir);\n\n const scriptFileNames = new Set(parsedCommandLine.fileNames);\n\n const host: ts.LanguageServiceHost = {\n getProjectVersion: () => projectVersion.toString(),\n getScriptVersion: (fileName) => (fileVersions.get(fileName) ?? 0).toString(),\n getScriptSnapshot: (fileName) => {\n const cached = fileSnapshots.get(fileName);\n if (cached) return cached;\n\n let text: string;\n try {\n text = readFileSync(fileName, 'utf-8');\n } catch {\n return undefined;\n }\n const snapshot = ts.ScriptSnapshot.fromString(text);\n fileSnapshots.set(fileName, snapshot);\n return snapshot;\n },\n getScriptFileNames: () => [...scriptFileNames],\n getCompilationSettings: () => parsedCommandLine.options,\n getCurrentDirectory: () => rootDir,\n getDefaultLibFileName: ts.getDefaultLibFilePath,\n fileExists: ts.sys.fileExists,\n readFile: ts.sys.readFile,\n readDirectory: ts.sys.readDirectory,\n directoryExists: ts.sys.directoryExists,\n getDirectories: ts.sys.getDirectories,\n resolveModuleNames: (moduleNames, containingFile) =>\n moduleNames.map((moduleName) => {\n const resolved = ts.resolveModuleName(\n moduleName,\n containingFile,\n parsedCommandLine.options,\n {\n fileExists: ts.sys.fileExists,\n readFile: ts.sys.readFile,\n realpath: ts.sys.realpath,\n directoryExists: ts.sys.directoryExists,\n getDirectories: ts.sys.getDirectories,\n getCurrentDirectory: () => rootDir,\n }\n );\n\n return resolved.resolvedModule;\n }),\n };\n\n const languageService = ts.createLanguageService(host, ts.createDocumentRegistry());\n\n function ensureFile(filePath: string): void {\n const resolved = resolve(filePath);\n if (!scriptFileNames.has(resolved)) {\n scriptFileNames.add(resolved);\n projectVersion++;\n }\n }\n\n function getChecker(): ts.TypeChecker {\n const program = languageService.getProgram();\n if (!program) throw new Error('Failed to get program from LanguageService');\n return program.getTypeChecker();\n }\n\n function getSourceFile(filePath: string): ts.SourceFile | undefined {\n return languageService.getProgram()?.getSourceFile(resolve(filePath));\n }\n\n return {\n extract(filePath: string, exportName?: string): ComponentMeta | null {\n const resolved = resolve(filePath);\n ensureFile(resolved);\n\n const sourceFile = getSourceFile(resolved);\n if (!sourceFile) return null;\n\n const checker = getChecker();\n const moduleSymbol = checker.getSymbolAtLocation(sourceFile);\n if (!moduleSymbol) return null;\n\n const exports = checker.getExportsOfModule(moduleSymbol);\n const targetName = exportName ?? findPrimaryExport(exports, sourceFile);\n if (!targetName) return null;\n\n const exportSymbol = exports.find(s => s.getName() === targetName);\n if (!exportSymbol) return null;\n\n const component = resolveExportedComponent(checker, exportSymbol, sourceFile);\n if (!component) return null;\n\n return buildComponentMeta(checker, component, resolved, sourceFile, exports);\n },\n\n extractAll(filePath: string): ComponentMeta[] {\n const resolved = resolve(filePath);\n ensureFile(resolved);\n\n const sourceFile = getSourceFile(resolved);\n if (!sourceFile) return [];\n\n const checker = getChecker();\n const moduleSymbol = checker.getSymbolAtLocation(sourceFile);\n if (!moduleSymbol) return [];\n\n const exports = checker.getExportsOfModule(moduleSymbol);\n const results: ComponentMeta[] = [];\n\n for (const exportSymbol of exports) {\n const name = exportSymbol.getName();\n // Only consider PascalCase exports as potential components\n if (!/^[A-Z]/.test(name)) continue;\n\n const component = resolveExportedComponent(checker, exportSymbol, sourceFile);\n if (!component) continue;\n\n const meta = buildComponentMeta(checker, component, resolved, sourceFile, exports);\n if (meta) results.push(meta);\n }\n\n return results;\n },\n\n invalidate(filePath: string): void {\n const resolved = resolve(filePath);\n fileVersions.set(resolved, (fileVersions.get(resolved) ?? 0) + 1);\n fileSnapshots.delete(resolved);\n projectVersion++;\n },\n\n dispose(): void {\n languageService.dispose();\n fileSnapshots.clear();\n fileVersions.clear();\n },\n };\n}\n\n// ---------------------------------------------------------------------------\n// tsconfig parsing\n// ---------------------------------------------------------------------------\n\nfunction parseTsConfig(tsconfigPath: string): ts.ParsedCommandLine {\n const resolved = resolve(tsconfigPath);\n const configFile = ts.readConfigFile(resolved, ts.sys.readFile);\n if (configFile.error) {\n throw new Error(`Failed to read tsconfig: ${ts.flattenDiagnosticMessageText(configFile.error.messageText, '\\n')}`);\n }\n\n return ts.parseJsonConfigFileContent(\n configFile.config,\n ts.sys,\n dirname(resolved),\n undefined,\n resolved,\n );\n}\n\nfunction inferCompilerOptions(rootDir: string): ts.ParsedCommandLine {\n return {\n options: {\n target: ts.ScriptTarget.ES2022,\n module: ts.ModuleKind.ESNext,\n moduleResolution: ts.ModuleResolutionKind.Bundler,\n jsx: ts.JsxEmit.ReactJSX,\n allowSyntheticDefaultImports: true,\n esModuleInterop: true,\n skipLibCheck: true,\n strict: false,\n noEmit: true,\n },\n fileNames: [],\n errors: [],\n };\n}\n\n// ---------------------------------------------------------------------------\n// Export resolution\n// ---------------------------------------------------------------------------\n\n/**\n * Find the \"primary\" export — prefers the default export or the first PascalCase export.\n */\nfunction findPrimaryExport(exports: ts.Symbol[], sourceFile: ts.SourceFile): string | null {\n // Default export\n const defaultExport = exports.find(s => s.getName() === 'default');\n if (defaultExport) return 'default';\n\n // First PascalCase named export\n for (const s of exports) {\n if (/^[A-Z][a-zA-Z0-9]*$/.test(s.getName())) {\n return s.getName();\n }\n }\n\n return null;\n}\n\n/**\n * Resolve an export symbol to a component with its props type.\n * Handles: direct functions, forwardRef, memo, Object.assign, FC<Props>.\n */\nfunction resolveExportedComponent(\n checker: ts.TypeChecker,\n exportSymbol: ts.Symbol,\n sourceFile: ts.SourceFile,\n): ResolvedComponent | null {\n const name = exportSymbol.getName();\n\n // Follow aliases (re-exports)\n let symbol = exportSymbol;\n if (symbol.flags & ts.SymbolFlags.Alias) {\n symbol = checker.getAliasedSymbol(symbol);\n }\n\n const declarations = symbol.getDeclarations();\n if (!declarations || declarations.length === 0) return null;\n\n const declaration = declarations[0];\n\n // Variable declaration: const X = ... (forwardRef, memo, Object.assign, arrow, FC)\n if (ts.isVariableDeclaration(declaration) && declaration.initializer) {\n return resolveFromExpression(checker, name, declaration.initializer, declaration, sourceFile);\n }\n\n // Function declaration: function X(props: Props) { ... }\n if (ts.isFunctionDeclaration(declaration)) {\n const propsType = extractPropsFromFunctionLike(checker, declaration);\n return propsType ? { name, propsType, componentNode: declaration, compoundParts: null } : null;\n }\n\n // Export assignment: export default X\n if (ts.isExportAssignment(declaration) && declaration.expression) {\n return resolveFromExpression(checker, name, declaration.expression, null, sourceFile);\n }\n\n return null;\n}\n\nfunction resolveFromExpression(\n checker: ts.TypeChecker,\n name: string,\n expression: ts.Expression,\n variableDecl: ts.VariableDeclaration | null,\n sourceFile: ts.SourceFile,\n): ResolvedComponent | null {\n // Unwrap parentheses, type assertions\n expression = unwrapExpression(expression);\n\n // Arrow function or function expression\n if (ts.isArrowFunction(expression) || ts.isFunctionExpression(expression)) {\n const propsType = extractPropsFromFunctionLike(checker, expression);\n return propsType ? { name, propsType, componentNode: expression, compoundParts: null } : null;\n }\n\n // Call expression: React.forwardRef, React.memo, Object.assign\n if (ts.isCallExpression(expression)) {\n return resolveCallExpression(checker, name, expression, variableDecl, sourceFile);\n }\n\n // Identifier reference — follow to its declaration\n if (ts.isIdentifier(expression)) {\n const sym = checker.getSymbolAtLocation(expression);\n if (sym) {\n const decls = sym.getDeclarations();\n if (decls && decls.length > 0) {\n const decl = decls[0];\n if (ts.isVariableDeclaration(decl) && decl.initializer) {\n return resolveFromExpression(checker, name, decl.initializer, decl, sourceFile);\n }\n if (ts.isFunctionDeclaration(decl)) {\n const propsType = extractPropsFromFunctionLike(checker, decl);\n return propsType ? { name, propsType, componentNode: decl, compoundParts: null } : null;\n }\n }\n }\n }\n\n // FC<Props> typed variable\n if (variableDecl?.type && ts.isTypeReferenceNode(variableDecl.type)) {\n const typeName = variableDecl.type.typeName.getText(sourceFile);\n if (typeName.includes('FC') || typeName.includes('FunctionComponent')) {\n const typeArg = variableDecl.type.typeArguments?.[0];\n if (typeArg) {\n const propsType = checker.getTypeFromTypeNode(typeArg);\n return { name, propsType, componentNode: expression, compoundParts: null };\n }\n }\n }\n\n return null;\n}\n\nfunction resolveCallExpression(\n checker: ts.TypeChecker,\n name: string,\n call: ts.CallExpression,\n variableDecl: ts.VariableDeclaration | null,\n sourceFile: ts.SourceFile,\n): ResolvedComponent | null {\n const callee = call.expression;\n\n // Object.assign(Root, { Header, Body, ... })\n if (isObjectAssignCall(callee, sourceFile)) {\n return resolveObjectAssign(checker, name, call, sourceFile);\n }\n\n // React.forwardRef<Ref, Props>(fn) or forwardRef<Ref, Props>(fn)\n if (isForwardRefCall(callee)) {\n return resolveForwardRef(checker, name, call, sourceFile);\n }\n\n // React.memo(Component) or memo(Component)\n if (isMemoCall(callee)) {\n const innerArg = call.arguments[0];\n if (innerArg) {\n return resolveFromExpression(checker, name, innerArg, variableDecl, sourceFile);\n }\n }\n\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Object.assign compound component resolution\n// ---------------------------------------------------------------------------\n\nfunction resolveObjectAssign(\n checker: ts.TypeChecker,\n name: string,\n call: ts.CallExpression,\n sourceFile: ts.SourceFile,\n): ResolvedComponent | null {\n if (call.arguments.length < 2) return null;\n\n // First arg is the root component\n const rootExpr = call.arguments[0];\n const rootResult = resolveFromExpression(checker, name, rootExpr, null, sourceFile);\n\n // Second arg is the object literal with sub-components\n const subsArg = call.arguments[1];\n const compoundParts = new Map<string, ts.Type>();\n\n if (ts.isObjectLiteralExpression(subsArg)) {\n for (const prop of subsArg.properties) {\n let subName: string | null = null;\n let subExpression: ts.Expression | null = null;\n\n if (ts.isShorthandPropertyAssignment(prop)) {\n subName = prop.name.text;\n // Resolve the identifier to its type\n const sym = checker.getSymbolAtLocation(prop.name);\n if (sym) {\n const subPropsType = extractPropsFromComponentSymbol(checker, sym);\n if (subPropsType) {\n compoundParts.set(subName, subPropsType);\n }\n }\n } else if (ts.isPropertyAssignment(prop) && ts.isIdentifier(prop.name)) {\n subName = prop.name.text;\n subExpression = prop.initializer;\n if (subExpression) {\n const subType = extractPropsFromExpression(checker, subExpression, sourceFile);\n if (subType) {\n compoundParts.set(subName, subType);\n }\n }\n }\n }\n }\n\n return {\n name,\n propsType: rootResult?.propsType ?? null,\n componentNode: rootResult?.componentNode ?? rootExpr,\n compoundParts: compoundParts.size > 0 ? compoundParts : null,\n };\n}\n\n/**\n * Extract props type from a component symbol (function, variable, etc.)\n */\nfunction extractPropsFromComponentSymbol(checker: ts.TypeChecker, symbol: ts.Symbol): ts.Type | null {\n // Follow aliases\n let sym = symbol;\n if (sym.flags & ts.SymbolFlags.Alias) {\n sym = checker.getAliasedSymbol(sym);\n }\n\n const decls = sym.getDeclarations();\n if (!decls || decls.length === 0) return null;\n\n const decl = decls[0];\n\n if (ts.isFunctionDeclaration(decl)) {\n return extractPropsFromFunctionLike(checker, decl);\n }\n\n if (ts.isVariableDeclaration(decl) && decl.initializer) {\n // forwardRef, memo, arrow function, etc.\n return extractPropsFromExpressionDeep(checker, decl);\n }\n\n return null;\n}\n\n/**\n * Extract props type from an arbitrary expression (used for Object.assign values).\n */\nfunction extractPropsFromExpression(checker: ts.TypeChecker, expr: ts.Expression, sourceFile: ts.SourceFile): ts.Type | null {\n expr = unwrapExpression(expr);\n\n if (ts.isIdentifier(expr)) {\n const sym = checker.getSymbolAtLocation(expr);\n if (sym) return extractPropsFromComponentSymbol(checker, sym);\n }\n\n if (ts.isArrowFunction(expr) || ts.isFunctionExpression(expr)) {\n return extractPropsFromFunctionLike(checker, expr);\n }\n\n if (ts.isCallExpression(expr)) {\n if (isForwardRefCall(expr.expression)) {\n const typeArg = expr.typeArguments?.[1];\n if (typeArg) return checker.getTypeFromTypeNode(typeArg);\n const innerArg = expr.arguments[0];\n if (innerArg && (ts.isArrowFunction(innerArg) || ts.isFunctionExpression(innerArg))) {\n return extractPropsFromFunctionLike(checker, innerArg);\n }\n }\n if (isMemoCall(expr.expression) && expr.arguments[0]) {\n return extractPropsFromExpression(checker, expr.arguments[0], sourceFile);\n }\n }\n\n return null;\n}\n\n/**\n * Deep extraction from a variable declaration.\n */\nfunction extractPropsFromExpressionDeep(checker: ts.TypeChecker, decl: ts.VariableDeclaration): ts.Type | null {\n if (!decl.initializer) return null;\n const expr = unwrapExpression(decl.initializer);\n\n if (ts.isArrowFunction(expr) || ts.isFunctionExpression(expr)) {\n return extractPropsFromFunctionLike(checker, expr);\n }\n\n if (ts.isCallExpression(expr)) {\n if (isForwardRefCall(expr.expression)) {\n const typeArg = expr.typeArguments?.[1];\n if (typeArg) return checker.getTypeFromTypeNode(typeArg);\n const innerArg = expr.arguments[0];\n if (innerArg && (ts.isArrowFunction(innerArg) || ts.isFunctionExpression(innerArg))) {\n return extractPropsFromFunctionLike(checker, innerArg);\n }\n }\n if (isMemoCall(expr.expression) && expr.arguments[0]) {\n return extractPropsFromExpressionDeep(checker, {\n ...decl,\n initializer: expr.arguments[0],\n } as ts.VariableDeclaration);\n }\n }\n\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// forwardRef resolution\n// ---------------------------------------------------------------------------\n\nfunction resolveForwardRef(\n checker: ts.TypeChecker,\n name: string,\n call: ts.CallExpression,\n sourceFile: ts.SourceFile,\n): ResolvedComponent | null {\n // Try type arguments first: forwardRef<Ref, Props>(...)\n const propsTypeArg = call.typeArguments?.[1];\n if (propsTypeArg) {\n const propsType = checker.getTypeFromTypeNode(propsTypeArg);\n const innerArg = call.arguments[0];\n const componentNode = innerArg && (ts.isArrowFunction(innerArg) || ts.isFunctionExpression(innerArg))\n ? innerArg : null;\n return { name, propsType, componentNode, compoundParts: null };\n }\n\n // Fall back to inner function's parameter type\n const innerArg = call.arguments[0];\n if (innerArg) {\n if (ts.isArrowFunction(innerArg) || ts.isFunctionExpression(innerArg)) {\n const propsType = extractPropsFromFunctionLike(checker, innerArg);\n return propsType ? { name, propsType, componentNode: innerArg, compoundParts: null } : null;\n }\n if (ts.isIdentifier(innerArg)) {\n const sym = checker.getSymbolAtLocation(innerArg);\n if (sym) {\n const propsType = extractPropsFromComponentSymbol(checker, sym);\n if (propsType) return { name, propsType, componentNode: innerArg, compoundParts: null };\n }\n }\n }\n\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Props extraction from function-like declarations\n// ---------------------------------------------------------------------------\n\n/**\n * Extract the props type from a function's first parameter.\n */\nfunction extractPropsFromFunctionLike(\n checker: ts.TypeChecker,\n func: ts.FunctionLikeDeclaration,\n): ts.Type | null {\n const firstParam = func.parameters[0];\n if (!firstParam) return null;\n\n // If there's a type annotation, use it\n if (firstParam.type) {\n const directType = checker.getTypeFromTypeNode(firstParam.type);\n if (checker.getPropertiesOfType(directType).length > 0) {\n return directType;\n }\n\n const apparentType = checker.getApparentType(directType);\n if (checker.getPropertiesOfType(apparentType).length > 0) {\n return apparentType;\n }\n\n const paramType = checker.getTypeAtLocation(firstParam);\n if (checker.getPropertiesOfType(paramType).length > 0) {\n return paramType;\n }\n\n const constrainedType = checker.getBaseConstraintOfType(directType);\n if (constrainedType && checker.getPropertiesOfType(constrainedType).length > 0) {\n return constrainedType;\n }\n\n return directType;\n }\n\n // Otherwise try to infer from the parameter's symbol\n const paramSymbol = checker.getSymbolAtLocation(firstParam.name);\n if (paramSymbol) {\n return checker.getTypeOfSymbolAtLocation(paramSymbol, firstParam);\n }\n\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Build ComponentMeta from resolved component\n// ---------------------------------------------------------------------------\n\nfunction buildComponentMeta(\n checker: ts.TypeChecker,\n component: ResolvedComponent,\n filePath: string,\n sourceFile: ts.SourceFile,\n moduleExports: ts.Symbol[],\n): ComponentMeta | null {\n const props: Record<string, PropMeta> = {};\n const sourceFilePath = toPosixPath(sourceFile.fileName);\n\n if (component.propsType) {\n extractPropsFromType(checker, component.propsType, props, sourceFilePath);\n if (Object.keys(props).length === 0) {\n const apparentPropsType = checker.getApparentType(component.propsType);\n if (apparentPropsType !== component.propsType) {\n extractPropsFromType(checker, apparentPropsType, props, sourceFilePath);\n }\n }\n if (Object.keys(props).length === 0) {\n const constrainedPropsType = checker.getBaseConstraintOfType(component.propsType);\n if (constrainedPropsType) {\n extractPropsFromType(checker, constrainedPropsType, props, sourceFilePath);\n }\n }\n }\n\n // Promote explicitly destructured props to \"local\" so wrapper components like\n // shadcn Input surface the props they actively customize from inherited DOM types.\n const destructuredProps = component.componentNode\n ? extractDestructuredPropNames(component.componentNode)\n : new Set<string>();\n for (const propName of destructuredProps) {\n if (props[propName]) {\n props[propName].source = 'local';\n }\n }\n\n // Extract defaults from the component function body\n const defaults = component.componentNode\n ? extractDefaultValues(component.componentNode)\n : {};\n\n // Apply defaults\n for (const [propName, defaultVal] of Object.entries(defaults)) {\n if (props[propName]) {\n props[propName].default = defaultVal;\n }\n }\n\n // Build composition meta\n let composition: CompositionMeta | null = null;\n if (component.compoundParts && component.compoundParts.size > 0) {\n const parts: PartMeta[] = [];\n for (const [partName, partType] of component.compoundParts) {\n const partProps: Record<string, PropMeta> = {};\n extractPropsFromType(checker, partType, partProps, sourceFilePath);\n parts.push({ name: partName, props: partProps });\n }\n\n composition = {\n pattern: 'compound',\n parts,\n required: [], // Could be inferred from usage patterns\n };\n }\n\n // Extract description from JSDoc\n let description = '';\n const componentSymbol = moduleExports.find(s => s.getName() === component.name);\n if (componentSymbol) {\n description = extractJSDocDescription(checker, componentSymbol);\n }\n\n // Collect export names\n const exportNames = moduleExports\n .filter(s => /^[A-Z]/.test(s.getName()))\n .map(s => s.getName());\n\n // Collect import dependencies (other components imported)\n const dependencies = extractDependencies(sourceFile);\n\n return {\n name: component.name,\n filePath,\n description,\n props,\n composition,\n exports: exportNames,\n dependencies,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Type → PropMeta extraction\n// ---------------------------------------------------------------------------\n\nfunction extractPropsFromType(\n checker: ts.TypeChecker,\n propsType: ts.Type,\n result: Record<string, PropMeta>,\n sourceFilePath: string,\n): void {\n for (const symbol of checker.getPropertiesOfType(propsType)) {\n const propName = symbol.getName();\n\n // Skip internal/private props\n if (propName.startsWith('_') || propName.startsWith('$')) continue;\n\n // Skip React internal props\n if (propName === 'key' || propName === 'ref') continue;\n\n const declarations = symbol.getDeclarations() ?? [];\n\n // Determine source: local vs inherited\n const isLocal = declarations.some(\n d => toPosixPath(d.getSourceFile().fileName) === sourceFilePath,\n );\n\n const referenceNode = declarations[0];\n if (!referenceNode) continue;\n\n const propType = checker.getTypeOfSymbolAtLocation(symbol, referenceNode);\n const serialized = serializePropType(checker, propType);\n const description = ts.displayPartsToString(symbol.getDocumentationComment(checker)).trim();\n const required = (symbol.flags & ts.SymbolFlags.Optional) === 0;\n\n // Extract @default from JSDoc tags\n let jsDocDefault: string | undefined;\n const jsDocTags = symbol.getJsDocTags(checker);\n const defaultTag = jsDocTags.find(t => t.name === 'default');\n if (defaultTag?.text) {\n jsDocDefault = ts.displayPartsToString(defaultTag.text).trim();\n }\n\n result[propName] = {\n name: propName,\n type: serialized.type,\n typeKind: serialized.typeKind,\n values: serialized.values,\n default: jsDocDefault,\n description: description || undefined,\n required,\n source: isLocal ? 'local' : 'inherited',\n };\n }\n}\n\n// ---------------------------------------------------------------------------\n// Type serializer: ts.Type → PropMeta shape\n// ---------------------------------------------------------------------------\n\nfunction serializePropType(\n checker: ts.TypeChecker,\n type: ts.Type,\n): Pick<PropMeta, 'type' | 'typeKind' | 'values'> {\n // Check for ReactNode/ReactElement BEFORE union decomposition,\n // because ReactNode is defined as a large union in React's types.\n const aliasSymbol = type.aliasSymbol;\n if (aliasSymbol) {\n const aliasName = aliasSymbol.getName();\n if (aliasName === 'ReactNode') {\n return { type: 'ReactNode', typeKind: 'node' };\n }\n if (aliasName === 'ReactElement') {\n return { type: 'ReactElement', typeKind: 'element' };\n }\n }\n\n // Handle union types (including optional which adds undefined)\n if (type.isUnion()) {\n const nonNullableTypes = type.types.filter(\n t => !((t.flags & ts.TypeFlags.Undefined) || (t.flags & ts.TypeFlags.Null) || (t.flags & ts.TypeFlags.Void)),\n );\n\n // Single type after filtering nullable\n if (nonNullableTypes.length === 1) {\n return serializePropType(checker, nonNullableTypes[0]);\n }\n\n // All string literals → enum\n if (nonNullableTypes.length > 0 && nonNullableTypes.every(t => t.isStringLiteral())) {\n const values = nonNullableTypes.map(t => (t as ts.StringLiteralType).value);\n return {\n type: values.map(v => `\"${v}\"`).join(' | '),\n typeKind: 'enum',\n values,\n };\n }\n\n // All boolean-like\n if (nonNullableTypes.every(t => isBooleanLike(t))) {\n return { type: 'boolean', typeKind: 'boolean' };\n }\n\n // Mixed union\n const typeStr = checker.typeToString(type, undefined, ts.TypeFormatFlags.NoTruncation);\n return { type: typeStr, typeKind: 'union' };\n }\n\n // Check for ReactNode / ReactElement\n const typeStr = checker.typeToString(type, undefined, ts.TypeFormatFlags.NoTruncation);\n if (typeStr.includes('ReactNode')) {\n return { type: 'ReactNode', typeKind: 'node' };\n }\n if (typeStr.includes('ReactElement') || typeStr.includes('JSX.Element')) {\n return { type: 'ReactElement', typeKind: 'element' };\n }\n\n // Function types\n if (type.getCallSignatures().length > 0) {\n return { type: typeStr, typeKind: 'function' };\n }\n\n // Primitives\n if (type.flags & ts.TypeFlags.String) return { type: 'string', typeKind: 'string' };\n if (type.flags & ts.TypeFlags.Number) return { type: 'number', typeKind: 'number' };\n if (type.flags & ts.TypeFlags.Boolean || type.flags & ts.TypeFlags.BooleanLiteral) {\n return { type: 'boolean', typeKind: 'boolean' };\n }\n\n // String literal (not in union)\n if (type.isStringLiteral()) {\n return { type: `\"${type.value}\"`, typeKind: 'enum', values: [type.value] };\n }\n\n // Array\n if (checker.isArrayType(type) || checker.isTupleType(type)) {\n return { type: typeStr, typeKind: 'array' };\n }\n\n // Object\n if (type.flags & ts.TypeFlags.Object) {\n return { type: typeStr, typeKind: 'object' };\n }\n\n return { type: typeStr, typeKind: 'custom' };\n}\n\n// ---------------------------------------------------------------------------\n// Default value extraction\n// ---------------------------------------------------------------------------\n\nfunction extractDefaultValues(node: ts.Node): Record<string, string> {\n const defaults: Record<string, string> = {};\n\n // Find function-like node\n let funcNode: ts.FunctionLikeDeclaration | null = null;\n if (ts.isFunctionDeclaration(node) || ts.isArrowFunction(node) || ts.isFunctionExpression(node)) {\n funcNode = node;\n }\n\n if (!funcNode?.parameters?.length) return defaults;\n\n const firstParam = funcNode.parameters[0];\n if (!ts.isObjectBindingPattern(firstParam.name)) return defaults;\n\n for (const element of firstParam.name.elements) {\n let propName: string | null = null;\n\n if (element.propertyName) {\n if (ts.isIdentifier(element.propertyName) || ts.isStringLiteral(element.propertyName)) {\n propName = element.propertyName.text;\n }\n } else if (ts.isIdentifier(element.name)) {\n propName = element.name.text;\n }\n\n if (!propName || !element.initializer) continue;\n\n const value = readLiteralValue(element.initializer);\n if (value !== undefined) {\n defaults[propName] = value;\n }\n }\n\n return defaults;\n}\n\nfunction extractDestructuredPropNames(node: ts.Node): Set<string> {\n const names = new Set<string>();\n\n let funcNode: ts.FunctionLikeDeclaration | null = null;\n if (ts.isFunctionDeclaration(node) || ts.isArrowFunction(node) || ts.isFunctionExpression(node)) {\n funcNode = node;\n }\n\n if (!funcNode?.parameters?.length) return names;\n\n const firstParam = funcNode.parameters[0];\n if (!ts.isObjectBindingPattern(firstParam.name)) return names;\n\n for (const element of firstParam.name.elements) {\n if (element.dotDotDotToken || !ts.isIdentifier(element.name)) continue;\n\n const propName = element.propertyName\n ? element.propertyName.getText()\n : element.name.text;\n\n if (propName === 'className' || propName === 'children' || propName === 'ref') {\n continue;\n }\n\n names.add(propName);\n }\n\n return names;\n}\n\nfunction readLiteralValue(expression: ts.Expression): string | undefined {\n if (ts.isStringLiteral(expression) || ts.isNoSubstitutionTemplateLiteral(expression)) {\n return expression.text;\n }\n if (ts.isNumericLiteral(expression)) {\n return expression.text;\n }\n if (expression.kind === ts.SyntaxKind.TrueKeyword) return 'true';\n if (expression.kind === ts.SyntaxKind.FalseKeyword) return 'false';\n if (expression.kind === ts.SyntaxKind.NullKeyword) return 'null';\n if (\n ts.isPrefixUnaryExpression(expression) &&\n expression.operator === ts.SyntaxKind.MinusToken &&\n ts.isNumericLiteral(expression.operand)\n ) {\n return `-${expression.operand.text}`;\n }\n\n return undefined;\n}\n\n// ---------------------------------------------------------------------------\n// JSDoc extraction\n// ---------------------------------------------------------------------------\n\nfunction extractJSDocDescription(checker: ts.TypeChecker, symbol: ts.Symbol): string {\n // Follow aliases\n let sym = symbol;\n if (sym.flags & ts.SymbolFlags.Alias) {\n sym = checker.getAliasedSymbol(sym);\n }\n\n const docComment = ts.displayPartsToString(sym.getDocumentationComment(checker)).trim();\n if (docComment) return docComment;\n\n // Try to get from the Props interface\n const decls = sym.getDeclarations();\n if (decls) {\n for (const decl of decls) {\n // Look for the Props type\n const sourceFile = decl.getSourceFile();\n for (const stmt of sourceFile.statements) {\n if (\n (ts.isInterfaceDeclaration(stmt) || ts.isTypeAliasDeclaration(stmt)) &&\n stmt.name.text === `${symbol.getName()}Props`\n ) {\n const propsDoc = ts.displayPartsToString(\n checker.getSymbolAtLocation(stmt.name)?.getDocumentationComment(checker) ?? [],\n ).trim();\n if (propsDoc) return propsDoc;\n }\n }\n }\n }\n\n return '';\n}\n\n// ---------------------------------------------------------------------------\n// Import dependency extraction\n// ---------------------------------------------------------------------------\n\nfunction extractDependencies(sourceFile: ts.SourceFile): string[] {\n const deps: string[] = [];\n for (const stmt of sourceFile.statements) {\n if (!ts.isImportDeclaration(stmt)) continue;\n if (!ts.isStringLiteral(stmt.moduleSpecifier)) continue;\n\n const modulePath = stmt.moduleSpecifier.text;\n // Only relative imports to other components\n if (!modulePath.startsWith('.') && !modulePath.startsWith('/')) continue;\n\n const clause = stmt.importClause;\n if (!clause) continue;\n\n // Default import\n if (clause.name && /^[A-Z]/.test(clause.name.text)) {\n deps.push(clause.name.text);\n }\n\n // Named imports\n if (clause.namedBindings && ts.isNamedImports(clause.namedBindings)) {\n for (const element of clause.namedBindings.elements) {\n if (/^[A-Z]/.test(element.name.text)) {\n deps.push(element.name.text);\n }\n }\n }\n }\n return deps;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction unwrapExpression(expr: ts.Expression): ts.Expression {\n while (true) {\n if (ts.isParenthesizedExpression(expr)) {\n expr = expr.expression;\n } else if (ts.isAsExpression(expr) || ts.isTypeAssertionExpression(expr)) {\n expr = expr.expression;\n } else {\n return expr;\n }\n }\n}\n\nfunction isObjectAssignCall(callee: ts.Expression, sourceFile: ts.SourceFile): boolean {\n if (\n ts.isPropertyAccessExpression(callee) &&\n ts.isIdentifier(callee.expression) &&\n callee.expression.text === 'Object' &&\n callee.name.text === 'assign'\n ) {\n return true;\n }\n return false;\n}\n\nfunction isForwardRefCall(callee: ts.Expression): boolean {\n // React.forwardRef(...)\n if (ts.isPropertyAccessExpression(callee) && callee.name.text === 'forwardRef') {\n return true;\n }\n // forwardRef(...)\n if (ts.isIdentifier(callee) && callee.text === 'forwardRef') {\n return true;\n }\n return false;\n}\n\nfunction isMemoCall(callee: ts.Expression): boolean {\n if (ts.isPropertyAccessExpression(callee) && callee.name.text === 'memo') {\n return true;\n }\n if (ts.isIdentifier(callee) && callee.text === 'memo') {\n return true;\n }\n return false;\n}\n\nfunction isBooleanLike(type: ts.Type): boolean {\n return (\n (type.flags & ts.TypeFlags.BooleanLike) !== 0 ||\n type.flags === ts.TypeFlags.BooleanLiteral\n );\n}\n\nfunction toPosixPath(filePath: string): string {\n return filePath.replace(/\\\\/g, '/');\n}\n"],"mappings":";;;AAYA,OAAO,QAAQ;AACf,SAAqB,oBAA2C;AAChE,SAAS,SAAS,eAAqB;AA6EhC,SAAS,yBAAyB,cAA2C;AAClF,MAAI,iBAAiB;AACrB,QAAM,eAAe,oBAAI,IAAoB;AAC7C,QAAM,gBAAgB,oBAAI,IAAgC;AAG1D,QAAM,UAAU,eAAe,QAAQ,QAAQ,YAAY,CAAC,IAAI,QAAQ,IAAI;AAC5E,QAAM,oBAAoB,eACtB,cAAc,YAAY,IAC1B,qBAAqB,OAAO;AAEhC,QAAM,kBAAkB,IAAI,IAAI,kBAAkB,SAAS;AAE3D,QAAM,OAA+B;AAAA,IACnC,mBAAmB,MAAM,eAAe,SAAS;AAAA,IACjD,kBAAkB,CAAC,cAAc,aAAa,IAAI,QAAQ,KAAK,GAAG,SAAS;AAAA,IAC3E,mBAAmB,CAAC,aAAa;AAC/B,YAAM,SAAS,cAAc,IAAI,QAAQ;AACzC,UAAI,OAAQ,QAAO;AAEnB,UAAI;AACJ,UAAI;AACF,eAAO,aAAa,UAAU,OAAO;AAAA,MACvC,QAAQ;AACN,eAAO;AAAA,MACT;AACA,YAAM,WAAW,GAAG,eAAe,WAAW,IAAI;AAClD,oBAAc,IAAI,UAAU,QAAQ;AACpC,aAAO;AAAA,IACT;AAAA,IACA,oBAAoB,MAAM,CAAC,GAAG,eAAe;AAAA,IAC7C,wBAAwB,MAAM,kBAAkB;AAAA,IAChD,qBAAqB,MAAM;AAAA,IAC3B,uBAAuB,GAAG;AAAA,IAC1B,YAAY,GAAG,IAAI;AAAA,IACnB,UAAU,GAAG,IAAI;AAAA,IACjB,eAAe,GAAG,IAAI;AAAA,IACtB,iBAAiB,GAAG,IAAI;AAAA,IACxB,gBAAgB,GAAG,IAAI;AAAA,IACvB,oBAAoB,CAAC,aAAa,mBAChC,YAAY,IAAI,CAAC,eAAe;AAC9B,YAAM,WAAW,GAAG;AAAA,QAClB;AAAA,QACA;AAAA,QACA,kBAAkB;AAAA,QAClB;AAAA,UACE,YAAY,GAAG,IAAI;AAAA,UACnB,UAAU,GAAG,IAAI;AAAA,UACjB,UAAU,GAAG,IAAI;AAAA,UACjB,iBAAiB,GAAG,IAAI;AAAA,UACxB,gBAAgB,GAAG,IAAI;AAAA,UACvB,qBAAqB,MAAM;AAAA,QAC7B;AAAA,MACF;AAEA,aAAO,SAAS;AAAA,IAClB,CAAC;AAAA,EACL;AAEA,QAAM,kBAAkB,GAAG,sBAAsB,MAAM,GAAG,uBAAuB,CAAC;AAElF,WAAS,WAAW,UAAwB;AAC1C,UAAM,WAAW,QAAQ,QAAQ;AACjC,QAAI,CAAC,gBAAgB,IAAI,QAAQ,GAAG;AAClC,sBAAgB,IAAI,QAAQ;AAC5B;AAAA,IACF;AAAA,EACF;AAEA,WAAS,aAA6B;AACpC,UAAM,UAAU,gBAAgB,WAAW;AAC3C,QAAI,CAAC,QAAS,OAAM,IAAI,MAAM,4CAA4C;AAC1E,WAAO,QAAQ,eAAe;AAAA,EAChC;AAEA,WAAS,cAAc,UAA6C;AAClE,WAAO,gBAAgB,WAAW,GAAG,cAAc,QAAQ,QAAQ,CAAC;AAAA,EACtE;AAEA,SAAO;AAAA,IACL,QAAQ,UAAkB,YAA2C;AACnE,YAAM,WAAW,QAAQ,QAAQ;AACjC,iBAAW,QAAQ;AAEnB,YAAM,aAAa,cAAc,QAAQ;AACzC,UAAI,CAAC,WAAY,QAAO;AAExB,YAAM,UAAU,WAAW;AAC3B,YAAM,eAAe,QAAQ,oBAAoB,UAAU;AAC3D,UAAI,CAAC,aAAc,QAAO;AAE1B,YAAM,UAAU,QAAQ,mBAAmB,YAAY;AACvD,YAAM,aAAa,cAAc,kBAAkB,SAAS,UAAU;AACtE,UAAI,CAAC,WAAY,QAAO;AAExB,YAAM,eAAe,QAAQ,KAAK,OAAK,EAAE,QAAQ,MAAM,UAAU;AACjE,UAAI,CAAC,aAAc,QAAO;AAE1B,YAAM,YAAY,yBAAyB,SAAS,cAAc,UAAU;AAC5E,UAAI,CAAC,UAAW,QAAO;AAEvB,aAAO,mBAAmB,SAAS,WAAW,UAAU,YAAY,OAAO;AAAA,IAC7E;AAAA,IAEA,WAAW,UAAmC;AAC5C,YAAM,WAAW,QAAQ,QAAQ;AACjC,iBAAW,QAAQ;AAEnB,YAAM,aAAa,cAAc,QAAQ;AACzC,UAAI,CAAC,WAAY,QAAO,CAAC;AAEzB,YAAM,UAAU,WAAW;AAC3B,YAAM,eAAe,QAAQ,oBAAoB,UAAU;AAC3D,UAAI,CAAC,aAAc,QAAO,CAAC;AAE3B,YAAM,UAAU,QAAQ,mBAAmB,YAAY;AACvD,YAAM,UAA2B,CAAC;AAElC,iBAAW,gBAAgB,SAAS;AAClC,cAAM,OAAO,aAAa,QAAQ;AAElC,YAAI,CAAC,SAAS,KAAK,IAAI,EAAG;AAE1B,cAAM,YAAY,yBAAyB,SAAS,cAAc,UAAU;AAC5E,YAAI,CAAC,UAAW;AAEhB,cAAM,OAAO,mBAAmB,SAAS,WAAW,UAAU,YAAY,OAAO;AACjF,YAAI,KAAM,SAAQ,KAAK,IAAI;AAAA,MAC7B;AAEA,aAAO;AAAA,IACT;AAAA,IAEA,WAAW,UAAwB;AACjC,YAAM,WAAW,QAAQ,QAAQ;AACjC,mBAAa,IAAI,WAAW,aAAa,IAAI,QAAQ,KAAK,KAAK,CAAC;AAChE,oBAAc,OAAO,QAAQ;AAC7B;AAAA,IACF;AAAA,IAEA,UAAgB;AACd,sBAAgB,QAAQ;AACxB,oBAAc,MAAM;AACpB,mBAAa,MAAM;AAAA,IACrB;AAAA,EACF;AACF;AAMA,SAAS,cAAc,cAA4C;AACjE,QAAM,WAAW,QAAQ,YAAY;AACrC,QAAM,aAAa,GAAG,eAAe,UAAU,GAAG,IAAI,QAAQ;AAC9D,MAAI,WAAW,OAAO;AACpB,UAAM,IAAI,MAAM,4BAA4B,GAAG,6BAA6B,WAAW,MAAM,aAAa,IAAI,CAAC,EAAE;AAAA,EACnH;AAEA,SAAO,GAAG;AAAA,IACR,WAAW;AAAA,IACX,GAAG;AAAA,IACH,QAAQ,QAAQ;AAAA,IAChB;AAAA,IACA;AAAA,EACF;AACF;AAEA,SAAS,qBAAqB,SAAuC;AACnE,SAAO;AAAA,IACL,SAAS;AAAA,MACP,QAAQ,GAAG,aAAa;AAAA,MACxB,QAAQ,GAAG,WAAW;AAAA,MACtB,kBAAkB,GAAG,qBAAqB;AAAA,MAC1C,KAAK,GAAG,QAAQ;AAAA,MAChB,8BAA8B;AAAA,MAC9B,iBAAiB;AAAA,MACjB,cAAc;AAAA,MACd,QAAQ;AAAA,MACR,QAAQ;AAAA,IACV;AAAA,IACA,WAAW,CAAC;AAAA,IACZ,QAAQ,CAAC;AAAA,EACX;AACF;AASA,SAAS,kBAAkB,SAAsB,YAA0C;AAEzF,QAAM,gBAAgB,QAAQ,KAAK,OAAK,EAAE,QAAQ,MAAM,SAAS;AACjE,MAAI,cAAe,QAAO;AAG1B,aAAW,KAAK,SAAS;AACvB,QAAI,sBAAsB,KAAK,EAAE,QAAQ,CAAC,GAAG;AAC3C,aAAO,EAAE,QAAQ;AAAA,IACnB;AAAA,EACF;AAEA,SAAO;AACT;AAMA,SAAS,yBACP,SACA,cACA,YAC0B;AAC1B,QAAM,OAAO,aAAa,QAAQ;AAGlC,MAAI,SAAS;AACb,MAAI,OAAO,QAAQ,GAAG,YAAY,OAAO;AACvC,aAAS,QAAQ,iBAAiB,MAAM;AAAA,EAC1C;AAEA,QAAM,eAAe,OAAO,gBAAgB;AAC5C,MAAI,CAAC,gBAAgB,aAAa,WAAW,EAAG,QAAO;AAEvD,QAAM,cAAc,aAAa,CAAC;AAGlC,MAAI,GAAG,sBAAsB,WAAW,KAAK,YAAY,aAAa;AACpE,WAAO,sBAAsB,SAAS,MAAM,YAAY,aAAa,aAAa,UAAU;AAAA,EAC9F;AAGA,MAAI,GAAG,sBAAsB,WAAW,GAAG;AACzC,UAAM,YAAY,6BAA6B,SAAS,WAAW;AACnE,WAAO,YAAY,EAAE,MAAM,WAAW,eAAe,aAAa,eAAe,KAAK,IAAI;AAAA,EAC5F;AAGA,MAAI,GAAG,mBAAmB,WAAW,KAAK,YAAY,YAAY;AAChE,WAAO,sBAAsB,SAAS,MAAM,YAAY,YAAY,MAAM,UAAU;AAAA,EACtF;AAEA,SAAO;AACT;AAEA,SAAS,sBACP,SACA,MACA,YACA,cACA,YAC0B;AAE1B,eAAa,iBAAiB,UAAU;AAGxC,MAAI,GAAG,gBAAgB,UAAU,KAAK,GAAG,qBAAqB,UAAU,GAAG;AACzE,UAAM,YAAY,6BAA6B,SAAS,UAAU;AAClE,WAAO,YAAY,EAAE,MAAM,WAAW,eAAe,YAAY,eAAe,KAAK,IAAI;AAAA,EAC3F;AAGA,MAAI,GAAG,iBAAiB,UAAU,GAAG;AACnC,WAAO,sBAAsB,SAAS,MAAM,YAAY,cAAc,UAAU;AAAA,EAClF;AAGA,MAAI,GAAG,aAAa,UAAU,GAAG;AAC/B,UAAM,MAAM,QAAQ,oBAAoB,UAAU;AAClD,QAAI,KAAK;AACP,YAAM,QAAQ,IAAI,gBAAgB;AAClC,UAAI,SAAS,MAAM,SAAS,GAAG;AAC7B,cAAM,OAAO,MAAM,CAAC;AACpB,YAAI,GAAG,sBAAsB,IAAI,KAAK,KAAK,aAAa;AACtD,iBAAO,sBAAsB,SAAS,MAAM,KAAK,aAAa,MAAM,UAAU;AAAA,QAChF;AACA,YAAI,GAAG,sBAAsB,IAAI,GAAG;AAClC,gBAAM,YAAY,6BAA6B,SAAS,IAAI;AAC5D,iBAAO,YAAY,EAAE,MAAM,WAAW,eAAe,MAAM,eAAe,KAAK,IAAI;AAAA,QACrF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,MAAI,cAAc,QAAQ,GAAG,oBAAoB,aAAa,IAAI,GAAG;AACnE,UAAM,WAAW,aAAa,KAAK,SAAS,QAAQ,UAAU;AAC9D,QAAI,SAAS,SAAS,IAAI,KAAK,SAAS,SAAS,mBAAmB,GAAG;AACrE,YAAM,UAAU,aAAa,KAAK,gBAAgB,CAAC;AACnD,UAAI,SAAS;AACX,cAAM,YAAY,QAAQ,oBAAoB,OAAO;AACrD,eAAO,EAAE,MAAM,WAAW,eAAe,YAAY,eAAe,KAAK;AAAA,MAC3E;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,sBACP,SACA,MACA,MACA,cACA,YAC0B;AAC1B,QAAM,SAAS,KAAK;AAGpB,MAAI,mBAAmB,QAAQ,UAAU,GAAG;AAC1C,WAAO,oBAAoB,SAAS,MAAM,MAAM,UAAU;AAAA,EAC5D;AAGA,MAAI,iBAAiB,MAAM,GAAG;AAC5B,WAAO,kBAAkB,SAAS,MAAM,MAAM,UAAU;AAAA,EAC1D;AAGA,MAAI,WAAW,MAAM,GAAG;AACtB,UAAM,WAAW,KAAK,UAAU,CAAC;AACjC,QAAI,UAAU;AACZ,aAAO,sBAAsB,SAAS,MAAM,UAAU,cAAc,UAAU;AAAA,IAChF;AAAA,EACF;AAEA,SAAO;AACT;AAMA,SAAS,oBACP,SACA,MACA,MACA,YAC0B;AAC1B,MAAI,KAAK,UAAU,SAAS,EAAG,QAAO;AAGtC,QAAM,WAAW,KAAK,UAAU,CAAC;AACjC,QAAM,aAAa,sBAAsB,SAAS,MAAM,UAAU,MAAM,UAAU;AAGlF,QAAM,UAAU,KAAK,UAAU,CAAC;AAChC,QAAM,gBAAgB,oBAAI,IAAqB;AAE/C,MAAI,GAAG,0BAA0B,OAAO,GAAG;AACzC,eAAW,QAAQ,QAAQ,YAAY;AACrC,UAAI,UAAyB;AAC7B,UAAI,gBAAsC;AAE1C,UAAI,GAAG,8BAA8B,IAAI,GAAG;AAC1C,kBAAU,KAAK,KAAK;AAEpB,cAAM,MAAM,QAAQ,oBAAoB,KAAK,IAAI;AACjD,YAAI,KAAK;AACP,gBAAM,eAAe,gCAAgC,SAAS,GAAG;AACjE,cAAI,cAAc;AAChB,0BAAc,IAAI,SAAS,YAAY;AAAA,UACzC;AAAA,QACF;AAAA,MACF,WAAW,GAAG,qBAAqB,IAAI,KAAK,GAAG,aAAa,KAAK,IAAI,GAAG;AACtE,kBAAU,KAAK,KAAK;AACpB,wBAAgB,KAAK;AACrB,YAAI,eAAe;AACjB,gBAAM,UAAU,2BAA2B,SAAS,eAAe,UAAU;AAC7E,cAAI,SAAS;AACX,0BAAc,IAAI,SAAS,OAAO;AAAA,UACpC;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA,WAAW,YAAY,aAAa;AAAA,IACpC,eAAe,YAAY,iBAAiB;AAAA,IAC5C,eAAe,cAAc,OAAO,IAAI,gBAAgB;AAAA,EAC1D;AACF;AAKA,SAAS,gCAAgC,SAAyB,QAAmC;AAEnG,MAAI,MAAM;AACV,MAAI,IAAI,QAAQ,GAAG,YAAY,OAAO;AACpC,UAAM,QAAQ,iBAAiB,GAAG;AAAA,EACpC;AAEA,QAAM,QAAQ,IAAI,gBAAgB;AAClC,MAAI,CAAC,SAAS,MAAM,WAAW,EAAG,QAAO;AAEzC,QAAM,OAAO,MAAM,CAAC;AAEpB,MAAI,GAAG,sBAAsB,IAAI,GAAG;AAClC,WAAO,6BAA6B,SAAS,IAAI;AAAA,EACnD;AAEA,MAAI,GAAG,sBAAsB,IAAI,KAAK,KAAK,aAAa;AAEtD,WAAO,+BAA+B,SAAS,IAAI;AAAA,EACrD;AAEA,SAAO;AACT;AAKA,SAAS,2BAA2B,SAAyB,MAAqB,YAA2C;AAC3H,SAAO,iBAAiB,IAAI;AAE5B,MAAI,GAAG,aAAa,IAAI,GAAG;AACzB,UAAM,MAAM,QAAQ,oBAAoB,IAAI;AAC5C,QAAI,IAAK,QAAO,gCAAgC,SAAS,GAAG;AAAA,EAC9D;AAEA,MAAI,GAAG,gBAAgB,IAAI,KAAK,GAAG,qBAAqB,IAAI,GAAG;AAC7D,WAAO,6BAA6B,SAAS,IAAI;AAAA,EACnD;AAEA,MAAI,GAAG,iBAAiB,IAAI,GAAG;AAC7B,QAAI,iBAAiB,KAAK,UAAU,GAAG;AACrC,YAAM,UAAU,KAAK,gBAAgB,CAAC;AACtC,UAAI,QAAS,QAAO,QAAQ,oBAAoB,OAAO;AACvD,YAAM,WAAW,KAAK,UAAU,CAAC;AACjC,UAAI,aAAa,GAAG,gBAAgB,QAAQ,KAAK,GAAG,qBAAqB,QAAQ,IAAI;AACnF,eAAO,6BAA6B,SAAS,QAAQ;AAAA,MACvD;AAAA,IACF;AACA,QAAI,WAAW,KAAK,UAAU,KAAK,KAAK,UAAU,CAAC,GAAG;AACpD,aAAO,2BAA2B,SAAS,KAAK,UAAU,CAAC,GAAG,UAAU;AAAA,IAC1E;AAAA,EACF;AAEA,SAAO;AACT;AAKA,SAAS,+BAA+B,SAAyB,MAA8C;AAC7G,MAAI,CAAC,KAAK,YAAa,QAAO;AAC9B,QAAM,OAAO,iBAAiB,KAAK,WAAW;AAE9C,MAAI,GAAG,gBAAgB,IAAI,KAAK,GAAG,qBAAqB,IAAI,GAAG;AAC7D,WAAO,6BAA6B,SAAS,IAAI;AAAA,EACnD;AAEA,MAAI,GAAG,iBAAiB,IAAI,GAAG;AAC7B,QAAI,iBAAiB,KAAK,UAAU,GAAG;AACrC,YAAM,UAAU,KAAK,gBAAgB,CAAC;AACtC,UAAI,QAAS,QAAO,QAAQ,oBAAoB,OAAO;AACvD,YAAM,WAAW,KAAK,UAAU,CAAC;AACjC,UAAI,aAAa,GAAG,gBAAgB,QAAQ,KAAK,GAAG,qBAAqB,QAAQ,IAAI;AACnF,eAAO,6BAA6B,SAAS,QAAQ;AAAA,MACvD;AAAA,IACF;AACA,QAAI,WAAW,KAAK,UAAU,KAAK,KAAK,UAAU,CAAC,GAAG;AACpD,aAAO,+BAA+B,SAAS;AAAA,QAC7C,GAAG;AAAA,QACH,aAAa,KAAK,UAAU,CAAC;AAAA,MAC/B,CAA2B;AAAA,IAC7B;AAAA,EACF;AAEA,SAAO;AACT;AAMA,SAAS,kBACP,SACA,MACA,MACA,YAC0B;AAE1B,QAAM,eAAe,KAAK,gBAAgB,CAAC;AAC3C,MAAI,cAAc;AAChB,UAAM,YAAY,QAAQ,oBAAoB,YAAY;AAC1D,UAAMA,YAAW,KAAK,UAAU,CAAC;AACjC,UAAM,gBAAgBA,cAAa,GAAG,gBAAgBA,SAAQ,KAAK,GAAG,qBAAqBA,SAAQ,KAC/FA,YAAW;AACf,WAAO,EAAE,MAAM,WAAW,eAAe,eAAe,KAAK;AAAA,EAC/D;AAGA,QAAM,WAAW,KAAK,UAAU,CAAC;AACjC,MAAI,UAAU;AACZ,QAAI,GAAG,gBAAgB,QAAQ,KAAK,GAAG,qBAAqB,QAAQ,GAAG;AACrE,YAAM,YAAY,6BAA6B,SAAS,QAAQ;AAChE,aAAO,YAAY,EAAE,MAAM,WAAW,eAAe,UAAU,eAAe,KAAK,IAAI;AAAA,IACzF;AACA,QAAI,GAAG,aAAa,QAAQ,GAAG;AAC7B,YAAM,MAAM,QAAQ,oBAAoB,QAAQ;AAChD,UAAI,KAAK;AACP,cAAM,YAAY,gCAAgC,SAAS,GAAG;AAC9D,YAAI,UAAW,QAAO,EAAE,MAAM,WAAW,eAAe,UAAU,eAAe,KAAK;AAAA,MACxF;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AASA,SAAS,6BACP,SACA,MACgB;AAChB,QAAM,aAAa,KAAK,WAAW,CAAC;AACpC,MAAI,CAAC,WAAY,QAAO;AAGxB,MAAI,WAAW,MAAM;AACnB,UAAM,aAAa,QAAQ,oBAAoB,WAAW,IAAI;AAC9D,QAAI,QAAQ,oBAAoB,UAAU,EAAE,SAAS,GAAG;AACtD,aAAO;AAAA,IACT;AAEA,UAAM,eAAe,QAAQ,gBAAgB,UAAU;AACvD,QAAI,QAAQ,oBAAoB,YAAY,EAAE,SAAS,GAAG;AACxD,aAAO;AAAA,IACT;AAEA,UAAM,YAAY,QAAQ,kBAAkB,UAAU;AACtD,QAAI,QAAQ,oBAAoB,SAAS,EAAE,SAAS,GAAG;AACrD,aAAO;AAAA,IACT;AAEA,UAAM,kBAAkB,QAAQ,wBAAwB,UAAU;AAClE,QAAI,mBAAmB,QAAQ,oBAAoB,eAAe,EAAE,SAAS,GAAG;AAC9E,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT;AAGA,QAAM,cAAc,QAAQ,oBAAoB,WAAW,IAAI;AAC/D,MAAI,aAAa;AACf,WAAO,QAAQ,0BAA0B,aAAa,UAAU;AAAA,EAClE;AAEA,SAAO;AACT;AAMA,SAAS,mBACP,SACA,WACA,UACA,YACA,eACsB;AACtB,QAAM,QAAkC,CAAC;AACzC,QAAM,iBAAiB,YAAY,WAAW,QAAQ;AAEtD,MAAI,UAAU,WAAW;AACvB,yBAAqB,SAAS,UAAU,WAAW,OAAO,cAAc;AACxE,QAAI,OAAO,KAAK,KAAK,EAAE,WAAW,GAAG;AACnC,YAAM,oBAAoB,QAAQ,gBAAgB,UAAU,SAAS;AACrE,UAAI,sBAAsB,UAAU,WAAW;AAC7C,6BAAqB,SAAS,mBAAmB,OAAO,cAAc;AAAA,MACxE;AAAA,IACF;AACA,QAAI,OAAO,KAAK,KAAK,EAAE,WAAW,GAAG;AACnC,YAAM,uBAAuB,QAAQ,wBAAwB,UAAU,SAAS;AAChF,UAAI,sBAAsB;AACxB,6BAAqB,SAAS,sBAAsB,OAAO,cAAc;AAAA,MAC3E;AAAA,IACF;AAAA,EACF;AAIA,QAAM,oBAAoB,UAAU,gBAChC,6BAA6B,UAAU,aAAa,IACpD,oBAAI,IAAY;AACpB,aAAW,YAAY,mBAAmB;AACxC,QAAI,MAAM,QAAQ,GAAG;AACnB,YAAM,QAAQ,EAAE,SAAS;AAAA,IAC3B;AAAA,EACF;AAGA,QAAM,WAAW,UAAU,gBACvB,qBAAqB,UAAU,aAAa,IAC5C,CAAC;AAGL,aAAW,CAAC,UAAU,UAAU,KAAK,OAAO,QAAQ,QAAQ,GAAG;AAC7D,QAAI,MAAM,QAAQ,GAAG;AACnB,YAAM,QAAQ,EAAE,UAAU;AAAA,IAC5B;AAAA,EACF;AAGA,MAAI,cAAsC;AAC1C,MAAI,UAAU,iBAAiB,UAAU,cAAc,OAAO,GAAG;AAC/D,UAAM,QAAoB,CAAC;AAC3B,eAAW,CAAC,UAAU,QAAQ,KAAK,UAAU,eAAe;AAC1D,YAAM,YAAsC,CAAC;AAC7C,2BAAqB,SAAS,UAAU,WAAW,cAAc;AACjE,YAAM,KAAK,EAAE,MAAM,UAAU,OAAO,UAAU,CAAC;AAAA,IACjD;AAEA,kBAAc;AAAA,MACZ,SAAS;AAAA,MACT;AAAA,MACA,UAAU,CAAC;AAAA;AAAA,IACb;AAAA,EACF;AAGA,MAAI,cAAc;AAClB,QAAM,kBAAkB,cAAc,KAAK,OAAK,EAAE,QAAQ,MAAM,UAAU,IAAI;AAC9E,MAAI,iBAAiB;AACnB,kBAAc,wBAAwB,SAAS,eAAe;AAAA,EAChE;AAGA,QAAM,cAAc,cACjB,OAAO,OAAK,SAAS,KAAK,EAAE,QAAQ,CAAC,CAAC,EACtC,IAAI,OAAK,EAAE,QAAQ,CAAC;AAGvB,QAAM,eAAe,oBAAoB,UAAU;AAEnD,SAAO;AAAA,IACL,MAAM,UAAU;AAAA,IAChB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,SAAS;AAAA,IACT;AAAA,EACF;AACF;AAMA,SAAS,qBACP,SACA,WACA,QACA,gBACM;AACN,aAAW,UAAU,QAAQ,oBAAoB,SAAS,GAAG;AAC3D,UAAM,WAAW,OAAO,QAAQ;AAGhC,QAAI,SAAS,WAAW,GAAG,KAAK,SAAS,WAAW,GAAG,EAAG;AAG1D,QAAI,aAAa,SAAS,aAAa,MAAO;AAE9C,UAAM,eAAe,OAAO,gBAAgB,KAAK,CAAC;AAGlD,UAAM,UAAU,aAAa;AAAA,MAC3B,OAAK,YAAY,EAAE,cAAc,EAAE,QAAQ,MAAM;AAAA,IACnD;AAEA,UAAM,gBAAgB,aAAa,CAAC;AACpC,QAAI,CAAC,cAAe;AAEpB,UAAM,WAAW,QAAQ,0BAA0B,QAAQ,aAAa;AACxE,UAAM,aAAa,kBAAkB,SAAS,QAAQ;AACtD,UAAM,cAAc,GAAG,qBAAqB,OAAO,wBAAwB,OAAO,CAAC,EAAE,KAAK;AAC1F,UAAM,YAAY,OAAO,QAAQ,GAAG,YAAY,cAAc;AAG9D,QAAI;AACJ,UAAM,YAAY,OAAO,aAAa,OAAO;AAC7C,UAAM,aAAa,UAAU,KAAK,OAAK,EAAE,SAAS,SAAS;AAC3D,QAAI,YAAY,MAAM;AACpB,qBAAe,GAAG,qBAAqB,WAAW,IAAI,EAAE,KAAK;AAAA,IAC/D;AAEA,WAAO,QAAQ,IAAI;AAAA,MACjB,MAAM;AAAA,MACN,MAAM,WAAW;AAAA,MACjB,UAAU,WAAW;AAAA,MACrB,QAAQ,WAAW;AAAA,MACnB,SAAS;AAAA,MACT,aAAa,eAAe;AAAA,MAC5B;AAAA,MACA,QAAQ,UAAU,UAAU;AAAA,IAC9B;AAAA,EACF;AACF;AAMA,SAAS,kBACP,SACA,MACgD;AAGhD,QAAM,cAAc,KAAK;AACzB,MAAI,aAAa;AACf,UAAM,YAAY,YAAY,QAAQ;AACtC,QAAI,cAAc,aAAa;AAC7B,aAAO,EAAE,MAAM,aAAa,UAAU,OAAO;AAAA,IAC/C;AACA,QAAI,cAAc,gBAAgB;AAChC,aAAO,EAAE,MAAM,gBAAgB,UAAU,UAAU;AAAA,IACrD;AAAA,EACF;AAGA,MAAI,KAAK,QAAQ,GAAG;AAClB,UAAM,mBAAmB,KAAK,MAAM;AAAA,MAClC,OAAK,EAAG,EAAE,QAAQ,GAAG,UAAU,aAAe,EAAE,QAAQ,GAAG,UAAU,QAAU,EAAE,QAAQ,GAAG,UAAU;AAAA,IACxG;AAGA,QAAI,iBAAiB,WAAW,GAAG;AACjC,aAAO,kBAAkB,SAAS,iBAAiB,CAAC,CAAC;AAAA,IACvD;AAGA,QAAI,iBAAiB,SAAS,KAAK,iBAAiB,MAAM,OAAK,EAAE,gBAAgB,CAAC,GAAG;AACnF,YAAM,SAAS,iBAAiB,IAAI,OAAM,EAA2B,KAAK;AAC1E,aAAO;AAAA,QACL,MAAM,OAAO,IAAI,OAAK,IAAI,CAAC,GAAG,EAAE,KAAK,KAAK;AAAA,QAC1C,UAAU;AAAA,QACV;AAAA,MACF;AAAA,IACF;AAGA,QAAI,iBAAiB,MAAM,OAAK,cAAc,CAAC,CAAC,GAAG;AACjD,aAAO,EAAE,MAAM,WAAW,UAAU,UAAU;AAAA,IAChD;AAGA,UAAMC,WAAU,QAAQ,aAAa,MAAM,QAAW,GAAG,gBAAgB,YAAY;AACrF,WAAO,EAAE,MAAMA,UAAS,UAAU,QAAQ;AAAA,EAC5C;AAGA,QAAM,UAAU,QAAQ,aAAa,MAAM,QAAW,GAAG,gBAAgB,YAAY;AACrF,MAAI,QAAQ,SAAS,WAAW,GAAG;AACjC,WAAO,EAAE,MAAM,aAAa,UAAU,OAAO;AAAA,EAC/C;AACA,MAAI,QAAQ,SAAS,cAAc,KAAK,QAAQ,SAAS,aAAa,GAAG;AACvE,WAAO,EAAE,MAAM,gBAAgB,UAAU,UAAU;AAAA,EACrD;AAGA,MAAI,KAAK,kBAAkB,EAAE,SAAS,GAAG;AACvC,WAAO,EAAE,MAAM,SAAS,UAAU,WAAW;AAAA,EAC/C;AAGA,MAAI,KAAK,QAAQ,GAAG,UAAU,OAAQ,QAAO,EAAE,MAAM,UAAU,UAAU,SAAS;AAClF,MAAI,KAAK,QAAQ,GAAG,UAAU,OAAQ,QAAO,EAAE,MAAM,UAAU,UAAU,SAAS;AAClF,MAAI,KAAK,QAAQ,GAAG,UAAU,WAAW,KAAK,QAAQ,GAAG,UAAU,gBAAgB;AACjF,WAAO,EAAE,MAAM,WAAW,UAAU,UAAU;AAAA,EAChD;AAGA,MAAI,KAAK,gBAAgB,GAAG;AAC1B,WAAO,EAAE,MAAM,IAAI,KAAK,KAAK,KAAK,UAAU,QAAQ,QAAQ,CAAC,KAAK,KAAK,EAAE;AAAA,EAC3E;AAGA,MAAI,QAAQ,YAAY,IAAI,KAAK,QAAQ,YAAY,IAAI,GAAG;AAC1D,WAAO,EAAE,MAAM,SAAS,UAAU,QAAQ;AAAA,EAC5C;AAGA,MAAI,KAAK,QAAQ,GAAG,UAAU,QAAQ;AACpC,WAAO,EAAE,MAAM,SAAS,UAAU,SAAS;AAAA,EAC7C;AAEA,SAAO,EAAE,MAAM,SAAS,UAAU,SAAS;AAC7C;AAMA,SAAS,qBAAqB,MAAuC;AACnE,QAAM,WAAmC,CAAC;AAG1C,MAAI,WAA8C;AAClD,MAAI,GAAG,sBAAsB,IAAI,KAAK,GAAG,gBAAgB,IAAI,KAAK,GAAG,qBAAqB,IAAI,GAAG;AAC/F,eAAW;AAAA,EACb;AAEA,MAAI,CAAC,UAAU,YAAY,OAAQ,QAAO;AAE1C,QAAM,aAAa,SAAS,WAAW,CAAC;AACxC,MAAI,CAAC,GAAG,uBAAuB,WAAW,IAAI,EAAG,QAAO;AAExD,aAAW,WAAW,WAAW,KAAK,UAAU;AAC9C,QAAI,WAA0B;AAE9B,QAAI,QAAQ,cAAc;AACxB,UAAI,GAAG,aAAa,QAAQ,YAAY,KAAK,GAAG,gBAAgB,QAAQ,YAAY,GAAG;AACrF,mBAAW,QAAQ,aAAa;AAAA,MAClC;AAAA,IACF,WAAW,GAAG,aAAa,QAAQ,IAAI,GAAG;AACxC,iBAAW,QAAQ,KAAK;AAAA,IAC1B;AAEA,QAAI,CAAC,YAAY,CAAC,QAAQ,YAAa;AAEvC,UAAM,QAAQ,iBAAiB,QAAQ,WAAW;AAClD,QAAI,UAAU,QAAW;AACvB,eAAS,QAAQ,IAAI;AAAA,IACvB;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,6BAA6B,MAA4B;AAChE,QAAM,QAAQ,oBAAI,IAAY;AAE9B,MAAI,WAA8C;AAClD,MAAI,GAAG,sBAAsB,IAAI,KAAK,GAAG,gBAAgB,IAAI,KAAK,GAAG,qBAAqB,IAAI,GAAG;AAC/F,eAAW;AAAA,EACb;AAEA,MAAI,CAAC,UAAU,YAAY,OAAQ,QAAO;AAE1C,QAAM,aAAa,SAAS,WAAW,CAAC;AACxC,MAAI,CAAC,GAAG,uBAAuB,WAAW,IAAI,EAAG,QAAO;AAExD,aAAW,WAAW,WAAW,KAAK,UAAU;AAC9C,QAAI,QAAQ,kBAAkB,CAAC,GAAG,aAAa,QAAQ,IAAI,EAAG;AAE9D,UAAM,WAAW,QAAQ,eACrB,QAAQ,aAAa,QAAQ,IAC7B,QAAQ,KAAK;AAEjB,QAAI,aAAa,eAAe,aAAa,cAAc,aAAa,OAAO;AAC7E;AAAA,IACF;AAEA,UAAM,IAAI,QAAQ;AAAA,EACpB;AAEA,SAAO;AACT;AAEA,SAAS,iBAAiB,YAA+C;AACvE,MAAI,GAAG,gBAAgB,UAAU,KAAK,GAAG,gCAAgC,UAAU,GAAG;AACpF,WAAO,WAAW;AAAA,EACpB;AACA,MAAI,GAAG,iBAAiB,UAAU,GAAG;AACnC,WAAO,WAAW;AAAA,EACpB;AACA,MAAI,WAAW,SAAS,GAAG,WAAW,YAAa,QAAO;AAC1D,MAAI,WAAW,SAAS,GAAG,WAAW,aAAc,QAAO;AAC3D,MAAI,WAAW,SAAS,GAAG,WAAW,YAAa,QAAO;AAC1D,MACE,GAAG,wBAAwB,UAAU,KACrC,WAAW,aAAa,GAAG,WAAW,cACtC,GAAG,iBAAiB,WAAW,OAAO,GACtC;AACA,WAAO,IAAI,WAAW,QAAQ,IAAI;AAAA,EACpC;AAEA,SAAO;AACT;AAMA,SAAS,wBAAwB,SAAyB,QAA2B;AAEnF,MAAI,MAAM;AACV,MAAI,IAAI,QAAQ,GAAG,YAAY,OAAO;AACpC,UAAM,QAAQ,iBAAiB,GAAG;AAAA,EACpC;AAEA,QAAM,aAAa,GAAG,qBAAqB,IAAI,wBAAwB,OAAO,CAAC,EAAE,KAAK;AACtF,MAAI,WAAY,QAAO;AAGvB,QAAM,QAAQ,IAAI,gBAAgB;AAClC,MAAI,OAAO;AACT,eAAW,QAAQ,OAAO;AAExB,YAAM,aAAa,KAAK,cAAc;AACtC,iBAAW,QAAQ,WAAW,YAAY;AACxC,aACG,GAAG,uBAAuB,IAAI,KAAK,GAAG,uBAAuB,IAAI,MAClE,KAAK,KAAK,SAAS,GAAG,OAAO,QAAQ,CAAC,SACtC;AACA,gBAAM,WAAW,GAAG;AAAA,YAClB,QAAQ,oBAAoB,KAAK,IAAI,GAAG,wBAAwB,OAAO,KAAK,CAAC;AAAA,UAC/E,EAAE,KAAK;AACP,cAAI,SAAU,QAAO;AAAA,QACvB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAMA,SAAS,oBAAoB,YAAqC;AAChE,QAAM,OAAiB,CAAC;AACxB,aAAW,QAAQ,WAAW,YAAY;AACxC,QAAI,CAAC,GAAG,oBAAoB,IAAI,EAAG;AACnC,QAAI,CAAC,GAAG,gBAAgB,KAAK,eAAe,EAAG;AAE/C,UAAM,aAAa,KAAK,gBAAgB;AAExC,QAAI,CAAC,WAAW,WAAW,GAAG,KAAK,CAAC,WAAW,WAAW,GAAG,EAAG;AAEhE,UAAM,SAAS,KAAK;AACpB,QAAI,CAAC,OAAQ;AAGb,QAAI,OAAO,QAAQ,SAAS,KAAK,OAAO,KAAK,IAAI,GAAG;AAClD,WAAK,KAAK,OAAO,KAAK,IAAI;AAAA,IAC5B;AAGA,QAAI,OAAO,iBAAiB,GAAG,eAAe,OAAO,aAAa,GAAG;AACnE,iBAAW,WAAW,OAAO,cAAc,UAAU;AACnD,YAAI,SAAS,KAAK,QAAQ,KAAK,IAAI,GAAG;AACpC,eAAK,KAAK,QAAQ,KAAK,IAAI;AAAA,QAC7B;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAMA,SAAS,iBAAiB,MAAoC;AAC5D,SAAO,MAAM;AACX,QAAI,GAAG,0BAA0B,IAAI,GAAG;AACtC,aAAO,KAAK;AAAA,IACd,WAAW,GAAG,eAAe,IAAI,KAAK,GAAG,0BAA0B,IAAI,GAAG;AACxE,aAAO,KAAK;AAAA,IACd,OAAO;AACL,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAEA,SAAS,mBAAmB,QAAuB,YAAoC;AACrF,MACE,GAAG,2BAA2B,MAAM,KACpC,GAAG,aAAa,OAAO,UAAU,KACjC,OAAO,WAAW,SAAS,YAC3B,OAAO,KAAK,SAAS,UACrB;AACA,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEA,SAAS,iBAAiB,QAAgC;AAExD,MAAI,GAAG,2BAA2B,MAAM,KAAK,OAAO,KAAK,SAAS,cAAc;AAC9E,WAAO;AAAA,EACT;AAEA,MAAI,GAAG,aAAa,MAAM,KAAK,OAAO,SAAS,cAAc;AAC3D,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEA,SAAS,WAAW,QAAgC;AAClD,MAAI,GAAG,2BAA2B,MAAM,KAAK,OAAO,KAAK,SAAS,QAAQ;AACxE,WAAO;AAAA,EACT;AACA,MAAI,GAAG,aAAa,MAAM,KAAK,OAAO,SAAS,QAAQ;AACrD,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEA,SAAS,cAAc,MAAwB;AAC7C,UACG,KAAK,QAAQ,GAAG,UAAU,iBAAiB,KAC5C,KAAK,UAAU,GAAG,UAAU;AAEhC;AAEA,SAAS,YAAY,UAA0B;AAC7C,SAAO,SAAS,QAAQ,OAAO,GAAG;AACpC;","names":["innerArg","typeStr"]}
|