embedia
Version:
Zero-configuration AI chatbot integration CLI - direct file copy with embedded API keys
163 lines (124 loc) • 4.55 kB
JavaScript
const fs = require('fs-extra');
const path = require('path');
const SafeASTModifier = require('../ast/safeModifier');
class BaseAdapter {
constructor(projectPath, framework, projectAnalysis) {
this.projectPath = projectPath;
this.framework = framework;
this.projectAnalysis = projectAnalysis;
this.safeModifier = new SafeASTModifier();
}
// Abstract method - must be implemented by subclasses
async integrate(embediaFiles) {
throw new Error('integrate() method must be implemented by subclass');
}
// Common helper methods
async createFile(relativePath, content) {
const fullPath = path.join(this.projectPath, relativePath);
await fs.ensureDir(path.dirname(fullPath));
await fs.writeFile(fullPath, content);
return relativePath;
}
async findFile(possiblePaths) {
for (const filePath of possiblePaths) {
const fullPath = path.join(this.projectPath, filePath);
if (await fs.pathExists(fullPath)) {
return filePath;
}
}
return null;
}
async modifyFile(filePath, modifier) {
const fullPath = path.join(this.projectPath, filePath);
return await this.safeModifier.modifyWithRollback(fullPath, modifier);
}
async fileExists(relativePath) {
return await fs.pathExists(path.join(this.projectPath, relativePath));
}
async readFile(relativePath) {
return await fs.readFile(path.join(this.projectPath, relativePath), 'utf-8');
}
async createComponentFiles(embediaFiles) {
const componentDir = path.join(this.projectPath, 'components/generated/embedia-chat');
await fs.ensureDir(componentDir);
// Create all component files
const files = [
{ path: 'index.js', content: embediaFiles.component },
{ path: 'config.json', content: JSON.stringify(embediaFiles.config, null, 2) },
{ path: 'index.d.ts', content: embediaFiles.types },
{ path: 'README.md', content: embediaFiles.readme || this.generateReadme(embediaFiles.config) }
];
// Create API directory
const apiDir = path.join(componentDir, 'api/chat');
await fs.ensureDir(apiDir);
// Add API route
files.push({
path: 'api/chat/route.js',
content: embediaFiles.apiRoute
});
// Write all files
for (const file of files) {
await fs.writeFile(
path.join(componentDir, file.path),
file.content
);
}
return 'components/generated/embedia-chat';
}
generateReadme(config) {
return `# Embedia Chat Component
This is a pre-compiled, isolated chat component generated by Embedia CLI.
## Configuration
Edit \`config.json\` to customize the chat widget:
- **chatbotName**: Display name of your chatbot
- **themeColors**: Color scheme customization
- **position**: Widget position on screen
- **systemPrompt**: AI behavior configuration
## Integration
This component works with simple script inclusion.
## API Endpoint
The chat API handler is located at \`api/chat/route.js\`.
Configure your environment variables for AI provider access.
## Support
For help, visit: https://docs.embedia.ai
`;
}
getIntegrationInstructions(frameworkName) {
return `
# Embedia Chat Integration - ${frameworkName}
The Embedia Chat component has been successfully installed!
## Next Steps
1. **Set up your API key**: Add to \`.env.local\`:
\`\`\`
GEMINI_API_KEY=your_api_key_here
\`\`\`
2. **Start your development server** and look for the chat widget
3. **Customize**: Edit \`components/generated/embedia-chat/config.json\`
## Troubleshooting
If the chat doesn't appear:
- Check the browser console for errors
- Verify the integration in your layout file
- Ensure API routes are properly configured
Need help? Run \`npx embedia doctor\` for diagnostics.
`;
}
// Helper for manual integration instructions
getManualIntegrationInstructions() {
return `To manually integrate Embedia Chat, add this to your layout or root component:
1. Import and render the component:
import EmbediaChat from '/components/generated/embedia-chat';
2. Add it to your JSX:
<EmbediaChat />`;
}
// Check if we're in a TypeScript project
async isTypeScriptProject() {
return await this.fileExists('tsconfig.json');
}
// Get the appropriate file extension
async getFileExtension(isComponent = true) {
const isTS = await this.isTypeScriptProject();
if (!isTS) return isComponent ? '.jsx' : '.js';
return isComponent ? '.tsx' : '.ts';
}
}
module.exports = BaseAdapter;