implement bookmark collections and enhance bookmark search functionality

This commit is contained in:
2025-06-02 17:31:36 +01:00
parent 6625451d47
commit 190c5c9caa
20 changed files with 758 additions and 427 deletions

View File

@@ -1,5 +1,5 @@
import type { User } from "@markone/core"
import type { Collection } from "@markone/core"
import type { Collection, Bookmark } from "@markone/core"
import { db } from "~/database.js"
function findCollections(user: User): Collection[] {
@@ -50,10 +50,23 @@ function deleteCollection(collectionId: string, user: User): void {
function findCollectionById(collectionId: string, user: User): Collection | null {
return db.query<Collection, { id: string; userId: string }>(`
SELECT *
SELECT id, name, description
FROM collections
WHERE id = $id AND user_id = $userId
`).get({ id: collectionId, userId: user.id })
}
export { findCollections, insertCollection, updateCollection, deleteCollection, findCollectionById }
function findCollectionBookmarks(
collection: Collection,
user: User
): Bookmark[] {
return db.query<Bookmark, { collectionId: string; userId: string }>(`
SELECT b.id, b.title, b.url
FROM bookmarks b
INNER JOIN bookmark_collections bc ON b.id = bc.bookmark_id
WHERE b.user_id = $userId
AND bc.collection_id = $collectionId
`).all({ collectionId: collection.id, userId: user.id })
}
export { findCollections, insertCollection, updateCollection, deleteCollection, findCollectionById, findCollectionBookmarks }

View File

@@ -2,7 +2,7 @@ import { type Collection, DEMO_USER, type User } from "@markone/core"
import { type } from "arktype"
import { ulid } from "ulid"
import { HttpError } from "~/error.ts"
import { findCollections, insertCollection, deleteCollection, updateCollection, findCollectionById } from "./collection.ts"
import { findCollections, insertCollection, deleteCollection, updateCollection, findCollectionById, findCollectionBookmarks } from "./collection.ts"
const AddCollectionRequestBody = type({
title: "string",
@@ -46,6 +46,16 @@ async function listUserCollections(request: Bun.BunRequest<"/api/collections">,
return Response.json(collections, { status: 200 })
}
async function fetchUserCollection(request: Bun.BunRequest<"/api/collections/:id">, user: User) {
const collection = findCollectionById(request.params.id, user)
if (!collection) {
throw new HttpError(404)
}
const bookmarks = findCollectionBookmarks(collection, user)
return Response.json({ ...collection, bookmarks }, { status: 200 })
}
async function deleteUserCollection(request: Bun.BunRequest<"/api/collections/:id">, user: User) {
if (user.id !== DEMO_USER.id) {
deleteCollection(request.params.id, user)
@@ -79,4 +89,14 @@ async function updateUserCollection(request: Bun.BunRequest<"/api/collections/:i
return Response.json(existingCollection, { status: 200 })
}
export { createCollection, listUserCollections, deleteUserCollection, updateUserCollection }
async function getCollectionBookmarks(request: Bun.BunRequest<"/api/collections/:id/bookmarks">, user: User) {
const collection = findCollectionById(request.params.id, user)
if (!collection) {
throw new HttpError(404)
}
const bookmarks = findCollectionBookmarks(collection, user)
return Response.json(bookmarks, { status: 200 })
}
export { createCollection, listUserCollections, deleteUserCollection, updateUserCollection, getCollectionBookmarks, fetchUserCollection }

View File

@@ -1,4 +1,4 @@
import { createCollection, deleteUserCollection, listUserCollections } from "~/collection/handlers.js"
import { createCollection, deleteUserCollection, getCollectionBookmarks, fetchUserCollection, listUserCollections } from "~/collection/handlers.js"
import { authenticated, login, logout, signUp, startBackgroundAuthTokenCleanup } from "./auth/auth.ts"
import { startBackgroundSessionCleanup } from "./auth/session.ts"
import { insertDemoBookmarks } from "./bookmark/bookmark.ts"
@@ -59,12 +59,16 @@ async function main() {
POST: authenticated(createCollection),
},
"/api/collections/:id": {
GET: authenticated(fetchUserCollection),
DELETE: authenticated(deleteUserCollection),
OPTIONS: preflightHandler({
allowedMethods: ["GET", "POST", "DELETE", "PATCH", "OPTIONS"],
allowedHeaders: ["Accept"],
}),
},
"/api/collections/:id/bookmarks": {
GET: authenticated(getCollectionBookmarks),
},
},
port: 8080,