Skip to content

feat(api_sports): add API-Sports plugin - #359

Merged
devjain32 merged 11 commits into
corsairdev:mainfrom
Ayush7614:feat/api_sports-plugin
Aug 12, 2026
Merged

feat(api_sports): add API-Sports plugin#359
devjain32 merged 11 commits into
corsairdev:mainfrom
Ayush7614:feat/api_sports-plugin

Conversation

@Ayush7614

@Ayush7614 Ayush7614 commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Description

Adds `@corsair-dev/api_sports` — a Corsair plugin for the API-Sports REST APIs (football, basketball, NBA, AFL, baseball, Formula 1, MMA, NFL).

  • 67 catalog operations with sport-specific base URLs and `x-apisports-key` auth
  • Typed Zod request/response schemas, structured error handlers (429/auth/4xx/5xx)
  • Correct host routing for standings helpers (football) and games events (NFL)
  • Client throws on API-Sports HTTP 200 body `errors` and hyphen-joins array query ids

Closes #358
Claim: https://corsair.dev/oss/api_sports

Checklist

Before submitting your PR, please verify the following:

  • I have run `pnpm lint` and all checks pass
  • I have run `pnpm typecheck` and there are no TypeScript errors
  • I have run `pnpm build` and all packages build successfully
  • I have run `pnpm test` and all tests pass
  • I have added or updated tests where applicable
  • I have added or updated necessary documentation

Screenshots / Demos (if applicable)

Screenshot 2026-08-04 at 12 46 01 PM

Summary by CodeRabbit

  • New Features
    • Added API-Sports integration with typed access to football, basketball, AFL, baseball, Formula 1, MMA, odds, standings, fixtures, player, and core sports data.
    • Added query validation, response schemas, authentication, caching, and structured error handling with retry support.
    • Added API-Sports as a supported provider.
  • Tests
    • Added coverage for supported sports, authentication failures, API errors, response validation, and query serialization.

Implement Corsair OSS plugin for API-Sports across football, NBA,
basketball, AFL, baseball, F1, MMA, and NFL APIs with x-apisports-key
auth, sport-specific base URLs, live-tested endpoints, and demo registration.

Closes corsairdev#358
@vercel

vercel Bot commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

@Ayush7614 is attempting to deploy a commit to the corsair Team on Vercel.

A member of the Team first needs to authorize it.

@github-actions github-actions Bot added the core Changes in packages/corsair label Jul 5, 2026
@greptile-apps

greptile-apps Bot commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR adds the API-Sports plugin with typed operations spanning eight sports, sport-specific request routing, API-key authentication, response-error normalization, and package registration.

  • Adds 67 catalog operations and shared request execution.
  • Routes requests across football, basketball, NBA, AFL, baseball, Formula 1, MMA, and NFL hosts.
  • Handles API-Sports error bodies, HTTP failures, rate limits, and missing credentials.
  • Adds Zod schemas, endpoint tests, build configuration, and provider registration.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains; all three previously reported issues are fixed at the current head.

Important Files Changed

Filename Overview
packages/apisports/index.ts Registers the plugin’s endpoint tree, schemas, error handlers, and API-key builder; the previously reported missing-key fallback now throws AuthMissingError.
packages/apisports/endpoints/routes.ts Centralizes sport and path selection; the previously duplicated game-statistics routes now select distinct basketball and NBA routes.
packages/apisports/client.ts Implements sport-specific GET requests, multi-ID query normalization, and conversion of HTTP and API-Sports body errors.
packages/apisports/error-handlers.ts Defines retry policies and now logs authentication failures through console.error.
packages/apisports/api.test.ts Exercises representative host routing, response parsing, authentication errors, body-level errors, and array query normalization.
packages/corsair/core/constants.ts Registers apisports as a recognized base provider.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  Caller["Corsair endpoint caller"] --> KeyBuilder["API-Sports keyBuilder"]
  KeyBuilder --> Endpoint["Typed endpoint implementation"]
  Endpoint --> Router["Sport-specific route lookup"]
  Router --> Client["Shared API-Sports HTTP client"]
  Client --> Provider["Selected API-Sports host"]
  Provider --> Errors{"HTTP or body errors?"}
  Errors -->|No| Response["Typed response"]
  Errors -->|Yes| Handler["API-Sports error handling"]
Loading

