src/lib/scaffold-template.ts 1.7 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
10
export async function scaffoldTemplate(
11
	options: Required<ProjectOptions>,
12
): Promise<boolean> {
13
	const { projectName, template, repo, branch } = options;
14
15
	const projectPath = path.resolve(process.cwd(), projectName);
16
17
	if (fs.existsSync(projectPath)) {
18
		const files = fs.readdirSync(projectPath);
19
		if (files.length > 0) {
20
			await fs.emptyDir(projectPath);
21
		}
22
	}
23
24
	fs.ensureDirSync(projectPath);
25
26
	const repoPath = repo || DEFAULT_REPO;
27
	const templateConfig =
28
		TEMPLATES[template as keyof typeof TEMPLATES] || TEMPLATES.default;
29
	const repoBranch = branch || (templateConfig?.branch ?? "main");
30
	const repoUrl = `${repoPath}#${repoBranch}`;
31
	const spinner = yoctoSpinner({ text: "Downloading template..." }).start();
32
33
	try {
34
		const emitter = degit(repoUrl, {
35
			cache: false,
36
			force: true,
37
			verbose: false,
38
		});
39
40
		await emitter.clone(projectPath);
41
		spinner.success(`Template downloaded successfully (${template} template)`);
42
43
		const pkgJsonPath = path.join(projectPath, "package.json");
44
		if (fs.existsSync(pkgJsonPath)) {
45
			const pkgJson = await fs.readJson(pkgJsonPath);
46
			pkgJson.name = projectName;
47
			await fs.writeJson(pkgJsonPath, pkgJson, { spaces: 2 });
48
		}
49
50
		const gitDir = path.join(projectPath, ".git");
51
		if (fs.existsSync(gitDir)) {
52
			await fs.remove(gitDir);
53
			console.log(pc.blue("Removed .git directory"));
54
		}
55
56
		return true;
57
	} catch (err) {
58
		spinner.error("Failed to download template");
59
		throw err;
60
	}
61
}