g1t/services/pages/src/route.ts
Pick any line to see why it is the way it is: the commit, the pull request and issue it came from, and what the agent was thinking.
| Agents and memory, checks and conflicts, profiles, slug renames, custom domains | 1 | /** |
| 2 | * What a request's host is: g1t.page itself, an app's address on it, the | |
| 3 | * hostname custom domains point at, or a custom domain. | |
| 4 | * | |
| 5 | * Kept free of imports so its tests run on Node as they are. | |
| 6 | */ | |
| 7 | ||
| 8 | export const DOMAIN = "g1t.page"; | |
| 9 | /** Where custom domains point (the Cloudflare for SaaS fallback origin). */ | |
| 10 | export const FALLBACK = `domains.${DOMAIN}`; | |
| 11 | ||
| 12 | export type Route = | |
| 13 | | { kind: "home" } | |
| 14 | | { kind: "fallback" } | |
| 15 | | { kind: "app"; label: string } | |
| 16 | | { kind: "custom"; hostname: string } | |
| 17 | | { kind: "invalid" }; | |
| 18 | ||
| 19 | const LABEL = /^[a-z0-9-]{1,63}$/; | |
| 20 | const HOST = /^(?!-)[a-z0-9-]{1,63}(?<!-)(\.(?!-)[a-z0-9-]{1,63}(?<!-))+$/; | |
| 21 | ||
| 22 | export function route(rawHost: string): Route { | |
| 23 | const host = rawHost.toLowerCase().replace(/\.$/, ""); | |
| 24 | if (host === DOMAIN) return { kind: "home" }; | |
| 25 | if (host === FALLBACK) return { kind: "fallback" }; | |
| 26 | if (host.endsWith(`.${DOMAIN}`)) { | |
| 27 | const label = host.slice(0, -DOMAIN.length - 1); | |
| 28 | return LABEL.test(label) ? { kind: "app", label } : { kind: "invalid" }; | |
| 29 | } | |
| 30 | return HOST.test(host) && host.length <= 253 ? { kind: "custom", hostname: host } : { kind: "invalid" }; | |
| 31 | } | |
| 32 | ||
| 33 | /** What the deployments service writes under a custom hostname. */ | |
| 34 | export type DomainEntry = { script: string; redirect: string | null; project?: string }; | |
| 35 | ||
| 36 | /** Reads a stored entry, or null if it is not one. */ | |
| 37 | export function parseEntry(value: unknown): DomainEntry | null { | |
| 38 | if (!value || typeof value !== "object") return null; | |
| 39 | const entry = value as Record<string, unknown>; | |
| 40 | if (typeof entry.script !== "string" || !LABEL.test(entry.script)) return null; | |
| 41 | const redirect = typeof entry.redirect === "string" && HOST.test(entry.redirect) ? entry.redirect : null; | |
| 42 | return { script: entry.script, redirect }; | |
| 43 | } | |
| 44 | ||
| 45 | /** The same path and query on `target`, over https. */ | |
| 46 | export function redirectTo(requestUrl: string, target: string): string { | |
| 47 | const url = new URL(requestUrl); | |
| 48 | return `https://${target}${url.pathname}${url.search}`; | |
| 49 | } |