- 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
41 lines
1.8 KiB
TypeScript
41 lines
1.8 KiB
TypeScript
// The startup drift check (D-20c): compares the CMS's content-type URL
|
|
// patterns, pagination form and segments and HTML-sitemap paths (the site
|
|
// answer, GET <apiBase>/site) with the build's routes (#seo-routes) and the
|
|
// layer's seo.pagination and seo.htmlSitemap options, and logs one
|
|
// "[vue-seo-layer] drift: ..." warning per mismatch. It runs once after the
|
|
// plugin returns, never blocks the start and never fails it; a backend
|
|
// without a site answer (before SEO v0.2.0) or one that does not answer is
|
|
// skipped. Off with the layer off or while prerendering.
|
|
|
|
import { routePatterns } from '#seo-routes'
|
|
import { seoServerConfig } from '../lib/config.ts'
|
|
import { driftWarnings, type LayerPaginationOption } from '../lib/drift.ts'
|
|
import { siteAnswer } from '../lib/site.ts'
|
|
|
|
export default defineNitroPlugin(() => {
|
|
if (import.meta.prerender) return
|
|
const config = useRuntimeConfig()
|
|
const cfg = seoServerConfig(config)
|
|
if (!cfg.enabled) return
|
|
const pub = ((config.public as Record<string, unknown>).seo ?? {}) as {
|
|
pagination?: LayerPaginationOption
|
|
htmlSitemap?: { paths?: Record<string, string> } | false
|
|
}
|
|
const pagination: LayerPaginationOption = {
|
|
form: pub.pagination?.form === 'path' ? 'path' : 'query',
|
|
param: pub.pagination?.param || 'page',
|
|
segments: { ...(pub.pagination?.segments ?? {}) },
|
|
}
|
|
const htmlSitemap = pub.htmlSitemap === false || (pub.htmlSitemap as unknown) === 'false' ? false : { ...(pub.htmlSitemap?.paths ?? {}) }
|
|
|
|
setTimeout(async () => {
|
|
try {
|
|
const state = await siteAnswer(cfg, {})
|
|
if (state.state !== 'ok') return
|
|
for (const warning of driftWarnings({ site: state.site, routes: routePatterns, pagination, htmlSitemap })) console.warn(warning)
|
|
} catch (err) {
|
|
console.warn('[vue-seo-layer] drift check failed:', (err as Error)?.message ?? err)
|
|
}
|
|
}, 0).unref?.()
|
|
})
|