import { PutObjectCommand, type S3Client } from "@aws-sdk/client-s3"; import type { SupabaseClient, User } from "@supabase/supabase-js"; import { type Context, Hono, type Next } from "hono"; import { getTabloFileNames, isTabloAdmin, isTabloMember } from "./helpers.js"; import { authMiddleware, r2Middleware, streamChatMiddleware, } from "./middleware.js"; export const tabloDataRouter = new Hono<{ Variables: { user: User; supabase: SupabaseClient; s3_client: S3Client; }; }>(); tabloDataRouter.use(authMiddleware); tabloDataRouter.use(streamChatMiddleware); tabloDataRouter.use(r2Middleware); const checkTabloMember = async (c: Context, next: Next) => { const supabase = c.get("supabase"); const user = c.get("user"); const tabloId = c.req.param("tabloId"); const isMember = await isTabloMember(supabase, tabloId, user.id); if (!isMember) { return c.json({ error: "You are not a member of this tablo" }, 403); } await next(); }; const checkTabloAdmin = async (c: Context, next: Next) => { const supabase = c.get("supabase"); const user = c.get("user"); const tabloId = c.req.param("tabloId"); const isAdmin = await isTabloAdmin(supabase, tabloId, user.id); if (!isAdmin) { return c.json({ error: "You are not an admin of this tablo" }, 403); } await next(); }; // GET /tablo-data/:tabloId/filenames - Get all files for a tablo tabloDataRouter.get("/:tabloId/filenames", checkTabloMember, async (c) => { const tabloId = c.req.param("tabloId"); const s3_client = c.get("s3_client"); try { const fileNames = await getTabloFileNames(s3_client, tabloId); return c.json({ fileNames: fileNames || [] }); } catch (error) { console.error("Error fetching tablo files:", error); return c.json({ error: "Failed to fetch tablo files" }, 500); } }); // GET /tablo-data/:tabloId/:fileName - Get a specific file tabloDataRouter.get("/:tabloId/:fileName", checkTabloMember, async (c) => { const tabloId = c.req.param("tabloId"); const fileName = c.req.param("fileName"); const s3_client = c.get("s3_client"); try { const { GetObjectCommand } = await import("@aws-sdk/client-s3"); const response = await s3_client.send( new GetObjectCommand({ Bucket: "tablo-data", Key: `${tabloId}/${fileName}`, }) ); if (!response.Body) { return c.json({ error: "File not found" }, 404); } const content = await response.Body.transformToString(); return c.json({ fileName, content, contentType: response.ContentType, lastModified: response.LastModified, }); } catch (error) { console.error("Error fetching file:", error); return c.json({ error: "Failed to fetch file" }, 500); } }); // POST /tablo-data/:tabloId/:fileName - Create or update a file tabloDataRouter.post("/:tabloId/:fileName", checkTabloAdmin, async (c) => { const tabloId = c.req.param("tabloId"); const fileName = c.req.param("fileName"); const s3_client = c.get("s3_client"); try { const body = await c.req.json(); const { content, contentType = "text/plain" } = body; if (!content) { return c.json({ error: "Content is required" }, 400); } await s3_client.send( new PutObjectCommand({ Bucket: "tablo-data", Key: `${tabloId}/${fileName}`, Body: content, ContentType: contentType, }) ); return c.json({ message: "File uploaded successfully", fileName, tabloId, }); } catch (error) { console.error("Error uploading file:", error); return c.json({ error: "Failed to upload file" }, 500); } }); // // PUT /tablo-data/:tabloId/:fileName - Update a file // tabloDataRouter.put("/:tabloId/:fileName", async (c) => { // const tabloId = c.req.param("tabloId"); // const fileName = c.req.param("fileName"); // const s3_client = c.get("s3_client"); // try { // const body = await c.req.json(); // const { content, contentType = "text/plain" } = body; // if (!content) { // return c.json({ error: "Content is required" }, 400); // } // const { PutObjectCommand } = await import("@aws-sdk/client-s3"); // await s3_client.send( // new PutObjectCommand({ // Bucket: "tablo-data", // Key: `${tabloId}/${fileName}`, // Body: content, // ContentType: contentType, // }) // ); // return c.json({ // message: "File updated successfully", // fileName, // tabloId, // }); // } catch (error) { // console.error("Error updating file:", error); // return c.json({ error: "Failed to update file" }, 500); // } // }); // DELETE /tablo-data/:tabloId/:fileName - Delete a file tabloDataRouter.delete("/:tabloId/:fileName", checkTabloAdmin, async (c) => { const tabloId = c.req.param("tabloId"); const fileName = c.req.param("fileName"); const s3_client = c.get("s3_client"); try { const { DeleteObjectCommand } = await import("@aws-sdk/client-s3"); await s3_client.send( new DeleteObjectCommand({ Bucket: "tablo-data", Key: `${tabloId}/${fileName}`, }) ); return c.json({ message: "File deleted successfully", fileName, tabloId, }); } catch (error) { console.error("Error deleting file:", error); return c.json({ error: "Failed to delete file" }, 500); } });