From 1a325cbc8956798e5ff317deaf28fd177256a06d Mon Sep 17 00:00:00 2001 From: Haoqun Jiang Date: Thu, 28 Jul 2022 16:53:48 +0800 Subject: [PATCH 1/7] fix: should use the `display` field as title whenver possible It was an accidental regression introduced in https://github.com/vitejs/vite/pull/3044/files#diff-49c9292bc736c3c8a1e0773acde605b3bf401a488198b2614885b4e8e7cfaa04L220 --- packages/create-vite/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/create-vite/index.js b/packages/create-vite/index.js index 40d0aa583124d3..1fd5181648ff70 100755 --- a/packages/create-vite/index.js +++ b/packages/create-vite/index.js @@ -191,7 +191,7 @@ async function init() { choices: FRAMEWORKS.map((framework) => { const frameworkColor = framework.color return { - title: frameworkColor(framework.name), + title: frameworkColor(framework.display || framework.name), value: framework } }) @@ -206,7 +206,7 @@ async function init() { framework.variants.map((variant) => { const variantColor = variant.color return { - title: variantColor(variant.name), + title: variantColor(variant.display || variant.name), value: variant.name } }) From d5f3198191ec99a554b95049a5f899426f18a3cb Mon Sep 17 00:00:00 2001 From: Haoqun Jiang Date: Thu, 28 Jul 2022 17:04:44 +0800 Subject: [PATCH 2/7] chore: use upper-case display name for frameworks too So that the casing is consistent between frameworks and variants --- packages/create-vite/index.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/create-vite/index.js b/packages/create-vite/index.js index 1fd5181648ff70..4dc11c02540701 100755 --- a/packages/create-vite/index.js +++ b/packages/create-vite/index.js @@ -25,6 +25,7 @@ const cwd = process.cwd() const FRAMEWORKS = [ { name: 'vanilla', + display: 'Vanilla', color: yellow, variants: [ { @@ -41,6 +42,7 @@ const FRAMEWORKS = [ }, { name: 'vue', + display: 'Vue', color: green, variants: [ { @@ -57,6 +59,7 @@ const FRAMEWORKS = [ }, { name: 'react', + display: 'React', color: cyan, variants: [ { @@ -73,6 +76,7 @@ const FRAMEWORKS = [ }, { name: 'preact', + display: 'Preact', color: magenta, variants: [ { @@ -89,6 +93,7 @@ const FRAMEWORKS = [ }, { name: 'lit', + display: 'Lit', color: lightRed, variants: [ { @@ -105,6 +110,7 @@ const FRAMEWORKS = [ }, { name: 'svelte', + display: 'Svelte', color: red, variants: [ { From 6bc8220682d1cdded856923ed422d056e6fbb82b Mon Sep 17 00:00:00 2001 From: Haoqun Jiang Date: Thu, 28 Jul 2022 17:07:07 +0800 Subject: [PATCH 3/7] feat: support more options with custom init commands Added a few convention here: 1. Options with custom init commands should have the name starting with `custom-`; 2. The custom init command can have a placeholder called `TARGET_DIR`, as the target directory for the project to be created in. --- packages/create-vite/index.js | 58 ++++++++++++++++++++++++++++++----- 1 file changed, 51 insertions(+), 7 deletions(-) diff --git a/packages/create-vite/index.js b/packages/create-vite/index.js index 4dc11c02540701..99d8581b57689e 100755 --- a/packages/create-vite/index.js +++ b/packages/create-vite/index.js @@ -4,12 +4,14 @@ import fs from 'node:fs' import path from 'node:path' import { fileURLToPath } from 'node:url' +import { spawnSync } from 'node:child_process' import minimist from 'minimist' import prompts from 'prompts' import { blue, cyan, green, + lightGreen, lightRed, magenta, red, @@ -47,13 +49,25 @@ const FRAMEWORKS = [ variants: [ { name: 'vue', - display: 'JavaScript', + display: 'Basic JavaScript', color: yellow }, { name: 'vue-ts', - display: 'TypeScript', + display: 'Basic TypeScript', color: blue + }, + { + name: 'custom-create-vue', + display: 'Customize with create-vue', + color: green, + customCommand: 'npm create vue@latest TARGET_DIR' + }, + { + name: 'custom-nuxt', + display: 'Nuxt', + color: lightGreen, + customCommand: 'npx nuxi init TARGET_DIR' } ] }, @@ -115,13 +129,19 @@ const FRAMEWORKS = [ variants: [ { name: 'svelte', - display: 'JavaScript', + display: 'Basic JavaScript', color: yellow }, { name: 'svelte-ts', - display: 'TypeScript', + display: 'Basic TypeScript', color: blue + }, + { + name: 'custom-svelte-kit', + display: 'SvelteKit', + color: red, + customCommand: 'npm create svelte@latest TARGET_DIR' } ] } @@ -243,6 +263,33 @@ async function init() { // determine template template = variant || framework || template + const pkgInfo = pkgFromUserAgent(process.env.npm_config_user_agent) + const pkgManager = pkgInfo ? pkgInfo.name : 'npm' + + if (template.startsWith('custom-')) { + const getCustomCommand = (name) => { + for (const f of FRAMEWORKS) { + for (const v of f.variants || []) { + if (v.name === name) { + return v.customCommand + } + } + } + } + const customCommand = getCustomCommand(template) + const fullCustomCommand = customCommand + .replace('TARGET_DIR', targetDir) + .replace(/^npm /, `${pkgManager} `) + // Only yarn doesn't support `@version` in the `create` command + .replace('@latest', () => (pkgManager === 'yarn' ? '' : '@latest')) + + const [command, ...args] = fullCustomCommand.split(' ') + const { status } = spawnSync(command, args, { + stdio: 'inherit' + }) + process.exit(status ?? 0) + } + console.log(`\nScaffolding project in ${root}...`) const templateDir = path.resolve( @@ -275,9 +322,6 @@ async function init() { write('package.json', JSON.stringify(pkg, null, 2)) - const pkgInfo = pkgFromUserAgent(process.env.npm_config_user_agent) - const pkgManager = pkgInfo ? pkgInfo.name : 'npm' - console.log(`\nDone. Now run:\n`) if (root !== cwd) { console.log(` cd ${path.relative(cwd, root)}`) From b42d46080d254d4a5d74bc96c1caa6fd399b64c5 Mon Sep 17 00:00:00 2001 From: Haoqun Jiang Date: Mon, 1 Aug 2022 21:57:17 +0800 Subject: [PATCH 4/7] chore: remove the "Basic" prefix from display names --- packages/create-vite/index.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/create-vite/index.js b/packages/create-vite/index.js index 99d8581b57689e..a26bb610e7495f 100755 --- a/packages/create-vite/index.js +++ b/packages/create-vite/index.js @@ -49,12 +49,12 @@ const FRAMEWORKS = [ variants: [ { name: 'vue', - display: 'Basic JavaScript', + display: 'JavaScript', color: yellow }, { name: 'vue-ts', - display: 'Basic TypeScript', + display: 'TypeScript', color: blue }, { @@ -129,12 +129,12 @@ const FRAMEWORKS = [ variants: [ { name: 'svelte', - display: 'Basic JavaScript', + display: 'JavaScript', color: yellow }, { name: 'svelte-ts', - display: 'Basic TypeScript', + display: 'TypeScript', color: blue }, { From 9847658c2e46846f9889f097a7e435a3410ffe52 Mon Sep 17 00:00:00 2001 From: Haoqun Jiang Date: Tue, 2 Aug 2022 14:01:49 +0800 Subject: [PATCH 5/7] fix: support Windows with `cross-spawn` --- packages/create-vite/index.js | 4 ++-- packages/create-vite/package.json | 1 + pnpm-lock.yaml | 8 ++------ 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/packages/create-vite/index.js b/packages/create-vite/index.js index a26bb610e7495f..f366b92499bd1d 100755 --- a/packages/create-vite/index.js +++ b/packages/create-vite/index.js @@ -4,7 +4,7 @@ import fs from 'node:fs' import path from 'node:path' import { fileURLToPath } from 'node:url' -import { spawnSync } from 'node:child_process' +import spawn from 'cross-spawn' import minimist from 'minimist' import prompts from 'prompts' import { @@ -284,7 +284,7 @@ async function init() { .replace('@latest', () => (pkgManager === 'yarn' ? '' : '@latest')) const [command, ...args] = fullCustomCommand.split(' ') - const { status } = spawnSync(command, args, { + const { status } = spawn.sync(command, args, { stdio: 'inherit' }) process.exit(status ?? 0) diff --git a/packages/create-vite/package.json b/packages/create-vite/package.json index 77ae57a92c60fd..5ec35494d5a90a 100644 --- a/packages/create-vite/package.json +++ b/packages/create-vite/package.json @@ -26,6 +26,7 @@ }, "homepage": "https://github.com/vitejs/vite/tree/main/packages/create-vite#readme", "dependencies": { + "cross-spawn": "^7.0.3", "kolorist": "^1.5.1", "minimist": "^1.2.6", "prompts": "^2.4.2" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 74c0cc0cb09e17..502a334b1bff44 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -128,10 +128,12 @@ importers: packages/create-vite: specifiers: + cross-spawn: ^7.0.3 kolorist: ^1.5.1 minimist: ^1.2.6 prompts: ^2.4.2 dependencies: + cross-spawn: 7.0.3 kolorist: 1.5.1 minimist: 1.2.6 prompts: 2.4.2 @@ -3955,7 +3957,6 @@ packages: path-key: 3.1.1 shebang-command: 2.0.0 which: 2.0.2 - dev: true /crosspath/0.0.8: resolution: {integrity: sha512-IKlS3MpP0fhJ50M6ltyLO7Q4NzwfhafpmolMH0EDKyyaY81HutF2mH4hLpCdm3fKZ/TSTW5qPIdTy62YnefEyQ==} @@ -5814,7 +5815,6 @@ packages: /isexe/2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - dev: true /jiti/1.13.0: resolution: {integrity: sha512-/n9mNxZj/HDSrincJ6RP+L+yXbpnB8FybySBa+IjIaoH9FIxBbrbRT5XUbe8R7zuVM2AQqNMNDDqz0bzx3znOQ==} @@ -6796,7 +6796,6 @@ packages: /path-key/3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} - dev: true /path-key/4.0.0: resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} @@ -7724,7 +7723,6 @@ packages: engines: {node: '>=8'} dependencies: shebang-regex: 3.0.0 - dev: true /shebang-regex/1.0.0: resolution: {integrity: sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=} @@ -7734,7 +7732,6 @@ packages: /shebang-regex/3.0.0: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} - dev: true /shell-exec/1.0.2: resolution: {integrity: sha512-jyVd+kU2X+mWKMmGhx4fpWbPsjvD53k9ivqetutVW/BQ+WIZoDoP4d8vUMGezV6saZsiNoW2f9GIhg9Dondohg==} @@ -8735,7 +8732,6 @@ packages: hasBin: true dependencies: isexe: 2.0.0 - dev: true /wide-align/1.1.5: resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} From a153e9b5b330b3aecd881f031fb4ecee3dbb7ca0 Mon Sep 17 00:00:00 2001 From: Haoqun Jiang Date: Tue, 2 Aug 2022 16:47:56 +0800 Subject: [PATCH 6/7] refactor: replace `npx` with `npm exec` and `yarn/pnpm dlx` --- packages/create-vite/index.js | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/packages/create-vite/index.js b/packages/create-vite/index.js index f366b92499bd1d..1a706a6fcf2792 100755 --- a/packages/create-vite/index.js +++ b/packages/create-vite/index.js @@ -67,7 +67,7 @@ const FRAMEWORKS = [ name: 'custom-nuxt', display: 'Nuxt', color: lightGreen, - customCommand: 'npx nuxi init TARGET_DIR' + customCommand: 'npm exec nuxi init TARGET_DIR' } ] }, @@ -265,6 +265,7 @@ async function init() { const pkgInfo = pkgFromUserAgent(process.env.npm_config_user_agent) const pkgManager = pkgInfo ? pkgInfo.name : 'npm' + const isYarn1 = pkgManager === 'yarn' && pkgInfo?.version.startsWith('1.') if (template.startsWith('custom-')) { const getCustomCommand = (name) => { @@ -279,9 +280,21 @@ async function init() { const customCommand = getCustomCommand(template) const fullCustomCommand = customCommand .replace('TARGET_DIR', targetDir) - .replace(/^npm /, `${pkgManager} `) - // Only yarn doesn't support `@version` in the `create` command - .replace('@latest', () => (pkgManager === 'yarn' ? '' : '@latest')) + .replace(/^npm create/, `${pkgManager} create`) + // Only Yarn 1.x doesn't support `@version` in the `create` command + .replace('@latest', () => (isYarn1 ? '' : '@latest')) + .replace('^npm exec', () => { + // Prefer `pnpm dlx` or `yarn dlx` + if (pkgManager === 'pnpm') { + return 'pnpm dlx' + } + if (pkgManager === 'yarn' && !isYarn1) { + return 'yarn dlx' + } + // Use `npm exec` in all other cases, + // including Yarn 1.x and other custom npm clients. + return 'npm exec' + }) const [command, ...args] = fullCustomCommand.split(' ') const { status } = spawn.sync(command, args, { From 98c6aad33d81f2d31ff6fd79f736f8c8b3d9b934 Mon Sep 17 00:00:00 2001 From: Haoqun Jiang Date: Tue, 2 Aug 2022 19:46:33 +0800 Subject: [PATCH 7/7] fix: typo (should be a regex) --- packages/create-vite/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/create-vite/index.js b/packages/create-vite/index.js index 1a706a6fcf2792..e19f53fe47a794 100755 --- a/packages/create-vite/index.js +++ b/packages/create-vite/index.js @@ -283,7 +283,7 @@ async function init() { .replace(/^npm create/, `${pkgManager} create`) // Only Yarn 1.x doesn't support `@version` in the `create` command .replace('@latest', () => (isYarn1 ? '' : '@latest')) - .replace('^npm exec', () => { + .replace(/^npm exec/, () => { // Prefer `pnpm dlx` or `yarn dlx` if (pkgManager === 'pnpm') { return 'pnpm dlx'