oilpriceapi 0.9.1 → 0.10.0
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 +78 -2
- package/dist/cjs/client.js +49 -0
- package/dist/cjs/index.js +4 -1
- package/dist/cjs/resources/market-brief.js +9 -0
- package/dist/cjs/resources/streaming.js +3 -3
- package/dist/cjs/resources/subscriptions.js +217 -0
- package/dist/cjs/version.js +1 -1
- package/dist/client.d.ts +36 -1
- package/dist/client.js +50 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.js +1 -0
- package/dist/resources/market-brief.d.ts +72 -0
- package/dist/resources/market-brief.js +8 -0
- package/dist/resources/streaming.d.ts +2 -2
- package/dist/resources/streaming.js +3 -3
- package/dist/resources/subscriptions.d.ts +238 -0
- package/dist/resources/subscriptions.js +212 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -26,6 +26,7 @@ The official Node.js/TypeScript SDK for [OilPriceAPI](https://www.oilpriceapi.co
|
|
|
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
28
|
- 🧰 **NEW** - Typed ICE Brent / Gasoil / WTI & gas/carbon futures helpers, `spreads`, `indicators`, and raw HTTP responses (`client.raw.*` with status + headers)
|
|
29
|
+
- 🤖 **NEW v0.10.0** - `getMarketBrief()` (multi-commodity structured + narrative summary) and agent `subscriptions` (persistent watches + event polling)
|
|
29
30
|
|
|
30
31
|
## Installation
|
|
31
32
|
|
|
@@ -645,8 +646,8 @@ logs.forEach((log) => {
|
|
|
645
646
|
|
|
646
647
|
Stream live price updates over a persistent WebSocket connection instead of
|
|
647
648
|
polling. Streaming uses the server's ActionCable `/cable` endpoint and the
|
|
648
|
-
`EnergyPricesChannel`, and is available on the **
|
|
649
|
-
(
|
|
649
|
+
`EnergyPricesChannel`, and is available on the **Professional plan
|
|
650
|
+
($99/mo) or higher**.
|
|
650
651
|
|
|
651
652
|
The `client.stream.prices()` method returns a subscription handle (an
|
|
652
653
|
`EventEmitter`). It performs the ActionCable handshake, answers server pings,
|
|
@@ -704,6 +705,81 @@ process.on("SIGINT", () => {
|
|
|
704
705
|
|
|
705
706
|
See [`examples/streaming.ts`](./examples/streaming.ts) for a complete runnable example.
|
|
706
707
|
|
|
708
|
+
### Market Brief (New in v0.10.0)
|
|
709
|
+
|
|
710
|
+
A single call returns a structured, multi-commodity market summary — latest
|
|
711
|
+
price, 24h change, freshness, and a 1-month forecast band per commodity — with
|
|
712
|
+
an optional natural-language narrative. Counts as one request against your quota.
|
|
713
|
+
|
|
714
|
+
```typescript
|
|
715
|
+
import { OilPriceAPI } from "oilpriceapi";
|
|
716
|
+
|
|
717
|
+
const client = new OilPriceAPI({ apiKey: "your_api_key" });
|
|
718
|
+
|
|
719
|
+
const brief = await client.getMarketBrief(["BRENT_CRUDE_USD", "WTI_USD"]);
|
|
720
|
+
|
|
721
|
+
for (const c of brief.commodities) {
|
|
722
|
+
console.log(`${c.name}: $${c.price} (${c.change_24h_pct}% 24h)`);
|
|
723
|
+
if (c.forecast_1m) {
|
|
724
|
+
console.log(
|
|
725
|
+
` 1m forecast: ${c.forecast_1m.point} [${c.forecast_1m.low}–${c.forecast_1m.high}]`,
|
|
726
|
+
);
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
// Include a natural-language narrative
|
|
731
|
+
const withNarrative = await client.getMarketBrief(["BRENT_CRUDE_USD"], {
|
|
732
|
+
narrative: true,
|
|
733
|
+
});
|
|
734
|
+
console.log(withNarrative.narrative);
|
|
735
|
+
```
|
|
736
|
+
|
|
737
|
+
### Agent Subscriptions / Watches (New in v0.10.0)
|
|
738
|
+
|
|
739
|
+
Persistent server-side "watches" evaluate a set of commodity codes on a recurring
|
|
740
|
+
interval and emit events you can poll for — ideal for autonomous agents that want
|
|
741
|
+
change notifications without holding an open connection. The friendly `interval`
|
|
742
|
+
("5m" / "15m" / "1h" / "daily", or a number of seconds) is mapped to the API's
|
|
743
|
+
`interval_seconds`. Polling for events does **not** consume your request quota.
|
|
744
|
+
|
|
745
|
+
```typescript
|
|
746
|
+
import { OilPriceAPI } from "oilpriceapi";
|
|
747
|
+
|
|
748
|
+
const client = new OilPriceAPI({ apiKey: "your_api_key" });
|
|
749
|
+
|
|
750
|
+
// Create a watch (source defaults to "sdk-node"; pass `tool` for attribution)
|
|
751
|
+
const watch = await client.subscriptions.create({
|
|
752
|
+
name: "Crude desk",
|
|
753
|
+
codes: ["BRENT_CRUDE_USD", "WTI_USD"],
|
|
754
|
+
interval: "5m",
|
|
755
|
+
tool: "my-trading-bot",
|
|
756
|
+
});
|
|
757
|
+
|
|
758
|
+
// List all watches
|
|
759
|
+
const watches = await client.subscriptions.list();
|
|
760
|
+
console.log(`You have ${watches.length} watch(es)`);
|
|
761
|
+
|
|
762
|
+
// Poll for new events using a cursor (does not burn quota)
|
|
763
|
+
let cursor = 0;
|
|
764
|
+
while (true) {
|
|
765
|
+
const {
|
|
766
|
+
events,
|
|
767
|
+
cursor: next,
|
|
768
|
+
has_more,
|
|
769
|
+
} = await client.subscriptions.events({
|
|
770
|
+
since: cursor,
|
|
771
|
+
});
|
|
772
|
+
for (const event of events) {
|
|
773
|
+
console.log(`event #${event.seq} on ${event.code} (${event.type})`);
|
|
774
|
+
}
|
|
775
|
+
cursor = next;
|
|
776
|
+
if (!has_more) break;
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
// Remove a watch when you're done
|
|
780
|
+
await client.subscriptions.delete(watch.id);
|
|
781
|
+
```
|
|
782
|
+
|
|
707
783
|
### Advanced Configuration
|
|
708
784
|
|
|
709
785
|
```typescript
|
package/dist/cjs/client.js
CHANGED
|
@@ -21,6 +21,7 @@ const spreads_js_1 = require("./resources/spreads.js");
|
|
|
21
21
|
const indicators_js_1 = require("./resources/indicators.js");
|
|
22
22
|
const raw_js_1 = require("./resources/raw.js");
|
|
23
23
|
const streaming_js_1 = require("./resources/streaming.js");
|
|
24
|
+
const subscriptions_js_1 = require("./resources/subscriptions.js");
|
|
24
25
|
/**
|
|
25
26
|
* Official Node.js client for Oil Price API
|
|
26
27
|
*
|
|
@@ -80,6 +81,7 @@ class OilPriceAPI {
|
|
|
80
81
|
this.indicators = new indicators_js_1.IndicatorsResource(this);
|
|
81
82
|
this.raw = new raw_js_1.RawResource(this);
|
|
82
83
|
this.stream = new streaming_js_1.StreamingResource(this);
|
|
84
|
+
this.subscriptions = new subscriptions_js_1.SubscriptionsResource(this);
|
|
83
85
|
}
|
|
84
86
|
/**
|
|
85
87
|
* Log debug messages if debug mode is enabled
|
|
@@ -215,6 +217,14 @@ class OilPriceAPI {
|
|
|
215
217
|
if (this.appName) {
|
|
216
218
|
headers["X-App-Name"] = this.appName;
|
|
217
219
|
}
|
|
220
|
+
// Per-request headers (e.g. MCP attribution X-OPA-Source / X-OPA-Tool).
|
|
221
|
+
if (options?.headers) {
|
|
222
|
+
Object.entries(options.headers).forEach(([key, value]) => {
|
|
223
|
+
if (value !== undefined && value !== null) {
|
|
224
|
+
headers[key] = value;
|
|
225
|
+
}
|
|
226
|
+
});
|
|
227
|
+
}
|
|
218
228
|
const fetchOptions = {
|
|
219
229
|
method: options?.method || "GET",
|
|
220
230
|
headers,
|
|
@@ -524,6 +534,45 @@ class OilPriceAPI {
|
|
|
524
534
|
async getCommodity(code) {
|
|
525
535
|
return this.request(`/v1/commodities/${code}`, {});
|
|
526
536
|
}
|
|
537
|
+
/**
|
|
538
|
+
* Get a multi-commodity market brief (OilPriceAPI #3245 Phase 1a).
|
|
539
|
+
*
|
|
540
|
+
* Returns a structured summary (latest price, 24h change, freshness, and a
|
|
541
|
+
* 1-month forecast band) for each requested commodity, optionally with a
|
|
542
|
+
* natural-language narrative. Counts as a single request against your quota,
|
|
543
|
+
* like `/v1/prices/batch`. The per-tier cap on `codes` is enforced server-side.
|
|
544
|
+
*
|
|
545
|
+
* @param codes - Commodity codes (e.g. ["BRENT_CRUDE_USD", "WTI_USD"]). Shorthand
|
|
546
|
+
* codes like "WTI"/"BRENT" are accepted and resolved server-side.
|
|
547
|
+
* @param options - `{ narrative }` to request the natural-language summary.
|
|
548
|
+
* @returns The structured (and optional narrative) market brief.
|
|
549
|
+
*
|
|
550
|
+
* @throws {ValidationError} If `codes` is empty.
|
|
551
|
+
*
|
|
552
|
+
* @example
|
|
553
|
+
* ```typescript
|
|
554
|
+
* const brief = await client.getMarketBrief(['BRENT_CRUDE_USD', 'WTI_USD']);
|
|
555
|
+
* for (const c of brief.commodities) {
|
|
556
|
+
* console.log(`${c.name}: $${c.price} (${c.change_24h_pct}%)`);
|
|
557
|
+
* }
|
|
558
|
+
*
|
|
559
|
+
* // With narrative
|
|
560
|
+
* const withText = await client.getMarketBrief(['BRENT_CRUDE_USD'], { narrative: true });
|
|
561
|
+
* console.log(withText.narrative);
|
|
562
|
+
* ```
|
|
563
|
+
*/
|
|
564
|
+
async getMarketBrief(codes, options) {
|
|
565
|
+
if (!Array.isArray(codes) || codes.length === 0) {
|
|
566
|
+
throw new errors_js_1.ValidationError("codes is required and must be a non-empty array of commodity codes");
|
|
567
|
+
}
|
|
568
|
+
const params = {
|
|
569
|
+
codes: codes.join(","),
|
|
570
|
+
};
|
|
571
|
+
if (options?.narrative) {
|
|
572
|
+
params.narrative = "true";
|
|
573
|
+
}
|
|
574
|
+
return this.request("/v1/market-brief", params);
|
|
575
|
+
}
|
|
527
576
|
/**
|
|
528
577
|
* Fetch live sample prices from the public, no-auth demo endpoint.
|
|
529
578
|
*
|
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.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;
|
|
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.intervalToSeconds = exports.SubscriptionsResource = 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");
|
|
@@ -25,6 +25,9 @@ var indicators_js_1 = require("./resources/indicators.js");
|
|
|
25
25
|
Object.defineProperty(exports, "IndicatorsResource", { enumerable: true, get: function () { return indicators_js_1.IndicatorsResource; } });
|
|
26
26
|
var raw_js_1 = require("./resources/raw.js");
|
|
27
27
|
Object.defineProperty(exports, "RawResource", { enumerable: true, get: function () { return raw_js_1.RawResource; } });
|
|
28
|
+
var subscriptions_js_1 = require("./resources/subscriptions.js");
|
|
29
|
+
Object.defineProperty(exports, "SubscriptionsResource", { enumerable: true, get: function () { return subscriptions_js_1.SubscriptionsResource; } });
|
|
30
|
+
Object.defineProperty(exports, "intervalToSeconds", { enumerable: true, get: function () { return subscriptions_js_1.intervalToSeconds; } });
|
|
28
31
|
var errors_js_1 = require("./errors.js");
|
|
29
32
|
Object.defineProperty(exports, "OilPriceAPIError", { enumerable: true, get: function () { return errors_js_1.OilPriceAPIError; } });
|
|
30
33
|
Object.defineProperty(exports, "AuthenticationError", { enumerable: true, get: function () { return errors_js_1.AuthenticationError; } });
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Market Brief types (OilPriceAPI #3245 Phase 1a)
|
|
4
|
+
*
|
|
5
|
+
* A multi-commodity structured (+ optional narrative) market summary composed
|
|
6
|
+
* from existing price + forecast data. Served by `GET /v1/market-brief` and
|
|
7
|
+
* surfaced on the client as {@link OilPriceAPI.getMarketBrief}.
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Real-time price streaming via the OilPriceAPI ActionCable endpoint
|
|
6
6
|
* (`wss://api.oilpriceapi.com/cable`).
|
|
7
7
|
*
|
|
8
|
-
* Streaming is a **
|
|
8
|
+
* Streaming is a **Professional plan ($99/mo) or higher** feature. Connections
|
|
9
9
|
* authenticate with your API key and subscribe to the `EnergyPricesChannel`,
|
|
10
10
|
* which pushes an initial `welcome` snapshot followed by live `price_update`
|
|
11
11
|
* and (for drilling-tier accounts) `rig_count_update` messages.
|
|
@@ -163,8 +163,8 @@ class PriceStreamSubscription extends node_events_1.EventEmitter {
|
|
|
163
163
|
return;
|
|
164
164
|
}
|
|
165
165
|
if (transportType === "reject_subscription") {
|
|
166
|
-
this.emit("error", new Error("WebSocket subscription rejected. Streaming requires a
|
|
167
|
-
"(
|
|
166
|
+
this.emit("error", new Error("WebSocket subscription rejected. Streaming requires a Professional " +
|
|
167
|
+
"plan ($99/mo) or higher and a valid API key."));
|
|
168
168
|
return;
|
|
169
169
|
}
|
|
170
170
|
if (transportType === "disconnect") {
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Agent Subscriptions ("Watches") Resource
|
|
4
|
+
*
|
|
5
|
+
* Persistent server-side "watches" that evaluate a set of commodity codes on a
|
|
6
|
+
* recurring interval and emit events an agent can poll for (OilPriceAPI #3245
|
|
7
|
+
* Phase 2). Designed for autonomous agents (MCP, schedulers, bots) that want
|
|
8
|
+
* change notifications without holding an open connection.
|
|
9
|
+
*
|
|
10
|
+
* The poll endpoint (`events`) does NOT consume the monthly request quota and
|
|
11
|
+
* has its own generous rate-limit lane, so agents can poll frequently.
|
|
12
|
+
*/
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.SubscriptionsResource = void 0;
|
|
15
|
+
exports.intervalToSeconds = intervalToSeconds;
|
|
16
|
+
const errors_js_1 = require("../errors.js");
|
|
17
|
+
/** Default attribution source for watches created via this SDK. */
|
|
18
|
+
const DEFAULT_SOURCE = "sdk-node";
|
|
19
|
+
/** Named interval presets mapped to seconds. */
|
|
20
|
+
const INTERVAL_PRESETS = {
|
|
21
|
+
"5m": 300,
|
|
22
|
+
"15m": 900,
|
|
23
|
+
"1h": 3600,
|
|
24
|
+
hourly: 3600,
|
|
25
|
+
daily: 86400,
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Convert a friendly interval ("5m" / "1h" / "daily" / 300) into seconds.
|
|
29
|
+
*
|
|
30
|
+
* Accepts:
|
|
31
|
+
* - presets: "5m", "15m", "1h", "hourly", "daily"
|
|
32
|
+
* - unit expressions: "<n>s", "<n>m", "<n>h", "<n>d"
|
|
33
|
+
* - a raw number of seconds
|
|
34
|
+
*
|
|
35
|
+
* @internal Exported for unit testing of the mapping.
|
|
36
|
+
*/
|
|
37
|
+
function intervalToSeconds(interval) {
|
|
38
|
+
if (interval === undefined) {
|
|
39
|
+
return INTERVAL_PRESETS["5m"];
|
|
40
|
+
}
|
|
41
|
+
if (typeof interval === "number") {
|
|
42
|
+
if (!Number.isFinite(interval) || interval <= 0) {
|
|
43
|
+
throw new errors_js_1.ValidationError("interval (seconds) must be a positive number");
|
|
44
|
+
}
|
|
45
|
+
return Math.floor(interval);
|
|
46
|
+
}
|
|
47
|
+
const key = interval.trim().toLowerCase();
|
|
48
|
+
if (key in INTERVAL_PRESETS) {
|
|
49
|
+
return INTERVAL_PRESETS[key];
|
|
50
|
+
}
|
|
51
|
+
// Unit expression: <number><unit> where unit ∈ s/m/h/d.
|
|
52
|
+
const match = /^(\d+)\s*(s|m|h|d)$/.exec(key);
|
|
53
|
+
if (match) {
|
|
54
|
+
const value = parseInt(match[1], 10);
|
|
55
|
+
const unit = match[2];
|
|
56
|
+
const multipliers = { s: 1, m: 60, h: 3600, d: 86400 };
|
|
57
|
+
const seconds = value * multipliers[unit];
|
|
58
|
+
if (seconds <= 0) {
|
|
59
|
+
throw new errors_js_1.ValidationError("interval must be greater than zero");
|
|
60
|
+
}
|
|
61
|
+
return seconds;
|
|
62
|
+
}
|
|
63
|
+
throw new errors_js_1.ValidationError(`Invalid interval "${interval}". Use a preset ("5m", "15m", "1h", "daily"), ` +
|
|
64
|
+
`a unit expression ("30s", "10m", "2h", "1d"), or a number of seconds.`);
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Agent Subscriptions ("Watches") Resource
|
|
68
|
+
*
|
|
69
|
+
* Manage persistent, recurring watches over commodity codes and poll for the
|
|
70
|
+
* events they emit.
|
|
71
|
+
*
|
|
72
|
+
* **Example:**
|
|
73
|
+
* ```typescript
|
|
74
|
+
* import { OilPriceAPI } from 'oilpriceapi';
|
|
75
|
+
*
|
|
76
|
+
* const client = new OilPriceAPI({ apiKey: 'your_key' });
|
|
77
|
+
*
|
|
78
|
+
* // Create a watch that evaluates Brent + WTI every 5 minutes
|
|
79
|
+
* const watch = await client.subscriptions.create({
|
|
80
|
+
* name: 'Crude desk',
|
|
81
|
+
* codes: ['BRENT_CRUDE_USD', 'WTI_USD'],
|
|
82
|
+
* interval: '5m',
|
|
83
|
+
* });
|
|
84
|
+
*
|
|
85
|
+
* // List all watches
|
|
86
|
+
* const watches = await client.subscriptions.list();
|
|
87
|
+
*
|
|
88
|
+
* // Poll for new events
|
|
89
|
+
* let cursor = 0;
|
|
90
|
+
* const { events, cursor: next } = await client.subscriptions.events({ since: cursor });
|
|
91
|
+
* cursor = next;
|
|
92
|
+
*
|
|
93
|
+
* // Remove a watch
|
|
94
|
+
* await client.subscriptions.delete(watch.id);
|
|
95
|
+
* ```
|
|
96
|
+
*/
|
|
97
|
+
class SubscriptionsResource {
|
|
98
|
+
constructor(client) {
|
|
99
|
+
this.client = client;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* List all subscriptions/watches for the authenticated user.
|
|
103
|
+
*
|
|
104
|
+
* @returns Array of subscriptions, newest first.
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* ```typescript
|
|
108
|
+
* const subscriptions = await client.subscriptions.list();
|
|
109
|
+
* console.log(`You have ${subscriptions.length} watches`);
|
|
110
|
+
* ```
|
|
111
|
+
*/
|
|
112
|
+
async list() {
|
|
113
|
+
const response = await this.client["request"]("/v1/subscriptions", {});
|
|
114
|
+
return Array.isArray(response) ? response : (response.subscriptions ?? []);
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Create a new subscription/watch.
|
|
118
|
+
*
|
|
119
|
+
* Maps the friendly `interval` ("5m" / "1h" / "daily" / seconds) to the
|
|
120
|
+
* API's `interval_seconds`, and forwards optional attribution as
|
|
121
|
+
* `X-OPA-Source` / `X-OPA-Tool` headers (source defaults to `"sdk-node"`).
|
|
122
|
+
*
|
|
123
|
+
* @param params - Watch configuration. `codes` is required.
|
|
124
|
+
* @returns The created subscription.
|
|
125
|
+
*
|
|
126
|
+
* @throws {ValidationError} If `codes` is empty or `interval` is invalid.
|
|
127
|
+
*
|
|
128
|
+
* @example
|
|
129
|
+
* ```typescript
|
|
130
|
+
* const watch = await client.subscriptions.create({
|
|
131
|
+
* name: 'Crude desk',
|
|
132
|
+
* codes: ['BRENT_CRUDE_USD', 'WTI_USD'],
|
|
133
|
+
* interval: '1h',
|
|
134
|
+
* tool: 'my-trading-bot',
|
|
135
|
+
* });
|
|
136
|
+
* ```
|
|
137
|
+
*/
|
|
138
|
+
async create(params) {
|
|
139
|
+
if (!params || !Array.isArray(params.codes) || params.codes.length === 0) {
|
|
140
|
+
throw new errors_js_1.ValidationError("codes is required and must be a non-empty array of commodity codes");
|
|
141
|
+
}
|
|
142
|
+
if (params.codes.some((c) => typeof c !== "string" || c.trim() === "")) {
|
|
143
|
+
throw new errors_js_1.ValidationError("every code must be a non-empty string");
|
|
144
|
+
}
|
|
145
|
+
const intervalSeconds = intervalToSeconds(params.interval);
|
|
146
|
+
const body = {
|
|
147
|
+
codes: params.codes,
|
|
148
|
+
interval_seconds: intervalSeconds,
|
|
149
|
+
};
|
|
150
|
+
if (params.name !== undefined) {
|
|
151
|
+
body.name = params.name;
|
|
152
|
+
}
|
|
153
|
+
if (params.deliverWebhook !== undefined) {
|
|
154
|
+
body.deliver_webhook = params.deliverWebhook;
|
|
155
|
+
}
|
|
156
|
+
const headers = {
|
|
157
|
+
"X-OPA-Source": params.source ?? DEFAULT_SOURCE,
|
|
158
|
+
};
|
|
159
|
+
if (params.tool !== undefined) {
|
|
160
|
+
headers["X-OPA-Tool"] = params.tool;
|
|
161
|
+
}
|
|
162
|
+
const response = await this.client["request"]("/v1/subscriptions", {}, { method: "POST", body, headers });
|
|
163
|
+
return "subscription" in response ? response.subscription : response;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Delete a subscription/watch.
|
|
167
|
+
*
|
|
168
|
+
* @param id - The subscription ID to delete.
|
|
169
|
+
*
|
|
170
|
+
* @throws {ValidationError} If `id` is not a non-empty string.
|
|
171
|
+
*
|
|
172
|
+
* @example
|
|
173
|
+
* ```typescript
|
|
174
|
+
* await client.subscriptions.delete(watch.id);
|
|
175
|
+
* ```
|
|
176
|
+
*/
|
|
177
|
+
async delete(id) {
|
|
178
|
+
if (!id || typeof id !== "string") {
|
|
179
|
+
throw new errors_js_1.ValidationError("Subscription ID must be a non-empty string");
|
|
180
|
+
}
|
|
181
|
+
await this.client["request"](`/v1/subscriptions/${id}`, {}, { method: "DELETE" });
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Poll for events emitted by your watches.
|
|
185
|
+
*
|
|
186
|
+
* Returns events with `seq` greater than the supplied cursor, ordered
|
|
187
|
+
* ascending. This endpoint does NOT consume the monthly request quota.
|
|
188
|
+
*
|
|
189
|
+
* @param options - Cursor (`since`), optional `watchId`, and `limit`.
|
|
190
|
+
* @returns The next cursor, a `has_more` flag, and the events.
|
|
191
|
+
*
|
|
192
|
+
* @example
|
|
193
|
+
* ```typescript
|
|
194
|
+
* let cursor = 0;
|
|
195
|
+
* while (true) {
|
|
196
|
+
* const { events, cursor: next, has_more } = await client.subscriptions.events({ since: cursor });
|
|
197
|
+
* for (const ev of events) handle(ev);
|
|
198
|
+
* cursor = next;
|
|
199
|
+
* if (!has_more) break;
|
|
200
|
+
* }
|
|
201
|
+
* ```
|
|
202
|
+
*/
|
|
203
|
+
async events(options = {}) {
|
|
204
|
+
const params = {};
|
|
205
|
+
if (options.since !== undefined) {
|
|
206
|
+
params.since = String(options.since);
|
|
207
|
+
}
|
|
208
|
+
if (options.watchId !== undefined) {
|
|
209
|
+
params.watch_id = options.watchId;
|
|
210
|
+
}
|
|
211
|
+
if (options.limit !== undefined) {
|
|
212
|
+
params.limit = String(options.limit);
|
|
213
|
+
}
|
|
214
|
+
return this.client["request"]("/v1/subscriptions/events", params);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
exports.SubscriptionsResource = SubscriptionsResource;
|
package/dist/cjs/version.js
CHANGED
package/dist/client.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { OilPriceAPIConfig, Price, LatestPricesOptions, HistoricalPricesOptions, Commodity, CommoditiesResponse, CategoriesResponse, DataConnectorPrice, DataConnectorOptions, DemoPricesResponse, DemoCommoditiesResponse } from "./types.js";
|
|
2
|
+
import type { MarketBrief, MarketBriefOptions } from "./resources/market-brief.js";
|
|
2
3
|
import { DieselResource } from "./resources/diesel.js";
|
|
3
4
|
import { AlertsResource } from "./resources/alerts.js";
|
|
4
5
|
import { CommoditiesResource } from "./resources/commodities.js";
|
|
@@ -17,6 +18,7 @@ import { SpreadsResource } from "./resources/spreads.js";
|
|
|
17
18
|
import { IndicatorsResource } from "./resources/indicators.js";
|
|
18
19
|
import { RawResource } from "./resources/raw.js";
|
|
19
20
|
import { StreamingResource } from "./resources/streaming.js";
|
|
21
|
+
import { SubscriptionsResource } from "./resources/subscriptions.js";
|
|
20
22
|
/**
|
|
21
23
|
* Raw HTTP response wrapper.
|
|
22
24
|
*
|
|
@@ -144,9 +146,14 @@ export declare class OilPriceAPI {
|
|
|
144
146
|
/**
|
|
145
147
|
* Real-time price streaming resource (WebSocket / ActionCable).
|
|
146
148
|
*
|
|
147
|
-
* Streaming requires a
|
|
149
|
+
* Streaming requires a Professional plan ($99/mo) or higher.
|
|
148
150
|
*/
|
|
149
151
|
readonly stream: StreamingResource;
|
|
152
|
+
/**
|
|
153
|
+
* Agent subscriptions ("watches") resource — persistent recurring watches
|
|
154
|
+
* over commodity codes plus an event poll endpoint (#3245 Phase 2).
|
|
155
|
+
*/
|
|
156
|
+
readonly subscriptions: SubscriptionsResource;
|
|
150
157
|
constructor(config?: OilPriceAPIConfig);
|
|
151
158
|
/**
|
|
152
159
|
* Log debug messages if debug mode is enabled
|
|
@@ -311,6 +318,34 @@ export declare class OilPriceAPI {
|
|
|
311
318
|
* ```
|
|
312
319
|
*/
|
|
313
320
|
getCommodity(code: string): Promise<Commodity>;
|
|
321
|
+
/**
|
|
322
|
+
* Get a multi-commodity market brief (OilPriceAPI #3245 Phase 1a).
|
|
323
|
+
*
|
|
324
|
+
* Returns a structured summary (latest price, 24h change, freshness, and a
|
|
325
|
+
* 1-month forecast band) for each requested commodity, optionally with a
|
|
326
|
+
* natural-language narrative. Counts as a single request against your quota,
|
|
327
|
+
* like `/v1/prices/batch`. The per-tier cap on `codes` is enforced server-side.
|
|
328
|
+
*
|
|
329
|
+
* @param codes - Commodity codes (e.g. ["BRENT_CRUDE_USD", "WTI_USD"]). Shorthand
|
|
330
|
+
* codes like "WTI"/"BRENT" are accepted and resolved server-side.
|
|
331
|
+
* @param options - `{ narrative }` to request the natural-language summary.
|
|
332
|
+
* @returns The structured (and optional narrative) market brief.
|
|
333
|
+
*
|
|
334
|
+
* @throws {ValidationError} If `codes` is empty.
|
|
335
|
+
*
|
|
336
|
+
* @example
|
|
337
|
+
* ```typescript
|
|
338
|
+
* const brief = await client.getMarketBrief(['BRENT_CRUDE_USD', 'WTI_USD']);
|
|
339
|
+
* for (const c of brief.commodities) {
|
|
340
|
+
* console.log(`${c.name}: $${c.price} (${c.change_24h_pct}%)`);
|
|
341
|
+
* }
|
|
342
|
+
*
|
|
343
|
+
* // With narrative
|
|
344
|
+
* const withText = await client.getMarketBrief(['BRENT_CRUDE_USD'], { narrative: true });
|
|
345
|
+
* console.log(withText.narrative);
|
|
346
|
+
* ```
|
|
347
|
+
*/
|
|
348
|
+
getMarketBrief(codes: string[], options?: MarketBriefOptions): Promise<MarketBrief>;
|
|
314
349
|
/**
|
|
315
350
|
* Fetch live sample prices from the public, no-auth demo endpoint.
|
|
316
351
|
*
|
package/dist/client.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { OilPriceAPIError, AuthenticationError, RateLimitError, NotFoundError, ServerError, TimeoutError, } from "./errors.js";
|
|
1
|
+
import { OilPriceAPIError, AuthenticationError, RateLimitError, NotFoundError, ServerError, TimeoutError, ValidationError, } from "./errors.js";
|
|
2
2
|
import { DieselResource } from "./resources/diesel.js";
|
|
3
3
|
import { AlertsResource } from "./resources/alerts.js";
|
|
4
4
|
import { CommoditiesResource } from "./resources/commodities.js";
|
|
@@ -18,6 +18,7 @@ import { SpreadsResource } from "./resources/spreads.js";
|
|
|
18
18
|
import { IndicatorsResource } from "./resources/indicators.js";
|
|
19
19
|
import { RawResource } from "./resources/raw.js";
|
|
20
20
|
import { StreamingResource } from "./resources/streaming.js";
|
|
21
|
+
import { SubscriptionsResource } from "./resources/subscriptions.js";
|
|
21
22
|
/**
|
|
22
23
|
* Official Node.js client for Oil Price API
|
|
23
24
|
*
|
|
@@ -77,6 +78,7 @@ export class OilPriceAPI {
|
|
|
77
78
|
this.indicators = new IndicatorsResource(this);
|
|
78
79
|
this.raw = new RawResource(this);
|
|
79
80
|
this.stream = new StreamingResource(this);
|
|
81
|
+
this.subscriptions = new SubscriptionsResource(this);
|
|
80
82
|
}
|
|
81
83
|
/**
|
|
82
84
|
* Log debug messages if debug mode is enabled
|
|
@@ -212,6 +214,14 @@ export class OilPriceAPI {
|
|
|
212
214
|
if (this.appName) {
|
|
213
215
|
headers["X-App-Name"] = this.appName;
|
|
214
216
|
}
|
|
217
|
+
// Per-request headers (e.g. MCP attribution X-OPA-Source / X-OPA-Tool).
|
|
218
|
+
if (options?.headers) {
|
|
219
|
+
Object.entries(options.headers).forEach(([key, value]) => {
|
|
220
|
+
if (value !== undefined && value !== null) {
|
|
221
|
+
headers[key] = value;
|
|
222
|
+
}
|
|
223
|
+
});
|
|
224
|
+
}
|
|
215
225
|
const fetchOptions = {
|
|
216
226
|
method: options?.method || "GET",
|
|
217
227
|
headers,
|
|
@@ -521,6 +531,45 @@ export class OilPriceAPI {
|
|
|
521
531
|
async getCommodity(code) {
|
|
522
532
|
return this.request(`/v1/commodities/${code}`, {});
|
|
523
533
|
}
|
|
534
|
+
/**
|
|
535
|
+
* Get a multi-commodity market brief (OilPriceAPI #3245 Phase 1a).
|
|
536
|
+
*
|
|
537
|
+
* Returns a structured summary (latest price, 24h change, freshness, and a
|
|
538
|
+
* 1-month forecast band) for each requested commodity, optionally with a
|
|
539
|
+
* natural-language narrative. Counts as a single request against your quota,
|
|
540
|
+
* like `/v1/prices/batch`. The per-tier cap on `codes` is enforced server-side.
|
|
541
|
+
*
|
|
542
|
+
* @param codes - Commodity codes (e.g. ["BRENT_CRUDE_USD", "WTI_USD"]). Shorthand
|
|
543
|
+
* codes like "WTI"/"BRENT" are accepted and resolved server-side.
|
|
544
|
+
* @param options - `{ narrative }` to request the natural-language summary.
|
|
545
|
+
* @returns The structured (and optional narrative) market brief.
|
|
546
|
+
*
|
|
547
|
+
* @throws {ValidationError} If `codes` is empty.
|
|
548
|
+
*
|
|
549
|
+
* @example
|
|
550
|
+
* ```typescript
|
|
551
|
+
* const brief = await client.getMarketBrief(['BRENT_CRUDE_USD', 'WTI_USD']);
|
|
552
|
+
* for (const c of brief.commodities) {
|
|
553
|
+
* console.log(`${c.name}: $${c.price} (${c.change_24h_pct}%)`);
|
|
554
|
+
* }
|
|
555
|
+
*
|
|
556
|
+
* // With narrative
|
|
557
|
+
* const withText = await client.getMarketBrief(['BRENT_CRUDE_USD'], { narrative: true });
|
|
558
|
+
* console.log(withText.narrative);
|
|
559
|
+
* ```
|
|
560
|
+
*/
|
|
561
|
+
async getMarketBrief(codes, options) {
|
|
562
|
+
if (!Array.isArray(codes) || codes.length === 0) {
|
|
563
|
+
throw new ValidationError("codes is required and must be a non-empty array of commodity codes");
|
|
564
|
+
}
|
|
565
|
+
const params = {
|
|
566
|
+
codes: codes.join(","),
|
|
567
|
+
};
|
|
568
|
+
if (options?.narrative) {
|
|
569
|
+
params.narrative = "true";
|
|
570
|
+
}
|
|
571
|
+
return this.request("/v1/market-brief", params);
|
|
572
|
+
}
|
|
524
573
|
/**
|
|
525
574
|
* Fetch live sample prices from the public, no-auth demo endpoint.
|
|
526
575
|
*
|
package/dist/index.d.ts
CHANGED
|
@@ -26,6 +26,9 @@ export type { MonthlyForecast, ForecastAccuracy, ArchivedForecast } from "./reso
|
|
|
26
26
|
export type { DataQualitySummary, DataQualityReportMeta, DataQualityReport, } from "./resources/data-quality.js";
|
|
27
27
|
export type { DrillingIntelligenceData, LatestDrillingData, DrillingSummary, DrillingTrend, FracSpreadData, WellPermitData, DUCWellData, CompletionData, WellsDrilledData, BasinDrillingData, } from "./resources/drilling.js";
|
|
28
28
|
export type { WellTimelineEvent, WellTimeline, RigCountRecord, RigCountByBasin, RigCountByState, HistoricalRigCount, OilInventoryRecord, OilInventorySummary, InventoryByProduct, HistoricalInventory, CushingInventory, OPECProductionRecord, TotalOPECProduction, ProductionByCountry, HistoricalProduction, TopProducer, DrillingProductivityRecord, DrillingProductivitySummary, DUCWellInventory, ProductivityByBasin, HistoricalProductivity, ProductivityTrend, ForecastRecord, ForecastSummary, PriceForecast, ProductionForecast, HistoricalForecast, ForecastComparison, WellPermitRecord, WellPermitSummary, PermitsByState, PermitsByOperator, PermitsByFormation, WellPermitSearchQuery, FracFocusRecord, FracFocusSummary, DisclosuresByState, DisclosuresByOperator, ChemicalUsage, WellChemical, FracFocusSearchQuery, } from "./resources/ei/index.js";
|
|
29
|
+
export type { MarketBrief, MarketBriefCommodity, MarketBriefForecast, MarketBriefOptions, } from "./resources/market-brief.js";
|
|
30
|
+
export type { Subscription, SubscriptionStatus, SubscriptionSource, SubscriptionInterval, CreateSubscriptionParams, SubscriptionEvent, SubscriptionEventsResult, SubscriptionEventsOptions, } from "./resources/subscriptions.js";
|
|
31
|
+
export { SubscriptionsResource, intervalToSeconds } from "./resources/subscriptions.js";
|
|
29
32
|
export type { WebhookEndpoint, CreateWebhookParams, UpdateWebhookParams, WebhookTestResponse as WebhookTestResult, WebhookEvent, } from "./resources/webhooks.js";
|
|
30
33
|
export type { DataSourceType, DataSourceStatus, DataSource, CreateDataSourceParams, UpdateDataSourceParams, DataSourceTestResponse, DataSourceLog, DataSourceHealth, CredentialRotationResponse, } from "./resources/data-sources.js";
|
|
31
34
|
export { OilPriceAPIError, AuthenticationError, RateLimitError, NotFoundError, ServerError, ValidationError, TimeoutError, } from "./errors.js";
|
package/dist/index.js
CHANGED
|
@@ -12,6 +12,7 @@ export { FUTURES_CONTRACTS, FUTURES_FAMILY_SLUGS, FuturesContractFamily, } from
|
|
|
12
12
|
export { SpreadsResource } from "./resources/spreads.js";
|
|
13
13
|
export { IndicatorsResource } from "./resources/indicators.js";
|
|
14
14
|
export { RawResource } from "./resources/raw.js";
|
|
15
|
+
export { SubscriptionsResource, intervalToSeconds } from "./resources/subscriptions.js";
|
|
15
16
|
export { OilPriceAPIError, AuthenticationError, RateLimitError, NotFoundError, ServerError, ValidationError, TimeoutError, } from "./errors.js";
|
|
16
17
|
export { DieselResource } from "./resources/diesel.js";
|
|
17
18
|
export { AlertsResource } from "./resources/alerts.js";
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Market Brief types (OilPriceAPI #3245 Phase 1a)
|
|
3
|
+
*
|
|
4
|
+
* A multi-commodity structured (+ optional narrative) market summary composed
|
|
5
|
+
* from existing price + forecast data. Served by `GET /v1/market-brief` and
|
|
6
|
+
* surfaced on the client as {@link OilPriceAPI.getMarketBrief}.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Short-horizon (1-month) point forecast for a commodity in a market brief.
|
|
10
|
+
*/
|
|
11
|
+
export interface MarketBriefForecast {
|
|
12
|
+
/** Central point estimate. */
|
|
13
|
+
point: number;
|
|
14
|
+
/** Low end of the forecast band. */
|
|
15
|
+
low: number;
|
|
16
|
+
/** High end of the forecast band. */
|
|
17
|
+
high: number;
|
|
18
|
+
/** Model confidence label (e.g. "low", "medium", "high"). */
|
|
19
|
+
confidence: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* One commodity's slice of a market brief.
|
|
23
|
+
*/
|
|
24
|
+
export interface MarketBriefCommodity {
|
|
25
|
+
/** Commodity code (e.g. "BRENT_CRUDE_USD"). */
|
|
26
|
+
code: string;
|
|
27
|
+
/** Human-readable commodity name. */
|
|
28
|
+
name: string;
|
|
29
|
+
/** Latest price. */
|
|
30
|
+
price: number;
|
|
31
|
+
/** ISO currency code (e.g. "USD"). */
|
|
32
|
+
currency: string;
|
|
33
|
+
/** Price unit (e.g. "barrel"). */
|
|
34
|
+
unit: string;
|
|
35
|
+
/** 24h percentage change. */
|
|
36
|
+
change_24h_pct: number;
|
|
37
|
+
/** 24h absolute change. */
|
|
38
|
+
change_24h_abs: number;
|
|
39
|
+
/** ISO timestamp the price was observed. */
|
|
40
|
+
as_of: string;
|
|
41
|
+
/** Upstream data source. */
|
|
42
|
+
source: string;
|
|
43
|
+
/** True when the price is stale (no fresh update). */
|
|
44
|
+
stale: boolean;
|
|
45
|
+
/** 1-month forecast band, when available. */
|
|
46
|
+
forecast_1m: MarketBriefForecast | null;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* A multi-commodity market brief.
|
|
50
|
+
*
|
|
51
|
+
* Returned by {@link OilPriceAPI.getMarketBrief}.
|
|
52
|
+
*/
|
|
53
|
+
export interface MarketBrief {
|
|
54
|
+
/** ISO timestamp the brief was generated. */
|
|
55
|
+
as_of: string;
|
|
56
|
+
/** The (resolved, canonical) codes included in the brief. */
|
|
57
|
+
codes: string[];
|
|
58
|
+
/** Per-commodity structured summary. */
|
|
59
|
+
commodities: MarketBriefCommodity[];
|
|
60
|
+
/** Optional natural-language narrative (only when `narrative: true`). */
|
|
61
|
+
narrative?: string;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Options for {@link OilPriceAPI.getMarketBrief}.
|
|
65
|
+
*/
|
|
66
|
+
export interface MarketBriefOptions {
|
|
67
|
+
/**
|
|
68
|
+
* Request a natural-language narrative alongside the structured data.
|
|
69
|
+
* Defaults to `false`.
|
|
70
|
+
*/
|
|
71
|
+
narrative?: boolean;
|
|
72
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Market Brief types (OilPriceAPI #3245 Phase 1a)
|
|
3
|
+
*
|
|
4
|
+
* A multi-commodity structured (+ optional narrative) market summary composed
|
|
5
|
+
* from existing price + forecast data. Served by `GET /v1/market-brief` and
|
|
6
|
+
* surfaced on the client as {@link OilPriceAPI.getMarketBrief}.
|
|
7
|
+
*/
|
|
8
|
+
export {};
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Real-time price streaming via the OilPriceAPI ActionCable endpoint
|
|
5
5
|
* (`wss://api.oilpriceapi.com/cable`).
|
|
6
6
|
*
|
|
7
|
-
* Streaming is a **
|
|
7
|
+
* Streaming is a **Professional plan ($99/mo) or higher** feature. Connections
|
|
8
8
|
* authenticate with your API key and subscribe to the `EnergyPricesChannel`,
|
|
9
9
|
* which pushes an initial `welcome` snapshot followed by live `price_update`
|
|
10
10
|
* and (for drilling-tier accounts) `rig_count_update` messages.
|
|
@@ -105,7 +105,7 @@ export interface WelcomeMessage {
|
|
|
105
105
|
};
|
|
106
106
|
}
|
|
107
107
|
/**
|
|
108
|
-
* Rig-count update broadcast (drilling /
|
|
108
|
+
* Rig-count update broadcast (drilling / Professional+ accounts).
|
|
109
109
|
*/
|
|
110
110
|
export interface RigCountUpdateMessage {
|
|
111
111
|
type: "rig_count_update";
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Real-time price streaming via the OilPriceAPI ActionCable endpoint
|
|
5
5
|
* (`wss://api.oilpriceapi.com/cable`).
|
|
6
6
|
*
|
|
7
|
-
* Streaming is a **
|
|
7
|
+
* Streaming is a **Professional plan ($99/mo) or higher** feature. Connections
|
|
8
8
|
* authenticate with your API key and subscribe to the `EnergyPricesChannel`,
|
|
9
9
|
* which pushes an initial `welcome` snapshot followed by live `price_update`
|
|
10
10
|
* and (for drilling-tier accounts) `rig_count_update` messages.
|
|
@@ -157,8 +157,8 @@ export class PriceStreamSubscription extends EventEmitter {
|
|
|
157
157
|
return;
|
|
158
158
|
}
|
|
159
159
|
if (transportType === "reject_subscription") {
|
|
160
|
-
this.emit("error", new Error("WebSocket subscription rejected. Streaming requires a
|
|
161
|
-
"(
|
|
160
|
+
this.emit("error", new Error("WebSocket subscription rejected. Streaming requires a Professional " +
|
|
161
|
+
"plan ($99/mo) or higher and a valid API key."));
|
|
162
162
|
return;
|
|
163
163
|
}
|
|
164
164
|
if (transportType === "disconnect") {
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent Subscriptions ("Watches") Resource
|
|
3
|
+
*
|
|
4
|
+
* Persistent server-side "watches" that evaluate a set of commodity codes on a
|
|
5
|
+
* recurring interval and emit events an agent can poll for (OilPriceAPI #3245
|
|
6
|
+
* Phase 2). Designed for autonomous agents (MCP, schedulers, bots) that want
|
|
7
|
+
* change notifications without holding an open connection.
|
|
8
|
+
*
|
|
9
|
+
* The poll endpoint (`events`) does NOT consume the monthly request quota and
|
|
10
|
+
* has its own generous rate-limit lane, so agents can poll frequently.
|
|
11
|
+
*/
|
|
12
|
+
import type { OilPriceAPI } from "../client.js";
|
|
13
|
+
/**
|
|
14
|
+
* Lifecycle status of a subscription/watch.
|
|
15
|
+
*/
|
|
16
|
+
export type SubscriptionStatus = "active" | "paused";
|
|
17
|
+
/**
|
|
18
|
+
* Attribution source recorded on a watch. Defaults to `"sdk-node"` when created
|
|
19
|
+
* via this SDK. The API canonicalizes unknown values to `"api"`.
|
|
20
|
+
*/
|
|
21
|
+
export type SubscriptionSource = string;
|
|
22
|
+
/**
|
|
23
|
+
* A persistent agent subscription ("watch").
|
|
24
|
+
*
|
|
25
|
+
* Returned by {@link SubscriptionsResource.list} and
|
|
26
|
+
* {@link SubscriptionsResource.create}.
|
|
27
|
+
*/
|
|
28
|
+
export interface Subscription {
|
|
29
|
+
/** Unique watch identifier (UUID). */
|
|
30
|
+
id: string;
|
|
31
|
+
/** User-friendly watch name. */
|
|
32
|
+
name: string | null;
|
|
33
|
+
/** Commodity codes this watch evaluates (e.g. ["BRENT_CRUDE_USD"]). */
|
|
34
|
+
codes: string[];
|
|
35
|
+
/** Evaluation cadence in seconds. */
|
|
36
|
+
interval_seconds: number;
|
|
37
|
+
/** Lifecycle status. */
|
|
38
|
+
status: SubscriptionStatus;
|
|
39
|
+
/** Whether matching events are also delivered via webhook. */
|
|
40
|
+
deliver_webhook: boolean;
|
|
41
|
+
/** Attribution source (e.g. "sdk-node", "mcp", "api"). */
|
|
42
|
+
source: string;
|
|
43
|
+
/** Attribution tool name, if any. */
|
|
44
|
+
tool_name: string | null;
|
|
45
|
+
/** ISO timestamp the watch was last evaluated, or null. */
|
|
46
|
+
last_evaluated_at: string | null;
|
|
47
|
+
/** ISO timestamp the watch is next scheduled to run, or null. */
|
|
48
|
+
next_run_at: string | null;
|
|
49
|
+
/** ISO timestamp when the watch was created. */
|
|
50
|
+
created_at: string;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* A friendly interval expression accepted by {@link SubscriptionsResource.create}.
|
|
54
|
+
*
|
|
55
|
+
* Either a preset string ("5m", "15m", "1h", "daily") or an explicit number of
|
|
56
|
+
* seconds.
|
|
57
|
+
*/
|
|
58
|
+
export type SubscriptionInterval = "5m" | "15m" | "1h" | "daily" | (string & {}) | number;
|
|
59
|
+
/**
|
|
60
|
+
* Parameters for creating a new subscription/watch.
|
|
61
|
+
*/
|
|
62
|
+
export interface CreateSubscriptionParams {
|
|
63
|
+
/** Commodity codes to watch (e.g. ["BRENT_CRUDE_USD", "WTI_USD"]). Required. */
|
|
64
|
+
codes: string[];
|
|
65
|
+
/**
|
|
66
|
+
* Evaluation cadence. A friendly preset ("5m" / "15m" / "1h" / "daily"), a
|
|
67
|
+
* `<n>m` / `<n>h` / `<n>d` / `<n>s` expression, or a number of seconds.
|
|
68
|
+
* Defaults to "5m" when omitted.
|
|
69
|
+
*/
|
|
70
|
+
interval?: SubscriptionInterval;
|
|
71
|
+
/** Optional friendly watch name. */
|
|
72
|
+
name?: string;
|
|
73
|
+
/** Whether to also deliver matching events via webhook. */
|
|
74
|
+
deliverWebhook?: boolean;
|
|
75
|
+
/**
|
|
76
|
+
* Attribution source → `X-OPA-Source` header. Defaults to `"sdk-node"`.
|
|
77
|
+
*/
|
|
78
|
+
source?: string;
|
|
79
|
+
/** Attribution tool name → `X-OPA-Tool` header. */
|
|
80
|
+
tool?: string;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* A single event emitted by a watch evaluation.
|
|
84
|
+
*
|
|
85
|
+
* The exact payload depends on the event type; common fields are surfaced here
|
|
86
|
+
* while the full server payload is preserved via the index signature.
|
|
87
|
+
*/
|
|
88
|
+
export interface SubscriptionEvent {
|
|
89
|
+
/** Monotonic per-user sequence number; use as the `since` cursor. */
|
|
90
|
+
seq: number;
|
|
91
|
+
/** The watch that produced this event. */
|
|
92
|
+
watch_id: string;
|
|
93
|
+
/** Event type (e.g. "evaluated", "threshold_crossed"). */
|
|
94
|
+
type?: string;
|
|
95
|
+
/** Commodity code the event concerns, if applicable. */
|
|
96
|
+
code?: string;
|
|
97
|
+
/** ISO timestamp the event was emitted. */
|
|
98
|
+
created_at?: string;
|
|
99
|
+
/** Any additional server-provided fields. */
|
|
100
|
+
[key: string]: unknown;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Response from {@link SubscriptionsResource.events}.
|
|
104
|
+
*/
|
|
105
|
+
export interface SubscriptionEventsResult {
|
|
106
|
+
/** The highest `seq` returned; pass as `since` on the next poll. */
|
|
107
|
+
cursor: number;
|
|
108
|
+
/** True if more events are available beyond this page. */
|
|
109
|
+
has_more: boolean;
|
|
110
|
+
/** Events with `seq > since`, ordered ascending by `seq`. */
|
|
111
|
+
events: SubscriptionEvent[];
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Options for {@link SubscriptionsResource.events}.
|
|
115
|
+
*/
|
|
116
|
+
export interface SubscriptionEventsOptions {
|
|
117
|
+
/** Return only events with `seq` greater than this cursor. Defaults to 0. */
|
|
118
|
+
since?: number;
|
|
119
|
+
/** Restrict to a single watch by id. */
|
|
120
|
+
watchId?: string;
|
|
121
|
+
/** Max events to return (1-500, server default 100). */
|
|
122
|
+
limit?: number;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Convert a friendly interval ("5m" / "1h" / "daily" / 300) into seconds.
|
|
126
|
+
*
|
|
127
|
+
* Accepts:
|
|
128
|
+
* - presets: "5m", "15m", "1h", "hourly", "daily"
|
|
129
|
+
* - unit expressions: "<n>s", "<n>m", "<n>h", "<n>d"
|
|
130
|
+
* - a raw number of seconds
|
|
131
|
+
*
|
|
132
|
+
* @internal Exported for unit testing of the mapping.
|
|
133
|
+
*/
|
|
134
|
+
export declare function intervalToSeconds(interval: SubscriptionInterval | undefined): number;
|
|
135
|
+
/**
|
|
136
|
+
* Agent Subscriptions ("Watches") Resource
|
|
137
|
+
*
|
|
138
|
+
* Manage persistent, recurring watches over commodity codes and poll for the
|
|
139
|
+
* events they emit.
|
|
140
|
+
*
|
|
141
|
+
* **Example:**
|
|
142
|
+
* ```typescript
|
|
143
|
+
* import { OilPriceAPI } from 'oilpriceapi';
|
|
144
|
+
*
|
|
145
|
+
* const client = new OilPriceAPI({ apiKey: 'your_key' });
|
|
146
|
+
*
|
|
147
|
+
* // Create a watch that evaluates Brent + WTI every 5 minutes
|
|
148
|
+
* const watch = await client.subscriptions.create({
|
|
149
|
+
* name: 'Crude desk',
|
|
150
|
+
* codes: ['BRENT_CRUDE_USD', 'WTI_USD'],
|
|
151
|
+
* interval: '5m',
|
|
152
|
+
* });
|
|
153
|
+
*
|
|
154
|
+
* // List all watches
|
|
155
|
+
* const watches = await client.subscriptions.list();
|
|
156
|
+
*
|
|
157
|
+
* // Poll for new events
|
|
158
|
+
* let cursor = 0;
|
|
159
|
+
* const { events, cursor: next } = await client.subscriptions.events({ since: cursor });
|
|
160
|
+
* cursor = next;
|
|
161
|
+
*
|
|
162
|
+
* // Remove a watch
|
|
163
|
+
* await client.subscriptions.delete(watch.id);
|
|
164
|
+
* ```
|
|
165
|
+
*/
|
|
166
|
+
export declare class SubscriptionsResource {
|
|
167
|
+
private client;
|
|
168
|
+
constructor(client: OilPriceAPI);
|
|
169
|
+
/**
|
|
170
|
+
* List all subscriptions/watches for the authenticated user.
|
|
171
|
+
*
|
|
172
|
+
* @returns Array of subscriptions, newest first.
|
|
173
|
+
*
|
|
174
|
+
* @example
|
|
175
|
+
* ```typescript
|
|
176
|
+
* const subscriptions = await client.subscriptions.list();
|
|
177
|
+
* console.log(`You have ${subscriptions.length} watches`);
|
|
178
|
+
* ```
|
|
179
|
+
*/
|
|
180
|
+
list(): Promise<Subscription[]>;
|
|
181
|
+
/**
|
|
182
|
+
* Create a new subscription/watch.
|
|
183
|
+
*
|
|
184
|
+
* Maps the friendly `interval` ("5m" / "1h" / "daily" / seconds) to the
|
|
185
|
+
* API's `interval_seconds`, and forwards optional attribution as
|
|
186
|
+
* `X-OPA-Source` / `X-OPA-Tool` headers (source defaults to `"sdk-node"`).
|
|
187
|
+
*
|
|
188
|
+
* @param params - Watch configuration. `codes` is required.
|
|
189
|
+
* @returns The created subscription.
|
|
190
|
+
*
|
|
191
|
+
* @throws {ValidationError} If `codes` is empty or `interval` is invalid.
|
|
192
|
+
*
|
|
193
|
+
* @example
|
|
194
|
+
* ```typescript
|
|
195
|
+
* const watch = await client.subscriptions.create({
|
|
196
|
+
* name: 'Crude desk',
|
|
197
|
+
* codes: ['BRENT_CRUDE_USD', 'WTI_USD'],
|
|
198
|
+
* interval: '1h',
|
|
199
|
+
* tool: 'my-trading-bot',
|
|
200
|
+
* });
|
|
201
|
+
* ```
|
|
202
|
+
*/
|
|
203
|
+
create(params: CreateSubscriptionParams): Promise<Subscription>;
|
|
204
|
+
/**
|
|
205
|
+
* Delete a subscription/watch.
|
|
206
|
+
*
|
|
207
|
+
* @param id - The subscription ID to delete.
|
|
208
|
+
*
|
|
209
|
+
* @throws {ValidationError} If `id` is not a non-empty string.
|
|
210
|
+
*
|
|
211
|
+
* @example
|
|
212
|
+
* ```typescript
|
|
213
|
+
* await client.subscriptions.delete(watch.id);
|
|
214
|
+
* ```
|
|
215
|
+
*/
|
|
216
|
+
delete(id: string): Promise<void>;
|
|
217
|
+
/**
|
|
218
|
+
* Poll for events emitted by your watches.
|
|
219
|
+
*
|
|
220
|
+
* Returns events with `seq` greater than the supplied cursor, ordered
|
|
221
|
+
* ascending. This endpoint does NOT consume the monthly request quota.
|
|
222
|
+
*
|
|
223
|
+
* @param options - Cursor (`since`), optional `watchId`, and `limit`.
|
|
224
|
+
* @returns The next cursor, a `has_more` flag, and the events.
|
|
225
|
+
*
|
|
226
|
+
* @example
|
|
227
|
+
* ```typescript
|
|
228
|
+
* let cursor = 0;
|
|
229
|
+
* while (true) {
|
|
230
|
+
* const { events, cursor: next, has_more } = await client.subscriptions.events({ since: cursor });
|
|
231
|
+
* for (const ev of events) handle(ev);
|
|
232
|
+
* cursor = next;
|
|
233
|
+
* if (!has_more) break;
|
|
234
|
+
* }
|
|
235
|
+
* ```
|
|
236
|
+
*/
|
|
237
|
+
events(options?: SubscriptionEventsOptions): Promise<SubscriptionEventsResult>;
|
|
238
|
+
}
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent Subscriptions ("Watches") Resource
|
|
3
|
+
*
|
|
4
|
+
* Persistent server-side "watches" that evaluate a set of commodity codes on a
|
|
5
|
+
* recurring interval and emit events an agent can poll for (OilPriceAPI #3245
|
|
6
|
+
* Phase 2). Designed for autonomous agents (MCP, schedulers, bots) that want
|
|
7
|
+
* change notifications without holding an open connection.
|
|
8
|
+
*
|
|
9
|
+
* The poll endpoint (`events`) does NOT consume the monthly request quota and
|
|
10
|
+
* has its own generous rate-limit lane, so agents can poll frequently.
|
|
11
|
+
*/
|
|
12
|
+
import { ValidationError } from "../errors.js";
|
|
13
|
+
/** Default attribution source for watches created via this SDK. */
|
|
14
|
+
const DEFAULT_SOURCE = "sdk-node";
|
|
15
|
+
/** Named interval presets mapped to seconds. */
|
|
16
|
+
const INTERVAL_PRESETS = {
|
|
17
|
+
"5m": 300,
|
|
18
|
+
"15m": 900,
|
|
19
|
+
"1h": 3600,
|
|
20
|
+
hourly: 3600,
|
|
21
|
+
daily: 86400,
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Convert a friendly interval ("5m" / "1h" / "daily" / 300) into seconds.
|
|
25
|
+
*
|
|
26
|
+
* Accepts:
|
|
27
|
+
* - presets: "5m", "15m", "1h", "hourly", "daily"
|
|
28
|
+
* - unit expressions: "<n>s", "<n>m", "<n>h", "<n>d"
|
|
29
|
+
* - a raw number of seconds
|
|
30
|
+
*
|
|
31
|
+
* @internal Exported for unit testing of the mapping.
|
|
32
|
+
*/
|
|
33
|
+
export function intervalToSeconds(interval) {
|
|
34
|
+
if (interval === undefined) {
|
|
35
|
+
return INTERVAL_PRESETS["5m"];
|
|
36
|
+
}
|
|
37
|
+
if (typeof interval === "number") {
|
|
38
|
+
if (!Number.isFinite(interval) || interval <= 0) {
|
|
39
|
+
throw new ValidationError("interval (seconds) must be a positive number");
|
|
40
|
+
}
|
|
41
|
+
return Math.floor(interval);
|
|
42
|
+
}
|
|
43
|
+
const key = interval.trim().toLowerCase();
|
|
44
|
+
if (key in INTERVAL_PRESETS) {
|
|
45
|
+
return INTERVAL_PRESETS[key];
|
|
46
|
+
}
|
|
47
|
+
// Unit expression: <number><unit> where unit ∈ s/m/h/d.
|
|
48
|
+
const match = /^(\d+)\s*(s|m|h|d)$/.exec(key);
|
|
49
|
+
if (match) {
|
|
50
|
+
const value = parseInt(match[1], 10);
|
|
51
|
+
const unit = match[2];
|
|
52
|
+
const multipliers = { s: 1, m: 60, h: 3600, d: 86400 };
|
|
53
|
+
const seconds = value * multipliers[unit];
|
|
54
|
+
if (seconds <= 0) {
|
|
55
|
+
throw new ValidationError("interval must be greater than zero");
|
|
56
|
+
}
|
|
57
|
+
return seconds;
|
|
58
|
+
}
|
|
59
|
+
throw new ValidationError(`Invalid interval "${interval}". Use a preset ("5m", "15m", "1h", "daily"), ` +
|
|
60
|
+
`a unit expression ("30s", "10m", "2h", "1d"), or a number of seconds.`);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Agent Subscriptions ("Watches") Resource
|
|
64
|
+
*
|
|
65
|
+
* Manage persistent, recurring watches over commodity codes and poll for the
|
|
66
|
+
* events they emit.
|
|
67
|
+
*
|
|
68
|
+
* **Example:**
|
|
69
|
+
* ```typescript
|
|
70
|
+
* import { OilPriceAPI } from 'oilpriceapi';
|
|
71
|
+
*
|
|
72
|
+
* const client = new OilPriceAPI({ apiKey: 'your_key' });
|
|
73
|
+
*
|
|
74
|
+
* // Create a watch that evaluates Brent + WTI every 5 minutes
|
|
75
|
+
* const watch = await client.subscriptions.create({
|
|
76
|
+
* name: 'Crude desk',
|
|
77
|
+
* codes: ['BRENT_CRUDE_USD', 'WTI_USD'],
|
|
78
|
+
* interval: '5m',
|
|
79
|
+
* });
|
|
80
|
+
*
|
|
81
|
+
* // List all watches
|
|
82
|
+
* const watches = await client.subscriptions.list();
|
|
83
|
+
*
|
|
84
|
+
* // Poll for new events
|
|
85
|
+
* let cursor = 0;
|
|
86
|
+
* const { events, cursor: next } = await client.subscriptions.events({ since: cursor });
|
|
87
|
+
* cursor = next;
|
|
88
|
+
*
|
|
89
|
+
* // Remove a watch
|
|
90
|
+
* await client.subscriptions.delete(watch.id);
|
|
91
|
+
* ```
|
|
92
|
+
*/
|
|
93
|
+
export class SubscriptionsResource {
|
|
94
|
+
constructor(client) {
|
|
95
|
+
this.client = client;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* List all subscriptions/watches for the authenticated user.
|
|
99
|
+
*
|
|
100
|
+
* @returns Array of subscriptions, newest first.
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* ```typescript
|
|
104
|
+
* const subscriptions = await client.subscriptions.list();
|
|
105
|
+
* console.log(`You have ${subscriptions.length} watches`);
|
|
106
|
+
* ```
|
|
107
|
+
*/
|
|
108
|
+
async list() {
|
|
109
|
+
const response = await this.client["request"]("/v1/subscriptions", {});
|
|
110
|
+
return Array.isArray(response) ? response : (response.subscriptions ?? []);
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Create a new subscription/watch.
|
|
114
|
+
*
|
|
115
|
+
* Maps the friendly `interval` ("5m" / "1h" / "daily" / seconds) to the
|
|
116
|
+
* API's `interval_seconds`, and forwards optional attribution as
|
|
117
|
+
* `X-OPA-Source` / `X-OPA-Tool` headers (source defaults to `"sdk-node"`).
|
|
118
|
+
*
|
|
119
|
+
* @param params - Watch configuration. `codes` is required.
|
|
120
|
+
* @returns The created subscription.
|
|
121
|
+
*
|
|
122
|
+
* @throws {ValidationError} If `codes` is empty or `interval` is invalid.
|
|
123
|
+
*
|
|
124
|
+
* @example
|
|
125
|
+
* ```typescript
|
|
126
|
+
* const watch = await client.subscriptions.create({
|
|
127
|
+
* name: 'Crude desk',
|
|
128
|
+
* codes: ['BRENT_CRUDE_USD', 'WTI_USD'],
|
|
129
|
+
* interval: '1h',
|
|
130
|
+
* tool: 'my-trading-bot',
|
|
131
|
+
* });
|
|
132
|
+
* ```
|
|
133
|
+
*/
|
|
134
|
+
async create(params) {
|
|
135
|
+
if (!params || !Array.isArray(params.codes) || params.codes.length === 0) {
|
|
136
|
+
throw new ValidationError("codes is required and must be a non-empty array of commodity codes");
|
|
137
|
+
}
|
|
138
|
+
if (params.codes.some((c) => typeof c !== "string" || c.trim() === "")) {
|
|
139
|
+
throw new ValidationError("every code must be a non-empty string");
|
|
140
|
+
}
|
|
141
|
+
const intervalSeconds = intervalToSeconds(params.interval);
|
|
142
|
+
const body = {
|
|
143
|
+
codes: params.codes,
|
|
144
|
+
interval_seconds: intervalSeconds,
|
|
145
|
+
};
|
|
146
|
+
if (params.name !== undefined) {
|
|
147
|
+
body.name = params.name;
|
|
148
|
+
}
|
|
149
|
+
if (params.deliverWebhook !== undefined) {
|
|
150
|
+
body.deliver_webhook = params.deliverWebhook;
|
|
151
|
+
}
|
|
152
|
+
const headers = {
|
|
153
|
+
"X-OPA-Source": params.source ?? DEFAULT_SOURCE,
|
|
154
|
+
};
|
|
155
|
+
if (params.tool !== undefined) {
|
|
156
|
+
headers["X-OPA-Tool"] = params.tool;
|
|
157
|
+
}
|
|
158
|
+
const response = await this.client["request"]("/v1/subscriptions", {}, { method: "POST", body, headers });
|
|
159
|
+
return "subscription" in response ? response.subscription : response;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Delete a subscription/watch.
|
|
163
|
+
*
|
|
164
|
+
* @param id - The subscription ID to delete.
|
|
165
|
+
*
|
|
166
|
+
* @throws {ValidationError} If `id` is not a non-empty string.
|
|
167
|
+
*
|
|
168
|
+
* @example
|
|
169
|
+
* ```typescript
|
|
170
|
+
* await client.subscriptions.delete(watch.id);
|
|
171
|
+
* ```
|
|
172
|
+
*/
|
|
173
|
+
async delete(id) {
|
|
174
|
+
if (!id || typeof id !== "string") {
|
|
175
|
+
throw new ValidationError("Subscription ID must be a non-empty string");
|
|
176
|
+
}
|
|
177
|
+
await this.client["request"](`/v1/subscriptions/${id}`, {}, { method: "DELETE" });
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Poll for events emitted by your watches.
|
|
181
|
+
*
|
|
182
|
+
* Returns events with `seq` greater than the supplied cursor, ordered
|
|
183
|
+
* ascending. This endpoint does NOT consume the monthly request quota.
|
|
184
|
+
*
|
|
185
|
+
* @param options - Cursor (`since`), optional `watchId`, and `limit`.
|
|
186
|
+
* @returns The next cursor, a `has_more` flag, and the events.
|
|
187
|
+
*
|
|
188
|
+
* @example
|
|
189
|
+
* ```typescript
|
|
190
|
+
* let cursor = 0;
|
|
191
|
+
* while (true) {
|
|
192
|
+
* const { events, cursor: next, has_more } = await client.subscriptions.events({ since: cursor });
|
|
193
|
+
* for (const ev of events) handle(ev);
|
|
194
|
+
* cursor = next;
|
|
195
|
+
* if (!has_more) break;
|
|
196
|
+
* }
|
|
197
|
+
* ```
|
|
198
|
+
*/
|
|
199
|
+
async events(options = {}) {
|
|
200
|
+
const params = {};
|
|
201
|
+
if (options.since !== undefined) {
|
|
202
|
+
params.since = String(options.since);
|
|
203
|
+
}
|
|
204
|
+
if (options.watchId !== undefined) {
|
|
205
|
+
params.watch_id = options.watchId;
|
|
206
|
+
}
|
|
207
|
+
if (options.limit !== undefined) {
|
|
208
|
+
params.limit = String(options.limit);
|
|
209
|
+
}
|
|
210
|
+
return this.client["request"]("/v1/subscriptions/events", params);
|
|
211
|
+
}
|
|
212
|
+
}
|
package/dist/version.d.ts
CHANGED
package/dist/version.js
CHANGED