@@ -6,6 +6,31 @@ const buildDir = path.join(rootDir, 'build');
66const staticDir = path . join ( rootDir , 'static' ) ;
77const siteUrl = process . env . SITE_URL || 'https://ralphstarter.ai' ;
88const expectedOrigin = new URL ( siteUrl ) . origin ;
9+ // Keep a minimum URL floor so we catch truncated/partial sitemap generation.
10+ const defaultMinSitemapUrls = 10 ;
11+
12+ function resolveMinSitemapUrls ( ) {
13+ const rawValue = process . env . MIN_SITEMAP_URLS ;
14+ if ( rawValue === undefined || rawValue . trim ( ) === '' ) {
15+ return defaultMinSitemapUrls ;
16+ }
17+
18+ const normalized = rawValue . trim ( ) ;
19+ if ( ! / ^ \d + $ / . test ( normalized ) ) {
20+ throw new Error (
21+ `Invalid MIN_SITEMAP_URLS value "${ rawValue } ". Expected a positive integer.`
22+ ) ;
23+ }
24+
25+ const parsedValue = Number ( normalized ) ;
26+ if ( ! Number . isSafeInteger ( parsedValue ) || parsedValue <= 0 ) {
27+ throw new Error (
28+ `Invalid MIN_SITEMAP_URLS value "${ rawValue } ". Expected a positive integer.`
29+ ) ;
30+ }
31+
32+ return parsedValue ;
33+ }
934
1035const requiredBuildFiles = [
1136 'sitemap.xml' ,
@@ -24,6 +49,8 @@ function assertFileExists(fullPath, label) {
2449}
2550
2651function main ( ) {
52+ const minSitemapUrls = resolveMinSitemapUrls ( ) ;
53+
2754 assertFileExists ( buildDir , 'Build directory' ) ;
2855
2956 for ( const file of requiredBuildFiles ) {
@@ -34,8 +61,10 @@ function main() {
3461 const sitemap = fs . readFileSync ( sitemapPath , 'utf8' ) ;
3562 const locMatches = [ ...sitemap . matchAll ( / < l o c > ( [ ^ < ] + ) < \/ l o c > / g) ] . map ( ( match ) => match [ 1 ] ) ;
3663
37- if ( locMatches . length < 10 ) {
38- throw new Error ( `Sitemap has too few URLs (${ locMatches . length } ).` ) ;
64+ if ( locMatches . length < minSitemapUrls ) {
65+ throw new Error (
66+ `Sitemap has too few URLs (${ locMatches . length } ). Expected at least ${ minSitemapUrls } .`
67+ ) ;
3968 }
4069
4170 if ( ! locMatches . some ( ( url ) => url . includes ( '/docs/intro' ) ) ) {
@@ -60,7 +89,13 @@ function main() {
6089 }
6190
6291 const docsManifestRaw = fs . readFileSync ( path . join ( buildDir , 'docs.json' ) , 'utf8' ) ;
63- const docsManifest = JSON . parse ( docsManifestRaw ) ;
92+ let docsManifest ;
93+ try {
94+ docsManifest = JSON . parse ( docsManifestRaw ) ;
95+ } catch ( error ) {
96+ const reason = error instanceof Error ? error . message : String ( error ) ;
97+ throw new Error ( `Malformed docs.json manifest: ${ reason } . Please regenerate docs artifacts.` ) ;
98+ }
6499 if ( ! Array . isArray ( docsManifest . docs ) || docsManifest . docs . length === 0 ) {
65100 throw new Error ( 'docs.json manifest has no docs entries.' ) ;
66101 }
@@ -77,4 +112,14 @@ function main() {
77112 console . log ( `- docs manifest entries: ${ docsManifest . docs . length } ` ) ;
78113}
79114
80- main ( ) ;
115+ try {
116+ main ( ) ;
117+ process . exitCode = 0 ;
118+ } catch ( error ) {
119+ if ( error instanceof Error ) {
120+ console . error ( 'Validation failed:\n' , error . stack || error . message ) ;
121+ } else {
122+ console . error ( 'Validation failed:' , error ) ;
123+ }
124+ process . exit ( 1 ) ;
125+ }
0 commit comments