a tool for shared writing and social publishing
1import { AtUri } from "@atproto/syntax";
2import { PubLeafletPublication } from "lexicons/api";
3import { isProductionDomain } from "src/utils/isProductionDeployment";
4import { Json } from "supabase/database.types";
5import {
6 normalizePublicationRecord,
7 isLeafletPublication,
8 type NormalizedDocument,
9 type NormalizedPublication,
10} from "src/utils/normalizeRecords";
11
12type PublicationInput =
13 | { uri: string; record: Json | NormalizedPublication | null }
14 | { uri: string; record: unknown };
15
16/**
17 * Gets the public URL for a publication.
18 * Works with both pub.leaflet.publication and site.standard.publication records.
19 */
20export function getPublicationURL(pub: PublicationInput): string {
21 const normalized = normalizePublicationRecord(pub.record);
22
23 // If we have a normalized record with a URL (site.standard format), use it
24 if (normalized?.url) {
25 return normalized.url;
26 }
27
28 // Fall back to checking raw record for legacy base_path
29 if (
30 isLeafletPublication(pub.record) &&
31 pub.record.base_path &&
32 isProductionDomain()
33 ) {
34 return `https://${pub.record.base_path}`;
35 }
36
37 return getBasePublicationURL(pub);
38}
39
40export function getBasePublicationURL(pub: PublicationInput): string {
41 const normalized = normalizePublicationRecord(pub.record);
42 const aturi = new AtUri(pub.uri);
43
44 //use rkey, fallback to name
45 const name = aturi.rkey || normalized?.name;
46 return `/lish/${aturi.host}/${encodeURIComponent(name || "")}`;
47}
48
49/**
50 * Gets the full URL for a document.
51 * Always appends the document's path property.
52 */
53export function getDocumentURL(
54 doc: NormalizedDocument,
55 docUri: string,
56 publication?: PublicationInput | NormalizedPublication | null,
57): string {
58 let path = doc.path || "/" + new AtUri(docUri).rkey;
59 if (path[0] !== "/") path = "/" + path;
60
61 if (!publication) {
62 return doc.site + path;
63 }
64
65 // Already-normalized publications: use URL directly
66 if (
67 (publication as NormalizedPublication).$type ===
68 "site.standard.publication"
69 ) {
70 return ((publication as NormalizedPublication).url || doc.site) + path;
71 }
72
73 // Raw publication input: delegate to getPublicationURL for full resolution
74 return getPublicationURL(publication as PublicationInput) + path;
75}