refactor: address maintainer feedback on routing logic and env fallbacks

This commit is contained in:
2026-04-30 13:10:08 +05:30
committed by hodlbod
parent e380e4e3d6
commit faf1b02a2c
+126 -62
View File
@@ -2,9 +2,10 @@ import path from "node:path"
import {promises as fs} from "node:fs" import {promises as fs} from "node:fs"
import {fileURLToPath} from "node:url" import {fileURLToPath} from "node:url"
import "dotenv/config"
import {serve} from "@hono/node-server" import {serve} from "@hono/node-server"
import {serveStatic} from "@hono/node-server/serve-static" import {serveStatic} from "@hono/node-server/serve-static"
import {fetchRelay} from "@welshman/app" import {loadRelay} from "@welshman/app"
import {displayRelayUrl, normalizeRelayUrl} from "@welshman/util" import {displayRelayUrl, normalizeRelayUrl} from "@welshman/util"
import {load} from "cheerio" import {load} from "cheerio"
import {Hono} from "hono" import {Hono} from "hono"
@@ -26,15 +27,8 @@ try {
process.exit(1) process.exit(1)
} }
const TEMPLATE_DOCUMENT = load(TEMPLATE_HTML) const PLATFORM_NAME = process.env.VITE_PLATFORM_NAME
const DEFAULT_PLATFORM_NAME = const PLATFORM_DESCRIPTION = process.env.VITE_PLATFORM_DESCRIPTION
process.env.VITE_PLATFORM_NAME ||
TEMPLATE_DOCUMENT('meta[property="og:title"]').attr("content") ||
"Flotilla"
const DEFAULT_PLATFORM_DESCRIPTION =
process.env.VITE_PLATFORM_DESCRIPTION ||
TEMPLATE_DOCUMENT('meta[name="description"]').attr("content") ||
"Flotilla is nostr - for communities."
// Match client-side decode logic // Match client-side decode logic
const decodeRelay = url => { const decodeRelay = url => {
@@ -61,72 +55,142 @@ const requestUrlFromContext = context => {
return requestUrl return requestUrl
} }
const resolveMetadata = async requestUrl => { const fetchRelayMeta = async relayUrl => {
const pathname = requestUrl.pathname if (!relayUrl) return undefined
let relayParam = undefined try {
return await loadRelay(normalizeRelayUrl(relayUrl))
// Match /join?r=... } catch (err) {
if (pathname === "/join" || pathname === "/join/") { console.error(`Failed to fetch relay metadata for ${relayUrl}:`, err)
relayParam = requestUrl.searchParams.get("r")
}
// Match /spaces/:relay/...
else if (pathname.startsWith("/spaces/")) {
const parts = pathname.split("/").filter(Boolean)
if (parts.length >= 2) {
relayParam = decodeRelay(parts[1])
}
}
if (!relayParam) {
return undefined return undefined
} }
}
try { const buildDefaultImage = requestUrl => {
// Note: fetchRelay from @welshman/app handles the ws->http conversion and caching return new URL("/maskable-icon-512x512.png", requestUrl.origin).toString()
const relayMetadata = await fetchRelay(normalizeRelayUrl(relayParam)) }
if (!relayMetadata) { const getMetadataForInvite = async (url, match) => {
return undefined const relayParam = url.searchParams.get("r")
} if (!relayParam) return undefined
const relayDisplay = displayRelayUrl(relayParam) const relayMetadata = await fetchRelayMeta(relayParam)
const spaceName = relayMetadata.name if (!relayMetadata) return undefined
const relayDescription = relayMetadata.description
const title = spaceName const relayDisplay = displayRelayUrl(relayParam)
? `Invite to ${spaceName} on ${DEFAULT_PLATFORM_NAME}` const spaceName = relayMetadata.name
: `Invite to a Space on ${DEFAULT_PLATFORM_NAME}` const relayDescription = relayMetadata.description
const parts = [] const title = spaceName
if (spaceName) { ? `Invite to ${spaceName} on ${PLATFORM_NAME}`
parts.push(`You are invited to join ${spaceName} on ${DEFAULT_PLATFORM_NAME}.`) : `Invite to a Space on ${PLATFORM_NAME}`
} else {
parts.push(`You are invited to join a space on ${DEFAULT_PLATFORM_NAME}.`)
}
if (relayDisplay) parts.push(`Relay: ${relayDisplay}.`) const parts = []
if (relayDescription) parts.push(relayDescription) if (spaceName) {
else parts.push(DEFAULT_PLATFORM_DESCRIPTION) parts.push(`You are invited to join ${spaceName} on ${PLATFORM_NAME}.`)
} else {
parts.push(`You are invited to join a space on ${PLATFORM_NAME}.`)
}
const description = parts.join(" ") if (relayDisplay) parts.push(`Relay: ${relayDisplay}.`)
const image = if (relayDescription) parts.push(relayDescription)
else parts.push(PLATFORM_DESCRIPTION)
const description = parts.join(" ")
const image =
relayMetadata.icon ||
relayMetadata.picture ||
relayMetadata.image ||
buildDefaultImage(url)
return {
title,
description,
image,
url: url.toString(),
site: url.origin,
}
}
const getMetadataForSpace = async (url, match) => {
const relayParam = decodeRelay(match[1])
if (!relayParam) return undefined
const relayMetadata = await fetchRelayMeta(relayParam)
if (!relayMetadata) return undefined
const spaceName = relayMetadata.name || displayRelayUrl(relayParam)
return {
title: `${spaceName} on ${PLATFORM_NAME}`,
description: relayMetadata.description || PLATFORM_DESCRIPTION,
image:
relayMetadata.icon || relayMetadata.icon ||
relayMetadata.picture || relayMetadata.picture ||
relayMetadata.image || relayMetadata.image ||
new URL("/maskable-icon-512x512.png", requestUrl.origin).toString() buildDefaultImage(url),
url: url.toString(),
return { site: url.origin,
title,
description,
image,
url: requestUrl.toString(),
site: requestUrl.origin,
}
} catch (err) {
return undefined
} }
} }
const getMetadataForSpaceSection = async (url, match) => {
const spaceMeta = await getMetadataForSpace(url, match)
if (!spaceMeta) return undefined
const section = match[2]
const sectionName = section.charAt(0).toUpperCase() + section.slice(1)
spaceMeta.title = `${sectionName} on ${spaceMeta.title}`
return spaceMeta
}
const getMetadataForSpaceItem = async (url, match) => {
const spaceMeta = await getMetadataForSpace(url, match)
if (!spaceMeta) return undefined
const section = match[2]
let itemType = "Item"
if (section === "calendar") itemType = "Event"
if (section === "threads") itemType = "Thread"
if (section === "polls") itemType = "Poll"
if (section === "goals") itemType = "Goal"
if (section === "classifieds") itemType = "Listing"
spaceMeta.title = `${itemType} on ${spaceMeta.title}`
return spaceMeta
}
const getMetadataForRoom = async (url, match) => {
const spaceMeta = await getMetadataForSpace(url, match)
if (!spaceMeta) return undefined
// Room metadata requires fetching from Nostr, which can be added later.
spaceMeta.title = `Room on ${spaceMeta.title}`
return spaceMeta
}
const routes = [
[/^\/join\/?$/, getMetadataForInvite],
[/^\/spaces\/([^/]+)\/(calendar|chat|threads|polls|goals|classifieds|recent)\/?$/, getMetadataForSpaceSection],
[/^\/spaces\/([^/]+)\/(calendar|threads|polls|goals|classifieds)\/([^/]+)\/?$/, getMetadataForSpaceItem],
[/^\/spaces\/([^/]+)\/([^/]+)\/?$/, getMetadataForRoom],
[/^\/spaces\/([^/]+)\/?$/, getMetadataForSpace],
]
const getMetadataForRoute = async url => {
for (const [regex, getMetadata] of routes) {
const match = url.pathname.match(regex)
if (match) {
try {
return await getMetadata(url, match)
} catch (err) {
console.error(`Error generating metadata for route ${url.pathname}:`, err)
return undefined
}
}
}
return undefined
}
const injectMeta = metadata => { const injectMeta = metadata => {
const $ = load(TEMPLATE_HTML) const $ = load(TEMPLATE_HTML)
@@ -196,7 +260,7 @@ app.get("*", async context => {
return context.text("Not found", 404) return context.text("Not found", 404)
} }
const metadata = await resolveMetadata(requestUrl) const metadata = await getMetadataForRoute(requestUrl)
const html = metadata ? injectMeta(metadata) : TEMPLATE_HTML const html = metadata ? injectMeta(metadata) : TEMPLATE_HTML
return context.html(html, 200, { return context.html(html, 200, {