You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

972 lines
43 KiB

"use strict";
var __webpack_require__ = {};
(()=>{
__webpack_require__.n = (module)=>{
var getter = module && module.__esModule ? ()=>module['default'] : ()=>module;
__webpack_require__.d(getter, {
a: getter
});
return getter;
};
})();
(()=>{
__webpack_require__.d = (exports1, definition)=>{
for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
enumerable: true,
get: definition[key]
});
};
})();
(()=>{
__webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
})();
(()=>{
__webpack_require__.r = (exports1)=>{
if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
value: 'Module'
});
Object.defineProperty(exports1, '__esModule', {
value: true
});
};
})();
var __webpack_exports__ = {};
__webpack_require__.r(__webpack_exports__);
__webpack_require__.d(__webpack_exports__, {
TsCheckerRspackPlugin: ()=>TsCheckerRspackPlugin
});
const external_node_path_namespaceObject = require("node:path");
var external_node_path_default = /*#__PURE__*/ __webpack_require__.n(external_node_path_namespaceObject);
function getInfrastructureLogger(compiler) {
const logger = compiler.getInfrastructureLogger('TsCheckerRspackPlugin');
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)
};
}
const addTrailingSep = (dir)=>dir.endsWith(external_node_path_namespaceObject.sep) ? dir : dir + external_node_path_namespaceObject.sep;
const isStrictSubdir = (parent, child)=>{
const parentDir = addTrailingSep(parent);
const childDir = addTrailingSep(child);
return parentDir !== childDir && childDir.startsWith(parentDir);
};
function excludeOutputPath(dependencies, compiler) {
const isContextIncluded = dependencies.dirs.includes(compiler.context);
if (!isContextIncluded) return dependencies;
const outputPath = 'string' == typeof compiler.options.output?.path ? compiler.options.output.path : compiler.outputPath;
if (!outputPath || !isStrictSubdir(compiler.context, outputPath) || dependencies.dirs.includes(outputPath)) return dependencies;
const excluded = new Set(dependencies.excluded);
excluded.add(outputPath);
return {
...dependencies,
excluded: Array.from(excluded)
};
}
function tapAfterCompileToAddDependencies(compiler, config, state) {
const { debug } = getInfrastructureLogger(compiler);
compiler.hooks.afterCompile.tapPromise('TsCheckerRspackPlugin', async (compilation)=>{
if (compilation.compiler !== compiler) return;
const dependencies = await state.dependenciesPromise;
debug("Got dependencies from the getDependenciesWorker.", dependencies);
if (dependencies) {
const sanitizedDependencies = excludeOutputPath(dependencies, compiler);
state.lastDependencies = sanitizedDependencies;
sanitizedDependencies.files.forEach((file)=>{
compilation.fileDependencies.add(file);
});
}
});
}
const external_chokidar_namespaceObject = require("chokidar");
var external_chokidar_default = /*#__PURE__*/ __webpack_require__.n(external_chokidar_namespaceObject);
const external_minimatch_namespaceObject = require("minimatch");
const external_is_glob_namespaceObject = require("is-glob");
var external_is_glob_default = /*#__PURE__*/ __webpack_require__.n(external_is_glob_namespaceObject);
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))
};
}
function consumeFilesChange(compiler) {
const change = getFilesChange(compiler);
clearFilesChange(compiler);
return change;
}
function updateFilesChange(compiler, change) {
compilerFilesChangeMap.set(compiler, aggregateFilesChanges([
getFilesChange(compiler),
change
]));
}
function clearFilesChange(compiler) {
compilerFilesChangeMap.delete(compiler);
}
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)
};
}
function isInsideAnotherPath(parent, directory) {
const relativePart = (0, external_node_path_namespaceObject.relative)(parent, directory);
if (relativePart.startsWith('..')) return false;
if (0 === relativePart.length) return false;
if ((0, external_node_path_namespaceObject.isAbsolute)(relativePart)) return false;
return true;
}
function _define_property(obj, key, value) {
if (key in obj) Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
else obj[key] = value;
return obj;
}
const BUILTIN_IGNORED_DIRS = [
'.git'
];
function createIsIgnored(ignored, excluded) {
const ignoredPatterns = ignored ? Array.isArray(ignored) ? [
...ignored
] : [
ignored
] : [];
const filteredExcluded = excluded.filter((pattern)=>{
if (external_is_glob_default()(pattern)) {
const shouldAppendStar = pattern.includes('**') && !pattern.endsWith('*');
if (shouldAppendStar) ignoredPatterns.push(pattern.endsWith('/') ? `${pattern}**` : `${pattern}/**`);
else ignoredPatterns.push(pattern);
return false;
}
return true;
});
const ignoredFunctions = ignoredPatterns.map((pattern)=>{
if ('string' == typeof pattern) return (path)=>(0, external_minimatch_namespaceObject.minimatch)(path, pattern);
if (pattern instanceof RegExp) return (path)=>pattern.test(path);
return ()=>false;
});
ignoredFunctions.push((path)=>filteredExcluded.some((excludedPath)=>isInsideAnotherPath(excludedPath, path)));
ignoredFunctions.push((path)=>BUILTIN_IGNORED_DIRS.some((ignoredDir)=>path.includes(`/${ignoredDir}/`) || path.includes(`\\${ignoredDir}\\`)));
return function(path) {
return ignoredFunctions.some((ignoredFunction)=>ignoredFunction(path));
};
}
class InclusiveNodeWatchFileSystem {
get watcher() {
return this.watchFileSystem.watcher || this.watchFileSystem.wfs?.watcher;
}
constructor(watchFileSystem, compiler, pluginState){
_define_property(this, "watchFileSystem", void 0);
_define_property(this, "compiler", void 0);
_define_property(this, "pluginState", void 0);
_define_property(this, "dirsWatchers", void 0);
_define_property(this, "paused", void 0);
_define_property(this, "deletedFiles", void 0);
_define_property(this, "watch", void 0);
this.watchFileSystem = watchFileSystem;
this.compiler = compiler;
this.pluginState = pluginState;
this.paused = true;
this.watch = (files, dirs, missing, startTime, options, callback, callbackUndelayed)=>{
const { debug } = getInfrastructureLogger(this.compiler);
clearFilesChange(this.compiler);
const isIgnored = createIsIgnored(options?.ignored, this.pluginState.lastDependencies?.excluded || []);
const standardWatcher = this.watchFileSystem.watch(files, dirs, missing, startTime, options, callback, callbackUndelayed);
this.watcher?.on('change', (file)=>{
if ('string' != typeof file) return;
if (isIgnored(file)) debug("Detected file change but it's ignored", file);
else {
debug('Detected file change', file);
this.deletedFiles.delete(file);
updateFilesChange(this.compiler, {
changedFiles: [
file
]
});
}
});
this.watcher?.on('remove', (file)=>{
if ('string' != typeof file) return;
if (this.deletedFiles.has(file)) return void debug('Skipping duplicated remove event.');
if (isIgnored(file)) debug("Detected file remove but it's ignored", file);
else {
debug('Detected file remove', file);
this.deletedFiles.add(file);
updateFilesChange(this.compiler, {
deletedFiles: [
file
]
});
}
});
const prevDirs = Array.from(this.dirsWatchers.keys());
const nextDirs = Array.from(this.pluginState.lastDependencies?.dirs || []);
const dirsToUnwatch = prevDirs.filter((prevDir)=>!nextDirs.includes(prevDir));
const dirsToWatch = nextDirs.filter((nextDir)=>!prevDirs.includes(nextDir) && !isIgnored(nextDir));
dirsToUnwatch.forEach((dirToUnwatch)=>{
this.dirsWatchers.get(dirToUnwatch)?.close();
this.dirsWatchers.delete(dirToUnwatch);
});
dirsToWatch.forEach((dirToWatch)=>{
const interval = 'number' == typeof options?.poll ? options.poll : void 0;
const dirWatcher = external_chokidar_default().watch(dirToWatch, {
ignoreInitial: true,
ignorePermissionErrors: true,
ignored: (path)=>isIgnored(path),
usePolling: options?.poll ? true : void 0,
interval: interval,
binaryInterval: interval,
alwaysStat: true,
atomic: true,
awaitWriteFinish: true
});
dirWatcher.on('add', (file, stats)=>{
if (this.paused) return;
const extension = (0, external_node_path_namespaceObject.extname)(file);
const supportedExtensions = this.pluginState.lastDependencies?.extensions || [];
if (!supportedExtensions.includes(extension)) return void debug('Detected new file add but extension is not supported', file);
debug('Detected new file add', file);
this.deletedFiles.delete(file);
updateFilesChange(this.compiler, {
changedFiles: [
file
]
});
this.watcher?._onChange(file, stats?.mtimeMs || stats?.ctimeMs || 1, file, 'rename');
});
dirWatcher.on('unlink', (file)=>{
if (this.paused) return;
const extension = (0, external_node_path_namespaceObject.extname)(file);
const supportedExtensions = this.pluginState.lastDependencies?.extensions || [];
if (!supportedExtensions.includes(extension)) return void debug('Detected new file remove but extension is not supported', file);
if (this.deletedFiles.has(file)) return void debug('Skipping duplicated unlink event.');
debug('Detected new file remove', file);
this.deletedFiles.add(file);
updateFilesChange(this.compiler, {
deletedFiles: [
file
]
});
this.watcher?._onRemove(dirToWatch, file, 'rename');
});
this.dirsWatchers.set(dirToWatch, dirWatcher);
});
this.paused = false;
return {
...standardWatcher,
close: ()=>{
clearFilesChange(this.compiler);
if (standardWatcher) standardWatcher.close();
this.dirsWatchers.forEach((dirWatcher)=>{
dirWatcher?.close();
});
this.dirsWatchers.clear();
this.paused = true;
},
pause: ()=>{
if (standardWatcher) standardWatcher.pause();
this.paused = true;
}
};
};
this.dirsWatchers = new Map();
this.deletedFiles = new Set();
}
}
function tapAfterEnvironmentToPatchWatching(compiler, state) {
const { debug } = getInfrastructureLogger(compiler);
compiler.hooks.afterEnvironment.tap('TsCheckerRspackPlugin', ()=>{
const watchFileSystem = compiler.watchFileSystem;
if (watchFileSystem) {
debug("Overwriting Rspack's watch file system.");
compiler.watchFileSystem = new InclusiveNodeWatchFileSystem(watchFileSystem, compiler, state);
} else debug('No watch file system found - plugin may not work correctly.');
});
}
const external_picocolors_namespaceObject = require("picocolors");
var external_picocolors_default = /*#__PURE__*/ __webpack_require__.n(external_picocolors_namespaceObject);
const lite_tapable_namespaceObject = require("@rspack/lite-tapable");
const compilerHookMap = new WeakMap();
function createPluginHooks() {
return {
start: new lite_tapable_namespaceObject.AsyncSeriesWaterfallHook([
'change',
'compilation'
]),
waiting: new lite_tapable_namespaceObject.SyncHook([
'compilation'
]),
canceled: new lite_tapable_namespaceObject.SyncHook([
'compilation'
]),
error: new lite_tapable_namespaceObject.SyncHook([
'error',
'compilation'
]),
issues: new lite_tapable_namespaceObject.SyncWaterfallHook([
'issues',
'compilation'
])
};
}
function forwardPluginHooks(source, target) {
source.start.tapPromise('TsCheckerRspackPlugin', target.start.promise);
source.waiting.tap('TsCheckerRspackPlugin', target.waiting.call);
source.canceled.tap('TsCheckerRspackPlugin', target.canceled.call);
source.error.tap('TsCheckerRspackPlugin', target.error.call);
source.issues.tap('TsCheckerRspackPlugin', target.issues.call);
}
function getPluginHooks(compiler) {
let hooks = compilerHookMap.get(compiler);
if (void 0 === hooks) {
hooks = createPluginHooks();
compilerHookMap.set(compiler, hooks);
if ('compilers' in compiler) compiler.compilers.forEach((childCompiler)=>{
const childHooks = getPluginHooks(childCompiler);
if (hooks) forwardPluginHooks(childHooks, hooks);
});
}
return hooks;
}
const external_node_process_namespaceObject = require("node:process");
function createControlledPromise() {
let resolve = ()=>void 0;
let reject = ()=>void 0;
const promise = new Promise((aResolve, aReject)=>{
resolve = aResolve;
reject = aReject;
});
return {
promise,
resolve,
reject
};
}
function rpc_error_define_property(obj, key, value) {
if (key in obj) Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
else obj[key] = value;
return obj;
}
class RpcExitError extends Error {
constructor(message, code, signal){
super(message), rpc_error_define_property(this, "code", void 0), rpc_error_define_property(this, "signal", void 0), this.code = code, this.signal = signal;
this.name = 'RpcExitError';
}
}
function wrapRpc(childProcess) {
return async (...args)=>{
if (childProcess.send) {
if (!childProcess.connected) throw new Error(`Process ${childProcess.pid} doesn't have open IPC channels`);
} else throw new Error(`Process ${childProcess.pid} doesn't have IPC channels`);
const id = uuid();
const { promise: resultPromise, resolve: resolveResult, reject: rejectResult } = createControlledPromise();
const { promise: sendPromise, resolve: resolveSend, reject: rejectSend } = createControlledPromise();
const handleMessage = (message)=>{
if (message?.id === id) {
if ('resolve' === message.type) {
resolveResult(message.value);
removeHandlers();
} else if ('reject' === message.type) {
rejectResult(message.error);
removeHandlers();
}
}
};
const handleClose = (code, signal)=>{
rejectResult(new RpcExitError(code ? `Process ${childProcess.pid} exited with code ${code}` + (signal ? ` [${signal}]` : '') : `Process ${childProcess.pid} exited` + (signal ? ` [${signal}]` : ''), code, signal));
removeHandlers();
};
const removeHandlers = ()=>{
childProcess.off('message', handleMessage);
childProcess.off('close', handleClose);
};
childProcess.on('message', handleMessage);
childProcess.on('close', handleClose);
childProcess.send({
type: 'call',
id,
args
}, (error)=>{
if (error) {
rejectSend(error);
removeHandlers();
} else resolveSend(void 0);
});
return sendPromise.then(()=>resultPromise);
};
}
function uuid() {
return new Array(4).fill(0).map(()=>Math.floor(Math.random() * Number.MAX_SAFE_INTEGER).toString(16)).join('-');
}
const external_node_child_process_namespaceObject = require("node:child_process");
const WORKER_DATA_ENV_KEY = 'WORKER_DATA';
function createRpcWorker(modulePath, data, memoryLimit) {
const options = {
env: {
...external_node_process_namespaceObject.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 = void 0;
remoteMethod = void 0;
}
if (!childProcess?.connected) {
childProcess = external_node_child_process_namespaceObject.fork(modulePath, options);
remoteMethod = wrapRpc(childProcess);
}
},
terminate () {
if (childProcess) {
childProcess.kill('SIGTERM');
childProcess = void 0;
remoteMethod = void 0;
}
},
get connected () {
return Boolean(childProcess?.connected);
},
get process () {
return childProcess;
}
};
return Object.assign((...args)=>{
if (!worker.connected) worker.connect();
if (!remoteMethod) return Promise.reject('Worker is not connected - cannot perform RPC.');
return remoteMethod(...args);
}, worker);
}
class AbortError extends Error {
static throwIfAborted(signal) {
if (signal?.aborted) throw new AbortError();
}
constructor(message = 'Task aborted.'){
super(message);
this.name = 'AbortError';
}
}
function tapErrorToLogMessage(compiler, config) {
const hooks = getPluginHooks(compiler);
hooks.error.tap('TsCheckerRspackPlugin', (error)=>{
if (error instanceof AbortError) return;
config.logger.error(String(error));
if (error instanceof RpcExitError) if ('SIGINT' === error.signal) config.logger.error(external_picocolors_default().red("[type-check] 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 TsCheckerRspackPlugin configuration."));
else config.logger.error(external_picocolors_default().red("[type-check] Issues checking service aborted - probably out of memory. Check the `memoryLimit` option in the TsCheckerRspackPlugin configuration.\nIf increasing the memory doesn't solve the issue, it's most probably a bug in the TypeScript."));
});
}
const external_node_os_namespaceObject = require("node:os");
var external_node_os_default = /*#__PURE__*/ __webpack_require__.n(external_node_os_namespaceObject);
function createPool(size) {
let pendingPromises = [];
const pool = {
async submit (task, signal) {
while(pendingPromises.length >= pool.size){
AbortError.throwIfAborted(signal);
await Promise.race(pendingPromises).catch(()=>void 0);
}
AbortError.throwIfAborted(signal);
const taskPromise = task(signal).finally(()=>{
pendingPromises = pendingPromises.filter((pendingPromise)=>pendingPromise !== taskPromise);
});
pendingPromises.push(taskPromise);
return taskPromise;
},
size,
get pending () {
return pendingPromises.length;
},
get drained () {
return new Promise(async (resolve)=>{
while(pendingPromises.length > 0)await Promise.race(pendingPromises).catch(()=>void 0);
resolve(void 0);
});
}
};
return pool;
}
const issuesPool = createPool(Math.max(1, external_node_os_namespaceObject.cpus().length));
const dependenciesPool = createPool(Math.max(1, external_node_os_namespaceObject.cpus().length));
function interceptDoneToGetDevServerTap(compiler, config, state) {
const { debug } = getInfrastructureLogger(compiler);
compiler.hooks.done.intercept({
register: (tap)=>{
if ([
'webpack-dev-server',
'rsbuild-dev-server'
].includes(tap.name) && 'sync' === tap.type && config.devServer) {
debug('Intercepting dev-server tap.');
state.DevServerDoneTap = tap;
}
return tap;
}
});
}
function forwardSlash(input) {
return external_node_path_default().normalize(input).replace(/\\+/g, '/');
}
function relativeToContext(file, context) {
let fileInContext = forwardSlash(external_node_path_default().relative(context, file));
if (!fileInContext.startsWith('../')) fileInContext = './' + fileInContext;
return fileInContext;
}
function formatIssueLocation(location) {
return `${location.start.line}:${location.start.column}`;
}
function issue_rspack_error_define_property(obj, key, value) {
if (key in obj) Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
else obj[key] = value;
return obj;
}
class IssueRspackError extends Error {
constructor(message, pathType, issue){
super(message), issue_rspack_error_define_property(this, "issue", void 0), issue_rspack_error_define_property(this, "hideStack", void 0), issue_rspack_error_define_property(this, "file", void 0), this.issue = issue, this.hideStack = true;
if (issue.file) {
this.file = 'absolute' === pathType ? forwardSlash(external_node_path_default().resolve(issue.file)) : relativeToContext(issue.file, process.cwd());
if (issue.location) this.file += `:${formatIssueLocation(issue.location)}`;
}
Error.captureStackTrace(this, this.constructor);
}
}
function tapAfterCompileToGetIssues(compiler, config, state) {
const hooks = getPluginHooks(compiler);
const { debug } = getInfrastructureLogger(compiler);
compiler.hooks.afterCompile.tapPromise('TsCheckerRspackPlugin', async (compilation)=>{
if (compilation.compiler !== compiler) return;
let issues = [];
try {
issues = await state.issuesPromise;
} catch (error) {
hooks.error.call(error, compilation);
return;
}
debug('Got issues from getIssuesWorker.', issues?.length);
if (!issues) return;
issues = issues.filter(config.issue.predicate);
issues = hooks.issues.call(issues, compilation);
issues.forEach((issue)=>{
const error = new IssueRspackError(config.formatter.format(issue), config.formatter.pathType, issue);
if ('warning' === issue.severity) compilation.warnings.push(error);
else compilation.errors.push(error);
});
});
}
function statsFormatter(issues, stats) {
const errorsNumber = issues.filter((issue)=>'error' === issue.severity).length;
const warningsNumber = issues.filter((issue)=>'warning' === issue.severity).length;
const errorsFormatted = errorsNumber ? external_picocolors_default().bold(external_picocolors_default().red(`${errorsNumber} ${1 === errorsNumber ? 'error' : 'errors'}`)) : '';
const warningsFormatted = warningsNumber ? external_picocolors_default().bold(external_picocolors_default().yellow(`${warningsNumber} ${1 === warningsNumber ? 'warning' : 'warnings'}`)) : '';
const timeFormatted = stats.startTime ? Math.round(Date.now() - stats.startTime) : 0;
if (!errorsFormatted && !warningsFormatted) return external_picocolors_default().green(`[type-check] no errors found in ${timeFormatted} ms`);
return [
'[type-check] found ',
errorsFormatted,
errorsFormatted && warningsFormatted ? ' and ' : '',
warningsFormatted,
timeFormatted ? ` in ${timeFormatted} ms` : ''
].join('');
}
function createRspackFormatter(formatter, pathType) {
return function(issue) {
const color = 'warning' === issue.severity ? external_picocolors_default().yellow : external_picocolors_default().red;
const severity = issue.severity.toUpperCase();
if (!issue.file) return [
`${external_picocolors_default().bold(color(severity))} in ` + formatter(issue),
''
].join(external_node_os_default().EOL);
{
let location = external_picocolors_default().bold('absolute' === pathType ? forwardSlash(external_node_path_default().resolve(issue.file)) : relativeToContext(issue.file, process.cwd()));
if (issue.location) location += `:${external_picocolors_default().bold(external_picocolors_default().green(formatIssueLocation(issue.location)))}`;
return [
`${external_picocolors_default().bold(color(severity))} in ${location}`,
formatter(issue),
''
].join(external_node_os_default().EOL);
}
};
}
function isPending(promise, timeout = 100) {
return Promise.race([
promise.then(()=>false).catch(()=>false),
new Promise((resolve)=>setTimeout(()=>resolve(true), timeout))
]);
}
function wait(timeout) {
return new Promise((resolve)=>setTimeout(resolve, timeout));
}
function tapDoneToAsyncGetIssues(compiler, config, state) {
const hooks = getPluginHooks(compiler);
const { debug } = getInfrastructureLogger(compiler);
compiler.hooks.done.tap('TsCheckerRspackPlugin', async (stats)=>{
if (stats.compilation.compiler !== compiler) return;
const issuesPromise = state.issuesPromise;
let issues;
try {
if (await isPending(issuesPromise)) {
hooks.waiting.call(stats.compilation);
config.logger.log(external_picocolors_default().cyan('[type-check] in progress...'));
} else await wait(10);
issues = await issuesPromise;
} catch (error) {
hooks.error.call(error, stats.compilation);
return;
}
if (!issues || state.issuesPromise !== issuesPromise) return;
debug(`Got ${issues?.length || 0} issues from getIssuesWorker.`);
issues = issues.filter(config.issue.predicate);
issues = hooks.issues.call(issues, stats.compilation);
const formatter = createRspackFormatter(config.formatter.format, config.formatter.pathType);
if (issues.length) config.logger.error(issues.map((issue)=>formatter(issue)).join('\n'));
config.logger.log(statsFormatter(issues, stats));
if (issues.length && state.DevServerDoneTap) {
issues.forEach((issue)=>{
const error = new IssueRspackError(config.formatter.format(issue), config.formatter.pathType, issue);
if ('warning' === issue.severity) stats.compilation.warnings.push(error);
else stats.compilation.errors.push(error);
});
debug('Sending issues to the dev-server.');
state.DevServerDoneTap.fn(stats);
}
});
}
function tapStartToRunWorkers(compiler, getIssuesWorker, getDependenciesWorker, config, state) {
const hooks = getPluginHooks(compiler);
const { log, debug } = getInfrastructureLogger(compiler);
compiler.hooks.run.tap('TsCheckerRspackPlugin', ()=>{
if (!state.initialized) {
debug('Initializing plugin for single run (not async).');
state.initialized = true;
state.watching = false;
tapAfterCompileToGetIssues(compiler, config, state);
}
});
compiler.hooks.watchRun.tap('TsCheckerRspackPlugin', async ()=>{
if (!state.initialized) {
state.initialized = true;
state.watching = true;
if (config.async) {
debug('Initializing plugin for watch run (async).');
tapDoneToAsyncGetIssues(compiler, config, state);
interceptDoneToGetDevServerTap(compiler, config, state);
} else {
debug('Initializing plugin for watch run (not async).');
tapAfterCompileToGetIssues(compiler, config, state);
}
}
});
compiler.hooks.compilation.tap('TsCheckerRspackPlugin', async (compilation)=>{
if (compilation.compiler !== compiler) return;
const iteration = ++state.iteration;
if (state.abortController) {
debug(`Aborting iteration ${iteration - 1}.`);
state.abortController.abort();
}
const abortController = new AbortController();
state.abortController = abortController;
let filesChange = {};
if (state.watching) {
filesChange = 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 = await hooks.start.promise(filesChange, compilation);
let aggregatedFilesChange = filesChange;
if (state.aggregatedFilesChange) {
aggregatedFilesChange = 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;
state.issuesPromise = (state.issuesPromise || Promise.resolve()).catch(()=>void 0).then(()=>{
if (abortController.signal.aborted) return;
debug(`Submitting the getIssuesWorker to the pool, iteration ${iteration}.`);
return issuesPool.submit(async ()=>{
try {
debug(`Running the getIssuesWorker, iteration ${iteration}.`);
const issues = await getIssuesWorker(aggregatedFilesChange, state.watching, config.issue.defaultSeverity);
if (state.aggregatedFilesChange === aggregatedFilesChange) state.aggregatedFilesChange = void 0;
if (state.abortController === abortController) state.abortController = void 0;
return issues;
} catch (error) {
hooks.error.call(error, compilation);
return;
} finally{
debug(`The getIssuesWorker finished its job, iteration ${iteration}.`);
}
}, abortController.signal);
});
debug(`Submitting the getDependenciesWorker to the pool, iteration ${iteration}.`);
state.dependenciesPromise = dependenciesPool.submit(async ()=>{
try {
debug(`Running the getDependenciesWorker, iteration ${iteration}.`);
return await getDependenciesWorker(filesChange);
} catch (error) {
hooks.error.call(error, compilation);
return;
} finally{
debug(`The getDependenciesWorker finished its job, iteration ${iteration}.`);
}
});
});
}
function tapStopToTerminateWorkers(compiler, getIssuesWorker, getDependenciesWorker, state) {
const { debug } = getInfrastructureLogger(compiler);
const terminateWorkers = ()=>{
debug('Compiler is going to close - terminating workers...');
getIssuesWorker.terminate();
getDependenciesWorker.terminate();
};
compiler.hooks.watchClose.tap('TsCheckerRspackPlugin', ()=>{
terminateWorkers();
});
compiler.hooks.done.tap('TsCheckerRspackPlugin', ()=>{
if (!state.watching) terminateWorkers();
});
compiler.hooks.failed.tap('TsCheckerRspackPlugin', ()=>{
if (!state.watching) terminateWorkers();
});
}
function createBasicFormatter() {
return function(issue) {
return external_picocolors_default().gray(issue.code + ': ') + issue.message;
};
}
const code_frame_namespaceObject = require("@babel/code-frame");
const external_node_fs_namespaceObject = require("node:fs");
var external_node_fs_default = /*#__PURE__*/ __webpack_require__.n(external_node_fs_namespaceObject);
function createCodeFrameFormatter(options) {
const basicFormatter = createBasicFormatter();
return function(issue) {
const source = issue.file && external_node_fs_default().existsSync(issue.file) && external_node_fs_default().readFileSync(issue.file, 'utf-8');
let frame = '';
if (source && issue.location) frame = (0, code_frame_namespaceObject.codeFrameColumns)(source, issue.location, {
highlightCode: true,
...options || {}
}).split('\n').map((line)=>' ' + line).join(external_node_os_default().EOL);
const lines = [
basicFormatter(issue)
];
if (frame) lines.push(frame);
return lines.join(external_node_os_default().EOL);
};
}
function createFormatterConfig(options) {
if ('function' == typeof options) return {
format: options,
pathType: 'relative'
};
const type = options ? 'object' == typeof options ? options.type || 'codeframe' : options : 'codeframe';
const pathType = options && 'object' == typeof options ? options.pathType || 'relative' : 'relative';
if (!type || 'basic' === type) return {
format: createBasicFormatter(),
pathType
};
if ('codeframe' === type) {
const config = options && 'object' == typeof options ? options.options || {} : {};
return {
format: createCodeFrameFormatter(config),
pathType
};
}
throw new Error(`Unknown "${type}" formatter. Available types are: "basic", "codeframe" or a custom function.`);
}
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, external_minimatch_namespaceObject.minimatch)(forwardSlash(external_node_path_default().relative(context, issue.file)), match.file));
return matchesSeverity && matchesCode && matchesFile;
};
}
function createTrivialIssuePredicate(result) {
return ()=>result;
}
function composeIssuePredicates(predicates) {
return (issue)=>predicates.some((predicate)=>predicate(issue));
}
function createIssuePredicateFromOption(context, option) {
if (Array.isArray(option)) return composeIssuePredicates(option.map((option)=>'function' == typeof option ? option : createIssuePredicateFromIssueMatch(context, option)));
return 'function' == typeof option ? option : 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) : createTrivialIssuePredicate(true);
const exclude = options.exclude ? createIssuePredicateFromOption(context, options.exclude) : createTrivialIssuePredicate(false);
const defaultSeverity = options.defaultSeverity ?? 'auto';
return {
predicate: (issue)=>include(issue) && !exclude(issue),
defaultSeverity
};
}
function createTypeScriptWorkerConfig(compiler, options) {
let configFile = 'object' == typeof options ? options.configFile || 'tsconfig.json' : 'tsconfig.json';
configFile = external_node_path_default().normalize(external_node_path_default().isAbsolute(configFile) ? configFile : external_node_path_default().resolve(compiler.options.context || process.cwd(), configFile));
const optionsAsObject = 'object' == typeof options ? options : {};
const typescriptPath = optionsAsObject.typescriptPath || require.resolve("typescript");
return {
enabled: Boolean(options) || void 0 === options,
memoryLimit: 8192,
build: false,
mode: optionsAsObject.build ? 'write-tsbuildinfo' : 'readonly',
profile: false,
...optionsAsObject,
configFile: configFile,
configOverwrite: optionsAsObject.configOverwrite || {},
context: optionsAsObject.context || external_node_path_default().dirname(configFile),
diagnosticOptions: {
syntactic: false,
semantic: true,
declaration: false,
global: false,
...optionsAsObject.diagnosticOptions || {}
},
typescriptPath: typescriptPath
};
}
function createPluginConfig(compiler, options = {}) {
return {
async: void 0 === options.async ? 'development' === compiler.options.mode : options.async,
typescript: createTypeScriptWorkerConfig(compiler, options.typescript),
issue: createIssueConfig(compiler, options.issue),
formatter: createFormatterConfig(options.formatter),
logger: 'webpack-infrastructure' === options.logger ? (()=>{
const { info, error } = getInfrastructureLogger(compiler);
return {
log: info,
error
};
})() : options.logger || console,
devServer: false !== options.devServer
};
}
function createPluginState() {
return {
issuesPromise: Promise.resolve(void 0),
dependenciesPromise: Promise.resolve(void 0),
abortController: void 0,
aggregatedFilesChange: void 0,
lastDependencies: void 0,
watching: false,
initialized: false,
iteration: 0,
DevServerDoneTap: void 0
};
}
function assertTypeScriptSupport(config) {
let typescriptVersion;
try {
typescriptVersion = require(config.typescriptPath).version;
} catch {}
if (!typescriptVersion) throw new Error("When you use TsCheckerRspackPlugin with typescript reporter enabled, you must install `typescript` package.");
if (!external_node_fs_default().existsSync(config.configFile)) throw new Error([
`Cannot find the "${config.configFile}" file.`,
"Please check Rspack and TsCheckerRspackPlugin configuration.",
"Possible errors:",
' - wrong `context` directory in Rspack 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(external_node_os_default().EOL));
}
function plugin_define_property(obj, key, value) {
if (key in obj) Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
else obj[key] = value;
return obj;
}
const pkgJson = JSON.parse((0, external_node_fs_namespaceObject.readFileSync)(external_node_path_namespaceObject.join(__dirname, '../package.json'), 'utf-8'));
class TsCheckerRspackPlugin {
static getCompilerHooks(compiler) {
return getPluginHooks(compiler);
}
apply(compiler) {
const config = createPluginConfig(compiler, this.options);
const state = createPluginState();
assertTypeScriptSupport(config.typescript);
const getIssuesWorker = createRpcWorker(external_node_path_namespaceObject.resolve(__dirname, './getIssuesWorker.js'), config.typescript, config.typescript.memoryLimit);
const getDependenciesWorker = createRpcWorker(external_node_path_namespaceObject.resolve(__dirname, './getDependenciesWorker.js'), config.typescript);
tapAfterEnvironmentToPatchWatching(compiler, state);
tapStartToRunWorkers(compiler, getIssuesWorker, getDependenciesWorker, config, state);
tapAfterCompileToAddDependencies(compiler, config, state);
tapStopToTerminateWorkers(compiler, getIssuesWorker, getDependenciesWorker, state);
tapErrorToLogMessage(compiler, config);
}
constructor(options = {}){
plugin_define_property(this, "options", void 0);
this.options = options;
}
}
plugin_define_property(TsCheckerRspackPlugin, "version", pkgJson.version);
plugin_define_property(TsCheckerRspackPlugin, "issuesPool", issuesPool);
plugin_define_property(TsCheckerRspackPlugin, "dependenciesPool", dependenciesPool);
plugin_define_property(TsCheckerRspackPlugin, "pool", issuesPool);
exports.TsCheckerRspackPlugin = __webpack_exports__.TsCheckerRspackPlugin;
for(var __webpack_i__ in __webpack_exports__)if (-1 === [
"TsCheckerRspackPlugin"
].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
Object.defineProperty(exports, '__esModule', {
value: true
});