diff --git a/.changeset/cold-rings-show.md b/.changeset/cold-rings-show.md new file mode 100644 index 00000000..cb12dbff --- /dev/null +++ b/.changeset/cold-rings-show.md @@ -0,0 +1,15 @@ +--- +'@tanstack/cta-cli': minor +'create-start-app': minor +'create-tanstack': minor +'create-tanstack-app': minor +'create-tsrouter-app': minor +'@tanstack/create-start': minor +'@tanstack/cta-framework-react-cra': minor +'@tanstack/cta-framework-solid': minor +'@tanstack/cta-engine': minor +'@tanstack/cta-ui': minor +'@tanstack/cta-ui-base': minor +--- + +no will prompt about overriding a directory that has contents diff --git a/packages/cta-cli/src/cli.ts b/packages/cta-cli/src/cli.ts index 3183a02b..3641149e 100644 --- a/packages/cta-cli/src/cli.ts +++ b/packages/cta-cli/src/cli.ts @@ -386,6 +386,11 @@ Remove your node_modules directory and package lock file and re-install.`, '--add-on-config ', 'JSON string with add-on configuration options', ) + .option( + '-f, --force', + 'force project creation even if the target directory is not empty', + false, + ) program.action(async (projectName: string, options: CliOptions) => { if (options.listAddOns) { diff --git a/packages/cta-cli/src/options.ts b/packages/cta-cli/src/options.ts index c8d10335..12b8b134 100644 --- a/packages/cta-cli/src/options.ts +++ b/packages/cta-cli/src/options.ts @@ -1,4 +1,5 @@ -import { intro } from '@clack/prompts' +import fs from 'node:fs' +import { cancel, confirm, intro, isCancel } from '@clack/prompts' import { finalizeAddOns, @@ -12,8 +13,8 @@ import { getProjectName, promptForAddOnOptions, selectAddOns, - selectGit, selectDeployment, + selectGit, selectPackageManager, selectRouterType, selectTailwind, @@ -46,6 +47,7 @@ export async function promptForCreateOptions( options.framework = getFrameworkById(cliOptions.framework || 'react-cra')! + // Validate project name if (cliOptions.projectName) { // Handle "." as project name - use sanitized current directory name if (cliOptions.projectName === '.') { @@ -62,6 +64,23 @@ export async function promptForCreateOptions( options.projectName = await getProjectName() } + // Check if target directory is empty + if ( + !cliOptions.force && + fs.existsSync(options.projectName) && + fs.readdirSync(options.projectName).length > 0 + ) { + const shouldContinue = await confirm({ + message: `Target directory ${options.projectName} is not empty. Do you want to continue?`, + initialValue: true, + }) + + if (isCancel(shouldContinue) || !shouldContinue) { + cancel('Operation cancelled.') + process.exit(0) + } + } + // Router type selection if (forcedMode) { options.mode = forcedMode diff --git a/packages/cta-cli/src/types.ts b/packages/cta-cli/src/types.ts index 2a732302..6b1ebede 100644 --- a/packages/cta-cli/src/types.ts +++ b/packages/cta-cli/src/types.ts @@ -23,4 +23,5 @@ export interface CliOptions { devWatch?: string install?: boolean addOnConfig?: string + force?: boolean } diff --git a/packages/cta-cli/src/ui-prompts.ts b/packages/cta-cli/src/ui-prompts.ts index 46a6110a..8bb2265b 100644 --- a/packages/cta-cli/src/ui-prompts.ts +++ b/packages/cta-cli/src/ui-prompts.ts @@ -18,7 +18,6 @@ import { validateProjectName } from './utils.js' import type { AddOn, PackageManager } from '@tanstack/cta-engine' import type { Framework } from '@tanstack/cta-engine/dist/types/types.js' -import { InitialData } from '../../cta-ui/src/types' export async function getProjectName(): Promise { const value = await text({