🎯 MapView v2.0 - Global Deployment Ready

 MAJOR FEATURES:
• Auto-zoom intelligence với smart bounds fitting
• Enhanced 3D GPS markers với pulsing effects
• Professional route display với 6-layer rendering
• Status-based parking icons với availability indicators
• Production-ready build optimizations

🗺️ AUTO-ZOOM FEATURES:
• Smart bounds fitting cho GPS + selected parking
• Adaptive padding (50px) cho visual balance
• Max zoom control (level 16) để tránh quá gần
• Dynamic centering khi không có selection

🎨 ENHANCED VISUALS:
• 3D GPS marker với multi-layer pulse effects
• Advanced parking icons với status colors
• Selection highlighting với animation
• Dimming system cho non-selected items

🛣️ ROUTE SYSTEM:
• OpenRouteService API integration
• Multi-layer route rendering (glow, shadow, main, animated)
• Real-time distance & duration calculation
• Visual route info trong popup

📱 PRODUCTION READY:
• SSR safe với dynamic imports
• Build errors resolved
• Global deployment via Vercel
• Optimized performance

🌍 DEPLOYMENT:
• Vercel: https://whatever-ctk2auuxr-phong12hexdockworks-projects.vercel.app
• Bundle size: 22.8 kB optimized
• Global CDN distribution
• HTTPS enabled

💾 VERSION CONTROL:
• MapView-v2.0.tsx backup created
• MAPVIEW_VERSIONS.md documentation
• Full version history tracking
This commit is contained in:
2025-07-20 19:52:16 +07:00
parent 3203463a6a
commit c65cc97a33
64624 changed files with 7199453 additions and 6462 deletions

View File

@@ -0,0 +1,17 @@
import type * as webpack from 'webpack';
interface FilesChange {
changedFiles?: string[];
deletedFiles?: string[];
}
declare function getFilesChange(compiler: webpack.Compiler): FilesChange;
declare function consumeFilesChange(compiler: webpack.Compiler): FilesChange;
declare function updateFilesChange(compiler: webpack.Compiler, change: FilesChange): void;
declare function clearFilesChange(compiler: webpack.Compiler): void;
/**
* Computes aggregated files change based on the subsequent files changes.
*
* @param changes List of subsequent files changes
* @returns Files change that represents all subsequent changes as a one event
*/
declare function aggregateFilesChanges(changes: FilesChange[]): FilesChange;
export { FilesChange, getFilesChange, consumeFilesChange, updateFilesChange, clearFilesChange, aggregateFilesChanges, };

View File

@@ -0,0 +1,57 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.aggregateFilesChanges = exports.clearFilesChange = exports.updateFilesChange = exports.consumeFilesChange = exports.getFilesChange = void 0;
// we ignore package.json file because of https://github.com/TypeStrong/fork-ts-checker-webpack-plugin/issues/674
const IGNORED_FILES = ['package.json'];
const isIgnoredFile = (file) => IGNORED_FILES.some((ignoredFile) => file.endsWith(`/${ignoredFile}`) || file.endsWith(`\\${ignoredFile}`));
const compilerFilesChangeMap = new WeakMap();
function getFilesChange(compiler) {
const { changedFiles = [], deletedFiles = [] } = compilerFilesChangeMap.get(compiler) || {
changedFiles: [],
deletedFiles: [],
};
return {
changedFiles: changedFiles.filter((changedFile) => !isIgnoredFile(changedFile)),
deletedFiles: deletedFiles.filter((deletedFile) => !isIgnoredFile(deletedFile)),
};
}
exports.getFilesChange = getFilesChange;
function consumeFilesChange(compiler) {
const change = getFilesChange(compiler);
clearFilesChange(compiler);
return change;
}
exports.consumeFilesChange = consumeFilesChange;
function updateFilesChange(compiler, change) {
compilerFilesChangeMap.set(compiler, aggregateFilesChanges([getFilesChange(compiler), change]));
}
exports.updateFilesChange = updateFilesChange;
function clearFilesChange(compiler) {
compilerFilesChangeMap.delete(compiler);
}
exports.clearFilesChange = clearFilesChange;
/**
* Computes aggregated files change based on the subsequent files changes.
*
* @param changes List of subsequent files changes
* @returns Files change that represents all subsequent changes as a one event
*/
function aggregateFilesChanges(changes) {
const changedFilesSet = new Set();
const deletedFilesSet = new Set();
for (const { changedFiles = [], deletedFiles = [] } of changes) {
for (const changedFile of changedFiles) {
changedFilesSet.add(changedFile);
deletedFilesSet.delete(changedFile);
}
for (const deletedFile of deletedFiles) {
changedFilesSet.delete(deletedFile);
deletedFilesSet.add(deletedFile);
}
}
return {
changedFiles: Array.from(changedFilesSet),
deletedFiles: Array.from(deletedFilesSet),
};
}
exports.aggregateFilesChanges = aggregateFilesChanges;

View File

@@ -0,0 +1,7 @@
interface FilesMatch {
files: string[];
dirs: string[];
excluded: string[];
extensions: string[];
}
export { FilesMatch };

View File

@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

View File

@@ -0,0 +1,3 @@
import type { Formatter } from './formatter';
declare function createBasicFormatter(): Formatter;
export { createBasicFormatter };

View File

@@ -0,0 +1,13 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createBasicFormatter = void 0;
const chalk_1 = __importDefault(require("chalk"));
function createBasicFormatter() {
return function basicFormatter(issue) {
return chalk_1.default.grey(issue.code + ': ') + issue.message;
};
}
exports.createBasicFormatter = createBasicFormatter;

View File

@@ -0,0 +1,4 @@
import type { Formatter } from './formatter';
import { BabelCodeFrameOptions } from './types/babel__code-frame';
declare function createCodeFrameFormatter(options?: BabelCodeFrameOptions): Formatter;
export { createCodeFrameFormatter, BabelCodeFrameOptions };

View File

@@ -0,0 +1,29 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createCodeFrameFormatter = void 0;
const os_1 = __importDefault(require("os"));
const code_frame_1 = require("@babel/code-frame");
const fs_extra_1 = __importDefault(require("fs-extra"));
const basic_formatter_1 = require("./basic-formatter");
function createCodeFrameFormatter(options) {
const basicFormatter = (0, basic_formatter_1.createBasicFormatter)();
return function codeFrameFormatter(issue) {
const source = issue.file && fs_extra_1.default.existsSync(issue.file) && fs_extra_1.default.readFileSync(issue.file, 'utf-8');
let frame = '';
if (source && issue.location) {
frame = (0, code_frame_1.codeFrameColumns)(source, issue.location, Object.assign({ highlightCode: true }, (options || {})))
.split('\n')
.map((line) => ' ' + line)
.join(os_1.default.EOL);
}
const lines = [basicFormatter(issue)];
if (frame) {
lines.push(frame);
}
return lines.join(os_1.default.EOL);
};
}
exports.createCodeFrameFormatter = createCodeFrameFormatter;

View File

@@ -0,0 +1,8 @@
import type { Formatter, FormatterPathType } from './formatter';
import type { FormatterOptions } from './formatter-options';
declare type FormatterConfig = {
format: Formatter;
pathType: FormatterPathType;
};
declare function createFormatterConfig(options: FormatterOptions | undefined): FormatterConfig;
export { FormatterConfig, createFormatterConfig };

View File

@@ -0,0 +1,36 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createFormatterConfig = void 0;
const basic_formatter_1 = require("./basic-formatter");
const code_frame_formatter_1 = require("./code-frame-formatter");
function createFormatterConfig(options) {
if (typeof options === 'function') {
return {
format: options,
pathType: 'relative',
};
}
const type = options
? typeof options === 'object'
? options.type || 'codeframe'
: options
: 'codeframe';
const pathType = options && typeof options === 'object' ? options.pathType || 'relative' : 'relative';
if (!type || type === 'basic') {
return {
format: (0, basic_formatter_1.createBasicFormatter)(),
pathType,
};
}
if (type === 'codeframe') {
const config = options && typeof options === 'object'
? options.options || {}
: {};
return {
format: (0, code_frame_formatter_1.createCodeFrameFormatter)(config),
pathType,
};
}
throw new Error(`Unknown "${type}" formatter. Available types are: "basic", "codeframe" or a custom function.`);
}
exports.createFormatterConfig = createFormatterConfig;

View File

@@ -0,0 +1,14 @@
import type { Formatter, FormatterPathType } from './formatter';
import type { BabelCodeFrameOptions } from './types/babel__code-frame';
declare type FormatterType = 'basic' | 'codeframe';
declare type BasicFormatterOptions = {
type: 'basic';
pathType?: FormatterPathType;
};
declare type CodeframeFormatterOptions = {
type: 'codeframe';
pathType?: FormatterPathType;
options?: BabelCodeFrameOptions;
};
declare type FormatterOptions = undefined | FormatterType | BasicFormatterOptions | CodeframeFormatterOptions | Formatter;
export { FormatterOptions, FormatterType, BasicFormatterOptions, CodeframeFormatterOptions };

View File

@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

View File

@@ -0,0 +1,4 @@
import type { Issue } from '../issue';
declare type Formatter = (issue: Issue) => string;
declare type FormatterPathType = 'relative' | 'absolute';
export { Formatter, FormatterPathType };

View File

@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

View File

@@ -0,0 +1,6 @@
export * from './formatter';
export * from './basic-formatter';
export * from './code-frame-formatter';
export * from './webpack-formatter';
export * from './formatter-options';
export * from './formatter-config';

View File

