import { GeminiHelper } from '../utils/gemini-helper.js';
// API integrations for external services and platforms
export interface APIIntegration {
name: string;
baseUrl: string;
authMethod: 'api-key' | 'oauth' | 'bearer' | 'basic';
rateLimit: number;
generateTailwindComponents(prompt: string): Promise<APIResponse>;
analyzeDesign(html: string): Promise<DesignAnalysis>;
optimizeCSS(css: string): Promise<OptimizationResult>;
}
export interface APIResponse {
success: boolean;
data: any;
error?: string;
usage?: {
tokens: number;
cost: number;
};
}
export interface DesignAnalysis {
score: number;
suggestions: string[];
accessibility: AccessibilityScore;
performance: PerformanceScore;
responsive: ResponsiveScore;
}
export interface AccessibilityScore {
score: number;
issues: string[];
compliance: 'WCAG-A' | 'WCAG-AA' | 'WCAG-AAA';
}
export interface PerformanceScore {
score: number;
bundleSize: number;
loadTime: number;
optimizations: string[];
}
export interface ResponsiveScore {
score: number;
breakpoints: string[];
issues: string[];
}
export interface OptimizationResult {
original: string;
optimized: string;
suggestions: string[];
removed: string[];
savings: {
size: number;
percentage: number;
};
changes: string[];
}
// Gemini AI Integration
export class GeminiAIIntegration implements APIIntegration {
name = 'Gemini AI';
baseUrl = 'https://generativelanguage.googleapis.com/v1beta';
authMethod: 'api-key' = 'api-key';
rateLimit = 60; // requests per minute
private gemini: GeminiHelper;
constructor(apiKey: string) {
this.gemini = new GeminiHelper({ apiKey });
}
async generateTailwindComponents(prompt: string): Promise<APIResponse> {
try {
const component = await this.gemini.generateContent(prompt);
return {
success: true,
data: {
component,
framework: 'html',
styling: 'tailwind'
},
usage: {
tokens: prompt.length + component.length,
cost: 0.001
}
};
} catch (error) {
return {
success: false,
data: null,
error: error instanceof Error ? error.message : 'Unknown error'
};
}
}
async analyzeDesign(html: string): Promise<DesignAnalysis> {
try {
const analysis = await this.gemini.analyzeDesign(html, {
checkAccessibility: true,
checkPerformance: true,
checkResponsive: true
});
return {
score: analysis.overallScore || 75,
suggestions: analysis.suggestions || [],
accessibility: {
score: analysis.accessibilityScore || 80,
issues: analysis.accessibilityIssues || [],
compliance: 'WCAG-AA'
},
performance: {
score: analysis.performanceScore || 70,
bundleSize: 45000, // bytes
loadTime: 1200, // ms
optimizations: analysis.performanceOptimizations || []
},
responsive: {
score: analysis.responsiveScore || 85,
breakpoints: ['mobile', 'tablet', 'desktop'],
issues: analysis.responsiveIssues || []
}
};
} catch (error) {
// Fallback analysis
return {
score: 60,
suggestions: ['Unable to perform AI analysis'],
accessibility: {
score: 60,
issues: ['Analysis unavailable'],
compliance: 'WCAG-A'
},
performance: {
score: 60,
bundleSize: 0,
loadTime: 0,
optimizations: []
},
responsive: {
score: 60,
breakpoints: [],
issues: []
}
};
}
}
async optimizeCSS(css: string): Promise<OptimizationResult> {
try {
const optimized = await this.gemini.optimizeClasses(css);
const originalSize = css.length;
const optimizedSize = optimized.optimized.length;
const savings = originalSize - optimizedSize;
return {
original: css,
optimized: optimized.optimized,
suggestions: optimized.suggestions,
removed: optimized.removed,
savings: {
size: savings,
percentage: Math.round((savings / originalSize) * 100)
},
changes: [
'Removed duplicate classes',
'Optimized spacing utilities',
'Merged shorthand properties'
]
};
} catch (error) {
return {
original: css,
optimized: css,
suggestions: [],
removed: [],
savings: { size: 0, percentage: 0 },
changes: ['Optimization failed']
};
}
}
}
// OpenAI Integration
export class OpenAIIntegration implements APIIntegration {
name = 'OpenAI';
baseUrl = 'https://api.openai.com/v1';
authMethod: 'bearer' = 'bearer';
rateLimit = 200; // requests per minute
constructor(private apiKey: string) {}
async generateTailwindComponents(prompt: string): Promise<APIResponse> {
try {
const response = await fetch(`${this.baseUrl}/chat/completions`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${this.apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
model: 'gpt-4',
messages: [
{
role: 'system',
content: 'You are a Tailwind CSS expert. Generate modern, responsive components with proper accessibility.'
},
{
role: 'user',
content: prompt
}
],
max_tokens: 2000,
temperature: 0.7
})
});
const data = await response.json() as any;
if (!response.ok) {
throw new Error(data.error?.message || 'OpenAI API error');
}
return {
success: true,
data: {
component: data.choices[0].message.content,
framework: 'html',
styling: 'tailwind'
},
usage: {
tokens: data.usage.total_tokens,
cost: data.usage.total_tokens * 0.00002 // GPT-4 pricing
}
};
} catch (error) {
return {
success: false,
data: null,
error: error instanceof Error ? error.message : 'Unknown error'
};
}
}
async analyzeDesign(html: string): Promise<DesignAnalysis> {
try {
const response = await fetch(`${this.baseUrl}/chat/completions`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${this.apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
model: 'gpt-4',
messages: [
{
role: 'system',
content: 'Analyze this HTML/Tailwind design for accessibility, performance, and responsive design. Provide scores and specific suggestions.'
},
{
role: 'user',
content: `Analyze this design:\n\n${html}`
}
],
max_tokens: 1500
})
});
const data = await response.json() as any;
const analysis = data.choices[0].message.content;
// Parse the analysis (simplified - would need more sophisticated parsing)
return {
score: 75,
suggestions: [analysis],
accessibility: {
score: 80,
issues: [],
compliance: 'WCAG-AA'
},
performance: {
score: 70,
bundleSize: 0,
loadTime: 0,
optimizations: []
},
responsive: {
score: 85,
breakpoints: [],
issues: []
}
};
} catch (error) {
throw error;
}
}
async optimizeCSS(css: string): Promise<OptimizationResult> {
try {
const response = await fetch(`${this.baseUrl}/chat/completions`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${this.apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
model: 'gpt-4',
messages: [
{
role: 'system',
content: 'Optimize these Tailwind CSS classes by removing duplicates, conflicts, and suggesting improvements.'
},
{
role: 'user',
content: css
}
],
max_tokens: 1000
})
});
const data = await response.json() as any;
const optimized = data.choices[0].message.content;
return {
original: css,
optimized: optimized,
savings: {
size: css.length - optimized.length,
percentage: Math.round(((css.length - optimized.length) / css.length) * 100)
},
changes: ['AI-optimized classes'],
suggestions: ['Optimized for better performance'],
removed: []
};
} catch (error) {
throw error;
}
}
}
// Claude Integration (Anthropic)
export class ClaudeIntegration implements APIIntegration {
name = 'Claude';
baseUrl = 'https://api.anthropic.com/v1';
authMethod: 'api-key' = 'api-key';
rateLimit = 100;
constructor(private apiKey: string) {}
async generateTailwindComponents(prompt: string): Promise<APIResponse> {
try {
const response = await fetch(`${this.baseUrl}/messages`, {
method: 'POST',
headers: {
'x-api-key': this.apiKey,
'Content-Type': 'application/json',
'anthropic-version': '2023-06-01'
},
body: JSON.stringify({
model: 'claude-3-sonnet-20240229',
max_tokens: 2000,
messages: [
{
role: 'user',
content: `Generate a Tailwind CSS component for: ${prompt}`
}
]
})
});
const data = await response.json() as any;
return {
success: true,
data: {
component: data.content[0].text,
framework: 'html',
styling: 'tailwind'
},
usage: {
tokens: data.usage.input_tokens + data.usage.output_tokens,
cost: 0.003 // Claude pricing
}
};
} catch (error) {
return {
success: false,
data: null,
error: error instanceof Error ? error.message : 'Unknown error'
};
}
}
async analyzeDesign(html: string): Promise<DesignAnalysis> {
// Similar implementation to OpenAI
return {
score: 75,
suggestions: [],
accessibility: { score: 80, issues: [], compliance: 'WCAG-AA' },
performance: { score: 70, bundleSize: 0, loadTime: 0, optimizations: [] },
responsive: { score: 85, breakpoints: [], issues: [] }
};
}
async optimizeCSS(css: string): Promise<OptimizationResult> {
// Similar implementation to OpenAI
return {
original: css,
optimized: css,
savings: { size: 0, percentage: 0 },
changes: [],
suggestions: ['No optimization needed'],
removed: []
};
}
}
// Design Tools Integration
export class FigmaIntegration {
name = 'Figma';
baseUrl = 'https://api.figma.com/v1';
constructor(private accessToken: string) {}
async getDesignTokens(fileId: string): Promise<any> {
try {
const response = await fetch(`${this.baseUrl}/files/${fileId}`, {
headers: {
'X-Figma-Token': this.accessToken
}
});
const data = await response.json();
return this.extractDesignTokens(data);
} catch (error) {
throw error;
}
}
async convertToTailwind(fileId: string, nodeId: string): Promise<string> {
try {
const response = await fetch(`${this.baseUrl}/files/${fileId}/nodes?ids=${nodeId}`, {
headers: {
'X-Figma-Token': this.accessToken
}
});
const data = await response.json() as any;
return this.convertFigmaToTailwind(data.nodes[nodeId]);
} catch (error) {
throw error;
}
}
private extractDesignTokens(figmaData: any): any {
// Extract colors, typography, spacing from Figma data
return {
colors: {},
typography: {},
spacing: {}
};
}
private convertFigmaToTailwind(node: any): string {
// Convert Figma node to Tailwind classes
const classes: string[] = [];
// Width and height
if (node.absoluteBoundingBox) {
classes.push(`w-[${node.absoluteBoundingBox.width}px]`);
classes.push(`h-[${node.absoluteBoundingBox.height}px]`);
}
// Background color
if (node.fills && node.fills[0]) {
const fill = node.fills[0];
if (fill.type === 'SOLID') {
const { r, g, b } = fill.color;
const hex = this.rgbToHex(r * 255, g * 255, b * 255);
classes.push(`bg-[${hex}]`);
}
}
// Border radius
if (node.cornerRadius) {
classes.push(`rounded-[${node.cornerRadius}px]`);
}
return classes.join(' ');
}
private rgbToHex(r: number, g: number, b: number): string {
return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
}
}
// Integration Manager
export class IntegrationManager {
private integrations: Map<string, APIIntegration> = new Map();
private designTools: Map<string, any> = new Map();
constructor() {
// Initialize default integrations if API keys are available
const geminiKey = process.env.GEMINI_API_KEY;
const openaiKey = process.env.OPENAI_API_KEY;
const claudeKey = process.env.CLAUDE_API_KEY;
const figmaToken = process.env.FIGMA_ACCESS_TOKEN;
if (geminiKey) {
this.integrations.set('gemini', new GeminiAIIntegration(geminiKey));
}
if (openaiKey) {
this.integrations.set('openai', new OpenAIIntegration(openaiKey));
}
if (claudeKey) {
this.integrations.set('claude', new ClaudeIntegration(claudeKey));
}
if (figmaToken) {
this.designTools.set('figma', new FigmaIntegration(figmaToken));
}
}
getIntegration(name: string): APIIntegration | null {
return this.integrations.get(name.toLowerCase()) || null;
}
getDesignTool(name: string): any {
return this.designTools.get(name.toLowerCase()) || null;
}
addIntegration(name: string, integration: APIIntegration): void {
this.integrations.set(name.toLowerCase(), integration);
}
addDesignTool(name: string, tool: any): void {
this.designTools.set(name.toLowerCase(), tool);
}
getAvailableIntegrations(): string[] {
return Array.from(this.integrations.keys());
}
getAvailableDesignTools(): string[] {
return Array.from(this.designTools.keys());
}
async generateWithBestAvailable(prompt: string): Promise<APIResponse> {
// Try integrations in order of preference
const preferredOrder = ['gemini', 'openai', 'claude'];
for (const name of preferredOrder) {
const integration = this.integrations.get(name);
if (integration) {
try {
return await integration.generateTailwindComponents(prompt);
} catch (error) {
console.warn(`${name} integration failed, trying next...`);
continue;
}
}
}
throw new Error('No AI integrations available');
}
async analyzeWithBestAvailable(html: string): Promise<DesignAnalysis> {
const preferredOrder = ['gemini', 'openai', 'claude'];
for (const name of preferredOrder) {
const integration = this.integrations.get(name);
if (integration) {
try {
return await integration.analyzeDesign(html);
} catch (error) {
console.warn(`${name} integration failed, trying next...`);
continue;
}
}
}
throw new Error('No AI integrations available for analysis');
}
}