diff --git a/frontend/src/app.d.ts b/frontend/src/app.d.ts index da08e6d..785b0e4 100644 --- a/frontend/src/app.d.ts +++ b/frontend/src/app.d.ts @@ -1,12 +1,10 @@ -// See https://svelte.dev/docs/kit/types#app.d.ts -// for information about these interfaces +import type { ConvexHttpClient } from 'convex/browser'; + declare global { namespace App { - // interface Error {} - // interface Locals {} - // interface PageData {} - // interface PageState {} - // interface Platform {} + interface Locals { + convex: ConvexHttpClient; + } } } diff --git a/frontend/src/hooks.server.ts b/frontend/src/hooks.server.ts new file mode 100644 index 0000000..77eff0a --- /dev/null +++ b/frontend/src/hooks.server.ts @@ -0,0 +1,8 @@ +import { ConvexHttpClient } from 'convex/browser'; +import { PUBLIC_CONVEX_URL } from '$env/static/public'; +import type { Handle } from '@sveltejs/kit'; + +export const handle: Handle = async ({ event, resolve }) => { + event.locals.convex = new ConvexHttpClient(PUBLIC_CONVEX_URL); + return resolve(event); +}; diff --git a/frontend/src/routes/[mnemonic]/+server.ts b/frontend/src/routes/[mnemonic]/+server.ts new file mode 100644 index 0000000..e937f7e --- /dev/null +++ b/frontend/src/routes/[mnemonic]/+server.ts @@ -0,0 +1,31 @@ +import { api } from '$lib/convex/_generated/api'; +import { error } from '@sveltejs/kit'; +import type { RequestHandler } from './$types'; + +export const POST: RequestHandler = async ({ params, request, locals }) => { + const mnemonic = params.mnemonic; + + const chatData = await locals.convex.query(api.chats.getByMnemonic, { mnemonic }); + if (!chatData) { + throw error(404, 'Chat not found'); + } + + const contentType = request.headers.get('content-type') || 'image/jpeg'; + const buffer = await request.arrayBuffer(); + const base64 = Buffer.from(buffer).toString('base64'); + + const caption = request.headers.get('x-caption') || ''; + + await locals.convex.mutation(api.messages.create, { + chatId: chatData._id, + role: 'user', + content: caption, + source: 'web', + imageBase64: base64, + imageMediaType: contentType + }); + + return new Response(JSON.stringify({ ok: true }), { + headers: { 'Content-Type': 'application/json' } + }); +};