MultiStats.js 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const identifierUtils = require("./util/identifier");
  7. /** @typedef {import("../declarations/WebpackOptions").StatsOptions} StatsOptions */
  8. /** @typedef {import("./Stats")} Stats */
  9. /** @typedef {import("./stats/DefaultStatsFactoryPlugin").KnownStatsCompilation} KnownStatsCompilation */
  10. /** @typedef {import("./stats/DefaultStatsFactoryPlugin").StatsCompilation} StatsCompilation */
  11. const indent = (str, prefix) => {
  12. const rem = str.replace(/\n([^\n])/g, "\n" + prefix + "$1");
  13. return prefix + rem;
  14. };
  15. class MultiStats {
  16. /**
  17. * @param {Stats[]} stats the child stats
  18. */
  19. constructor(stats) {
  20. this.stats = stats;
  21. }
  22. get hash() {
  23. return this.stats.map(stat => stat.hash).join("");
  24. }
  25. /**
  26. * @returns {boolean} true if a child compilation encountered an error
  27. */
  28. hasErrors() {
  29. return this.stats.some(stat => stat.hasErrors());
  30. }
  31. /**
  32. * @returns {boolean} true if a child compilation had a warning
  33. */
  34. hasWarnings() {
  35. return this.stats.some(stat => stat.hasWarnings());
  36. }
  37. _createChildOptions(options, context) {
  38. if (!options) {
  39. options = {};
  40. }
  41. const { children: childrenOptions = undefined, ...baseOptions } =
  42. typeof options === "string" ? { preset: options } : options;
  43. const children = this.stats.map((stat, idx) => {
  44. const childOptions = Array.isArray(childrenOptions)
  45. ? childrenOptions[idx]
  46. : childrenOptions;
  47. return stat.compilation.createStatsOptions(
  48. {
  49. ...baseOptions,
  50. ...(typeof childOptions === "string"
  51. ? { preset: childOptions }
  52. : childOptions && typeof childOptions === "object"
  53. ? childOptions
  54. : undefined)
  55. },
  56. context
  57. );
  58. });
  59. return {
  60. version: children.every(o => o.version),
  61. hash: children.every(o => o.hash),
  62. errorsCount: children.every(o => o.errorsCount),
  63. warningsCount: children.every(o => o.warningsCount),
  64. errors: children.every(o => o.errors),
  65. warnings: children.every(o => o.warnings),
  66. children
  67. };
  68. }
  69. /**
  70. * @param {any} options stats options
  71. * @returns {StatsCompilation} json output
  72. */
  73. toJson(options) {
  74. options = this._createChildOptions(options, { forToString: false });
  75. /** @type {KnownStatsCompilation} */
  76. const obj = {};
  77. obj.children = this.stats.map((stat, idx) => {
  78. const obj = stat.toJson(options.children[idx]);
  79. const compilationName = stat.compilation.name;
  80. const name =
  81. compilationName &&
  82. identifierUtils.makePathsRelative(
  83. options.context,
  84. compilationName,
  85. stat.compilation.compiler.root
  86. );
  87. obj.name = name;
  88. return obj;
  89. });
  90. if (options.version) {
  91. obj.version = obj.children[0].version;
  92. }
  93. if (options.hash) {
  94. obj.hash = obj.children.map(j => j.hash).join("");
  95. }
  96. const mapError = (j, obj) => {
  97. return {
  98. ...obj,
  99. compilerPath: obj.compilerPath
  100. ? `${j.name}.${obj.compilerPath}`
  101. : j.name
  102. };
  103. };
  104. if (options.errors) {
  105. obj.errors = [];
  106. for (const j of obj.children) {
  107. for (const i of j.errors) {
  108. obj.errors.push(mapError(j, i));
  109. }
  110. }
  111. }
  112. if (options.warnings) {
  113. obj.warnings = [];
  114. for (const j of obj.children) {
  115. for (const i of j.warnings) {
  116. obj.warnings.push(mapError(j, i));
  117. }
  118. }
  119. }
  120. if (options.errorsCount) {
  121. obj.errorsCount = 0;
  122. for (const j of obj.children) {
  123. obj.errorsCount += j.errorsCount;
  124. }
  125. }
  126. if (options.warningsCount) {
  127. obj.warningsCount = 0;
  128. for (const j of obj.children) {
  129. obj.warningsCount += j.warningsCount;
  130. }
  131. }
  132. return obj;
  133. }
  134. toString(options) {
  135. options = this._createChildOptions(options, { forToString: true });
  136. const results = this.stats.map((stat, idx) => {
  137. const str = stat.toString(options.children[idx]);
  138. const compilationName = stat.compilation.name;
  139. const name =
  140. compilationName &&
  141. identifierUtils
  142. .makePathsRelative(
  143. options.context,
  144. compilationName,
  145. stat.compilation.compiler.root
  146. )
  147. .replace(/\|/g, " ");
  148. if (!str) return str;
  149. return name ? `${name}:\n${indent(str, " ")}` : str;
  150. });
  151. return results.filter(Boolean).join("\n\n");
  152. }
  153. }
  154. module.exports = MultiStats;