galaxy-design 0.2.1 → 0.2.3

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utils/component-copier.ts"],"sourcesContent":["import { copyFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';\nimport { dirname, join, relative } from 'path';\nimport type { Platform } from './platform-detector';\nimport { getComponentSourceDir, isMobilePlatform } from './platform-detector';\nimport { getComponent, validateComponentDependencies } from './registry-loader';\nimport {\n\tfetchAndSaveFile,\n\tgetComponentGitHubPath,\n\tcheckGitHubConnection,\n} from './github-fetcher';\n\n/**\n * Component copy options\n */\nexport interface ComponentCopyOptions {\n\t/** Target directory to copy components to */\n\ttargetDir: string;\n\t/** Platform to copy for */\n\tplatform: Platform;\n\t/** Overwrite existing files */\n\toverwrite?: boolean;\n\t/** Dry run (don't actually copy) */\n\tdryRun?: boolean;\n\t/** Registry directory (for testing) */\n\tregistryDir?: string;\n\t/** Source packages directory (for testing) */\n\tpackagesDir?: string;\n}\n\n/**\n * Copy result for a single component\n */\nexport interface ComponentCopyResult {\n\tcomponentName: string;\n\tsuccess: boolean;\n\tfilesCopied: string[];\n\terrors: string[];\n\tskipped: string[];\n}\n\n/**\n * Copy a component to target project\n *\n * @param componentName - Name of component to copy\n * @param options - Copy options\n * @returns Copy result\n */\nexport async function copyComponent(\n\tcomponentName: string,\n\toptions: ComponentCopyOptions,\n): Promise<ComponentCopyResult> {\n\tconst result: ComponentCopyResult = {\n\t\tcomponentName,\n\t\tsuccess: false,\n\t\tfilesCopied: [],\n\t\terrors: [],\n\t\tskipped: [],\n\t};\n\n\t// Get component metadata\n\tconst component = getComponent(componentName, options.platform, options.registryDir);\n\n\tif (!component) {\n\t\tresult.errors.push(`Component \"${componentName}\" not found in registry`);\n\t\treturn result;\n\t}\n\n\t// Validate dependencies\n\tconst validation = validateComponentDependencies(\n\t\tcomponentName,\n\t\toptions.platform,\n\t\toptions.registryDir,\n\t);\n\n\tif (!validation.valid) {\n\t\tresult.errors.push(\n\t\t\t`Missing dependencies: ${validation.missing.join(', ')}. Please add these components first.`,\n\t\t);\n\t\treturn result;\n\t}\n\n\t// Determine target directory based on platform\n\tconst componentsTargetDir = getComponentsTargetDir(options.platform, options.targetDir);\n\n\t// Determine source mode: GitHub or local\n\tconst useGitHub = !options.packagesDir;\n\n\t// Copy each file\n\tfor (const file of component.files) {\n\t\tconst targetFile = join(componentsTargetDir, file);\n\n\t\t// Check if target already exists\n\t\tif (existsSync(targetFile) && !options.overwrite) {\n\t\t\tresult.skipped.push(relative(options.targetDir, targetFile));\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Dry run - don't actually copy\n\t\tif (options.dryRun) {\n\t\t\tresult.filesCopied.push(relative(options.targetDir, targetFile));\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Create target directory if needed\n\t\tconst targetDir = dirname(targetFile);\n\t\tif (!existsSync(targetDir)) {\n\t\t\tmkdirSync(targetDir, { recursive: true });\n\t\t}\n\n\t\t// Copy file - from GitHub or local\n\t\ttry {\n\t\t\tif (useGitHub) {\n\t\t\t\t// Fetch from GitHub\n\t\t\t\tconst githubPath = getComponentGitHubPath(options.platform, componentName, file);\n\t\t\t\tconst success = await fetchAndSaveFile(githubPath, targetFile);\n\n\t\t\t\tif (!success) {\n\t\t\t\t\tresult.errors.push(`Failed to fetch ${file} from GitHub`);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Copy from local packages directory (for development)\n\t\t\t\tconst packagesDir = options.packagesDir!;\n\t\t\t\tconst componentSourceDir = getComponentSourceDir(options.platform);\n\t\t\t\tconst sourceDir = join(packagesDir, componentSourceDir);\n\t\t\t\tconst sourceFile = join(sourceDir, file);\n\n\t\t\t\tif (!existsSync(sourceFile)) {\n\t\t\t\t\tresult.errors.push(`Source file not found: ${sourceFile}`);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tcopyFileSync(sourceFile, targetFile);\n\t\t\t}\n\n\t\t\tresult.filesCopied.push(relative(options.targetDir, targetFile));\n\t\t} catch (error) {\n\t\t\tresult.errors.push(\n\t\t\t\t`Failed to copy ${file}: ${error instanceof Error ? error.message : 'Unknown error'}`,\n\t\t\t);\n\t\t}\n\t}\n\n\tresult.success = result.errors.length === 0;\n\treturn result;\n}\n\n/**\n * Copy multiple components\n *\n * @param componentNames - Array of component names\n * @param options - Copy options\n * @returns Array of copy results\n */\nexport async function copyComponents(\n\tcomponentNames: string[],\n\toptions: ComponentCopyOptions,\n): Promise<ComponentCopyResult[]> {\n\tconst results: ComponentCopyResult[] = [];\n\n\tfor (const name of componentNames) {\n\t\tconst result = await copyComponent(name, options);\n\t\tresults.push(result);\n\n\t\t// If this component failed, log warning but continue\n\t\tif (!result.success) {\n\t\t\tconsole.warn(`⚠️ Failed to copy component \"${name}\"`);\n\t\t}\n\t}\n\n\treturn results;\n}\n\n/**\n * Get components target directory based on platform\n *\n * @param platform - Target platform\n * @param projectRoot - Project root directory\n * @returns Target directory for components\n */\nfunction getComponentsTargetDir(platform: Platform, projectRoot: string): string {\n\tswitch (platform) {\n\t\tcase 'react-native':\n\t\t\t// React Native: src/components or components\n\t\t\tif (existsSync(join(projectRoot, 'src'))) {\n\t\t\t\treturn join(projectRoot, 'src', 'components');\n\t\t\t}\n\t\t\treturn join(projectRoot, 'components');\n\n\t\tcase 'flutter':\n\t\t\t// Flutter: lib/components\n\t\t\treturn join(projectRoot, 'lib', 'components');\n\n\t\tcase 'vue':\n\t\t\t// Vue: src/components\n\t\t\treturn join(projectRoot, 'src', 'components');\n\n\t\tcase 'react':\n\t\t\t// React: src/components\n\t\t\treturn join(projectRoot, 'src', 'components');\n\n\t\tcase 'angular':\n\t\t\t// Angular: src/components or components\n\t\t\tif (existsSync(join(projectRoot, 'src', 'app'))) {\n\t\t\t\treturn join(projectRoot, 'src', 'app', 'components');\n\t\t\t}\n\t\t\treturn join(projectRoot, 'components');\n\n\t\tdefault:\n\t\t\t// Default: components at root\n\t\t\treturn join(projectRoot, 'components');\n\t}\n}\n\n/**\n * Generate import statement for component\n *\n * @param componentName - Component name\n * @param platform - Target platform\n * @param options - Options\n * @returns Import statement\n */\nexport function generateImportStatement(\n\tcomponentName: string,\n\tplatform: Platform,\n\toptions?: { registryDir?: string },\n): string {\n\tconst component = getComponent(componentName, platform, options?.registryDir);\n\n\tif (!component) {\n\t\treturn `// Component \"${componentName}\" not found`;\n\t}\n\n\tconst exports = component.exports;\n\n\tswitch (platform) {\n\t\tcase 'react-native':\n\t\tcase 'react':\n\t\t\t// TypeScript/JSX import\n\t\t\treturn `import { ${exports.join(', ')} } from './components/${componentName}';`;\n\n\t\tcase 'flutter':\n\t\t\t// Dart import\n\t\t\treturn `import 'package:your_app/components/${componentName}/${componentName.replace(/-/g, '_')}.dart';`;\n\n\t\tcase 'vue':\n\t\t\t// Vue import\n\t\t\treturn `import { ${exports.join(', ')} } from '@/components/${componentName}';`;\n\n\t\tcase 'angular':\n\t\t\t// Angular import\n\t\t\treturn `import { ${exports.join(', ')} } from './components/${componentName}';`;\n\n\t\tdefault:\n\t\t\treturn `// Import for platform \"${platform}\" not supported`;\n\t}\n}\n\n/**\n * Create components.json config file for project\n *\n * @param platform - Target platform\n * @param projectRoot - Project root directory\n * @param options - Additional config options\n */\nexport function createComponentsConfig(\n\tplatform: Platform,\n\tprojectRoot: string,\n\toptions?: {\n\t\tframework?: string;\n\t\ttypescript?: boolean;\n\t\tstyling?: 'tailwind' | 'css' | 'styled-components';\n\t},\n): void {\n\tconst config = {\n\t\t$schema: 'https://galaxy-design.vercel.app/schema.json',\n\t\tplatform: platform,\n\t\tframework: options?.framework || platform,\n\t\ttypescript: options?.typescript !== false,\n\t\tstyling: options?.styling || (isMobilePlatform(platform) ? 'styled-components' : 'tailwind'),\n\t\tcomponents: getComponentsTargetDir(platform, projectRoot),\n\t\tutils: join(projectRoot, isMobilePlatform(platform) ? 'lib' : 'src', 'lib'),\n\t};\n\n\tconst configPath = join(projectRoot, 'components.json');\n\twriteFileSync(configPath, JSON.stringify(config, null, 2), 'utf-8');\n}\n\n/**\n * Read components.json config\n *\n * @param projectRoot - Project root directory\n * @returns Config object or null if not found\n */\nexport function readComponentsConfig(projectRoot: string): any | null {\n\tconst configPath = join(projectRoot, 'components.json');\n\n\tif (!existsSync(configPath)) {\n\t\treturn null;\n\t}\n\n\ttry {\n\t\tconst content = readFileSync(configPath, 'utf-8');\n\t\treturn JSON.parse(content);\n\t} catch (error) {\n\t\tconsole.error('Failed to read components.json:', error);\n\t\treturn null;\n\t}\n}\n"],"names":["copyFileSync","existsSync","mkdirSync","readFileSync","writeFileSync","dirname","join","relative","getComponentSourceDir","isMobilePlatform","getComponent","validateComponentDependencies","fetchAndSaveFile","getComponentGitHubPath","copyComponent","componentName","options","result","success","filesCopied","errors","skipped","component","platform","registryDir","push","validation","valid","missing","componentsTargetDir","getComponentsTargetDir","targetDir","useGitHub","packagesDir","file","files","targetFile","overwrite","dryRun","recursive","githubPath","componentSourceDir","sourceDir","sourceFile","error","Error","message","length","copyComponents","componentNames","results","name","console","warn","projectRoot","generateImportStatement","exports","replace","createComponentsConfig","config","$schema","framework","typescript","styling","components","utils","configPath","JSON","stringify","readComponentsConfig","content","parse"],"mappings":"AAAA,SAASA,YAAY,EAAEC,UAAU,EAAEC,SAAS,EAAEC,YAAY,EAAEC,aAAa,QAAQ,KAAK;AACtF,SAASC,OAAO,EAAEC,IAAI,EAAEC,QAAQ,QAAQ,OAAO;AAE/C,SAASC,qBAAqB,EAAEC,gBAAgB,QAAQ,sBAAsB;AAC9E,SAASC,YAAY,EAAEC,6BAA6B,QAAQ,oBAAoB;AAChF,SACCC,gBAAgB,EAChBC,sBAAsB,QAEhB,mBAAmB;AA+B1B;;;;;;CAMC,GACD,OAAO,eAAeC,cACrBC,aAAqB,EACrBC,OAA6B;IAE7B,MAAMC,SAA8B;QACnCF;QACAG,SAAS;QACTC,aAAa,EAAE;QACfC,QAAQ,EAAE;QACVC,SAAS,EAAE;IACZ;IAEA,yBAAyB;IACzB,MAAMC,YAAYZ,aAAaK,eAAeC,QAAQO,QAAQ,EAAEP,QAAQQ,WAAW;IAEnF,IAAI,CAACF,WAAW;QACfL,OAAOG,MAAM,CAACK,IAAI,CAAC,CAAC,WAAW,EAAEV,cAAc,uBAAuB,CAAC;QACvE,OAAOE;IACR;IAEA,wBAAwB;IACxB,MAAMS,aAAaf,8BAClBI,eACAC,QAAQO,QAAQ,EAChBP,QAAQQ,WAAW;IAGpB,IAAI,CAACE,WAAWC,KAAK,EAAE;QACtBV,OAAOG,MAAM,CAACK,IAAI,CACjB,CAAC,sBAAsB,EAAEC,WAAWE,OAAO,CAACtB,IAAI,CAAC,MAAM,oCAAoC,CAAC;QAE7F,OAAOW;IACR;IAEA,+CAA+C;IAC/C,MAAMY,sBAAsBC,uBAAuBd,QAAQO,QAAQ,EAAEP,QAAQe,SAAS;IAEtF,yCAAyC;IACzC,MAAMC,YAAY,CAAChB,QAAQiB,WAAW;IAEtC,iBAAiB;IACjB,KAAK,MAAMC,QAAQZ,UAAUa,KAAK,CAAE;QACnC,MAAMC,aAAa9B,KAAKuB,qBAAqBK;QAE7C,iCAAiC;QACjC,IAAIjC,WAAWmC,eAAe,CAACpB,QAAQqB,SAAS,EAAE;YACjDpB,OAAOI,OAAO,CAACI,IAAI,CAAClB,SAASS,QAAQe,SAAS,EAAEK;YAChD;QACD;QAEA,gCAAgC;QAChC,IAAIpB,QAAQsB,MAAM,EAAE;YACnBrB,OAAOE,WAAW,CAACM,IAAI,CAAClB,SAASS,QAAQe,SAAS,EAAEK;YACpD;QACD;QAEA,oCAAoC;QACpC,MAAML,YAAY1B,QAAQ+B;QAC1B,IAAI,CAACnC,WAAW8B,YAAY;YAC3B7B,UAAU6B,WAAW;gBAAEQ,WAAW;YAAK;QACxC;QAEA,mCAAmC;QACnC,IAAI;YACH,IAAIP,WAAW;gBACd,oBAAoB;gBACpB,MAAMQ,aAAa3B,uBAAuBG,QAAQO,QAAQ,EAAER,eAAemB;gBAC3E,MAAMhB,UAAU,MAAMN,iBAAiB4B,YAAYJ;gBAEnD,IAAI,CAAClB,SAAS;oBACbD,OAAOG,MAAM,CAACK,IAAI,CAAC,CAAC,gBAAgB,EAAES,KAAK,YAAY,CAAC;oBACxD;gBACD;YACD,OAAO;gBACN,uDAAuD;gBACvD,MAAMD,cAAcjB,QAAQiB,WAAW;gBACvC,MAAMQ,qBAAqBjC,sBAAsBQ,QAAQO,QAAQ;gBACjE,MAAMmB,YAAYpC,KAAK2B,aAAaQ;gBACpC,MAAME,aAAarC,KAAKoC,WAAWR;gBAEnC,IAAI,CAACjC,WAAW0C,aAAa;oBAC5B1B,OAAOG,MAAM,CAACK,IAAI,CAAC,CAAC,uBAAuB,EAAEkB,YAAY;oBACzD;gBACD;gBAEA3C,aAAa2C,YAAYP;YAC1B;YAEAnB,OAAOE,WAAW,CAACM,IAAI,CAAClB,SAASS,QAAQe,SAAS,EAAEK;QACrD,EAAE,OAAOQ,OAAO;YACf3B,OAAOG,MAAM,CAACK,IAAI,CACjB,CAAC,eAAe,EAAES,KAAK,EAAE,EAAEU,iBAAiBC,QAAQD,MAAME,OAAO,GAAG,iBAAiB;QAEvF;IACD;IAEA7B,OAAOC,OAAO,GAAGD,OAAOG,MAAM,CAAC2B,MAAM,KAAK;IAC1C,OAAO9B;AACR;AAEA;;;;;;CAMC,GACD,OAAO,eAAe+B,eACrBC,cAAwB,EACxBjC,OAA6B;IAE7B,MAAMkC,UAAiC,EAAE;IAEzC,KAAK,MAAMC,QAAQF,eAAgB;QAClC,MAAMhC,SAAS,MAAMH,cAAcqC,MAAMnC;QACzCkC,QAAQzB,IAAI,CAACR;QAEb,qDAAqD;QACrD,IAAI,CAACA,OAAOC,OAAO,EAAE;YACpBkC,QAAQC,IAAI,CAAC,CAAC,8BAA8B,EAAEF,KAAK,CAAC,CAAC;QACtD;IACD;IAEA,OAAOD;AACR;AAEA;;;;;;CAMC,GACD,SAASpB,uBAAuBP,QAAkB,EAAE+B,WAAmB;IACtE,OAAQ/B;QACP,KAAK;YACJ,6CAA6C;YAC7C,IAAItB,WAAWK,KAAKgD,aAAa,SAAS;gBACzC,OAAOhD,KAAKgD,aAAa,OAAO;YACjC;YACA,OAAOhD,KAAKgD,aAAa;QAE1B,KAAK;YACJ,0BAA0B;YAC1B,OAAOhD,KAAKgD,aAAa,OAAO;QAEjC,KAAK;YACJ,sBAAsB;YACtB,OAAOhD,KAAKgD,aAAa,OAAO;QAEjC,KAAK;YACJ,wBAAwB;YACxB,OAAOhD,KAAKgD,aAAa,OAAO;QAEjC,KAAK;YACJ,wCAAwC;YACxC,IAAIrD,WAAWK,KAAKgD,aAAa,OAAO,SAAS;gBAChD,OAAOhD,KAAKgD,aAAa,OAAO,OAAO;YACxC;YACA,OAAOhD,KAAKgD,aAAa;QAE1B;YACC,8BAA8B;YAC9B,OAAOhD,KAAKgD,aAAa;IAC3B;AACD;AAEA;;;;;;;CAOC,GACD,OAAO,SAASC,wBACfxC,aAAqB,EACrBQ,QAAkB,EAClBP,OAAkC;IAElC,MAAMM,YAAYZ,aAAaK,eAAeQ,UAAUP,2BAAAA,QAASQ,WAAW;IAE5E,IAAI,CAACF,WAAW;QACf,OAAO,CAAC,cAAc,EAAEP,cAAc,WAAW,CAAC;IACnD;IAEA,MAAMyC,UAAUlC,UAAUkC,OAAO;IAEjC,OAAQjC;QACP,KAAK;QACL,KAAK;YACJ,wBAAwB;YACxB,OAAO,CAAC,SAAS,EAAEiC,QAAQlD,IAAI,CAAC,MAAM,sBAAsB,EAAES,cAAc,EAAE,CAAC;QAEhF,KAAK;YACJ,cAAc;YACd,OAAO,CAAC,oCAAoC,EAAEA,cAAc,CAAC,EAAEA,cAAc0C,OAAO,CAAC,MAAM,KAAK,OAAO,CAAC;QAEzG,KAAK;YACJ,aAAa;YACb,OAAO,CAAC,SAAS,EAAED,QAAQlD,IAAI,CAAC,MAAM,sBAAsB,EAAES,cAAc,EAAE,CAAC;QAEhF,KAAK;YACJ,iBAAiB;YACjB,OAAO,CAAC,SAAS,EAAEyC,QAAQlD,IAAI,CAAC,MAAM,sBAAsB,EAAES,cAAc,EAAE,CAAC;QAEhF;YACC,OAAO,CAAC,wBAAwB,EAAEQ,SAAS,eAAe,CAAC;IAC7D;AACD;AAEA;;;;;;CAMC,GACD,OAAO,SAASmC,uBACfnC,QAAkB,EAClB+B,WAAmB,EACnBtC,OAIC;IAED,MAAM2C,SAAS;QACdC,SAAS;QACTrC,UAAUA;QACVsC,WAAW7C,CAAAA,2BAAAA,QAAS6C,SAAS,KAAItC;QACjCuC,YAAY9C,CAAAA,2BAAAA,QAAS8C,UAAU,MAAK;QACpCC,SAAS/C,CAAAA,2BAAAA,QAAS+C,OAAO,KAAKtD,CAAAA,iBAAiBc,YAAY,sBAAsB,UAAS;QAC1FyC,YAAYlC,uBAAuBP,UAAU+B;QAC7CW,OAAO3D,KAAKgD,aAAa7C,iBAAiBc,YAAY,QAAQ,OAAO;IACtE;IAEA,MAAM2C,aAAa5D,KAAKgD,aAAa;IACrClD,cAAc8D,YAAYC,KAAKC,SAAS,CAACT,QAAQ,MAAM,IAAI;AAC5D;AAEA;;;;;CAKC,GACD,OAAO,SAASU,qBAAqBf,WAAmB;IACvD,MAAMY,aAAa5D,KAAKgD,aAAa;IAErC,IAAI,CAACrD,WAAWiE,aAAa;QAC5B,OAAO;IACR;IAEA,IAAI;QACH,MAAMI,UAAUnE,aAAa+D,YAAY;QACzC,OAAOC,KAAKI,KAAK,CAACD;IACnB,EAAE,OAAO1B,OAAO;QACfQ,QAAQR,KAAK,CAAC,mCAAmCA;QACjD,OAAO;IACR;AACD"}
1
+ {"version":3,"sources":["../../src/utils/component-copier.ts"],"sourcesContent":["import { copyFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';\nimport { dirname, join, relative } from 'path';\nimport type { Platform } from './platform-detector';\nimport { getComponentSourceDir, isMobilePlatform } from './platform-detector';\nimport { getComponent, validateComponentDependencies } from './registry-loader';\nimport {\n\tfetchAndSaveFile,\n\tgetComponentGitHubPath,\n\tcheckGitHubConnection,\n} from './github-fetcher';\nimport { transformComponent } from './component-transformer';\n\n/**\n * Component copy options\n */\nexport interface ComponentCopyOptions {\n\t/** Target directory to copy components to */\n\ttargetDir: string;\n\t/** Platform to copy for */\n\tplatform: Platform;\n\t/** Overwrite existing files */\n\toverwrite?: boolean;\n\t/** Dry run (don't actually copy) */\n\tdryRun?: boolean;\n\t/** Registry directory (for testing) */\n\tregistryDir?: string;\n\t/** Source packages directory (for testing) */\n\tpackagesDir?: string;\n}\n\n/**\n * Copy result for a single component\n */\nexport interface ComponentCopyResult {\n\tcomponentName: string;\n\tsuccess: boolean;\n\tfilesCopied: string[];\n\terrors: string[];\n\tskipped: string[];\n}\n\n/**\n * Copy a component to target project\n *\n * @param componentName - Name of component to copy\n * @param options - Copy options\n * @returns Copy result\n */\nexport async function copyComponent(\n\tcomponentName: string,\n\toptions: ComponentCopyOptions,\n): Promise<ComponentCopyResult> {\n\tconst result: ComponentCopyResult = {\n\t\tcomponentName,\n\t\tsuccess: false,\n\t\tfilesCopied: [],\n\t\terrors: [],\n\t\tskipped: [],\n\t};\n\n\t// Get component metadata\n\tconst component = getComponent(componentName, options.platform, options.registryDir);\n\n\tif (!component) {\n\t\tresult.errors.push(`Component \"${componentName}\" not found in registry`);\n\t\treturn result;\n\t}\n\n\t// Validate dependencies\n\tconst validation = validateComponentDependencies(\n\t\tcomponentName,\n\t\toptions.platform,\n\t\toptions.registryDir,\n\t);\n\n\tif (!validation.valid) {\n\t\tresult.errors.push(\n\t\t\t`Missing dependencies: ${validation.missing.join(', ')}. Please add these components first.`,\n\t\t);\n\t\treturn result;\n\t}\n\n\t// Determine target directory based on platform\n\tconst componentsTargetDir = getComponentsTargetDir(options.platform, options.targetDir);\n\n\t// Determine source mode: GitHub or local\n\tconst useGitHub = !options.packagesDir;\n\n\t// Copy each file\n\tfor (const file of component.files) {\n\t\tconst targetFile = join(componentsTargetDir, file);\n\n\t\t// Check if target already exists\n\t\tif (existsSync(targetFile) && !options.overwrite) {\n\t\t\tresult.skipped.push(relative(options.targetDir, targetFile));\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Dry run - don't actually copy\n\t\tif (options.dryRun) {\n\t\t\tresult.filesCopied.push(relative(options.targetDir, targetFile));\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Create target directory if needed\n\t\tconst targetDir = dirname(targetFile);\n\t\tif (!existsSync(targetDir)) {\n\t\t\tmkdirSync(targetDir, { recursive: true });\n\t\t}\n\n\t\t// Copy file - from GitHub or local\n\t\ttry {\n\t\t\tlet fileContent: string;\n\n\t\t\tif (useGitHub) {\n\t\t\t\t// Fetch from GitHub\n\t\t\t\tconst githubPath = getComponentGitHubPath(options.platform, componentName, file);\n\t\t\t\tconst success = await fetchAndSaveFile(githubPath, targetFile);\n\n\t\t\t\tif (!success) {\n\t\t\t\t\tresult.errors.push(`Failed to fetch ${file} from GitHub`);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Read the fetched content for transformation\n\t\t\t\tfileContent = readFileSync(targetFile, 'utf-8');\n\t\t\t} else {\n\t\t\t\t// Copy from local packages directory (for development)\n\t\t\t\tconst packagesDir = options.packagesDir!;\n\t\t\t\tconst componentSourceDir = getComponentSourceDir(options.platform);\n\t\t\t\tconst sourceDir = join(packagesDir, componentSourceDir);\n\t\t\t\tconst sourceFile = join(sourceDir, file);\n\n\t\t\t\tif (!existsSync(sourceFile)) {\n\t\t\t\t\tresult.errors.push(`Source file not found: ${sourceFile}`);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tfileContent = readFileSync(sourceFile, 'utf-8');\n\t\t\t}\n\n\t\t\t// Transform component if needed (Next.js, Nuxt.js)\n\t\t\tconst transformResult = transformComponent(fileContent, {\n\t\t\t\tplatform: options.platform,\n\t\t\t\tcomponentName,\n\t\t\t\tfilePath: targetFile,\n\t\t\t});\n\n\t\t\t// Write the transformed content\n\t\t\twriteFileSync(targetFile, transformResult.content, 'utf-8');\n\n\t\t\t// Log transformation notes if modified\n\t\t\tif (transformResult.modified && transformResult.notes.length > 0) {\n\t\t\t\t// Store notes for later display (optional)\n\t\t\t\tconsole.log(` 📝 ${file}: ${transformResult.notes.join(', ')}`);\n\t\t\t}\n\n\t\t\tresult.filesCopied.push(relative(options.targetDir, targetFile));\n\t\t} catch (error) {\n\t\t\tresult.errors.push(\n\t\t\t\t`Failed to copy ${file}: ${error instanceof Error ? error.message : 'Unknown error'}`,\n\t\t\t);\n\t\t}\n\t}\n\n\tresult.success = result.errors.length === 0;\n\treturn result;\n}\n\n/**\n * Copy multiple components\n *\n * @param componentNames - Array of component names\n * @param options - Copy options\n * @returns Array of copy results\n */\nexport async function copyComponents(\n\tcomponentNames: string[],\n\toptions: ComponentCopyOptions,\n): Promise<ComponentCopyResult[]> {\n\tconst results: ComponentCopyResult[] = [];\n\n\tfor (const name of componentNames) {\n\t\tconst result = await copyComponent(name, options);\n\t\tresults.push(result);\n\n\t\t// If this component failed, log warning but continue\n\t\tif (!result.success) {\n\t\t\tconsole.warn(`⚠️ Failed to copy component \"${name}\"`);\n\t\t}\n\t}\n\n\treturn results;\n}\n\n/**\n * Get components target directory based on platform\n *\n * @param platform - Target platform\n * @param projectRoot - Project root directory\n * @returns Target directory for components\n */\nfunction getComponentsTargetDir(platform: Platform, projectRoot: string): string {\n\tswitch (platform) {\n\t\tcase 'react-native':\n\t\t\t// React Native: src/components or components\n\t\t\tif (existsSync(join(projectRoot, 'src'))) {\n\t\t\t\treturn join(projectRoot, 'src', 'components');\n\t\t\t}\n\t\t\treturn join(projectRoot, 'components');\n\n\t\tcase 'flutter':\n\t\t\t// Flutter: lib/components\n\t\t\treturn join(projectRoot, 'lib', 'components');\n\n\t\tcase 'vue':\n\t\tcase 'nuxtjs':\n\t\t\t// Vue/Nuxt: src/components or components\n\t\t\tif (existsSync(join(projectRoot, 'src'))) {\n\t\t\t\treturn join(projectRoot, 'src', 'components');\n\t\t\t}\n\t\t\treturn join(projectRoot, 'components');\n\n\t\tcase 'react':\n\t\tcase 'nextjs':\n\t\t\t// React/Next.js: src/components or components\n\t\t\tif (existsSync(join(projectRoot, 'src'))) {\n\t\t\t\treturn join(projectRoot, 'src', 'components');\n\t\t\t}\n\t\t\treturn join(projectRoot, 'components');\n\n\t\tcase 'angular':\n\t\t\t// Angular: src/components or components\n\t\t\tif (existsSync(join(projectRoot, 'src', 'app'))) {\n\t\t\t\treturn join(projectRoot, 'src', 'app', 'components');\n\t\t\t}\n\t\t\treturn join(projectRoot, 'components');\n\n\t\tdefault:\n\t\t\t// Default: components at root\n\t\t\treturn join(projectRoot, 'components');\n\t}\n}\n\n/**\n * Generate import statement for component\n *\n * @param componentName - Component name\n * @param platform - Target platform\n * @param options - Options\n * @returns Import statement\n */\nexport function generateImportStatement(\n\tcomponentName: string,\n\tplatform: Platform,\n\toptions?: { registryDir?: string },\n): string {\n\tconst component = getComponent(componentName, platform, options?.registryDir);\n\n\tif (!component) {\n\t\treturn `// Component \"${componentName}\" not found`;\n\t}\n\n\tconst exports = component.exports;\n\n\tswitch (platform) {\n\t\tcase 'react-native':\n\t\tcase 'react':\n\t\tcase 'nextjs':\n\t\t\t// TypeScript/JSX import\n\t\t\treturn `import { ${exports.join(', ')} } from '@/components/${componentName}';`;\n\n\t\tcase 'flutter':\n\t\t\t// Dart import\n\t\t\treturn `import 'package:your_app/components/${componentName}/${componentName.replace(/-/g, '_')}.dart';`;\n\n\t\tcase 'vue':\n\t\tcase 'nuxtjs':\n\t\t\t// Vue import\n\t\t\treturn `import { ${exports.join(', ')} } from '@/components/${componentName}';`;\n\n\t\tcase 'angular':\n\t\t\t// Angular import\n\t\t\treturn `import { ${exports.join(', ')} } from './components/${componentName}';`;\n\n\t\tdefault:\n\t\t\treturn `// Import for platform \"${platform}\" not supported`;\n\t}\n}\n\n/**\n * Create components.json config file for project\n *\n * @param platform - Target platform\n * @param projectRoot - Project root directory\n * @param options - Additional config options\n */\nexport function createComponentsConfig(\n\tplatform: Platform,\n\tprojectRoot: string,\n\toptions?: {\n\t\tframework?: string;\n\t\ttypescript?: boolean;\n\t\tstyling?: 'tailwind' | 'css' | 'styled-components';\n\t},\n): void {\n\tconst config = {\n\t\t$schema: 'https://galaxy-design.vercel.app/schema.json',\n\t\tplatform: platform,\n\t\tframework: options?.framework || platform,\n\t\ttypescript: options?.typescript !== false,\n\t\tstyling: options?.styling || (isMobilePlatform(platform) ? 'styled-components' : 'tailwind'),\n\t\tcomponents: getComponentsTargetDir(platform, projectRoot),\n\t\tutils: join(projectRoot, isMobilePlatform(platform) ? 'lib' : 'src', 'lib'),\n\t};\n\n\tconst configPath = join(projectRoot, 'components.json');\n\twriteFileSync(configPath, JSON.stringify(config, null, 2), 'utf-8');\n}\n\n/**\n * Read components.json config\n *\n * @param projectRoot - Project root directory\n * @returns Config object or null if not found\n */\nexport function readComponentsConfig(projectRoot: string): any | null {\n\tconst configPath = join(projectRoot, 'components.json');\n\n\tif (!existsSync(configPath)) {\n\t\treturn null;\n\t}\n\n\ttry {\n\t\tconst content = readFileSync(configPath, 'utf-8');\n\t\treturn JSON.parse(content);\n\t} catch (error) {\n\t\tconsole.error('Failed to read components.json:', error);\n\t\treturn null;\n\t}\n}\n"],"names":["existsSync","mkdirSync","readFileSync","writeFileSync","dirname","join","relative","getComponentSourceDir","isMobilePlatform","getComponent","validateComponentDependencies","fetchAndSaveFile","getComponentGitHubPath","transformComponent","copyComponent","componentName","options","result","success","filesCopied","errors","skipped","component","platform","registryDir","push","validation","valid","missing","componentsTargetDir","getComponentsTargetDir","targetDir","useGitHub","packagesDir","file","files","targetFile","overwrite","dryRun","recursive","fileContent","githubPath","componentSourceDir","sourceDir","sourceFile","transformResult","filePath","content","modified","notes","length","console","log","error","Error","message","copyComponents","componentNames","results","name","warn","projectRoot","generateImportStatement","exports","replace","createComponentsConfig","config","$schema","framework","typescript","styling","components","utils","configPath","JSON","stringify","readComponentsConfig","parse"],"mappings":"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"}
@@ -0,0 +1,175 @@
1
+ import { _ as _extends } from "@swc/helpers/_/_extends";
2
+ import { readFileSync } from 'fs';
3
+ /**
4
+ * Check if a React/Next.js component needs 'use client' directive
5
+ *
6
+ * Components need 'use client' if they use:
7
+ * - React hooks (useState, useEffect, etc.)
8
+ * - Event handlers (onClick, onChange, etc.)
9
+ * - Browser APIs (window, document, etc.)
10
+ * - Client-side libraries
11
+ */ function needsUseClient(content) {
12
+ const clientIndicators = [
13
+ // React hooks
14
+ /\buse[A-Z]\w+\s*\(/,
15
+ /useState|useEffect|useContext|useReducer|useCallback|useMemo|useRef/,
16
+ // Event handlers
17
+ /\bon[A-Z]\w+\s*=/,
18
+ /onClick|onChange|onSubmit|onFocus|onBlur|onKeyDown|onKeyUp|onMouseEnter|onMouseLeave/,
19
+ // Browser APIs
20
+ /\bwindow\./,
21
+ /\bdocument\./,
22
+ /\bnavigator\./,
23
+ /\blocalStorage\./,
24
+ /\bsessionStorage\./,
25
+ // Client-side only features
26
+ /addEventListener/,
27
+ /removeEventListener/,
28
+ /createPortal/
29
+ ];
30
+ return clientIndicators.some((indicator)=>indicator.test(content));
31
+ }
32
+ /**
33
+ * Check if file already has 'use client' directive
34
+ */ function hasUseClientDirective(content) {
35
+ const lines = content.split('\n');
36
+ const firstNonEmptyLine = lines.find((line)=>line.trim() !== '');
37
+ return (firstNonEmptyLine == null ? void 0 : firstNonEmptyLine.trim().startsWith("'use client'")) || (firstNonEmptyLine == null ? void 0 : firstNonEmptyLine.trim().startsWith('"use client"')) || false;
38
+ }
39
+ /**
40
+ * Add 'use client' directive to Next.js component
41
+ */ function addUseClientDirective(content) {
42
+ // Skip if already has the directive
43
+ if (hasUseClientDirective(content)) {
44
+ return content;
45
+ }
46
+ // Find the first import or code line
47
+ const lines = content.split('\n');
48
+ let insertIndex = 0;
49
+ // Skip shebang and comments at the top
50
+ for(let i = 0; i < lines.length; i++){
51
+ const line = lines[i].trim();
52
+ if (line === '' || line.startsWith('//') || line.startsWith('/*')) {
53
+ insertIndex = i + 1;
54
+ } else {
55
+ break;
56
+ }
57
+ }
58
+ // Insert 'use client' directive
59
+ lines.splice(insertIndex, 0, "'use client'", '');
60
+ return lines.join('\n');
61
+ }
62
+ /**
63
+ * Transform component for Next.js
64
+ *
65
+ * Adds 'use client' directive if component uses client-side features
66
+ */ function transformNextjsComponent(content, componentName) {
67
+ const notes = [];
68
+ let modified = false;
69
+ let transformedContent = content;
70
+ // Check if component needs 'use client'
71
+ if (needsUseClient(content) && !hasUseClientDirective(content)) {
72
+ transformedContent = addUseClientDirective(content);
73
+ modified = true;
74
+ notes.push(`Added 'use client' directive (component uses client-side features)`);
75
+ } else if (hasUseClientDirective(content)) {
76
+ notes.push(`Component already has 'use client' directive`);
77
+ } else {
78
+ notes.push(`Component appears to be server-safe (no 'use client' needed)`);
79
+ }
80
+ return {
81
+ content: transformedContent,
82
+ modified,
83
+ notes
84
+ };
85
+ }
86
+ /**
87
+ * Transform component for Nuxt.js
88
+ *
89
+ * Currently no transformations needed, but placeholder for future enhancements
90
+ */ function transformNuxtjsComponent(content, componentName) {
91
+ const notes = [];
92
+ // Check for Nuxt-specific patterns
93
+ const hasNuxtImports = /from ['"]#app['"]/.test(content);
94
+ const hasAutoImports = /\b(navigateTo|useFetch|useAsyncData|useState)\b/.test(content);
95
+ if (hasNuxtImports) {
96
+ notes.push('Component uses Nuxt 3 auto-imports (#app)');
97
+ }
98
+ if (hasAutoImports) {
99
+ notes.push('Component uses Nuxt 3 composables (auto-imported)');
100
+ }
101
+ if (!hasNuxtImports && !hasAutoImports) {
102
+ notes.push('Component appears to be standard Vue 3 (works in Nuxt)');
103
+ }
104
+ return {
105
+ content,
106
+ modified: false,
107
+ notes
108
+ };
109
+ }
110
+ /**
111
+ * Transform component file based on platform
112
+ *
113
+ * @param content - File content
114
+ * @param options - Transform options
115
+ * @returns Transform result
116
+ */ export function transformComponent(content, options) {
117
+ const { platform, componentName } = options;
118
+ switch(platform){
119
+ case 'nextjs':
120
+ return transformNextjsComponent(content, componentName);
121
+ case 'nuxtjs':
122
+ return transformNuxtjsComponent(content, componentName);
123
+ // Other platforms don't need transformation
124
+ case 'react':
125
+ case 'vue':
126
+ case 'angular':
127
+ case 'react-native':
128
+ case 'flutter':
129
+ default:
130
+ return {
131
+ content,
132
+ modified: false,
133
+ notes: [
134
+ 'No transformation needed for this platform'
135
+ ]
136
+ };
137
+ }
138
+ }
139
+ /**
140
+ * Transform component file from file path
141
+ *
142
+ * @param filePath - Path to component file
143
+ * @param options - Transform options
144
+ * @returns Transform result
145
+ */ export function transformComponentFile(filePath, options) {
146
+ const content = readFileSync(filePath, 'utf-8');
147
+ return transformComponent(content, _extends({}, options, {
148
+ filePath
149
+ }));
150
+ }
151
+ /**
152
+ * Batch transform multiple files
153
+ *
154
+ * @param files - Array of file paths
155
+ * @param options - Transform options (without filePath)
156
+ * @returns Array of transform results
157
+ */ export function transformComponentFiles(files, options) {
158
+ const results = new Map();
159
+ for (const filePath of files){
160
+ const componentName = options.componentName || extractComponentName(filePath);
161
+ const result = transformComponentFile(filePath, _extends({}, options, {
162
+ componentName
163
+ }));
164
+ results.set(filePath, result);
165
+ }
166
+ return results;
167
+ }
168
+ /**
169
+ * Extract component name from file path
170
+ */ function extractComponentName(filePath) {
171
+ const fileName = filePath.split('/').pop() || '';
172
+ return fileName.replace(/\.(tsx?|vue|js|jsx)$/, '');
173
+ }
174
+
175
+ //# sourceMappingURL=component-transformer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/utils/component-transformer.ts"],"sourcesContent":["import { readFileSync } from 'fs';\nimport type { Platform } from './platform-detector';\n\n/**\n * Transform options for component files\n */\nexport interface TransformOptions {\n\t/** Target platform */\n\tplatform: Platform;\n\t/** Component name */\n\tcomponentName: string;\n\t/** File path */\n\tfilePath: string;\n}\n\n/**\n * Transform result\n */\nexport interface TransformResult {\n\t/** Transformed content */\n\tcontent: string;\n\t/** Whether content was modified */\n\tmodified: boolean;\n\t/** Transformation notes */\n\tnotes: string[];\n}\n\n/**\n * Check if a React/Next.js component needs 'use client' directive\n *\n * Components need 'use client' if they use:\n * - React hooks (useState, useEffect, etc.)\n * - Event handlers (onClick, onChange, etc.)\n * - Browser APIs (window, document, etc.)\n * - Client-side libraries\n */\nfunction needsUseClient(content: string): boolean {\n\tconst clientIndicators = [\n\t\t// React hooks\n\t\t/\\buse[A-Z]\\w+\\s*\\(/,\n\t\t/useState|useEffect|useContext|useReducer|useCallback|useMemo|useRef/,\n\n\t\t// Event handlers\n\t\t/\\bon[A-Z]\\w+\\s*=/,\n\t\t/onClick|onChange|onSubmit|onFocus|onBlur|onKeyDown|onKeyUp|onMouseEnter|onMouseLeave/,\n\n\t\t// Browser APIs\n\t\t/\\bwindow\\./,\n\t\t/\\bdocument\\./,\n\t\t/\\bnavigator\\./,\n\t\t/\\blocalStorage\\./,\n\t\t/\\bsessionStorage\\./,\n\n\t\t// Client-side only features\n\t\t/addEventListener/,\n\t\t/removeEventListener/,\n\t\t/createPortal/,\n\t];\n\n\treturn clientIndicators.some(indicator => indicator.test(content));\n}\n\n/**\n * Check if file already has 'use client' directive\n */\nfunction hasUseClientDirective(content: string): boolean {\n\tconst lines = content.split('\\n');\n\tconst firstNonEmptyLine = lines.find(line => line.trim() !== '');\n\treturn firstNonEmptyLine?.trim().startsWith(\"'use client'\") ||\n\t firstNonEmptyLine?.trim().startsWith('\"use client\"') || false;\n}\n\n/**\n * Add 'use client' directive to Next.js component\n */\nfunction addUseClientDirective(content: string): string {\n\t// Skip if already has the directive\n\tif (hasUseClientDirective(content)) {\n\t\treturn content;\n\t}\n\n\t// Find the first import or code line\n\tconst lines = content.split('\\n');\n\tlet insertIndex = 0;\n\n\t// Skip shebang and comments at the top\n\tfor (let i = 0; i < lines.length; i++) {\n\t\tconst line = lines[i].trim();\n\t\tif (line === '' || line.startsWith('//') || line.startsWith('/*')) {\n\t\t\tinsertIndex = i + 1;\n\t\t} else {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t// Insert 'use client' directive\n\tlines.splice(insertIndex, 0, \"'use client'\", '');\n\treturn lines.join('\\n');\n}\n\n/**\n * Transform component for Next.js\n *\n * Adds 'use client' directive if component uses client-side features\n */\nfunction transformNextjsComponent(content: string, componentName: string): TransformResult {\n\tconst notes: string[] = [];\n\tlet modified = false;\n\tlet transformedContent = content;\n\n\t// Check if component needs 'use client'\n\tif (needsUseClient(content) && !hasUseClientDirective(content)) {\n\t\ttransformedContent = addUseClientDirective(content);\n\t\tmodified = true;\n\t\tnotes.push(`Added 'use client' directive (component uses client-side features)`);\n\t} else if (hasUseClientDirective(content)) {\n\t\tnotes.push(`Component already has 'use client' directive`);\n\t} else {\n\t\tnotes.push(`Component appears to be server-safe (no 'use client' needed)`);\n\t}\n\n\treturn {\n\t\tcontent: transformedContent,\n\t\tmodified,\n\t\tnotes,\n\t};\n}\n\n/**\n * Transform component for Nuxt.js\n *\n * Currently no transformations needed, but placeholder for future enhancements\n */\nfunction transformNuxtjsComponent(content: string, componentName: string): TransformResult {\n\tconst notes: string[] = [];\n\n\t// Check for Nuxt-specific patterns\n\tconst hasNuxtImports = /from ['\"]#app['\"]/.test(content);\n\tconst hasAutoImports = /\\b(navigateTo|useFetch|useAsyncData|useState)\\b/.test(content);\n\n\tif (hasNuxtImports) {\n\t\tnotes.push('Component uses Nuxt 3 auto-imports (#app)');\n\t}\n\tif (hasAutoImports) {\n\t\tnotes.push('Component uses Nuxt 3 composables (auto-imported)');\n\t}\n\tif (!hasNuxtImports && !hasAutoImports) {\n\t\tnotes.push('Component appears to be standard Vue 3 (works in Nuxt)');\n\t}\n\n\treturn {\n\t\tcontent,\n\t\tmodified: false,\n\t\tnotes,\n\t};\n}\n\n/**\n * Transform component file based on platform\n *\n * @param content - File content\n * @param options - Transform options\n * @returns Transform result\n */\nexport function transformComponent(content: string, options: TransformOptions): TransformResult {\n\tconst { platform, componentName } = options;\n\n\tswitch (platform) {\n\t\tcase 'nextjs':\n\t\t\treturn transformNextjsComponent(content, componentName);\n\n\t\tcase 'nuxtjs':\n\t\t\treturn transformNuxtjsComponent(content, componentName);\n\n\t\t// Other platforms don't need transformation\n\t\tcase 'react':\n\t\tcase 'vue':\n\t\tcase 'angular':\n\t\tcase 'react-native':\n\t\tcase 'flutter':\n\t\tdefault:\n\t\t\treturn {\n\t\t\t\tcontent,\n\t\t\t\tmodified: false,\n\t\t\t\tnotes: ['No transformation needed for this platform'],\n\t\t\t};\n\t}\n}\n\n/**\n * Transform component file from file path\n *\n * @param filePath - Path to component file\n * @param options - Transform options\n * @returns Transform result\n */\nexport function transformComponentFile(filePath: string, options: Omit<TransformOptions, 'filePath'>): TransformResult {\n\tconst content = readFileSync(filePath, 'utf-8');\n\treturn transformComponent(content, { ...options, filePath });\n}\n\n/**\n * Batch transform multiple files\n *\n * @param files - Array of file paths\n * @param options - Transform options (without filePath)\n * @returns Array of transform results\n */\nexport function transformComponentFiles(\n\tfiles: string[],\n\toptions: Omit<TransformOptions, 'filePath' | 'componentName'>\n): Map<string, TransformResult> {\n\tconst results = new Map<string, TransformResult>();\n\n\tfor (const filePath of files) {\n\t\tconst componentName = options.componentName || extractComponentName(filePath);\n\t\tconst result = transformComponentFile(filePath, { ...options, componentName });\n\t\tresults.set(filePath, result);\n\t}\n\n\treturn results;\n}\n\n/**\n * Extract component name from file path\n */\nfunction extractComponentName(filePath: string): string {\n\tconst fileName = filePath.split('/').pop() || '';\n\treturn fileName.replace(/\\.(tsx?|vue|js|jsx)$/, '');\n}\n"],"names":["readFileSync","needsUseClient","content","clientIndicators","some","indicator","test","hasUseClientDirective","lines","split","firstNonEmptyLine","find","line","trim","startsWith","addUseClientDirective","insertIndex","i","length","splice","join","transformNextjsComponent","componentName","notes","modified","transformedContent","push","transformNuxtjsComponent","hasNuxtImports","hasAutoImports","transformComponent","options","platform","transformComponentFile","filePath","transformComponentFiles","files","results","Map","extractComponentName","result","set","fileName","pop","replace"],"mappings":"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"}
@@ -6,7 +6,9 @@ export const frameworkSchema = z.enum([
6
6
  'react',
7
7
  'angular',
8
8
  'react-native',
9
- 'flutter'
9
+ 'flutter',
10
+ 'nextjs',
11
+ 'nuxtjs'
10
12
  ]);
11
13
  // Base color types
12
14
  export const baseColorSchema = z.enum([
@@ -137,6 +139,42 @@ export const defaultConfigs = {
137
139
  lib: 'lib'
138
140
  },
139
141
  iconLibrary: 'lucide'
142
+ },
143
+ nextjs: {
144
+ framework: 'nextjs',
145
+ typescript: true,
146
+ tailwind: {
147
+ config: 'tailwind.config.ts',
148
+ css: 'app/globals.css',
149
+ baseColor: 'slate',
150
+ cssVariables: true,
151
+ prefix: ''
152
+ },
153
+ aliases: {
154
+ components: '@/components',
155
+ utils: '@/lib/utils',
156
+ ui: '@/components/ui',
157
+ lib: '@/lib'
158
+ },
159
+ iconLibrary: 'lucide'
160
+ },
161
+ nuxtjs: {
162
+ framework: 'nuxtjs',
163
+ typescript: true,
164
+ tailwind: {
165
+ config: 'tailwind.config.js',
166
+ css: 'assets/css/main.css',
167
+ baseColor: 'slate',
168
+ cssVariables: true,
169
+ prefix: ''
170
+ },
171
+ aliases: {
172
+ components: '@/components',
173
+ utils: '@/lib/utils',
174
+ ui: '@/components/ui',
175
+ lib: '@/lib'
176
+ },
177
+ iconLibrary: 'lucide'
140
178
  }
141
179
  };
142
180
  /**
@@ -165,11 +203,13 @@ export const defaultConfigs = {
165
203
  const ext = typescript ? 'ts' : 'js';
166
204
  switch(framework){
167
205
  case 'vue':
206
+ case 'nuxtjs':
168
207
  return [
169
208
  '.vue',
170
209
  `.${ext}`
171
210
  ];
172
211
  case 'react':
212
+ case 'nextjs':
173
213
  return [
174
214
  `.tsx`,
175
215
  `.jsx`,
@@ -204,8 +244,10 @@ export const defaultConfigs = {
204
244
  */ export function getComponentPath(framework) {
205
245
  switch(framework){
206
246
  case 'vue':
247
+ case 'nuxtjs':
207
248
  return 'src/components';
208
249
  case 'react':
250
+ case 'nextjs':
209
251
  return 'src/components';
210
252
  case 'react-native':
211
253
  return 'src/components';
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utils/config-schema.ts"],"sourcesContent":["import { z } from 'zod';\n\n// Framework types\nexport const frameworkSchema = z.enum(['vue', 'react', 'angular', 'react-native', 'flutter']);\nexport type Framework = z.infer<typeof frameworkSchema>;\n\n// Base color types\nexport const baseColorSchema = z.enum(['slate', 'gray', 'zinc', 'neutral', 'stone']);\nexport type BaseColor = z.infer<typeof baseColorSchema>;\n\n// Icon library types\nexport const iconLibrarySchema = z.enum(['lucide', 'heroicons', 'radix-icons']);\nexport type IconLibrary = z.infer<typeof iconLibrarySchema>;\n\n// Tailwind configuration\nexport const tailwindConfigSchema = z.object({\n config: z.string().default('tailwind.config.js'),\n css: z.string(),\n baseColor: baseColorSchema.default('slate'),\n cssVariables: z.boolean().default(true),\n prefix: z.string().optional().default(''),\n});\nexport type TailwindConfig = z.infer<typeof tailwindConfigSchema>;\n\n// Aliases configuration\nexport const aliasesSchema = z.object({\n components: z.string(),\n utils: z.string(),\n ui: z.string().optional(),\n lib: z.string().optional(),\n});\nexport type Aliases = z.infer<typeof aliasesSchema>;\n\n// Main components.json schema\nexport const componentsConfigSchema = z.object({\n $schema: z.string().optional(),\n framework: frameworkSchema,\n typescript: z.boolean().default(true),\n tailwind: tailwindConfigSchema,\n aliases: aliasesSchema,\n iconLibrary: iconLibrarySchema.default('lucide'),\n});\nexport type ComponentsConfig = z.infer<typeof componentsConfigSchema>;\n\n// Default configurations per framework\nexport const defaultConfigs: Record<Framework, Partial<ComponentsConfig>> = {\n vue: {\n framework: 'vue',\n typescript: true,\n tailwind: {\n config: 'tailwind.config.js',\n css: 'src/assets/styles/global.css',\n baseColor: 'slate',\n cssVariables: true,\n prefix: '',\n },\n aliases: {\n components: '@/components',\n utils: '@/lib/utils',\n ui: '@/components/ui',\n lib: '@/lib',\n },\n iconLibrary: 'lucide',\n },\n react: {\n framework: 'react',\n typescript: true,\n tailwind: {\n config: 'tailwind.config.js',\n css: 'src/app/globals.css',\n baseColor: 'slate',\n cssVariables: true,\n prefix: '',\n },\n aliases: {\n components: '@/components',\n utils: '@/lib/utils',\n ui: '@/components/ui',\n lib: '@/lib',\n },\n iconLibrary: 'lucide',\n },\n angular: {\n framework: 'angular',\n typescript: true,\n tailwind: {\n config: 'tailwind.config.js',\n css: 'src/styles.css',\n baseColor: 'slate',\n cssVariables: true,\n prefix: '',\n },\n aliases: {\n components: '@/components',\n utils: '@/lib/utils',\n ui: '@/components/ui',\n lib: '@/lib',\n },\n iconLibrary: 'lucide',\n },\n 'react-native': {\n framework: 'react-native',\n typescript: true,\n tailwind: {\n config: 'tailwind.config.js',\n css: 'global.css',\n baseColor: 'slate',\n cssVariables: true,\n prefix: '',\n },\n aliases: {\n components: '@/components',\n utils: '@/lib/utils',\n ui: '@/components/ui',\n lib: '@/lib',\n },\n iconLibrary: 'lucide',\n },\n flutter: {\n framework: 'flutter',\n typescript: false, // Flutter uses Dart\n tailwind: {\n config: '', // Flutter doesn't use Tailwind\n css: '',\n baseColor: 'slate',\n cssVariables: false,\n prefix: '',\n },\n aliases: {\n components: 'lib/components',\n utils: 'lib/utils',\n ui: 'lib/components/ui',\n lib: 'lib',\n },\n iconLibrary: 'lucide',\n },\n};\n\n/**\n * Get default config for a framework\n */\nexport function getDefaultConfig(framework: Framework): ComponentsConfig {\n const defaults = defaultConfigs[framework];\n return {\n $schema: 'https://galaxy-design.vercel.app/schema.json',\n ...defaults,\n } as ComponentsConfig;\n}\n\n/**\n * Validate components.json config\n */\nexport function validateConfig(config: unknown): ComponentsConfig {\n try {\n return componentsConfigSchema.parse(config);\n } catch (error) {\n if (error instanceof z.ZodError) {\n throw new Error(\n `Invalid components.json configuration:\\n${error.issues\n .map((e: z.ZodIssue) => ` - ${e.path.join('.')}: ${e.message}`)\n .join('\\n')}`\n );\n }\n throw error;\n }\n}\n\n/**\n * Get framework-specific file extensions\n */\nexport function getFileExtensions(framework: Framework, typescript: boolean): string[] {\n const ext = typescript ? 'ts' : 'js';\n\n switch (framework) {\n case 'vue':\n return ['.vue', `.${ext}`];\n case 'react':\n return [`.tsx`, `.jsx`, `.${ext}`];\n case 'react-native':\n return [`.tsx`, `.jsx`, `.native.${ext}`, `.${ext}`];\n case 'angular':\n return [`.component.ts`, `.service.ts`, `.directive.ts`, `.${ext}`];\n case 'flutter':\n return ['.dart'];\n default:\n return [`.${ext}`];\n }\n}\n\n/**\n * Get framework-specific component path patterns\n */\nexport function getComponentPath(framework: Framework): string {\n switch (framework) {\n case 'vue':\n return 'src/components';\n case 'react':\n return 'src/components';\n case 'react-native':\n return 'src/components';\n case 'angular':\n return 'src/app/components';\n case 'flutter':\n return 'lib/components';\n default:\n return 'src/components';\n }\n}\n"],"names":["z","frameworkSchema","enum","baseColorSchema","iconLibrarySchema","tailwindConfigSchema","object","config","string","default","css","baseColor","cssVariables","boolean","prefix","optional","aliasesSchema","components","utils","ui","lib","componentsConfigSchema","$schema","framework","typescript","tailwind","aliases","iconLibrary","defaultConfigs","vue","react","angular","flutter","getDefaultConfig","defaults","validateConfig","parse","error","ZodError","Error","issues","map","e","path","join","message","getFileExtensions","ext","getComponentPath"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/utils/config-schema.ts"],"sourcesContent":["import { z } from 'zod';\n\n// Framework types\nexport const frameworkSchema = z.enum(['vue', 'react', 'angular', 'react-native', 'flutter', 'nextjs', 'nuxtjs']);\nexport type Framework = z.infer<typeof frameworkSchema>;\n\n// Base color types\nexport const baseColorSchema = z.enum(['slate', 'gray', 'zinc', 'neutral', 'stone']);\nexport type BaseColor = z.infer<typeof baseColorSchema>;\n\n// Icon library types\nexport const iconLibrarySchema = z.enum(['lucide', 'heroicons', 'radix-icons']);\nexport type IconLibrary = z.infer<typeof iconLibrarySchema>;\n\n// Tailwind configuration\nexport const tailwindConfigSchema = z.object({\n config: z.string().default('tailwind.config.js'),\n css: z.string(),\n baseColor: baseColorSchema.default('slate'),\n cssVariables: z.boolean().default(true),\n prefix: z.string().optional().default(''),\n});\nexport type TailwindConfig = z.infer<typeof tailwindConfigSchema>;\n\n// Aliases configuration\nexport const aliasesSchema = z.object({\n components: z.string(),\n utils: z.string(),\n ui: z.string().optional(),\n lib: z.string().optional(),\n});\nexport type Aliases = z.infer<typeof aliasesSchema>;\n\n// Main components.json schema\nexport const componentsConfigSchema = z.object({\n $schema: z.string().optional(),\n framework: frameworkSchema,\n typescript: z.boolean().default(true),\n tailwind: tailwindConfigSchema,\n aliases: aliasesSchema,\n iconLibrary: iconLibrarySchema.default('lucide'),\n});\nexport type ComponentsConfig = z.infer<typeof componentsConfigSchema>;\n\n// Default configurations per framework\nexport const defaultConfigs: Record<Framework, Partial<ComponentsConfig>> = {\n vue: {\n framework: 'vue',\n typescript: true,\n tailwind: {\n config: 'tailwind.config.js',\n css: 'src/assets/styles/global.css',\n baseColor: 'slate',\n cssVariables: true,\n prefix: '',\n },\n aliases: {\n components: '@/components',\n utils: '@/lib/utils',\n ui: '@/components/ui',\n lib: '@/lib',\n },\n iconLibrary: 'lucide',\n },\n react: {\n framework: 'react',\n typescript: true,\n tailwind: {\n config: 'tailwind.config.js',\n css: 'src/app/globals.css',\n baseColor: 'slate',\n cssVariables: true,\n prefix: '',\n },\n aliases: {\n components: '@/components',\n utils: '@/lib/utils',\n ui: '@/components/ui',\n lib: '@/lib',\n },\n iconLibrary: 'lucide',\n },\n angular: {\n framework: 'angular',\n typescript: true,\n tailwind: {\n config: 'tailwind.config.js',\n css: 'src/styles.css',\n baseColor: 'slate',\n cssVariables: true,\n prefix: '',\n },\n aliases: {\n components: '@/components',\n utils: '@/lib/utils',\n ui: '@/components/ui',\n lib: '@/lib',\n },\n iconLibrary: 'lucide',\n },\n 'react-native': {\n framework: 'react-native',\n typescript: true,\n tailwind: {\n config: 'tailwind.config.js',\n css: 'global.css',\n baseColor: 'slate',\n cssVariables: true,\n prefix: '',\n },\n aliases: {\n components: '@/components',\n utils: '@/lib/utils',\n ui: '@/components/ui',\n lib: '@/lib',\n },\n iconLibrary: 'lucide',\n },\n flutter: {\n framework: 'flutter',\n typescript: false, // Flutter uses Dart\n tailwind: {\n config: '', // Flutter doesn't use Tailwind\n css: '',\n baseColor: 'slate',\n cssVariables: false,\n prefix: '',\n },\n aliases: {\n components: 'lib/components',\n utils: 'lib/utils',\n ui: 'lib/components/ui',\n lib: 'lib',\n },\n iconLibrary: 'lucide',\n },\n nextjs: {\n framework: 'nextjs',\n typescript: true,\n tailwind: {\n config: 'tailwind.config.ts',\n css: 'app/globals.css', // Next.js App Router\n baseColor: 'slate',\n cssVariables: true,\n prefix: '',\n },\n aliases: {\n components: '@/components',\n utils: '@/lib/utils',\n ui: '@/components/ui',\n lib: '@/lib',\n },\n iconLibrary: 'lucide',\n },\n nuxtjs: {\n framework: 'nuxtjs',\n typescript: true,\n tailwind: {\n config: 'tailwind.config.js',\n css: 'assets/css/main.css', // Nuxt 3 default\n baseColor: 'slate',\n cssVariables: true,\n prefix: '',\n },\n aliases: {\n components: '@/components',\n utils: '@/lib/utils',\n ui: '@/components/ui',\n lib: '@/lib',\n },\n iconLibrary: 'lucide',\n },\n};\n\n/**\n * Get default config for a framework\n */\nexport function getDefaultConfig(framework: Framework): ComponentsConfig {\n const defaults = defaultConfigs[framework];\n return {\n $schema: 'https://galaxy-design.vercel.app/schema.json',\n ...defaults,\n } as ComponentsConfig;\n}\n\n/**\n * Validate components.json config\n */\nexport function validateConfig(config: unknown): ComponentsConfig {\n try {\n return componentsConfigSchema.parse(config);\n } catch (error) {\n if (error instanceof z.ZodError) {\n throw new Error(\n `Invalid components.json configuration:\\n${error.issues\n .map((e: z.ZodIssue) => ` - ${e.path.join('.')}: ${e.message}`)\n .join('\\n')}`\n );\n }\n throw error;\n }\n}\n\n/**\n * Get framework-specific file extensions\n */\nexport function getFileExtensions(framework: Framework, typescript: boolean): string[] {\n const ext = typescript ? 'ts' : 'js';\n\n switch (framework) {\n case 'vue':\n case 'nuxtjs':\n return ['.vue', `.${ext}`];\n case 'react':\n case 'nextjs':\n return [`.tsx`, `.jsx`, `.${ext}`];\n case 'react-native':\n return [`.tsx`, `.jsx`, `.native.${ext}`, `.${ext}`];\n case 'angular':\n return [`.component.ts`, `.service.ts`, `.directive.ts`, `.${ext}`];\n case 'flutter':\n return ['.dart'];\n default:\n return [`.${ext}`];\n }\n}\n\n/**\n * Get framework-specific component path patterns\n */\nexport function getComponentPath(framework: Framework): string {\n switch (framework) {\n case 'vue':\n case 'nuxtjs':\n return 'src/components';\n case 'react':\n case 'nextjs':\n return 'src/components';\n case 'react-native':\n return 'src/components';\n case 'angular':\n return 'src/app/components';\n case 'flutter':\n return 'lib/components';\n default:\n return 'src/components';\n }\n}\n"],"names":["z","frameworkSchema","enum","baseColorSchema","iconLibrarySchema","tailwindConfigSchema","object","config","string","default","css","baseColor","cssVariables","boolean","prefix","optional","aliasesSchema","components","utils","ui","lib","componentsConfigSchema","$schema","framework","typescript","tailwind","aliases","iconLibrary","defaultConfigs","vue","react","angular","flutter","nextjs","nuxtjs","getDefaultConfig","defaults","validateConfig","parse","error","ZodError","Error","issues","map","e","path","join","message","getFileExtensions","ext","getComponentPath"],"mappings":";AAAA,SAASA,CAAC,QAAQ,MAAM;AAExB,kBAAkB;AAClB,OAAO,MAAMC,kBAAkBD,EAAEE,IAAI,CAAC;IAAC;IAAO;IAAS;IAAW;IAAgB;IAAW;IAAU;CAAS,EAAE;AAGlH,mBAAmB;AACnB,OAAO,MAAMC,kBAAkBH,EAAEE,IAAI,CAAC;IAAC;IAAS;IAAQ;IAAQ;IAAW;CAAQ,EAAE;AAGrF,qBAAqB;AACrB,OAAO,MAAME,oBAAoBJ,EAAEE,IAAI,CAAC;IAAC;IAAU;IAAa;CAAc,EAAE;AAGhF,yBAAyB;AACzB,OAAO,MAAMG,uBAAuBL,EAAEM,MAAM,CAAC;IAC3CC,QAAQP,EAAEQ,MAAM,GAAGC,OAAO,CAAC;IAC3BC,KAAKV,EAAEQ,MAAM;IACbG,WAAWR,gBAAgBM,OAAO,CAAC;IACnCG,cAAcZ,EAAEa,OAAO,GAAGJ,OAAO,CAAC;IAClCK,QAAQd,EAAEQ,MAAM,GAAGO,QAAQ,GAAGN,OAAO,CAAC;AACxC,GAAG;AAGH,wBAAwB;AACxB,OAAO,MAAMO,gBAAgBhB,EAAEM,MAAM,CAAC;IACpCW,YAAYjB,EAAEQ,MAAM;IACpBU,OAAOlB,EAAEQ,MAAM;IACfW,IAAInB,EAAEQ,MAAM,GAAGO,QAAQ;IACvBK,KAAKpB,EAAEQ,MAAM,GAAGO,QAAQ;AAC1B,GAAG;AAGH,8BAA8B;AAC9B,OAAO,MAAMM,yBAAyBrB,EAAEM,MAAM,CAAC;IAC7CgB,SAAStB,EAAEQ,MAAM,GAAGO,QAAQ;IAC5BQ,WAAWtB;IACXuB,YAAYxB,EAAEa,OAAO,GAAGJ,OAAO,CAAC;IAChCgB,UAAUpB;IACVqB,SAASV;IACTW,aAAavB,kBAAkBK,OAAO,CAAC;AACzC,GAAG;AAGH,uCAAuC;AACvC,OAAO,MAAMmB,iBAA+D;IAC1EC,KAAK;QACHN,WAAW;QACXC,YAAY;QACZC,UAAU;YACRlB,QAAQ;YACRG,KAAK;YACLC,WAAW;YACXC,cAAc;YACdE,QAAQ;QACV;QACAY,SAAS;YACPT,YAAY;YACZC,OAAO;YACPC,IAAI;YACJC,KAAK;QACP;QACAO,aAAa;IACf;IACAG,OAAO;QACLP,WAAW;QACXC,YAAY;QACZC,UAAU;YACRlB,QAAQ;YACRG,KAAK;YACLC,WAAW;YACXC,cAAc;YACdE,QAAQ;QACV;QACAY,SAAS;YACPT,YAAY;YACZC,OAAO;YACPC,IAAI;YACJC,KAAK;QACP;QACAO,aAAa;IACf;IACAI,SAAS;QACPR,WAAW;QACXC,YAAY;QACZC,UAAU;YACRlB,QAAQ;YACRG,KAAK;YACLC,WAAW;YACXC,cAAc;YACdE,QAAQ;QACV;QACAY,SAAS;YACPT,YAAY;YACZC,OAAO;YACPC,IAAI;YACJC,KAAK;QACP;QACAO,aAAa;IACf;IACA,gBAAgB;QACdJ,WAAW;QACXC,YAAY;QACZC,UAAU;YACRlB,QAAQ;YACRG,KAAK;YACLC,WAAW;YACXC,cAAc;YACdE,QAAQ;QACV;QACAY,SAAS;YACPT,YAAY;YACZC,OAAO;YACPC,IAAI;YACJC,KAAK;QACP;QACAO,aAAa;IACf;IACAK,SAAS;QACPT,WAAW;QACXC,YAAY;QACZC,UAAU;YACRlB,QAAQ;YACRG,KAAK;YACLC,WAAW;YACXC,cAAc;YACdE,QAAQ;QACV;QACAY,SAAS;YACPT,YAAY;YACZC,OAAO;YACPC,IAAI;YACJC,KAAK;QACP;QACAO,aAAa;IACf;IACAM,QAAQ;QACNV,WAAW;QACXC,YAAY;QACZC,UAAU;YACRlB,QAAQ;YACRG,KAAK;YACLC,WAAW;YACXC,cAAc;YACdE,QAAQ;QACV;QACAY,SAAS;YACPT,YAAY;YACZC,OAAO;YACPC,IAAI;YACJC,KAAK;QACP;QACAO,aAAa;IACf;IACAO,QAAQ;QACNX,WAAW;QACXC,YAAY;QACZC,UAAU;YACRlB,QAAQ;YACRG,KAAK;YACLC,WAAW;YACXC,cAAc;YACdE,QAAQ;QACV;QACAY,SAAS;YACPT,YAAY;YACZC,OAAO;YACPC,IAAI;YACJC,KAAK;QACP;QACAO,aAAa;IACf;AACF,EAAE;AAEF;;CAEC,GACD,OAAO,SAASQ,iBAAiBZ,SAAoB;IACnD,MAAMa,WAAWR,cAAc,CAACL,UAAU;IAC1C,OAAO;QACLD,SAAS;OACNc;AAEP;AAEA;;CAEC,GACD,OAAO,SAASC,eAAe9B,MAAe;IAC5C,IAAI;QACF,OAAOc,uBAAuBiB,KAAK,CAAC/B;IACtC,EAAE,OAAOgC,OAAO;QACd,IAAIA,iBAAiBvC,EAAEwC,QAAQ,EAAE;YAC/B,MAAM,IAAIC,MACR,CAAC,wCAAwC,EAAEF,MAAMG,MAAM,CACpDC,GAAG,CAAC,CAACC,IAAkB,CAAC,IAAI,EAAEA,EAAEC,IAAI,CAACC,IAAI,CAAC,KAAK,EAAE,EAAEF,EAAEG,OAAO,EAAE,EAC9DD,IAAI,CAAC,OAAO;QAEnB;QACA,MAAMP;IACR;AACF;AAEA;;CAEC,GACD,OAAO,SAASS,kBAAkBzB,SAAoB,EAAEC,UAAmB;IACzE,MAAMyB,MAAMzB,aAAa,OAAO;IAEhC,OAAQD;QACN,KAAK;QACL,KAAK;YACH,OAAO;gBAAC;gBAAQ,CAAC,CAAC,EAAE0B,KAAK;aAAC;QAC5B,KAAK;QACL,KAAK;YACH,OAAO;gBAAC,CAAC,IAAI,CAAC;gBAAE,CAAC,IAAI,CAAC;gBAAE,CAAC,CAAC,EAAEA,KAAK;aAAC;QACpC,KAAK;YACH,OAAO;gBAAC,CAAC,IAAI,CAAC;gBAAE,CAAC,IAAI,CAAC;gBAAE,CAAC,QAAQ,EAAEA,KAAK;gBAAE,CAAC,CAAC,EAAEA,KAAK;aAAC;QACtD,KAAK;YACH,OAAO;gBAAC,CAAC,aAAa,CAAC;gBAAE,CAAC,WAAW,CAAC;gBAAE,CAAC,aAAa,CAAC;gBAAE,CAAC,CAAC,EAAEA,KAAK;aAAC;QACrE,KAAK;YACH,OAAO;gBAAC;aAAQ;QAClB;YACE,OAAO;gBAAC,CAAC,CAAC,EAAEA,KAAK;aAAC;IACtB;AACF;AAEA;;CAEC,GACD,OAAO,SAASC,iBAAiB3B,SAAoB;IACnD,OAAQA;QACN,KAAK;QACL,KAAK;YACH,OAAO;QACT,KAAK;QACL,KAAK;YACH,OAAO;QACT,KAAK;YACH,OAAO;QACT,KAAK;YACH,OAAO;QACT,KAAK;YACH,OAAO;QACT;YACE,OAAO;IACX;AACF"}
@@ -20,6 +20,14 @@ import { resolve } from 'path';
20
20
  if (deps['react-native']) {
21
21
  return 'react-native';
22
22
  }
23
+ // Check for Next.js (must be before React check)
24
+ if (deps['next']) {
25
+ return 'nextjs';
26
+ }
27
+ // Check for Nuxt.js (must be before Vue check)
28
+ if (deps['nuxt'] || deps['nuxt3']) {
29
+ return 'nuxtjs';
30
+ }
23
31
  if (deps['@angular/core']) {
24
32
  return 'angular';
25
33
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utils/detect.ts"],"sourcesContent":["import { existsSync, readFileSync } from 'fs';\nimport { resolve } from 'path';\n\nexport type Framework = 'angular' | 'react' | 'vue' | 'react-native' | 'flutter' | 'unknown';\nexport type PackageManager = 'npm' | 'pnpm' | 'yarn' | 'bun' | 'pub';\n\n/**\n * Detect the framework being used in the project\n */\nexport function detectFramework(cwd: string): Framework {\n // Check for Flutter first (uses pubspec.yaml instead of package.json)\n const pubspecPath = resolve(cwd, 'pubspec.yaml');\n if (existsSync(pubspecPath)) {\n return 'flutter';\n }\n\n const packageJsonPath = resolve(cwd, 'package.json');\n\n if (!existsSync(packageJsonPath)) {\n return 'unknown';\n }\n\n try {\n const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));\n const deps = {\n ...packageJson.dependencies,\n ...packageJson.devDependencies,\n };\n\n // Check for React Native (must be before React check)\n if (deps['react-native']) {\n return 'react-native';\n }\n\n if (deps['@angular/core']) {\n return 'angular';\n }\n if (deps['react']) {\n return 'react';\n }\n if (deps['vue']) {\n return 'vue';\n }\n\n return 'unknown';\n } catch {\n return 'unknown';\n }\n}\n\n/**\n * Detect the package manager being used\n */\nexport function detectPackageManager(cwd: string): PackageManager {\n // Check for Flutter package manager\n if (existsSync(resolve(cwd, 'pubspec.yaml'))) {\n return 'pub';\n }\n\n if (existsSync(resolve(cwd, 'bun.lockb')) || existsSync(resolve(cwd, 'bun.lock'))) {\n return 'bun';\n }\n if (existsSync(resolve(cwd, 'pnpm-lock.yaml'))) {\n return 'pnpm';\n }\n if (existsSync(resolve(cwd, 'yarn.lock'))) {\n return 'yarn';\n }\n return 'npm';\n}\n\n/**\n * Check if project is already initialized with Galaxy UI\n */\nexport function isGalaxyInitialized(cwd: string): boolean {\n const packageJsonPath = resolve(cwd, 'package.json');\n\n if (!existsSync(packageJsonPath)) {\n return false;\n }\n\n try {\n const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));\n const deps = {\n ...packageJson.dependencies,\n ...packageJson.devDependencies,\n };\n\n return !!(deps['lucide-angular'] && deps['clsx'] && deps['tailwind-merge']);\n } catch {\n return false;\n }\n}\n\n/**\n * Check if Tailwind CSS is installed\n */\nexport function isTailwindInstalled(cwd: string): boolean {\n const packageJsonPath = resolve(cwd, 'package.json');\n\n if (!existsSync(packageJsonPath)) {\n return false;\n }\n\n try {\n const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));\n const deps = {\n ...packageJson.dependencies,\n ...packageJson.devDependencies,\n };\n\n return !!deps['tailwindcss'];\n } catch {\n return false;\n }\n}\n"],"names":["existsSync","readFileSync","resolve","detectFramework","cwd","pubspecPath","packageJsonPath","packageJson","JSON","parse","deps","dependencies","devDependencies","detectPackageManager","isGalaxyInitialized","isTailwindInstalled"],"mappings":";AAAA,SAASA,UAAU,EAAEC,YAAY,QAAQ,KAAK;AAC9C,SAASC,OAAO,QAAQ,OAAO;AAK/B;;CAEC,GACD,OAAO,SAASC,gBAAgBC,GAAW;IACzC,sEAAsE;IACtE,MAAMC,cAAcH,QAAQE,KAAK;IACjC,IAAIJ,WAAWK,cAAc;QAC3B,OAAO;IACT;IAEA,MAAMC,kBAAkBJ,QAAQE,KAAK;IAErC,IAAI,CAACJ,WAAWM,kBAAkB;QAChC,OAAO;IACT;IAEA,IAAI;QACF,MAAMC,cAAcC,KAAKC,KAAK,CAACR,aAAaK,iBAAiB;QAC7D,MAAMI,OAAO,aACRH,YAAYI,YAAY,EACxBJ,YAAYK,eAAe;QAGhC,sDAAsD;QACtD,IAAIF,IAAI,CAAC,eAAe,EAAE;YACxB,OAAO;QACT;QAEA,IAAIA,IAAI,CAAC,gBAAgB,EAAE;YACzB,OAAO;QACT;QACA,IAAIA,IAAI,CAAC,QAAQ,EAAE;YACjB,OAAO;QACT;QACA,IAAIA,IAAI,CAAC,MAAM,EAAE;YACf,OAAO;QACT;QAEA,OAAO;IACT,EAAE,UAAM;QACN,OAAO;IACT;AACF;AAEA;;CAEC,GACD,OAAO,SAASG,qBAAqBT,GAAW;IAC9C,oCAAoC;IACpC,IAAIJ,WAAWE,QAAQE,KAAK,kBAAkB;QAC5C,OAAO;IACT;IAEA,IAAIJ,WAAWE,QAAQE,KAAK,iBAAiBJ,WAAWE,QAAQE,KAAK,cAAc;QACjF,OAAO;IACT;IACA,IAAIJ,WAAWE,QAAQE,KAAK,oBAAoB;QAC9C,OAAO;IACT;IACA,IAAIJ,WAAWE,QAAQE,KAAK,eAAe;QACzC,OAAO;IACT;IACA,OAAO;AACT;AAEA;;CAEC,GACD,OAAO,SAASU,oBAAoBV,GAAW;IAC7C,MAAME,kBAAkBJ,QAAQE,KAAK;IAErC,IAAI,CAACJ,WAAWM,kBAAkB;QAChC,OAAO;IACT;IAEA,IAAI;QACF,MAAMC,cAAcC,KAAKC,KAAK,CAACR,aAAaK,iBAAiB;QAC7D,MAAMI,OAAO,aACRH,YAAYI,YAAY,EACxBJ,YAAYK,eAAe;QAGhC,OAAO,CAAC,CAAEF,CAAAA,IAAI,CAAC,iBAAiB,IAAIA,IAAI,CAAC,OAAO,IAAIA,IAAI,CAAC,iBAAiB,AAAD;IAC3E,EAAE,UAAM;QACN,OAAO;IACT;AACF;AAEA;;CAEC,GACD,OAAO,SAASK,oBAAoBX,GAAW;IAC7C,MAAME,kBAAkBJ,QAAQE,KAAK;IAErC,IAAI,CAACJ,WAAWM,kBAAkB;QAChC,OAAO;IACT;IAEA,IAAI;QACF,MAAMC,cAAcC,KAAKC,KAAK,CAACR,aAAaK,iBAAiB;QAC7D,MAAMI,OAAO,aACRH,YAAYI,YAAY,EACxBJ,YAAYK,eAAe;QAGhC,OAAO,CAAC,CAACF,IAAI,CAAC,cAAc;IAC9B,EAAE,UAAM;QACN,OAAO;IACT;AACF"}
1
+ {"version":3,"sources":["../../src/utils/detect.ts"],"sourcesContent":["import { existsSync, readFileSync } from 'fs';\nimport { resolve } from 'path';\n\nexport type Framework = 'angular' | 'react' | 'vue' | 'react-native' | 'flutter' | 'nextjs' | 'nuxtjs' | 'unknown';\nexport type PackageManager = 'npm' | 'pnpm' | 'yarn' | 'bun' | 'pub';\n\n/**\n * Detect the framework being used in the project\n */\nexport function detectFramework(cwd: string): Framework {\n // Check for Flutter first (uses pubspec.yaml instead of package.json)\n const pubspecPath = resolve(cwd, 'pubspec.yaml');\n if (existsSync(pubspecPath)) {\n return 'flutter';\n }\n\n const packageJsonPath = resolve(cwd, 'package.json');\n\n if (!existsSync(packageJsonPath)) {\n return 'unknown';\n }\n\n try {\n const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));\n const deps = {\n ...packageJson.dependencies,\n ...packageJson.devDependencies,\n };\n\n // Check for React Native (must be before React check)\n if (deps['react-native']) {\n return 'react-native';\n }\n\n // Check for Next.js (must be before React check)\n if (deps['next']) {\n return 'nextjs';\n }\n\n // Check for Nuxt.js (must be before Vue check)\n if (deps['nuxt'] || deps['nuxt3']) {\n return 'nuxtjs';\n }\n\n if (deps['@angular/core']) {\n return 'angular';\n }\n if (deps['react']) {\n return 'react';\n }\n if (deps['vue']) {\n return 'vue';\n }\n\n return 'unknown';\n } catch {\n return 'unknown';\n }\n}\n\n/**\n * Detect the package manager being used\n */\nexport function detectPackageManager(cwd: string): PackageManager {\n // Check for Flutter package manager\n if (existsSync(resolve(cwd, 'pubspec.yaml'))) {\n return 'pub';\n }\n\n if (existsSync(resolve(cwd, 'bun.lockb')) || existsSync(resolve(cwd, 'bun.lock'))) {\n return 'bun';\n }\n if (existsSync(resolve(cwd, 'pnpm-lock.yaml'))) {\n return 'pnpm';\n }\n if (existsSync(resolve(cwd, 'yarn.lock'))) {\n return 'yarn';\n }\n return 'npm';\n}\n\n/**\n * Check if project is already initialized with Galaxy UI\n */\nexport function isGalaxyInitialized(cwd: string): boolean {\n const packageJsonPath = resolve(cwd, 'package.json');\n\n if (!existsSync(packageJsonPath)) {\n return false;\n }\n\n try {\n const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));\n const deps = {\n ...packageJson.dependencies,\n ...packageJson.devDependencies,\n };\n\n return !!(deps['lucide-angular'] && deps['clsx'] && deps['tailwind-merge']);\n } catch {\n return false;\n }\n}\n\n/**\n * Check if Tailwind CSS is installed\n */\nexport function isTailwindInstalled(cwd: string): boolean {\n const packageJsonPath = resolve(cwd, 'package.json');\n\n if (!existsSync(packageJsonPath)) {\n return false;\n }\n\n try {\n const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));\n const deps = {\n ...packageJson.dependencies,\n ...packageJson.devDependencies,\n };\n\n return !!deps['tailwindcss'];\n } catch {\n return false;\n }\n}\n"],"names":["existsSync","readFileSync","resolve","detectFramework","cwd","pubspecPath","packageJsonPath","packageJson","JSON","parse","deps","dependencies","devDependencies","detectPackageManager","isGalaxyInitialized","isTailwindInstalled"],"mappings":";AAAA,SAASA,UAAU,EAAEC,YAAY,QAAQ,KAAK;AAC9C,SAASC,OAAO,QAAQ,OAAO;AAK/B;;CAEC,GACD,OAAO,SAASC,gBAAgBC,GAAW;IACzC,sEAAsE;IACtE,MAAMC,cAAcH,QAAQE,KAAK;IACjC,IAAIJ,WAAWK,cAAc;QAC3B,OAAO;IACT;IAEA,MAAMC,kBAAkBJ,QAAQE,KAAK;IAErC,IAAI,CAACJ,WAAWM,kBAAkB;QAChC,OAAO;IACT;IAEA,IAAI;QACF,MAAMC,cAAcC,KAAKC,KAAK,CAACR,aAAaK,iBAAiB;QAC7D,MAAMI,OAAO,aACRH,YAAYI,YAAY,EACxBJ,YAAYK,eAAe;QAGhC,sDAAsD;QACtD,IAAIF,IAAI,CAAC,eAAe,EAAE;YACxB,OAAO;QACT;QAEA,iDAAiD;QACjD,IAAIA,IAAI,CAAC,OAAO,EAAE;YAChB,OAAO;QACT;QAEA,+CAA+C;QAC/C,IAAIA,IAAI,CAAC,OAAO,IAAIA,IAAI,CAAC,QAAQ,EAAE;YACjC,OAAO;QACT;QAEA,IAAIA,IAAI,CAAC,gBAAgB,EAAE;YACzB,OAAO;QACT;QACA,IAAIA,IAAI,CAAC,QAAQ,EAAE;YACjB,OAAO;QACT;QACA,IAAIA,IAAI,CAAC,MAAM,EAAE;YACf,OAAO;QACT;QAEA,OAAO;IACT,EAAE,UAAM;QACN,OAAO;IACT;AACF;AAEA;;CAEC,GACD,OAAO,SAASG,qBAAqBT,GAAW;IAC9C,oCAAoC;IACpC,IAAIJ,WAAWE,QAAQE,KAAK,kBAAkB;QAC5C,OAAO;IACT;IAEA,IAAIJ,WAAWE,QAAQE,KAAK,iBAAiBJ,WAAWE,QAAQE,KAAK,cAAc;QACjF,OAAO;IACT;IACA,IAAIJ,WAAWE,QAAQE,KAAK,oBAAoB;QAC9C,OAAO;IACT;IACA,IAAIJ,WAAWE,QAAQE,KAAK,eAAe;QACzC,OAAO;IACT;IACA,OAAO;AACT;AAEA;;CAEC,GACD,OAAO,SAASU,oBAAoBV,GAAW;IAC7C,MAAME,kBAAkBJ,QAAQE,KAAK;IAErC,IAAI,CAACJ,WAAWM,kBAAkB;QAChC,OAAO;IACT;IAEA,IAAI;QACF,MAAMC,cAAcC,KAAKC,KAAK,CAACR,aAAaK,iBAAiB;QAC7D,MAAMI,OAAO,aACRH,YAAYI,YAAY,EACxBJ,YAAYK,eAAe;QAGhC,OAAO,CAAC,CAAEF,CAAAA,IAAI,CAAC,iBAAiB,IAAIA,IAAI,CAAC,OAAO,IAAIA,IAAI,CAAC,iBAAiB,AAAD;IAC3E,EAAE,UAAM;QACN,OAAO;IACT;AACF;AAEA;;CAEC,GACD,OAAO,SAASK,oBAAoBX,GAAW;IAC7C,MAAME,kBAAkBJ,QAAQE,KAAK;IAErC,IAAI,CAACJ,WAAWM,kBAAkB;QAChC,OAAO;IACT;IAEA,IAAI;QACF,MAAMC,cAAcC,KAAKC,KAAK,CAACR,aAAaK,iBAAiB;QAC7D,MAAMI,OAAO,aACRH,YAAYI,YAAY,EACxBJ,YAAYK,eAAe;QAGhC,OAAO,CAAC,CAACF,IAAI,CAAC,cAAc;IAC9B,EAAE,UAAM;QACN,OAAO;IACT;AACF"}
@@ -13,7 +13,14 @@ const registryCache = new Map();
13
13
  if (registryCache.has(framework)) {
14
14
  return registryCache.get(framework);
15
15
  }
16
- const registryPath = resolve(__dirname, `../registries/registry-${framework}.json`);
16
+ // Map Next.js to React registry and Nuxt.js to Vue registry
17
+ let registryFramework = framework;
18
+ if (framework === 'nextjs') {
19
+ registryFramework = 'react';
20
+ } else if (framework === 'nuxtjs') {
21
+ registryFramework = 'vue';
22
+ }
23
+ const registryPath = resolve(__dirname, `../registries/registry-${registryFramework}.json`);
17
24
  if (!existsSync(registryPath)) {
18
25
  throw new Error(`Registry not found for framework: ${framework}. Expected at ${registryPath}`);
19
26
  }
@@ -21,7 +28,7 @@ const registryCache = new Map();
21
28
  const registryContent = readFileSync(registryPath, 'utf-8');
22
29
  const registry = JSON.parse(registryContent);
23
30
  // Try to load and merge blocks registry
24
- const blocksRegistryPath = resolve(__dirname, `../registries/blocks-${framework}.json`);
31
+ const blocksRegistryPath = resolve(__dirname, `../registries/blocks-${registryFramework}.json`);
25
32
  if (existsSync(blocksRegistryPath)) {
26
33
  try {
27
34
  const blocksContent = readFileSync(blocksRegistryPath, 'utf-8');
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utils/framework-registry.ts"],"sourcesContent":["import { readFileSync, existsSync } from 'fs';\nimport { resolve, dirname } from 'path';\nimport { fileURLToPath } from 'url';\nimport type { Framework } from './config-schema.js';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\nexport interface FrameworkComponent {\n name: string;\n type: 'form' | 'layout' | 'navigation' | 'feedback' | 'data-display' | 'modal-overlay' | 'block' | 'other';\n description: string;\n files: string[];\n dependencies: string[];\n devDependencies: string[];\n peerDependencies?: string[];\n registryDependencies: string[];\n category: string;\n}\n\nexport interface FrameworkComponentGroup {\n name: string;\n components: string[];\n}\n\nexport interface FrameworkRegistry {\n name: string;\n components: Record<string, FrameworkComponent>;\n groups: Record<string, FrameworkComponentGroup>;\n}\n\n// Cache registries by framework\nconst registryCache: Map<Framework, FrameworkRegistry> = new Map();\n\n/**\n * Load framework-specific registry (includes both components and blocks)\n */\nexport function loadFrameworkRegistry(framework: Framework): FrameworkRegistry {\n // Check cache first\n if (registryCache.has(framework)) {\n return registryCache.get(framework)!;\n }\n\n const registryPath = resolve(__dirname, `../registries/registry-${framework}.json`);\n\n if (!existsSync(registryPath)) {\n throw new Error(\n `Registry not found for framework: ${framework}. Expected at ${registryPath}`\n );\n }\n\n try {\n const registryContent = readFileSync(registryPath, 'utf-8');\n const registry: FrameworkRegistry = JSON.parse(registryContent);\n\n // Try to load and merge blocks registry\n const blocksRegistryPath = resolve(__dirname, `../registries/blocks-${framework}.json`);\n if (existsSync(blocksRegistryPath)) {\n try {\n const blocksContent = readFileSync(blocksRegistryPath, 'utf-8');\n const blocksRegistry: FrameworkRegistry = JSON.parse(blocksContent);\n\n // Merge blocks into main registry\n registry.components = {\n ...registry.components,\n ...blocksRegistry.components,\n };\n\n registry.groups = {\n ...registry.groups,\n ...blocksRegistry.groups,\n };\n } catch (error) {\n // Blocks registry is optional, so we just log and continue\n console.warn(`Warning: Failed to load blocks registry for ${framework}`);\n }\n }\n\n // Cache the merged registry\n registryCache.set(framework, registry);\n\n return registry;\n } catch (error) {\n throw new Error(`Failed to load registry for ${framework}: ${error}`);\n }\n}\n\n/**\n * Get a component by name from framework registry\n */\nexport function getFrameworkComponent(\n framework: Framework,\n name: string\n): FrameworkComponent | undefined {\n const registry = loadFrameworkRegistry(framework);\n return registry.components[name];\n}\n\n/**\n * Get all components from framework registry\n */\nexport function getAllFrameworkComponents(\n framework: Framework\n): Record<string, FrameworkComponent> {\n const registry = loadFrameworkRegistry(framework);\n return registry.components;\n}\n\n/**\n * Get components by type from framework registry\n */\nexport function getFrameworkComponentsByType(\n framework: Framework,\n type: FrameworkComponent['type']\n): FrameworkComponent[] {\n const registry = loadFrameworkRegistry(framework);\n return Object.values(registry.components).filter((c) => c.type === type);\n}\n\n/**\n * Get components by group name from framework registry\n */\nexport function getFrameworkComponentsByGroup(\n framework: Framework,\n groupName: string\n): FrameworkComponent[] {\n const registry = loadFrameworkRegistry(framework);\n const group = registry.groups[groupName];\n\n if (!group) {\n return [];\n }\n\n return group.components\n .map((name) => registry.components[name])\n .filter(Boolean);\n}\n\n/**\n * Get all component groups from framework registry\n */\nexport function getAllFrameworkGroups(\n framework: Framework\n): Record<string, FrameworkComponentGroup> {\n const registry = loadFrameworkRegistry(framework);\n return registry.groups;\n}\n\n/**\n * Check if a component exists in framework registry\n */\nexport function frameworkComponentExists(\n framework: Framework,\n name: string\n): boolean {\n const registry = loadFrameworkRegistry(framework);\n return !!registry.components[name];\n}\n\n/**\n * Get component dependencies (including registry dependencies)\n */\nexport function getFrameworkComponentDependencies(\n framework: Framework,\n name: string\n): {\n dependencies: string[];\n devDependencies: string[];\n registryDependencies: string[];\n} {\n const component = getFrameworkComponent(framework, name);\n\n if (!component) {\n return {\n dependencies: [],\n devDependencies: [],\n registryDependencies: [],\n };\n }\n\n // Merge peerDependencies into dependencies for installation\n const allDependencies = [\n ...(component.dependencies || []),\n ...(component.peerDependencies || []),\n ];\n\n return {\n dependencies: allDependencies,\n devDependencies: component.devDependencies || [],\n registryDependencies: component.registryDependencies || [],\n };\n}\n\n/**\n * Resolve component name with aliases (case-insensitive match)\n */\nexport function resolveFrameworkComponentName(\n framework: Framework,\n input: string\n): string | null {\n const registry = loadFrameworkRegistry(framework);\n\n // Check exact match\n if (registry.components[input]) {\n return input;\n }\n\n // Check group match\n if (registry.groups[input]) {\n return input;\n }\n\n // Check case-insensitive match\n const lowerInput = input.toLowerCase();\n for (const name of Object.keys(registry.components)) {\n if (name.toLowerCase() === lowerInput) {\n return name;\n }\n }\n\n return null;\n}\n\n/**\n * Clear registry cache (useful for testing)\n */\nexport function clearRegistryCache(): void {\n registryCache.clear();\n}\n"],"names":["readFileSync","existsSync","resolve","dirname","fileURLToPath","__filename","url","__dirname","registryCache","Map","loadFrameworkRegistry","framework","has","get","registryPath","Error","registryContent","registry","JSON","parse","blocksRegistryPath","blocksContent","blocksRegistry","components","groups","error","console","warn","set","getFrameworkComponent","name","getAllFrameworkComponents","getFrameworkComponentsByType","type","Object","values","filter","c","getFrameworkComponentsByGroup","groupName","group","map","Boolean","getAllFrameworkGroups","frameworkComponentExists","getFrameworkComponentDependencies","component","dependencies","devDependencies","registryDependencies","allDependencies","peerDependencies","resolveFrameworkComponentName","input","lowerInput","toLowerCase","keys","clearRegistryCache","clear"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/utils/framework-registry.ts"],"sourcesContent":["import { readFileSync, existsSync } from 'fs';\nimport { resolve, dirname } from 'path';\nimport { fileURLToPath } from 'url';\nimport type { Framework } from './config-schema.js';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\nexport interface FrameworkComponent {\n name: string;\n type: 'form' | 'layout' | 'navigation' | 'feedback' | 'data-display' | 'modal-overlay' | 'block' | 'other';\n description: string;\n files: string[];\n dependencies: string[];\n devDependencies: string[];\n peerDependencies?: string[];\n registryDependencies: string[];\n category: string;\n}\n\nexport interface FrameworkComponentGroup {\n name: string;\n components: string[];\n}\n\nexport interface FrameworkRegistry {\n name: string;\n components: Record<string, FrameworkComponent>;\n groups: Record<string, FrameworkComponentGroup>;\n}\n\n// Cache registries by framework\nconst registryCache: Map<Framework, FrameworkRegistry> = new Map();\n\n/**\n * Load framework-specific registry (includes both components and blocks)\n */\nexport function loadFrameworkRegistry(framework: Framework): FrameworkRegistry {\n // Check cache first\n if (registryCache.has(framework)) {\n return registryCache.get(framework)!;\n }\n\n // Map Next.js to React registry and Nuxt.js to Vue registry\n let registryFramework = framework;\n if (framework === 'nextjs') {\n registryFramework = 'react';\n } else if (framework === 'nuxtjs') {\n registryFramework = 'vue';\n }\n\n const registryPath = resolve(__dirname, `../registries/registry-${registryFramework}.json`);\n\n if (!existsSync(registryPath)) {\n throw new Error(\n `Registry not found for framework: ${framework}. Expected at ${registryPath}`\n );\n }\n\n try {\n const registryContent = readFileSync(registryPath, 'utf-8');\n const registry: FrameworkRegistry = JSON.parse(registryContent);\n\n // Try to load and merge blocks registry\n const blocksRegistryPath = resolve(__dirname, `../registries/blocks-${registryFramework}.json`);\n if (existsSync(blocksRegistryPath)) {\n try {\n const blocksContent = readFileSync(blocksRegistryPath, 'utf-8');\n const blocksRegistry: FrameworkRegistry = JSON.parse(blocksContent);\n\n // Merge blocks into main registry\n registry.components = {\n ...registry.components,\n ...blocksRegistry.components,\n };\n\n registry.groups = {\n ...registry.groups,\n ...blocksRegistry.groups,\n };\n } catch (error) {\n // Blocks registry is optional, so we just log and continue\n console.warn(`Warning: Failed to load blocks registry for ${framework}`);\n }\n }\n\n // Cache the merged registry\n registryCache.set(framework, registry);\n\n return registry;\n } catch (error) {\n throw new Error(`Failed to load registry for ${framework}: ${error}`);\n }\n}\n\n/**\n * Get a component by name from framework registry\n */\nexport function getFrameworkComponent(\n framework: Framework,\n name: string\n): FrameworkComponent | undefined {\n const registry = loadFrameworkRegistry(framework);\n return registry.components[name];\n}\n\n/**\n * Get all components from framework registry\n */\nexport function getAllFrameworkComponents(\n framework: Framework\n): Record<string, FrameworkComponent> {\n const registry = loadFrameworkRegistry(framework);\n return registry.components;\n}\n\n/**\n * Get components by type from framework registry\n */\nexport function getFrameworkComponentsByType(\n framework: Framework,\n type: FrameworkComponent['type']\n): FrameworkComponent[] {\n const registry = loadFrameworkRegistry(framework);\n return Object.values(registry.components).filter((c) => c.type === type);\n}\n\n/**\n * Get components by group name from framework registry\n */\nexport function getFrameworkComponentsByGroup(\n framework: Framework,\n groupName: string\n): FrameworkComponent[] {\n const registry = loadFrameworkRegistry(framework);\n const group = registry.groups[groupName];\n\n if (!group) {\n return [];\n }\n\n return group.components\n .map((name) => registry.components[name])\n .filter(Boolean);\n}\n\n/**\n * Get all component groups from framework registry\n */\nexport function getAllFrameworkGroups(\n framework: Framework\n): Record<string, FrameworkComponentGroup> {\n const registry = loadFrameworkRegistry(framework);\n return registry.groups;\n}\n\n/**\n * Check if a component exists in framework registry\n */\nexport function frameworkComponentExists(\n framework: Framework,\n name: string\n): boolean {\n const registry = loadFrameworkRegistry(framework);\n return !!registry.components[name];\n}\n\n/**\n * Get component dependencies (including registry dependencies)\n */\nexport function getFrameworkComponentDependencies(\n framework: Framework,\n name: string\n): {\n dependencies: string[];\n devDependencies: string[];\n registryDependencies: string[];\n} {\n const component = getFrameworkComponent(framework, name);\n\n if (!component) {\n return {\n dependencies: [],\n devDependencies: [],\n registryDependencies: [],\n };\n }\n\n // Merge peerDependencies into dependencies for installation\n const allDependencies = [\n ...(component.dependencies || []),\n ...(component.peerDependencies || []),\n ];\n\n return {\n dependencies: allDependencies,\n devDependencies: component.devDependencies || [],\n registryDependencies: component.registryDependencies || [],\n };\n}\n\n/**\n * Resolve component name with aliases (case-insensitive match)\n */\nexport function resolveFrameworkComponentName(\n framework: Framework,\n input: string\n): string | null {\n const registry = loadFrameworkRegistry(framework);\n\n // Check exact match\n if (registry.components[input]) {\n return input;\n }\n\n // Check group match\n if (registry.groups[input]) {\n return input;\n }\n\n // Check case-insensitive match\n const lowerInput = input.toLowerCase();\n for (const name of Object.keys(registry.components)) {\n if (name.toLowerCase() === lowerInput) {\n return name;\n }\n }\n\n return null;\n}\n\n/**\n * Clear registry cache (useful for testing)\n */\nexport function clearRegistryCache(): void {\n registryCache.clear();\n}\n"],"names":["readFileSync","existsSync","resolve","dirname","fileURLToPath","__filename","url","__dirname","registryCache","Map","loadFrameworkRegistry","framework","has","get","registryFramework","registryPath","Error","registryContent","registry","JSON","parse","blocksRegistryPath","blocksContent","blocksRegistry","components","groups","error","console","warn","set","getFrameworkComponent","name","getAllFrameworkComponents","getFrameworkComponentsByType","type","Object","values","filter","c","getFrameworkComponentsByGroup","groupName","group","map","Boolean","getAllFrameworkGroups","frameworkComponentExists","getFrameworkComponentDependencies","component","dependencies","devDependencies","registryDependencies","allDependencies","peerDependencies","resolveFrameworkComponentName","input","lowerInput","toLowerCase","keys","clearRegistryCache","clear"],"mappings":"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"}
@@ -63,6 +63,32 @@ import { join } from 'path';
63
63
  try {
64
64
  const packageJson = require(join(cwd, 'package.json'));
65
65
  const deps = _extends({}, packageJson.dependencies, packageJson.devDependencies);
66
+ // Check for Next.js (must be before React check)
67
+ if (deps['next']) {
68
+ evidence.push('Found Next.js in dependencies');
69
+ if (existsSync(join(cwd, 'next.config.js')) || existsSync(join(cwd, 'next.config.ts'))) {
70
+ evidence.push('Found next.config (Next.js config)');
71
+ }
72
+ return {
73
+ platform: 'nextjs',
74
+ confidence: 'high',
75
+ evidence,
76
+ framework: 'nextjs'
77
+ };
78
+ }
79
+ // Check for Nuxt.js (must be before Vue check)
80
+ if (deps['nuxt'] || deps['nuxt3']) {
81
+ evidence.push('Found Nuxt.js in dependencies');
82
+ if (existsSync(join(cwd, 'nuxt.config.ts')) || existsSync(join(cwd, 'nuxt.config.js'))) {
83
+ evidence.push('Found nuxt.config (Nuxt.js config)');
84
+ }
85
+ return {
86
+ platform: 'nuxtjs',
87
+ confidence: 'high',
88
+ evidence,
89
+ framework: 'nuxtjs'
90
+ };
91
+ }
66
92
  // Check for Vue
67
93
  if (deps['vue'] || deps['@vue/cli']) {
68
94
  evidence.push('Found Vue in dependencies');
@@ -124,6 +150,8 @@ import { join } from 'path';
124
150
  'vue': 'Vue.js',
125
151
  'react': 'React',
126
152
  'angular': 'Angular',
153
+ 'nextjs': 'Next.js',
154
+ 'nuxtjs': 'Nuxt.js',
127
155
  'unknown': 'Unknown'
128
156
  };
129
157
  return names[platform];
@@ -136,7 +164,7 @@ import { join } from 'path';
136
164
  /**
137
165
  * Check if platform is web
138
166
  */ export function isWebPlatform(platform) {
139
- return platform === 'vue' || platform === 'react' || platform === 'angular';
167
+ return platform === 'vue' || platform === 'react' || platform === 'angular' || platform === 'nextjs' || platform === 'nuxtjs';
140
168
  }
141
169
  /**
142
170
  * Get registry file name for platform
@@ -147,7 +175,9 @@ import { join } from 'path';
147
175
  case 'flutter':
148
176
  return 'registry-flutter.json';
149
177
  case 'vue':
178
+ case 'nuxtjs':
150
179
  case 'react':
180
+ case 'nextjs':
151
181
  case 'angular':
152
182
  return 'registry.json'; // Web platforms use same registry
153
183
  default:
@@ -163,8 +193,10 @@ import { join } from 'path';
163
193
  case 'flutter':
164
194
  return 'packages/flutter/lib/components';
165
195
  case 'vue':
196
+ case 'nuxtjs':
166
197
  return 'packages/vue/src/components';
167
198
  case 'react':
199
+ case 'nextjs':
168
200
  return 'packages/react/src/components';
169
201
  case 'angular':
170
202
  return 'packages/angular/src/components';