aboutsummaryrefslogtreecommitdiff
path: root/apps/web/app/api
diff options
context:
space:
mode:
authorDhravya <[email protected]>2024-05-25 23:38:48 -0500
committerDhravya <[email protected]>2024-05-25 23:38:48 -0500
commitc12ecfc4316a6f37d2d07c57e4dfefa231783c0d (patch)
treec04612a8db2b06060e1e1087ef298fa124aa71e4 /apps/web/app/api
parentfix global file stuff (diff)
downloadsupermemory-c12ecfc4316a6f37d2d07c57e4dfefa231783c0d.tar.xz
supermemory-c12ecfc4316a6f37d2d07c57e4dfefa231783c0d.zip
brought all the APIs back
Diffstat (limited to 'apps/web/app/api')
-rw-r--r--apps/web/app/api/chat/route.ts73
-rw-r--r--apps/web/app/api/getCount/route.ts47
-rw-r--r--apps/web/app/api/me/route.ts47
-rw-r--r--apps/web/app/api/spaces/route.ts29
-rw-r--r--apps/web/app/api/store/route.ts121
5 files changed, 317 insertions, 0 deletions
diff --git a/apps/web/app/api/chat/route.ts b/apps/web/app/api/chat/route.ts
new file mode 100644
index 00000000..34099848
--- /dev/null
+++ b/apps/web/app/api/chat/route.ts
@@ -0,0 +1,73 @@
+import { type NextRequest } from "next/server";
+import { ChatHistory } from "@repo/shared-types";
+import { ensureAuth } from "../ensureAuth";
+
+export const runtime = "edge";
+
+export async function POST(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 query = new URL(req.url).searchParams.get("q");
+ const spaces = new URL(req.url).searchParams.get("spaces");
+
+ const sourcesOnly =
+ new URL(req.url).searchParams.get("sourcesOnly") ?? "false";
+
+ const chatHistory = (await req.json()) as {
+ chatHistory: ChatHistory[];
+ };
+
+ console.log("CHathistory", chatHistory);
+
+ if (!query) {
+ return new Response(JSON.stringify({ message: "Invalid query" }), {
+ status: 400,
+ });
+ }
+
+ try {
+ const resp = await fetch(
+ `https://cf-ai-backend.dhravya.workers.dev/chat?q=${query}&user=${session.user.email ?? session.user.name}&sourcesOnly=${sourcesOnly}&spaces=${spaces}`,
+ {
+ headers: {
+ "X-Custom-Auth-Key": process.env.BACKEND_SECURITY_KEY!,
+ },
+ method: "POST",
+ body: JSON.stringify({
+ chatHistory: chatHistory.chatHistory ?? [],
+ }),
+ },
+ );
+
+ console.log("sourcesOnly", sourcesOnly);
+
+ if (sourcesOnly == "true") {
+ const data = await resp.json();
+ console.log("data", data);
+ return new Response(JSON.stringify(data), { status: 200 });
+ }
+
+ if (resp.status !== 200 || !resp.ok) {
+ const errorData = await resp.json();
+ console.log(errorData);
+ return new Response(
+ JSON.stringify({ message: "Error in CF function", error: errorData }),
+ { status: resp.status },
+ );
+ }
+
+ // Stream the response back to the client
+ const { readable, writable } = new TransformStream();
+ resp && resp.body!.pipeTo(writable);
+
+ return new Response(readable, { status: 200 });
+ } catch {}
+}
diff --git a/apps/web/app/api/getCount/route.ts b/apps/web/app/api/getCount/route.ts
new file mode 100644
index 00000000..f760c145
--- /dev/null
+++ b/apps/web/app/api/getCount/route.ts
@@ -0,0 +1,47 @@
+import { db } from "@/app/helpers/server/db";
+import { and, eq, ne, sql } from "drizzle-orm";
+import { sessions, storedContent, users } from "@/app/helpers/server/db/schema";
+import { type NextRequest, NextResponse } from "next/server";
+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 });
+ }
+
+ const tweetsCount = await db
+ .select({
+ count: sql<number>`count(*)`.mapWith(Number),
+ })
+ .from(storedContent)
+ .where(
+ and(
+ eq(storedContent.user, session.user.id),
+ eq(storedContent.type, "twitter-bookmark"),
+ ),
+ );
+
+ const pageCount = await db
+ .select({
+ count: sql<number>`count(*)`.mapWith(Number),
+ })
+ .from(storedContent)
+ .where(
+ and(
+ eq(storedContent.user, session.user.id),
+ ne(storedContent.type, "twitter-bookmark"),
+ ),
+ );
+
+ return NextResponse.json({
+ tweetsCount: tweetsCount[0]!.count,
+ tweetsLimit: 1000,
+ pageCount: pageCount[0]!.count,
+ pageLimit: 100,
+ user: session.user.email,
+ });
+}
diff --git a/apps/web/app/api/me/route.ts b/apps/web/app/api/me/route.ts
new file mode 100644
index 00000000..20b6aece
--- /dev/null
+++ b/apps/web/app/api/me/route.ts
@@ -0,0 +1,47 @@
+import { db } from "@/app/helpers/server/db";
+import { eq } from "drizzle-orm";
+import { sessions, users } from "@/app/helpers/server/db/schema";
+import { type NextRequest, NextResponse } from "next/server";
+
+export const runtime = "edge";
+
+export async function GET(req: NextRequest) {
+ const token =
+ req.cookies.get("next-auth.session-token")?.value ??
+ req.cookies.get("__Secure-authjs.session-token")?.value ??
+ req.cookies.get("authjs.session-token")?.value ??
+ req.headers.get("Authorization")?.replace("Bearer ", "");
+
+ const session = await db
+ .select()
+ .from(sessions)
+ .where(eq(sessions.sessionToken, token!));
+
+ if (!session || session.length === 0) {
+ return new Response(
+ JSON.stringify({ message: "Invalid Key, session not found." }),
+ { status: 404 },
+ );
+ }
+
+ const user = await db
+ .select()
+ .from(users)
+ .where(eq(users.id, session[0]!.userId))
+ .limit(1);
+
+ if (!user || user.length === 0) {
+ return NextResponse.json(
+ { message: "Invalid Key, session not found." },
+ { status: 404 },
+ );
+ }
+
+ return new Response(
+ JSON.stringify({
+ message: "OK",
+ data: { session: session[0], user: user[0] },
+ }),
+ { status: 200 },
+ );
+}
diff --git a/apps/web/app/api/spaces/route.ts b/apps/web/app/api/spaces/route.ts
new file mode 100644
index 00000000..c46b02fc
--- /dev/null
+++ b/apps/web/app/api/spaces/route.ts
@@ -0,0 +1,29 @@
+import { db } from "@/app/helpers/server/db";
+import { sessions, space, users } from "@/app/helpers/server/db/schema";
+import { eq } from "drizzle-orm";
+import { NextRequest, NextResponse } from "next/server";
+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 });
+ }
+
+ const spaces = await db
+ .select()
+ .from(space)
+ .where(eq(space.user, session.user.id))
+ .all();
+
+ return NextResponse.json(
+ {
+ message: "OK",
+ data: spaces,
+ },
+ { status: 200 },
+ );
+}
diff --git a/apps/web/app/api/store/route.ts b/apps/web/app/api/store/route.ts
new file mode 100644
index 00000000..f96f90cf
--- /dev/null
+++ b/apps/web/app/api/store/route.ts
@@ -0,0 +1,121 @@
+import { db } from "@/app/helpers/server/db";
+import { and, eq, sql, inArray } from "drizzle-orm";
+import {
+ contentToSpace,
+ sessions,
+ storedContent,
+ users,
+ space,
+} from "@/app/helpers/server/db/schema";
+import { type NextRequest, NextResponse } from "next/server";
+import { getMetaData } from "@/app/helpers/lib/get-metadata";
+import { ensureAuth } from "../ensureAuth";
+
+export const runtime = "edge";
+
+export async function POST(req: NextRequest) {
+ const session = await ensureAuth(req);
+
+ if (!session) {
+ return new Response("Unauthorized", { status: 401 });
+ }
+
+ const data = (await req.json()) as {
+ pageContent: string;
+ url: string;
+ spaces?: string[];
+ };
+
+ const metadata = await getMetaData(data.url);
+ let storeToSpaces = data.spaces;
+
+ if (!storeToSpaces) {
+ storeToSpaces = [];
+ }
+
+ const count = await db
+ .select({
+ count: sql<number>`count(*)`.mapWith(Number),
+ })
+ .from(storedContent)
+ .where(
+ and(
+ eq(storedContent.user, session.user.id),
+ eq(storedContent.type, "page"),
+ ),
+ );
+
+ if (count[0]!.count > 100) {
+ return NextResponse.json(
+ { message: "Error", error: "Limit exceeded" },
+ { status: 499 },
+ );
+ }
+
+ const rep = await db
+ .insert(storedContent)
+ .values({
+ content: data.pageContent,
+ title: metadata.title,
+ description: metadata.description,
+ url: data.url,
+ baseUrl: metadata.baseUrl,
+ image: metadata.image,
+ savedAt: new Date(),
+ user: session.user.id,
+ })
+ .returning({ id: storedContent.id });
+
+ const id = rep[0]?.id;
+
+ if (!id) {
+ return NextResponse.json(
+ { message: "Error", error: "Error in CF function" },
+ { status: 500 },
+ );
+ }
+
+ if (storeToSpaces.length > 0) {
+ const spaceData = await db
+ .select()
+ .from(space)
+ .where(
+ and(
+ inArray(space.name, storeToSpaces ?? []),
+ eq(space.user, session.user.id),
+ ),
+ )
+ .all();
+
+ await Promise.all([
+ spaceData.forEach(async (space) => {
+ await db
+ .insert(contentToSpace)
+ .values({ contentId: id, spaceId: space.id });
+ }),
+ ]);
+ }
+
+ const res = (await Promise.race([
+ fetch("https://cf-ai-backend.dhravya.workers.dev/add", {
+ method: "POST",
+ headers: {
+ "X-Custom-Auth-Key": process.env.BACKEND_SECURITY_KEY,
+ },
+ body: JSON.stringify({ ...data, user: session.user.email }),
+ }),
+ new Promise((_, reject) =>
+ setTimeout(() => reject(new Error("Request timed out")), 40000),
+ ),
+ ])) as Response;
+
+ if (res.status !== 200) {
+ console.log(res.status, res.statusText);
+ return NextResponse.json(
+ { message: "Error", error: "Error in CF function" },
+ { status: 500 },
+ );
+ }
+
+ return NextResponse.json({ message: "OK", data: "Success" }, { status: 200 });
+}