UNPKG

amend-bundle

Version:

Bundle all code from an amend container to one file

157 lines (139 loc) 4.28 kB
require('node-jsx').install({extension: '.jsx'}) var amend = require('amend'); var babel = require('babel') var uglify = require('uglify-js') var fs = require('fs') var getConfigPaths = amend.getConfigPaths; var evaluateType = amend.evaluateType; var readFile = require('./read-file'); var R = require('ramda') var RF = require('ramda-fantasy') var Future = RF.Future var wrap = require('./wrap') var ject = require('ject') var dependencyTemplate = "di.{{type}}('{{key}}', require('{{registeredPath}}'))\n" var moduleTemplate = "di.{{type}}('{{key}}', {{code}})\n" var codeLens = R.lensProp('code') var stripExports = R.map(R.replace(/^module.exports = /, ''), codeLens) var callback /* * 1 Get paths * 2 Filter out config files * 3 ForEach: require, evaluateType, return Future of object with path, type, code * 4 Transform code, inject in di, babel, uglify * 5 commute * 6 wrap in wrapper * * Listen: * perform step 4 for that specific file * replace cached future with new one * step 5 and 6 * */ function fetchModule(mod) { var out; var future = Future.cache(readFile(mod.path) .map(function(code) { return R.assoc('code', code, out); }).map(processModuleCode)) return out = R.assoc('future', future, mod); } function includeDependency (mod) { var code = ject(dependencyTemplate, mod) var outModule = R.assoc('code', code, mod) var future = Future.of(outModule) .map(function (a) { return R.assoc('future', future, a) }) return R.assoc('future', future, outModule) } function logError(e) { console.error(e); console.error(e.stack); console.error(e.stack); } var rejectConfigs = R.reject(R.prop('isConfig')); var filterLocals = R.filter(R.prop('isLocal')) var noLocals = R.reject(R.prop('isLocal')) var resolvePath = function(mod) { return R.assoc('path', require.resolve(mod.path), mod); } function doEvaluateType (mod) { var type = evaluateType(mod.module, require(mod.path)) return R.assoc('type', type, mod) } var transduceFn = R.compose(rejectConfigs, R.map(doEvaluateType), R.map(resolvePath)) var findIndexByPath = R.useWith(R.findIndex, R.propEq('path')); var futures; function listenForFilechange(path) { var opts = { interval: 200 }; fs.watchFile(path, opts, function() { var i = findIndexByPath(path, futures); var incorrect = R.filter(R.compose(R.isNil, R.prop('future')), futures) futures = R.adjust(fetchModule, i, futures); callback(createOutputFuture(futures)) }) } function watchModule(mod) { listenForFilechange(mod.path); } var processModules = R.compose( //R.map(R.tap(watchModule)), R.map(R.ifElse(R.prop('isLocal'), fetchModule, includeDependency)) ) function isJSON (fileName) { return filename.endsWith('.json') } function doBabel(mod) { try { if (isJSON(mod.path)) { return mod } var transformed = babel.transform(mod.code, { blacklist: [ 'strict' ]}).code var exportIndex = R.indexOf('module.exports', transformed) var trimmed = R.drop(exportIndex, transformed) return R.assoc('code', trimmed, mod) } catch (e) { throw new Error('Babel error in module ' + mod.path) } } function doUglify(mod) { try { var result = uglify.minify(mod.code, { fromString: true, mangle: false }); return R.assoc('code', result.code, mod); } catch (e) { e.filename = mod.path throw e } } function removeExports (mod) { var stripped = stripExports(mod) var result = ject(moduleTemplate, stripped) return R.assoc('code', result, mod) } function removeLastSemi (code) { return R.replace(/;$/, '', code) } var processModuleCode = R.compose( // doUglify, removeExports, R.map(removeLastSemi, codeLens), doBabel ) function createOutputFuture(modules) { return R.commute(Future.of, R.pluck('future', modules)) .map(R.tap(function(list) { futures = list; })) .map(R.pluck('code')) .map(R.reduce(R.concat, '')) .map(wrap) } module.exports = function bundle(opts, config, cb) { callback = cb var modules = getConfigPaths(opts.baseDir, config); modules = R.transduce(transduceFn, R.flip(R.append), [], modules); modules = processModules(modules) var incorrect = R.filter(R.compose(R.isNil, R.prop('future')), modules) cb(createOutputFuture(modules)) }