2.3 KiB
2.3 KiB
routes/public-routes.ts
Purpose
Builds the public (no-auth) Hono route tree that the plugin mounts under the configured routePrefix. The two endpoints exposed here are the entrypoints used by edge / SSR consumers that haven't yet authenticated — domain resolution drives multi-tenant routing decisions at request ingress, and the public-info endpoint surfaces a santised view of the site (theme + feature flags) so client bundles can render branded shells without leaking push config or secrets.
Routes are wired through @hono/zod-openapi so the OpenAPI document the host app exposes is automatically populated from the same Zod schemas the service layer validates against.
Features
GET /sites/resolve/{domain}— resolves a domain to a site + organization envelope.GET /sites/{id}/public— returns theSitePublicInfoprojection.- Both routes leverage the canonical
SiteSchema/SitePublicInfoSchemafor OpenAPI typing. - Failures bubble up as
SiteErrorso the host-app error middleware can map them to RFC 7807 / structured envelopes consistently with other plugins.
Usage: Basic
import { createPublicSiteRoutes } from "@suaveplan/api-plugin-site/routes/public-routes";
const publicRouter = createPublicSiteRoutes({ siteService, domainResolver });
app.route("/api", publicRouter);
Usage: Advanced
// Mount under a custom prefix and layer additional middleware.
const publicRouter = createPublicSiteRoutes({ siteService, domainResolver });
app.use("/v1", rateLimitMiddleware);
app.route("/v1", publicRouter);
API Reference
interface PublicSiteRoutesDeps—siteService,domainResolver.createPublicSiteRoutes(deps: PublicSiteRoutesDeps): OpenAPIHono.
Implementation Notes
- The resolve route always returns 200 with
success: falseon miss — this mirrors the upstream contract so an existing consumer's redirect logic does not have to swap between 200 and 404. - The public-info route DOES throw
SITE.SITE_NOT_FOUNDon miss, because the route is the integration boundary between "lookup" and "render" — a 404 here is the conventional signal to the upstream caller. - The conditional spread (
...(site.slug !== undefined && {...})) keeps the JSON payload tight by omitting absent optionals rather than emittingnull.