import 'server-only'; import { fileNotFound, ServiceError, unexpectedError } from "../../lib/serviceError"; import { FileSourceRequest, FileSourceResponse } from "./types"; import { isServiceError } from "../../lib/utils"; import { search } from "./searchApi"; import { sew } from "@/actions"; import { withOptionalAuthV2 } from "@/withAuthV2"; import { QueryIR } from './ir'; import escapeStringRegexp from "escape-string-regexp"; // @todo (bkellam) #574 : We should really be using `git show :` to fetch file contents here. // This will allow us to support permalinks to files at a specific revision that may not be indexed // by zoekt. We should also refactor this out of the /search folder. export const getFileSource = async ({ fileName, repository, branch }: FileSourceRequest): Promise => sew(() => withOptionalAuthV2(async () => { const query: QueryIR = { and: { children: [ { repo: { regexp: `^${escapeStringRegexp(repository)}$`, }, }, { substring: { pattern: fileName, case_sensitive: true, file_name: true, content: false, } }, ...(branch ? [{ branch: { pattern: branch, exact: true, }, }]: []) ] } } const searchResponse = await search({ queryType: 'ir', query, options: { matches: 1, whole: true, } }); if (isServiceError(searchResponse)) { return searchResponse; } const files = searchResponse.files; if (!files || files.length === 0) { return fileNotFound(fileName, repository); } const file = files[0]; const source = file.content ?? ''; const language = file.language; const repoInfo = searchResponse.repositoryInfo.find((repo) => repo.id === file.repositoryId); if (!repoInfo) { // This should never happen. return unexpectedError("Repository info not found"); } return { source, language, path: fileName, repository, repositoryCodeHostType: repoInfo.codeHostType, repositoryDisplayName: repoInfo.displayName, repositoryWebUrl: repoInfo.webUrl, branch, webUrl: file.webUrl, } satisfies FileSourceResponse; }));