UNPKG

embedia

Version:

Zero-configuration AI chatbot integration CLI - direct file copy with embedded API keys

137 lines (117 loc) 4.21 kB
const fs = require('fs-extra'); const path = require('path'); class LayoutDetector { async findLayoutFiles(projectPath, routerType) { const layouts = []; if (routerType === 'app') { // Check all possible app router layout locations const possiblePaths = [ 'app/layout.tsx', 'app/layout.ts', 'app/layout.jsx', 'app/layout.js', 'src/app/layout.tsx', 'src/app/layout.ts', 'src/app/layout.jsx', 'src/app/layout.js' ]; for (const layoutPath of possiblePaths) { const fullPath = path.join(projectPath, layoutPath); if (await fs.pathExists(fullPath)) { const content = await fs.readFile(fullPath, 'utf-8'); layouts.push({ path: layoutPath, fullPath: fullPath, content: content, isTypeScript: layoutPath.endsWith('.ts') || layoutPath.endsWith('.tsx'), hasClientDirective: content.includes("'use client'") || content.includes('"use client"'), hasScriptImport: content.includes('next/script') }); } } } else if (routerType === 'pages') { // Check pages router app files const appPaths = [ 'pages/_app.tsx', 'pages/_app.ts', 'pages/_app.jsx', 'pages/_app.js', 'src/pages/_app.tsx', 'src/pages/_app.ts', 'src/pages/_app.jsx', 'src/pages/_app.js' ]; for (const appPath of appPaths) { const fullPath = path.join(projectPath, appPath); if (await fs.pathExists(fullPath)) { const content = await fs.readFile(fullPath, 'utf-8'); layouts.push({ path: appPath, fullPath: fullPath, content: content, isTypeScript: appPath.endsWith('.ts') || appPath.endsWith('.tsx') }); } } } return layouts; } async findBestLayoutForIntegration(layouts) { if (layouts.length === 0) return null; // Prefer TypeScript files const tsLayouts = layouts.filter(l => l.isTypeScript); if (tsLayouts.length > 0) return tsLayouts[0]; // Otherwise return first layout return layouts[0]; } async createLayoutIfMissing(projectPath, routerType, isTypeScript) { if (routerType === 'app') { const layoutDir = await fs.pathExists(path.join(projectPath, 'src')) ? 'src/app' : 'app'; const layoutPath = path.join(projectPath, layoutDir, `layout.${isTypeScript ? 'tsx' : 'jsx'}`); if (!await fs.pathExists(layoutPath)) { await fs.ensureDir(path.join(projectPath, layoutDir)); const layoutContent = this.generateDefaultLayout(isTypeScript, true); await fs.writeFile(layoutPath, layoutContent); return layoutPath; } } else if (routerType === 'pages') { const appDir = await fs.pathExists(path.join(projectPath, 'src')) ? 'src/pages' : 'pages'; const appPath = path.join(projectPath, appDir, `_app.${isTypeScript ? 'tsx' : 'jsx'}`); if (!await fs.pathExists(appPath)) { await fs.ensureDir(path.join(projectPath, appDir)); const appContent = this.generateDefaultApp(isTypeScript); await fs.writeFile(appPath, appContent); return appPath; } } return null; } generateDefaultLayout(isTypeScript, isAppRouter) { if (isAppRouter) { const typeAnnotations = isTypeScript ? ': { children: React.ReactNode }' : ''; return `import './globals.css' export const metadata = { title: 'My App', description: 'Created with Embedia', } export default function RootLayout({ children }${typeAnnotations}) { return ( <html lang="en"> <body>{children}</body> </html> ) }`; } return ''; } generateDefaultApp(isTypeScript) { const typeImport = isTypeScript ? "import type { AppProps } from 'next/app'" : ''; const typeAnnotation = isTypeScript ? ': AppProps' : ''; return `${typeImport} function MyApp({ Component, pageProps }${typeAnnotation}) { return <Component {...pageProps} /> } export default MyApp`; } } module.exports = LayoutDetector;