Skip to content

Commit af8e44a

Browse files
authored
Merge pull request #26568 from Microsoft/typesVersions
Adds support for "typesVersions" redirects
2 parents cbde861 + a255d9a commit af8e44a

File tree

69 files changed

+2428
-323
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+2428
-323
lines changed

src/compiler/checker.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -2292,12 +2292,12 @@ namespace ts {
22922292
? chainDiagnosticMessages(
22932293
/*details*/ undefined,
22942294
Diagnostics.If_the_0_package_actually_exposes_this_module_consider_sending_a_pull_request_to_amend_https_Colon_Slash_Slashgithub_com_SlashDefinitelyTyped_SlashDefinitelyTyped_Slashtree_Slashmaster_Slashtypes_Slash_1,
2295-
packageId.name, getMangledNameForScopedPackage(packageId.name))
2295+
packageId.name, mangleScopedPackageName(packageId.name))
22962296
: chainDiagnosticMessages(
22972297
/*details*/ undefined,
22982298
Diagnostics.Try_npm_install_types_Slash_1_if_it_exists_or_add_a_new_declaration_d_ts_file_containing_declare_module_0,
22992299
moduleReference,
2300-
getMangledNameForScopedPackage(packageId.name))
2300+
mangleScopedPackageName(packageId.name))
23012301
: undefined;
23022302
errorOrSuggestion(isError, errorNode, chainDiagnosticMessages(
23032303
errorInfo,

src/compiler/core.ts

+1
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ namespace ts {
6565

6666
/* @internal */
6767
namespace ts {
68+
export const emptyArray: never[] = [] as never[];
6869

6970
/** Create a MapLike with good performance. */
7071
function createDictionaryObject<T>(): MapLike<T> {

src/compiler/diagnosticMessages.json

+17-1
Original file line numberDiff line numberDiff line change
@@ -3294,7 +3294,7 @@
32943294
"category": "Message",
32953295
"code": 6104
32963296
},
3297-
"Expected type of '{0}' field in 'package.json' to be 'string', got '{1}'.": {
3297+
"Expected type of '{0}' field in 'package.json' to be '{1}', got '{2}'.": {
32983298
"category": "Message",
32993299
"code": 6105
33003300
},
@@ -3692,6 +3692,22 @@
36923692
"category": "Error",
36933693
"code": 6205
36943694
},
3695+
"'package.json' has a 'typesVersions' field with version-specific path mappings.": {
3696+
"category": "Message",
3697+
"code": 6206
3698+
},
3699+
"'package.json' does not have a 'typesVersions' entry that matches version '{0}'.": {
3700+
"category": "Message",
3701+
"code": 6207
3702+
},
3703+
"'package.json' has a 'typesVersions' entry '{0}' that matches compiler version '{1}', looking for a pattern to match module name '{2}'.": {
3704+
"category": "Message",
3705+
"code": 6208
3706+
},
3707+
"'package.json' has a 'typesVersions' entry '{0}' that is not a valid semver range.": {
3708+
"category": "Message",
3709+
"code": 6209
3710+
},
36953711

36963712
"Projects to reference": {
36973713
"category": "Message",

src/compiler/moduleNameResolver.ts

+321-213
Large diffs are not rendered by default.

src/compiler/moduleSpecifiers.ts

+29-13
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,8 @@ namespace ts.moduleSpecifiers {
235235
const suffix = pattern.substr(indexOfStar + 1);
236236
if (relativeToBaseUrl.length >= prefix.length + suffix.length &&
237237
startsWith(relativeToBaseUrl, prefix) &&
238-
endsWith(relativeToBaseUrl, suffix)) {
238+
endsWith(relativeToBaseUrl, suffix) ||
239+
!suffix && relativeToBaseUrl === removeTrailingDirectorySeparator(prefix)) {
239240
const matchedStar = relativeToBaseUrl.substr(prefix.length, relativeToBaseUrl.length - suffix.length);
240241
return key.replace("*", matchedStar);
241242
}
@@ -264,6 +265,26 @@ namespace ts.moduleSpecifiers {
264265
return undefined;
265266
}
266267

268+
const packageRootPath = moduleFileName.substring(0, parts.packageRootIndex);
269+
const packageJsonPath = combinePaths(packageRootPath, "package.json");
270+
const packageJsonContent = host.fileExists!(packageJsonPath)
271+
? JSON.parse(host.readFile!(packageJsonPath)!)
272+
: undefined;
273+
const versionPaths = packageJsonContent && packageJsonContent.typesVersions
274+
? getPackageJsonTypesVersionsPaths(packageJsonContent.typesVersions)
275+
: undefined;
276+
if (versionPaths) {
277+
const subModuleName = moduleFileName.slice(parts.packageRootIndex + 1);
278+
const fromPaths = tryGetModuleNameFromPaths(
279+
removeFileExtension(subModuleName),
280+
removeExtensionAndIndexPostFix(subModuleName, Ending.Minimal, options),
281+
versionPaths.paths
282+
);
283+
if (fromPaths !== undefined) {
284+
moduleFileName = combinePaths(moduleFileName.slice(0, parts.packageRootIndex), fromPaths);
285+
}
286+
}
287+
267288
// Simplify the full file path to something that can be resolved by Node.
268289

269290
// If the module could be imported by a directory name, use that directory's name
@@ -274,23 +295,18 @@ namespace ts.moduleSpecifiers {
274295

275296
// If the module was found in @types, get the actual Node package name
276297
const nodeModulesDirectoryName = moduleSpecifier.substring(parts.topLevelPackageNameIndex + 1);
277-
const packageName = getPackageNameFromAtTypesDirectory(nodeModulesDirectoryName);
298+
const packageName = getPackageNameFromTypesPackageName(nodeModulesDirectoryName);
278299
// For classic resolution, only allow importing from node_modules/@types, not other node_modules
279300
return getEmitModuleResolutionKind(options) !== ModuleResolutionKind.NodeJs && packageName === nodeModulesDirectoryName ? undefined : packageName;
280301

281302
function getDirectoryOrExtensionlessFileName(path: string): string {
282303
// If the file is the main module, it can be imported by the package name
283-
const packageRootPath = path.substring(0, parts.packageRootIndex);
284-
const packageJsonPath = combinePaths(packageRootPath, "package.json");
285-
if (host.fileExists!(packageJsonPath)) { // TODO: GH#18217
286-
const packageJsonContent = JSON.parse(host.readFile!(packageJsonPath)!);
287-
if (packageJsonContent) {
288-
const mainFileRelative = packageJsonContent.typings || packageJsonContent.types || packageJsonContent.main;
289-
if (mainFileRelative) {
290-
const mainExportFile = toPath(mainFileRelative, packageRootPath, getCanonicalFileName);
291-
if (removeFileExtension(mainExportFile) === removeFileExtension(getCanonicalFileName(path))) {
292-
return packageRootPath;
293-
}
304+
if (packageJsonContent) {
305+
const mainFileRelative = packageJsonContent.typings || packageJsonContent.types || packageJsonContent.main;
306+
if (mainFileRelative) {
307+
const mainExportFile = toPath(mainFileRelative, packageRootPath, getCanonicalFileName);
308+
if (removeFileExtension(mainExportFile) === removeFileExtension(getCanonicalFileName(path))) {
309+
return packageRootPath;
294310
}
295311
}
296312
}

0 commit comments

Comments
 (0)