Skip to content

Commit afe1c26

Browse files
committed
Fix config validation
1 parent 6129054 commit afe1c26

File tree

2 files changed

+80
-10
lines changed

2 files changed

+80
-10
lines changed

integration/vite-prerender-test.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -577,6 +577,58 @@ test.describe("Prerendering", () => {
577577
expect(html).toMatch('<h2 data-route="true">About</h2>');
578578
expect(html).toMatch('<p data-loader-data="true">About Loader Data</p>');
579579
});
580+
581+
test("Permits a concurrency option", async () => {
582+
fixture = await createFixture({
583+
prerender: true,
584+
files: {
585+
...files,
586+
"react-router.config.ts": js`
587+
export default {
588+
prerender: {
589+
paths: ['/', '/about'],
590+
unstable_concurrency: 2,
591+
},
592+
}
593+
`,
594+
"vite.config.ts": js`
595+
import { defineConfig } from "vite";
596+
import { reactRouter } from "@react-router/dev/vite";
597+
598+
export default defineConfig({
599+
build: { manifest: true },
600+
plugins: [
601+
reactRouter()
602+
],
603+
});
604+
`,
605+
},
606+
});
607+
appFixture = await createAppFixture(fixture);
608+
609+
let clientDir = path.join(fixture.projectDir, "build", "client");
610+
expect(listAllFiles(clientDir).sort()).toEqual([
611+
"_root.data",
612+
"about.data",
613+
"about/index.html",
614+
"favicon.ico",
615+
"index.html",
616+
]);
617+
618+
let res = await fixture.requestDocument("/");
619+
let html = await res.text();
620+
expect(html).toMatch("<title>Index Title: Index Loader Data</title>");
621+
expect(html).toMatch("<h1>Root</h1>");
622+
expect(html).toMatch('<h2 data-route="true">Index</h2>');
623+
expect(html).toMatch('<p data-loader-data="true">Index Loader Data</p>');
624+
625+
res = await fixture.requestDocument("/about");
626+
html = await res.text();
627+
expect(html).toMatch("<title>About Title: About Loader Data</title>");
628+
expect(html).toMatch("<h1>Root</h1>");
629+
expect(html).toMatch('<h2 data-route="true">About</h2>');
630+
expect(html).toMatch('<p data-loader-data="true">About Loader Data</p>');
631+
});
580632
});
581633

582634
test.describe("ssr: true", () => {

packages/react-router-dev/config/config.ts

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -475,17 +475,35 @@ async function resolveConfig({
475475
serverBundles = undefined;
476476
}
477477

478-
let isValidPrerenderConfig =
479-
prerender == null ||
480-
typeof prerender === "boolean" ||
481-
Array.isArray(prerender) ||
482-
typeof prerender === "function";
478+
if (prerender) {
479+
let isValidPrerenderPathsConfig = (p: unknown) =>
480+
typeof p === "boolean" || typeof p === "function" || Array.isArray(p);
483481

484-
if (!isValidPrerenderConfig) {
485-
return err(
486-
"The `prerender` config must be a boolean, an array of string paths, " +
487-
"or a function returning a boolean or array of string paths",
488-
);
482+
let isValidPrerenderConfig =
483+
isValidPrerenderPathsConfig(prerender) ||
484+
(typeof prerender === "object" &&
485+
"paths" in prerender &&
486+
isValidPrerenderPathsConfig(prerender.paths));
487+
488+
if (!isValidPrerenderConfig) {
489+
return err(
490+
"The `prerender`/`prerender.paths` config must be a boolean, an array " +
491+
"of string paths, or a function returning a boolean or array of string paths.",
492+
);
493+
}
494+
495+
let isValidConcurrencyConfig =
496+
typeof prerender != "object" ||
497+
!("unstable_concurrency" in prerender) ||
498+
(typeof prerender.unstable_concurrency === "number" &&
499+
Number.isInteger(prerender.unstable_concurrency) &&
500+
prerender.unstable_concurrency > 0);
501+
502+
if (!isValidConcurrencyConfig) {
503+
return err(
504+
"The `prerender.unstable_concurrency` config must be a positive integer if specified.",
505+
);
506+
}
489507
}
490508

491509
let routeDiscovery: ResolvedReactRouterConfig["routeDiscovery"];

0 commit comments

Comments
 (0)