UNPKG

8.71 kBJavaScriptView Raw
1/* eslint-disable global-require */
2
3const argv = process.argv.slice(2);
4
5// partial impl from `rc`
6const win = process.platform === 'win32';
7const cwd = process.cwd();
8const etc = '/etc';
9
10const home = win
11 ? process.env.USERPROFILE
12 : process.env.HOME;
13
14let _task = 'default';
15
16/* istanbul ignore else */
17if (/^(?!-)[\w:-]+$/.test(argv[0])) {
18 _task = argv.shift() || _task;
19}
20
21let $;
22
23try {
24 $ = require('wargs')(argv, {
25 camelCase: true,
26 boolean: 'ODIGRCAVvdqfhba',
27 alias: {
28 O: 'no-install-opts',
29 D: 'no-install-dev',
30 I: 'no-install',
31 G: 'no-clone',
32 R: 'no-exec',
33 C: 'no-copy',
34 A: 'no-add',
35 V: 'verbose',
36 v: 'version',
37 d: 'debug',
38 q: 'quiet',
39 f: 'force',
40 e: 'entry',
41 g: 'gist',
42 h: 'help',
43 b: 'bare',
44 a: 'ask',
45 },
46 });
47} catch (e) {
48 process.stderr.write(`\r\x1b[31m${e.message}\x1b[0m\n`);
49 process.exit(1);
50}
51
52const cleanStack = require('clean-stack');
53const path = require('path');
54const fs = require('fs');
55
56// nice logs!
57const log = require('log-pose')
58 .getLogger(12, process.stdout, process.stderr);
59
60const Haki = require('../lib');
61const util = require('../lib/utils');
62const thisPkg = require('../package.json');
63
64const CONFIG = {};
65const CACHE = [];
66
67const _gists = path.join(home, '.config', thisPkg.name, 'gists');
68
69/* istanbul ignore else */
70if (!fs.existsSync(path.dirname(_gists))) {
71 fs.mkdirSync(path.dirname(_gists));
72}
73
74/* istanbul ignore else */
75if (!fs.existsSync(_gists)) {
76 fs.mkdirSync(_gists);
77}
78
79let depth = 20;
80let pwd = cwd;
81let tmp;
82
83const haki = new Haki(util.extend({}, $.flags, { data: $._ }));
84
85if ($.flags.entry) {
86 haki.load(path.resolve($.flags.entry));
87}
88
89function showError(e) {
90 log.printf('{% fail %s %}\r\n', ($.flags.debug && cleanStack(e.stack)) || e.message);
91}
92
93function showHelp(tasks) {
94 log.write('\r\n Usage:\n haki COMMAND [...]\n');
95
96 /* istanbul ignore else */
97 if (tasks.length) {
98 tasks.forEach(params => {
99 log.write(` haki ${util.padding(params.name, 20)}${
100 params.message ? [' # ', params.message].join('') : ''
101 }\n`);
102 });
103 }
104
105 log.write(`
106 Options:
107 -g, ${util.padding('[--gist]', 15)} # Manage and download gists (e.g. -g 7f473b462ca7ecd3f648853ba6e44e2a)
108 -f, ${util.padding('[--force]', 15)} # Overwrite files that already exist
109 -f, ${util.padding('[--verbose]', 15)} # Display more information on logs
110 -v, ${util.padding('[--version]', 15)} # Print version and quit
111 -d, ${util.padding('[--debug]', 15)} # Print stack on error
112 -q, ${util.padding('[--quiet]', 15)} # Supress status output
113 -b, ${util.padding('[--bare]', 15)} # Remove additional logs
114 -b, ${util.padding('[--ask]', 15)} # Choose from registered tasks
115 -h, ${util.padding('[--help]', 15)} # Show this help message
116
117`);
118
119 /* istanbul ignore else */
120 if ($.flags.verbose) {
121 log.write(' Hakifiles:\n');
122
123 CACHE.forEach(file => {
124 log.write(` ${file}\n`);
125 });
126
127 log.write('\n');
128 }
129}
130
131function gists(id) {
132 /* istanbul ignore else */
133 if (!tmp) {
134 tmp = {};
135 fs.readdirSync(_gists)
136 .filter(src => src.indexOf('.json') > -1)
137 .forEach(src => {
138 tmp[path.basename(src, '.json')] = require(path.join(_gists, src));
139 });
140 }
141
142 /* istanbul ignore else */
143 if (id) {
144 return tmp[id];
145 }
146
147 return tmp;
148}
149
150function detail(data) {
151 log.printf('{% link %s %}\r\n', data.html_url);
152 log.printf(' {% gray %s <%s> %}\r\n', data.updated_at, data.owner.login);
153 log.printf(' {% gray %s %}\r\n', data.description);
154}
155
156function setup(id, data) {
157 return Promise.resolve()
158 .then(() => {
159 /* istanbul ignore else */
160 if (data.message) {
161 log.printf('\r\r{% warn %s %}\n', data.message);
162 log.printf('{% link %s %}\n', data.documentation_url);
163 util.die(1);
164 }
165
166 /* istanbul ignore else */
167 if (!(data.files && data.files['Hakifile.js'])) {
168 throw new Error(`Gist ${data.html_url} does not contains a Hakifile.js`);
169 }
170
171 const dir = path.join(_gists, id);
172
173 /* istanbul ignore else */
174 if (!fs.existsSync(dir)) {
175 fs.mkdirSync(dir);
176 }
177
178 Object.keys(data.files).forEach(src => {
179 fs.writeFileSync(path.join(dir, src), data.files[src].content);
180 });
181
182 detail(data);
183 });
184}
185
186function save(id, data) {
187 try {
188 return setup(id, data).then(() => {
189 fs.writeFileSync(path.join(_gists, `${id}.json`), JSON.stringify(data));
190 util.die();
191 }).catch(e => {
192 showError(e);
193 util.die(1);
194 });
195 } catch (e) {
196 showError(e);
197 util.die(1);
198 }
199}
200
201function load(filepath) {
202 /* istanbul ignore else */
203 if (CACHE.indexOf(filepath) > -1) {
204 return;
205 }
206
207 try {
208 /* istanbul ignore else */
209 if (fs.existsSync(filepath)) {
210 if (fs.statSync(filepath).isDirectory()) {
211 const Hakifile = fs.readdirSync(filepath)
212 .filter(file => file.indexOf('Hakifile') > -1);
213
214 /* istanbul ignore else */
215 if (Hakifile.length) {
216 require(path.join(filepath, Hakifile[0]))(haki);
217 CACHE.push(filepath);
218 }
219 } else {
220 util.extend(CONFIG, JSON.parse(fs.readFileSync(filepath).toString()));
221 }
222 }
223 } catch (e) {
224 showError(e);
225 util.die(1);
226 }
227}
228
229function list() {
230 log.printf('{% info Listing gists from %s %}\n', _gists);
231
232 const src = gists();
233 const keys = Object.keys(src).length;
234
235 Object.keys(src).forEach(key => {
236 detail(src[key]);
237 });
238
239 log.printf('{% log %s gist%s found %}\n', keys, keys === 1 ? '' : 's');
240}
241
242function get(id) {
243 try {
244 log(false, `Fetching Gist ${id} ...`, () => {
245 /* istanbul ignore else */
246 if (gists(id) && $.flags.force !== true) {
247 showError(new Error(`Gist ${id} already installed`));
248 util.die(1);
249 }
250
251 return new Promise((resolve, reject) => {
252 let data = '';
253
254 require('https').get({
255 path: `/gists/${id}`,
256 host: 'api.github.com',
257 headers: {
258 'User-Agent': `NodeJS/Haki v${thisPkg.version}`,
259 },
260 }, res => {
261 res.on('data', chunk => {
262 data += chunk;
263 });
264
265 res.on('end', () => {
266 try {
267 save(id, JSON.parse(data))
268 .then(resolve)
269 .catch(reject);
270 } catch (e) {
271 reject(e);
272 }
273 });
274 }).on('error', e => {
275 reject(e);
276 });
277 }).catch(e => {
278 showError(e);
279 util.die(1);
280 });
281 });
282 } catch (e) {
283 showError(e);
284 util.die(1);
285 }
286}
287
288function run() {
289 if (!$.flags.bare) {
290 log.printf('{% wait Finding Hakifile(s) ... %}\r\r');
291
292 // built-in generators
293 require('./Hakifile')(haki);
294
295 load(path.join(etc, '.config', thisPkg.name));
296 load(path.join(etc, `.${thisPkg.name}rc`));
297
298 load(path.join(home, '.config', thisPkg.name));
299 load(path.join(home, `.${thisPkg.name}rc`));
300
301 while (depth > 0) {
302 load(path.join(pwd, '.config', thisPkg.name));
303 load(path.join(pwd, `.${thisPkg.name}rc`));
304 load(pwd);
305
306 pwd = path.dirname(pwd);
307
308 depth -= 1;
309
310 /* istanbul ignore else */
311 if (pwd === '/' || pwd === home) {
312 break;
313 }
314 }
315
316 // installed gists
317 Object.keys(gists()).forEach(id => {
318 load(path.join(_gists, id));
319 });
320
321 log.printf('{% log %s Hakifile%s found %}\r\n', CACHE.length, CACHE.length === 1 ? '' : 's');
322 }
323
324 /* istanbul ignore else */
325 if ($.flags.help) {
326 showHelp(haki.getGeneratorList());
327 util.die();
328 }
329
330 if (haki.hasGenerator(_task)) {
331 haki.runGenerator(_task, util.extend({}, $.data, $.params, CONFIG))
332 .catch(e => {
333 showError(e);
334 util.die(1);
335 });
336 } else {
337 log.printf('{% fail Missing `%s` generator %}\r\n', _task);
338 util.die(1);
339 }
340}
341
342/* istanbul ignore else */
343if ($.flags.version) {
344 log.printf('{% green %s v%s %} {% gray (node %s) %}\n',
345 thisPkg.name, thisPkg.version, process.version);
346 util.die();
347}
348
349if (!$.flags.bare) {
350 log.printf('{% green Haki v%s %} {% gray (%s in %s) %}\n', thisPkg.version, _task, process.env.NODE_ENV || '?');
351}
352
353process.on('exit', statusCode => {
354 /* istanbul ignore else */
355 if (!statusCode && !$.flags.bare) {
356 log.printf('\r\r{% end Done. %}\r\n');
357 }
358 util.die();
359});
360
361/* istanbul ignore else */
362if ($.flags.gist) {
363 /* istanbul ignore else */
364 if ($.flags.gist !== true) {
365 get($.flags.gist);
366 } else {
367 list();
368 }
369} else if ($.flags.ask) {
370 haki.chooseGeneratorList()
371 .catch(e => {
372 showError(e);
373 util.die(1);
374 });
375} else {
376 run();
377}