import type { PageServerLoad, Actions } from './$types'; import { db } from '$lib/server/db/index.js'; import { wikiPages, wikiCategories, wikiTags, wikiPageTags } from '$lib/server/db/schema.js'; import { eq, ilike, or, desc, sql, count } from 'drizzle-orm'; import { fail } from '@sveltejs/kit'; import { slugify } from '$lib/utils/slug.js'; export const load: PageServerLoad = async ({ url }) => { const search = url.searchParams.get('q'); const tagFilter = url.searchParams.get('tag'); // Categories const categories = await db .select() .from(wikiCategories) .orderBy(wikiCategories.sortOrder, wikiCategories.name); // Pages query let pagesQuery; if (tagFilter) { // Filter by tag const [tag] = await db.select().from(wikiTags).where(eq(wikiTags.name, tagFilter)); if (tag) { const taggedPageIds = await db .select({ pageId: wikiPageTags.pageId }) .from(wikiPageTags) .where(eq(wikiPageTags.tagId, tag.id)); const ids = taggedPageIds.map((r) => r.pageId); if (ids.length > 0) { pagesQuery = db .select({ id: wikiPages.id, title: wikiPages.title, slug: wikiPages.slug, categoryId: wikiPages.categoryId, categoryName: wikiCategories.name, updatedAt: wikiPages.updatedAt, updatedBy: wikiPages.updatedBy }) .from(wikiPages) .leftJoin(wikiCategories, eq(wikiPages.categoryId, wikiCategories.id)) .where(sql`${wikiPages.id} IN ${ids}`) .orderBy(desc(wikiPages.updatedAt)); } } } else if (search) { pagesQuery = db .select({ id: wikiPages.id, title: wikiPages.title, slug: wikiPages.slug, categoryId: wikiPages.categoryId, categoryName: wikiCategories.name, updatedAt: wikiPages.updatedAt, updatedBy: wikiPages.updatedBy }) .from(wikiPages) .leftJoin(wikiCategories, eq(wikiPages.categoryId, wikiCategories.id)) .where(or(ilike(wikiPages.title, `%${search}%`), ilike(wikiPages.content, `%${search}%`))) .orderBy(desc(wikiPages.updatedAt)); } else { pagesQuery = db .select({ id: wikiPages.id, title: wikiPages.title, slug: wikiPages.slug, categoryId: wikiPages.categoryId, categoryName: wikiCategories.name, updatedAt: wikiPages.updatedAt, updatedBy: wikiPages.updatedBy }) .from(wikiPages) .leftJoin(wikiCategories, eq(wikiPages.categoryId, wikiCategories.id)) .orderBy(desc(wikiPages.updatedAt)); } const pages = pagesQuery ? await pagesQuery : []; // Get tags for each page const pageIds = pages.map((p) => p.id); let tagsByPage: Record = {}; if (pageIds.length > 0) { const pageTags = await db .select({ pageId: wikiPageTags.pageId, tagName: wikiTags.name }) .from(wikiPageTags) .innerJoin(wikiTags, eq(wikiPageTags.tagId, wikiTags.id)) .where(sql`${wikiPageTags.pageId} IN ${pageIds}`); for (const pt of pageTags) { if (!tagsByPage[pt.pageId]) tagsByPage[pt.pageId] = []; tagsByPage[pt.pageId].push(pt.tagName); } } // All tags with counts const allTags = await db .select({ name: wikiTags.name, count: count() }) .from(wikiTags) .innerJoin(wikiPageTags, eq(wikiTags.id, wikiPageTags.tagId)) .groupBy(wikiTags.name) .orderBy(wikiTags.name); return { categories, pages: pages.map((p) => ({ ...p, tags: tagsByPage[p.id] ?? [] })), allTags, filters: { search, tag: tagFilter } }; }; export const actions: Actions = { createCategory: async ({ request }) => { const formData = await request.formData(); const name = (formData.get('name') as string)?.trim(); if (!name) return fail(400, { error: 'Category name is required' }); const slug = slugify(name); await db.insert(wikiCategories).values({ name, slug }); return { categoryCreated: true }; }, deleteCategory: async ({ request }) => { const formData = await request.formData(); const id = formData.get('id') as string; await db.delete(wikiCategories).where(eq(wikiCategories.id, id)); return { categoryDeleted: true }; } };