Source code for repomatic.npm
# Copyright Kevin Deldycke <[email protected]> and contributors.
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
"""npm registry API integration.
The npm counterpart to {mod}`repomatic.pypi`, used by `sync-workflow-pins` to
resolve the npm version literals embedded in workflow YAML (like
`npm install [email protected]`).
"""
from __future__ import annotations
from .config import load_repomatic_config
from .http import get_cached_json
TYPE_CHECKING = False
if TYPE_CHECKING:
from typing import Any
NPM_PACKAGE_URL = "https://www.npmjs.com/package/{package}"
"""npm package homepage URL. The npm counterpart to
{data}`repomatic.pypi.PYPI_PACKAGE_URL`."""
NPM_REGISTRY_URL = "https://registry.npmjs.org/{package}"
"""npm registry metadata URL for a package."""
def _fetch_json(package: str) -> dict[str, Any] | None:
"""Fetch the full JSON metadata for an npm package.
Results are cached under the `npm` namespace. Freshness TTL is read from
`CacheConfig.npm_ttl`. Returns `None` for every failure mode (HTTP error,
network error, timeout, JSON parse error).
:param package: The npm package name.
:return: Parsed JSON response, or `None` on any failure.
"""
return get_cached_json(
"npm",
package,
NPM_REGISTRY_URL.format(package=package),
ttl=load_repomatic_config().cache.npm_ttl,
log_label=f"npm lookup failed for {package}",
)
[docs]
def get_release_dates(package: str) -> dict[str, str]:
"""Get publication dates for all versions of an npm package.
:param package: The npm package name (e.g. `awesome-lint`).
:return: Dict mapping version strings to `YYYY-MM-DD` publication dates.
Empty if the package is not found or the request fails.
"""
data = _fetch_json(package)
if data is None:
return {}
# The `time` map is keyed by version, plus two housekeeping keys
# (`created`, `modified`) that are not versions.
times = data.get("time", {})
return {
version: stamp[:10]
for version, stamp in times.items()
if version not in ("created", "modified") and stamp
}