@lownoise-studio/rendershield 0.1.6 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,32 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ### Added
11
+
12
+ - `verify --prod <url>`: production check that asserts `x-rendershield: bot-hit` and runs the same HTML contract validation as build.
13
+ - Worker response header `x-rendershield`: `bot-hit` | `bot-fallback` | `pass-through` so routing is observable without inferring from HTML.
14
+ - CLI `--version` / `-V`: prints version from package.json.
15
+ - Vitest test suite: contract validation, loadConfig (including sitemap/robots path preservation and worker validation), path safety, and integration build.
16
+
17
+ ### Fixed
18
+
19
+ - Config: sitemap and robots `path` are preserved and defaulted when only `enabled` is set; no longer lost when using boolean flags.
20
+ - Config: when `worker.enabled` is true, full worker object is kept (lovableOrigin, rewriteRouteBases, etc.) instead of being replaced by the flag.
21
+ - Worker: 500 error response body is generic ("Service temporarily unavailable.") to avoid leaking internals.
22
+ - JSON-LD in generated HTML: script body is no longer HTML-escaped so contract validation and crawlers can parse it.
23
+
24
+ ### Changed
25
+
26
+ - Help text shows version and documents that `verify --prod` requires `x-rendershield: bot-hit`.
27
+ - TypeScript: reduced `any`; use `unknown` and typed interfaces in CLI, loadConfig, validateOutput, loadMarkdown.
28
+ - README: added "Production check" for `verify --prod`.
29
+
30
+ ## [0.3.0] - 2025-02-18
31
+
32
+ - Initial npm release with init, build, verify, optional Cloudflare Worker, and HTML contract validation.
package/README.md CHANGED
@@ -108,6 +108,12 @@ node dist/cli.js verify
108
108
 
109
109
  This prints curl commands you can use to confirm crawler behavior.
110
110
 
111
+ **Production check:** After deploying the Worker, run:
112
+
113
+ `rendershield verify --prod https://your-domain.com`
114
+
115
+ This fetches the URL as a bot and asserts the response has `x-rendershield: bot-hit` (proving the Worker served prerendered HTML). If the header is missing or `bot-fallback`, the command fails.
116
+
111
117
  ---
112
118
 
113
119
  ## Deployment
package/dist/cli.js CHANGED
@@ -1,28 +1,41 @@
1
1
  #!/usr/bin/env node
2
+ import { createRequire } from "node:module";
2
3
  import { cmdInit } from "./commands/init.js";
3
4
  import { cmdBuild } from "./commands/build.js";
4
5
  import { cmdVerify } from "./commands/verify.js";
