Skip to content

add rust client via codegen#221

Merged
justinmakaila merged 7 commits intomainfrom
feature/rust-client
Apr 21, 2026
Merged

add rust client via codegen#221
justinmakaila merged 7 commits intomainfrom
feature/rust-client

Conversation

@justinmakaila
Copy link
Copy Markdown
Contributor

@justinmakaila justinmakaila commented Apr 21, 2026

Summary by CodeRabbit

  • New Features

    • Added Rust API client library with support for 17+ endpoints
    • Added generated TypeScript/JavaScript API clients (Axios and Fetch implementations)
    • Added comprehensive API endpoint documentation and model definitions
  • Documentation

    • Added example code for member lookup operations
    • Documented all supported endpoints and request/response models
  • Chores

    • Updated workspace configuration for multi-language support
    • Bumped OpenAPI generator CLI to version 2.31.1
    • Updated code formatting and styling across generated clients

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 21, 2026

Warning

Rate limit exceeded

@justinmakaila has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 45 minutes and 21 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 45 minutes and 21 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 7d075fb0-ccf8-48ba-9269-7638c885dd15

📥 Commits

Reviewing files that changed from the base of the PR and between ab76c64 and 61824e3.

📒 Files selected for processing (5)
  • crates/iracing-data-api-client/.openapi-generator/FILES
  • crates/iracing-data-api-client/README.md
  • openapi/iracing.json
  • openapi/oauth.json
  • packages/helpers/api-schema-to-openapi/src/index.ts
📝 Walkthrough

Walkthrough

A new Rust client crate for the iRacing data API was added to the workspace alongside workspace configuration updates. TypeScript client implementations were reformatted with quote/indentation standardization. Documentation, examples, and configuration files were added to support the new Rust client.

Changes

Cohort / File(s) Summary
Workspace & Rust Configuration
Cargo.toml, .cargo/config.toml, dist-workspace.toml, docs/RELEASING.md
Added workspace-level Cargo configuration with lints and a dist profile; configured iracing-data-api-client crate as workspace member; added dist build metadata and release instructions for Rust packages.
Rust API Client Implementation
crates/iracing-data-api-client/src/apis/{auth,car,carclass,constants,driver_stats,hosted,league,lookup,member,results,season,series,stats,team,time_attack,track}_api.rs, crates/iracing-data-api-client/src/apis/{configuration,mod}.rs
Generated complete API client with 17 endpoint modules, each implementing typed request parameters, error enums, and async functions using reqwest; added shared configuration, error handling infrastructure, and utility functions.
Rust Data Models
crates/iracing-data-api-client/src/models/{error_response,iracing_api_response,iracing_category,iracing_division,iracing_event_type,iracing_service_method_docs,iracing_service_method_parameters_docs,post_auth_request,mod}.rs
Added 8 serializable/deserializable model types supporting the API client with proper Serde mappings and constructors.
Rust Client Configuration & Metadata
crates/iracing-data-api-client/Cargo.toml, crates/iracing-data-api-client/src/lib.rs, crates/iracing-data-api-client/.openapi-generator-ignore, crates/iracing-data-api-client/.openapi-generator/{VERSION,FILES}
Created crate manifest with dependencies (serde, reqwest, tokio), library entry point, and OpenAPI generator configuration files.
Rust Documentation & Examples
crates/iracing-data-api-client/README.md, crates/iracing-data-api-client/docs/\*Api.md, crates/iracing-data-api-client/docs/\*.md, crates/iracing-data-api-client/examples/get_member.rs, crates/iracing-data-api-client/git_push.sh
Added comprehensive API endpoint documentation, model documentation, example CLI for fetching member data, and git initialization helper script.
Root Configuration & Documentation
.gitignore, package.json, README.md
Extended .gitignore for Rust artifacts; updated OpenAPI generator script delegation and version (^2.31.1); added Rust client reference to root README.
TypeScript Axios Client
packages/api/client/axios/{base,common,configuration,index}.ts, packages/api/client/axios/package.json
Reformatted code to use double-quote string literals, consistent indentation, and improved trailing semicolon/comma placement; updated package metadata (version 0.0.1, adjusted description/repository).
TypeScript Fetch Client
packages/api/client/fetch/src/apis/{Auth,Car,Carclass,Constants,DriverStats,Hosted,League,Lookup,Member,Results,Season,Series,Stats,Team}Api.ts, packages/api/client/fetch/package.json
Restructured all API classes with double-quoted imports and consistent formatting; reorganized methods into *Raw/convenience wrapper pairs; updated package metadata (version 0.0.1, simplified repository/description).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 A Rust client hops into view, bringing iRacing data straight and true,
With typed endpoints and models so grand, the API shines across the land.
While TypeScript clients get their style refreshed, all the pieces are now enmeshed!
✨🏎️

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/rust-client

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 45

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.gitignore:
- Around line 140-143: Update the .gitignore entries "debug" and "target" to be
anchored to the repository root by replacing the bare names with "/debug" and
"/target" so they only ignore the workspace-level Cargo build directories
(change the existing unanchored lines shown in the diff to use leading slashes).

In `@Cargo.toml`:
- Around line 1-3: Optional improvement: centralize shared dependency versions
and common metadata by adding a [workspace.dependencies] table for pinned
dependency versions and a [workspace.package] section for shared package
metadata so new crates inherit them; update existing crate manifests (e.g., the
crate in crates/iracing-data-api-client) to remove duplicated version/metadata
entries and rely on the workspace tables ([workspace.dependencies],
[workspace.package]) to prevent drift as more crates are added.

In `@crates/iracing-data-api-client/.gitignore`:
- Around line 1-14: The crate-level .gitignore
(crates/iracing-data-api-client/.gitignore) duplicates patterns already present
at repo root; to fix, add an .openapi-generator-ignore entry to the
OpenAPI/codegen config so the generator stops emitting this file (or update the
generator template to omit crate-level .gitignore), and remove the duplicate
file from the repo so only the root .gitignore (which already includes patterns
like debug, target, **/*.rs.bk, *.pdb, and **/mutants.out*/) is the single
source of truth.

In `@crates/iracing-data-api-client/.travis.yml`:
- Line 1: This repo still contains an unused .travis.yml file; add ".travis.yml"
to .openapi-generator-ignore and remove the .travis.yml file from the repository
so the generator and readers don't assume Travis CI is configured—ensure the
entry is added exactly as ".travis.yml" to the .openapi-generator-ignore file
and then commit the deletion of .travis.yml.

In `@crates/iracing-data-api-client/Cargo.toml`:
- Line 15: The reqwest dependency in Cargo.toml currently enables the unused
"multipart" feature; remove "multipart" from the features array for the reqwest
entry (keeping default-features = false and the "json" feature) in the reqwest =
{ ... } line so the dependency becomes leaner, then rebuild to verify no missing
feature errors.

In `@crates/iracing-data-api-client/docs/CarApi.md`:
- Line 23: The return-section links currently point to "iracingAPIResponse.md"
but the generated model file is named "IracingApiResponse.md"; update the links
in CarApi.md so any reference to iracingAPIResponse.md (e.g., the return
sections linking [**models::IracingApiResponse**](iracingAPIResponse.md)) uses
the correctly-cased "IracingApiResponse.md" instead, and search/replace other
occurrences (the comment notes this applies to multiple places) to ensure all
return-model links point to IracingApiResponse.md.

