Skip to content
66 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
30export type Failure = { code: FailureCode; message: string };
31
32export type Result<T> = { ok: true; value: T } | { ok: false; error: Failure };
33
34export function ok<T>(value: T): Result<T> {
35 return { ok: true, value };
36}
37
38export function fail(code: FailureCode, message: string): Result<never> {
39 return { ok: false, error: { code, message } };
40}
41
42const HTTP_STATUS: Record<FailureCode, number> = {
43 not_found: 404,
44 forbidden: 403,
45 unauthenticated: 401,
46 conflict: 409,
47 invalid: 422,
48 payment_required: 402,
49 not_paid: 402,
50 trial_used: 402,
51 limit: 402,
52 paused: 409,
53 oss_pool_empty: 402,
54 reauth_required: 403,
55 unavailable: 503,
56};
57
58export function httpStatus(failure: Failure): number {
59 return HTTP_STATUS[failure.code];
60}
61
62/** Returned when an account with an unconfirmed email tries to change something. */
63export const UNVERIFIED = fail(
64 "forbidden",
65 "Confirm your email address first. Check your inbox, or resend the link from the banner on g1t.sh.",
66);