From 7f3dce9596bcd9fb7ff518a0642d8e620b1656bd Mon Sep 17 00:00:00 2001 From: Benjamin Lichtman Date: Fri, 1 Jun 2018 14:11:45 -0700 Subject: [PATCH 1/7] Handle installed package missing from registry --- src/services/jsTyping.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/jsTyping.ts b/src/services/jsTyping.ts index c6f97ec2a1acb..bc2853083055e 100644 --- a/src/services/jsTyping.ts +++ b/src/services/jsTyping.ts @@ -160,7 +160,7 @@ namespace ts.JsTyping { } // Add the cached typing locations for inferred typings that are already installed packageNameToTypingLocation.forEach((typing, name) => { - if (inferredTypings.has(name) && inferredTypings.get(name) === undefined && isTypingUpToDate(typing, typesRegistry.get(name))) { + if (inferredTypings.has(name) && inferredTypings.get(name) === undefined && typesRegistry.has(name) && isTypingUpToDate(typing, typesRegistry.get(name)!)) { inferredTypings.set(name, typing.typingLocation); } }); From a0e54296f56fc23236e12bd3500f97679a3faded Mon Sep 17 00:00:00 2001 From: Benjamin Lichtman Date: Fri, 1 Jun 2018 14:21:21 -0700 Subject: [PATCH 2/7] Add test --- src/harness/unittests/typingsInstaller.ts | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/harness/unittests/typingsInstaller.ts b/src/harness/unittests/typingsInstaller.ts index 2f83fe90c8a17..0cb021b5d8371 100644 --- a/src/harness/unittests/typingsInstaller.ts +++ b/src/harness/unittests/typingsInstaller.ts @@ -1340,6 +1340,27 @@ namespace ts.projectSystem { assert.deepEqual(result.newTypingNames, ["bar"]); }); + it("should gracefully handle packages that have been removed from the types-registry", () => { + const f = { + path: "/a/b/app.js", + content: "" + }; + const node = { + path: "/a/b/node.d.ts", + content: "" + }; + const host = createServerHost([f, node]); + const cache = createMapFromTemplate({ node: { typingLocation: node.path, version: Semver.parse("1.3.0") } }); + const logger = trackingLogger(); + const result = JsTyping.discoverTypings(host, logger.log, [f.path], getDirectoryPath(f.path), emptySafeList, cache, { enable: true }, ["fs", "bar"], emptyMap); + assert.deepEqual(logger.finish(), [ + 'Inferred typings from unresolved imports: ["node","bar"]', + 'Result: {"cachedTypingPaths":[],"newTypingNames":["node","bar"],"filesToWatch":["/a/b/bower_components","/a/b/node_modules"]}', + ]); + assert.deepEqual(result.cachedTypingPaths, []); + assert.deepEqual(result.newTypingNames, ["node", "bar"]); + }); + it("should search only 2 levels deep", () => { const app = { path: "/app.js", From ed2eb2edf21e5e0fad1dc42aed8c92a229fecef7 Mon Sep 17 00:00:00 2001 From: Benjamin Lichtman Date: Fri, 1 Jun 2018 15:21:22 -0700 Subject: [PATCH 3/7] Replace has with get and check undefined --- src/services/jsTyping.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/services/jsTyping.ts b/src/services/jsTyping.ts index bc2853083055e..480fac5ff511b 100644 --- a/src/services/jsTyping.ts +++ b/src/services/jsTyping.ts @@ -160,7 +160,8 @@ namespace ts.JsTyping { } // Add the cached typing locations for inferred typings that are already installed packageNameToTypingLocation.forEach((typing, name) => { - if (inferredTypings.has(name) && inferredTypings.get(name) === undefined && typesRegistry.has(name) && isTypingUpToDate(typing, typesRegistry.get(name)!)) { + const registryEntry = typesRegistry.get(name); + if (inferredTypings.has(name) && inferredTypings.get(name) === undefined && registryEntry !== undefined && isTypingUpToDate(typing, typesRegistry.get(name)!)) { inferredTypings.set(name, typing.typingLocation); } }); From 3d4bc3558cb064ec0bca98882e8d3d11e641afdb Mon Sep 17 00:00:00 2001 From: Benjamin Lichtman Date: Fri, 1 Jun 2018 15:32:23 -0700 Subject: [PATCH 4/7] Remove second get call --- src/services/jsTyping.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/jsTyping.ts b/src/services/jsTyping.ts index 480fac5ff511b..839ea18c62f63 100644 --- a/src/services/jsTyping.ts +++ b/src/services/jsTyping.ts @@ -161,7 +161,7 @@ namespace ts.JsTyping { // Add the cached typing locations for inferred typings that are already installed packageNameToTypingLocation.forEach((typing, name) => { const registryEntry = typesRegistry.get(name); - if (inferredTypings.has(name) && inferredTypings.get(name) === undefined && registryEntry !== undefined && isTypingUpToDate(typing, typesRegistry.get(name)!)) { + if (inferredTypings.has(name) && inferredTypings.get(name) === undefined && registryEntry !== undefined && isTypingUpToDate(typing, registryEntry!)) { inferredTypings.set(name, typing.typingLocation); } }); From 0b362089bb1982775fa50b7e70eb66671bb74301 Mon Sep 17 00:00:00 2001 From: Benjamin Lichtman Date: Mon, 4 Jun 2018 09:20:49 -0700 Subject: [PATCH 5/7] Remove redundant null assertion --- src/services/jsTyping.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/jsTyping.ts b/src/services/jsTyping.ts index 839ea18c62f63..0f69146ae9424 100644 --- a/src/services/jsTyping.ts +++ b/src/services/jsTyping.ts @@ -161,7 +161,7 @@ namespace ts.JsTyping { // Add the cached typing locations for inferred typings that are already installed packageNameToTypingLocation.forEach((typing, name) => { const registryEntry = typesRegistry.get(name); - if (inferredTypings.has(name) && inferredTypings.get(name) === undefined && registryEntry !== undefined && isTypingUpToDate(typing, registryEntry!)) { + if (inferredTypings.has(name) && inferredTypings.get(name) === undefined && registryEntry !== undefined && isTypingUpToDate(typing, registryEntry)) { inferredTypings.set(name, typing.typingLocation); } }); From f24652ce478e707312e758c00cbebea7d27ba064 Mon Sep 17 00:00:00 2001 From: Benjamin Lichtman Date: Fri, 1 Jun 2018 15:52:19 -0700 Subject: [PATCH 6/7] Always get latest tag of types-registry --- src/server/typingsInstaller/nodeTypingsInstaller.ts | 2 +- src/server/typingsInstaller/typingsInstaller.ts | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/server/typingsInstaller/nodeTypingsInstaller.ts b/src/server/typingsInstaller/nodeTypingsInstaller.ts index 35f926f1c1407..13886c43798f4 100644 --- a/src/server/typingsInstaller/nodeTypingsInstaller.ts +++ b/src/server/typingsInstaller/nodeTypingsInstaller.ts @@ -106,7 +106,7 @@ namespace ts.server.typingsInstaller { if (this.log.isEnabled()) { this.log.writeLine(`Updating ${typesRegistryPackageName} npm package...`); } - this.execSyncAndLog(`${this.npmPath} install --ignore-scripts ${typesRegistryPackageName}`, { cwd: globalTypingsCacheLocation }); + this.execSyncAndLog(`${this.npmPath} install --ignore-scripts ${typesRegistryPackageName}@${this.latestDistTag}`, { cwd: globalTypingsCacheLocation }); if (this.log.isEnabled()) { this.log.writeLine(`Updated ${typesRegistryPackageName} npm package`); } diff --git a/src/server/typingsInstaller/typingsInstaller.ts b/src/server/typingsInstaller/typingsInstaller.ts index 7d8cf02fab08a..641aabf59ef73 100644 --- a/src/server/typingsInstaller/typingsInstaller.ts +++ b/src/server/typingsInstaller/typingsInstaller.ts @@ -349,8 +349,8 @@ namespace ts.server.typingsInstaller { } // packageName is guaranteed to exist in typesRegistry by filterTypings - const distTags = this.typesRegistry.get(packageName); - const newVersion = Semver.parse(distTags[`ts${versionMajorMinor}`] || distTags[latestDistTag]); + const distTags = this.typesRegistry.get(packageName)!; + const newVersion = Semver.parse(distTags[`ts${versionMajorMinor}`] || distTags[this.latestDistTag]); const newTyping: JsTyping.CachedTyping = { typingLocation: typingFile, version: newVersion }; this.packageNameToTypingLocation.set(packageName, newTyping); installedTypingFiles.push(typingFile); @@ -523,12 +523,12 @@ namespace ts.server.typingsInstaller { protected abstract installWorker(requestId: number, packageNames: string[], cwd: string, onRequestCompleted: RequestCompletedAction): void; protected abstract sendResponse(response: SetTypings | InvalidateCachedTypings | BeginInstallTypes | EndInstallTypes): void; + + protected latestDistTag = "latest"; } /* @internal */ export function typingsName(packageName: string): string { return `@types/${packageName}@ts${versionMajorMinor}`; } - - const latestDistTag = "latest"; } From fd7411b8a9d0f588ce2ae965e9d4455fc1944b8a Mon Sep 17 00:00:00 2001 From: Benjamin Lichtman Date: Fri, 1 Jun 2018 16:03:04 -0700 Subject: [PATCH 7/7] Make tag readonly --- src/server/typingsInstaller/typingsInstaller.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/typingsInstaller/typingsInstaller.ts b/src/server/typingsInstaller/typingsInstaller.ts index 641aabf59ef73..59ea6aa5033b4 100644 --- a/src/server/typingsInstaller/typingsInstaller.ts +++ b/src/server/typingsInstaller/typingsInstaller.ts @@ -524,7 +524,7 @@ namespace ts.server.typingsInstaller { protected abstract installWorker(requestId: number, packageNames: string[], cwd: string, onRequestCompleted: RequestCompletedAction): void; protected abstract sendResponse(response: SetTypings | InvalidateCachedTypings | BeginInstallTypes | EndInstallTypes): void; - protected latestDistTag = "latest"; + protected readonly latestDistTag = "latest"; } /* @internal */