@@ -0,0 +1,18 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
__exportStar(require("./formatter"), exports);
__exportStar(require("./basic-formatter"), exports);
__exportStar(require("./code-frame-formatter"), exports);
__exportStar(require("./webpack-formatter"), exports);
__exportStar(require("./formatter-options"), exports);
__exportStar(require("./formatter-config"), exports);

View File

@@ -0,0 +1,3 @@
import type { Stats } from 'webpack';
import type { Issue } from '../issue';
export declare function statsFormatter(issues: Issue[], stats: Stats): string;

View File

@@ -0,0 +1,28 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.statsFormatter = void 0;
const chalk_1 = __importDefault(require("chalk"));
// mimics webpack's stats summary formatter
function statsFormatter(issues, stats) {
const errorsNumber = issues.filter((issue) => issue.severity === 'error').length;
const warningsNumber = issues.filter((issue) => issue.severity === 'warning').length;
const errorsFormatted = errorsNumber
? chalk_1.default.red.bold(`${errorsNumber} ${errorsNumber === 1 ? 'error' : 'errors'}`)
: '';
const warningsFormatted = warningsNumber
? chalk_1.default.yellow.bold(`${warningsNumber} ${warningsNumber === 1 ? 'warning' : 'warnings'}`)
: '';
const timeFormatted = Math.round(Date.now() - stats.startTime);
return [
'Found ',
errorsFormatted,
errorsFormatted && warningsFormatted ? ' and ' : '',
warningsFormatted,
` in ${timeFormatted} ms`,
'.',
].join('');
}
exports.statsFormatter = statsFormatter;

View File

@@ -0,0 +1,21 @@
export interface BabelCodeFrameOptions {
/** Syntax highlight the code as JavaScript for terminals. default: false */
highlightCode?: boolean;
/** The number of lines to show above the error. default: 2 */
linesAbove?: number;
/** The number of lines to show below the error. default: 3 */
linesBelow?: number;
/**
* Forcibly syntax highlight the code as JavaScript (for non-terminals);
* overrides highlightCode.
* default: false
*/
forceColor?: boolean;
/**
* Pass in a string to be displayed inline (if possible) next to the
* highlighted location in the code. If it can't be positioned inline,
* it will be placed above the code frame.
* default: nothing
*/
message?: string;
}

View File

@@ -0,0 +1,7 @@
"use strict";
// Base on the type definitions for @babel/code-frame 7.0
// Project: https://github.com/babel/babel/tree/main/packages/babel-code-frame, https://babeljs.io
// Definitions by: Mohsen Azimi <https://github.com/mohsen1>
// Forbes Lindesay <https://github.com/ForbesLindesay>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
Object.defineProperty(exports, "__esModule", { value: true });

View File

@@ -0,0 +1,3 @@
import type { Formatter, FormatterPathType } from './formatter';
declare function createWebpackFormatter(formatter: Formatter, pathType: FormatterPathType): Formatter;
export { createWebpackFormatter };

View File

@@ -0,0 +1,32 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createWebpackFormatter = void 0;
const os_1 = __importDefault(require("os"));
const path_1 = __importDefault(require("path"));
const chalk_1 = __importDefault(require("chalk"));
const issue_1 = require("../issue");
const forward_slash_1 = require("../utils/path/forward-slash");
const relative_to_context_1 = require("../utils/path/relative-to-context");
function createWebpackFormatter(formatter, pathType) {
// mimics webpack error formatter
return function webpackFormatter(issue) {
const color = issue.severity === 'warning' ? chalk_1.default.yellow.bold : chalk_1.default.red.bold;
const severity = issue.severity.toUpperCase();
if (issue.file) {
let location = chalk_1.default.bold(pathType === 'absolute'
? (0, forward_slash_1.forwardSlash)(path_1.default.resolve(issue.file))
: (0, relative_to_context_1.relativeToContext)(issue.file, process.cwd()));
if (issue.location) {
location += `:${chalk_1.default.green.bold((0, issue_1.formatIssueLocation)(issue.location))}`;
}
return [`${color(severity)} in ${location}`, formatter(issue), ''].join(os_1.default.EOL);
}
else {
return [`${color(severity)} in ` + formatter(issue), ''].join(os_1.default.EOL);
}
};
}
exports.createWebpackFormatter = createWebpackFormatter;

View File

@@ -0,0 +1,5 @@
import type * as webpack from 'webpack';
import type { ForkTsCheckerWebpackPluginConfig } from '../plugin-config';
import type { ForkTsCheckerWebpackPluginState } from '../plugin-state';
declare function interceptDoneToGetDevServerTap(compiler: webpack.Compiler, config: ForkTsCheckerWebpackPluginConfig, state: ForkTsCheckerWebpackPluginState): void;
export { interceptDoneToGetDevServerTap };

View File

@@ -0,0 +1,18 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.interceptDoneToGetDevServerTap = void 0;
const infrastructure_logger_1 = require("../infrastructure-logger");
function interceptDoneToGetDevServerTap(compiler, config, state) {
const { debug } = (0, infrastructure_logger_1.getInfrastructureLogger)(compiler);
// inspired by https://github.com/ypresto/fork-ts-checker-async-overlay-webpack-plugin
compiler.hooks.done.intercept({
register: (tap) => {
if (tap.name === 'webpack-dev-server' && tap.type === 'sync' && config.devServer) {
debug('Intercepting webpack-dev-server tap.');
state.webpackDevServerDoneTap = tap;
}
return tap;
},
});
}
exports.interceptDoneToGetDevServerTap = interceptDoneToGetDevServerTap;

View File

@@ -0,0 +1,5 @@
import type * as webpack from 'webpack';
import type { ForkTsCheckerWebpackPluginConfig } from '../plugin-config';
import type { ForkTsCheckerWebpackPluginState } from '../plugin-state';
declare function tapAfterCompileToAddDependencies(compiler: webpack.Compiler, config: ForkTsCheckerWebpackPluginConfig, state: ForkTsCheckerWebpackPluginState): void;
export { tapAfterCompileToAddDependencies };

View File

@@ -0,0 +1,31 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.tapAfterCompileToAddDependencies = void 0;
const infrastructure_logger_1 = require("../infrastructure-logger");
function tapAfterCompileToAddDependencies(compiler, config, state) {
const { debug } = (0, infrastructure_logger_1.getInfrastructureLogger)(compiler);
compiler.hooks.afterCompile.tapPromise('ForkTsCheckerWebpackPlugin', (compilation) => __awaiter(this, void 0, void 0, function* () {
if (compilation.compiler !== compiler) {
// run only for the compiler that the plugin was registered for
return;
}
const dependencies = yield state.dependenciesPromise;
debug(`Got dependencies from the getDependenciesWorker.`, dependencies);
if (dependencies) {
state.lastDependencies = dependencies;
dependencies.files.forEach((file) => {
compilation.fileDependencies.add(file);
});
}
}));
}
exports.tapAfterCompileToAddDependencies = tapAfterCompileToAddDependencies;

View File

@@ -0,0 +1,5 @@
import type * as webpack from 'webpack';
import type { ForkTsCheckerWebpackPluginConfig } from '../plugin-config';
import type { ForkTsCheckerWebpackPluginState } from '../plugin-state';
declare function tapAfterCompileToGetIssues(compiler: webpack.Compiler, config: ForkTsCheckerWebpackPluginConfig, state: ForkTsCheckerWebpackPluginState): void;
export { tapAfterCompileToGetIssues };

View File

@@ -0,0 +1,52 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.tapAfterCompileToGetIssues = void 0;
const infrastructure_logger_1 = require("../infrastructure-logger");
const issue_webpack_error_1 = require("../issue/issue-webpack-error");
const plugin_hooks_1 = require("../plugin-hooks");
function tapAfterCompileToGetIssues(compiler, config, state) {
const hooks = (0, plugin_hooks_1.getPluginHooks)(compiler);
const { debug } = (0, infrastructure_logger_1.getInfrastructureLogger)(compiler);
compiler.hooks.afterCompile.tapPromise('ForkTsCheckerWebpackPlugin', (compilation) => __awaiter(this, void 0, void 0, function* () {
if (compilation.compiler !== compiler) {
// run only for the compiler that the plugin was registered for
return;
}
let issues = [];
try {
issues = yield state.issuesPromise;
}
catch (error) {
hooks.error.call(error, compilation);
return;
}
debug('Got issues from getIssuesWorker.', issues === null || issues === void 0 ? void 0 : issues.length);
if (!issues) {
// some error has been thrown or it was canceled
return;
}
// filter list of issues by provided issue predicate
issues = issues.filter(config.issue.predicate);
// modify list of issues in the plugin hooks
issues = hooks.issues.call(issues, compilation);
issues.forEach((issue) => {
const error = new issue_webpack_error_1.IssueWebpackError(config.formatter.format(issue), config.formatter.pathType, issue);
if (issue.severity === 'warning') {
compilation.warnings.push(error);
}
else {
compilation.errors.push(error);
}
});
}));
}
exports.tapAfterCompileToGetIssues = tapAfterCompileToGetIssues;

View File

@@ -0,0 +1,4 @@
import type * as webpack from 'webpack';
import type { ForkTsCheckerWebpackPluginState } from '../plugin-state';
declare function tapAfterEnvironmentToPatchWatching(compiler: webpack.Compiler, state: ForkTsCheckerWebpackPluginState): void;
export { tapAfterEnvironmentToPatchWatching };

View File

