🚀 Big News: Socket Acquires Coana to Bring Reachability Analysis to Every Appsec Team.Learn more
Socket
DemoInstallSign in
Socket

eslint-import-resolver-webpack

Package Overview
Dependencies
Maintainers
3
Versions
45
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

eslint-import-resolver-webpack - npm Package Compare versions

Comparing version

to
0.13.9

593

index.js

@@ -6,5 +6,4 @@ 'use strict';

const isEqual = require('lodash/isEqual');
const find = require('array.prototype.find');
const interpret = require('interpret');
const fs = require('fs');
const existsSync = require('fs').existsSync;
const isCore = require('is-core-module');

@@ -15,2 +14,5 @@ const resolve = require('resolve/sync');

const isRegex = require('is-regex');
const isArray = Array.isArray;
const keys = Object.keys;
const assign = Object.assign;

@@ -21,201 +23,124 @@ const log = require('debug')('eslint-plugin-import:resolver:webpack');

/**
* Find the full path to 'source', given 'file' as a full reference path.
*
* resolveImport('./foo', '/Users/ben/bar.js') => '/Users/ben/foo.js'
* @param {string} source - the module to resolve; i.e './some-module'
* @param {string} file - the importing file's full path; i.e. '/usr/local/bin/file.js'
* @param {object} settings - the webpack config file name, as well as cwd
* @example
* options: {
* // Path to the webpack config
* config: 'webpack.config.js',
* // Path to be used to determine where to resolve webpack from
* // (may differ from the cwd in some cases)
* cwd: process.cwd()
* }
* @return {string?} the resolved path to source, undefined if not resolved, or null
* if resolved to a non-FS resource (i.e. script tag at page load)
*/
exports.resolve = function (source, file, settings) {
// strip loaders
const finalBang = source.lastIndexOf('!');
if (finalBang >= 0) {
source = source.slice(finalBang + 1);
function registerCompiler(moduleDescriptor) {
if (moduleDescriptor) {
if (typeof moduleDescriptor === 'string') {
require(moduleDescriptor);
} else if (!isArray(moduleDescriptor)) {
moduleDescriptor.register(require(moduleDescriptor.module));
} else {
for (let i = 0; i < moduleDescriptor.length; i++) {
try {
registerCompiler(moduleDescriptor[i]);
break;
} catch (e) {
log('Failed to register compiler for moduleDescriptor[]:', i, moduleDescriptor);
}
}
}
}
}
// strip resource query
const finalQuestionMark = source.lastIndexOf('?');
if (finalQuestionMark >= 0) {
source = source.slice(0, finalQuestionMark);
}
function findConfigPath(configPath, packageDir) {
const extensions = keys(interpret.extensions).sort(function (a, b) {
return a === '.js' ? -1 : b === '.js' ? 1 : a.length - b.length;
});
let extension;
let webpackConfig;
const _configPath = settings && settings.config;
/**
* Attempt to set the current working directory.
* If none is passed, default to the `cwd` where the config is located.
*/
const cwd = settings && settings.cwd;
const configIndex = settings && settings['config-index'];
const env = settings && settings.env;
const argv = settings && typeof settings.argv !== 'undefined' ? settings.argv : {};
let packageDir;
let configPath = typeof _configPath === 'string' && _configPath.startsWith('.')
? path.resolve(_configPath)
: _configPath;
log('Config path from settings:', configPath);
// see if we've got a config path, a config object, an array of config objects or a config function
if (!configPath || typeof configPath === 'string') {
// see if we've got an absolute path
if (!configPath || !path.isAbsolute(configPath)) {
// if not, find ancestral package.json and use its directory as base for the path
packageDir = findRoot(path.resolve(file));
if (!packageDir) { throw new Error('package not found above ' + file); }
}
configPath = findConfigPath(configPath, packageDir);
log('Config path resolved to:', configPath);
if (configPath) {
try {
webpackConfig = require(configPath);
} catch (e) {
console.log('Error resolving webpackConfig', e);
throw e;
if (configPath) {
for (let i = extensions.length - 1; i >= 0 && !extension; i--) {
const maybeExtension = extensions[i];
if (configPath.slice(-maybeExtension.length) === maybeExtension) {
extension = maybeExtension;
}
} else {
log('No config path found relative to', file, '; using {}');
webpackConfig = {};
}
if (webpackConfig && webpackConfig.default) {
log('Using ES6 module "default" key instead of module.exports.');
webpackConfig = webpackConfig.default;
// see if we've got an absolute path
if (!path.isAbsolute(configPath)) {
configPath = path.join(packageDir, configPath);
}
} else {
webpackConfig = configPath;
configPath = null;
}
if (typeof webpackConfig === 'function') {
webpackConfig = webpackConfig(env, argv);
}
if (Array.isArray(webpackConfig)) {
webpackConfig = webpackConfig.map((cfg) => {
if (typeof cfg === 'function') {
return cfg(env, argv);
for (let i = 0; i < extensions.length && !extension; i++) {
const maybeExtension = extensions[i];
const maybePath = path.resolve(
path.join(packageDir, 'webpack.config' + maybeExtension)
);
if (existsSync(maybePath)) {
configPath = maybePath;
extension = maybeExtension;
}
return cfg;
});
if (typeof configIndex !== 'undefined' && webpackConfig.length > configIndex) {
webpackConfig = webpackConfig[configIndex];
} else {
webpackConfig = find(webpackConfig, function findFirstWithResolve(config) {
return !!config.resolve;
});
}
}
if (typeof webpackConfig.then === 'function') {
webpackConfig = {};
registerCompiler(interpret.extensions[extension]);
return configPath;
}
console.warn('Webpack config returns a `Promise`; that signature is not supported at the moment. Using empty object instead.');
}
function findExternal(source, externals, context, resolveSync) {
if (!externals) { return false; }
if (webpackConfig == null) {
webpackConfig = {};
// string match
if (typeof externals === 'string') { return source === externals; }
console.warn('No webpack configuration with a "resolve" field found. Using empty object instead.');
// array: recurse
if (isArray(externals)) {
return externals.some(function (e) { return findExternal(source, e, context, resolveSync); });
}
log('Using config: ', webpackConfig);
const resolveSync = getResolveSync(configPath, webpackConfig, cwd);
// externals
if (findExternal(source, webpackConfig.externals, path.dirname(file), resolveSync)) {
return { found: true, path: null };
if (isRegex(externals)) {
return externals.test(source);
}
// otherwise, resolve "normally"
try {
return { found: true, path: resolveSync(path.dirname(file), source) };
} catch (err) {
if (isCore(source)) {
return { found: true, path: null };
if (typeof externals === 'function') {
let functionExternalFound = false;
const callback = function (err, value) {
if (err) {
functionExternalFound = false;
} else {
functionExternalFound = findExternal(source, value, context, resolveSync);
}
};
// - for prior webpack 5, 'externals function' uses 3 arguments
// - for webpack 5, the count of arguments is less than 3
if (externals.length === 3) {
externals.call(null, context, source, callback);
} else {
const ctx = {
context,
request: source,
contextInfo: {
issuer: '',
issuerLayer: null,
compiler: '',
},
getResolve: () => (resolveContext, requestToResolve, cb) => {
if (cb) {
try {
cb(null, resolveSync(resolveContext, requestToResolve));
} catch (e) {
cb(e);
}
} else {
log('getResolve without callback not supported');
return Promise.reject(new Error('Not supported'));
}
},
};
const result = externals.call(null, ctx, callback);
// todo handling Promise object (using synchronous-promise package?)
if (result && typeof result.then === 'function') {
log('Asynchronous functions for externals not supported');
}
}
log('Error during module resolution:', err);
return { found: false };
return functionExternalFound;
}
};
const MAX_CACHE = 10;
const _cache = [];
function getResolveSync(configPath, webpackConfig, cwd) {
const cacheKey = { configPath, webpackConfig };
let cached = find(_cache, function (entry) { return isEqual(entry.key, cacheKey); });
if (!cached) {
cached = {
key: cacheKey,
value: createResolveSync(configPath, webpackConfig, cwd),
};
// put in front and pop last item
if (_cache.unshift(cached) > MAX_CACHE) {
_cache.pop();
// else, vanilla object
for (const key in externals) {
if (hasOwn(externals, key) && source === key) {
return true;
}
}
return cached.value;
return false;
}
function createResolveSync(configPath, webpackConfig, cwd) {
let webpackRequire;
let basedir = null;
if (typeof configPath === 'string') {
// This can be changed via the settings passed in when defining the resolver
basedir = cwd || path.dirname(configPath);
log(`Attempting to load webpack path from ${basedir}`);
}
try {
// Attempt to resolve webpack from the given `basedir`
const webpackFilename = resolve('webpack', { basedir, preserveSymlinks: false });
const webpackResolveOpts = { basedir: path.dirname(webpackFilename), preserveSymlinks: false };
webpackRequire = function (id) {
return require(resolve(id, webpackResolveOpts));
};
} catch (e) {
// Something has gone wrong (or we're in a test). Use our own bundled
// enhanced-resolve.
log('Using bundled enhanced-resolve.');
webpackRequire = require;
}
const enhancedResolvePackage = webpackRequire('enhanced-resolve/package.json');
const enhancedResolveVersion = enhancedResolvePackage.version;
log('enhanced-resolve version:', enhancedResolveVersion);
const resolveConfig = webpackConfig.resolve || {};
if (semver.major(enhancedResolveVersion) >= 2) {
return createWebpack2ResolveSync(webpackRequire, resolveConfig);
}
return createWebpack1ResolveSync(webpackRequire, resolveConfig, webpackConfig.plugins);
}
/**

@@ -237,3 +162,3 @@ * webpack 2 defaults:

return EnhancedResolve.create.sync(Object.assign({}, webpack2DefaultResolveConfig, resolveConfig));
return EnhancedResolve.create.sync(assign({}, webpack2DefaultResolveConfig, resolveConfig));
}

@@ -243,8 +168,30 @@

* webpack 1 defaults: https://webpack.github.io/docs/configuration.html#resolve-packagemains
* @type {Array}
* @type {string[]}
*/
const webpack1DefaultMains = [
'webpack', 'browser', 'web', 'browserify', ['jam', 'main'], 'main',
'webpack',
'browser',
'web',
'browserify',
['jam', 'main'],
'main',
];
/* eslint-disable */
// from https://github.com/webpack/webpack/blob/v1.13.0/lib/WebpackOptionsApply.js#L365
function makeRootPlugin(ModulesInRootPlugin, name, root) {
if (typeof root === 'string') {
return new ModulesInRootPlugin(name, root);
}
if (isArray(root)) {
return function () {
root.forEach(function (root) {
this.apply(new ModulesInRootPlugin(name, root));
}, this);
};
}
return function () {};
}
/* eslint-enable */
// adapted from tests &

@@ -299,3 +246,3 @@ // https://github.com/webpack/webpack/blob/v1.13.0/lib/WebpackOptionsApply.js#L322

&& plugin.constructor.name === 'ResolverPlugin'
&& Array.isArray(plugin.plugins)
&& isArray(plugin.plugins)
) {

@@ -314,141 +261,167 @@ resolvePlugins.push.apply(resolvePlugins, plugin.plugins);

/* eslint-disable */
// from https://github.com/webpack/webpack/blob/v1.13.0/lib/WebpackOptionsApply.js#L365
function makeRootPlugin(ModulesInRootPlugin, name, root) {
if (typeof root === 'string') {
return new ModulesInRootPlugin(name, root);
} else if (Array.isArray(root)) {
return function() {
root.forEach(function (root) {
this.apply(new ModulesInRootPlugin(name, root));
}, this);
function createResolveSync(configPath, webpackConfig, cwd) {
let webpackRequire;
let basedir = null;
if (typeof configPath === 'string') {
// This can be changed via the settings passed in when defining the resolver
basedir = cwd || path.dirname(configPath);
log(`Attempting to load webpack path from ${basedir}`);
}
try {
// Attempt to resolve webpack from the given `basedir`
const webpackFilename = resolve('webpack', { basedir, preserveSymlinks: false });
const webpackResolveOpts = { basedir: path.dirname(webpackFilename), preserveSymlinks: false };
webpackRequire = function (id) {
return require(resolve(id, webpackResolveOpts));
};
} catch (e) {
// Something has gone wrong (or we're in a test). Use our own bundled
// enhanced-resolve.
log('Using bundled enhanced-resolve.');
webpackRequire = require;
}
return function () {};
}
/* eslint-enable */
function findExternal(source, externals, context, resolveSync) {
if (!externals) { return false; }
const enhancedResolvePackage = webpackRequire('enhanced-resolve/package.json');
const enhancedResolveVersion = enhancedResolvePackage.version;
log('enhanced-resolve version:', enhancedResolveVersion);
// string match
if (typeof externals === 'string') { return source === externals; }
const resolveConfig = webpackConfig.resolve || {};
// array: recurse
if (Array.isArray(externals)) {
return externals.some(function (e) { return findExternal(source, e, context, resolveSync); });
if (semver.major(enhancedResolveVersion) >= 2) {
return createWebpack2ResolveSync(webpackRequire, resolveConfig);
}
if (isRegex(externals)) {
return externals.test(source);
}
return createWebpack1ResolveSync(webpackRequire, resolveConfig, webpackConfig.plugins);
}
if (typeof externals === 'function') {
let functionExternalFound = false;
const callback = function (err, value) {
if (err) {
functionExternalFound = false;
} else {
functionExternalFound = findExternal(source, value, context, resolveSync);
}
};
// - for prior webpack 5, 'externals function' uses 3 arguments
// - for webpack 5, the count of arguments is less than 3
if (externals.length === 3) {
externals.call(null, context, source, callback);
} else {
const ctx = {
context,
request: source,
contextInfo: {
issuer: '',
issuerLayer: null,
compiler: '',
},
getResolve: () => (resolveContext, requestToResolve, cb) => {
if (cb) {
try {
cb(null, resolveSync(resolveContext, requestToResolve));
} catch (e) {
cb(e);
}
} else {
log('getResolve without callback not supported');
return Promise.reject(new Error('Not supported'));
}
},
};
const result = externals.call(null, ctx, callback);
// todo handling Promise object (using synchronous-promise package?)
if (result && typeof result.then === 'function') {
log('Asynchronous functions for externals not supported');
}
const MAX_CACHE = 10;
const _cache = [];
function getResolveSync(configPath, webpackConfig, cwd) {
const cacheKey = { configPath, webpackConfig };
for (let i = 0; i < _cache.length; i++) {
if (isEqual(_cache[i].key, cacheKey)) {
return _cache[i].value;
}
return functionExternalFound;
}
// else, vanilla object
for (const key in externals) {
if (!hasOwn(externals, key)) { continue; }
if (source === key) { return true; }
const cached = {
key: cacheKey,
value: createResolveSync(configPath, webpackConfig, cwd),
};
// put in front and pop last item
if (_cache.unshift(cached) > MAX_CACHE) {
_cache.pop();
}
return false;
return cached.value;
}
function findConfigPath(configPath, packageDir) {
const extensions = Object.keys(interpret.extensions).sort(function (a, b) {
return a === '.js' ? -1 : b === '.js' ? 1 : a.length - b.length;
});
let extension;
/**
* Find the full path to 'source', given 'file' as a full reference path.
*
* resolveImport('./foo', '/Users/ben/bar.js') => '/Users/ben/foo.js'
* @param {string} source - the module to resolve; i.e './some-module'
* @param {string} file - the importing file's full path; i.e. '/usr/local/bin/file.js'
* @param {object} settings - the webpack config file name, as well as cwd
* @example
* options: {
* // Path to the webpack config
* config: 'webpack.config.js',
* // Path to be used to determine where to resolve webpack from
* // (may differ from the cwd in some cases)
* cwd: process.cwd()
* }
* @return {string?} the resolved path to source, undefined if not resolved, or null
* if resolved to a non-FS resource (i.e. script tag at page load)
*/
exports.resolve = function (source, file, settings) {
if (configPath) {
// extensions is not reused below, so safe to mutate it here.
extensions.reverse();
extensions.forEach(function (maybeExtension) {
if (extension) {
return;
}
// strip loaders
const finalBang = source.lastIndexOf('!');
if (finalBang >= 0) {
source = source.slice(finalBang + 1);
}
if (configPath.substr(-maybeExtension.length) === maybeExtension) {
extension = maybeExtension;
}
});
// strip resource query
const finalQuestionMark = source.lastIndexOf('?');
if (finalQuestionMark >= 0) {
source = source.slice(0, finalQuestionMark);
}
let webpackConfig;
const _configPath = settings && settings.config;
/**
* Attempt to set the current working directory.
* If none is passed, default to the `cwd` where the config is located.
*/
const cwd = settings && settings.cwd;
const configIndex = settings && settings['config-index'];
const env = settings && settings.env;
const argv = settings && typeof settings.argv !== 'undefined' ? settings.argv : {};
let packageDir;
let configPath = typeof _configPath === 'string' && _configPath.startsWith('.')
? path.resolve(_configPath)
: _configPath;
log('Config path from settings:', configPath);
// see if we've got a config path, a config object, an array of config objects or a config function
if (!configPath || typeof configPath === 'string') {
// see if we've got an absolute path
if (!path.isAbsolute(configPath)) {
configPath = path.join(packageDir, configPath);
if (!configPath || !path.isAbsolute(configPath)) {
// if not, find ancestral package.json and use its directory as base for the path
packageDir = findRoot(path.resolve(file));
if (!packageDir) { throw new Error('package not found above ' + file); }
}
configPath = findConfigPath(configPath, packageDir);
log('Config path resolved to:', configPath);
if (configPath) {
try {
webpackConfig = require(configPath);
} catch (e) {
console.log('Error resolving webpackConfig', e);
throw e;
}
} else {
log('No config path found relative to', file, '; using {}');
webpackConfig = {};
}
if (webpackConfig && webpackConfig.default) {
log('Using ES6 module "default" key instead of module.exports.');
webpackConfig = webpackConfig.default;
}
} else {
extensions.forEach(function (maybeExtension) {
if (extension) {
return;
webpackConfig = configPath;
configPath = null;
}
if (typeof webpackConfig === 'function') {
webpackConfig = webpackConfig(env, argv);
}
if (isArray(webpackConfig)) {
webpackConfig = webpackConfig.map((cfg) => {
if (typeof cfg === 'function') {
return cfg(env, argv);
}
const maybePath = path.resolve(
path.join(packageDir, 'webpack.config' + maybeExtension)
);
if (fs.existsSync(maybePath)) {
configPath = maybePath;
extension = maybeExtension;
}
return cfg;
});
}
registerCompiler(interpret.extensions[extension]);
return configPath;
}
function registerCompiler(moduleDescriptor) {
if (moduleDescriptor) {
if (typeof moduleDescriptor === 'string') {
require(moduleDescriptor);
} else if (!Array.isArray(moduleDescriptor)) {
moduleDescriptor.register(require(moduleDescriptor.module));
if (typeof configIndex !== 'undefined' && webpackConfig.length > configIndex) {
webpackConfig = webpackConfig[configIndex];
} else {
for (let i = 0; i < moduleDescriptor.length; i++) {
try {
registerCompiler(moduleDescriptor[i]);
for (let i = 0; i < webpackConfig.length; i++) {
if (webpackConfig[i].resolve) {
webpackConfig = webpackConfig[i];
break;
} catch (e) {
log('Failed to register compiler for moduleDescriptor[]:', i, moduleDescriptor);
}

@@ -458,2 +431,36 @@ }

}
}
if (typeof webpackConfig.then === 'function') {
webpackConfig = {};
console.warn('Webpack config returns a `Promise`; that signature is not supported at the moment. Using empty object instead.');
}
if (webpackConfig == null) {
webpackConfig = {};
console.warn('No webpack configuration with a "resolve" field found. Using empty object instead.');
}
log('Using config: ', webpackConfig);
const resolveSync = getResolveSync(configPath, webpackConfig, cwd);
// externals
if (findExternal(source, webpackConfig.externals, path.dirname(file), resolveSync)) {
return { found: true, path: null };
}
// otherwise, resolve "normally"
try {
return { found: true, path: resolveSync(path.dirname(file), source) };
} catch (err) {
if (isCore(source)) {
return { found: true, path: null };
}
log('Error during module resolution:', err);
return { found: false };
}
};
{
"name": "eslint-import-resolver-webpack",
"version": "0.13.8",
"version": "0.13.9",
"description": "Resolve paths to dependencies, given a webpack.config.js. Plugin for eslint-plugin-import.",

@@ -17,3 +17,4 @@ "main": "index.js",

"type": "git",
"url": "git+https://github.com/import-js/eslint-plugin-import.git"
"url": "git+https://github.com/import-js/eslint-plugin-import.git",
"directory": "resolvers/webpack"
},

@@ -34,3 +35,2 @@ "keywords": [

"dependencies": {
"array.prototype.find": "^2.2.2",
"debug": "^3.2.7",

@@ -37,0 +37,0 @@ "enhanced-resolve": "^0.9.1",