Socket
Socket
Sign inDemoInstall

enhanced-resolve

Package Overview
Dependencies
Maintainers
4
Versions
130
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

enhanced-resolve - npm Package Compare versions

Comparing version 4.1.0 to 5.0.0-beta.0

lib/JoinRequestPartPlugin.js

84

lib/AliasFieldPlugin.js

@@ -19,35 +19,59 @@ /*

const target = resolver.ensureHook(this.target);
resolver.getHook(this.source).tapAsync("AliasFieldPlugin", (request, resolveContext, callback) => {
if(!request.descriptionFileData) return callback();
const innerRequest = getInnerRequest(resolver, request);
if(!innerRequest) return callback();
const fieldData = DescriptionFileUtils.getField(request.descriptionFileData, this.field);
if(typeof fieldData !== "object") {
if(resolveContext.log) resolveContext.log("Field '" + this.field + "' doesn't contain a valid alias configuration");
return callback();
}
const data1 = fieldData[innerRequest];
const data2 = fieldData[innerRequest.replace(/^\.\//, "")];
const data = typeof data1 !== "undefined" ? data1 : data2;
if(data === innerRequest) return callback();
if(data === undefined) return callback();
if(data === false) {
const ignoreObj = Object.assign({}, request, {
path: false
});
return callback(null, ignoreObj);
}
const obj = Object.assign({}, request, {
path: request.descriptionFileRoot,
request: data
});
resolver.doResolve(target, obj, "aliased from description file " + request.descriptionFilePath + " with mapping '" + innerRequest + "' to '" + data + "'", resolveContext, (err, result) => {
if(err) return callback(err);
resolver
.getHook(this.source)
.tapAsync("AliasFieldPlugin", (request, resolveContext, callback) => {
if (!request.descriptionFileData) return callback();
const innerRequest = getInnerRequest(resolver, request);
if (!innerRequest) return callback();
const fieldData = DescriptionFileUtils.getField(
request.descriptionFileData,
this.field
);
if (typeof fieldData !== "object") {
if (resolveContext.log)
resolveContext.log(
"Field '" +
this.field +
"' doesn't contain a valid alias configuration"
);
return callback();
}
const data1 = fieldData[innerRequest];
const data2 = fieldData[innerRequest.replace(/^\.\//, "")];
const data = typeof data1 !== "undefined" ? data1 : data2;
if (data === innerRequest) return callback();
if (data === undefined) return callback();
if (data === false) {
const ignoreObj = {
...request,
path: false
};
return callback(null, ignoreObj);
}
const obj = {
...request,
path: request.descriptionFileRoot,
request: data
};
resolver.doResolve(
target,
obj,
"aliased from description file " +
request.descriptionFilePath +
" with mapping '" +
innerRequest +
"' to '" +
data +
"'",
resolveContext,
(err, result) => {
if (err) return callback(err);
// Don't allow other aliasing or raw request
if(result === undefined) return callback(null, null);
callback(null, result);
// Don't allow other aliasing or raw request
if (result === undefined) return callback(null, null);
callback(null, result);
}
);
});
});
}
};

@@ -7,19 +7,4 @@ /*

function startsWith(string, searchString) {
const stringLength = string.length;
const searchLength = searchString.length;
const forEachBail = require("./forEachBail");
// early out if the search length is greater than the search string
if(searchLength > stringLength) {
return false;
}
let index = -1;
while(++index < searchLength) {
if(string.charCodeAt(index) !== searchString.charCodeAt(index)) {
return false;
}
}
return true;
}
module.exports = class AliasPlugin {

@@ -34,25 +19,71 @@ constructor(source, options, target) {

const target = resolver.ensureHook(this.target);
resolver.getHook(this.source).tapAsync("AliasPlugin", (request, resolveContext, callback) => {
const innerRequest = request.request || request.path;
if(!innerRequest) return callback();
for(const item of this.options) {
if(innerRequest === item.name || (!item.onlyModule && startsWith(innerRequest, item.name + "/"))) {
if(innerRequest !== item.alias && !startsWith(innerRequest, item.alias + "/")) {
const newRequestStr = item.alias + innerRequest.substr(item.name.length);
const obj = Object.assign({}, request, {
request: newRequestStr
});
return resolver.doResolve(target, obj, "aliased with mapping '" + item.name + "': '" + item.alias + "' to '" + newRequestStr + "'", resolveContext, (err, result) => {
if(err) return callback(err);
resolver
.getHook(this.source)
.tapAsync("AliasPlugin", (request, resolveContext, callback) => {
const innerRequest = request.request || request.path;
if (!innerRequest) return callback();
forEachBail(
this.options,
(item, callback) => {
let shouldStop = false;
if (
innerRequest === item.name ||
(!item.onlyModule && innerRequest.startsWith(item.name + "/"))
) {
const remainingRequest = innerRequest.substr(item.name.length);
const resolveWithAlias = (alias, callback) => {
if (
innerRequest !== alias &&
!innerRequest.startsWith(alias + "/")
) {
shouldStop = true;
const newRequestStr = alias + remainingRequest;
const obj = {
...request,
request: newRequestStr
};
return resolver.doResolve(
target,
obj,
"aliased with mapping '" +
item.name +
"': '" +
alias +
"' to '" +
newRequestStr +
"'",
resolveContext,
(err, result) => {
if (err) return callback(err);
if (result) return callback(null, result);
return callback();
}
);
}
return callback();
};
const stoppingCallback = (err, result) => {
if (err) return callback(err);
// Don't allow other aliasing or raw request
if(result === undefined) return callback(null, null);
callback(null, result);
});
}
}
}
return callback();
});
if (result) return callback(null, result);
// Don't allow other aliasing or raw request
if (shouldStop) return callback(null, null);
return callback();
};
if (Array.isArray(item.alias)) {
return forEachBail(
item.alias,
resolveWithAlias,
stoppingCallback
);
} else {
return resolveWithAlias(item.alias, stoppingCallback);
}
}
return callback();
},
callback
);
});
}
};

@@ -16,10 +16,20 @@ /*

const target = resolver.ensureHook(this.target);
resolver.getHook(this.source).tapAsync("AppendPlugin", (request, resolveContext, callback) => {
const obj = Object.assign({}, request, {
path: request.path + this.appending,
relativePath: request.relativePath && (request.relativePath + this.appending)
resolver
.getHook(this.source)
.tapAsync("AppendPlugin", (request, resolveContext, callback) => {
const obj = {
...request,
path: request.path + this.appending,
relativePath:
request.relativePath && request.relativePath + this.appending
};
resolver.doResolve(
target,
obj,
this.appending,
resolveContext,
callback
);
});
resolver.doResolve(target, obj, this.appending, resolveContext, callback);
});
}
};

@@ -13,6 +13,15 @@ /*

this.levels = [];
if(duration > 0) {
this.levels.push(new Set(), new Set(), new Set(), new Set(), new Set(), new Set(), new Set(), new Set(), new Set());
for(let i = 8000; i < duration; i += 500)
this.levels.push(new Set());
if (duration > 0) {
this.levels.push(
new Set(),
new Set(),
new Set(),
new Set(),
new Set(),
new Set(),
new Set(),
new Set(),
new Set()
);
for (let i = 8000; i < duration; i += 500) this.levels.push(new Set());
}

@@ -28,4 +37,7 @@ this.count = 0;

ensureTick() {
if(!this.interval && this.duration > 0 && !this.nextTick)
this.interval = setInterval(this.tick, Math.floor(this.duration / this.levels.length));
if (!this.interval && this.duration > 0 && !this.nextTick)
this.interval = setInterval(
this.tick,
Math.floor(this.duration / this.levels.length)
);
}

@@ -36,3 +48,3 @@

this.running.delete(name);
if(this.duration > 0) {
if (this.duration > 0) {
this.data.set(name, [err, result]);

@@ -45,3 +57,3 @@ const levelData = this.levels[0];

}
for(let i = 0; i < callbacks.length; i++) {
for (let i = 0; i < callbacks.length; i++) {
callbacks[i](err, result);

@@ -52,3 +64,3 @@ }

finishedSync(name, err, result) {
if(this.duration > 0) {
if (this.duration > 0) {
this.data.set(name, [err, result]);

@@ -64,3 +76,3 @@ const levelData = this.levels[0];

provide(name, provider, callback) {
if(typeof name !== "string") {
if (typeof name !== "string") {
callback(new TypeError("path must be a string"));

@@ -70,10 +82,10 @@ return;

let running = this.running.get(name);
if(running) {
if (running) {
running.push(callback);
return;
}
if(this.duration > 0) {
if (this.duration > 0) {
this.checkTicks();
const data = this.data.get(name);
if(data) {
if (data) {
return process.nextTick(() => {

@@ -84,3 +96,3 @@ callback.apply(null, data);

}
this.running.set(name, running = [callback]);
this.running.set(name, (running = [callback]));
provider(name, (err, result) => {

@@ -92,11 +104,10 @@ this.finished(name, err, result);

provideSync(name, provider) {
if(typeof name !== "string") {
if (typeof name !== "string") {
throw new TypeError("path must be a string");
}
if(this.duration > 0) {
if (this.duration > 0) {
this.checkTicks();
const data = this.data.get(name);
if(data) {
if(data[0])
throw data[0];
if (data) {
if (data[0]) throw data[0];
return data[1];

@@ -108,3 +119,3 @@ }

result = provider(name);
} catch(e) {
} catch (e) {
this.finishedSync(name, e);

@@ -119,3 +130,3 @@ throw e;

const decay = this.levels.pop();
for(let item of decay) {
for (let item of decay) {
this.data.delete(item);

@@ -126,3 +137,3 @@ }

this.levels.unshift(decay);
if(this.count === 0) {
if (this.count === 0) {
clearInterval(this.interval);

@@ -132,14 +143,18 @@ this.interval = null;

return true;
} else if(this.nextTick) {
} else if (this.nextTick) {
this.nextTick += Math.floor(this.duration / this.levels.length);
const time = new Date().getTime();
if(this.nextTick > time) {
if (this.nextTick > time) {
this.nextTick = null;
this.interval = setInterval(this.tick, Math.floor(this.duration / this.levels.length));
this.interval = setInterval(
this.tick,
Math.floor(this.duration / this.levels.length)
);
return true;
}
} else if(this.passive) {
} else if (this.passive) {
clearInterval(this.interval);
this.interval = null;
this.nextTick = new Date().getTime() + Math.floor(this.duration / this.levels.length);
this.nextTick =
new Date().getTime() + Math.floor(this.duration / this.levels.length);
} else {

@@ -152,4 +167,4 @@ this.passive = true;

this.passive = false;
if(this.nextTick) {
while(!this.tick());
if (this.nextTick) {
while (!this.tick());
}

@@ -159,3 +174,3 @@ }

purge(what) {
if(!what) {
if (!what) {
this.count = 0;

@@ -168,9 +183,8 @@ clearInterval(this.interval);

});
} else if(typeof what === "string") {
for(let key of this.data.keys()) {
if(key.startsWith(what))
this.data.delete(key);
} else if (typeof what === "string") {
for (let key of this.data.keys()) {
if (key.startsWith(what)) this.data.delete(key);
}
} else {
for(let i = what.length - 1; i >= 0; i--) {
for (let i = what.length - 1; i >= 0; i--) {
this.purge(what[i]);

@@ -191,30 +205,42 @@ }

this._stat = this.fileSystem.stat ? this.fileSystem.stat.bind(this.fileSystem) : null;
if(!this._stat) this.stat = null;
this._stat = this.fileSystem.stat
? this.fileSystem.stat.bind(this.fileSystem)
: null;
if (!this._stat) this.stat = null;
this._statSync = this.fileSystem.statSync ? this.fileSystem.statSync.bind(this.fileSystem) : null;
if(!this._statSync) this.statSync = null;
this._statSync = this.fileSystem.statSync
? this.fileSystem.statSync.bind(this.fileSystem)
: null;
if (!this._statSync) this.statSync = null;
this._readdir = this.fileSystem.readdir ? this.fileSystem.readdir.bind(this.fileSystem) : null;
if(!this._readdir) this.readdir = null;
this._readdir = this.fileSystem.readdir
? this.fileSystem.readdir.bind(this.fileSystem)
: null;
if (!this._readdir) this.readdir = null;
this._readdirSync = this.fileSystem.readdirSync ? this.fileSystem.readdirSync.bind(this.fileSystem) : null;
if(!this._readdirSync) this.readdirSync = null;
this._readdirSync = this.fileSystem.readdirSync
? this.fileSystem.readdirSync.bind(this.fileSystem)
: null;
if (!this._readdirSync) this.readdirSync = null;
this._readFile = this.fileSystem.readFile ? this.fileSystem.readFile.bind(this.fileSystem) : null;
if(!this._readFile) this.readFile = null;
this._readFile = this.fileSystem.readFile
? this.fileSystem.readFile.bind(this.fileSystem)
: null;
if (!this._readFile) this.readFile = null;
this._readFileSync = this.fileSystem.readFileSync ? this.fileSystem.readFileSync.bind(this.fileSystem) : null;
if(!this._readFileSync) this.readFileSync = null;
this._readFileSync = this.fileSystem.readFileSync
? this.fileSystem.readFileSync.bind(this.fileSystem)
: null;
if (!this._readFileSync) this.readFileSync = null;
if(this.fileSystem.readJson) {
if (this.fileSystem.readJson) {
this._readJson = this.fileSystem.readJson.bind(this.fileSystem);
} else if(this.readFile) {
} else if (this.readFile) {
this._readJson = (path, callback) => {
this.readFile(path, (err, buffer) => {
if(err) return callback(err);
if (err) return callback(err);
let data;
try {
data = JSON.parse(buffer.toString("utf-8"));
} catch(e) {
} catch (e) {
return callback(e);

@@ -228,6 +254,6 @@ }

}
if(this.fileSystem.readJsonSync) {
if (this.fileSystem.readJsonSync) {
this._readJsonSync = this.fileSystem.readJsonSync.bind(this.fileSystem);
} else if(this.readFileSync) {
this._readJsonSync = (path) => {
} else if (this.readFileSync) {
this._readJsonSync = path => {
const buffer = this.readFileSync(path);

@@ -241,7 +267,11 @@ const data = JSON.parse(buffer.toString("utf-8"));

this._readlink = this.fileSystem.readlink ? this.fileSystem.readlink.bind(this.fileSystem) : null;
if(!this._readlink) this.readlink = null;
this._readlink = this.fileSystem.readlink
? this.fileSystem.readlink.bind(this.fileSystem)
: null;
if (!this._readlink) this.readlink = null;
this._readlinkSync = this.fileSystem.readlinkSync ? this.fileSystem.readlinkSync.bind(this.fileSystem) : null;
if(!this._readlinkSync) this.readlinkSync = null;
this._readlinkSync = this.fileSystem.readlinkSync
? this.fileSystem.readlinkSync.bind(this.fileSystem)
: null;
if (!this._readlinkSync) this.readlinkSync = null;
}

@@ -248,0 +278,0 @@

@@ -17,12 +17,23 @@ /*

const target = resolver.ensureHook(this.target);
resolver.getHook(this.source).tapAsync("CloneBasenamePlugin", (request, resolveContext, callback) => {
const filename = basename(request.path);
const filePath = resolver.join(request.path, filename);
const obj = Object.assign({}, request, {
path: filePath,
relativePath: request.relativePath && resolver.join(request.relativePath, filename)
resolver
.getHook(this.source)
.tapAsync("CloneBasenamePlugin", (request, resolveContext, callback) => {
const filename = basename(request.path);
const filePath = resolver.join(request.path, filename);
const obj = {
...request,
path: filePath,
relativePath:
request.relativePath &&
resolver.join(request.relativePath, filename)
};
resolver.doResolve(
target,
obj,
"using path: " + filePath,
resolveContext,
callback
);
});
resolver.doResolve(target, obj, "using path: " + filePath, resolveContext, callback);
});
}
};

@@ -7,10 +7,13 @@ /*

module.exports = function createInnerContext(options, message, messageOptional) {
module.exports = function createInnerContext(
options,
message,
messageOptional
) {
let messageReported = false;
const childContext = {
log: (() => {
if(!options.log) return undefined;
if(!message) return options.log;
const logFunction = (msg) => {
if(!messageReported) {
let innerLog = undefined;
if (options.log) {
if (message) {
innerLog = msg => {
if (!messageReported) {
options.log(message);

@@ -21,8 +24,14 @@ messageReported = true;

};
return logFunction;
})(),
stack: options.stack,
missing: options.missing
} else {
innerLog = options.log;
}
}
const childContext = {
log: innerLog,
fileDependencies: options.fileDependencies,
contextDependencies: options.contextDependencies,
missingDependencies: options.missingDependencies,
stack: options.stack
};
return childContext;
};

@@ -10,5 +10,6 @@ /*

module.exports = class DescriptionFilePlugin {
constructor(source, filenames, target) {
constructor(source, filenames, pathIsFile, target) {
this.source = source;
this.filenames = [].concat(filenames);
this.pathIsFile = pathIsFile;
this.target = target;

@@ -19,32 +20,64 @@ }

const target = resolver.ensureHook(this.target);
resolver.getHook(this.source).tapAsync("DescriptionFilePlugin", (request, resolveContext, callback) => {
const directory = request.path;
DescriptionFileUtils.loadDescriptionFile(resolver, directory, this.filenames, resolveContext, (err, result) => {
if(err) return callback(err);
if(!result) {
if(resolveContext.missing) {
this.filenames.forEach((filename) => {
resolveContext.missing.add(resolver.join(directory, filename));
});
}
if(resolveContext.log) resolveContext.log("No description file found");
return callback();
resolver
.getHook(this.source)
.tapAsync(
"DescriptionFilePlugin",
(request, resolveContext, callback) => {
const directory = this.pathIsFile
? DescriptionFileUtils.cdUp(request.path)
: request.path;
if (!directory) return callback();
DescriptionFileUtils.loadDescriptionFile(
resolver,
directory,
this.filenames,
request.descriptionFilePath && {
path: request.descriptionFilePath,
content: request.descriptionFileData,
directory: request.descriptionFileRoot
},
resolveContext,
(err, result) => {
if (err) return callback(err);
if (!result) {
if (resolveContext.log)
resolveContext.log(
`No description file found in ${directory} or above`
);
return callback();
}
const relativePath =
"." +
request.path
.substr(result.directory.length)
.replace(/\\/g, "/");
const obj = {
...request,
descriptionFilePath: result.path,
descriptionFileData: result.content,
descriptionFileRoot: result.directory,
relativePath: relativePath
};
resolver.doResolve(
target,
obj,
"using description file: " +
result.path +
" (relative path: " +
relativePath +
")",
resolveContext,
(err, result) => {
if (err) return callback(err);
// Don't allow other processing
if (result === undefined) return callback(null, null);
callback(null, result);
}
);
}
);
}
const relativePath = "." + request.path.substr(result.directory.length).replace(/\\/g, "/");
const obj = Object.assign({}, request, {
descriptionFilePath: result.path,
descriptionFileData: result.content,
descriptionFileRoot: result.directory,
relativePath: relativePath
});
resolver.doResolve(target, obj, "using description file: " + result.path + " (relative path: " + relativePath + ")", resolveContext, (err, result) => {
if(err) return callback(err);
// Don't allow other processing
if(result === undefined) return callback(null, null);
callback(null, result);
});
});
});
);
}
};

@@ -9,63 +9,100 @@ /*

function loadDescriptionFile(resolver, directory, filenames, resolveContext, callback) {
function loadDescriptionFile(
resolver,
directory,
filenames,
oldInfo,
resolveContext,
callback
) {
(function findDescriptionFile() {
forEachBail(filenames, (filename, callback) => {
const descriptionFilePath = resolver.join(directory, filename);
if(resolver.fileSystem.readJson) {
resolver.fileSystem.readJson(descriptionFilePath, (err, content) => {
if(err) {
if(typeof err.code !== "undefined") return callback();
return onJson(err);
if (oldInfo && oldInfo.directory === directory) {
// We already have info for this directory and can reuse it
return callback(null, oldInfo);
}
forEachBail(
filenames,
(filename, callback) => {
const descriptionFilePath = resolver.join(directory, filename);
if (resolver.fileSystem.readJson) {
resolver.fileSystem.readJson(descriptionFilePath, (err, content) => {
if (err) {
if (typeof err.code !== "undefined") {
if (resolveContext.missingDependencies) {
resolveContext.missingDependencies.add(descriptionFilePath);
}
return callback();
}
if (resolveContext.fileDependencies) {
resolveContext.fileDependencies.add(descriptionFilePath);
}
return onJson(err);
}
if (resolveContext.fileDependencies) {
resolveContext.fileDependencies.add(descriptionFilePath);
}
onJson(null, content);
});
} else {
resolver.fileSystem.readFile(descriptionFilePath, (err, content) => {
if (err) {
if (resolveContext.missingDependencies) {
resolveContext.missingDependencies.add(descriptionFilePath);
}
return callback();
}
if (resolveContext.fileDependencies) {
resolveContext.fileDependencies.add(descriptionFilePath);
}
let json;
try {
json = JSON.parse(content);
} catch (e) {
onJson(e);
}
onJson(null, json);
});
}
function onJson(err, content) {
if (err) {
if (resolveContext.log)
resolveContext.log(
descriptionFilePath + " (directory description file): " + err
);
else
err.message =
descriptionFilePath + " (directory description file): " + err;
return callback(err);
}
onJson(null, content);
});
} else {
resolver.fileSystem.readFile(descriptionFilePath, (err, content) => {
if(err) return callback();
let json;
try {
json = JSON.parse(content);
} catch(e) {
onJson(e);
}
onJson(null, json);
});
}
function onJson(err, content) {
if(err) {
if(resolveContext.log)
resolveContext.log(descriptionFilePath + " (directory description file): " + err);
else
err.message = descriptionFilePath + " (directory description file): " + err;
return callback(err);
callback(null, {
content: content,
directory: directory,
path: descriptionFilePath
});
}
callback(null, {
content: content,
directory: directory,
path: descriptionFilePath
});
}
}, (err, result) => {
if(err) return callback(err);
if(result) {
return callback(null, result);
} else {
directory = cdUp(directory);
if(!directory) {
return callback();
},
(err, result) => {
if (err) return callback(err);
if (result) {
return callback(null, result);
} else {
return findDescriptionFile();
directory = cdUp(directory);
if (!directory) {
return callback();
} else {
return findDescriptionFile();
}
}
}
});
}());
);
})();
}
function getField(content, field) {
if(!content) return undefined;
if(Array.isArray(field)) {
if (!content) return undefined;
if (Array.isArray(field)) {
let current = content;
for(let j = 0; j < field.length; j++) {
if(current === null || typeof current !== "object") {
for (let j = 0; j < field.length; j++) {
if (current === null || typeof current !== "object") {
current = null;

@@ -76,7 +113,7 @@ break;

}
if(typeof current === "object") {
if (typeof current === "object") {
return current;
}
} else {
if(typeof content[field] === "object") {
if (typeof content[field] === "object") {
return content[field];

@@ -88,7 +125,7 @@ }

function cdUp(directory) {
if(directory === "/") return null;
if (directory === "/") return null;
const i = directory.lastIndexOf("/"),
j = directory.lastIndexOf("\\");
const p = i < 0 ? j : j < 0 ? i : i < j ? j : i;
if(p < 0) return null;
if (p < 0) return null;
return directory.substr(0, p || 1);

@@ -95,0 +132,0 @@ }

@@ -15,20 +15,37 @@ /*

const target = resolver.ensureHook(this.target);
resolver.getHook(this.source).tapAsync("DirectoryExistsPlugin", (request, resolveContext, callback) => {
const fs = resolver.fileSystem;
const directory = request.path;
fs.stat(directory, (err, stat) => {
if(err || !stat) {
if(resolveContext.missing) resolveContext.missing.add(directory);
if(resolveContext.log) resolveContext.log(directory + " doesn't exist");
return callback();
resolver
.getHook(this.source)
.tapAsync(
"DirectoryExistsPlugin",
(request, resolveContext, callback) => {
const fs = resolver.fileSystem;
const directory = request.path;
fs.stat(directory, (err, stat) => {
if (err || !stat) {
if (resolveContext.missingDependencies)
resolveContext.missingDependencies.add(directory);
if (resolveContext.log)
resolveContext.log(directory + " doesn't exist");
return callback();
}
if (!stat.isDirectory()) {
if (resolveContext.missingDependencies)
resolveContext.missingDependencies.add(directory);
if (resolveContext.log)
resolveContext.log(directory + " is not a directory");
return callback();
}
if (resolveContext.fileDependencies)
resolveContext.fileDependencies.add(directory);
resolver.doResolve(
target,
request,
`existing directory ${directory}`,
resolveContext,
callback
);
});
}
if(!stat.isDirectory()) {
if(resolveContext.missing) resolveContext.missing.add(directory);
if(resolveContext.log) resolveContext.log(directory + " is not a directory");
return callback();
}
resolver.doResolve(target, request, "existing directory", resolveContext, callback);
});
});
);
}
};

@@ -16,19 +16,31 @@ /*

const fs = resolver.fileSystem;
resolver.getHook(this.source).tapAsync("FileExistsPlugin", (request, resolveContext, callback) => {
const file = request.path;
fs.stat(file, (err, stat) => {
if(err || !stat) {
if(resolveContext.missing) resolveContext.missing.add(file);
if(resolveContext.log) resolveContext.log(file + " doesn't exist");
return callback();
}
if(!stat.isFile()) {
if(resolveContext.missing) resolveContext.missing.add(file);
if(resolveContext.log) resolveContext.log(file + " is not a file");
return callback();
}
resolver.doResolve(target, request, "existing file: " + file, resolveContext, callback);
resolver
.getHook(this.source)
.tapAsync("FileExistsPlugin", (request, resolveContext, callback) => {
const file = request.path;
fs.stat(file, (err, stat) => {
if (err || !stat) {
if (resolveContext.missingDependencies)
resolveContext.missingDependencies.add(file);
if (resolveContext.log) resolveContext.log(file + " doesn't exist");
return callback();
}
if (!stat.isFile()) {
if (resolveContext.missingDependencies)
resolveContext.missingDependencies.add(file);
if (resolveContext.log) resolveContext.log(file + " is not a file");
return callback();
}
if (resolveContext.fileDependencies)
resolveContext.fileDependencies.add(file);
resolver.doResolve(
target,
request,
"existing file: " + file,
resolveContext,
callback
);
});
});
});
}
};

@@ -15,9 +15,9 @@ /*

const target = resolver.ensureHook(this.target);
resolver.getHook(this.source).tapAsync("FileKindPlugin", (request, resolveContext, callback) => {
if(request.directory) return callback();
const obj = Object.assign({}, request);
delete obj.directory;
resolver.doResolve(target, obj, null, resolveContext, callback);
});
resolver
.getHook(this.source)
.tapAsync("FileKindPlugin", (request, resolveContext, callback) => {
if (request.directory) return callback();
resolver.doResolve(target, request, null, resolveContext, callback);
});
}
};

@@ -8,59 +8,55 @@ /*

module.exports = function forEachBail(array, iterator, callback) {
if(array.length === 0) return callback();
let currentPos = array.length;
let currentResult;
let done = [];
for(let i = 0; i < array.length; i++) {
const itCb = createIteratorCallback(i);
iterator(array[i], itCb);
if(currentPos === 0) break;
}
if (array.length === 0) return callback();
function createIteratorCallback(i) {
return(...args) => { // eslint-disable-line
if(i >= currentPos) return; // ignore
done.push(i);
if(args.length > 0) {
currentPos = i + 1;
done = done.filter(item => {
return item <= i;
});
currentResult = args;
let index = 0;
let inCall = true;
let inCallResult;
const innerCallback = (err, result) => {
if (err || result !== undefined) {
if (inCall) {
inCallResult = [err, result];
return;
}
if(done.length === currentPos) {
callback.apply(null, currentResult);
currentPos = 0;
callback(err, result);
return;
}
if (inCall) {
inCallResult = true;
return;
}
inCall = true;
// eslint-disable-next-line no-constant-condition
while (true) {
if (index === array.length) return callback();
iterator(array[index++], innerCallback);
if (inCallResult !== undefined) {
if (inCallResult !== true) {
return callback(...inCallResult);
}
inCallResult = undefined;
// continue loop
} else {
inCall = false;
return;
}
};
}
};
}
};
module.exports.withIndex = function forEachBailWithIndex(array, iterator, callback) {
if(array.length === 0) return callback();
let currentPos = array.length;
let currentResult;
let done = [];
for(let i = 0; i < array.length; i++) {
const itCb = createIteratorCallback(i);
iterator(array[i], i, itCb);
if(currentPos === 0) break;
}
function createIteratorCallback(i) {
return(...args) => { // eslint-disable-line
if(i >= currentPos) return; // ignore
done.push(i);
if(args.length > 0) {
currentPos = i + 1;
done = done.filter(item => {
return item <= i;
});
currentResult = args;
inCall = true;
// eslint-disable-next-line no-constant-condition
while (true) {
if (index === array.length) return callback();
iterator(array[index++], innerCallback);
if (inCallResult !== undefined) {
if (inCallResult !== true) {
return callback(...inCallResult);
}
if(done.length === currentPos) {
callback.apply(null, currentResult);
currentPos = 0;
}
};
inCallResult = undefined;
// continue loop
} else {
inCall = false;
return;
}
}
};

@@ -8,10 +8,12 @@ /*

module.exports = function getInnerRequest(resolver, request) {
if(typeof request.__innerRequest === "string" &&
if (
typeof request.__innerRequest === "string" &&
request.__innerRequest_request === request.request &&
request.__innerRequest_relativePath === request.relativePath)
request.__innerRequest_relativePath === request.relativePath
)
return request.__innerRequest;
let innerRequest;
if(request.request) {
if (request.request) {
innerRequest = request.request;
if(/^\.\.?\//.test(innerRequest) && request.relativePath) {
if (/^\.\.?\//.test(innerRequest) && request.relativePath) {
innerRequest = resolver.join(request.relativePath, innerRequest);

@@ -24,3 +26,3 @@ }

request.__innerRequest_relativePath = request.relativePath;
return request.__innerRequest = innerRequest;
return (request.__innerRequest = innerRequest);
};

@@ -8,3 +8,3 @@ /*

module.exports = function getPaths(path) {
const parts = path.split(/(.*?[\\\/]+)/);
const parts = path.split(/(.*?[\\/]+)/);
const paths = [path];

@@ -14,3 +14,3 @@ const seqments = [parts[parts.length - 1]];

path = path.substr(0, path.length - part.length - 1);
for(let i = parts.length - 2; i > 2; i -= 2) {
for (let i = parts.length - 2; i > 2; i -= 2) {
paths.push(path);

@@ -34,5 +34,5 @@ part = parts[i];

const p = i < 0 ? j : j < 0 ? i : i < j ? j : i;
if(p < 0) return null;
if (p < 0) return null;
const s = path.substr(p + 1);
return s;
};

@@ -15,11 +15,16 @@ /*

const target = resolver.ensureHook(this.target);
resolver.getHook(this.source).tapAsync("JoinRequestPlugin", (request, resolveContext, callback) => {
const obj = Object.assign({}, request, {
path: resolver.join(request.path, request.request),
relativePath: request.relativePath && resolver.join(request.relativePath, request.request),
request: undefined
resolver
.getHook(this.source)
.tapAsync("JoinRequestPlugin", (request, resolveContext, callback) => {
const obj = {
...request,
path: resolver.join(request.path, request.request),
relativePath:
request.relativePath &&
resolver.join(request.relativePath, request.request),
request: undefined
};
resolver.doResolve(target, obj, null, resolveContext, callback);
});
resolver.doResolve(target, obj, null, resolveContext, callback);
});
}
};

@@ -14,16 +14,29 @@ /*

const source = this.source;
resolver.getHook(this.source).tapAsync("LogInfoPlugin", (request, resolveContext, callback) => {
if(!resolveContext.log) return callback();
const log = resolveContext.log;
const prefix = "[" + source + "] ";
if(request.path) log(prefix + "Resolving in directory: " + request.path);
if(request.request) log(prefix + "Resolving request: " + request.request);
if(request.module) log(prefix + "Request is an module request.");
if(request.directory) log(prefix + "Request is a directory request.");
if(request.query) log(prefix + "Resolving request query: " + request.query);
if(request.descriptionFilePath) log(prefix + "Has description data from " + request.descriptionFilePath);
if(request.relativePath) log(prefix + "Relative path from description file is: " + request.relativePath);
callback();
});
resolver
.getHook(this.source)
.tapAsync("LogInfoPlugin", (request, resolveContext, callback) => {
if (!resolveContext.log) return callback();
const log = resolveContext.log;
const prefix = "[" + source + "] ";
if (request.path)
log(prefix + "Resolving in directory: " + request.path);
if (request.request)
log(prefix + "Resolving request: " + request.request);
if (request.module) log(prefix + "Request is an module request.");
if (request.directory) log(prefix + "Request is a directory request.");
if (request.query)
log(prefix + "Resolving request query: " + request.query);
if (request.descriptionFilePath)
log(
prefix + "Has description data from " + request.descriptionFilePath
);
if (request.relativePath)
log(
prefix +
"Relative path from description file is: " +
request.relativePath
);
callback();
});
}
};

@@ -18,36 +18,55 @@ /*

const target = resolver.ensureHook(this.target);
resolver.getHook(this.source).tapAsync("MainFieldPlugin", (request, resolveContext, callback) => {
if(request.path !== request.descriptionFileRoot) return callback();
if(request.alreadyTriedMainField === request.descriptionFilePath) return callback();
const content = request.descriptionFileData;
const filename = path.basename(request.descriptionFilePath);
let mainModule;
const field = this.options.name;
if(Array.isArray(field)) {
let current = content;
for(let j = 0; j < field.length; j++) {
if(current === null || typeof current !== "object") {
current = null;
break;
resolver
.getHook(this.source)
.tapAsync("MainFieldPlugin", (request, resolveContext, callback) => {
if (request.path !== request.descriptionFileRoot) return callback();
if (request.alreadyTriedMainField === request.descriptionFilePath)
return callback();
const content = request.descriptionFileData;
const filename = path.basename(request.descriptionFilePath);
let mainModule;
const field = this.options.name;
if (Array.isArray(field)) {
let current = content;
for (let j = 0; j < field.length; j++) {
if (current === null || typeof current !== "object") {
current = null;
break;
}
current = current[field[j]];
}
current = current[field[j]];
if (typeof current === "string") {
mainModule = current;
}
} else {
if (typeof content[field] === "string") {
mainModule = content[field];
}
}
if(typeof current === "string") {
mainModule = current;
if (!mainModule || mainModule === "." || mainModule === "./") {
return callback();
}
} else {
if(typeof content[field] === "string") {
mainModule = content[field];
}
}
if(!mainModule) return callback();
if(this.options.forceRelative && !/^\.\.?\//.test(mainModule))
mainModule = "./" + mainModule;
const obj = Object.assign({}, request, {
request: mainModule,
alreadyTriedMainField: request.descriptionFilePath
if (this.options.forceRelative && !/^\.\.?\//.test(mainModule))
mainModule = "./" + mainModule;
const obj = {
...request,
request: mainModule,
module: false,
directory: mainModule.endsWith("/"),
alreadyTriedMainField: request.descriptionFilePath
};
return resolver.doResolve(
target,
obj,
"use " +
mainModule +
" from " +
this.options.name +
" in " +
filename,
resolveContext,
callback
);
});
return resolver.doResolve(target, obj, "use " + mainModule + " from " + this.options.name + " in " + filename, resolveContext, callback);
});
}
};

@@ -15,15 +15,21 @@ /*

const target = resolver.ensureHook(this.target);
resolver.getHook(this.source).tapAsync("ModuleKindPlugin", (request, resolveContext, callback) => {
if(!request.module) return callback();
const obj = Object.assign({}, request);
delete obj.module;
resolver.doResolve(target, obj, "resolve as module", resolveContext, (err, result) => {
if(err) return callback(err);
resolver
.getHook(this.source)
.tapAsync("ModuleKindPlugin", (request, resolveContext, callback) => {
if (!request.module) return callback();
resolver.doResolve(
target,
request,
"resolve as module",
resolveContext,
(err, result) => {
if (err) return callback(err);
// Don't allow other alternatives
if(result === undefined) return callback(null, null);
callback(null, result);
// Don't allow other alternatives
if (result === undefined) return callback(null, null);
callback(null, result);
}
);
});
});
}
};

@@ -19,27 +19,50 @@ /*

const target = resolver.ensureHook(this.target);
resolver.getHook(this.source).tapAsync("ModulesInHierachicDirectoriesPlugin", (request, resolveContext, callback) => {
const fs = resolver.fileSystem;
const addrs = getPaths(request.path).paths.map(p => {
return this.directories.map(d => resolver.join(p, d));
}).reduce((array, p) => {
array.push.apply(array, p);
return array;
}, []);
forEachBail(addrs, (addr, callback) => {
fs.stat(addr, (err, stat) => {
if(!err && stat && stat.isDirectory()) {
const obj = Object.assign({}, request, {
path: addr,
request: "./" + request.request
});
const message = "looking for modules in " + addr;
return resolver.doResolve(target, obj, message, resolveContext, callback);
}
if(resolveContext.log) resolveContext.log(addr + " doesn't exist or is not a directory");
if(resolveContext.missing) resolveContext.missing.add(addr);
return callback();
});
}, callback);
});
resolver
.getHook(this.source)
.tapAsync(
"ModulesInHierachicDirectoriesPlugin",
(request, resolveContext, callback) => {
const fs = resolver.fileSystem;
const addrs = getPaths(request.path)
.paths.map(p => {
return this.directories.map(d => resolver.join(p, d));
})
.reduce((array, p) => {
array.push.apply(array, p);
return array;
}, []);
forEachBail(
addrs,
(addr, callback) => {
fs.stat(addr, (err, stat) => {
if (!err && stat && stat.isDirectory()) {
const obj = {
...request,
path: addr,
request: "./" + request.request,
module: false
};
const message = "looking for modules in " + addr;
return resolver.doResolve(
target,
obj,
message,
resolveContext,
callback
);
}
if (resolveContext.log)
resolveContext.log(
addr + " doesn't exist or is not a directory"
);
if (resolveContext.missingDependencies)
resolveContext.missingDependencies.add(addr);
return callback();
});
},
callback
);
}
);
}
};

@@ -16,10 +16,20 @@ /*

const target = resolver.ensureHook(this.target);
resolver.getHook(this.source).tapAsync("ModulesInRootPlugin", (request, resolveContext, callback) => {
const obj = Object.assign({}, request, {
path: this.path,
request: "./" + request.request
resolver
.getHook(this.source)
.tapAsync("ModulesInRootPlugin", (request, resolveContext, callback) => {
const obj = {
...request,
path: this.path,
request: "./" + request.request,
module: false
};
resolver.doResolve(
target,
obj,
"looking for modules in " + this.path,
resolveContext,
callback
);
});
resolver.doResolve(target, obj, "looking for modules in " + this.path, resolveContext, callback);
});
}
};

@@ -15,6 +15,8 @@ /*

const target = resolver.ensureHook(this.target);
resolver.getHook(this.source).tapAsync("NextPlugin", (request, resolveContext, callback) => {
resolver.doResolve(target, request, null, resolveContext, callback);
});
resolver
.getHook(this.source)
.tapAsync("NextPlugin", (request, resolveContext, callback) => {
resolver.doResolve(target, request, null, resolveContext, callback);
});
}
};

@@ -7,13 +7,10 @@ /*

const fs = require("fs");
const ResolverFactory = require("./ResolverFactory");
const NodeJsInputFileSystem = require("./NodeJsInputFileSystem");
const CachedInputFileSystem = require("./CachedInputFileSystem");
const nodeFileSystem = new CachedInputFileSystem(new NodeJsInputFileSystem(), 4000);
const nodeFileSystem = new CachedInputFileSystem(fs, 4000);
const nodeContext = {
environments: [
"node+es3+es5+process+native"
]
environments: ["node+es3+es5+process+native"]
};

@@ -25,4 +22,10 @@

});
module.exports = function resolve(context, path, request, resolveContext, callback) {
if(typeof context === "string") {
module.exports = function resolve(
context,
path,
request,
resolveContext,
callback
) {
if (typeof context === "string") {
callback = resolveContext;

@@ -34,3 +37,3 @@ resolveContext = request;

}
if(typeof callback !== "function") {
if (typeof callback !== "function") {
callback = resolveContext;

@@ -47,3 +50,3 @@ }

module.exports.sync = function resolveSync(context, path, request) {
if(typeof context === "string") {
if (typeof context === "string") {
request = path;

@@ -56,79 +59,10 @@ path = context;

const asyncContextResolver = ResolverFactory.createResolver({
extensions: [".js", ".json", ".node"],
resolveToContext: true,
fileSystem: nodeFileSystem
});
module.exports.context = function resolveContext(context, path, request, resolveContext, callback) {
if(typeof context === "string") {
callback = resolveContext;
resolveContext = request;
request = path;
path = context;
context = nodeContext;
}
if(typeof callback !== "function") {
callback = resolveContext;
}
asyncContextResolver.resolve(context, path, request, resolveContext, callback);
};
const syncContextResolver = ResolverFactory.createResolver({
extensions: [".js", ".json", ".node"],
resolveToContext: true,
useSyncFileSystemCalls: true,
fileSystem: nodeFileSystem
});
module.exports.context.sync = function resolveContextSync(context, path, request) {
if(typeof context === "string") {
request = path;
path = context;
context = nodeContext;
}
return syncContextResolver.resolveSync(context, path, request);
};
const asyncLoaderResolver = ResolverFactory.createResolver({
extensions: [".js", ".json", ".node"],
moduleExtensions: ["-loader"],
mainFields: ["loader", "main"],
fileSystem: nodeFileSystem
});
module.exports.loader = function resolveLoader(context, path, request, resolveContext, callback) {
if(typeof context === "string") {
callback = resolveContext;
resolveContext = request;
request = path;
path = context;
context = nodeContext;
}
if(typeof callback !== "function") {
callback = resolveContext;
}
asyncLoaderResolver.resolve(context, path, request, resolveContext, callback);
};
const syncLoaderResolver = ResolverFactory.createResolver({
extensions: [".js", ".json", ".node"],
moduleExtensions: ["-loader"],
mainFields: ["loader", "main"],
useSyncFileSystemCalls: true,
fileSystem: nodeFileSystem
});
module.exports.loader.sync = function resolveLoaderSync(context, path, request) {
if(typeof context === "string") {
request = path;
path = context;
context = nodeContext;
}
return syncLoaderResolver.resolveSync(context, path, request);
};
module.exports.create = function create(options) {
options = Object.assign({
fileSystem: nodeFileSystem
}, options);
options = {
fileSystem: nodeFileSystem,
...options
};
const resolver = ResolverFactory.createResolver(options);
return function(context, path, request, resolveContext, callback) {
if(typeof context === "string") {
if (typeof context === "string") {
callback = resolveContext;

@@ -140,3 +74,3 @@ resolveContext = request;

}
if(typeof callback !== "function") {
if (typeof callback !== "function") {
callback = resolveContext;

@@ -149,9 +83,10 @@ }

module.exports.create.sync = function createSync(options) {
options = Object.assign({
options = {
useSyncFileSystemCalls: true,
fileSystem: nodeFileSystem
}, options);
fileSystem: nodeFileSystem,
...options
};
const resolver = ResolverFactory.createResolver(options);
return function(context, path, request) {
if(typeof context === "string") {
if (typeof context === "string") {
request = path;

@@ -168,3 +103,2 @@ path = context;

module.exports.NodeJsInputFileSystem = NodeJsInputFileSystem;
module.exports.CachedInputFileSystem = CachedInputFileSystem;

@@ -15,17 +15,18 @@ /*

const target = resolver.ensureHook(this.target);
resolver.getHook(this.source).tapAsync("ParsePlugin", (request, resolveContext, callback) => {
const parsed = resolver.parse(request.request);
const obj = Object.assign({}, request, parsed);
if(request.query && !parsed.query) {
obj.query = request.query;
}
if(parsed && resolveContext.log) {
if(parsed.module)
resolveContext.log("Parsed request is a module");
if(parsed.directory)
resolveContext.log("Parsed request is a directory");
}
resolver.doResolve(target, obj, null, resolveContext, callback);
});
resolver
.getHook(this.source)
.tapAsync("ParsePlugin", (request, resolveContext, callback) => {
const parsed = resolver.parse(request.request);
const obj = { ...request, ...parsed };
if (request.query && !parsed.query) {
obj.query = request.query;
}
if (parsed && resolveContext.log) {
if (parsed.module) resolveContext.log("Parsed request is a module");
if (parsed.directory)
resolveContext.log("Parsed request is a directory");
}
resolver.doResolve(target, obj, null, resolveContext, callback);
});
}
};

@@ -7,17 +7,11 @@ /*

const util = require("util");
const Tapable = require("tapable/lib/Tapable");
const SyncHook = require("tapable/lib/SyncHook");
const AsyncSeriesBailHook = require("tapable/lib/AsyncSeriesBailHook");
const AsyncSeriesHook = require("tapable/lib/AsyncSeriesHook");
const { AsyncSeriesBailHook, AsyncSeriesHook, SyncHook } = require("tapable");
const createInnerContext = require("./createInnerContext");
const {
normalize,
cachedJoin: join,
getType,
PathType
} = require("./pathUtils");
const REGEXP_NOT_MODULE = /^\.$|^\.[\\\/]|^\.\.$|^\.\.[\/\\]|^\/|^[A-Z]:[\\\/]/i;
const REGEXP_DIRECTORY = /[\/\\]$/i;
const memoryFsJoin = require("memory-fs/lib/join");
const memoizedJoin = new Map();
const memoryFsNormalize = require("memory-fs/lib/normalize");
function withName(name, hook) {

@@ -32,17 +26,4 @@ hook.name = name;

const deprecatedPushToMissing = util.deprecate((set, item) => {
set.add(item);
}, "Resolver: 'missing' is now a Set. Use add instead of push.");
const deprecatedResolveContextInCallback = util.deprecate((x) => {
return x;
}, "Resolver: The callback argument was splitted into resolveContext and callback.");
const deprecatedHookAsString = util.deprecate((x) => {
return x;
}, "Resolver#doResolve: The type arguments (string) is now a hook argument (Hook). Pass a reference to the hook instead.");
class Resolver extends Tapable {
class Resolver {
constructor(fileSystem) {
super();
this.fileSystem = fileSystem;

@@ -52,46 +33,26 @@ this.hooks = {

noResolve: withName("noResolve", new SyncHook(["request", "error"])),
resolve: withName("resolve", new AsyncSeriesBailHook(["request", "resolveContext"])),
resolve: withName(
"resolve",
new AsyncSeriesBailHook(["request", "resolveContext"])
),
result: new AsyncSeriesHook(["result", "resolveContext"])
};
this._pluginCompat.tap("Resolver: before/after", options => {
if(/^before-/.test(options.name)) {
options.name = options.name.substr(7);
options.stage = -10;
} else if(/^after-/.test(options.name)) {
options.name = options.name.substr(6);
options.stage = 10;
}
});
this._pluginCompat.tap("Resolver: step hooks", options => {
const name = options.name;
const stepHook = !/^resolve(-s|S)tep$|^no(-r|R)esolve$/.test(name);
if(stepHook) {
options.async = true;
this.ensureHook(name);
const fn = options.fn;
options.fn = (request, resolverContext, callback) => {
const innerCallback = (err, result) => {
if(err) return callback(err);
if(result !== undefined) return callback(null, result);
callback();
};
for(const key in resolverContext) {
innerCallback[key] = resolverContext[key];
}
fn.call(this, request, innerCallback);
};
}
});
}
ensureHook(name) {
if(typeof name !== "string") return name;
if (typeof name !== "string") {
return name;
}
name = toCamelCase(name);
if(/^before/.test(name)) {
return this.ensureHook(name[6].toLowerCase() + name.substr(7)).withOptions({
if (/^before/.test(name)) {
return this.ensureHook(
name[6].toLowerCase() + name.substr(7)
).withOptions({
stage: -10
});
}
if(/^after/.test(name)) {
return this.ensureHook(name[5].toLowerCase() + name.substr(6)).withOptions({
if (/^after/.test(name)) {
return this.ensureHook(
name[5].toLowerCase() + name.substr(6)
).withOptions({
stage: 10

@@ -101,4 +62,7 @@ });

const hook = this.hooks[name];
if(!hook) {
return this.hooks[name] = withName(name, new AsyncSeriesBailHook(["request", "resolveContext"]));
if (!hook) {
return (this.hooks[name] = withName(
name,
new AsyncSeriesBailHook(["request", "resolveContext"])
));
}

@@ -109,5 +73,7 @@ return hook;

getHook(name) {
if(typeof name !== "string") return name;
if (typeof name !== "string") {
return name;
}
name = toCamelCase(name);
if(/^before/.test(name)) {
if (/^before/.test(name)) {
return this.getHook(name[6].toLowerCase() + name.substr(7)).withOptions({

@@ -117,3 +83,3 @@ stage: -10

}
if(/^after/.test(name)) {
if (/^after/.test(name)) {
return this.getHook(name[5].toLowerCase() + name.substr(6)).withOptions({

@@ -124,3 +90,3 @@ stage: 10

const hook = this.hooks[name];
if(!hook) {
if (!hook) {
throw new Error(`Hook ${name} doesn't exist`);

@@ -132,3 +98,5 @@ }

resolveSync(context, path, request) {
let err, result, sync = false;
let err,
result,
sync = false;
this.resolve(context, path, request, {}, (e, r) => {

@@ -139,4 +107,8 @@ err = e;

});
if(!sync) throw new Error("Cannot 'resolveSync' because the fileSystem is not sync. Use 'resolve'!");
if(err) throw err;
if (!sync) {
throw new Error(
"Cannot 'resolveSync' because the fileSystem is not sync. Use 'resolve'!"
);
}
if (err) throw err;
return result;

@@ -146,10 +118,2 @@ }

resolve(context, path, request, resolveContext, callback) {
// TODO remove in enhanced-resolve 5
// For backward compatiblity START
if(typeof callback !== "function") {
callback = deprecatedResolveContextInCallback(resolveContext);
// resolveContext is a function containing additional properties
// It's now used for resolveContext and callback
}
// END
const obj = {

@@ -161,61 +125,97 @@ context: context,

const message = "resolve '" + request + "' in '" + path + "'";
const message = `resolve '${request}' in '${path}'`;
// Try to resolve assuming there is no error
// We don't log stuff in this case
return this.doResolve(this.hooks.resolve, obj, message, {
missing: resolveContext.missing,
stack: resolveContext.stack
}, (err, result) => {
if(!err && result) {
return callback(null, result.path === false ? false : result.path + (result.query || ""), result);
}
const finishResolved = result => {
return callback(
null,
result.path === false ? false : result.path + (result.query || ""),
result
);
};
const localMissing = new Set();
// TODO remove in enhanced-resolve 5
localMissing.push = item => deprecatedPushToMissing(localMissing, item);
const finishWithoutResolve = log => {
const error = new Error("Can't " + message);
error.details = log.join("\n");
this.hooks.noResolve.call(obj, error);
return callback(error);
};
if (resolveContext.log) {
// We need log anyway to capture it in case of an error
const log = [];
return this.doResolve(this.hooks.resolve, obj, message, {
log: msg => {
if(resolveContext.log) {
return this.doResolve(
this.hooks.resolve,
obj,
message,
{
log: msg => {
resolveContext.log(msg);
}
log.push(msg);
log.push(msg);
},
fileDependencies: resolveContext.fileDependencies,
contextDependencies: resolveContext.contextDependencies,
missingDependencies: resolveContext.missingDependencies,
stack: resolveContext.stack
},
missing: localMissing,
stack: resolveContext.stack
}, (err, result) => {
if(err) return callback(err);
(err, result) => {
if (err) return callback(err);
const error = new Error("Can't " + message);
error.details = log.join("\n");
error.missing = Array.from(localMissing);
this.hooks.noResolve.call(obj, error);
return callback(error);
});
});
if (result) return finishResolved(result);
return finishWithoutResolve(log);
}
);
} else {
// Try to resolve assuming there is no error
// We don't log stuff in this case
return this.doResolve(
this.hooks.resolve,
obj,
message,
{
log: undefined,
fileDependencies: resolveContext.fileDependencies,
contextDependencies: resolveContext.contextDependencies,
missingDependencies: resolveContext.missingDependencies,
stack: resolveContext.stack
},
(err, result) => {
if (err) return callback(err);
if (result) return finishResolved(result);
// log is missing for the error details
// so we redo the resolving for the log info
// this is more expensive to the success case
// is assumed by default
const log = [];
return this.doResolve(
this.hooks.resolve,
obj,
message,
{
log: msg => log.push(msg),
stack: resolveContext.stack
},
(err, result) => {
if (err) return callback(err);
return finishWithoutResolve(log);
}
);
}
);
}
}
doResolve(hook, request, message, resolveContext, callback) {
// TODO remove in enhanced-resolve 5
// For backward compatiblity START
if(typeof callback !== "function") {
callback = deprecatedResolveContextInCallback(resolveContext);
// resolveContext is a function containing additional properties
// It's now used for resolveContext and callback
}
if(typeof hook === "string") {
const name = toCamelCase(hook);
hook = deprecatedHookAsString(this.hooks[name]);
if(!hook) {
throw new Error(`Hook "${name}" doesn't exist`);
}
}
// END
if(typeof callback !== "function") throw new Error("callback is not a function " + Array.from(arguments));
if(!resolveContext) throw new Error("resolveContext is not an object " + Array.from(arguments));
const stackLine = hook.name + ": (" + request.path + ") " +
(request.request || "") + (request.query || "") +
const stackLine =
hook.name +
": (" +
request.path +
") " +
(request.request || "") +
(request.query || "") +
(request.directory ? " directory" : "") +

@@ -225,9 +225,13 @@ (request.module ? " module" : "");

let newStack;
if(resolveContext.stack) {
if (resolveContext.stack) {
newStack = new Set(resolveContext.stack);
if(resolveContext.stack.has(stackLine)) {
if (resolveContext.stack.has(stackLine)) {
// Prevent recursion
const recursionError = new Error("Recursion in resolving\nStack:\n " + Array.from(newStack).join("\n "));
const recursionError = new Error(
"Recursion in resolving\nStack:\n " +
Array.from(newStack).join("\n ")
);
recursionError.recursion = true;
if(resolveContext.log) resolveContext.log("abort resolving because of recursion");
if (resolveContext.log)
resolveContext.log("abort resolving because of recursion");
return callback(recursionError);

@@ -241,11 +245,16 @@ }

if(hook.isUsed()) {
const innerContext = createInnerContext({
log: resolveContext.log,
missing: resolveContext.missing,
stack: newStack
}, message);
if (hook.isUsed()) {
const innerContext = createInnerContext(
{
log: resolveContext.log,
fileDependencies: resolveContext.fileDependencies,
contextDependencies: resolveContext.contextDependencies,
missingDependencies: resolveContext.missingDependencies,
stack: newStack
},
message
);
return hook.callAsync(request, innerContext, (err, result) => {
if(err) return callback(err);
if(result) return callback(null, result);
if (err) return callback(err);
if (result) return callback(null, result);
callback();

@@ -259,3 +268,3 @@ });

parse(identifier) {
if(identifier === "") return null;
if (identifier === "") return null;
const part = {

@@ -269,5 +278,5 @@ request: "",

const idxQuery = identifier.indexOf("?");
if(idxQuery === 0) {
if (idxQuery === 0) {
part.query = identifier;
} else if(idxQuery > 0) {
} else if (idxQuery > 0) {
part.request = identifier.slice(0, idxQuery);

@@ -278,6 +287,6 @@ part.query = identifier.slice(idxQuery);

}
if(part.request) {
if (part.request) {
part.module = this.isModule(part.request);
part.directory = this.isDirectory(part.request);
if(part.directory) {
if (part.directory) {
part.request = part.request.substr(0, part.request.length - 1);

@@ -290,26 +299,19 @@ }

isModule(path) {
return !REGEXP_NOT_MODULE.test(path);
return getType(path) === PathType.Normal;
}
/**
* @param {string} path a path
* @returns {boolean} true, if the path is a directory path
*/
isDirectory(path) {
return REGEXP_DIRECTORY.test(path);
return path.endsWith("/");
}
join(path, request) {
let cacheEntry;
let pathCache = memoizedJoin.get(path);
if(typeof pathCache === "undefined") {
memoizedJoin.set(path, pathCache = new Map());
} else {
cacheEntry = pathCache.get(request);
if(typeof cacheEntry !== "undefined")
return cacheEntry;
}
cacheEntry = memoryFsJoin(path, request);
pathCache.set(request, cacheEntry);
return cacheEntry;
return join(path, request);
}
normalize(path) {
return memoryFsNormalize(path);
return normalize(path);
}

