// Cloudflare Worker that holds the TonePerfect key for a mobile app. // Secret: `npx wrangler secret put TONEPERFECT_API_KEY`. Shared app token: // `npx wrangler secret put APP_TOKEN` (a speed bump, not real auth: replace it // with your own sign-in check before launch). const LANGUAGES = new Set(['zh-CN', 'en-US', 'fr-FR', 'es-419', 'de-DE', 'it-IT', 'pt-BR', 'ru-RU', 'ko-KR', 'ja-JP']); const json = (body, status = 200) => new Response(JSON.stringify(body), { status, headers: { 'Content-Type': 'application/json' } }); export default { async fetch(request, env) { if (request.method !== 'POST' || new URL(request.url).pathname !== '/assess') return json({ error: { code: 'not_found', message: 'POST /assess' } }, 404); if (env.APP_TOKEN && request.headers.get('x-app-token') !== env.APP_TOKEN) return json({ error: { code: 'unauthorized', message: 'Unknown app.' } }, 401); const form = await request.formData(); const audio = form.get('audio'); const text = String(form.get('text') || '').slice(0, 500); const language = String(form.get('language') || 'zh-CN'); if (!(audio instanceof Blob) || audio.size === 0 || audio.size > 10 * 1024 * 1024) return json({ error: { code: 'invalid_audio', message: 'Send one recording up to 10 MB.' } }, 422); if (!text || !LANGUAGES.has(language)) return json({ error: { code: 'invalid_input', message: 'Send text and a supported language.' } }, 422); const upstream = new FormData(); upstream.append('audio', audio, 'recording.m4a'); upstream.append('text', text); upstream.append('language', language); const response = await fetch(`${env.TONEPERFECT_BASE_URL || 'https://api.toneperfect.app'}/v1/assess`, { method: 'POST', body: upstream, headers: { Authorization: `Bearer ${env.TONEPERFECT_API_KEY}`, 'Idempotency-Key': request.headers.get('idempotency-key') || crypto.randomUUID(), 'TonePerfect-Response': 'compact', }, }); return new Response(await response.text(), { status: response.status, headers: { 'Content-Type': 'application/json' } }); }, };