create-lve 0.4.28 → 0.4.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +80 -49
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -7,70 +7,101 @@ import path from 'node:path'
|
|
|
7
7
|
import { execSync } from 'node:child_process'
|
|
8
8
|
import { __dirname, applyProjectTransform, cleanupTemplate, installDependencies } from './config.js'
|
|
9
9
|
|
|
10
|
+
const version = JSON.parse(
|
|
11
|
+
fs.readFileSync(new URL('./package.json', import.meta.url), 'utf-8'),
|
|
12
|
+
).version
|
|
13
|
+
|
|
14
|
+
function parseArgs() {
|
|
15
|
+
const args = process.argv.slice(2)
|
|
16
|
+
const flags = {}
|
|
17
|
+
const positional = []
|
|
18
|
+
for (const arg of args) {
|
|
19
|
+
if (arg === '--default') flags.default = true
|
|
20
|
+
else if (!arg.startsWith('-')) positional.push(arg)
|
|
21
|
+
}
|
|
22
|
+
return { flags, positional }
|
|
23
|
+
}
|
|
24
|
+
|
|
10
25
|
function randomName() {
|
|
11
26
|
const hash = Math.random().toString(36).slice(2, 6)
|
|
12
27
|
return `vite-app-${hash}`
|
|
13
28
|
}
|
|
14
29
|
|
|
30
|
+
function onCancel() {
|
|
31
|
+
p.cancel('操作取消')
|
|
32
|
+
process.exit(0)
|
|
33
|
+
}
|
|
34
|
+
|
|
15
35
|
async function main() {
|
|
36
|
+
const { flags, positional } = parseArgs()
|
|
16
37
|
process.stdout.write('\u001b[3J\u001b[2J\u001b[1J')
|
|
17
38
|
console.clear()
|
|
18
39
|
const logo = `
|
|
19
40
|
${pc.cyan('█ █ █ █▀▀▀')}
|
|
20
|
-
${pc.cyan('█ █ █ █▀▀ ')}
|
|
41
|
+
${pc.cyan('█ █ █ █▀▀ ')}
|
|
21
42
|
${pc.cyan('█▄▄▄ ▀▄▀ █▄▄▄')} ${pc.gray('THE ULTRA-FAST FRONTEND STACK')}
|
|
22
43
|
`
|
|
23
44
|
console.log(logo)
|
|
24
|
-
p.intro(`${pc.bgCyan(pc.black(
|
|
25
|
-
|
|
26
|
-
const project = await p.group(
|
|
27
|
-
{
|
|
28
|
-
path: () =>
|
|
29
|
-
p.text({
|
|
30
|
-
message: '项目名称',
|
|
31
|
-
placeholder: 'your-project-name',
|
|
32
|
-
defaultValue: randomName(),
|
|
33
|
-
validate: (value) => {
|
|
34
|
-
if (!value || value.length === 0) return
|
|
35
|
-
if (value.match(/[<>:"|?*]/)) return '路径包含非法字符'
|
|
36
|
-
},
|
|
37
|
-
}),
|
|
38
|
-
|
|
39
|
-
shouldOverwrite: ({ results }) => {
|
|
40
|
-
const targetDir = path.resolve(process.cwd(), results.path)
|
|
41
|
-
if (fs.existsSync(targetDir) && fs.readdirSync(targetDir).length > 0) {
|
|
42
|
-
return p.confirm({ message: `目录已存在,是否清空?`, initialValue: false })
|
|
43
|
-
}
|
|
44
|
-
},
|
|
45
|
+
p.intro(`${pc.bgCyan(pc.black(` LVE-CLI v${version} `))}`)
|
|
45
46
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
47
|
+
let project
|
|
48
|
+
|
|
49
|
+
if (flags.default) {
|
|
50
|
+
// --default: React + Tailwind,跳过所有 prompt
|
|
51
|
+
const name = positional[0] || randomName()
|
|
52
|
+
const targetDir = path.resolve(process.cwd(), name)
|
|
53
|
+
let shouldOverwrite = false
|
|
54
|
+
if (fs.existsSync(targetDir) && fs.readdirSync(targetDir).length > 0) {
|
|
55
|
+
shouldOverwrite = await p.confirm({ message: `目录已存在,是否清空?`, initialValue: false })
|
|
56
|
+
if (p.isCancel(shouldOverwrite)) onCancel()
|
|
57
|
+
}
|
|
58
|
+
project = { path: name, framework: 'react', cssEngine: 'tailwind', shouldOverwrite }
|
|
59
|
+
} else {
|
|
60
|
+
// 交互模式
|
|
61
|
+
project = await p.group(
|
|
62
|
+
{
|
|
63
|
+
path: () =>
|
|
64
|
+
p.text({
|
|
65
|
+
message: '项目名称',
|
|
66
|
+
placeholder: 'your-project-name',
|
|
67
|
+
defaultValue: randomName(),
|
|
68
|
+
validate: (value) => {
|
|
69
|
+
if (!value || value.length === 0) return
|
|
70
|
+
if (value.match(/[<>:"|?*]/)) return '路径包含非法字符'
|
|
71
|
+
},
|
|
72
|
+
}),
|
|
73
|
+
|
|
74
|
+
shouldOverwrite: ({ results }) => {
|
|
75
|
+
const targetDir = path.resolve(process.cwd(), results.path)
|
|
76
|
+
if (fs.existsSync(targetDir) && fs.readdirSync(targetDir).length > 0) {
|
|
77
|
+
return p.confirm({ message: `目录已存在,是否清空?`, initialValue: false })
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
|
|
81
|
+
framework: () =>
|
|
82
|
+
p.select({
|
|
83
|
+
message: '选择框架',
|
|
84
|
+
options: [
|
|
85
|
+
{ value: 'react', label: 'React 19', hint: '' },
|
|
86
|
+
{ value: 'vue', label: 'Vue 3', hint: '' },
|
|
87
|
+
{ value: 'next', label: 'Next.js 16', hint: '' },
|
|
88
|
+
],
|
|
89
|
+
}),
|
|
90
|
+
|
|
91
|
+
cssEngine: ({ results }) =>
|
|
92
|
+
results.framework === 'next'
|
|
93
|
+
? p.note('Next.js 已内置 Tailwind,无需选择')
|
|
94
|
+
: p.select({
|
|
95
|
+
message: '选择 CSS',
|
|
96
|
+
options: [
|
|
97
|
+
{ value: 'tailwind', label: 'Tailwind v4' },
|
|
98
|
+
{ value: 'unocss', label: 'UnoCSS' },
|
|
99
|
+
],
|
|
100
|
+
}),
|
|
71
101
|
},
|
|
72
|
-
|
|
73
|
-
|
|
102
|
+
{ onCancel },
|
|
103
|
+
)
|
|
104
|
+
}
|
|
74
105
|
|
|
75
106
|
const ctx = {
|
|
76
107
|
name: project.path,
|