import { createError, defineEventHandler, readBody } from "h3"; import { createClient } from "@libsql/client"; function readEnv(name: string): string | undefined { return (globalThis as any)?.process?.env?.[name]; } function getTursoClient() { const url = readEnv("TURSO_DATABASE_URL") || readEnv("TURSO_URL"); if (!url) return null; return createClient({ url, authToken: readEnv("TURSO_AUTH_TOKEN") || readEnv("TURSO_TOKEN") }); } export default defineEventHandler(async (event) => { const client = getTursoClient(); if (!client) { throw createError({ statusCode: 500, statusMessage: "Turso not configured" }); } const table = readEnv("SHIP_FEEDBACK_TURSO_TABLE"); if (!table) { throw createError({ statusCode: 500, statusMessage: "SHIP_FEEDBACK_TURSO_TABLE not set" }); } const body = await readBody(event); // Accept either raw text or { csv: '...' } const csvText = typeof body === "string" ? body : (body && (body.csv || body.text)) || null; if (!csvText || typeof csvText !== "string") { throw createError({ statusCode: 400, statusMessage: "Missing CSV text in request body (send raw text or JSON {csv: '...'})" }); } const key = readEnv("SHIP_FEEDBACK_TURSO_KEY") || "ship_feedback.csv"; try { // Ensure table exists with simple (key,value) storage await client.execute(`CREATE TABLE IF NOT EXISTS ${table} (key TEXT PRIMARY KEY, value TEXT)`); // Use parameterized query to avoid injection await client.execute(`INSERT OR REPLACE INTO ${table} (key, value) VALUES (?, ?);`, [key, csvText]); return { ok: true, storedAt: `turso:${table}:${key}` }; } catch (err: any) { throw createError({ statusCode: 500, statusMessage: `Failed to store CSV to Turso: ${String(err?.message ?? err)}` }); } });