Created
April 28, 2011 15:39
-
-
Save deanlandolt/946592 to your computer and use it in GitHub Desktop.
Monkey-patch node require to support a "packages" key in package.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// monkey patch for and adaption of node module loader code | |
// joiner from node/lib/modules.js | |
var joiner = process.platform === 'win32' ? '\\' : '/'; | |
// allow package default to be overridden | |
exports.defaultPackageDir = 'node_modules'; | |
exports.patch = function() { | |
var fs = require('fs'); | |
var path = require('path'); | |
var Module = require('module'); | |
var packageCache = {}; | |
function readPackage(requestPath) { | |
if (packageCache.hasOwnProperty(requestPath)) { | |
return packageCache[requestPath]; | |
} | |
try { | |
var jsonPath = path.resolve(requestPath, 'package.json'); | |
var json = fs.readFileSync(jsonPath, 'utf8'); | |
// TODO copy partial object to only cache relevant bits | |
var pkg = packageCache[requestPath] = JSON.parse(json); | |
return pkg; | |
} catch (e) {} | |
return false; | |
} | |
// 'from' is the __dirname of the module. | |
Module._nodeModulePaths = function(from) { | |
// guarantee that 'from' is absolute. | |
from = path.resolve(from); | |
// note: this approach *only* works when the path is guaranteed | |
// to be absolute. Doing a fully-edge-case-correct path.split | |
// that works on both Windows and Posix is non-trivial. | |
var splitRe = process.platform === 'win32' ? /[\/\\]/ : /\//; | |
var paths = []; | |
var parts = from.split(splitRe); | |
var packageDir = exports.defaultPackageDir; | |
for (var tip = parts.length - 1; tip >= 0; tip--) { | |
var dir = parts.slice(0, tip + 1); | |
if (tip > 0) { | |
var packageMeta = readPackage(dir.join(joiner)); | |
var packages = packageMeta && packageMeta.packages; | |
// packages key can be an array | |
if (packages && packages.length) { | |
if (typeof packages === 'string') packages = [packages]; | |
var i = packages.length; | |
// loop backward for better paths specifity | |
while (i--) { | |
var name = normalizeDir(packages[i]); | |
paths.push(dir.concat(name).join(joiner)); | |
} | |
// stop now that we've found the package root | |
break; | |
} | |
} | |
// don't search in, e.g. node_modules/node_modules | |
if (parts[tip] === exports.defaultPackageDir) continue; | |
paths.push(dir.concat(exports.defaultPackageDir).join(joiner)); | |
} | |
return paths; | |
}; | |
}; | |
function normalizeDir(name) { | |
name = name || ''; | |
var parts = name.split(joiner); | |
if (parts.length < 2) return parts[0]; | |
// allow './' just to be friendly, but throw on everything else | |
if (parts.length === 2 && parts[0] === '.') return parts[1]; | |
throw new Error('Invalid directories key in package.json: ' + name); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment