forked from StructZ/CodeTranslateAI
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.ts
More file actions
188 lines (159 loc) · 6.07 KB
/
index.ts
File metadata and controls
188 lines (159 loc) · 6.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
import { GoogleGenerativeAI } from '@google/generative-ai';
export interface Env {
RATE_LIMIT: KVNamespace;
LANG_TRANSLATION_ANALYTICS: KVNamespace;
GEMINI_API_KEY: string;
}
const corsHeaders = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'POST, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type',
};
const MAX_REQUESTS_ALLOWED = 10;
const DURATION = 60_000;
async function checkRateLimit(ip: string, env: Env) {
const key = `ip_key:${ip}`.toLowerCase();
const now = Date.now();
let value = await env.RATE_LIMIT.get(key);
let data = { count: 0, time: now };
if (value) {
try {
data = JSON.parse(value);
} catch {
data = { count: 0, time: now };
}
}
if (now - data.time > DURATION) {
data.count = 0;
data.time = now;
}
data.count += 1;
await env.RATE_LIMIT.put(key, JSON.stringify(data), { expirationTtl: 65 });
return data.count <= MAX_REQUESTS_ALLOWED;
}
async function updateAnalytics(source: string, dest: string, env: Env) {
const normalizedSource = source.trim().toLowerCase();
const normalizedDest = dest.trim().toLowerCase();
const key = `${normalizedSource}-${normalizedDest}`;
let value = await env.LANG_TRANSLATION_ANALYTICS.get(key);
let data = { count: 0 };
if (value) {
try {
data = JSON.parse(value);
} catch {
data = { count: 0 };
}
}
data.count += 1; // increment usage count
await env.LANG_TRANSLATION_ANALYTICS.put(key, JSON.stringify(data));
}
async function handleTranslate(request: Request, model: ReturnType<GoogleGenerativeAI['getGenerativeModel']>, env: Env) {
const { code, targetLanguage } = await request.json<{ code: string; targetLanguage: string }>();
if (!code || !targetLanguage) {
return new Response(JSON.stringify({ error: "Missing 'code' or 'targetLanguage' in request body." }), {
status: 400,
headers: { ...corsHeaders, 'Content-Type': 'application/json' },
});
}
const sourceLanguage = await detectLanguage(code, model);
const prompt = `Translate the following code snippet to ${targetLanguage}.
Do not add any explanation, commentary, or markdown formatting like \`\`\` around the code.
**IMPORTANT: Preserve all original comments and their exact placement in the translated code. Do not add extra spaces in between.**
Only provide the raw, translated code itself.
Original Code:
${code}`;
const result = await model.generateContent(prompt);
const translatedCode = result.response.text();
await updateAnalytics(sourceLanguage, targetLanguage, env);
return new Response(JSON.stringify({ translation: translatedCode}), {
status: 200,
headers: { ...corsHeaders, 'Content-Type': 'application/json' },
});
}
async function handleExplain(request: Request, model: ReturnType<GoogleGenerativeAI['getGenerativeModel']>) {
const { code } = await request.json<{ code: string }>();
if (!code) {
return new Response(JSON.stringify({ error: "Missing 'code' in request body." }), {
status: 400,
headers: { ...corsHeaders, 'Content-Type': 'application/json' },
});
}
const prompt = `Explain the following code snippet in detail:
1. Provide a clear breakdown of what each part (functions, variables, logic blocks) does.
2. If applicable, describe the overall purpose or intent of the code.
3. Offer a step-by-step explanation of how the code executes.
4. If the code is executable, show a sample input and the corresponding output.
5. Keep the explanation beginner-friendly but technically accurate.
Code:
${code}`;
const result = await model.generateContent(prompt);
const explanation = result.response.text();
return new Response(JSON.stringify({ explanation }), {
status: 200,
headers: { ...corsHeaders, 'Content-Type': 'application/json' },
});
}
export default {
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
if (request.method === 'OPTIONS') {
return new Response(null, { headers: corsHeaders });
}
try {
const ip = request.headers.get('CF-Connecting-IP') || 'unknown';
const allowed = await checkRateLimit(ip, env);
if (!allowed) {
return new Response(JSON.stringify({ error: 'Too many requests. Try again later.' }), {
status: 429,
headers: { ...corsHeaders, 'Content-Type': 'application/json' },
});
}
const url = new URL(request.url);
const path = url.pathname;
const genAI = new GoogleGenerativeAI(env.GEMINI_API_KEY);
const model = genAI.getGenerativeModel({ model: 'gemini-2.0-flash' });
if (path === '/v1/analytics') {
const list = await env.LANG_TRANSLATION_ANALYTICS.list();
const stats: Record<string, any> = {};
for (const key of list.keys) {
const val = await env.LANG_TRANSLATION_ANALYTICS.get(key.name);
try {
stats[key.name] = JSON.parse(val || '{}');
} catch (e) {
console.error(`Failed to parse analytics value for key "${key.name}":`, e);
stats[key.name] = {};
}
}
return new Response(JSON.stringify(stats, null, 2), {
headers: { ...corsHeaders, 'Content-Type': 'application/json' },
});
}
if (path === '/test-rate-limit') {
return new Response(JSON.stringify('Proceed !'));
}
if (path === '/' || path === '/v1/translate') {
return await handleTranslate(request, model, env);
}
if (path === '/v1/explain') {
return await handleExplain(request, model);
}
return new Response(JSON.stringify({ error: 'Route not found.' }), {
status: 404,
headers: { ...corsHeaders, 'Content-Type': 'application/json' },
});
} catch (error) {
console.error('Error during request:', error);
return new Response(JSON.stringify({ error: 'An internal error occurred.' }), {
status: 500,
headers: { ...corsHeaders, 'Content-Type': 'application/json' },
});
}
},
};
async function detectLanguage(code: string, model: ReturnType<GoogleGenerativeAI['getGenerativeModel']>) {
const prompt = `Identify the programming language of the following code.
Only respond with the exact language name (e.g., "python", "javascript", "c++", "java", etc.) without any extra text or punctuation.
Code:
${code}`;
const result = await model.generateContent(prompt);
return result.response.text().trim().toLowerCase();
}