Skip to content

Commit

Permalink
Use npm ls to batch registries scan if possible
Browse files Browse the repository at this point in the history
Fixes #136 again
  • Loading branch information
WarningImHack3r committed Sep 28, 2024
1 parent 8632964 commit 04e7ad3
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 1 deletion.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
### Added

- Add HTTP caching for some requests to the npm registry, improving performance (#135)
- Attempt to batch registries scan without network requests before falling back to the original behavior, speeding up the first scan (#136)
- Many thanks to [@SCjona](https://github.com/SCjona) for the whole 3.1.0 and the two issues of this release!

### Fixed

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package com.github.warningimhack3r.npmupdatedependencies.backend.engine

import com.github.warningimhack3r.npmupdatedependencies.backend.extensions.asJsonObject
import com.github.warningimhack3r.npmupdatedependencies.backend.extensions.asString
import com.intellij.openapi.components.Service
import com.intellij.openapi.components.service
import com.intellij.openapi.diagnostic.logger
import com.intellij.openapi.project.Project
import kotlinx.serialization.json.Json

@Service(Service.Level.PROJECT)
class RegistriesScanner(private val project: Project) {
Expand All @@ -26,8 +29,53 @@ class RegistriesScanner(private val project: Project) {

fun scan() {
log.info("Starting to scan registries")
val shellRunner = ShellRunner.getInstance(project)
val state = NUDState.getInstance(project)
// Populate packageRegistries with the contents of `npm ls --json`
shellRunner.execute(arrayOf("npm", "ls", "--json"))?.let { json ->
val jsonElement = Json.parseToJsonElement(json).asJsonObject ?: return@let.also {
log.warn("Failed to parse JSON from npm ls --json")
}
val dependencies = jsonElement["dependencies"]?.asJsonObject ?: return@let.also {
log.warn("No dependencies found in JSON from npm ls --json")
}
var registriesSet = setOf<String>()
for (packageName in dependencies.keys) {
val values = dependencies[packageName]?.asJsonObject ?: continue.also {
log.warn("No values found for package $packageName in JSON from npm ls --json")
}
if (values.keys.contains("extraneous")) {
log.debug("Package $packageName is extraneous, skipping")
continue
}
val registry = dependencies[packageName]?.asJsonObject?.get("resolved")?.asString ?: continue.also {
log.warn("No resolved found for package $packageName in JSON from npm ls --json")
}
if (!registry.startsWith("http")) {
log.warn("Invalid registry $registry for package $packageName, skipping")
continue
}
val formattedRegistry = registry.substringBefore("/$packageName")
log.debug("Found registry $formattedRegistry for package $packageName")
registriesSet += formattedRegistry

Check notice on line 60 in src/main/kotlin/com/github/warningimhack3r/npmupdatedependencies/backend/engine/RegistriesScanner.kt

View workflow job for this annotation

GitHub Actions / Qodana Community for JVM

Augmented assignment creates a new collection under the hood

'+=' on a read-only set creates a new set under the hood
state.packageRegistries[packageName] = formattedRegistry
}
registries = registriesSet.toList()
}
if (registries.isNotEmpty()) {
// There are extra thin chances of missing registries with
// this logic, like when a package with a custom registry is
// installed with pnpm BUT at least one other is installed
// with npm.
// We'll consider here such edge cases negligible (and the user's
// responsibility), prioritizing speed and simplicity instead of
// slowing things down for everyone because of a few weird cases.
log.info("Found registries from `npm ls`: $registries")
if (!scanned) scanned = true
return
}
// Run `npm config ls` to get the list of registries
val config = ShellRunner.getInstance(project).execute(arrayOf("npm", "config", "ls")) ?: return
val config = shellRunner.execute(arrayOf("npm", "config", "ls")) ?: return
registries = config.lines().asSequence().map { it.trim() }.filter { line ->
line.isNotEmpty() && line.isNotBlank() && !line.startsWith(";") &&
(line.contains("registry =") || line.contains("registry=")
Expand Down

0 comments on commit 04e7ad3

Please sign in to comment.