#!/usr/bin/env node /** * Generates src/lib/last-updated-routes.js by scanning src/pages for .mdx files * and reading the last commit date for each from git. Used by Layout.jsx to * render an "Updated " line in the right rail. * * Skips src/pages/ipa/resources/ — those are auto-generated from the OpenAPI * spec, so their git date reflects generator runs, not real content edits. * * Run automatically with dev and build. */ import fs from 'fs' import path from 'path' import { fileURLToPath } from 'url' import { buildGitDateMap } from './git-dates.mjs' const __dirname = path.dirname(fileURLToPath(import.meta.url)) const ROOT = path.join(__dirname, '..') const PAGES_DIR = path.join(ROOT, 'src/pages') const OUT_PATH = path.join(ROOT, 'src/lib/last-updated-routes.mjs') const SKIP_PREFIX = 'ipa/resources' function findMdxRoutes(dir, basePath = '') { const entries = fs.readdirSync(dir, { withFileTypes: true }) const results = [] for (const e of entries) { const rel = basePath ? `${basePath}/${e.name}` : e.name if (e.isDirectory()) { if (rel === SKIP_PREFIX || rel.startsWith(`${SKIP_PREFIX}/`)) continue results.push(...findMdxRoutes(path.join(dir, e.name), rel)) } else if (e.name.endsWith('.mdx')) { const filePath = path.join(dir, e.name) const route = e.name === 'index.mdx' ? '/' + basePath : '/' + rel.replace(/\.mdx$/, '') results.push({ route, filePath }) } } return results } const entries = findMdxRoutes(PAGES_DIR) .filter((r) => r.route !== '/' && r.route !== '') .sort((a, b) => a.route.localeCompare(b.route)) const gitDates = buildGitDateMap() const map = {} for (const { route, filePath } of entries) { const date = gitDates.get(path.relative(ROOT, filePath)) if (date) map[route] = date } const content = `// Auto-generated by scripts/generate-last-updated.mjs – do not edit /** Last commit date (YYYY-MM-DD) keyed by Next.js router.pathname. */ export const LAST_UPDATED_BY_ROUTE = ${JSON.stringify(map, null, 2)}; ` fs.mkdirSync(path.dirname(OUT_PATH), { recursive: true }) fs.writeFileSync(OUT_PATH, content, 'utf8') console.log('Generated', OUT_PATH, 'with', Object.keys(map).length, 'dated routes') if (Object.keys(map).length === 0) { const msg = '[last-updated] no routes received a date, git history is unavailable or the clone is shallow' // Hard-fail only where full history is guaranteed (the GitHub workflow // checks out with fetch-depth: 0). Other CI environments like Vercel // shallow-clone by design, so there a missing map is expected: warn and // ship pages without "Updated" dates instead of breaking the deploy. if (process.env.GITHUB_ACTIONS) { console.error( `${msg}. Failing the build: the workflow checks out with fetch-depth: 0, so an empty map means something is broken.` ) process.exit(1) } console.warn(`${msg}. Pages will render without an "Updated" date.`) }