diff --git a/lib/friendly-errors/asset-output-display-plugin.js b/lib/friendly-errors/asset-output-display-plugin.js deleted file mode 100644 index 2b380bca..00000000 --- a/lib/friendly-errors/asset-output-display-plugin.js +++ /dev/null @@ -1,31 +0,0 @@ -/* - * This file is part of the Symfony Webpack Encore package. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -import pc from 'picocolors'; - -function AssetOutputDisplayPlugin(outputPath, friendlyErrorsPlugin) { - this.outputPath = outputPath; - this.friendlyErrorsPlugin = friendlyErrorsPlugin; -} - -AssetOutputDisplayPlugin.prototype.apply = function (compiler) { - const emit = (compilation, callback) => { - // completely reset messages key to avoid adding more and more messages - // when using watch - this.friendlyErrorsPlugin.compilationSuccessInfo.messages = [ - `${pc.yellow(Object.keys(compilation.assets).length)} files written to ${pc.yellow(this.outputPath)}`, - ]; - - callback(); - }; - - compiler.hooks.emit.tapAsync({ name: 'AssetOutputDisplayPlugin' }, emit); -}; - -export default AssetOutputDisplayPlugin; diff --git a/lib/friendly-errors/asset-output-display-plugin.ts b/lib/friendly-errors/asset-output-display-plugin.ts new file mode 100644 index 00000000..974cbf87 --- /dev/null +++ b/lib/friendly-errors/asset-output-display-plugin.ts @@ -0,0 +1,41 @@ +/* + * This file is part of the Symfony Webpack Encore package. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +import type FriendlyErrorsWebpackPlugin from '@kocal/friendly-errors-webpack-plugin'; +import pc from 'picocolors'; +import type { Compilation, Compiler } from 'webpack'; + +class AssetOutputDisplayPlugin { + outputPath: string; + friendlyErrorsPlugin: FriendlyErrorsWebpackPlugin; + + constructor(outputPath: string, friendlyErrorsPlugin: FriendlyErrorsWebpackPlugin) { + this.outputPath = outputPath; + this.friendlyErrorsPlugin = friendlyErrorsPlugin; + } + + apply(compiler: Compiler): void { + const emit = (compilation: Compilation, callback: () => void) => { + // completely reset messages key to avoid adding more and more messages + // when using watch + const plugin = this.friendlyErrorsPlugin as FriendlyErrorsWebpackPlugin & { + compilationSuccessInfo: { messages: string[] }; + }; + plugin.compilationSuccessInfo.messages = [ + `${pc.yellow(Object.keys(compilation.assets).length)} files written to ${pc.yellow(this.outputPath)}`, + ]; + + callback(); + }; + + compiler.hooks.emit.tapAsync({ name: 'AssetOutputDisplayPlugin' }, emit); + } +} + +export default AssetOutputDisplayPlugin; diff --git a/lib/friendly-errors/formatters/missing-css-file.js b/lib/friendly-errors/formatters/missing-css-file.ts similarity index 70% rename from lib/friendly-errors/formatters/missing-css-file.js rename to lib/friendly-errors/formatters/missing-css-file.ts index a98568ba..2061909b 100644 --- a/lib/friendly-errors/formatters/missing-css-file.js +++ b/lib/friendly-errors/formatters/missing-css-file.ts @@ -7,17 +7,22 @@ * file that was distributed with this source code. */ +import type { FriendlyError } from '@kocal/friendly-errors-webpack-plugin'; import pc from 'picocolors'; -function formatErrors(errors) { +interface MissingCssFileError extends FriendlyError { + ref?: string; +} + +function formatErrors(errors: MissingCssFileError[]): string[] { if (errors.length === 0) { return []; } - let messages = []; + const messages: string[] = []; messages.push(pc.red('Module build failed: Module not found:')); - for (let error of errors) { + for (const error of errors) { messages.push(`"${error.file}" contains a reference to the file "${error.ref}".`); messages.push( 'This file can not be found, please check it for typos or update it if the file got moved.' @@ -28,7 +33,7 @@ function formatErrors(errors) { return messages; } -function format(errors) { +function format(errors: FriendlyError[]): string[] { return formatErrors(errors.filter((e) => e.type === 'missing-css-file')); } diff --git a/lib/friendly-errors/formatters/missing-loader.js b/lib/friendly-errors/formatters/missing-loader.ts similarity index 75% rename from lib/friendly-errors/formatters/missing-loader.js rename to lib/friendly-errors/formatters/missing-loader.ts index 94409050..87d1d26e 100644 --- a/lib/friendly-errors/formatters/missing-loader.js +++ b/lib/friendly-errors/formatters/missing-loader.ts @@ -7,22 +7,29 @@ * file that was distributed with this source code. */ +import type { FriendlyError } from '@kocal/friendly-errors-webpack-plugin'; import pc from 'picocolors'; import loaderFeatures from '../../features.js'; -function formatErrors(errors) { +interface MissingLoaderError extends FriendlyError { + loaderName?: string; + isVueLoader?: boolean; + origin?: string; +} + +function formatErrors(errors: MissingLoaderError[]): string[] { if (errors.length === 0) { return []; } - let messages = []; + let messages: string[] = []; - for (let error of errors) { - const fixes = []; + for (const error of errors) { + const fixes: string[] = []; if (error.loaderName) { - let neededCode = `Encore.${loaderFeatures.getFeatureMethod(error.loaderName)}`; + const neededCode = `Encore.${loaderFeatures.getFeatureMethod(error.loaderName)}`; fixes.push(`Add ${pc.green(neededCode)} to your Webpack config file.`); const packageRecommendations = loaderFeatures.getMissingPackageRecommendations( @@ -43,7 +50,7 @@ function formatErrors(errors) { // vue hides their filenames (via a stacktrace) inside error.origin if (error.isVueLoader) { messages.push(error.message); - messages.push(error.origin); + messages.push(error.origin ?? ''); messages.push(''); } else { messages = messages.concat([pc.red(`Error loading ${pc.yellow(error.file)}`), '']); @@ -58,7 +65,7 @@ function formatErrors(errors) { } let index = 0; - for (let fix of fixes) { + for (const fix of fixes) { messages.push(` ${++index}. ${fix}`); } @@ -68,7 +75,7 @@ function formatErrors(errors) { return messages; } -function format(errors) { +function format(errors: FriendlyError[]): string[] { return formatErrors(errors.filter((e) => e.type === 'loader-not-enabled')); } diff --git a/lib/friendly-errors/formatters/missing-postcss-config.js b/lib/friendly-errors/formatters/missing-postcss-config.ts similarity index 85% rename from lib/friendly-errors/formatters/missing-postcss-config.js rename to lib/friendly-errors/formatters/missing-postcss-config.ts index 879213e1..68d0ec14 100644 --- a/lib/friendly-errors/formatters/missing-postcss-config.js +++ b/lib/friendly-errors/formatters/missing-postcss-config.ts @@ -7,14 +7,15 @@ * file that was distributed with this source code. */ +import type { FriendlyError } from '@kocal/friendly-errors-webpack-plugin'; import pc from 'picocolors'; -function formatErrors(errors) { +function formatErrors(errors: FriendlyError[]): string[] { if (errors.length === 0) { return []; } - let messages = []; + const messages: string[] = []; // there will be an error for *every* file, but showing // the error over and over again is not helpful @@ -50,7 +51,7 @@ module.exports = { return messages; } -function format(errors) { +function format(errors: FriendlyError[]): string[] { return formatErrors(errors.filter((e) => e.type === 'missing-postcss-config')); } diff --git a/lib/friendly-errors/transformers/missing-css-file.js b/lib/friendly-errors/transformers/missing-css-file.ts similarity index 78% rename from lib/friendly-errors/transformers/missing-css-file.js rename to lib/friendly-errors/transformers/missing-css-file.ts index 867c64fe..0d095109 100644 --- a/lib/friendly-errors/transformers/missing-css-file.js +++ b/lib/friendly-errors/transformers/missing-css-file.ts @@ -7,9 +7,11 @@ * file that was distributed with this source code. */ +import type { FriendlyError } from '@kocal/friendly-errors-webpack-plugin'; + const TYPE = 'missing-css-file'; -function isMissingConfigError(e) { +function isMissingConfigError(e: FriendlyError): boolean { if (e.name !== 'ModuleNotFoundError') { return false; } @@ -21,14 +23,14 @@ function isMissingConfigError(e) { return true; } -function getReference(error) { +function getReference(error: FriendlyError): string { const index = error.message.indexOf("Can't resolve '") + 15; const endIndex = error.message.indexOf("' in '"); return error.message.substring(index, endIndex); } -function transform(error) { +function transform(error: FriendlyError): FriendlyError { if (!isMissingConfigError(error)) { return error; } diff --git a/lib/friendly-errors/transformers/missing-loader.js b/lib/friendly-errors/transformers/missing-loader.ts similarity index 73% rename from lib/friendly-errors/transformers/missing-loader.js rename to lib/friendly-errors/transformers/missing-loader.ts index afff0045..238a8ac7 100644 --- a/lib/friendly-errors/transformers/missing-loader.js +++ b/lib/friendly-errors/transformers/missing-loader.ts @@ -7,11 +7,14 @@ * file that was distributed with this source code. */ +import type { FriendlyError, Transformer } from '@kocal/friendly-errors-webpack-plugin'; + import getVueVersion from '../../utils/get-vue-version.ts'; +import type WebpackConfig from '../../WebpackConfig.js'; const TYPE = 'loader-not-enabled'; -function isMissingLoaderError(e) { +function isMissingLoaderError(e: FriendlyError): boolean { if (e.name !== 'ModuleParseError') { return false; } @@ -23,7 +26,7 @@ function isMissingLoaderError(e) { return true; } -function isErrorFromVueLoader(filename) { +function isErrorFromVueLoader(filename: string): boolean { // vue3 if (/vue-loader\/dist(\/index\.js)?\?\?/.test(filename)) { return true; @@ -37,7 +40,7 @@ function isErrorFromVueLoader(filename) { return false; } -function getFileExtension(filename) { +function getFileExtension(filename: string): string { // ??vue-loader-options if (isErrorFromVueLoader(filename)) { // vue is strange, the "filename" is reported as something like @@ -54,18 +57,20 @@ function getFileExtension(filename) { const str = filename.replace(/\?.*/, ''); const split = str.split('.'); - return split.pop(); + return split.pop() ?? ''; } -function transform(error, webpackConfig) { +function transform(error: FriendlyError, webpackConfig: WebpackConfig): FriendlyError { if (!isMissingLoaderError(error)) { return error; } error = Object.assign({}, error); - error.isVueLoader = isErrorFromVueLoader(error.file); - const extension = getFileExtension(error.file); + const filename = error.file ?? ''; + error.isVueLoader = isErrorFromVueLoader(filename); + + const extension = getFileExtension(filename); switch (extension) { case 'sass': case 'scss': @@ -78,7 +83,7 @@ function transform(error, webpackConfig) { error.loaderName = 'react'; break; case 'vue': - error.loaderName = 'vue' + getVueVersion(webpackConfig); + error.loaderName = `vue${getVueVersion(webpackConfig)}`; break; case 'tsx': case 'ts': @@ -99,8 +104,8 @@ function transform(error, webpackConfig) { /* * Returns a factory to get the function. */ -export default function (webpackConfig) { - return function (error) { +export default function (webpackConfig: WebpackConfig): Transformer { + return function (error: FriendlyError): FriendlyError { return transform(error, webpackConfig); }; } diff --git a/lib/friendly-errors/transformers/missing-postcss-config.js b/lib/friendly-errors/transformers/missing-postcss-config.ts similarity index 75% rename from lib/friendly-errors/transformers/missing-postcss-config.js rename to lib/friendly-errors/transformers/missing-postcss-config.ts index f0471ee1..df8633a0 100644 --- a/lib/friendly-errors/transformers/missing-postcss-config.js +++ b/lib/friendly-errors/transformers/missing-postcss-config.ts @@ -7,9 +7,11 @@ * file that was distributed with this source code. */ +import type { FriendlyError } from '@kocal/friendly-errors-webpack-plugin'; + const TYPE = 'missing-postcss-config'; -function isMissingConfigError(e) { +function isMissingConfigError(e: FriendlyError): boolean { if (!e.message || !e.message.includes('No PostCSS Config found')) { return false; } @@ -17,7 +19,7 @@ function isMissingConfigError(e) { return true; } -function transform(error) { +function transform(error: FriendlyError): FriendlyError { if (!isMissingConfigError(error)) { return error; } diff --git a/lib/plugins/asset-output-display.ts b/lib/plugins/asset-output-display.ts index 24a34970..824e8737 100644 --- a/lib/plugins/asset-output-display.ts +++ b/lib/plugins/asset-output-display.ts @@ -10,7 +10,7 @@ import type FriendlyErrorsWebpackPlugin from '@kocal/friendly-errors-webpack-plugin'; import pathUtil from '../config/path-util.js'; -import AssetOutputDisplayPlugin from '../friendly-errors/asset-output-display-plugin.js'; +import AssetOutputDisplayPlugin from '../friendly-errors/asset-output-display-plugin.ts'; import type WebpackConfig from '../WebpackConfig.js'; import PluginPriorities from './plugin-priorities.ts'; diff --git a/lib/plugins/friendly-errors.ts b/lib/plugins/friendly-errors.ts index 1342f411..07b3bf6d 100644 --- a/lib/plugins/friendly-errors.ts +++ b/lib/plugins/friendly-errors.ts @@ -9,12 +9,12 @@ import FriendlyErrorsWebpackPlugin from '@kocal/friendly-errors-webpack-plugin'; -import missingCssFileFormatter from '../friendly-errors/formatters/missing-css-file.js'; -import missingLoaderFormatter from '../friendly-errors/formatters/missing-loader.js'; -import missingPostCssConfigFormatter from '../friendly-errors/formatters/missing-postcss-config.js'; -import missingCssFileTransformer from '../friendly-errors/transformers/missing-css-file.js'; -import missingLoaderTransformerFactory from '../friendly-errors/transformers/missing-loader.js'; -import missingPostCssConfigTransformer from '../friendly-errors/transformers/missing-postcss-config.js'; +import missingCssFileFormatter from '../friendly-errors/formatters/missing-css-file.ts'; +import missingLoaderFormatter from '../friendly-errors/formatters/missing-loader.ts'; +import missingPostCssConfigFormatter from '../friendly-errors/formatters/missing-postcss-config.ts'; +import missingCssFileTransformer from '../friendly-errors/transformers/missing-css-file.ts'; +import missingLoaderTransformerFactory from '../friendly-errors/transformers/missing-loader.ts'; +import missingPostCssConfigTransformer from '../friendly-errors/transformers/missing-postcss-config.ts'; import applyOptionsCallback from '../utils/apply-options-callback.ts'; import type WebpackConfig from '../WebpackConfig.js'; diff --git a/test/friendly-errors/formatters/missing-css-file.js b/test/friendly-errors/formatters/missing-css-file.js index 20dd294c..7c1a2d9c 100644 --- a/test/friendly-errors/formatters/missing-css-file.js +++ b/test/friendly-errors/formatters/missing-css-file.js @@ -9,7 +9,7 @@ import { describe, it, expect } from 'vitest'; -import formatter from '../../../lib/friendly-errors/formatters/missing-css-file.js'; +import formatter from '../../../lib/friendly-errors/formatters/missing-css-file.ts'; describe('formatters/missing-css-file', function () { describe('test format()', function () { diff --git a/test/friendly-errors/formatters/missing-loader.js b/test/friendly-errors/formatters/missing-loader.js index cf5e2022..2da33891 100644 --- a/test/friendly-errors/formatters/missing-loader.js +++ b/test/friendly-errors/formatters/missing-loader.js @@ -9,7 +9,7 @@ import { describe, it, expect } from 'vitest'; -import formatter from '../../../lib/friendly-errors/formatters/missing-loader.js'; +import formatter from '../../../lib/friendly-errors/formatters/missing-loader.ts'; describe('formatters/missing-loader', function () { describe('test format()', function () { diff --git a/test/friendly-errors/transformers/missing-css-file.js b/test/friendly-errors/transformers/missing-css-file.js index c2dbef08..4bf1ec4d 100644 --- a/test/friendly-errors/transformers/missing-css-file.js +++ b/test/friendly-errors/transformers/missing-css-file.js @@ -9,7 +9,7 @@ import { describe, it, expect } from 'vitest'; -import transform from '../../../lib/friendly-errors/transformers/missing-css-file.js'; +import transform from '../../../lib/friendly-errors/transformers/missing-css-file.ts'; describe('transform/missing-css-file', function () { describe('test transform', function () { diff --git a/test/friendly-errors/transformers/missing-loader.js b/test/friendly-errors/transformers/missing-loader.js index bd757935..69572c15 100644 --- a/test/friendly-errors/transformers/missing-loader.js +++ b/test/friendly-errors/transformers/missing-loader.js @@ -10,7 +10,7 @@ import { describe, it, expect } from 'vitest'; import RuntimeConfig from '../../../lib/config/RuntimeConfig.js'; -import transformFactory from '../../../lib/friendly-errors/transformers/missing-loader.js'; +import transformFactory from '../../../lib/friendly-errors/transformers/missing-loader.ts'; import WebpackConfig from '../../../lib/WebpackConfig.js'; const runtimeConfig = new RuntimeConfig();