@@ -0,0 +1,22 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.tapAfterEnvironmentToPatchWatching = void 0;
const infrastructure_logger_1 = require("../infrastructure-logger");
const inclusive_node_watch_file_system_1 = require("../watch/inclusive-node-watch-file-system");
function tapAfterEnvironmentToPatchWatching(compiler, state) {
const { debug } = (0, infrastructure_logger_1.getInfrastructureLogger)(compiler);
compiler.hooks.afterEnvironment.tap('ForkTsCheckerWebpackPlugin', () => {
const watchFileSystem = compiler.watchFileSystem;
if (watchFileSystem) {
debug("Overwriting webpack's watch file system.");
// wrap original watch file system
compiler.watchFileSystem = new inclusive_node_watch_file_system_1.InclusiveNodeWatchFileSystem(
// we use some internals here
watchFileSystem, compiler, state);
}
else {
debug('No watch file system found - plugin may not work correctly.');
}
});
}
exports.tapAfterEnvironmentToPatchWatching = tapAfterEnvironmentToPatchWatching;

View File

@@ -0,0 +1,5 @@
import type * as webpack from 'webpack';
import type { ForkTsCheckerWebpackPluginConfig } from '../plugin-config';
import type { ForkTsCheckerWebpackPluginState } from '../plugin-state';
declare function tapDoneToAsyncGetIssues(compiler: webpack.Compiler, config: ForkTsCheckerWebpackPluginConfig, state: ForkTsCheckerWebpackPluginState): void;
export { tapDoneToAsyncGetIssues };

View File

@@ -0,0 +1,86 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.tapDoneToAsyncGetIssues = void 0;
const chalk_1 = __importDefault(require("chalk"));
const stats_formatter_1 = require("../formatter/stats-formatter");
const webpack_formatter_1 = require("../formatter/webpack-formatter");
const infrastructure_logger_1 = require("../infrastructure-logger");
const issue_webpack_error_1 = require("../issue/issue-webpack-error");
const plugin_hooks_1 = require("../plugin-hooks");
const is_pending_1 = require("../utils/async/is-pending");
const wait_1 = require("../utils/async/wait");
function tapDoneToAsyncGetIssues(compiler, config, state) {
const hooks = (0, plugin_hooks_1.getPluginHooks)(compiler);
const { debug } = (0, infrastructure_logger_1.getInfrastructureLogger)(compiler);
compiler.hooks.done.tap('ForkTsCheckerWebpackPlugin', (stats) => __awaiter(this, void 0, void 0, function* () {
if (stats.compilation.compiler !== compiler) {
// run only for the compiler that the plugin was registered for
return;
}
const issuesPromise = state.issuesPromise;
let issues;
try {
if (yield (0, is_pending_1.isPending)(issuesPromise)) {
hooks.waiting.call(stats.compilation);
config.logger.log(chalk_1.default.cyan('Type-checking in progress...'));
}
else {
// wait 10ms to log issues after webpack stats
yield (0, wait_1.wait)(10);
}
issues = yield issuesPromise;
}
catch (error) {
hooks.error.call(error, stats.compilation);
return;
}
if (!issues || // some error has been thrown
state.issuesPromise !== issuesPromise // we have a new request - don't show results for the old one
) {
return;
}
debug(`Got ${(issues === null || issues === void 0 ? void 0 : issues.length) || 0} issues from getIssuesWorker.`);
// filter list of issues by provided issue predicate
issues = issues.filter(config.issue.predicate);
// modify list of issues in the plugin hooks
issues = hooks.issues.call(issues, stats.compilation);
const formatter = (0, webpack_formatter_1.createWebpackFormatter)(config.formatter.format, config.formatter.pathType);
if (issues.length) {
// follow webpack's approach - one process.write to stderr with all errors and warnings
config.logger.error(issues.map((issue) => formatter(issue)).join('\n'));
// print stats of the compilation
config.logger.log((0, stats_formatter_1.statsFormatter)(issues, stats));
}
else {
config.logger.log(chalk_1.default.green('No errors found.'));
}
// report issues to webpack-dev-server, if it's listening
// skip reporting if there are no issues, to avoid an extra hot reload
if (issues.length && state.webpackDevServerDoneTap) {
issues.forEach((issue) => {
const error = new issue_webpack_error_1.IssueWebpackError(config.formatter.format(issue), config.formatter.pathType, issue);
if (issue.severity === 'warning') {
stats.compilation.warnings.push(error);
}
else {
stats.compilation.errors.push(error);
}
});
debug('Sending issues to the webpack-dev-server.');
state.webpackDevServerDoneTap.fn(stats);
}
}));
}
exports.tapDoneToAsyncGetIssues = tapDoneToAsyncGetIssues;

View File

@@ -0,0 +1,4 @@
import type * as webpack from 'webpack';
import type { ForkTsCheckerWebpackPluginConfig } from '../plugin-config';
declare function tapErrorToLogMessage(compiler: webpack.Compiler, config: ForkTsCheckerWebpackPluginConfig): void;
export { tapErrorToLogMessage };

View File

