123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224 |
- 'use strict'
-
- var BuiltinModule = require('module')
-
- // Guard against poorly mocked module constructors
- var Module = module.constructor.length > 1
- ? module.constructor
- : BuiltinModule
-
- var nodePath = require('path')
-
- var modulePaths = []
- var moduleAliases = {}
- var moduleAliasNames = []
-
- var oldNodeModulePaths = Module._nodeModulePaths
- Module._nodeModulePaths = function (from) {
- var paths = oldNodeModulePaths.call(this, from)
-
- // Only include the module path for top-level modules
- // that were not installed:
- if (from.indexOf('node_modules') === -1) {
- paths = modulePaths.concat(paths)
- }
-
- return paths
- }
-
- var oldResolveFilename = Module._resolveFilename
- Module._resolveFilename = function (request, parentModule, isMain, options) {
- for (var i = moduleAliasNames.length; i-- > 0;) {
- var alias = moduleAliasNames[i]
- if (isPathMatchesAlias(request, alias)) {
- var aliasTarget = moduleAliases[alias]
- // Custom function handler
- if (typeof moduleAliases[alias] === 'function') {
- var fromPath = parentModule.filename
- aliasTarget = moduleAliases[alias](fromPath, request, alias)
- if (!aliasTarget || typeof aliasTarget !== 'string') {
- throw new Error('[module-alias] Expecting custom handler function to return path.')
- }
- }
- request = nodePath.join(aliasTarget, request.substr(alias.length))
- // Only use the first match
- break
- }
- }
-
- return oldResolveFilename.call(this, request, parentModule, isMain, options)
- }
-
- function isPathMatchesAlias (path, alias) {
- // Matching /^alias(\/|$)/
- if (path.indexOf(alias) === 0) {
- if (path.length === alias.length) return true
- if (path[alias.length] === '/') return true
- }
-
- return false
- }
-
- function addPathHelper (path, targetArray) {
- path = nodePath.normalize(path)
- if (targetArray && targetArray.indexOf(path) === -1) {
- targetArray.unshift(path)
- }
- }
-
- function removePathHelper (path, targetArray) {
- if (targetArray) {
- var index = targetArray.indexOf(path)
- if (index !== -1) {
- targetArray.splice(index, 1)
- }
- }
- }
-
- function addPath (path) {
- var parent
- path = nodePath.normalize(path)
-
- if (modulePaths.indexOf(path) === -1) {
- modulePaths.push(path)
- // Enable the search path for the current top-level module
- var mainModule = getMainModule()
- if (mainModule) {
- addPathHelper(path, mainModule.paths)
- }
- parent = module.parent
-
- // Also modify the paths of the module that was used to load the
- // app-module-paths module and all of it's parents
- while (parent && parent !== mainModule) {
- addPathHelper(path, parent.paths)
- parent = parent.parent
- }
- }
- }
-
- function addAliases (aliases) {
- for (var alias in aliases) {
- addAlias(alias, aliases[alias])
- }
- }
-
- function addAlias (alias, target) {
- moduleAliases[alias] = target
- // Cost of sorting is lower here than during resolution
- moduleAliasNames = Object.keys(moduleAliases)
- moduleAliasNames.sort()
- }
-
- /**
- * Reset any changes maded (resets all registered aliases
- * and custom module directories)
- * The function is undocumented and for testing purposes only
- */
- function reset () {
- var mainModule = getMainModule()
-
- // Reset all changes in paths caused by addPath function
- modulePaths.forEach(function (path) {
- if (mainModule) {
- removePathHelper(path, mainModule.paths)
- }
-
- // Delete from require.cache if the module has been required before.
- // This is required for node >= 11
- Object.getOwnPropertyNames(require.cache).forEach(function (name) {
- if (name.indexOf(path) !== -1) {
- delete require.cache[name]
- }
- })
-
- var parent = module.parent
- while (parent && parent !== mainModule) {
- removePathHelper(path, parent.paths)
- parent = parent.parent
- }
- })
-
- modulePaths = []
- moduleAliases = {}
- moduleAliasNames = []
- }
-
- /**
- * Import aliases from package.json
- * @param {object} options
- */
- function init (options) {
- if (typeof options === 'string') {
- options = { base: options }
- }
-
- options = options || {}
-
- var candidatePackagePaths
- if (options.base) {
- candidatePackagePaths = [nodePath.resolve(options.base.replace(/\/package\.json$/, ''))]
- } else {
- // There is probably 99% chance that the project root directory in located
- // above the node_modules directory,
- // Or that package.json is in the node process' current working directory (when
- // running a package manager script, e.g. `yarn start` / `npm run start`)
- candidatePackagePaths = [nodePath.join(__dirname, '../..'), process.cwd()]
- }
-
- var npmPackage
- var base
- for (var i in candidatePackagePaths) {
- try {
- base = candidatePackagePaths[i]
-
- npmPackage = require(nodePath.join(base, 'package.json'))
- break
- } catch (e) {
- // noop
- }
- }
-
- if (typeof npmPackage !== 'object') {
- var pathString = candidatePackagePaths.join(',\n')
- throw new Error('Unable to find package.json in any of:\n[' + pathString + ']')
- }
-
- //
- // Import aliases
- //
-
- var aliases = npmPackage._moduleAliases || {}
-
- for (var alias in aliases) {
- if (aliases[alias][0] !== '/') {
- aliases[alias] = nodePath.join(base, aliases[alias])
- }
- }
-
- addAliases(aliases)
-
- //
- // Register custom module directories (like node_modules)
- //
-
- if (npmPackage._moduleDirectories instanceof Array) {
- npmPackage._moduleDirectories.forEach(function (dir) {
- if (dir === 'node_modules') return
-
- var modulePath = nodePath.join(base, dir)
- addPath(modulePath)
- })
- }
- }
-
- function getMainModule () {
- return require.main._simulateRepl ? undefined : require.main
- }
-
- module.exports = init
- module.exports.addPath = addPath
- module.exports.addAlias = addAlias
- module.exports.addAliases = addAliases
- module.exports.isPathMatchesAlias = isPathMatchesAlias
- module.exports.reset = reset
|