Skip to content
44 linesCodeBlameRaw
1import type { AccessToken, User, Viewer } from "@g1t/contracts";
2import { data } from "react-router";
3
4import type { WorkspaceChoice } from "../components/token-form";
5import { identity, repos } from "./services.server";
6import { unwrap } from "./session.server";
7
8/** Each workspace you belong to, with its rules for tokens and the repositories you can choose from. */
9export async function workspaceChoices(user: User): Promise<WorkspaceChoice[]> {
10 return Promise.all(
11 (user.workspaces ?? []).map(async (membership): Promise<WorkspaceChoice> => {
12 const [policy, listed] = await Promise.all([
13 identity.getTokenPolicy(membership.slug, user),
14 repos.list(user, { namespace: membership.slug }).catch(() => []),
15 ]);
16 return {
17 slug: membership.slug,
18 owner: membership.role === "owner",
19 policy: policy.ok ? policy.value : null,
20 repos: listed.map((repo) => `${repo.namespace}/${repo.name}`).sort(),
21 };
22 }),
23 );
24}
25
26/** A workspace's repositories, as `owner/name`, for choosing a token's. */
27export async function workspaceRepos(viewer: Viewer, slug: string): Promise<string[]> {
28 const listed = await repos.list(viewer, { namespace: slug }).catch(() => []);
29 return listed.map((repo) => `${repo.namespace}/${repo.name}`).sort();
30}
31
32/** One of your own tokens, or a 404. */
33export async function personalToken(user: User, id: string): Promise<AccessToken> {
34 const token = (await identity.listAccessTokens(user)).find((token) => token.id === id);
35 if (!token) throw data("No such token.", { status: 404 });
36 return token;
37}
38
39/** One of a workspace's own tokens, or a 404. */
40export async function workspaceToken(viewer: Viewer, slug: string, id: string): Promise<AccessToken> {
41 const token = unwrap(await identity.listWorkspaceTokens(slug, viewer)).find((token) => token.id === id);
42 if (!token) throw data("No such token.", { status: 404 });
43 return token;
44}