UNPKG

10.2 kBJavaScriptView Raw
1#!/usr/bin/env node
2'use strict';
3
4var _commander = require('commander');
5
6var _commander2 = _interopRequireDefault(_commander);
7
8var _child_process = require('child_process');
9
10var _child_process2 = _interopRequireDefault(_child_process);
11
12var _fs = require('fs');
13
14var _fs2 = _interopRequireDefault(_fs);
15
16var _path = require('path');
17
18var _path2 = _interopRequireDefault(_path);
19
20var _tsort = require('tsort');
21
22var _tsort2 = _interopRequireDefault(_tsort);
23
24var _stream = require('stream');
25
26var _stream2 = _interopRequireDefault(_stream);
27
28var _maketConf = require('@eknkc/maket-conf');
29
30var _maketConf2 = _interopRequireDefault(_maketConf);
31
32var _flatten = require('./flatten');
33
34var _flatten2 = _interopRequireDefault(_flatten);
35
36var _lodash = require('lodash.template');
37
38var _lodash2 = _interopRequireDefault(_lodash);
39
40function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
41
42const json = require.resolve('.bin/json');
43const concurrently = require.resolve('.bin/concurrently');
44const nodemon = require.resolve('.bin/nodemon');
45const babel = require.resolve('.bin/babel');
46const stylus = require.resolve('.bin/stylus');
47const babelParams = ['-s', 'inline', '-D'];
48const cwd = process.cwd();
49
50const config = (0, _maketConf2.default)(cwd);
51
52if (!config) exit("No maket.yaml config found.");
53
54function resolve(path, name = path) {
55 try {
56 let res = _child_process2.default.spawnSync('/usr/bin/env', ['node', '-e', 'process.stdout.write(require.resolve(process.argv[1]))', path], { cwd });
57
58 if (res.status !== 0) throw new Error();
59
60 return res.stdout.toString('utf8');
61 } catch (e) {
62 return exit(`Unable to resolve ${ name }`);
63 }
64}
65
66_commander2.default.command('browserify').option('-w, --watch', 'Watch mode').description("Build browserify bundle").action(function () {
67 const browserify = require('browserify');
68 const watchify = require('watchify');
69 const browserifycss = require('browserify-css');
70 const babelify = require('babelify');
71 const envify = require('envify/custom');
72 const factor = require('factor-bundle');
73
74 if (!config.$browserify) return exit("No browserify configuration found.");
75
76 let cnf = config.$browserify;
77
78 if (!Array.isArray(cnf)) cnf = [cnf];
79
80 cnf.forEach(cf => {
81 if (!cf.add || !cf.dest) return exit("Browserify needs an add and dest field");
82 if (!Array.isArray(cf.add)) cf.add = [cf.add];
83 cf.add = cf.add.map(a => _path2.default.resolve(cwd, a));
84
85 var b = browserify(cf.add, {
86 extensions: [".js", ".jsx", ".json", ".css"],
87 paths: [_path2.default.join(cwd, 'node_modules')],
88 cache: {},
89 packageCache: {},
90 debug: !!this.watch
91 }).transform(babelify, { presets: [require('babel-preset-es2015'), require('babel-preset-react')] }).transform(browserifycss, {
92 global: true,
93 onFlush({ data }, done) {
94 done(`
95 (function() {
96 var elem = document.createElement('style');
97 var css = ${ JSON.stringify(data) };
98 elem.setAttribute('type', 'text/css');
99
100 if ('textContent' in elem) {
101 elem.textContent = css;
102 } else {
103 elem.styleSheet.cssText = css;
104 }
105
106 var head = document.getElementsByTagName('head')[0];
107 head.appendChild(elem);
108 })();
109 `);
110 }
111 }).transform(envify({
112 NODE_ENV: this.watch ? 'development' : 'production'
113 }), {
114 global: true
115 }).transform((filename, opts) => {
116 if (this.watch || /\.min\./.test(filename) || /\.json$/.test(filename)) return new _stream2.default.PassThrough();
117
118 var uglifyjs = require('uglify-js');
119
120 var js = "";
121 var transform = new _stream2.default.Transform();
122
123 transform._transform = function (data, enc, next) {
124 js += data.toString('utf8');
125 next();
126 };
127
128 transform._flush = function (next) {
129 try {
130 js = uglifyjs.minify(js, { fromString: true }).code;
131 this.push(js);
132 next(null);
133 } catch (e) {
134 next(e);
135 }
136 };
137
138 return transform;
139 }, {
140 global: true
141 });
142
143 if (cf.factor && Array.isArray(cf.factor)) b.plugin(factor, { outputs: cf.factor.map(f => _path2.default.resolve(cwd, f)) });
144
145 bundle();
146
147 if (this.watch) {
148 b.plugin(watchify);
149 b.on('update', bundle);
150 }
151
152 function bundle() {
153 b.bundle().on('error', function (err) {
154 console.log("browserify", "error");
155
156 if (err._babel && err instanceof SyntaxError) {
157 console.log(`${ err.name }: ${ err.message }\n${ err.codeFrame }`);
158 } else if (err.stack) {
159 console.log(err.stack);
160 } else {
161 console.log(err);
162 }
163 }).pipe(_fs2.default.createWriteStream(_path2.default.resolve(cwd, cf.dest))).on('close', () => {
164 console.log('browserify', 'buildEnd', cf.dest);
165 });
166 }
167 });
168});
169
170_commander2.default.command('stylus').option('-w, --watch', 'Watch mode').description("Build stylus").action(function () {
171 if (!config.$stylus) return exit("No stylus configuration found.");
172
173 let entry = config.$stylus.entry;
174 let dest = config.$stylus.dest;
175
176 if (!entry || !dest) return exit("Malformed stylus config.");
177
178 let params = ['-u', require.resolve('nib'), '-u', require.resolve('jeet'), '-u', require.resolve('rupture')];
179
180 if (this.watch) params.push('-w', "--sourcemap-inline");else params.push('--compress');
181
182 if (config.$stylus.paths) {
183 config.$stylus.paths.forEach(p => params.push('-I', _path2.default.resolve(cwd, p)));
184 }
185
186 params.push('--out', _path2.default.resolve(cwd, dest));
187 params.push(_path2.default.resolve(cwd, entry));
188
189 console.log('stylus', this.watch ? 'watch' : 'buildStart', dest);
190 _child_process2.default.spawnSync(stylus, params, {
191 stdio: ['ignore', 'ignore', 'inherit'],
192 cwd: __dirname
193 });
194 console.log('stylus', 'buildEnd', dest);
195});
196
197_commander2.default.command('babel').option('-w, --watch', 'Watch mode').description("Build babel").action(function () {
198 if (!config.$babel) return exit("No babel configuration found.");
199
200 let source = config.$babel.source;
201 let dest = config.$babel.dest;
202
203 if (!source || !dest) return exit("Babel requires source and dest.");
204
205 let params = [...babelParams];
206
207 params.push('--presets', [require.resolve('babel-preset-es2015-node'), require.resolve('babel-preset-stage-3')].join(','));
208
209 if (this.watch) params.push('--watch');
210
211 params.push('--out-dir', _path2.default.resolve(cwd, dest), _path2.default.resolve(cwd, source));
212
213 console.log('babel', this.watch ? 'watch' : 'buildStart', source, dest);
214 _child_process2.default.spawnSync(babel, params, {
215 stdio: ['ignore', 'ignore', 'inherit'],
216 cwd: __dirname
217 });
218 console.log('babel', 'buildEnd', source, dest);
219});
220
221_commander2.default.command('json [args...]').description("JSON helper").action(function (args) {
222 _child_process2.default.spawnSync(json, args, { stdio: 'inherit' });
223});
224
225_commander2.default.command('concurrent [args...]').description("Run multiple shell commands at once").action(function (args) {
226 _child_process2.default.spawnSync(concurrently, ['-k', ...args], { stdio: 'inherit' });
227});
228
229_commander2.default.command('nodemon -- [args...]').description("Nodemon proxy").action(function (args) {
230 _child_process2.default.spawnSync(nodemon, args, { stdio: 'inherit' });
231});
232
233_commander2.default.command('run <script> [args...]').description("Run a maket script").action(function (script, args) {
234 let scripts = {};
235 let graph = (0, _tsort2.default)();
236
237 addScript(script);
238
239 function addScript(name) {
240 if (scripts[name]) return;
241
242 let scr = getScript(name);
243 scripts[name] = scr;
244
245 graph.add(name);
246
247 if (scr.after.length) {
248 scr.after.forEach(addScript);
249 graph.add([...scr.after, name]);
250 }
251
252 if (scr.before.length) {
253 scr.before.forEach(addScript);
254 graph.add([name, ...scr.before]);
255 }
256 }
257
258 let queue;
259
260 try {
261 queue = graph.sort().map(s => scripts[s]);
262 } catch (e) {
263 return exit("There is a cycle in script order.");
264 }
265
266 let env = {
267 MAKET: __filename
268 };
269
270 let fconf = (0, _flatten2.default)(config);
271
272 Object.keys(fconf).forEach(k => {
273 if (k.indexOf('$') >= 0) return;
274
275 env[`MAKET_${ k.toUpperCase().replace(/[\.\[\]]/g, '_') }`] = fconf[k];
276 });
277
278 let proc = _child_process2.default.spawn('/usr/bin/env', ['bash'], {
279 stdio: ['pipe', 'inherit', 'inherit'],
280 env: Object.assign({}, process.env, env)
281 });
282
283 proc.stdin.write('set -e\n');
284
285 queue.forEach(q => {
286 q.commands.forEach(c => {
287 proc.stdin.write(c + '\n');
288 });
289 });
290
291 proc.stdin.end();
292});
293
294_commander2.default.command('tpl <filename>').description("Render template").action(function (filename) {
295 let tpl;
296
297 try {
298 tpl = _fs2.default.readFileSync(_path2.default.resolve(cwd, filename), { encoding: 'utf8' });
299 } catch (e) {
300 return exit("Unable to read file: " + filename);
301 }
302
303 process.stdout.write((0, _lodash2.default)(tpl)(Object.assign({ encode }, config)));
304
305 function encode(value) {
306 return JSON.stringify(value).replace(/^"/, "").replace(/"$/, "");
307 }
308});
309
310_commander2.default.command('config [path]').description("Get maket configuration").action(function (cpath) {
311 let res = config;
312
313 if (cpath) res = res[cpath];
314
315 if (typeof res === 'string') return process.stdout.write(res);
316
317 process.stdout.write(JSON.stringify(res, null, " "));
318});
319
320_commander2.default.parse(process.argv);
321
322function exit(message, code = -1) {
323 console.error(message);
324 process.exit(code);
325}
326
327function getScript(name) {
328 let scripts = config.$scripts || {};
329 let scr = scripts[name];
330
331 if (!scr) return exit("Script not found.");
332
333 if (typeof scr === 'string') scr = { commands: [scr] };else if (Array.isArray(scr)) scr = { commands: scr };
334
335 scr.after = scr.run_after || [];
336 scr.before = scr.run_before || [];
337 scr.commands = scr.commands || scr.cmd || [];
338
339 if (!Array.isArray(scr.after)) scr.after = [scr.after];
340 if (!Array.isArray(scr.before)) scr.before = [scr.before];
341 if (!Array.isArray(scr.commands)) scr.commands = [scr.commands];
342
343 return scr;
344}
\No newline at end of file