AK-21/Graphite-Industrial-Intelligence
0
1var fs = require('fs');2var getHomedir = require('./homedir');3var path = require('path');4var caller = require('./caller');5var nodeModulesPaths = require('./node-modules-paths');6var normalizeOptions = require('./normalize-options');7var isCore = require('is-core-module');8var $Error = require('es-errors');9var $TypeError = require('es-errors/type');10 11var realpathFS = process.platform !== 'win32' && fs.realpath && typeof fs.realpath.native === 'function' ? fs.realpath.native : fs.realpath;12 13var relativePathRegex = /^(?:\.\.?(?:\/|$)|\/|([A-Za-z]:)?[/\\])/;14var windowsDriveRegex = /^\w:[/\\]*$/;15var nodeModulesRegex = /[/\\]node_modules[/\\]*$/;16 17var homedir = getHomedir();18function defaultPaths() {19 if (!homedir) return [];20 return [21 path.join(homedir, '.node_modules'),22 path.join(homedir, '.node_libraries')23 ];24}25 26var defaultIsFile = function isFile(file, cb) {27 fs.stat(file, function (err, stat) {28 if (!err) {29 return cb(null, stat.isFile() || stat.isFIFO());30 }31 if (err.code === 'ENOENT' || err.code === 'ENOTDIR') return cb(null, false);32 return cb(err);33 });34};35 36var defaultIsDir = function isDirectory(dir, cb) {37 fs.stat(dir, function (err, stat) {38 if (!err) {39 return cb(null, stat.isDirectory());40 }41 if (err.code === 'ENOENT' || err.code === 'ENOTDIR') return cb(null, false);42 return cb(err);43 });44};45 46var defaultRealpath = function realpath(x, cb) {47 realpathFS(x, function (realpathErr, realPath) {48 if (realpathErr && realpathErr.code !== 'ENOENT') cb(realpathErr);49 else cb(null, realpathErr ? x : realPath);50 });51};52 53function maybeRealpath(realpath, x, opts, cb) {54 if (opts && opts.preserveSymlinks === false) {55 realpath(x, cb);56 } else {57 cb(null, x);58 }59}60 61function defaultReadPackage(readFile, pkgfile, cb) {62 readFile(pkgfile, function (readFileErr, body) {63 if (readFileErr) cb(readFileErr);64 else {65 try {66 var pkg = JSON.parse(body);67 cb(null, pkg);68 } catch (jsonErr) {69 cb(null);70 }71 }72 });73}74 75function getPackageCandidates(x, start, opts) {76 var dirs = nodeModulesPaths(start, opts, x);77 for (var i = 0; i < dirs.length; i++) {78 dirs[i] = path.join(dirs[i], x);79 }80 return dirs;81}82 83module.exports = function resolve(x, options, callback) {84 var cb = callback;85 var opts = options;86 if (typeof options === 'function') {87 cb = opts;88 opts = {};89 }90 if (typeof x !== 'string') {91 var err = new $TypeError('Path must be a string.');92 return process.nextTick(function () {93 cb(err);94 });95 }96 97 opts = normalizeOptions(x, opts);98 99 var isFile = opts.isFile || defaultIsFile;100 var isDirectory = opts.isDirectory || defaultIsDir;101 var readFile = opts.readFile || fs.readFile;102 var realpath = opts.realpath || defaultRealpath;103 var readPackage = opts.readPackage || defaultReadPackage;104 if (opts.readFile && opts.readPackage) {105 var conflictErr = new $TypeError('`readFile` and `readPackage` are mutually exclusive.');106 return process.nextTick(function () {107 cb(conflictErr);108 });109 }110 var packageIterator = opts.packageIterator;111 112 var extensions = opts.extensions || ['.js'];113 var includeCoreModules = opts.includeCoreModules !== false;114 var basedir = opts.basedir || path.dirname(caller());115 var parent = opts.filename || basedir;116 117 opts.paths = opts.paths || defaultPaths();118 119 // ensure that `basedir` is an absolute path at this point, resolving against the process' current working directory120 var absoluteStart = path.resolve(basedir);121 122 maybeRealpath(123 realpath,124 absoluteStart,125 opts,126 function (err, realStart) {127 if (err) cb(err);128 else init(realStart);129 }130 );131 132 var res;133 function init(basedir) {134 if (relativePathRegex.test(x)) {135 res = path.resolve(basedir, x);136 if (x === '.' || x === '..' || x.slice(-1) === '/') res += '/';137 if (x.slice(-1) === '/' && res === basedir) {138 loadAsDirectory(res, opts.package, onfile);139 } else loadAsFile(res, opts.package, onfile);140 } else if (includeCoreModules && isCore(x)) {141 return cb(null, x);142 } else loadNodeModules(x, basedir, function (err, n, pkg) {143 if (err) cb(err);144 else if (n) {145 return maybeRealpath(realpath, n, opts, function (err, realN) {146 if (err) {147 cb(err);148 } else {149 cb(null, realN, pkg);150 }151 });152 } else {153 var moduleError = new $Error("Cannot find module '" + x + "' from '" + parent + "'");154 moduleError.code = 'MODULE_NOT_FOUND';155 cb(moduleError);156 }157 });158 }159 160 function onfile(err, m, pkg) {161 if (err) cb(err);162 else if (m) cb(null, m, pkg);163 else loadAsDirectory(res, function (err, d, pkg) {164 if (err) cb(err);165 else if (d) {166 maybeRealpath(realpath, d, opts, function (err, realD) {167 if (err) {168 cb(err);169 } else {170 cb(null, realD, pkg);171 }172 });173 } else {174 var moduleError = new $Error("Cannot find module '" + x + "' from '" + parent + "'");175 moduleError.code = 'MODULE_NOT_FOUND';176 cb(moduleError);177 }178 });179 }180 181 function loadAsFile(x, thePackage, callback) {182 var loadAsFilePackage = thePackage;183 var cb = callback;184 if (typeof loadAsFilePackage === 'function') {185 cb = loadAsFilePackage;186 loadAsFilePackage = undefined;187 }188 189 var exts = [''].concat(extensions);190 load(exts, x, loadAsFilePackage);191 192 function load(exts, x, loadPackage) {193 if (exts.length === 0) return cb(null, undefined, loadPackage);194 var file = x + exts[0];195 196 var pkg = loadPackage;197 if (pkg) onpkg(null, pkg);198 else loadpkg(path.dirname(file), onpkg);199 200 function onpkg(err, pkg_, dir) {201 pkg = pkg_;202 if (err) return cb(err);203 if (dir && pkg && opts.pathFilter) {204 var rfile = path.relative(dir, file);205 var rel = rfile.slice(0, rfile.length - exts[0].length);206 var r = opts.pathFilter(pkg, x, rel);207 if (r) return load(208 [''].concat(extensions),209 path.resolve(dir, r),210 pkg211 );212 }213 isFile(file, onex);214 }215 function onex(err, ex) {216 if (err) return cb(err);217 if (ex) return cb(null, file, pkg);218 load(exts.slice(1), x, pkg);219 }220 }221 }222 223 function loadpkg(dir, cb) {224 if (dir === '' || dir === '/') return cb(null);225 if (process.platform === 'win32' && windowsDriveRegex.test(dir)) {226 return cb(null);227 }228 if (nodeModulesRegex.test(dir)) return cb(null);229 230 maybeRealpath(realpath, dir, opts, function (unwrapErr, pkgdir) {231 if (unwrapErr) return loadpkg(path.dirname(dir), cb);232 var pkgfile = path.join(pkgdir, 'package.json');233 isFile(pkgfile, function (err, ex) {234 // on err, ex is false235 if (!ex) return loadpkg(path.dirname(dir), cb);236 237 readPackage(readFile, pkgfile, function (err, pkgParam) {238 if (err) { return cb(err); }239 240 var pkg = pkgParam;241 242 if (pkg && opts.packageFilter) {243 pkg = opts.packageFilter(pkg, pkgfile);244 }245 cb(null, pkg, dir);246 });247 });248 });249 }250 251 function loadAsDirectory(x, loadAsDirectoryPackage, callback) {252 var cb = callback;253 var fpkg = loadAsDirectoryPackage;254 if (typeof fpkg === 'function') {255 cb = fpkg;256 fpkg = opts.package;257 }258 259 maybeRealpath(realpath, x, opts, function (unwrapErr, pkgdir) {260 if (unwrapErr) return cb(unwrapErr);261 var pkgfile = path.join(pkgdir, 'package.json');262 isFile(pkgfile, function (err, ex) {263 if (err) return cb(err);264 if (!ex) return loadAsFile(path.join(x, 'index'), fpkg, cb);265 266 readPackage(readFile, pkgfile, function (err, pkgParam) {267 if (err) return cb(err);268 269 var pkg = pkgParam;270 271 if (pkg && opts.packageFilter) {272 pkg = opts.packageFilter(pkg, pkgfile);273 }274 275 if (pkg && pkg.main) {276 if (typeof pkg.main !== 'string') {277 var mainError = new $TypeError('package “' + pkg.name + '” `main` must be a string');278 mainError.code = 'INVALID_PACKAGE_MAIN';279 return cb(mainError);280 }281 if (pkg.main === '.' || pkg.main === './') {282 pkg.main = 'index';283 }284 loadAsFile(path.resolve(x, pkg.main), pkg, function (err, m, pkg) {285 if (err) return cb(err);286 if (m) return cb(null, m, pkg);287 if (!pkg) return loadAsFile(path.join(x, 'index'), pkg, cb);288 289 var dir = path.resolve(x, pkg.main);290 loadAsDirectory(dir, pkg, function (err, n, pkg) {291 if (err) return cb(err);292 if (n) return cb(null, n, pkg);293 loadAsFile(path.join(x, 'index'), pkg, cb);294 });295 });296 return;297 }298 299 loadAsFile(path.join(x, '/index'), pkg, cb);300 });301 });302 });303 }304 305 function processDirs(cb, dirs) {306 if (dirs.length === 0) return cb(null, undefined);307 var dir = dirs[0];308 309 isDirectory(path.dirname(dir), isdir);310 311 function isdir(err, isdir) {312 if (err) return cb(err);313 if (!isdir) return processDirs(cb, dirs.slice(1));314 loadAsFile(dir, opts.package, onfile);315 }316 317 function onfile(err, m, pkg) {318 if (err) return cb(err);319 if (m) return cb(null, m, pkg);320 loadAsDirectory(dir, opts.package, ondir);321 }322 323 function ondir(err, n, pkg) {324 if (err) return cb(err);325 if (n) return cb(null, n, pkg);326 processDirs(cb, dirs.slice(1));327 }328 }329 function loadNodeModules(x, start, cb) {330 var thunk = function () { return getPackageCandidates(x, start, opts); };331 processDirs(332 cb,333 packageIterator ? packageIterator(x, start, thunk, opts) : thunk()334 );335 }336};337 