Files
vue-seo-layer/server/lib/routeReport.ts
Jakub Zych 3abc986f42 feat: route report and drift check at server start
- the module writes #seo-routes (static paths and route patterns) from the
  resolved pages; options seo.routeReport, seo.pagination and
  seo.htmlSitemap reach the public runtime config
- seo-route-report: POST /registry/routes once per process with the
  route-report token, one retry after 60 s on failure, nothing without a
  token, with the layer off or with routeReport false
- seo-drift: one "[vue-seo-layer] drift:" warning per mismatch between
  the CMS's site answer (URL patterns, pagination, HTML sitemap paths)
  and the build
- GET /api/__seo__/site and useSeoSite()
- smoke grammar routereport and log, fixture registry route, drift run
2026-11-04 11:49:21 +01:00

34 lines
1.5 KiB
TypeScript

// The route report (D-33): at server start the layer posts its static
// routes (#seo-routes, built from the pages) to the SEO plugin's
// POST /_seo/api/v1/registry/routes with the route-report token, so the
// CMS's page registry knows every frontend page. Pure helpers for the
// Nitro plugin server/plugins/seo-route-report.ts, so `node --test` drives
// them.
/** The plugin's limits: at most 2000 paths of at most 2048 bytes each. */
export const ROUTE_REPORT_MAX_ROUTES = 2000
export const ROUTE_REPORT_MAX_BYTES = 2048
/** The one retry after a failed report waits this long. */
export const ROUTE_REPORT_RETRY_MS = 60_000
/** The request body: the paths within the plugin's limits. */
export function routeReportBody(paths: readonly string[]): { routes: string[] } {
const routes = paths
.filter((p) => typeof p === 'string' && p.startsWith('/') && Buffer.byteLength(p, 'utf8') <= ROUTE_REPORT_MAX_BYTES)
.slice(0, ROUTE_REPORT_MAX_ROUTES)
return { routes }
}
/**
* What an answer means: sent (2xx), absent (404: a backend without the
* page registry, or with both tokens empty; never retried), refused (401 or
* 403: the token is wrong; never retried) or retry (no answer, or any other
* status: tried once more after ROUTE_REPORT_RETRY_MS).
*/
export function routeReportOutcome(status: number | null): 'sent' | 'absent' | 'refused' | 'retry' {
if (status !== null && status >= 200 && status < 300) return 'sent'
if (status === 404) return 'absent'
if (status === 401 || status === 403) return 'refused'
return 'retry'
}