Reviews (6): Last reviewed commit: "fix(apisports): rename package to drop u..." | Re-trigger Greptile

Comment thread packages/api_sports/endpoints/routes.ts Outdated
Comment thread packages/api_sports/index.ts Outdated
Comment thread packages/apisports/error-handlers.ts
Route getGameStatisticsByTeams to basketball /games/statistics/teams,
throw AuthMissingError when API key is absent, and use console.error for auth failures.
@Ayush7614

Copy link
Copy Markdown
Contributor Author

@greptileai

Cache sport/path/query lookups via ctx.db.queries upserts following the
Slack plugin pattern; remove generator script from PR.
@Ayush7614

Copy link
Copy Markdown
Contributor Author

@greptileai

@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 6002ddd2-7abb-499e-8a3b-d840841fdfc2

📥 Commits

Reviewing files that changed from the base of the PR and between 4c4496a and b30732f.

📒 Files selected for processing (2)
  • packages/apisports/api.test.ts
  • packages/apisports/client.ts

📝 Walkthrough

Walkthrough

Changes

API-Sports provider

Layer / File(s) Summary
API-Sports contracts and package foundation
packages/apisports/endpoints/routes.ts, packages/apisports/endpoints/types.ts, packages/apisports/schema/*, packages/apisports/package.json, packages/apisports/*config*
Adds typed routes, query and response schemas, database schema, package metadata, and build configuration.
Request transport, caching, and errors
packages/apisports/client.ts, packages/apisports/endpoints/shared.ts, packages/apisports/error-handlers.ts
Adds authenticated sport-specific requests, query normalization, API error conversion, retry handling, and query metadata caching.
Typed sport endpoint handlers
packages/apisports/endpoints/*.ts
Adds 67 endpoint handlers for core football, fixtures, standings, players, odds, basketball, AFL, baseball, Formula 1, and MMA operations.
Corsair plugin assembly and provider registration
packages/apisports/index.ts, packages/apisports/endpoints/index.ts, packages/corsair/core/constants.ts
Registers endpoint implementations, schemas, metadata, authentication, error handlers, exports, and the apisports provider.
Integration validation
packages/apisports/api.test.ts
Adds live API tests for route sports, response schemas, API errors, authentication failures, and array query serialization.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant ApiSportsPlugin
  participant EndpointHandler
  participant executeApiSportsRequest
  participant makeApiSportsRequest
  participant ApiSportsAPI
  participant QueryStorage
  ApiSportsPlugin->>EndpointHandler: invoke typed endpoint
  EndpointHandler->>executeApiSportsRequest: pass route, API key, and query
  executeApiSportsRequest->>makeApiSportsRequest: execute authenticated GET request
  makeApiSportsRequest->>ApiSportsAPI: send normalized query
  ApiSportsAPI-->>makeApiSportsRequest: return response or API error
  executeApiSportsRequest->>QueryStorage: upsert query metadata
Loading

Possibly related PRs

Suggested labels: plugin, needs-maintainer

Suggested reviewers: devjain32

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the primary change: adding the API-Sports plugin.
Linked Issues check ✅ Passed The changes implement the 67 requested API-Sports operations, authentication, sport-specific URLs, typed schemas, error handling, and no webhook triggers [#358].
Out of Scope Changes check ✅ Passed The package, tests, schemas, endpoint registry, error handlers, and provider registration directly support the API-Sports integration objectives.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@Dhirenderchoudhary

Copy link
Copy Markdown
Collaborator

@greptile review

@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown

Plugin PR scorecard — packages/apisports

Check Status Notes
R1 — Scope: plugin files only
R2 — Tests with assertions
R3 — Description complete
R3 — Linked issue / claim
R4 — Demo video / recording

Rules: PLUGIN_PR_RULES.md · re-runs on every push

@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown

Hey @Ayush7614, thanks for the contribution! 🏴‍☠️ Before a maintainer reviews, please fix the items below — the review re-runs automatically on your next push.

Must fix

  • P1 packages/api_sports/endpoints/routes.tsgetGameStatisticsByTeams and getNbaGameStatistics share the same route
    Both endpoints map to nba /games/statistics. Any call to getGameStatisticsByTeams will silently hit the same endpoint as getNbaGameStatistics, returning data the caller did not request. This looks like a copy-paste error; the game-statistics-by-teams endpoint likely requires a different path to distinguish it from the generic game statistics endpoint.
	getNbaGameStatistics: { sport: 'nba', path: '/games/statistics', description: "Get NBA Game Statistics" },
	getPlayerStatistics: { sport: 'nba', path: '/players/statistics', description: "Get Player Statistics" },
	getGameStatisticsByTeams: { sport: 'nba', path: '/games/statistics/teams', description: "Get Game Statistics by Teams" },
  • P1 packages/api_sports/index.tsSilent empty-key fallback bypasses auth enforcement
    When ctx.keys.get_api_key() returns null or undefined (no key configured), res ?? '' returns an empty string. That empty string becomes the x-apisports-key header value, so the request is sent without a real key and the API will respond with a 401. The plugin then enters the retry/error path rather than failing immediately with a descriptive AuthMissingError, wasting quota and obscuring the root cause. Replace return res ?? '' with if (!res) throw new AuthMissingError('api_sports', 'api_key'); return res;.
Optional improvements (P2)
  • P2 packages/api_sports/error-handlers.ts:44console.log used for an authentication failure
    Authentication failure is an error condition; using console.log rather than console.error means it won't appear in error-level log streams and may be silently dropped in production log filters.
		handler: async () => {
			console.error('[API_SPORTS] Authentication failed — check your x-apisports-key.');
			return { maxRetries: 0 };

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

If anything remains after your next push, a bot commit will clean it up; a maintainer always does the final review and merge.

@github-actions github-actions Bot added the bot:round-1 Review bot posted consolidated findings label Aug 4, 2026
@Dhirenderchoudhary

Copy link
Copy Markdown
Collaborator

@greptile Review

@github-actions github-actions Bot added the bot:round-2 Review bot pushed an automated fix label Aug 4, 2026
@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown

Remaining findings are being fixed by a bot commit — it will be re-reviewed automatically.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (3)
packages/apisports/endpoints/types.ts (1)

41-319: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚖️ Poor tradeoff

The 67-operation list is hand-copied into five places. packages/apisports/endpoints/routes.ts already holds every route key and its description, but the key list is re-typed in four maps in types.ts and again in apiSportsEndpointMeta in index.ts. Adding one route requires five coordinated edits, and a description edit in routes.ts does not reach index.ts. The satisfies constraints catch missing keys at compile time, so this is a maintenance cost rather than a correctness defect.

  • packages/apisports/endpoints/types.ts#L41-L319: derive ApiSportsEndpointInputs, ApiSportsEndpointOutputs, ApiSportsEndpointInputSchemas, and ApiSportsEndpointOutputSchemas from ApiSportsRouteKey and API_SPORTS_ROUTES.
  • packages/apisports/index.ts#L497-L766: build each apiSportsEndpointMeta entry from the matching API_SPORTS_ROUTES[op].description instead of a repeated literal string.

Keep the explicit literal maps if RequiredPluginEndpointSchemas and RequiredPluginEndpointMeta require literal key inference to type-check.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/apisports/endpoints/types.ts` around lines 41 - 319, The
67-operation key and description lists are duplicated across endpoint types and
metadata. In packages/apisports/endpoints/types.ts#L41-319, derive
ApiSportsEndpointInputs, ApiSportsEndpointOutputs,
ApiSportsEndpointInputSchemas, and ApiSportsEndpointOutputSchemas from
ApiSportsRouteKey and API_SPORTS_ROUTES while preserving explicit literal maps
if required for RequiredPluginEndpointSchemas inference; in
packages/apisports/index.ts#L497-766, source each apiSportsEndpointMeta
description from API_SPORTS_ROUTES[op].description instead of repeating string
literals.
packages/apisports/endpoints/routes.ts (1)

229-234: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider renaming getGamesEvents to reflect the NFL host.

The route targets the nfl sport, but index.ts registers getGamesEvents under the basketball group. A caller reads basketball.getGamesEvents and expects NBA data. The same applies to standings.getStandingsDivisions and standings.getNflStandingsConferences, which also target nfl.

A name such as getNflGamesEvents plus an nfl group would remove the ambiguity. The code comment documents the current intent, so this is a naming preference only.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/apisports/endpoints/routes.ts` around lines 229 - 234, Rename the
NFL-specific route key getGamesEvents to getNflGamesEvents in the route
definitions and update its registration in index.ts to use the nfl group instead
of basketball. Apply the same naming/grouping clarification to
standings.getStandingsDivisions and standings.getNflStandingsConferences,
preserving their existing NFL paths and behavior.
packages/apisports/api.test.ts (1)

101-109: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Verify that the nba /games/events request fails for the expected reason.

The test asserts that the call rejects with ApiSportsAPIError. The route table comment at packages/apisports/endpoints/routes.ts line 229 states that NBA has no /games/events. A rejection can also come from a rate limit, a plan restriction, or a network timeout. The assertion then passes for the wrong reason.

Assert on the error message content, as the test at line 116 does.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/apisports/api.test.ts` around lines 101 - 109, Strengthen the
`throws on API-Sports body errors` test by asserting that the rejected
`ApiSportsAPIError` also contains the expected missing-route message for NBA
`/games/events`, following the message-content assertion pattern used by the
nearby test. Keep the existing API-key guard and request unchanged.
🔇 Additional comments (28)
packages/apisports/endpoints/routes.ts (1)

1-228: LGTM!

Also applies to: 235-333

packages/apisports/endpoints/types.ts (1)

1-39: LGTM!

packages/apisports/schema/database.ts (1)

3-7: 🗄️ Data Integrity & Integration

⚠️ Unverified finding
Sandbox verification was unavailable.

Verify that all-optional fields are correct for a persisted entity.

sport, path, and queriedAt are each optional, so {} parses successfully. The plugin registers this schema as the queries entity. If client.ts uses sport and path as the cache lookup key, an undefined value produces an unusable row. Most Corsair plugin entities also declare an id field.

Confirm the writer always supplies sport and path, or make those fields required.

packages/apisports/schema/index.ts (1)

1-8: LGTM!

packages/apisports/package.json (2)

25-34: 📐 Maintainability & Code Quality

⚠️ Unverified finding
Sandbox verification was unavailable.

Verify the devDependency version style matches sibling plugin packages.

typescript uses catalog:, but jest, ts-jest, tsup, dotenv, and zod use explicit ranges. If the workspace catalog already pins these tools, the explicit ranges can drift from the rest of the monorepo. The PR screenshot also shows pnpm warnings about pnpm.overrides and pnpm.onlyBuiltDependencies being ignored outside the workspace root; confirm this package does not declare those fields.


1-24: LGTM!

Also applies to: 35-45

packages/apisports/jest.config.cjs (2)

22-25: 📐 Maintainability & Code Quality | 💤 Low value

⚠️ Unverified finding
Sandbox verification was unavailable.

Add a corsair/core mapping to moduleNameMapper.

moduleNameMapper maps only corsair/http. The plugin entry packages/apisports/index.ts imports from corsair/core. The current test file does not import index.ts, so tests pass today. A future test that imports the plugin factory apisports() would fail to resolve corsair/core.

♻️ Proposed mapping
 	moduleNameMapper: {
+		'^corsair/core$': '<rootDir>/../corsair/core/index.ts',
 		'^corsair/http$': '<rootDir>/../corsair/http.ts',
 		'^(\\.\\.?/.*)\\.js$': '$1',
 	},

Confirm the corsair/core entry path before you apply the change.


1-21: LGTM!

Also applies to: 26-29

packages/apisports/index.ts (2)

814-826: LGTM!


1-496: LGTM!

Also applies to: 767-813, 830-842

packages/corsair/core/constants.ts (1)

32-32: LGTM!

Also applies to: 144-144, 263-263

packages/apisports/api.test.ts (1)

55-99: LGTM!

packages/apisports/tsconfig.json (1)

1-20: LGTM!

packages/apisports/tsup.config.ts (1)

1-15: LGTM!

packages/apisports/client.ts (1)

1-165: LGTM!

packages/apisports/endpoints/shared.ts (1)

1-61: LGTM!

packages/apisports/endpoints/baseball.ts (1)

1-21: LGTM!

packages/apisports/endpoints/formula1.ts (1)

1-137: LGTM!

packages/apisports/endpoints/mma.ts (1)

1-107: LGTM!

packages/apisports/endpoints/index.ts (1)

1-12: LGTM!

packages/apisports/error-handlers.ts (1)

1-68: LGTM!

packages/apisports/endpoints/core.ts (1)

1-252: LGTM!

packages/apisports/endpoints/fixtures.ts (1)

1-119: LGTM!

packages/apisports/endpoints/standings.ts (1)

1-69: LGTM!

packages/apisports/endpoints/players.ts (1)

1-155: LGTM!

packages/apisports/endpoints/odds.ts (1)

1-108: LGTM!

packages/apisports/endpoints/basketball.ts (1)

1-119: LGTM!

packages/apisports/endpoints/afl.ts (1)

1-91: LGTM!

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/apisports/api.test.ts`:
- Around line 119-135: Replace the network-dependent “joins array query params
with hyphens” test in api.test.ts with a unit test for the query serialization
helper from client.ts. Assert the exact serialized output for an ids array,
ensuring values are joined with hyphens rather than commas or repeated keys;
remove the API-key guard, network request, response-schema parsing, and
catch-based assertions.
- Around line 10-17: Replace per-test early returns based on TEST_API_KEY with a
conditional describe block so API-dependent tests are reported as skipped when
API_SPORTS_API_KEY is unset; preserve their existing assertions and warning
behavior as appropriate. Move the “throws auth body errors for invalid key” test
into a separate describe block that always runs without requiring TEST_API_KEY.

---

Nitpick comments:
In `@packages/apisports/api.test.ts`:
- Around line 101-109: Strengthen the `throws on API-Sports body errors` test by
asserting that the rejected `ApiSportsAPIError` also contains the expected
missing-route message for NBA `/games/events`, following the message-content
assertion pattern used by the nearby test. Keep the existing API-key guard and
request unchanged.

In `@packages/apisports/endpoints/routes.ts`:
- Around line 229-234: Rename the NFL-specific route key getGamesEvents to
getNflGamesEvents in the route definitions and update its registration in
index.ts to use the nfl group instead of basketball. Apply the same
naming/grouping clarification to standings.getStandingsDivisions and
standings.getNflStandingsConferences, preserving their existing NFL paths and
behavior.

In `@packages/apisports/endpoints/types.ts`:
- Around line 41-319: The 67-operation key and description lists are duplicated
across endpoint types and metadata. In
packages/apisports/endpoints/types.ts#L41-319, derive ApiSportsEndpointInputs,
ApiSportsEndpointOutputs, ApiSportsEndpointInputSchemas, and
ApiSportsEndpointOutputSchemas from ApiSportsRouteKey and API_SPORTS_ROUTES
while preserving explicit literal maps if required for
RequiredPluginEndpointSchemas inference; in
packages/apisports/index.ts#L497-766, source each apiSportsEndpointMeta
description from API_SPORTS_ROUTES[op].description instead of repeating string
literals.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 26ddebbc-1041-4660-8738-559c3e946d73

📥 Commits

Reviewing files that changed from the base of the PR and between bbb7cb9 and 4c4496a.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (25)
  • packages/apisports/api.test.ts
  • packages/apisports/client.ts
  • packages/apisports/endpoints/afl.ts
  • packages/apisports/endpoints/baseball.ts
  • packages/apisports/endpoints/basketball.ts
  • packages/apisports/endpoints/core.ts
  • packages/apisports/endpoints/fixtures.ts
  • packages/apisports/endpoints/formula1.ts
  • packages/apisports/endpoints/index.ts
  • packages/apisports/endpoints/mma.ts
  • packages/apisports/endpoints/odds.ts
  • packages/apisports/endpoints/players.ts
  • packages/apisports/endpoints/routes.ts
  • packages/apisports/endpoints/shared.ts
  • packages/apisports/endpoints/standings.ts
  • packages/apisports/endpoints/types.ts
  • packages/apisports/error-handlers.ts
  • packages/apisports/index.ts
  • packages/apisports/jest.config.cjs
  • packages/apisports/package.json
  • packages/apisports/schema/database.ts
  • packages/apisports/schema/index.ts
  • packages/apisports/tsconfig.json
  • packages/apisports/tsup.config.ts
  • packages/corsair/core/constants.ts

Comment thread packages/apisports/api.test.ts Outdated
Comment thread packages/apisports/api.test.ts Outdated
@devjain32
devjain32 merged commit 5869452 into corsairdev:main Aug 12, 2026
9 of 10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bot:round-1 Review bot posted consolidated findings bot:round-2 Review bot pushed an automated fix core Changes in packages/corsair

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Integration request: API-Sports

3 participants