| 1 | /*
|
|---|
| 2 | MIT License http://www.opensource.org/licenses/mit-license.php
|
|---|
| 3 | Author Tobias Koppers @sokra
|
|---|
| 4 | */
|
|---|
| 5 |
|
|---|
| 6 | "use strict";
|
|---|
| 7 |
|
|---|
| 8 | const RequestShortener = require("../RequestShortener");
|
|---|
| 9 |
|
|---|
| 10 | /** @typedef {import("../../declarations/WebpackOptions").StatsOptions} StatsOptions */
|
|---|
| 11 | /** @typedef {import("../../declarations/WebpackOptions").StatsValue} StatsValue */
|
|---|
| 12 | /** @typedef {import("../Compilation")} Compilation */
|
|---|
| 13 | /** @typedef {import("../Compilation").CreateStatsOptionsContext} CreateStatsOptionsContext */
|
|---|
| 14 | /** @typedef {import("../Compilation").KnownNormalizedStatsOptions} KnownNormalizedStatsOptions */
|
|---|
| 15 | /** @typedef {import("../Compilation").NormalizedStatsOptions} NormalizedStatsOptions */
|
|---|
| 16 | /** @typedef {import("../Compiler")} Compiler */
|
|---|
| 17 | /** @typedef {import("./DefaultStatsFactoryPlugin").StatsError} StatsError */
|
|---|
| 18 |
|
|---|
| 19 | /**
|
|---|
| 20 | * Processes the provided normalized stats option.
|
|---|
| 21 | * @param {Partial<NormalizedStatsOptions>} options options
|
|---|
| 22 | * @param {StatsOptions} defaults default options
|
|---|
| 23 | */
|
|---|
| 24 | const applyDefaults = (options, defaults) => {
|
|---|
| 25 | for (const _k of Object.keys(defaults)) {
|
|---|
| 26 | const key = /** @type {keyof StatsOptions} */ (_k);
|
|---|
| 27 | if (typeof options[key] === "undefined") {
|
|---|
| 28 | options[/** @type {keyof NormalizedStatsOptions} */ (key)] =
|
|---|
| 29 | defaults[key];
|
|---|
| 30 | }
|
|---|
| 31 | }
|
|---|
| 32 | };
|
|---|
| 33 |
|
|---|
| 34 | /** @typedef {{ [Key in Exclude<StatsValue, boolean | StatsOptions | "normal">]: StatsOptions }} NamedPresets */
|
|---|
| 35 |
|
|---|
| 36 | /** @type {NamedPresets} */
|
|---|
| 37 | const NAMED_PRESETS = {
|
|---|
| 38 | verbose: {
|
|---|
| 39 | hash: true,
|
|---|
| 40 | builtAt: true,
|
|---|
| 41 | relatedAssets: true,
|
|---|
| 42 | entrypoints: true,
|
|---|
| 43 | chunkGroups: true,
|
|---|
| 44 | ids: true,
|
|---|
| 45 | modules: false,
|
|---|
| 46 | chunks: true,
|
|---|
| 47 | chunkRelations: true,
|
|---|
| 48 | chunkModules: true,
|
|---|
| 49 | dependentModules: true,
|
|---|
| 50 | chunkOrigins: true,
|
|---|
| 51 | depth: true,
|
|---|
| 52 | env: true,
|
|---|
| 53 | reasons: true,
|
|---|
| 54 | usedExports: true,
|
|---|
| 55 | providedExports: true,
|
|---|
| 56 | optimizationBailout: true,
|
|---|
| 57 | errorDetails: true,
|
|---|
| 58 | errorStack: true,
|
|---|
| 59 | errorCause: true,
|
|---|
| 60 | errorErrors: true,
|
|---|
| 61 | publicPath: true,
|
|---|
| 62 | logging: "verbose",
|
|---|
| 63 | orphanModules: true,
|
|---|
| 64 | runtimeModules: true,
|
|---|
| 65 | exclude: false,
|
|---|
| 66 | errorsSpace: Infinity,
|
|---|
| 67 | warningsSpace: Infinity,
|
|---|
| 68 | modulesSpace: Infinity,
|
|---|
| 69 | chunkModulesSpace: Infinity,
|
|---|
| 70 | assetsSpace: Infinity,
|
|---|
| 71 | reasonsSpace: Infinity,
|
|---|
| 72 | children: true
|
|---|
| 73 | },
|
|---|
| 74 | detailed: {
|
|---|
| 75 | hash: true,
|
|---|
| 76 | builtAt: true,
|
|---|
| 77 | relatedAssets: true,
|
|---|
| 78 | entrypoints: true,
|
|---|
| 79 | chunkGroups: true,
|
|---|
| 80 | ids: true,
|
|---|
| 81 | chunks: true,
|
|---|
| 82 | chunkRelations: true,
|
|---|
| 83 | chunkModules: false,
|
|---|
| 84 | chunkOrigins: true,
|
|---|
| 85 | depth: true,
|
|---|
| 86 | usedExports: true,
|
|---|
| 87 | providedExports: true,
|
|---|
| 88 | optimizationBailout: true,
|
|---|
| 89 | errorDetails: true,
|
|---|
| 90 | errorCause: true,
|
|---|
| 91 | errorErrors: true,
|
|---|
| 92 | publicPath: true,
|
|---|
| 93 | logging: true,
|
|---|
| 94 | runtimeModules: true,
|
|---|
| 95 | exclude: false,
|
|---|
| 96 | errorsSpace: 1000,
|
|---|
| 97 | warningsSpace: 1000,
|
|---|
| 98 | modulesSpace: 1000,
|
|---|
| 99 | assetsSpace: 1000,
|
|---|
| 100 | reasonsSpace: 1000
|
|---|
| 101 | },
|
|---|
| 102 | minimal: {
|
|---|
| 103 | all: false,
|
|---|
| 104 | version: true,
|
|---|
| 105 | timings: true,
|
|---|
| 106 | modules: true,
|
|---|
| 107 | errorsSpace: 0,
|
|---|
| 108 | warningsSpace: 0,
|
|---|
| 109 | modulesSpace: 0,
|
|---|
| 110 | assets: true,
|
|---|
| 111 | assetsSpace: 0,
|
|---|
| 112 | errors: true,
|
|---|
| 113 | errorsCount: true,
|
|---|
| 114 | warnings: true,
|
|---|
| 115 | warningsCount: true,
|
|---|
| 116 | logging: "warn"
|
|---|
| 117 | },
|
|---|
| 118 | "errors-only": {
|
|---|
| 119 | all: false,
|
|---|
| 120 | errors: true,
|
|---|
| 121 | errorsCount: true,
|
|---|
| 122 | errorsSpace: Infinity,
|
|---|
| 123 | moduleTrace: true,
|
|---|
| 124 | logging: "error"
|
|---|
| 125 | },
|
|---|
| 126 | "errors-warnings": {
|
|---|
| 127 | all: false,
|
|---|
| 128 | errors: true,
|
|---|
| 129 | errorsCount: true,
|
|---|
| 130 | errorsSpace: Infinity,
|
|---|
| 131 | warnings: true,
|
|---|
| 132 | warningsCount: true,
|
|---|
| 133 | warningsSpace: Infinity,
|
|---|
| 134 | logging: "warn"
|
|---|
| 135 | },
|
|---|
| 136 | summary: {
|
|---|
| 137 | all: false,
|
|---|
| 138 | version: true,
|
|---|
| 139 | errorsCount: true,
|
|---|
| 140 | warningsCount: true
|
|---|
| 141 | },
|
|---|
| 142 | none: {
|
|---|
| 143 | all: false
|
|---|
| 144 | }
|
|---|
| 145 | };
|
|---|
| 146 |
|
|---|
| 147 | /**
|
|---|
| 148 | * Returns true when enabled, otherwise false.
|
|---|
| 149 | * @param {Partial<NormalizedStatsOptions>} all stats options
|
|---|
| 150 | * @returns {boolean} true when enabled, otherwise false
|
|---|
| 151 | */
|
|---|
| 152 | const NORMAL_ON = ({ all }) => all !== false;
|
|---|
| 153 | /**
|
|---|
| 154 | * Returns true when enabled, otherwise false.
|
|---|
| 155 | * @param {Partial<NormalizedStatsOptions>} all stats options
|
|---|
| 156 | * @returns {boolean} true when enabled, otherwise false
|
|---|
| 157 | */
|
|---|
| 158 | const NORMAL_OFF = ({ all }) => all === true;
|
|---|
| 159 | /**
|
|---|
| 160 | * Returns true when enabled, otherwise false.
|
|---|
| 161 | * @param {Partial<NormalizedStatsOptions>} all stats options
|
|---|
| 162 | * @param {CreateStatsOptionsContext} forToString stats options context
|
|---|
| 163 | * @returns {boolean} true when enabled, otherwise false
|
|---|
| 164 | */
|
|---|
| 165 | const ON_FOR_TO_STRING = ({ all }, { forToString }) =>
|
|---|
| 166 | forToString ? all !== false : all === true;
|
|---|
| 167 | /**
|
|---|
| 168 | * Returns true when enabled, otherwise false.
|
|---|
| 169 | * @param {Partial<NormalizedStatsOptions>} all stats options
|
|---|
| 170 | * @param {CreateStatsOptionsContext} forToString stats options context
|
|---|
| 171 | * @returns {boolean} true when enabled, otherwise false
|
|---|
| 172 | */
|
|---|
| 173 | const OFF_FOR_TO_STRING = ({ all }, { forToString }) =>
|
|---|
| 174 | forToString ? all === true : all !== false;
|
|---|
| 175 | /**
|
|---|
| 176 | * Auto for to string.
|
|---|
| 177 | * @param {Partial<NormalizedStatsOptions>} all stats options
|
|---|
| 178 | * @param {CreateStatsOptionsContext} forToString stats options context
|
|---|
| 179 | * @returns {boolean | "auto"} true when enabled, otherwise false
|
|---|
| 180 | */
|
|---|
| 181 | const AUTO_FOR_TO_STRING = ({ all }, { forToString }) => {
|
|---|
| 182 | if (all === false) return false;
|
|---|
| 183 | if (all === true) return true;
|
|---|
| 184 | if (forToString) return "auto";
|
|---|
| 185 | return true;
|
|---|
| 186 | };
|
|---|
| 187 |
|
|---|
| 188 | /** @typedef {keyof NormalizedStatsOptions} DefaultsKeys */
|
|---|
| 189 | /** @typedef {{ [Key in DefaultsKeys]: (options: Partial<NormalizedStatsOptions>, context: CreateStatsOptionsContext, compilation: Compilation) => NormalizedStatsOptions[Key] | RequestShortener }} Defaults */
|
|---|
| 190 |
|
|---|
| 191 | /** @type {Defaults} */
|
|---|
| 192 | const DEFAULTS = {
|
|---|
| 193 | context: (options, context, compilation) => compilation.compiler.context,
|
|---|
| 194 | requestShortener: (options, context, compilation) =>
|
|---|
| 195 | compilation.compiler.context === options.context
|
|---|
| 196 | ? compilation.requestShortener
|
|---|
| 197 | : new RequestShortener(
|
|---|
| 198 | /** @type {string} */
|
|---|
| 199 | (options.context),
|
|---|
| 200 | compilation.compiler.root
|
|---|
| 201 | ),
|
|---|
| 202 | performance: NORMAL_ON,
|
|---|
| 203 | hash: OFF_FOR_TO_STRING,
|
|---|
| 204 | env: NORMAL_OFF,
|
|---|
| 205 | version: NORMAL_ON,
|
|---|
| 206 | timings: NORMAL_ON,
|
|---|
| 207 | builtAt: OFF_FOR_TO_STRING,
|
|---|
| 208 | assets: NORMAL_ON,
|
|---|
| 209 | entrypoints: AUTO_FOR_TO_STRING,
|
|---|
| 210 | chunkGroups: OFF_FOR_TO_STRING,
|
|---|
| 211 | chunkGroupAuxiliary: OFF_FOR_TO_STRING,
|
|---|
| 212 | chunkGroupChildren: OFF_FOR_TO_STRING,
|
|---|
| 213 | chunkGroupMaxAssets: (o, { forToString }) => (forToString ? 5 : Infinity),
|
|---|
| 214 | chunks: OFF_FOR_TO_STRING,
|
|---|
| 215 | chunkRelations: OFF_FOR_TO_STRING,
|
|---|
| 216 | chunkModules: ({ all, modules }) => {
|
|---|
| 217 | if (all === false) return false;
|
|---|
| 218 | if (all === true) return true;
|
|---|
| 219 | if (modules) return false;
|
|---|
| 220 | return true;
|
|---|
| 221 | },
|
|---|
| 222 | dependentModules: OFF_FOR_TO_STRING,
|
|---|
| 223 | chunkOrigins: OFF_FOR_TO_STRING,
|
|---|
| 224 | ids: OFF_FOR_TO_STRING,
|
|---|
| 225 | modules: ({ all, chunks, chunkModules }, { forToString }) => {
|
|---|
| 226 | if (all === false) return false;
|
|---|
| 227 | if (all === true) return true;
|
|---|
| 228 | if (forToString && chunks && chunkModules) return false;
|
|---|
| 229 | return true;
|
|---|
| 230 | },
|
|---|
| 231 | nestedModules: OFF_FOR_TO_STRING,
|
|---|
| 232 | groupModulesByType: ON_FOR_TO_STRING,
|
|---|
| 233 | groupModulesByCacheStatus: ON_FOR_TO_STRING,
|
|---|
| 234 | groupModulesByLayer: ON_FOR_TO_STRING,
|
|---|
| 235 | groupModulesByAttributes: ON_FOR_TO_STRING,
|
|---|
| 236 | groupModulesByPath: ON_FOR_TO_STRING,
|
|---|
| 237 | groupModulesByExtension: ON_FOR_TO_STRING,
|
|---|
| 238 | modulesSpace: (o, { forToString }) => (forToString ? 15 : Infinity),
|
|---|
| 239 | chunkModulesSpace: (o, { forToString }) => (forToString ? 10 : Infinity),
|
|---|
| 240 | nestedModulesSpace: (o, { forToString }) => (forToString ? 10 : Infinity),
|
|---|
| 241 | relatedAssets: OFF_FOR_TO_STRING,
|
|---|
| 242 | groupAssetsByEmitStatus: ON_FOR_TO_STRING,
|
|---|
| 243 | groupAssetsByInfo: ON_FOR_TO_STRING,
|
|---|
| 244 | groupAssetsByPath: ON_FOR_TO_STRING,
|
|---|
| 245 | groupAssetsByExtension: ON_FOR_TO_STRING,
|
|---|
| 246 | groupAssetsByChunk: ON_FOR_TO_STRING,
|
|---|
| 247 | assetsSpace: (o, { forToString }) => (forToString ? 15 : Infinity),
|
|---|
| 248 | orphanModules: OFF_FOR_TO_STRING,
|
|---|
| 249 | runtimeModules: ({ all, runtime }, { forToString }) =>
|
|---|
| 250 | runtime !== undefined
|
|---|
| 251 | ? runtime
|
|---|
| 252 | : forToString
|
|---|
| 253 | ? all === true
|
|---|
| 254 | : all !== false,
|
|---|
| 255 | cachedModules: ({ all, cached }, { forToString }) =>
|
|---|
| 256 | cached !== undefined ? cached : forToString ? all === true : all !== false,
|
|---|
| 257 | moduleAssets: OFF_FOR_TO_STRING,
|
|---|
| 258 | depth: OFF_FOR_TO_STRING,
|
|---|
| 259 | cachedAssets: OFF_FOR_TO_STRING,
|
|---|
| 260 | reasons: OFF_FOR_TO_STRING,
|
|---|
| 261 | reasonsSpace: (o, { forToString }) => (forToString ? 15 : Infinity),
|
|---|
| 262 | groupReasonsByOrigin: ON_FOR_TO_STRING,
|
|---|
| 263 | usedExports: OFF_FOR_TO_STRING,
|
|---|
| 264 | providedExports: OFF_FOR_TO_STRING,
|
|---|
| 265 | optimizationBailout: OFF_FOR_TO_STRING,
|
|---|
| 266 | children: OFF_FOR_TO_STRING,
|
|---|
| 267 | source: NORMAL_OFF,
|
|---|
| 268 | moduleTrace: NORMAL_ON,
|
|---|
| 269 | errors: NORMAL_ON,
|
|---|
| 270 | errorsCount: NORMAL_ON,
|
|---|
| 271 | errorDetails: AUTO_FOR_TO_STRING,
|
|---|
| 272 | errorStack: OFF_FOR_TO_STRING,
|
|---|
| 273 | errorCause: AUTO_FOR_TO_STRING,
|
|---|
| 274 | errorErrors: AUTO_FOR_TO_STRING,
|
|---|
| 275 | warnings: NORMAL_ON,
|
|---|
| 276 | warningsCount: NORMAL_ON,
|
|---|
| 277 | publicPath: OFF_FOR_TO_STRING,
|
|---|
| 278 | logging: ({ all }, { forToString }) =>
|
|---|
| 279 | forToString && all !== false ? "info" : false,
|
|---|
| 280 | loggingDebug: () => [],
|
|---|
| 281 | loggingTrace: OFF_FOR_TO_STRING,
|
|---|
| 282 | excludeModules: () => [],
|
|---|
| 283 | excludeAssets: () => [],
|
|---|
| 284 | modulesSort: () => "depth",
|
|---|
| 285 | chunkModulesSort: () => "name",
|
|---|
| 286 | nestedModulesSort: () => false,
|
|---|
| 287 | chunksSort: () => false,
|
|---|
| 288 | assetsSort: () => "!size",
|
|---|
| 289 | outputPath: OFF_FOR_TO_STRING,
|
|---|
| 290 | colors: () => false
|
|---|
| 291 | };
|
|---|
| 292 |
|
|---|
| 293 | /**
|
|---|
| 294 | * Defines the normalize function type used by this module.
|
|---|
| 295 | * @template T
|
|---|
| 296 | * @typedef {(value: T, ...args: EXPECTED_ANY[]) => boolean} NormalizeFunction
|
|---|
| 297 | */
|
|---|
| 298 |
|
|---|
| 299 | /**
|
|---|
| 300 | * Returns normalize fn.
|
|---|
| 301 | * @template {string} T
|
|---|
| 302 | * @param {string | ({ test: (value: T) => boolean }) | NormalizeFunction<T> | boolean} item item to normalize
|
|---|
| 303 | * @returns {NormalizeFunction<T>} normalize fn
|
|---|
| 304 | */
|
|---|
| 305 | const normalizeFilter = (item) => {
|
|---|
| 306 | if (typeof item === "string") {
|
|---|
| 307 | const regExp = new RegExp(
|
|---|
| 308 | `[\\\\/]${item.replace(/[-[\]{}()*+?.\\^$|]/g, "\\$&")}([\\\\/]|$|!|\\?)`
|
|---|
| 309 | );
|
|---|
| 310 | return (ident) => regExp.test(/** @type {T} */ (ident));
|
|---|
| 311 | }
|
|---|
| 312 | if (item && typeof item === "object" && typeof item.test === "function") {
|
|---|
| 313 | return (ident) => item.test(ident);
|
|---|
| 314 | }
|
|---|
| 315 | if (typeof item === "boolean") {
|
|---|
| 316 | return () => item;
|
|---|
| 317 | }
|
|---|
| 318 |
|
|---|
| 319 | return /** @type {NormalizeFunction<T>} */ (item);
|
|---|
| 320 | };
|
|---|
| 321 |
|
|---|
| 322 | /** @typedef {keyof (KnownNormalizedStatsOptions | StatsOptions)} NormalizerKeys */
|
|---|
| 323 | /** @typedef {{ [Key in NormalizerKeys]?: (value: StatsOptions[Key]) => KnownNormalizedStatsOptions[Key] }} Normalizers */
|
|---|
| 324 |
|
|---|
| 325 | /**
|
|---|
| 326 | * Defines the warning filter fn callback.
|
|---|
| 327 | * @callback WarningFilterFn
|
|---|
| 328 | * @param {StatsError} warning warning
|
|---|
| 329 | * @param {string} warningString warning string
|
|---|
| 330 | * @returns {boolean} result
|
|---|
| 331 | */
|
|---|
| 332 |
|
|---|
| 333 | /** @type {Normalizers} */
|
|---|
| 334 | const NORMALIZER = {
|
|---|
| 335 | excludeModules: (value) => {
|
|---|
| 336 | if (!Array.isArray(value)) {
|
|---|
| 337 | value = value
|
|---|
| 338 | ? /** @type {KnownNormalizedStatsOptions["excludeModules"]} */ ([value])
|
|---|
| 339 | : [];
|
|---|
| 340 | }
|
|---|
| 341 | return value.map(normalizeFilter);
|
|---|
| 342 | },
|
|---|
| 343 | excludeAssets: (value) => {
|
|---|
| 344 | if (!Array.isArray(value)) {
|
|---|
| 345 | value = value ? [value] : [];
|
|---|
| 346 | }
|
|---|
| 347 | return value.map(normalizeFilter);
|
|---|
| 348 | },
|
|---|
| 349 | warningsFilter: (value) => {
|
|---|
| 350 | if (!Array.isArray(value)) {
|
|---|
| 351 | value = value ? [value] : [];
|
|---|
| 352 | }
|
|---|
| 353 | return value.map(
|
|---|
| 354 | /**
|
|---|
| 355 | * Handles the warnings filter callback for this hook.
|
|---|
| 356 | * @param {StatsOptions["warningsFilter"]} filter a warning filter
|
|---|
| 357 | * @returns {WarningFilterFn} result
|
|---|
| 358 | */
|
|---|
| 359 | (filter) => {
|
|---|
| 360 | if (typeof filter === "string") {
|
|---|
| 361 | return (warning, warningString) => warningString.includes(filter);
|
|---|
| 362 | }
|
|---|
| 363 | if (filter instanceof RegExp) {
|
|---|
| 364 | return (warning, warningString) => filter.test(warningString);
|
|---|
| 365 | }
|
|---|
| 366 | if (typeof filter === "function") {
|
|---|
| 367 | return filter;
|
|---|
| 368 | }
|
|---|
| 369 | throw new Error(
|
|---|
| 370 | `Can only filter warnings with Strings or RegExps. (Given: ${filter})`
|
|---|
| 371 | );
|
|---|
| 372 | }
|
|---|
| 373 | );
|
|---|
| 374 | },
|
|---|
| 375 | logging: (value) => {
|
|---|
| 376 | if (value === true) value = "log";
|
|---|
| 377 | return /** @type {KnownNormalizedStatsOptions["logging"]} */ (value);
|
|---|
| 378 | },
|
|---|
| 379 | loggingDebug: (value) => {
|
|---|
| 380 | if (!Array.isArray(value)) {
|
|---|
| 381 | value = value
|
|---|
| 382 | ? /** @type {KnownNormalizedStatsOptions["loggingDebug"]} */ ([value])
|
|---|
| 383 | : [];
|
|---|
| 384 | }
|
|---|
| 385 | return value.map(normalizeFilter);
|
|---|
| 386 | }
|
|---|
| 387 | };
|
|---|
| 388 |
|
|---|
| 389 | const PLUGIN_NAME = "DefaultStatsPresetPlugin";
|
|---|
| 390 |
|
|---|
| 391 | class DefaultStatsPresetPlugin {
|
|---|
| 392 | /**
|
|---|
| 393 | * Applies the plugin by registering its hooks on the compiler.
|
|---|
| 394 | * @param {Compiler} compiler the compiler instance
|
|---|
| 395 | * @returns {void}
|
|---|
| 396 | */
|
|---|
| 397 | apply(compiler) {
|
|---|
| 398 | compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => {
|
|---|
| 399 | for (const key of Object.keys(NAMED_PRESETS)) {
|
|---|
| 400 | const defaults = NAMED_PRESETS[/** @type {keyof NamedPresets} */ (key)];
|
|---|
| 401 | compilation.hooks.statsPreset
|
|---|
| 402 | .for(key)
|
|---|
| 403 | .tap(PLUGIN_NAME, (options, _context) => {
|
|---|
| 404 | applyDefaults(options, defaults);
|
|---|
| 405 | });
|
|---|
| 406 | }
|
|---|
| 407 | compilation.hooks.statsNormalize.tap(PLUGIN_NAME, (options, context) => {
|
|---|
| 408 | for (const key of Object.keys(DEFAULTS)) {
|
|---|
| 409 | if (options[key] === undefined) {
|
|---|
| 410 | options[key] = DEFAULTS[/** @type {DefaultsKeys} */ (key)](
|
|---|
| 411 | options,
|
|---|
| 412 | context,
|
|---|
| 413 | compilation
|
|---|
| 414 | );
|
|---|
| 415 | }
|
|---|
| 416 | }
|
|---|
| 417 | for (const key of Object.keys(NORMALIZER)) {
|
|---|
| 418 | options[key] =
|
|---|
| 419 | /** @type {NonNullable<Normalizers[keyof Normalizers]>} */
|
|---|
| 420 | (NORMALIZER[/** @type {NormalizerKeys} */ (key)])(options[key]);
|
|---|
| 421 | }
|
|---|
| 422 | });
|
|---|
| 423 | });
|
|---|
| 424 | }
|
|---|
| 425 | }
|
|---|
| 426 |
|
|---|
| 427 | module.exports = DefaultStatsPresetPlugin;
|
|---|