src/lib/setup-biome.ts 2.9 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
		const clientPath = path.join(projectPath, "client");
11
		const clientPkgJsonPath = path.join(clientPath, "package.json");
12
		const eslintConfigPath = path.join(clientPath, "eslint.config.js");
13
14
		// Remove ESLint config file
15
		if (fs.existsSync(eslintConfigPath)) {
16
			await fs.remove(eslintConfigPath);
17
		}
18
19
		// Read client package.json and remove ESLint dependencies
20
		const clientPkgJson = await fs.readJson(clientPkgJsonPath);
21
		const devDependencies = clientPkgJson.devDependencies || {};
22
		const eslintDeps = Object.keys(devDependencies).filter(
23
			(dep) => dep.includes("eslint") || dep.includes("@eslint"),
24
		);
25
26
		if (eslintDeps.length > 0) {
27
			spinner.text = "Replacing ESLint dependencies...";
28
			await execa("bun", ["remove", ...eslintDeps], { cwd: clientPath });
29
		}
30
31
		// Install Biome in the root of the project
32
		spinner.text = "Installing Biome...";
33
		await execa("bun", ["add", "-D", "@biomejs/biome"], { cwd: projectPath });
34
35
		// Create biome.json in the root of the project
36
		spinner.text = "Creating biome.json...";
37
		const biomeConfig = {
38
			$schema: "https://biomejs.dev/schemas/2.2.4/schema.json",
39
			vcs: {
40
				enabled: true,
41
				clientKind: "git",
42
				useIgnoreFile: true,
43
			},
44
			files: { ignoreUnknown: false, ignore: [] },
45
			formatter: { enabled: true },
46
			organizeImports: { enabled: true },
47
			linter: {
48
				enabled: true,
49
				rules: {
50
					recommended: true,
51
				},
52
			},
53
		};
54
		const biomeConfigPath = path.join(projectPath, "biome.json");
55
		await fs.writeJson(biomeConfigPath, biomeConfig, { spaces: 2 });
56
57
		// Update client package.json scripts to remove lint
58
		spinner.text = "Updating scripts in client/package.json...";
59
		const newClientPkgJson = await fs.readJson(clientPkgJsonPath);
60
		if (newClientPkgJson.scripts || newClientPkgJson.scripts.lint) {
61
			delete newClientPkgJson.scripts.lint;
62
		}
63
		await fs.writeJson(clientPkgJsonPath, newClientPkgJson, { spaces: 2 });
64
65
		// Update root package.json with biome scripts
66
		spinner.text = "Updating scripts in root/package.json...";
67
		const rootPkgJsonPath = path.join(projectPath, "package.json");
68
		if (fs.existsSync(rootPkgJsonPath)) {
69
			const rootPkgJson = await fs.readJson(rootPkgJsonPath);
70
			rootPkgJson.scripts = rootPkgJson.scripts || {};
71
			rootPkgJson.scripts.format = "biome format . --write";
72
			rootPkgJson.scripts.lint = "biome lint .";
73
			await fs.writeJson(rootPkgJsonPath, rootPkgJson, { spaces: 2 });
74
		}
75
76
		spinner.success("Biome setup complete.");
77
	} catch (error) {
78
		spinner.error("Biome setup failed.");
79
		if (error instanceof Error) {
80
			console.error(pc.red("\nError:"), error.message);
81
		} else {
82
			console.error(pc.red("\nError: Unknown error during Biome setup."));
83
		}
84
	}
85
}