fix: correct futures latest/curve paths (404) + live CI tests (v0.9.1)#20
Conversation
The futures `latest` endpoint is served from the bare slug path
`GET /v1/futures/{slug}` (no `/latest` suffix). The published v0.9.0 SDK
built `/v1/futures/{slug}/latest`, which 404s.
Fixes:
- FuturesContractFamily.latest() now hits `/v1/futures/{slug}` instead of
`/v1/futures/{slug}/latest`. This corrects all typed helpers
(`.brent().latest()`, `.gasoil().latest()`, etc.).
- Top-level `client.futures.latest(code)` now resolves a contract code or
family slug to its slug and hits `/v1/futures/{slug}`. Previously it
passed the raw code (e.g. "BZ") straight into the path -> 404.
- Added `resolveFuturesFamilySlug()` + a `QS` alias for ICE Gasoil.
Code -> slug: BZ->ice-brent, CL->ice-wti, G/QS->ice-gasoil,
NG->natural-gas, TTF->ttf-gas, JKM->lng-jkm, EUA->eua-carbon,
UKA->uk-carbon.
- Updated doc comments that wrongly claimed families support `/latest`.
curve/historical/ohlc/intraday/spreads/spread-history family paths were
already correct and are unchanged.
Tests + CI:
- New live test (tests/live/futures.test.ts) hits the REAL API via
OILPRICEAPI_TEST_KEY and asserts brent().latest() + top-level latest()
return 200 + a sane price. Skips gracefully when the key is absent;
spaces requests to respect the 1 req/sec limit.
- New live-tests.yml workflow runs `npm run test:live` on push/PR to main,
gated on the OILPRICEAPI_TEST_KEY secret so forks never fail.
- Updated unit tests to assert the corrected paths + code->slug mapping.
Bumped 0.9.0 -> 0.9.1.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Warning Review limit reached
More reviews will be available in 29 minutes and 57 seconds. Learn how PR review limits work. Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file). ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits. 🚦 How do rate limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, the refill rate gradually slows as usage increases. The highest same-day bursts are limited more strictly. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (7)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…a (v0.9.1)
GET /v1/futures/{slug} returns a TOP-LEVEL object (no {status,data}
envelope); the latest price lives at front_month.last_price with the
full term structure in contracts[]. The FuturesPrice type modeled a
flat {contract, price, currency} shape that did not match reality, so
the LIVE CI test failed even though request()'s as-is fallback already
returned the real object.
- FuturesPrice: model real top-level shape (commodity, source,
updated_at, settlement_date, front_month, contracts[], metadata).
Legacy flat fields kept optional for backward compatibility.
- Add FuturesContractMonth interface (code, contract_month, last_price,
currency, open/close/high/low).
- FuturesCurveData: make `curve` optional and add `error`/`date` so the
documented no-data response ({error:"No futures data available for
curve analysis", date}) is a valid, typed state rather than a failure.
- Live test: assert front_month.last_price is a sane number; make
curve() tolerant of EITHER curve data OR the no-data response. Kept to
3 calls spaced >=1.1s.
- Mock unit tests: latest() now uses the real top-level shape; added a
curve() no-data case.
Gates: tsc --noEmit clean, 400 tests pass, build OK, lint 0 errors.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ence) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The path bug
The published v0.9.0 SDK builds the wrong URL for futures
latest:FuturesContractFamily.latest()(e.g.client.futures.brent().latest()) built/v1/futures/{slug}/latest→ 404.client.futures.latest(code)passed the raw contract code (e.g."BZ") straight into the path →/v1/futures/BZ→ 404 (the API routes are slug-based, not code-based).The correct futures API (confirmed live + against
config/routes.rblines ~377-452 andapp/controllers/v1/futures_controller.rb):GET /v1/futures/{slug}— the bare slug, NO/latestsuffix.curve=/v1/futures/{slug}/curve;historical/ohlc/intraday/spreads/spread-history=/{slug}/...— these family paths were already correct and are unchanged./v1/futures/latest?contract=route.Valid slugs:
ice-brent, ice-wti, ice-gasoil, natural-gas, ttf-gas, lng-jkm, eua-carbon, uk-carbon(+continuous/brent,continuous/wti).The fix
FuturesContractFamily.latest()→ now hits/v1/futures/{slug}. Corrects all typed helpers (.brent(),.wti(),.gasoil(),.naturalGas(),.ttfGas(),.lngJkm(),.euaCarbon(),.ukCarbon()).client.futures.latest(contract)→ resolves a contract code or a family slug to the slug, then hits/v1/futures/{slug}. Throws a clearValidationErrorfor unknown inputs.resolveFuturesFamilySlug()and aQSalias for ICE Gasoil./latest.Code → slug mapping
BZice-brentCLice-wtiG/QSice-gasoilNGnatural-gasTTFttf-gasJKMlng-jkmEUAeua-carbonUKAuk-carbon(Family slugs are also accepted directly, case-insensitively.)
Live CI tests
tests/live/futures.test.ts— hits the REAL API usingprocess.env.OILPRICEAPI_TEST_KEYand assertsclient.futures.brent().latest()and the top-levelclient.futures.latest('BZ' / 'CL')return 200 + a sane price shape. Skips gracefully when the key env is absent (offline / forks). Requests are spaced (~1.1s) to respect the 1 req/sec rate limit, kept to a handful of calls to avoid 429s..github/workflows/live-tests.yml— new job runsnpm run test:liveon push/PR tomainwithOILPRICEAPI_TEST_KEY: ${{ secrets.OILPRICEAPI_TEST_KEY }}. Gated so it only runs the live step when the secret is present (if: ${{ secrets.OILPRICEAPI_TEST_KEY != '' }}) and the job is skipped for external-fork PRs, so forks are never blocked.Version
Bumped
package.json+src/version.ts0.9.0 → 0.9.1.Gates
npx tsc --noEmit— cleannpm test— 399 passing (offline unit suite)npm run build— cleannpm run lint— 0 errors (pre-existing warnings only, none in changed files)npm run test:live— skips gracefully locally (no key); will run against prod in CI via the secret🤖 Generated with Claude Code