@nuggetwise/cli
Version:
Magic Nuggetwise CLI for Cursor IDE integration
192 lines (168 loc) • 5.51 kB
text/typescript
import axios, { AxiosInstance } from 'axios';
import { GatewayResponse, SSEEvent } from '../types/index.js';
export class GatewayClient {
private client: AxiosInstance;
private apiKey: string;
private baseUrl: string;
constructor(apiKey: string, baseUrl?: string) {
this.apiKey = apiKey;
// Construct the proper Gateway URL
let gatewayUrl = baseUrl;
if (!gatewayUrl) {
const supabaseUrl = process.env.SUPABASE_URL || process.env.NUGGETWISE_GATEWAY_URL;
if (supabaseUrl) {
// If it's already a full Gateway URL, use it as is
if (supabaseUrl.includes('/functions/v1/gateway')) {
gatewayUrl = supabaseUrl;
} else {
// Otherwise, construct the Gateway URL from Supabase URL
gatewayUrl = `${supabaseUrl}/functions/v1/gateway`;
}
} else {
gatewayUrl = 'https://your-project-ref.supabase.co/functions/v1/gateway';
}
}
this.baseUrl = gatewayUrl;
this.client = axios.create({
baseURL: this.baseUrl,
timeout: 30000,
headers: {
'Authorization': `Bearer ${process.env.SUPABASE_ANON_KEY}`,
'Content-Type': 'application/json',
'User-Agent': 'nuggetwise-cli/1.0.0'
}
});
// Add response interceptor for error handling
this.client.interceptors.response.use(
(response) => response,
(error) => {
console.error('Gateway request failed:', error.message);
throw error;
}
);
}
async getComponents(query?: string): Promise<GatewayResponse> {
try {
const params = query ? { search: query } : {};
const response = await this.client.get('/v1/components', { params });
return {
success: true,
data: response.data,
tokenCost: response.headers['x-token-cost'],
tokensRemaining: response.headers['x-tokens-remaining']
};
} catch (error: any) {
return {
success: false,
error: error.response?.data?.error || error.message
};
}
}
async generateComponent(prompt: string, projectContext?: any): Promise<GatewayResponse> {
try {
const params = new URLSearchParams();
params.append('prompt', prompt);
params.append('userId', 'default');
const response = await this.client.get(`/v1/generate?${params.toString()}`);
return {
success: true,
data: response.data,
tokenCost: response.headers['x-token-cost'],
tokensRemaining: response.headers['x-tokens-remaining']
};
} catch (error: any) {
return {
success: false,
error: error.response?.data?.error || error.message
};
}
}
async streamGeneration(prompt: string, projectContext?: any): Promise<void> {
try {
const response = await this.client.post('/v1/generate/stream', {
prompt,
projectContext
}, {
responseType: 'stream',
headers: {
'Accept': 'text/event-stream',
'Cache-Control': 'no-cache'
}
});
// For now, just log the stream events
response.data.on('data', (chunk: Buffer) => {
console.log('SSE Chunk:', chunk.toString());
});
response.data.on('end', () => {
console.log('SSE Stream ended');
});
response.data.on('error', (error: Error) => {
console.error('SSE Stream error:', error);
});
} catch (error: any) {
throw new Error(`Stream generation failed: ${error.message}`);
}
}
async validateApiKey(): Promise<boolean> {
try {
const response = await this.client.get('/v1/auth/validate');
return response.status === 200;
} catch (error) {
return false;
}
}
async getUsage(): Promise<GatewayResponse> {
try {
const response = await this.client.get('/v1/usage');
return {
success: true,
data: response.data
};
} catch (error: any) {
return {
success: false,
error: error.response?.data?.error || error.message
};
}
}
async generateReadme(prompt: string, projectContext?: any): Promise<GatewayResponse> {
try {
const params = new URLSearchParams();
params.append('prompt', prompt);
params.append('userId', 'default');
params.append('type', 'readme');
const response = await this.client.get(`/v1/generate?${params.toString()}`);
return {
success: true,
data: response.data,
tokenCost: response.headers['x-token-cost'],
tokensRemaining: response.headers['x-tokens-remaining']
};
} catch (error: any) {
return {
success: false,
error: error.response?.data?.error || error.message
};
}
}
async analyzeProject(prompt: string, projectContext?: any): Promise<GatewayResponse> {
try {
const params = new URLSearchParams();
params.append('prompt', prompt);
params.append('userId', 'default');
params.append('type', 'analysis');
const response = await this.client.get(`/v1/generate?${params.toString()}`);
return {
success: true,
data: response.data,
tokenCost: response.headers['x-token-cost'],
tokensRemaining: response.headers['x-tokens-remaining']
};
} catch (error: any) {
return {
success: false,
error: error.response?.data?.error || error.message
};
}
}
}