From 2efac525696b86276a5cdc1e29fe1d492e01789c Mon Sep 17 00:00:00 2001 From: Liang Chun Wong Date: Sat, 21 Jul 2018 17:17:34 +0200 Subject: [PATCH] partially fix #3, workaround for #2 --- CHANGELOG.md | 23 ++++++++ lib/formatForkTsCheckerMessages.js | 28 ++++++++++ lib/formatTsLoaderMessages.js | 87 ------------------------------ lib/webpack.config.dev.js | 16 ++++-- lib/webpack.config.prod.js | 16 ++++-- package.json | 2 + template/tsconfig.json | 2 +- yarn.lock | 58 +++++++++++++++++++- 8 files changed, 136 insertions(+), 96 deletions(-) create mode 100644 CHANGELOG.md create mode 100644 lib/formatForkTsCheckerMessages.js delete mode 100644 lib/formatTsLoaderMessages.js diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..f0252c64 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,23 @@ +## 0.4.0 + * Fix issue where ambient TypeScript files (with only type definitions) being persisted across incremental builds + * Use `fork-ts-checker-webpack-plugin` for checking + * Use `babel-code-frame` for displaying source in terminal + * Ignore test files in tsconfig.json template + +## 0.3.0 + * Support Jest configuration overrides for keys + * `collectCoverageFrom` + * `coverageReporters` + * `coverageThreshold` + +## 0.2.4 + * Added meaningful defaults for tslint + +## 0.2.3 + * Add missing support for code and signal handling in child process + +## 0.2.2 + * (lib) Fix case sensitive imports + +## 0.2.1 + * Initial version diff --git a/lib/formatForkTsCheckerMessages.js b/lib/formatForkTsCheckerMessages.js new file mode 100644 index 00000000..2801bd62 --- /dev/null +++ b/lib/formatForkTsCheckerMessages.js @@ -0,0 +1,28 @@ +const os = require('os') +const codeFrame = require('babel-code-frame') +const chalk = require('chalk') +const fs = require('fs') + +module.exports = (codeFrameOptions = {}) => (message, useColors) => { + const colors = new chalk.constructor({ enabled: useColors }) + const file = message.getFile() + const source = file && fs.existsSync(file) && fs.readFileSync(file, 'utf-8') + + let frame = '' + + if (source) { + frame = codeFrame(source, message.line, message.character, { + ...codeFrameOptions, + highlightCode: useColors, + }) + .split('\n') + .map(str => ' ' + str.replace('|', '│')) + .join(os.EOL) + } + return ( + message.getContent() + + colors.cyan(` (TS${message.getCode()})`) + + os.EOL + + (frame ? os.EOL + frame : '') + ) +} diff --git a/lib/formatTsLoaderMessages.js b/lib/formatTsLoaderMessages.js deleted file mode 100644 index 2f8aaf06..00000000 --- a/lib/formatTsLoaderMessages.js +++ /dev/null @@ -1,87 +0,0 @@ -const fs = require('fs') -const textTable = require('text-table') -const stripAnsi = require('strip-ansi') - -/** - * Creates an array with the number range - * Example: range(1, 4) => [1, 2, 3, 4] - * @param {number} min - * @param {number} max - */ -const range = (min, max) => { - const len = max - min + 1 - return Array.from({ length: len }).map((_, i) => i + min) -} - -/** - * Creates an array where mid is the middle number in an array, - * and padded by padLength number of elements on the left and right - * Example: padNumber(4, 3) => [1, 2, 3, 4, 5, 6, 7] - * @param {number} mid - * @param {number} padLength - */ -const padNumber = (mid, padLength) => range(mid - padLength, mid + padLength) - -module.exports = (error, colors) => { - const friendlyMessage = - error.content + ' ' + colors.cyan('(TS' + error.code + ')') - - // if there are no source files to parse, return only the message - if (!error.file) { - return friendlyMessage - } - - // try to load the file - let fileContents = '' - try { - fileContents = fs.readFileSync(error.file, 'utf-8') - } catch (e) { - return colors.red( - '[TNS] Unable to read file ' + error.file + '\nReason: ' + e.message - ) - } - - const SEPERATOR = colors.dim('│') - - const lines = fileContents.split('\n') - const parsedLines = padNumber(error.line, 2) - - /** - * Parse the line contents into a 2D array where one line is an array of - * [line number, seperator, content] - */ - const tableBuffer = [] - parsedLines.forEach(line => { - const isSourceLine = line === error.line - const lineContent = lines[line - 1] - - // if there is no data inside the line, return - if (lineContent === undefined) { - return - } - - // if it's the source line, we want to display the message - // with a red arrow and a carat to indicate the position - // otherwise, we will just display it with the source dimmed - if (isSourceLine) { - const lineNumber = colors.red('> ' + line) - const carat = - ' '.repeat(error.character - 1) + colors.redBright('^') - tableBuffer.push( - [lineNumber, SEPERATOR, lineContent], - ['', SEPERATOR, carat] - ) - } else { - const lineNumber = colors.dim(line) - tableBuffer.push([lineNumber, SEPERATOR, colors.dim(lineContent)]) - } - }) - - return [ - friendlyMessage, - textTable(tableBuffer, { - align: ['r', 'c', 'l'], - stringLength: l => stripAnsi(l).length, - }), - ].join('\n\n') -} diff --git a/lib/webpack.config.dev.js b/lib/webpack.config.dev.js index 35d2078a..ec712ad4 100644 --- a/lib/webpack.config.dev.js +++ b/lib/webpack.config.dev.js @@ -1,7 +1,9 @@ const paths = require('./paths') const nodeExternals = require('webpack-node-externals') const tsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin') -const formatTsLoaderMessages = require('./formatTsLoaderMessages') +const forkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin') + +const formatForkTsCheckerMessages = require('./formatForkTsCheckerMessages') const { tslintShouldEmitErrors } = require('./tsLintHelper') module.exports = { @@ -46,12 +48,20 @@ module.exports = { include: paths.appSrc, loader: require.resolve('ts-loader'), options: { - colors: true, - errorFormatter: formatTsLoaderMessages, + transpileOnly: true, }, }, ], }, + plugins: [ + new forkTsCheckerWebpackPlugin({ + silent: true, + async: false, + watch: paths.appSrc, + tsconfig: paths.appTsConfig, + formatter: formatForkTsCheckerMessages({}), + }), + ], optimization: { nodeEnv: false, }, diff --git a/lib/webpack.config.prod.js b/lib/webpack.config.prod.js index 472dfe00..dacee6b6 100644 --- a/lib/webpack.config.prod.js +++ b/lib/webpack.config.prod.js @@ -1,7 +1,9 @@ const paths = require('./paths') const nodeExternals = require('webpack-node-externals') -const formatTsLoaderMessages = require('./formatTsLoaderMessages') const tsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin') +const forkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin') + +const formatForkTsCheckerMessages = require('./formatForkTsCheckerMessages') const { tslintShouldEmitErrors } = require('./tsLintHelper') module.exports = { @@ -46,12 +48,20 @@ module.exports = { include: paths.appSrc, loader: require.resolve('ts-loader'), options: { - colors: true, - errorFormatter: formatTsLoaderMessages, + transpileOnly: true, }, }, ], }, + plugins: [ + new forkTsCheckerWebpackPlugin({ + silent: true, + async: false, + watch: paths.appSrc, + tsconfig: paths.appTsConfig, + formatter: formatForkTsCheckerMessages({}), + }), + ], optimization: { nodeEnv: false, }, diff --git a/package.json b/package.json index fdacfad5..0965b59a 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,9 @@ "repository": "https://github.com/liangchunn/typescript-node-scripts", "license": "MIT", "dependencies": { + "babel-code-frame": "6.26.0", "chalk": "2.4.1", + "fork-ts-checker-webpack-plugin": "0.4.3", "fs-extra": "6.0.1", "jest": "23.1.0", "strip-ansi": "4.0.0", diff --git a/template/tsconfig.json b/template/tsconfig.json index 35dda224..e8f2c8a5 100644 --- a/template/tsconfig.json +++ b/template/tsconfig.json @@ -18,5 +18,5 @@ "~/*": ["src/*"] } }, - "exclude": ["node_modules", "build", "coverage", "dist", "setupTests.ts"] + "exclude": ["node_modules", "build", "coverage", "dist", "setupTests.ts", "**/__tests__/*"] } diff --git a/yarn.lock b/yarn.lock index 1fd1dd6a..385cb713 100644 --- a/yarn.lock +++ b/yarn.lock @@ -26,6 +26,10 @@ version "23.1.0" resolved "https://registry.yarnpkg.com/@types/jest/-/jest-23.1.0.tgz#8054dd838ba23dc331794d26456b86c7e50bf0f6" +"@types/node@*": + version "10.5.2" + resolved "https://registry.yarnpkg.com/@types/node/-/node-10.5.2.tgz#f19f05314d5421fe37e74153254201a7bf00a707" + "@types/node@^10.3.3": version "10.3.3" resolved "https://registry.yarnpkg.com/@types/node/-/node-10.3.3.tgz#8798d9e39af2fa604f715ee6a6b19796528e46c3" @@ -438,7 +442,7 @@ aws4@^1.6.0: version "1.7.0" resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.7.0.tgz#d4d0e9b9dbfca77bf08eeb0a8a471550fe39e289" -babel-code-frame@^6.22.0, babel-code-frame@^6.26.0: +babel-code-frame@6.26.0, babel-code-frame@^6.22.0, babel-code-frame@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" dependencies: @@ -871,7 +875,7 @@ chardet@^0.4.0: version "0.4.2" resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.4.2.tgz#b5473b33dc97c424e5d98dc87d55d4d8a29c8bf2" -chokidar@^1.6.0: +chokidar@^1.6.0, chokidar@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468" dependencies: @@ -1837,6 +1841,22 @@ forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" +fork-ts-checker-webpack-plugin@0.4.3: + version "0.4.3" + resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-0.4.3.tgz#f08baa5122ee3de8760c5935e724f4f9f214fea8" + dependencies: + babel-code-frame "^6.22.0" + chalk "^1.1.3" + chokidar "^1.7.0" + lodash.endswith "^4.2.1" + lodash.isfunction "^3.0.8" + lodash.isstring "^4.0.1" + lodash.startswith "^4.2.1" + minimatch "^3.0.4" + resolve "^1.5.0" + tapable "^1.0.0" + vue-parser "^1.1.5" + form-data@~2.3.1: version "2.3.2" resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.2.tgz#4970498be604c20c005d4f5c23aecd21d6b49099" @@ -3230,10 +3250,26 @@ locate-path@^2.0.0: p-locate "^2.0.0" path-exists "^3.0.0" +lodash.endswith@^4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/lodash.endswith/-/lodash.endswith-4.2.1.tgz#fed59ac1738ed3e236edd7064ec456448b37bc09" + +lodash.isfunction@^3.0.8: + version "3.0.9" + resolved "https://registry.yarnpkg.com/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz#06de25df4db327ac931981d1bdb067e5af68d051" + +lodash.isstring@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451" + lodash.sortby@^4.7.0: version "4.7.0" resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" +lodash.startswith@^4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/lodash.startswith/-/lodash.startswith-4.2.1.tgz#c598c4adce188a27e53145731cdc6c0e7177600c" + lodash@^4.13.1, lodash@^4.17.10, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.3.0: version "4.17.10" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.10.tgz#1b7793cf7259ea38fb3661d4d38b3260af8ae4e7" @@ -3840,6 +3876,12 @@ parse5@4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/parse5/-/parse5-4.0.0.tgz#6d78656e3da8d78b4ec0b906f7c08ef1dfe3f608" +parse5@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-3.0.3.tgz#042f792ffdd36851551cf4e9e066b3874ab45b5c" + dependencies: + "@types/node" "*" + pascalcase@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" @@ -4248,6 +4290,12 @@ resolve@^1.1.7, resolve@^1.3.2: dependencies: path-parse "^1.0.5" +resolve@^1.5.0: + version "1.8.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.8.1.tgz#82f1ec19a423ac1fbd080b0bab06ba36e84a7a26" + dependencies: + path-parse "^1.0.5" + restore-cursor@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-1.0.1.tgz#34661f46886327fed2991479152252df92daa541" @@ -5110,6 +5158,12 @@ vm-browserify@0.0.4: dependencies: indexof "0.0.1" +vue-parser@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/vue-parser/-/vue-parser-1.1.6.tgz#3063c8431795664ebe429c23b5506899706e6355" + dependencies: + parse5 "^3.0.3" + w3c-hr-time@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz#82ac2bff63d950ea9e3189a58a65625fedf19045"