1 | #! /usr/bin/env node
|
2 | const path = require('path');
|
3 | const fs = require('fs');
|
4 | const readline = require('readline');
|
5 | const help = require('./helper');
|
6 | const shell = require('shelljs');
|
7 | const colors = require('colors');
|
8 | const cwdPath = process.cwd();
|
9 | const package = require('../package.json');
|
10 | const templatePath = path.resolve(__dirname, '../template');
|
11 | const templateComponentPath = path.resolve(__dirname, '../cmp_template');
|
12 | const program = require('../utils/commander');
|
13 |
|
14 | const FILENAMEREGX = (() => {
|
15 | let regstr = '';
|
16 | |
17 |
|
18 |
|
19 | ['png', 'jpg', 'jpeg', 'bmp', 'webp', 'jar', 'gif', 'ttf', 'dll', 'svg'].forEach(e => {
|
20 | regstr += e + '|';
|
21 | });
|
22 | regstr = `\.(${regstr.slice(0, -1)})`;
|
23 | return new RegExp(regstr);
|
24 | })();
|
25 |
|
26 |
|
27 |
|
28 |
|
29 |
|
30 |
|
31 |
|
32 |
|
33 | function fsExistsSync(path) {
|
34 | try {
|
35 | fs.accessSync(path, fs.F_OK);
|
36 | } catch (e) {
|
37 | return false;
|
38 | }
|
39 | return true;
|
40 | }
|
41 |
|
42 |
|
43 |
|
44 |
|
45 |
|
46 |
|
47 | function copyFile(templatePath, targetPath) {
|
48 | fs.writeFileSync(targetPath, fs.readFileSync(templatePath));
|
49 | }
|
50 |
|
51 | function confirmOverride() {
|
52 | const terminal = readline.createInterface({
|
53 | input: process.stdin,
|
54 | output: process.stdout
|
55 | });
|
56 | return new Promise((resolve, reject) => {
|
57 | terminal.question('Floder is already exits, do you want override it ? yes/no ', answer => {
|
58 | if (answer === 'yes' || answer === 'y') {
|
59 | resolve(true);
|
60 | terminal.close();
|
61 | } else {
|
62 | process.exit();
|
63 | }
|
64 | });
|
65 | });
|
66 | }
|
67 |
|
68 |
|
69 |
|
70 |
|
71 |
|
72 |
|
73 |
|
74 | function copyTemplate(templatePath, targetPath) {
|
75 | try {
|
76 | if (fs.statSync(templatePath).isDirectory() && !fsExistsSync(targetPath)) {
|
77 | fs.mkdirSync(targetPath);
|
78 | }
|
79 |
|
80 | const subpaths = fs.readdirSync(templatePath);
|
81 | subpaths.forEach(subpath => {
|
82 | const tarPath = path.resolve(targetPath, subpath);
|
83 | const tempPath = path.resolve(templatePath, subpath);
|
84 |
|
85 | if (fs.statSync(tempPath).isDirectory()) {
|
86 | copyTemplate(tempPath, tarPath);
|
87 | } else {
|
88 | copyFile(tempPath, tarPath);
|
89 | }
|
90 | });
|
91 | } catch (error) {
|
92 | console.log(error);
|
93 | return false;
|
94 | }
|
95 | return true;
|
96 | }
|
97 |
|
98 |
|
99 |
|
100 |
|
101 |
|
102 |
|
103 | function renameProject(targetPath, projectName) {
|
104 | try {
|
105 | const paths = fs.readdirSync(targetPath);
|
106 | paths.forEach(subpath => {
|
107 | const subfile = path.resolve(targetPath, subpath);
|
108 | const newPath = subfile.replace(/MoleStarter/gim, projectName);
|
109 | if (!fs.statSync(subfile).isFile()) {
|
110 | if (subpath !== 'images') {
|
111 | fs.renameSync(subfile, newPath);
|
112 | renameProject(newPath, projectName);
|
113 | }
|
114 | } else {
|
115 | if (!FILENAMEREGX.test(subfile)) {
|
116 | fs.renameSync(subfile, newPath);
|
117 | fs.writeFileSync(
|
118 | newPath,
|
119 | fs
|
120 | .readFileSync(newPath)
|
121 | .toString()
|
122 | .replace(/MoleStarter/gim, projectName)
|
123 | );
|
124 | }
|
125 | }
|
126 | });
|
127 | } catch (error) {
|
128 | console.log(error);
|
129 | }
|
130 | }
|
131 | function renameComponent(targetPath, projectName) {
|
132 | try {
|
133 | const paths = fs.readdirSync(targetPath);
|
134 | paths.forEach(subpath => {
|
135 | const subfile = path.resolve(targetPath, subpath);
|
136 | const newPath = subfile.replace(/MoleUI/gim, projectName);
|
137 | if (!fs.statSync(subfile).isFile()) {
|
138 | if (subpath !== 'images') {
|
139 | fs.renameSync(subfile, newPath);
|
140 | renameComponent(newPath, projectName);
|
141 | }
|
142 | } else {
|
143 | if (!FILENAMEREGX.test(subfile)) {
|
144 | fs.renameSync(subfile, newPath);
|
145 | fs.writeFileSync(
|
146 | newPath,
|
147 | fs
|
148 | .readFileSync(newPath)
|
149 | .toString()
|
150 | .replace(/MoleUI/gim, projectName)
|
151 | );
|
152 | }
|
153 | }
|
154 | });
|
155 | } catch (error) {
|
156 | console.log(error);
|
157 | }
|
158 | }
|
159 |
|
160 |
|
161 |
|
162 |
|
163 | function installDependencies(projectName) {
|
164 | console.log('\ninstalling...');
|
165 | if (shell.exec(`cd ${projectName} && npm install`).code) {
|
166 | if (shell.exec(`cd ${projectName} && npm install`).code) {
|
167 | console.log(colors.red('install dependencies failed!'));
|
168 | } else {
|
169 | console.log(
|
170 | colors.yellow(
|
171 | [
|
172 | `Success! Created ${projectName} at ${cwdPath}.`,
|
173 | 'Inside that directory, you can run several commands and more:',
|
174 | ' * npm run start-web: Starts you project for web.',
|
175 | ' * npm run start-rn: Starts you project for rn.',
|
176 | ' * npm run run-ios: Starts you project for ios.',
|
177 | ' * npm run run-android: Starts you project for android.',
|
178 | ' We suggest that you begin by typing:',
|
179 | ` cd ${projectName}`,
|
180 | ' npm run start-rn',
|
181 | 'Happy coding!'
|
182 | ].join('\n')
|
183 | )
|
184 | );
|
185 | }
|
186 | }
|
187 | }
|
188 |
|
189 | function backupDir(templatePath, backupPath) {
|
190 | if (fs.statSync(templatePath).isDirectory()) {
|
191 | fs.mkdirSync(backupPath);
|
192 | }
|
193 | const subpaths = fs.readdirSync(templatePath);
|
194 | subpaths.forEach(subpath => {
|
195 | const bacPath = path.resolve(backupPath, subpath);
|
196 | const tempPath = path.resolve(templatePath, subpath);
|
197 | if (fs.statSync(tempPath).isDirectory()) {
|
198 | backupDir(tempPath, bacPath);
|
199 | } else {
|
200 | copyFile(tempPath, bacPath);
|
201 | }
|
202 | });
|
203 | }
|
204 |
|
205 | function removeBackup(backupPath) {
|
206 | shell.rm('-rf', backupPath);
|
207 | }
|
208 |
|
209 |
|
210 |
|
211 |
|
212 |
|
213 |
|
214 |
|
215 |
|
216 |
|
217 |
|
218 |
|
219 |
|
220 |
|
221 |
|
222 |
|
223 |
|
224 |
|
225 |
|
226 |
|
227 | async function newComponent(component){
|
228 |
|
229 | const targetPath = `${cwdPath}/${component}`;
|
230 |
|
231 | if (fsExistsSync(targetPath)) {
|
232 | if (await confirmOverride()) {
|
233 | if (copyTemplate(templateComponentPath, targetPath)) {
|
234 | renameComponent(targetPath, component);
|
235 | console.log('🎉🎉🎉恭喜您, 组件[' + component + ']创建成功.');
|
236 |
|
237 | }
|
238 |
|
239 | }
|
240 | } else {
|
241 |
|
242 | if (copyTemplate(templateComponentPath, targetPath)) {
|
243 | renameComponent(targetPath, component);
|
244 | console.log('🎉🎉🎉恭喜您, 组件[' + component + ']创建成功.');
|
245 |
|
246 | }
|
247 | }
|
248 | }
|
249 |
|
250 |
|
251 |
|
252 |
|
253 |
|
254 |
|
255 | async function newProject(projectName) {
|
256 | const targetPath = `${cwdPath}/${projectName}`;
|
257 |
|
258 | if (fsExistsSync(targetPath)) {
|
259 | if (await confirmOverride()) {
|
260 | if (copyTemplate(templatePath, targetPath)) {
|
261 | renameProject(targetPath, projectName);
|
262 | installDependencies(projectName);
|
263 | }
|
264 |
|
265 | }
|
266 | } else {
|
267 |
|
268 | if (copyTemplate(templatePath, targetPath)) {
|
269 | renameProject(targetPath, projectName);
|
270 | installDependencies(projectName);
|
271 | }
|
272 | }
|
273 | }
|
274 |
|
275 | try {
|
276 | program.option('-h, --help', help).option('-v, --version', () => {
|
277 | console.log(package.version);
|
278 | });
|
279 | program.command('project <project>').action(newProject);
|
280 |
|
281 | program.command('component <component>').action(newComponent);
|
282 | program.catch((...argvs) => {
|
283 |
|
284 | shell.exec('mole-rn-cli --help')
|
285 |
|
286 | });
|
287 | program.parse(process.argv);
|
288 | } catch (error) {
|
289 | console.log(error);
|
290 | }
|