g1t/packages/contracts/src/projects.ts

99 lines4,205 bytesCodeBlame
1import type { User, Viewer } from "./identity";
2import type { RepoPath } from "./repos";
3import type { Result } from "./result";
4
5/**
6 * Projects: the thing a workspace builds and runs. A project has exactly
7 * one source, where its code lives; everything about running it
8 * (deployments, environments, domains, secrets and variables) belongs to
9 * the project, while branches, pull requests and review stay with the
10 * repository. One repository may carry several projects, each from its own
11 * root directory. Every repository on g1t gets a project of its own name.
12 */
13
14/** Where a project's code lives. */
15export type ProjectSource =
16 /** A repository hosted on g1t. */
17 | { kind: "hosted"; repoId: string; repo: RepoPath; rootDir: string; defaultBranch: string }
18 /** Mirrored from another host; coming next. */
19 | { kind: "mirror"; provider: "github" | "gitlab" | "bitbucket"; url: string; rootDir: string };
20
21export type Project = {
22 id: string;
23 /** The workspace's slug. */
24 workspace: string;
25 /** Unique in its workspace; the project's address is `g1t.sh/<workspace>/<slug>`. */
26 slug: string;
27 name: string;
28 /** The project's own description, or its repository's while it has none. */
29 description: string | null;
30 /** Whether `description` is its repository's, following it as it changes. */
31 descriptionInherited: boolean;
32 source: ProjectSource;
33 /** Whether its repository is private: only people with a role on it can see it. */
34 private: boolean;
35 /** Whether its repository is archived: read-only, kept for reference. */
36 archived: boolean;
37 /** Whether it is the project its repository's workflows read secrets from. */
38 primary: boolean;
39 createdBy: string;
40 /** RFC 3339. */
41 createdAt: string;
42 updatedAt: string;
43};
44
45export type NewProject = {
46 name: string;
47 description?: string | null;
48 /** The hosted repository it builds from. */
49 repo: RepoPath;
50 /** Where in the repository it lives; empty for the whole repository. */
51 rootDir?: string;
52};
53
54/** One end of a dependency, as a page shows it. */
55export type DependencyLink = {
56 slug: string;
57 name: string;
58 /** The variable carrying the other project's address, such as `API_URL`. */
59 as: string | null;
60 /** Declared on the site, or in the project's `.g1t/project.yml`. */
61 source: "ui" | "file";
62};
63
64/** What a project uses, and what uses it. */
65export type Dependencies = { dependsOn: DependencyLink[]; usedBy: DependencyLink[] };
66
67/** A project's dependencies by id, for services. */
68export type ProjectGraph = {
69 dependsOn: { id: string; slug: string; workspace: string; as: string | null }[];
70 usedBy: { id: string; slug: string; workspace: string; as: string | null }[];
71};
72
73export interface ProjectsApi {
74 /** A workspace's projects, by name. Members, or anyone for public repositories. */
75 list(workspace: string, viewer: Viewer): Promise<Result<Project[]>>;
76 get(workspace: string, slug: string, viewer: Viewer): Promise<Result<Project>>;
77 /** The projects built from a repository, its primary one first. For services. */
78 byRepo(repoId: string): Promise<Project[]>;
79 /** Members only. */
80 create(actor: User, workspace: string, input: NewProject): Promise<Result<Project>>;
81 /** Members only. A null or blank description goes back to the repository's. */
82 update(
83 actor: User,
84 workspace: string,
85 slug: string,
86 changes: { name?: string; description?: string | null; rootDir?: string },
87 ): Promise<Result<Project>>;
88 /** What a project uses and what uses it. Whoever may see the project. */
89 dependencies(workspace: string, slug: string, viewer: Viewer): Promise<Result<Dependencies>>;
90 /**
91 * `slug` uses `on`, with `as` the variable that carries `on`'s address.
92 * Members only; refused if it would make a cycle.
93 */
94 addDependency(actor: User, workspace: string, slug: string, on: string, as: string | null): Promise<Result<Dependencies>>;
95 /** Members only. A dependency from `.g1t/project.yml` is changed there. */
96 removeDependency(actor: User, workspace: string, slug: string, on: string): Promise<Result<Dependencies>>;
97 /** For services: a project's dependencies by id. */
98 graph(projectId: string): Promise<ProjectGraph>;
99}