From e62094fd2704b52d0b58afd5fe1b048eab8ca0b7 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 22 Apr 2024 11:41:28 +1000 Subject: [PATCH 1/5] feat: project name from 1st param with path --- packages/create-vite/src/index.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/create-vite/src/index.ts b/packages/create-vite/src/index.ts index ea22e52c2384a7..ca66dcf5a688ef 100755 --- a/packages/create-vite/src/index.ts +++ b/packages/create-vite/src/index.ts @@ -252,8 +252,7 @@ async function init() { const argTemplate = argv.template || argv.t let targetDir = argTargetDir || defaultTargetDir - const getProjectName = () => - targetDir === '.' ? path.basename(path.resolve()) : targetDir + const getProjectName = () => path.basename(path.resolve(targetDir)) let result: prompts.Answers< 'projectName' | 'overwrite' | 'packageName' | 'framework' | 'variant' From d1416cd8b13a48a34075931cf4adc59aa42dddd2 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 22 Apr 2024 14:46:14 +1000 Subject: [PATCH 2/5] docs: project name param doubles as target folder --- docs/guide/index.md | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/docs/guide/index.md b/docs/guide/index.md index 406d342c2be28f..c75adc2516fc07 100644 --- a/docs/guide/index.md +++ b/docs/guide/index.md @@ -69,7 +69,7 @@ $ bun create vite Then follow the prompts! -You can also directly specify the project name and the template you want to use via additional command line options. For example, to scaffold a Vite + Vue project, run: +You can also directly specify the project name as the first parameter, and then template you want to use via additional command line options. For example, to scaffold a Vite + Vue project, run: ```bash # npm 7+, extra double-dash is needed: @@ -85,6 +85,20 @@ pnpm create vite my-vue-app --template vue bun create vite my-vue-app --template vue ``` +The project name parameter also doubles as the target folder for your new Vite project. So the command: + +```bash +npm create vite@latest my-vue-app -- --template vue +``` + +Will create your new project in the folder ./my-vue-app as a sub-folder of the folder from which you invoked the command, as well as setting its project name to "my-vue-app". If your project name/folder parameter contains a path then the project name will be taken from the deepest level folder of that path. So the the command: + +```bash +npm create vite@latest ./my-sub-folder/my-vue-app -- --template vue +``` + +will create the project in that target folder, but set its project name to just "my-vue-app" again. + See [create-vite](https://github.com/vitejs/vite/tree/main/packages/create-vite) for more details on each supported template: `vanilla`, `vanilla-ts`, `vue`, `vue-ts`, `react`, `react-ts`, `react-swc`, `react-swc-ts`, `preact`, `preact-ts`, `lit`, `lit-ts`, `svelte`, `svelte-ts`, `solid`, `solid-ts`, `qwik`, `qwik-ts`. ## Community Templates From 3bd86922d944cb0a02897f3caae79413ed514210 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 22 Apr 2024 17:19:41 +1000 Subject: [PATCH 3/5] chore: cli test override non-empty with subfolder --- packages/create-vite/__tests__/cli.spec.ts | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/packages/create-vite/__tests__/cli.spec.ts b/packages/create-vite/__tests__/cli.spec.ts index e34d4e14f6e4cf..cb7899dd0da254 100644 --- a/packages/create-vite/__tests__/cli.spec.ts +++ b/packages/create-vite/__tests__/cli.spec.ts @@ -5,24 +5,30 @@ import fs from 'fs-extra' import { afterEach, beforeAll, expect, test } from 'vitest' const CLI_PATH = join(__dirname, '..') +console.log('TCL ~ CLI_PATH:', CLI_PATH) const projectName = 'test-app' const genPath = join(__dirname, projectName) +const genPathWithSubfolder = join(__dirname, 'subfolder', projectName) +console.log('TCL ~ genPathWithSubfolder:', { genPath, genPathWithSubfolder }) const run = ( args: string[], options: SyncOptions = {}, ): ExecaSyncReturnValue => { - return execaCommandSync(`node ${CLI_PATH} ${args.join(' ')}`, options) + const commandToExecute = `node ${CLI_PATH} ${args.join(' ')}` + console.log('TCL ~ commandToExecute:', { commandToExecute, options }) + return execaCommandSync(commandToExecute, options) } // Helper to create a non-empty directory -const createNonEmptyDir = () => { +const createNonEmptyDir = (overrideFolder?: string) => { // Create the temporary directory - fs.mkdirpSync(genPath) + const newNonEmptyFolder = overrideFolder || genPath + fs.mkdirpSync(newNonEmptyFolder) // Create a package.json file - const pkgJson = join(genPath, 'package.json') + const pkgJson = join(newNonEmptyFolder, 'package.json') fs.writeFileSync(pkgJson, '{ "foo": "bar" }') } @@ -70,6 +76,14 @@ test('asks to overwrite non-empty target directory', () => { expect(stdout).toContain(`Target directory "${projectName}" is not empty.`) }) +test('asks to overwrite non-empty target directory with subfolder', () => { + createNonEmptyDir(genPathWithSubfolder) + const { stdout } = run([`subfolder/${projectName}`], { cwd: __dirname }) + expect(stdout).toContain( + `Target directory "subfolder/${projectName}" is not empty.`, + ) +}) + test('asks to overwrite non-empty current directory', () => { createNonEmptyDir() const { stdout } = run(['.'], { cwd: genPath }) From de279e011dcbdf9f8ce5a8cacb1539d16bef98f2 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 22 Apr 2024 17:47:19 +1000 Subject: [PATCH 4/5] chore: new test scaffold react with subfolder --- packages/create-vite/__tests__/cli.spec.ts | 42 +++++++++++++++++++--- 1 file changed, 37 insertions(+), 5 deletions(-) diff --git a/packages/create-vite/__tests__/cli.spec.ts b/packages/create-vite/__tests__/cli.spec.ts index cb7899dd0da254..feb79ee67dc04a 100644 --- a/packages/create-vite/__tests__/cli.spec.ts +++ b/packages/create-vite/__tests__/cli.spec.ts @@ -5,19 +5,16 @@ import fs from 'fs-extra' import { afterEach, beforeAll, expect, test } from 'vitest' const CLI_PATH = join(__dirname, '..') -console.log('TCL ~ CLI_PATH:', CLI_PATH) const projectName = 'test-app' const genPath = join(__dirname, projectName) const genPathWithSubfolder = join(__dirname, 'subfolder', projectName) -console.log('TCL ~ genPathWithSubfolder:', { genPath, genPathWithSubfolder }) const run = ( args: string[], options: SyncOptions = {}, ): ExecaSyncReturnValue => { const commandToExecute = `node ${CLI_PATH} ${args.join(' ')}` - console.log('TCL ~ commandToExecute:', { commandToExecute, options }) return execaCommandSync(commandToExecute, options) } @@ -39,8 +36,32 @@ const templateFiles = fs .map((filePath) => (filePath === '_gitignore' ? '.gitignore' : filePath)) .sort() -beforeAll(() => fs.remove(genPath)) -afterEach(() => fs.remove(genPath)) +// React starter template +const templateFilesReact = fs + .readdirSync(join(CLI_PATH, 'template-react')) + // _gitignore is renamed to .gitignore + .map((filePath) => (filePath === '_gitignore' ? '.gitignore' : filePath)) + .sort() + +// beforeAll(() => fs.remove(genPath)) +// afterEach(() => fs.remove(genPath)) +beforeAll(() => { + if (fs.existsSync(genPath)) { + fs.removeSync(genPath) + } + if (fs.existsSync(genPathWithSubfolder)) { + fs.removeSync(genPathWithSubfolder) + } +}) + +afterEach(() => { + if (fs.existsSync(genPath)) { + fs.removeSync(genPath) + } + if (fs.existsSync(genPathWithSubfolder)) { + fs.removeSync(genPathWithSubfolder) + } +}) test('prompts for the project name if none supplied', () => { const { stdout } = run([]) @@ -101,6 +122,17 @@ test('successfully scaffolds a project based on vue starter template', () => { expect(templateFiles).toEqual(generatedFiles) }) +test('successfully scaffolds a project with subfolder based on react starter template', () => { + const { stdout } = run([`subfolder/${projectName}`, '--template', 'react'], { + cwd: __dirname, + }) + const generatedFiles = fs.readdirSync(genPathWithSubfolder).sort() + + // Assertions + expect(stdout).toContain(`Scaffolding project in ${genPathWithSubfolder}`) + expect(templateFilesReact).toEqual(generatedFiles) +}) + test('works with the -t alias', () => { const { stdout } = run([projectName, '-t', 'vue'], { cwd: __dirname, From 10ccc5d56d1834e94499e8df02256254f1c3110b Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 22 Apr 2024 17:49:37 +1000 Subject: [PATCH 5/5] chore: tidy up --- packages/create-vite/__tests__/cli.spec.ts | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/packages/create-vite/__tests__/cli.spec.ts b/packages/create-vite/__tests__/cli.spec.ts index feb79ee67dc04a..051697a224bbf1 100644 --- a/packages/create-vite/__tests__/cli.spec.ts +++ b/packages/create-vite/__tests__/cli.spec.ts @@ -43,25 +43,17 @@ const templateFilesReact = fs .map((filePath) => (filePath === '_gitignore' ? '.gitignore' : filePath)) .sort() -// beforeAll(() => fs.remove(genPath)) -// afterEach(() => fs.remove(genPath)) -beforeAll(() => { +const clearAnyPreviousFolders = () => { if (fs.existsSync(genPath)) { fs.removeSync(genPath) } if (fs.existsSync(genPathWithSubfolder)) { fs.removeSync(genPathWithSubfolder) } -}) +} -afterEach(() => { - if (fs.existsSync(genPath)) { - fs.removeSync(genPath) - } - if (fs.existsSync(genPathWithSubfolder)) { - fs.removeSync(genPathWithSubfolder) - } -}) +beforeAll(() => clearAnyPreviousFolders()) +afterEach(() => clearAnyPreviousFolders()) test('prompts for the project name if none supplied', () => { const { stdout } = run([])