1
1
#!/usr/bin/env node
2
- function runCommand ( command , options ) {
2
+
3
+ process . exitCode = 0 ;
4
+
5
+ /**
6
+ * @param {string } command process to run
7
+ * @param {string[] } args commandline arguments
8
+ * @returns {Promise<void> } promise
9
+ */
10
+ const runCommand = ( command , args ) => {
3
11
const cp = require ( "child_process" ) ;
4
12
return new Promise ( ( resolve , reject ) => {
5
- const executedCommand = cp . spawn ( command , options , {
13
+ const executedCommand = cp . spawn ( command , args , {
6
14
stdio : "inherit" ,
7
15
shell : true
8
16
} ) ;
@@ -13,114 +21,146 @@ function runCommand(command, options) {
13
21
14
22
executedCommand . on ( "exit" , code => {
15
23
if ( code === 0 ) {
16
- resolve ( true ) ;
24
+ resolve ( ) ;
17
25
} else {
18
26
reject ( ) ;
19
27
}
20
28
} ) ;
21
29
} ) ;
22
- }
30
+ } ;
23
31
24
- function isInstalled ( packageName ) {
32
+ /**
33
+ * @param {string } packageName name of the package
34
+ * @returns {boolean } is the package installed?
35
+ */
36
+ const isInstalled = packageName => {
25
37
try {
26
38
require . resolve ( packageName ) ;
27
39
28
40
return true ;
29
41
} catch ( err ) {
30
42
return false ;
31
43
}
32
- }
33
-
34
- const CLI = [
44
+ } ;
45
+
46
+ /**
47
+ * @typedef {Object } CliOption
48
+ * @property {string } name display name
49
+ * @property {string } package npm package name
50
+ * @property {string } alias shortcut for choice
51
+ * @property {boolean } installed currently installed?
52
+ * @property {string } url homepage
53
+ * @property {string } description description
54
+ */
55
+
56
+ /** @type {CliOption[] } */
57
+ const CLIs = [
35
58
{
36
59
name : "webpack-cli" ,
60
+ package : "webpack-cli" ,
61
+ alias : "cli" ,
37
62
installed : isInstalled ( "webpack-cli" ) ,
38
- URL : "https://github.com/webpack/webpack-cli" ,
39
- description : "The original webpack full-featured CLI from webpack@3 ."
63
+ url : "https://github.com/webpack/webpack-cli" ,
64
+ description : "The original webpack full-featured CLI."
40
65
} ,
41
66
{
42
67
name : "webpack-command" ,
68
+ package : "webpack-command" ,
69
+ alias : "command" ,
43
70
installed : isInstalled ( "webpack-command" ) ,
44
- URL : "https://github.com/webpack-contrib/webpack-command" ,
71
+ url : "https://github.com/webpack-contrib/webpack-command" ,
45
72
description : "A lightweight, opinionated webpack CLI."
46
73
}
47
74
] ;
48
75
49
- if ( CLI . every ( item => ! item . installed ) ) {
76
+ const installedClis = CLIs . filter ( cli => cli . installed ) ;
77
+
78
+ if ( installedClis . length === 0 ) {
50
79
const path = require ( "path" ) ;
51
80
const fs = require ( "fs" ) ;
52
81
const readLine = require ( "readline" ) ;
53
82
54
83
let notify =
55
- "The CLI for webpack must be installed as a separate package, for which there are choices:\n " ;
84
+ "One CLI for webpack must be installed. These are recommended choices, delivered as separate packages: " ;
56
85
57
- CLI . forEach ( item => {
58
- notify += ` ${ item . name } (${ item . URL } ): ${ item . description } \n ` ;
59
- } ) ;
86
+ for ( const item of CLIs ) {
87
+ notify += `\n - ${ item . name } (${ item . url } )\n ${ item . description } ` ;
88
+ }
60
89
61
90
console . error ( notify ) ;
62
91
63
92
const isYarn = fs . existsSync ( path . resolve ( process . cwd ( ) , "yarn.lock" ) ) ;
64
93
65
94
const packageManager = isYarn ? "yarn" : "npm" ;
66
- const installOptions = [ "install" , "-D" ] ;
95
+ const installOptions = [ isYarn ? "add" : "install" , "-D" ] ;
67
96
68
- if ( isYarn ) {
69
- installOptions [ 0 ] = "add" ;
70
- }
97
+ console . error (
98
+ `We will use "${ packageManager } " to install the CLI via "${ packageManager } ${ installOptions . join (
99
+ " "
100
+ ) } ".`
101
+ ) ;
71
102
72
- let question = `Would you like to install (${ CLI . map ( item => item . name ) . join (
73
- "/"
74
- ) } ):\n`;
103
+ let question = `Which one do you like to install (${ CLIs . map (
104
+ item => item . name
105
+ ) . join ( "/" ) } ):\n`;
75
106
76
107
const questionInterface = readLine . createInterface ( {
77
108
input : process . stdin ,
78
- output : process . stdout
109
+ output : process . stderr
79
110
} ) ;
80
111
questionInterface . question ( question , answer => {
81
112
questionInterface . close ( ) ;
82
113
83
114
const normalizedAnswer = answer . toLowerCase ( ) ;
84
- const selectedPackage = CLI . find ( item => item . name === normalizedAnswer ) ;
115
+ const selectedPackage = CLIs . find ( item => {
116
+ return item . name === normalizedAnswer || item . alias === normalizedAnswer ;
117
+ } ) ;
85
118
86
- if ( ! selectedPackage ) {
119
+ if ( ! normalizedAnswer ) {
87
120
console . error (
88
- "It needs to be installed alongside webpack to use the CLI"
121
+ "One CLI needs to be installed alongside webpack to use the CLI."
122
+ ) ;
123
+ process . exitCode = 1 ;
124
+
125
+ return ;
126
+ } else if ( ! selectedPackage ) {
127
+ console . error (
128
+ "No matching choice.\n" +
129
+ "One CLI needs to be installed alongside webpack to use the CLI.\n" +
130
+ "Try to installing your CLI of choice manually."
89
131
) ;
90
132
process . exitCode = 1 ;
91
133
92
134
return ;
93
135
}
94
136
95
- installOptions . push ( normalizedAnswer ) ;
137
+ const packageName = selectedPackage . package ;
96
138
97
139
console . log (
98
- `Installing '${ normalizedAnswer } ' (running '${ packageManager } ${ installOptions . join (
140
+ `Installing '${
141
+ selectedPackage . name
142
+ } ' (running '${ packageManager } ${ installOptions . join (
99
143
" "
100
- ) } ')...`
144
+ ) } ${ packageName } ')...`
101
145
) ;
102
146
103
- runCommand ( packageManager , installOptions )
104
- . then ( result => {
105
- return require ( normalizedAnswer ) ; //eslint-disable-line
147
+ runCommand ( packageManager , installOptions . concat ( packageName ) )
148
+ . then ( ( ) => {
149
+ require ( packageName ) ; //eslint-disable-line
106
150
} )
107
151
. catch ( error => {
108
152
console . error ( error ) ;
109
153
process . exitCode = 1 ;
110
154
} ) ;
111
155
} ) ;
156
+ } else if ( installedClis . length === 1 ) {
157
+ require ( installedClis [ 0 ] . package ) ; // eslint-disable-line
112
158
} else {
113
- const installedPackage = CLI . map (
114
- item => ( item . installed ? item . name : "" )
115
- ) . filter ( v => v ) ;
116
-
117
- if ( installedPackage . length > 1 ) {
118
- console . warn (
119
- `You have installed ${ installedPackage . join (
159
+ console . warn (
160
+ `You have installed ${ installedClis
161
+ . map ( item => item . name )
162
+ . join (
120
163
" and "
121
- ) } together. To work with the webpack you need only one CLI package, please remove one of them`
122
- ) ;
123
- }
124
-
125
- require ( installedPackage [ 0 ] ) ; // eslint-disable-line
164
+ ) } together. To work with the "webpack" command you need only one CLI package, please remove one of them or use them directly via their binary.`
165
+ ) ;
126
166
}
0 commit comments