/** * Shared comment query functions. * Centralizes comment fetching logic to avoid duplication. */ import { contentDb } from '$lib/server/db'; import { posts, comments } from '$lib/server/db/schema'; import { desc, eq, and, type SQL } from 'drizzle-orm'; import type { CommentBase } from '../enrichment'; export const DEFAULT_COMMENTS_LIMIT = 50; /** Comment with post context for display in listings */ export interface CommentWithPostContext extends CommentBase { postRkey: string; postTitle: string; } /** Options for fetching comments */ export interface GetCommentsOptions { /** Number of comments to fetch (default: 50) */ limit?: number; /** Additional WHERE clause for comments table */ where?: SQL; /** Include hidden comments (default: false, set true for admin views) */ includeHidden?: boolean; /** Filter to comments by this author DID */ authorDid?: string; /** Filter to comments on this post URI */ postUri?: string; } /** * Fetch recent comments with post context. * Hidden comments and comments on hidden posts are excluded by default. */ export async function getCommentsWithPostContext( options: GetCommentsOptions = {} ): Promise { const { limit = DEFAULT_COMMENTS_LIMIT, where, includeHidden = false, authorDid, postUri } = options; // Build where conditions const conditions: SQL[] = []; if (!includeHidden) { conditions.push(eq(comments.isHidden, 0)); conditions.push(eq(posts.isHidden, 0)); } if (authorDid) { conditions.push(eq(comments.authorDid, authorDid)); } if (postUri) { conditions.push(eq(comments.postUri, postUri)); } if (where) { conditions.push(where); } const whereClause = conditions.length > 0 ? and(...conditions) : undefined; let query = contentDb .select({ uri: comments.uri, cid: comments.cid, authorDid: comments.authorDid, rkey: comments.rkey, postUri: comments.postUri, parentUri: comments.parentUri, text: comments.text, createdAt: comments.createdAt, indexedAt: comments.indexedAt, postRkey: posts.rkey, postTitle: posts.title }) .from(comments) .innerJoin(posts, eq(comments.postUri, posts.uri)) .orderBy(desc(comments.createdAt)) .limit(limit); if (whereClause) { query = query.where(whereClause) as typeof query; } return query; } /** * Fetch comments for a specific post. * Hidden comments are excluded unless includeHidden is true. * Note: Does not check if the post itself is hidden - caller should verify. */ export async function getCommentsForPost( postUri: string, options: { includeHidden?: boolean } = {} ): Promise { const { includeHidden = false } = options; const whereClause = includeHidden ? eq(comments.postUri, postUri) : and(eq(comments.postUri, postUri), eq(comments.isHidden, 0)); return contentDb .select({ uri: comments.uri, cid: comments.cid, authorDid: comments.authorDid, rkey: comments.rkey, postUri: comments.postUri, parentUri: comments.parentUri, text: comments.text, createdAt: comments.createdAt, indexedAt: comments.indexedAt }) .from(comments) .where(whereClause); }