oilpriceapi 0.8.2 → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +201 -19
- package/dist/cjs/client.js +139 -19
- package/dist/cjs/index.js +17 -3
- package/dist/cjs/resources/analytics.js +99 -137
- package/dist/cjs/resources/bunker-fuels.js +37 -23
- package/dist/cjs/resources/data-sources.js +13 -12
- package/dist/cjs/resources/ei/frac-focus.js +16 -6
- package/dist/cjs/resources/ei/well-permits.js +18 -6
- package/dist/cjs/resources/forecasts.js +11 -5
- package/dist/cjs/resources/futures.js +244 -16
- package/dist/cjs/resources/indicators.js +79 -0
- package/dist/cjs/resources/raw.js +128 -0
- package/dist/cjs/resources/rig-counts.js +5 -2
- package/dist/cjs/resources/spreads.js +105 -0
- package/dist/cjs/resources/storage.js +5 -5
- package/dist/cjs/resources/streaming.js +350 -0
- package/dist/cjs/resources/webhooks.js +3 -14
- package/dist/cjs/version.js +1 -1
- package/dist/client.d.ts +97 -1
- package/dist/client.js +139 -19
- package/dist/index.d.ts +12 -3
- package/dist/index.js +5 -0
- package/dist/resources/analytics.d.ts +147 -214
- package/dist/resources/analytics.js +99 -137
- package/dist/resources/bunker-fuels.d.ts +35 -12
- package/dist/resources/bunker-fuels.js +37 -23
- package/dist/resources/data-sources.d.ts +31 -31
- package/dist/resources/data-sources.js +13 -12
- package/dist/resources/ei/frac-focus.d.ts +23 -9
- package/dist/resources/ei/frac-focus.js +16 -6
- package/dist/resources/ei/well-permits.d.ts +25 -9
- package/dist/resources/ei/well-permits.js +18 -6
- package/dist/resources/forecasts.d.ts +4 -1
- package/dist/resources/forecasts.js +11 -5
- package/dist/resources/futures.d.ts +287 -33
- package/dist/resources/futures.js +241 -15
- package/dist/resources/indicators.d.ts +170 -0
- package/dist/resources/indicators.js +75 -0
- package/dist/resources/raw.d.ts +94 -0
- package/dist/resources/raw.js +124 -0
- package/dist/resources/rig-counts.js +5 -2
- package/dist/resources/spreads.d.ts +121 -0
- package/dist/resources/spreads.js +101 -0
- package/dist/resources/storage.d.ts +5 -4
- package/dist/resources/storage.js +5 -5
- package/dist/resources/streaming.d.ts +272 -0
- package/dist/resources/streaming.js +342 -0
- package/dist/resources/webhooks.d.ts +37 -23
- package/dist/resources/webhooks.js +3 -14
- package/dist/types.d.ts +41 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +7 -1
package/README.md
CHANGED
|
@@ -25,6 +25,7 @@ The official Node.js/TypeScript SDK for [OilPriceAPI](https://www.oilpriceapi.co
|
|
|
25
25
|
- ⛽ **NEW v0.4.0** - Diesel prices (state averages + station-level pricing)
|
|
26
26
|
- 🔔 **NEW v0.5.0** - Price alerts with webhook notifications
|
|
27
27
|
- 📊 **NEW v0.7.0** - Futures, storage, rig counts, analytics, drilling intelligence, webhooks, and energy intelligence
|
|
28
|
+
- 🧰 **NEW** - Typed ICE Brent / Gasoil / WTI & gas/carbon futures helpers, `spreads`, `indicators`, and raw HTTP responses (`client.raw.*` with status + headers)
|
|
28
29
|
|
|
29
30
|
## Installation
|
|
30
31
|
|
|
@@ -267,9 +268,7 @@ console.log("Alert deleted successfully");
|
|
|
267
268
|
const result = await client.alerts.testWebhook("https://your-app.com/webhook");
|
|
268
269
|
|
|
269
270
|
if (result.success) {
|
|
270
|
-
console.log(
|
|
271
|
-
`Webhook OK (${result.status_code}) - ${result.response_time_ms}ms`,
|
|
272
|
-
);
|
|
271
|
+
console.log(`Webhook OK (${result.status_code}) - ${result.response_time_ms}ms`);
|
|
273
272
|
} else {
|
|
274
273
|
console.error(`Webhook failed: ${result.error}`);
|
|
275
274
|
}
|
|
@@ -341,6 +340,138 @@ curve.curve.forEach((point) => {
|
|
|
341
340
|
});
|
|
342
341
|
```
|
|
343
342
|
|
|
343
|
+
#### Typed contract-family helpers (ICE Brent, Gasoil, WTI, gas & carbon)
|
|
344
|
+
|
|
345
|
+
The generic `futures.*` methods take raw contract codes. For the most-requested
|
|
346
|
+
families you can use ergonomic, typed helpers that map to the
|
|
347
|
+
`/v1/futures/{family}/...` endpoints — no need to remember URL slugs. Each
|
|
348
|
+
family supports `latest`, `historical`, `ohlc`, `intraday`, `spreads`, `curve`,
|
|
349
|
+
and `spreadHistory`.
|
|
350
|
+
|
|
351
|
+
```typescript
|
|
352
|
+
import { OilPriceAPI, FUTURES_CONTRACTS } from "oilpriceapi";
|
|
353
|
+
|
|
354
|
+
const client = new OilPriceAPI({ apiKey: "your_key" });
|
|
355
|
+
|
|
356
|
+
// ICE Brent
|
|
357
|
+
const brent = await client.futures.brent().latest();
|
|
358
|
+
console.log(`Brent: $${brent.price}`);
|
|
359
|
+
|
|
360
|
+
// ICE Gasoil
|
|
361
|
+
const gasoil = await client.futures.gasoil().curve();
|
|
362
|
+
|
|
363
|
+
// ICE WTI
|
|
364
|
+
const wti = await client.futures.wti().ohlc("2024-01-15");
|
|
365
|
+
|
|
366
|
+
// Natural gas families
|
|
367
|
+
await client.futures.naturalGas().latest(); // Henry Hub
|
|
368
|
+
await client.futures.ttfGas().historical({ startDate: "2024-01-01" }); // TTF (Europe)
|
|
369
|
+
await client.futures.lngJkm().spreads(); // LNG JKM (Asia)
|
|
370
|
+
|
|
371
|
+
// Carbon
|
|
372
|
+
await client.futures.euaCarbon().latest(); // EU carbon allowance
|
|
373
|
+
await client.futures.ukCarbon().spreadHistory(); // UK carbon allowance
|
|
374
|
+
|
|
375
|
+
// Or address a family by slug
|
|
376
|
+
const fam = client.futures.family("ice-brent");
|
|
377
|
+
await fam.intraday();
|
|
378
|
+
|
|
379
|
+
// Ergonomic contract-code constants for the generic methods
|
|
380
|
+
const brentLatest = await client.futures.latest(FUTURES_CONTRACTS.BRENT); // "BZ"
|
|
381
|
+
const gasoilCode = FUTURES_CONTRACTS.GASOIL; // "G"
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
Available families: `ice-brent`, `ice-gasoil`, `ice-wti`, `natural-gas`,
|
|
385
|
+
`ttf-gas`, `lng-jkm`, `eua-carbon`, `uk-carbon`.
|
|
386
|
+
|
|
387
|
+
### Spreads
|
|
388
|
+
|
|
389
|
+
Crack spreads, basis differentials, curve structure (contango/backwardation),
|
|
390
|
+
refining margins, and physical premiums. Each spread type supports the latest
|
|
391
|
+
value, full history, and an `all` listing
|
|
392
|
+
(`/v1/spreads/{type}`, `/v1/spreads/{type}/historical`, `/v1/spreads/{type}/all`).
|
|
393
|
+
|
|
394
|
+
```typescript
|
|
395
|
+
// Latest values via named helpers
|
|
396
|
+
const crack = await client.spreads.crack();
|
|
397
|
+
console.log(`Crack spread: ${crack.value} ${crack.unit}`);
|
|
398
|
+
|
|
399
|
+
await client.spreads.basis();
|
|
400
|
+
await client.spreads.curveStructure();
|
|
401
|
+
await client.spreads.margin();
|
|
402
|
+
await client.spreads.physicalPremium();
|
|
403
|
+
|
|
404
|
+
// Or address a type directly
|
|
405
|
+
const margin = await client.spreads.get("margin");
|
|
406
|
+
|
|
407
|
+
// Historical spread series
|
|
408
|
+
const history = await client.spreads.historical("basis", {
|
|
409
|
+
startDate: "2024-01-01",
|
|
410
|
+
endDate: "2024-12-31",
|
|
411
|
+
});
|
|
412
|
+
|
|
413
|
+
// All values for a spread type
|
|
414
|
+
const allCrack = await client.spreads.all("crack");
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
### Indicators
|
|
418
|
+
|
|
419
|
+
Derived market indicators and signals: fuel-switching economics, price context,
|
|
420
|
+
storage analytics, market annotations, CFTC positioning, and congressional
|
|
421
|
+
energy-sector trades (`/v1/indicators/{type}`).
|
|
422
|
+
|
|
423
|
+
```typescript
|
|
424
|
+
// Fuel-switching economics
|
|
425
|
+
const fs = await client.indicators.fuelSwitching();
|
|
426
|
+
console.log(`Switching economical: ${fs.economical}`);
|
|
427
|
+
|
|
428
|
+
// Where the current price sits historically
|
|
429
|
+
const ctx = await client.indicators.priceContext();
|
|
430
|
+
console.log(`Percentile: ${ctx.percentile}`);
|
|
431
|
+
|
|
432
|
+
// Storage analytics
|
|
433
|
+
await client.indicators.storageAnalytics();
|
|
434
|
+
|
|
435
|
+
// Market annotations (notable events)
|
|
436
|
+
const annotations = await client.indicators.annotations();
|
|
437
|
+
|
|
438
|
+
// CFTC positioning (Commitment of Traders)
|
|
439
|
+
const cftc = await client.indicators.cftcPositioning();
|
|
440
|
+
cftc.forEach((p) => console.log(`${p.market}: net ${p.net_position}`));
|
|
441
|
+
|
|
442
|
+
// Congressional energy-sector trades
|
|
443
|
+
const trades = await client.indicators.congressionalTrades();
|
|
444
|
+
|
|
445
|
+
// Or address a type directly
|
|
446
|
+
const custom = await client.indicators.get("price-context");
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
### Raw HTTP responses (status + headers)
|
|
450
|
+
|
|
451
|
+
By default the SDK returns just the parsed data. When you also need the
|
|
452
|
+
underlying HTTP status code and response headers (e.g. rate-limit headers),
|
|
453
|
+
use the `client.raw.*` accessor. It returns `{ data, status, headers }` while
|
|
454
|
+
`data` keeps the exact same shape as the equivalent non-raw method.
|
|
455
|
+
|
|
456
|
+
```typescript
|
|
457
|
+
const { data, status, headers } = await client.raw.getLatestPrices({
|
|
458
|
+
commodity: "WTI_USD",
|
|
459
|
+
});
|
|
460
|
+
|
|
461
|
+
console.log(`HTTP ${status}`);
|
|
462
|
+
console.log(`Rate limit remaining: ${headers.get("x-ratelimit-remaining")}`);
|
|
463
|
+
console.log(`Price: ${data[0].price}`);
|
|
464
|
+
|
|
465
|
+
// Also available: getHistoricalPrices, getCommodities,
|
|
466
|
+
// getCommodityCategories, getCommodity
|
|
467
|
+
const commodities = await client.raw.getCommodities();
|
|
468
|
+
console.log(commodities.status, commodities.headers.get("content-type"));
|
|
469
|
+
|
|
470
|
+
// Generic raw GET for any endpoint without a dedicated helper
|
|
471
|
+
const futures = await client.raw.get("/v1/futures/CL.1");
|
|
472
|
+
console.log(futures.status, futures.data);
|
|
473
|
+
```
|
|
474
|
+
|
|
344
475
|
### Storage Levels (New in v0.7.0)
|
|
345
476
|
|
|
346
477
|
```typescript
|
|
@@ -383,11 +514,7 @@ console.log(`30-day return: ${perf.return_percent}%`);
|
|
|
383
514
|
console.log(`Volatility: ${perf.volatility}`);
|
|
384
515
|
|
|
385
516
|
// Analyze correlation between commodities
|
|
386
|
-
const corr = await client.analytics.correlation(
|
|
387
|
-
"WTI_USD",
|
|
388
|
-
"BRENT_CRUDE_USD",
|
|
389
|
-
90,
|
|
390
|
-
);
|
|
517
|
+
const corr = await client.analytics.correlation("WTI_USD", "BRENT_CRUDE_USD", 90);
|
|
391
518
|
console.log(`Correlation: ${corr.correlation} (${corr.strength})`);
|
|
392
519
|
```
|
|
393
520
|
|
|
@@ -510,12 +637,73 @@ console.log(`Connection ${test.success ? "OK" : "failed"}`);
|
|
|
510
637
|
// View sync logs
|
|
511
638
|
const logs = await client.dataSources.logs(source.id);
|
|
512
639
|
logs.forEach((log) => {
|
|
513
|
-
console.log(
|
|
514
|
-
`${log.timestamp}: ${log.status} - ${log.records_synced} records`,
|
|
515
|
-
);
|
|
640
|
+
console.log(`${log.timestamp}: ${log.status} - ${log.records_synced} records`);
|
|
516
641
|
});
|
|
517
642
|
```
|
|
518
643
|
|
|
644
|
+
### Real-time Streaming (WebSocket)
|
|
645
|
+
|
|
646
|
+
Stream live price updates over a persistent WebSocket connection instead of
|
|
647
|
+
polling. Streaming uses the server's ActionCable `/cable` endpoint and the
|
|
648
|
+
`EnergyPricesChannel`, and is available on the **Reservoir Mastery
|
|
649
|
+
(Professional+)** plan.
|
|
650
|
+
|
|
651
|
+
The `client.stream.prices()` method returns a subscription handle (an
|
|
652
|
+
`EventEmitter`). It performs the ActionCable handshake, answers server pings,
|
|
653
|
+
auto-reconnects with exponential backoff, and surfaces typed events. Call
|
|
654
|
+
`.close()` for a clean teardown.
|
|
655
|
+
|
|
656
|
+
```typescript
|
|
657
|
+
import { OilPriceAPI } from "oilpriceapi";
|
|
658
|
+
|
|
659
|
+
const client = new OilPriceAPI({ apiKey: process.env.OILPRICEAPI_KEY });
|
|
660
|
+
|
|
661
|
+
// Optional onUpdate callback fires on every live price_update.
|
|
662
|
+
const sub = client.stream.prices(
|
|
663
|
+
{ commodities: ["WTI_USD", "BRENT_CRUDE_USD"] }, // optional client-side filter
|
|
664
|
+
(update) => {
|
|
665
|
+
const wti = update.prices.oil.wti;
|
|
666
|
+
if (wti) {
|
|
667
|
+
console.log(`WTI ${wti.original_price} ${wti.original_currency} @ ${update.timestamp}`);
|
|
668
|
+
}
|
|
669
|
+
},
|
|
670
|
+
);
|
|
671
|
+
|
|
672
|
+
// Lifecycle + typed events
|
|
673
|
+
sub.on("connected", () => console.log("subscription confirmed"));
|
|
674
|
+
sub.on("welcome", (snapshot) => console.log("initial snapshot", snapshot.data));
|
|
675
|
+
sub.on("price_update", (update) => console.log("oil:", update.prices.oil));
|
|
676
|
+
sub.on("rig_count_update", (m) => console.log(`${m.rig_count.region}: ${m.rig_count.count} rigs`));
|
|
677
|
+
sub.on("reconnecting", ({ attempt, delay }) => console.log(`reconnect #${attempt} in ${delay}ms`));
|
|
678
|
+
sub.on("disconnected", ({ code }) => console.log("socket closed", code));
|
|
679
|
+
sub.on("error", (err) => console.error("stream error:", err.message));
|
|
680
|
+
|
|
681
|
+
// Clean teardown (unsubscribe + close socket)
|
|
682
|
+
process.on("SIGINT", () => {
|
|
683
|
+
sub.close();
|
|
684
|
+
process.exit(0);
|
|
685
|
+
});
|
|
686
|
+
```
|
|
687
|
+
|
|
688
|
+
**Events emitted by the subscription handle:**
|
|
689
|
+
|
|
690
|
+
| Event | Payload | Description |
|
|
691
|
+
| ------------------ | ----------------------- | ------------------------------------------------------ |
|
|
692
|
+
| `connected` | — | Channel subscription confirmed by the server |
|
|
693
|
+
| `welcome` | `WelcomeMessage` | Initial price snapshot sent on subscribe |
|
|
694
|
+
| `price_update` | `PriceUpdateMessage` | Live price broadcast (oil + natural gas) |
|
|
695
|
+
| `rig_count_update` | `RigCountUpdateMessage` | Drilling rig-count broadcast (drilling-tier accounts) |
|
|
696
|
+
| `message` | `StreamMessage` | Every decoded channel message (incl. unknown types) |
|
|
697
|
+
| `reconnecting` | `{ attempt, delay }` | A reconnect attempt has been scheduled |
|
|
698
|
+
| `disconnected` | `{ code, reason }` | The transport closed |
|
|
699
|
+
| `error` | `Error` | Transport error, rejected subscription, or retries out |
|
|
700
|
+
| `close` | — | The subscription was closed via `.close()` |
|
|
701
|
+
|
|
702
|
+
**Options** (`StreamPricesOptions`): `commodities`, `autoReconnect`,
|
|
703
|
+
`reconnectDelay`, `maxReconnectDelay`, `maxReconnectAttempts`.
|
|
704
|
+
|
|
705
|
+
See [`examples/streaming.ts`](./examples/streaming.ts) for a complete runnable example.
|
|
706
|
+
|
|
519
707
|
### Advanced Configuration
|
|
520
708
|
|
|
521
709
|
```typescript
|
|
@@ -557,11 +745,7 @@ try {
|
|
|
557
745
|
if (error instanceof AuthenticationError) {
|
|
558
746
|
console.error("Invalid API key:", error.message);
|
|
559
747
|
} else if (error instanceof RateLimitError) {
|
|
560
|
-
console.error(
|
|
561
|
-
"Rate limit exceeded. Retry after:",
|
|
562
|
-
error.retryAfter,
|
|
563
|
-
"seconds",
|
|
564
|
-
);
|
|
748
|
+
console.error("Rate limit exceeded. Retry after:", error.retryAfter, "seconds");
|
|
565
749
|
} else if (error instanceof TimeoutError) {
|
|
566
750
|
console.error("Request timed out:", error.message);
|
|
567
751
|
} else if (error instanceof ServerError) {
|
|
@@ -812,9 +996,7 @@ const result = await client.diesel.getStations({
|
|
|
812
996
|
console.log(`Found ${result.stations.length} stations`);
|
|
813
997
|
console.log(`Regional average: $${result.regional_average.price}/gallon`);
|
|
814
998
|
|
|
815
|
-
const cheapest = result.stations.reduce((min, s) =>
|
|
816
|
-
s.diesel_price < min.diesel_price ? s : min,
|
|
817
|
-
);
|
|
999
|
+
const cheapest = result.stations.reduce((min, s) => (s.diesel_price < min.diesel_price ? s : min));
|
|
818
1000
|
console.log(`Cheapest: ${cheapest.name} at ${cheapest.formatted_price}`);
|
|
819
1001
|
```
|
|
820
1002
|
|
package/dist/cjs/client.js
CHANGED
|
@@ -17,6 +17,10 @@ const index_js_1 = require("./resources/ei/index.js");
|
|
|
17
17
|
const webhooks_js_1 = require("./resources/webhooks.js");
|
|
18
18
|
const data_sources_js_1 = require("./resources/data-sources.js");
|
|
19
19
|
const version_js_1 = require("./version.js");
|
|
20
|
+
const spreads_js_1 = require("./resources/spreads.js");
|
|
21
|
+
const indicators_js_1 = require("./resources/indicators.js");
|
|
22
|
+
const raw_js_1 = require("./resources/raw.js");
|
|
23
|
+
const streaming_js_1 = require("./resources/streaming.js");
|
|
20
24
|
/**
|
|
21
25
|
* Official Node.js client for Oil Price API
|
|
22
26
|
*
|
|
@@ -72,6 +76,10 @@ class OilPriceAPI {
|
|
|
72
76
|
this.ei = new index_js_1.EnergyIntelligenceResource(this);
|
|
73
77
|
this.webhooks = new webhooks_js_1.WebhooksResource(this);
|
|
74
78
|
this.dataSources = new data_sources_js_1.DataSourcesResource(this);
|
|
79
|
+
this.spreads = new spreads_js_1.SpreadsResource(this);
|
|
80
|
+
this.indicators = new indicators_js_1.IndicatorsResource(this);
|
|
81
|
+
this.raw = new raw_js_1.RawResource(this);
|
|
82
|
+
this.stream = new streaming_js_1.StreamingResource(this);
|
|
75
83
|
}
|
|
76
84
|
/**
|
|
77
85
|
* Log debug messages if debug mode is enabled
|
|
@@ -125,12 +133,51 @@ class OilPriceAPI {
|
|
|
125
133
|
// Don't retry on client errors (4xx except 429)
|
|
126
134
|
return false;
|
|
127
135
|
}
|
|
136
|
+
/**
|
|
137
|
+
* Shape a parsed JSON response body into the value returned to callers.
|
|
138
|
+
*
|
|
139
|
+
* Centralizes the response-structure handling so that both {@link request}
|
|
140
|
+
* and {@link requestRaw} return identical data. Handles the latest/historical
|
|
141
|
+
* envelope shapes as well as the generic `{ data }` fallback used by resource
|
|
142
|
+
* mutations, alerts, webhooks, etc.
|
|
143
|
+
*/
|
|
144
|
+
shapeResponseData(responseData) {
|
|
145
|
+
// Handle different response structures
|
|
146
|
+
// Latest endpoint: { status, data: { price, ... } }
|
|
147
|
+
// Historical endpoint: { status, data: { prices: [...] } }
|
|
148
|
+
if (responseData.status === "success" && responseData.data) {
|
|
149
|
+
if (responseData.data.prices) {
|
|
150
|
+
// Historical endpoint - return prices array
|
|
151
|
+
this.log(`Returning ${responseData.data.prices.length} prices`);
|
|
152
|
+
return responseData.data.prices;
|
|
153
|
+
}
|
|
154
|
+
else if (responseData.data.price !== undefined) {
|
|
155
|
+
// Latest endpoint - wrap single price in array
|
|
156
|
+
this.log("Returning single price (wrapped in array)");
|
|
157
|
+
return [responseData.data];
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
// Fallback - return data as-is (used by resource mutations, alerts, webhooks, etc.)
|
|
161
|
+
this.log("Returning data as-is");
|
|
162
|
+
return (responseData.data !== undefined ? responseData.data : responseData);
|
|
163
|
+
}
|
|
128
164
|
/**
|
|
129
165
|
* Internal method to make HTTP requests with retry and timeout.
|
|
130
166
|
* Supports all HTTP methods (GET, POST, PATCH, DELETE) with consistent
|
|
131
167
|
* retry logic, timeout handling, and typed error responses.
|
|
132
168
|
*/
|
|
133
169
|
async request(endpoint, params, options) {
|
|
170
|
+
const { data } = await this.requestRaw(endpoint, params, options);
|
|
171
|
+
return data;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Internal method identical to {@link request} but returns the underlying
|
|
175
|
+
* HTTP status and headers alongside the parsed data.
|
|
176
|
+
*
|
|
177
|
+
* Used by the public {@link raw} accessor to expose response metadata
|
|
178
|
+
* (issue #7) without changing the return shape of existing methods.
|
|
179
|
+
*/
|
|
180
|
+
async requestRaw(endpoint, params, options) {
|
|
134
181
|
// Build URL with query parameters
|
|
135
182
|
const url = new URL(`${this.baseUrl}${endpoint}`);
|
|
136
183
|
if (params) {
|
|
@@ -221,7 +268,11 @@ class OilPriceAPI {
|
|
|
221
268
|
const responseText = await response.text();
|
|
222
269
|
if (!responseText) {
|
|
223
270
|
this.log("Empty response body");
|
|
224
|
-
return {
|
|
271
|
+
return {
|
|
272
|
+
data: {},
|
|
273
|
+
status: response.status,
|
|
274
|
+
headers: response.headers,
|
|
275
|
+
};
|
|
225
276
|
}
|
|
226
277
|
// Parse successful response
|
|
227
278
|
const responseData = JSON.parse(responseText);
|
|
@@ -229,24 +280,11 @@ class OilPriceAPI {
|
|
|
229
280
|
status: responseData.status,
|
|
230
281
|
hasData: !!responseData.data,
|
|
231
282
|
});
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
// Historical endpoint - return prices array
|
|
238
|
-
this.log(`Returning ${responseData.data.prices.length} prices`);
|
|
239
|
-
return responseData.data.prices;
|
|
240
|
-
}
|
|
241
|
-
else if (responseData.data.price !== undefined) {
|
|
242
|
-
// Latest endpoint - wrap single price in array
|
|
243
|
-
this.log("Returning single price (wrapped in array)");
|
|
244
|
-
return [responseData.data];
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
// Fallback - return data as-is (used by resource mutations, alerts, webhooks, etc.)
|
|
248
|
-
this.log("Returning data as-is");
|
|
249
|
-
return (responseData.data !== undefined ? responseData.data : responseData);
|
|
283
|
+
return {
|
|
284
|
+
data: this.shapeResponseData(responseData),
|
|
285
|
+
status: response.status,
|
|
286
|
+
headers: response.headers,
|
|
287
|
+
};
|
|
250
288
|
}
|
|
251
289
|
catch (error) {
|
|
252
290
|
// Handle abort (timeout)
|
|
@@ -486,5 +524,87 @@ class OilPriceAPI {
|
|
|
486
524
|
async getCommodity(code) {
|
|
487
525
|
return this.request(`/v1/commodities/${code}`, {});
|
|
488
526
|
}
|
|
527
|
+
/**
|
|
528
|
+
* Fetch live sample prices from the public, no-auth demo endpoint.
|
|
529
|
+
*
|
|
530
|
+
* Hits `GET /v1/demo/prices` (no API key required) and returns the parsed
|
|
531
|
+
* `{ prices, meta }` envelope. Useful for trying the client without
|
|
532
|
+
* credentials. Subject to the demo rate limit (~20 requests/hour).
|
|
533
|
+
*
|
|
534
|
+
* @example
|
|
535
|
+
* ```typescript
|
|
536
|
+
* const demo = await client.getDemoPrices();
|
|
537
|
+
* const brent = demo.prices.find(p => p.code === 'BRENT_CRUDE_USD');
|
|
538
|
+
* console.log(brent?.price);
|
|
539
|
+
* ```
|
|
540
|
+
*/
|
|
541
|
+
async getDemoPrices() {
|
|
542
|
+
return this.requestDemo("/v1/demo/prices");
|
|
543
|
+
}
|
|
544
|
+
/**
|
|
545
|
+
* Fetch the catalogue of commodities from the public, no-auth demo endpoint.
|
|
546
|
+
*
|
|
547
|
+
* Hits `GET /v1/demo/commodities` (no API key required) and returns the parsed
|
|
548
|
+
* `{ commodities, meta }` envelope, where `meta.free_commodities` lists the
|
|
549
|
+
* codes available on the free demo tier.
|
|
550
|
+
*
|
|
551
|
+
* @example
|
|
552
|
+
* ```typescript
|
|
553
|
+
* const demo = await client.getDemoCommodities();
|
|
554
|
+
* console.log(demo.meta.total, demo.meta.free_commodities);
|
|
555
|
+
* ```
|
|
556
|
+
*/
|
|
557
|
+
async getDemoCommodities() {
|
|
558
|
+
return this.requestDemo("/v1/demo/commodities");
|
|
559
|
+
}
|
|
560
|
+
/**
|
|
561
|
+
* Minimal fetch for the no-auth demo endpoints.
|
|
562
|
+
*
|
|
563
|
+
* Unlike {@link request}, this does NOT run the latest/historical response
|
|
564
|
+
* shaping (which would strip the `meta` block) and does NOT require an API
|
|
565
|
+
* key — it returns the raw `data` envelope from `{ status, data }`.
|
|
566
|
+
*/
|
|
567
|
+
async requestDemo(endpoint) {
|
|
568
|
+
const url = `${this.baseUrl}${endpoint}`;
|
|
569
|
+
this.log(`Demo request: ${url}`);
|
|
570
|
+
const controller = new AbortController();
|
|
571
|
+
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
572
|
+
try {
|
|
573
|
+
const response = await fetch(url, {
|
|
574
|
+
method: "GET",
|
|
575
|
+
headers: {
|
|
576
|
+
"Content-Type": "application/json",
|
|
577
|
+
"User-Agent": (0, version_js_1.buildUserAgent)(),
|
|
578
|
+
"X-SDK-Name": version_js_1.SDK_NAME,
|
|
579
|
+
"X-SDK-Version": version_js_1.SDK_VERSION,
|
|
580
|
+
},
|
|
581
|
+
signal: controller.signal,
|
|
582
|
+
});
|
|
583
|
+
if (!response.ok) {
|
|
584
|
+
const body = await response.text();
|
|
585
|
+
let message = `HTTP ${response.status}: ${response.statusText}`;
|
|
586
|
+
try {
|
|
587
|
+
const json = JSON.parse(body);
|
|
588
|
+
message = json.message || json.error || message;
|
|
589
|
+
}
|
|
590
|
+
catch {
|
|
591
|
+
// non-JSON error body
|
|
592
|
+
}
|
|
593
|
+
throw new errors_js_1.OilPriceAPIError(message, response.status, "HTTP_ERROR");
|
|
594
|
+
}
|
|
595
|
+
const parsed = JSON.parse(await response.text());
|
|
596
|
+
// Demo envelope is { status: "success", data: { ... } }.
|
|
597
|
+
return (parsed.data !== undefined ? parsed.data : parsed);
|
|
598
|
+
}
|
|
599
|
+
catch (error) {
|
|
600
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
601
|
+
throw new errors_js_1.TimeoutError("Request timeout", this.timeout);
|
|
602
|
+
}
|
|
603
|
+
throw error;
|
|
604
|
+
}
|
|
605
|
+
finally {
|
|
606
|
+
clearTimeout(timeoutId);
|
|
607
|
+
}
|
|
608
|
+
}
|
|
489
609
|
}
|
|
490
610
|
exports.OilPriceAPI = OilPriceAPI;
|
package/dist/cjs/index.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* @packageDocumentation
|
|
8
8
|
*/
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
-
exports.DataSourcesResource = exports.WebhooksResource = exports.EIFracFocusResource = exports.EIWellPermitsResource = exports.EIForecastsResource = exports.EIDrillingProductivityResource = exports.EIOPECProductionResource = exports.EIOilInventoriesResource = exports.EIRigCountsResource = exports.EnergyIntelligenceResource = exports.DrillingIntelligenceResource = exports.DataQualityResource = exports.ForecastsResource = exports.AnalyticsResource = exports.BunkerFuelsResource = exports.RigCountsResource = exports.StorageResource = exports.FuturesResource = exports.CommoditiesResource = exports.AlertsResource = exports.DieselResource = exports.TimeoutError = exports.ValidationError = exports.ServerError = exports.NotFoundError = exports.RateLimitError = exports.AuthenticationError = exports.OilPriceAPIError = exports.SDK_NAME = exports.SDK_VERSION = exports.OilPriceAPI = void 0;
|
|
10
|
+
exports.ENERGY_PRICES_CHANNEL = exports.PriceStreamSubscription = exports.StreamingResource = exports.DataSourcesResource = exports.WebhooksResource = exports.EIFracFocusResource = exports.EIWellPermitsResource = exports.EIForecastsResource = exports.EIDrillingProductivityResource = exports.EIOPECProductionResource = exports.EIOilInventoriesResource = exports.EIRigCountsResource = exports.EnergyIntelligenceResource = exports.DrillingIntelligenceResource = exports.DataQualityResource = exports.ForecastsResource = exports.AnalyticsResource = exports.BunkerFuelsResource = exports.RigCountsResource = exports.StorageResource = exports.FuturesResource = exports.CommoditiesResource = exports.AlertsResource = exports.DieselResource = exports.TimeoutError = exports.ValidationError = exports.ServerError = exports.NotFoundError = exports.RateLimitError = exports.AuthenticationError = exports.OilPriceAPIError = exports.RawResource = exports.IndicatorsResource = exports.SpreadsResource = exports.FuturesContractFamily = exports.FUTURES_FAMILY_SLUGS = exports.FUTURES_CONTRACTS = exports.SDK_NAME = exports.SDK_VERSION = exports.OilPriceAPI = void 0;
|
|
11
11
|
exports.verifyWebhookSignature = verifyWebhookSignature;
|
|
12
12
|
const node_crypto_1 = require("node:crypto");
|
|
13
13
|
var client_js_1 = require("./client.js");
|
|
@@ -15,6 +15,16 @@ Object.defineProperty(exports, "OilPriceAPI", { enumerable: true, get: function
|
|
|
15
15
|
var version_js_1 = require("./version.js");
|
|
16
16
|
Object.defineProperty(exports, "SDK_VERSION", { enumerable: true, get: function () { return version_js_1.SDK_VERSION; } });
|
|
17
17
|
Object.defineProperty(exports, "SDK_NAME", { enumerable: true, get: function () { return version_js_1.SDK_NAME; } });
|
|
18
|
+
var futures_js_1 = require("./resources/futures.js");
|
|
19
|
+
Object.defineProperty(exports, "FUTURES_CONTRACTS", { enumerable: true, get: function () { return futures_js_1.FUTURES_CONTRACTS; } });
|
|
20
|
+
Object.defineProperty(exports, "FUTURES_FAMILY_SLUGS", { enumerable: true, get: function () { return futures_js_1.FUTURES_FAMILY_SLUGS; } });
|
|
21
|
+
Object.defineProperty(exports, "FuturesContractFamily", { enumerable: true, get: function () { return futures_js_1.FuturesContractFamily; } });
|
|
22
|
+
var spreads_js_1 = require("./resources/spreads.js");
|
|
23
|
+
Object.defineProperty(exports, "SpreadsResource", { enumerable: true, get: function () { return spreads_js_1.SpreadsResource; } });
|
|
24
|
+
var indicators_js_1 = require("./resources/indicators.js");
|
|
25
|
+
Object.defineProperty(exports, "IndicatorsResource", { enumerable: true, get: function () { return indicators_js_1.IndicatorsResource; } });
|
|
26
|
+
var raw_js_1 = require("./resources/raw.js");
|
|
27
|
+
Object.defineProperty(exports, "RawResource", { enumerable: true, get: function () { return raw_js_1.RawResource; } });
|
|
18
28
|
var errors_js_1 = require("./errors.js");
|
|
19
29
|
Object.defineProperty(exports, "OilPriceAPIError", { enumerable: true, get: function () { return errors_js_1.OilPriceAPIError; } });
|
|
20
30
|
Object.defineProperty(exports, "AuthenticationError", { enumerable: true, get: function () { return errors_js_1.AuthenticationError; } });
|
|
@@ -29,8 +39,8 @@ var alerts_js_1 = require("./resources/alerts.js");
|
|
|
29
39
|
Object.defineProperty(exports, "AlertsResource", { enumerable: true, get: function () { return alerts_js_1.AlertsResource; } });
|
|
30
40
|
var commodities_js_1 = require("./resources/commodities.js");
|
|
31
41
|
Object.defineProperty(exports, "CommoditiesResource", { enumerable: true, get: function () { return commodities_js_1.CommoditiesResource; } });
|
|
32
|
-
var
|
|
33
|
-
Object.defineProperty(exports, "FuturesResource", { enumerable: true, get: function () { return
|
|
42
|
+
var futures_js_2 = require("./resources/futures.js");
|
|
43
|
+
Object.defineProperty(exports, "FuturesResource", { enumerable: true, get: function () { return futures_js_2.FuturesResource; } });
|
|
34
44
|
var storage_js_1 = require("./resources/storage.js");
|
|
35
45
|
Object.defineProperty(exports, "StorageResource", { enumerable: true, get: function () { return storage_js_1.StorageResource; } });
|
|
36
46
|
var rig_counts_js_1 = require("./resources/rig-counts.js");
|
|
@@ -58,6 +68,10 @@ var webhooks_js_1 = require("./resources/webhooks.js");
|
|
|
58
68
|
Object.defineProperty(exports, "WebhooksResource", { enumerable: true, get: function () { return webhooks_js_1.WebhooksResource; } });
|
|
59
69
|
var data_sources_js_1 = require("./resources/data-sources.js");
|
|
60
70
|
Object.defineProperty(exports, "DataSourcesResource", { enumerable: true, get: function () { return data_sources_js_1.DataSourcesResource; } });
|
|
71
|
+
var streaming_js_1 = require("./resources/streaming.js");
|
|
72
|
+
Object.defineProperty(exports, "StreamingResource", { enumerable: true, get: function () { return streaming_js_1.StreamingResource; } });
|
|
73
|
+
Object.defineProperty(exports, "PriceStreamSubscription", { enumerable: true, get: function () { return streaming_js_1.PriceStreamSubscription; } });
|
|
74
|
+
Object.defineProperty(exports, "ENERGY_PRICES_CHANNEL", { enumerable: true, get: function () { return streaming_js_1.ENERGY_PRICES_CHANNEL; } });
|
|
61
75
|
/**
|
|
62
76
|
* Standalone webhook signature verification.
|
|
63
77
|
*
|