Class: GemCP::Client

Inherits:
Object
  • Object
show all
Defined in:
lib/gemcp/client.rb

Overview

HTTP client for the RubyGems.org API with local-first resolution, conditional caching (ETag/If-Modified-Since), and rate limiting.

Constant Summary collapse

DEFAULT_BASE_URL =
"https://rubygems.org"
USER_AGENT =
"gemcp/#{VERSION} (+https://github.com/baweaver/gemcp)"

Instance Method Summary collapse

Constructor Details

#initialize(base_url: ENV.fetch("RUBYGEMS_API_BASE_URL", DEFAULT_BASE_URL), open_timeout: 3, read_timeout: 10, config: nil, local_repository: nil, cache: nil, rate_limiter: nil) ⇒ Client

Returns a new instance of Client.

Parameters:

  • base_url (String) (defaults to: ENV.fetch("RUBYGEMS_API_BASE_URL", DEFAULT_BASE_URL))

    RubyGems API origin

  • open_timeout (Integer) (defaults to: 3)

    TCP connect timeout in seconds

  • read_timeout (Integer) (defaults to: 10)

    response read timeout in seconds

  • config (Config, nil) (defaults to: nil)

    configuration (built from env if nil)

  • local_repository (LocalRepository, nil) (defaults to: nil)
  • cache (Cache, nil) (defaults to: nil)
  • rate_limiter (RateLimiter, nil) (defaults to: nil)


21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/gemcp/client.rb', line 21

def initialize(
  base_url: ENV.fetch("RUBYGEMS_API_BASE_URL", DEFAULT_BASE_URL),
  open_timeout: 3,
  read_timeout: 10,
  config: nil,
  local_repository: nil,
  cache: nil,
  rate_limiter: nil
)
  @config = config || Config.new
  @local_repository = local_repository || LocalRepository.new
  @cache = cache || Cache.new(directory: @config.cache_dir)
  @rate_limiter = rate_limiter || RateLimiter.new(requests_per_second: @config.requests_per_second)
  @base_url = base_url.delete_suffix("/")
  @open_timeout = open_timeout
  @read_timeout = read_timeout
end

Instance Method Details

#gem(name) ⇒ Hash

Get metadata for the latest version of a gem.

Parameters:

  • name (String)

    gem name

Returns:

  • (Hash)

    gem metadata including version, downloads, URIs, dependencies

Raises:

  • (NotFound)

    if the gem does not exist



55
56
57
58
59
60
# File 'lib/gemcp/client.rb', line 55

def gem(name)
  local = @config.local_first ? @local_repository.gem(name) : nil
  return local if local

  get_json("/api/v1/gems/#{escape(name)}.json")
end

#latest_version(name) ⇒ Hash

Get the latest version number for a gem.

Parameters:

  • name (String)

    gem name

Returns:

  • (Hash)

    hash with "version" key

Raises:

  • (NotFound)

    if the gem does not exist



79
80
81
82
83
84
# File 'lib/gemcp/client.rb', line 79

def latest_version(name)
  local = @config.local_first ? @local_repository.gem(name) : nil
  return { "version" => local.fetch("version"), "metadata_source" => "local" } if local

  get_json("/api/v1/versions/#{escape(name)}/latest.json")
end

#owners(name) ⇒ Array<Hash>

Get public owners/maintainers for a gem.

Parameters:

  • name (String)

    gem name

Returns:

  • (Array<Hash>)

    owner records with id, handle, role

Raises:

  • (NotFound)

    if the gem does not exist



106
107
108
# File 'lib/gemcp/client.rb', line 106

def owners(name)
  get_json("/api/v1/gems/#{escape(name)}/owners.json")
end

#reverse_dependencies(name) ⇒ Array<String>

Get gems that depend on this gem (reverse dependencies).

Parameters:

  • name (String)

    gem name

Returns:

  • (Array<String>)

    names of gems that declare a runtime dependency on this gem

Raises:

  • (NotFound)

    if the gem does not exist



115
116
117
# File 'lib/gemcp/client.rb', line 115

def reverse_dependencies(name)
  get_json("/api/v1/gems/#{escape(name)}/reverse_dependencies.json")
end

#search(query) ⇒ Array<Hash>

Search for gems by name or description.

Parameters:

  • query (String)

    search text

Returns:

  • (Array<Hash>)

    list of gem metadata hashes



43
44
45
46
47
48
# File 'lib/gemcp/client.rb', line 43

def search(query)
  local = @config.local_first ? @local_repository.search(query) : []
  return local if local.any?

  get_json("/api/v1/search.json", query: { query: query })
end

#version(name, number, platform: nil) ⇒ Hash

Get metadata for a specific version and optional platform.

Parameters:

  • name (String)

    gem name

  • number (String)

    version number

  • platform (String, nil) (defaults to: nil)

    platform filter (e.g. "x86_64-linux")

Returns:

  • (Hash)

    version metadata

Raises:

  • (NotFound)

    if the version does not exist



93
94
95
96
97
98
99
# File 'lib/gemcp/client.rb', line 93

def version(name, number, platform: nil)
  local = @config.local_first ? @local_repository.version(name, number, platform: platform) : nil
  return local if local

  query = platform ? { platform: platform } : nil
  get_json("/api/v2/rubygems/#{escape(name)}/versions/#{escape(number)}.json", query: query)
end

#versions(name) ⇒ Array<Hash>

List all published versions of a gem.

Parameters:

  • name (String)

    gem name

Returns:

  • (Array<Hash>)

    version metadata ordered newest-first

Raises:

  • (NotFound)

    if the gem does not exist



67
68
69
70
71
72
# File 'lib/gemcp/client.rb', line 67

def versions(name)
  local = @config.local_first ? @local_repository.versions(name) : []
  return local if local.any?

  get_json("/api/v1/versions/#{escape(name)}.json")
end