Skip to content

Commit 6cf476a

Browse files
feat(cli): add vibe rules addon (#481)
1 parent 9005a43 commit 6cf476a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+429
-302
lines changed

.changeset/smooth-cows-enter.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"create-better-t-stack": minor
3+
---
4+
5+
add vibe-rules addon with a better t stack rules file

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,5 @@ yarn-error.log*
3737
*.pem
3838
.vscode
3939
.env*.local
40+
41+
.smoke

apps/cli/src/constants.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ export const ADDON_COMPATIBILITY: Record<Addons, readonly Frontend[]> = {
135135
turborepo: [],
136136
starlight: [],
137137
ultracite: [],
138+
"vibe-rules": [],
138139
oxlint: [],
139140
fumadocs: [],
140141
none: [],

apps/cli/src/helpers/database-providers/neon-setup.ts

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import path from "node:path";
2-
import { cancel, isCancel, log, select, spinner, text } from "@clack/prompts";
2+
import { isCancel, log, select, spinner, text } from "@clack/prompts";
33
import { consola } from "consola";
44
import { execa } from "execa";
55
import fs from "fs-extra";
66
import pc from "picocolors";
77
import type { PackageManager, ProjectConfig } from "../../types";
8+
import { exitCancelled } from "../../utils/errors";
89
import { getPackageExecutionCommand } from "../../utils/package-runner";
910
import {
1011
addEnvVariablesToFile,
@@ -177,10 +178,7 @@ export async function setupNeonPostgres(config: ProjectConfig) {
177178
initialValue: "neondb",
178179
});
179180

180-
if (isCancel(setupMethod)) {
181-
cancel(pc.red("Operation cancelled"));
182-
process.exit(0);
183-
}
181+
if (isCancel(setupMethod)) return exitCancelled("Operation cancelled");
184182

185183
if (setupMethod === "neondb") {
186184
await setupWithNeonDb(projectDir, packageManager);
@@ -198,10 +196,8 @@ export async function setupNeonPostgres(config: ProjectConfig) {
198196
initialValue: NEON_REGIONS[0].value,
199197
});
200198

201-
if (isCancel(projectName) || isCancel(regionId)) {
202-
cancel(pc.red("Operation cancelled"));
203-
process.exit(0);
204-
}
199+
if (isCancel(projectName) || isCancel(regionId))
200+
return exitCancelled("Operation cancelled");
205201

206202
const neonConfig = await createNeonProject(
207203
projectName as string,

apps/cli/src/helpers/database-providers/prisma-postgres-setup.ts

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import path from "node:path";
2-
import { cancel, isCancel, log, select, text } from "@clack/prompts";
2+
import { isCancel, log, select, text } from "@clack/prompts";
33
import { consola } from "consola";
44
import { execa } from "execa";
55
import fs from "fs-extra";
66
import pc from "picocolors";
77
import type { ORM, PackageManager, ProjectConfig } from "../../types";
88
import { addPackageDependency } from "../../utils/add-package-deps";
9+
import { exitCancelled } from "../../utils/errors";
910
import { getPackageExecutionCommand } from "../../utils/package-runner";
1011
import {
1112
addEnvVariablesToFile,
@@ -60,10 +61,7 @@ async function setupWithCreateDb(
6061
},
6162
});
6263

63-
if (isCancel(databaseUrl)) {
64-
cancel("Database setup cancelled");
65-
return null;
66-
}
64+
if (isCancel(databaseUrl)) return null;
6765

6866
return {
6967
databaseUrl: databaseUrl as string,
@@ -115,10 +113,7 @@ async function initPrismaDatabase(
115113
},
116114
});
117115

118-
if (isCancel(databaseUrl)) {
119-
cancel("Database setup cancelled");
120-
return null;
121-
}
116+
if (isCancel(databaseUrl)) return null;
122117

123118
return {
124119
databaseUrl: databaseUrl as string,
@@ -245,10 +240,7 @@ export async function setupPrismaPostgres(config: ProjectConfig) {
245240
initialValue: "create-db",
246241
});
247242

248-
if (isCancel(setupMethod)) {
249-
cancel(pc.red("Operation cancelled"));
250-
process.exit(0);
251-
}
243+
if (isCancel(setupMethod)) return exitCancelled("Operation cancelled");
252244

253245
let prismaConfig: PrismaConfig | null = null;
254246

apps/cli/src/helpers/database-providers/turso-setup.ts

Lines changed: 5 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,12 @@
11
import os from "node:os";
22
import path from "node:path";
3-
import {
4-
cancel,
5-
confirm,
6-
isCancel,
7-
log,
8-
select,
9-
spinner,
10-
text,
11-
} from "@clack/prompts";
3+
import { confirm, isCancel, log, select, spinner, text } from "@clack/prompts";
124
import consola from "consola";
135
import { $ } from "execa";
146
import pc from "picocolors";
157
import type { ProjectConfig } from "../../types";
168
import { commandExists } from "../../utils/command-exists";
9+
import { exitCancelled } from "../../utils/errors";
1710
import {
1811
addEnvVariablesToFile,
1912
type EnvVariable,
@@ -129,10 +122,7 @@ async function selectTursoGroup(): Promise<string | null> {
129122
options: groupOptions,
130123
});
131124

132-
if (isCancel(selectedGroup)) {
133-
cancel(pc.red("Operation cancelled"));
134-
process.exit(0);
135-
}
125+
if (isCancel(selectedGroup)) return exitCancelled("Operation cancelled");
136126

137127
return selectedGroup as string;
138128
}
@@ -236,10 +226,7 @@ export async function setupTurso(config: ProjectConfig) {
236226
initialValue: true,
237227
});
238228