In `@crates/iracing-data-api-client/docs/CarclassApi.md`:
- Line 22: The markdown link for the return type references the wrong filename
casing: change the link target from "iracingAPIResponse.md" to the generated
model filename "IracingApiResponse.md" so the reference for
models::IracingApiResponse resolves correctly; update the link text or target in
CarclassApi.md accordingly.
- Line 33: Remove the empty "Back to top" anchor in CarclassApi.md that uses the
placeholder link "(#)"; edit the header link list containing "[[Back to top]](#)
[[Back to API list]]..." and either delete the "[[Back to top]](#)" segment or
replace "(#)" with a valid anchor target for the page (e.g., the actual top
section id), ensuring the markdownlint MD042 violation is resolved.

In `@crates/iracing-data-api-client/docs/ConstantsApi.md`:
- Around line 7-9: The three API method rows in ConstantsApi.md
(get_constants_categories, get_constants_divisions, get_constants_event_types)
are missing Description cells which breaks the markdown table; update each table
row to include a short description (e.g., "List all constant categories", "List
division constants", "List event type constants" or equivalent) so every row has
a non-empty Description column and the table columns remain balanced.
- Line 26: Update the return-type markdown links in ConstantsApi.md that
currently point to iracingAPIResponse.md to use the correct model document name
IracingApiResponse.md; specifically edit the three occurrences (previously at
lines mentioned in review) so the link target matches the model file casing and
spelling (IracingApiResponse.md) to maintain consistency with the model docs.
- Line 37: Remove the empty "(#)" anchors used in the "Back to top" link
instances in ConstantsApi.md (the links with text "Back to top") and either
delete those empty hrefs or replace them with a concrete anchor (e.g. "#top" or
the actual section id) so the markdown no longer violates MD042; update every
occurrence of the `[[Back to top]](#)` link (also present similarly near the
other lists) to use a valid target or plain text.

In `@crates/iracing-data-api-client/docs/DriverStatsApi.md`:
- Line 25: The markdown link referencing the return type uses the wrong filename
case; update the link target from iracingAPIResponse.md to IracingApiResponse.md
so it correctly points to the model documentation for IracingApiResponse (ensure
the link text and href match the exact filename casing of
IracingApiResponse.md).
- Line 21: The link for the parameter type IracingCategory is broken in
DriverStatsApi.md (currently linking to "(.md)"); update the markdown link
target so the table entry for **category** points to IracingCategory.md (i.e.,
reference IracingCategory.md instead of .md) so the IracingCategory
documentation is reachable.

In `@crates/iracing-data-api-client/docs/HostedApi.md`:
- Line 28: The docs currently link to the wrong filename (iracingAPIResponse.md)
for the response model; update the two return-section links in HostedApi.md
(both references to models::IracingApiResponse) to point to the generated
IracingApiResponse.md instead so the link resolves correctly.

In `@crates/iracing-data-api-client/docs/IracingApiResponse.md`:
- Around line 1-12: Add an exclusion for the generated docs to the markdownlint
configuration so the auto-generated file IracingApiResponse.md (and its sibling
files) are ignored; update .markdownlint.json/.markdownlint.yml or the lint
config used in CI to add the pattern that matches the generated docs (e.g.,
crates/iracing-data-api-client/docs/**) to the ignore list, commit the config
change, and run the linter to verify the MD055/MD056 warnings no longer appear
for those generated files.

In `@crates/iracing-data-api-client/docs/IracingDivision.md`:
- Around line 1-22: The generated enum IracingDivision uses non-semantic
Variant0..Variant10; update the upstream OpenAPI schema for IracingDivision to
add x-enum-varnames (and optionally x-enum-descriptions) mapping each numeric
value to meaningful identifiers (e.g., Rookie, Division1, Division2, …) and
verify whether the allowed values should be 1–10 (and whether 0 is valid) so the
mapping matches the real domain; after updating the IracingDivision schema in
the spec, re-run the client generation so the Rust enum names (IracingDivision)
pick up the new identifiers.

In `@crates/iracing-data-api-client/docs/IracingEventType.md`:
- Around line 1-15: The IracingEventType enum currently uses non-semantic
numeric variant names; update the OpenAPI/JSON schema for IracingEventType to
include x-enum-varnames: [Practice, Qualify, TimeTrial, Race] (and optionally
x-enum-descriptions with short texts for each) so the generated Rust enum and
the docs reflect semantic names rather than 2/3/4/5; locate the IracingEventType
schema entry in the API model and add the x-enum-varnames (and descriptions if
desired) under that schema to ensure codegen and docs pick up the friendly
names.

In `@crates/iracing-data-api-client/docs/IracingServiceMethodDocs.md`:
- Line 8: The markdown link for the parameters model has incorrect filename
casing; update the link target on the parameters row (the reference to
iracingServiceMethodParametersDocs.md) to use the correct filename
IracingServiceMethodParametersDocs.md so the link matches the actual model doc
file name; ensure the displayed text ([std::collections::HashMap<String,
models::IracingServiceMethodParametersDocs>]) and the link target are
consistent.
- Around line 7-8: The markdown table rows for the "**link**" and
"**parameters**" entries in IracingServiceMethodDocs.md have empty trailing
cells causing MD056; update those rows so every row has the same number of
columns by either removing the extra trailing pipe(s) or filling the empty
cell(s) with appropriate content (e.g., a short description or "—") so the
"**link**" and "**parameters**" table lines match the table's column count and
pass the markdown linter.

In `@crates/iracing-data-api-client/docs/MemberApi.md`:
- Line 32: The generated markdown links use the wrong-cased filename
"[**models::IracingApiResponse**](iracingAPIResponse.md)" causing 404s; update
the OpenAPI/generator template/config so it emits links pointing to
"IracingApiResponse.md" (capital I) instead of "iracingAPIResponse.md". Locate
the template or config responsible for model link generation (search for the
models::IracingApiResponse rendering in the generator templates or the
name-mangling logic) and normalize the casing rule for model filenames (or use
the model class name verbatim) so all generated docs (MemberApi.md,
LeagueApi.md, LookupApi.md, StatsApi.md, etc.) consistently reference
IracingApiResponse.md across the ~67 occurrences. Ensure the change is in the
generator templates/config rather than editing generated markdown files.

In `@crates/iracing-data-api-client/docs/PostAuthRequest.md`:
- Around line 1-12: The PostAuthRequest schema lacks a descriptive/secret
annotation for the password field; update the upstream OpenAPI spec so the
PostAuthRequest.password property includes a clear description (e.g., note the
expected lowercased-email-salted SHA256 hash if applicable) and set format:
password to mark it sensitive, then re-generate the docs/models so the change is
reflected in the generated PostAuthRequest code and documentation.

In `@crates/iracing-data-api-client/docs/ResultsApi.md`:
- Line 226: Update the docs line for event_type to fix the broken link and typo:
replace the empty link target "(.md)" with the correct target referencing the
IracingEventType documentation (e.g., [IracingEventType](IracingEventType.md) or
the appropriate anchor) and correct the word "Retrict" to "Restrict" in the
description for event_type/IracingEventType.

In `@crates/iracing-data-api-client/docs/SeasonApi.md`:
- Line 29: The SeasonApi.md contains incorrect/auto-generated model links:
change the link target `iracingAPIResponse.md` to the correct
`IracingApiResponse.md`, replace `models::IracingEventType.md` with the actual
model doc filename (e.g. `IracingEventType.md`), and remove or stop linking
primitives like `f64` (don’t point them to `f64.md`); update all occurrences
referenced in this file (including the other spots mentioned around lines 58,
82, 86, 110-111, 115) so each model uses the correct filename and primitives are
plain text.

In `@crates/iracing-data-api-client/docs/SeriesApi.md`:
- Line 77: The OpenAPI schema currently types identifier properties like
series_id (and season_id) as number/float causing generated types to be f64;
update the upstream OpenAPI definitions for all *_id properties to use type:
integer (add format: int64 where appropriate) so the generator emits integer
types (i64/i32) instead of f64. Locate identifier properties such as series_id
in the schema definitions referenced by the client (e.g., the model used to
generate SeriesApi, TimeAttackApi, TeamApi, StatsApi, ResultsApi, LeagueApi,
MemberApi, HostedApi, LookupApi) and change their type from number to integer
and add format:int64 when needed, then re-run the code generator to regenerate
the affected files.

In `@crates/iracing-data-api-client/docs/StatsApi.md`:
- Line 236: The markdown links for the type IracingDivision are broken (they
show [**IracingDivision**](.md)) in the generated API docs; update all
occurrences to point to the real target file by replacing the empty link target
(.md) with IracingDivision.md so the links read
[**IracingDivision**](IracingDivision.md); search for the token
"IracingDivision" in StatsApi.md and fix all five occurrences (the
Option<[**IracingDivision**](.md)> patterns) to use the correct file name.

In `@crates/iracing-data-api-client/docs/TeamApi.md`:
- Around line 22-23: The parameter table in TeamApi.md has missing Notes cells
for the parameters team_id and include_licenses; update the two rows so the
5-column table remains consistent by adding an explicit Notes value (e.g.,
"None" or a short note) for **team_id** and **include_licenses**—locate the rows
containing **team_id** and **include_licenses** and append the Notes column text
to each row to restore table consistency.
- Line 27: Update the two Markdown links in TeamApi.md that point to the model
documentation so their filenames use the correct casing: replace occurrences of
"iracingAPIResponse.md" with "IracingApiResponse.md" (the model is
models::IracingApiResponse) so both links consistently reference
IracingApiResponse.md.
- Around line 7-8: The markdown table rows for the Team API methods do not have
Description values; open TeamApi.md and add concise descriptions for the methods
referenced by the links get_team and get_team_membership (e.g., "Retrieve team
details" for get_team and "Get team membership info" for get_team_membership) so
the Description column is not empty and the table column count warnings are
resolved; update the table cells next to [**get_team**](TeamApi.md#get_team) and
[**get_team_membership**](TeamApi.md#get_team_membership) accordingly.
- Line 38: Replace the empty top anchors that cause MD042 by changing the links
from "[Back to top](#)" to a valid target (e.g. "[Back to top](`#top`)") and add a
matching top-level anchor/heading id (e.g. "<a id=\"top\"></a>" or a top heading
"## Top" with id) so the links resolve; update both occurrences of the "[Back to
top](#)" link (the one around "Back to top" at the two places flagged) and
ensure the top of the document contains the corresponding "top" anchor/heading.

In `@crates/iracing-data-api-client/docs/TimeAttackApi.md`:
- Around line 23-25: The Markdown link for the return type in TimeAttackApi.md
points to the wrong-cased file `iracingAPIResponse.md`; update the link target
to the generated model filename `IracingApiResponse.md` (the referenced model is
models::IracingApiResponse) so the path matches case-sensitively and the link
resolves correctly.

In `@crates/iracing-data-api-client/docs/TrackApi.md`:
- Line 34: The markdown uses empty link targets '[[Back to top]](#)' which
triggers MD042; update these occurrences in TrackApi.md by replacing '[[Back to
top]](#)' with a non-empty anchor such as '[[Back to top]](`#top`)' (and ensure
any corresponding '#top' anchor exists on the page or use an existing header
id), applying the same replacement for the second occurrence noted.
- Line 23: Update the broken model doc link in TrackApi.md: replace the
lowercase filename target `iracingAPIResponse.md` with the correctly-cased
`IracingApiResponse.md` for the models::IracingApiResponse link so the
local/docs link resolves; also scan other doc references to ensure they use
`IracingApiResponse.md` consistently.
- Around line 7-8: The table rows for the endpoints get_track and
get_track_assets are missing the Description column, causing MD056; open the
TrackApi.md table and add a brief description or a placeholder like "N/A" for
both entries (e.g., "Retrieve track metadata" for get_track and "Retrieve track
asset list" or simply "N/A" for get_track_assets) so each row has three columns
and the table consistency is restored.

In `@crates/iracing-data-api-client/git_push.sh`:
- Around line 1-57: The generated git_push.sh is dead code inside this monorepo
and contains unquoted variable usages (git_user_id, git_repo_id, git_host) from
the generator template; exclude it from future generation and remove it now by
adding "git_push.sh" to .openapi-generator-ignore and deleting the git_push.sh
file from the repo so it won't be regenerated by pnpm codegen:client:api:rust
and won't confuse contributors.

In `@crates/iracing-data-api-client/README.md`:
- Around line 29-31: Several rows in the README API endpoint table have empty
Description cells causing MD056/MD055 warnings; update each blank Description
(for entries like post_auth, get_car, get_car_assets and the other rows around
lines referenced) to a consistent short text such as "N/A" or a one-line
summary; locate the table entries by the endpoint function names (e.g.,
post_auth in AuthApi, get_car and get_car_assets in CarApi) and replace empty
cells with the chosen placeholder so all table rows have non-empty Description
values.

In `@crates/iracing-data-api-client/src/apis/auth_api.rs`:
- Around line 19-21: PostAuthParams currently has pub post_auth_request:
Option<models::PostAuthRequest> which causes a literal JSON null to be sent when
.json(&None) is called; update the caller that builds the request (where
.json(...) is invoked—referenced in the auth API request builder around the
`.json` call) to only attach the body when post_auth_request is Some, or
alternatively change PostAuthParams to make post_auth_request non-optional (pub
post_auth_request: models::PostAuthRequest) so callers must provide credentials;
pick one fix and apply it consistently (either add a guard like if let
Some(body) = params.post_auth_request { request = request.json(&body); } or
change the struct and call sites to pass a concrete PostAuthRequest).

In `@crates/iracing-data-api-client/src/apis/carclass_api.rs`:
- Around line 21-25: The GetCarClassError enum (variants Status401, Status429,
Status503) is currently relying on untagged deserialization which will match the
first compatible shape; instead change error handling to decode by HTTP status
code: in the response-to-error path (where GetCarClassError is constructed)
switch on the response status and deserialize the body into
models::ErrorResponse for each specific status to return the corresponding
variant (Status401, Status429, Status503), and fall back to UnknownValue by
attempting serde_json::from_value for other statuses; update any code
constructing GetCarClassError to use this status-based match rather than relying
on serde untagged deserialization.

In `@crates/iracing-data-api-client/src/apis/configuration.rs`:
- Around line 13-21: The derived Debug on Configuration (and ApiKey) will expose
secrets (basic_auth, oauth_access_token, bearer_access_token, api_key); replace
the derive(Debug) by implementing a custom std::fmt::Debug for Configuration and
for ApiKey that prints non-sensitive fields (e.g., base_path, user_agent, client
type info) but redacts or omits sensitive fields such as basic_auth,
oauth_access_token, bearer_access_token, and api_key; ensure the Debug impl for
BasicAuth/ApiKey also redacts credentials so logging Configuration or ApiKey
never includes secret values.

In `@crates/iracing-data-api-client/src/apis/constants_api.rs`:
- Around line 49-50: The three constants endpoints currently try to deserialize
array JSON into models::IracingApiResponse, causing runtime failures; update the
signatures and deserialization to return and parse the appropriate Vec types:
change get_constants_categories(...) -> Result<Vec<models::IracingCategory>,
Error<GetConstantsCategoriesError>> and parse the response body with
response.json::<Vec<models::IracingCategory>>(), change
get_constants_divisions(...) -> Result<Vec<models::IracingDivision>,
Error<GetConstantsDivisionsError>> and parse with
response.json::<Vec<models::IracingDivision>>(), and change
get_constants_event_types(...) -> Result<Vec<models::IracingEventType>,
Error<GetConstantsEventTypesError>> and parse with
response.json::<Vec<models::IracingEventType>>() so the functions and their
error generics match the new return types.

In `@crates/iracing-data-api-client/src/apis/member_api.rs`:
- Around line 17-23: Change the GetMemberParams.cust_ids field from String to a
typed collection (preferably Vec<i64>) and update its serialization to produce
the same comma-separated query value so callers pass Vec<i64> and the client
builds the query string; locate GetMemberParams in member_api.rs and replace the
cust_ids type and any code that constructs the query param accordingly, and
apply the same change pattern to the category_ids/event_types fields in
results_api.rs so they use Vec<...> (integer type) with identical
comma-separated serialization.

In `@crates/iracing-data-api-client/src/apis/mod.rs`:
- Around line 64-91: The helper parse_deep_object currently panics on non-Object
inputs via unimplemented!, so change it to gracefully return an empty Vec when
value is not an Object (i.e., replace the final unimplemented! call with return
vec![]), keeping the same signature; this prevents aborts when callers pass an
array/number/null and lets request-building continue safely while preserving all
existing object-handling logic in parse_deep_object.
- Around line 1-132: The OpenAPI spec currently declares all numeric ID
parameters (e.g., award_id, subsession_id, season_id, league_id, team_id,
car_id, track_id, series_id, etc.) as type: number, which generates f64 IDs;
update those schema/parameter definitions to use type: integer with format:
int64 for all ID fields, then re-run the OpenAPI generator to regenerate the
client so generated signatures in the API modules (e.g., car_api, league_api,
stats_api, team_api, results_api) use i64 instead of f64; after regeneration,
inspect generated function signatures and models (the places that previously
accepted f64 IDs) to confirm they now use i64 and run tests/formatting.

In `@crates/iracing-data-api-client/src/apis/season_api.rs`:
- Around line 178-232: The match expressions using the constant "multi" are dead
code; in both get_season_spectator_subsession_ids and
get_season_spectator_subsession_ids_detail remove the `match "multi" { "multi"
=> ..., _ => ... }` and instead call req_builder.query(...) directly for
params.event_types and params.season_ids (use the existing
param_value.into_iter().map(...).collect::<Vec<(_,_)>>() form for multi-valued
queries). Update the blocks that reference params.event_types in
get_season_spectator_subsession_ids and params.event_types and params.season_ids
in get_season_spectator_subsession_ids_detail to eliminate the unreachable `_`
arm.

In `@crates/iracing-data-api-client/src/models/iracing_api_response.rs`:
- Around line 16-22: The generated struct IracingApiResponse shows expires as
String and various IDs are emitted as f64 because the OpenAPI source and
generator config aren’t specifying integer/date-time types; update the OpenAPI
spec so the expires property has type: string and format: date-time (so
generators can map it to chrono::DateTime<Utc> when the chrono feature is
enabled) and change all identifier schemas (cust_id, season_id, league_id,
car_id, customerId, etc.) from type: number to type: integer with an appropriate
format (int64 or int32) so the generator emits i64/i32; also enable/configure
the codegen to use chrono for date-time mapping rather than editing generated
files directly.

In `@crates/iracing-data-api-client/src/models/post_auth_request.rs`:
- Around line 14-19: PostAuthRequest currently derives Debug and leaks
credentials; to fix, prevent the generated file from being overwritten (add
src/models/post_auth_request.rs to .openapi-generator-ignore) and add a custom
Debug implementation for PostAuthRequest that redacts email/password values (so
Debug prints safe placeholders); ensure PostAuthParams in auth_api.rs will then
inherit the safe Debug output; alternatively, if you prefer generator-side
fixes, create a custom OpenAPI Generator template to emit the redacted Debug
impl for PostAuthRequest during generation.
🪄 Autofix (Beta)

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: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 192e3896-fa97-492a-bfcc-5fb1617d22d7

📥 Commits

Reviewing files that changed from the base of the PR and between ced4824 and 199d25a.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (65)
  • .gitignore
  • Cargo.toml
  • crates/iracing-data-api-client/.gitignore
  • crates/iracing-data-api-client/.openapi-generator-ignore
  • crates/iracing-data-api-client/.openapi-generator/FILES
  • crates/iracing-data-api-client/.openapi-generator/VERSION
  • crates/iracing-data-api-client/.travis.yml
  • crates/iracing-data-api-client/Cargo.toml
  • crates/iracing-data-api-client/README.md
  • crates/iracing-data-api-client/docs/AuthApi.md
  • crates/iracing-data-api-client/docs/CarApi.md
  • crates/iracing-data-api-client/docs/CarclassApi.md
  • crates/iracing-data-api-client/docs/ConstantsApi.md
  • crates/iracing-data-api-client/docs/DocApi.md
  • crates/iracing-data-api-client/docs/DriverStatsApi.md
  • crates/iracing-data-api-client/docs/ErrorResponse.md
  • crates/iracing-data-api-client/docs/HostedApi.md
  • crates/iracing-data-api-client/docs/IracingApiResponse.md
  • crates/iracing-data-api-client/docs/IracingCategory.md
  • crates/iracing-data-api-client/docs/IracingDivision.md
  • crates/iracing-data-api-client/docs/IracingEventType.md
  • crates/iracing-data-api-client/docs/IracingServiceMethodDocs.md
  • crates/iracing-data-api-client/docs/IracingServiceMethodParametersDocs.md
  • crates/iracing-data-api-client/docs/LeagueApi.md
  • crates/iracing-data-api-client/docs/LookupApi.md
  • crates/iracing-data-api-client/docs/MemberApi.md
  • crates/iracing-data-api-client/docs/PostAuthRequest.md
  • crates/iracing-data-api-client/docs/ResultsApi.md
  • crates/iracing-data-api-client/docs/SeasonApi.md
  • crates/iracing-data-api-client/docs/SeriesApi.md
  • crates/iracing-data-api-client/docs/StatsApi.md
  • crates/iracing-data-api-client/docs/TeamApi.md
  • crates/iracing-data-api-client/docs/TimeAttackApi.md
  • crates/iracing-data-api-client/docs/TrackApi.md
  • crates/iracing-data-api-client/git_push.sh
  • crates/iracing-data-api-client/src/apis/auth_api.rs
  • crates/iracing-data-api-client/src/apis/car_api.rs
  • crates/iracing-data-api-client/src/apis/carclass_api.rs
  • crates/iracing-data-api-client/src/apis/configuration.rs
  • crates/iracing-data-api-client/src/apis/constants_api.rs
  • crates/iracing-data-api-client/src/apis/doc_api.rs
  • crates/iracing-data-api-client/src/apis/driver_stats_api.rs
  • crates/iracing-data-api-client/src/apis/hosted_api.rs
  • crates/iracing-data-api-client/src/apis/league_api.rs
  • crates/iracing-data-api-client/src/apis/lookup_api.rs
  • crates/iracing-data-api-client/src/apis/member_api.rs
  • crates/iracing-data-api-client/src/apis/mod.rs
  • crates/iracing-data-api-client/src/apis/results_api.rs
  • crates/iracing-data-api-client/src/apis/season_api.rs
  • crates/iracing-data-api-client/src/apis/series_api.rs
  • crates/iracing-data-api-client/src/apis/stats_api.rs
  • crates/iracing-data-api-client/src/apis/team_api.rs
  • crates/iracing-data-api-client/src/apis/time_attack_api.rs
  • crates/iracing-data-api-client/src/apis/track_api.rs
  • crates/iracing-data-api-client/src/lib.rs
  • crates/iracing-data-api-client/src/models/error_response.rs
  • crates/iracing-data-api-client/src/models/iracing_api_response.rs
  • crates/iracing-data-api-client/src/models/iracing_category.rs
  • crates/iracing-data-api-client/src/models/iracing_division.rs
  • crates/iracing-data-api-client/src/models/iracing_event_type.rs
  • crates/iracing-data-api-client/src/models/iracing_service_method_docs.rs
  • crates/iracing-data-api-client/src/models/iracing_service_method_parameters_docs.rs
  • crates/iracing-data-api-client/src/models/mod.rs
  • crates/iracing-data-api-client/src/models/post_auth_request.rs
  • package.json

Comment thread .gitignore Outdated
Comment thread Cargo.toml
Comment thread crates/iracing-data-api-client/.gitignore Outdated
Comment thread crates/iracing-data-api-client/.travis.yml Outdated
Comment thread crates/iracing-data-api-client/Cargo.toml Outdated
Comment thread crates/iracing-data-api-client/src/apis/auth_api.rs
Comment on lines +21 to +25
pub enum GetCarClassError {
Status401(models::ErrorResponse),
Status429(models::ErrorResponse),
Status503(models::ErrorResponse),
UnknownValue(serde_json::Value),
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Decode typed errors by HTTP status, not untagged shape.

Because Status401, Status429, and Status503 all wrap models::ErrorResponse, untagged serde deserialization will pick the first matching variant. A valid 429/503 body can therefore become Status401.

🐛 Proposed fix for this endpoint
-        let entity: Option<GetCarClassError> = serde_json::from_str(&content).ok();
+        let entity: Option<GetCarClassError> = match status.as_u16() {
+            401 => serde_json::from_str(&content).ok().map(GetCarClassError::Status401),
+            429 => serde_json::from_str(&content).ok().map(GetCarClassError::Status429),
+            503 => serde_json::from_str(&content).ok().map(GetCarClassError::Status503),
+            _ => serde_json::from_str(&content).ok().map(GetCarClassError::UnknownValue),
+        };
         Err(Error::ResponseError(ResponseContent { status, content, entity }))

Also applies to: 60-62

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/iracing-data-api-client/src/apis/carclass_api.rs` around lines 21 -
25, The GetCarClassError enum (variants Status401, Status429, Status503) is
currently relying on untagged deserialization which will match the first
compatible shape; instead change error handling to decode by HTTP status code:
in the response-to-error path (where GetCarClassError is constructed) switch on
the response status and deserialize the body into models::ErrorResponse for each
specific status to return the corresponding variant (Status401, Status429,
Status503), and fall back to UnknownValue by attempting serde_json::from_value
for other statuses; update any code constructing GetCarClassError to use this
status-based match rather than relying on serde untagged deserialization.

Comment thread crates/iracing-data-api-client/src/apis/configuration.rs
Comment on lines +16 to +22
pub struct IracingApiResponse {
/// A link to the cached data
#[serde(rename = "link")]
pub link: String,
#[serde(rename = "expires")]
pub expires: String,
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Locate the OpenAPI spec driving codegen and check whether IDs are typed as number vs integer.
fd -t f -e yaml -e yml -e json | xargs rg -l -i 'openapi|swagger' 2>/dev/null
echo "---"
fd -t f -e yaml -e yml -e json | xargs rg -n -C2 -i 'cust_id|season_id|league_id' 2>/dev/null | head -60

Repository: racedirector/iracing-data-api

Length of output: 50385


🏁 Script executed:

#!/bin/bash

# Find the IracingApiResponse schema definition in the OpenAPI spec
echo "=== Searching for IracingApiResponse definition ==="
rg -A 10 'IracingApiResponse|"link".*"expires"' openapi/iracing.json | head -50

echo ""
echo "=== Checking how expires is typed ==="
rg -B 5 -A 5 '"expires"' openapi/iracing.json | head -80

echo ""
echo "=== Sample ID field types (cust_id, season_id, league_id, car_id) ==="
rg -B 2 -A 2 '"(cust_id|season_id|league_id|car_id)".*"type"' openapi/iracing.json | head -100

Repository: racedirector/iracing-data-api

Length of output: 50386


🏁 Script executed:

#!/bin/bash
python3 << 'EOF'
import json

# Read the OpenAPI spec
with open('openapi/iracing.json', 'r') as f:
    spec = json.load(f)

# 1. Find customerId schema
print("=== customerId Schema ===")
if 'customerId' in spec.get('components', {}).get('schemas', {}):
    cust_id_schema = spec['components']['schemas']['customerId']
    print(json.dumps(cust_id_schema, indent=2))
else:
    print("customerId schema not found")

print("\n=== Sample ID parameters (first 3) ===")
# Find some ID parameters in paths
count = 0
for path, methods in spec.get('paths', {}).items():
    for method, details in methods.items():
        if isinstance(details, dict):
            for param in details.get('parameters', []):
                if 'id' in param.get('name', '').lower():
                    print(f"Path: {path}, Param: {param['name']}")
                    print(f"  Schema: {json.dumps(param.get('schema', {}), indent=4)}")
                    count += 1
                    if count >= 3:
                        break
        if count >= 3:
            break
    if count >= 3:
        break

print("\n=== Success Response (partial) ===")
if 'Success' in spec.get('components', {}).get('responses', {}):
    success_resp = spec['components']['responses']['Success']
    print(json.dumps(success_resp, indent=2)[:500])
EOF

Repository: racedirector/iracing-data-api

Length of output: 1150


🏁 Script executed:

#!/bin/bash
python3 << 'EOF'
import json

with open('openapi/iracing.json', 'r') as f:
    spec = json.load(f)

# Look for iracingAPIResponse schema
print("=== iracingAPIResponse Schema ===")
schemas = spec.get('components', {}).get('schemas', {})

# Try different case variations
for schema_name in ['iracingAPIResponse', 'IracingAPIResponse', 'iracingApiResponse']:
    if schema_name in schemas:
        resp = schemas[schema_name]
        print(f"Found as '{schema_name}':")
        print(json.dumps(resp, indent=2))
        break
else:
    # List all schemas with 'response' in name
    print("Available response-like schemas:")
    for name in schemas:
        if 'response' in name.lower():
            print(f"  - {name}")

print("\n=== Checking for 'expires' field across all schemas ===")
for schema_name, schema_def in schemas.items():
    if isinstance(schema_def, dict) and 'properties' in schema_def:
        if 'expires' in schema_def['properties']:
            print(f"Found in {schema_name}:")
            print(json.dumps(schema_def['properties']['expires'], indent=2))

# Count number of fields using type: number
print("\n=== Counting ID-like fields with type: number ===")
number_count = 0
integer_count = 0
for schema_name, schema_def in schemas.items():
    if isinstance(schema_def, dict) and 'properties' in schema_def:
        for field_name, field_def in schema_def['properties'].items():
            if isinstance(field_def, dict):
                if field_def.get('type') == 'number' and ('id' in field_name.lower() or 'count' in field_name.lower()):
                    number_count += 1
                elif field_def.get('type') == 'integer' and ('id' in field_name.lower() or 'count' in field_name.lower()):
                    integer_count += 1

print(f"ID/count fields as type: number = {number_count}")
print(f"ID/count fields as type: integer = {integer_count}")
EOF

Repository: racedirector/iracing-data-api

Length of output: 1358


The OpenAPI spec already specifies expires with format: date-time, but the Rust code generator is not honoring it and continues emitting String. Additionally, numeric identifiers across the spec use type: number instead of type: integer, causing them to generate as f64 instead of i64/i32.

Two observations worth surfacing:

  1. expires field: The spec correctly defines expires with format: date-time, but the generated Rust code shows pub expires: String. The code generator needs to be updated to respect the date-time format and emit chrono::DateTime<Utc> (with the chrono feature). Alternatively, if the generator doesn't support this, the spec format directive may need adjustment.

  2. Numeric identifiers: Across the spec, IDs like cust_id, season_id, league_id, car_id (and the customerId schema) use type: number rather than type: integer. This causes them to generate as f64, which loses precision above 2^53 and silently accepts fractional values — problematic for integer identifiers. Change these to type: integer (with format: int64 or int32 as appropriate) to emit i64/i32.

These changes belong in the OpenAPI source document and/or the code generation configuration, not in the generated files.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/iracing-data-api-client/src/models/iracing_api_response.rs` around
lines 16 - 22, The generated struct IracingApiResponse shows expires as String
and various IDs are emitted as f64 because the OpenAPI source and generator
config aren’t specifying integer/date-time types; update the OpenAPI spec so the
expires property has type: string and format: date-time (so generators can map
it to chrono::DateTime<Utc> when the chrono feature is enabled) and change all
identifier schemas (cust_id, season_id, league_id, car_id, customerId, etc.)
from type: number to type: integer with an appropriate format (int64 or int32)
so the generator emits i64/i32; also enable/configure the codegen to use chrono
for date-time mapping rather than editing generated files directly.

Comment on lines +14 to +19
#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
pub struct PostAuthRequest {
#[serde(rename = "email")]
pub email: String,
#[serde(rename = "password")]
pub password: String,
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Confirms Debug derivations around auth request types and sensitive fields.
rg -n -C3 '#\[derive\([^]]*Debug|pub email: String|pub password: String|PostAuthParams' crates/iracing-data-api-client/src/models/post_auth_request.rs crates/iracing-data-api-client/src/apis/auth_api.rs

Repository: racedirector/iracing-data-api

Length of output: 3011


🏁 Script executed:

# Search for other auth-related models that might contain sensitive fields
fd -e rs crates/iracing-data-api-client/src/models/ | xargs rg -l -i 'auth|login|credential|token|password|secret' | head -20

Repository: racedirector/iracing-data-api

Length of output: 1405


🏁 Script executed:

# Check what other types are in the models directory and whether they contain sensitive fields
rg -n 'pub struct.*auth|pub enum.*auth' -i crates/iracing-data-api-client/src/models/

Repository: racedirector/iracing-data-api

Length of output: 167


🏁 Script executed:

# Verify the custom Debug implementation syntax is valid Rust
cat > /tmp/test_debug.rs << 'EOF'
use std::fmt;

#[derive(Clone, Default, PartialEq)]
pub struct PostAuthRequest {
    pub email: String,
    pub password: String,
}

impl fmt::Debug for PostAuthRequest {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("PostAuthRequest")
            .field("email", &"<redacted>")
            .field("password", &"<redacted>")
            .finish()
    }
}

fn main() {
    let req = PostAuthRequest {
        email: "test@example.com".to_string(),
        password: "secret123".to_string(),
    };
    println!("{:?}", req);
}
EOF
rustc /tmp/test_debug.rs -o /tmp/test_debug 2>&1 && /tmp/test_debug

Repository: racedirector/iracing-data-api

Length of output: 319


🏁 Script executed:

# List all files in models directory to understand scope
fd . crates/iracing-data-api-client/src/models/ -type f -name "*.rs" | head -30

Repository: racedirector/iracing-data-api

Length of output: 243


🏁 Script executed:

# Search for all Debug derives in auth_api.rs and surrounding context
rg -n 'derive.*Debug|pub struct|pub enum' crates/iracing-data-api-client/src/apis/auth_api.rs

Repository: racedirector/iracing-data-api

Length of output: 209


🏁 Script executed:

# List all Rust files in models directory
find crates/iracing-data-api-client/src/models/ -name "*.rs" -type f | sort

Repository: racedirector/iracing-data-api

Length of output: 655


🏁 Script executed:

# Check if there are any other types containing auth request or sensitive data
rg -l 'PostAuthRequest|email|password' crates/iracing-data-api-client/src/

Repository: racedirector/iracing-data-api

Length of output: 236


🏁 Script executed:

# Check mod.rs to see how PostAuthRequest is exported
cat crates/iracing-data-api-client/src/models/mod.rs | grep -A2 -B2 PostAuthRequest

Repository: racedirector/iracing-data-api

Length of output: 239


🏁 Script executed:

# Verify the entire post_auth_request.rs file structure to ensure the fix location is correct
cat -n crates/iracing-data-api-client/src/models/post_auth_request.rs

Repository: racedirector/iracing-data-api

Length of output: 976


🏁 Script executed:

# Check if there's an OpenAPI schema file that generates this
find . -name "*.yaml" -o -name "*.yml" -o -name "*.json" | xargs grep -l "PostAuthRequest\|/auth" 2>/dev/null | head -10

Repository: racedirector/iracing-data-api

Length of output: 116


🏁 Script executed:

# Look for OpenAPI generator configuration or scripts
find . -name "*openapi*" -o -name "*swagger*" -o -name "*.generator*" | grep -v node_modules | grep -v ".git" | head -20

Repository: racedirector/iracing-data-api

Length of output: 605


🏁 Script executed:

# Check if there's a note about how this file was generated and how to modify it
head -20 crates/iracing-data-api-client/src/models/post_auth_request.rs | grep -i "generated\|openapi\|modify"

Repository: racedirector/iracing-data-api

Length of output: 276


🏁 Script executed:

# Check what's in the openapi-generator-ignore and openapi-generator files
cat crates/iracing-data-api-client/.openapi-generator-ignore

Repository: racedirector/iracing-data-api

Length of output: 1112


🏁 Script executed:

# Also check the generator config
cat crates/iracing-data-api-client/.openapi-generator/config.json | head -50

Repository: racedirector/iracing-data-api

Length of output: 166


🏁 Script executed:

# Check what files are already being ignored in the generator ignore file
ls -la crates/iracing-data-api-client/.openapi-generator/

Repository: racedirector/iracing-data-api

Length of output: 295


🏁 Script executed:

# Search for any custom Debug implementations or ignored files in the crate
find crates/iracing-data-api-client -name "*.rs" -exec grep -l "impl.*Debug" {} \;

Repository: racedirector/iracing-data-api

Length of output: 119


🏁 Script executed:

# Check if there's documentation about modifying generated files
cat crates/iracing-data-api-client/README.md 2>/dev/null | head -50

Repository: racedirector/iracing-data-api

Length of output: 3604


🏁 Script executed:

# Verify what's in the custom Debug impl in mod.rs
grep -A20 "impl.*Debug" crates/iracing-data-api-client/src/apis/mod.rs

Repository: racedirector/iracing-data-api

Length of output: 627


🏁 Script executed:

# Check if PostAuthRequest is used anywhere else that might be affected
rg -n 'PostAuthRequest' crates/iracing-data-api-client/src/ | grep -v "^Binary"

Repository: racedirector/iracing-data-api

Length of output: 699


🏁 Script executed:

# Check what files are listed in .openapi-generator/FILES (files that were generated)
cat crates/iracing-data-api-client/.openapi-generator/FILES | head -20

Repository: racedirector/iracing-data-api

Length of output: 478


🏁 Script executed:

# Verify if post_auth_request.rs is in the generated files list
cat crates/iracing-data-api-client/.openapi-generator/FILES | grep post_auth_request

Repository: racedirector/iracing-data-api

Length of output: 104


🏁 Script executed:

# Check if there's a Cargo.toml or build script that regenerates these files
find crates/iracing-data-api-client -name "Cargo.toml" -o -name "build.rs" | xargs cat

Repository: racedirector/iracing-data-api

Length of output: 741


🏁 Script executed:

# Check if the openapi-generator-ignore file has been modified to include post_auth_request.rs
grep -i "post_auth" crates/iracing-data-api-client/.openapi-generator-ignore

Repository: racedirector/iracing-data-api

Length of output: 55


🏁 Script executed:

# Check the root of the repo for OpenAPI generation scripts or documentation
ls -la | grep -i openapi

Repository: racedirector/iracing-data-api

Length of output: 202


🏁 Script executed:

# Look for any documentation or scripts about regenerating the client
find . -name "*.md" -o -name "*.sh" | xargs grep -l "openapi\|generate" | grep -v node_modules | head -10

Repository: racedirector/iracing-data-api

Length of output: 384


🏁 Script executed:

# Check the openapitools.json to understand the generator configuration
cat openapitools.json

Repository: racedirector/iracing-data-api

Length of output: 226


🏁 Script executed:

# Look at the README to understand how the client is regenerated
head -50 README.md

Repository: racedirector/iracing-data-api

Length of output: 3441


Add custom Debug impl to redact credentials, accounting for generated code.

Deriving Debug on PostAuthRequest containing email and password leaks credentials through logs, traces, and test failures. Note that this file is generated by OpenAPI Generator (v7.17.0), so the fix must account for regeneration. Either:

  1. Add src/models/post_auth_request.rs to .openapi-generator-ignore to preserve manual modifications across regenerations, or
  2. Use a custom OpenAPI Generator template to inject the redacted Debug impl during generation.

If using option 1, implement the custom Debug as shown. PostAuthParams in auth_api.rs also derives Debug and wraps PostAuthRequest, so once the model has a custom impl, the parameter struct will inherit correct behavior.

🔐 Proposed redaction fix (if using .openapi-generator-ignore)
-#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
+#[derive(Clone, Default, PartialEq, Serialize, Deserialize)]
 pub struct PostAuthRequest {
     #[serde(rename = "email")]
     pub email: String,
     #[serde(rename = "password")]
     pub password: String,
 }
+
+impl std::fmt::Debug for PostAuthRequest {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        f.debug_struct("PostAuthRequest")
+            .field("email", &"<redacted>")
+            .field("password", &"<redacted>")
+            .finish()
+    }
+}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
pub struct PostAuthRequest {
#[serde(rename = "email")]
pub email: String,
#[serde(rename = "password")]
pub password: String,
#[derive(Clone, Default, PartialEq, Serialize, Deserialize)]
pub struct PostAuthRequest {
#[serde(rename = "email")]
pub email: String,
#[serde(rename = "password")]
pub password: String,
}
impl std::fmt::Debug for PostAuthRequest {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("PostAuthRequest")
.field("email", &"<redacted>")
.field("password", &"<redacted>")
.finish()
}
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/iracing-data-api-client/src/models/post_auth_request.rs` around lines
14 - 19, PostAuthRequest currently derives Debug and leaks credentials; to fix,
prevent the generated file from being overwritten (add
src/models/post_auth_request.rs to .openapi-generator-ignore) and add a custom
Debug implementation for PostAuthRequest that redacts email/password values (so
Debug prints safe placeholders); ensure PostAuthParams in auth_api.rs will then
inherit the safe Debug output; alternatively, if you prefer generator-side
fixes, create a custom OpenAPI Generator template to emit the redacted Debug
impl for PostAuthRequest during generation.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Review continued from previous batch...

Comment on lines +49 to +50
/// Constant; returned directly as an array of objects
pub async fn get_constants_categories(configuration: &configuration::Configuration) -> Result<models::IracingApiResponse, Error<GetConstantsCategoriesError>> {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Inspect constants endpoint docs and available generated models.
# Expectation: Constants endpoints should document/define array response models, not IracingApiResponse.

set -euo pipefail

fd -a 'ConstantsApi\.md$|iracing_api_response\.rs$|mod\.rs$' . \
  | xargs -r sed -n '1,220p'

rg -n -C3 'get_constants_(categories|divisions|event_types)|IracingApiResponse|array of objects|Vec<|\\[\\]' --glob '*.rs' --glob '*.md'

Repository: racedirector/iracing-data-api

Length of output: 50386


🏁 Script executed:

cat -n crates/iracing-data-api-client/src/apis/constants_api.rs

Repository: racedirector/iracing-data-api

Length of output: 8348


Fix constants endpoints to deserialize array responses.

The comments correctly state these endpoints return "directly as an array of objects", but all three functions attempt to deserialize into models::IracingApiResponse (which only has link and expires fields). Valid array responses will fail deserialization at runtime.

Update return types to use the appropriate array model: Vec<IracingCategory> for get_constants_categories, Vec<IracingDivision> for get_constants_divisions, and Vec<IracingEventType> for get_constants_event_types.

Also applies to: lines 73-78 (get_constants_divisions), 87-88 (get_constants_divisions), 111-116 (get_constants_divisions), 125-126 (get_constants_event_types), 149-154 (get_constants_event_types)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/iracing-data-api-client/src/apis/constants_api.rs` around lines 49 -
50, The three constants endpoints currently try to deserialize array JSON into
models::IracingApiResponse, causing runtime failures; update the signatures and
deserialization to return and parse the appropriate Vec types: change
get_constants_categories(...) -> Result<Vec<models::IracingCategory>,
Error<GetConstantsCategoriesError>> and parse the response body with
response.json::<Vec<models::IracingCategory>>(), change
get_constants_divisions(...) -> Result<Vec<models::IracingDivision>,
Error<GetConstantsDivisionsError>> and parse with
response.json::<Vec<models::IracingDivision>>(), and change
get_constants_event_types(...) -> Result<Vec<models::IracingEventType>,
Error<GetConstantsEventTypesError>> and parse with
response.json::<Vec<models::IracingEventType>>() so the functions and their
error generics match the new return types.

Comment on lines +17 to +23
/// struct for passing parameters to the method [`get_member`]
#[derive(Clone, Debug)]
pub struct GetMemberParams {
/// Comma-separated list of customer IDs. Example: ?cust_ids=2,3,4
pub cust_ids: String,
pub include_licenses: Option<bool>
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

cust_ids as a free-form String shifts validation to callers.

Typing cust_ids as String (lines 20-21) means callers are responsible for assembling a comma-separated list, and bad input ("12, ,abc") only surfaces as a 4xx from iRacing. The other multi-value endpoints in this crate (e.g., season event_types/season_ids) use Vec<...> and let the client build the query string. Modeling this as Vec<i64> (preferred) or Vec<f64> and serializing identically would catch typos at compile time, eliminate manual formatting, and match the crate's own conventions. Same concern applies to category_ids/event_types in results_api.rs. Likely a spec fix (type: array, items: {type: integer}) rather than a template tweak.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/iracing-data-api-client/src/apis/member_api.rs` around lines 17 - 23,
Change the GetMemberParams.cust_ids field from String to a typed collection
(preferably Vec<i64>) and update its serialization to produce the same
comma-separated query value so callers pass Vec<i64> and the client builds the
query string; locate GetMemberParams in member_api.rs and replace the cust_ids
type and any code that constructs the query param accordingly, and apply the
same change pattern to the category_ids/event_types fields in results_api.rs so
they use Vec<...> (integer type) with identical comma-separated serialization.

Comment on lines +1 to +132
use std::error;
use std::fmt;

#[derive(Debug, Clone)]
pub struct ResponseContent<T> {
pub status: reqwest::StatusCode,
pub content: String,
pub entity: Option<T>,
}

#[derive(Debug)]
pub enum Error<T> {
Reqwest(reqwest::Error),
Serde(serde_json::Error),
Io(std::io::Error),
ResponseError(ResponseContent<T>),
}

impl <T> fmt::Display for Error<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let (module, e) = match self {
Error::Reqwest(e) => ("reqwest", e.to_string()),
Error::Serde(e) => ("serde", e.to_string()),
Error::Io(e) => ("IO", e.to_string()),
Error::ResponseError(e) => ("response", format!("status code {}", e.status)),
};
write!(f, "error in {}: {}", module, e)
}
}

impl <T: fmt::Debug> error::Error for Error<T> {
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
Some(match self {
Error::Reqwest(e) => e,
Error::Serde(e) => e,
Error::Io(e) => e,
Error::ResponseError(_) => return None,
})
}
}

impl <T> From<reqwest::Error> for Error<T> {
fn from(e: reqwest::Error) -> Self {
Error::Reqwest(e)
}
}

impl <T> From<serde_json::Error> for Error<T> {
fn from(e: serde_json::Error) -> Self {
Error::Serde(e)
}
}

impl <T> From<std::io::Error> for Error<T> {
fn from(e: std::io::Error) -> Self {
Error::Io(e)
}
}

pub fn urlencode<T: AsRef<str>>(s: T) -> String {
::url::form_urlencoded::byte_serialize(s.as_ref().as_bytes()).collect()
}

pub fn parse_deep_object(prefix: &str, value: &serde_json::Value) -> Vec<(String, String)> {
if let serde_json::Value::Object(object) = value {
let mut params = vec![];

for (key, value) in object {
match value {
serde_json::Value::Object(_) => params.append(&mut parse_deep_object(
&format!("{}[{}]", prefix, key),
value,
)),
serde_json::Value::Array(array) => {
for (i, value) in array.iter().enumerate() {
params.append(&mut parse_deep_object(
&format!("{}[{}][{}]", prefix, key, i),
value,
));
}
},
serde_json::Value::String(s) => params.push((format!("{}[{}]", prefix, key), s.clone())),
_ => params.push((format!("{}[{}]", prefix, key), value.to_string())),
}
}

return params;
}

unimplemented!("Only objects are supported with style=deepObject")
}

/// Internal use only
/// A content type supported by this client.
#[allow(dead_code)]
enum ContentType {
Json,
Text,
Unsupported(String)
}

impl From<&str> for ContentType {
fn from(content_type: &str) -> Self {
if content_type.starts_with("application") && content_type.contains("json") {
return Self::Json;
} else if content_type.starts_with("text/plain") {
return Self::Text;
} else {
return Self::Unsupported(content_type.to_string());
}
}
}

pub mod auth_api;
pub mod car_api;
pub mod carclass_api;
pub mod constants_api;
pub mod doc_api;
pub mod driver_stats_api;
pub mod hosted_api;
pub mod league_api;
pub mod lookup_api;
pub mod member_api;
pub mod results_api;
pub mod season_api;
pub mod series_api;
pub mod stats_api;
pub mod team_api;
pub mod time_attack_api;
pub mod track_api;

pub mod configuration;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

🧩 Analysis chain

🌐 Web query:

openapi-generator rust client type mapping integer int64

💡 Result:

In OpenAPI Generator's Rust client generator (rust), the default type mappings for integer types are: - OpenAPI "integer" (no format or int32) maps to Rust i32 - OpenAPI "integer" with format "int64" or "long" maps to Rust i64 This is explicitly defined in the RustClientCodegen source code: typeMapping.put("integer", "i32"); typeMapping.put("long", "i64"); The generator supports additional integer fitting logic via config options: - bestFitInt (default: false): Uses the best fitting integer type (e.g., i16, i64, u32) based on schema minimum/maximum values. - preferUnsignedInt (default: false): Prefers unsigned integers (u32, u64) when minimum >= 0. To enable smarter mapping (e.g., uint64/int64 with min=0 to u64), pass --additional-properties=bestFitInt=true,preferUnsignedInt=true during generation. For full customization, use --type-mappings (e.g., integer=i64) or --import-mappings, though not typically needed for standard int64 -> i64. Note: Recent fixes (e.g., PR #22853) improved integer fitting primarily for Rust servers, but client benefits from the same options. Some server generators (rust-axum) have bugs with uint32/uint64 formats as of 2026-03 (issue #23336).

Citations:


🏁 Script executed:

# First, let's look at the structure to understand where the OpenAPI spec might be
find . -type f \( -name "*.json" -o -name "*.yaml" -o -name "*.yml" \) | grep -E "(openapi|swagger|spec)" | head -20

Repository: racedirector/iracing-data-api

Length of output: 482


🏁 Script executed:

# Check one of the generated API modules to see what types are actually used for ID parameters
ls -la crates/iracing-data-api-client/src/apis/ | head -20

Repository: racedirector/iracing-data-api

Length of output: 1291


🏁 Script executed:

# Let's examine a specific API module (e.g., member_api) to see the parameter types
head -100 crates/iracing-data-api-client/src/apis/member_api.rs

Repository: racedirector/iracing-data-api

Length of output: 3138


🏁 Script executed:

# Search for ID parameters across all generated API files to see their types
rg "cust_id|subsession_id|season_id|league_id|team_id|car_id|track_id|series_id" crates/iracing-data-api-client/src/apis/ -A 2 | head -60

Repository: racedirector/iracing-data-api

Length of output: 4120


🏁 Script executed:

# Check the OpenAPI spec for ID parameter definitions
rg "cust_id|team_id|season_id|award_id|subsession_id" ./openapi/iracing.json -A 5 -B 2 | head -100

Repository: racedirector/iracing-data-api

Length of output: 50385


🏁 Script executed:

# Check the generator configuration
cat ./openapitools.json

Repository: racedirector/iracing-data-api

Length of output: 226


🏁 Script executed:

# Let's look for type definitions in the spec that show "type: number"
rg '"type":\s*"number"' ./openapi/iracing.json -B 5 | head -80

Repository: racedirector/iracing-data-api

Length of output: 50385


🏁 Script executed:

# Look for the customerId schema definition in the OpenAPI spec
jq '.components.schemas | keys' ./openapi/iracing.json | head -40

Repository: racedirector/iracing-data-api

Length of output: 317


🏁 Script executed:

# Get the customerId schema definition specifically
jq '.components.schemas.customerId' ./openapi/iracing.json

Repository: racedirector/iracing-data-api

Length of output: 152


🏁 Script executed:

# Count how many parameters use "type":"number" vs "type":"integer"
python3 << 'EOF'
import json

with open('./openapi/iracing.json', 'r') as f:
    spec = json.load(f)

number_count = 0
integer_count = 0
number_params = []
integer_params = []

# Iterate through all paths and their parameters
for path, methods in spec.get('paths', {}).items():
    for method, details in methods.items():
        if isinstance(details, dict) and 'parameters' in details:
            for param in details['parameters']:
                if 'schema' in param:
                    param_type = param['schema'].get('type')
                    param_name = param.get('name')
                    if param_type == 'number':
                        number_count += 1
                        if param_name and 'id' in param_name.lower():
                            number_params.append(param_name)
                    elif param_type == 'integer':
                        integer_count += 1
                        if param_name and 'id' in param_name.lower():
                            integer_params.append(param_name)

print(f"Parameters with 'type: number': {number_count}")
print(f"Parameters with 'type: integer': {integer_count}")
print(f"\nID parameters with 'number': {sorted(set(number_params))[:20]}")
print(f"\nID parameters with 'integer': {sorted(set(integer_params))[:20]}")
EOF

Repository: racedirector/iracing-data-api

Length of output: 394


Update OpenAPI spec to use type: integer (format: int64) instead of type: number for all ID parameters.

The OpenAPI specification currently defines all 76 numeric ID parameters (award_id, subsession_id, season_id, league_id, team_id, car_id, track_id, series_id, etc.) with type: number, which causes the OpenAPI Generator to map them to Rust's f64. This has two practical consequences:

  1. Silent precision loss for IDs ≥ 2^53 — a latent correctness trap if iRacing ID ranges grow beyond this threshold.
  2. Invalid values are representable (NaN, inf, fractional IDs), pushing invalid HTTP requests onto users who receive opaque 4xx responses; f64::to_string() also renders NaN/inf as literal strings in query parameters.

Changing the spec to type: integer with format: int64 would generate i64 instead of f64, eliminating this whole class of issues at the source. The OpenAPI Generator already properly handles this mapping; the fix requires only updating the schema definitions in ./openapi/iracing.json and regenerating the client.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/iracing-data-api-client/src/apis/mod.rs` around lines 1 - 132, The
OpenAPI spec currently declares all numeric ID parameters (e.g., award_id,
subsession_id, season_id, league_id, team_id, car_id, track_id, series_id, etc.)
as type: number, which generates f64 IDs; update those schema/parameter
definitions to use type: integer with format: int64 for all ID fields, then
re-run the OpenAPI generator to regenerate the client so generated signatures in
the API modules (e.g., car_api, league_api, stats_api, team_api, results_api)
use i64 instead of f64; after regeneration, inspect generated function
signatures and models (the places that previously accepted f64 IDs) to confirm
they now use i64 and run tests/formatting.

Comment on lines +64 to +91
pub fn parse_deep_object(prefix: &str, value: &serde_json::Value) -> Vec<(String, String)> {
if let serde_json::Value::Object(object) = value {
let mut params = vec![];

for (key, value) in object {
match value {
serde_json::Value::Object(_) => params.append(&mut parse_deep_object(
&format!("{}[{}]", prefix, key),
value,
)),
serde_json::Value::Array(array) => {
for (i, value) in array.iter().enumerate() {
params.append(&mut parse_deep_object(
&format!("{}[{}][{}]", prefix, key, i),
value,
));
}
},
serde_json::Value::String(s) => params.push((format!("{}[{}]", prefix, key), s.clone())),
_ => params.push((format!("{}[{}]", prefix, key), value.to_string())),
}
}

return params;
}

unimplemented!("Only objects are supported with style=deepObject")
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

parse_deep_object panics on non-object input.

If a caller ever passes a serde_json::Value that isn't an Object (e.g., a bare array, number, or Null because the user's struct serialized unexpectedly), line 90 panics via unimplemented!(), which propagates up through the generated endpoint functions and aborts the caller's async task. A generated helper used on the request-building hot path should degrade gracefully rather than panic.

🛡️ Suggested fallback
-    unimplemented!("Only objects are supported with style=deepObject")
+    // deepObject style only defines serialization for objects; for any other
+    // shape produce no query pairs rather than panicking at runtime.
+    Vec::new()
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/iracing-data-api-client/src/apis/mod.rs` around lines 64 - 91, The
helper parse_deep_object currently panics on non-Object inputs via
unimplemented!, so change it to gracefully return an empty Vec when value is not
an Object (i.e., replace the final unimplemented! call with return vec![]),
keeping the same signature; this prevents aborts when callers pass an
array/number/null and lets request-building continue safely while preserving all
existing object-handling logic in parse_deep_object.

Comment on lines +178 to +232
if let Some(ref param_value) = params.event_types {
req_builder = match "multi" {
"multi" => req_builder.query(&param_value.into_iter().map(|p| ("event_types".to_owned(), p.to_string())).collect::<Vec<(std::string::String, std::string::String)>>()),
_ => req_builder.query(&[("event_types", &param_value.into_iter().map(|p| p.to_string()).collect::<Vec<String>>().join(",").to_string())]),
};
}
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};

let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;

let status = resp.status();
let content_type = resp
.headers()
.get("content-type")
.and_then(|v| v.to_str().ok())
.unwrap_or("application/octet-stream");
let content_type = super::ContentType::from(content_type);

if !status.is_client_error() && !status.is_server_error() {
let content = resp.text().await?;
match content_type {
ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::IracingApiResponse`"))),
ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::IracingApiResponse`")))),
}
} else {
let content = resp.text().await?;
let entity: Option<GetSeasonSpectatorSubsessionIdsError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}

pub async fn get_season_spectator_subsession_ids_detail(configuration: &configuration::Configuration, params: GetSeasonSpectatorSubsessionIdsDetailParams) -> Result<models::IracingApiResponse, Error<GetSeasonSpectatorSubsessionIdsDetailError>> {

let uri_str = format!("{}/data/season/spectator_subsessionids_detail", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);

if let Some(ref param_value) = params.event_types {
req_builder = match "multi" {
"multi" => req_builder.query(&param_value.into_iter().map(|p| ("event_types".to_owned(), p.to_string())).collect::<Vec<(std::string::String, std::string::String)>>()),
_ => req_builder.query(&[("event_types", &param_value.into_iter().map(|p| p.to_string()).collect::<Vec<String>>().join(",").to_string())]),
};
}
if let Some(ref param_value) = params.season_ids {
req_builder = match "multi" {
"multi" => req_builder.query(&param_value.into_iter().map(|p| ("season_ids".to_owned(), p.to_string())).collect::<Vec<(std::string::String, std::string::String)>>()),
_ => req_builder.query(&[("season_ids", &param_value.into_iter().map(|p| p.to_string()).collect::<Vec<String>>().join(",").to_string())]),
};
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

🧩 Analysis chain

🌐 Web query:

openapi-generator rust reqwest array query parameter multi collectionFormat

💡 Result:

OpenAPI Generator's Rust Reqwest client supports array query parameters using the collectionFormat property from OpenAPI 2.0 specs (or equivalent style in OpenAPI 3.0). Supported formats include csv (comma-separated), multi (repeated parameters), and others like pipes. Key evidence: - PR #11169 (merged in v5.4.0): Added explicit support for collectionFormat="multi" in Rust client, generating repeated query params (e.g., ?param=value1&param=value2). - Recent PR #22683 (merged Jan 2026, v7.19.0): Fixes enum array query param serialization (uniqueItems/HashSet), docs show Vec/HashSet for arrays, confirms iteration over array elements for .query. - Official docs confirm Query parameter support for OAS2/OAS3, Array data type ✓. - Reqwest .query handles arrays by repeating keys (matches multi/csv via to_string on elements). Generated code example pattern (from PR diffs/tests): if let Some(ref param_value) = my_array { // Vec or HashSet for value in param_value { req_builder = req_builder.query(&[("myParam", &value.to_string)]); } } This serializes as ?myParam=value1&myParam=value2 (multi) or adapts for csv. For OpenAPI 3.0, uses style: form (multi repeat) or style: simple (csv), with explode=true flattening arrays. Use library=reqwest when generating. Recent fixes ensure enums serialize correctly without JSON quoting. To generate: openapi-generator-cli generate -i spec.yaml -g rust --library=reqwest -o out/rust Test with petstore sample (has array queries like tags/status).

Citations:


🏁 Script executed:

# First, check if the file exists and get its line count
wc -l crates/iracing-data-api-client/src/apis/season_api.rs

Repository: racedirector/iracing-data-api

Length of output: 130


🏁 Script executed:

# Read the specific lines mentioned in the review (178-232)
sed -n '178,232p' crates/iracing-data-api-client/src/apis/season_api.rs

Repository: racedirector/iracing-data-api

Length of output: 3374


🏁 Script executed:

# Search for all occurrences of "match \"multi\"" pattern in the file
rg 'match\s+"multi"' crates/iracing-data-api-client/src/apis/season_api.rs -n

Repository: racedirector/iracing-data-api

Length of output: 198


🏁 Script executed:

# Check if similar patterns exist in other API files
fd 'api\.rs$' crates/iracing-data-api-client/src/apis/ --exec rg 'match\s+"multi"' {} +

Repository: racedirector/iracing-data-api

Length of output: 1079


🏁 Script executed:

# Search for all "match \"multi\"" patterns in all API files
find crates/iracing-data-api-client/src/apis -name "*.rs" -type f -exec rg 'match\s+"multi"' {} + | wc -l

Repository: racedirector/iracing-data-api

Length of output: 74


🏁 Script executed:

# List which API files contain this pattern
find crates/iracing-data-api-client/src/apis -name "*.rs" -type f -exec sh -c 'if rg -q "match.*\"multi\"" "$1"; then echo "$1"; fi' _ {} \;

Repository: racedirector/iracing-data-api

Length of output: 126


🏁 Script executed:

# Verify the exact pattern structure once more at line 179
sed -n '179,182p' crates/iracing-data-api-client/src/apis/season_api.rs

Repository: racedirector/iracing-data-api

Length of output: 453


Remove unreachable _ arm in match "multi" pattern—dead code generates compiler warnings.

Lines 179–182, 222–225, and 228–231 contain match "multi" statements that always take the "multi" arm, leaving the _ branch unreachable. This triggers Rust's unreachable_patterns warning and clutters the codebase with unused logic.

Simplify by removing the match and calling .query() directly with the multi-parameter iteration:

♻️ Simplify to single branch
-    if let Some(ref param_value) = params.event_types {
-        req_builder = match "multi" {
-            "multi" => req_builder.query(&param_value.into_iter().map(|p| ("event_types".to_owned(), p.to_string())).collect::<Vec<(std::string::String, std::string::String)>>()),
-            _ => req_builder.query(&[("event_types", &param_value.into_iter().map(|p| p.to_string()).collect::<Vec<String>>().join(",").to_string())]),
-        };
-    }
+    if let Some(ref param_value) = params.event_types {
+        req_builder = req_builder.query(
+            &param_value
+                .iter()
+                .map(|p| ("event_types".to_owned(), p.to_string()))
+                .collect::<Vec<(String, String)>>(),
+        );
+    }

Apply the same simplification to season_ids (lines 227–231) and event_types in the first function (lines 179–182).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/iracing-data-api-client/src/apis/season_api.rs` around lines 178 -
232, The match expressions using the constant "multi" are dead code; in both
get_season_spectator_subsession_ids and
get_season_spectator_subsession_ids_detail remove the `match "multi" { "multi"
=> ..., _ => ... }` and instead call req_builder.query(...) directly for
params.event_types and params.season_ids (use the existing
param_value.into_iter().map(...).collect::<Vec<(_,_)>>() form for multi-valued
queries). Update the blocks that reference params.event_types in
get_season_spectator_subsession_ids and params.event_types and params.season_ids
in get_season_spectator_subsession_ids_detail to eliminate the unreachable `_`
arm.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 15

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
examples/oauth-password-limited/src/index.ts (1)

281-297: ⚠️ Potential issue | 🟡 Minor

Validate username before using as session id.

username comes from process.env.IRACING_AUTH_USERNAME and is typed as string | undefined, but is asserted non-null via username! when passed to restoreSessionForId. If the env var is unset, the store will be queried with the literal key undefined (or a runtime error depending on store semantics), masking a misconfiguration as a "no session found" path and then attempting passwordLimitedAuthorization() with undefined credentials. Consider failing fast with a clear error when username is missing.

🛡️ Proposed guard
   const username = process.env.IRACING_AUTH_USERNAME;
+  if (!username) {
+    throw new Error("IRACING_AUTH_USERNAME is required");
+  }
@@
-    session = await client.restoreSessionForId(username!);
+    session = await client.restoreSessionForId(username);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/oauth-password-limited/src/index.ts` around lines 281 - 297, Check
and fail fast if process.env.IRACING_AUTH_USERNAME is missing before using it as
the session id or embedding it in OAuthClient clientMetadata: validate the
username variable and throw a clear error (or process.exit with a message)
rather than using username!; update the code around the OAuthClient construction
and the call to client.restoreSessionForId(username!) to use the validated
non-null username (and avoid calling passwordLimitedAuthorization with undefined
credentials). Reference: the username variable, OAuthClient constructor, and
restoreSessionForId (and passwordLimitedAuthorization) to locate where to add
the guard and error handling.
packages/api/client/axios/configuration.ts (1)

1-144: ⚠️ Potential issue | 🟡 Minor

Formatting-only changes to an auto-generated file.

This file is marked "auto generated by OpenAPI Generator... Do not edit the class manually." Manual reformatting will be clobbered on the next codegen run unless the generator's formatting options (e.g., Prettier config passed to openapi-generator, or a post-gen pnpm format step) are updated to produce this style. Consider wiring the formatting into the codegen pipeline so the diff is reproducible.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/api/client/axios/configuration.ts` around lines 1 - 144, The diff
shows manual/formatting-only edits to an auto-generated type file (notably the
AWSv4Configuration interface, Configuration class constructor and isJsonMime
method) which will be overwritten by the OpenAPI generator; revert these manual
formatting changes back to the generator's original output (restore the
generated whitespace/ordering) and instead ensure formatting is integrated into
the generation pipeline (e.g., add a post-gen formatting step or pass Prettier
config into the OpenAPI Generator) so future codegen produces consistent,
reproducible formatting and you do not edit Configuration, AWSv4Configuration,
or isJsonMime by hand.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@crates/iracing-data-api-client/Cargo.toml`:
- Around line 4-7: Update the Cargo.toml metadata entries to replace OpenAPI
Generator placeholders: set authors to the actual crate author(s) (replace the
authors = ["OpenAPI Generator team and contributors"] line), provide a concise
project-specific description (replace the generated description string), and
confirm or change the license field from "Unlicense" to the intended license
identifier used across the workspace (update the license = "Unlicense" value);
ensure these edits are made in the Cargo.toml where the authors, description,
and license keys are declared.

In `@crates/iracing-data-api-client/examples/get_member.rs`:
- Around line 9-14: The CLI currently requires a bearer token as a
positional/long arg and derives Debug on Cli, which risks leaking secrets;
change the access_token field in struct Cli to be loaded from a secure source
instead of mandating it on argv (e.g. use clap's env support: keep #[arg(long,
env = "ACCESS_TOKEN")] or remove the arg entirely and read via a password prompt
like rpassword::prompt_password("Access token: ")), and remove Debug from the
derive list (leave only Parser) so the token isn't accidentally logged; keep the
struct name Cli and the access_token field but update attributes and callers to
read from env/prompt rather than command-line.
- Around line 45-64: The example currently uses Configuration::new() which
creates a reqwest::Client with no timeout, so the downstream
configuration.client.get(&response.link).send().await can hang; update the setup
to configure an HTTP timeout by building a reqwest::Client with a timeout and
assigning it to configuration.client (or modify Configuration::new to
accept/construct a Client with a timeout), then proceed to call
member_api::get_member and the subsequent configuration.client.get(...) as
before so all outbound requests use the configured timeout.

In `@crates/iracing-data-api-client/README.md`:
- Around line 19-21: Update the README fenced code blocks to include language
identifiers: annotate the dependency snippet containing iracing-data-api-client
= { path = "./iracing-data-api-client" } with ```toml and annotate the command
snippet containing cargo doc --open with ```bash (also apply the same change to
the other occurrences noted around lines 210-212) so markdown lint MD040 is
satisfied and syntax highlighting works.

In `@dist-workspace.toml`:
- Around line 15-32: The [dist] block in dist-workspace.toml is incorrect for
this repo: remove or revise it; either delete the entire [dist] table (including
targets, cargo-dist-version and installers) if cargo-dist is not being used, or
if you intend to use cargo-dist update cargo-dist-version to "0.31.0", remove
the unsupported "wasm32-unknown-unknown" entry from targets and ensure you only
list crates with [[bin]] targets (the library-only crate iracing-data-api-client
will not produce artifacts), and set installers appropriately; apply the change
to the [dist], targets, cargo-dist-version, and installers entries.

In `@docs/RELEASING.md`:
- Around line 189-193: Update the release docs to document the Rust crate tag
format for the crate named iracing-data-api-client and ensure the
tag-format/release steps explicitly show using a git tag (e.g.,
iracing-data-api-client-v0.0.1) and pushing it before running dist plan
--tag=iracing-data-api-client-v0.0.1; also add a short note in the release flow
clarifying maintainers should not use the npm-style tag format
`@iracing-data/`<package>@<version> for Rust releases so the crate uses the
iracing-data-api-client-v<version> convention.

In `@packages/api/client/axios/package.json`:
- Around line 6-9: Update package.json to replace the generated placeholder
repository.url value ("https://github.com/GIT_USER_ID/GIT_REPO_ID.git") with the
real git URL for this repo and ensure package metadata includes correct package
directory info (e.g., add or correct the "directories" or "repository.directory"
field if you split monorepo packages) so consumers and npm links resolve; modify
the "repository.url" and, if needed, add "repository.directory" or a top-level
"directories" entry to point to the axios client package and keep the existing
"type" key unchanged.

In `@packages/api/client/fetch/package.json`:
- Around line 6-9: The package.json currently contains a placeholder repository
object; replace the generated "repository.url" value
("https://github.com/GIT_USER_ID/GIT_REPO_ID.git") with the real GitHub repo URL
for this project and update any package directory metadata fields so they
reflect the actual package directory (e.g., set the correct "repository.type"
and real URL, and ensure any "directories" or related metadata point to this
package's folder). Locate and edit the "repository" object in package.json (and
any adjacent metadata keys) to restore the accurate repository URL and directory
metadata before publishing.

In `@packages/api/client/fetch/src/apis/AuthApi.ts`:
- Around line 22-23: The request type and caller allow sending an empty auth
body; make PostAuthOperationRequest.post_auth_request required (remove the ? on
post_auth_request) and update the postAuth(...) implementation to stop
defaulting the body to {} — instead validate that post_auth_request is provided
(and has email/password) and throw/return a clear error if missing before
serializing; apply the same change to any other operations in this file (lines
32-60) that similarly default their request bodies to {} so callers cannot POST
/auth with no credentials.

In `@packages/api/client/fetch/src/apis/ConstantsApi.ts`:
- Around line 31-61: The raw response methods (e.g., getConstantsCategoriesRaw)
currently parse responses with IracingAPIResponseFromJSON but the endpoint
returns a direct JSON array; update these methods to return the correct array
type instead of decoding to IracingAPIResponse: modify getConstantsCategoriesRaw
(and the other raw methods referenced around the second and third blocks) so the
runtime.JSONApiResponse parser simply returns the parsed JSON as the expected
typed array (e.g., Array<ConstantCategory> or the generated array type) or
adjust the OpenAPI generator to emit array response types, ensuring
headerParameters/auth logic stays the same but the final JSONApiResponse uses a
parser that preserves the array shape rather than calling
IracingAPIResponseFromJSON.

In `@packages/api/client/fetch/src/apis/HostedApi.ts`:
- Around line 35-39: getHostedCombinedSessionsRaw currently assumes
requestParameters is provided and throws when called without one; default the
optional raw request object to an empty object (e.g. in
getHostedCombinedSessionsRaw signature or immediately inside the function set
requestParameters = requestParameters || {}) so access to optional fields like
package_id is safe, and mirror that same defensive defaulting where
getHostedCombinedSessions calls getHostedCombinedSessionsRaw to ensure both
functions handle undefined request objects gracefully.

In `@packages/api/client/fetch/src/apis/MemberApi.ts`:
- Around line 180-188: The raw API methods (e.g., getMemberAwardsRaw) assume
requestParameters is defined and currently dereference it; change the function
signatures to provide a default empty object for requestParameters (e.g.,
requestParameters: GetMemberAwardsRequest = {}) so callers can omit the
optional-only params; apply the same default to the other raw methods noted
(around the 397-405 block) so all raw wrappers that only use optional query
params safely handle undefined inputs.

In `@packages/api/client/fetch/src/apis/ResultsApi.ts`:
- Around line 382-386: The raw methods getResultsSearchHostedRaw and
getResultsSearchSeriesRaw currently assume requestParameters is defined and
index into it, causing errors when called with no args; change their signatures
to default requestParameters to an empty object (e.g., requestParameters:
GetResultsSearchHostedRequest = {}) and similarly for the Series variant so the
method can safely access properties without throwing, and ensure any internal
usages still read from requestParameters as before.

In `@packages/api/client/fetch/src/apis/SeasonApi.ts`:
- Around line 126-130: The raw API methods (getSeasonRaceGuideRaw,
getSeasonSpectatorSubsessionIdsRaw, getSeasonSpectatorSubsessionIdsDetailRaw)
currently assume requestParameters is defined and will throw if called with no
argument; change each method to default requestParameters to an empty object
(e.g., treat undefined as {}) before reading optional filters (or use a
parameter default) so calling api.getSeasonRaceGuideRaw() works the same as the
wrapper that passes {} — adjust the code that accesses
requestParameters.<seasonId, seriesId, etc.> to use the safe/defaulted
requestParameters (refer to the GetSeasonRaceGuideRequest and related request
types) so no request is attempted before building queryParameters.

In `@README.md`:
- Around line 49-51: The "## Rust" heading in README.md is missing a blank line
before its following list; edit the README and insert a single blank line
immediately after the "## Rust" heading so the list below (the
iracing-data-api-client entry) is separated like the other top-level headings,
resolving the markdownlint MD022 warning for the "## Rust" section.

---

Outside diff comments:
In `@examples/oauth-password-limited/src/index.ts`:
- Around line 281-297: Check and fail fast if process.env.IRACING_AUTH_USERNAME
is missing before using it as the session id or embedding it in OAuthClient
clientMetadata: validate the username variable and throw a clear error (or
process.exit with a message) rather than using username!; update the code around
the OAuthClient construction and the call to
client.restoreSessionForId(username!) to use the validated non-null username
(and avoid calling passwordLimitedAuthorization with undefined credentials).
Reference: the username variable, OAuthClient constructor, and
restoreSessionForId (and passwordLimitedAuthorization) to locate where to add
the guard and error handling.

In `@packages/api/client/axios/configuration.ts`:
- Around line 1-144: The diff shows manual/formatting-only edits to an
auto-generated type file (notably the AWSv4Configuration interface,
Configuration class constructor and isJsonMime method) which will be overwritten
by the OpenAPI generator; revert these manual formatting changes back to the
generator's original output (restore the generated whitespace/ordering) and
instead ensure formatting is integrated into the generation pipeline (e.g., add
a post-gen formatting step or pass Prettier config into the OpenAPI Generator)
so future codegen produces consistent, reproducible formatting and you do not
edit Configuration, AWSv4Configuration, or isJsonMime by hand.
🪄 Autofix (Beta)

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: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 983b30ad-cc12-4c52-93ec-72a0edfb0834

📥 Commits

Reviewing files that changed from the base of the PR and between 199d25a and ab76c64.

⛔ Files ignored due to path filters (2)
  • Cargo.lock is excluded by !**/*.lock
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (56)
  • .cargo/config.toml
  • .gitignore
  • Cargo.toml
  • README.md
  • crates/iracing-data-api-client/.openapi-generator-ignore
  • crates/iracing-data-api-client/.openapi-generator/FILES
  • crates/iracing-data-api-client/Cargo.toml
  • crates/iracing-data-api-client/README.md
  • crates/iracing-data-api-client/examples/get_member.rs
  • dist-workspace.toml
  • docs/RELEASING.md
  • examples/oauth-password-limited/src/index.ts
  • openapi/iracing.json
  • package.json
  • packages/api/client/axios/api.ts
  • packages/api/client/axios/base.ts
  • packages/api/client/axios/common.ts
  • packages/api/client/axios/configuration.ts
  • packages/api/client/axios/index.ts
  • packages/api/client/axios/package.json
  • packages/api/client/fetch/package.json
  • packages/api/client/fetch/src/apis/AuthApi.ts
  • packages/api/client/fetch/src/apis/CarApi.ts
  • packages/api/client/fetch/src/apis/CarclassApi.ts
  • packages/api/client/fetch/src/apis/ConstantsApi.ts
  • packages/api/client/fetch/src/apis/DocApi.ts
  • packages/api/client/fetch/src/apis/DriverStatsApi.ts
  • packages/api/client/fetch/src/apis/HostedApi.ts
  • packages/api/client/fetch/src/apis/LeagueApi.ts
  • packages/api/client/fetch/src/apis/LookupApi.ts
  • packages/api/client/fetch/src/apis/MemberApi.ts
  • packages/api/client/fetch/src/apis/ResultsApi.ts
  • packages/api/client/fetch/src/apis/SeasonApi.ts
  • packages/api/client/fetch/src/apis/SeriesApi.ts
  • packages/api/client/fetch/src/apis/StatsApi.ts
  • packages/api/client/fetch/src/apis/TeamApi.ts
  • packages/api/client/fetch/src/apis/TimeAttackApi.ts
  • packages/api/client/fetch/src/apis/TrackApi.ts
  • packages/api/client/fetch/src/apis/index.ts
  • packages/api/client/fetch/src/index.ts
  • packages/api/client/fetch/src/models/ErrorResponse.ts
  • packages/api/client/fetch/src/models/IracingAPIResponse.ts
  • packages/api/client/fetch/src/models/IracingCategory.ts
  • packages/api/client/fetch/src/models/IracingDivision.ts
  • packages/api/client/fetch/src/models/IracingEventType.ts
  • packages/api/client/fetch/src/models/IracingServiceMethodDocs.ts
  • packages/api/client/fetch/src/models/IracingServiceMethodParametersDocs.ts
  • packages/api/client/fetch/src/models/PostAuthRequest.ts
  • packages/api/client/fetch/src/models/index.ts
  • packages/api/client/fetch/src/runtime.ts
  • rustfmt.toml
  • scripts/openapi-generator-axios.sh
  • scripts/openapi-generator-fetch.sh
  • scripts/openapi-generator-rust-post-process.sh
  • scripts/openapi-generator-rust.sh
  • scripts/openapi-generator-ts-post-process.sh

Comment on lines +4 to +7
authors = ["OpenAPI Generator team and contributors"]
description = "No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)"
# Override this license by providing a License Object in the OpenAPI.
license = "Unlicense"
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Consider replacing the generator placeholder package metadata.

authors and description still carry the OpenAPI Generator defaults. If there's any intent to publish this crate (or even just to make cargo doc/crates.io searches meaningful), set a project-specific description and author(s), and consider whether Unlicense is really the intended license for a crate in this repo (the rest of the workspace may use a different license).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/iracing-data-api-client/Cargo.toml` around lines 4 - 7, Update the
Cargo.toml metadata entries to replace OpenAPI Generator placeholders: set
authors to the actual crate author(s) (replace the authors = ["OpenAPI Generator
team and contributors"] line), provide a concise project-specific description
(replace the generated description string), and confirm or change the license
field from "Unlicense" to the intended license identifier used across the
workspace (update the license = "Unlicense" value); ensure these edits are made
in the Cargo.toml where the authors, description, and license keys are declared.

Comment on lines +9 to +14
#[derive(Debug, Parser)]
#[command(author, version, about = "Fetch iRacing member data for customer IDs")]
struct Cli {
/// Bearer access token used to sign the request.
#[arg(long)]
access_token: String,
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Avoid requiring the access token in argv.

Line 14 puts a bearer token in command-line arguments, which can leak via shell history, process listings, and CI logs. Also avoid deriving Debug for a struct containing secrets.

🛡️ Proposed safer token handling
-#[derive(Debug, Parser)]
+#[derive(Parser)]
 #[command(author, version, about = "Fetch iRacing member data for customer IDs")]
 struct Cli {
-    /// Bearer access token used to sign the request.
+    /// Bearer access token used to sign the request.
+    ///
+    /// Prefer setting IRACING_ACCESS_TOKEN to avoid exposing secrets in argv.
     #[arg(long)]
-    access_token: String,
+    access_token: Option<String>,
-    let cli = Cli::parse();
-    let cust_ids = normalize_customer_ids(&cli.customer_ids)?;
+    let Cli {
+        access_token,
+        customer_ids,
+        include_licenses,
+    } = Cli::parse();
+    let cust_ids = normalize_customer_ids(&customer_ids)?;
+    let access_token = access_token
+        .or_else(|| std::env::var("IRACING_ACCESS_TOKEN").ok())
+        .ok_or("provide --access-token or set IRACING_ACCESS_TOKEN")?;
 
     let mut configuration = Configuration::new();
-    configuration.bearer_access_token = Some(cli.access_token);
+    configuration.bearer_access_token = Some(access_token);
-            include_licenses: cli.include_licenses.then_some(true),
+            include_licenses: include_licenses.then_some(true),
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/iracing-data-api-client/examples/get_member.rs` around lines 9 - 14,
The CLI currently requires a bearer token as a positional/long arg and derives
Debug on Cli, which risks leaking secrets; change the access_token field in
struct Cli to be loaded from a secure source instead of mandating it on argv
(e.g. use clap's env support: keep #[arg(long, env = "ACCESS_TOKEN")] or remove
the arg entirely and read via a password prompt like
rpassword::prompt_password("Access token: ")), and remove Debug from the derive
list (leave only Parser) so the token isn't accidentally logged; keep the struct
name Cli and the access_token field but update attributes and callers to read
from env/prompt rather than command-line.

Comment on lines +45 to +64
let mut configuration = Configuration::new();
configuration.bearer_access_token = Some(cli.access_token);

let response = member_api::get_member(
&configuration,
GetMemberParams {
cust_ids,
include_licenses: cli.include_licenses.then_some(true),
},
)
.await?;

let data_text = configuration
.client
.get(&response.link)
.send()
.await?
.error_for_status()?
.text()
.await?;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Inspect reqwest client construction and timeout usage.
# Expectation after the fix: client construction or request builders include explicit timeout configuration.

rg -n -C3 'Client::new|Client::builder|\.timeout\s*\(' --iglob '*.rs'

Repository: racedirector/iracing-data-api

Length of output: 808


🏁 Script executed:

#!/bin/bash
# Get more details about Configuration struct and default implementation
echo "=== Configuration struct definition ==="
cat -n crates/iracing-data-api-client/src/apis/configuration.rs | head -60

echo -e "\n=== Check for any timeout in Configuration ==="
rg -n 'timeout|Duration' crates/iracing-data-api-client/src/apis/configuration.rs

echo -e "\n=== Check Cargo.toml for reqwest version ==="
rg -n 'reqwest' crates/iracing-data-api-client/Cargo.toml

Repository: racedirector/iracing-data-api

Length of output: 1950


🏁 Script executed:

#!/bin/bash
# Check if get_member.rs or related code implements any timeout mechanisms
echo "=== Check get_member.rs for timeout config ==="
cat -n crates/iracing-data-api-client/examples/get_member.rs | sed -n '40,70p'

echo -e "\n=== Search for any timeout in the entire example ==="
rg -n 'timeout|Duration' crates/iracing-data-api-client/examples/get_member.rs

echo -e "\n=== Check if reqwest is used elsewhere with timeout ==="
rg -B5 -A5 '\.timeout\(' crates/iracing-data-api-client/examples/ 2>/dev/null || echo "No timeout usage found in examples"

Repository: racedirector/iracing-data-api

Length of output: 1324


🌐 Web query:

reqwest 0.12 Client::new() default timeout behavior

💡 Result:

In reqwest 0.12, Client::new creates a Client with no default timeout. Requests made with this client will not time out unless a timeout is explicitly set on the Client via ClientBuilder::timeout or on individual requests via RequestBuilder::timeout.

Citations:


Configure an HTTP timeout before making outbound requests.

Configuration::default() uses reqwest::Client::new() per crates/iracing-data-api-client/src/apis/configuration.rs:39-50, so these awaits can hang indefinitely if either endpoint stalls. reqwest 0.12 provides no default timeout, requiring explicit configuration.

⏱️ Proposed timeout configuration
     let mut configuration = Configuration::new();
+    configuration.client = reqwest::Client::builder()
+        .timeout(std::time::Duration::from_secs(30))
+        .build()?;
     configuration.bearer_access_token = Some(cli.access_token);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
let mut configuration = Configuration::new();
configuration.bearer_access_token = Some(cli.access_token);
let response = member_api::get_member(
&configuration,
GetMemberParams {
cust_ids,
include_licenses: cli.include_licenses.then_some(true),
},
)
.await?;
let data_text = configuration
.client
.get(&response.link)
.send()
.await?
.error_for_status()?
.text()
.await?;
let mut configuration = Configuration::new();
configuration.client = reqwest::Client::builder()
.timeout(std::time::Duration::from_secs(30))
.build()?;
configuration.bearer_access_token = Some(cli.access_token);
let response = member_api::get_member(
&configuration,
GetMemberParams {
cust_ids,
include_licenses: cli.include_licenses.then_some(true),
},
)
.await?;
let data_text = configuration
.client
.get(&response.link)
.send()
.await?
.error_for_status()?
.text()
.await?;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/iracing-data-api-client/examples/get_member.rs` around lines 45 - 64,
The example currently uses Configuration::new() which creates a reqwest::Client
with no timeout, so the downstream
configuration.client.get(&response.link).send().await can hang; update the setup
to configure an HTTP timeout by building a reqwest::Client with a timeout and
assigning it to configuration.client (or modify Configuration::new to
accept/construct a Client with a timeout), then proceed to call
member_api::get_member and the subsequent configuration.client.get(...) as
before so all outbound requests use the configured timeout.

Comment on lines +19 to +21
```
iracing-data-api-client = { path = "./iracing-data-api-client" }
```
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Add language tags to fenced code blocks (MD040).

Both code fences wrap snippets with well-known languages and can be annotated to improve rendering/linting; this is a cheap post-generation fix.

📝 Proposed fix
-```
+```toml
 iracing-data-api-client = { path = "./iracing-data-api-client" }

```diff
-```
+```bash
 cargo doc --open

</details>




Also applies to: 210-212

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 markdownlint-cli2 (0.22.0)</summary>

[warning] 19-19: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

</details>

</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @crates/iracing-data-api-client/README.md around lines 19 - 21, Update the
README fenced code blocks to include language identifiers: annotate the
dependency snippet containing iracing-data-api-client = { path =
"./iracing-data-api-client" } with toml and annotate the command snippet containing cargo doc --open with bash (also apply the same change to the
other occurrences noted around lines 210-212) so markdown lint MD040 is
satisfied and syntax highlighting works.


</details>

<!-- fingerprinting:phantom:medusa:nectarine:d5f3d9ec-404e-4dd8-ab19-83f9765941c3 -->

<!-- This is an auto-generated comment by CodeRabbit -->

Comment thread dist-workspace.toml
Comment on lines +15 to +32
# Config for 'dist'
[dist]
# Target platforms to build apps for (Rust target-triple syntax)
targets = [
"aarch64-apple-darwin",
"x86_64-apple-darwin",
"aarch64-pc-windows-msvc",
"x86_64-pc-windows-msvc",
"aarch64-unknown-linux-gnu",
"x86_64-unknown-linux-gnu",
"aarch64-unknown-linux-musl",
"x86_64-unknown-linux-musl",
"wasm32-unknown-unknown",
]
# The preferred dist version to use in CI (Cargo.toml SemVer syntax)
cargo-dist-version = "0.30.4"
# The installers to generate for each app
installers = []
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Confirm the crate has no [[bin]] targets (i.e., it's library-only)
fd -t f 'Cargo.toml' crates/
echo '---'
fd -t f 'Cargo.toml' crates/ --exec cat {}
echo '---'
# Look for any release workflow that consumes dist-workspace.toml
fd -t f -e yml -e yaml . .github/workflows/ 2>/dev/null | xargs -I {} sh -c 'echo "=== {} ==="; cat {}'

Repository: racedirector/iracing-data-api

Length of output: 6908


🌐 Web query:

Does cargo-dist (dist) 0.30.4 support wasm32-unknown-unknown as a target triple, and what is the latest stable version of dist/cargo-dist?

💡 Result:

No, cargo-dist (dist) 0.30.4 does not support wasm32-unknown-unknown as a target triple. The latest stable version of dist/cargo-dist is 0.31.0.

Citations:


Remove the [dist] block or reconsider its purpose.

This dist-workspace.toml configuration has several issues:

  1. wasm32-unknown-unknown is unsupported by cargo-dist 0.30.4 (and earlier versions). This target produces .wasm modules, not executables, and will fail during CI when the dist workflow runs. If you need to distribute a Wasm artifact, use a separate tool like wasm-pack.

  2. iracing-data-api-client is a library-only crate with no [[bin]] targets and installers = []. cargo-dist is designed to package binaries; this configuration will produce no release artifacts.

  3. The actual release workflow (release.yml) is npm-based (pnpm/Node.js) and does not use cargo-dist or this configuration file at all. If the intent is to publish the Rust library to crates.io, the [dist] block is unnecessary—standard cargo publish suffices.

If cargo-dist is meant to be used here, clarify the intent with the team. Otherwise, remove this [dist] block to avoid confusing future maintainers. If you do keep it, upgrade to the latest cargo-dist-version = "0.31.0" and remove the unsupported wasm32-unknown-unknown target.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@dist-workspace.toml` around lines 15 - 32, The [dist] block in
dist-workspace.toml is incorrect for this repo: remove or revise it; either
delete the entire [dist] table (including targets, cargo-dist-version and
installers) if cargo-dist is not being used, or if you intend to use cargo-dist
update cargo-dist-version to "0.31.0", remove the unsupported
"wasm32-unknown-unknown" entry from targets and ensure you only list crates with
[[bin]] targets (the library-only crate iracing-data-api-client will not produce
artifacts), and set installers appropriately; apply the change to the [dist],
targets, cargo-dist-version, and installers entries.

Comment on lines +35 to +39
async getHostedCombinedSessionsRaw(
requestParameters: GetHostedCombinedSessionsRequest,
initOverrides?: RequestInit | runtime.InitOverrideFunction,
): Promise<runtime.ApiResponse<IracingAPIResponse>> {
const queryParameters: any = {};
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Default the optional raw request object.

package_id is optional and the wrapper supports getHostedCombinedSessions(), but getHostedCombinedSessionsRaw() throws if called without a request object.

🐛 Proposed fix
   async getHostedCombinedSessionsRaw(
-    requestParameters: GetHostedCombinedSessionsRequest,
+    requestParameters: GetHostedCombinedSessionsRequest = {},
     initOverrides?: RequestInit | runtime.InitOverrideFunction,
   ): Promise<runtime.ApiResponse<IracingAPIResponse>> {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/api/client/fetch/src/apis/HostedApi.ts` around lines 35 - 39,
getHostedCombinedSessionsRaw currently assumes requestParameters is provided and
throws when called without one; default the optional raw request object to an
empty object (e.g. in getHostedCombinedSessionsRaw signature or immediately
inside the function set requestParameters = requestParameters || {}) so access
to optional fields like package_id is safe, and mirror that same defensive
defaulting where getHostedCombinedSessions calls getHostedCombinedSessionsRaw to
ensure both functions handle undefined request objects gracefully.

Comment on lines +180 to +188
async getMemberAwardsRaw(
requestParameters: GetMemberAwardsRequest,
initOverrides?: RequestInit | runtime.InitOverrideFunction,
): Promise<runtime.ApiResponse<IracingAPIResponse>> {
const queryParameters: any = {};

if (requestParameters["cust_id"] != null) {
queryParameters["cust_id"] = requestParameters["cust_id"];
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Default optional-only raw request objects to {}.

Both raw methods expose only optional query parameters, but calling them without an object currently dereferences undefined. Match the wrapper behavior so raw consumers can omit optional params safely.

Proposed fix
   async getMemberAwardsRaw(
-    requestParameters: GetMemberAwardsRequest,
+    requestParameters: GetMemberAwardsRequest = {},
     initOverrides?: RequestInit | runtime.InitOverrideFunction,
   ): Promise<runtime.ApiResponse<IracingAPIResponse>> {
@@
   async getMemberProfileRaw(
-    requestParameters: GetMemberProfileRequest,
+    requestParameters: GetMemberProfileRequest = {},
     initOverrides?: RequestInit | runtime.InitOverrideFunction,
   ): Promise<runtime.ApiResponse<IracingAPIResponse>> {

Also applies to: 397-405

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/api/client/fetch/src/apis/MemberApi.ts` around lines 180 - 188, The
raw API methods (e.g., getMemberAwardsRaw) assume requestParameters is defined
and currently dereference it; change the function signatures to provide a
default empty object for requestParameters (e.g., requestParameters:
GetMemberAwardsRequest = {}) so callers can omit the optional-only params; apply
the same default to the other raw methods noted (around the 397-405 block) so
all raw wrappers that only use optional query params safely handle undefined
inputs.

Comment on lines +382 to +386
async getResultsSearchHostedRaw(
requestParameters: GetResultsSearchHostedRequest,
initOverrides?: RequestInit | runtime.InitOverrideFunction,
): Promise<runtime.ApiResponse<IracingAPIResponse>> {
const queryParameters: any = {};
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Default all-optional raw request objects to {}.

getResultsSearchHostedRaw() and getResultsSearchSeriesRaw() are public, but calling either without filters throws before the request because requestParameters is indexed while undefined. The non-raw wrappers already support no-arg calls, so keep the raw methods consistent.

🐛 Proposed fix
   async getResultsSearchHostedRaw(
-    requestParameters: GetResultsSearchHostedRequest,
+    requestParameters: GetResultsSearchHostedRequest = {},
     initOverrides?: RequestInit | runtime.InitOverrideFunction,
   ): Promise<runtime.ApiResponse<IracingAPIResponse>> {
@@
   async getResultsSearchSeriesRaw(
-    requestParameters: GetResultsSearchSeriesRequest,
+    requestParameters: GetResultsSearchSeriesRequest = {},
     initOverrides?: RequestInit | runtime.InitOverrideFunction,
   ): Promise<runtime.ApiResponse<IracingAPIResponse>> {

Also applies to: 487-491

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/api/client/fetch/src/apis/ResultsApi.ts` around lines 382 - 386, The
raw methods getResultsSearchHostedRaw and getResultsSearchSeriesRaw currently
assume requestParameters is defined and index into it, causing errors when
called with no args; change their signatures to default requestParameters to an
empty object (e.g., requestParameters: GetResultsSearchHostedRequest = {}) and
similarly for the Series variant so the method can safely access properties
without throwing, and ensure any internal usages still read from
requestParameters as before.

Comment on lines +126 to +130
async getSeasonRaceGuideRaw(
requestParameters: GetSeasonRaceGuideRequest,
initOverrides?: RequestInit | runtime.InitOverrideFunction,
): Promise<runtime.ApiResponse<IracingAPIResponse>> {
const queryParameters: any = {};
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Keep raw methods callable without optional filters.

These request types only contain optional filters, and the wrapper methods default to {}. The raw variants should do the same; otherwise api.getSeasonRaceGuideRaw(), api.getSeasonSpectatorSubsessionIdsRaw(), and api.getSeasonSpectatorSubsessionIdsDetailRaw() throw before making a request.

🐛 Proposed fix
   async getSeasonRaceGuideRaw(
-    requestParameters: GetSeasonRaceGuideRequest,
+    requestParameters: GetSeasonRaceGuideRequest = {},
     initOverrides?: RequestInit | runtime.InitOverrideFunction,
   ): Promise<runtime.ApiResponse<IracingAPIResponse>> {
@@
   async getSeasonSpectatorSubsessionIdsRaw(
-    requestParameters: GetSeasonSpectatorSubsessionIdsRequest,
+    requestParameters: GetSeasonSpectatorSubsessionIdsRequest = {},
     initOverrides?: RequestInit | runtime.InitOverrideFunction,
   ): Promise<runtime.ApiResponse<IracingAPIResponse>> {
@@
   async getSeasonSpectatorSubsessionIdsDetailRaw(
-    requestParameters: GetSeasonSpectatorSubsessionIdsDetailRequest,
+    requestParameters: GetSeasonSpectatorSubsessionIdsDetailRequest = {},
     initOverrides?: RequestInit | runtime.InitOverrideFunction,
   ): Promise<runtime.ApiResponse<IracingAPIResponse>> {

Also applies to: 184-188, 237-241

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/api/client/fetch/src/apis/SeasonApi.ts` around lines 126 - 130, The
raw API methods (getSeasonRaceGuideRaw, getSeasonSpectatorSubsessionIdsRaw,
getSeasonSpectatorSubsessionIdsDetailRaw) currently assume requestParameters is
defined and will throw if called with no argument; change each method to default
requestParameters to an empty object (e.g., treat undefined as {}) before
reading optional filters (or use a parameter default) so calling
api.getSeasonRaceGuideRaw() works the same as the wrapper that passes {} —
adjust the code that accesses requestParameters.<seasonId, seriesId, etc.> to
use the safe/defaulted requestParameters (refer to the GetSeasonRaceGuideRequest
and related request types) so no request is attempted before building
queryParameters.

Comment thread README.md
Comment on lines +49 to +51
## Rust
- [iracing-data-api-client](crates/iracing-data-api-client/README.md) – Generated Rust client for the iRacing `/data` API. Use `cargo get-member --access-token "$IRACING_ACCESS_TOKEN" --customer-ids 378767 --include-licenses` to run the member lookup example.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Add a blank line after the ## Rust heading for consistency with other top-level sections.

markdownlint (MD022) flags this because, unlike ## Packages, ## Apps, and ## Development, the new ## Rust heading is not separated from its list by a blank line.

📝 Proposed fix
 ## Rust
+
 - [iracing-data-api-client](crates/iracing-data-api-client/README.md) – Generated Rust client for the iRacing `/data` API. Use `cargo get-member --access-token "$IRACING_ACCESS_TOKEN" --customer-ids 378767 --include-licenses` to run the member lookup example.
🧰 Tools
🪛 markdownlint-cli2 (0.22.0)

[warning] 49-49: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@README.md` around lines 49 - 51, The "## Rust" heading in README.md is
missing a blank line before its following list; edit the README and insert a
single blank line immediately after the "## Rust" heading so the list below (the
iracing-data-api-client entry) is separated like the other top-level headings,
resolving the markdownlint MD022 warning for the "## Rust" section.

@justinmakaila justinmakaila merged commit d0e6dc2 into main Apr 21, 2026
5 checks passed
@justinmakaila justinmakaila deleted the feature/rust-client branch April 21, 2026 16:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant