UNPKG

12.5 kBJavaScriptView Raw
1'use strict';
2
3function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
4
5const _ = require('underscore');
6const path = require('path');
7const webpack = require('webpack');
8const fs = require('fs-extra');
9const writePkg = require('write-pkg');
10
11const server_config = require('../webpack/webpack.config.server.js');
12const client_config = require('../webpack/webpack.config.client.js');
13const createStrategy = require('./strategy');
14const generateServerStrategy = require('./generateServerStrategy');
15const generateClient = require('./generateClient');
16const generateIncludes = require('./generateIncludes');
17
18const PROJECT_DIR = process.cwd();
19const DIST_DIR = path.resolve(PROJECT_DIR, 'dist');
20const MODULES_DIR = path.resolve(PROJECT_DIR, 'node_modules');
21const LIB_DIR = path.resolve(DIST_DIR, 'lib');
22const packageJson = require(path.resolve(PROJECT_DIR, 'package.json'));
23
24let stdin = process.stdin;
25let stdout = process.stdout;
26
27const mapValues = (obj, iterator) => {
28 const keys = Object.keys(obj);
29 const mapped = {};
30 keys.forEach(key => {
31 mapped[key] = iterator(obj[key], key, obj);
32 });
33 return mapped;
34};
35
36const getDependencies = () => {
37 const nodeModuleDir = path.resolve(PROJECT_DIR, 'node_modules');
38 const deps = Object.assign({}, packageJson.dependencies, packageJson.devDependencies);
39 return mapValues(deps, (_, name) => {
40 const pjf = path.resolve(nodeModuleDir, name, 'package.json');
41 const pj = require(pjf);
42 return pj.version;
43 });
44};
45
46const runWebpack = (config, options) => {
47 return new Promise((resolve, reject) => {
48 config = config(options);
49 webpack(config, (err, stats) => {
50 if (err) return reject(err);
51 const errors = stats.toJson('errors-only').errors.toString();
52 if (errors) return reject(errors);
53 resolve();
54 });
55 });
56};
57
58const copyStatic = (() => {
59 var _ref = _asyncToGenerator(function* () {
60 const src = packageJson.linc && packageJson.linc.staticDir;
61 if (src) {
62 const dirname = path.basename(src);
63 const dest = path.resolve(DIST_DIR, 'static', dirname);
64 console.log(`Copying ${src} to ${dest}`);
65 return fs.copy(src, dest, {
66 overwrite: true,
67 dereference: true,
68 preserveTimestamps: true
69 });
70 }
71 });
72
73 return function copyStatic() {
74 return _ref.apply(this, arguments);
75 };
76})();
77
78const makeBabelAbsolute = babelOptions => {
79 if (Array.isArray(babelOptions)) {
80 babelOptions[0] = path.resolve(MODULES_DIR, babelOptions[0]);
81 return babelOptions;
82 } else {
83 return path.resolve(MODULES_DIR, babelOptions);
84 }
85};
86
87const mergeOptions = (acc, curr) => {
88 acc.alias = Object.assign({}, acc.alias, curr.alias);
89 if (curr.babel && curr.babel.presets) {
90 const presets = curr.babel.presets.map(makeBabelAbsolute);
91 acc.babel.presets = acc.babel.presets.concat(presets);
92 }
93 if (curr.babel && curr.babel.plugins) {
94 const plugins = curr.babel.plugins.map(makeBabelAbsolute);
95 acc.babel.plugins = acc.babel.plugins.concat(plugins);
96 }
97 if (Array.isArray(curr.plugins)) {
98 acc.plugins = acc.plugins.concat(curr.plugins);
99 } else if (curr.plugins) {
100 acc.plugins.push(curr.plugins);
101 }
102 return acc;
103};
104
105const getConfigFragments = strategy => {
106 const all = strategy.libs.map(lib => {
107 try {
108 return require(`./libs/config_client/${lib}`).configFragment;
109 } catch (e) {}
110 }).filter(e => !!e);
111
112 const empty = { imports: [], values: [] };
113 return all.reduce((acc, curr) => {
114 if (curr.imports) acc.imports.push(curr.imports);
115 if (curr.values) acc.values = acc.values.concat(curr.values);
116 return acc;
117 }, empty);
118};
119
120const getWebpackOptions = (strategy, env) => {
121 const all = strategy.libs.map(lib => {
122 try {
123 return require(`./libs/config_client/${lib}`).webpackConfig;
124 } catch (e) {}
125 }).filter(e => !!e);
126
127 const empty = { alias: {}, babel: { presets: [], plugins: [] }, plugins: [] };
128 const options = all.map(e => e(DIST_DIR)[env]).reduce(mergeOptions, empty);
129 return options;
130};
131
132const readOnce = () => new Promise(resolve => {
133 stdin.once('data', resolve);
134});
135
136const ask = (() => {
137 var _ref2 = _asyncToGenerator(function* (question, suggestion) {
138 stdout.write(`${question}: `);
139
140 let answer = yield readOnce();
141 if (answer) {
142 answer = answer.toString().trim();
143 if (answer.length > 0) {
144 return answer;
145 }
146 }
147 stdout.write(`${suggestion}\n`);
148 return ask(question, suggestion);
149 });
150
151 return function ask(_x, _x2) {
152 return _ref2.apply(this, arguments);
153 };
154})();
155
156const getSourceDir = (() => {
157 var _ref3 = _asyncToGenerator(function* () {
158 stdin.resume();
159 const srcDir = yield ask('Directory containing your source code', 'Please provide a valid directory.');
160 stdin.pause();
161 return srcDir;
162 });
163
164 return function getSourceDir() {
165 return _ref3.apply(this, arguments);
166 };
167})();
168
169/**
170 * Get option value
171 * @param option
172 * @returns {Promise<*>}
173 */
174const getOptionValue = (() => {
175 var _ref4 = _asyncToGenerator(function* (option) {
176 stdin.resume();
177 const optionValue = yield ask(`${option.comment}, e.g., '${option.example ? option.example : option.default}'`, 'This is a mandatory field. Please enter a value.');
178 stdin.pause();
179 return optionValue;
180 });
181
182 return function getOptionValue(_x3) {
183 return _ref4.apply(this, arguments);
184 };
185})();
186
187const configLines = {
188 top: ['const config = {', " // polyfills: 'default,fetch,Symbol,Symbol.iterator,Array.prototype.find',", ' // requestExtendedUserInfo: true,'],
189 bottom: ['};', '', 'export default config']
190};
191
192const option = (() => {
193 var _ref5 = _asyncToGenerator(function* (opt, memo, lvl) {
194 const indent = ' '.repeat(lvl + 1);
195 const keys = Object.keys(opt);
196
197 // Lookahead to see if we've reached the innermost level
198 const o = opt[keys[0]];
199 const ks = Object.keys(o);
200 if (typeof o[ks[0]] === 'object') {
201 // We can go a level deeper
202 var _iteratorNormalCompletion = true;
203 var _didIteratorError = false;
204 var _iteratorError = undefined;
205
206 try {
207 for (var _iterator = keys[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
208 let k = _step.value;
209
210 memo.values = memo.values.concat(`${indent}${k}: {`);
211 yield option(opt[k], memo, lvl + 1);
212 memo.values = memo.values.concat(`${indent}},`);
213 }
214 } catch (err) {
215 _didIteratorError = true;
216 _iteratorError = err;
217 } finally {
218 try {
219 if (!_iteratorNormalCompletion && _iterator.return) {
220 _iterator.return();
221 }
222 } finally {
223 if (_didIteratorError) {
224 throw _iteratorError;
225 }
226 }
227 }
228 } else {
229 let isRequired = false;
230 // Yep, innermost level
231 var _iteratorNormalCompletion2 = true;
232 var _didIteratorError2 = false;
233 var _iteratorError2 = undefined;
234
235 try {
236 for (var _iterator2 = keys[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
237 let k = _step2.value;
238
239 let optn = opt[k];
240 let s;
241 if (optn.required) {
242 isRequired = true;
243 s = `${indent}${k}: ${yield getOptionValue(optn)}`;
244 } else {
245 if (optn.example) {
246 s = `${indent}// ${k}: ${optn.example}`;
247 } else if (optn.default) {
248 s = `${indent}// ${k}: ${optn.default}`;
249 }
250 }
251 if (s) {
252 memo.values = memo.values.concat(`${s},`);
253 }
254 }
255 } catch (err) {
256 _didIteratorError2 = true;
257 _iteratorError2 = err;
258 } finally {
259 try {
260 if (!_iteratorNormalCompletion2 && _iterator2.return) {
261 _iterator2.return();
262 }
263 } finally {
264 if (_didIteratorError2) {
265 throw _iteratorError2;
266 }
267 }
268 }
269
270 memo.required.push(isRequired);
271 }
272 });
273
274 return function option(_x4, _x5, _x6) {
275 return _ref5.apply(this, arguments);
276 };
277})();
278
279const createConfigFileContents = (() => {
280 var _ref6 = _asyncToGenerator(function* (all) {
281 const memo = {
282 values: configLines.top,
283 required: []
284 };
285 var _iteratorNormalCompletion3 = true;
286 var _didIteratorError3 = false;
287 var _iteratorError3 = undefined;
288
289 try {
290 for (var _iterator3 = all.values[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
291 let x = _step3.value;
292
293 yield option(x, memo, 0);
294 }
295 } catch (err) {
296 _didIteratorError3 = true;
297 _iteratorError3 = err;
298 } finally {
299 try {
300 if (!_iteratorNormalCompletion3 && _iterator3.return) {
301 _iterator3.return();
302 }
303 } finally {
304 if (_didIteratorError3) {
305 throw _iteratorError3;
306 }
307 }
308 }
309
310 memo.values = memo.values.concat(configLines.bottom);
311
312 // This creates a list of imports, where the imports for non-required
313 // options are commented out.
314 const imports = _.reduce(all.imports, function (m, v, i) {
315 v.forEach(function (o) {
316 return m.push(memo.required[i] ? o : `// ${o}`);
317 });
318 return m;
319 }, []);
320
321 return [imports.join('\n'), '', memo.values.join('\n'), ''].join('\n');
322 });
323
324 return function createConfigFileContents(_x7) {
325 return _ref6.apply(this, arguments);
326 };
327})();
328
329const writeFile = (file, contents) => new Promise((resolve, reject) => {
330 return fs.writeFile(file, contents, err => {
331 if (err) return reject(err);
332
333 stdout.write(`**\n** Created new config file ${file}\n**\n`);
334 return resolve();
335 });
336});
337
338const createConfigFile = (() => {
339 var _ref7 = _asyncToGenerator(function* (strategy) {
340 const CONFIG_FILENAME = 'src/linc.config.js';
341 const configFile = path.join(process.cwd(), CONFIG_FILENAME);
342
343 // Don't do anything if config file exists
344 if (!fs.existsSync(configFile)) {
345 const all = getConfigFragments(strategy);
346 const contents = yield createConfigFileContents(all);
347 writeFile(configFile, contents);
348 }
349 });
350
351 return function createConfigFile(_x8) {
352 return _ref7.apply(this, arguments);
353 };
354})();
355
356const postBuild = (() => {
357 var _ref8 = _asyncToGenerator(function* () {
358 const linc = packageJson.linc || {};
359 if (!linc.sourceDir) {
360 linc.sourceDir = yield getSourceDir();
361 yield writePkg(packageJson);
362 }
363 });
364
365 return function postBuild() {
366 return _ref8.apply(this, arguments);
367 };
368})();
369
370const build = (() => {
371 var _ref9 = _asyncToGenerator(function* (opts, callback) {
372 if (!callback) {
373 callback = opts;
374 } else {
375 stdin = opts.stdin || stdin;
376 stdout = opts.stdout || stdout;
377 }
378
379 const strategy = createStrategy(getDependencies());
380 yield createConfigFile(strategy);
381 yield generateClient(path.resolve(DIST_DIR, 'client.js'), strategy);
382 const serverStrategy = generateServerStrategy(path.resolve(DIST_DIR, 'server-strategy.js'), strategy);
383 console.log('Creating a client package. This can take a minute or two..');
384 const staticCopy = copyStatic();
385 yield runWebpack(client_config, getWebpackOptions(strategy, 'client'));
386 console.log('Created client package');
387
388 yield generateIncludes(path.resolve(LIB_DIR, 'includes.js'), path.resolve(LIB_DIR, 'includes'));
389
390 console.log('Now working on server package');
391 yield serverStrategy;
392 yield runWebpack(server_config, getWebpackOptions(strategy, 'server'));
393 yield staticCopy;
394 console.log('Created server package');
395
396 console.log('Running post build operations');
397 yield postBuild();
398
399 console.log('We have created an overview of your bundles in dist/bundle-report.html');
400
401 callback();
402 });
403
404 return function build(_x9, _x10) {
405 return _ref9.apply(this, arguments);
406 };
407})();
408
409module.exports = build;
410//# sourceMappingURL=index.js.map
\No newline at end of file