src/lib/patch-files-rpc.ts 2.5 K raw
1
import path from "node:path";
2
import { consola } from "consola";
3
import { execa } from "execa";
4
import fs from "fs-extra";
5
import pc from "picocolors";
6
import yoctoSpinner from "yocto-spinner";
7
import {
8
	defaultTemplate,
9
	honoClientTemplate,
10
	honoRpcTemplate,
11
	shadcnTemplate,
12
	tailwindTemplate,
13
} from "@/utils/templates";
14
15
export async function patchFilesForRPC(
16
	projectPath: string,
17
	templateChoice: string,
18
): Promise<boolean> {
19
	const spinner = yoctoSpinner({ text: "Setting up RPC client..." }).start();
20
21
	try {
22
		// 1. Update client package.json to ensure hono client is installed
23
		const clientPkgPath = path.join(projectPath, "client", "package.json");
24
		const clientPkg = await fs.readJson(clientPkgPath);
25
26
		if (!clientPkg.dependencies.hono) {
27
			await execa("bun", ["install", "hono"], { cwd: projectPath });
28
		}
29
30
		await fs.writeJson(clientPkgPath, clientPkg, { spaces: 2 });
31
32
		// 2. Update server package.json dev script for RPC
33
		const serverPkgPath = path.join(projectPath, "server", "package.json");
34
		const serverPkg = await fs.readJson(serverPkgPath);
35
36
		// Update the dev script to include TypeScript compilation
37
		serverPkg.scripts.dev = "bun --watch run src/index.ts && tsc --watch";
38
39
		await fs.writeJson(serverPkgPath, serverPkg, { spaces: 2 });
40
41
		// 3. Server modification for RPC export type (no client imports)
42
		const serverIndexPath = path.join(projectPath, "server", "src", "index.ts");
43
		await fs.writeFile(serverIndexPath, honoRpcTemplate, "utf8");
44
45
		// 4. Create separate client helper file
46
		const clientHelperPath = path.join(
47
			projectPath,
48
			"server",
49
			"src",
50
			"client.ts",
51
		);
52
		await fs.writeFile(clientHelperPath, honoClientTemplate, "utf8");
53
54
		// 5. Update App.tsx based on template selection using switch statement
55
		const appTsxPath = path.join(projectPath, "client", "src", "App.tsx");
56
57
		// Determine template content based on the template type
58
		let updatedAppContent: string;
59
60
		// Select template based on choice
61
		switch (templateChoice) {
62
			case "shadcn":
63
				updatedAppContent = shadcnTemplate;
64
				break;
65
			case "tailwind":
66
				updatedAppContent = tailwindTemplate;
67
				break;
68
			default:
69
				updatedAppContent = defaultTemplate;
70
				break;
71
		}
72
73
		await fs.writeFile(appTsxPath, updatedAppContent, "utf8");
74
		spinner.success("RPC client setup completed");
75
		return true;
76
	} catch (err: unknown) {
77
		spinner.error("Failed to set up RPC client");
78
		if (err instanceof Error) {
79
			consola.error(pc.red("Error:"), err.message);
80
		} else {
81
			consola.error(pc.red("Error: Unknown error"));
82
		}
83
		return false;
84
	}
85
}