Files
turbostarter/packages/api/src/modules/ai/tts.ts
Alejandro Gutiérrez 3527e732d4 feat: turbostarter boilerplate
Production-ready Next.js boilerplate with:
- Runtime env validation (fail-fast on missing vars)
- Feature-gated config (S3, Stripe, email, OAuth)
- Docker + Coolify deployment pipeline
- PostgreSQL + pgvector, MinIO S3, Better Auth
- TypeScript strict mode (no ignoreBuildErrors)
- i18n (en/es), AI modules, billing, monitoring

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 01:01:55 +01:00

41 lines
1.0 KiB
TypeScript

import { Hono } from "hono";
import { Credits } from "@turbostarter/ai/credits/utils";
import { getVoices, textToSpeech } from "@turbostarter/ai/tts/api";
import { ttsSchema } from "@turbostarter/ai/tts/schema";
import { deductCredits, enforceAuth, rateLimiter, validate } from "../../middleware";
import type { User } from "@turbostarter/auth";
export const ttsRouter = new Hono<{
Variables: {
user: User;
};
}>()
.post(
"/",
enforceAuth,
rateLimiter,
validate("json", ttsSchema),
async (c) => {
const input = c.req.valid("json");
// Deduct credits
await deductCredits(Credits.COST.HIGH, "text-to-speech")(c, async () => { /* noop */ });
return new Response(
(await textToSpeech(input)) as unknown as ConstructorParameters<
typeof Response
>[0],
{
headers: { "Content-Type": "audio/mpeg" },
},
);
},
)
.get("/voices", enforceAuth, async (c) => {
const voices = await getVoices();
return c.json(voices);
});