@4399ywkf/cli 0.0.1
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/README.md +28 -0
- package/bin/api.js +32 -0
- package/bin/cli.js +115 -0
- package/bin/templates.js +15 -0
- package/package.json +36 -0
package/README.md
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# 学习搭建cli脚手架
|
|
2
|
+
|
|
3
|
+
## 安装
|
|
4
|
+
|
|
5
|
+
### 全局安装
|
|
6
|
+
```bash
|
|
7
|
+
pnpm install -g @4399ywkf/cli
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
### 使用
|
|
11
|
+
创建模版
|
|
12
|
+
```bash
|
|
13
|
+
@4399ywkf/cli create <name> [-t|--template]
|
|
14
|
+
```
|
|
15
|
+
示例
|
|
16
|
+
```bash
|
|
17
|
+
@4399ywkf/cli create hello-cli -t dumi2-demo
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
### 不全局安装,借助npx
|
|
21
|
+
创建模版
|
|
22
|
+
```bash
|
|
23
|
+
npx @4399ywkf/cli create <name> [-t|--template]
|
|
24
|
+
```
|
|
25
|
+
示例
|
|
26
|
+
```bash
|
|
27
|
+
npx @4399ywkf/cli create hello-cli -template dumi2-demo
|
|
28
|
+
```
|
package/bin/api.js
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// bin/api.js
|
|
2
|
+
const https = require('https')
|
|
3
|
+
|
|
4
|
+
/** 获取用户git仓库列表信息 */
|
|
5
|
+
function getGitReposList(username) {
|
|
6
|
+
return new Promise((resolve, reject) => {
|
|
7
|
+
https.request(`https://api.github.com/users/${username}/repos`, {
|
|
8
|
+
headers: {
|
|
9
|
+
'User-Agent': username
|
|
10
|
+
}
|
|
11
|
+
}, (res) => {
|
|
12
|
+
let data = ''
|
|
13
|
+
res.on('data', (chunk) => {
|
|
14
|
+
data += chunk.toString()
|
|
15
|
+
})
|
|
16
|
+
res.on('end', () => {
|
|
17
|
+
const list = JSON.parse(data)
|
|
18
|
+
resolve(list.map(item => ({ // 组合成模版所需要的name,value结构
|
|
19
|
+
name: item.name,
|
|
20
|
+
value: `https://github.com:${username}/${item.name}`
|
|
21
|
+
})))
|
|
22
|
+
})
|
|
23
|
+
res.on('error', (err) => {
|
|
24
|
+
reject(err)
|
|
25
|
+
})
|
|
26
|
+
}).end()
|
|
27
|
+
})
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
module.exports = {
|
|
31
|
+
getGitReposList
|
|
32
|
+
}
|
package/bin/cli.js
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const program = require("commander")
|
|
3
|
+
const inquirer = require("inquirer")
|
|
4
|
+
const path = require("path")
|
|
5
|
+
const downloadGitRepo = require('download-git-repo')
|
|
6
|
+
const ora = require('ora') // 引入ora
|
|
7
|
+
const fs = require('fs-extra')
|
|
8
|
+
const { exec } = require('child_process');
|
|
9
|
+
|
|
10
|
+
// const templates = require("./templates.js")
|
|
11
|
+
const { getGitReposList } = require('./api.js')
|
|
12
|
+
const package = require("../package.json")
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
function cloneRepository(repoUrl, destination) {
|
|
16
|
+
return new Promise((resolve, reject) => {
|
|
17
|
+
const command = `git clone ${repoUrl} ${destination}`;
|
|
18
|
+
exec(command, (error, stdout, stderr) => {
|
|
19
|
+
if (error) {
|
|
20
|
+
reject(`Error cloning repository: ${stderr}`);
|
|
21
|
+
} else {
|
|
22
|
+
resolve(`Repository cloned successfully: ${stdout}`);
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
program
|
|
30
|
+
.command("create [projectName]")
|
|
31
|
+
.description("创建模版")
|
|
32
|
+
.option('-t, --template <template>', '模版名称')
|
|
33
|
+
.action(async (projectName, options) => {
|
|
34
|
+
const getRepoLoading = ora('获取模版列表...')
|
|
35
|
+
getRepoLoading.start()
|
|
36
|
+
// const templates = await getGitReposList('Emma-Alpha')
|
|
37
|
+
const templates = [
|
|
38
|
+
{
|
|
39
|
+
value: "https://ywgit.gz4399.com/ywkf/subApplicate_demo.git",
|
|
40
|
+
name: "subApplicate_demo"
|
|
41
|
+
}
|
|
42
|
+
]
|
|
43
|
+
|
|
44
|
+
getRepoLoading.succeed('获取模版列表成功!')
|
|
45
|
+
// 1. 从模版列表中找到对应的模版
|
|
46
|
+
let project = templates.find(template => template.name === options.template)
|
|
47
|
+
// 2. 如果匹配到模版就赋值,没有匹配到就是undefined
|
|
48
|
+
let projectTemplate = project ? project.value : undefined
|
|
49
|
+
|
|
50
|
+
// 3. // 如果用户没有传入名称就交互式输入
|
|
51
|
+
if(!projectName) {
|
|
52
|
+
const { name } = await inquirer.prompt({
|
|
53
|
+
type: "input",
|
|
54
|
+
name: "name",
|
|
55
|
+
message: "请输入项目名称:",
|
|
56
|
+
})
|
|
57
|
+
projectName = name // 赋值输入的项目名称
|
|
58
|
+
}
|
|
59
|
+
console.log('项目名称:', projectName)
|
|
60
|
+
|
|
61
|
+
// 4. 如果用户没有传入模版就交互式输入
|
|
62
|
+
if(!projectTemplate) {
|
|
63
|
+
const { template } = await inquirer.prompt({
|
|
64
|
+
type: 'list',
|
|
65
|
+
name: 'template',
|
|
66
|
+
message: '请选择模版:',
|
|
67
|
+
choices: templates // 模版列表
|
|
68
|
+
})
|
|
69
|
+
projectTemplate = template // 赋值选择的项目名称
|
|
70
|
+
}
|
|
71
|
+
console.log('模版:', projectTemplate)
|
|
72
|
+
|
|
73
|
+
// 获取目标文件夹路径
|
|
74
|
+
const dest = path.join(process.cwd(), projectName)
|
|
75
|
+
// 判断文件夹是否存在,存在就交互询问用户是否覆盖
|
|
76
|
+
if(fs.existsSync(dest)) {
|
|
77
|
+
const { force } = await inquirer.prompt({
|
|
78
|
+
type: 'confirm',
|
|
79
|
+
name: 'force',
|
|
80
|
+
message: '目录已存在,是否覆盖?'
|
|
81
|
+
})
|
|
82
|
+
// 如果覆盖就删除文件夹继续往下执行,否的话就退出进程
|
|
83
|
+
force ? fs.removeSync(dest) : process.exit(1)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// 开始loading
|
|
87
|
+
const loading = ora('正在下载模版...')
|
|
88
|
+
loading.start()
|
|
89
|
+
// 5. 开始下载模版
|
|
90
|
+
try {
|
|
91
|
+
const result = await cloneRepository(projectTemplate, dest);
|
|
92
|
+
loading.succeed('创建模版成功!') // 成功loading
|
|
93
|
+
console.log(`\ncd ${projectName}`)
|
|
94
|
+
console.log('npm i')
|
|
95
|
+
console.log('npm start\n')
|
|
96
|
+
} catch (error) {
|
|
97
|
+
loading.fail('创建模版失败:' + error) // 失败loading
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// downloadGitRepo(projectTemplate, dest, (err) => {
|
|
101
|
+
// if (err) {
|
|
102
|
+
// loading.fail('创建模版失败:' + err) // 失败loading
|
|
103
|
+
// } else {
|
|
104
|
+
// loading.succeed('创建模版成功!') // 成功loading
|
|
105
|
+
// console.log(`\ncd ${projectName}`)
|
|
106
|
+
// console.log('npm i')
|
|
107
|
+
// console.log('npm start\n')
|
|
108
|
+
// }
|
|
109
|
+
// })
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
// 定义当前版本
|
|
113
|
+
program.version(`v${package.version}`)
|
|
114
|
+
program.on('--help', () => {}) // 添加--help
|
|
115
|
+
program.parse(process.argv)
|
package/bin/templates.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** 暴露模版代码 */
|
|
2
|
+
module.exports = [
|
|
3
|
+
{
|
|
4
|
+
name: 'webpack5-react-ts',
|
|
5
|
+
value: 'https://github.com:guojiongwei/webpack5-react-ts'
|
|
6
|
+
},
|
|
7
|
+
{
|
|
8
|
+
name: 'react18-vite2-ts',
|
|
9
|
+
value: 'https://github.com:guojiongwei/react18-vite2-ts'
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
name: 'dumi2-demo',
|
|
13
|
+
value: 'https://github.com:guojiongwei/dumi2-demo'
|
|
14
|
+
}
|
|
15
|
+
]
|
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@4399ywkf/cli",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "运维开发部脚手架",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"ywkf-cli": "./bin/cli.js"
|
|
8
|
+
},
|
|
9
|
+
"publishConfig": {
|
|
10
|
+
"access": "public"
|
|
11
|
+
},
|
|
12
|
+
"scripts": {
|
|
13
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
14
|
+
},
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "git+https://github.com/Emma-Alpha/ywkf-cli.git"
|
|
18
|
+
},
|
|
19
|
+
"keywords": [],
|
|
20
|
+
"author": "",
|
|
21
|
+
"license": "ISC",
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"child_process": "^1.0.2",
|
|
24
|
+
"commander": "^10.0.1",
|
|
25
|
+
"download-git-repo": "^3.0.2",
|
|
26
|
+
"fs-extra": "^11.1.1",
|
|
27
|
+
"inquirer": "^8.2.5",
|
|
28
|
+
"ora": "^5.4.1"
|
|
29
|
+
},
|
|
30
|
+
"files": [
|
|
31
|
+
"bin"
|
|
32
|
+
],
|
|
33
|
+
"authors": [
|
|
34
|
+
"ywjszx@4399.com"
|
|
35
|
+
]
|
|
36
|
+
}
|