File: //var/www/zaklada/html/node_modules/node-haste/lib/PathResolver.js
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
var path = require('path');
var modulePaths = [];
var NODE_PATH_ENV = 'NODE_PATH';
/**
* Copyright 2013 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This module is heavily inspired from the base module.js file in node's repo.
* The license at the top of this JS module applies to this file only. Its
* purpose is to contain only the logic needed to reason about paths - which is
* perfectly compatible with node's own resolution, but in a way that works with
* a logical resource map input, that doesn't require reading from the disk.
* Often when building your own tooling, you'll already have read the resources
* needed, and path lookup can reuse that cached information (ResourceMap) to
* reason about path lookups much more quickly.
*
* The main entrypoints to this module (`_resolvefileName`) expects a
* `ResourceMap` argument, which is expected to be of Type `{getResourceByPath:
* string-> {data: string, path: string}`
*/
/**
* given a module name, and a list of paths to test, returns the first matching
* file in the following precedence.
*
* require("a.<ext>")
* -> a.<ext>
*
* require("a")
* -> a
* -> a.<ext>
* -> a/index.<ext>
*
* @param {string} basePath Base path to search for "main" entrypoint of a
* package.
* @param {object} exts Extensions to search.
* @param {ResourceMap} resourceMap ResourceMap containing projects and files.
* @return {string} Absolutely resolved file path or null if no package is found
* in the ResourceMap.
*/
function tryPackage(basePath, exts, resourceMap) {
var projectConfigurationResource =
resourceMap.getResourceByPath(path.join(basePath, 'package.json'));
if (!projectConfigurationResource) {
return false;
}
var data = projectConfigurationResource && projectConfigurationResource.data;
var mainFileBase = data && data.main ?
path.resolve(projectConfigurationResource.path, '..', data.main) :
basePath;
return tryFile(mainFileBase, resourceMap) ||
tryExtensions(mainFileBase, exts, resourceMap) ||
tryExtensions(path.resolve(mainFileBase, 'index'), exts, resourceMap);
}
/**
* Check if the file exists and is not a directory.
*/
function tryFile(requestPath, resourceMap) {
var resourceAtPath = resourceMap.getResourceByPath(requestPath);
return resourceAtPath &&
!resourceAtPath.isLegacy &&
resourceAtPath.path;
}
/**
* Given a path check a the file exists with any of the set extensions
*/
function tryExtensions(p, exts, resourceMap) {
for (var i = 0, EL = exts.length; i < EL; i++) {
var fileName = tryFile(p + exts[i], resourceMap);
if (fileName) {
return fileName;
}
}
return false;
}
var _extensions = {'.js': true};
var _extensionKeys = Object.keys(_extensions);
var PathResolver = {
_findPath: function(request, paths, resourceMap) {
var exts = _extensionKeys;
if (request.charAt(0) === '/') {
paths = [''];
}
var trailingSlash = (request.slice(-1) === '/');
// For each path
for (var i = 0, PL = paths.length; i < PL; i++) {
var basePath = path.resolve(paths[i], request);
var fileName;
if (!trailingSlash) {
// try to join the request to the path
fileName = tryFile(basePath, resourceMap);
if (!fileName && !trailingSlash) {
// try it with each of the extensions
fileName = tryExtensions(basePath, exts, resourceMap);
}
}
if (!fileName) {
fileName = tryPackage(basePath, exts, resourceMap);
}
if (!fileName) {
// try it with each of the extensions at "index"
fileName = tryExtensions(path.resolve(basePath, 'index'), exts, resourceMap);
}
if (fileName) {
return fileName;
}
}
return false;
},
// 'from' is the __dirname of the 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);
for (var tip = parts.length - 1; tip >= 0; tip--) {
// don't search in .../node_modules/node_modules
if (parts[tip] === 'node_modules') {
continue;
}
var dir = parts.slice(0, tip + 1).concat('node_modules').join(path.sep);
paths.push(dir);
}
return paths;
},
_resolveLookupPaths: function(request, parent) {
var start = request.substring(0, 2);
if (start !== './' && start !== '..') {
var paths = modulePaths;
if (parent) {
if (!parent.paths) {
parent.paths = [];
}
paths = parent.paths.concat(paths);
}
return paths;
}
// with --eval, parent.id is not set and parent.fileName is null
if (!parent || !parent.id || !parent.fileName) {
// make require('./path/to/foo') work - normally the path is taken
// from realpath(__fileName) but with eval there is no fileName
var mainPaths = ['.'].concat(modulePaths);
mainPaths = PathResolver._nodeModulePaths('.').concat(mainPaths);
return mainPaths;
}
// Is the parent an index module?
// We can assume the parent has a valid extension,
// as it already has been accepted as a module.
var isIndex = /^index\.\w+?$/.test(path.basename(parent.fileName));
var parentIdPath = isIndex ? parent.id : path.dirname(parent.id);
var id = path.resolve(parentIdPath, request);
// make sure require('./path') and require('path') get distinct ids, even
// when called from the toplevel js file
if (parentIdPath === '.' && id.indexOf('/') === -1) {
id = './' + id;
}
return [path.dirname(parent.fileName)];
},
/**
* @param {string} request Argument to require()
* @param {string} parent path of module that is calling require.
* @param {ResourceMap} resourceMap ResourceMap for looking up project
* configuration etc so that we don't need to read from the disk.
* @return {string} Resolved absolute path of the module corresponding to the
* callers require(request).
*/
_resolveFileName: function(request, parent, resourceMap) {
var resolvedPaths = PathResolver._resolveLookupPaths(request, parent);
return PathResolver._findPath(request, resolvedPaths, resourceMap);
},
_initPaths: function() {
var isWindows = process.platform === 'win32';
var homeDir = isWindows ? process.env.USERPROFILE : process.env.HOME;
var paths = [path.resolve(process.execPath, '..', '..', 'lib', 'node')];
if (homeDir) {
paths.unshift(path.resolve(homeDir, '.node_libraries'));
paths.unshift(path.resolve(homeDir, '.node_modules'));
}
if (process.env[NODE_PATH_ENV]) {
paths = process.env[NODE_PATH_ENV].split(path.delimiter).concat(paths);
}
modulePaths = paths;
}
};
PathResolver._initPaths();
module.exports = PathResolver;