UNPKG

5.73 kBJavaScriptView Raw
1'use strict';
2
3const shell = require('shelljs');
4const async = require('async');
5
6const replaceStream = require('replacestream');
7
8const Manager = require('../modules/manager.js');
9const UtilFs = require('../utils/fs.js');
10
11exports.usage = '项目初始化';
12exports.abbr = 'i';
13
14exports.setOptions = () => {
15 optimist.alias('r', 'registry');
16 optimist.describe('r', '指定 npm 仓库');
17};
18
19exports.run = function(options) {
20 const userRegistry = options.r || options.registry;
21
22 Manager.reloadRC();
23
24 let cwd = options.cwd,
25 defaultName = '',
26 packageJsonPath = sysPath.join(cwd, './package.json');
27
28 if (UtilFs.fileExists(packageJsonPath)) {
29 defaultName = JSON.parse(fs.readFileSync(packageJsonPath)).name;
30 } else {
31 defaultName = sysPath.basename(cwd);
32 }
33
34 // TODO 也许可以改成通过命令行让用户输入
35 const projectName = defaultName;
36 const initTmplPath = sysPath.resolve(__dirname, '../../static/initTmpl/');
37
38 // 如果初始化时带着初始化类型
39 if (typeof process.argv[3] === 'string') {
40 const initParam = process.argv[3];
41 const qunarRegistry = 'http://npmrepo.corp.qunar.com';
42 const taobaoRegistry = 'https://registry.npm.taobao.org';
43 let isInitReady = false;
44
45 spinner.start();
46 spinner.text = `Checking package ykit-config-${initParam}`;
47 async.series([
48 // qnpm 寻找是否存在 @qnpm/ykit-config-xxx 的插件
49 (callback) => {
50 checkConfigPkg(callback, `@qnpm/ykit-config-${initParam}`, userRegistry || qunarRegistry);
51 },
52 // qnpm 寻找是否存在 ykit-config-xxx 的插件
53 (callback) => {
54 checkConfigPkg(callback, `ykit-config-${initParam}`, userRegistry || qunarRegistry);
55 },
56 // cnpm 寻找是否存在 ykit-config-xxx 的插件
57 (callback) => {
58 checkConfigPkg(callback, `ykit-config-${initParam}`, userRegistry || taobaoRegistry);
59 }
60 ], () => {
61 if (isInitReady) {
62 spinner.stop();
63 } else {
64 spinner.text = `Can't find package ykit-config-${initParam}`;
65 spinner.fail();
66 }
67 });
68
69 function checkConfigPkg(callback, packageName, registry) {
70 if (!isInitReady) {
71 let timeout;
72 const child = shell.exec(`npm view ${packageName} --registry ${registry}`, {
73 silent: true
74 }, (code, stdout, stderr) => {
75 if (stdout) {
76 isInitReady = true;
77 initProject(packageName, registry);
78 }
79 clearTimeout(timeout);
80 callback(null);
81 });
82
83 // 防止超时
84 timeout = setTimeout(() => {
85 child.kill('SIGINT');
86 }, 20000);
87 } else {
88 callback(null, 'two');
89 }
90 }
91 } else {
92 // 只初始化一个空白项目
93 initProject();
94 }
95
96 function initProject(configPkgName, registry) {
97 let funcSeries = [];
98
99 if (configPkgName) {
100 funcSeries = [
101 (callback) => createPackageJson(callback),
102 (callback) => installConfigPlugin(callback, configPkgName, registry),
103 (callback) => createConfigFile(callback, configPkgName),
104 (callback) => setup(callback, configPkgName)
105 ];
106 } else {
107 funcSeries = [
108 (callback) => createPackageJson(callback),
109 (callback) => createConfigFile(callback, configPkgName),
110 (callback) => createTmpl(callback)
111 ];
112 }
113
114 async.series(funcSeries, (err, results) => {});
115 }
116
117 function installConfigPlugin(callback, configPkgName, registry) {
118 log('Install ' + configPkgName + '...');
119
120 shell.exec(`npm install ${configPkgName} --registry ${registry} --save`, {
121 silent: false
122 }, (code, stdout, stderr) => {
123 callback(null); // npm install 中的警告也会当成 stderr 输出,所以不在这里做错误处理
124 });
125 }
126
127 function createPackageJson(callback) {
128 if (!UtilFs.fileExists(packageJsonPath)) {
129 let writePackageJsonStream = create();
130 writePackageJsonStream.on('finish', () => {
131 logInfo('Write ' + 'package.json'.green.bold + ' in ' + cwd);
132 callback(null);
133 });
134 } else {
135 callback(null);
136 }
137
138 function create() {
139 return fs.createReadStream(sysPath.resolve(initTmplPath, 'package.json'))
140 .pipe(replaceStream('@PROJECT_NAME', projectName))
141 .pipe(fs.createWriteStream(sysPath.resolve(cwd, 'package.json')));
142 }
143 }
144
145 function createConfigFile(callback, configPkgName) {
146 const pluginName = configPkgName ? configPkgName.match(/ykit-config-([^\-]+)/)[1] : '';
147 const configFileName = 'ykit.js';
148
149 if (!UtilFs.fileExists('./' + configFileName)) {
150 const writeStream = fs.createWriteStream(sysPath.resolve(cwd, configFileName));
151 const configFilePath = sysPath.resolve(initTmplPath, 'ykit.js');
152 const stream = fs.createReadStream(configFilePath)
153 .pipe(replaceStream('@PROJECT_NAME', projectName))
154 .pipe(replaceStream('@PLUGIN_NAME', pluginName ? '[\'' + pluginName + '\']' : '[]'))
155 .pipe(writeStream);
156
157 stream.on('finish', () => {
158 logInfo('Write ' + configFileName.green.bold + ' in ' + cwd);
159 callback(null);
160 });
161 } else {
162 callback(null);
163 }
164 }
165
166 function setup(callback) {
167 const initParams = process.argv.slice(4) || [];
168 const setupCmd = `node ${sysPath.join(__dirname, '../../bin/ykit')} setup ${initParams.join(' ')}`;
169
170 logInfo('Run ' + setupCmd);
171 shell.exec(setupCmd, {
172 silent: false
173 }, (code, stdout, stderr) => {
174 callback(null);
175 });
176 }
177
178 function createTmpl(callback) {
179 fs.copySync(sysPath.resolve(initTmplPath, './index.html'), sysPath.resolve(cwd, './index.html'));
180 fs.copySync(sysPath.resolve(initTmplPath, './src'), sysPath.resolve(cwd, './src'));
181
182 // fix: PT-4696
183 try {
184 shell.mkdir('-p', `${sysPath.resolve(process.cwd(), YKIT_CACHE_DIR)}`);
185 } catch (e) {
186 warn(`Create folder failed ! you need run 'mkdir -p ${sysPath.resolve(process.cwd(), YKIT_CACHE_DIR)}'`);
187 }
188
189 callback(null);
190 }
191};