npm-link-up
Version:
Use this package to link your projects together for local development.
152 lines (151 loc) • 5.66 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const path = require("path");
const fs = require("fs");
const logging_1 = require("../../logging");
const chalk_1 = require("chalk");
const cmd_line_opts_1 = require("../run/cmd-line-opts");
const dashdash = require('dashdash');
const async = require("async");
const utils_1 = require("../../utils");
const treeify = require('treeify');
const allowUnknown = process.argv.indexOf('--allow-unknown') > 0;
let opts, globalConf, parser = dashdash.createParser({ options: cmd_line_opts_1.default, allowUnknown });
try {
opts = parser.parse(process.argv);
}
catch (e) {
logging_1.default.error(chalk_1.default.magenta('CLI parsing error:'), chalk_1.default.magentaBright.bold(e.message));
process.exit(1);
}
if (opts.help) {
let help = parser.help({ includeEnv: true }).trimRight();
console.log('usage: nlu run [OPTIONS]\n'
+ 'options:\n'
+ help);
process.exit(0);
}
const cwd = process.cwd();
let { nluFilePath } = utils_1.handleConfigCLIOpt(cwd, opts);
const searchRoot = process.cwd();
logging_1.default.info('Searching for symlinked packages in this directory:', searchRoot, '\n');
const queue = async.queue((task, cb) => task(cb), 8);
let key = `${path.basename(searchRoot)} (root)`;
const treeObj = { [key]: {} };
const ignore = new Set(['.git', '.idea', '.r2g', 'dist', 'build', '.vscode']);
const searchDir = (dir, node, cb) => {
const handleSymbolicLink = (itemPath, name, cb) => {
fs.stat(itemPath, (err, stats) => {
if (err) {
logging_1.default.warning(err);
return cb(null);
}
if (!stats.isDirectory()) {
logging_1.default.warning('Symbolic link in node_modules points to a non-directory:', itemPath);
return cb(null);
}
fs.realpath(itemPath, (err, p) => {
if (err) {
logging_1.default.warning(err);
return cb(null);
}
node[name] = chalk_1.default.bold('❖ ') + chalk_1.default.underline(p) + ' ';
cb(null);
});
});
};
const handleOrg = (orgDir, orgName, cb) => {
fs.readdir(orgDir, (err, items) => {
if (err) {
logging_1.default.warning(err.message);
return cb(null);
}
async.eachLimit(items, 8, (v, cb) => {
const pth = path.resolve(orgDir, v);
fs.lstat(pth, (err, stats) => {
if (err) {
logging_1.default.warning(err.message);
return cb(null);
}
if (stats.isSymbolicLink()) {
return handleSymbolicLink(pth, orgName + '/' + v, cb);
}
cb(null);
});
}, cb);
});
};
queue.push(callback => {
fs.readdir(dir, (err, items) => {
callback(null);
if (err) {
logging_1.default.warning(err.message);
return cb(null);
}
const searchable = items.filter(v => !ignore.has(v));
async.eachLimit(searchable, 8, (v, cb) => {
const itemPath = path.resolve(dir + '/' + v);
const parentDir = path.basename(path.dirname(itemPath));
const nodeModulesIsParent = parentDir === 'node_modules';
fs.lstat(itemPath, (err, stats) => {
if (err) {
logging_1.default.warning(err.message);
return cb(null);
}
if (stats.isFile()) {
return cb(null);
}
if (nodeModulesIsParent) {
if (stats.isSymbolicLink()) {
return handleSymbolicLink(itemPath, v, cb);
}
if (stats.isDirectory() && v.startsWith('@')) {
return handleOrg(itemPath, v, cb);
}
return cb(null);
}
if (stats.isDirectory()) {
return searchDir(itemPath, node[v] = {}, cb);
}
delete node[v];
cb(null);
});
}, cb);
});
});
};
const cleanTree = (treeObj) => {
(function recurse(node, parent, key, hasNodeModules, list) {
if (hasNodeModules) {
for (let v of list) {
v.hasNodeModules = true;
}
}
const children = Object.keys(node);
const x = {
hasNodeModules: false
};
for (let v of children) {
if (node[v] && typeof node[v] === 'object') {
recurse(node[v], node, v, hasNodeModules || v === 'node_modules', list.concat(x));
}
}
if (x.hasNodeModules === false) {
if (parent && key && key !== 'node_modules') {
delete parent[key];
}
}
})(treeObj, null, null, false, []);
};
searchDir(searchRoot, treeObj[key], err => {
if (err) {
throw err;
}
cleanTree(treeObj);
const treeString = treeify.asTree(treeObj, true);
const formattedStr = String(treeString).split('\n').map(function (line) {
return '\t' + line;
});
console.log(chalk_1.default.white(formattedStr.join('\n')));
process.exit(0);
});