Class: ShelfWatch::Client
- Inherits:
-
Object
- Object
- ShelfWatch::Client
- Defined in:
- lib/shelfwatch/client.rb
Overview
Synchronous client for ShelfWatch APIs v2.
Authenticate with either an API key or OAuth client credentials. Credentials are project-scoped (create them in Console → Integrations).
Example (API key):
client = ShelfWatch::Client.new(
api_key: "swpk_…",
project_id: "PROJECT_UUID",
)
visits = client.visits.list(
start_date: "2026-07-01",
end_date: "2026-07-31",
)
Example (OAuth):
client = ShelfWatch::Client.new(
client_id: "swoc_…",
client_secret: "swocs_…",
project_id: "PROJECT_UUID",
)
Constant Summary collapse
- DEFAULT_BASE_URL =
"https://api.shelfwatch.io"- DEFAULT_TIMEOUT =
60.0- TOKEN_SKEW_SECONDS =
Refresh OAuth tokens this many seconds before expires_in.
60
Instance Attribute Summary collapse
-
#base_url ⇒ Object
readonly
Returns the value of attribute base_url.
-
#mdm ⇒ Object
readonly
Returns the value of attribute mdm.
-
#project_id ⇒ Object
readonly
Returns the value of attribute project_id.
-
#reports ⇒ Object
readonly
Returns the value of attribute reports.
-
#visits ⇒ Object
readonly
Returns the value of attribute visits.
Instance Method Summary collapse
-
#close ⇒ Object
Close the underlying HTTP connection.
-
#connection ⇒ Object
Expose the underlying Faraday connection (useful for tests).
-
#health ⇒ Object
Call GET /health (no auth).
-
#initialize(api_key: nil, client_id: nil, client_secret: nil, project_id: nil, base_url: DEFAULT_BASE_URL, timeout: DEFAULT_TIMEOUT, connection: nil) ⇒ Client
constructor
A new instance of Client.
-
#project(project_id = nil) ⇒ Object
Resolve project_id from the call or the client default.
-
#request(method, path, params: nil, data: nil, json: nil) ⇒ Object
Send an authenticated request and return the JSON body.
Constructor Details
#initialize(api_key: nil, client_id: nil, client_secret: nil, project_id: nil, base_url: DEFAULT_BASE_URL, timeout: DEFAULT_TIMEOUT, connection: nil) ⇒ Client
Returns a new instance of Client.
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
# File 'lib/shelfwatch/client.rb', line 39 def initialize( api_key: nil, client_id: nil, client_secret: nil, project_id: nil, base_url: DEFAULT_BASE_URL, timeout: DEFAULT_TIMEOUT, connection: nil ) has_key = !api_key.nil? && api_key != "" has_oauth = (!client_id.nil? && client_id != "") || (!client_secret.nil? && client_secret != "") if has_key && has_oauth raise ValidationError, "Provide either api_key or client_id/client_secret, not both" end if has_oauth && (client_id.nil? || client_id == "" || client_secret.nil? || client_secret == "") raise ValidationError, "Both client_id and client_secret are required" end unless has_key || has_oauth raise ValidationError, "Provide api_key or client_id and client_secret" end @project_id = project_id @base_url = base_url.to_s.sub(%r{/+\z}, "") @api_key = has_key ? api_key : nil @client_id = has_oauth ? client_id : nil @client_secret = has_oauth ? client_secret : nil @access_token = nil @token_expires_at = 0.0 @connection = connection || Faraday.new(url: @base_url) do |f| f..timeout = timeout f..open_timeout = timeout f.headers["Accept"] = "application/json" f.headers["User-Agent"] = "shelfwatch-ruby/#{VERSION}" f.adapter Faraday.default_adapter end @visits = Resources::Visits.new(self) @mdm = Resources::Mdm.new(self) @reports = Resources::Reports.new(self) return unless block_given? begin yield self ensure close end end |
Instance Attribute Details
#base_url ⇒ Object (readonly)
Returns the value of attribute base_url.
37 38 39 |
# File 'lib/shelfwatch/client.rb', line 37 def base_url @base_url end |
#mdm ⇒ Object (readonly)
Returns the value of attribute mdm.
37 38 39 |
# File 'lib/shelfwatch/client.rb', line 37 def mdm @mdm end |
#project_id ⇒ Object (readonly)
Returns the value of attribute project_id.
37 38 39 |
# File 'lib/shelfwatch/client.rb', line 37 def project_id @project_id end |
#reports ⇒ Object (readonly)
Returns the value of attribute reports.
37 38 39 |
# File 'lib/shelfwatch/client.rb', line 37 def reports @reports end |
#visits ⇒ Object (readonly)
Returns the value of attribute visits.
37 38 39 |
# File 'lib/shelfwatch/client.rb', line 37 def visits @visits end |
Instance Method Details
#close ⇒ Object
Close the underlying HTTP connection.
146 147 148 |
# File 'lib/shelfwatch/client.rb', line 146 def close @connection.close if @connection.respond_to?(:close) end |
#connection ⇒ Object
Expose the underlying Faraday connection (useful for tests).
141 142 143 |
# File 'lib/shelfwatch/client.rb', line 141 def connection @connection end |
#health ⇒ Object
Call GET /health (no auth).
131 132 133 134 135 136 137 138 |
# File 'lib/shelfwatch/client.rb', line 131 def health response = @connection.get("/health") Http.raise_for_status(response.status, response.body, response.reason_phrase) payload = JSON.parse(response.body) return { "data" => payload } unless payload.is_a?(Hash) payload end |
#project(project_id = nil) ⇒ Object
Resolve project_id from the call or the client default.
92 93 94 95 96 97 98 99 |
# File 'lib/shelfwatch/client.rb', line 92 def project(project_id = nil) value = project_id || @project_id if value.nil? || value == "" raise ValidationError, "project_id is required (pass it to ShelfWatch::Client.new(...) or to this method)" end value end |
#request(method, path, params: nil, data: nil, json: nil) ⇒ Object
Send an authenticated request and return the JSON body.
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
# File 'lib/shelfwatch/client.rb', line 102 def request(method, path, params: nil, data: nil, json: nil) token = ensure_token response = @connection.run_request(method.downcase.to_sym, path, nil, {}) do |req| req.headers["Authorization"] = "Bearer #{token}" req.params.update(stringify_keys(params)) if params if data req.headers["Content-Type"] = "application/x-www-form-urlencoded" req.body = URI.encode_www_form(stringify_keys(data)) elsif !json.nil? req.headers["Content-Type"] = "application/json" req.body = JSON.generate(json) end end Http.raise_for_status(response.status, response.body, response.reason_phrase) return {} if response.status == 204 || response.body.nil? || response.body.empty? begin payload = JSON.parse(response.body) rescue JSON::ParserError return { "data" => response.body } end return { "data" => payload } unless payload.is_a?(Hash) payload end |