| 1 | import { useRouteLoaderData } from "react-router"; |
| 2 | |
| 3 | /** |
| 4 | * Where this g1t lives: the site, the REST API, the MCP server and the |
| 5 | * social-card service. g1t.sh uses the defaults below; a self-hosted g1t |
| 6 | * sets its own (app/lib/addresses.server.ts reads them), and the root |
| 7 | * loader hands them to every page. |
| 8 | */ |
| 9 | export type Addresses = { |
| 10 | /** The site's origin, such as `https://g1t.sh`. Git remotes are under it. */ |
| 11 | site: string; |
| 12 | /** The REST API's origin, which is also the OAuth issuer. */ |
| 13 | api: string; |
| 14 | /** The MCP server's URL, as agents are told to add it. */ |
| 15 | mcp: string; |
| 16 | /** The social-card image service's origin, or null when there is none. */ |
| 17 | og: string | null; |
| 18 | }; |
| 19 | |
| 20 | export const HOSTED_ADDRESSES: Addresses = { |
| 21 | site: "https://g1t.sh", |
| 22 | api: "https://api.g1t.sh", |
| 23 | mcp: "https://mcp.g1t.sh", |
| 24 | og: "https://og.g1t.sh", |
| 25 | }; |
| 26 | |
| 27 | /** The Worker settings the addresses come from; every one optional. */ |
| 28 | export type AddressSettings = { SITE_URL?: string; API_URL?: string; MCP_URL?: string; OG_URL?: string }; |
| 29 | |
| 30 | const trim = (value: string) => value.trim().replace(/\/+$/, ""); |
| 31 | |
| 32 | /** |
| 33 | * The addresses from the Worker's settings. An unset or empty setting is |
| 34 | * g1t.sh's address, except `OG_URL`: set to an empty string, it means there |
| 35 | * is no card service, and pages carry no image tags. |
| 36 | */ |
| 37 | export function addressesFor(settings: AddressSettings): Addresses { |
| 38 | const pick = (value: string | undefined, fallback: string) => (value ? trim(value) : "") || fallback; |
| 39 | return { |
| 40 | site: pick(settings.SITE_URL, HOSTED_ADDRESSES.site), |
| 41 | api: pick(settings.API_URL, HOSTED_ADDRESSES.api), |
| 42 | mcp: pick(settings.MCP_URL, HOSTED_ADDRESSES.mcp), |
| 43 | og: settings.OG_URL === undefined ? HOSTED_ADDRESSES.og : trim(settings.OG_URL) || null, |
| 44 | }; |
| 45 | } |
| 46 | |
| 47 | /** The addresses in the root loader's data, or g1t.sh's when it has none. */ |
| 48 | export function addressesFrom(rootData: unknown): Addresses { |
| 49 | return (rootData as { addresses?: Addresses } | null | undefined)?.addresses ?? HOSTED_ADDRESSES; |
| 50 | } |
| 51 | |
| 52 | /** This g1t's addresses, from the root loader. */ |
| 53 | export function useAddresses(): Addresses { |
| 54 | return addressesFrom(useRouteLoaderData("root")); |
| 55 | } |
| 56 | |
| 57 | /** The HTTPS clone address of a repository, from its `owner/name`. */ |
| 58 | export function cloneUrl(addresses: Pick<Addresses, "site">, path: string): string { |
| 59 | return `${addresses.site}/${path.replace(/^\/+/, "")}.git`; |
| 60 | } |