/* MIT License http://www.opensource.org/licenses/mit-license.php Author Tobias Koppers @sokra */ "use strict"; const DescriptionFileUtils = require("./DescriptionFileUtils"); const getInnerRequest = require("./getInnerRequest"); /** @typedef {import("./Resolver")} Resolver */ /** @typedef {import("./Resolver").JsonPrimitive} JsonPrimitive */ /** @typedef {import("./Resolver").ResolveRequest} ResolveRequest */ /** @typedef {import("./Resolver").ResolveStepHook} ResolveStepHook */ module.exports = class AliasFieldPlugin { /** * @param {string | ResolveStepHook} source source * @param {string | Array} field field * @param {string | ResolveStepHook} target target */ constructor(source, field, target) { this.source = source; this.field = field; this.target = target; } /** * @param {Resolver} resolver the resolver * @returns {void} */ apply(resolver) { 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 (fieldData === null || typeof fieldData !== "object") { if (resolveContext.log) { resolveContext.log( `Field '${ this.field }' doesn't contain a valid alias configuration`, ); } return callback(); } /** @type {JsonPrimitive | undefined} */ const data = Object.prototype.hasOwnProperty.call( fieldData, innerRequest, ) ? /** @type {{[Key in string]: JsonPrimitive}} */ (fieldData)[ innerRequest ] : innerRequest.startsWith("./") ? /** @type {{[Key in string]: JsonPrimitive}} */ (fieldData)[ innerRequest.slice(2) ] : undefined; if (data === innerRequest) return callback(); if (data === undefined) return callback(); if (data === false) { /** @type {ResolveRequest} */ const ignoreObj = { ...request, path: false, }; if (typeof resolveContext.yield === "function") { resolveContext.yield(ignoreObj); return callback(null, null); } return callback(null, ignoreObj); } /** @type {ResolveRequest} */ const obj = { ...request, path: /** @type {string} */ (request.descriptionFileRoot), request: /** @type {string} */ (data), fullySpecified: false, }; resolver.doResolve( target, obj, `aliased from description file ${ request.descriptionFilePath } with mapping '${innerRequest}' to '${/** @type {string} */ 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); }, ); }); } };