File
Blob: src/worker/lib/site-public-url.ts
| 1 | import { slugify } from "@/lib/slugify"; |
| 2 | |
| 3 | export interface PublicUrlSiteRow { |
| 4 | slug: string; |
| 5 | published_at: string | null; |
| 6 | home_page_id: string | null; |
| 7 | } |
| 8 | |
| 9 | function isLocalSitesDomain(baseDomain: string): boolean { |
| 10 | return baseDomain === "localhost" || baseDomain.endsWith(".localhost"); |
| 11 | } |
| 12 | |
| 13 | /** |
| 14 | * Construct the public URL that a viewer should land on for a published page. |
| 15 | * |
| 16 | * Production domains are real hostnames served over HTTPS without a port. |
| 17 | * Local dev (e.g. `PUBLISHED_SITE_DOMAIN=bland.localhost`) derives the |
| 18 | * protocol and port from the request so that URLs copied out of the dialog |
| 19 | * point at the running Vite dev server rather than `https://...localhost/`. |
| 20 | */ |
| 21 | export function buildSitePublicUrl( |
| 22 | site: PublicUrlSiteRow, |
| 23 | baseDomain: string | null, |
| 24 | pageId: string, |
| 25 | pageTitle: string, |
| 26 | requestUrl: URL, |
| 27 | ): string | null { |
| 28 | if (!site.published_at || !baseDomain) return null; |
| 29 | const local = isLocalSitesDomain(baseDomain); |
| 30 | const protocol = local ? requestUrl.protocol : "https:"; |
| 31 | const port = local && requestUrl.port ? `:${requestUrl.port}` : ""; |
| 32 | const origin = `${protocol}//${site.slug}.${baseDomain}${port}`; |
| 33 | if (site.home_page_id === pageId) return `${origin}/`; |
| 34 | return `${origin}${buildSitePagePath(pageId, pageTitle)}`; |
| 35 | } |
| 36 | |
| 37 | export function buildSitePagePath(pageId: string, pageTitle: string): string { |
| 38 | const slugPart = slugify(pageTitle) || "untitled"; |
| 39 | return `/${slugPart}-${pageId.toLowerCase()}`; |
| 40 | } |