diff --git a/apps/web/app/(dash)/(memories)/content.tsx b/apps/web/app/(dash)/(memories)/content.tsx index 9409b45f..fea4477a 100644 --- a/apps/web/app/(dash)/(memories)/content.tsx +++ b/apps/web/app/(dash)/(memories)/content.tsx @@ -1,6 +1,5 @@ "use client"; -import { getAllUserMemoriesAndSpaces } from "@/app/actions/fetchers"; import { Content, StoredSpace } from "@/server/db/schema"; import { MemoriesIcon, NextIcon, SearchIcon, UrlIcon } from "@repo/ui/icons"; import { diff --git a/apps/web/app/actions/doers.ts b/apps/web/app/actions/doers.ts index 3ff0e531..a2cdb4f5 100644 --- a/apps/web/app/actions/doers.ts +++ b/apps/web/app/actions/doers.ts @@ -426,7 +426,6 @@ export const createChatObject = async ( error: "No chat object found", }; } - console.log("sources: ", lastChat.answer.sources); const saved = await db.insert(chatHistory).values({ question: lastChat.question, diff --git a/apps/web/app/actions/fetchers.ts b/apps/web/app/actions/fetchers.ts index 539fadf9..1838ee1c 100644 --- a/apps/web/app/actions/fetchers.ts +++ b/apps/web/app/actions/fetchers.ts @@ -18,7 +18,6 @@ import { import { ServerActionReturnType, Space } from "./types"; import { auth } from "../../server/auth"; import { ChatHistory, SourceZod } from "@repo/shared-types"; -import { ChatHistory as ChatHistoryType } from "../../server/db/schema"; import { z } from "zod"; import { redirect } from "next/navigation"; import { cookies, headers } from "next/headers"; diff --git a/apps/web/app/api/chat/history/route.ts b/apps/web/app/api/chat/history/route.ts index 6c0cf41b..98b66064 100644 --- a/apps/web/app/api/chat/history/route.ts +++ b/apps/web/app/api/chat/history/route.ts @@ -1,7 +1,37 @@ import { NextRequest } from "next/server"; +import { ensureAuth } from "../../ensureAuth"; +import { db } from "@/server/db"; +import { eq } from "drizzle-orm"; +import { chatThreads } from "@/server/db/schema"; export const runtime = "edge"; export async function GET(req: NextRequest) { - return new Response("Hello, World!"); + const session = await ensureAuth(req); + + if (!session) { + return new Response("Unauthorized", { status: 401 }); + } + + if (!process.env.BACKEND_SECURITY_KEY) { + return new Response("Missing BACKEND_SECURITY_KEY", { status: 500 }); + } + + try { + const chatHistorys = await db.query.chatThreads.findMany({ + where: eq(chatThreads.userId, session.user.id), + }); + + return new Response(JSON.stringify({ success: true, data: chatHistorys }), { + status: 200, + }); + } catch (e) { + return new Response( + JSON.stringify({ + success: false, + error: (e as Error).message, + }), + { status: 400 }, + ); + } } diff --git a/apps/web/app/api/memories/route.ts b/apps/web/app/api/memories/route.ts new file mode 100644 index 00000000..acb43b5d --- /dev/null +++ b/apps/web/app/api/memories/route.ts @@ -0,0 +1,85 @@ +import { NextRequest } from "next/server"; +import { db } from "@/server/db"; +import { eq } from "drizzle-orm"; +import { + chatThreads, + contentToSpace, + storedContent, + users, +} from "@/server/db/schema"; +import { ensureAuth } from "../ensureAuth"; + +export const runtime = "edge"; + +export async function GET(req: NextRequest) { + const session = await ensureAuth(req); + + if (!session) { + return new Response("Unauthorized", { status: 401 }); + } + + if (!process.env.BACKEND_SECURITY_KEY) { + return new Response("Missing BACKEND_SECURITY_KEY", { status: 500 }); + } + + const url = new URL(req.url); + + const spaceId = url.searchParams.get("space"); + + try { + if (spaceId) { + const memories = await db + .select({ + id: storedContent.id, + content: storedContent.content, + title: storedContent.title, + description: storedContent.description, + url: storedContent.url, + savedAt: storedContent.savedAt, + baseUrl: storedContent.baseUrl, + ogImage: storedContent.ogImage, + type: storedContent.type, + image: storedContent.image, + userId: storedContent.userId, + noteId: storedContent.noteId, + }) + .from(storedContent) + .innerJoin( + contentToSpace, + eq(storedContent.id, contentToSpace.contentId), + ) + .where(eq(contentToSpace.spaceId, parseInt(spaceId))); + + return new Response( + JSON.stringify({ + success: true, + data: { memories: memories }, + }), + { status: 200 }, + ); + } + + const spaces = await db.query.space.findMany({ + where: eq(users, session.user.id), + }); + + const memories = await db.query.storedContent.findMany({ + where: eq(users, session.user.id), + }); + + return new Response( + JSON.stringify({ + success: true, + data: { spaces: spaces, memories: memories }, + }), + ); + } catch (e) { + return new Response( + JSON.stringify({ + success: false, + error: (e as Error).message, + }), + { status: 400 }, + ); + } +} diff --git a/apps/web/app/api/spaces/route.ts b/apps/web/app/api/spaces/route.ts index ae0215a1..e85e07ed 100644 --- a/apps/web/app/api/spaces/route.ts +++ b/apps/web/app/api/spaces/route.ts @@ -1,8 +1,9 @@ import { db } from "@/server/db"; -import { sessions, space, users } from "@/server/db/schema"; +import { space } from "@/server/db/schema"; import { eq } from "drizzle-orm"; import { NextRequest, NextResponse } from "next/server"; import { ensureAuth } from "../ensureAuth"; +import { z } from "zod"; export const runtime = "edge"; @@ -19,6 +20,7 @@ export async function GET(req: NextRequest) { .where(eq(space.user, session.user.id)) .all(); + // We want to slowly move away from this pattern and return `new Response` directly return NextResponse.json( { message: "OK", @@ -27,3 +29,56 @@ export async function GET(req: NextRequest) { { status: 200 }, ); } + +export async function POST(req: NextRequest) { + const session = await ensureAuth(req); + + if (!session) { + return new Response("Unauthorized", { status: 401 }); + } + + const expectedInput = z.object({ + name: z.string(), + }); + + const jsonRequest = await req.json(); + + const validated = expectedInput.safeParse(jsonRequest); + if (!validated.success) { + return new Response( + JSON.stringify({ success: false, error: validated.error }), + { + status: 400, + }, + ); + } + + const newSpace = await db.insert(space).values({ + name: validated.data.name, + createdAt: new Date(), + user: session.user.id, + }); + + return new Response(JSON.stringify({ success: true, data: newSpace }), { + status: 200, + }); +} + +export const DELETE = async (req: NextRequest) => { + const session = await ensureAuth(req); + + if (!session) { + return new Response("Unauthorized", { status: 401 }); + } + + const url = new URL(req.url); + const spaceId = url.searchParams.get("space"); + + if (!spaceId) { + return new Response("Invalid space id", { status: 400 }); + } + + await db.delete(space).where(eq(space.id, parseInt(spaceId))); + + return new Response(JSON.stringify({ success: true }), { status: 200 }); +};