flecks/packages/core/build/resolve.js
2024-01-31 15:57:11 -06:00

73 lines
2.0 KiB
JavaScript

const {resolve: resolvePath} = require('path');
const D = require('./debug');
const debug = D('@flecks/core/build/resolve');
module.exports = function resolve({alias, fallback}, stubs) {
debug('installing resolution magic');
const {Module} = require('module');
// eslint-disable-next-line no-underscore-dangle
Module._initPaths();
const {require: Mr} = Module.prototype;
function preprocessMatchers(matchers) {
return Object.entries(matchers)
.map(([from, to]) => {
if (false === to) {
stubs.push(from);
return undefined;
}
if (from.endsWith('$')) {
return {
exact: true,
from: from.slice(0, -1),
to,
};
}
return {
exact: false,
from,
to,
};
})
.filter((entry) => entry);
}
function match(path, request, matchers) {
for (let i = 0; i < matchers.length; ++i) {
const {exact, from, to} = matchers[i];
const resolvedFrom = resolvePath(path, from);
const resolvedTo = resolvePath(path, to);
if (exact) {
if (resolvedFrom === request) {
return request.replace(resolvedFrom, resolvedTo);
}
}
else if (request.startsWith(resolvedFrom)) {
return request.replace(resolvedFrom, resolvedTo);
}
}
return undefined;
}
const aliases = preprocessMatchers(alias, stubs);
const fallbacks = preprocessMatchers(fallback, stubs);
Module.prototype.require = function flecksResolutionMagic(request, options) {
for (let i = 0; i < stubs.length; ++i) {
if (request.startsWith(stubs[i])) {
return undefined;
}
}
const qualified = resolvePath(this.path, request);
let resolved = match(this.path, qualified, aliases);
if (!resolved) {
resolved = match(this.path, qualified, fallbacks);
}
if (!resolved) {
resolved = request;
}
return Mr.call(this, resolved, options);
};
return () => {
Module.prototype.require = Mr;
};
};