AliasFieldPlugin.js 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const DescriptionFileUtils = require("./DescriptionFileUtils");
  7. const getInnerRequest = require("./getInnerRequest");
  8. /** @typedef {import("./Resolver")} Resolver */
  9. /** @typedef {import("./Resolver").JsonPrimitive} JsonPrimitive */
  10. /** @typedef {import("./Resolver").ResolveRequest} ResolveRequest */
  11. /** @typedef {import("./Resolver").ResolveStepHook} ResolveStepHook */
  12. module.exports = class AliasFieldPlugin {
  13. /**
  14. * @param {string | ResolveStepHook} source source
  15. * @param {string | Array<string>} field field
  16. * @param {string | ResolveStepHook} target target
  17. */
  18. constructor(source, field, target) {
  19. this.source = source;
  20. this.field = field;
  21. this.target = target;
  22. }
  23. /**
  24. * @param {Resolver} resolver the resolver
  25. * @returns {void}
  26. */
  27. apply(resolver) {
  28. const target = resolver.ensureHook(this.target);
  29. resolver
  30. .getHook(this.source)
  31. .tapAsync("AliasFieldPlugin", (request, resolveContext, callback) => {
  32. if (!request.descriptionFileData) return callback();
  33. const innerRequest = getInnerRequest(resolver, request);
  34. if (!innerRequest) return callback();
  35. const fieldData = DescriptionFileUtils.getField(
  36. request.descriptionFileData,
  37. this.field
  38. );
  39. if (fieldData === null || typeof fieldData !== "object") {
  40. if (resolveContext.log)
  41. resolveContext.log(
  42. "Field '" +
  43. this.field +
  44. "' doesn't contain a valid alias configuration"
  45. );
  46. return callback();
  47. }
  48. /** @type {JsonPrimitive | undefined} */
  49. const data = Object.prototype.hasOwnProperty.call(
  50. fieldData,
  51. innerRequest
  52. )
  53. ? /** @type {{[Key in string]: JsonPrimitive}} */ (fieldData)[
  54. innerRequest
  55. ]
  56. : innerRequest.startsWith("./")
  57. ? /** @type {{[Key in string]: JsonPrimitive}} */ (fieldData)[
  58. innerRequest.slice(2)
  59. ]
  60. : undefined;
  61. if (data === innerRequest) return callback();
  62. if (data === undefined) return callback();
  63. if (data === false) {
  64. /** @type {ResolveRequest} */
  65. const ignoreObj = {
  66. ...request,
  67. path: false
  68. };
  69. if (typeof resolveContext.yield === "function") {
  70. resolveContext.yield(ignoreObj);
  71. return callback(null, null);
  72. }
  73. return callback(null, ignoreObj);
  74. }
  75. /** @type {ResolveRequest} */
  76. const obj = {
  77. ...request,
  78. path: /** @type {string} */ (request.descriptionFileRoot),
  79. request: /** @type {string} */ (data),
  80. fullySpecified: false
  81. };
  82. resolver.doResolve(
  83. target,
  84. obj,
  85. "aliased from description file " +
  86. request.descriptionFilePath +
  87. " with mapping '" +
  88. innerRequest +
  89. "' to '" +
  90. /** @type {string} */ (data) +
  91. "'",
  92. resolveContext,
  93. (err, result) => {
  94. if (err) return callback(err);
  95. // Don't allow other aliasing or raw request
  96. if (result === undefined) return callback(null, null);
  97. callback(null, result);
  98. }
  99. );
  100. });
  101. }
  102. };