src/installers/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 { honoClientTemplate, honoRpcTemplate } from "@/utils/templates";
8
import type { ProjectOptions } from "@/types";
9
import { EXTRAS_DIR } from "@/utils";
10
import { nameGenerator } from "@/utils/name-generator";
11
12
export async function rpcInstaller(
13
	options: Required<ProjectOptions>,
14
): Promise<boolean> {
15
	const spinner = yoctoSpinner({ text: "Setting up RPC client..." }).start();
16
17
	try {
18
		const { projectName, rpc, shadcn, tailwind } = options;
19
		const projectPath = path.resolve(process.cwd(), projectName);
20
21
		// 1. Update client package.json to ensure hono client is installed
22
		const clientPkgPath = path.join(projectPath, "client", "package.json");
23
		const clientPkg = await fs.readJson(clientPkgPath);
24
25
		if (!clientPkg.dependencies.hono) {
26
			await execa("bun", ["install", "hono"], { cwd: projectPath });
27
		}
28
29
		await fs.writeJson(clientPkgPath, clientPkg, { spaces: 2 });
30
31
		// 2. Update server package.json dev script for RPC
32
		const serverPkgPath = path.join(projectPath, "server", "package.json");
33
		const serverPkg = await fs.readJson(serverPkgPath);
34
35
		// Update the dev script to include parallel TypeScript compilation
36
		serverPkg.scripts.dev = "bun --watch run src/index.ts & tsc --watch";
37
38
		await fs.writeJson(serverPkgPath, serverPkg, { spaces: 2 });
39
40
		// 3. Server modification for RPC export type (no client imports)
41
		const serverIndexPath = path.join(projectPath, "server", "src", "index.ts");
42
		await fs.writeFile(serverIndexPath, honoRpcTemplate, "utf8");
43
44
		// 4. Create separate client helper file
45
		const clientHelperPath = path.join(
46
			projectPath,
47
			"server",
48
			"src",
49
			"client.ts",
50
		);
51
		await fs.writeFile(clientHelperPath, honoClientTemplate, "utf8");
52
53
		// 5. Update App.tsx based on template selection using switch statement
54
		const appTsxSrc = path.join(
55
			EXTRAS_DIR,
56
			"client",
57
			"src",
58
			"App.tsx",
59
			nameGenerator("App.tsx", { tailwind, shadcn, rpc }),
60
		);
61
		const appTsxTarget = path.join(projectPath, "client", "src", "App.tsx");
62
63
		fs.copySync(appTsxSrc, appTsxTarget);
64
		spinner.success("RPC client setup completed");
65
		return true;
66
	} catch (err: unknown) {
67
		spinner.error("Failed to set up RPC client");
68
		if (err instanceof Error) {
69
			consola.error(pc.red("Error:"), err.message);
70
		} else {
71
			consola.error(pc.red("Error: Unknown error"));
72
		}
73
		return false;
74
	}
75
}