src/lib/setup-biome.ts 2.7 K raw
1
import path from "node:path";
2
import { execa } from "execa";
3
import fs from "fs-extra";
4
import pc from "picocolors";
5
import yoctoSpinner from "yocto-spinner";
6
7
export async function setupBiome(projectPath: string): Promise<void> {
8
	const spinner = yoctoSpinner({ text: "Setting up Biome..." }).start();
9
	try {
10
		// Check if bunx is available
11
		try {
12
			await execa("bunx", ["--version"]);
13
		} catch {
14
			spinner.error("bunx is not available");
15
			throw new Error(
16
				"bunx must be installed. Please install Bun first: https://bun.sh",
17
			);
18
		}
19
20
		const clientPath = path.join(projectPath, "client");
21
		const clientPkgJsonPath = path.join(clientPath, "package.json");
22
		const eslintConfigPath = path.join(clientPath, "eslint.config.js");
23
24
		// Remove ESLint config file
25
		if (fs.existsSync(eslintConfigPath)) {
26
			await fs.remove(eslintConfigPath);
27
		}
28
29
		// Read client package.json and remove ESLint dependencies
30
		const clientPkgJson = await fs.readJson(clientPkgJsonPath);
31
		const devDependencies = clientPkgJson.devDependencies || {};
32
		const eslintDeps = Object.keys(devDependencies).filter(
33
			(dep) => dep.includes("eslint") || dep.includes("@eslint"),
34
		);
35
36
		if (eslintDeps.length > 0) {
37
			spinner.text = "Replacing ESLint dependencies...";
38
			await execa("bun", ["remove", ...eslintDeps], { cwd: clientPath });
39
		}
40
41
		// Install Biome in the root of the project
42
		spinner.text = "Installing Biome...";
43
		await execa("bun", ["add", "-D", "@biomejs/biome"], { cwd: projectPath });
44
45
		// Create biome.json in the root of the project
46
		spinner.text = "Creating biome.json...";
47
		await execa("bunx", ["@biome-js/biome", "init"], { cwd: projectPath });
48
49
		// Update client package.json scripts to remove lint
50
		spinner.text = "Updating scripts in client/package.json...";
51
		const newClientPkgJson = await fs.readJson(clientPkgJsonPath);
52
		if (newClientPkgJson.scripts || newClientPkgJson.scripts.lint) {
53
			delete newClientPkgJson.scripts.lint;
54
		}
55
		await fs.writeJson(clientPkgJsonPath, newClientPkgJson, { spaces: 2 });
56
57
		// Update root package.json with biome scripts
58
		spinner.text = "Updating scripts in root/package.json...";
59
		const rootPkgJsonPath = path.join(projectPath, "package.json");
60
		if (fs.existsSync(rootPkgJsonPath)) {
61
			const rootPkgJson = await fs.readJson(rootPkgJsonPath);
62
			rootPkgJson.scripts = rootPkgJson.scripts || {};
63
			rootPkgJson.scripts.format = "biome format . --write";
64
			rootPkgJson.scripts.lint = "biome lint .";
65
			await fs.writeJson(rootPkgJsonPath, rootPkgJson, { spaces: 2 });
66
		}
67
68
		spinner.success("Biome setup complete.");
69
	} catch (error) {
70
		spinner.error("Biome setup failed.");
71
		if (error instanceof Error) {
72
			console.error(pc.red("\nError:"), error.message);
73
		} else {
74
			console.error(pc.red("\nError: Unknown error during Biome setup."));
75
		}
76
	}
77
}