· 6 years ago · May 01, 2019, 04:44 AM
1'use strict';
2
3import chalk from 'chalk';
4import elegantSpinner from 'elegant-spinner';
5import fs from 'fs';
6import inquirer from 'inquirer';
7import logUpdate from 'log-update';
8import shell from 'shelljs';
9import Table from 'cli-table3';
10import validate from 'validate-npm-package-name';
11
12import boilerplate from '../../config.json';
13import { showBanner } from '../../external/banner';
14import { validateInstallation } from '../../utils/validations';
15
16let availableCommands = new Table();
17let frame = elegantSpinner();
18
19let projectName;
20let projectConfig;
21
22let showTables = () => {
23 console.log(chalk.yellow('\n Available commands:-'));
24
25 availableCommands.push(
26 {
27 'mevn version': 'Current CLI version',
28 },
29 {
30 'mevn serve': 'To launch client/server',
31 },
32 {
33 'mevn add:package': 'Add additional packages',
34 },
35 {
36 'mevn generate': 'To generate config files',
37 },
38 {
39 'mevn create:component <name>': 'Create new components',
40 },
41 {
42 'mevn codesplit <name>': 'Lazy load components',
43 },
44 {
45 'mevn create:git-repo': 'Create a GitHub Repo',
46 },
47 {
48 'mevn dockerize': 'Launch within docker containers',
49 },
50 {
51 'mevn deploy': 'Deploy the app to Heroku',
52 },
53 );
54 console.log(availableCommands.toString());
55
56 console.log(
57 chalk.cyanBright(
58 `\n\n Make sure that you've done ${chalk.greenBright(
59 `cd ${projectName}`,
60 )}`,
61 ),
62 );
63 console.log(chalk.redBright('\n warning:'));
64 console.log(' Do not delete mevn.json file');
65};
66
67let fetchTemplate = async template => {
68 try {
69 await validateInstallation('git');
70
71 shell.exec(
72 `${boilerplate[template]} ${projectName}`,
73 { silent: true },
74 { async: true },
75 );
76
77 let fetchSpinner = setInterval(() => {
78 logUpdate('Fetching the boilerplate ' + chalk.cyan.bold.dim(frame()));
79 }, 50);
80
81 setTimeout(() => {
82 console.log('\n');
83 clearInterval(fetchSpinner);
84 logUpdate.clear();
85 showTables();
86 }, 2000);
87
88 fs.writeFileSync(
89 `./${projectName}/mevn.json`,
90 projectConfig.join('\n').toString(),
91 );
92
93 // Prompt for choosing additional features (ESLint, JSHint, JSLint, Prettier)
94 if (template) {
95 setTimeout(() => {
96 inquirer
97 .prompt([
98 {
99 name: 'feature',
100 type: 'list',
101 message: 'Please select additional feature',
102 choices: ['ESLint', 'JSHint', 'JSLint', 'Prettier', 'None'],
103 },
104 ])
105 .then(answer => {
106 if (answer.feature === 'ESLint') {
107 if (template === 'nuxt') {
108 shell.echo('Installing ESLint for your nuxt template : server');
109 shell.cd(`${projectName}/server`);
110 shell.exec('npm install eslint', { silent: true });
111 shell.cd('../..');
112 } else {
113 // configuring client
114 shell.echo(
115 'Installing ESLint for your ' +
116 template +
117 ' template : client',
118 );
119 shell.cd(`${projectName}/client`);
120 shell.exec('npm install eslint', { silent: true });
121 shell.cd('../..');
122 //configuring server
123 shell.echo(
124 'Installing ESLint for your ' +
125 template +
126 ' template : server',
127 );
128 shell.cd(`${projectName}/server`);
129 shell.exec('npm install eslint', { silent: true });
130 shell.cd('../..');
131 }
132 } else if (answer.feature === 'JSHint') {
133 if (template === 'nuxt') {
134 shell.echo('Installing JSHint for your nuxt template : server');
135 shell.cd(`${projectName}/server`);
136 shell.exec('npm install jshint', { silent: true });
137 shell.cd('../..');
138 } else {
139 // configuring client
140 shell.echo(
141 'Installing JSHint for your ' +
142 template +
143 ' template : client',
144 );
145 shell.cd(`${projectName}/client`);
146 shell.exec('npm install jshint', { silent: true });
147 shell.cd('../..');
148 //configuring server
149 shell.echo(
150 'Installing JSHint for your ' +
151 template +
152 ' template : server',
153 );
154 shell.cd(`${projectName}/server`);
155 shell.exec('npm install jshint', { silent: true });
156 shell.cd('../..');
157 }
158 } else if (answer.feature === 'JSLint') {
159 if (template === 'nuxt') {
160 shell.echo('Installing JSLint for your nuxt template : server');
161 shell.cd(`${projectName}/server`);
162 shell.exec('npm install jslint', { silent: true });
163 shell.cd('../..');
164 } else {
165 // configuring client
166 shell.echo(
167 'Installing JSLint for your ' +
168 template +
169 ' template : client',
170 );
171 shell.cd(`${projectName}/client`);
172 shell.exec('npm install jslint', { silent: true });
173 shell.cd('../..');
174 //configuring server
175 shell.echo(
176 'Installing JSLint for your ' +
177 template +
178 ' template : server',
179 );
180 shell.cd(`${projectName}/server`);
181 shell.exec('npm install jslint', { silent: true });
182 shell.cd('../..');
183 }
184 } else if (answer.feature === 'Prettier') {
185 if (template === 'nuxt') {
186 shell.echo(
187 'Installing Prettier for your nuxt template : server',
188 );
189 shell.cd(`${projectName}/server`);
190 shell.exec('npm install prettier', { silent: true });
191 shell.cd('../..');
192 } else {
193 // configuring client
194 shell.echo(
195 'Installing Prettier for your ' +
196 template +
197 ' template : client',
198 );
199 shell.cd(`${projectName}/client`);
200 shell.exec('npm install prettier', { silent: true });
201 shell.cd('../..');
202 //configuring server
203 shell.echo(
204 '\nInstalling Prettier for your ' +
205 template +
206 ' template : server',
207 );
208 shell.cd(`${projectName}/server`);
209 shell.exec('npm install prettier', { silent: true });
210 shell.cd('../..');
211 }
212 } else if (answer.feature === 'None') {
213 console.log('\n');
214 }
215 });
216 }, 2000);
217 }
218
219 if (template === 'nuxt') {
220 setTimeout(() => {
221 console.log('\n');
222
223 inquirer
224 .prompt([
225 {
226 name: 'mode',
227 type: 'list',
228 message: 'Choose your preferred mode',
229 choices: ['Universal', 'SPA'],
230 },
231 ])
232 .then(choice => {
233 if (choice.mode === 'Universal') {
234 let configFile = fs
235 .readFileSync(`./${projectName}/nuxt.config.js`, 'utf8')
236 .toString()
237 .split('\n');
238 let index = configFile.indexOf(
239 configFile.find(line => line.includes('mode')),
240 );
241 configFile[index] = ` mode: 'universal',`;
242
243 fs.writeFileSync(
244 `./${projectName}/nuxt.config.js`,
245 configFile.join('\n'),
246 );
247 }
248 showTables();
249 });
250 }, 9000);
251 }
252 } catch (error) {
253 throw error;
254 }
255};
256
257exports.initializeProject = appName => {
258 showBanner();
259 console.log('\n');
260
261 let initialSpinner = setInterval(() => {
262 logUpdate('Initializing ' + chalk.cyan.bold.dim(frame()));
263 }, 50);
264
265 setTimeout(() => {
266 const hasMultipleProjectNameArgs =
267 process.argv[4] && !process.argv[4].startsWith('-');
268 // Validation for multiple directory names
269 if (hasMultipleProjectNameArgs) {
270 console.log(
271 chalk.red.bold(
272 '\n Kindly provide only one argument as the directory name!!',
273 ),
274 );
275 process.exit(1);
276 }
277
278 const validationResult = validate(appName);
279 if (!validationResult.validForNewPackages) {
280 console.error(
281 `Could not create a project called ${chalk.red(
282 `"${appName}"`,
283 )} because of npm naming restrictions:`,
284 );
285 process.exit(1);
286 }
287
288 if (fs.existsSync(appName)) {
289 console.error(
290 chalk.red.bold(`\n Directory ${appName} already exists in path!`),
291 );
292 process.exit(1);
293 }
294
295 clearInterval(initialSpinner);
296 logUpdate.clear();
297 projectName = appName;
298
299 inquirer
300 .prompt([
301 {
302 name: 'template',
303 type: 'list',
304 message: 'Please select one',
305 choices: ['basic', 'pwa', 'graphql', 'Nuxt-js'],
306 },
307 ])
308 .then(choice => {
309 projectConfig = [
310 '{',
311 `"name": "${appName}",`,
312 `"template": "${choice.template}"`,
313 '}',
314 ];
315
316 if (choice.template === 'Nuxt-js') {
317 choice.template = 'nuxt';
318 }
319 fetchTemplate(choice.template);
320 });
321 }, 1000);
322};