Skip to content

Latest commit

 

History

History
540 lines (387 loc) · 25.9 KB

CHANGELOG.md

File metadata and controls

540 lines (387 loc) · 25.9 KB

Changelog

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

[2.1.0] - 2026-10-03

Four methods called routes the API has never served, so every call returned HTTP 404 (#125). They now reject immediately with OilPriceAPIError code ENDPOINT_NOT_AVAILABLE, name the supported alternative, and make no request. They are deprecated and will be removed in the next major.

Deprecated

  • client.drilling.trends(): no trends endpoint exists. Use summary(), or completions() / wellsDrilled() / ducWells() for basin-level series.
  • client.drilling.basin(name): no per-basin endpoint exists. Read the by_basin maps from completions(), wellsDrilled(), ducWells() or fracSpreads().
  • client.futures.spreads(contract1, contract2): no arbitrary two-contract spread endpoint exists. Use client.futures.family(slug).spreads(), e.g. client.futures.brent().spreads().
  • client.futures.continuous(contract, months): no per-contract continuous endpoint exists. Use continuousFrontMonth().

Added

  • client.futures.continuousFrontMonth("brent" | "wti") for GET /v1/futures/continuous/{family}, returning ContinuousFrontMonth.
  • tests/api-path-contract.test.ts, which fails CI when any SDK path is missing from a snapshot of the API's routes. Refresh the snapshot with scripts/refresh-api-paths.mjs.

Security

  • Dev-only lockfile updates: fast-uri 3.1.8 (GHSA-hrr3-gc8f-f4qj) and markdown-it 14.3.2 (GHSA-253c-mchw-3w2r).

[2.0.0] - 2026-09-14

A major release: several resources were typed and called in ways production never supported. The changes below are breaking at compile time or runtime, and in nearly every case the old call could not work correctly against the live API.

Breaking changes

Spreads (client.spreads) (#112)

  • Removed get(type), historical(type, options) and all(type). They could not send the parameters the routes require; use the named methods.
  • basis(pair) and curveStructure(commodity) now require their argument.
  • crack({ type, crude }), margin({ index }) and physicalPremium({ commodity }) take an options object and return CrackSpread, RefineryMargin and PhysicalPremium with the field names the API sends (spread_type, margin_usd_bbl, premium_pct).
  • SpreadValue, HistoricalSpreadValue, HistoricalSpreadOptions and SpreadType are deprecated.

Indicators (client.indicators) (#112)

  • Removed get(type), congressionalTrades() and CongressionalTradeIndicator. The route has never returned data.
  • priceContext(code, { relatedSpreads }) and annotations(code) now require code. annotations returns a MarketAnnotations object instead of an array.
  • cftcPositioning({ commodity }) returns one CftcPositioning object; the list is cftcPositioningAll().
  • fuelSwitching() and storageAnalytics() return FuelSwitching and StorageAnalytics.
  • Deprecated aliases: FuelSwitchingIndicator, PriceContextIndicator, StorageAnalyticsIndicator, AnnotationIndicator (now a single annotation) and CFTCPositioningIndicator. IndicatorType no longer includes "congressional-trades".

Rig counts (client.rigCounts) (#108)

  • latest() returns RigCountObservation, with the value in count. total, oil, gas, misc, timestamp and change are gone because no route sends them; use client.ei.rigCounts for the oil/gas split. RigCountData is a deprecated alias.
  • current() returns CurrentRigCounts.
  • historical() returns the page envelope RigCountsPage. It previously returned undefined.
  • trends() rejects periods the route does not honour (week, month, quarter, year) with ValidationError.

Energy Intelligence (client.ei) (#104, #105)

  • Rig-count reports: list() returns RigCountReportSummary[]; latest() and get(id) return RigCountReport with totals under us_total. RigCountRecord is a deprecated alias.
  • The six by* methods on wellPermits and fracFocus now require their filter, throw ValidationError before sending when it is missing, and return the records together with pagination meta instead of a bare array.

Subscriptions (#78)

  • subscriptions.list() throws unexpected_response_shape instead of resolving [] when the response has no subscriptions array, so [] now only ever means the API sent an empty list. create() likewise throws on a body it cannot map.

Published types (#94)

  • Types describe the payloads production returns. CategoriesResponse changed shape, so code reading categories.oil no longer compiles (it could not work at runtime). Commodity.category is optional.

Errors (#111, #117)

  • For { status: "fail", data: { ... } } responses, error.message now carries the API's reason, and a snake-case data.error (VALIDATION_ERROR, invalid_code, no_price_data) becomes error.code. Code that branched on "HTTP_ERROR" for these responses should branch on the specific code. error.code is no longer undefined when the body carries none.

Base URL (#89)

  • A baseUrl containing a query string or fragment now throws at construction, and the base path is pinned.

Unmappable responses

  • Across rig counts, spreads, indicators, Energy Intelligence and subscriptions, a 200 whose body cannot be mapped raises OilPriceAPIError with code: "unexpected_response_shape" instead of returning an object with missing fields.

Added

  • Spreads: crackHistorical, crackAll, gasoilCrack, basisHistorical, basisAll, curveStructureAll, marginHistorical, marginAll, physicalPremiumHistorical and physicalPremiumAll (#112).
  • Indicators: fuelSwitchingHistorical, storageAnalyticsAll, annotationsBatch (up to ANNOTATIONS_BATCH_MAX_CODES, 20 codes), cftcPositioningHistorical and cftcPositioningAll (#112).
  • Subscriptions: get, update, pause and resume (#78).
  • Fuel surcharge: typed LTL and parcel clients (#79).
  • Rig counts: latest({ code }), historical({ period, page, perPage, code }) and trends({ period, region }) (#108).

Fixed

  • The request timeout stays armed until the response body has been read (#81).
  • Pagination no longer stops at the server's 500-row page cap (#90).
  • Caller-supplied ids are encoded into a single path segment (#92).
  • The streaming client no longer terminates its host process on a socket error, ends a permanently rejected stream, and bounds setup (#91, #84).
  • CommonJS consumers get .d.cts declarations, and @types/ws and @types/node are runtime dependencies (#93).
  • Energy Intelligence methods no longer return undefined after double unwrapping (#83).

[1.3.0] - 2026-09-13

Security

  • Raw paths can no longer change the authenticated API origin (#87). A bare relative path was the worst form: v1/prices produced the host api.oilpriceapi.comv1 — it looks like an ordinary path and silently became a foreign hostname carrying the API key. Userinfo append (@fixture.invalid), host-suffix append (.fixture.invalid -> api.oilpriceapi.com.fixture.invalid), a bare port (:8443) and scheme prefixes all reached hosts that were not ours. 14 attack forms and 3 legitimate forms are asserted against the real outbound fetch.

Changed

  • Breaking: non-idempotent writes are no longer replayed (#88). POST was retried 4x on timeout, 4x on 503 and 4x on a malformed 200; PATCH 4x on 502.
  • Breaking: retries: -1 now throws at construction instead of failing later with "Unknown error occurred".

Fixed

  • Durable quota exhaustion is no longer retried — it was retried 4x, sleeping 3 x 3,600,000 ms. Detection reads X-RateLimit-State and the counter names, verified against the API's base_controller.rb, not guessed from prose.
  • Retry-After: 86400 no longer sleeps 86,400,000 ms, and a body retry_after: -30 no longer sleeps -30,000 ms.
  • retryDelay: 0 is honoured instead of silently becoming 1000 ms.

[1.2.6] - 2026-08-12

Fixed

  • Scan every customer-readable file in the exact packed npm distribution, regardless of filename suffix, so future text, Markdown, source-map, or extensionless package data cannot bypass the storefront claim contract. Binary package data remains excluded from text parsing.

[1.2.5] - 2026-08-12

Fixed

  • Remove the nonexistent telemetry request-bonus claim from authored and generated package surfaces. The recursive storefront guard now rejects equivalent telemetry or app-metadata quota rewards in both source and the exact packed npm artifact.

[1.2.4] - 2026-08-11

Fixed

  • Remove the stale monthly quota assumption from customer recovery copy and reject fixed daily, weekly, monthly, or yearly quota-window claims even when they do not contain a numeric allowance. Quota recovery now follows the live API response and reviewed product facts.

[1.2.3] - 2026-08-11

Fixed

  • Resolve npm publication state from typed registry responses so only an exact HTTP 404 permits first publication, while mismatched metadata, malformed responses, server errors, and network failures stop the release.
  • Verify both the exact public version and the latest tag against the checksummed tarball before completing the release.

[1.2.2] - 2026-08-11

Added

  • Document a coverage-gated permit-to-production flow using live permit search results and per-well monthly production history.
  • Add well-permit, drilling-data, and oil-well-production discovery keywords.

Fixed

  • Route futures contract codes and named helpers through instrument-generic Brent, WTI, Gasoil, and EU-carbon paths while retaining explicit legacy slugs as backward-compatible inputs.
  • Unwrap the production { well_permits, meta } search envelope through the new searchLatest() method while preserving the existing search() return type.

[1.2.1] - 2026-08-11

Fixed

  • Remove stale plan-price, quota-exemption, cadence, cost-comparison, and generic real-time claims from generated docs and published package comments.
  • Discover authored docs and package source recursively, then validate the exact packed npm artifact so a generated declaration cannot bypass the reviewed product-claim contract.

[1.2.0] - 2026-08-11

Added

  • Allow clients without credentials to call the public demo price and commodity methods without sending an Authorization header.
  • Export normalized authentication, authorization, validation, rate-limit, quota, server, and timeout error classes with stable recovery metadata.

Fixed

  • Fail authenticated HTTP and streaming calls locally with MISSING_API_KEY instead of constructing an invalid request.
  • Validate the dynamic demo catalogue by contract and make production 429s fail the live release gate rather than silently skipping the check.
  • Update runtime, build, lint, type, and GitHub Actions dependencies and resolve all known npm audit findings at release time.

[1.1.0] - 2026-07-19

Changed

  • Replaced the npm storefront with reviewed source-timestamped wording and removed unsupported fixed catalog, traffic, cadence, and entitlement claims.
  • Made the canonical first-request snippet fail closed unless symbol, numeric value, currency, unit, source, and an exact API timestamp field are present.
  • Added the source-context response fields to the public Price type and a CI storefront claim guard.

[1.0.2] - 2026-07-10

Changed

  • Loosen source typing and align examples with the API's masked source labels: the response source now returns market_reporting for non-government series (government labels like EIA/opec.org are unchanged). The FuturesPrice.source field remains a free string (no venue enum); doc-comment and test fixture examples no longer use venue names such as ICE. See oilpriceapi-api#4175.

[1.0.1] - 2026-07-03

Changed

  • docs: registry storefront README — hero, "What can you get?" commodity table, and cross-SDK toolbox table so the npm page matches the other OilPriceAPI SDKs. No code changes.

[1.0.0] - 2026-07-03

First stable release. The public API surface is now covered by semantic versioning: breaking changes will only ship in major versions.

Breaking

  • Bunker fuels response types corrected to match the live API (#29):
    • bunkerFuels.port(): prices is an array of per-grade entries ({ grade, grade_name, price, currency, unit, change_24h, change_pct_24h, last_updated, ... }), not a { VLSFO: number } keyed object. port is an info object ({ code, name, country, ... }), not a string. Response also includes spreads and metadata blocks.
    • bunkerFuels.all() returns { ports, metadata } with port data keyed by port code (previously typed as a flat array; at runtime it returned undefined because the declared shape never matched the API).
    • bunkerFuels.compare() returns { comparison, spreads, metadata } with per-port data keyed by port code (previously typed as { fuel_type, ports: [...] }).
    • bunkerFuels.spreads() returns { from_port, to_port, fuel_grade, spreads, metadata }.
    • bunkerFuels.historical() returns { port, historical_data, period, metadata } (previously typed as a flat array; at runtime it returned undefined).
    • bunkerFuels.export() is typed as BunkerExportRow[] (JSON format).
    • New exported types: BunkerPortInfo, BunkerSpreadValue, BunkerResponseMetadata, PortPricesEntry, AllBunkerPrices, PortToPortSpreadDetail, HistoricalBunkerData, BunkerExportRow. BunkerFuelPrice, PortBunkerPrices, PortPriceComparison, BunkerFuelSpreads, and HistoricalBunkerPrice have new shapes.

Fixed

  • README bunker examples now use valid 3-letter port codes (SIN, not SGSIN — the route only accepts [A-Z]{3}) and the correct compare(["SIN", "RTM"]) signature.

[0.7.0] - 2026-02-11

Added

  • Commodities Resource: client.commodities.list(), get(), categories() for commodity catalog discovery
  • Futures Resource: client.futures.latest(), historical(), ohlc(), intraday(), spreads(), curve(), continuous() for futures contract data
  • Storage Resource: client.storage.all(), cushing(), spr(), regional() for oil inventory levels
  • Rig Counts Resource: client.rigCounts.current(), historical(), latest(), summary() for Baker Hughes rig count data
  • Bunker Fuels Resource: client.bunkerFuels.all(), port(), compare(), spreads(), historical(), export() for marine fuel prices
  • Analytics Resource: client.analytics.performance(), statistics(), correlation(), trend(), spread(), forecast() for price analytics
  • Forecasts Resource: client.forecasts.monthly(), accuracy(), archive(), get() for EIA monthly price forecasts
  • Data Quality Resource: client.dataQuality.summary(), reports(), report() for data quality monitoring
  • Drilling Intelligence Resource: client.drilling.latest(), summary(), trends(), fracSpreads(), wellPermits(), ducWells(), completions(), wellsDrilled(), basin() for drilling activity data
  • Energy Intelligence Resource: client.ei with 7 sub-resources: rigCounts, oilInventories, opecProduction, drillingProductivity, forecasts, wellPermits, fracFocus for comprehensive EIA data
  • Webhooks Resource: client.webhooks.create(), list(), get(), update(), delete(), test(), events() for webhook management
  • Data Sources Resource: client.dataSources.list(), get(), create(), update(), delete(), test(), logs(), health() for data connector management
  • Enhanced Alerts: Added test(), triggers(), analyticsHistory() methods to existing alerts resource
  • Data Connector Support: client.getDataConnectorPrices() for BYOS (Bring Your Own Subscription) prices
  • Telemetry Headers: appUrl and appName options for API usage attribution

Testing

  • 70 new unit tests added (185 total, 0 failures)
  • 13 new test files covering all resource modules
  • All tests pass with TypeScript strict mode

Breaking Changes

None - All new resources are additive. Existing code continues to work unchanged.

[0.6.0] - 2025-12-24

Added

  • PERFORMANCE: Added interval parameter to getHistoricalPrices() for aggregated queries
    • 'raw' - Individual price points (default, can be slow for year-long queries)
    • 'hourly' - Hourly averages
    • 'daily' - Daily averages (recommended for year-long queries - 365 points vs 600k+)
    • 'weekly' - Weekly averages (52 points per year)
    • 'monthly' - Monthly averages (12 points per year)
  • PERFORMANCE: Added perPage parameter for pagination control (default: 100, max: 1000)
  • PERFORMANCE: Added page parameter for pagination navigation
  • New TypeScript type: AggregationInterval

Performance Improvements

  • Year-long queries improved from 74+ seconds to <1 second when using interval: 'daily'
  • Example: getHistoricalPrices({ period: 'past_year', commodity: 'BRENT_CRUDE_USD', interval: 'daily' })

Testing

  • Added 7 new tests for interval and pagination parameters
  • All 118 tests passing

Breaking Changes

None - This is a backwards-compatible feature addition. Existing code continues to work.

[0.5.3] - 2025-12-17

Fixed

  • CRITICAL: Fixed historical date range queries returning incorrect dates
    • Changed getHistoricalPrices() to use /v1/prices/past_year endpoint instead of /v1/prices
    • The /v1/prices endpoint was not correctly handling start_date/end_date parameters
    • This was the same bug that affected the Python SDK (fixed in v1.4.4)
    • Users requesting data for specific date ranges now receive correct results

Testing

  • Added comprehensive test suite for historical price queries (22 new tests)
  • Added error handling test suite (31 new tests)
  • Test coverage now at 95%+ for all source files

Breaking Changes

None - This is a bug fix that corrects behavior to match documentation.

[0.5.2] - 2025-12-17

Added

  • Centralized version management in src/version.ts
  • Export SDK_VERSION and SDK_NAME constants for tracking
  • User-Agent header: oilpriceapi-node/{version} node/{node_version}
  • X-Api-Client and X-Client-Version headers for SDK tracking

Testing

  • Added integration tests for User-Agent header verification (11 tests)

[0.5.1] - 2025-12-16

Added

  • Minor improvements to diesel and alerts resources

[0.5.0] - 2025-12-15

Added

  • Price Alerts: New client.alerts resource for automated price monitoring with webhook notifications
  • Alert Management: Full CRUD operations for price alerts
    • alerts.list() - Get all configured alerts
    • alerts.get(id) - Get specific alert by ID
    • alerts.create(params) - Create new price alert
    • alerts.update(id, params) - Update existing alert
    • alerts.delete(id) - Delete an alert
    • alerts.testWebhook(url) - Test webhook endpoint
  • Alert Operators: 5 comparison operators for flexible conditions
    • greater_than - Trigger when price exceeds threshold
    • less_than - Trigger when price falls below threshold
    • equals - Trigger when price matches threshold exactly
    • greater_than_or_equal - Trigger at or above threshold
    • less_than_or_equal - Trigger at or below threshold
  • Webhook Integration: HTTPS webhook notifications when alerts trigger
  • Cooldown Periods: Configurable cooldown (0-1440 minutes) to prevent alert spam
  • New TypeScript interfaces: PriceAlert, CreateAlertParams, UpdateAlertParams, AlertOperator, WebhookTestResponse
  • Comprehensive input validation for all alert parameters
  • Detailed error handling with clear validation messages

Documentation

  • Added complete Price Alerts section to README with examples
  • Added CRUD operation examples for alerts
  • Added webhook payload documentation
  • Updated Quick Examples section with alerts example
  • Updated feature list to highlight price alerts
  • Added API reference for alert limits and constraints

Testing

  • Added comprehensive test suite for alerts resource (24 test cases)
  • Tests cover all CRUD operations and validation scenarios
  • 100% coverage of alerts functionality
  • Tests for all 5 alert operators
  • Validation tests for name, commodity code, operator, value, webhook URL, and cooldown

Supported Endpoints

Now supports 12 endpoints (up from 7):

  • GET /v1/prices/latest - Get latest commodity prices
  • GET /v1/prices - Get historical commodity prices
  • GET /v1/commodities - Get all commodities metadata
  • GET /v1/commodities/categories - Get commodity categories
  • GET /v1/commodities/{code} - Get specific commodity details
  • GET /v1/diesel-prices - Get state average diesel prices
  • POST /v1/diesel-prices/stations - Get nearby diesel stations
  • GET /v1/alerts - List all price alerts (NEW)
  • GET /v1/alerts/{id} - Get specific alert (NEW)
  • POST /v1/alerts - Create price alert (NEW)
  • PATCH /v1/alerts/{id} - Update alert (NEW)
  • DELETE /v1/alerts/{id} - Delete alert (NEW)

Breaking Changes

None - This is a backwards-compatible feature addition.

[0.4.0] - 2025-12-15

Added

  • Diesel Prices Support: New client.diesel resource for diesel price data
  • State Average Diesel Prices: diesel.getPrice(state) - Get EIA state-level diesel averages (free tier)
  • Station-Level Diesel Pricing: diesel.getStations(options) - Get nearby diesel stations with current prices from Google Maps (paid tiers)
  • New TypeScript interfaces: DieselPrice, DieselStation, DieselStationsResponse, GetDieselStationsOptions
  • Comprehensive input validation for coordinates, state codes, and radius
  • Detailed error handling for tier restrictions (403) and rate limits (429)

Documentation

  • Added diesel prices usage examples to README
  • Added API reference section for client.diesel resource
  • Added complete type definitions for all diesel-related interfaces
  • Updated Quick Examples section with diesel examples
  • Updated feature list to highlight diesel prices support

Testing

  • Added comprehensive test suite for diesel resource (15 test cases)
  • Tests cover input validation, error handling, and API responses
  • 100% coverage of diesel functionality

Supported Endpoints

Now supports 7 endpoints (up from 5):

  • GET /v1/prices/latest - Get latest commodity prices
  • GET /v1/prices - Get historical commodity prices
  • GET /v1/commodities - Get all commodities metadata
  • GET /v1/commodities/categories - Get commodity categories
  • GET /v1/commodities/{code} - Get specific commodity details
  • GET /v1/diesel-prices - Get state average diesel prices (NEW)
  • POST /v1/diesel-prices/stations - Get nearby diesel stations (NEW)

Breaking Changes

None - This is a backwards-compatible feature addition.

[0.3.1] - 2025-11-26

Fixed

  • Fixed QA test to use correct API response fields (price instead of value, formatted instead of code + name)
  • Updated README examples to match actual API response structure
  • Corrected blog post examples for accuracy
  • Verified 100% test pass rate (7/7 tests passing)

Documentation

  • All code examples now use correct fields: price, formatted, code, created_at
  • Removed references to non-existent name, value, and unit fields in latest prices response
  • Added clarification on timeout configuration for historical data queries (120s recommended)

Testing

  • Historical prices endpoint working correctly with 120s timeout
  • All 5 endpoints tested and verified against live API

0.3.0 - 2024-11-25

Added

  • Commodities Endpoint: getCommodities() - Get metadata for all supported commodities
  • Commodity Categories: getCommodityCategories() - Get all commodity categories with their commodities
  • Commodity Details: getCommodity(code) - Get metadata for a specific commodity by code
  • New TypeScript interfaces: Commodity, CommoditiesResponse, CommodityCategory, CategoriesResponse

Supported Endpoints

Now supports 5 endpoints (up from 2):

  • GET /v1/prices/latest - Get latest commodity prices
  • GET /v1/prices - Get historical commodity prices
  • GET /v1/commodities - Get all commodities metadata
  • GET /v1/commodities/categories - Get commodity categories
  • GET /v1/commodities/{code} - Get specific commodity details

0.2.0 - 2024-11-24

Added

  • Retry Logic: Automatic retries with configurable strategies (exponential, linear, fixed)
  • Timeout Handling: Request timeouts with AbortController
  • Debug Logging: Optional debug mode for detailed request/response logging
  • TimeoutError: New error class for timeout scenarios
  • Smart Error Handling: Intelligent retry logic based on error type
  • Rate Limit Handling: Automatic retry with Retry-After header support

Changed

  • User-Agent updated to oilpriceapi-node/0.2.0
  • Improved error messages with more context
  • Better TypeScript type definitions for configuration options

Configuration Options

New configuration options available:

  • retries: Maximum number of retry attempts (default: 3)
  • retryDelay: Initial delay between retries in ms (default: 1000)
  • retryStrategy: Retry backoff strategy - 'exponential', 'linear', or 'fixed' (default: 'exponential')
  • timeout: Request timeout in milliseconds (default: 30000)
  • debug: Enable debug logging (default: false)

0.1.0 - 2024-11-24

Added

  • Initial release
  • Basic API client with TypeScript support
  • Latest prices endpoint support
  • Historical prices endpoint support
  • Custom error classes (AuthenticationError, RateLimitError, NotFoundError, ServerError)
  • Zero runtime dependencies
  • Full TypeScript type definitions
  • Comprehensive README documentation

Supported Endpoints

  • GET /v1/prices/latest - Get latest commodity prices
  • GET /v1/prices - Get historical commodity prices