src/lib/prompt-for-options.ts 3.4 K raw
1
import { consola } from "consola";
2
import pc from "picocolors";
3
import type { ProjectOptions } from "@/types";
4
import { TEMPLATES } from "@/utils/templates";
5
import { tryCatch } from "@/utils/try-catch";
6
7
export async function promptForOptions(
8
	options: ProjectOptions,
9
): Promise<ProjectOptions> {
10
	let projectName = options.projectName;
11
12
	if (!projectName && !options.yes) {
13
		const { data, error } = await tryCatch(
14
			consola.prompt(pc.yellow("What is the name of your project?"), {
15
				type: "text",
16
				default: "my-bhvr-app",
17
				placeholder: "my-bhvr-app",
18
				cancel: "reject",
19
			}),
20
		);
21
22
		if (!data || error) {
23
			consola.error(pc.red("Project creation cancelled."));
24
			process.exit(1);
25
		}
26
27
		projectName = data;
28
	}
29
30
	let templateChoice = options.template || "default";
31
32
	if (!options.yes && !options.branch) {
33
		const templateChoices = Object.keys(TEMPLATES).map((key) => ({
34
			label: `${key} (${TEMPLATES[key]?.description})`,
35
			value: key,
36
		}));
37
38
		const { data, error } = await tryCatch(
39
			consola.prompt(pc.yellow("Select a template:"), {
40
				type: "select",
41
				options: templateChoices,
42
				initial: "default",
43
				cancel: "reject",
44
			}),
45
		);
46
47
		if (!data || error) {
48
			consola.error("Project creation cancelled.");
49
			process.exit(1);
50
		}
51
52
		templateChoice = data;
53
	}
54
55
	let useRpc = options.rpc;
56
57
	if (!options.yes && !options.rpc) {
58
		const { data: rpcResponse, error } = await tryCatch(
59
			consola.prompt("Use Hono RPC client for type-safe API communication?", {
60
				type: "confirm",
61
				initial: false,
62
			}),
63
		);
64
65
		if (error) {
66
			consola.error("Project creation cancelled.");
67
			process.exit(1);
68
		}
69
70
		useRpc = rpcResponse;
71
	}
72
73
	let linter = options.linter;
74
75
	if (!options.yes && !options.linter) {
76
		const { data: linterResponse, error } = await tryCatch(
77
			consola.prompt("Select a linter:", {
78
				type: "select",
79
				options: [
80
					{ label: "ESLint (default)", value: "eslint" },
81
					{ label: "Biome", value: "biome" },
82
				],
83
				initial: "eslint",
84
				cancel: "reject",
85
			}),
86
		);
87
88
		if (error) {
89
			console.log(pc.yellow("Project creation cancelled."));
90
			process.exit(1);
91
		}
92
93
		linter = linterResponse as "eslint" | "biome";
94
	}
95
96
	let router = options.router;
97
98
	if (!options.yes && !options.router) {
99
		const { data: routerResponse, error } = await tryCatch(
100
			consola.prompt("Select a client router:", {
101
				type: "select",
102
				options: [
103
					{ label: "None (default)", value: "none" },
104
					{ label: "React Router", value: "reactrouter" },
105
					{ label: "TanStack Router", value: "tanstackrouter" },
106
				],
107
				initial: "none",
108
				cancel: "reject",
109
			}),
110
		);
111
112
		if (error) {
113
			console.log(pc.yellow("Project creation cancelled."));
114
			process.exit(1);
115
		}
116
117
		router = routerResponse as "none" | "reactrouter" | "tanstackrouter";
118
	}
119
120
	let useTanstackQuery = options.tanstackQuery;
121
122
	if (!options.yes && !options.tanstackQuery) {
123
		const { data: tanstackQueryResponse, error } = await tryCatch(
124
			consola.prompt(
125
				"Would you like to enable TanStack Query for data fetching and state management?",
126
				{
127
					type: "confirm",
128
					initial: false,
129
				},
130
			),
131
		);
132
133
		if (error) {
134
			consola.error("Project creation cancelled.");
135
			process.exit(1);
136
		}
137
138
		useTanstackQuery = tanstackQueryResponse;
139
	}
140
141
	return {
142
		...options,
143
		projectName,
144
		template: templateChoice,
145
		tailwind: templateChoice === "tailwind" || templateChoice === "shadcn",
146
		shadcn: templateChoice === "shadcn",
147
		rpc: useRpc,
148
		linter,
149
		router,
150
		tanstackQuery: useTanstackQuery,
151
	};
152
}