@mpxjs/cli 3.1.1 → 3.3.0
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/.release-it.js +13 -0
- package/README.md +2 -4
- package/__tests__/preset.spec.js +206 -0
- package/bin/mpx.js +85 -113
- package/env/index.js +7 -0
- package/lib/create.js +201 -0
- package/lib/info.js +19 -0
- package/lib/inspect.js +36 -0
- package/lib/preset.js +6 -6
- package/lib/prompts.js +53 -11
- package/package.json +20 -12
- package/utils/index.js +27 -0
- package/lib/plugins.js +0 -27
package/.release-it.js
ADDED
package/README.md
CHANGED
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
jest.mock('inquirer')
|
|
2
|
+
|
|
3
|
+
const path = require('path')
|
|
4
|
+
const fs = require('fs')
|
|
5
|
+
const create = require('@mpxjs/cli/lib/create')
|
|
6
|
+
|
|
7
|
+
test('normal', async () => {
|
|
8
|
+
const cwd = path.resolve(__dirname, '../../test')
|
|
9
|
+
const name = 'test-normal'
|
|
10
|
+
await create(
|
|
11
|
+
name,
|
|
12
|
+
{
|
|
13
|
+
force: true,
|
|
14
|
+
git: false,
|
|
15
|
+
cwd
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
srcMode: 'wx',
|
|
19
|
+
appid: 'test',
|
|
20
|
+
description: 'test',
|
|
21
|
+
cross: true,
|
|
22
|
+
plugins: {},
|
|
23
|
+
useConfigFiles: true
|
|
24
|
+
}
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
const pkg = require(path.resolve(cwd, name, 'package.json'))
|
|
28
|
+
expect(pkg.devDependencies).toHaveProperty('@mpxjs/vue-cli-plugin-mpx')
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* 非跨平台项目不生成static/ali目录
|
|
33
|
+
*/
|
|
34
|
+
test('normal-nocross', async () => {
|
|
35
|
+
const cwd = path.resolve(__dirname, '../../test')
|
|
36
|
+
const name = 'normal-nocross'
|
|
37
|
+
await create(
|
|
38
|
+
name,
|
|
39
|
+
{
|
|
40
|
+
force: true,
|
|
41
|
+
git: false,
|
|
42
|
+
cwd
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
srcMode: 'wx',
|
|
46
|
+
appid: 'test',
|
|
47
|
+
description: 'test',
|
|
48
|
+
cross: false,
|
|
49
|
+
plugins: {},
|
|
50
|
+
useConfigFiles: true
|
|
51
|
+
}
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
const staticAliDir = fs.existsSync(path.resolve(cwd, name, 'static/ali'))
|
|
55
|
+
expect(staticAliDir).toBe(false)
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
test('test-ts', async () => {
|
|
59
|
+
const cwd = path.resolve(__dirname, '../../test')
|
|
60
|
+
const name = 'test-ts'
|
|
61
|
+
await create(
|
|
62
|
+
name,
|
|
63
|
+
{
|
|
64
|
+
force: true,
|
|
65
|
+
git: false,
|
|
66
|
+
cwd
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
srcMode: 'wx',
|
|
70
|
+
appid: 'test',
|
|
71
|
+
description: 'test',
|
|
72
|
+
cross: true,
|
|
73
|
+
needTs: true,
|
|
74
|
+
plugins: {},
|
|
75
|
+
useConfigFiles: true
|
|
76
|
+
}
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
const pkg = require(path.resolve(cwd, name, 'package.json'))
|
|
80
|
+
expect(pkg.devDependencies).toHaveProperty('@mpxjs/vue-cli-plugin-mpx-typescript')
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
test('test-cloud-func', async () => {
|
|
84
|
+
const cwd = path.resolve(__dirname, '../../test')
|
|
85
|
+
const name = 'test-cloud-func'
|
|
86
|
+
await create(
|
|
87
|
+
name,
|
|
88
|
+
{
|
|
89
|
+
force: true,
|
|
90
|
+
git: false,
|
|
91
|
+
cwd
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
srcMode: 'wx',
|
|
95
|
+
appid: 'test',
|
|
96
|
+
description: 'test',
|
|
97
|
+
cross: true,
|
|
98
|
+
cloudFunc: true,
|
|
99
|
+
plugins: {},
|
|
100
|
+
useConfigFiles: true
|
|
101
|
+
}
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
const pkg = require(path.resolve(cwd, name, 'package.json'))
|
|
105
|
+
expect(pkg.devDependencies).toHaveProperty('@mpxjs/vue-cli-plugin-mpx-cloud-func')
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
test('test-cloud-func', async () => {
|
|
109
|
+
const cwd = path.resolve(__dirname, '../../test')
|
|
110
|
+
const name = 'test-cloud-func'
|
|
111
|
+
await create(
|
|
112
|
+
name,
|
|
113
|
+
{
|
|
114
|
+
force: true,
|
|
115
|
+
git: false,
|
|
116
|
+
cwd
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
srcMode: 'wx',
|
|
120
|
+
appid: 'test',
|
|
121
|
+
description: 'test',
|
|
122
|
+
cross: true,
|
|
123
|
+
cloudFunc: true,
|
|
124
|
+
plugins: {},
|
|
125
|
+
useConfigFiles: true
|
|
126
|
+
}
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
const pkg = require(path.resolve(cwd, name, 'package.json'))
|
|
130
|
+
expect(pkg.devDependencies).toHaveProperty('@mpxjs/vue-cli-plugin-mpx-cloud-func')
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
test('test-plugin', async () => {
|
|
134
|
+
const cwd = path.resolve(__dirname, '../../test')
|
|
135
|
+
const name = 'test-plugin'
|
|
136
|
+
await create(
|
|
137
|
+
name,
|
|
138
|
+
{
|
|
139
|
+
force: true,
|
|
140
|
+
git: false,
|
|
141
|
+
cwd
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
srcMode: 'wx',
|
|
145
|
+
appid: 'test',
|
|
146
|
+
description: 'test',
|
|
147
|
+
cross: true,
|
|
148
|
+
isPlugin: true,
|
|
149
|
+
plugins: {},
|
|
150
|
+
useConfigFiles: true
|
|
151
|
+
}
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
const pkg = require(path.resolve(cwd, name, 'package.json'))
|
|
155
|
+
expect(pkg.devDependencies).toHaveProperty('@mpxjs/vue-cli-plugin-mpx-plugin-mode')
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
test('test-unit', async () => {
|
|
159
|
+
const cwd = path.resolve(__dirname, '../../test')
|
|
160
|
+
const name = 'test-unit'
|
|
161
|
+
await create(
|
|
162
|
+
name,
|
|
163
|
+
{
|
|
164
|
+
force: true,
|
|
165
|
+
git: false,
|
|
166
|
+
cwd
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
srcMode: 'wx',
|
|
170
|
+
appid: 'test',
|
|
171
|
+
description: 'test',
|
|
172
|
+
cross: true,
|
|
173
|
+
needUnitTest: true,
|
|
174
|
+
plugins: {},
|
|
175
|
+
useConfigFiles: true
|
|
176
|
+
}
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
const pkg = require(path.resolve(cwd, name, 'package.json'))
|
|
180
|
+
expect(pkg.devDependencies).toHaveProperty('@mpxjs/vue-cli-plugin-mpx-unit-test')
|
|
181
|
+
})
|
|
182
|
+
|
|
183
|
+
test('test-e2e', async () => {
|
|
184
|
+
const cwd = path.resolve(__dirname, '../../test')
|
|
185
|
+
const name = 'test-e2e'
|
|
186
|
+
await create(
|
|
187
|
+
name,
|
|
188
|
+
{
|
|
189
|
+
force: true,
|
|
190
|
+
git: false,
|
|
191
|
+
cwd
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
srcMode: 'wx',
|
|
195
|
+
appid: 'test',
|
|
196
|
+
description: 'test',
|
|
197
|
+
cross: true,
|
|
198
|
+
needE2ETest: true,
|
|
199
|
+
plugins: {},
|
|
200
|
+
useConfigFiles: true
|
|
201
|
+
}
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
const pkg = require(path.resolve(cwd, name, 'package.json'))
|
|
205
|
+
expect(pkg.devDependencies).toHaveProperty('@mpxjs/vue-cli-plugin-mpx-e2e-test')
|
|
206
|
+
})
|
package/bin/mpx.js
CHANGED
|
@@ -1,127 +1,99 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
const path = require('path')
|
|
4
|
-
const execa = require('execa')
|
|
2
|
+
const program = require('commander')
|
|
5
3
|
const minimist = require('minimist')
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
const inquirer = require('inquirer')
|
|
9
|
-
const prompts = require('../lib/prompts')
|
|
10
|
-
const plugins = require('../lib/plugins')
|
|
11
|
-
const loadRemotePreset = require('@vue/cli/lib/util/loadRemotePreset')
|
|
12
|
-
const loadLocalPreset = require('@vue/cli/lib/util/loadLocalPreset')
|
|
13
|
-
const {
|
|
14
|
-
chalk,
|
|
15
|
-
exit,
|
|
16
|
-
error,
|
|
17
|
-
log
|
|
18
|
-
} = require('@vue/cli-shared-utils')
|
|
19
|
-
const merge = require('lodash.merge')
|
|
4
|
+
const { doVueCli } = require('../utils')
|
|
5
|
+
const { chalk } = require('@vue/cli-shared-utils')
|
|
20
6
|
|
|
21
|
-
|
|
22
|
-
|
|
7
|
+
program
|
|
8
|
+
.version(`@mpx/cli ${require('../package').version}`)
|
|
9
|
+
.usage('<command> [options]')
|
|
23
10
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
11
|
+
program.command('create <app-name>')
|
|
12
|
+
.description('create a new project powered by mpx-cli-service')
|
|
13
|
+
.option(
|
|
14
|
+
'-p, --preset <presetName>',
|
|
15
|
+
'Skip prompts and use saved or remote preset'
|
|
16
|
+
)
|
|
17
|
+
.option('-d, --default', 'Skip prompts and use default preset')
|
|
18
|
+
.option(
|
|
19
|
+
'-i, --inlinePreset <json>',
|
|
20
|
+
'Skip prompts and use inline JSON string as preset'
|
|
21
|
+
)
|
|
22
|
+
.option(
|
|
23
|
+
'-m, --packageManager <command>',
|
|
24
|
+
'Use specified npm client when installing dependencies'
|
|
25
|
+
)
|
|
26
|
+
.option(
|
|
27
|
+
'-r, --registry <url>',
|
|
28
|
+
'Use specified npm registry when installing dependencies (only for npm)'
|
|
29
|
+
)
|
|
30
|
+
.option(
|
|
31
|
+
'-g, --git [message]',
|
|
32
|
+
'Force git initialization with initial commit message'
|
|
33
|
+
)
|
|
34
|
+
.option('-n, --no-git', 'Skip git initialization')
|
|
35
|
+
.option('-f, --force', 'Overwrite target directory if it exists')
|
|
36
|
+
.option('--merge', 'Merge target directory if it exists')
|
|
37
|
+
.option('-c, --clone', 'Use git clone when fetching remote preset')
|
|
38
|
+
.option('-x, --proxy <proxyUrl>', 'Use specified proxy when creating project')
|
|
39
|
+
.option('-b, --bare', 'Scaffold project without beginner instructions')
|
|
40
|
+
.action(async (appName, options) => {
|
|
41
|
+
if (minimist(process.argv.slice(3))._.length > 1) {
|
|
42
|
+
console.log(chalk.yellow('\n Info: You provided more than one argument. The first one will be used as the app\'s name, the rest are ignored.'))
|
|
41
43
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
try {
|
|
46
|
-
res = JSON.parse(cliPreset)
|
|
47
|
-
} catch (e) {
|
|
48
|
-
error(`CLI inline preset is not valid JSON: ${cliPreset}`);
|
|
49
|
-
exit(1)
|
|
44
|
+
// --git makes commander to default git to true
|
|
45
|
+
if (process.argv.includes('-g') || process.argv.includes('--git')) {
|
|
46
|
+
options.forceGit = true
|
|
50
47
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
async function resolvePrompts(name, builtInPreset) {
|
|
56
|
-
return new Promise(function(resolve) {
|
|
57
|
-
inquirer.prompt(prompts).then(answers => {
|
|
58
|
-
if (answers.needTs) {
|
|
59
|
-
Object.assign(builtInPreset.plugins, plugins.tsSupport)
|
|
60
|
-
}
|
|
61
|
-
if (answers.cloudFunc) {
|
|
62
|
-
Object.assign(builtInPreset.plugins, plugins.cloudFunc)
|
|
63
|
-
}
|
|
64
|
-
if (answers.isPlugin) {
|
|
65
|
-
Object.assign(builtInPreset.plugins, plugins.isPlugin)
|
|
66
|
-
}
|
|
67
|
-
if (answers.transWeb) {
|
|
68
|
-
Object.assign(builtInPreset.plugins, plugins.transWeb)
|
|
69
|
-
}
|
|
70
|
-
// TODO: 添加其他 prompt 插件配置
|
|
71
|
-
|
|
72
|
-
// 各插件共享 answers 配置
|
|
73
|
-
Object.keys(builtInPreset.plugins).forEach(function(key) {
|
|
74
|
-
let plugin = builtInPreset.plugins[key]
|
|
75
|
-
plugin = Object.assign(plugin, {
|
|
76
|
-
...answers,
|
|
77
|
-
name
|
|
78
|
-
})
|
|
79
|
-
})
|
|
48
|
+
return require('../lib/create')(appName, options)
|
|
49
|
+
})
|
|
80
50
|
|
|
81
|
-
|
|
82
|
-
|
|
51
|
+
program
|
|
52
|
+
.command('add <plugin> [pluginOptions]')
|
|
53
|
+
.description('install a plugin and invoke its generator in an already created project')
|
|
54
|
+
.option('--registry <url>', 'Use specified npm registry when installing dependencies (only for npm)')
|
|
55
|
+
.allowUnknownOption()
|
|
56
|
+
.action((plugin) => {
|
|
57
|
+
doVueCli(process.argv.slice(2))
|
|
83
58
|
})
|
|
84
|
-
}
|
|
85
59
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
}
|
|
60
|
+
program
|
|
61
|
+
.command('invoke <plugin> [pluginOptions]')
|
|
62
|
+
.description('invoke the generator of a plugin in an already created project')
|
|
63
|
+
.option('--registry <url>', 'Use specified npm registry when installing dependencies (only for npm)')
|
|
64
|
+
.allowUnknownOption()
|
|
65
|
+
.action(() => {
|
|
66
|
+
doVueCli(process.argv.slice(2))
|
|
94
67
|
})
|
|
95
|
-
return cmd
|
|
96
|
-
}
|
|
97
68
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
69
|
+
program
|
|
70
|
+
.command('inspect [paths...]')
|
|
71
|
+
.description('inspect the webpack config in a project with mpx-cli-service')
|
|
72
|
+
.option('--mode <mode>')
|
|
73
|
+
.option('--targets <targets>')
|
|
74
|
+
.option('--env <env>', 'custom define __mpx_env__')
|
|
75
|
+
.option('-v --verbose', 'Show full function definitions in output')
|
|
76
|
+
.action((paths, options) => {
|
|
77
|
+
require('../lib/inspect')(paths, options)
|
|
78
|
+
})
|
|
104
79
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
80
|
+
program
|
|
81
|
+
.command('config [value]')
|
|
82
|
+
.description('inspect and modify the config')
|
|
83
|
+
.option('-g, --get <path>', 'get value from option')
|
|
84
|
+
.option('-s, --set <path> <value>', 'set option value')
|
|
85
|
+
.option('-d, --delete <path>', 'delete option from config')
|
|
86
|
+
.option('-e, --edit', 'open config with default editor')
|
|
87
|
+
.option('--json', 'outputs JSON result only')
|
|
88
|
+
.action((value, options) => {
|
|
89
|
+
doVueCli(process.argv.slice(2))
|
|
90
|
+
})
|
|
108
91
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
}
|
|
92
|
+
program
|
|
93
|
+
.command('info')
|
|
94
|
+
.description('print debugging information about your environment')
|
|
95
|
+
.action((cmd) => {
|
|
96
|
+
require('../lib/info')()
|
|
97
|
+
})
|
|
115
98
|
|
|
116
|
-
|
|
117
|
-
execa(
|
|
118
|
-
'node',
|
|
119
|
-
[
|
|
120
|
-
vueCliBinPath,
|
|
121
|
-
...args
|
|
122
|
-
],
|
|
123
|
-
{
|
|
124
|
-
stdio: 'inherit'
|
|
125
|
-
}
|
|
126
|
-
)
|
|
127
|
-
}
|
|
99
|
+
program.parse(process.argv)
|
package/env/index.js
ADDED
package/lib/create.js
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
const path = require('path')
|
|
2
|
+
const inquirer = require('inquirer')
|
|
3
|
+
const fs = require('fs-extra')
|
|
4
|
+
const validateProjectName = require('validate-npm-package-name')
|
|
5
|
+
const {
|
|
6
|
+
chalk,
|
|
7
|
+
exit,
|
|
8
|
+
error,
|
|
9
|
+
log,
|
|
10
|
+
stopSpinner
|
|
11
|
+
} = require('@vue/cli-shared-utils')
|
|
12
|
+
const Creator = require('@vue/cli/lib/Creator')
|
|
13
|
+
const loadRemotePreset = require('@vue/cli/lib/util/loadRemotePreset')
|
|
14
|
+
const loadLocalPreset = require('@vue/cli/lib/util/loadLocalPreset')
|
|
15
|
+
const { getPromptModules } = require('@vue/cli/lib/util/createTools')
|
|
16
|
+
const { clearConsole } = require('@vue/cli/lib/util/clearConsole')
|
|
17
|
+
const { linkBin } = require('@vue/cli/lib/util/linkBin')
|
|
18
|
+
const merge = require('lodash.merge')
|
|
19
|
+
const prompts = require('./prompts')
|
|
20
|
+
const builtInPreset = require('./preset')
|
|
21
|
+
|
|
22
|
+
async function resolvePreset (args = {}) {
|
|
23
|
+
const { p, preset, c, clone } = args
|
|
24
|
+
let res = {}
|
|
25
|
+
let cliPreset = {}
|
|
26
|
+
if (p || preset) {
|
|
27
|
+
// mpx create foo --preset bar
|
|
28
|
+
cliPreset = p || preset
|
|
29
|
+
if (
|
|
30
|
+
cliPreset.endsWith('.json') ||
|
|
31
|
+
/^\./.test(cliPreset) ||
|
|
32
|
+
path.isAbsolute(cliPreset)
|
|
33
|
+
) {
|
|
34
|
+
res = await loadLocalPreset(path.resolve(cliPreset))
|
|
35
|
+
} else if (cliPreset.includes('/')) {
|
|
36
|
+
try {
|
|
37
|
+
log(`Fetching remote preset ${chalk.cyan(cliPreset)}...`)
|
|
38
|
+
res = await loadRemotePreset(cliPreset, c || clone)
|
|
39
|
+
} catch (e) {
|
|
40
|
+
error(`Failed fetching remote preset ${chalk.cyan(cliPreset)}:`)
|
|
41
|
+
throw e
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return res
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
async function resolvePrompts () {
|
|
49
|
+
return inquirer.prompt(prompts).then((answers) => answers)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* 从vue-cli clone 下来,方便处理creator的创建以及生命周期管理
|
|
54
|
+
* @param {*} projectName
|
|
55
|
+
* @param {*} options
|
|
56
|
+
* @param {*} preset
|
|
57
|
+
* @returns
|
|
58
|
+
*/
|
|
59
|
+
async function create (projectName, options, preset = null) {
|
|
60
|
+
// resolve preset
|
|
61
|
+
if (!preset) {
|
|
62
|
+
if (options.preset) {
|
|
63
|
+
preset = await resolvePreset(options)
|
|
64
|
+
} else if (options.inlinePreset) {
|
|
65
|
+
try {
|
|
66
|
+
preset = JSON.parse(options.inlinePreset)
|
|
67
|
+
} catch (error) {
|
|
68
|
+
error(`CLI inline preset is not valid JSON: ${options.inlinePreset}`)
|
|
69
|
+
exit(1)
|
|
70
|
+
}
|
|
71
|
+
} else {
|
|
72
|
+
preset = await resolvePrompts()
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
// css preprocessor
|
|
76
|
+
preset.cssPreprocessor = 'stylus'
|
|
77
|
+
|
|
78
|
+
// mpx cli 插件
|
|
79
|
+
preset.plugins = Object.assign(
|
|
80
|
+
{},
|
|
81
|
+
preset.plugins,
|
|
82
|
+
builtInPreset.plugins
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
// 合并问答中的preset
|
|
86
|
+
prompts.forEach(v => {
|
|
87
|
+
if (preset[v.name]) {
|
|
88
|
+
merge(preset, v.preset)
|
|
89
|
+
}
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
// 设置代理
|
|
93
|
+
if (options.proxy) {
|
|
94
|
+
process.env.HTTP_PROXY = options.proxy
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const cwd = options.cwd || process.cwd()
|
|
98
|
+
const inCurrent = projectName === '.'
|
|
99
|
+
const name = inCurrent ? path.relative('../', cwd) : projectName
|
|
100
|
+
const targetDir = path.resolve(cwd, projectName || '.')
|
|
101
|
+
|
|
102
|
+
const result = validateProjectName(name)
|
|
103
|
+
if (!result.validForNewPackages) {
|
|
104
|
+
console.error(chalk.red(`Invalid project name: "${name}"`))
|
|
105
|
+
result.errors &&
|
|
106
|
+
result.errors.forEach((err) => {
|
|
107
|
+
console.error(chalk.red.dim('Error: ' + err))
|
|
108
|
+
})
|
|
109
|
+
result.warnings &&
|
|
110
|
+
result.warnings.forEach((warn) => {
|
|
111
|
+
console.error(chalk.red.dim('Warning: ' + warn))
|
|
112
|
+
})
|
|
113
|
+
exit(1)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (fs.existsSync(targetDir) && !options.merge) {
|
|
117
|
+
if (options.force) {
|
|
118
|
+
await fs.remove(targetDir)
|
|
119
|
+
} else {
|
|
120
|
+
await clearConsole()
|
|
121
|
+
if (inCurrent) {
|
|
122
|
+
const { ok } = await inquirer.prompt([
|
|
123
|
+
{
|
|
124
|
+
name: 'ok',
|
|
125
|
+
type: 'confirm',
|
|
126
|
+
message: 'Generate project in current directory?'
|
|
127
|
+
}
|
|
128
|
+
])
|
|
129
|
+
if (!ok) {
|
|
130
|
+
return
|
|
131
|
+
}
|
|
132
|
+
} else {
|
|
133
|
+
const { action } = await inquirer.prompt([
|
|
134
|
+
{
|
|
135
|
+
name: 'action',
|
|
136
|
+
type: 'list',
|
|
137
|
+
message: `Target directory ${chalk.cyan(
|
|
138
|
+
targetDir
|
|
139
|
+
)} already exists. Pick an action:`,
|
|
140
|
+
choices: [
|
|
141
|
+
{ name: 'Overwrite', value: 'overwrite' },
|
|
142
|
+
{ name: 'Merge', value: 'merge' },
|
|
143
|
+
{ name: 'Cancel', value: false }
|
|
144
|
+
]
|
|
145
|
+
}
|
|
146
|
+
])
|
|
147
|
+
if (!action) {
|
|
148
|
+
return
|
|
149
|
+
} else if (action === 'overwrite') {
|
|
150
|
+
console.log(`\nRemoving ${chalk.cyan(targetDir)}...`)
|
|
151
|
+
await fs.remove(targetDir)
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
Object.keys(preset.plugins).forEach(function (key) {
|
|
158
|
+
const plugin = preset.plugins[key]
|
|
159
|
+
Object.assign(plugin, {
|
|
160
|
+
srcMode: preset.srcMode,
|
|
161
|
+
appid: preset.appid,
|
|
162
|
+
description: preset.description,
|
|
163
|
+
needE2ETest: preset.needE2ETest,
|
|
164
|
+
needUnitTest: preset.needUnitTest,
|
|
165
|
+
needTs: preset.needTs,
|
|
166
|
+
isPlugin: preset.isPlugin,
|
|
167
|
+
cloudFunc: preset.cloudFunc,
|
|
168
|
+
cross: preset.cross,
|
|
169
|
+
name
|
|
170
|
+
})
|
|
171
|
+
})
|
|
172
|
+
|
|
173
|
+
const creator = new Creator(name, targetDir, getPromptModules())
|
|
174
|
+
|
|
175
|
+
if (process.env.VUE_CLI_TEST || process.env.VUE_CLI_DEBUG) {
|
|
176
|
+
// 单测下,link bin文件到源码
|
|
177
|
+
creator.on('creation', ({ event }) => {
|
|
178
|
+
if (event === 'plugins-install') {
|
|
179
|
+
linkBin(
|
|
180
|
+
require.resolve('@mpxjs/mpx-cli-service/bin/mpx-cli-service'),
|
|
181
|
+
path.join(targetDir, 'node_modules', '.bin', 'mpx-cli-service')
|
|
182
|
+
)
|
|
183
|
+
}
|
|
184
|
+
})
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
await creator.create({
|
|
188
|
+
...options,
|
|
189
|
+
inlinePreset: JSON.stringify(preset)
|
|
190
|
+
})
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
module.exports = function (...args) {
|
|
194
|
+
return create(...args).catch((err) => {
|
|
195
|
+
stopSpinner(false) // do not persist
|
|
196
|
+
error(err)
|
|
197
|
+
if (!process.env.VUE_CLI_TEST) {
|
|
198
|
+
process.exit(1)
|
|
199
|
+
}
|
|
200
|
+
})
|
|
201
|
+
}
|
package/lib/info.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
const { chalk } = require('@vue/cli-shared-utils')
|
|
2
|
+
|
|
3
|
+
module.exports = function () {
|
|
4
|
+
console.log(chalk.bold('\nEnvironment Info:'))
|
|
5
|
+
require('envinfo').run(
|
|
6
|
+
{
|
|
7
|
+
System: ['OS', 'CPU'],
|
|
8
|
+
Binaries: ['Node', 'Yarn', 'npm'],
|
|
9
|
+
Browsers: ['Chrome', 'Edge', 'Firefox', 'Safari'],
|
|
10
|
+
npmPackages: '/**/{typescript,*vue*,@vue/*/,*mpx*,@mpxjs/*/}',
|
|
11
|
+
npmGlobalPackages: ['@vue/cli', '@mpxjs/cli']
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
showNotFound: true,
|
|
15
|
+
duplicates: true,
|
|
16
|
+
fullTree: true
|
|
17
|
+
}
|
|
18
|
+
).then(console.log)
|
|
19
|
+
}
|
package/lib/inspect.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
const fs = require('fs')
|
|
2
|
+
const path = require('path')
|
|
3
|
+
const resolve = require('resolve')
|
|
4
|
+
const { execa } = require('@vue/cli-shared-utils')
|
|
5
|
+
|
|
6
|
+
module.exports = function inspect (paths, args) {
|
|
7
|
+
const cwd = process.cwd()
|
|
8
|
+
let servicePath
|
|
9
|
+
try {
|
|
10
|
+
servicePath = resolve.sync('@mpxjs/mpx-cli-service', { basedir: cwd })
|
|
11
|
+
} catch (e) {
|
|
12
|
+
const { error } = require('@vue/cli-shared-utils')
|
|
13
|
+
error(
|
|
14
|
+
'Failed to locate @mpxjs/mpx-cli-service.\n' +
|
|
15
|
+
'Note that `mpx inspect` is an alias of `@mpxjs/mpx-cli-service inspect`\n' +
|
|
16
|
+
'and can only be used in a project where @mpxjs/mpx-cli-service is locally installed.'
|
|
17
|
+
)
|
|
18
|
+
process.exit(1)
|
|
19
|
+
}
|
|
20
|
+
const binPath = path.resolve(servicePath, '../../bin/mpx-cli-service.js')
|
|
21
|
+
if (fs.existsSync(binPath)) {
|
|
22
|
+
execa('node', [
|
|
23
|
+
binPath,
|
|
24
|
+
'inspect',
|
|
25
|
+
...(args.mode ? ['--mode', args.mode] : []),
|
|
26
|
+
...(args.targets ? ['--targets', args.targets] : []),
|
|
27
|
+
...(args.env ? ['--env', args.env] : []),
|
|
28
|
+
...(args.rule ? ['--rule', args.rule] : []),
|
|
29
|
+
...(args.plugin ? ['--plugin', args.plugin] : []),
|
|
30
|
+
...(args.rules ? ['--rules'] : []),
|
|
31
|
+
...(args.plugins ? ['--plugins'] : []),
|
|
32
|
+
...(args.verbose ? ['--verbose'] : []),
|
|
33
|
+
...paths
|
|
34
|
+
], { cwd, stdio: 'inherit' })
|
|
35
|
+
}
|
|
36
|
+
}
|
package/lib/preset.js
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 默认preset
|
|
3
|
+
*/
|
|
1
4
|
module.exports = {
|
|
2
5
|
cssPreprocessor: 'stylus',
|
|
3
6
|
plugins: {
|
|
4
7
|
'@mpxjs/mpx-cli-service': {
|
|
5
|
-
version: '^
|
|
8
|
+
version: '^2.0.0'
|
|
6
9
|
},
|
|
7
10
|
'@mpxjs/vue-cli-plugin-mpx': {
|
|
8
|
-
version: '^
|
|
9
|
-
},
|
|
10
|
-
'@mpxjs/vue-cli-plugin-mpx-mp': {
|
|
11
|
-
version: '^1.0.0'
|
|
11
|
+
version: '^2.0.0'
|
|
12
12
|
},
|
|
13
13
|
'@mpxjs/vue-cli-plugin-mpx-eslint': {
|
|
14
|
-
version: '^
|
|
14
|
+
version: '^2.0.0'
|
|
15
15
|
}
|
|
16
16
|
}
|
|
17
17
|
}
|
package/lib/prompts.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
+
const prefix = '@mpxjs/vue-cli-plugin-mpx'
|
|
2
|
+
|
|
1
3
|
module.exports = [
|
|
2
4
|
{
|
|
3
5
|
name: 'srcMode',
|
|
4
6
|
type: 'list',
|
|
5
7
|
required: true,
|
|
6
8
|
message: '请选择小程序项目所属平台(目前仅微信下支持跨平台输出)',
|
|
7
|
-
choices: ['wx', 'ali', 'swan', 'qq', 'tt'],
|
|
9
|
+
choices: ['wx', 'ali', 'swan', 'qq', 'tt', 'dd'],
|
|
8
10
|
default: 'wx'
|
|
9
11
|
},
|
|
10
12
|
{
|
|
@@ -14,19 +16,19 @@ module.exports = [
|
|
|
14
16
|
type: 'confirm',
|
|
15
17
|
default: true
|
|
16
18
|
},
|
|
17
|
-
{
|
|
18
|
-
name: 'transWeb',
|
|
19
|
-
when: ({ srcMode, cross }) => srcMode === 'wx' && cross === true,
|
|
20
|
-
message: '是否需要支持输出web',
|
|
21
|
-
type: 'confirm',
|
|
22
|
-
default: false
|
|
23
|
-
},
|
|
24
19
|
{
|
|
25
20
|
name: 'cloudFunc',
|
|
26
21
|
when: ({ srcMode, cross }) => srcMode === 'wx' && cross === false,
|
|
27
22
|
message: '是否需要使用小程序云开发能力',
|
|
28
23
|
type: 'confirm',
|
|
29
|
-
default: false
|
|
24
|
+
default: false,
|
|
25
|
+
preset: {
|
|
26
|
+
plugins: {
|
|
27
|
+
[`${prefix}-cloud-func`]: {
|
|
28
|
+
version: '^2.0.0'
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
30
32
|
},
|
|
31
33
|
{
|
|
32
34
|
name: 'isPlugin',
|
|
@@ -34,13 +36,53 @@ module.exports = [
|
|
|
34
36
|
type: 'confirm',
|
|
35
37
|
message:
|
|
36
38
|
'是否是个插件项目?(不清楚请选 No !什么是插件项目请看微信官方文档!)',
|
|
37
|
-
default: false
|
|
39
|
+
default: false,
|
|
40
|
+
preset: {
|
|
41
|
+
plugins: {
|
|
42
|
+
[`${prefix}-plugin-mode`]: {
|
|
43
|
+
version: '^2.0.0'
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
38
47
|
},
|
|
39
48
|
{
|
|
40
49
|
name: 'needTs',
|
|
41
50
|
type: 'confirm',
|
|
42
51
|
message: '是否需要typescript',
|
|
43
|
-
default: false
|
|
52
|
+
default: false,
|
|
53
|
+
preset: {
|
|
54
|
+
plugins: {
|
|
55
|
+
[`${prefix}-typescript`]: {
|
|
56
|
+
version: '^2.0.0'
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
name: 'needUnitTest',
|
|
63
|
+
message: '是否需要单元测试',
|
|
64
|
+
type: 'confirm',
|
|
65
|
+
default: false,
|
|
66
|
+
preset: {
|
|
67
|
+
plugins: {
|
|
68
|
+
[`${prefix}-unit-test`]: {
|
|
69
|
+
version: '^2.0.0'
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
name: 'needE2ETest',
|
|
76
|
+
message: '是否需要自动化测试',
|
|
77
|
+
type: 'confirm',
|
|
78
|
+
default: false,
|
|
79
|
+
preset: {
|
|
80
|
+
plugins: {
|
|
81
|
+
[`${prefix}-e2e-test`]: {
|
|
82
|
+
version: '^2.0.0'
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
44
86
|
},
|
|
45
87
|
{
|
|
46
88
|
name: 'description',
|
package/package.json
CHANGED
|
@@ -1,25 +1,33 @@
|
|
|
1
1
|
{
|
|
2
|
-
"
|
|
3
|
-
"version": "3.1.1",
|
|
4
|
-
"description": "",
|
|
5
|
-
"main": "index.js",
|
|
2
|
+
"author": "",
|
|
6
3
|
"bin": {
|
|
7
4
|
"mpx": "bin/mpx.js"
|
|
8
5
|
},
|
|
9
|
-
"keywords": [],
|
|
10
|
-
"author": "",
|
|
11
|
-
"license": "Apache",
|
|
12
6
|
"dependencies": {
|
|
7
|
+
"@types/inquirer": "^8.1.3",
|
|
13
8
|
"@vue/cli": "^5.0.0",
|
|
14
|
-
"
|
|
9
|
+
"commander": "^7.1.0",
|
|
10
|
+
"fs-extra": "^9.1.0",
|
|
11
|
+
"inquirer": "^8.0.0",
|
|
15
12
|
"lodash.merge": "^4.6.2",
|
|
16
|
-
"
|
|
13
|
+
"minimist": "^1.2.5",
|
|
14
|
+
"resolve": "^1.20.0",
|
|
15
|
+
"shelljs": "^0.8.4",
|
|
16
|
+
"validate-npm-package-name": "^3.0.0"
|
|
17
|
+
},
|
|
18
|
+
"description": "",
|
|
19
|
+
"devDependencies": {
|
|
20
|
+
"cmd-shim": "^4.1.0"
|
|
17
21
|
},
|
|
18
22
|
"engines": {
|
|
19
23
|
"node": ">=8.9"
|
|
20
24
|
},
|
|
25
|
+
"keywords": [],
|
|
26
|
+
"license": "Apache",
|
|
27
|
+
"name": "@mpxjs/cli",
|
|
21
28
|
"publishConfig": {
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
}
|
|
29
|
+
"access": "public",
|
|
30
|
+
"registry": "https://registry.npmjs.org"
|
|
31
|
+
},
|
|
32
|
+
"version": "3.3.0"
|
|
25
33
|
}
|
package/utils/index.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
const { execa } = require('@vue/cli-shared-utils')
|
|
2
|
+
const vueCliBinPath = require.resolve('@vue/cli/bin/vue')
|
|
3
|
+
|
|
4
|
+
module.exports.regenCmd = function regenCmd (parsedArgs) {
|
|
5
|
+
const cmd = [...parsedArgs._, '--skipGetStarted']
|
|
6
|
+
const ignoreKey = ['_', 'p', 'preset', 'i', 'inlinePreset']
|
|
7
|
+
Object.keys(parsedArgs).forEach((key = '') => {
|
|
8
|
+
if (key && !ignoreKey.includes(key)) {
|
|
9
|
+
cmd.push(key.length > 1 ? `--${key}` : `-${key}`)
|
|
10
|
+
cmd.push(parsedArgs[key])
|
|
11
|
+
}
|
|
12
|
+
})
|
|
13
|
+
return cmd
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
module.exports.doVueCli = function doVueCli (args) {
|
|
17
|
+
return execa(
|
|
18
|
+
'node',
|
|
19
|
+
[
|
|
20
|
+
vueCliBinPath,
|
|
21
|
+
...args
|
|
22
|
+
],
|
|
23
|
+
{
|
|
24
|
+
stdio: 'inherit'
|
|
25
|
+
}
|
|
26
|
+
)
|
|
27
|
+
}
|
package/lib/plugins.js
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
const prefix = '@mpxjs/vue-cli-plugin-mpx'
|
|
2
|
-
|
|
3
|
-
const plugins = {
|
|
4
|
-
tsSupport: {
|
|
5
|
-
[`${prefix}-typescript`]: {
|
|
6
|
-
version: '^1.0.0'
|
|
7
|
-
}
|
|
8
|
-
},
|
|
9
|
-
cloudFunc: {
|
|
10
|
-
[`${prefix}-cloud-func`]: {
|
|
11
|
-
version: '^1.0.0'
|
|
12
|
-
}
|
|
13
|
-
},
|
|
14
|
-
isPlugin: {
|
|
15
|
-
[`${prefix}-plugin-mode`]: {
|
|
16
|
-
version: '^1.0.0'
|
|
17
|
-
}
|
|
18
|
-
},
|
|
19
|
-
transWeb: {
|
|
20
|
-
[`${prefix}-web`]: {
|
|
21
|
-
version: '^1.0.0'
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
// TODO: 添加其他插件配置
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
module.exports = plugins
|