Skip to content
Closed
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/yellow-carpets-own.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@react-router/dev": patch
---

Fix typegen support for routes outside appDirectory
1 change: 1 addition & 0 deletions contributors.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
- alberto
- AlemTuzlak
- Aleuck
- alex-pex
- alexandernanberg
- alexanderson1993
- alexlbr
Expand Down
1 change: 1 addition & 0 deletions integration/helpers/fixtures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ type Edits = Record<string, string | ((contents: string) => string)>;
async function applyEdits(cwd: string, edits: Edits) {
const promises = Object.entries(edits).map(async ([file, transform]) => {
const filepath = Path.join(cwd, file);
await fs.mkdir(Path.dirname(filepath), { recursive: true });
await fs.writeFile(
filepath,
typeof transform === "function"
Expand Down
39 changes: 39 additions & 0 deletions integration/typegen-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,45 @@ test.describe("typegen", () => {
await $("pnpm typecheck");
});

test("routes outside app dir", async ({ edit, $ }) => {
await edit({
"react-router.config.ts": tsx`
export default {
appDirectory: "app/router",
}
`,
"app/router/routes.ts": tsx`
import { type RouteConfig, route } from "@react-router/dev/routes";

export default [
route("products/:id", "../pages/product.tsx")
] satisfies RouteConfig;
`,
"app/router/root.tsx": tsx`
import { Outlet } from "react-router";

export default function Root() {
return <Outlet />;
}
`,
"app/pages/product.tsx": tsx`
import type { Expect, Equal } from "../expect-type"
import type { Route } from "./+types/product"

export function loader({ params }: Route.LoaderArgs) {
type Test = Expect<Equal<typeof params, { id: string }>>
return { planet: "world" }
}

export default function Component({ loaderData }: Route.ComponentProps) {
type Test = Expect<Equal<typeof loaderData.planet, string>>
return <h1>Hello, {loaderData.planet}!</h1>
}
`,
});
await $("pnpm typecheck");
});

test("matches", async ({ edit, $ }) => {
await edit({
"app/routes.ts": tsx`
Expand Down
6 changes: 3 additions & 3 deletions packages/react-router-dev/typegen/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ export function generateRoutes(ctx: Context): Array<VirtualFile> {

// **/+types/*.ts
const allAnnotations: Array<VirtualFile> = Array.from(fileToRoutes.entries())
.filter(([file]) => isInAppDirectory(ctx, file))
.filter(([file]) => isInRootDirectory(ctx, file))
.map(([file, routeIds]) =>
getRouteAnnotations({ ctx, file, routeIds, lineages }),
);
Expand Down Expand Up @@ -221,9 +221,9 @@ function routeModulesType(ctx: Context) {
);
}

function isInAppDirectory(ctx: Context, routeFile: string): boolean {
function isInRootDirectory(ctx: Context, routeFile: string): boolean {
const path = Path.resolve(ctx.config.appDirectory, routeFile);
return path.startsWith(ctx.config.appDirectory);
return path.startsWith(ctx.rootDirectory);
}

function getRouteAnnotations({
Expand Down