Skip to content

Commit

Permalink
Fix reveal and routes CLI commands (#12745)
Browse files Browse the repository at this point in the history
  • Loading branch information
markdalgleish authored Jan 16, 2025
1 parent c5b2641 commit c364bd4
Show file tree
Hide file tree
Showing 16 changed files with 142 additions and 200 deletions.
5 changes: 5 additions & 0 deletions .changeset/popular-lobsters-agree.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@react-router/dev": patch
---

Fix `reveal` and `routes` CLI commands
77 changes: 77 additions & 0 deletions packages/react-router-dev/__tests__/cli-reveal-test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import path from "node:path";
import fse from "fs-extra";
import execa from "execa";

function getProjectDir() {
let projectDir = path.join(
__dirname,
".tmp",
`reveal-test-${Math.random().toString(32).slice(2)}`
);
fse.copySync(path.join(__dirname, "fixtures", "basic"), projectDir);
return projectDir;
}

async function runCli(cwd: string, args: string[]) {
return await execa(
"node",
[
"--require",
require.resolve("esbuild-register"),
path.resolve(__dirname, "../cli/index.ts"),
...args,
],
{ cwd }
);
}

describe("the reveal command", () => {
it("generates an entry.server.tsx file in the app directory", async () => {
let projectDir = getProjectDir();

let entryClientFile = path.join(projectDir, "app", "entry.client.tsx");
let entryServerFile = path.join(projectDir, "app", "entry.server.tsx");

expect(fse.existsSync(entryServerFile)).toBeFalsy();
expect(fse.existsSync(entryClientFile)).toBeFalsy();

await runCli(projectDir, ["reveal"]);

expect(fse.existsSync(entryServerFile)).toBeTruthy();
expect(fse.existsSync(entryClientFile)).toBeTruthy();
});

it("generates an entry.server.tsx file in the app directory when specific entries are provided", async () => {
let projectDir = getProjectDir();

let entryClientFile = path.join(projectDir, "app", "entry.client.tsx");
let entryServerFile = path.join(projectDir, "app", "entry.server.tsx");

expect(fse.existsSync(entryServerFile)).toBeFalsy();
expect(fse.existsSync(entryClientFile)).toBeFalsy();

await runCli(projectDir, ["reveal", "entry.server"]);
expect(fse.existsSync(entryServerFile)).toBeTruthy();
expect(fse.existsSync(entryClientFile)).toBeFalsy();
fse.removeSync(entryServerFile);

await runCli(projectDir, ["reveal", "entry.client"]);
expect(fse.existsSync(entryClientFile)).toBeTruthy();
expect(fse.existsSync(entryServerFile)).toBeFalsy();
});

it("generates an entry.server.jsx file in the app directory", async () => {
let projectDir = getProjectDir();

let entryClientFile = path.join(projectDir, "app", "entry.client.jsx");
let entryServerFile = path.join(projectDir, "app", "entry.server.jsx");

expect(fse.existsSync(entryServerFile)).toBeFalsy();
expect(fse.existsSync(entryClientFile)).toBeFalsy();

await runCli(projectDir, ["reveal", "--no-typescript"]);

expect(fse.existsSync(entryServerFile)).toBeTruthy();
expect(fse.existsSync(entryClientFile)).toBeTruthy();
});
});
31 changes: 31 additions & 0 deletions packages/react-router-dev/__tests__/cli-routes-test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import path from "node:path";
import execa from "execa";

async function runCli(cwd: string, args: string[]) {
return await execa(
"node",
[
"--require",
require.resolve("esbuild-register"),
path.resolve(__dirname, "../cli/index.ts"),
...args,
],
{ cwd }
);
}

describe("the routes command", () => {
it("displays routes", async () => {
let projectDir = path.join(__dirname, "fixtures", "basic");

let result = await runCli(projectDir, ["routes"]);

expect(result.stdout).toMatchInlineSnapshot(`
"<Routes>
<Route file="root.tsx">
<Route index file="routes/_index.tsx" />
</Route>
</Routes>"
`);
});
});
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
node_modules

/.cache
/build
/public/build
.env

.react-router/
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// Note that since this is used in a unit test context, we don't have access to
// the `dev` build yet, so we can't import from `@react-router/dev/routes`.
const routes = [{ file: "routes/_index.tsx", index: true }];

export default routes;
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
{
"include": ["remix.env.d.ts", "**/*.ts", "**/*.tsx"],
"include": ["**/*.ts", "**/*.tsx"],
"compilerOptions": {
"lib": ["DOM", "DOM.Iterable", "ES2022"],
"types": ["@react-router/node", "vite/client"],
"verbatimModuleSyntax": true,
"esModuleInterop": true,
"jsx": "react-jsx",
Expand Down
38 changes: 0 additions & 38 deletions packages/react-router-dev/__tests__/fixtures/node/README.md

This file was deleted.

Binary file not shown.

This file was deleted.

97 changes: 0 additions & 97 deletions packages/react-router-dev/__tests__/reveal-test.ts

This file was deleted.

40 changes: 20 additions & 20 deletions packages/react-router-dev/cli/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ import fse from "fs-extra";
import PackageJson from "@npmcli/package-json";
import exitHook from "exit-hook";
import colors from "picocolors";
// Workaround for "ERR_REQUIRE_CYCLE_MODULE" in Node 22.10.0+
import "react-router";

import type { ViteDevOptions } from "../vite/dev";
import type { ViteBuildOptions } from "../vite/build";
import { loadConfig } from "../config/config";
import { formatRoutes } from "../config/format";
import type { RoutesFormat } from "../config/format";
import { loadPluginContext } from "../vite/plugin";
import { transpile as convertFileToJS } from "./useJavascript";
import * as profiler from "../vite/profiler";
import * as Typegen from "../typegen";
Expand All @@ -21,20 +23,16 @@ export async function routes(
json?: boolean;
} = {}
): Promise<void> {
let ctx = await loadPluginContext({
root: reactRouterRoot,
configFile: flags.config,
});
let rootDirectory = reactRouterRoot ?? process.cwd();
let configResult = await loadConfig({ rootDirectory });

if (!ctx) {
console.error(
colors.red("React Router Vite plugin not found in Vite config")
);
if (!configResult.ok) {
console.error(colors.red(configResult.error));
process.exit(1);
}

let format: RoutesFormat = flags.json ? "json" : "jsx";
console.log(formatRoutes(ctx.reactRouterConfig.routes, format));
console.log(formatRoutes(configResult.value.routes, format));
}

export async function build(
Expand Down Expand Up @@ -78,28 +76,30 @@ let conjunctionListFormat = new Intl.ListFormat("en", {
});

export async function generateEntry(
entry: string,
reactRouterRoot: string,
entry?: string,
reactRouterRoot?: string,
flags: {
typescript?: boolean;
config?: string;
} = {}
) {
let ctx = await loadPluginContext({
root: reactRouterRoot,
configFile: flags.config,
});

let rootDirectory = ctx.rootDirectory;
let appDirectory = ctx.reactRouterConfig.appDirectory;

// if no entry passed, attempt to create both
if (!entry) {
await generateEntry("entry.client", reactRouterRoot, flags);
await generateEntry("entry.server", reactRouterRoot, flags);
return;
}

let rootDirectory = reactRouterRoot ?? process.cwd();
let configResult = await loadConfig({ rootDirectory });

if (!configResult.ok) {
console.error(colors.red(configResult.error));
return;
}

let appDirectory = configResult.value.appDirectory;

if (!entries.includes(entry)) {
let entriesArray = Array.from(entries);
let list = conjunctionListFormat.format(entriesArray);
Expand Down
Loading

0 comments on commit c364bd4

Please sign in to comment.