@@ -0,0 +1,32 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.tapErrorToLogMessage = void 0;
const chalk_1 = __importDefault(require("chalk"));
const plugin_hooks_1 = require("../plugin-hooks");
const rpc_1 = require("../rpc");
const abort_error_1 = require("../utils/async/abort-error");
function tapErrorToLogMessage(compiler, config) {
const hooks = (0, plugin_hooks_1.getPluginHooks)(compiler);
hooks.error.tap('ForkTsCheckerWebpackPlugin', (error) => {
if (error instanceof abort_error_1.AbortError) {
return;
}
config.logger.error(String(error));
if (error instanceof rpc_1.RpcExitError) {
if (error.signal === 'SIGINT') {
config.logger.error(chalk_1.default.red('Issues checking service interrupted - If running in a docker container, this may be caused ' +
"by the container running out of memory. If so, try increasing the container's memory limit " +
'or lowering the `memoryLimit` value in the ForkTsCheckerWebpackPlugin configuration.'));
}
else {
config.logger.error(chalk_1.default.red('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."));
}
}
});
}
exports.tapErrorToLogMessage = tapErrorToLogMessage;

View File

@@ -0,0 +1,8 @@
import type * as webpack from 'webpack';
import type { ForkTsCheckerWebpackPluginConfig } from '../plugin-config';
import type { ForkTsCheckerWebpackPluginState } from '../plugin-state';
import type { RpcWorker } from '../rpc';
import type { GetDependenciesWorker } from '../typescript/worker/get-dependencies-worker';
import type { GetIssuesWorker } from '../typescript/worker/get-issues-worker';
declare function tapStartToRunWorkers(compiler: webpack.Compiler, getIssuesWorker: RpcWorker<GetIssuesWorker>, getDependenciesWorker: RpcWorker<GetDependenciesWorker>, config: ForkTsCheckerWebpackPluginConfig, state: ForkTsCheckerWebpackPluginState): void;
export { tapStartToRunWorkers };

View File

@@ -0,0 +1,132 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.tapStartToRunWorkers = void 0;
const node_abort_controller_1 = require("node-abort-controller");
const files_change_1 = require("../files-change");
const infrastructure_logger_1 = require("../infrastructure-logger");
const plugin_hooks_1 = require("../plugin-hooks");
const plugin_pools_1 = require("../plugin-pools");
const intercept_done_to_get_dev_server_tap_1 = require("./intercept-done-to-get-dev-server-tap");
const tap_after_compile_to_get_issues_1 = require("./tap-after-compile-to-get-issues");
const tap_done_to_async_get_issues_1 = require("./tap-done-to-async-get-issues");
function tapStartToRunWorkers(compiler, getIssuesWorker, getDependenciesWorker, config, state) {
const hooks = (0, plugin_hooks_1.getPluginHooks)(compiler);
const { log, debug } = (0, infrastructure_logger_1.getInfrastructureLogger)(compiler);
compiler.hooks.run.tap('ForkTsCheckerWebpackPlugin', () => {
if (!state.initialized) {
debug('Initializing plugin for single run (not async).');
state.initialized = true;
state.watching = false;
(0, tap_after_compile_to_get_issues_1.tapAfterCompileToGetIssues)(compiler, config, state);
}
});
compiler.hooks.watchRun.tap('ForkTsCheckerWebpackPlugin', () => __awaiter(this, void 0, void 0, function* () {
if (!state.initialized) {
state.initialized = true;
state.watching = true;
if (config.async) {
debug('Initializing plugin for watch run (async).');
(0, tap_done_to_async_get_issues_1.tapDoneToAsyncGetIssues)(compiler, config, state);
(0, intercept_done_to_get_dev_server_tap_1.interceptDoneToGetDevServerTap)(compiler, config, state);
}
else {
debug('Initializing plugin for watch run (not async).');
(0, tap_after_compile_to_get_issues_1.tapAfterCompileToGetIssues)(compiler, config, state);
}
}
}));
compiler.hooks.compilation.tap('ForkTsCheckerWebpackPlugin', (compilation) => __awaiter(this, void 0, void 0, function* () {
if (compilation.compiler !== compiler) {
// run only for the compiler that the plugin was registered for
return;
}
// get current iteration number
const iteration = ++state.iteration;
// abort previous iteration
if (state.abortController) {
debug(`Aborting iteration ${iteration - 1}.`);
state.abortController.abort();
}
// create new abort controller for the new iteration
const abortController = new node_abort_controller_1.AbortController();
state.abortController = abortController;
let filesChange = {};
if (state.watching) {
filesChange = (0, files_change_1.consumeFilesChange)(compiler);
log([
'Calling reporter service for incremental check.',
` Changed files: ${JSON.stringify(filesChange.changedFiles)}`,
` Deleted files: ${JSON.stringify(filesChange.deletedFiles)}`,
].join('\n'));
}
else {
log('Calling reporter service for single check.');
}
filesChange = yield hooks.start.promise(filesChange, compilation);
let aggregatedFilesChange = filesChange;
if (state.aggregatedFilesChange) {
aggregatedFilesChange = (0, files_change_1.aggregateFilesChanges)([aggregatedFilesChange, filesChange]);
debug([
`Aggregating with previous files change, iteration ${iteration}.`,
` Changed files: ${JSON.stringify(aggregatedFilesChange.changedFiles)}`,
` Deleted files: ${JSON.stringify(aggregatedFilesChange.deletedFiles)}`,
].join('\n'));
}
state.aggregatedFilesChange = aggregatedFilesChange;
// submit one at a time for a single compiler
state.issuesPromise = (state.issuesPromise || Promise.resolve())
// resolve to undefined on error
.catch(() => undefined)
.then(() => {
// early return
if (abortController.signal.aborted) {
return undefined;
}
debug(`Submitting the getIssuesWorker to the pool, iteration ${iteration}.`);
return plugin_pools_1.issuesPool.submit(() => __awaiter(this, void 0, void 0, function* () {
try {
debug(`Running the getIssuesWorker, iteration ${iteration}.`);
const issues = yield getIssuesWorker(aggregatedFilesChange, state.watching);
if (state.aggregatedFilesChange === aggregatedFilesChange) {
state.aggregatedFilesChange = undefined;
}
if (state.abortController === abortController) {
state.abortController = undefined;
}
return issues;
}
catch (error) {
hooks.error.call(error, compilation);
return undefined;
}
finally {
debug(`The getIssuesWorker finished its job, iteration ${iteration}.`);
}
}), abortController.signal);
});
debug(`Submitting the getDependenciesWorker to the pool, iteration ${iteration}.`);
state.dependenciesPromise = plugin_pools_1.dependenciesPool.submit(() => __awaiter(this, void 0, void 0, function* () {
try {
debug(`Running the getDependenciesWorker, iteration ${iteration}.`);
return yield getDependenciesWorker(filesChange);
}
catch (error) {
hooks.error.call(error, compilation);
return undefined;
}
finally {
debug(`The getDependenciesWorker finished its job, iteration ${iteration}.`);
}
})); // don't pass abortController.signal because getDependencies() is blocking
}));
}
exports.tapStartToRunWorkers = tapStartToRunWorkers;

View File

@@ -0,0 +1,5 @@
import type * as webpack from 'webpack';
import type { ForkTsCheckerWebpackPluginState } from '../plugin-state';
import type { RpcWorker } from '../rpc';
declare function tapStopToTerminateWorkers(compiler: webpack.Compiler, getIssuesWorker: RpcWorker, getDependenciesWorker: RpcWorker, state: ForkTsCheckerWebpackPluginState): void;
export { tapStopToTerminateWorkers };

View File

@@ -0,0 +1,26 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.tapStopToTerminateWorkers = void 0;
const infrastructure_logger_1 = require("../infrastructure-logger");
function tapStopToTerminateWorkers(compiler, getIssuesWorker, getDependenciesWorker, state) {
const { debug } = (0, infrastructure_logger_1.getInfrastructureLogger)(compiler);
const terminateWorkers = () => {
debug('Compiler is going to close - terminating workers...');
getIssuesWorker.terminate();
getDependenciesWorker.terminate();
};
compiler.hooks.watchClose.tap('ForkTsCheckerWebpackPlugin', () => {
terminateWorkers();
});
compiler.hooks.done.tap('ForkTsCheckerWebpackPlugin', () => {
if (!state.watching) {
terminateWorkers();
}
});
compiler.hooks.failed.tap('ForkTsCheckerWebpackPlugin', () => {
if (!state.watching) {
terminateWorkers();
}
});
}
exports.tapStopToTerminateWorkers = tapStopToTerminateWorkers;

View File

@@ -0,0 +1,2 @@
import { ForkTsCheckerWebpackPlugin } from './plugin';
export = ForkTsCheckerWebpackPlugin;

View File

@@ -0,0 +1,3 @@
"use strict";
const plugin_1 = require("./plugin");
module.exports = plugin_1.ForkTsCheckerWebpackPlugin;

View File

@@ -0,0 +1,9 @@
import type * as webpack from 'webpack';
export interface InfrastructureLogger {
log(...args: unknown[]): void;
debug(...args: unknown[]): void;
error(...args: unknown[]): void;
warn(...args: unknown[]): void;
info(...args: unknown[]): void;
}
export declare function getInfrastructureLogger(compiler: webpack.Compiler): InfrastructureLogger;

View File

@@ -0,0 +1,14 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getInfrastructureLogger = void 0;
function getInfrastructureLogger(compiler) {
const logger = compiler.getInfrastructureLogger('ForkTsCheckerWebpackPlugin');
return {
log: logger.log.bind(logger),
debug: logger.debug.bind(logger),
error: logger.error.bind(logger),
warn: logger.warn.bind(logger),
info: logger.info.bind(logger),
};
}
exports.getInfrastructureLogger = getInfrastructureLogger;

View File

@@ -0,0 +1,3 @@
export * from './issue';
export * from './issue-severity';
export * from './issue-location';

View File

@@ -0,0 +1,15 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
__exportStar(require("./issue"), exports);
__exportStar(require("./issue-severity"), exports);
__exportStar(require("./issue-location"), exports);

View File

@@ -0,0 +1,8 @@
import type * as webpack from 'webpack';
import type { IssueOptions } from './issue-options';
import type { IssuePredicate } from './issue-predicate';
interface IssueConfig {
predicate: IssuePredicate;
}
declare function createIssueConfig(compiler: webpack.Compiler, options: IssueOptions | undefined): IssueConfig;
export { IssueConfig, createIssueConfig };

View File

@@ -0,0 +1,29 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createIssueConfig = void 0;
const issue_match_1 = require("./issue-match");
const issue_predicate_1 = require("./issue-predicate");
function createIssuePredicateFromOption(context, option) {
if (Array.isArray(option)) {
return (0, issue_predicate_1.composeIssuePredicates)(option.map((option) => typeof option === 'function' ? option : (0, issue_match_1.createIssuePredicateFromIssueMatch)(context, option)));
}
return typeof option === 'function'
? option
: (0, issue_match_1.createIssuePredicateFromIssueMatch)(context, option);
}
function createIssueConfig(compiler, options) {
const context = compiler.options.context || process.cwd();
if (!options) {
options = {};
}
const include = options.include
? createIssuePredicateFromOption(context, options.include)
: (0, issue_predicate_1.createTrivialIssuePredicate)(true);
const exclude = options.exclude
? createIssuePredicateFromOption(context, options.exclude)
: (0, issue_predicate_1.createTrivialIssuePredicate)(false);
return {
predicate: (issue) => include(issue) && !exclude(issue),
};
}
exports.createIssueConfig = createIssueConfig;

View File

@@ -0,0 +1,8 @@
import type { IssuePosition } from './issue-position';
interface IssueLocation {
start: IssuePosition;
end: IssuePosition;
}
declare function compareIssueLocations(locationA?: IssueLocation, locationB?: IssueLocation): number;
declare function formatIssueLocation(location: IssueLocation): string;
export { IssueLocation, compareIssueLocations, formatIssueLocation };

View File

@@ -0,0 +1,22 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.formatIssueLocation = exports.compareIssueLocations = void 0;
const issue_position_1 = require("./issue-position");
function compareIssueLocations(locationA, locationB) {
if (locationA === locationB) {
return 0;
}
if (!locationA) {
return -1;
}
if (!locationB) {
return 1;
}
return ((0, issue_position_1.compareIssuePositions)(locationA.start, locationB.start) ||
(0, issue_position_1.compareIssuePositions)(locationA.end, locationB.end));
}
exports.compareIssueLocations = compareIssueLocations;
function formatIssueLocation(location) {
return `${location.start.line}:${location.start.column}`;
}
exports.formatIssueLocation = formatIssueLocation;

View File

@@ -0,0 +1,5 @@
import type { IssuePredicate } from './issue-predicate';
import type { Issue } from './index';
declare type IssueMatch = Partial<Pick<Issue, 'severity' | 'code' | 'file'>>;
declare function createIssuePredicateFromIssueMatch(context: string, match: IssueMatch): IssuePredicate;
export { IssueMatch, createIssuePredicateFromIssueMatch };

View File

@@ -0,0 +1,20 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createIssuePredicateFromIssueMatch = void 0;
const path_1 = __importDefault(require("path"));
const minimatch_1 = __importDefault(require("minimatch"));
const forward_slash_1 = require("../utils/path/forward-slash");
function createIssuePredicateFromIssueMatch(context, match) {
return (issue) => {
const matchesSeverity = !match.severity || match.severity === issue.severity;
const matchesCode = !match.code || match.code === issue.code;
const matchesFile = !issue.file ||
(!!issue.file &&
(!match.file || (0, minimatch_1.default)((0, forward_slash_1.forwardSlash)(path_1.default.relative(context, issue.file)), match.file)));
return matchesSeverity && matchesCode && matchesFile;
};
}
exports.createIssuePredicateFromIssueMatch = createIssuePredicateFromIssueMatch;

View File

@@ -0,0 +1,8 @@
import type { IssueMatch } from './issue-match';
import type { IssuePredicate } from './issue-predicate';
declare type IssuePredicateOption = IssuePredicate | IssueMatch | (IssuePredicate | IssueMatch)[];
interface IssueOptions {
include?: IssuePredicateOption;
exclude?: IssuePredicateOption;
}
export { IssueOptions, IssuePredicateOption };

View File

@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

View File

@@ -0,0 +1,6 @@
interface IssuePosition {
line: number;
column: number;
}
declare function compareIssuePositions(positionA?: IssuePosition, positionB?: IssuePosition): number;
export { IssuePosition, compareIssuePositions };

View File

@@ -0,0 +1,16 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.compareIssuePositions = void 0;
function compareIssuePositions(positionA, positionB) {
if (positionA === positionB) {
return 0;
}
if (!positionA) {
return -1;
}
if (!positionB) {
return 1;
}
return (Math.sign(positionA.line - positionB.line) || Math.sign(positionA.column - positionB.column));
}
exports.compareIssuePositions = compareIssuePositions;

View File

@@ -0,0 +1,5 @@
import type { Issue } from './index';
declare type IssuePredicate = (issue: Issue) => boolean;
declare function createTrivialIssuePredicate(result: boolean): IssuePredicate;
declare function composeIssuePredicates(predicates: IssuePredicate[]): IssuePredicate;
export { IssuePredicate, createTrivialIssuePredicate, composeIssuePredicates };

View File

@@ -0,0 +1,11 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.composeIssuePredicates = exports.createTrivialIssuePredicate = void 0;
function createTrivialIssuePredicate(result) {
return () => result;
}
exports.createTrivialIssuePredicate = createTrivialIssuePredicate;
function composeIssuePredicates(predicates) {
return (issue) => predicates.some((predicate) => predicate(issue));
}
exports.composeIssuePredicates = composeIssuePredicates;

View File

@@ -0,0 +1,4 @@
declare type IssueSeverity = 'error' | 'warning';
declare function isIssueSeverity(value: unknown): value is IssueSeverity;
declare function compareIssueSeverities(severityA: IssueSeverity, severityB: IssueSeverity): number;
export { IssueSeverity, isIssueSeverity, compareIssueSeverities };

View File

@@ -0,0 +1,12 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.compareIssueSeverities = exports.isIssueSeverity = void 0;
function isIssueSeverity(value) {
return ['error', 'warning'].includes(value);
}
exports.isIssueSeverity = isIssueSeverity;
function compareIssueSeverities(severityA, severityB) {
const [priorityA, priorityB] = [severityA, severityB].map((severity) => ['warning' /* 0 */, 'error' /* 1 */].indexOf(severity));
return Math.sign(priorityB - priorityA);
}
exports.compareIssueSeverities = compareIssueSeverities;

View File

@@ -0,0 +1,9 @@
import * as webpack from 'webpack';
import type { FormatterPathType } from '../formatter';
import type { Issue } from './issue';
declare class IssueWebpackError extends webpack.WebpackError {
readonly issue: Issue;
readonly hideStack = true;
constructor(message: string, pathType: FormatterPathType, issue: Issue);
}
export { IssueWebpackError };

View File

@@ -0,0 +1,51 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.IssueWebpackError = void 0;
const path_1 = __importDefault(require("path"));
const webpack = __importStar(require("webpack"));
const forward_slash_1 = require("../utils/path/forward-slash");
const relative_to_context_1 = require("../utils/path/relative-to-context");
const issue_location_1 = require("./issue-location");
class IssueWebpackError extends webpack.WebpackError {
constructor(message, pathType, issue) {
super(message);
this.issue = issue;
this.hideStack = true;
// to display issue location using `loc` property, webpack requires `error.module` which
// should be a NormalModule instance.
// to avoid such a dependency, we do a workaround - error.file will contain formatted location instead
if (issue.file) {
this.file =
pathType === 'absolute'
? (0, forward_slash_1.forwardSlash)(path_1.default.resolve(issue.file))
: (0, relative_to_context_1.relativeToContext)(issue.file, process.cwd());
if (issue.location) {
this.file += `:${(0, issue_location_1.formatIssueLocation)(issue.location)}`;
}
}
Error.captureStackTrace(this, this.constructor);
}
}
exports.IssueWebpackError = IssueWebpackError;

View File

@@ -0,0 +1,12 @@
import type { IssueLocation } from './issue-location';
import type { IssueSeverity } from './issue-severity';
interface Issue {
severity: IssueSeverity;
code: string;
message: string;
file?: string;
location?: IssueLocation;
}
declare function isIssue(value: unknown): value is Issue;
declare function deduplicateAndSortIssues(issues: Issue[]): Issue[];
export { Issue, isIssue, deduplicateAndSortIssues };

View File

@@ -0,0 +1,41 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.deduplicateAndSortIssues = exports.isIssue = void 0;
const issue_location_1 = require("./issue-location");
const issue_severity_1 = require("./issue-severity");
function isIssue(value) {
return (!!value &&
typeof value === 'object' &&
(0, issue_severity_1.isIssueSeverity)(value.severity) &&
!!value.code &&
!!value.message);
}
exports.isIssue = isIssue;
function compareStrings(stringA, stringB) {
if (stringA === stringB) {
return 0;
}
if (stringA === undefined || stringA === null) {
return -1;
}
if (stringB === undefined || stringB === null) {
return 1;
}
return stringA.toString().localeCompare(stringB.toString());
}
function compareIssues(issueA, issueB) {
return ((0, issue_severity_1.compareIssueSeverities)(issueA.severity, issueB.severity) ||
compareStrings(issueA.file, issueB.file) ||
(0, issue_location_1.compareIssueLocations)(issueA.location, issueB.location) ||
compareStrings(issueA.code, issueB.code) ||
compareStrings(issueA.message, issueB.message) ||
0 /* EqualTo */);
}
function equalsIssues(issueA, issueB) {
return compareIssues(issueA, issueB) === 0;
}
function deduplicateAndSortIssues(issues) {
const sortedIssues = issues.filter(isIssue).sort(compareIssues);
return sortedIssues.filter((issue, index) => index === 0 || !equalsIssues(issue, sortedIssues[index - 1]));
}
exports.deduplicateAndSortIssues = deduplicateAndSortIssues;

View File

@@ -0,0 +1,5 @@
interface Logger {
log: (message: string) => void;
error: (message: string) => void;
}
export { Logger };

View File

@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

View File

@@ -0,0 +1,16 @@
import type * as webpack from 'webpack';
import type { FormatterConfig } from './formatter';
import type { IssueConfig } from './issue/issue-config';
import type { Logger } from './logger';
import type { ForkTsCheckerWebpackPluginOptions } from './plugin-options';
import type { TypeScriptWorkerConfig } from './typescript/type-script-worker-config';
interface ForkTsCheckerWebpackPluginConfig {
async: boolean;
typescript: TypeScriptWorkerConfig;
issue: IssueConfig;
formatter: FormatterConfig;
logger: Logger;
devServer: boolean;
}
declare function createPluginConfig(compiler: webpack.Compiler, options?: ForkTsCheckerWebpackPluginOptions): ForkTsCheckerWebpackPluginConfig;
export { ForkTsCheckerWebpackPluginConfig, createPluginConfig };

View File

@@ -0,0 +1,26 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createPluginConfig = void 0;
const formatter_1 = require("./formatter");
const infrastructure_logger_1 = require("./infrastructure-logger");
const issue_config_1 = require("./issue/issue-config");
const type_script_worker_config_1 = require("./typescript/type-script-worker-config");
function createPluginConfig(compiler, options = {}) {
return {
async: options.async === undefined ? compiler.options.mode === 'development' : options.async,
typescript: (0, type_script_worker_config_1.createTypeScriptWorkerConfig)(compiler, options.typescript),
issue: (0, issue_config_1.createIssueConfig)(compiler, options.issue),
formatter: (0, formatter_1.createFormatterConfig)(options.formatter),
logger: options.logger === 'webpack-infrastructure'
? (() => {
const { info, error } = (0, infrastructure_logger_1.getInfrastructureLogger)(compiler);
return {
log: info,
error,
};
})()
: options.logger || console,
devServer: options.devServer !== false,
};
}
exports.createPluginConfig = createPluginConfig;

View File

@@ -0,0 +1,20 @@
import { SyncHook, SyncWaterfallHook, AsyncSeriesWaterfallHook } from 'tapable';
import type * as webpack from 'webpack';
import type { FilesChange } from './files-change';
import type { Issue } from './issue';
declare function createPluginHooks(): {
start: AsyncSeriesWaterfallHook<[FilesChange, webpack.Compilation], import("tapable").UnsetAdditionalOptions>;
waiting: SyncHook<[webpack.Compilation], void, import("tapable").UnsetAdditionalOptions>;
canceled: SyncHook<[webpack.Compilation], void, import("tapable").UnsetAdditionalOptions>;
error: SyncHook<[unknown, webpack.Compilation], void, import("tapable").UnsetAdditionalOptions>;
issues: SyncWaterfallHook<[Issue[], webpack.Compilation | undefined], void>;
};
declare type ForkTsCheckerWebpackPluginHooks = ReturnType<typeof createPluginHooks>;
declare function getPluginHooks(compiler: webpack.Compiler | webpack.MultiCompiler): {
start: AsyncSeriesWaterfallHook<[FilesChange, webpack.Compilation], import("tapable").UnsetAdditionalOptions>;
waiting: SyncHook<[webpack.Compilation], void, import("tapable").UnsetAdditionalOptions>;
canceled: SyncHook<[webpack.Compilation], void, import("tapable").UnsetAdditionalOptions>;
error: SyncHook<[unknown, webpack.Compilation], void, import("tapable").UnsetAdditionalOptions>;
issues: SyncWaterfallHook<[Issue[], webpack.Compilation | undefined], void>;
};
export { getPluginHooks, ForkTsCheckerWebpackPluginHooks };

View File

@@ -0,0 +1,45 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getPluginHooks = void 0;
const tapable_1 = require("tapable");
const compilerHookMap = new WeakMap();
function createPluginHooks() {
return {
start: new tapable_1.AsyncSeriesWaterfallHook([
'change',
'compilation',
]),
waiting: new tapable_1.SyncHook(['compilation']),
canceled: new tapable_1.SyncHook(['compilation']),
error: new tapable_1.SyncHook(['error', 'compilation']),
issues: new tapable_1.SyncWaterfallHook([
'issues',
'compilation',
]),
};
}
function forwardPluginHooks(source, target) {
source.start.tapPromise('ForkTsCheckerWebpackPlugin', target.start.promise);
source.waiting.tap('ForkTsCheckerWebpackPlugin', target.waiting.call);
source.canceled.tap('ForkTsCheckerWebpackPlugin', target.canceled.call);
source.error.tap('ForkTsCheckerWebpackPlugin', target.error.call);
source.issues.tap('ForkTsCheckerWebpackPlugin', target.issues.call);
}
function getPluginHooks(compiler) {
let hooks = compilerHookMap.get(compiler);
if (hooks === undefined) {
hooks = createPluginHooks();
compilerHookMap.set(compiler, hooks);
// proxy hooks for multi-compiler
if ('compilers' in compiler) {
compiler.compilers.forEach((childCompiler) => {
const childHooks = getPluginHooks(childCompiler);
if (hooks) {
forwardPluginHooks(childHooks, hooks);
}
});
}
}
return hooks;
}
exports.getPluginHooks = getPluginHooks;

View File

@@ -0,0 +1,13 @@
import type { FormatterOptions } from './formatter';
import type { IssueOptions } from './issue/issue-options';
import type { Logger } from './logger';
import type { TypeScriptWorkerOptions } from './typescript/type-script-worker-options';
interface ForkTsCheckerWebpackPluginOptions {
async?: boolean;
typescript?: TypeScriptWorkerOptions;
formatter?: FormatterOptions;
issue?: IssueOptions;
logger?: Logger | 'webpack-infrastructure';
devServer?: boolean;
}
export { ForkTsCheckerWebpackPluginOptions };

View File

@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

View File

@@ -0,0 +1,197 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"async": {
"type": "boolean",
"description": "When true, plugin will not block compilation to finish issues checking"
},
"typescript": {
"$ref": "#/definitions/TypeScriptOptions"
},
"formatter": {
"$ref": "#/definitions/FormatterOptions"
},
"issue": {
"$ref": "#/definitions/IssueOptions"
},
"logger": {
"$ref": "#/definitions/Logger"
},
"devServer": {
"type": "boolean",
"description": "Enable reporting to Webpack Dev Server."
}
},
"additionalProperties": false,
"definitions": {
"Formatter": {
"instanceof": "Function"
},
"ComplexFormatterPreferences": {
"type": "object",
"properties": {
"type": {
"$ref": "#/definitions/FormatterType"
},
"pathType": {
"$ref": "#/definitions/FormatterPathType"
},
"options": {
"type": "object",
"additionalProperties": true
}
},
"required": ["type"]
},
"FormatterType": {
"type": "string",
"enum": ["basic", "codeframe"]
},
"FormatterPathType": {
"type": "string",
"enum": ["relative", "absolute"]
},
"IssueMatch": {
"type": "object",
"properties": {
"severity": {
"type": "string",
"enum": ["error", "warning"]
},
"code": {
"type": "string"
},
"file": {
"type": "string"
}
}
},
"IssuePredicate": {
"instanceof": "Function"
},
"IssuePredicateOption": {
"oneOf": [
{
"$ref": "#/definitions/IssuePredicate"
},
{
"$ref": "#/definitions/IssueMatch"
},
{
"type": "array",
"items": {
"oneOf": [
{
"$ref": "#/definitions/IssuePredicate"
},
{
"$ref": "#/definitions/IssueMatch"
}
]
}
}
]
},
"Logger": {
"oneOf": [
{
"type": "object",
"properties": {
"error": {
"instanceof": "Function"
},
"log": {
"instanceof": "Function"
}
}
},
{
"type": "string",
"enum": ["webpack-infrastructure"]
}
]
},
"TypeScriptOptions": {
"type": "object",
"properties": {
"memoryLimit": {
"type": "number",
"description": "Memory limit for TypeScript reporter process."
},
"configFile": {
"type": "string",
"description": "Path to tsconfig.json. By default plugin uses context or process.cwd() to localize tsconfig.json file."
},
"context": {
"type": "string",
"description": "The base path for finding files specified in the tsconfig.json. Same as context option from the ts-loader."
},
"build": {
"type": "boolean",
"description": "The equivalent of the `--build` flag from the `tsc`."
},
"mode": {
"type": "string",
"enum": ["readonly", "write-tsbuildinfo", "write-dts", "write-references"],
"description": "`readonly` keeps all emitted files in memory, `write-tsbuildinfo` which writes only .tsbuildinfo files, `write-dts` writes .tsbuildinfo and type definition files, and `write-references` which writes both .tsbuildinfo and referenced projects output"
},
"compilerOptions": {
"type": "object",
"description": "Custom compilerOptions to be passed to the TypeScript compiler.",
"additionalProperties": true
},
"diagnosticOptions": {
"type": "object",
"description": "Types of diagnostics to be reported.",
"properties": {
"syntactic": {
"type": "boolean"
},
"semantic": {
"type": "boolean"
},
"declaration": {
"type": "boolean"
},
"global": {
"type": "boolean"
}
}
},
"profile": {
"type": "boolean",
"description": "Measures and prints timings related to the TypeScript performance."
},
"typescriptPath": {
"type": "string",
"description": "If supplied this is a custom path where TypeScript can be found."
}
}
},
"FormatterOptions": {
"oneOf": [
{
"$ref": "#/definitions/FormatterType"
},
{
"$ref": "#/definitions/ComplexFormatterPreferences"
},
{
"$ref": "#/definitions/Formatter"
}
]
},
"IssueOptions": {
"type": "object",
"properties": {
"include": {
"$ref": "#/definitions/IssuePredicateOption"
},
"exclude": {
"$ref": "#/definitions/IssuePredicateOption"
}
}
}
}
}

