@gx-design-vue/create-gx-cli 0.1.5 → 0.1.7

Sign up to get free protection for your applications and to get access to all the features.
package/README.md CHANGED
@@ -10,6 +10,15 @@ npm init @gx-design-vue/create-gx-cli
10
10
  npx @gx-design-vue/create-gx-cli
11
11
  # or
12
12
  npm install -g @gx-design-vue/create-gx-cli
13
+
14
+ # create project
13
15
  create-gx-cli
16
+ # cli version
17
+ create-gx-cli -v
18
+ # short create(first: project name、--template: template project)
19
+ create-gx-cli app --template gx-design-pro
20
+ create-gx-cli app --template gx-design-thin
21
+ create-gx-cli app --template mobile-vant-cli
22
+ create-gx-cli app --template mobile-vant-html
14
23
  ```
15
24
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gx-design-vue/create-gx-cli",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
4
4
  "license": "MIT",
5
5
  "description": "a cli to bootstrap gx project",
6
6
  "main": "src/index.js",
@@ -15,14 +15,15 @@
15
15
  "author": "gx12358",
16
16
  "dependencies": {
17
17
  "chalk": "^2.4.2",
18
+ "child_process": "^1.0.2",
18
19
  "esm": "^3.2.18",
20
+ "execa": "^8.0.1",
19
21
  "inquirer": "^6.2.2",
20
22
  "kolorist": "^1.6.0",
21
23
  "listr": "^0.14.3",
22
24
  "minimist": "^1.2.7",
23
25
  "nanospinner": "^1.1.0",
24
26
  "ncp": "^2.0.0",
25
- "obtain-git-repo": "^1.0.2",
26
27
  "prompts": "^2.4.1"
27
28
  },
28
29
  "files": [
package/src/cli.js CHANGED
@@ -1,9 +1,14 @@
1
+ import chalk from 'chalk'
1
2
  import minimist from 'minimist'
2
3
  import prompts from 'prompts'
3
4
  import { yellow, reset, blue, red, green } from 'kolorist'
4
5
  import { createProject } from './main'
5
6
 
6
- const defaultTargetDir = 'gx-cli-project'
7
+ import pag from '../package.json'
8
+
9
+ const { version } = pag
10
+
11
+ const defaultTargetDir = 'vue3-project'
7
12
 
8
13
  const FRAMEWORKS = [
9
14
  {
@@ -37,20 +42,24 @@ function parseArgumentsIntoOptions() {
37
42
  const argTargetDir = formatTargetDir(argv._[0])
38
43
  const argTemplate = argv.template || argv.t
39
44
  return {
45
+ v: argv.v,
40
46
  template: argTemplate,
41
47
  projectName: argTargetDir
42
48
  }
43
49
  }
44
50
 
45
51
  async function promptForMissingOptions(options) {
46
- const answers = await prompts([
47
- {
52
+ const projectNamePrompts = []
53
+ if (!options.projectName) {
54
+ projectNamePrompts.push({
48
55
  type: options.projectName ? null : 'text',
49
56
  name: 'projectName',
50
57
  message: reset('Project name:'),
51
58
  initial: defaultTargetDir
52
- },
53
- {
59
+ })
60
+ }
61
+ if (typeof options.template !== 'string' || !TEMPLATES.includes(options.template)) {
62
+ projectNamePrompts.push({
54
63
  type: 'select',
55
64
  name: 'template',
56
65
  message:
@@ -66,20 +75,36 @@ async function promptForMissingOptions(options) {
66
75
  value: framework
67
76
  }
68
77
  })
69
- }
70
- ])
78
+ })
79
+ }
80
+ let answers = {
81
+ template: {
82
+ name: ''
83
+ },
84
+ projectName: ''
85
+ }
86
+
87
+ if (projectNamePrompts.length) {
88
+ answers = await prompts(projectNamePrompts)
89
+ }
71
90
 
72
91
  return {
73
92
  ...options,
74
- template: options.template || answers.template ? answers.template.name : '',
93
+ template: options.template || (answers.template ? answers.template.name : ''),
75
94
  projectName: options.projectName || answers.projectName || ''
76
95
  }
77
96
  }
78
97
 
79
98
  export async function cli() {
80
99
  let options = parseArgumentsIntoOptions()
100
+ if (options.v) {
101
+ console.log(chalk.whiteBright(version))
102
+ process.exit(1)
103
+ }
81
104
  options = await promptForMissingOptions(options)
82
105
  if (options.template && options.projectName) {
83
106
  await createProject(options)
107
+ } else {
108
+ process.exit(1)
84
109
  }
85
110
  }
package/src/git.js ADDED
@@ -0,0 +1,76 @@
1
+ import { spawn } from 'child_process'
2
+
3
+ function git(opts) {
4
+ return opts.git || 'git'
5
+ }
6
+
7
+ function buildCloneCommand(repo, targetPath, opts) {
8
+ let args = [ 'clone' ]
9
+ const userArgs = opts.args || []
10
+
11
+ if (opts.shallow) {
12
+ if (userArgs.indexOf('--depth') >= 0) {
13
+ throw new Error('\'--depth\' cannot be specified when shallow is set to \'true\'')
14
+ }
15
+ args.push('--depth', '1')
16
+ }
17
+
18
+ if (opts.progress) {
19
+ args.push('--progress')
20
+ }
21
+
22
+ args = args.concat(userArgs)
23
+ args.push('--', repo, targetPath)
24
+
25
+ return [ git(opts), args ]
26
+ }
27
+
28
+ function buildCheckoutCommand(ref, opts) {
29
+ return [ git(opts), [ 'checkout', ref ] ]
30
+ }
31
+
32
+ export function clone(repo, targetPath, opts, onSuccess, onError) {
33
+ const [ cmd, args ] = buildCloneCommand(repo, targetPath, opts)
34
+ const proc = spawn(cmd, args)
35
+
36
+ if (opts.progress) {
37
+ proc.stderr.on('data', (evt) => {
38
+ const line = evt.toString()
39
+ if (line.match(/Receiving objects:\s+(\d+)%/)) {
40
+ opts.progress({
41
+ phase: 'receivingObjects',
42
+ percent: Number(RegExp.$1)
43
+ })
44
+ } else if (line.match(/Resolving deltas:\s+(\d+)%/)) {
45
+ opts.progress({
46
+ phase: 'resolvingDeltas',
47
+ percent: Number(RegExp.$1)
48
+ })
49
+ }
50
+ })
51
+ }
52
+
53
+ proc.on('close', (status) => {
54
+ if (status == 0) {
55
+ if (opts.checkout) {
56
+ _checkout()
57
+ } else {
58
+ onSuccess()
59
+ }
60
+ } else {
61
+ onError(new Error('\'git clone\' failed with status ' + status))
62
+ }
63
+ })
64
+
65
+ function _checkout() {
66
+ const [ cmd, args ] = buildCheckoutCommand(opts.checkout, opts)
67
+ const proc = spawn(cmd, args, { cwd: targetPath })
68
+ proc.on('close', function (status) {
69
+ if (status == 0) {
70
+ onSuccess()
71
+ } else {
72
+ onError(new Error('\'git checkout\' failed with status ' + status))
73
+ }
74
+ })
75
+ }
76
+ }
package/src/main.js CHANGED
@@ -1,23 +1,34 @@
1
1
  import chalk from 'chalk'
2
2
  import fs from 'fs'
3
+ import { reset } from 'kolorist'
4
+ import prompts from 'prompts'
3
5
  import { fileURLToPath } from 'url'
4
6
  import Listr from 'listr'
5
7
  import ncp from 'ncp'
6
8
  import path from 'path'
7
9
  import { promisify } from 'util'
8
10
  import { createSpinner } from 'nanospinner'
9
- import { download } from 'obtain-git-repo'
11
+ import { clone } from './git'
10
12
 
11
13
  const copy = promisify(ncp)
12
14
 
13
15
  const gitRepositoryList = [
14
16
  {
15
17
  name: 'gx-design-pro',
16
- git: 'https://gitee.com/gx12358/vue3-antd-admin.git'
18
+ children: [
19
+ {
20
+ name: 'Gitee',
21
+ url: 'https://gitee.com/gx12358/vue3-antd-admin.git',
22
+ },
23
+ {
24
+ name: 'Github',
25
+ url: 'https://github.com/gx12358/vue3-antd-admin.git',
26
+ }
27
+ ]
17
28
  },
18
29
  {
19
30
  name: 'gx-design-thin',
20
- git: 'https://gitee.com/gx12358/gx-admin-thin.git'
31
+ url: 'https://gitee.com/gx12358/gx-admin-thin.git'
21
32
  }
22
33
  ]
23
34
 
@@ -64,19 +75,35 @@ function doneLog(cwd, root) {
64
75
  if (root !== cwd) {
65
76
  console.log(chalk.blueBright(`cd ${path.relative(cwd, root)}`))
66
77
  }
67
- console.log(chalk.blueBright(`pnpm(yarn、npm) install`))
68
- console.log(chalk.blueBright(`pnpm(yarn、npm) run dev`))
78
+ console.log(chalk.blueBright(`pnpmyarn、npm install`))
79
+ console.log(chalk.blueBright(`pnpmyarn、npm run dev`))
69
80
  console.log()
70
81
  }
71
82
 
83
+ function getProjectName(projectName) {
84
+ return projectName === '.' ? path.basename(path.resolve()) : projectName
85
+ }
86
+
87
+ function download(url, root, projectName) {
88
+ const spinner = createSpinner(`开始下载...${url}`).start()
89
+ // 下载git代码
90
+ clone(`${url}`, root, { clone: true }, async () => {
91
+ await editPackageJson(root, projectName || getProjectName(projectName))
92
+ spinner.success({
93
+ text: '项目创建成功,请依次执行以下命令'
94
+ })
95
+ doneLog(process.cwd(), root)
96
+ },async function (err) {
97
+ console.log(err)
98
+ spinner.error({ text: '下载失败' })
99
+ })
100
+ }
101
+
72
102
  export async function createProject(options) {
73
103
  const cwd = process.cwd()
74
104
 
75
105
  const root = path.join(cwd, options.projectName)
76
106
 
77
- const getProjectName = () =>
78
- options.projectName === '.' ? path.basename(path.resolve()) : options.projectName
79
-
80
107
  const downloadGit = gitRepositoryList.find(el => el.name === options.template)
81
108
 
82
109
  const templateDir = path.resolve(
@@ -103,19 +130,25 @@ export async function createProject(options) {
103
130
  }
104
131
 
105
132
  if (downloadGit) {
106
- const spinner = createSpinner(`开始下载...${downloadGit.git}`).start()
107
- // 下载git代码
108
- download(`direct:${downloadGit.git}`, root, { clone: true }, async function (err) {
109
- if (err) {
110
- spinner.error({ text: '下载失败' })
111
- } else {
112
- await editPackageJson(root, options.projectName || getProjectName())
113
- spinner.success({
114
- text: '项目创建成功,请依次执行以下命令'
115
- })
116
- fs.doneLog(cwd, root)
117
- }
118
- })
133
+ if (downloadGit.children && downloadGit.children.length > 0) {
134
+ prompts([
135
+ {
136
+ type: 'select',
137
+ name: 'url',
138
+ message: reset('Select a Url:'),
139
+ choices: downloadGit.children.map((item) => {
140
+ return {
141
+ title: item.name,
142
+ value: item.url
143
+ }
144
+ })
145
+ }
146
+ ]).then(answers => {
147
+ if (answers.url) download(answers.url, root, options.projectName)
148
+ })
149
+ } else if (downloadGit.url) {
150
+ download(downloadGit.url, root, options.projectName)
151
+ }
119
152
  } else {
120
153
  const tasks = new Listr(
121
154
  [
@@ -125,7 +158,7 @@ export async function createProject(options) {
125
158
  },
126
159
  options.template !== 'mobile-vant-html' ? {
127
160
  title: '初始化项目',
128
- task: () => editPackageJson(root, options.projectName || getProjectName())
161
+ task: () => editPackageJson(root, options.projectName || getProjectName(options.projectName))
129
162
  } : {}
130
163
  ],
131
164
  {
@@ -54,4 +54,4 @@
54
54
  "vite-plugin-vue-setup-extend": "^0.4.0",
55
55
  "vue-tsc": "^1.8.27"
56
56
  }
57
- }
57
+ }