Skip to content

Commit 1673f3d

Browse files
authored
feat(create-vite): add support for custom init commands (create-vue, Nuxt, and SvelteKit) (#9406)
1 parent 0452224 commit 1673f3d

File tree

3 files changed

+71
-11
lines changed

3 files changed

+71
-11
lines changed

packages/create-vite/index.js

+68-5
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,14 @@
44
import fs from 'node:fs'
55
import path from 'node:path'
66
import { fileURLToPath } from 'node:url'
7+
import spawn from 'cross-spawn'
78
import minimist from 'minimist'
89
import prompts from 'prompts'
910
import {
1011
blue,
1112
cyan,
1213
green,
14+
lightGreen,
1315
lightRed,
1416
magenta,
1517
red,
@@ -25,6 +27,7 @@ const cwd = process.cwd()
2527
const FRAMEWORKS = [
2628
{
2729
name: 'vanilla',
30+
display: 'Vanilla',
2831
color: yellow,
2932
variants: [
3033
{
@@ -41,6 +44,7 @@ const FRAMEWORKS = [
4144
},
4245
{
4346
name: 'vue',
47+
display: 'Vue',
4448
color: green,
4549
variants: [
4650
{
@@ -52,11 +56,24 @@ const FRAMEWORKS = [
5256
name: 'vue-ts',
5357
display: 'TypeScript',
5458
color: blue
59+
},
60+
{
61+
name: 'custom-create-vue',
62+
display: 'Customize with create-vue',
63+
color: green,
64+
customCommand: 'npm create vue@latest TARGET_DIR'
65+
},
66+
{
67+
name: 'custom-nuxt',
68+
display: 'Nuxt',
69+
color: lightGreen,
70+
customCommand: 'npm exec nuxi init TARGET_DIR'
5571
}
5672
]
5773
},
5874
{
5975
name: 'react',
76+
display: 'React',
6077
color: cyan,
6178
variants: [
6279
{
@@ -73,6 +90,7 @@ const FRAMEWORKS = [
7390
},
7491
{
7592
name: 'preact',
93+
display: 'Preact',
7694
color: magenta,
7795
variants: [
7896
{
@@ -89,6 +107,7 @@ const FRAMEWORKS = [
89107
},
90108
{
91109
name: 'lit',
110+
display: 'Lit',
92111
color: lightRed,
93112
variants: [
94113
{
@@ -105,6 +124,7 @@ const FRAMEWORKS = [
105124
},
106125
{
107126
name: 'svelte',
127+
display: 'Svelte',
108128
color: red,
109129
variants: [
110130
{
@@ -116,6 +136,12 @@ const FRAMEWORKS = [
116136
name: 'svelte-ts',
117137
display: 'TypeScript',
118138
color: blue
139+
},
140+
{
141+
name: 'custom-svelte-kit',
142+
display: 'SvelteKit',
143+
color: red,
144+
customCommand: 'npm create svelte@latest TARGET_DIR'
119145
}
120146
]
121147
}
@@ -191,7 +217,7 @@ async function init() {
191217
choices: FRAMEWORKS.map((framework) => {
192218
const frameworkColor = framework.color
193219
return {
194-
title: frameworkColor(framework.name),
220+
title: frameworkColor(framework.display || framework.name),
195221
value: framework
196222
}
197223
})
@@ -206,7 +232,7 @@ async function init() {
206232
framework.variants.map((variant) => {
207233
const variantColor = variant.color
208234
return {
209-
title: variantColor(variant.name),
235+
title: variantColor(variant.display || variant.name),
210236
value: variant.name
211237
}
212238
})
@@ -237,6 +263,46 @@ async function init() {
237263
// determine template
238264
template = variant || framework || template
239265

266+
const pkgInfo = pkgFromUserAgent(process.env.npm_config_user_agent)
267+
const pkgManager = pkgInfo ? pkgInfo.name : 'npm'
268+
const isYarn1 = pkgManager === 'yarn' && pkgInfo?.version.startsWith('1.')
269+
270+
if (template.startsWith('custom-')) {
271+
const getCustomCommand = (name) => {
272+
for (const f of FRAMEWORKS) {
273+
for (const v of f.variants || []) {
274+
if (v.name === name) {
275+
return v.customCommand
276+
}
277+
}
278+
}
279+
}
280+
const customCommand = getCustomCommand(template)
281+
const fullCustomCommand = customCommand
282+
.replace('TARGET_DIR', targetDir)
283+
.replace(/^npm create/, `${pkgManager} create`)
284+
// Only Yarn 1.x doesn't support `@version` in the `create` command
285+
.replace('@latest', () => (isYarn1 ? '' : '@latest'))
286+
.replace(/^npm exec/, () => {
287+
// Prefer `pnpm dlx` or `yarn dlx`
288+
if (pkgManager === 'pnpm') {
289+
return 'pnpm dlx'
290+
}
291+
if (pkgManager === 'yarn' && !isYarn1) {
292+
return 'yarn dlx'
293+
}
294+
// Use `npm exec` in all other cases,
295+
// including Yarn 1.x and other custom npm clients.
296+
return 'npm exec'
297+
})
298+
299+
const [command, ...args] = fullCustomCommand.split(' ')
300+
const { status } = spawn.sync(command, args, {
301+
stdio: 'inherit'
302+
})
303+
process.exit(status ?? 0)
304+
}
305+
240306
console.log(`\nScaffolding project in ${root}...`)
241307

242308
const templateDir = path.resolve(
@@ -269,9 +335,6 @@ async function init() {
269335

270336
write('package.json', JSON.stringify(pkg, null, 2))
271337

272-
const pkgInfo = pkgFromUserAgent(process.env.npm_config_user_agent)
273-
const pkgManager = pkgInfo ? pkgInfo.name : 'npm'
274-
275338
console.log(`\nDone. Now run:\n`)
276339
if (root !== cwd) {
277340
console.log(` cd ${path.relative(cwd, root)}`)

packages/create-vite/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
},
2727
"homepage": "https://github.com/vitejs/vite/tree/main/packages/create-vite#readme",
2828
"dependencies": {
29+
"cross-spawn": "^7.0.3",
2930
"kolorist": "^1.5.1",
3031
"minimist": "^1.2.6",
3132
"prompts": "^2.4.2"

pnpm-lock.yaml

+2-6
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)