defmodule NPM.PackumentCache do
@moduledoc """
Disk cache for npm registry packuments.
Registry packuments are fetched frequently during dependency resolution.
Caching them under `NPM.Cache.dir()/packuments` reduces repeat network
requests while keeping the cache short-lived enough to pick up newly published
versions during normal development.
The TTL defaults to one hour and can be configured with
`config :duskmoon_npm, :packument_cache_ttl`.
"""
@default_ttl_seconds 3600
def dir do
Path.join(NPM.Cache.dir(), "packuments")
end
@spec get(String.t()) :: {:ok, term()} | :miss
def get(package) do
path = path_for(package)
with {:ok, %{mtime: mtime}} <- File.stat(path, time: :posix),
true <- System.os_time(:second) - mtime < ttl(),
{:ok, data} <- File.read(path) do
{:ok, :erlang.binary_to_term(data)}
else
_ -> :miss
end
rescue
_ -> :miss
end
@spec put(String.t(), term()) :: :ok
def put(package, packument) do
path = path_for(package)
File.mkdir_p!(Path.dirname(path))
File.write!(path, :erlang.term_to_binary(packument))
:ok
end
defp path_for(package) do
encoded = String.replace(package, "/", "__")
Path.join(dir(), "#{encoded}.etf")
end
defp ttl do
Application.get_env(:duskmoon_npm, :packument_cache_ttl, @default_ttl_seconds)
end
end