6
+ const require = createRequire(import.meta.url);
7
+ const pkg = require("../package.json");
8
+ const VERSION = pkg.version ?? "0.0.0";
5
9
  function printHelp() {
6
- console.log(`
7
- RenderShield (v0) — boring bot-aware prerendering.
8
-
9
- Usage:
10
- rendershield init
11
- rendershield build
12
- rendershield verify
13
-
14
- Notes:
15
- - Config file: rendershield.config.json
16
- - Content: content/<collection>/**/*.md (frontmatter required)
17
- - Output: dist-prerender/
10
+ console.log(`
11
+ RenderShield v${VERSION} — boring bot-aware prerendering.
12
+
13
+ Usage:
14
+ rendershield init
15
+ rendershield build
16
+ rendershield verify [--prod <url>]
17
+
18
+ verify Print curl commands for local/build output.
19
+ verify --prod Fetch URL as bot and human; verify bot sees full HTML and contract fields.
20
+ Requires x-rendershield: bot-hit from the Worker.
21
+
22
+ Notes:
23
+ - Config file: rendershield.config.json
24
+ - Content: content/<collection>/**/*.md (frontmatter required)
25
+ - Output: dist-prerender/
18
26
  `);
19
27
  }
20
28
  async function main() {
21
- const cmd = process.argv[2]?.trim();
29
+ const args = process.argv.slice(2);
30
+ const cmd = args[0]?.trim();
22
31
  if (!cmd || cmd === "-h" || cmd === "--help") {
23
32
  printHelp();
24
33
  process.exit(0);
25
34
  }
35
+ if (cmd === "-V" || cmd === "--version") {
36
+ console.log(VERSION);
37
+ process.exit(0);
38
+ }
26
39
  try {
27
40
  if (cmd === "init") {
28
41
  await cmdInit();
@@ -33,7 +46,14 @@ async function main() {
33
46
  return;
34
47
  }
35
48
  if (cmd === "verify") {
36
- await cmdVerify();
49
+ const verifyArgs = args.slice(1);
50
+ if (verifyArgs.includes("-h") || verifyArgs.includes("--help")) {
51
+ printHelp();
52
+ process.exit(0);
53
+ }
54
+ const prodIdx = verifyArgs.indexOf("--prod");
55
+ const prodUrl = prodIdx >= 0 && verifyArgs[prodIdx + 1] ? verifyArgs[prodIdx + 1].trim() : undefined;
56
+ await cmdVerify(undefined, prodUrl ? { prodUrl } : undefined);
37
57
  return;
38
58
  }
39
59
  console.error(`Unknown command: ${cmd}\n`);
@@ -41,7 +61,7 @@ async function main() {
41
61
  process.exit(1);
42
62
  }
43
63
  catch (err) {
44
- const msg = err?.message ? String(err.message) : String(err);
64
+ const msg = err instanceof Error ? err.message : String(err);
45
65
  console.error(`\nRenderShield error: ${msg}\n`);
46
66
  process.exit(1);
47
67
  }
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEjD,SAAS,SAAS;IAChB,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;CAYb,CAAC,CAAC;AACH,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC;IAEpC,IAAI,CAAC,GAAG,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC7C,SAAS,EAAE,CAAC;QACZ,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,CAAC;QACH,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;YACnB,MAAM,OAAO,EAAE,CAAC;YAChB,OAAO;QACT,CAAC;QACD,IAAI,GAAG,KAAK,OAAO,EAAE,CAAC;YACpB,MAAM,QAAQ,EAAE,CAAC;YACjB,OAAO;QACT,CAAC;QACD,IAAI,GAAG,KAAK,QAAQ,EAAE,CAAC;YACrB,MAAM,SAAS,EAAE,CAAC;YAClB,OAAO;QACT,CAAC;QAED,OAAO,CAAC,KAAK,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAAC;QAC3C,SAAS,EAAE,CAAC;QACZ,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,MAAM,GAAG,GAAG,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC7D,OAAO,CAAC,KAAK,CAAC,yBAAyB,GAAG,IAAI,CAAC,CAAC;QAChD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -12,8 +12,103 @@ function routeToOutDir(outDirAbs, routePath) {
12
12
  const clean = routePath.replace(/^\//, "");
13
13
  return path.join(outDirAbs, clean);
14
14
  }
15
+ /**
16
+ * Validates output path before any destructive operation (fs.remove).
17
+ * Pass: outDir is a subdirectory inside project root; no symlink escape.
18
+ * Fail: "/", "C:\", "..", "../", or outDir (or any of its existing parents) resolving outside project.
19
+ * Policy: strict — build hard-fails before any delete attempt.
20
+ * Segment-safe: uses path.relative(root, out) only; no prefix startsWith.
21
+ */
22
+ async function validateOutputPath(outDir, cwd) {
23
+ const cwdAbs = path.resolve(cwd);
24
+ let cwdReal;
25
+ try {
26
+ cwdReal = await fs.realpath(cwdAbs);
27
+ }
28
+ catch (err) {
29
+ const msg = err instanceof Error ? err.message : String(err);
30
+ throw new Error(`Cannot resolve project root: ${cwdAbs}. ${msg}`);
31
+ }
32
+ const outDirAbs = path.resolve(cwdAbs, outDir);
33
+ // Order: realpath → normalize → then case-fold for comparisons
34
+ const normalizedCwd = path.normalize(cwdReal);
35
+ const normalizedOut = path.normalize(outDirAbs);
36
+ // Segment-safe: use path.relative only (no prefix startsWith on full path). Cross-platform: relative()
37
+ // rarely returns absolute on Windows; startsWith("..") and path.isAbsolute(rel) cover escapes.
38
+ const relative = path.relative(normalizedCwd, normalizedOut);
39
+ if (relative.startsWith("..") || relative === ".." || path.isAbsolute(relative)) {
40
+ throw new Error(`Output directory "${outDir}" resolves outside project root. Use a relative path within the project.`);
41
+ }
42
+ // Reject: root filesystem (/, C:\, C:/) — early reject; real safety is "inside root" above
43
+ const rootPaths = ["/", "c:\\", "c:/"];
44
+ const outLower = normalizedOut.toLowerCase();
45
+ if (rootPaths.includes(outLower)) {
46
+ throw new Error(`Output directory "${outDir}" resolves to root filesystem. This is not allowed for safety.`);
47
+ }
48
+ // Reject: output dir equals project root (would delete entire project). Case-fold after normalize.
49
+ const cwdLower = normalizedCwd.toLowerCase();
50
+ if (outLower === cwdLower) {
51
+ throw new Error(`Output directory "${outDir}" cannot be the project root. Use a subdirectory (e.g. dist-prerender).`);
52
+ }
53
+ if (await fs.pathExists(outDirAbs)) {
54
+ // Path exists: resolve symlinks and ensure real path is inside root
55
+ let outDirReal;
56
+ try {
57
+ outDirReal = await fs.realpath(outDirAbs);
58
+ }
59
+ catch {
60
+ outDirReal = outDirAbs;
61
+ }
62
+ const outDirRealNorm = path.normalize(outDirReal);
63
+ const relativeReal = path.relative(normalizedCwd, outDirRealNorm);
64
+ if (relativeReal.startsWith("..") || relativeReal === ".." || path.isAbsolute(relativeReal)) {
65
+ throw new Error(`Output directory "${outDir}" resolves (via symlink) outside project root. Use a path that does not escape the project.`);
66
+ }
67
+ }
68
+ else {
69
+ // Path does not exist: walk up to nearest existing parent, realpath it, ensure it stays inside root.
70
+ // Guards e.g. outDir "dist-link/prerender-new" where dist-link is a symlink to /.
71
+ // If we never find an existing parent (or the only one is root), we must reject — do not treat as "fine."
72
+ let current = normalizedOut;
73
+ const rootDir = path.normalize(path.parse(normalizedCwd).root);
74
+ let foundParentInsideRoot = false;
75
+ while (current) {
76
+ if (await fs.pathExists(current)) {
77
+ let parentReal;
78
+ try {
79
+ parentReal = await fs.realpath(current);
80
+ }
81
+ catch {
82
+ parentReal = current;
83
+ }
84
+ const parentRealNorm = path.normalize(parentReal);
85
+ // Nearest existing parent is filesystem root → outside project, reject
86
+ const parentLower = parentRealNorm.toLowerCase();
87
+ if (rootPaths.includes(parentLower)) {
88
+ throw new Error(`Output directory "${outDir}" has a parent that resolves to filesystem root. Use a path inside the project.`);
89
+ }
90
+ const relParent = path.relative(normalizedCwd, parentRealNorm);
91
+ if (relParent.startsWith("..") || relParent === ".." || path.isAbsolute(relParent)) {
92
+ throw new Error(`Output directory "${outDir}" has a parent that resolves (via symlink) outside project root. Use a path that does not escape the project.`);
93
+ }
94
+ foundParentInsideRoot = true;
95
+ break;
96
+ }
97
+ const parent = path.dirname(current);
98
+ if (parent === current)
99
+ break;
100
+ current = parent;
101
+ }
102
+ if (!foundParentInsideRoot) {
103
+ // No existing parent found before hitting dirname loop stop (shouldn't happen on a normal FS)
104
+ throw new Error(`Output directory "${outDir}" could not be validated: no existing parent path found. Use a path inside the project.`);
105
+ }
106
+ }
107
+ }
15
108
  export async function cmdBuild(cwd = process.cwd()) {
16
109
  const cfg = await loadConfig(cwd);
110
+ // Validate output path before any destructive operations
111
+ await validateOutputPath(cfg.output.outDir, cwd);
17
112
  const outDirAbs = path.join(cwd, cfg.output.outDir);
18
113
  // Clean output (boring + deterministic)
19
114
  await fs.remove(outDirAbs);
@@ -32,6 +127,7 @@ export async function cmdBuild(cwd = process.cwd()) {
32
127
  html,
33
128
  outFile,
34
129
  routePath: doc.routePath,
130
+ sourcePath: doc.sourcePath,
35
131
  });
36
132
  await fs.writeFile(outFile, html, "utf8");
37
133
  }
@@ -1 +1 @@
1
- {"version":3,"file":"build.js","sourceRoot":"","sources":["../../src/commands/build.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"build.js","sourceRoot":"","sources":["../../src/commands/build.ts"],"names":[],"mappings":"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"}
@@ -14,9 +14,9 @@ const DEFAULT_CONFIG = {
14
14
  baseDir: "content",
15
15
  collections: [
16
16
  {
17
- name: "pages",
18
- pattern: "pages/**/*.md",
19
- routeBase: "/pages",
17
+ name: "blog",
18
+ pattern: "blog/**/*.md",
19
+ routeBase: "/blog",
20
20
  schemaType: "Article"
21
21
  }
22
22
  ]
@@ -37,7 +37,7 @@ const DEFAULT_CONFIG = {
37
37
  worker: {
38
38
  enabled: true,
39
39
  lovableOrigin: "https://YOUR_SITE.lovable.app",
40
- rewriteRouteBases: ["/pages/"],
40
+ rewriteRouteBases: ["/blog/"],
41
41
  botUserAgentPatterns: [
42
42
  "googlebot",
43
43
  "bingbot",
@@ -73,7 +73,7 @@ That's the whole trick.
73
73
  `;
74
74
  export async function cmdInit(cwd = process.cwd()) {
75
75
  const configPath = path.join(cwd, CONFIG_NAME);
76
- const contentDir = path.join(cwd, "content", "pages");
76
+ const contentDir = path.join(cwd, "content", "blog");
77
77
  const samplePath = path.join(contentDir, "hello-world.md");
78
78
  const configExists = await fs.pathExists(configPath);
79
79
  if (!configExists) {
@@ -87,7 +87,7 @@ export async function cmdInit(cwd = process.cwd()) {
87
87
  const sampleExists = await fs.pathExists(samplePath);
88
88
  if (!sampleExists) {
89
89
  await fs.writeFile(samplePath, SAMPLE_POST, "utf8");
90
- console.log(`Created sample content: content/pages/hello-world.md`);
90
+ console.log(`Created sample content: content/blog/hello-world.md`);
91
91
  }
92
92
  else {
93
93
  console.log(`Sample content already exists (leaving it alone)`);
@@ -95,7 +95,7 @@ export async function cmdInit(cwd = process.cwd()) {
95
95
  console.log(`
96
96
  Next:
97
97
  1) Edit rendershield.config.json
98
- 2) Add content under content/pages/
98
+ 2) Add content under content/blog/
99
99
  3) Run: rendershield build
100
100
  `);
101
101
  }
@@ -1 +1 @@
1
- {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  import fs from "fs-extra";
2
2
  import path from "node:path";
3
3
  import { loadConfig } from "../core/loadConfig.js";
4
+ import { checkPrerenderContract } from "../core/validateOutput.js";
4
5
  function joinUrl(base, routePath) {
5
6
  const b = base.endsWith("/") ? base.slice(0, -1) : base;
6
7
  const p = routePath.startsWith("/") ? routePath : `/${routePath}`;
@@ -43,58 +44,151 @@ function indexHtmlPathToRoute(outDirAbs, indexPathAbs) {
43
44
  const normalized = noFile.split(path.sep).join("/").replace(/\/+$/, "");
44
45
  return "/" + normalized.replace(/^\/+/, "");
45
46
  }
46
- export async function cmdVerify(cwd = process.cwd()) {
47
+ const BOT_UA = "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)";
48
+ const HUMAN_UA = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36";
49
+ /** Heuristic: likely SPA shell if body has almost no visible content and no article. */
50
+ function looksLikeSpaShell(html) {
51
+ const bodyMatch = html.match(/<body[^>]*>([\s\S]*?)<\/body>/i);
52
+ const bodyHtml = bodyMatch ? bodyMatch[1] : html;
53
+ const noScript = bodyHtml
54
+ .replace(/<script[\s\S]*?<\/script>/gi, " ")
55
+ .replace(/<style[\s\S]*?<\/style>/gi, " ")
56
+ .replace(/<noscript[\s\S]*?<\/noscript>/gi, " ");
57
+ const text = noScript.replace(/<\/?[^>]+>/g, " ").replace(/\s+/g, " ").trim();
58
+ if (text.length < 150) {
59
+ return { likely: true, reason: `Body text very short (${text.length} chars); likely app shell.` };
60
+ }
61
+ if (!/<article\b/i.test(html)) {
62
+ return { likely: true, reason: "No <article> present; may be SPA shell." };
63
+ }
64
+ const rootOnly = /<body[^>]*>\s*<div[^>]*id=["'](?:root|app|__next)["'][^>]*>\s*<\/div>\s*<\/body>/i.test(html.replace(/\s+/g, " "));
65
+ if (rootOnly) {
66
+ return { likely: true, reason: "Single root div (e.g. #root, #app) with no content." };
67
+ }
68
+ return { likely: false };
69
+ }
70
+ export async function cmdVerify(cwd = process.cwd(), options) {
71
+ if (options?.prodUrl) {
72
+ await runVerifyProd(options.prodUrl);
73
+ return;
74
+ }
47
75
  const cfg = await loadConfig(cwd);
48
76
  const outDirAbs = path.join(cwd, cfg.output.outDir);
49
77
  const exists = await fs.pathExists(outDirAbs);
50
78
  if (!exists) {
51
- console.log(`
52
- RenderShield verify
53
-
54
- No prerender output directory found: ${cfg.output.outDir}/
55
-
56
- Run:
57
- node dist/cli.js build
79
+ console.log(`
80
+ RenderShield verify
81
+
82
+ No prerender output directory found: ${cfg.output.outDir}/
83
+
84
+ Run:
85
+ node dist/cli.js build
58
86
  `);
59
87
  return;
60
88
  }
61
89
  const firstIndex = await findFirstIndexHtml(outDirAbs);
62
90
  if (!firstIndex) {
63
- console.log(`
64
- RenderShield verify
65
-
66
- No prerendered pages found inside: ${cfg.output.outDir}/
67
-
68
- Run:
69
- node dist/cli.js build
91
+ console.log(`
92
+ RenderShield verify
93
+
94
+ No prerendered pages found inside: ${cfg.output.outDir}/
95
+
96
+ Run:
97
+ node dist/cli.js build
70
98
  `);
71
99
  return;
72
100
  }
73
101
  const routePath = indexHtmlPathToRoute(outDirAbs, firstIndex);
74
102
  const url = joinUrl(cfg.site.canonicalBase, routePath);
75
- console.log(`
76
- RenderShield verify
77
-
78
- Using:
79
- canonicalBase: ${cfg.site.canonicalBase}
80
- routePath: ${routePath}
81
- output file: ${path.relative(cwd, firstIndex)}
82
-
83
- Smoke tests:
84
-
85
- 1) Human (usually SPA shell):
86
- curl -s ${url} | grep -i "<title>"
87
-
88
- 2) Bot (should see prerendered, route-specific title):
89
- curl -s -H "User-Agent: Googlebot" ${url} | grep -i "<title>"
90
-
91
- 3) Debug headers (Worker must be routed + proxy ON):
92
- curl -I -H "User-Agent: GPTBot" ${url}
93
-
94
- Expected headers (if debugHeaders enabled):
95
- X-Bot-Detected: true
96
- X-Prerender: true
97
- X-Final-Path: ${routePath.replace(/\/?$/, "/index.html")}
103
+ console.log(`
104
+ RenderShield verify
105
+
106
+ Using:
107
+ canonicalBase: ${cfg.site.canonicalBase}
108
+ routePath: ${routePath}
109
+ output file: ${path.relative(cwd, firstIndex)}
110
+
111
+ Smoke tests:
112
+
113
+ 1) Human (usually SPA shell):
114
+ curl -s ${url} | grep -i "<title>"
115
+
116
+ 2) Bot (should see prerendered, route-specific title):
117
+ curl -s -H "User-Agent: Googlebot" ${url} | grep -i "<title>"
118
+
119
+ 3) Debug headers (Worker must be routed + proxy ON):
120
+ curl -I -H "User-Agent: GPTBot" ${url}
121
+
122
+ Expected: x-rendershield: bot-hit (proves Worker served prerender to bot).
123
+ If debugHeaders enabled: X-Bot-Detected, X-Prerender, X-Final-Path.
98
124
  `);
99
125
  }
126
+ async function runVerifyProd(url) {
127
+ const normalizedUrl = url.startsWith("http") ? url : `https://${url}`;
128
+ let botHtml;
129
+ let humanHtml;
130
+ let botStatus;
131
+ let humanStatus;
132
+ let xRenderShield;
133
+ try {
134
+ const [botRes, humanRes] = await Promise.all([
135
+ fetch(normalizedUrl, {
136
+ headers: { "User-Agent": BOT_UA },
137
+ redirect: "follow",
138
+ }),
139
+ fetch(normalizedUrl, {
140
+ headers: { "User-Agent": HUMAN_UA },
141
+ redirect: "follow",
142
+ }),
143
+ ]);
144
+ botStatus = botRes.status;
145
+ humanStatus = humanRes.status;
146
+ xRenderShield = botRes.headers.get("x-rendershield");
147
+ botHtml = await botRes.text();
148
+ humanHtml = await humanRes.text();
149
+ }
150
+ catch (err) {
151
+ const msg = err instanceof Error ? err.message : String(err);
152
+ throw new Error(`RenderShield verify --prod: failed to fetch ${normalizedUrl}. ${msg}`);
153
+ }
154
+ // Prove routing: Worker must set x-rendershield: bot-hit for bot requests. No inference.
155
+ const routingOk = xRenderShield === "bot-hit";
156
+ if (xRenderShield === "bot-fallback") {
157
+ throw new Error(`RenderShield verify --prod: bot request received x-rendershield: bot-fallback. ` +
158
+ `Prerender origin returned non-200; Worker fell back to SPA. Fix deployment or origin so bots get prerendered HTML.`);
159
+ }
160
+ if (!routingOk) {
161
+ const hint = xRenderShield == null
162
+ ? " If no Worker is deployed, use verify without --prod to check local/build output."
163
+ : "";
164
+ throw new Error(`RenderShield verify --prod: expected x-rendershield: bot-hit (proving Worker routed bot to prerender). ` +
165
+ `Got: ${xRenderShield ?? "(missing)"}. Ensure the Worker is deployed and bound to this route.${hint}`);
166
+ }
167
+ const contract = checkPrerenderContract(botHtml, {
168
+ routePath: normalizedUrl,
169
+ outFile: normalizedUrl,
170
+ });
171
+ const humanSpa = looksLikeSpaShell(humanHtml);
172
+ // Report
173
+ console.log(`
174
+ RenderShield verify --prod
175
+ URL: ${normalizedUrl}
176
+
177
+ Fetch:
178
+ Bot (Googlebot): ${botStatus} (${botHtml.length} bytes) x-rendershield: ${xRenderShield ?? "(none)"}
179
+ Human (Chrome): ${humanStatus} (${humanHtml.length} bytes)
180
+
181
+ Routing: x-rendershield: bot-hit (Worker served prerendered HTML to bot)
182
+
183
+ Bot contract (title, meta, canonical, OG, JSON-LD, article):
184
+ ${contract.ok ? "PASS — all required fields present." : "FAIL — missing or invalid:"}
185
+ ${contract.missing.length > 0 ? contract.missing.map((m) => ` - ${m}`).join("\n") : ""}
186
+
187
+ Human response:
188
+ ${humanSpa.likely ? `Likely SPA shell: ${humanSpa.reason ?? "unknown"}` : "Has substantial content (not a minimal SPA shell)."}
189
+ `);
190
+ if (!contract.ok) {
191
+ throw new Error(`Production URL did not satisfy bot contract. Missing: ${contract.missing.join("; ")}`);
192
+ }
193
+ }
100
194
  //# sourceMappingURL=verify.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"verify.js","sourceRoot":"","sources":["../../src/commands/verify.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"verify.js","sourceRoot":"","sources":["../../src/commands/verify.ts"],"names":[],"mappings":"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"}