UNPKG

steal-tools

Version:

Futuristic build tools for ES6 Module applications.

201 lines (173 loc) 5.84 kB
var clone = require("lodash/clone"); var assign = require("lodash/assign"); var includes = require("lodash/includes"); var dependencyGraph = require("./make_graph"); var normalizeBundle = require("../loader/normalize_bundle"); var through = require("through2"); var fs = require("fs-extra"); var assignDefaultOptions = require("../assign_default_options"); var slice = Array.prototype.slice; function addBundleOnEveryModule (graph, bundle){ for(var name in graph) { addBundle( graph[name],bundle ); } } function addBundle (node, bundle) { if(!node.bundles) { node.bundles = [bundle]; } else if(node.bundles.indexOf(bundle) == -1) { node.bundles.push(bundle); } } // merges everything in `newGraph` into `masterGraph` and make sure it lists // `bundle` as one of its bundles. function mergeIntoMasterAndAddBundle(opts) { var mains = opts.mains; var loader = opts.loader; var newGraph = opts.newGraph; var bundleName = opts.bundleName; var masterGraph = opts.masterGraph; for(var name in newGraph) { if(!masterGraph[name]) { masterGraph[name] = newGraph[name]; } // If it's a plugin we'll use the new node but need to copy any previous // bundles onto the new node else if(masterGraph[name] && masterGraph[name].isPlugin) { var oldBundle = masterGraph[name].bundles || []; masterGraph[name] = newGraph[name]; oldBundle.forEach(function(bundle){ addBundle(masterGraph[name], bundle); }); } // If this is the configMain like package.json!npm we need to override // the source every time because it continuously changes. else if(masterGraph[name] && name === loader.configMain) { var node = masterGraph[name]; node.load.source = newGraph[name].load.source; } // do not track bundles of entry point modules (a.k.a mains) unless // it is its own bundle. if (name === bundleName || !includes(mains, name)) { addBundle(masterGraph[name], bundleName); } } } function mergeConfigForNextBundle(system, loader){ if(loader.npmContext) { system.npmContext = loader.npmContext; } if(loader.npmParentMap) { system.npmParentMap = loader.npmParentMap; } } // Create temporary files for virtual modules. function createModuleConfig(loader) { var tmp = require("tmp"); var config = {}; var virtualModules = loader.virtualModules || {}; for(var moduleName in virtualModules) { var filename = tmp.fileSync().name; var source = virtualModules[moduleName]; fs.writeFileSync(filename, source, "utf8"); var paths = config.paths = config.paths || {}; paths[moduleName] = "file:"+filename; } return config; } // If `prop` exists in the `src` object, it copies its value to `dest` function copyIfSet(src, dest, prop) { if (src[prop]) { dest[prop] = src[prop]; } } var makeBundleGraph = module.exports = function makeBundleGraph(config, options) { if(!options) options = {}; options = assignDefaultOptions(config, options); // the names of everything we are going to load var bundleNames = []; var cfg = clone(config, true); if( Array.isArray(cfg.main) ) { bundleNames = slice.call(cfg.main); cfg.main = bundleNames.shift(); } // Get the first dependency graph return dependencyGraph(cfg, options) .then(normalizeBundle) .then(function(data){ // TODO I left off here, need to make sure main is normalized. var masterGraph = data.graph, main = data.steal.System.main; // add the "main" bundle to everything currently on the main dependency graph; addBundleOnEveryModule(masterGraph, main); // Get the bundles of the loader var loader = data.steal.System; bundleNames = bundleNames.concat(loader.bundle.slice(0)); // Get config for virtual modules options.system = createModuleConfig(loader); mergeConfigForNextBundle(options.system, data.loader); // Get the next bundle name and gets a graph for it. // Merges those nodes into the masterGraph var getNextGraphAndMerge = function(){ var nextBundle = bundleNames.shift(); var mains = Array.isArray(config.main) ? config.main.slice(0) : [data.loader.main]; var mainsPromise = Promise.all(mains.map(function(main){ return data.loader.normalize(main); })); if(!nextBundle) { return mainsPromise.then(function(nmains) { // If there are no more bundles, return data return { graph: masterGraph, steal: data.steal, loader: data.loader, buildLoader: data.buildLoader, mains: nmains, config: config, options: options }; }); } else { var nmains; var copy = assign(clone(cfg), { main: nextBundle }); // share these objects among steal instances so the configuration // from all bundles can be collected in a single object, otherwise // each time the dependency graph of a bundle is created; any // plugin/extension used by the bundle will set its configuration // to a fresh object reference that's lost after the dependency // graph is created. copyIfSet(data.loader, options, "slimConfig"); return mainsPromise .then(function(normalised) { nmains = normalised; return dependencyGraph(copy, options); }) .then(function(data){ mergeIntoMasterAndAddBundle({ masterGraph: masterGraph, newGraph: data.graph, bundleName: data.steal.System.main, loader: data.loader, mains: nmains }); mergeConfigForNextBundle(options.system, data.loader); return getNextGraphAndMerge(); }); } }; return getNextGraphAndMerge(); }); }; // A Stream version of makeBundleGraph makeBundleGraph.createBundleGraphStream = function(){ var args = arguments; var stream = through.obj(function(moduleName, enc, done){ return makeBundleGraph.apply(null, args).then(function(data){ done(null, data); }, done); }); stream.write(); return stream; };