239-
if (isCancel(shouldInstall)) {
240-
cancel(pc.red("Operation cancelled"));
241-
process.exit(0);
242-
}
229+
if (isCancel(shouldInstall)) return exitCancelled("Operation cancelled");
243230

244231
if (!shouldInstall) {
245232
await writeEnvFile(projectDir);
@@ -269,10 +256,7 @@ export async function setupTurso(config: ProjectConfig) {
269256
placeholder: suggestedName,
270257
});
271258

272-
if (isCancel(dbNameResponse)) {
273-
cancel(pc.red("Operation cancelled"));
274-
process.exit(0);
275-
}
259+
if (isCancel(dbNameResponse)) return exitCancelled("Operation cancelled");
276260

277261
dbName = dbNameResponse as string;
278262

apps/cli/src/helpers/project-generation/add-addons.ts

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import path from "node:path";
2-
import { cancel, log } from "@clack/prompts";
2+
import { log } from "@clack/prompts";
33
import pc from "picocolors";
44
import type { AddInput, Addons, ProjectConfig } from "../../types";
55
import { validateAddonCompatibility } from "../../utils/addon-compatibility";
66
import { updateBtsConfig } from "../../utils/bts-config";
7+
import { exitWithError } from "../../utils/errors";
78
import { setupAddons } from "../setup/addons-setup";
89
import {
910
detectProjectConfig,
@@ -12,11 +13,6 @@ import {
1213
import { installDependencies } from "./install-dependencies";
1314
import { setupAddonsTemplate } from "./template-manager";
1415

15-
function exitWithError(message: string): never {
16-
cancel(pc.red(message));
17-
process.exit(1);
18-
}
19-
2016
export async function addAddonsToProject(
2117
input: AddInput & { addons: Addons[]; suppressInstallMessage?: boolean },
2218
) {
@@ -71,10 +67,6 @@ export async function addAddonsToProject(
7167
}
7268
}
7369

74-
log.info(
75-
`Adding ${input.addons.join(", ")} to ${config.frontend.join("/")}`,
76-
);
77-
7870
await setupAddonsTemplate(projectDir, config);
7971
await setupAddons(config, true);
8072

apps/cli/src/helpers/project-generation/add-deployment.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import path from "node:path";
2-
import { cancel, log } from "@clack/prompts";
2+
import { log } from "@clack/prompts";
33
import pc from "picocolors";
44
import type { AddInput, ProjectConfig, WebDeploy } from "../../types";
55
import { updateBtsConfig } from "../../utils/bts-config";
6+
import { exitWithError } from "../../utils/errors";
67
import { setupWebDeploy } from "../setup/web-deploy-setup";
78
import {
89
detectProjectConfig,
@@ -11,11 +12,6 @@ import {
1112
import { installDependencies } from "./install-dependencies";
1213
import { setupDeploymentTemplates } from "./template-manager";
1314

14-
function exitWithError(message: string): never {
15-
cancel(pc.red(message));
16-
process.exit(1);
17-
}
18-
1915
export async function addDeploymentToProject(
2016
input: AddInput & { webDeploy: WebDeploy; suppressInstallMessage?: boolean },
2117
) {

apps/cli/src/helpers/project-generation/command-handlers.ts

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import path from "node:path";
2-
import { cancel, intro, log, outro } from "@clack/prompts";
2+
import { intro, log, outro } from "@clack/prompts";
33
import fs from "fs-extra";
44
import pc from "picocolors";
55
import { DEFAULT_CONFIG } from "../../constants";
@@ -10,6 +10,7 @@ import { getDeploymentToAdd } from "../../prompts/web-deploy";
1010
import type { AddInput, CreateInput, ProjectConfig } from "../../types";
1111
import { trackProjectCreation } from "../../utils/analytics";
1212
import { displayConfig } from "../../utils/display-config";
13+
import { exitWithError, handleError } from "../../utils/errors";
1314
import { generateReproducibleCommand } from "../../utils/generate-reproducible-command";
1415
import {
1516
handleDirectoryConflict,
@@ -131,8 +132,7 @@ export async function createProjectHandler(
131132
),
132133
);
133134
} catch (error) {
134-
console.error(error);
135-
process.exit(1);
135+
handleError(error, "Failed to create project");
136136
}
137137
}
138138

@@ -142,12 +142,9 @@ export async function addAddonsHandler(input: AddInput) {
142142
const detectedConfig = await detectProjectConfig(projectDir);
143143

144144
if (!detectedConfig) {
145-
cancel(
146-
pc.red(
147-
"Could not detect project configuration. Please ensure this is a valid Better-T Stack project.",
148-
),
145+
exitWithError(
146+
"Could not detect project configuration. Please ensure this is a valid Better-T Stack project.",
149147
);
150-
process.exit(1);
151148
}
152149

153150
if (!input.addons || input.addons.length === 0) {
@@ -215,7 +212,6 @@ export async function addAddonsHandler(input: AddInput) {
215212

216213
outro("Add command completed successfully!");
217214
} catch (error) {
218-
console.error(error);
219-
process.exit(1);
215+
handleError(error, "Failed to add addons or deployment");
220216
}
221217
}

apps/cli/src/helpers/project-generation/create-project.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import { cancel, log } from "@clack/prompts";
1+
import { log } from "@clack/prompts";
22
import fs from "fs-extra";
3-
import pc from "picocolors";
43
import type { ProjectConfig } from "../../types";
54
import { writeBtsConfig } from "../../utils/bts-config";
5+
import { exitWithError } from "../../utils/errors";
66
import { setupAddons } from "../setup/addons-setup";
77
import { setupApi } from "../setup/api-setup";
88
import { setupAuth } from "../setup/auth-setup";
@@ -104,13 +104,11 @@ export async function createProject(options: ProjectConfig) {
104104
return projectDir;
105105
} catch (error) {
106106
if (error instanceof Error) {
107-
cancel(pc.red(`Error during project creation: ${error.message}`));
108107
console.error(error.stack);
109-
process.exit(1);
108+
exitWithError(`Error during project creation: ${error.message}`);
110109
} else {
111-
cancel(pc.red(`An unexpected error occurred: ${String(error)}`));
112110
console.error(error);
113-
process.exit(1);
111+
exitWithError(`An unexpected error occurred: ${String(error)}`);
114112
}
115113
}
116114
}

0 commit comments

Comments
 (0)