feat(repositories): UI API client for connection flow + clone credentials

Add begin/complete connection, searchable paginated discovery, multi-select
import, and clone-credential resolution methods bound to the new server
contract and shared types.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
DottaandPaperclip committed 2026-08-12 02:34:33 +00:00
1 parent 490c9a4ac9
commit 9803ef406c
1 file changed
+56
+56
View File
@@ -1,16 +1,42 @@
import type {
AgentRepositoryGrantEntry,
BeginRepositoryConnectionResult,
CompleteRepositoryConnectionResult,
CreateManualRepository,
CreateRepositoryConnection,
EffectiveRepositoryAccess,
ImportRepositoriesResult,
ProjectRepositoryEntry,
Repository,
RepositoryCatalogItem,
RepositoryConnection,
RepositoryDiscoveryPage,
UpdateRepository,
} from "@paperclipai/shared";
import { api } from "./client";
export interface RepositoryCloneCredential {
username: string;
token: string;
authenticatedCloneUrl: string;
expiresAt: string;
}
export interface RepositoryDiscoveryQuery {
query?: string | null;
cursor?: string | null;
pageSize?: number;
}
function discoveryQueryString(opts: RepositoryDiscoveryQuery = {}): string {
const params = new URLSearchParams();
if (opts.query) params.set("query", opts.query);
if (opts.cursor) params.set("cursor", opts.cursor);
if (typeof opts.pageSize === "number") params.set("pageSize", String(opts.pageSize));
const qs = params.toString();
return qs ? `?${qs}` : "";
}
export const repositoriesApi = {
list: (companyId: string, opts: { includeArchived?: boolean } = {}) =>
api.get<RepositoryCatalogItem[]>(
@@ -43,6 +69,36 @@ export const repositoriesApi = {
`/repository-connections/${encodeURIComponent(connectionId)}`,
),
// ---- Guided provider connection flow (GitHub.com + other providers) ----
beginConnection: (companyId: string, provider: string, input: { redirectPath?: string | null } = {}) =>
api.post<BeginRepositoryConnectionResult>(
`/companies/${encodeURIComponent(companyId)}/repository-connections/${encodeURIComponent(provider)}/install`,
input,
),
completeConnection: (
companyId: string,
provider: string,
input: { state: string; installationId: string },
) =>
api.post<CompleteRepositoryConnectionResult>(
`/companies/${encodeURIComponent(companyId)}/repository-connections/${encodeURIComponent(provider)}/callback`,
input,
),
discoverConnectionRepositories: (connectionId: string, opts: RepositoryDiscoveryQuery = {}) =>
api.get<RepositoryDiscoveryPage>(
`/repository-connections/${encodeURIComponent(connectionId)}/discover${discoveryQueryString(opts)}`,
),
importConnectionRepositories: (connectionId: string, providerRepositoryIds: string[]) =>
api.post<ImportRepositoriesResult>(
`/repository-connections/${encodeURIComponent(connectionId)}/import`,
{ providerRepositoryIds },
),
resolveCloneCredential: (repositoryId: string) =>
api.post<RepositoryCloneCredential>(
`/repositories/${encodeURIComponent(repositoryId)}/clone-credential`,
{},
),
listProjectRepositories: (projectId: string) =>
api.get<ProjectRepositoryEntry[]>(`/projects/${encodeURIComponent(projectId)}/repositories`),
attachProjectRepository: (projectId: string, repositoryId: string, displayOrder = 0) =>