@@ -316,0 +318,0 @@ }

@@ -8,2 +8,3 @@ /*

const Resolver = require("./Resolver");
const { getType, PathType } = require("./pathUtils");

@@ -19,2 +20,3 @@ const SyncAsyncFileSystemDecorator = require("./SyncAsyncFileSystemDecorator");

const JoinRequestPlugin = require("./JoinRequestPlugin");
const JoinRequestPartPlugin = require("./JoinRequestPartPlugin");
const ModulesInHierachicDirectoriesPlugin = require("./ModulesInHierachicDirectoriesPlugin");

@@ -24,5 +26,2 @@ const ModulesInRootPlugin = require("./ModulesInRootPlugin");

const AliasFieldPlugin = require("./AliasFieldPlugin");
const ConcordExtensionsPlugin = require("./ConcordExtensionsPlugin");
const ConcordMainPlugin = require("./ConcordMainPlugin");
const ConcordModulesPlugin = require("./ConcordModulesPlugin");
const DirectoryExistsPlugin = require("./DirectoryExistsPlugin");

@@ -35,7 +34,6 @@ const FileExistsPlugin = require("./FileExistsPlugin");

const ResultPlugin = require("./ResultPlugin");
const ModuleAppendPlugin = require("./ModuleAppendPlugin");
const UnsafeCachePlugin = require("./UnsafeCachePlugin");
const PnpPlugin = require("./PnpPlugin");
exports.createResolver = function(options) {
//// OPTIONS ////

@@ -69,13 +67,17 @@

// A list of module extensions which should be tried for modules
let moduleExtensions = options.moduleExtensions || [];
// Enforce that a extension from moduleExtensions must be used
const enforceModuleExtension = options.enforceModuleExtension || false;
// A list of module alias configurations or an object which maps key to value
let alias = options.alias || [];
// A PnP API that should be used - null is "never", undefined is "auto"
const pnpApi =
options.pnpApi === undefined
? process.versions.pnp
? // eslint-disable-next-line node/no-missing-require
require("pnpapi")
: null
: options.pnpApi;
// Resolve symlinks to their symlinked location
const symlinks = typeof options.symlinks !== "undefined" ? options.symlinks : true;
const symlinks =
typeof options.symlinks !== "undefined" ? options.symlinks : true;

@@ -89,12 +91,14 @@ // Resolve to a context instead of a file

// Whether or not the unsafeCache should include request context as part of the cache key.
const cacheWithContext = typeof options.cacheWithContext !== "undefined" ? options.cacheWithContext : true;
const cacheWithContext =
typeof options.cacheWithContext !== "undefined"
? options.cacheWithContext
: true;
// Enable concord description file instructions
const enableConcord = options.concord || false;
// A function which decides whether a request should be cached or not.
// an object is passed with `path` and `request` properties.
const cachePredicate = options.cachePredicate || function() {
return true;
};
const cachePredicate =
options.cachePredicate ||
function() {
return true;
};

@@ -112,15 +116,19 @@ // The file system which should be used

if(!resolver) {
resolver = new Resolver(useSyncFileSystemCalls ? new SyncAsyncFileSystemDecorator(fileSystem) : fileSystem);
if (!resolver) {
resolver = new Resolver(
useSyncFileSystemCalls
? new SyncAsyncFileSystemDecorator(fileSystem)
: fileSystem
);
}
extensions = [].concat(extensions);
moduleExtensions = [].concat(moduleExtensions);
modules = mergeFilteredToArray([].concat(modules), item => {
return !isAbsolutePath(item);
const type = getType(item);
return type === PathType.Normal || type === PathType.Relative;
});
mainFields = mainFields.map(item => {
if(typeof item === "string" || Array.isArray(item)) {
if (typeof item === "string" || Array.isArray(item)) {
item = {

@@ -134,11 +142,11 @@ name: item,

if(typeof alias === "object" && !Array.isArray(alias)) {
if (typeof alias === "object" && !Array.isArray(alias)) {
alias = Object.keys(alias).map(key => {
let onlyModule = false;
let obj = alias[key];
if(/\$$/.test(key)) {
if (/\$$/.test(key)) {
onlyModule = true;
key = key.substr(0, key.length - 1);
}
if(typeof obj === "string") {
if (typeof obj === "string" || Array.isArray(obj)) {
obj = {

@@ -148,6 +156,7 @@ alias: obj

}
obj = Object.assign({
obj = {
name: key,
onlyModule: onlyModule
}, obj);
onlyModule: onlyModule,
...obj
};
return obj;

@@ -157,3 +166,3 @@ });

if(unsafeCache && typeof unsafeCache !== "object") {
if (unsafeCache && typeof unsafeCache !== "object") {
unsafeCache = {};

@@ -169,5 +178,8 @@ }

resolver.ensureHook("module");
resolver.ensureHook("resolveInDirectory");
resolver.ensureHook("resolveInExistingDirectory");
resolver.ensureHook("relative");
resolver.ensureHook("describedRelative");
resolver.ensureHook("directory");
resolver.ensureHook("undescribedExistingDirectory");
resolver.ensureHook("existingDirectory");

@@ -181,4 +193,12 @@ resolver.ensureHook("undescribedRawFile");

// resolve
if(unsafeCache) {
plugins.push(new UnsafeCachePlugin("resolve", cachePredicate, unsafeCache, cacheWithContext, "new-resolve"));
if (unsafeCache) {
plugins.push(
new UnsafeCachePlugin(
"resolve",
cachePredicate,
unsafeCache,
cacheWithContext,
"new-resolve"
)
);
plugins.push(new ParsePlugin("new-resolve", "parsed-resolve"));

@@ -190,11 +210,15 @@ } else {

// parsed-resolve
plugins.push(new DescriptionFilePlugin("parsed-resolve", descriptionFiles, "described-resolve"));
plugins.push(
new DescriptionFilePlugin(
"parsed-resolve",
descriptionFiles,
false,
"described-resolve"
)
);
plugins.push(new NextPlugin("after-parsed-resolve", "described-resolve"));
// described-resolve
if(alias.length > 0)
if (alias.length > 0)
plugins.push(new AliasPlugin("described-resolve", alias, "resolve"));
if(enableConcord) {
plugins.push(new ConcordModulesPlugin("described-resolve", {}, "resolve"));
}
aliasFields.forEach(item => {

@@ -206,57 +230,117 @@ plugins.push(new AliasFieldPlugin("described-resolve", item, "resolve"));

// raw-module
moduleExtensions.forEach(item => {
plugins.push(new ModuleAppendPlugin("raw-module", item, "module"));
});
if(!enforceModuleExtension)
plugins.push(new TryNextPlugin("raw-module", null, "module"));
// module
if (pnpApi) {
plugins.push(new PnpPlugin("raw-module", pnpApi, "relative"));
}
modules.forEach(item => {
if(Array.isArray(item))
plugins.push(new ModulesInHierachicDirectoriesPlugin("module", item, "resolve"));
else
plugins.push(new ModulesInRootPlugin("module", item, "resolve"));
if (Array.isArray(item))
plugins.push(
new ModulesInHierachicDirectoriesPlugin("raw-module", item, "module")
);
else plugins.push(new ModulesInRootPlugin("raw-module", item, "module"));
});
// module
plugins.push(new JoinRequestPartPlugin("module", "resolve-in-directory"));
// resolve-in-directory
if (!resolveToContext) {
plugins.push(
new TryNextPlugin(
"resolve-in-directory",
"single file module",
"undescribed-raw-file"
)
);
}
plugins.push(
new DirectoryExistsPlugin(
"resolve-in-directory",
"resolve-in-existing-directory"
)
);
// resolve-in-existing-directory
plugins.push(
new JoinRequestPlugin("resolve-in-existing-directory", "relative")
);
// relative
plugins.push(new DescriptionFilePlugin("relative", descriptionFiles, "described-relative"));
plugins.push(
new DescriptionFilePlugin(
"relative",
descriptionFiles,
true,
"described-relative"
)
);
plugins.push(new NextPlugin("after-relative", "described-relative"));
// described-relative
plugins.push(new FileKindPlugin("described-relative", "raw-file"));
plugins.push(new TryNextPlugin("described-relative", "as directory", "directory"));
if (!resolveToContext) {
plugins.push(new FileKindPlugin("described-relative", "raw-file"));
}
plugins.push(
new TryNextPlugin("described-relative", "as directory", "directory")
);
// directory
plugins.push(new DirectoryExistsPlugin("directory", "existing-directory"));
plugins.push(
new DirectoryExistsPlugin("directory", "undescribed-existing-directory")
);
if(resolveToContext) {
// existing-directory
plugins.push(new NextPlugin("existing-directory", "resolved"));
if (resolveToContext) {
// undescribed-existing-directory
plugins.push(new NextPlugin("undescribed-existing-directory", "resolved"));
} else {
// undescribed-existing-directory
plugins.push(
new DescriptionFilePlugin(
"undescribed-existing-directory",
descriptionFiles,
false,
"existing-directory"
)
);
mainFiles.forEach(item => {
plugins.push(
new UseFilePlugin(
"undescribed-existing-directory",
item,
"undescribed-raw-file"
)
);
});
// existing-directory
if(enableConcord) {
plugins.push(new ConcordMainPlugin("existing-directory", {}, "resolve"));
}
// described-existing-directory
mainFields.forEach(item => {
plugins.push(new MainFieldPlugin("existing-directory", item, "resolve"));
plugins.push(
new MainFieldPlugin(
"existing-directory",
item,
"resolve-in-existing-directory"
)
);
});
mainFiles.forEach(item => {
plugins.push(new UseFilePlugin("existing-directory", item, "undescribed-raw-file"));
plugins.push(
new UseFilePlugin("existing-directory", item, "undescribed-raw-file")
);
});
// undescribed-raw-file
plugins.push(new DescriptionFilePlugin("undescribed-raw-file", descriptionFiles, "raw-file"));
plugins.push(
new DescriptionFilePlugin(
"undescribed-raw-file",
descriptionFiles,
true,
"raw-file"
)
);
plugins.push(new NextPlugin("after-undescribed-raw-file", "raw-file"));
// raw-file
if(!enforceExtension) {
if (!enforceExtension) {
plugins.push(new TryNextPlugin("raw-file", "no extension", "file"));
}
if(enableConcord) {
plugins.push(new ConcordExtensionsPlugin("raw-file", {}, "file"));
}
extensions.forEach(item => {

@@ -267,17 +351,13 @@ plugins.push(new AppendPlugin("raw-file", item, "file"));

// file
if(alias.length > 0)
if (alias.length > 0)
plugins.push(new AliasPlugin("file", alias, "resolve"));
if(enableConcord) {
plugins.push(new ConcordModulesPlugin("file", {}, "resolve"));
}
aliasFields.forEach(item => {
plugins.push(new AliasFieldPlugin("file", item, "resolve"));
});
if(symlinks)
plugins.push(new SymlinkPlugin("file", "relative"));
plugins.push(new FileExistsPlugin("file", "existing-file"));
// existing-file
if (symlinks)
plugins.push(new SymlinkPlugin("existing-file", "existing-file"));
plugins.push(new NextPlugin("existing-file", "resolved"));
}

@@ -299,5 +379,5 @@

return array.reduce((array, item) => {
if(filter(item)) {
if (filter(item)) {
const lastElement = array[array.length - 1];
if(Array.isArray(lastElement)) {
if (Array.isArray(lastElement)) {
lastElement.push(item);

@@ -314,5 +394,1 @@ } else {

}
function isAbsolutePath(path) {
return /^[A-Z]:|^\//.test(path);
}

@@ -13,11 +13,15 @@ /*

apply(resolver) {
this.source.tapAsync("ResultPlugin", (request, resolverContext, callback) => {
const obj = Object.assign({}, request);
if(resolverContext.log) resolverContext.log("reporting result " + obj.path);
resolver.hooks.result.callAsync(obj, resolverContext, err => {
if(err) return callback(err);
callback(null, obj);
});
});
this.source.tapAsync(
"ResultPlugin",
(request, resolverContext, callback) => {
const obj = { ...request };
if (resolverContext.log)
resolverContext.log("reporting result " + obj.path);
resolver.hooks.result.callAsync(obj, resolverContext, err => {
if (err) return callback(err);
callback(null, obj);
});
}
);
}
};

@@ -9,2 +9,3 @@ /*

const forEachBail = require("./forEachBail");
const { getType, PathType } = require("./pathUtils");

@@ -20,32 +21,58 @@ module.exports = class SymlinkPlugin {

const fs = resolver.fileSystem;
resolver.getHook(this.source).tapAsync("SymlinkPlugin", (request, resolveContext, callback) => {
const pathsResult = getPaths(request.path);
const pathSeqments = pathsResult.seqments;
const paths = pathsResult.paths;
resolver
.getHook(this.source)
.tapAsync("SymlinkPlugin", (request, resolveContext, callback) => {
if (request.ignoreSymlinks) return callback();
const pathsResult = getPaths(request.path);
const pathSeqments = pathsResult.seqments;
const paths = pathsResult.paths;
let containsSymlink = false;
forEachBail.withIndex(paths, (path, idx, callback) => {
fs.readlink(path, (err, result) => {
if(!err && result) {
pathSeqments[idx] = result;
containsSymlink = true;
// Shortcut when absolute symlink found
if(/^(\/|[a-zA-Z]:($|\\))/.test(result))
return callback(null, idx);
let containsSymlink = false;
let idx = -1;
forEachBail(
paths,
(path, callback) => {
idx++;
if (resolveContext.fileDependencies)
resolveContext.fileDependencies.add(path);
fs.readlink(path, (err, result) => {
if (!err && result) {
pathSeqments[idx] = result;
containsSymlink = true;
// Shortcut when absolute symlink found
const resultType = getType(result);
if (
resultType === PathType.AbsoluteWin ||
resultType === PathType.AbsolutePosix
) {
return callback(null, idx);
}
}
callback();
});
},
(err, idx) => {
if (!containsSymlink) return callback();
const resultSeqments =
typeof idx === "number"
? pathSeqments.slice(0, idx + 1)
: pathSeqments.slice();
const result = resultSeqments.reverse().reduce((a, b) => {
return resolver.join(a, b);
});
const obj = {
...request,
path: result
};
resolver.doResolve(
target,
obj,
"resolved symlink to " + result,
resolveContext,
callback
);
}
callback();
});
}, (err, idx) => {
if(!containsSymlink) return callback();
const resultSeqments = typeof idx === "number" ? pathSeqments.slice(0, idx + 1) : pathSeqments.slice();
const result = resultSeqments.reverse().reduce((a, b) => {
return resolver.join(a, b);
});
const obj = Object.assign({}, request, {
path: result
});
resolver.doResolve(target, obj, "resolved symlink to " + result, resolveContext, callback);
);
});
});
}
};

@@ -9,8 +9,8 @@ /*

this.fs = fs;
if(fs.statSync) {
this.stat = function(arg, callback) {
if (fs.statSync) {
this.stat = (arg, callback) => {
let result;
try {
result = fs.statSync(arg);
} catch(e) {
} catch (e) {
return callback(e);

@@ -20,9 +20,11 @@ }

};
this.statSync = arg => fs.statSync(arg);
}
if(fs.readdirSync) {
this.readdir = function(arg, callback) {
if (fs.readdirSync) {
this.readdir = (arg, callback) => {
let result;
try {
result = fs.readdirSync(arg);
} catch(e) {
} catch (e) {
return callback(e);

@@ -32,9 +34,11 @@ }

};
this.readdirSync = arg => fs.readdirSync(arg);
}
if(fs.readFileSync) {
this.readFile = function(arg, callback) {
if (fs.readFileSync) {
this.readFile = (arg, callback) => {
let result;
try {
result = fs.readFileSync(arg);
} catch(e) {
} catch (e) {
return callback(e);

@@ -44,9 +48,11 @@ }

};
this.readFileSync = arg => fs.readFileSync(arg);
}
if(fs.readlinkSync) {
this.readlink = function(arg, callback) {
if (fs.readlinkSync) {
this.readlink = (arg, callback) => {
let result;
try {
result = fs.readlinkSync(arg);
} catch(e) {
} catch (e) {
return callback(e);

@@ -56,9 +62,11 @@ }

};
this.readlinkSync = arg => fs.readlinkSync(arg);
}
if(fs.readJsonSync) {
this.readJson = function(arg, callback) {
if (fs.readJsonSync) {
this.readJson = (arg, callback) => {
let result;
try {
result = fs.readJsonSync(arg);
} catch(e) {
} catch (e) {
return callback(e);

@@ -68,4 +76,6 @@ }

};
this.readJsonSync = arg => fs.readJsonSync(arg);
}
}
module.exports = SyncAsyncFileSystemDecorator;

@@ -16,6 +16,14 @@ /*

const target = resolver.ensureHook(this.target);
resolver.getHook(this.source).tapAsync("TryNextPlugin", (request, resolveContext, callback) => {
resolver.doResolve(target, request, this.message, resolveContext, callback);
});
resolver
.getHook(this.source)
.tapAsync("TryNextPlugin", (request, resolveContext, callback) => {
resolver.doResolve(
target,
request,
this.message,
resolveContext,
callback
);
});
}
};

@@ -27,16 +27,24 @@ /*

const target = resolver.ensureHook(this.target);
resolver.getHook(this.source).tapAsync("UnsafeCachePlugin", (request, resolveContext, callback) => {
if(!this.filterPredicate(request)) return callback();
const cacheId = getCacheId(request, this.withContext);
const cacheEntry = this.cache[cacheId];
if(cacheEntry) {
return callback(null, cacheEntry);
}
resolver.doResolve(target, request, null, resolveContext, (err, result) => {
if(err) return callback(err);
if(result) return callback(null, this.cache[cacheId] = result);
callback();
resolver
.getHook(this.source)
.tapAsync("UnsafeCachePlugin", (request, resolveContext, callback) => {
if (!this.filterPredicate(request)) return callback();
const cacheId = getCacheId(request, this.withContext);
const cacheEntry = this.cache[cacheId];
if (cacheEntry) {
return callback(null, cacheEntry);
}
resolver.doResolve(
target,
request,
null,
resolveContext,
(err, result) => {
if (err) return callback(err);
if (result) return callback(null, (this.cache[cacheId] = result));
callback();
}
);
});
});
}
};

@@ -16,11 +16,22 @@ /*

const target = resolver.ensureHook(this.target);
resolver.getHook(this.source).tapAsync("UseFilePlugin", (request, resolveContext, callback) => {
const filePath = resolver.join(request.path, this.filename);
const obj = Object.assign({}, request, {
path: filePath,
relativePath: request.relativePath && resolver.join(request.relativePath, this.filename)
resolver
.getHook(this.source)
.tapAsync("UseFilePlugin", (request, resolveContext, callback) => {
const filePath = resolver.join(request.path, this.filename);
const obj = {
...request,
path: filePath,
relativePath:
request.relativePath &&
resolver.join(request.relativePath, this.filename)
};
resolver.doResolve(
target,
obj,
"using path: " + filePath,
resolveContext,
callback
);
});
resolver.doResolve(target, obj, "using path: " + filePath, resolveContext, callback);
});
}
};
{
"name": "enhanced-resolve",
"version": "4.1.0",
"version": "5.0.0-beta.0",
"author": "Tobias Koppers @sokra",

@@ -11,5 +11,4 @@ "description": "Offers a async require.resolve function. It's highly configurable.",

"dependencies": {
"graceful-fs": "^4.1.2",
"memory-fs": "^0.4.0",
"tapable": "^1.0.0"
"graceful-fs": "^4.2.0",
"tapable": "^2.0.0-beta"
},

@@ -23,15 +22,16 @@ "licenses": [

"devDependencies": {
"beautify-lint": "^1.0.3",
"codecov.io": "^0.1.6",
"coveralls": "^2.11.6",
"eslint": "^3.14.1",
"eslint-plugin-node": "^3.0.5",
"eslint-plugin-nodeca": "^1.0.3",
"istanbul": "^0.4.1",
"js-beautify": "^1.5.10",
"mocha": "^2.3.4",
"eslint": "^5.9.0",
"eslint-config-prettier": "^3.3.0",
"eslint-plugin-node": "^8.0.0",
"eslint-plugin-prettier": "^3.0.0",
"husky": "^1.2.0",
"lint-staged": "^8.1.0",
"memfs": "^2.15.4",
"mocha": "^6.1.4",
"nyc": "^14.1.1",
"prettier": "^1.15.2",
"should": "^8.0.2"
},
"engines": {
"node": ">=6.9.0"
"node": ">=8.9.0"
},

@@ -41,11 +41,21 @@ "main": "lib/node.js",

"scripts": {
"beautify-lint": "beautify-lint lib/**.js test/*.js",
"beautify": "beautify-rewrite lib/**.js test/*.js",
"lint": "eslint lib test",
"pretest": "npm run lint && npm run beautify-lint",
"pretty": "prettier --loglevel warn --write \"{lib,test}/**/*.{js,json}\"",
"pretest": "yarn lint",
"test": "mocha --full-trace --check-leaks",
"precover": "npm run lint && npm run beautify-lint",
"cover": "istanbul cover node_modules/mocha/bin/_mocha",
"travis": "npm run cover -- --report lcovonly"
"precover": "yarn lint",
"cover": "nyc --reporter=html node node_modules/mocha/bin/_mocha",
"pretravis": "yarn lint",
"travis": "nyc --reporter=lcovonly node node_modules/mocha/bin/_mocha"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"*.js": [
"eslint --cache"
]
},
"repository": {

@@ -52,0 +62,0 @@ "type": "git",

@@ -7,9 +7,10 @@ # enhanced-resolve

* plugin system
* provide a custom filesystem
* sync and async node.js filesystems included
- plugin system
- provide a custom filesystem
- sync and async node.js filesystems included
## Getting Started
## Getting Started
### Install
```sh

@@ -22,17 +23,42 @@ # npm

### Resolve
There is a Node.js API which allows to resolve requests according to the Node.js resolving rules.
Sync and async APIs are offered. A `create` method allows to create a custom resolve function.
```js
const resolve = require("enhanced-resolve");
resolve("/some/path/to/folder", "module/dir", (err, result) => {
result; // === "/some/path/node_modules/module/dir/index.js"
});
resolve.sync("/some/path/to/folder", "../../dir");
// === "/some/path/dir/index.js"
const myResolve = resolve.create({
// or resolve.create.sync
extensions: [".ts", ".js"]
// see more options below
});
myResolve("/some/path/to/folder", "ts-module", (err, result) => {
result; // === "/some/node_modules/ts-module/index.ts"
});
```
### Creating a Resolver
The easiest way to create a resolver is to use the `createResolver` function on `ResolveFactory`, along with one of the supplied File System implementations.
```js
const {
NodeJsInputFileSystem,
CachedInputFileSystem,
ResolverFactory
} = require('enhanced-resolve');
const fs = require("fs");
const { CachedInputFileSystem, ResolverFactory } = require("enhanced-resolve");
// create a resolver
const myResolver = ResolverFactory.createResolver({
// Typical usage will consume the `NodeJsInputFileSystem` + `CachedInputFileSystem`, which wraps the Node.js `fs` wrapper to add resilience + caching.
fileSystem: new CachedInputFileSystem(new NodeJsInputFileSystem(), 4000),
extensions: ['.js', '.json']
/* any other resolver options here. Options/defaults can be seen below */
// Typical usage will consume the `fs` + `CachedInputFileSystem`, which wraps Node.js `fs` to add caching.
fileSystem: new CachedInputFileSystem(fs, 4000),
extensions: [".js", ".json"]
/* any other resolver options here. Options/defaults can be seen below */
});

@@ -43,52 +69,58 @@

const resolveContext = {};
const lookupStartPath = '/Users/webpack/some/root/dir';
const request = './path/to-look-up.js';
myResolver.resolve({}, lookupStartPath, request, resolveContext, (err/*Error*/, filepath/*string*/) => {
// Do something with the path
const lookupStartPath = "/Users/webpack/some/root/dir";
const request = "./path/to-look-up.js";
myResolver.resolve({}, lookupStartPath, request, resolveContext, (
err /*Error*/,
filepath /*string*/
) => {
// Do something with the path
});
```
For more examples creating different types resolvers (sync/async, context, etc) see `lib/node.js`.
#### Resolver Options
| Field | Default | Description |
| ------------------------ | --------------------------- | ---------------------------------------------------------------------------------- |
| alias | [] | A list of module alias configurations or an object which maps key to value |
| aliasFields | [] | A list of alias fields in description files |
| cacheWithContext | true | If unsafe cache is enabled, includes `request.context` in the cache key |
| descriptionFiles | ["package.json"] | A list of description files to read from |
| enforceExtension | false | Enforce that a extension from extensions must be used |
| enforceModuleExtension | false | Enforce that a extension from moduleExtensions must be used |
| extensions | [".js", ".json", ".node"] | A list of extensions which should be tried for files |
| mainFields | ["main"] | A list of main fields in description files |
| mainFiles | ["index"] | A list of main files in directories |
| modules | ["node_modules"] | A list of directories to resolve modules from, can be absolute path or folder name |
| unsafeCache | false | Use this cache object to unsafely cache the successful requests |
| plugins | [] | A list of additional resolve plugins which should be applied |
| symlinks | true | Whether to resolve symlinks to their symlinked location |
| cachePredicate | function() { return true }; | A function which decides whether a request should be cached or not. An object is passed to the function with `path` and `request` properties. |
| moduleExtensions | [] | A list of module extensions which should be tried for modules |
| resolveToContext | false | Resolve to a context instead of a file |
| fileSystem | | The file system which should be used |
| resolver | undefined | A prepared Resolver to which the plugins are attached |
| Field | Default | Description |
| ---------------- | --------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| alias | [] | A list of module alias configurations or an object which maps key to value |
| aliasFields | [] | A list of alias fields in description files |
| cacheWithContext | true | If unsafe cache is enabled, includes `request.context` in the cache key |
| descriptionFiles | ["package.json"] | A list of description files to read from |
| enforceExtension | false | Enforce that a extension from extensions must be used |
| extensions | [".js", ".json", ".node"] | A list of extensions which should be tried for files |
| mainFields | ["main"] | A list of main fields in description files |
| mainFiles | ["index"] | A list of main files in directories |
| modules | ["node_modules"] | A list of directories to resolve modules from, can be absolute path or folder name |
| unsafeCache | false | Use this cache object to unsafely cache the successful requests |
| plugins | [] | A list of additional resolve plugins which should be applied |
| symlinks | true | Whether to resolve symlinks to their symlinked location |
| cachePredicate | function() { return true }; | A function which decides whether a request should be cached or not. An object is passed to the function with `path` and `request` properties. |
| resolveToContext | false | Resolve to a context instead of a file |
| fileSystem | | The file system which should be used |
| resolver | undefined | A prepared Resolver to which the plugins are attached |
## Plugins
Similar to `webpack`, the core of `enhanced-resolve` functionality is implemented as individual plugins that are executed using [`Tapable`](https://github.com/webpack/tapable). These plugins can extend the functionality of the library, adding other ways for files/contexts to be resolved.
Similar to `webpack`, the core of `enhanced-resolve` functionality is implemented as individual plugins that are executed using [`tapable`](https://github.com/webpack/tapable).
These plugins can extend the functionality of the library, adding other ways for files/contexts to be resolved.
A plugin should be a `class` (or its ES5 equivalent) with an `apply` method. The `apply` method will receive a `resolver` instance, that can be used to hook in to the event system.
### Plugin Boilerplate
```js
class MyResolverPlugin {
constructor(source, target) {
this.source = source;
this.target = target;
}
constructor(source, target) {
this.source = source;
this.target = target;
}
apply(resolver) {
const target = resolver.ensureHook(this.target);
resolver.getHook(this.source).tapAsync("MyResolverPlugin", (request, resolveContext, callback) => {
// Any logic you need to create a new `request` can go here
resolver.doResolve(target, request, null, resolveContext, callback);
});
}
apply(resolver) {
const target = resolver.ensureHook(this.target);
resolver
.getHook(this.source)
.tapAsync("MyResolverPlugin", (request, resolveContext, callback) => {
// Any logic you need to create a new `request` can go here
resolver.doResolve(target, request, null, resolveContext, callback);
});
}
}

@@ -101,3 +133,3 @@ ```

``` javascript
```javascript
npm test

@@ -108,4 +140,4 @@ ```

## Passing options from webpack
## Passing options from webpack
If you are using `webpack`, and you want to pass custom options to `enhanced-resolve`, the options are passed from the `resolve` key of your webpack configuration e.g.:

@@ -115,4 +147,4 @@

resolve: {
extensions: ['', '.js', '.jsx'],
modules: ['src', 'node_modules'],
extensions: ['.js', '.jsx'],
modules: [path.resolve(__dirname, 'src'), 'node_modules'],
plugins: [new DirectoryNamedWebpackPlugin()]

@@ -125,4 +157,4 @@ ...

Copyright (c) 2012-2016 Tobias Koppers
Copyright (c) 2012-2019 JS Foundation and other contributors
MIT (http://www.opensource.org/licenses/mit-license.php)

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc