|
2 | 2 | Provides a `PackageManager` representation of `npm`. |
3 | 3 | """ |
4 | 4 |
|
| 5 | +import json |
5 | 6 | import logging |
6 | 7 | import os |
7 | 8 | import shutil |
@@ -170,8 +171,35 @@ def list_installed_packages(self) -> list[Package]: |
170 | 171 | Returns: |
171 | 172 | A `list[Package]` representing all `npm` packages installed in the active |
172 | 173 | `npm` environment. |
| 174 | +
|
| 175 | + Raises: |
| 176 | + RuntimeError: Failed to list installed packages or decode report JSON. |
| 177 | + ValueError: Encountered a malformed report for an installed package. |
173 | 178 | """ |
174 | | - raise NotImplementedError("Not yet implemented") |
| 179 | + def dependencies_to_packages(dependencies: dict[str, dict]) -> set[Package]: |
| 180 | + packages = set() |
| 181 | + |
| 182 | + for name, package_data in dependencies.items(): |
| 183 | + if (package_dependencies := package_data.get("dependencies")): |
| 184 | + packages |= dependencies_to_packages(package_dependencies) |
| 185 | + packages.add(Package(ECOSYSTEM.Npm, name, package_data["version"])) |
| 186 | + |
| 187 | + return packages |
| 188 | + |
| 189 | + try: |
| 190 | + npm_list_command = self._normalize_command(["npm", "list", "--all", "--json"]) |
| 191 | + npm_list = subprocess.run(npm_list_command, check=True, text=True, capture_output=True) |
| 192 | + dependencies = json.loads(npm_list.stdout.strip()).get("dependencies") |
| 193 | + return list(dependencies_to_packages(dependencies)) if dependencies else [] |
| 194 | + |
| 195 | + except subprocess.CalledProcessError: |
| 196 | + raise RuntimeError("Failed to list npm installed packages") |
| 197 | + |
| 198 | + except json.JSONDecodeError: |
| 199 | + raise RuntimeError("Failed to decode installed package report JSON") |
| 200 | + |
| 201 | + except KeyError: |
| 202 | + raise ValueError("Malformed installed package report") |
175 | 203 |
|
176 | 204 | def _normalize_command(self, command: list[str]) -> list[str]: |
177 | 205 | """ |
|
0 commit comments