Skip to content

Where people and agents ship software together. The open-source git platform for the whole job: issues, agents, checks and deploys to the edge.

72 linesCodeBlameRaw
1/**
2 * Expected failures cross service boundaries as values, not exceptions:
3 * Worker RPC does not preserve error classes, and callers should have to
4 * handle them.
5 */
6export type FailureCode =
7 | "not_found"
8 | "forbidden"
9 | "unauthenticated"
10 | "conflict"
11 | "invalid"
12 /** The workspace has to pay before this can happen. */
13 | "payment_required"
14 /** Billing's refusals to start compute (`reserve`); each message says what to do. */
15 /** No plan, and no trial or pool that pays for this work: a card check or the g1t plan is needed. */
16 | "not_paid"
17 /** The workspace's one trial is spent. */
18 | "trial_used"
19 /** The spend limit or g1t's ceiling is reached. */
20 | "limit"
21 /** Compute is paused: a spend spike waiting for an owner, or a hold. */
22 | "paused"
23 /** This month's open-source pool, or the repository's share of it, is spent. */
24 | "oss_pool_empty"
25 /** A sensitive change needs a recent sign-in or the password again. */
26 | "reauth_required"
27 /** Another host g1t depends on for this did not answer. */
28 | "unavailable"
29 /** What was sent is larger than this takes, such as an attachment over 10 MB. */
30 | "too_large"
31 /** What was sent is not of a type this takes, such as an attachment that is not an image. */
32 | "unsupported_type";
33
34export type Failure = { code: FailureCode; message: string };
35
36export type Result<T> = { ok: true; value: T } | { ok: false; error: Failure };
37
38export function ok<T>(value: T): Result<T> {
39 return { ok: true, value };
40}
41
42export function fail(code: FailureCode, message: string): Result<never> {
43 return { ok: false, error: { code, message } };
44}
45
46const HTTP_STATUS: Record<FailureCode, number> = {
47 not_found: 404,
48 forbidden: 403,
49 unauthenticated: 401,
50 conflict: 409,
51 invalid: 422,
52 payment_required: 402,
53 not_paid: 402,
54 trial_used: 402,
55 limit: 402,
56 paused: 409,
57 oss_pool_empty: 402,
58 reauth_required: 403,
59 unavailable: 503,
60 too_large: 413,
61 unsupported_type: 415,
62};
63
64export function httpStatus(failure: Failure): number {
65 return HTTP_STATUS[failure.code];
66}
67
68/** Returned when an account with an unconfirmed email tries to change something. */
69export const UNVERIFIED = fail(
70 "forbidden",
71 "Confirm your email address first. Check your inbox, or resend the link from the banner on g1t.sh.",
72);