UNPKG

7.16 kBJavaScriptView Raw
1/**
2 * ----------------------------------
3 * @file core.js
4 * @desc Client 上下文作用域
5 * @author Matrix <fangbo.fb@alibaba-inc.com>
6 * @create: 2018/6
7 * ----------------------------------
8 */
9
10const program = require('commander');
11const path = require('path');
12const util = require('./util');
13const memFs = require('./util/file');
14const inquirer = require('inquirer');
15const EventEmitter = require('events');
16const readPkgUp = require('read-pkg-up');
17const findUp = require('find-up');
18const makeDir = require('make-dir');
19const fs = require('fs');
20const _ = require('lodash');
21const chalk = require('chalk');
22const log = require('./util/log');
23const config = require('../bin/config');
24const debug = require('debug')('dingtalk-cli-pro:core');
25
26
27const SYSTEM_PLUGIN_LIST = config.SYSTEM_PLUGIN_LIST
28
29const SYS_COMMAND_LIST = [
30 {
31 name: 'init',
32 path: path.resolve(__dirname, './commands', './init')
33 },
34 {
35 name: 'dev',
36 path: path.resolve(__dirname, './commands', './dev')
37 },
38 {
39 name: 'must',
40 path: path.resolve(__dirname, './commands', './must')
41 },
42 {
43 name: 'test',
44 path: path.resolve(__dirname, './commands', './test')
45 },
46 {
47 name: 'publish',
48 path: path.resolve(__dirname, './commands', './publish')
49 },
50 {
51 name: 'build',
52 path: path.resolve(__dirname, './commands', './build')
53 },
54 {
55 name: 'generator',
56 path: path.resolve(__dirname, './commands', './generator')
57 }
58]
59
60const COMMAND_MAP = new Map();
61
62class Client extends EventEmitter {
63 constructor(options) {
64 super(options);
65 this.fs = memFs;
66 this.program = program;
67 this.log = log;
68 this.context = {
69 plugins: []
70 }
71 }
72
73 prompt(question) {
74 return inquirer.prompt(question)
75 }
76
77 registryCommand(cmdString) {
78 if (COMMAND_MAP.has(cmdString)) {
79 this.log.error(`${cmdString} command aleady has be registried, please rename it`)
80 return null;
81 } else {
82 COMMAND_MAP.set(cmdString, 1);
83 return this.program.command(cmdString)
84 }
85 }
86
87 hasCommand(cmdString) {
88 return COMMAND_MAP.has(cmdString);
89 }
90
91 executeSystemPlugin() {
92 this.context.plugins = this.context.plugins.concat(SYS_COMMAND_LIST);
93 this.executePlugin(SYS_COMMAND_LIST);
94 }
95
96 loaderInstalledPlugin(root) {
97 const plugins = util.getPluginNameAndPath(root) || [];
98 const context = this.context;
99
100 const reducePlugins = plugins.filter(plugin => {
101 if (context.plugins.map(item => item.name).indexOf(plugin.name) === -1) {
102 return true;
103 } else {
104 if (SYSTEM_PLUGIN_LIST.indexOf(plugin.name) === -1) {
105 this.log.error(`${plugin.name} is registried, please rename it`)
106 }
107
108 return false
109 }
110 });
111
112 if (reducePlugins.length) {
113 context.plugins = context.plugins.concat(reducePlugins);
114 this.executePlugin(reducePlugins);
115 }
116 }
117
118 loaderConfigPluginDir(dir) {
119 fs.readdirSync(dir).forEach(file => {
120 if (/\.js?/.test(file)) {
121 require(path.join(dir, file)).call(this, this);
122 }
123 })
124 }
125 loaderConfigPluginFiles(list, dir) {
126 debug(`configpluinfiles: %o, ${dir}`, list);
127 list.forEach(item => {
128 const file = item[0];
129 const options = item[1];
130 if (/\.js?/.test(file)) {
131 if (path.isAbsolute(file)) {
132 require(file).call(this, this, options)
133 } else {
134 require(path.join(dir, file)).call(this, this, options);
135 }
136 }
137 })
138 }
139 executePlugin(plugins){
140 plugins.forEach(plugin => {
141 require(plugin.path).call(this, this)
142 })
143 }
144
145 pluginIsExist(name) {
146 const context = this.context;
147 return context.plugins.filter(plugin => plugin.name === name).length ? true : false;
148 }
149
150 /**
151 * Determine the root generator name (the one who's extending Generator).
152 * @return {String} The name of the root generator
153 */
154 rootGeneratorName() {
155
156 const pkg = readPkgUp.sync().package;
157 return pkg ? pkg.name : '*';
158 }
159
160 readPackageInfo() {
161 return readPkgUp.sync();
162 }
163
164 /**
165 * Determine the root generator version (the one who's extending Generator).
166 * @return {String} The version of the root generator
167 */
168 rootGeneratorVersion() {
169 const pkg = readPkgUp.sync().package;
170 return pkg ? pkg.version : '0.0.0';
171 }
172
173 /**
174 * Change the generator destination root directory.
175 * This path is used to find storage, when using a file system helper method (like
176 * `this.write` and `this.copy`)
177 * @param {String} rootPath new destination root path
178 * @return {String} destination root path
179 */
180 destinationRoot(rootPath) {
181 let _destinationRoot = null
182 if (typeof rootPath === 'string') {
183 _destinationRoot = path.resolve(rootPath);
184
185 if (!fs.existsSync(rootPath)) {
186 makeDir.sync(rootPath);
187 }
188
189 process.chdir(rootPath);
190 } else {
191 _destinationRoot = path.resolve(rootPath);
192 }
193
194
195 return _destinationRoot;
196 }
197 /**
198 * Change the generator source root directory.
199 * This path is used by multiples file system methods like (`this.read` and `this.copy`)
200 * @param {String} rootPath new source root path
201 * @return {String} source root path
202 */
203 sourceRoot(rootPath) {
204 let _sourceRoot = null;
205 if (typeof rootPath === 'string') {
206 _sourceRoot = path.resolve(rootPath);
207 } else {
208 _sourceRoot = path.resolve('./templates');
209 }
210
211 return _sourceRoot;
212 }
213
214 /**
215 * Join a path to the source root.
216 * @param {...String} path
217 * @return {String} joined path
218 */
219 templatePath(rootPath, ...args) {
220 let filepath = path.join.apply(path, args);
221
222 if (!path.isAbsolute(filepath)) {
223 filepath = path.join(rootPath, filepath);
224 }
225
226 return filepath;
227 }
228
229 /**
230 * Join a path to the destination root.
231 * @param {...String} path
232 * @return {String} joined path
233 */
234 destinationPath(rootPath, ...args) {
235 let filepath = path.join.apply(path, args);
236
237 if (!path.isAbsolute(filepath)) {
238 filepath = path.join(rootPath, filepath);
239 }
240
241 return filepath;
242 }
243
244 async createGenerator(options) {
245 let config = {};
246 // config default options with sourcePath, targetPath
247 const _config = async () => {
248 const sourcePath = this.sourceRoot(config.origin);
249 const targetPath = this.destinationRoot(config.target);
250 this.templatePath = this.templatePath.bind(this, sourcePath);
251 this.destinationPath = this.destinationPath.bind(this, targetPath);
252 }
253
254 const { configuring = async () => {}, writing, install = async () => {}, end = async () => {}} = options
255 try {
256 config = await configuring();
257
258 await _config();
259 await writing.call(this);
260 await install.call(this);
261 await end.call(this);
262 } catch(err) {
263 throw err;
264 }
265
266
267
268 }
269}
270
271_.extend(Client.prototype, util);
272_.extend(Client.prototype, require('./util/user'));
273_.extend(Client.prototype, require('./util/install'));
274_.extend(Client.prototype, require('./util/spawn-command'));
275_.extend(Client.prototype, require('./util/emoji'));
276
277
278
279module.exports = new Client({});
\No newline at end of file