View File

@@ -0,0 +1,4 @@
import type { Pool } from './utils/async/pool';
declare const issuesPool: Pool;
declare const dependenciesPool: Pool;
export { issuesPool, dependenciesPool };

View File

@@ -0,0 +1,28 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.dependenciesPool = exports.issuesPool = void 0;
const os = __importStar(require("os"));
const pool_1 = require("./utils/async/pool");
const issuesPool = (0, pool_1.createPool)(Math.max(1, os.cpus().length));
exports.issuesPool = issuesPool;
const dependenciesPool = (0, pool_1.createPool)(Math.max(1, os.cpus().length));
exports.dependenciesPool = dependenciesPool;

View File

@@ -0,0 +1,18 @@
import type { AbortController } from 'node-abort-controller';
import type { FullTap } from 'tapable';
import type { FilesChange } from './files-change';
import type { FilesMatch } from './files-match';
import type { Issue } from './issue';
interface ForkTsCheckerWebpackPluginState {
issuesPromise: Promise<Issue[] | undefined>;
dependenciesPromise: Promise<FilesMatch | undefined>;
abortController: AbortController | undefined;
aggregatedFilesChange: FilesChange | undefined;
lastDependencies: FilesMatch | undefined;
watching: boolean;
initialized: boolean;
iteration: number;
webpackDevServerDoneTap: FullTap | undefined;
}
declare function createPluginState(): ForkTsCheckerWebpackPluginState;
export { ForkTsCheckerWebpackPluginState, createPluginState };

