async.js (6622B)
1 var core = require('./core'); 2 var fs = require('fs'); 3 var path = require('path'); 4 var caller = require('./caller.js'); 5 var nodeModulesPaths = require('./node-modules-paths.js'); 6 var splitRe = process.platform === 'win32' ? /[\/\\]/ : /\//; 7 8 module.exports = function resolve (x, opts, cb) { 9 if (typeof opts === 'function') { 10 cb = opts; 11 opts = {}; 12 } 13 if (!opts) opts = {}; 14 if (typeof x !== 'string') { 15 return process.nextTick(function () { 16 cb(new Error('path must be a string')); 17 }); 18 } 19 20 var isFile = opts.isFile || function (file, cb) { 21 fs.stat(file, function (err, stat) { 22 if (err && err.code === 'ENOENT') cb(null, false) 23 else if (err) cb(err) 24 else cb(null, stat.isFile() || stat.isFIFO()) 25 }); 26 }; 27 var readFile = opts.readFile || fs.readFile; 28 29 var extensions = opts.extensions || [ '.js' ]; 30 var y = opts.basedir || path.dirname(caller()); 31 32 opts.paths = opts.paths || []; 33 34 if (/^(?:\.\.?(?:\/|$)|\/|([A-Za-z]:)?[\\\/])/.test(x)) { 35 var res = path.resolve(y, x); 36 if (x === '..') res += '/'; 37 if (/\/$/.test(x) && res === y) { 38 loadAsDirectory(res, opts.package, onfile); 39 } 40 else loadAsFile(res, opts.package, onfile); 41 } 42 else loadNodeModules(x, y, function (err, n, pkg) { 43 if (err) cb(err) 44 else if (n) cb(null, n, pkg) 45 else if (core[x]) return cb(null, x); 46 else cb(new Error("Cannot find module '" + x + "' from '" + y + "'")) 47 }); 48 49 function onfile (err, m, pkg) { 50 if (err) cb(err) 51 else if (m) cb(null, m, pkg) 52 else loadAsDirectory(res, function (err, d, pkg) { 53 if (err) cb(err) 54 else if (d) cb(null, d, pkg) 55 else cb(new Error("Cannot find module '" + x + "' from '" + y + "'")) 56 }) 57 } 58 59 function loadAsFile (x, pkg, cb) { 60 if (typeof pkg === 'function') { 61 cb = pkg; 62 pkg = undefined; 63 } 64 65 var exts = [''].concat(extensions); 66 load(exts, x, pkg) 67 68 function load (exts, x, pkg) { 69 if (exts.length === 0) return cb(null, undefined, pkg); 70 var file = x + exts[0]; 71 72 if (pkg) onpkg(null, pkg) 73 else loadpkg(path.dirname(file), onpkg); 74 75 function onpkg (err, pkg_, dir) { 76 pkg = pkg_; 77 if (err) return cb(err) 78 if (dir && pkg && opts.pathFilter) { 79 var rfile = path.relative(dir, file); 80 var rel = rfile.slice(0, rfile.length - exts[0].length); 81 var r = opts.pathFilter(pkg, x, rel); 82 if (r) return load( 83 [''].concat(extensions.slice()), 84 path.resolve(dir, r), 85 pkg 86 ); 87 } 88 isFile(file, onex); 89 } 90 function onex (err, ex) { 91 if (err) cb(err) 92 else if (!ex) load(exts.slice(1), x, pkg) 93 else cb(null, file, pkg) 94 } 95 } 96 } 97 98 function loadpkg (dir, cb) { 99 if (dir === '' || dir === '/') return cb(null); 100 if (process.platform === 'win32' && /^\w:[\\\/]*$/.test(dir)) { 101 return cb(null); 102 } 103 if (/[\\\/]node_modules[\\\/]*$/.test(dir)) return cb(null); 104 105 var pkgfile = path.join(dir, 'package.json'); 106 isFile(pkgfile, function (err, ex) { 107 // on err, ex is false 108 if (!ex) return loadpkg( 109 path.dirname(dir), cb 110 ); 111 112 readFile(pkgfile, function (err, body) { 113 if (err) cb(err); 114 try { var pkg = JSON.parse(body) } 115 catch (err) {} 116 117 if (pkg && opts.packageFilter) { 118 pkg = opts.packageFilter(pkg, pkgfile); 119 } 120 cb(null, pkg, dir); 121 }); 122 }); 123 } 124 125 function loadAsDirectory (x, fpkg, cb) { 126 if (typeof fpkg === 'function') { 127 cb = fpkg; 128 fpkg = opts.package; 129 } 130 131 var pkgfile = path.join(x, '/package.json'); 132 isFile(pkgfile, function (err, ex) { 133 if (err) return cb(err); 134 if (!ex) return loadAsFile(path.join(x, '/index'), fpkg, cb); 135 136 readFile(pkgfile, function (err, body) { 137 if (err) return cb(err); 138 try { 139 var pkg = JSON.parse(body); 140 } 141 catch (err) {} 142 143 if (opts.packageFilter) { 144 pkg = opts.packageFilter(pkg, pkgfile); 145 } 146 147 if (pkg.main) { 148 if (pkg.main === '.' || pkg.main === './'){ 149 pkg.main = 'index' 150 } 151 loadAsFile(path.resolve(x, pkg.main), pkg, function (err, m, pkg) { 152 if (err) return cb(err); 153 if (m) return cb(null, m, pkg); 154 if (!pkg) return loadAsFile(path.join(x, '/index'), pkg, cb); 155 156 var dir = path.resolve(x, pkg.main); 157 loadAsDirectory(dir, pkg, function (err, n, pkg) { 158 if (err) return cb(err); 159 if (n) return cb(null, n, pkg); 160 loadAsFile(path.join(x, '/index'), pkg, cb); 161 }); 162 }); 163 return; 164 } 165 166 loadAsFile(path.join(x, '/index'), pkg, cb); 167 }); 168 }); 169 } 170 171 function loadNodeModules (x, start, cb) { 172 (function process (dirs) { 173 if (dirs.length === 0) return cb(null, undefined); 174 var dir = dirs[0]; 175 176 var file = path.join(dir, '/', x); 177 loadAsFile(file, undefined, onfile); 178 179 function onfile (err, m, pkg) { 180 if (err) return cb(err); 181 if (m) return cb(null, m, pkg); 182 loadAsDirectory(path.join(dir, '/', x), undefined, ondir); 183 } 184 185 function ondir (err, n, pkg) { 186 if (err) return cb(err); 187 if (n) return cb(null, n, pkg); 188 process(dirs.slice(1)); 189 } 190 })(nodeModulesPaths(start, opts)); 191 } 192 };