215 lines
7.9 KiB
JavaScript
215 lines
7.9 KiB
JavaScript
|
/**
|
||
|
* This webpack resolver is largely based on TypeScript's "paths" handling
|
||
|
* The TypeScript license can be found here:
|
||
|
* https://github.com/microsoft/TypeScript/blob/214df64e287804577afa1fea0184c18c40f7d1ca/LICENSE.txt
|
||
|
*/ "use strict";
|
||
|
Object.defineProperty(exports, "__esModule", {
|
||
|
value: true
|
||
|
});
|
||
|
0 && (module.exports = {
|
||
|
hasZeroOrOneAsteriskCharacter: null,
|
||
|
pathIsRelative: null,
|
||
|
tryParsePattern: null,
|
||
|
findBestPatternMatch: null,
|
||
|
matchPatternOrExact: null,
|
||
|
isString: null,
|
||
|
matchedText: null,
|
||
|
patternText: null,
|
||
|
JsConfigPathsPlugin: null
|
||
|
});
|
||
|
function _export(target, all) {
|
||
|
for(var name in all)Object.defineProperty(target, name, {
|
||
|
enumerable: true,
|
||
|
get: all[name]
|
||
|
});
|
||
|
}
|
||
|
_export(exports, {
|
||
|
hasZeroOrOneAsteriskCharacter: function() {
|
||
|
return hasZeroOrOneAsteriskCharacter;
|
||
|
},
|
||
|
pathIsRelative: function() {
|
||
|
return pathIsRelative;
|
||
|
},
|
||
|
tryParsePattern: function() {
|
||
|
return tryParsePattern;
|
||
|
},
|
||
|
findBestPatternMatch: function() {
|
||
|
return findBestPatternMatch;
|
||
|
},
|
||
|
matchPatternOrExact: function() {
|
||
|
return matchPatternOrExact;
|
||
|
},
|
||
|
isString: function() {
|
||
|
return isString;
|
||
|
},
|
||
|
matchedText: function() {
|
||
|
return matchedText;
|
||
|
},
|
||
|
patternText: function() {
|
||
|
return patternText;
|
||
|
},
|
||
|
JsConfigPathsPlugin: function() {
|
||
|
return JsConfigPathsPlugin;
|
||
|
}
|
||
|
});
|
||
|
const _path = /*#__PURE__*/ _interop_require_default(require("path"));
|
||
|
const _debug = require("next/dist/compiled/debug");
|
||
|
function _interop_require_default(obj) {
|
||
|
return obj && obj.__esModule ? obj : {
|
||
|
default: obj
|
||
|
};
|
||
|
}
|
||
|
const log = (0, _debug.debug)("next:jsconfig-paths-plugin");
|
||
|
const asterisk = 0x2a;
|
||
|
function hasZeroOrOneAsteriskCharacter(str) {
|
||
|
let seenAsterisk = false;
|
||
|
for(let i = 0; i < str.length; i++){
|
||
|
if (str.charCodeAt(i) === asterisk) {
|
||
|
if (!seenAsterisk) {
|
||
|
seenAsterisk = true;
|
||
|
} else {
|
||
|
// have already seen asterisk
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
function pathIsRelative(testPath) {
|
||
|
return /^\.\.?($|[\\/])/.test(testPath);
|
||
|
}
|
||
|
function tryParsePattern(pattern) {
|
||
|
// This should be verified outside of here and a proper error thrown.
|
||
|
const indexOfStar = pattern.indexOf("*");
|
||
|
return indexOfStar === -1 ? undefined : {
|
||
|
prefix: pattern.slice(0, indexOfStar),
|
||
|
suffix: pattern.slice(indexOfStar + 1)
|
||
|
};
|
||
|
}
|
||
|
function isPatternMatch({ prefix, suffix }, candidate) {
|
||
|
return candidate.length >= prefix.length + suffix.length && candidate.startsWith(prefix) && candidate.endsWith(suffix);
|
||
|
}
|
||
|
function findBestPatternMatch(values, getPattern, candidate) {
|
||
|
let matchedValue;
|
||
|
// use length of prefix as betterness criteria
|
||
|
let longestMatchPrefixLength = -1;
|
||
|
for (const v of values){
|
||
|
const pattern = getPattern(v);
|
||
|
if (isPatternMatch(pattern, candidate) && pattern.prefix.length > longestMatchPrefixLength) {
|
||
|
longestMatchPrefixLength = pattern.prefix.length;
|
||
|
matchedValue = v;
|
||
|
}
|
||
|
}
|
||
|
return matchedValue;
|
||
|
}
|
||
|
function matchPatternOrExact(patternStrings, candidate) {
|
||
|
const patterns = [];
|
||
|
for (const patternString of patternStrings){
|
||
|
if (!hasZeroOrOneAsteriskCharacter(patternString)) continue;
|
||
|
const pattern = tryParsePattern(patternString);
|
||
|
if (pattern) {
|
||
|
patterns.push(pattern);
|
||
|
} else if (patternString === candidate) {
|
||
|
// pattern was matched as is - no need to search further
|
||
|
return patternString;
|
||
|
}
|
||
|
}
|
||
|
return findBestPatternMatch(patterns, (_)=>_, candidate);
|
||
|
}
|
||
|
function isString(text) {
|
||
|
return typeof text === "string";
|
||
|
}
|
||
|
function matchedText(pattern, candidate) {
|
||
|
return candidate.substring(pattern.prefix.length, candidate.length - pattern.suffix.length);
|
||
|
}
|
||
|
function patternText({ prefix, suffix }) {
|
||
|
return `${prefix}*${suffix}`;
|
||
|
}
|
||
|
/**
|
||
|
* Calls the iterator function for each entry of the array
|
||
|
* until the first result or error is reached
|
||
|
*/ function forEachBail(array, iterator, callback) {
|
||
|
if (array.length === 0) return callback();
|
||
|
let i = 0;
|
||
|
const next = ()=>{
|
||
|
let loop = undefined;
|
||
|
iterator(array[i++], (err, result)=>{
|
||
|
if (err || result !== undefined || i >= array.length) {
|
||
|
return callback(err, result);
|
||
|
}
|
||
|
if (loop === false) while(next());
|
||
|
loop = true;
|
||
|
});
|
||
|
if (!loop) loop = false;
|
||
|
return loop;
|
||
|
};
|
||
|
while(next());
|
||
|
}
|
||
|
const NODE_MODULES_REGEX = /node_modules/;
|
||
|
class JsConfigPathsPlugin {
|
||
|
constructor(paths, resolvedBaseUrl){
|
||
|
this.paths = paths;
|
||
|
this.resolvedBaseUrl = resolvedBaseUrl;
|
||
|
this.jsConfigPlugin = true;
|
||
|
log("tsconfig.json or jsconfig.json paths: %O", paths);
|
||
|
log("resolved baseUrl: %s", resolvedBaseUrl);
|
||
|
}
|
||
|
apply(resolver) {
|
||
|
const target = resolver.ensureHook("resolve");
|
||
|
resolver.getHook("described-resolve").tapAsync("JsConfigPathsPlugin", (request, resolveContext, callback)=>{
|
||
|
const paths = this.paths;
|
||
|
const pathsKeys = Object.keys(paths);
|
||
|
// If no aliases are added bail out
|
||
|
if (pathsKeys.length === 0) {
|
||
|
log("paths are empty, bailing out");
|
||
|
return callback();
|
||
|
}
|
||
|
const moduleName = request.request;
|
||
|
// Exclude node_modules from paths support (speeds up resolving)
|
||
|
if (request.path.match(NODE_MODULES_REGEX)) {
|
||
|
log("skipping request as it is inside node_modules %s", moduleName);
|
||
|
return callback();
|
||
|
}
|
||
|
if (_path.default.posix.isAbsolute(moduleName) || process.platform === "win32" && _path.default.win32.isAbsolute(moduleName)) {
|
||
|
log("skipping request as it is an absolute path %s", moduleName);
|
||
|
return callback();
|
||
|
}
|
||
|
if (pathIsRelative(moduleName)) {
|
||
|
log("skipping request as it is a relative path %s", moduleName);
|
||
|
return callback();
|
||
|
}
|
||
|
// log('starting to resolve request %s', moduleName)
|
||
|
// If the module name does not match any of the patterns in `paths` we hand off resolving to webpack
|
||
|
const matchedPattern = matchPatternOrExact(pathsKeys, moduleName);
|
||
|
if (!matchedPattern) {
|
||
|
log("moduleName did not match any paths pattern %s", moduleName);
|
||
|
return callback();
|
||
|
}
|
||
|
const matchedStar = isString(matchedPattern) ? undefined : matchedText(matchedPattern, moduleName);
|
||
|
const matchedPatternText = isString(matchedPattern) ? matchedPattern : patternText(matchedPattern);
|
||
|
let triedPaths = [];
|
||
|
forEachBail(paths[matchedPatternText], (subst, pathCallback)=>{
|
||
|
const curPath = matchedStar ? subst.replace("*", matchedStar) : subst;
|
||
|
// Ensure .d.ts is not matched
|
||
|
if (curPath.endsWith(".d.ts")) {
|
||
|
// try next path candidate
|
||
|
return pathCallback();
|
||
|
}
|
||
|
const candidate = _path.default.join(this.resolvedBaseUrl, curPath);
|
||
|
const obj = Object.assign({}, request, {
|
||
|
request: candidate
|
||
|
});
|
||
|
resolver.doResolve(target, obj, `Aliased with tsconfig.json or jsconfig.json ${matchedPatternText} to ${candidate}`, resolveContext, (resolverErr, resolverResult)=>{
|
||
|
if (resolverErr || resolverResult === undefined) {
|
||
|
triedPaths.push(candidate);
|
||
|
// try next path candidate
|
||
|
return pathCallback();
|
||
|
}
|
||
|
return pathCallback(resolverErr, resolverResult);
|
||
|
});
|
||
|
}, callback);
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//# sourceMappingURL=jsconfig-paths-plugin.js.map
|