48 lines · 2.2 KB
import { repoDb, stmt } from "./scoped-db";
import { forgetLocator, locate } from "./scoped-db/locators";
import { VISIBLE_COMMENT } from "./issue-counters";

/**
 * Deletes an issue comment. The count update runs before the delete and only subtracts a visible comment: a hidden
 * one already left `comments_count` when it was hidden.
 */
export async function deleteIssueComment(comment: { id: string; issue_id: string }): Promise<void> {
  const repoId = await locate("issue", comment.issue_id);
  if (!repoId) return;
  await repoDb(repoId).batch([
    stmt("DELETE FROM reactions WHERE subject_type = 'comment' AND subject_id = ?", comment.id),
    stmt(
      `UPDATE issues SET comments_count = MAX(comments_count - ${VISIBLE_COMMENT}, 0) WHERE id = ?`,
      comment.id,
      comment.issue_id,
    ),
    stmt("DELETE FROM comments WHERE id = ?", comment.id),
  ]);
  await forgetLocator("comment", comment.id);
}

/** Deletes a discussion comment and its replies; only the visible ones come off `comments_count`. */
export async function deleteDiscussionComment(comment: { id: string; discussion_id: string }): Promise<void> {
  const repoId = await locate("discussion", comment.discussion_id);
  if (!repoId) return;
  const db = repoDb(repoId);
  const removed = await db.first<{ count: number }>(
    "SELECT COUNT(*) AS count FROM discussion_comments WHERE (id = ?1 OR parent_id = ?1) AND hidden_at IS NULL",
    comment.id,
  );
  const subjects = "SELECT id FROM discussion_comments WHERE id = ?1 OR parent_id = ?1";
  const ids = await db.all<{ id: string }>(subjects, comment.id);
  await db.batch([
    stmt(`DELETE FROM reactions WHERE subject_type = 'discussion_comment' AND subject_id IN (${subjects})`, comment.id),
    stmt(`DELETE FROM discussion_votes WHERE subject_id IN (${subjects})`, comment.id),
    stmt("DELETE FROM discussion_comments WHERE id = ?", comment.id),
    stmt("UPDATE discussions SET answer_id = NULL WHERE answer_id = ?", comment.id),
    stmt(