DefaultStatsPrinterPlugin.js 57 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. /** @typedef {import("../Compiler")} Compiler */
  7. /** @typedef {import("../logging/Logger").LogTypeEnum} LogTypeEnum */
  8. /** @typedef {import("./DefaultStatsFactoryPlugin").ChunkId} ChunkId */
  9. /** @typedef {import("./DefaultStatsFactoryPlugin").ChunkName} ChunkName */
  10. /** @typedef {import("./DefaultStatsFactoryPlugin").KnownStatsAsset} KnownStatsAsset */
  11. /** @typedef {import("./DefaultStatsFactoryPlugin").KnownStatsAssetChunk} KnownStatsAssetChunk */
  12. /** @typedef {import("./DefaultStatsFactoryPlugin").KnownStatsAssetChunkIdHint} KnownStatsAssetChunkIdHint */
  13. /** @typedef {import("./DefaultStatsFactoryPlugin").KnownStatsAssetChunkName} KnownStatsAssetChunkName */
  14. /** @typedef {import("./DefaultStatsFactoryPlugin").KnownStatsChunk} KnownStatsChunk */
  15. /** @typedef {import("./DefaultStatsFactoryPlugin").KnownStatsChunkGroup} KnownStatsChunkGroup */
  16. /** @typedef {import("./DefaultStatsFactoryPlugin").KnownStatsChunkOrigin} KnownStatsChunkOrigin */
  17. /** @typedef {import("./DefaultStatsFactoryPlugin").KnownStatsCompilation} KnownStatsCompilation */
  18. /** @typedef {import("./DefaultStatsFactoryPlugin").KnownStatsError} KnownStatsError */
  19. /** @typedef {import("./DefaultStatsFactoryPlugin").KnownStatsLogging} KnownStatsLogging */
  20. /** @typedef {import("./DefaultStatsFactoryPlugin").KnownStatsLoggingEntry} KnownStatsLoggingEntry */
  21. /** @typedef {import("./DefaultStatsFactoryPlugin").KnownStatsModule} KnownStatsModule */
  22. /** @typedef {import("./DefaultStatsFactoryPlugin").KnownStatsModuleIssuer} KnownStatsModuleIssuer */
  23. /** @typedef {import("./DefaultStatsFactoryPlugin").KnownStatsModuleReason} KnownStatsModuleReason */
  24. /** @typedef {import("./DefaultStatsFactoryPlugin").KnownStatsModuleTraceDependency} KnownStatsModuleTraceDependency */
  25. /** @typedef {import("./DefaultStatsFactoryPlugin").KnownStatsModuleTraceItem} KnownStatsModuleTraceItem */
  26. /** @typedef {import("./DefaultStatsFactoryPlugin").KnownStatsProfile} KnownStatsProfile */
  27. /** @typedef {import("./DefaultStatsFactoryPlugin").StatsCompilation} StatsCompilation */
  28. /** @typedef {import("./StatsPrinter")} StatsPrinter */
  29. /** @typedef {import("./StatsPrinter").ColorFunction} ColorFunction */
  30. /** @typedef {import("./StatsPrinter").KnownStatsPrinterColorFunctions} KnownStatsPrinterColorFunctions */
  31. /** @typedef {import("./StatsPrinter").KnownStatsPrinterContext} KnownStatsPrinterContext */
  32. /** @typedef {import("./StatsPrinter").KnownStatsPrinterFormatters} KnownStatsPrinterFormatters */
  33. /** @typedef {import("./StatsPrinter").StatsPrinterContext} StatsPrinterContext */
  34. /** @typedef {import("./StatsPrinter").StatsPrinterContextWithExtra} StatsPrinterContextWithExtra */
  35. const DATA_URI_CONTENT_LENGTH = 16;
  36. const MAX_MODULE_IDENTIFIER_LENGTH = 80;
  37. /**
  38. * @param {number} n a number
  39. * @param {string} singular singular
  40. * @param {string} plural plural
  41. * @returns {string} if n is 1, singular, else plural
  42. */
  43. const plural = (n, singular, plural) => (n === 1 ? singular : plural);
  44. /**
  45. * @param {Record<string, number>} sizes sizes by source type
  46. * @param {StatsPrinterContext} options options
  47. * @returns {string | undefined} text
  48. */
  49. const printSizes = (sizes, { formatSize = n => `${n}` }) => {
  50. const keys = Object.keys(sizes);
  51. if (keys.length > 1) {
  52. return keys.map(key => `${formatSize(sizes[key])} (${key})`).join(" ");
  53. } else if (keys.length === 1) {
  54. return formatSize(sizes[keys[0]]);
  55. }
  56. };
  57. /**
  58. * @param {string | null} resource resource
  59. * @returns {string} resource name for display
  60. */
  61. const getResourceName = resource => {
  62. if (!resource) return "";
  63. const dataUrl = /^data:[^,]+,/.exec(resource);
  64. if (!dataUrl) return resource;
  65. const len = dataUrl[0].length + DATA_URI_CONTENT_LENGTH;
  66. if (resource.length < len) return resource;
  67. return `${resource.slice(
  68. 0,
  69. Math.min(resource.length - /* '..'.length */ 2, len)
  70. )}..`;
  71. };
  72. /**
  73. * @param {string} name module name
  74. * @returns {[string,string]} prefix and module name
  75. */
  76. const getModuleName = name => {
  77. const [, prefix, resource] =
  78. /** @type {[string, string, string]} */
  79. (/** @type {unknown} */ (/^(.*!)?([^!]*)$/.exec(name)));
  80. if (resource.length > MAX_MODULE_IDENTIFIER_LENGTH) {
  81. const truncatedResource = `${resource.slice(
  82. 0,
  83. Math.min(
  84. resource.length - /* '...(truncated)'.length */ 14,
  85. MAX_MODULE_IDENTIFIER_LENGTH
  86. )
  87. )}...(truncated)`;
  88. return [prefix, getResourceName(truncatedResource)];
  89. }
  90. return [prefix, getResourceName(resource)];
  91. };
  92. /**
  93. * @param {string} str string
  94. * @param {(item: string) => string} fn function to apply to each line
  95. * @returns {string} joined string
  96. */
  97. const mapLines = (str, fn) => str.split("\n").map(fn).join("\n");
  98. /**
  99. * @param {number} n a number
  100. * @returns {string} number as two digit string, leading 0
  101. */
  102. const twoDigit = n => (n >= 10 ? `${n}` : `0${n}`);
  103. /**
  104. * @param {string | number | null} id an id
  105. * @returns {id is string | number} is i
  106. */
  107. const isValidId = id => {
  108. if (typeof id === "number" || id) {
  109. return true;
  110. }
  111. return false;
  112. };
  113. /**
  114. * @template T
  115. * @param {Array<T> | undefined} list of items
  116. * @param {number} count number of items to show
  117. * @returns {string} string representation of list
  118. */
  119. const moreCount = (list, count) =>
  120. list && list.length > 0 ? `+ ${count}` : `${count}`;
  121. /**
  122. * @template T
  123. * @template {keyof T} K
  124. * @typedef {{ [P in K]-?: T[P] }} WithRequired
  125. */
  126. /**
  127. * @template {keyof StatsPrinterContext} RequiredStatsPrinterContextKeys
  128. * @typedef {StatsPrinterContextWithExtra & WithRequired<StatsPrinterContext, "compilation" | RequiredStatsPrinterContextKeys>} DefineStatsPrinterContext
  129. */
  130. /**
  131. * @template T
  132. * @template {keyof StatsPrinterContext} RequiredStatsPrinterContextKeys
  133. * @typedef {(thing: Exclude<T, undefined>, context: DefineStatsPrinterContext<RequiredStatsPrinterContextKeys>, printer: StatsPrinter) => string | undefined} SimplePrinter
  134. */
  135. /**
  136. * @template T
  137. * @typedef {T extends (infer U)[] ? U : T} Unpacked
  138. */
  139. /**
  140. * @template {object} O
  141. * @template {keyof O} K
  142. * @template {string} B
  143. * @typedef {K extends string ? Exclude<O[K], undefined> extends EXPECTED_ANY[] ? never : `${B}.${K}` : never} PropertyName
  144. */
  145. /**
  146. * @template {object} O
  147. * @template {keyof O} K
  148. * @template {string} B
  149. * @typedef {K extends string ? NonNullable<O[K]> extends EXPECTED_ANY[] ? `${B}.${K}[]` : never : never} ArrayPropertyName
  150. */
  151. /**
  152. * @template {object} O
  153. * @template {keyof O} K
  154. * @template {string} B
  155. * @typedef {K extends string ? Exclude<O[K], undefined> extends EXPECTED_ANY[] ? `${B}.${K}` : never : never} MultiplePropertyName
  156. */
  157. /**
  158. * @template {object} O
  159. * @template {string} K
  160. * @template {string} E
  161. * @typedef {{ [property in `${K}!`]?: SimplePrinter<O, "compilation" | E> }} Exclamation
  162. */
  163. /**
  164. * @template {object} O
  165. * @template {string} B
  166. * @template {string} [R=B]
  167. * @typedef {{ [K in keyof O as PropertyName<O, K, B>]?: SimplePrinter<O[K], R> } &
  168. * { [K in keyof O as ArrayPropertyName<O, K, B>]?: Exclude<O[K], undefined> extends (infer I)[] ? SimplePrinter<I, R> : never } &
  169. * { [K in keyof O as MultiplePropertyName<O, K, B>]?: SimplePrinter<O[K], R> }
  170. * } Printers
  171. */
  172. /**
  173. * @typedef {Printers<KnownStatsCompilation, "compilation"> &
  174. * { ["compilation.summary!"]?: SimplePrinter<KnownStatsCompilation, "compilation"> } &
  175. * { ["compilation.errorsInChildren!"]?: SimplePrinter<KnownStatsCompilation, "compilation"> } &
  176. * { ["compilation.warningsInChildren!"]?: SimplePrinter<KnownStatsCompilation, "compilation"> }} CompilationSimplePrinters
  177. */
  178. /**
  179. * @type {CompilationSimplePrinters}
  180. */
  181. const COMPILATION_SIMPLE_PRINTERS = {
  182. "compilation.summary!": (
  183. _,
  184. {
  185. type,
  186. bold,
  187. green,
  188. red,
  189. yellow,
  190. formatDateTime,
  191. formatTime,
  192. compilation: {
  193. name,
  194. hash,
  195. version,
  196. time,
  197. builtAt,
  198. errorsCount,
  199. warningsCount
  200. }
  201. }
  202. ) => {
  203. const root = type === "compilation.summary!";
  204. const warningsMessage =
  205. /** @type {number} */ (warningsCount) > 0
  206. ? yellow(
  207. `${warningsCount} ${plural(/** @type {number} */ (warningsCount), "warning", "warnings")}`
  208. )
  209. : "";
  210. const errorsMessage =
  211. /** @type {number} */ (errorsCount) > 0
  212. ? red(
  213. `${errorsCount} ${plural(/** @type {number} */ (errorsCount), "error", "errors")}`
  214. )
  215. : "";
  216. const timeMessage = root && time ? ` in ${formatTime(time)}` : "";
  217. const hashMessage = hash ? ` (${hash})` : "";
  218. const builtAtMessage =
  219. root && builtAt ? `${formatDateTime(builtAt)}: ` : "";
  220. const versionMessage = root && version ? `webpack ${version}` : "";
  221. const nameMessage =
  222. root && name
  223. ? bold(name)
  224. : name
  225. ? `Child ${bold(name)}`
  226. : root
  227. ? ""
  228. : "Child";
  229. const subjectMessage =
  230. nameMessage && versionMessage
  231. ? `${nameMessage} (${versionMessage})`
  232. : versionMessage || nameMessage || "webpack";
  233. let statusMessage;
  234. if (errorsMessage && warningsMessage) {
  235. statusMessage = `compiled with ${errorsMessage} and ${warningsMessage}`;
  236. } else if (errorsMessage) {
  237. statusMessage = `compiled with ${errorsMessage}`;
  238. } else if (warningsMessage) {
  239. statusMessage = `compiled with ${warningsMessage}`;
  240. } else if (errorsCount === 0 && warningsCount === 0) {
  241. statusMessage = `compiled ${green("successfully")}`;
  242. } else {
  243. statusMessage = "compiled";
  244. }
  245. if (
  246. builtAtMessage ||
  247. versionMessage ||
  248. errorsMessage ||
  249. warningsMessage ||
  250. (errorsCount === 0 && warningsCount === 0) ||
  251. timeMessage ||
  252. hashMessage
  253. ) {
  254. return `${builtAtMessage}${subjectMessage} ${statusMessage}${timeMessage}${hashMessage}`;
  255. }
  256. },
  257. "compilation.filteredWarningDetailsCount": count =>
  258. count
  259. ? `${count} ${plural(
  260. count,
  261. "warning has",
  262. "warnings have"
  263. )} detailed information that is not shown.\nUse 'stats.errorDetails: true' resp. '--stats-error-details' to show it.`
  264. : undefined,
  265. "compilation.filteredErrorDetailsCount": (count, { yellow }) =>
  266. count
  267. ? yellow(
  268. `${count} ${plural(
  269. count,
  270. "error has",
  271. "errors have"
  272. )} detailed information that is not shown.\nUse 'stats.errorDetails: true' resp. '--stats-error-details' to show it.`
  273. )
  274. : undefined,
  275. "compilation.env": (env, { bold }) =>
  276. env
  277. ? `Environment (--env): ${bold(JSON.stringify(env, null, 2))}`
  278. : undefined,
  279. "compilation.publicPath": (publicPath, { bold }) =>
  280. `PublicPath: ${bold(publicPath || "(none)")}`,
  281. "compilation.entrypoints": (entrypoints, context, printer) =>
  282. Array.isArray(entrypoints)
  283. ? undefined
  284. : printer.print(context.type, Object.values(entrypoints), {
  285. ...context,
  286. chunkGroupKind: "Entrypoint"
  287. }),
  288. "compilation.namedChunkGroups": (namedChunkGroups, context, printer) => {
  289. if (!Array.isArray(namedChunkGroups)) {
  290. const {
  291. compilation: { entrypoints }
  292. } = context;
  293. let chunkGroups = Object.values(namedChunkGroups);
  294. if (entrypoints) {
  295. chunkGroups = chunkGroups.filter(
  296. group =>
  297. !Object.prototype.hasOwnProperty.call(
  298. entrypoints,
  299. /** @type {string} */
  300. (group.name)
  301. )
  302. );
  303. }
  304. return printer.print(context.type, chunkGroups, {
  305. ...context,
  306. chunkGroupKind: "Chunk Group"
  307. });
  308. }
  309. },
  310. "compilation.assetsByChunkName": () => "",
  311. "compilation.filteredModules": (
  312. filteredModules,
  313. { compilation: { modules } }
  314. ) =>
  315. filteredModules > 0
  316. ? `${moreCount(modules, filteredModules)} ${plural(
  317. filteredModules,
  318. "module",
  319. "modules"
  320. )}`
  321. : undefined,
  322. "compilation.filteredAssets": (
  323. filteredAssets,
  324. { compilation: { assets } }
  325. ) =>
  326. filteredAssets > 0
  327. ? `${moreCount(assets, filteredAssets)} ${plural(
  328. filteredAssets,
  329. "asset",
  330. "assets"
  331. )}`
  332. : undefined,
  333. "compilation.logging": (logging, context, printer) =>
  334. Array.isArray(logging)
  335. ? undefined
  336. : printer.print(
  337. context.type,
  338. Object.entries(logging).map(([name, value]) => ({ ...value, name })),
  339. context
  340. ),
  341. "compilation.warningsInChildren!": (_, { yellow, compilation }) => {
  342. if (
  343. !compilation.children &&
  344. /** @type {number} */ (compilation.warningsCount) > 0 &&
  345. compilation.warnings
  346. ) {
  347. const childWarnings =
  348. /** @type {number} */ (compilation.warningsCount) -
  349. compilation.warnings.length;
  350. if (childWarnings > 0) {
  351. return yellow(
  352. `${childWarnings} ${plural(
  353. childWarnings,
  354. "WARNING",
  355. "WARNINGS"
  356. )} in child compilations${
  357. compilation.children
  358. ? ""
  359. : " (Use 'stats.children: true' resp. '--stats-children' for more details)"
  360. }`
  361. );
  362. }
  363. }
  364. },
  365. "compilation.errorsInChildren!": (_, { red, compilation }) => {
  366. if (
  367. !compilation.children &&
  368. /** @type {number} */ (compilation.errorsCount) > 0 &&
  369. compilation.errors
  370. ) {
  371. const childErrors =
  372. /** @type {number} */ (compilation.errorsCount) -
  373. compilation.errors.length;
  374. if (childErrors > 0) {
  375. return red(
  376. `${childErrors} ${plural(
  377. childErrors,
  378. "ERROR",
  379. "ERRORS"
  380. )} in child compilations${
  381. compilation.children
  382. ? ""
  383. : " (Use 'stats.children: true' resp. '--stats-children' for more details)"
  384. }`
  385. );
  386. }
  387. }
  388. }
  389. };
  390. /**
  391. * @typedef {Printers<KnownStatsAsset, "asset"> &
  392. * Printers<KnownStatsAsset["info"], "asset.info"> &
  393. * Exclamation<KnownStatsAsset, "asset.separator", "asset"> &
  394. * { ["asset.filteredChildren"]?: SimplePrinter<number, "asset"> } &
  395. * { assetChunk?: SimplePrinter<KnownStatsAssetChunk, "asset"> } &
  396. * { assetChunkName?: SimplePrinter<KnownStatsAssetChunkName, "asset"> } &
  397. * { assetChunkIdHint?: SimplePrinter<KnownStatsAssetChunkIdHint, "asset"> }} AssetSimplePrinters
  398. */
  399. /** @type {AssetSimplePrinters} */
  400. const ASSET_SIMPLE_PRINTERS = {
  401. "asset.type": type => type,
  402. "asset.name": (name, { formatFilename, asset: { isOverSizeLimit } }) =>
  403. formatFilename(name, isOverSizeLimit),
  404. "asset.size": (size, { asset: { isOverSizeLimit }, yellow, formatSize }) =>
  405. isOverSizeLimit ? yellow(formatSize(size)) : formatSize(size),
  406. "asset.emitted": (emitted, { green, formatFlag }) =>
  407. emitted ? green(formatFlag("emitted")) : undefined,
  408. "asset.comparedForEmit": (comparedForEmit, { yellow, formatFlag }) =>
  409. comparedForEmit ? yellow(formatFlag("compared for emit")) : undefined,
  410. "asset.cached": (cached, { green, formatFlag }) =>
  411. cached ? green(formatFlag("cached")) : undefined,
  412. "asset.isOverSizeLimit": (isOverSizeLimit, { yellow, formatFlag }) =>
  413. isOverSizeLimit ? yellow(formatFlag("big")) : undefined,
  414. "asset.info.immutable": (immutable, { green, formatFlag }) =>
  415. immutable ? green(formatFlag("immutable")) : undefined,
  416. "asset.info.javascriptModule": (javascriptModule, { formatFlag }) =>
  417. javascriptModule ? formatFlag("javascript module") : undefined,
  418. "asset.info.sourceFilename": (sourceFilename, { formatFlag }) =>
  419. sourceFilename ? formatFlag(`from: ${sourceFilename}`) : undefined,
  420. "asset.info.development": (development, { green, formatFlag }) =>
  421. development ? green(formatFlag("dev")) : undefined,
  422. "asset.info.hotModuleReplacement": (
  423. hotModuleReplacement,
  424. { green, formatFlag }
  425. ) => (hotModuleReplacement ? green(formatFlag("hmr")) : undefined),
  426. "asset.separator!": () => "\n",
  427. "asset.filteredRelated": (filteredRelated, { asset: { related } }) =>
  428. filteredRelated > 0
  429. ? `${moreCount(related, filteredRelated)} related ${plural(
  430. filteredRelated,
  431. "asset",
  432. "assets"
  433. )}`
  434. : undefined,
  435. "asset.filteredChildren": (filteredChildren, { asset: { children } }) =>
  436. filteredChildren > 0
  437. ? `${moreCount(children, filteredChildren)} ${plural(
  438. filteredChildren,
  439. "asset",
  440. "assets"
  441. )}`
  442. : undefined,
  443. assetChunk: (id, { formatChunkId }) => formatChunkId(id),
  444. assetChunkName: name => name || undefined,
  445. assetChunkIdHint: name => name || undefined
  446. };
  447. /**
  448. * @typedef {Printers<KnownStatsModule, "module"> &
  449. * Exclamation<KnownStatsModule, "module.separator", "module"> &
  450. * { ["module.filteredChildren"]?: SimplePrinter<number, "module"> } &
  451. * { ["module.filteredReasons"]?: SimplePrinter<number, "module"> }} ModuleSimplePrinters
  452. */
  453. /** @type {ModuleSimplePrinters} */
  454. const MODULE_SIMPLE_PRINTERS = {
  455. "module.type": type => (type !== "module" ? type : undefined),
  456. "module.id": (id, { formatModuleId }) =>
  457. isValidId(id) ? formatModuleId(id) : undefined,
  458. "module.name": (name, { bold }) => {
  459. const [prefix, resource] = getModuleName(name);
  460. return `${prefix || ""}${bold(resource || "")}`;
  461. },
  462. "module.identifier": _identifier => undefined,
  463. "module.layer": (layer, { formatLayer }) =>
  464. layer ? formatLayer(layer) : undefined,
  465. "module.sizes": printSizes,
  466. "module.chunks[]": (id, { formatChunkId }) => formatChunkId(id),
  467. "module.depth": (depth, { formatFlag }) =>
  468. depth !== null ? formatFlag(`depth ${depth}`) : undefined,
  469. "module.cacheable": (cacheable, { formatFlag, red }) =>
  470. cacheable === false ? red(formatFlag("not cacheable")) : undefined,
  471. "module.orphan": (orphan, { formatFlag, yellow }) =>
  472. orphan ? yellow(formatFlag("orphan")) : undefined,
  473. // "module.runtime": (runtime, { formatFlag, yellow }) =>
  474. // runtime ? yellow(formatFlag("runtime")) : undefined,
  475. "module.optional": (optional, { formatFlag, yellow }) =>
  476. optional ? yellow(formatFlag("optional")) : undefined,
  477. "module.dependent": (dependent, { formatFlag, cyan }) =>
  478. dependent ? cyan(formatFlag("dependent")) : undefined,
  479. "module.built": (built, { formatFlag, yellow }) =>
  480. built ? yellow(formatFlag("built")) : undefined,
  481. "module.codeGenerated": (codeGenerated, { formatFlag, yellow }) =>
  482. codeGenerated ? yellow(formatFlag("code generated")) : undefined,
  483. "module.buildTimeExecuted": (buildTimeExecuted, { formatFlag, green }) =>
  484. buildTimeExecuted ? green(formatFlag("build time executed")) : undefined,
  485. "module.cached": (cached, { formatFlag, green }) =>
  486. cached ? green(formatFlag("cached")) : undefined,
  487. "module.assets": (assets, { formatFlag, magenta }) =>
  488. assets && assets.length
  489. ? magenta(
  490. formatFlag(
  491. `${assets.length} ${plural(assets.length, "asset", "assets")}`
  492. )
  493. )
  494. : undefined,
  495. "module.warnings": (warnings, { formatFlag, yellow }) =>
  496. warnings
  497. ? yellow(
  498. formatFlag(`${warnings} ${plural(warnings, "warning", "warnings")}`)
  499. )
  500. : undefined,
  501. "module.errors": (errors, { formatFlag, red }) =>
  502. errors
  503. ? red(formatFlag(`${errors} ${plural(errors, "error", "errors")}`))
  504. : undefined,
  505. "module.providedExports": (providedExports, { formatFlag, cyan }) => {
  506. if (Array.isArray(providedExports)) {
  507. if (providedExports.length === 0) return cyan(formatFlag("no exports"));
  508. return cyan(formatFlag(`exports: ${providedExports.join(", ")}`));
  509. }
  510. },
  511. "module.usedExports": (usedExports, { formatFlag, cyan, module }) => {
  512. if (usedExports !== true) {
  513. if (usedExports === null) return cyan(formatFlag("used exports unknown"));
  514. if (usedExports === false) return cyan(formatFlag("module unused"));
  515. if (Array.isArray(usedExports)) {
  516. if (usedExports.length === 0) {
  517. return cyan(formatFlag("no exports used"));
  518. }
  519. const providedExportsCount = Array.isArray(module.providedExports)
  520. ? module.providedExports.length
  521. : null;
  522. if (
  523. providedExportsCount !== null &&
  524. providedExportsCount === usedExports.length
  525. ) {
  526. return cyan(formatFlag("all exports used"));
  527. }
  528. return cyan(
  529. formatFlag(`only some exports used: ${usedExports.join(", ")}`)
  530. );
  531. }
  532. }
  533. },
  534. "module.optimizationBailout[]": (optimizationBailout, { yellow }) =>
  535. yellow(optimizationBailout),
  536. "module.issuerPath": (issuerPath, { module }) =>
  537. module.profile ? undefined : "",
  538. "module.profile": _profile => undefined,
  539. "module.filteredModules": (filteredModules, { module: { modules } }) =>
  540. filteredModules > 0
  541. ? `${moreCount(modules, filteredModules)} nested ${plural(
  542. filteredModules,
  543. "module",
  544. "modules"
  545. )}`
  546. : undefined,
  547. "module.filteredReasons": (filteredReasons, { module: { reasons } }) =>
  548. filteredReasons > 0
  549. ? `${moreCount(reasons, filteredReasons)} ${plural(
  550. filteredReasons,
  551. "reason",
  552. "reasons"
  553. )}`
  554. : undefined,
  555. "module.filteredChildren": (filteredChildren, { module: { children } }) =>
  556. filteredChildren > 0
  557. ? `${moreCount(children, filteredChildren)} ${plural(
  558. filteredChildren,
  559. "module",
  560. "modules"
  561. )}`
  562. : undefined,
  563. "module.separator!": () => "\n"
  564. };
  565. /**
  566. * @typedef {Printers<KnownStatsModuleIssuer, "moduleIssuer"> &
  567. * Printers<KnownStatsModuleIssuer["profile"], "moduleIssuer.profile", "moduleIssuer">} ModuleIssuerPrinters
  568. */
  569. /** @type {ModuleIssuerPrinters} */
  570. const MODULE_ISSUER_PRINTERS = {
  571. "moduleIssuer.id": (id, { formatModuleId }) => formatModuleId(id),
  572. "moduleIssuer.profile.total": (value, { formatTime }) => formatTime(value)
  573. };
  574. /**
  575. * @typedef {Printers<KnownStatsModuleReason, "moduleReason"> &
  576. * { ["moduleReason.filteredChildren"]?: SimplePrinter<number, "moduleReason"> }} ModuleReasonsPrinters
  577. */
  578. /** @type {ModuleReasonsPrinters} */
  579. const MODULE_REASON_PRINTERS = {
  580. "moduleReason.type": type => type || undefined,
  581. "moduleReason.userRequest": (userRequest, { cyan }) =>
  582. cyan(getResourceName(userRequest)),
  583. "moduleReason.moduleId": (moduleId, { formatModuleId }) =>
  584. isValidId(moduleId) ? formatModuleId(moduleId) : undefined,
  585. "moduleReason.module": (module, { magenta }) =>
  586. module ? magenta(module) : undefined,
  587. "moduleReason.loc": loc => loc || undefined,
  588. "moduleReason.explanation": (explanation, { cyan }) =>
  589. explanation ? cyan(explanation) : undefined,
  590. "moduleReason.active": (active, { formatFlag }) =>
  591. active ? undefined : formatFlag("inactive"),
  592. "moduleReason.resolvedModule": (module, { magenta }) =>
  593. module ? magenta(module) : undefined,
  594. "moduleReason.filteredChildren": (
  595. filteredChildren,
  596. { moduleReason: { children } }
  597. ) =>
  598. filteredChildren > 0
  599. ? `${moreCount(children, filteredChildren)} ${plural(
  600. filteredChildren,
  601. "reason",
  602. "reasons"
  603. )}`
  604. : undefined
  605. };
  606. /** @typedef {Printers<KnownStatsProfile, "module.profile", "profile">} ModuleProfilePrinters */
  607. /** @type {ModuleProfilePrinters} */
  608. const MODULE_PROFILE_PRINTERS = {
  609. "module.profile.total": (value, { formatTime }) => formatTime(value),
  610. "module.profile.resolving": (value, { formatTime }) =>
  611. `resolving: ${formatTime(value)}`,
  612. "module.profile.restoring": (value, { formatTime }) =>
  613. `restoring: ${formatTime(value)}`,
  614. "module.profile.integration": (value, { formatTime }) =>
  615. `integration: ${formatTime(value)}`,
  616. "module.profile.building": (value, { formatTime }) =>
  617. `building: ${formatTime(value)}`,
  618. "module.profile.storing": (value, { formatTime }) =>
  619. `storing: ${formatTime(value)}`,
  620. "module.profile.additionalResolving": (value, { formatTime }) =>
  621. value ? `additional resolving: ${formatTime(value)}` : undefined,
  622. "module.profile.additionalIntegration": (value, { formatTime }) =>
  623. value ? `additional integration: ${formatTime(value)}` : undefined
  624. };
  625. /**
  626. * @typedef {Exclamation<KnownStatsChunkGroup, "chunkGroup.kind", "chunkGroupKind"> &
  627. * Exclamation<KnownStatsChunkGroup, "chunkGroup.separator", "chunkGroup"> &
  628. * Printers<KnownStatsChunkGroup, "chunkGroup"> &
  629. * Exclamation<KnownStatsChunkGroup, "chunkGroup.is", "chunkGroup"> &
  630. * Printers<Exclude<KnownStatsChunkGroup["assets"], undefined>[number], "chunkGroupAsset" | "chunkGroup"> &
  631. * { ['chunkGroupChildGroup.type']?: SimplePrinter<string, "chunkGroupAsset"> } &
  632. * { ['chunkGroupChild.assets[]']?: SimplePrinter<string, "chunkGroupAsset"> } &
  633. * { ['chunkGroupChild.chunks[]']?: SimplePrinter<ChunkId, "chunkGroupAsset"> } &
  634. * { ['chunkGroupChild.name']?: SimplePrinter<ChunkName, "chunkGroupAsset"> }} ChunkGroupPrinters
  635. */
  636. /** @type {ChunkGroupPrinters} */
  637. const CHUNK_GROUP_PRINTERS = {
  638. "chunkGroup.kind!": (_, { chunkGroupKind }) => chunkGroupKind,
  639. "chunkGroup.separator!": () => "\n",
  640. "chunkGroup.name": (name, { bold }) => (name ? bold(name) : undefined),
  641. "chunkGroup.isOverSizeLimit": (isOverSizeLimit, { formatFlag, yellow }) =>
  642. isOverSizeLimit ? yellow(formatFlag("big")) : undefined,
  643. "chunkGroup.assetsSize": (size, { formatSize }) =>
  644. size ? formatSize(size) : undefined,
  645. "chunkGroup.auxiliaryAssetsSize": (size, { formatSize }) =>
  646. size ? `(${formatSize(size)})` : undefined,
  647. "chunkGroup.filteredAssets": (n, { chunkGroup: { assets } }) =>
  648. n > 0
  649. ? `${moreCount(assets, n)} ${plural(n, "asset", "assets")}`
  650. : undefined,
  651. "chunkGroup.filteredAuxiliaryAssets": (
  652. n,
  653. { chunkGroup: { auxiliaryAssets } }
  654. ) =>
  655. n > 0
  656. ? `${moreCount(auxiliaryAssets, n)} auxiliary ${plural(
  657. n,
  658. "asset",
  659. "assets"
  660. )}`
  661. : undefined,
  662. "chunkGroup.is!": () => "=",
  663. "chunkGroupAsset.name": (asset, { green }) => green(asset),
  664. "chunkGroupAsset.size": (size, { formatSize, chunkGroup }) =>
  665. chunkGroup.assets &&
  666. (chunkGroup.assets.length > 1 ||
  667. (chunkGroup.auxiliaryAssets && chunkGroup.auxiliaryAssets.length > 0)
  668. ? formatSize(size)
  669. : undefined),
  670. "chunkGroup.children": (children, context, printer) =>
  671. Array.isArray(children)
  672. ? undefined
  673. : printer.print(
  674. context.type,
  675. Object.keys(children).map(key => ({
  676. type: key,
  677. children: children[key]
  678. })),
  679. context
  680. ),
  681. "chunkGroupChildGroup.type": type => `${type}:`,
  682. "chunkGroupChild.assets[]": (file, { formatFilename }) =>
  683. formatFilename(file),
  684. "chunkGroupChild.chunks[]": (id, { formatChunkId }) => formatChunkId(id),
  685. "chunkGroupChild.name": name => (name ? `(name: ${name})` : undefined)
  686. };
  687. /**
  688. * @typedef {Printers<KnownStatsChunk, "chunk"> &
  689. * { ["chunk.childrenByOrder[].type"]: SimplePrinter<string, "chunk"> } &
  690. * { ["chunk.childrenByOrder[].children[]"]: SimplePrinter<ChunkId, "chunk"> } &
  691. * Exclamation<KnownStatsChunk, "chunk.separator", "chunk"> &
  692. * Printers<KnownStatsChunkOrigin, "chunkOrigin">} ChunkPrinters
  693. */
  694. /** @type {ChunkPrinters} */
  695. const CHUNK_PRINTERS = {
  696. "chunk.id": (id, { formatChunkId }) => formatChunkId(id),
  697. "chunk.files[]": (file, { formatFilename }) => formatFilename(file),
  698. "chunk.names[]": name => name,
  699. "chunk.idHints[]": name => name,
  700. "chunk.runtime[]": name => name,
  701. "chunk.sizes": (sizes, context) => printSizes(sizes, context),
  702. "chunk.parents[]": (parents, context) =>
  703. context.formatChunkId(parents, "parent"),
  704. "chunk.siblings[]": (siblings, context) =>
  705. context.formatChunkId(siblings, "sibling"),
  706. "chunk.children[]": (children, context) =>
  707. context.formatChunkId(children, "child"),
  708. "chunk.childrenByOrder": (childrenByOrder, context, printer) =>
  709. Array.isArray(childrenByOrder)
  710. ? undefined
  711. : printer.print(
  712. context.type,
  713. Object.keys(childrenByOrder).map(key => ({
  714. type: key,
  715. children: childrenByOrder[key]
  716. })),
  717. context
  718. ),
  719. "chunk.childrenByOrder[].type": type => `${type}:`,
  720. "chunk.childrenByOrder[].children[]": (id, { formatChunkId }) =>
  721. isValidId(id) ? formatChunkId(id) : undefined,
  722. "chunk.entry": (entry, { formatFlag, yellow }) =>
  723. entry ? yellow(formatFlag("entry")) : undefined,
  724. "chunk.initial": (initial, { formatFlag, yellow }) =>
  725. initial ? yellow(formatFlag("initial")) : undefined,
  726. "chunk.rendered": (rendered, { formatFlag, green }) =>
  727. rendered ? green(formatFlag("rendered")) : undefined,
  728. "chunk.recorded": (recorded, { formatFlag, green }) =>
  729. recorded ? green(formatFlag("recorded")) : undefined,
  730. "chunk.reason": (reason, { yellow }) => (reason ? yellow(reason) : undefined),
  731. "chunk.filteredModules": (filteredModules, { chunk: { modules } }) =>
  732. filteredModules > 0
  733. ? `${moreCount(modules, filteredModules)} chunk ${plural(
  734. filteredModules,
  735. "module",
  736. "modules"
  737. )}`
  738. : undefined,
  739. "chunk.separator!": () => "\n",
  740. "chunkOrigin.request": request => request,
  741. "chunkOrigin.moduleId": (moduleId, { formatModuleId }) =>
  742. isValidId(moduleId) ? formatModuleId(moduleId) : undefined,
  743. "chunkOrigin.moduleName": (moduleName, { bold }) => bold(moduleName),
  744. "chunkOrigin.loc": loc => loc
  745. };
  746. /**
  747. * @typedef {Printers<KnownStatsError, "error"> &
  748. * { ["error.filteredDetails"]?: SimplePrinter<number, "error"> } &
  749. * Exclamation<KnownStatsError, "error.separator", "error">} ErrorPrinters
  750. */
  751. /**
  752. * @type {ErrorPrinters}
  753. */
  754. const ERROR_PRINTERS = {
  755. "error.compilerPath": (compilerPath, { bold }) =>
  756. compilerPath ? bold(`(${compilerPath})`) : undefined,
  757. "error.chunkId": (chunkId, { formatChunkId }) =>
  758. isValidId(chunkId) ? formatChunkId(chunkId) : undefined,
  759. "error.chunkEntry": (chunkEntry, { formatFlag }) =>
  760. chunkEntry ? formatFlag("entry") : undefined,
  761. "error.chunkInitial": (chunkInitial, { formatFlag }) =>
  762. chunkInitial ? formatFlag("initial") : undefined,
  763. "error.file": (file, { bold }) => bold(file),
  764. "error.moduleName": (moduleName, { bold }) =>
  765. moduleName.includes("!")
  766. ? `${bold(moduleName.replace(/^(\s|\S)*!/, ""))} (${moduleName})`
  767. : `${bold(moduleName)}`,
  768. "error.loc": (loc, { green }) => green(loc),
  769. "error.message": (message, { bold, formatError }) =>
  770. message.includes("\u001B[") ? message : bold(formatError(message)),
  771. "error.details": (details, { formatError }) => formatError(details),
  772. "error.filteredDetails": filteredDetails =>
  773. filteredDetails ? `+ ${filteredDetails} hidden lines` : undefined,
  774. "error.stack": stack => stack,
  775. "error.cause": (cause, context, printer) =>
  776. cause
  777. ? indent(
  778. `[cause]: ${
  779. /** @type {string} */
  780. (printer.print(`${context.type}.error`, cause, context))
  781. }`,
  782. " "
  783. )
  784. : undefined,
  785. "error.moduleTrace": _moduleTrace => undefined,
  786. "error.separator!": () => "\n"
  787. };
  788. /**
  789. * @typedef {Printers<KnownStatsLoggingEntry, `loggingEntry(${LogTypeEnum}).loggingEntry`> &
  790. * { ["loggingEntry(clear).loggingEntry"]?: SimplePrinter<KnownStatsLoggingEntry, "logging"> } &
  791. * { ["loggingEntry.trace[]"]?: SimplePrinter<Exclude<KnownStatsLoggingEntry["trace"], undefined>[number], "logging"> } &
  792. * { loggingGroup?: SimplePrinter<KnownStatsLogging[], "logging"> } &
  793. * Printers<KnownStatsLogging & { name: string }, `loggingGroup`> &
  794. * Exclamation<KnownStatsLogging, "loggingGroup.separator", "loggingGroup">} LogEntryPrinters
  795. */
  796. /** @type {LogEntryPrinters} */
  797. const LOG_ENTRY_PRINTERS = {
  798. "loggingEntry(error).loggingEntry.message": (message, { red }) =>
  799. mapLines(message, x => `<e> ${red(x)}`),
  800. "loggingEntry(warn).loggingEntry.message": (message, { yellow }) =>
  801. mapLines(message, x => `<w> ${yellow(x)}`),
  802. "loggingEntry(info).loggingEntry.message": (message, { green }) =>
  803. mapLines(message, x => `<i> ${green(x)}`),
  804. "loggingEntry(log).loggingEntry.message": (message, { bold }) =>
  805. mapLines(message, x => ` ${bold(x)}`),
  806. "loggingEntry(debug).loggingEntry.message": message =>
  807. mapLines(message, x => ` ${x}`),
  808. "loggingEntry(trace).loggingEntry.message": message =>
  809. mapLines(message, x => ` ${x}`),
  810. "loggingEntry(status).loggingEntry.message": (message, { magenta }) =>
  811. mapLines(message, x => `<s> ${magenta(x)}`),
  812. "loggingEntry(profile).loggingEntry.message": (message, { magenta }) =>
  813. mapLines(message, x => `<p> ${magenta(x)}`),
  814. "loggingEntry(profileEnd).loggingEntry.message": (message, { magenta }) =>
  815. mapLines(message, x => `</p> ${magenta(x)}`),
  816. "loggingEntry(time).loggingEntry.message": (message, { magenta }) =>
  817. mapLines(message, x => `<t> ${magenta(x)}`),
  818. "loggingEntry(group).loggingEntry.message": (message, { cyan }) =>
  819. mapLines(message, x => `<-> ${cyan(x)}`),
  820. "loggingEntry(groupCollapsed).loggingEntry.message": (message, { cyan }) =>
  821. mapLines(message, x => `<+> ${cyan(x)}`),
  822. "loggingEntry(clear).loggingEntry": () => " -------",
  823. "loggingEntry(groupCollapsed).loggingEntry.children": () => "",
  824. "loggingEntry.trace[]": trace =>
  825. trace ? mapLines(trace, x => `| ${x}`) : undefined,
  826. loggingGroup: loggingGroup =>
  827. loggingGroup.entries.length === 0 ? "" : undefined,
  828. "loggingGroup.debug": (flag, { red }) => (flag ? red("DEBUG") : undefined),
  829. "loggingGroup.name": (name, { bold }) => bold(`LOG from ${name}`),
  830. "loggingGroup.separator!": () => "\n",
  831. "loggingGroup.filteredEntries": filteredEntries =>
  832. filteredEntries > 0 ? `+ ${filteredEntries} hidden lines` : undefined
  833. };
  834. /** @typedef {Printers<KnownStatsModuleTraceItem, "moduleTraceItem">} ModuleTraceItemPrinters */
  835. /** @type {ModuleTraceItemPrinters} */
  836. const MODULE_TRACE_ITEM_PRINTERS = {
  837. "moduleTraceItem.originName": originName => originName
  838. };
  839. /** @typedef {Printers<KnownStatsModuleTraceDependency, "moduleTraceDependency">} ModuleTraceDependencyPrinters */
  840. /** @type {ModuleTraceDependencyPrinters} */
  841. const MODULE_TRACE_DEPENDENCY_PRINTERS = {
  842. "moduleTraceDependency.loc": loc => loc
  843. };
  844. /**
  845. * @type {Record<string, string | ((item: KnownStatsLoggingEntry) => string)>}
  846. */
  847. const ITEM_NAMES = {
  848. "compilation.assets[]": "asset",
  849. "compilation.modules[]": "module",
  850. "compilation.chunks[]": "chunk",
  851. "compilation.entrypoints[]": "chunkGroup",
  852. "compilation.namedChunkGroups[]": "chunkGroup",
  853. "compilation.errors[]": "error",
  854. "compilation.warnings[]": "error",
  855. "compilation.logging[]": "loggingGroup",
  856. "compilation.children[]": "compilation",
  857. "asset.related[]": "asset",
  858. "asset.children[]": "asset",
  859. "asset.chunks[]": "assetChunk",
  860. "asset.auxiliaryChunks[]": "assetChunk",
  861. "asset.chunkNames[]": "assetChunkName",
  862. "asset.chunkIdHints[]": "assetChunkIdHint",
  863. "asset.auxiliaryChunkNames[]": "assetChunkName",
  864. "asset.auxiliaryChunkIdHints[]": "assetChunkIdHint",
  865. "chunkGroup.assets[]": "chunkGroupAsset",
  866. "chunkGroup.auxiliaryAssets[]": "chunkGroupAsset",
  867. "chunkGroupChild.assets[]": "chunkGroupAsset",
  868. "chunkGroupChild.auxiliaryAssets[]": "chunkGroupAsset",
  869. "chunkGroup.children[]": "chunkGroupChildGroup",
  870. "chunkGroupChildGroup.children[]": "chunkGroupChild",
  871. "module.modules[]": "module",
  872. "module.children[]": "module",
  873. "module.reasons[]": "moduleReason",
  874. "moduleReason.children[]": "moduleReason",
  875. "module.issuerPath[]": "moduleIssuer",
  876. "chunk.origins[]": "chunkOrigin",
  877. "chunk.modules[]": "module",
  878. "loggingGroup.entries[]": logEntry =>
  879. `loggingEntry(${logEntry.type}).loggingEntry`,
  880. "loggingEntry.children[]": logEntry =>
  881. `loggingEntry(${logEntry.type}).loggingEntry`,
  882. "error.moduleTrace[]": "moduleTraceItem",
  883. "error.errors[]": "error",
  884. "moduleTraceItem.dependencies[]": "moduleTraceDependency"
  885. };
  886. const ERROR_PREFERRED_ORDER = [
  887. "compilerPath",
  888. "chunkId",
  889. "chunkEntry",
  890. "chunkInitial",
  891. "file",
  892. "separator!",
  893. "moduleName",
  894. "loc",
  895. "separator!",
  896. "message",
  897. "separator!",
  898. "details",
  899. "separator!",
  900. "filteredDetails",
  901. "separator!",
  902. "stack",
  903. "separator!",
  904. "cause",
  905. "separator!",
  906. "missing",
  907. "separator!",
  908. "moduleTrace"
  909. ];
  910. /** @type {Record<string, string[]>} */
  911. const PREFERRED_ORDERS = {
  912. compilation: [
  913. "name",
  914. "hash",
  915. "version",
  916. "time",
  917. "builtAt",
  918. "env",
  919. "publicPath",
  920. "assets",
  921. "filteredAssets",
  922. "entrypoints",
  923. "namedChunkGroups",
  924. "chunks",
  925. "modules",
  926. "filteredModules",
  927. "children",
  928. "logging",
  929. "warnings",
  930. "warningsInChildren!",
  931. "filteredWarningDetailsCount",
  932. "errors",
  933. "errorsInChildren!",
  934. "filteredErrorDetailsCount",
  935. "summary!",
  936. "needAdditionalPass"
  937. ],
  938. asset: [
  939. "type",
  940. "name",
  941. "size",
  942. "chunks",
  943. "auxiliaryChunks",
  944. "emitted",
  945. "comparedForEmit",
  946. "cached",
  947. "info",
  948. "isOverSizeLimit",
  949. "chunkNames",
  950. "auxiliaryChunkNames",
  951. "chunkIdHints",
  952. "auxiliaryChunkIdHints",
  953. "related",
  954. "filteredRelated",
  955. "children",
  956. "filteredChildren"
  957. ],
  958. "asset.info": [
  959. "immutable",
  960. "sourceFilename",
  961. "javascriptModule",
  962. "development",
  963. "hotModuleReplacement"
  964. ],
  965. chunkGroup: [
  966. "kind!",
  967. "name",
  968. "isOverSizeLimit",
  969. "assetsSize",
  970. "auxiliaryAssetsSize",
  971. "is!",
  972. "assets",
  973. "filteredAssets",
  974. "auxiliaryAssets",
  975. "filteredAuxiliaryAssets",
  976. "separator!",
  977. "children"
  978. ],
  979. chunkGroupAsset: ["name", "size"],
  980. chunkGroupChildGroup: ["type", "children"],
  981. chunkGroupChild: ["assets", "chunks", "name"],
  982. module: [
  983. "type",
  984. "name",
  985. "identifier",
  986. "id",
  987. "layer",
  988. "sizes",
  989. "chunks",
  990. "depth",
  991. "cacheable",
  992. "orphan",
  993. "runtime",
  994. "optional",
  995. "dependent",
  996. "built",
  997. "codeGenerated",
  998. "cached",
  999. "assets",
  1000. "failed",
  1001. "warnings",
  1002. "errors",
  1003. "children",
  1004. "filteredChildren",
  1005. "providedExports",
  1006. "usedExports",
  1007. "optimizationBailout",
  1008. "reasons",
  1009. "filteredReasons",
  1010. "issuerPath",
  1011. "profile",
  1012. "modules",
  1013. "filteredModules"
  1014. ],
  1015. moduleReason: [
  1016. "active",
  1017. "type",
  1018. "userRequest",
  1019. "moduleId",
  1020. "module",
  1021. "resolvedModule",
  1022. "loc",
  1023. "explanation",
  1024. "children",
  1025. "filteredChildren"
  1026. ],
  1027. "module.profile": [
  1028. "total",
  1029. "separator!",
  1030. "resolving",
  1031. "restoring",
  1032. "integration",
  1033. "building",
  1034. "storing",
  1035. "additionalResolving",
  1036. "additionalIntegration"
  1037. ],
  1038. chunk: [
  1039. "id",
  1040. "runtime",
  1041. "files",
  1042. "names",
  1043. "idHints",
  1044. "sizes",
  1045. "parents",
  1046. "siblings",
  1047. "children",
  1048. "childrenByOrder",
  1049. "entry",
  1050. "initial",
  1051. "rendered",
  1052. "recorded",
  1053. "reason",
  1054. "separator!",
  1055. "origins",
  1056. "separator!",
  1057. "modules",
  1058. "separator!",
  1059. "filteredModules"
  1060. ],
  1061. chunkOrigin: ["request", "moduleId", "moduleName", "loc"],
  1062. error: ERROR_PREFERRED_ORDER,
  1063. warning: ERROR_PREFERRED_ORDER,
  1064. "chunk.childrenByOrder[]": ["type", "children"],
  1065. loggingGroup: [
  1066. "debug",
  1067. "name",
  1068. "separator!",
  1069. "entries",
  1070. "separator!",
  1071. "filteredEntries"
  1072. ],
  1073. loggingEntry: ["message", "trace", "children"]
  1074. };
  1075. /** @typedef {(items: string[]) => string | undefined} SimpleItemsJoiner */
  1076. /** @type {SimpleItemsJoiner} */
  1077. const itemsJoinOneLine = items => items.filter(Boolean).join(" ");
  1078. /** @type {SimpleItemsJoiner} */
  1079. const itemsJoinOneLineBrackets = items =>
  1080. items.length > 0 ? `(${items.filter(Boolean).join(" ")})` : undefined;
  1081. /** @type {SimpleItemsJoiner} */
  1082. const itemsJoinMoreSpacing = items => items.filter(Boolean).join("\n\n");
  1083. /** @type {SimpleItemsJoiner} */
  1084. const itemsJoinComma = items => items.filter(Boolean).join(", ");
  1085. /** @type {SimpleItemsJoiner} */
  1086. const itemsJoinCommaBrackets = items =>
  1087. items.length > 0 ? `(${items.filter(Boolean).join(", ")})` : undefined;
  1088. /** @type {(item: string) => SimpleItemsJoiner} */
  1089. const itemsJoinCommaBracketsWithName = name => items =>
  1090. items.length > 0
  1091. ? `(${name}: ${items.filter(Boolean).join(", ")})`
  1092. : undefined;
  1093. /** @type {Record<string, SimpleItemsJoiner>} */
  1094. const SIMPLE_ITEMS_JOINER = {
  1095. "chunk.parents": itemsJoinOneLine,
  1096. "chunk.siblings": itemsJoinOneLine,
  1097. "chunk.children": itemsJoinOneLine,
  1098. "chunk.names": itemsJoinCommaBrackets,
  1099. "chunk.idHints": itemsJoinCommaBracketsWithName("id hint"),
  1100. "chunk.runtime": itemsJoinCommaBracketsWithName("runtime"),
  1101. "chunk.files": itemsJoinComma,
  1102. "chunk.childrenByOrder": itemsJoinOneLine,
  1103. "chunk.childrenByOrder[].children": itemsJoinOneLine,
  1104. "chunkGroup.assets": itemsJoinOneLine,
  1105. "chunkGroup.auxiliaryAssets": itemsJoinOneLineBrackets,
  1106. "chunkGroupChildGroup.children": itemsJoinComma,
  1107. "chunkGroupChild.assets": itemsJoinOneLine,
  1108. "chunkGroupChild.auxiliaryAssets": itemsJoinOneLineBrackets,
  1109. "asset.chunks": itemsJoinComma,
  1110. "asset.auxiliaryChunks": itemsJoinCommaBrackets,
  1111. "asset.chunkNames": itemsJoinCommaBracketsWithName("name"),
  1112. "asset.auxiliaryChunkNames": itemsJoinCommaBracketsWithName("auxiliary name"),
  1113. "asset.chunkIdHints": itemsJoinCommaBracketsWithName("id hint"),
  1114. "asset.auxiliaryChunkIdHints":
  1115. itemsJoinCommaBracketsWithName("auxiliary id hint"),
  1116. "module.chunks": itemsJoinOneLine,
  1117. "module.issuerPath": items =>
  1118. items
  1119. .filter(Boolean)
  1120. .map(item => `${item} ->`)
  1121. .join(" "),
  1122. "compilation.errors": itemsJoinMoreSpacing,
  1123. "compilation.warnings": itemsJoinMoreSpacing,
  1124. "compilation.logging": itemsJoinMoreSpacing,
  1125. "compilation.children": items =>
  1126. indent(/** @type {string} */ (itemsJoinMoreSpacing(items)), " "),
  1127. "moduleTraceItem.dependencies": itemsJoinOneLine,
  1128. "loggingEntry.children": items =>
  1129. indent(items.filter(Boolean).join("\n"), " ", false)
  1130. };
  1131. /**
  1132. * @param {Item[]} items items
  1133. * @returns {string} result
  1134. */
  1135. const joinOneLine = items =>
  1136. items
  1137. .map(item => item.content)
  1138. .filter(Boolean)
  1139. .join(" ");
  1140. /**
  1141. * @param {Item[]} items items
  1142. * @returns {string} result
  1143. */
  1144. const joinInBrackets = items => {
  1145. const res = [];
  1146. let mode = 0;
  1147. for (const item of items) {
  1148. if (item.element === "separator!") {
  1149. switch (mode) {
  1150. case 0:
  1151. case 1:
  1152. mode += 2;
  1153. break;
  1154. case 4:
  1155. res.push(")");
  1156. mode = 3;
  1157. break;
  1158. }
  1159. }
  1160. if (!item.content) continue;
  1161. switch (mode) {
  1162. case 0:
  1163. mode = 1;
  1164. break;
  1165. case 1:
  1166. res.push(" ");
  1167. break;
  1168. case 2:
  1169. res.push("(");
  1170. mode = 4;
  1171. break;
  1172. case 3:
  1173. res.push(" (");
  1174. mode = 4;
  1175. break;
  1176. case 4:
  1177. res.push(", ");
  1178. break;
  1179. }
  1180. res.push(item.content);
  1181. }
  1182. if (mode === 4) res.push(")");
  1183. return res.join("");
  1184. };
  1185. /**
  1186. * @param {string} str a string
  1187. * @param {string} prefix prefix
  1188. * @param {boolean=} noPrefixInFirstLine need prefix in the first line?
  1189. * @returns {string} result
  1190. */
  1191. const indent = (str, prefix, noPrefixInFirstLine) => {
  1192. const rem = str.replace(/\n([^\n])/g, `\n${prefix}$1`);
  1193. if (noPrefixInFirstLine) return rem;
  1194. const ind = str[0] === "\n" ? "" : prefix;
  1195. return ind + rem;
  1196. };
  1197. /**
  1198. * @param {(false | Item)[]} items items
  1199. * @param {string} indenter indenter
  1200. * @returns {string} result
  1201. */
  1202. const joinExplicitNewLine = (items, indenter) => {
  1203. let firstInLine = true;
  1204. let first = true;
  1205. return items
  1206. .map(item => {
  1207. if (!item || !item.content) return;
  1208. let content = indent(item.content, first ? "" : indenter, !firstInLine);
  1209. if (firstInLine) {
  1210. content = content.replace(/^\n+/, "");
  1211. }
  1212. if (!content) return;
  1213. first = false;
  1214. const noJoiner = firstInLine || content.startsWith("\n");
  1215. firstInLine = content.endsWith("\n");
  1216. return noJoiner ? content : ` ${content}`;
  1217. })
  1218. .filter(Boolean)
  1219. .join("")
  1220. .trim();
  1221. };
  1222. /**
  1223. * @param {boolean} error is an error
  1224. * @returns {SimpleElementJoiner} joiner
  1225. */
  1226. const joinError =
  1227. error =>
  1228. /**
  1229. * @param {Item[]} items items
  1230. * @param {StatsPrinterContextWithExtra} ctx context
  1231. * @returns {string} result
  1232. */
  1233. (items, { red, yellow }) =>
  1234. `${error ? red("ERROR") : yellow("WARNING")} in ${joinExplicitNewLine(
  1235. items,
  1236. ""
  1237. )}`;
  1238. /** @typedef {{ element: string, content: string | undefined }} Item */
  1239. /** @typedef {(items: Item[], context: StatsPrinterContextWithExtra & Required<KnownStatsPrinterContext>) => string} SimpleElementJoiner */
  1240. /** @type {Record<string, SimpleElementJoiner>} */
  1241. const SIMPLE_ELEMENT_JOINERS = {
  1242. compilation: items => {
  1243. const result = [];
  1244. let lastNeedMore = false;
  1245. for (const item of items) {
  1246. if (!item.content) continue;
  1247. const needMoreSpace =
  1248. item.element === "warnings" ||
  1249. item.element === "filteredWarningDetailsCount" ||
  1250. item.element === "errors" ||
  1251. item.element === "filteredErrorDetailsCount" ||
  1252. item.element === "logging";
  1253. if (result.length !== 0) {
  1254. result.push(needMoreSpace || lastNeedMore ? "\n\n" : "\n");
  1255. }
  1256. result.push(item.content);
  1257. lastNeedMore = needMoreSpace;
  1258. }
  1259. if (lastNeedMore) result.push("\n");
  1260. return result.join("");
  1261. },
  1262. asset: items =>
  1263. joinExplicitNewLine(
  1264. items.map(item => {
  1265. if (
  1266. (item.element === "related" || item.element === "children") &&
  1267. item.content
  1268. ) {
  1269. return {
  1270. ...item,
  1271. content: `\n${item.content}\n`
  1272. };
  1273. }
  1274. return item;
  1275. }),
  1276. " "
  1277. ),
  1278. "asset.info": joinOneLine,
  1279. module: (items, { module }) => {
  1280. let hasName = false;
  1281. return joinExplicitNewLine(
  1282. items.map(item => {
  1283. switch (item.element) {
  1284. case "id":
  1285. if (module.id === module.name) {
  1286. if (hasName) return false;
  1287. if (item.content) hasName = true;
  1288. }
  1289. break;
  1290. case "name":
  1291. if (hasName) return false;
  1292. if (item.content) hasName = true;
  1293. break;
  1294. case "providedExports":
  1295. case "usedExports":
  1296. case "optimizationBailout":
  1297. case "reasons":
  1298. case "issuerPath":
  1299. case "profile":
  1300. case "children":
  1301. case "modules":
  1302. if (item.content) {
  1303. return {
  1304. ...item,
  1305. content: `\n${item.content}\n`
  1306. };
  1307. }
  1308. break;
  1309. }
  1310. return item;
  1311. }),
  1312. " "
  1313. );
  1314. },
  1315. chunk: items => {
  1316. let hasEntry = false;
  1317. return `chunk ${joinExplicitNewLine(
  1318. items.filter(item => {
  1319. switch (item.element) {
  1320. case "entry":
  1321. if (item.content) hasEntry = true;
  1322. break;
  1323. case "initial":
  1324. if (hasEntry) return false;
  1325. break;
  1326. }
  1327. return true;
  1328. }),
  1329. " "
  1330. )}`;
  1331. },
  1332. "chunk.childrenByOrder[]": items => `(${joinOneLine(items)})`,
  1333. chunkGroup: items => joinExplicitNewLine(items, " "),
  1334. chunkGroupAsset: joinOneLine,
  1335. chunkGroupChildGroup: joinOneLine,
  1336. chunkGroupChild: joinOneLine,
  1337. moduleReason: (items, { moduleReason }) => {
  1338. let hasName = false;
  1339. return joinExplicitNewLine(
  1340. items.map(item => {
  1341. switch (item.element) {
  1342. case "moduleId":
  1343. if (moduleReason.moduleId === moduleReason.module && item.content) {
  1344. hasName = true;
  1345. }
  1346. break;
  1347. case "module":
  1348. if (hasName) return false;
  1349. break;
  1350. case "resolvedModule":
  1351. if (moduleReason.module === moduleReason.resolvedModule) {
  1352. return false;
  1353. }
  1354. break;
  1355. case "children":
  1356. if (item.content) {
  1357. return {
  1358. ...item,
  1359. content: `\n${item.content}\n`
  1360. };
  1361. }
  1362. break;
  1363. }
  1364. return item;
  1365. }),
  1366. " "
  1367. );
  1368. },
  1369. "module.profile": joinInBrackets,
  1370. moduleIssuer: joinOneLine,
  1371. chunkOrigin: items => `> ${joinOneLine(items)}`,
  1372. "errors[].error": joinError(true),
  1373. "warnings[].error": joinError(false),
  1374. error: items => joinExplicitNewLine(items, ""),
  1375. "error.errors[].error": items =>
  1376. indent(`[errors]: ${joinExplicitNewLine(items, "")}`, " "),
  1377. loggingGroup: items => joinExplicitNewLine(items, "").trimEnd(),
  1378. moduleTraceItem: items => ` @ ${joinOneLine(items)}`,
  1379. moduleTraceDependency: joinOneLine
  1380. };
  1381. /** @type {Record<keyof KnownStatsPrinterColorFunctions, string>} */
  1382. const AVAILABLE_COLORS = {
  1383. bold: "\u001B[1m",
  1384. yellow: "\u001B[1m\u001B[33m",
  1385. red: "\u001B[1m\u001B[31m",
  1386. green: "\u001B[1m\u001B[32m",
  1387. cyan: "\u001B[1m\u001B[36m",
  1388. magenta: "\u001B[1m\u001B[35m"
  1389. };
  1390. /**
  1391. * @template T
  1392. * @typedef {T extends [infer Head, ...infer Tail] ? Tail : undefined} Tail
  1393. */
  1394. /** @typedef {Required<{ [Key in keyof KnownStatsPrinterFormatters]: (value: Parameters<NonNullable<KnownStatsPrinterFormatters[Key]>>[0], options: Required<KnownStatsPrinterColorFunctions> & StatsPrinterContextWithExtra, ...args: Tail<Parameters<NonNullable<KnownStatsPrinterFormatters[Key]>>>) => string }>} AvailableFormats */
  1395. /** @type {AvailableFormats} */
  1396. const AVAILABLE_FORMATS = {
  1397. formatChunkId: (id, { yellow }, direction) => {
  1398. switch (direction) {
  1399. case "parent":
  1400. return `<{${yellow(id)}}>`;
  1401. case "sibling":
  1402. return `={${yellow(id)}}=`;
  1403. case "child":
  1404. return `>{${yellow(id)}}<`;
  1405. default:
  1406. return `{${yellow(id)}}`;
  1407. }
  1408. },
  1409. formatModuleId: id => `[${id}]`,
  1410. formatFilename: (filename, { green, yellow }, oversize) =>
  1411. (oversize ? yellow : green)(filename),
  1412. formatFlag: flag => `[${flag}]`,
  1413. formatLayer: layer => `(in ${layer})`,
  1414. formatSize: require("../SizeFormatHelpers").formatSize,
  1415. formatDateTime: (dateTime, { bold }) => {
  1416. const d = new Date(dateTime);
  1417. const x = twoDigit;
  1418. const date = `${d.getFullYear()}-${x(d.getMonth() + 1)}-${x(d.getDate())}`;
  1419. const time = `${x(d.getHours())}:${x(d.getMinutes())}:${x(d.getSeconds())}`;
  1420. return `${date} ${bold(time)}`;
  1421. },
  1422. formatTime: (
  1423. time,
  1424. { timeReference, bold, green, yellow, red },
  1425. boldQuantity
  1426. ) => {
  1427. const unit = " ms";
  1428. if (timeReference && time !== timeReference) {
  1429. const times = [
  1430. timeReference / 2,
  1431. timeReference / 4,
  1432. timeReference / 8,
  1433. timeReference / 16
  1434. ];
  1435. if (time < times[3]) return `${time}${unit}`;
  1436. else if (time < times[2]) return bold(`${time}${unit}`);
  1437. else if (time < times[1]) return green(`${time}${unit}`);
  1438. else if (time < times[0]) return yellow(`${time}${unit}`);
  1439. return red(`${time}${unit}`);
  1440. }
  1441. return `${boldQuantity ? bold(time) : time}${unit}`;
  1442. },
  1443. formatError: (message, { green, yellow, red }) => {
  1444. if (message.includes("\u001B[")) return message;
  1445. const highlights = [
  1446. { regExp: /(Did you mean .+)/g, format: green },
  1447. {
  1448. regExp: /(Set 'mode' option to 'development' or 'production')/g,
  1449. format: green
  1450. },
  1451. { regExp: /(\(module has no exports\))/g, format: red },
  1452. { regExp: /\(possible exports: (.+)\)/g, format: green },
  1453. { regExp: /(?:^|\n)(.* doesn't exist)/g, format: red },
  1454. { regExp: /('\w+' option has not been set)/g, format: red },
  1455. {
  1456. regExp: /(Emitted value instead of an instance of Error)/g,
  1457. format: yellow
  1458. },
  1459. { regExp: /(Used? .+ instead)/gi, format: yellow },
  1460. { regExp: /\b(deprecated|must|required)\b/g, format: yellow },
  1461. {
  1462. regExp: /\b(BREAKING CHANGE)\b/gi,
  1463. format: red
  1464. },
  1465. {
  1466. regExp:
  1467. /\b(error|failed|unexpected|invalid|not found|not supported|not available|not possible|not implemented|doesn't support|conflict|conflicting|not existing|duplicate)\b/gi,
  1468. format: red
  1469. }
  1470. ];
  1471. for (const { regExp, format } of highlights) {
  1472. message = message.replace(
  1473. regExp,
  1474. /**
  1475. * @param {string} match match
  1476. * @param {string} content content
  1477. * @returns {string} result
  1478. */
  1479. (match, content) => match.replace(content, format(content))
  1480. );
  1481. }
  1482. return message;
  1483. }
  1484. };
  1485. /** @typedef {(result: string) => string} ResultModifierFn */
  1486. /** @type {Record<string, ResultModifierFn>} */
  1487. const RESULT_MODIFIER = {
  1488. "module.modules": result => indent(result, "| ")
  1489. };
  1490. /**
  1491. * @param {string[]} array array
  1492. * @param {string[]} preferredOrder preferred order
  1493. * @returns {string[]} result
  1494. */
  1495. const createOrder = (array, preferredOrder) => {
  1496. const originalArray = [...array];
  1497. /** @type {Set<string>} */
  1498. const set = new Set(array);
  1499. /** @type {Set<string>} */
  1500. const usedSet = new Set();
  1501. array.length = 0;
  1502. for (const element of preferredOrder) {
  1503. if (element.endsWith("!") || set.has(element)) {
  1504. array.push(element);
  1505. usedSet.add(element);
  1506. }
  1507. }
  1508. for (const element of originalArray) {
  1509. if (!usedSet.has(element)) {
  1510. array.push(element);
  1511. }
  1512. }
  1513. return array;
  1514. };
  1515. const PLUGIN_NAME = "DefaultStatsPrinterPlugin";
  1516. class DefaultStatsPrinterPlugin {
  1517. /**
  1518. * Apply the plugin
  1519. * @param {Compiler} compiler the compiler instance
  1520. * @returns {void}
  1521. */
  1522. apply(compiler) {
  1523. compiler.hooks.compilation.tap(PLUGIN_NAME, compilation => {
  1524. compilation.hooks.statsPrinter.tap(PLUGIN_NAME, (stats, options) => {
  1525. // Put colors into context
  1526. stats.hooks.print
  1527. .for("compilation")
  1528. .tap(PLUGIN_NAME, (compilation, context) => {
  1529. for (const color of Object.keys(AVAILABLE_COLORS)) {
  1530. const name =
  1531. /** @type {keyof KnownStatsPrinterColorFunctions} */
  1532. (color);
  1533. /** @type {string | undefined} */
  1534. let start;
  1535. if (options.colors) {
  1536. if (
  1537. typeof options.colors === "object" &&
  1538. typeof options.colors[name] === "string"
  1539. ) {
  1540. start = options.colors[name];
  1541. } else {
  1542. start = AVAILABLE_COLORS[name];
  1543. }
  1544. }
  1545. if (start) {
  1546. /** @type {ColorFunction} */
  1547. context[color] = str =>
  1548. `${start}${
  1549. typeof str === "string"
  1550. ? str.replace(
  1551. // eslint-disable-next-line no-control-regex
  1552. /((\u001B\[39m|\u001B\[22m|\u001B\[0m)+)/g,
  1553. `$1${start}`
  1554. )
  1555. : str
  1556. }\u001B[39m\u001B[22m`;
  1557. } else {
  1558. /**
  1559. * @param {string} str string
  1560. * @returns {string} str string
  1561. */
  1562. context[color] = str => str;
  1563. }
  1564. }
  1565. for (const _format of Object.keys(AVAILABLE_FORMATS)) {
  1566. const format =
  1567. /** @type {keyof KnownStatsPrinterFormatters} */
  1568. (_format);
  1569. context[format] =
  1570. /** @type {(content: Parameters<NonNullable<KnownStatsPrinterFormatters[keyof KnownStatsPrinterFormatters]>>[0], ...args: Tail<Parameters<NonNullable<KnownStatsPrinterFormatters[keyof KnownStatsPrinterFormatters]>>>) => string} */
  1571. (content, ...args) =>
  1572. /** @type {TODO} */
  1573. (AVAILABLE_FORMATS)[format](
  1574. content,
  1575. /** @type {StatsPrinterContext & Required<KnownStatsPrinterColorFunctions>} */
  1576. (context),
  1577. ...args
  1578. );
  1579. }
  1580. context.timeReference = compilation.time;
  1581. });
  1582. for (const key of Object.keys(COMPILATION_SIMPLE_PRINTERS)) {
  1583. stats.hooks.print.for(key).tap(PLUGIN_NAME, (obj, ctx) =>
  1584. /** @type {TODO} */
  1585. (
  1586. COMPILATION_SIMPLE_PRINTERS[
  1587. /** @type {keyof CompilationSimplePrinters} */
  1588. (key)
  1589. ]
  1590. )(
  1591. obj,
  1592. /** @type {DefineStatsPrinterContext<"compilation">} */
  1593. (ctx),
  1594. stats
  1595. )
  1596. );
  1597. }
  1598. for (const key of Object.keys(ASSET_SIMPLE_PRINTERS)) {
  1599. stats.hooks.print.for(key).tap(PLUGIN_NAME, (obj, ctx) =>
  1600. /** @type {NonNullable<AssetSimplePrinters[keyof AssetSimplePrinters]>} */
  1601. (
  1602. ASSET_SIMPLE_PRINTERS[
  1603. /** @type {keyof AssetSimplePrinters} */
  1604. (key)
  1605. ]
  1606. )(
  1607. obj,
  1608. /** @type {DefineStatsPrinterContext<"asset" | "asset.info">} */
  1609. (ctx),
  1610. stats
  1611. )
  1612. );
  1613. }
  1614. for (const key of Object.keys(MODULE_SIMPLE_PRINTERS)) {
  1615. stats.hooks.print.for(key).tap(PLUGIN_NAME, (obj, ctx) =>
  1616. /** @type {TODO} */
  1617. (
  1618. MODULE_SIMPLE_PRINTERS[
  1619. /** @type {keyof ModuleSimplePrinters} */
  1620. (key)
  1621. ]
  1622. )(
  1623. obj,
  1624. /** @type {DefineStatsPrinterContext<"module">} */
  1625. (ctx),
  1626. stats
  1627. )
  1628. );
  1629. }
  1630. for (const key of Object.keys(MODULE_ISSUER_PRINTERS)) {
  1631. stats.hooks.print.for(key).tap(PLUGIN_NAME, (obj, ctx) =>
  1632. /** @type {NonNullable<ModuleIssuerPrinters[keyof ModuleIssuerPrinters]>} */
  1633. (
  1634. MODULE_ISSUER_PRINTERS[
  1635. /** @type {keyof ModuleIssuerPrinters} */
  1636. (key)
  1637. ]
  1638. )(
  1639. obj,
  1640. /** @type {DefineStatsPrinterContext<"moduleIssuer">} */
  1641. (ctx),
  1642. stats
  1643. )
  1644. );
  1645. }
  1646. for (const key of Object.keys(MODULE_REASON_PRINTERS)) {
  1647. stats.hooks.print.for(key).tap(PLUGIN_NAME, (obj, ctx) =>
  1648. /** @type {TODO} */
  1649. (
  1650. MODULE_REASON_PRINTERS[
  1651. /** @type {keyof ModuleReasonsPrinters} */
  1652. (key)
  1653. ]
  1654. )(
  1655. obj,
  1656. /** @type {DefineStatsPrinterContext<"moduleReason">} */
  1657. (ctx),
  1658. stats
  1659. )
  1660. );
  1661. }
  1662. for (const key of Object.keys(MODULE_PROFILE_PRINTERS)) {
  1663. stats.hooks.print.for(key).tap(PLUGIN_NAME, (obj, ctx) =>
  1664. /** @type {NonNullable<ModuleProfilePrinters[keyof ModuleProfilePrinters]>} */
  1665. (
  1666. MODULE_PROFILE_PRINTERS[
  1667. /** @type {keyof ModuleProfilePrinters} */
  1668. (key)
  1669. ]
  1670. )(
  1671. obj,
  1672. /** @type {DefineStatsPrinterContext<"profile">} */
  1673. (ctx),
  1674. stats
  1675. )
  1676. );
  1677. }
  1678. for (const key of Object.keys(CHUNK_GROUP_PRINTERS)) {
  1679. stats.hooks.print.for(key).tap(PLUGIN_NAME, (obj, ctx) =>
  1680. /** @type {TODO} */
  1681. (
  1682. CHUNK_GROUP_PRINTERS[
  1683. /** @type {keyof ChunkGroupPrinters} */
  1684. (key)
  1685. ]
  1686. )(
  1687. obj,
  1688. /** @type {DefineStatsPrinterContext<"chunkGroupKind" | "chunkGroup">} */
  1689. (ctx),
  1690. stats
  1691. )
  1692. );
  1693. }
  1694. for (const key of Object.keys(CHUNK_PRINTERS)) {
  1695. stats.hooks.print.for(key).tap(PLUGIN_NAME, (obj, ctx) =>
  1696. /** @type {TODO} */
  1697. (CHUNK_PRINTERS[/** @type {keyof ChunkPrinters} */ (key)])(
  1698. obj,
  1699. /** @type {DefineStatsPrinterContext<"chunk">} */
  1700. (ctx),
  1701. stats
  1702. )
  1703. );
  1704. }
  1705. for (const key of Object.keys(ERROR_PRINTERS)) {
  1706. stats.hooks.print.for(key).tap(PLUGIN_NAME, (obj, ctx) =>
  1707. /** @type {TODO} */
  1708. (ERROR_PRINTERS[/** @type {keyof ErrorPrinters} */ (key)])(
  1709. obj,
  1710. /** @type {DefineStatsPrinterContext<"error">} */
  1711. (ctx),
  1712. stats
  1713. )
  1714. );
  1715. }
  1716. for (const key of Object.keys(LOG_ENTRY_PRINTERS)) {
  1717. stats.hooks.print.for(key).tap(PLUGIN_NAME, (obj, ctx) =>
  1718. /** @type {TODO} */
  1719. (
  1720. LOG_ENTRY_PRINTERS[
  1721. /** @type {keyof LogEntryPrinters} */
  1722. (key)
  1723. ]
  1724. )(
  1725. obj,
  1726. /** @type {DefineStatsPrinterContext<"logging">} */
  1727. (ctx),
  1728. stats
  1729. )
  1730. );
  1731. }
  1732. for (const key of Object.keys(MODULE_TRACE_DEPENDENCY_PRINTERS)) {
  1733. stats.hooks.print.for(key).tap(PLUGIN_NAME, (obj, ctx) =>
  1734. /** @type {NonNullable<ModuleTraceDependencyPrinters[keyof ModuleTraceDependencyPrinters]>} */
  1735. (
  1736. MODULE_TRACE_DEPENDENCY_PRINTERS[
  1737. /** @type {keyof ModuleTraceDependencyPrinters} */
  1738. (key)
  1739. ]
  1740. )(
  1741. obj,
  1742. /** @type {DefineStatsPrinterContext<"moduleTraceDependency">} */
  1743. (ctx),
  1744. stats
  1745. )
  1746. );
  1747. }
  1748. for (const key of Object.keys(MODULE_TRACE_ITEM_PRINTERS)) {
  1749. stats.hooks.print.for(key).tap(PLUGIN_NAME, (obj, ctx) =>
  1750. /** @type {NonNullable<ModuleTraceItemPrinters[keyof ModuleTraceItemPrinters]>} */
  1751. (
  1752. MODULE_TRACE_ITEM_PRINTERS[
  1753. /** @type {keyof ModuleTraceItemPrinters} */
  1754. (key)
  1755. ]
  1756. )(
  1757. obj,
  1758. /** @type {DefineStatsPrinterContext<"moduleTraceItem">} */
  1759. (ctx),
  1760. stats
  1761. )
  1762. );
  1763. }
  1764. for (const key of Object.keys(PREFERRED_ORDERS)) {
  1765. const preferredOrder = PREFERRED_ORDERS[key];
  1766. stats.hooks.sortElements
  1767. .for(key)
  1768. .tap(PLUGIN_NAME, (elements, _context) => {
  1769. createOrder(elements, preferredOrder);
  1770. });
  1771. }
  1772. for (const key of Object.keys(ITEM_NAMES)) {
  1773. const itemName = ITEM_NAMES[key];
  1774. stats.hooks.getItemName
  1775. .for(key)
  1776. .tap(
  1777. PLUGIN_NAME,
  1778. typeof itemName === "string" ? () => itemName : itemName
  1779. );
  1780. }
  1781. for (const key of Object.keys(SIMPLE_ITEMS_JOINER)) {
  1782. const joiner = SIMPLE_ITEMS_JOINER[key];
  1783. stats.hooks.printItems.for(key).tap(PLUGIN_NAME, joiner);
  1784. }
  1785. for (const key of Object.keys(SIMPLE_ELEMENT_JOINERS)) {
  1786. const joiner = SIMPLE_ELEMENT_JOINERS[key];
  1787. stats.hooks.printElements
  1788. .for(key)
  1789. .tap(PLUGIN_NAME, /** @type {TODO} */ (joiner));
  1790. }
  1791. for (const key of Object.keys(RESULT_MODIFIER)) {
  1792. const modifier = RESULT_MODIFIER[key];
  1793. stats.hooks.result.for(key).tap(PLUGIN_NAME, modifier);
  1794. }
  1795. });
  1796. });
  1797. }
  1798. }
  1799. module.exports = DefaultStatsPrinterPlugin;