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
This commit is contained in:
@@ -4,11 +4,14 @@
|
||||
// GET /_seo/api/v1/resolve?url=… the answer for that exact url from
|
||||
// <dir>/seo/resolve.json, then
|
||||
// <dir>/resolve.json, else not_found
|
||||
// GET /_seo/api/v1/site <dir>/seo/site.json (404 without the
|
||||
// file or with { site: false }: an
|
||||
// older backend)
|
||||
// GET /_seo/api/v1/site <dir>/seo/site.json, or <dir>/seo/<siteFile>
|
||||
// (404 without the file or with
|
||||
// { site: false }: an older backend)
|
||||
// POST /_seo/api/v1/notfound 204 with `Authorization: Bearer <token>`,
|
||||
// 401 with another token, 404 without one
|
||||
// POST /_seo/api/v1/registry/routes the route report: the same token rules;
|
||||
// 404 with { site: false } (an older
|
||||
// backend has no page registry)
|
||||
// GET /_seo/api/v1/verification/<name> <dir>/verification/<name> or
|
||||
// <dir>/seo/verification/<name>, else 404
|
||||
// GET /robots.txt, /llms.txt, <dir>/seo/root/<name>, else 404
|
||||
@@ -52,10 +55,10 @@ function contentType(name) {
|
||||
|
||||
/**
|
||||
* Starts the fixture API on 127.0.0.1.
|
||||
* @param {{ dir: string, port?: number, token?: string, site?: boolean }} opts
|
||||
* @param {{ dir: string, port?: number, token?: string, site?: boolean, siteFile?: string }} opts
|
||||
* @returns {Promise<FixtureApi>}
|
||||
*/
|
||||
export function startFixtureApi({ dir, port = 0, token = FIXTURE_NOTFOUND_TOKEN, site = true }) {
|
||||
export function startFixtureApi({ dir, port = 0, token = FIXTURE_NOTFOUND_TOKEN, site = true, siteFile = 'site.json' }) {
|
||||
/** @type {FixtureRequest[]} */
|
||||
const requests = []
|
||||
/** @type {Record<string, unknown>} */
|
||||
@@ -64,7 +67,7 @@ export function startFixtureApi({ dir, port = 0, token = FIXTURE_NOTFOUND_TOKEN,
|
||||
let siteAnswer = null
|
||||
const load = () => {
|
||||
answers = { ...(readJson(join(dir, 'resolve.json')) ?? {}), ...(readJson(join(dir, 'seo', 'resolve.json')) ?? {}) }
|
||||
siteAnswer = site ? readJson(join(dir, 'seo', 'site.json')) : null
|
||||
siteAnswer = site ? readJson(join(dir, 'seo', siteFile)) : null
|
||||
}
|
||||
load()
|
||||
|
||||
@@ -103,6 +106,10 @@ export function startFixtureApi({ dir, port = 0, token = FIXTURE_NOTFOUND_TOKEN,
|
||||
if (!token) return { status: 404, body: { error: 'not_found' } }
|
||||
return req.headers.authorization === `Bearer ${token}` ? { status: 204 } : { status: 401, body: { error: 'unauthorized' } }
|
||||
}
|
||||
if (path === '/registry/routes' && req.method === 'POST') {
|
||||
if (!site || !token) return { status: 404, body: { error: 'not_found' } }
|
||||
return req.headers.authorization === `Bearer ${token}` ? { status: 204 } : { status: 401, body: { error: 'unauthorized' } }
|
||||
}
|
||||
const v = /^\/verification\/([A-Za-z0-9._-]+)$/.exec(path)
|
||||
if (v && req.method === 'GET') {
|
||||
for (const file of [join(dir, 'verification', v[1]), join(dir, 'seo', 'verification', v[1])]) {
|
||||
|
||||
Reference in New Issue
Block a user