diff options
| author | Dhravya Shah <[email protected]> | 2025-02-14 15:53:44 -0800 |
|---|---|---|
| committer | Dhravya Shah <[email protected]> | 2025-02-14 15:53:44 -0800 |
| commit | af1093d4aab6d5654364e7cd9df76fd766bbee03 (patch) | |
| tree | f128bdb8cac4b44ed41289dc9a158c33fe86c5ec /apps/backend/src | |
| parent | twitter import fix (diff) | |
| download | supermemory-af1093d4aab6d5654364e7cd9df76fd766bbee03.tar.xz supermemory-af1093d4aab6d5654364e7cd9df76fd766bbee03.zip | |
intuitive memory movement, avoid duplicates in home
Diffstat (limited to 'apps/backend/src')
| -rw-r--r-- | apps/backend/src/index.tsx | 4 | ||||
| -rw-r--r-- | apps/backend/src/routes/memories.ts | 32 | ||||
| -rw-r--r-- | apps/backend/src/routes/spaces.ts | 116 |
3 files changed, 146 insertions, 6 deletions
diff --git a/apps/backend/src/index.tsx b/apps/backend/src/index.tsx index 1d62b543..48790e90 100644 --- a/apps/backend/src/index.tsx +++ b/apps/backend/src/index.tsx @@ -47,6 +47,10 @@ export const app = new Hono<{ Variables: Variables; Bindings: Env }>() .use("/v1/*", auth) .use("/v1/*", (c, next) => { const user = c.get("user"); + + if (c.env.NODE_ENV === "development") { + return next(); + } // RATELIMITS const rateLimitConfig = { diff --git a/apps/backend/src/routes/memories.ts b/apps/backend/src/routes/memories.ts index efcc6fb7..aa35877b 100644 --- a/apps/backend/src/routes/memories.ts +++ b/apps/backend/src/routes/memories.ts @@ -8,7 +8,7 @@ import { spaceAccess, contentToSpace, } from "@supermemory/db/schema"; -import { and, database, desc, eq, or, sql } from "@supermemory/db"; +import { and, database, desc, eq, or, sql, isNull } from "@supermemory/db"; const memories = new Hono<{ Variables: Variables; Bindings: Env }>() .get( @@ -124,9 +124,20 @@ const memories = new Hono<{ Variables: Variables; Bindings: Env }>() const [items, [{ total }]] = await Promise.all([ db - .select() + .select({ + documents: documents, + }) .from(documents) - .where(eq(documents.userId, user.id)) + .leftJoin( + contentToSpace, + eq(documents.id, contentToSpace.contentId) + ) + .where( + and( + eq(documents.userId, user.id), + isNull(contentToSpace.contentId) + ) + ) .orderBy(desc(documents.createdAt)) .limit(count) .offset(start), @@ -135,13 +146,22 @@ const memories = new Hono<{ Variables: Variables; Bindings: Env }>() total: sql<number>`count(*)`.as("total"), }) .from(documents) - .where(eq(documents.userId, user.id)), + .leftJoin( + contentToSpace, + eq(documents.id, contentToSpace.contentId) + ) + .where( + and( + eq(documents.userId, user.id), + isNull(contentToSpace.contentId) + ) + ), ]); return c.json({ items: items.map((item) => ({ - ...item, - id: item.uuid, + ...item.documents, + id: item.documents.uuid, })), total, }); diff --git a/apps/backend/src/routes/spaces.ts b/apps/backend/src/routes/spaces.ts index 2ca2e461..bede366c 100644 --- a/apps/backend/src/routes/spaces.ts +++ b/apps/backend/src/routes/spaces.ts @@ -99,6 +99,7 @@ const spacesRoute = new Hono<{ Variables: Variables; Bindings: Env }>() const spaceId = c.req.param("spaceId"); const db = database(c.env.HYPERDRIVE.connectionString); + const space = await db .select() .from(spaces) @@ -178,6 +179,10 @@ const spacesRoute = new Hono<{ Variables: Variables; Bindings: Env }>() return c.json({ error: "Unauthorized" }, 401); } + if (body.spaceName.trim() === "<HOME>") { + return c.json({ error: "Cannot create space with name <HOME>" }, 400); + } + const db = database(c.env.HYPERDRIVE.connectionString); const uuid = randomId(); @@ -264,6 +269,99 @@ const spacesRoute = new Hono<{ Variables: Variables; Bindings: Env }>() } ) .post( + "/moveContent", + zValidator( + "json", + z.object({ + spaceId: z.string(), + documentId: z.string(), + }) + ), + async (c) => { + const body = c.req.valid("json"); + const user = c.get("user"); + const { spaceId, documentId } = body; + + if (!user) { + return c.json({ error: "Unauthorized" }, 401); + } + + const db = database(c.env.HYPERDRIVE.connectionString); + + try { + await db.transaction(async (tx) => { + // If moving to <HOME>, just remove all space connections + if (spaceId === "<HOME>") { + const doc = await tx + .select() + .from(documents) + .where(eq(documents.uuid, documentId)) + .limit(1); + + if (!doc[0]) { + return c.json({ error: "Document not found" }, 404); + } + + await tx + .delete(contentToSpace) + .where(eq(contentToSpace.contentId, doc[0].id)); + return; + } + + // Get space and document, verify space ownership + const results = ( + await tx + .select({ + spaceId: spaces.id, + documentId: documents.id, + ownerId: spaces.ownerId, + spaceName: spaces.name, + }) + .from(spaces) + .innerJoin( + documents, + and(eq(spaces.uuid, spaceId), eq(documents.uuid, documentId)) + ) + .limit(1) + )[0]; + + if (!results) { + return c.json({ error: "Space or document not found" }, 404); + } + + if (results.ownerId !== user.id) { + return c.json( + { error: "Not authorized to modify this space" }, + 403 + ); + } + + // Delete existing space relations for this document + await tx + .delete(contentToSpace) + .where(eq(contentToSpace.contentId, results.documentId)); + + // Add new space relation + await tx.insert(contentToSpace).values({ + contentId: results.documentId, + spaceId: results.spaceId, + }); + }); + + return c.json({ success: true, spaceId }); + } catch (e) { + console.error("Failed to move content to space:", e); + return c.json( + { + error: "Failed to move content to space", + details: e instanceof Error ? e.message : "Unknown error", + }, + 500 + ); + } + } + ) + .post( "/addContent", zValidator( "json", @@ -285,6 +383,24 @@ const spacesRoute = new Hono<{ Variables: Variables; Bindings: Env }>() try { await db.transaction(async (tx) => { + // If adding to <HOME>, just remove all space connections + if (spaceId === "<HOME>") { + const doc = await tx + .select() + .from(documents) + .where(eq(documents.uuid, documentId)) + .limit(1); + + if (!doc[0]) { + return c.json({ error: "Document not found" }, 404); + } + + await tx + .delete(contentToSpace) + .where(eq(contentToSpace.contentId, doc[0].id)); + return; + } + // Get space and document, verify space ownership const results = ( await tx |