View File

@@ -0,0 +1,17 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createPluginState = void 0;
function createPluginState() {
return {
issuesPromise: Promise.resolve(undefined),
dependenciesPromise: Promise.resolve(undefined),
abortController: undefined,
aggregatedFilesChange: undefined,
lastDependencies: undefined,
watching: false,
initialized: false,
iteration: 0,
webpackDevServerDoneTap: undefined,
};
}
exports.createPluginState = createPluginState;

View File

@@ -0,0 +1,28 @@
import type * as webpack from 'webpack';
import type { ForkTsCheckerWebpackPluginOptions } from './plugin-options';
declare class ForkTsCheckerWebpackPlugin {
/**
* Current version of the plugin
*/
static readonly version: string;
/**
* Default pools for the plugin concurrency limit
*/
static readonly issuesPool: import("./utils/async/pool").Pool;
static readonly dependenciesPool: import("./utils/async/pool").Pool;
/**
* @deprecated Use ForkTsCheckerWebpackPlugin.issuesPool instead
*/
static readonly pool: import("./utils/async/pool").Pool;
private readonly options;
constructor(options?: ForkTsCheckerWebpackPluginOptions);
static getCompilerHooks(compiler: webpack.Compiler): {
start: import("tapable").AsyncSeriesWaterfallHook<[import("./files-change").FilesChange, webpack.Compilation], import("tapable").UnsetAdditionalOptions>;
waiting: import("tapable").SyncHook<[webpack.Compilation], void, import("tapable").UnsetAdditionalOptions>;
canceled: import("tapable").SyncHook<[webpack.Compilation], void, import("tapable").UnsetAdditionalOptions>;
error: import("tapable").SyncHook<[unknown, webpack.Compilation], void, import("tapable").UnsetAdditionalOptions>;
issues: import("tapable").SyncWaterfallHook<[import("./issue/issue").Issue[], webpack.Compilation | undefined], void>;
};
apply(compiler: webpack.Compiler): void;
}
export { ForkTsCheckerWebpackPlugin };

