Files
SnapOtter/apps/landing/scripts/generate-redirects.mjs
T
SnapOtterandGitHub 84c18eb82c test(landing): guard _redirects against catalog drift (#575)
Exports a pure buildRedirects() from generate-redirects.mjs and adds a unit test asserting the committed apps/landing/public/_redirects matches it, so tool additions can't silently leave the generated redirects stale (see #573).
2026-07-19 16:36:33 +08:00

38 lines
1.6 KiB
JavaScript

// Generates public/_redirects (Cloudflare Pages) mapping old flat tool URLs
// (/tools/<id>) to the new section-nested URLs (/tools/<section>/<id>/).
// Both slash variants are emitted because Cloudflare matches paths exactly.
//
// buildRedirects() is exported (side-effect-free) so a drift test can assert the
// committed public/_redirects still matches the catalog; the file is only
// written when this script runs directly (the landing prebuild).
import { writeFileSync } from "node:fs";
import { fileURLToPath, pathToFileURL } from "node:url";
import { TOOLS, toolSection } from "@snapotter/shared";
/** Build the full _redirects file contents from the shared TOOLS catalog. */
export function buildRedirects() {
const lines = ["# Generated by scripts/generate-redirects.mjs -- do not edit by hand"];
for (const tool of TOOLS) {
const to = `/tools/${toolSection(tool)}/${tool.id}/`;
lines.push(`/tools/${tool.id}/ ${to} 301`);
lines.push(`/tools/${tool.id} ${to} 301`);
}
return `${lines.join("\n")}\n`;
}
/** Absolute path to the generated file. */
export const REDIRECTS_PATH = fileURLToPath(new URL("../public/_redirects", import.meta.url));
function writeRedirects() {
const content = buildRedirects();
writeFileSync(REDIRECTS_PATH, content);
const redirectLines = content.trimEnd().split("\n").length - 1;
console.log(`wrote ${REDIRECTS_PATH} (${TOOLS.length} tools, ${redirectLines} redirect lines)`);
}
// Write only when executed directly (prebuild); importing for the drift test
// stays side-effect-free.
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
writeRedirects();
}