Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

## Installation

This plugin requires minimum **Node.js 12**, **Webpack 5**, **TypeScript 3.6**
This plugin requires minimum **Node.js 12+**, **Webpack ^5.11.0**, **TypeScript ^3.6.0**

* If you depend on **TypeScript 2.1 - 2.6.2**, please use [version 4](https://github.com/TypeStrong/fork-ts-checker-webpack-plugin/tree/v4.1.4) of the plugin.
* If you depend on **Webpack 4**, **TypeScript 2.7 - 3.5.3** or **ESLint** feature, please use [version 6](https://github.com/TypeStrong/fork-ts-checker-webpack-plugin/tree/v6.2.6) of the plugin.
Expand Down
8 changes: 5 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,10 @@
"minimatch": "^3.0.4",
"schema-utils": "2.7.0",
"semver": "^7.3.2",
"tapable": "^1.0.0"
"tapable": "^2.0.0"
},
"peerDependencies": {
"webpack": "^5.11.0"
},
"devDependencies": {
"@commitlint/config-conventional": "^11.0.0",
Expand All @@ -90,7 +93,6 @@
"@types/node": "^14.11.10",
"@types/rimraf": "^3.0.0",
"@types/semver": "^7.3.4",
"@types/webpack": "^4.41.22",
"@typescript-eslint/eslint-plugin": "^2.27.0",
"@typescript-eslint/parser": "^2.27.0",
"commitlint": "^11.0.0",
Expand All @@ -115,7 +117,7 @@
"tree-kill": "^1.2.2",
"ts-jest": "^26.4.1",
"typescript": "^3.8.3",
"webpack": "^4.42.1"
"webpack": "^5.11.0"
},
"engines": {
"node": ">=10",
Expand Down
2 changes: 1 addition & 1 deletion src/ForkTsCheckerWebpackPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { tapAfterEnvironmentToPatchWatching } from './hooks/tapAfterEnvironmentT
import { createPool, Pool } from './utils/async/pool';
import os from 'os';

class ForkTsCheckerWebpackPlugin implements webpack.Plugin {
class ForkTsCheckerWebpackPlugin {
/**
* Current version of the plugin
*/
Expand Down
4 changes: 2 additions & 2 deletions src/ForkTsCheckerWebpackPluginState.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Tap } from 'tapable';
import { FullTap } from 'tapable';
import { FilesMatch, Report } from './reporter';
import { Issue } from './issue';

Expand All @@ -9,7 +9,7 @@ interface ForkTsCheckerWebpackPluginState {
lastDependencies: FilesMatch | undefined;
watching: boolean;
initialized: boolean;
webpackDevServerDoneTap: Tap | undefined;
webpackDevServerDoneTap: FullTap | undefined;
}

function createForkTsCheckerWebpackPluginState(): ForkTsCheckerWebpackPluginState {
Expand Down
10 changes: 5 additions & 5 deletions src/hooks/pluginHooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ const compilerHookMap = new WeakMap<

function createForkTsCheckerWebpackPluginHooks() {
return {
start: new AsyncSeriesWaterfallHook<FilesChange, webpack.compilation.Compilation>([
start: new AsyncSeriesWaterfallHook<[FilesChange, webpack.Compilation]>([
'change',
'compilation',
]),
waiting: new SyncHook<webpack.compilation.Compilation>(['compilation']),
canceled: new SyncHook<webpack.compilation.Compilation>(['compilation']),
error: new SyncHook<Error, webpack.compilation.Compilation>(['error', 'compilation']),
issues: new SyncWaterfallHook<Issue[], webpack.compilation.Compilation | undefined, void>([
waiting: new SyncHook<[webpack.Compilation]>(['compilation']),
canceled: new SyncHook<[webpack.Compilation]>(['compilation']),
error: new SyncHook<[Error, webpack.Compilation]>(['error', 'compilation']),
issues: new SyncWaterfallHook<[Issue[], webpack.Compilation | undefined], void>([
'issues',
'compilation',
]),
Expand Down
9 changes: 5 additions & 4 deletions src/hooks/tapAfterEnvironmentToPatchWatching.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import webpack from 'webpack';
import { ForkTsCheckerWebpackPluginState } from '../ForkTsCheckerWebpackPluginState';
import { InclusiveNodeWatchFileSystem } from '../watch/InclusiveNodeWatchFileSystem';
import { CompilerWithWatchFileSystem } from '../watch/CompilerWithWatchFileSystem';
import { WatchFileSystem } from '../watch/WatchFileSystem';

function tapAfterEnvironmentToPatchWatching(
compiler: webpack.Compiler,
state: ForkTsCheckerWebpackPluginState
) {
compiler.hooks.afterEnvironment.tap('ForkTsCheckerWebpackPlugin', () => {
const watchFileSystem = (compiler as CompilerWithWatchFileSystem).watchFileSystem;
const watchFileSystem = compiler.watchFileSystem;
if (watchFileSystem) {
// wrap original watch file system
(compiler as CompilerWithWatchFileSystem).watchFileSystem = new InclusiveNodeWatchFileSystem(
watchFileSystem,
compiler.watchFileSystem = new InclusiveNodeWatchFileSystem(
// we use some internals here
watchFileSystem as WatchFileSystem,
compiler,
state
);
Expand Down
2 changes: 1 addition & 1 deletion src/hooks/tapDoneToAsyncGetIssues.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ function tapDoneToAsyncGetIssues(
}

if (stats.startTime) {
configuration.logger.infrastructure.info(
configuration.logger.infrastructure.log(
`Time: ${Math.round(Date.now() - stats.startTime).toString()} ms`
);
}
Expand Down
4 changes: 2 additions & 2 deletions src/hooks/tapStartToConnectAndRunReporter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,15 @@ function tapStartToConnectAndRunReporter(
if (state.watching) {
change = getFilesChange(compiler);

configuration.logger.infrastructure.info(
configuration.logger.infrastructure.log(
[
'Calling reporter service for incremental check.',
` Changed files: ${JSON.stringify(change.changedFiles)}`,
` Deleted files: ${JSON.stringify(change.deletedFiles)}`,
].join('\n')
);
} else {
configuration.logger.infrastructure.info('Calling reporter service for single check.');
configuration.logger.infrastructure.log('Calling reporter service for single check.');
}

let resolveDependencies: (dependencies: FilesMatch | undefined) => void;
Expand Down
5 changes: 3 additions & 2 deletions src/issue/IssueWebpackError.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import webpack from 'webpack';
import { relative } from 'path';
import { Issue } from './Issue';
import { formatIssueLocation } from './IssueLocation';
import forwardSlash from '../utils/path/forwardSlash';

class IssueWebpackError extends Error {
class IssueWebpackError extends webpack.WebpackError {
readonly hideStack = true;
readonly file: string | undefined;
readonly file: string = '';

constructor(message: string, readonly issue: Issue) {
super(message);
Expand Down
5 changes: 4 additions & 1 deletion src/logger/LoggerConfiguration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@ function createLoggerConfiguration(
options: LoggerOptions | undefined
): LoggerConfiguration {
return {
infrastructure: createLogger((options && options.infrastructure) || 'silent', compiler),
infrastructure: createLogger(
(options && options.infrastructure) || 'webpack-infrastructure',
compiler
),
issues: createLogger((options && options.issues) || 'console', compiler),
devServer: options?.devServer !== false,
};
Expand Down
2 changes: 1 addition & 1 deletion src/reporter/FilesChange.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ interface FilesChange {
const compilerFilesChangeMap = new WeakMap<Compiler, FilesChange>();

function getFilesChange(compiler: Compiler): FilesChange {
return compilerFilesChangeMap.get(compiler) || {};
return compilerFilesChangeMap.get(compiler) || { changedFiles: [], deletedFiles: [] };
}

function updateFilesChange(compiler: Compiler, change: FilesChange): void {
Expand Down
9 changes: 0 additions & 9 deletions src/watch/CompilerWithWatchFileSystem.ts

This file was deleted.

26 changes: 12 additions & 14 deletions src/watch/InclusiveNodeWatchFileSystem.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,21 @@
import { ForkTsCheckerWebpackPluginState } from '../ForkTsCheckerWebpackPluginState';
import chokidar, { FSWatcher } from 'chokidar';
import { extname } from 'path';
import { Watcher, WatchFileSystem, WatchFileSystemOptions } from './WatchFileSystem';
import { WatchFileSystem } from './WatchFileSystem';
import { Compiler } from 'webpack';
import { clearFilesChange, updateFilesChange } from '../reporter';
import minimatch from 'minimatch';

const BUILTIN_IGNORED_DIRS = ['node_modules', '.git', '.yarn', '.pnp'];

function createIsIgnored(
ignored: WatchFileSystemOptions['ignored'] | undefined
ignored: string | RegExp | (string | RegExp)[] | undefined
): (path: string) => boolean {
const ignoredPatterns = ignored ? (Array.isArray(ignored) ? ignored : [ignored]) : [];
const ignoredFunctions = ignoredPatterns.map((pattern) => {
// ensure patterns are valid - see https://github.com/TypeStrong/fork-ts-checker-webpack-plugin/issues/594
if (typeof pattern === 'string') {
return (path: string) => minimatch(path, pattern);
} else if (typeof pattern === 'function') {
return pattern;
} else if (pattern instanceof RegExp) {
return (path: string) => pattern.test(path);
} else {
Expand Down Expand Up @@ -50,15 +48,15 @@ class InclusiveNodeWatchFileSystem implements WatchFileSystem {

private paused = true;

watch(
files: Iterable<string>,
dirs: Iterable<string>,
missing: Iterable<string>,
startTime?: number,
options?: Partial<WatchFileSystemOptions>,
callback?: Function,
callbackUndelayed?: Function
): Watcher {
watch: WatchFileSystem['watch'] = (
files,
dirs,
missing,
startTime,
options,
callback,
callbackUndelayed
) => {
clearFilesChange(this.compiler);
const isIgnored = createIsIgnored(options?.ignored);

Expand Down Expand Up @@ -173,7 +171,7 @@ class InclusiveNodeWatchFileSystem implements WatchFileSystem {
this.paused = true;
},
};
}
};
}

export { InclusiveNodeWatchFileSystem };
38 changes: 4 additions & 34 deletions src/watch/WatchFileSystem.ts
Original file line number Diff line number Diff line change
@@ -1,50 +1,20 @@
import { EventEmitter } from 'events';

interface WatchFileSystemOptions {
aggregateTimeout: number;
poll: boolean;
followSymlinks: boolean;
ignored: string | RegExp | Function | (string | RegExp | Function)[];
}
import webpack from 'webpack';

// watchpack v1 and v2 internal interface
interface Watchpack extends EventEmitter {
_onChange(item: string, mtime: number, file: string, type?: string): void;
_onRemove(item: string, file: string, type?: string): void;
}

// webpack 4 interface
interface WatcherV4 {
close(): void;
pause(): void;
getFileTimestamps(): Map<string, number>;
getContextTimestamps(): Map<string, number>;
}

// webpack 5 interface
interface WatcherV5 {
close(): void;
pause(): void;
getFileTimeInfoEntries(): Map<string, number>;
getContextTimeInfoEntries(): Map<string, number>;
}

type Watcher = WatcherV4 | WatcherV5;
type Watch = webpack.Compiler['watchFileSystem']['watch'];

interface WatchFileSystem {
watcher: Watchpack;
wfs?: {
watcher: Watchpack;
};
watch(
files: Iterable<string>,
dirs: Iterable<string>,
missing: Iterable<string>,
startTime?: number,
options?: Partial<WatchFileSystemOptions>,
callback?: Function,
callbackUndelayed?: Function
): Watcher;
watch: Watch;
}

export { WatchFileSystem, WatchFileSystemOptions, Watchpack, WatcherV4, WatcherV5, Watcher };
export { WatchFileSystem, Watchpack };
60 changes: 29 additions & 31 deletions test/e2e/OutOfMemoryAndCosmiconfig.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,40 +2,38 @@ import path from 'path';
import { createProcessDriver } from 'karton';

describe('ForkTsCheckerWebpackPlugin Out Of Memory and Cosmiconfig', () => {
it.each([
{ async: false, webpack: '4.0.0' },
{ async: true, webpack: '^4.0.0' },
{ async: false, webpack: '^5.0.0' },
{ async: true, webpack: '^5.0.0' },
])('handles out of memory for %p', async ({ async, webpack }) => {
await sandbox.load(path.join(__dirname, 'fixtures/typescript-basic'));
await sandbox.install('yarn', { webpack });
await sandbox.patch('webpack.config.js', 'async: false,', `async: ${JSON.stringify(async)},`);
it.each([{ async: false }, { async: true }])(
'handles out of memory for %p',
async ({ async }) => {
await sandbox.load(path.join(__dirname, 'fixtures/typescript-basic'));
await sandbox.install('yarn', {});
await sandbox.patch('webpack.config.js', 'async: false,', `async: ${JSON.stringify(async)},`);

await sandbox.write(
'fork-ts-checker.config.js',
`module.exports = { typescript: { memoryLimit: 10 } };`
);
await sandbox.write(
'fork-ts-checker.config.js',
`module.exports = { typescript: { memoryLimit: 10 } };`
);

const driver = createProcessDriver(sandbox.spawn('npm run webpack-dev-server'));
const driver = createProcessDriver(sandbox.spawn('yarn webpack serve --mode=development'));

// we should see an error message about out of memory
await driver.waitForStderrIncludes(
'Issues checking service aborted - probably out of memory. Check the `memoryLimit` option in the ForkTsCheckerWebpackPlugin configuration.\n' +
"If increasing the memory doesn't solve the issue, it's most probably a bug in the TypeScript."
);
// we should see an error message about out of memory
await driver.waitForStderrIncludes(
'Issues checking service aborted - probably out of memory. Check the `memoryLimit` option in the ForkTsCheckerWebpackPlugin configuration.\n' +
"If increasing the memory doesn't solve the issue, it's most probably a bug in the TypeScript."
);

// let's modify one file to check if plugin will try to restart the service
await sandbox.patch(
'src/index.ts',
"import { getUserName } from './model/User';",
"import { getUserName } from './model/User';\n"
);
// let's modify one file to check if plugin will try to restart the service
await sandbox.patch(
'src/index.ts',
"import { getUserName } from './model/User';",
"import { getUserName } from './model/User';\n"
);

// we should see an error message about out of memory again
await driver.waitForStderrIncludes(
'Issues checking service aborted - probably out of memory. Check the `memoryLimit` option in the ForkTsCheckerWebpackPlugin configuration.\n' +
"If increasing the memory doesn't solve the issue, it's most probably a bug in the TypeScript."
);
});
// we should see an error message about out of memory again
await driver.waitForStderrIncludes(
'Issues checking service aborted - probably out of memory. Check the `memoryLimit` option in the ForkTsCheckerWebpackPlugin configuration.\n' +
"If increasing the memory doesn't solve the issue, it's most probably a bug in the TypeScript."
);
}
);
});
4 changes: 2 additions & 2 deletions test/e2e/TypeDefinitions.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ describe('Type Definitions', () => {
await sandbox.load(path.join(__dirname, 'fixtures/type-definitions'));
await sandbox.install('yarn', {});

expect(await sandbox.exec('npm run tsc').catch((error) => error)).toContain(
expect(await sandbox.exec('yarn tsc', { fail: true })).toContain(
"webpack.config.ts(7,7): error TS2322: Type 'string' is not assignable to type 'boolean | undefined'."
);

await sandbox.patch('webpack.config.ts', "async: 'invalid_value'", 'async: true');

expect(await sandbox.exec('npm run tsc')).not.toContain('error TS');
expect(await sandbox.exec('yarn tsc')).not.toContain('error TS');
});
});
Loading