import { z } from "zod";
import { captureServerEvent } from "./analytics";
import { all, placeholders } from "./db";
import { repoDb, stmt } from "./scoped-db";
import { forgetLocator, registerLocator, registerLocators, type LocatorKind } from "./scoped-db/locators";
import { scopedId } from "./scoped-db/ids";
import { badRequest, conflict, forbidden, notFoundError } from "./errors";
import { emitNotification, emitWebhook } from "./events/emit";
import { kickBranch, kickMergeAutomation } from "./merge-automation";
import { pullUrl } from "./pull-access";
import { addIssueEvent } from "./pulls";
import type { PullRow } from "./pulls";
import { assertNotArchived } from "./repos";
import { assertAssignable } from "./assignable";
import { rerequestReview } from "./review-requests";
import { markdownBody } from "~/lib/validation";
import type { Permission, RepoRow, Viewer } from "~/lib/types";
import { issuesChanged } from "./repo-state";
/** A resolved pull plus the caller's effective permission on its repo (already capped by any token scope). */
export type PullAccess = { repo: RepoRow; permission: Permission; pull: PullRow };
export const reviewCommentInput = z
.object({
path: z.string().min(1),
line: z.number().int().positive(),
side: z.enum(["LEFT", "RIGHT"]),
startLine: z.number().int().positive().nullish(),
startSide: z.enum(["LEFT", "RIGHT"]).nullish(),
body: markdownBody.min(1),
})
.refine((comment) => !comment.startLine || comment.startLine < comment.line, "Start line must precede the end line");
export type ReviewCommentInput = z.infer<typeof reviewCommentInput>;
export type ReviewEvent = "approve" | "request_changes" | "comment";
function canWrite(permission: Permission): boolean {
return permission === "write" || permission === "admin";
}