View File

@@ -0,0 +1,82 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ForkTsCheckerWebpackPlugin = void 0;
const path = __importStar(require("path"));
const cosmiconfig_1 = require("cosmiconfig");
const deepmerge_1 = __importDefault(require("deepmerge"));
const schema_utils_1 = require("schema-utils");
const tap_after_compile_to_add_dependencies_1 = require("./hooks/tap-after-compile-to-add-dependencies");
const tap_after_environment_to_patch_watching_1 = require("./hooks/tap-after-environment-to-patch-watching");
const tap_error_to_log_message_1 = require("./hooks/tap-error-to-log-message");
const tap_start_to_run_workers_1 = require("./hooks/tap-start-to-run-workers");
const tap_stop_to_terminate_workers_1 = require("./hooks/tap-stop-to-terminate-workers");
const plugin_config_1 = require("./plugin-config");
const plugin_hooks_1 = require("./plugin-hooks");
const plugin_options_json_1 = __importDefault(require("./plugin-options.json"));
const plugin_pools_1 = require("./plugin-pools");
const plugin_state_1 = require("./plugin-state");
const rpc_1 = require("./rpc");
const type_script_support_1 = require("./typescript/type-script-support");
class ForkTsCheckerWebpackPlugin {
constructor(options = {}) {
const explorerSync = (0, cosmiconfig_1.cosmiconfigSync)('fork-ts-checker');
const { config: externalOptions } = explorerSync.search() || {};
// first validate options directly passed to the constructor
const config = { name: 'ForkTsCheckerWebpackPlugin' };
(0, schema_utils_1.validate)(plugin_options_json_1.default, options, config);
this.options = (0, deepmerge_1.default)(externalOptions || {}, options || {});
// then validate merged options
(0, schema_utils_1.validate)(plugin_options_json_1.default, this.options, config);
}
static getCompilerHooks(compiler) {
return (0, plugin_hooks_1.getPluginHooks)(compiler);
}
apply(compiler) {
const config = (0, plugin_config_1.createPluginConfig)(compiler, this.options);
const state = (0, plugin_state_1.createPluginState)();
(0, type_script_support_1.assertTypeScriptSupport)(config.typescript);
const getIssuesWorker = (0, rpc_1.createRpcWorker)(path.resolve(__dirname, './typescript/worker/get-issues-worker.js'), config.typescript, config.typescript.memoryLimit);
const getDependenciesWorker = (0, rpc_1.createRpcWorker)(path.resolve(__dirname, './typescript/worker/get-dependencies-worker.js'), config.typescript);
(0, tap_after_environment_to_patch_watching_1.tapAfterEnvironmentToPatchWatching)(compiler, state);
(0, tap_start_to_run_workers_1.tapStartToRunWorkers)(compiler, getIssuesWorker, getDependenciesWorker, config, state);
(0, tap_after_compile_to_add_dependencies_1.tapAfterCompileToAddDependencies)(compiler, config, state);
(0, tap_stop_to_terminate_workers_1.tapStopToTerminateWorkers)(compiler, getIssuesWorker, getDependenciesWorker, state);
(0, tap_error_to_log_message_1.tapErrorToLogMessage)(compiler, config);
}
}
exports.ForkTsCheckerWebpackPlugin = ForkTsCheckerWebpackPlugin;
/**
* Current version of the plugin
*/
ForkTsCheckerWebpackPlugin.version = '9.0.2'; // will be replaced by the @semantic-release/exec
/**
* Default pools for the plugin concurrency limit
*/
ForkTsCheckerWebpackPlugin.issuesPool = plugin_pools_1.issuesPool;
ForkTsCheckerWebpackPlugin.dependenciesPool = plugin_pools_1.dependenciesPool;
/**
* @deprecated Use ForkTsCheckerWebpackPlugin.issuesPool instead
*/
ForkTsCheckerWebpackPlugin.pool = plugin_pools_1.issuesPool;

View File

@@ -0,0 +1 @@
export declare function exposeRpc(fn: (...args: any[]) => any): void;

View File

@@ -0,0 +1,78 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.exposeRpc = void 0;
const process_1 = __importDefault(require("process"));
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function exposeRpc(fn) {
const sendMessage = (message) => new Promise((resolve, reject) => {
if (!process_1.default.send) {
reject(new Error(`Process ${process_1.default.pid} doesn't have IPC channels`));
}
else if (!process_1.default.connected) {
reject(new Error(`Process ${process_1.default.pid} doesn't have open IPC channels`));
}
else {
process_1.default.send(message, undefined, undefined, (error) => {
if (error) {
reject(error);
}
else {
resolve(undefined);
}
});
}
});
const handleMessage = (message) => __awaiter(this, void 0, void 0, function* () {
if (message.type === 'call') {
if (!process_1.default.send) {
// process disconnected - skip
return;
}
let value;
let error;
try {
value = yield fn(...message.args);
}
catch (fnError) {
error = fnError;
}
try {
if (error) {
yield sendMessage({
type: 'reject',
id: message.id,
error,
});
}
else {
yield sendMessage({
type: 'resolve',
id: message.id,
value,
});
}
}
catch (sendError) {
// we can't send things back to the parent process - let's use stdout to communicate error
if (error) {
console.error(error);
}
console.error(sendError);
}
}
});
process_1.default.on('message', handleMessage);
}
exports.exposeRpc = exposeRpc;

View File

@@ -0,0 +1,5 @@
export { exposeRpc } from './expose-rpc';
export { wrapRpc } from './wrap-rpc';
export { createRpcWorker, getRpcWorkerData, RpcWorker } from './rpc-worker';
export { RpcExitError } from './rpc-error';
export { RpcRemoteMethod } from './types';

View File

@@ -0,0 +1,12 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.RpcExitError = exports.getRpcWorkerData = exports.createRpcWorker = exports.wrapRpc = exports.exposeRpc = void 0;
var expose_rpc_1 = require("./expose-rpc");
Object.defineProperty(exports, "exposeRpc", { enumerable: true, get: function () { return expose_rpc_1.exposeRpc; } });
var wrap_rpc_1 = require("./wrap-rpc");
Object.defineProperty(exports, "wrapRpc", { enumerable: true, get: function () { return wrap_rpc_1.wrapRpc; } });
var rpc_worker_1 = require("./rpc-worker");
Object.defineProperty(exports, "createRpcWorker", { enumerable: true, get: function () { return rpc_worker_1.createRpcWorker; } });
Object.defineProperty(exports, "getRpcWorkerData", { enumerable: true, get: function () { return rpc_worker_1.getRpcWorkerData; } });
var rpc_error_1 = require("./rpc-error");
Object.defineProperty(exports, "RpcExitError", { enumerable: true, get: function () { return rpc_error_1.RpcExitError; } });

View File

@@ -0,0 +1,6 @@
declare class RpcExitError extends Error {
readonly code?: string | number | null | undefined;
readonly signal?: string | null | undefined;
constructor(message: string, code?: string | number | null | undefined, signal?: string | null | undefined);
}
export { RpcExitError };

View File

@@ -0,0 +1,12 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.RpcExitError = void 0;
class RpcExitError extends Error {
constructor(message, code, signal) {
super(message);
this.code = code;
this.signal = signal;
this.name = 'RpcExitError';
}
}
exports.RpcExitError = RpcExitError;

View File

@@ -0,0 +1,13 @@
/// <reference types="node" />
import type { ChildProcess } from 'child_process';
import type { RpcMethod, RpcRemoteMethod } from './types';
interface RpcWorkerBase {
connect(): void;
terminate(): void;
readonly connected: boolean;
readonly process: ChildProcess | undefined;
}
declare type RpcWorker<T extends RpcMethod = RpcMethod> = RpcWorkerBase & RpcRemoteMethod<T>;
declare function createRpcWorker<T extends RpcMethod>(modulePath: string, data: unknown, memoryLimit?: number): RpcWorker<T>;
declare function getRpcWorkerData(): unknown;
export { createRpcWorker, getRpcWorkerData, RpcWorker };

View File

@@ -0,0 +1,79 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getRpcWorkerData = exports.createRpcWorker = void 0;
const child_process = __importStar(require("child_process"));
const process = __importStar(require("process"));
const wrap_rpc_1 = require("./wrap-rpc");
const WORKER_DATA_ENV_KEY = 'WORKER_DATA';
function createRpcWorker(modulePath, data, memoryLimit) {
const options = {
env: Object.assign(Object.assign({}, process.env), { [WORKER_DATA_ENV_KEY]: JSON.stringify(data || {}) }),
stdio: ['inherit', 'inherit', 'inherit', 'ipc'],
serialization: 'advanced',
};
if (memoryLimit) {
options.execArgv = [`--max-old-space-size=${memoryLimit}`];
}
let childProcess;
let remoteMethod;
const worker = {
connect() {
if (childProcess && !childProcess.connected) {
childProcess.kill('SIGTERM');
childProcess = undefined;
remoteMethod = undefined;
}
if (!(childProcess === null || childProcess === void 0 ? void 0 : childProcess.connected)) {
childProcess = child_process.fork(modulePath, options);
remoteMethod = (0, wrap_rpc_1.wrapRpc)(childProcess);
}
},
terminate() {
if (childProcess) {
childProcess.kill('SIGTERM');
childProcess = undefined;
remoteMethod = undefined;
}
},
get connected() {
return Boolean(childProcess === null || childProcess === void 0 ? void 0 : childProcess.connected);
},
get process() {
return childProcess;
},
};
return Object.assign((...args) => {
if (!worker.connected) {
// try to auto-connect
worker.connect();
}
if (!remoteMethod) {
return Promise.reject('Worker is not connected - cannot perform RPC.');
}
return remoteMethod(...args);
}, worker);
}
exports.createRpcWorker = createRpcWorker;
function getRpcWorkerData() {
return JSON.parse(process.env[WORKER_DATA_ENV_KEY] || '{}');
}
exports.getRpcWorkerData = getRpcWorkerData;

