114 lines · 4.9 KB
import { env } from "cloudflare:workers";
import type { ReactNode } from "react";
import { featurePage } from "~/lib/marketing/features";
import { accountCardVersion, featureCardVersion, OG_PREFIX, repoCardVersion, siteCardVersion } from "~/lib/og";
import { enforceRateLimit, requestIp } from "../limits";
import { loadRepo } from "../repos";
import { AccountCard, FeatureCard, RepoCard, SiteCard } from "./cards";
import { accountCardData, avatarDataUri, repoCardData, repoCardVisible } from "./data";

/** Versioned URLs change whenever the card would, so they can sit in caches for two weeks. */
export const OG_VERSIONED_CACHE = "public, max-age=1209600";
/** Unversioned or stale URLs, and the generic card every hidden target gets, revalidate hourly. */
export const OG_FALLBACK_CACHE = "public, max-age=3600";
const CACHE_NAME = "og-cards";

type Card = { key: string; version: string; render: () => Promise<ReactNode> };

function host(): string {
  return new URL(env.PUBLIC_URL).host;
}

function siteCard(): Card {
  return { key: "site", version: siteCardVersion(), render: async () => <SiteCard host={host()} /> };
}

function decode(segment: string): string | null {
  try {
    return decodeURIComponent(segment);
  } catch {
    return null;
  }
}

/**
 * Resolves the card for a path, or null for the generic card. Every lookup reads only public data and never the
 * session, and every refusal (private, hidden, taken down, missing, malformed) collapses to the same null.
 */
async function resolveCard(pathname: string): Promise<Card | null> {
  const rest = pathname.slice(OG_PREFIX.length);
  if (!rest.endsWith(".png")) return null;