Lightning.Adaptors.NPM.Registry (Lightning v2.19.0)

View Source

NPM registry HTTP client for Lightning.Adaptors.NPM.

Talks to registry.npmjs.org. Responsible for the list_adaptors/0 scope listing and the packument endpoint fetch_adaptor/1 uses.

list_adaptors/0 deliberately merges two endpoints rather than calling one:

  • /-/user/openfn/package is the authoritative name list for the @openfn org and the trust boundary, since it cannot return a name Lightning does not already trust. It has no version data.
  • /-/v1/search is only a cheap version lookup for whichever of those names it happens to cover. npm's relevance ranking demotes or excludes deprecated packages from search results even on an exact-name query, so search alone silently drops names. It is not a safe source of scope membership, only of version data for names already known to be in scope.

Any authoritative name missing from the search results falls back to a per-name get_packument/1 and latest_version/1 call, bounded to the handful of names search does not cover. Do not "simplify" this back to a single search call or a pagination bump. Search's result count is capped by npm's relevance ranking regardless of size and from, and deprecated packages are excluded from ranking entirely, so no amount of paging recovers them.

Base URL via Lightning.Adaptors.Config.strategy_opts(Lightning.Adaptors.NPM)[:registry_url], default https://registry.npmjs.org.

Summary

Functions

Build the per-version version_record list from a packument.

Is the given version in packument flagged as deprecated?

Fetch the full packument for a package.

Extract the dist-tags.latest version from a packument.

Full @openfn/language-* scope listing, each with a real latest_version.

Normalise the packument's repository field to a plain URL string.

Resolve the tarball URL for version in packument.

Functions

build_versions(packument)

@spec build_versions(map()) :: [map()]

Build the per-version version_record list from a packument.

deprecated?(packument, version)

@spec deprecated?(map(), String.t()) :: boolean()

Is the given version in packument flagged as deprecated?

get_packument(name)

@spec get_packument(String.t()) ::
  {:ok, map()} | {:error, :not_found} | {:error, term()}

Fetch the full packument for a package.

latest_version(packument)

@spec latest_version(map()) :: {:ok, String.t()} | {:error, :no_latest_version}

Extract the dist-tags.latest version from a packument.

list_adaptors()

@spec list_adaptors() ::
  {:ok, [%{name: String.t(), latest_version: String.t()}]} | {:error, term()}

Full @openfn/language-* scope listing, each with a real latest_version.

Merges /-/user/openfn/package (authoritative name list) with /-/v1/search (cheap version lookup), falling back to a per-name packument fetch for any name search doesn't cover. See the moduledoc for why this isn't a single call.

The @openfn org holds hundreds of packages, so a registry answering with none of them has not told us the adaptors are gone; it is a mirror that has not synced the scope, or a mistyped URL. Rather than report an empty catalogue and have the Scheduler act on it, an empty list is {:error, :empty_listing} and a 200 whose body is not a map is {:error, :malformed_listing}, both of which leave the stored rows alone.

repository_url(url)

@spec repository_url(term()) :: String.t() | nil

Normalise the packument's repository field to a plain URL string.

require_tarball_url(packument, version)

@spec require_tarball_url(map(), String.t()) ::
  {:ok, String.t()} | {:error, :no_tarball_url}

Resolve the tarball URL for version in packument.