src/lib/scaffold-template.ts 1.9 K raw
1
import path from "node:path";
2
import degit from "degit";
3
import fs from "fs-extra";
4
import pc from "picocolors";
5
import yoctoSpinner from "yocto-spinner";
6
import type { ProjectOptions } from "@/types";
7
import { DEFAULT_REPO } from "@/utils/constants";
8
import { TEMPLATES } from "@/utils/templates";
9
import { patchFilesForRPC } from "./patch-files-rpc";
10
import { setupBiome } from "./setup-biome";
11
12
export async function scaffoldTemplate(
13
	options: Required<ProjectOptions>,
14
): Promise<boolean> {
15
	const { projectName, template, repo, branch, rpc, linter } = options;
16
17
	const projectPath = path.resolve(process.cwd(), projectName);
18
19
	if (fs.existsSync(projectPath)) {
20
		const files = fs.readdirSync(projectPath);
21
		if (files.length > 0) {
22
			await fs.emptyDir(projectPath);
23
		}
24
	}
25
26
	fs.ensureDirSync(projectPath);
27
28
	const repoPath = repo || DEFAULT_REPO;
29
	const templateConfig =
30
		TEMPLATES[template as keyof typeof TEMPLATES] || TEMPLATES.default;
31
	const repoBranch = branch || (templateConfig?.branch ?? "main");
32
	const repoUrl = `${repoPath}#${repoBranch}`;
33
	const spinner = yoctoSpinner({ text: "Downloading template..." }).start();
34
35
	try {
36
		const emitter = degit(repoUrl, {
37
			cache: false,
38
			force: true,
39
			verbose: false,
40
		});
41
42
		await emitter.clone(projectPath);
43
		spinner.success(`Template downloaded successfully (${template} template)`);
44
45
		const pkgJsonPath = path.join(projectPath, "package.json");
46
		if (fs.existsSync(pkgJsonPath)) {
47
			const pkgJson = await fs.readJson(pkgJsonPath);
48
			pkgJson.name = projectName;
49
			await fs.writeJson(pkgJsonPath, pkgJson, { spaces: 2 });
50
		}
51
52
		const gitDir = path.join(projectPath, ".git");
53
		if (fs.existsSync(gitDir)) {
54
			await fs.remove(gitDir);
55
			console.log(pc.blue("Removed .git directory"));
56
		}
57
58
		if (rpc) {
59
			await patchFilesForRPC(projectPath, template);
60
		}
61
62
		if (linter === "biome") {
63
			await setupBiome(projectPath);
64
		}
65
66
		return true;
67
	} catch (err) {
68
		spinner.error("Failed to download template");
69
		throw err;
70
	}
71
}