236 lines · 8.1 KB
import { createServerFn } from "@tanstack/react-start";
import { resolveMentions } from "~/server/mentions";
import { z } from "zod";
import { requireViewer, viewerMiddleware } from "./middleware";
import { repoDb } from "~/server/scoped-db";
import { randomId } from "~/server/crypto";
import { limitWrite } from "~/server/limits";
import { requireRepoAccess, requireRepoMutation } from "~/server/repos";
import { assertCount, PLANNING_CAPS } from "~/server/planning";
import { renderMarkdown } from "~/server/markdown";
import { accountOrGhost, accountsById } from "~/server/people";
import { notFoundError } from "~/server/errors";
import { labelColor, markdownBody, repoRef, title } from "~/lib/validation";

type MilestoneRow = {
  id: string;
  title: string;
  description: string;
  due_on: number | null;
  state: "open" | "closed";
  updated_at: number;
  open_count: number;
  closed_count: number;
};

const MILESTONE_SELECT = `SELECT m.id, m.title, m.description, m.due_on, m.state, m.updated_at,
  (SELECT COUNT(*) FROM issues i WHERE i.milestone_id = m.id AND i.state = 'open') AS open_count,
  (SELECT COUNT(*) FROM issues i WHERE i.milestone_id = m.id AND i.state = 'closed') AS closed_count
  FROM milestones m`;
const MILESTONE_ISSUES_LIMIT = 200;

function toMilestone(row: MilestoneRow) {
  return {
    id: row.id,
    title: row.title,
    description: row.description,
    dueOn: row.due_on,
    state: row.state,
    updatedAt: row.updated_at,
    openCount: row.open_count,