Skip to content

Commit

Permalink
Resolve npm package references to the ambient module when not found.
Browse files Browse the repository at this point in the history
  • Loading branch information
dsherret committed Oct 7, 2022
1 parent 58f8bcf commit a77af13
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 0 deletions.
19 changes: 19 additions & 0 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3595,6 +3595,25 @@ namespace ts {
}

function resolveExternalModule(location: Node, moduleReference: string, moduleNotFoundError: DiagnosticMessage | undefined, errorNode: Node, isForAugmentation = false): Symbol | undefined {
const result = resolveExternalModuleInner(location, moduleReference, moduleNotFoundError, errorNode, isForAugmentation);

// deno: attempt to resolve an npm package reference to its bare specifier w/ path ambient module
// when not found and the symbol has zero exports
if (moduleReference.startsWith("npm:") && (result == null || result?.exports?.size === 0)) {
const npmPackageRef = deno.tryParseNpmPackageReference(moduleReference);
if (npmPackageRef) {
const bareSpecifier = npmPackageRef.name + (npmPackageRef.subPath == null ? "" : "/" + npmPackageRef.subPath);
const ambientModule = tryFindAmbientModule(bareSpecifier, /*withAugmentations*/ true);
if (ambientModule) {
return ambientModule;
}
}
}

return result;
}

function resolveExternalModuleInner(location: Node, moduleReference: string, moduleNotFoundError: DiagnosticMessage | undefined, errorNode: Node, isForAugmentation = false): Symbol | undefined {
if (startsWith(moduleReference, "@types/")) {
const diag = Diagnostics.Cannot_import_type_declaration_files_Consider_importing_0_instead_of_1;
const withoutAtTypePrefix = removePrefix(moduleReference, "@types/");
Expand Down
39 changes: 39 additions & 0 deletions src/compiler/deno.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,4 +174,43 @@ namespace ts.deno {
}
}
}

export interface NpmPackageReference {
name: string;
versionReq: string;
subPath: string | undefined;
}

export function tryParseNpmPackageReference(text: string) {
try {
return parseNpmPackageReference(text);
} catch {
return undefined;
}
}

export function parseNpmPackageReference(text: string) {
if (!text.startsWith("npm:")) {
throw new Error(`Not an npm specifier: ${text}`);
}
text = text.replace(/^npm:/, "");
const parts = text.split("/");
const namePartLen = text.startsWith("@") ? 2 : 1;
if (parts.length < namePartLen) {
throw new Error(`Not a valid package: ${text}`);
}
const nameParts = parts.slice(0, namePartLen);
const lastNamePart = nameParts.at(-1)!;
const lastAtIndex = lastNamePart.lastIndexOf("@");
let versionReq: string | undefined = undefined;
if (lastAtIndex > 0) {
versionReq = lastNamePart.substring(lastAtIndex + 1);
nameParts[nameParts.length - 1] = lastNamePart.substring(0, lastAtIndex);
}
return {
name: nameParts.join("/"),
versionReq,
subPath: parts.length > nameParts.length ? parts.slice(nameParts.length).join("/") : undefined,
};
}
}

0 comments on commit a77af13

Please sign in to comment.