Skip to content

Instantly share code, notes, and snippets.

@bowd
Created January 16, 2015 01:13
Show Gist options
  • Save bowd/35069f835b7b34bc1b88 to your computer and use it in GitHub Desktop.
Save bowd/35069f835b7b34bc1b88 to your computer and use it in GitHub Desktop.
/* Node modules builder for components */
var fs = require('fs')
, _ = require('lodash')
, mkdirp = require('mkdirp')
, path = require('path');
var NodeModulesBuilder = function(tree, base) {
this.traverseCache = {};
this.buildNodeModules(tree);
};
_.extend(NodeModulesBuilder.prototype, {
buildNodeModules: function(node) {
var self = this, deps;
// Short circuite if the dependency has already been modulized
if (this.traverseCache[node.name]) {
return;
} else {
this.traverseCache[node.name] = true;
}
// Make sure the component has an index.js/jsx
// to be compatible with default node lookup
if (node.type == 'dependency' && !this.hasEntryPoint(node)) {
this.createDependencyEntryPoint(node);
}
// Create a node_modules folder if none exists
this.createNodeModulesFolder(node);
deps = _.union(_.values(node.locals), _.values(node.dependencies));
_.each(deps, function(dep) {
self.buildNodeModules(dep);
self.linkDepLocally(node, dep);
});
},
linkDepLocally: function(source, target) {
var sourceNodeModules = path.join(source.path, 'node_modules')
, pathSegments = target.node.name.split(path.sep)
, symlinkTarget, symlinkTargetHead, symlinkTargetTail;
if (pathSegments.length > 1 ) {
// We need to make some nesting dirs first
symlinkTargetHead = pathSegments.pop()
symlinkTargetTail = path.join(
sourceNodeModules,
pathSegments.join(path.sep)
);
mkdirp.sync(symlinkTargetTail);
symlinkTarget = path.join(symlinkTargetTail, symlinkTargetHead);
} else {
symlinkTarget = path.join(sourceNodeModules, target.node.name);
}
if (fs.existsSync(symlinkTarget)) {
if (fs.readlinkSync(symlinkTarget) !== target.path) {
fs.unlinkSync(symlinkTarget);
fs.symlinkSync(target.path, symlinkTarget);
}
} else {
fs.symlinkSync(target.path, symlinkTarget);
}
},
createNodeModulesFolder: function(node) {
var nodeModulesPath = path.join(node.path, 'node_modules');
if (!fs.existsSync(nodeModulesPath)) {
fs.mkdirSync(nodeModulesPath);
}
},
hasEntryPoint: function(node) {
var jsEntryPoint = path.join(node.path, 'index.js')
, jsxEntryPoint = path.join(node.path, 'index.jsx');
return fs.existsSync(jsEntryPoint) ||
fs.existsSync(jsxEntryPoint);
},
createDependencyEntryPoint: function(node) {
var entryPoint = path.join(node.path, node.node.main)
, canonicalEntryPoint = path.join(
node.path,
node.node.main.match(/jsx$/) !== null ? 'index.jsx' : 'index.js'
);
fs.symlinkSync(entryPoint, canonicalEntryPoint);
},
});
module.exports = function(tree, base, cb) {
var builder = new NodeModulesBuilder(tree, base);
return cb();
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment