import { all, batch, chunks, first, placeholders, stmt } from "./db";
import { allocateIssueNumber, indexIssue } from "./issues";
import type { IssueRow } from "./issues";
import { addIssueEvent } from "./pulls";
import { assertBelowCap } from "./limits";
import type { RepoRow } from "~/lib/types";
/** Per-scope count caps for workstream 6 entities; kept here so `limits.ts` stays merge-friendly. */
export const PLANNING_CAPS = {
milestonesPerRepo: 100,
issueTypesPerRepo: 25,
subIssuesPerParent: 100,
pinnedPerRepo: 3,
projectsPerOwner: 100,
fieldsPerProject: 30,
optionsPerField: 50,
itemsPerProject: 1000,
categoriesPerRepo: 25,
discussionCommentsPerThread: 2000,
} as const;
export async function assertCount(sql: string, param: string, cap: number, what: string): Promise<void> {
const row = await first<{ count: number }>(sql, param);
assertBelowCap(row?.count ?? 0, cap, what);
}
export type Progress = { total: number; closed: number };
/** Closed/total counts of sub-issues for each parent issue id. */
export async function subIssueProgress(parentIds: string[]): Promise<Map<string, Progress>> {
const out = new Map<string, Progress>();
for (const part of chunks([...new Set(parentIds)])) {
const rows = await all<{ parent_id: string; total: number; closed: number }>(
`SELECT parent_id, COUNT(*) AS total, SUM(state = 'closed') AS closed FROM issues
WHERE parent_id IN (${placeholders(part.length)}) GROUP BY parent_id`,
...part,
);
for (const row of rows) out.set(row.parent_id, { total: row.total, closed: row.closed ?? 0 });
}
return out;