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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Changelog

## 9.6.2
* [chore: trim runtime dependencies — remove enhanced-resolve/semver, swap micromatch → picomatch](https://github.com/TypeStrong/ts-loader/pull/1701) - thanks @johnnyreilly

Officially ts-loader has supported 3.6.3+ versions of TypeScript. This change means that certain scenarios with older versions of TS will now certainly fail. If anyone is actually using these versions it would be surprising.

## 9.6.1
* [fix: rspack support](https://github.com/TypeStrong/ts-loader/pull/1699) - thanks @johnnyreilly and @bhollis

Expand Down
13 changes: 5 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ts-loader",
"version": "9.6.1",
"version": "9.6.2",
"description": "TypeScript loader for webpack",
"main": "index.js",
"types": "dist",
Expand Down Expand Up @@ -54,16 +54,13 @@
"homepage": "https://github.com/TypeStrong/ts-loader",
"dependencies": {
"chalk": "^4.1.0",
"enhanced-resolve": "^5.0.0",
"micromatch": "^4.0.0",
"semver": "^7.3.4",
"picomatch": "^4.0.0",
"source-map": "^0.7.4"
},
"devDependencies": {
"@eslint/js": "^10.0.1",
"@types/micromatch": "^4.0.0",
"@types/node": "*",
"@types/semver": "^7.3.4",
"@types/node": "^26.0.0",
"@types/picomatch": "^4.0.0",
"babel": "^6.0.0",
"babel-core": "^6.0.0",
"babel-loader": "^7.0.0",
Expand All @@ -74,7 +71,6 @@
"escape-string-regexp": "^2.0.0",
"eslint": "^10.0.0",
"eslint-config-prettier": "^10.0.0",
"eslint-plugin-n": "^17.0.0",
"fs-extra": "^11.0.0",
"glob": "^7.1.1",
"husky": "^8.0.0",
Expand All @@ -92,6 +88,7 @@
"mocha": "^6.0.0",
"prettier": "^2.0.5",
"rimraf": "^2.6.2",
"semver": "^7.8.5",
"typescript": "^6.0.2",
"typescript-eslint": "^8.59.4",
"webpack": "^5.74.0",
Expand Down
14 changes: 2 additions & 12 deletions src/compilerSetup.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import * as semver from 'semver';
import type typescript from 'typescript';

import type { LoaderOptions } from './interfaces';
Expand All @@ -25,17 +24,8 @@ export function getCompiler(loaderOptions: LoaderOptions, log: logger.Logger) {
}`;
compilerCompatible = false;
if (loaderOptions.compiler === 'typescript') {
if (
compiler!.version !== undefined &&
semver.gte(compiler!.version, '3.6.3')
) {
// don't log yet in this case, if a tsconfig.json exists we want to combine the message
compilerCompatible = true;
} else {
log.logError(
`${compilerDetailsLogMessage}. This version is incompatible with ts-loader. Please upgrade to the latest version of TypeScript.`
);
}
// don't log yet in this case, if a tsconfig.json exists we want to combine the message
compilerCompatible = true;
} else {
log.logWarning(
`${compilerDetailsLogMessage}. This version may or may not be compatible with ts-loader.`
Expand Down
2 changes: 0 additions & 2 deletions src/resolver.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import type * as webpack from 'webpack';

import { create as _create } from 'enhanced-resolve';

export function makeResolver(
_options: webpack.WebpackOptionsNormalized
): ResolveSync {
Expand Down
90 changes: 58 additions & 32 deletions src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { Chalk } from 'chalk';
import * as fs from 'fs';
import micromatch from 'micromatch';
import picomatch from 'picomatch';
import * as path from 'path';
import * as webpack from 'webpack';
import type typescript from 'typescript';
Expand Down Expand Up @@ -38,6 +38,40 @@ function defaultErrorFormatter(error: ErrorInfo, colors: Chalk) {
);
}

/**
* Build a file-matcher from a reportFiles pattern array that replicates
* micromatch semantics: a file must match a positive pattern AND not match
* any negative pattern. Returns null when reportFiles is empty (no filtering).
*/
function makeReportFilesMatcher(
reportFiles: string[],
): ((fileName: string) => boolean) | null {
if (reportFiles.length === 0) {
return null;
}
const { positivePatterns, negativePatterns } = reportFiles.reduce<{
positivePatterns: string[];
negativePatterns: string[];
}>(
(acc, p) => {
if (p.startsWith('!')) {
acc.negativePatterns.push(p.slice(1));
} else {
acc.positivePatterns.push(p);
}
return acc;
},
{ positivePatterns: [], negativePatterns: [] },
);
const matchPos = picomatch(
positivePatterns.length > 0 ? positivePatterns : ['**'],
);
const matchNeg =
negativePatterns.length > 0 ? picomatch(negativePatterns) : null;
return (fileName: string) =>
matchPos(fileName) && !(matchNeg && matchNeg(fileName));
}

/**
* Take TypeScript errors, parse them and format to webpack errors
* Optionally adds a file name
Expand All @@ -48,30 +82,21 @@ export function formatErrors(
colors: Chalk,
compiler: typeof typescript,
merge: { file?: string; module?: webpack.Module },
context: string
context: string,
): webpack.WebpackError[] {
const matchesReportFiles = makeReportFilesMatcher(loaderOptions.reportFiles);

return diagnostics === undefined
? []
: diagnostics
.filter(diagnostic => {
if (loaderOptions.ignoreDiagnostics.indexOf(diagnostic.code) !== -1) {
return false;
}
if (
loaderOptions.reportFiles.length > 0 &&
diagnostic.file !== undefined
) {
const relativeFileName = path.relative(
context,
diagnostic.file.fileName
);
const matchResult = micromatch(
[relativeFileName],
loaderOptions.reportFiles
);
if (matchResult.length === 0) {
if (matchesReportFiles !== null &&
diagnostic.file !== undefined &&
!matchesReportFiles(path.relative(context, diagnostic.file.fileName))) {
return false;
}
}
return true;
})
Expand All @@ -88,7 +113,7 @@ export function formatErrors(
].toLowerCase() as Severity,
content: compiler.flattenDiagnosticMessageText(
diagnostic.messageText,
constants.EOL
constants.EOL,
),
file: file === undefined ? '' : path.normalize(file.fileName),
line: start === undefined ? 0 : start.line,
Expand All @@ -106,7 +131,7 @@ export function formatErrors(
message,
merge.file === undefined ? errorInfo.file : merge.file,
start,
end
end,
);

return Object.assign(error, merge);
Expand All @@ -116,7 +141,7 @@ export function formatErrors(
function getFileLocations(
file: typescript.SourceFile,
position: number,
length = 0
length = 0,
) {
const startLC = file.getLineAndCharacterOfPosition(position);
const start: FileLocation = {
Expand All @@ -136,7 +161,7 @@ function getFileLocations(

export function fsReadFile(
fileName: string,
encoding: BufferEncoding | undefined = 'utf8'
encoding: BufferEncoding | undefined = 'utf8',
) {
fileName = path.normalize(fileName);
try {
Expand All @@ -151,7 +176,7 @@ export function makeError(
message: string,
file: string,
location?: FileLocation,
endLocation?: FileLocation
endLocation?: FileLocation,
): webpack.WebpackError {
if (isWebpack5) {
const error = new webpack.WebpackError(message);
Expand All @@ -163,7 +188,7 @@ export function makeError(
error.details = tsLoaderSource(loaderOptions);

return error;
}
}

return {
message,
Expand All @@ -185,7 +210,7 @@ interface WebpackSourcePosition {

function makeWebpackLocation(
location: FileLocation,
endLocation?: FileLocation
endLocation?: FileLocation,
) {
const start: WebpackSourcePosition = {
line: location.line,
Expand All @@ -205,7 +230,7 @@ export function tsLoaderSource(loaderOptions: LoaderOptions) {
export function appendSuffixIfMatch(
patterns: (RegExp | string)[],
filePath: string,
suffix: string
suffix: string,
): string {
if (patterns.length > 0) {
for (const regexp of patterns) {
Expand All @@ -219,7 +244,7 @@ export function appendSuffixIfMatch(

export function appendSuffixesIfMatch(
suffixDict: { [suffix: string]: (RegExp | string)[] },
filePath: string
filePath: string,
): string {
let amendedPath = filePath;
for (const suffix in suffixDict) {
Expand All @@ -243,10 +268,10 @@ export function unorderedRemoveItem<T>(array: T[], item: T): boolean {
export function populateDependencyGraph(
resolvedModules: ResolvedModule[],
instance: TSInstance,
containingFile: string
containingFile: string,
) {
resolvedModules = resolvedModules.filter(
mod => mod !== null && mod !== undefined
mod => mod !== null && mod !== undefined,
);
if (resolvedModules.length) {
const containingFileKey = instance.filePathKeyMapper(containingFile);
Expand All @@ -268,7 +293,7 @@ export function populateReverseDependencyGraph(instance: TSInstance) {
instance.solutionBuilderHost
? getInputFileNameFromOutput(instance, resolvedFileName) ||
resolvedFileName
: resolvedFileName
: resolvedFileName,
);
let map = reverseDependencyGraph.get(key);
if (!map) {
Expand All @@ -287,7 +312,7 @@ export function populateReverseDependencyGraph(instance: TSInstance) {
export function collectAllDependants(
reverseDependencyGraph: ReverseDependencyGraph,
fileName: FilePathKey,
result: Map<FilePathKey, true> = new Map()
result: Map<FilePathKey, true> = new Map(),
): Map<FilePathKey, true> {
result.set(fileName, true);
const dependants = reverseDependencyGraph.get(fileName);
Expand Down Expand Up @@ -316,7 +341,8 @@ export function ensureProgram(instance: TSInstance) {
instance.watchHost.updateRootFileNames();
}
if (instance.watchOfFilesAndCompilerOptions) {
instance.builderProgram = instance.watchOfFilesAndCompilerOptions.getProgram();
instance.builderProgram =
instance.watchOfFilesAndCompilerOptions.getProgram();
instance.program = instance.builderProgram.getProgram();
}
instance.hasUnaccountedModifiedFiles = false;
Expand All @@ -342,14 +368,14 @@ export function isReferencedFile(instance: TSInstance, filePath: string) {
return (
!!instance.solutionBuilderHost &&
!!instance.solutionBuilderHost.watchedFiles.get(
instance.filePathKeyMapper(filePath)
instance.filePathKeyMapper(filePath),
)
);
}

export function useCaseSensitiveFileNames(
compiler: typeof typescript,
loaderOptions: LoaderOptions
loaderOptions: LoaderOptions,
) {
return loaderOptions.useCaseSensitiveFileNames !== undefined
? loaderOptions.useCaseSensitiveFileNames
Expand Down
Loading