View File

@@ -0,0 +1,19 @@
interface RpcCallMessage {
type: 'call';
id: string;
args: unknown[];
}
interface RpcResolveMessage {
type: 'resolve';
id: string;
value: unknown;
}
interface RpcRejectMessage {
type: 'reject';
id: string;
error: unknown;
}
declare type RpcMessage = RpcCallMessage | RpcResolveMessage | RpcRejectMessage;
declare type RpcMethod = (...args: any[]) => any;
declare type RpcRemoteMethod<T extends RpcMethod> = T extends (...args: infer A) => infer R ? R extends Promise<any> ? (...args: A) => R : (...args: A) => Promise<R> : (...args: unknown[]) => Promise<unknown>;
export { RpcCallMessage, RpcResolveMessage, RpcRejectMessage, RpcMessage, RpcMethod, RpcRemoteMethod, };

View File

@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

View File

@@ -0,0 +1,4 @@
/// <reference types="node" />
import type { ChildProcess } from 'child_process';
import type { RpcRemoteMethod } from './types';
export declare function wrapRpc<T extends (...args: any[]) => any>(childProcess: ChildProcess): RpcRemoteMethod<T>;

View File

@@ -0,0 +1,79 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.wrapRpc = void 0;
const controlled_promise_1 = require("../utils/async/controlled-promise");
const rpc_error_1 = require("./rpc-error");
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function wrapRpc(childProcess) {
return ((...args) => __awaiter(this, void 0, void 0, function* () {
if (!childProcess.send) {
throw new Error(`Process ${childProcess.pid} doesn't have IPC channels`);
}
else if (!childProcess.connected) {
throw new Error(`Process ${childProcess.pid} doesn't have open IPC channels`);
}
const id = uuid();
// create promises
const { promise: resultPromise, resolve: resolveResult, reject: rejectResult, } = (0, controlled_promise_1.createControlledPromise)();
const { promise: sendPromise, resolve: resolveSend, reject: rejectSend, } = (0, controlled_promise_1.createControlledPromise)();
const handleMessage = (message) => {
if ((message === null || message === void 0 ? void 0 : message.id) === id) {
if (message.type === 'resolve') {
// assume the contract is respected
resolveResult(message.value);
removeHandlers();
}
else if (message.type === 'reject') {
rejectResult(message.error);
removeHandlers();
}
}
};
const handleClose = (code, signal) => {
rejectResult(new rpc_error_1.RpcExitError(code
? `Process ${childProcess.pid} exited with code ${code}` +
(signal ? ` [${signal}]` : '')
: `Process ${childProcess.pid} exited` + (signal ? ` [${signal}]` : ''), code, signal));
removeHandlers();
};
// to prevent event handler leaks
const removeHandlers = () => {
childProcess.off('message', handleMessage);
childProcess.off('close', handleClose);
};
// add event listeners
childProcess.on('message', handleMessage);
childProcess.on('close', handleClose);
// send call message
childProcess.send({
type: 'call',
id,
args,
}, (error) => {
if (error) {
rejectSend(error);
removeHandlers();
}
else {
resolveSend(undefined);
}
});
return sendPromise.then(() => resultPromise);
}));
}
exports.wrapRpc = wrapRpc;
function uuid() {
return new Array(4)
.fill(0)
.map(() => Math.floor(Math.random() * Number.MAX_SAFE_INTEGER).toString(16))
.join('-');
}

View File

@@ -0,0 +1,12 @@
interface TypeScriptConfigOverwrite {
extends?: string;
compilerOptions?: any;
include?: string[];
exclude?: string[];
files?: string[];
references?: {
path: string;
prepend?: boolean;
}[];
}
export { TypeScriptConfigOverwrite };

View File

@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

View File

@@ -0,0 +1,7 @@
interface TypeScriptDiagnosticsOptions {
syntactic: boolean;
semantic: boolean;
declaration: boolean;
global: boolean;
}
export { TypeScriptDiagnosticsOptions };

View File

@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

View File

@@ -0,0 +1,3 @@
import type { TypeScriptWorkerConfig } from './type-script-worker-config';
declare function assertTypeScriptSupport(config: TypeScriptWorkerConfig): void;
export { assertTypeScriptSupport };

View File

@@ -0,0 +1,63 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.assertTypeScriptSupport = void 0;
const os_1 = __importDefault(require("os"));
const fs_extra_1 = __importDefault(require("fs-extra"));
const semver = __importStar(require("semver"));
function assertTypeScriptSupport(config) {
let typescriptVersion;
try {
// eslint-disable-next-line @typescript-eslint/no-var-requires
typescriptVersion = require(config.typescriptPath).version;
}
catch (error) {
// silent catch
}
if (!typescriptVersion) {
throw new Error('When you use ForkTsCheckerWebpackPlugin with typescript reporter enabled, you must install `typescript` package.');
}
if (semver.lt(typescriptVersion, '3.6.0')) {
throw new Error([
`ForkTsCheckerWebpackPlugin cannot use the current typescript version of ${typescriptVersion}.`,
'The minimum required version is 3.6.0.',
].join(os_1.default.EOL));
}
if (config.build && semver.lt(typescriptVersion, '3.8.0')) {
throw new Error([
`ForkTsCheckerWebpackPlugin doesn't support build option for the current typescript version of ${typescriptVersion}.`,
'The minimum required version is 3.8.0.',
].join(os_1.default.EOL));
}
if (!fs_extra_1.default.existsSync(config.configFile)) {
throw new Error([
`Cannot find the "${config.configFile}" file.`,
`Please check webpack and ForkTsCheckerWebpackPlugin configuration.`,
`Possible errors:`,
' - wrong `context` directory in webpack configuration (if `configFile` is not set or is a relative path in the fork plugin configuration)',
' - wrong `typescript.configFile` path in the plugin configuration (should be a relative or absolute path)',
].join(os_1.default.EOL));
}
}
exports.assertTypeScriptSupport = assertTypeScriptSupport;

View File

@@ -0,0 +1,18 @@
import type * as webpack from 'webpack';
import type { TypeScriptConfigOverwrite } from './type-script-config-overwrite';
import type { TypeScriptDiagnosticsOptions } from './type-script-diagnostics-options';
import type { TypeScriptWorkerOptions } from './type-script-worker-options';
interface TypeScriptWorkerConfig {
enabled: boolean;
memoryLimit: number;
configFile: string;
configOverwrite: TypeScriptConfigOverwrite;
build: boolean;
context: string;
mode: 'readonly' | 'write-dts' | 'write-tsbuildinfo' | 'write-references';
diagnosticOptions: TypeScriptDiagnosticsOptions;
profile: boolean;
typescriptPath: string;
}
declare function createTypeScriptWorkerConfig(compiler: webpack.Compiler, options: TypeScriptWorkerOptions | undefined): TypeScriptWorkerConfig;
export { createTypeScriptWorkerConfig, TypeScriptWorkerConfig };

View File

@@ -0,0 +1,18 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createTypeScriptWorkerConfig = void 0;
const path_1 = __importDefault(require("path"));
function createTypeScriptWorkerConfig(compiler, options) {
let configFile = typeof options === 'object' ? options.configFile || 'tsconfig.json' : 'tsconfig.json';
// ensure that `configFile` is an absolute normalized path
configFile = path_1.default.normalize(path_1.default.isAbsolute(configFile)
? configFile
: path_1.default.resolve(compiler.options.context || process.cwd(), configFile));
const optionsAsObject = typeof options === 'object' ? options : {};
const typescriptPath = optionsAsObject.typescriptPath || require.resolve('typescript');
return Object.assign(Object.assign({ enabled: options !== false, memoryLimit: 2048, build: false, mode: optionsAsObject.build ? 'write-tsbuildinfo' : 'readonly', profile: false }, optionsAsObject), { configFile: configFile, configOverwrite: optionsAsObject.configOverwrite || {}, context: optionsAsObject.context || path_1.default.dirname(configFile), diagnosticOptions: Object.assign({ syntactic: false, semantic: true, declaration: false, global: false }, (optionsAsObject.diagnosticOptions || {})), typescriptPath: typescriptPath });
}
exports.createTypeScriptWorkerConfig = createTypeScriptWorkerConfig;

View File

@@ -0,0 +1,14 @@
import type { TypeScriptConfigOverwrite } from './type-script-config-overwrite';
import type { TypeScriptDiagnosticsOptions } from './type-script-diagnostics-options';
declare type TypeScriptWorkerOptions = {
memoryLimit?: number;
configFile?: string;
configOverwrite?: TypeScriptConfigOverwrite;
context?: string;
build?: boolean;
mode?: 'readonly' | 'write-tsbuildinfo' | 'write-dts' | 'write-references';
diagnosticOptions?: Partial<TypeScriptDiagnosticsOptions>;
profile?: boolean;
typescriptPath?: string;
};
export { TypeScriptWorkerOptions };

View File

@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

View File

@@ -0,0 +1,5 @@
import type { FilesChange } from '../../files-change';
import type { FilesMatch } from '../../files-match';
declare const getDependenciesWorker: (change: FilesChange) => FilesMatch;
export declare type GetDependenciesWorker = typeof getDependenciesWorker;
export {};

Some files were not shown because too many files have changed in this diff Show More