sleeper_api 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +1 -1
- data/CHANGELOG.md +15 -0
- data/CLAUDE.md +59 -0
- data/README.md +2 -0
- data/lib/sleeper_api/client.rb +1 -1
- data/lib/sleeper_api/league.rb +6 -6
- data/lib/sleeper_api/user.rb +2 -1
- data/lib/sleeper_api/version.rb +1 -1
- metadata +4 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 92a31d66b4e0b110e6daf96f0689fdcc626b341bc7550ac8f1d982eaae8796bf
|
|
4
|
+
data.tar.gz: 14b9b6d090c28a8087edb9a45d61eadeae4c8fd6027995b206456cc45c95c9f5
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d24b6c42b978e3a14c70ff6c9db5c08f6747ff73c64206ccb8a7374741b56e6f034a9451a03f4d93670743414a5c30011c311a709a02743219f593e9cf8299e1
|
|
7
|
+
data.tar.gz: 16e2f0ab8bb4fa2053cc01f0e35b4a3a6e2bde9d8a55173b8781329378323045da0c826711a33c13117ccb8e17e58b04572c34591d9e123235f21d2378ee51d9
|
data/.github/workflows/ci.yml
CHANGED
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,18 @@
|
|
|
1
|
+
## [1.0.1] - 2026-08-12
|
|
2
|
+
|
|
3
|
+
### Fixed
|
|
4
|
+
|
|
5
|
+
- `User#leagues` returned `nil` on every call after the first, because the memoization guard was the method's return value
|
|
6
|
+
- `League#users` raised `NoMethodError` when any league member had no `metadata` (Sleeper omits it for users who never set a team name), which also broke `#playoff_bracket` and `#toilet_bowl`
|
|
7
|
+
- `Client#make_request` raised `NameError: undefined local variable 'config'` when a retry fired with a logger configured — the retry path was only reachable with logging on, so it never surfaced in tests
|
|
8
|
+
- `League#matchups_by_week` returned a literal `nil` element for any roster with no `matchup_id` (bye weeks / unscheduled rosters)
|
|
9
|
+
- `League#matchups_by_week` raised `NoMethodError` when a matchup roster had no `players` or no `points`
|
|
10
|
+
- `League#users` memoization checked an undefined `@fetch_users` ivar instead of `@league_users`
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- SimpleCov now starts before the library is required. It previously started after, so no lines were instrumented and the `minimum_coverage 90` gate passed vacuously on 0/0 lines. Real coverage at the time was 72%; `lib/` is now at 100%.
|
|
15
|
+
|
|
1
16
|
## [1.0.0] - 2025-01-17
|
|
2
17
|
|
|
3
18
|
### Added
|
data/CLAUDE.md
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## What this is
|
|
6
|
+
|
|
7
|
+
`sleeper_api` — a published Ruby gem (rubygems.org, v1.0.0) wrapping [Sleeper's fantasy football API](https://docs.sleeper.com/). Read-only public API: no auth, no API key, no write endpoints.
|
|
8
|
+
|
|
9
|
+
Consumed by the `fantasy-football-manager` project in the sibling directory, which is the primary real-world user.
|
|
10
|
+
|
|
11
|
+
## Commands
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
bin/setup # install deps
|
|
15
|
+
bundle exec rake ci # rubocop + rspec — this is what CI runs
|
|
16
|
+
bundle exec rspec
|
|
17
|
+
bundle exec rspec spec/sleeper_api/league_spec.rb:42 # single example
|
|
18
|
+
bundle exec rubocop -A # autocorrect
|
|
19
|
+
bin/console # IRB with the gem loaded
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
CI (`.github/workflows/ci.yml`) runs `bundle exec rake ci` on Ruby 3.2 only. The gemspec claims `required_ruby_version >= 2.6.0` and RuboCop targets 2.6, but nothing tests below 3.2 — treat 2.6 compatibility as unverified.
|
|
23
|
+
|
|
24
|
+
## Architecture
|
|
25
|
+
|
|
26
|
+
Four layers, with a deliberate split between HTTP and modeling:
|
|
27
|
+
|
|
28
|
+
- **`SleeperApi`** (`lib/sleeper_api.rb`) — module-level config + memoized global `SleeperApi.client`. `Configuration` validates `timeout` (10–60) and `retries` (0–5), raising `SleeperApi::Error` outside those bounds.
|
|
29
|
+
- **`Client`** — the only thing that talks HTTP. `include HTTParty` with `base_uri "https://api.sleeper.app/v1"`. Every call funnels through the private `make_request`, which handles retry-on-timeout, logging, and converts non-2xx into `SleeperApi::Error`. It also owns the 24-hour in-memory player cache.
|
|
30
|
+
- **`League` / `User` / `Draft`** — resource objects. Each takes `(id, client)`, fetches eagerly in the constructor, memoizes into ivars, and exposes formatted hashes.
|
|
31
|
+
- **`Helpers`** — mixed into all four. `deep_symbolize_keys` plus `player_details`, which reaches through `@client` — so any class including it must define `@client`.
|
|
32
|
+
|
|
33
|
+
### Conventions that matter
|
|
34
|
+
|
|
35
|
+
**Raw data is string-keyed; formatted output is symbol-keyed.** The `ATTRIBUTES` readers (defined via `define_method` on each class) return raw API values straight off the string-keyed hash. The `format_*` private methods return symbol-keyed hashes. Don't mix the two — inside `format_rosters` you're indexing `roster["starters"]` but returning `starters:`.
|
|
36
|
+
|
|
37
|
+
**`Client` returns `HTTParty::Response`, not Hash.** `make_request` returns the response object, which delegates `[]` and `dig` to `parsed_response`, so it usually behaves like a Hash. `get_players` is the exception — it explicitly stores `.parsed_response`. If you add code that needs a real Hash (e.g. `.merge`, `.transform_keys`), call `.parsed_response` yourself; `fetch_playoff_bracket` already does.
|
|
38
|
+
|
|
39
|
+
**Eager construction.** `League.new` and `User.new` hit the network in the constructor. `League.new(id, client, no_data: true)` skips it — used by `User#rosters` to avoid N redundant league fetches. Be aware `no_data: true` leaves `@league_data` nil, so `format_rosters`' `remaining_faab` falls back to `0 - waiver_budget_used`.
|
|
40
|
+
|
|
41
|
+
**Guard nil defensively.** Sleeper omits fields freely — users without `metadata`, rosters without `players`, matchups without `points`. Real leagues hit these; the spec fixtures often don't. Use `&.dig` rather than `[]` on anything nested off an API response.
|
|
42
|
+
|
|
43
|
+
**Never fan out `get_players`.** It's a multi-megabyte payload of every NFL player. It's cached for 24h in an ivar on the client instance — which means the cache dies with the client. Consumers holding a short-lived client re-download it every time.
|
|
44
|
+
|
|
45
|
+
## Testing
|
|
46
|
+
|
|
47
|
+
RSpec + WebMock, with `WebMock.disable_net_connect!` — **specs must never hit the network**. Stub with `stub_request` (see `client_spec.rb`) or `instance_double(SleeperApi::Client)` for resource-object specs (see `league_spec.rb`).
|
|
48
|
+
|
|
49
|
+
`spec_helper.rb` resets `SleeperApi`'s `@client` and `@configuration` ivars before each example, since both are module-level memoized state that would otherwise leak between tests.
|
|
50
|
+
|
|
51
|
+
**SimpleCov must start before `require "sleeper_api"`.** It previously started after, which meant zero lines were instrumented and `minimum_coverage 90` passed vacuously on 0/0. Don't reorder those requires back — it silently disables the gate rather than failing loudly.
|
|
52
|
+
|
|
53
|
+
`lib/` is at 100% line coverage. Every bug found in this gem so far has been in a `League#format_*` method handling a field Sleeper omitted, exercised only by real data. When adding a formatter, write the nil-field case first.
|
|
54
|
+
|
|
55
|
+
## Release
|
|
56
|
+
|
|
57
|
+
Version lives in `lib/sleeper_api/version.rb`. `bundle exec rake release` tags and pushes to rubygems. Update `CHANGELOG.md` first.
|
|
58
|
+
|
|
59
|
+
v1.0.0 is published with six bugs that are fixed in the working tree but not yet released — see the unreleased section of `CHANGELOG.md`. Consumers on the published gem still hit them.
|
data/README.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# SleeperApi
|
|
2
2
|
|
|
3
|
+
[](https://badge.fury.io/rb/sleeper_api)
|
|
4
|
+
|
|
3
5
|
A comprehensive Ruby gem for interacting with [Sleeper's fantasy football API](https://docs.sleeper.com/). Built with performance, reliability, and developer experience in mind.
|
|
4
6
|
|
|
5
7
|
## Features
|
data/lib/sleeper_api/client.rb
CHANGED
|
@@ -264,7 +264,7 @@ module SleeperApi
|
|
|
264
264
|
rescue Net::OpenTimeout, Net::ReadTimeout => e
|
|
265
265
|
retries += 1
|
|
266
266
|
if retries <= @config.retries
|
|
267
|
-
@config.logger&.warn("Retrying #{path} (attempt #{retries}/#{config.retries}) due to #{e}")
|
|
267
|
+
@config.logger&.warn("Retrying #{path} (attempt #{retries}/#{@config.retries}) due to #{e}")
|
|
268
268
|
sleep(1)
|
|
269
269
|
retry
|
|
270
270
|
else
|
data/lib/sleeper_api/league.rb
CHANGED
|
@@ -134,7 +134,7 @@ module SleeperApi
|
|
|
134
134
|
# puts "#{user[:display_name]} #{role}"
|
|
135
135
|
# end
|
|
136
136
|
def users
|
|
137
|
-
fetch_users unless @
|
|
137
|
+
fetch_users unless @league_users
|
|
138
138
|
format_users
|
|
139
139
|
end
|
|
140
140
|
|
|
@@ -310,14 +310,14 @@ module SleeperApi
|
|
|
310
310
|
{
|
|
311
311
|
matchup_id: matchup_id,
|
|
312
312
|
rosters: matchup_entries.map do |roster|
|
|
313
|
-
starters = roster["starters"]
|
|
313
|
+
starters = roster["starters"] || []
|
|
314
314
|
|
|
315
|
-
bench = roster["players"] - starters
|
|
315
|
+
bench = (roster["players"] || []) - starters
|
|
316
316
|
{
|
|
317
317
|
roster_id: roster["roster_id"],
|
|
318
318
|
points: roster["points"],
|
|
319
319
|
custom_points: roster["custom_points"],
|
|
320
|
-
total_points: roster["points"] + (roster["custom_points"] || 0),
|
|
320
|
+
total_points: (roster["points"] || 0) + (roster["custom_points"] || 0),
|
|
321
321
|
starters: starters,
|
|
322
322
|
bench: bench,
|
|
323
323
|
starter_points: (starters || []).map do |starter_id|
|
|
@@ -329,7 +329,7 @@ module SleeperApi
|
|
|
329
329
|
}
|
|
330
330
|
end
|
|
331
331
|
}
|
|
332
|
-
end
|
|
332
|
+
end.compact
|
|
333
333
|
end
|
|
334
334
|
|
|
335
335
|
def format_users
|
|
@@ -342,7 +342,7 @@ module SleeperApi
|
|
|
342
342
|
username: user["username"],
|
|
343
343
|
display_name: user["display_name"],
|
|
344
344
|
avatar_id: user["avatar"],
|
|
345
|
-
team_name: user_metadata
|
|
345
|
+
team_name: user_metadata&.dig("team_name"),
|
|
346
346
|
commissioner: user["is_owner"],
|
|
347
347
|
is_bot: user["is_bot"],
|
|
348
348
|
metadata: user_metadata.is_a?(Hash) ? user_metadata.transform_keys(&:to_sym) : user_metadata,
|
data/lib/sleeper_api/user.rb
CHANGED
|
@@ -50,7 +50,8 @@ module SleeperApi
|
|
|
50
50
|
def leagues(season = Time.now.year)
|
|
51
51
|
raise ArgumentError, "season must be a valid year" unless season.is_a?(Integer)
|
|
52
52
|
|
|
53
|
-
fetch_leagues(season)
|
|
53
|
+
fetch_leagues(season)
|
|
54
|
+
@leagues
|
|
54
55
|
end
|
|
55
56
|
|
|
56
57
|
# Get all rosters for this user across all leagues in a season.
|
data/lib/sleeper_api/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: sleeper_api
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0.
|
|
4
|
+
version: 1.0.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Eruity1
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: exe
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: httparty
|
|
@@ -138,6 +137,7 @@ files:
|
|
|
138
137
|
- ".rubocop.yml"
|
|
139
138
|
- ".rubocop_todo.yml"
|
|
140
139
|
- CHANGELOG.md
|
|
140
|
+
- CLAUDE.md
|
|
141
141
|
- Gemfile
|
|
142
142
|
- LICENSE.txt
|
|
143
143
|
- README.md
|
|
@@ -162,7 +162,6 @@ metadata:
|
|
|
162
162
|
source_code_uri: https://github.com/eruity1/sleeper_api
|
|
163
163
|
changelog_uri: https://github.com/eruity1/sleeper_api/blob/main/CHANGELOG.md
|
|
164
164
|
documentation_uri: https://github.com/eruity1/sleeper_api/blob/main/README.md
|
|
165
|
-
post_install_message:
|
|
166
165
|
rdoc_options: []
|
|
167
166
|
require_paths:
|
|
168
167
|
- lib
|
|
@@ -177,8 +176,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
177
176
|
- !ruby/object:Gem::Version
|
|
178
177
|
version: '0'
|
|
179
178
|
requirements: []
|
|
180
|
-
rubygems_version: 3.
|
|
181
|
-
signing_key:
|
|
179
|
+
rubygems_version: 3.6.7
|
|
182
180
|
specification_version: 4
|
|
183
181
|
summary: Comprehensive Ruby wrapper for the Sleeper's fantasy sports API
|
|
184
182
|
test_files: []
|