162 lines · 5.6 KB
import { run } from "../db";
import { repoDb, stmt } from "../scoped-db";
import { registerLocator } from "../scoped-db/locators";
import { scopedId } from "../scoped-db/ids";
import { repoActivityStatement } from "../issue-scope";
import { captureServerEvent } from "../analytics";
import { accountOrGhost, accountsById } from "../people";
import { forbidden } from "../errors";
import { assertNotArchived } from "../repos";
import { allocateIssueNumber, indexIssue, issueUrl, setIssueState } from "../issues";
import type { IssueRow } from "../issues";
import { emitNotification, emitWebhook } from "../events/emit";
import type { RepoRow, Viewer } from "~/lib/types";

/** Mirrors the web issue form (src/fns/issues.ts createIssue) for an already-authorized caller. */
export async function insertIssue(repo: RepoRow, viewer: Viewer, title: string, body: string): Promise<number> {
  assertNotArchived(repo);
  if (repo.has_issues !== 1) throw forbidden("Issues are disabled for this repository");
  const number = await allocateIssueNumber(repo.id);
  const id = scopedId(repo.id);
  const now = Date.now();
  await repoDb(repo.id).batch([
    stmt(
      `INSERT INTO issues (id, repo_id, number, author_id, title, body, state, is_pull, created_at, updated_at)
       VALUES (?, ?, ?, ?, ?, ?, 'open', 0, ?, ?)`,
      id,
      repo.id,
      number,
      viewer.id,
      title,
      body,
      now,
      now,
    ),
    repoActivityStatement(viewer.id, repo.id, "issue_opened", {
      number,
      title,
    }),
  ]);
  await registerLocator("issue", id, repo.id);