src/installers/tanstack-router.ts 3.3 K raw
1
import path from "node:path";
2
import fs from "fs-extra";
3
import type { ProjectOptions } from "@/types";
4
import yoctoSpinner from "yocto-spinner";
5
import pc from "picocolors";
6
import { consola } from "consola";
7
import { addPackageDependency } from "@/utils/add-package-dependency";
8
import { EXTRAS_DIR } from "@/utils";
9
import { nameGenerator } from "@/utils/name-generator";
10
import { execa } from "execa";
11
12
export const tanstackRouterInstaller = async (
13
	options: Required<ProjectOptions>,
14
): Promise<boolean> => {
15
	const spinner = yoctoSpinner({
16
		text: "Setting up TanStack Router...",
17
	}).start();
18
19
	try {
20
		// Check if bunx is available
21
		try {
22
			await execa("bunx", ["--version"]);
23
		} catch {
24
			spinner.error("bunx is not available");
25
			consola.error(
26
				pc.red("Error:"),
27
				"bunx must be installed. Please install Bun first: https://bun.sh",
28
			);
29
			return false;
30
		}
31
32
		const { projectName, rpc, shadcn, tailwind, tanstackQuery } = options;
33
34
		const projectPath = path.resolve(process.cwd(), projectName);
35
		spinner.text = "Installing TanStack Router...";
36
		await addPackageDependency({
37
			dependencies: [
38
				"@tanstack/react-router",
39
				"@tanstack/react-router-devtools",
40
			],
41
			target: "client",
42
			projectName,
43
		});
44
45
		await addPackageDependency({
46
			dependencies: ["@tanstack/router-plugin"],
47
			devMode: true,
48
			target: "client",
49
			projectName,
50
		});
51
52
		const viteConfigTemplate = nameGenerator("vite.config.ts", {
53
			tailwind,
54
			shadcn,
55
			tanstackRouter: true,
56
		});
57
		const viteConfigSrc = path.join(
58
			EXTRAS_DIR,
59
			"client",
60
			"vite.config.ts",
61
			viteConfigTemplate,
62
		);
63
		const viteConfigTarget = path.join(projectPath, "client", "vite.config.ts");
64
		fs.copySync(viteConfigSrc, viteConfigTarget);
65
66
		const rootTsxSrc = path.join(
67
			EXTRAS_DIR,
68
			"client",
69
			"src",
70
			"routes",
71
			"__root.tsx",
72
		);
73
		const rootTsxTarget = path.join(
74
			projectPath,
75
			"client",
76
			"src",
77
			"routes",
78
			"__root.tsx",
79
		);
80
		fs.copySync(rootTsxSrc, rootTsxTarget);
81
82
		const indexTsxSrc = path.join(
83
			EXTRAS_DIR,
84
			"client",
85
			"src",
86
			"routes",
87
			"index.tsx",
88
			nameGenerator("index.tsx", { tanstackQuery, tailwind, shadcn, rpc }),
89
		);
90
		const indexTsxTarget = path.join(
91
			projectPath,
92
			"client",
93
			"src",
94
			"routes",
95
			"index.tsx",
96
		);
97
		fs.copySync(indexTsxSrc, indexTsxTarget);
98
99
		const mainTsxSrc = path.join(
100
			EXTRAS_DIR,
101
			"client",
102
			"src",
103
			"main.tsx",
104
			nameGenerator("main.tsx", { tanstackQuery, tanstackRouter: true }),
105
		);
106
		const mainTsxTarget = path.join(projectPath, "client", "src", "main.tsx");
107
		fs.copySync(mainTsxSrc, mainTsxTarget);
108
109
		const appTsxTarget = path.join(projectPath, "client", "src", "App.tsx");
110
		fs.remove(appTsxTarget);
111
112
		spinner.text = "Generating TanStack Route Tree...";
113
114
		// await execa("vite", ["--config", "vite.config.ts", "--force"], {
115
		// 	cwd: path.join(projectPath, "client"),
116
		// });
117
		//
118
		await execa("bunx", ["vite", "build"], {
119
			cwd: path.join(projectPath, "client"),
120
		});
121
122
		await execa("bunx", ["tsc", "-b"], {
123
			cwd: path.join(projectPath, "client"),
124
		});
125
126
		spinner.success("TanStack Router setup completed");
127
		return true;
128
	} catch (err: unknown) {
129
		spinner.error("Failed to set up TanStack Router");
130
		if (err instanceof Error) {
131
			consola.error(pc.red("Error:"), err.message);
132
		} else {
133
			consola.error(pc.red("Error: Unknown error"));
134
		}
135
		return false;
136
	}
137
};