From 751b2df12aaec96a7a045cfdaf29ba5ba1247e92 Mon Sep 17 00:00:00 2001 From: Aman Varshney Date: Thu, 11 Sep 2025 01:30:06 +0530 Subject: [PATCH 1/2] chore(cli): remove all explicit return types --- .cursor/rules/better-t-stack-repo.mdc | 1 + apps/cli/src/constants.ts | 5 ++-- apps/cli/src/helpers/addons/addons-setup.ts | 2 +- apps/cli/src/helpers/core/auth-setup.ts | 2 +- apps/cli/src/helpers/core/command-handlers.ts | 7 +++-- apps/cli/src/helpers/core/create-readme.ts | 16 +++++------ .../src/helpers/core/detect-project-config.ts | 5 +--- .../cli/src/helpers/core/post-installation.ts | 22 +++++++-------- .../docker-compose-setup.ts | 2 +- .../database-providers/mongodb-atlas-setup.ts | 4 +-- .../database-providers/supabase-setup.ts | 2 +- .../helpers/database-providers/turso-setup.ts | 13 +++------ .../alchemy/alchemy-svelte-setup.ts | 2 +- apps/cli/src/index.ts | 5 +--- apps/cli/src/prompts/addons.ts | 4 +-- apps/cli/src/prompts/api.ts | 2 +- apps/cli/src/prompts/backend.ts | 2 +- apps/cli/src/prompts/config-prompts.ts | 12 ++++++--- apps/cli/src/prompts/database-setup.ts | 2 +- apps/cli/src/prompts/database.ts | 2 +- apps/cli/src/prompts/examples.ts | 2 +- apps/cli/src/prompts/frontend.ts | 2 +- apps/cli/src/prompts/orm.ts | 2 +- apps/cli/src/prompts/package-manager.ts | 4 +-- apps/cli/src/prompts/project-name.ts | 8 +++--- apps/cli/src/prompts/runtime.ts | 5 +--- apps/cli/src/prompts/server-deploy.ts | 4 +-- apps/cli/src/prompts/web-deploy.ts | 6 ++--- apps/cli/src/utils/addon-compatibility.ts | 2 +- apps/cli/src/utils/biome-formatter.ts | 27 ++++++++----------- apps/cli/src/utils/bts-config.ts | 4 +-- apps/cli/src/utils/compatibility-rules.ts | 4 +-- apps/cli/src/utils/config-processing.ts | 17 +++++------- apps/cli/src/utils/config-validation.ts | 18 ++++++------- apps/cli/src/utils/docker-utils.ts | 10 +++---- apps/cli/src/utils/errors.ts | 2 +- .../utils/generate-reproducible-command.ts | 2 +- apps/cli/src/utils/package-runner.ts | 2 +- apps/cli/src/utils/project-directory.ts | 7 ++--- apps/cli/src/utils/project-name-validation.ts | 6 ++--- apps/cli/src/utils/sponsors.ts | 4 +-- apps/cli/src/utils/telemetry.ts | 2 +- apps/cli/src/utils/ts-morph.ts | 2 +- apps/cli/src/validation.ts | 4 +-- apps/web/src/lib/stack-utils.ts | 14 +++------- 45 files changed, 114 insertions(+), 158 deletions(-) diff --git a/.cursor/rules/better-t-stack-repo.mdc b/.cursor/rules/better-t-stack-repo.mdc index 90a5fa2cd..4141758db 100644 --- a/.cursor/rules/better-t-stack-repo.mdc +++ b/.cursor/rules/better-t-stack-repo.mdc @@ -7,3 +7,4 @@ alwaysApply: true - Do not include emojis. - Use TypeScript type aliases instead of interface declarations. - In Handlebars templates, avoid generic if/else blocks. Write explicit conditions, such as: use if (eq orm "prisma") for Prisma, and else if (eq orm "drizzle") for Drizzle. +- Do not use explicit return types \ No newline at end of file diff --git a/apps/cli/src/constants.ts b/apps/cli/src/constants.ts index 3488dde0f..d3079e5d7 100644 --- a/apps/cli/src/constants.ts +++ b/apps/cli/src/constants.ts @@ -1,6 +1,5 @@ import path from "node:path"; import { fileURLToPath } from "node:url"; -import type { Addons, Frontend, ProjectConfig } from "./types"; import { getUserPkgManager } from "./utils/get-package-manager"; const __filename = fileURLToPath(import.meta.url); @@ -26,7 +25,7 @@ export const DEFAULT_CONFIG_BASE = { serverDeploy: "none", } as const; -export function getDefaultConfig(): ProjectConfig { +export function getDefaultConfig() { return { ...DEFAULT_CONFIG_BASE, projectDir: path.resolve(process.cwd(), DEFAULT_CONFIG_BASE.projectName), @@ -160,7 +159,7 @@ export const dependencyVersionMap = { export type AvailableDependencies = keyof typeof dependencyVersionMap; -export const ADDON_COMPATIBILITY: Record = { +export const ADDON_COMPATIBILITY = { pwa: ["tanstack-router", "react-router", "solid", "next"], tauri: ["tanstack-router", "react-router", "nuxt", "svelte", "solid", "next"], biome: [], diff --git a/apps/cli/src/helpers/addons/addons-setup.ts b/apps/cli/src/helpers/addons/addons-setup.ts index 9791b9893..fcb2e7ef4 100644 --- a/apps/cli/src/helpers/addons/addons-setup.ts +++ b/apps/cli/src/helpers/addons/addons-setup.ts @@ -95,7 +95,7 @@ ${pc.cyan("Docs:")} ${pc.underline("https://turborepo.com/docs")} } } -function getWebAppDir(projectDir: string, frontends: Frontend[]): string { +function getWebAppDir(projectDir: string, frontends: Frontend[]) { if ( frontends.some((f) => ["react-router", "tanstack-router", "nuxt", "svelte", "solid"].includes( diff --git a/apps/cli/src/helpers/core/auth-setup.ts b/apps/cli/src/helpers/core/auth-setup.ts index a7163c3de..3b6603968 100644 --- a/apps/cli/src/helpers/core/auth-setup.ts +++ b/apps/cli/src/helpers/core/auth-setup.ts @@ -115,7 +115,7 @@ export async function setupAuth(config: ProjectConfig) { } } -export function generateAuthSecret(length = 32): string { +export function generateAuthSecret(length = 32) { const characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; let result = ""; diff --git a/apps/cli/src/helpers/core/command-handlers.ts b/apps/cli/src/helpers/core/command-handlers.ts index e78335268..095058e0a 100644 --- a/apps/cli/src/helpers/core/command-handlers.ts +++ b/apps/cli/src/helpers/core/command-handlers.ts @@ -13,7 +13,6 @@ import type { AddInput, CreateInput, DirectoryConflict, - InitResult, ProjectConfig, } from "../../types"; import { trackProjectCreation } from "../../utils/analytics"; @@ -40,7 +39,7 @@ import { installDependencies } from "./install-dependencies"; export async function createProjectHandler( input: CreateInput & { projectName?: string }, -): Promise { +) { const startTime = Date.now(); const timeScaffolded = new Date().toISOString(); @@ -58,7 +57,7 @@ export async function createProjectHandler( currentPathInput = input.projectName; } else if (input.yes) { const defaultConfig = getDefaultConfig(); - let defaultName = defaultConfig.relativePath; + let defaultName: string = defaultConfig.relativePath; let counter = 1; while ( (await fs.pathExists(path.resolve(process.cwd(), defaultName))) && @@ -210,7 +209,7 @@ export async function createProjectHandler( async function handleDirectoryConflictProgrammatically( currentPathInput: string, strategy: DirectoryConflict, -): Promise<{ finalPathInput: string; shouldClearDirectory: boolean }> { +) { const currentPath = path.resolve(process.cwd(), currentPathInput); if (!(await fs.pathExists(currentPath))) { diff --git a/apps/cli/src/helpers/core/create-readme.ts b/apps/cli/src/helpers/core/create-readme.ts index 5cb8430a8..0cd154003 100644 --- a/apps/cli/src/helpers/core/create-readme.ts +++ b/apps/cli/src/helpers/core/create-readme.ts @@ -24,7 +24,7 @@ export async function createReadme(projectDir: string, options: ProjectConfig) { } } -function generateReadmeContent(options: ProjectConfig): string { +function generateReadmeContent(options: ProjectConfig) { const { projectName, packageManager, @@ -163,7 +163,7 @@ function generateStackDescription( backend: string, api: API, isConvex: boolean, -): string { +) { const parts: string[] = []; const hasTanstackRouter = frontend.includes("tanstack-router"); @@ -210,7 +210,7 @@ function generateRunningInstructions( webPort: string, hasNative: boolean, isConvex: boolean, -): string { +) { const instructions: string[] = []; const hasFrontendNone = frontend.length === 0 || frontend.includes("none"); @@ -265,7 +265,7 @@ function generateProjectStructure( isConvex: boolean, api: API, auth: Auth, -): string { +) { const structure: string[] = [`${projectName}/`, "├── apps/"]; const hasFrontendNone = frontend.length === 0 || frontend.includes("none"); @@ -349,7 +349,7 @@ function generateFeaturesList( frontend: Frontend[], backend: string, api: API, -): string { +) { const isConvex = backend === "convex"; const isBackendNone = backend === "none"; const hasTanstackRouter = frontend.includes("tanstack-router"); @@ -493,7 +493,7 @@ function generateDatabaseSetup( orm: ORM, dbSetup: DatabaseSetup, serverDeploy?: string, -): string { +) { if (database === "none") { return ""; } @@ -591,7 +591,7 @@ function generateScriptsList( hasNative: boolean, addons: Addons[], backend: string, -): string { +) { const isConvex = backend === "convex"; const isBackendNone = backend === "none"; @@ -657,7 +657,7 @@ function generateDeploymentCommands( packageManagerRunCmd: string, webDeploy?: string, serverDeploy?: string, -): string { +) { const lines: string[] = []; if (webDeploy === "alchemy" || serverDeploy === "alchemy") { diff --git a/apps/cli/src/helpers/core/detect-project-config.ts b/apps/cli/src/helpers/core/detect-project-config.ts index 4211910bc..f4857dbf9 100644 --- a/apps/cli/src/helpers/core/detect-project-config.ts +++ b/apps/cli/src/helpers/core/detect-project-config.ts @@ -1,11 +1,8 @@ import path from "node:path"; import fs from "fs-extra"; -import type { ProjectConfig } from "../../types"; import { readBtsConfig } from "../../utils/bts-config"; -export async function detectProjectConfig( - projectDir: string, -): Promise | null> { +export async function detectProjectConfig(projectDir: string) { try { const btsConfig = await readBtsConfig(projectDir); if (btsConfig) { diff --git a/apps/cli/src/helpers/core/post-installation.ts b/apps/cli/src/helpers/core/post-installation.ts index 6511394a1..9c14d16f2 100644 --- a/apps/cli/src/helpers/core/post-installation.ts +++ b/apps/cli/src/helpers/core/post-installation.ts @@ -203,7 +203,7 @@ export async function displayPostInstallInstructions( consola.box(output); } -function getNativeInstructions(isConvex: boolean): string { +function getNativeInstructions(isConvex: boolean) { const envVar = isConvex ? "EXPO_PUBLIC_CONVEX_URL" : "EXPO_PUBLIC_SERVER_URL"; const exampleUrl = isConvex ? "https://" @@ -226,7 +226,7 @@ function getNativeInstructions(isConvex: boolean): string { return instructions; } -function getLintingInstructions(runCmd?: string): string { +function getLintingInstructions(runCmd?: string) { return `${pc.bold("Linting and formatting:")}\n${pc.cyan( "•", )} Format and lint fix: ${`${runCmd} check`}\n`; @@ -239,7 +239,7 @@ async function getDatabaseInstructions( runtime?: Runtime, dbSetup?: DatabaseSetup, serverDeploy?: string, -): Promise { +) { const instructions: string[] = []; if (dbSetup === "docker") { @@ -384,7 +384,7 @@ async function getDatabaseInstructions( : ""; } -function getTauriInstructions(runCmd?: string): string { +function getTauriInstructions(runCmd?: string) { return `\n${pc.bold("Desktop app with Tauri:")}\n${pc.cyan( "•", )} Start desktop app: ${`cd apps/web && ${runCmd} desktop:dev`}\n${pc.cyan( @@ -394,13 +394,13 @@ function getTauriInstructions(runCmd?: string): string { )} Tauri requires Rust and platform-specific dependencies.\n See: ${"https://v2.tauri.app/start/prerequisites/"}`; } -function getPwaInstructions(): string { +function getPwaInstructions() { return `\n${pc.bold("PWA with React Router v7:")}\n${pc.yellow( "NOTE:", )} There is a known compatibility issue between VitePWA\n and React Router v7. See:\n https://github.com/vite-pwa/vite-plugin-pwa/issues/809`; } -function getStarlightInstructions(runCmd?: string): string { +function getStarlightInstructions(runCmd?: string) { return `\n${pc.bold("Documentation with Starlight:")}\n${pc.cyan( "•", )} Start docs site: ${`cd apps/docs && ${runCmd} dev`}\n${pc.cyan( @@ -408,13 +408,13 @@ function getStarlightInstructions(runCmd?: string): string { )} Build docs site: ${`cd apps/docs && ${runCmd} build`}`; } -function getNoOrmWarning(): string { +function getNoOrmWarning() { return `\n${pc.yellow( "WARNING:", )} Database selected without an ORM. Features requiring\n database access (e.g., examples, auth) need manual setup.`; } -function getBunWebNativeWarning(): string { +function getBunWebNativeWarning() { return `\n${pc.yellow( "WARNING:", )} 'bun' might cause issues with web + native apps in a monorepo.\n Use 'pnpm' if problems arise.`; @@ -424,7 +424,7 @@ function getWranglerDeployInstructions( runCmd?: string, webDeploy?: string, serverDeploy?: string, -): string { +) { const instructions: string[] = []; if (webDeploy === "wrangler") { @@ -441,7 +441,7 @@ function getWranglerDeployInstructions( return instructions.length ? `\n${instructions.join("\n")}` : ""; } -function getClerkInstructions(): string { +function getClerkInstructions() { return `${pc.bold("Clerk Authentication Setup:")}\n${pc.cyan("•")} Follow the guide: ${pc.underline("https://docs.convex.dev/auth/clerk")}\n${pc.cyan("•")} Set CLERK_JWT_ISSUER_DOMAIN in Convex Dashboard\n${pc.cyan("•")} Set CLERK_PUBLISHABLE_KEY in apps/*/.env`; } @@ -449,7 +449,7 @@ function getAlchemyDeployInstructions( runCmd?: string, webDeploy?: string, serverDeploy?: string, -): string { +) { const instructions: string[] = []; if (webDeploy === "alchemy" && serverDeploy !== "alchemy") { diff --git a/apps/cli/src/helpers/database-providers/docker-compose-setup.ts b/apps/cli/src/helpers/database-providers/docker-compose-setup.ts index f81155a8d..32b417765 100644 --- a/apps/cli/src/helpers/database-providers/docker-compose-setup.ts +++ b/apps/cli/src/helpers/database-providers/docker-compose-setup.ts @@ -34,7 +34,7 @@ async function writeEnvFile( await addEnvVariablesToFile(envPath, variables); } -function getDatabaseUrl(database: Database, projectName: string): string { +function getDatabaseUrl(database: Database, projectName: string) { switch (database) { case "postgres": return `postgresql://postgres:password@localhost:5432/${projectName}`; diff --git a/apps/cli/src/helpers/database-providers/mongodb-atlas-setup.ts b/apps/cli/src/helpers/database-providers/mongodb-atlas-setup.ts index 266f42c25..09693f41b 100644 --- a/apps/cli/src/helpers/database-providers/mongodb-atlas-setup.ts +++ b/apps/cli/src/helpers/database-providers/mongodb-atlas-setup.ts @@ -31,9 +31,7 @@ async function checkAtlasCLI() { } } -async function initMongoDBAtlas( - serverDir: string, -): Promise { +async function initMongoDBAtlas(serverDir: string) { try { const hasAtlas = await checkAtlasCLI(); diff --git a/apps/cli/src/helpers/database-providers/supabase-setup.ts b/apps/cli/src/helpers/database-providers/supabase-setup.ts index fa4bdbbc5..9bcdad0e5 100644 --- a/apps/cli/src/helpers/database-providers/supabase-setup.ts +++ b/apps/cli/src/helpers/database-providers/supabase-setup.ts @@ -37,7 +37,7 @@ async function writeSupabaseEnvFile(projectDir: string, databaseUrl: string) { } } -function extractDbUrl(output: string): string | null { +function extractDbUrl(output: string) { const dbUrlMatch = output.match(/DB URL:\s*(postgresql:\/\/[^\s]+)/); const url = dbUrlMatch?.[1]; if (url) { diff --git a/apps/cli/src/helpers/database-providers/turso-setup.ts b/apps/cli/src/helpers/database-providers/turso-setup.ts index 5f339ce8a..51f8f944a 100644 --- a/apps/cli/src/helpers/database-providers/turso-setup.ts +++ b/apps/cli/src/helpers/database-providers/turso-setup.ts @@ -14,13 +14,6 @@ type TursoConfig = { authToken: string; }; -type TursoGroup = { - name: string; - locations: string; - version: string; - status: string; -}; - async function isTursoInstalled() { return commandExists("turso"); } @@ -71,7 +64,7 @@ async function installTursoCLI(isMac: boolean) { } } -async function getTursoGroups(): Promise { +async function getTursoGroups() { const s = spinner(); try { s.start("Fetching Turso groups..."); @@ -97,7 +90,7 @@ async function getTursoGroups(): Promise { } } -async function selectTursoGroup(): Promise { +async function selectTursoGroup() { const groups = await getTursoGroups(); if (groups.length === 0) { @@ -119,7 +112,7 @@ async function selectTursoGroup(): Promise { options: groupOptions, }); - if (isCancel(selectedGroup)) return exitCancelled("Operation cancelled"); + if (isCancel(selectedGroup)) exitCancelled("Operation cancelled"); return selectedGroup as string; } diff --git a/apps/cli/src/helpers/deployment/alchemy/alchemy-svelte-setup.ts b/apps/cli/src/helpers/deployment/alchemy/alchemy-svelte-setup.ts index 08dade710..a176b24ea 100644 --- a/apps/cli/src/helpers/deployment/alchemy/alchemy-svelte-setup.ts +++ b/apps/cli/src/helpers/deployment/alchemy/alchemy-svelte-setup.ts @@ -76,7 +76,7 @@ export async function setupSvelteAlchemyDeploy( } } -function updateAdapterInConfig(configObject: Node): void { +function updateAdapterInConfig(configObject: Node) { if (!Node.isObjectLiteralExpression(configObject)) return; const kitProperty = configObject.getProperty("kit"); diff --git a/apps/cli/src/index.ts b/apps/cli/src/index.ts index f3bd14061..95ade3e3b 100644 --- a/apps/cli/src/index.ts +++ b/apps/cli/src/index.ts @@ -218,10 +218,7 @@ export function createBtsCli() { * } * ``` */ -export async function init( - projectName?: string, - options?: CreateInput, -): Promise { +export async function init(projectName?: string, options?: CreateInput) { const opts = (options ?? {}) as CreateInput; const programmaticOpts = { ...opts, verbose: true }; const prev = process.env.BTS_PROGRAMMATIC; diff --git a/apps/cli/src/prompts/addons.ts b/apps/cli/src/prompts/addons.ts index 24b2aebfb..d2099a05a 100644 --- a/apps/cli/src/prompts/addons.ts +++ b/apps/cli/src/prompts/addons.ts @@ -75,7 +75,7 @@ const ADDON_GROUPS = { export async function getAddonsChoice( addons?: Addons[], frontends?: Frontend[], -): Promise { +) { if (addons !== undefined) return addons; const allAddons = AddonsSchema.options.filter((addon) => addon !== "none"); @@ -131,7 +131,7 @@ export async function getAddonsChoice( export async function getAddonsToAdd( frontend: Frontend[], existingAddons: Addons[] = [], -): Promise { +) { const groupedOptions: Record = { Documentation: [], Linting: [], diff --git a/apps/cli/src/prompts/api.ts b/apps/cli/src/prompts/api.ts index 67e40124a..5e9026084 100644 --- a/apps/cli/src/prompts/api.ts +++ b/apps/cli/src/prompts/api.ts @@ -7,7 +7,7 @@ export async function getApiChoice( Api?: API | undefined, frontend?: Frontend[], backend?: Backend, -): Promise { +) { if (backend === "convex" || backend === "none") { return "none"; } diff --git a/apps/cli/src/prompts/backend.ts b/apps/cli/src/prompts/backend.ts index 5ee902b95..323cac002 100644 --- a/apps/cli/src/prompts/backend.ts +++ b/apps/cli/src/prompts/backend.ts @@ -6,7 +6,7 @@ import { exitCancelled } from "../utils/errors"; export async function getBackendFrameworkChoice( backendFramework?: Backend, frontends?: Frontend[], -): Promise { +) { if (backendFramework !== undefined) return backendFramework; const hasIncompatibleFrontend = frontends?.some((f) => f === "solid"); diff --git a/apps/cli/src/prompts/config-prompts.ts b/apps/cli/src/prompts/config-prompts.ts index c6fa2be24..c56acddbc 100644 --- a/apps/cli/src/prompts/config-prompts.ts +++ b/apps/cli/src/prompts/config-prompts.ts @@ -55,7 +55,7 @@ export async function gatherConfig( projectName: string, projectDir: string, relativePath: string, -): Promise { +) { const result = await group( { frontend: () => @@ -75,10 +75,14 @@ export async function gatherConfig( results.runtime, ), api: ({ results }) => - getApiChoice(flags.api, results.frontend, results.backend), + getApiChoice( + flags.api, + results.frontend, + results.backend, + ) as Promise, auth: ({ results }) => getAuthChoice( - flags.auth as import("../types").Auth | undefined, + flags.auth, results.database !== "none", results.backend, results.frontend, @@ -91,7 +95,7 @@ export async function gatherConfig( results.frontend, results.backend, results.api, - ), + ) as Promise, dbSetup: ({ results }) => getDBSetupChoice( results.database ?? "none", diff --git a/apps/cli/src/prompts/database-setup.ts b/apps/cli/src/prompts/database-setup.ts index 670d47fe8..e0c3aed7a 100644 --- a/apps/cli/src/prompts/database-setup.ts +++ b/apps/cli/src/prompts/database-setup.ts @@ -8,7 +8,7 @@ export async function getDBSetupChoice( _orm?: ORM, backend?: Backend, runtime?: Runtime, -): Promise { +) { if (backend === "convex") { return "none"; } diff --git a/apps/cli/src/prompts/database.ts b/apps/cli/src/prompts/database.ts index 16c717d44..85da1b464 100644 --- a/apps/cli/src/prompts/database.ts +++ b/apps/cli/src/prompts/database.ts @@ -7,7 +7,7 @@ export async function getDatabaseChoice( database?: Database, backend?: Backend, runtime?: Runtime, -): Promise { +) { if (backend === "convex" || backend === "none") { return "none"; } diff --git a/apps/cli/src/prompts/examples.ts b/apps/cli/src/prompts/examples.ts index bd0113a0e..440c3e27e 100644 --- a/apps/cli/src/prompts/examples.ts +++ b/apps/cli/src/prompts/examples.ts @@ -13,7 +13,7 @@ export async function getExamplesChoice( frontends?: Frontend[], backend?: Backend, api?: API, -): Promise { +) { if (examples !== undefined) return examples; if (api === "none") { diff --git a/apps/cli/src/prompts/frontend.ts b/apps/cli/src/prompts/frontend.ts index 9b9b60fe4..f4079c857 100644 --- a/apps/cli/src/prompts/frontend.ts +++ b/apps/cli/src/prompts/frontend.ts @@ -8,7 +8,7 @@ export async function getFrontendChoice( frontendOptions?: Frontend[], backend?: Backend, auth?: string, -): Promise { +) { if (frontendOptions !== undefined) return frontendOptions; const frontendTypes = await multiselect({ diff --git a/apps/cli/src/prompts/orm.ts b/apps/cli/src/prompts/orm.ts index da050cf28..d2c54a49e 100644 --- a/apps/cli/src/prompts/orm.ts +++ b/apps/cli/src/prompts/orm.ts @@ -27,7 +27,7 @@ export async function getORMChoice( database?: Database, backend?: Backend, runtime?: Runtime, -): Promise { +) { if (backend === "convex") { return "none"; } diff --git a/apps/cli/src/prompts/package-manager.ts b/apps/cli/src/prompts/package-manager.ts index 78bc740e1..ef49ef514 100644 --- a/apps/cli/src/prompts/package-manager.ts +++ b/apps/cli/src/prompts/package-manager.ts @@ -3,9 +3,7 @@ import type { PackageManager } from "../types"; import { exitCancelled } from "../utils/errors"; import { getUserPkgManager } from "../utils/get-package-manager"; -export async function getPackageManagerChoice( - packageManager?: PackageManager, -): Promise { +export async function getPackageManagerChoice(packageManager?: PackageManager) { if (packageManager !== undefined) return packageManager; const detectedPackageManager = getUserPkgManager(); diff --git a/apps/cli/src/prompts/project-name.ts b/apps/cli/src/prompts/project-name.ts index 8173ce24b..4d15bf612 100644 --- a/apps/cli/src/prompts/project-name.ts +++ b/apps/cli/src/prompts/project-name.ts @@ -7,13 +7,13 @@ import { DEFAULT_CONFIG } from "../constants"; import { ProjectNameSchema } from "../types"; import { exitCancelled } from "../utils/errors"; -function isPathWithinCwd(targetPath: string): boolean { +function isPathWithinCwd(targetPath: string) { const resolved = path.resolve(targetPath); const rel = path.relative(process.cwd(), resolved); return !rel.startsWith("..") && !path.isAbsolute(rel); } -function validateDirectoryName(name: string): string | undefined { +function validateDirectoryName(name: string) { if (name === ".") return undefined; const result = ProjectNameSchema.safeParse(name); @@ -23,7 +23,7 @@ function validateDirectoryName(name: string): string | undefined { return undefined; } -export async function getProjectName(initialName?: string): Promise { +export async function getProjectName(initialName?: string) { if (initialName) { if (initialName === ".") { return initialName; @@ -41,7 +41,7 @@ export async function getProjectName(initialName?: string): Promise { let isValid = false; let projectPath = ""; - let defaultName = DEFAULT_CONFIG.projectName; + let defaultName: string = DEFAULT_CONFIG.projectName; let counter = 1; while ( diff --git a/apps/cli/src/prompts/runtime.ts b/apps/cli/src/prompts/runtime.ts index 0c630c3ea..f58eb5837 100644 --- a/apps/cli/src/prompts/runtime.ts +++ b/apps/cli/src/prompts/runtime.ts @@ -3,10 +3,7 @@ import { DEFAULT_CONFIG } from "../constants"; import type { Backend, Runtime } from "../types"; import { exitCancelled } from "../utils/errors"; -export async function getRuntimeChoice( - runtime?: Runtime, - backend?: Backend, -): Promise { +export async function getRuntimeChoice(runtime?: Runtime, backend?: Backend) { if (backend === "convex" || backend === "none") { return "none"; } diff --git a/apps/cli/src/prompts/server-deploy.ts b/apps/cli/src/prompts/server-deploy.ts index 8e08457ed..8ce689545 100644 --- a/apps/cli/src/prompts/server-deploy.ts +++ b/apps/cli/src/prompts/server-deploy.ts @@ -36,7 +36,7 @@ export async function getServerDeploymentChoice( runtime?: Runtime, backend?: Backend, webDeploy?: WebDeploy, -): Promise { +) { if (deployment !== undefined) return deployment; if (backend === "none" || backend === "convex") { @@ -82,7 +82,7 @@ export async function getServerDeploymentToAdd( runtime?: Runtime, existingDeployment?: ServerDeploy, backend?: Backend, -): Promise { +) { if (backend !== "hono") { return "none"; } diff --git a/apps/cli/src/prompts/web-deploy.ts b/apps/cli/src/prompts/web-deploy.ts index 7c3933a0e..4352ed722 100644 --- a/apps/cli/src/prompts/web-deploy.ts +++ b/apps/cli/src/prompts/web-deploy.ts @@ -4,7 +4,7 @@ import type { Backend, Frontend, Runtime, WebDeploy } from "../types"; import { WEB_FRAMEWORKS } from "../utils/compatibility"; import { exitCancelled } from "../utils/errors"; -function hasWebFrontend(frontends: Frontend[]): boolean { +function hasWebFrontend(frontends: Frontend[]) { return frontends.some((f) => WEB_FRAMEWORKS.includes(f)); } @@ -41,7 +41,7 @@ export async function getDeploymentChoice( _runtime?: Runtime, _backend?: Backend, frontend: Frontend[] = [], -): Promise { +) { if (deployment !== undefined) return deployment; if (!hasWebFrontend(frontend)) { return "none"; @@ -72,7 +72,7 @@ export async function getDeploymentChoice( export async function getDeploymentToAdd( frontend: Frontend[], existingDeployment?: WebDeploy, -): Promise { +) { if (!hasWebFrontend(frontend)) { return "none"; } diff --git a/apps/cli/src/utils/addon-compatibility.ts b/apps/cli/src/utils/addon-compatibility.ts index 5279d5110..a9c56d6e5 100644 --- a/apps/cli/src/utils/addon-compatibility.ts +++ b/apps/cli/src/utils/addon-compatibility.ts @@ -30,7 +30,7 @@ export function getCompatibleAddons( allAddons: Addons[], frontend: Frontend[], existingAddons: Addons[] = [], -): Addons[] { +) { return allAddons.filter((addon) => { if (existingAddons.includes(addon)) return false; diff --git a/apps/cli/src/utils/biome-formatter.ts b/apps/cli/src/utils/biome-formatter.ts index 87fd46771..586674301 100644 --- a/apps/cli/src/utils/biome-formatter.ts +++ b/apps/cli/src/utils/biome-formatter.ts @@ -5,10 +5,7 @@ import consola from "consola"; let biome: Biome | null = null; let projectKey: number | null = null; -async function initializeBiome(): Promise<{ - biome: Biome; - projectKey: number; -}> { +async function initializeBiome() { if (biome && projectKey !== null) return { biome, projectKey }; try { @@ -39,19 +36,18 @@ async function initializeBiome(): Promise<{ }); return { biome, projectKey }; - } catch (error) { - consola.error("Failed to initialize Biome:", error); - throw error; + } catch (_error) { + return null; } } -function isSupportedFile(filePath: string): boolean { +function isSupportedFile(filePath: string) { const ext = path.extname(filePath).toLowerCase(); const supportedExtensions = [".js", ".jsx", ".ts", ".tsx", ".json", ".jsonc"]; return supportedExtensions.includes(ext); } -function shouldSkipFile(filePath: string): boolean { +function shouldSkipFile(filePath: string) { const basename = path.basename(filePath); const skipPatterns = [ ".hbs", @@ -65,16 +61,16 @@ function shouldSkipFile(filePath: string): boolean { return skipPatterns.some((pattern) => basename.includes(pattern)); } -export async function formatFileWithBiome( - filePath: string, - content: string, -): Promise { +export async function formatFileWithBiome(filePath: string, content: string) { if (!isSupportedFile(filePath) || shouldSkipFile(filePath)) { return null; } try { - const { biome: biomeInstance, projectKey: key } = await initializeBiome(); + const biomeResult = await initializeBiome(); + if (!biomeResult) return null; + + const { biome: biomeInstance, projectKey: key } = biomeResult; const result = biomeInstance.formatContent(key, content, { filePath: path.basename(filePath), @@ -88,8 +84,7 @@ export async function formatFileWithBiome( } return result.content; - } catch (error) { - consola.warn(`Failed to format ${filePath} with Biome:`, error); + } catch (_error) { return null; } } diff --git a/apps/cli/src/utils/bts-config.ts b/apps/cli/src/utils/bts-config.ts index 16f4293aa..3dba5f52a 100644 --- a/apps/cli/src/utils/bts-config.ts +++ b/apps/cli/src/utils/bts-config.ts @@ -62,9 +62,7 @@ ${configContent}`; await fs.writeFile(configPath, finalContent, "utf-8"); } -export async function readBtsConfig( - projectDir: string, -): Promise { +export async function readBtsConfig(projectDir: string) { try { const configPath = path.join(projectDir, BTS_CONFIG_FILE); diff --git a/apps/cli/src/utils/compatibility-rules.ts b/apps/cli/src/utils/compatibility-rules.ts index 3186db1a6..ba8fbcc4a 100644 --- a/apps/cli/src/utils/compatibility-rules.ts +++ b/apps/cli/src/utils/compatibility-rules.ts @@ -12,7 +12,7 @@ import { validateAddonCompatibility } from "./addon-compatibility"; import { WEB_FRAMEWORKS } from "./compatibility"; import { exitWithError } from "./errors"; -export function isWebFrontend(value: Frontend): boolean { +export function isWebFrontend(value: Frontend) { return WEB_FRAMEWORKS.includes(value); } @@ -138,7 +138,7 @@ export function isFrontendAllowedWithBackend( return true; } -export function allowedApisForFrontends(frontends: Frontend[] = []): API[] { +export function allowedApisForFrontends(frontends: Frontend[] = []) { const includesNuxt = frontends.includes("nuxt"); const includesSvelte = frontends.includes("svelte"); const includesSolid = frontends.includes("solid"); diff --git a/apps/cli/src/utils/config-processing.ts b/apps/cli/src/utils/config-processing.ts index 255c0ca41..62f40ded2 100644 --- a/apps/cli/src/utils/config-processing.ts +++ b/apps/cli/src/utils/config-processing.ts @@ -14,9 +14,7 @@ import type { WebDeploy, } from "../types"; -export function processArrayOption( - options: (T | "none")[] | undefined, -): T[] { +export function processArrayOption(options: (T | "none")[] | undefined) { if (!options || options.length === 0) return []; if (options.includes("none" as T | "none")) return []; return options.filter((item): item is T => item !== "none"); @@ -25,7 +23,7 @@ export function processArrayOption( export function deriveProjectName( projectName?: string, projectDirectory?: string, -): string { +) { if (projectName) { return projectName; } @@ -35,10 +33,7 @@ export function deriveProjectName( return ""; } -export function processFlags( - options: CLIInput, - projectName?: string, -): Partial { +export function processFlags(options: CLIInput, projectName?: string) { const config: Partial = {}; if (options.api) { @@ -109,7 +104,7 @@ export function processFlags( return config; } -export function getProvidedFlags(options: CLIInput): Set { +export function getProvidedFlags(options: CLIInput) { return new Set( Object.keys(options).filter( (key) => options[key as keyof CLIInput] !== undefined, @@ -120,7 +115,7 @@ export function getProvidedFlags(options: CLIInput): Set { export function validateNoneExclusivity( options: (T | "none")[] | undefined, optionName: string, -): void { +) { if (!options || options.length === 0) return; if (options.includes("none" as T | "none") && options.length > 1) { @@ -128,7 +123,7 @@ export function validateNoneExclusivity( } } -export function validateArrayOptions(options: CLIInput): void { +export function validateArrayOptions(options: CLIInput) { validateNoneExclusivity(options.frontend, "frontend options"); validateNoneExclusivity(options.addons, "addons"); validateNoneExclusivity(options.examples, "examples"); diff --git a/apps/cli/src/utils/config-validation.ts b/apps/cli/src/utils/config-validation.ts index 2966f4d8a..ad5121a95 100644 --- a/apps/cli/src/utils/config-validation.ts +++ b/apps/cli/src/utils/config-validation.ts @@ -20,7 +20,7 @@ import { exitWithError } from "./errors"; export function validateDatabaseOrmAuth( cfg: Partial, flags?: Set, -): void { +) { const db = cfg.database; const orm = cfg.orm; const has = (k: string) => (flags ? flags.has(k) : true); @@ -91,7 +91,7 @@ export function validateDatabaseOrmAuth( export function validateDatabaseSetup( config: Partial, providedFlags: Set, -): void { +) { const { dbSetup, database, runtime } = config; if ( @@ -188,7 +188,7 @@ export function validateDatabaseSetup( export function validateConvexConstraints( config: Partial, providedFlags: Set, -): void { +) { const { backend } = config; if (backend !== "convex") { @@ -243,7 +243,7 @@ export function validateConvexConstraints( export function validateBackendNoneConstraints( config: Partial, providedFlags: Set, -): void { +) { const { backend } = config; if (backend !== "none") { @@ -299,7 +299,7 @@ export function validateBackendConstraints( config: Partial, providedFlags: Set, options: CLIInput, -): void { +) { const { backend } = config; if (config.auth === "clerk" && backend !== "convex") { @@ -353,7 +353,7 @@ export function validateBackendConstraints( export function validateFrontendConstraints( config: Partial, providedFlags: Set, -): void { +) { const { frontend } = config; if (frontend && frontend.length > 0) { @@ -375,7 +375,7 @@ export function validateFrontendConstraints( export function validateApiConstraints( config: Partial, options: CLIInput, -): void { +) { if (config.api === "none") { if ( options.examples && @@ -393,7 +393,7 @@ export function validateFullConfig( config: Partial, providedFlags: Set, options: CLIInput, -): void { +) { validateDatabaseOrmAuth(config, providedFlags); validateDatabaseSetup(config, providedFlags); @@ -430,7 +430,7 @@ export function validateFullConfig( export function validateConfigForProgrammaticUse( config: Partial, -): void { +) { try { validateDatabaseOrmAuth(config); diff --git a/apps/cli/src/utils/docker-utils.ts b/apps/cli/src/utils/docker-utils.ts index 8a14db8fc..501a6ee17 100644 --- a/apps/cli/src/utils/docker-utils.ts +++ b/apps/cli/src/utils/docker-utils.ts @@ -1,4 +1,5 @@ import os from "node:os"; +import { $ } from "execa"; import pc from "picocolors"; import type { Database } from "../types"; import { commandExists } from "./command-exists"; @@ -9,7 +10,6 @@ export async function isDockerInstalled() { export async function isDockerRunning() { try { - const { $ } = await import("execa"); await $`docker info`; return true; } catch { @@ -20,7 +20,7 @@ export async function isDockerRunning() { export function getDockerInstallInstructions( platform: string, database: Database, -): string { +) { const isMac = platform === "darwin"; const isWindows = platform === "win32"; const isLinux = platform === "linux"; @@ -50,11 +50,7 @@ export function getDockerInstallInstructions( return `${pc.yellow("IMPORTANT:")} Docker required for ${databaseName}. Install for ${platformName}:\n${pc.blue(installUrl)}`; } -export async function getDockerStatus(database: Database): Promise<{ - installed: boolean; - running: boolean; - message?: string; -}> { +export async function getDockerStatus(database: Database) { const platform = os.platform(); const installed = await isDockerInstalled(); diff --git a/apps/cli/src/utils/errors.ts b/apps/cli/src/utils/errors.ts index 83559ea9f..4021728ed 100644 --- a/apps/cli/src/utils/errors.ts +++ b/apps/cli/src/utils/errors.ts @@ -2,7 +2,7 @@ import { cancel } from "@clack/prompts"; import consola from "consola"; import pc from "picocolors"; -function isProgrammatic(): boolean { +function isProgrammatic() { return process.env.BTS_PROGRAMMATIC === "1"; } diff --git a/apps/cli/src/utils/generate-reproducible-command.ts b/apps/cli/src/utils/generate-reproducible-command.ts index 942c70568..b01442bfd 100644 --- a/apps/cli/src/utils/generate-reproducible-command.ts +++ b/apps/cli/src/utils/generate-reproducible-command.ts @@ -1,6 +1,6 @@ import type { ProjectConfig } from "../types"; -export function generateReproducibleCommand(config: ProjectConfig): string { +export function generateReproducibleCommand(config: ProjectConfig) { const flags: string[] = []; if (config.frontend && config.frontend.length > 0) { diff --git a/apps/cli/src/utils/package-runner.ts b/apps/cli/src/utils/package-runner.ts index 4898e50aa..c5be13107 100644 --- a/apps/cli/src/utils/package-runner.ts +++ b/apps/cli/src/utils/package-runner.ts @@ -11,7 +11,7 @@ import type { PackageManager } from "../types"; export function getPackageExecutionCommand( packageManager: PackageManager | null | undefined, commandWithArgs: string, -): string { +) { switch (packageManager) { case "pnpm": return `pnpm dlx ${commandWithArgs}`; diff --git a/apps/cli/src/utils/project-directory.ts b/apps/cli/src/utils/project-directory.ts index 943b73c90..fb9a37440 100644 --- a/apps/cli/src/utils/project-directory.ts +++ b/apps/cli/src/utils/project-directory.ts @@ -8,10 +8,7 @@ import { exitCancelled, handleError } from "./errors"; export async function handleDirectoryConflict( currentPathInput: string, silent = false, -): Promise<{ - finalPathInput: string; - shouldClearDirectory: boolean; -}> { +) { while (true) { const resolvedPath = path.resolve(process.cwd(), currentPathInput); const dirExists = await fs.pathExists(resolvedPath); @@ -86,7 +83,7 @@ export async function handleDirectoryConflict( export async function setupProjectDirectory( finalPathInput: string, shouldClearDirectory: boolean, -): Promise<{ finalResolvedPath: string; finalBaseName: string }> { +) { let finalResolvedPath: string; let finalBaseName: string; diff --git a/apps/cli/src/utils/project-name-validation.ts b/apps/cli/src/utils/project-name-validation.ts index bf3d3d652..1fa9df4de 100644 --- a/apps/cli/src/utils/project-name-validation.ts +++ b/apps/cli/src/utils/project-name-validation.ts @@ -2,7 +2,7 @@ import path from "node:path"; import { ProjectNameSchema } from "../types"; import { exitWithError } from "./errors"; -export function validateProjectName(name: string): void { +export function validateProjectName(name: string) { const result = ProjectNameSchema.safeParse(name); if (!result.success) { exitWithError( @@ -13,7 +13,7 @@ export function validateProjectName(name: string): void { } } -export function validateProjectNameThrow(name: string): void { +export function validateProjectNameThrow(name: string) { const result = ProjectNameSchema.safeParse(name); if (!result.success) { throw new Error(`Invalid project name: ${result.error.issues[0]?.message}`); @@ -24,7 +24,7 @@ export function extractAndValidateProjectName( projectName?: string, projectDirectory?: string, throwOnError = false, -): string { +) { const derivedName = projectName || (projectDirectory diff --git a/apps/cli/src/utils/sponsors.ts b/apps/cli/src/utils/sponsors.ts index dbddc4d65..1da7763bd 100644 --- a/apps/cli/src/utils/sponsors.ts +++ b/apps/cli/src/utils/sponsors.ts @@ -41,9 +41,7 @@ type SponsorEntry = { export const SPONSORS_JSON_URL = "https://sponsors.better-t-stack.dev/sponsors.json"; -export async function fetchSponsors( - url: string = SPONSORS_JSON_URL, -): Promise { +export async function fetchSponsors(url: string = SPONSORS_JSON_URL) { const s = spinner(); s.start("Fetching sponsors…"); diff --git a/apps/cli/src/utils/telemetry.ts b/apps/cli/src/utils/telemetry.ts index 77518d3de..7adbdc1e5 100644 --- a/apps/cli/src/utils/telemetry.ts +++ b/apps/cli/src/utils/telemetry.ts @@ -4,7 +4,7 @@ * - If BTS_TELEMETRY_DISABLED is present and "1", disables analytics. * - Otherwise, BTS_TELEMETRY: "0" disables, "1" enables (default: enabled). */ -export function isTelemetryEnabled(): boolean { +export function isTelemetryEnabled() { const BTS_TELEMETRY_DISABLED = process.env.BTS_TELEMETRY_DISABLED; const BTS_TELEMETRY = process.env.BTS_TELEMETRY; diff --git a/apps/cli/src/utils/ts-morph.ts b/apps/cli/src/utils/ts-morph.ts index 136e74a1e..222b91e8d 100644 --- a/apps/cli/src/utils/ts-morph.ts +++ b/apps/cli/src/utils/ts-morph.ts @@ -19,7 +19,7 @@ export const tsProject = new Project({ export function ensureArrayProperty( obj: ObjectLiteralExpression, name: string, -): ArrayLiteralExpression { +) { return (obj .getProperty(name) ?.getFirstDescendantByKind(SyntaxKind.ArrayLiteralExpression) ?? diff --git a/apps/cli/src/validation.ts b/apps/cli/src/validation.ts index 515f190ce..db1f781ba 100644 --- a/apps/cli/src/validation.ts +++ b/apps/cli/src/validation.ts @@ -48,7 +48,7 @@ export function processAndValidateFlags( options: CLIInput, providedFlags: Set, projectName?: string, -): Partial { +) { if (options.yolo) { const cfg = processFlags(options, projectName); const validatedProjectName = extractAndValidateProjectName( @@ -89,7 +89,7 @@ export function processAndValidateFlags( export function processProvidedFlagsWithoutValidation( options: CLIInput, projectName?: string, -): Partial { +) { if (!options.yolo) { const providedFlags = getProvidedFlags(options); validateYesFlagCombination(options, providedFlags); diff --git a/apps/web/src/lib/stack-utils.ts b/apps/web/src/lib/stack-utils.ts index a5d5b8e94..65ee9760d 100644 --- a/apps/web/src/lib/stack-utils.ts +++ b/apps/web/src/lib/stack-utils.ts @@ -25,7 +25,7 @@ const CATEGORY_ORDER: Array = [ "install", ]; -export function generateStackSummary(stack: StackState): string { +export function generateStackSummary(stack: StackState) { const selectedTechs = CATEGORY_ORDER.flatMap((category) => { const options = TECH_OPTIONS[category]; const selectedValue = stack[category as keyof StackState]; @@ -51,7 +51,7 @@ export function generateStackSummary(stack: StackState): string { return selectedTechs.length > 0 ? selectedTechs.join(" • ") : "Custom stack"; } -export function generateStackCommand(stack: StackState): string { +export function generateStackCommand(stack: StackState) { const packageManagerCommands = { npm: "npx create-better-t-stack@latest", pnpm: "pnpm create better-t-stack@latest", @@ -126,10 +126,7 @@ export function generateStackCommand(stack: StackState): string { return `${base} ${projectName} ${flags.join(" ")}`; } -export function generateStackUrlFromState( - stack: StackState, - baseUrl?: string, -): string { +export function generateStackUrlFromState(stack: StackState, baseUrl?: string) { const origin = baseUrl || "https://better-t-stack.dev"; const stackParams = new URLSearchParams(); @@ -147,10 +144,7 @@ export function generateStackUrlFromState( return `${origin}/new${searchString ? `?${searchString}` : ""}`; } -export function generateStackSharingUrl( - stack: StackState, - baseUrl?: string, -): string { +export function generateStackSharingUrl(stack: StackState, baseUrl?: string) { const origin = baseUrl || "https://better-t-stack.dev"; const stackParams = new URLSearchParams(); From e556c826aa5a9bed6e7c0ac68202c905372d95ab Mon Sep 17 00:00:00 2001 From: Aman Varshney Date: Thu, 11 Sep 2025 10:00:28 +0530 Subject: [PATCH 2/2] fix --- apps/cli/src/helpers/database-providers/turso-setup.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/cli/src/helpers/database-providers/turso-setup.ts b/apps/cli/src/helpers/database-providers/turso-setup.ts index 51f8f944a..c8ce849a0 100644 --- a/apps/cli/src/helpers/database-providers/turso-setup.ts +++ b/apps/cli/src/helpers/database-providers/turso-setup.ts @@ -112,7 +112,7 @@ async function selectTursoGroup() { options: groupOptions, }); - if (isCancel(selectedGroup)) exitCancelled("Operation cancelled"); + if (isCancel(selectedGroup)) return exitCancelled("Operation cancelled"); return selectedGroup as string; }