oilpriceapi 0.5.3 → 0.7.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.
Files changed (49) hide show
  1. package/README.md +395 -110
  2. package/dist/client.d.ts +83 -3
  3. package/dist/client.js +118 -38
  4. package/dist/index.d.ts +31 -6
  5. package/dist/index.js +17 -3
  6. package/dist/resources/alerts.d.ts +52 -15
  7. package/dist/resources/alerts.js +143 -85
  8. package/dist/resources/analytics.d.ts +325 -0
  9. package/dist/resources/analytics.js +221 -0
  10. package/dist/resources/bunker-fuels.d.ts +270 -0
  11. package/dist/resources/bunker-fuels.js +191 -0
  12. package/dist/resources/commodities.d.ts +148 -0
  13. package/dist/resources/commodities.js +110 -0
  14. package/dist/resources/data-quality.d.ts +229 -0
  15. package/dist/resources/data-quality.js +139 -0
  16. package/dist/resources/data-sources.d.ts +365 -0
  17. package/dist/resources/data-sources.js +349 -0
  18. package/dist/resources/drilling.d.ts +403 -0
  19. package/dist/resources/drilling.js +264 -0
  20. package/dist/resources/ei/drilling-productivity.d.ts +173 -0
  21. package/dist/resources/ei/drilling-productivity.js +103 -0
  22. package/dist/resources/ei/forecasts.d.ts +177 -0
  23. package/dist/resources/ei/forecasts.js +101 -0
  24. package/dist/resources/ei/frac-focus.d.ts +212 -0
  25. package/dist/resources/ei/frac-focus.js +150 -0
  26. package/dist/resources/ei/index.d.ts +140 -0
  27. package/dist/resources/ei/index.js +87 -0
  28. package/dist/resources/ei/oil-inventories.d.ts +155 -0
  29. package/dist/resources/ei/oil-inventories.js +92 -0
  30. package/dist/resources/ei/opec-production.d.ts +146 -0
  31. package/dist/resources/ei/opec-production.js +92 -0
  32. package/dist/resources/ei/rig-counts.d.ts +131 -0
  33. package/dist/resources/ei/rig-counts.js +88 -0
  34. package/dist/resources/ei/well-permits.d.ts +178 -0
  35. package/dist/resources/ei/well-permits.js +119 -0
  36. package/dist/resources/forecasts.d.ts +200 -0
  37. package/dist/resources/forecasts.js +157 -0
  38. package/dist/resources/futures.d.ts +322 -0
  39. package/dist/resources/futures.js +228 -0
  40. package/dist/resources/rig-counts.d.ts +221 -0
  41. package/dist/resources/rig-counts.js +157 -0
  42. package/dist/resources/storage.d.ts +182 -0
  43. package/dist/resources/storage.js +161 -0
  44. package/dist/resources/webhooks.d.ts +290 -0
  45. package/dist/resources/webhooks.js +297 -0
  46. package/dist/types.d.ts +106 -6
  47. package/dist/version.d.ts +1 -1
  48. package/dist/version.js +1 -1
  49. package/package.json +3 -3
@@ -0,0 +1,297 @@
1
+ /**
2
+ * Webhooks Resource
3
+ *
4
+ * Manage webhook endpoints for real-time event notifications.
5
+ */
6
+ /**
7
+ * Webhooks Resource
8
+ *
9
+ * Manage webhook endpoints for real-time notifications about price changes,
10
+ * alerts, and other events.
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * import { OilPriceAPI } from 'oilpriceapi';
15
+ *
16
+ * const client = new OilPriceAPI({ apiKey: 'your_key' });
17
+ *
18
+ * // Create a webhook
19
+ * const webhook = await client.webhooks.create({
20
+ * name: 'Price Updates',
21
+ * url: 'https://myapp.com/webhooks/prices',
22
+ * events: ['price.updated', 'alert.triggered'],
23
+ * enabled: true
24
+ * });
25
+ *
26
+ * // Test the webhook
27
+ * const test = await client.webhooks.test(webhook.id);
28
+ * console.log(`Test result: ${test.success ? 'passed' : 'failed'}`);
29
+ *
30
+ * // List all webhooks
31
+ * const webhooks = await client.webhooks.list();
32
+ * webhooks.forEach(wh => {
33
+ * console.log(`${wh.name}: ${wh.successful_deliveries} successful`);
34
+ * });
35
+ *
36
+ * // Update webhook
37
+ * await client.webhooks.update(webhook.id, {
38
+ * enabled: false
39
+ * });
40
+ *
41
+ * // Delete webhook
42
+ * await client.webhooks.delete(webhook.id);
43
+ * ```
44
+ */
45
+ export class WebhooksResource {
46
+ constructor(client) {
47
+ this.client = client;
48
+ }
49
+ /**
50
+ * List all webhook endpoints
51
+ *
52
+ * @returns Array of webhook endpoints
53
+ *
54
+ * @throws {OilPriceAPIError} If API request fails
55
+ * @throws {AuthenticationError} If API key is invalid
56
+ *
57
+ * @example
58
+ * ```typescript
59
+ * const webhooks = await client.webhooks.list();
60
+ * webhooks.forEach(wh => {
61
+ * console.log(`${wh.name} (${wh.enabled ? 'enabled' : 'disabled'})`);
62
+ * console.log(` Events: ${wh.events.join(', ')}`);
63
+ * });
64
+ * ```
65
+ */
66
+ async list() {
67
+ const response = await this.client["request"]("/v1/webhooks", {});
68
+ return Array.isArray(response) ? response : response.webhooks;
69
+ }
70
+ /**
71
+ * Get a specific webhook endpoint
72
+ *
73
+ * @param id - Webhook ID
74
+ * @returns Webhook endpoint details
75
+ *
76
+ * @throws {NotFoundError} If webhook not found
77
+ * @throws {OilPriceAPIError} If API request fails
78
+ *
79
+ * @example
80
+ * ```typescript
81
+ * const webhook = await client.webhooks.get('webhook-id');
82
+ * console.log(`${webhook.name}: ${webhook.url}`);
83
+ * console.log(`Success rate: ${webhook.successful_deliveries}/${webhook.successful_deliveries + webhook.failed_deliveries}`);
84
+ * ```
85
+ */
86
+ async get(id) {
87
+ if (!id || typeof id !== "string") {
88
+ throw new Error("Webhook ID must be a non-empty string");
89
+ }
90
+ const response = await this.client["request"](`/v1/webhooks/${id}`, {});
91
+ return "webhook" in response ? response.webhook : response;
92
+ }
93
+ /**
94
+ * Create a new webhook endpoint
95
+ *
96
+ * @param params - Webhook configuration
97
+ * @returns Created webhook endpoint
98
+ *
99
+ * @throws {OilPriceAPIError} If API request fails
100
+ * @throws {AuthenticationError} If API key is invalid
101
+ *
102
+ * @example
103
+ * ```typescript
104
+ * const webhook = await client.webhooks.create({
105
+ * name: 'Production Alerts',
106
+ * url: 'https://api.myapp.com/webhooks',
107
+ * events: ['alert.triggered', 'price.updated'],
108
+ * secret: 'my-webhook-secret',
109
+ * enabled: true
110
+ * });
111
+ * console.log(`Webhook created: ${webhook.id}`);
112
+ * ```
113
+ */
114
+ async create(params) {
115
+ if (!params.name || typeof params.name !== "string") {
116
+ throw new Error("Webhook name is required");
117
+ }
118
+ if (!params.url || !params.url.startsWith("https://")) {
119
+ throw new Error("Webhook URL must use HTTPS protocol");
120
+ }
121
+ if (!params.events ||
122
+ !Array.isArray(params.events) ||
123
+ params.events.length === 0) {
124
+ throw new Error("At least one event type is required");
125
+ }
126
+ const url = `${this.client["baseUrl"]}/v1/webhooks`;
127
+ const response = await fetch(url, {
128
+ method: "POST",
129
+ headers: {
130
+ Authorization: `Bearer ${this.client["apiKey"]}`,
131
+ "Content-Type": "application/json",
132
+ },
133
+ body: JSON.stringify({
134
+ webhook: {
135
+ name: params.name,
136
+ url: params.url,
137
+ events: params.events,
138
+ enabled: params.enabled ?? true,
139
+ secret: params.secret,
140
+ metadata: params.metadata,
141
+ },
142
+ }),
143
+ });
144
+ if (!response.ok) {
145
+ const errorText = await response.text();
146
+ throw new Error(`Failed to create webhook: ${response.status} ${errorText}`);
147
+ }
148
+ const data = (await response.json());
149
+ return "webhook" in data ? data.webhook : data;
150
+ }
151
+ /**
152
+ * Update a webhook endpoint
153
+ *
154
+ * @param id - Webhook ID
155
+ * @param params - Fields to update
156
+ * @returns Updated webhook endpoint
157
+ *
158
+ * @throws {NotFoundError} If webhook not found
159
+ * @throws {OilPriceAPIError} If API request fails
160
+ *
161
+ * @example
162
+ * ```typescript
163
+ * // Disable a webhook
164
+ * await client.webhooks.update(webhookId, { enabled: false });
165
+ *
166
+ * // Change events
167
+ * await client.webhooks.update(webhookId, {
168
+ * events: ['alert.triggered']
169
+ * });
170
+ * ```
171
+ */
172
+ async update(id, params) {
173
+ if (!id || typeof id !== "string") {
174
+ throw new Error("Webhook ID must be a non-empty string");
175
+ }
176
+ if (params.url !== undefined && !params.url.startsWith("https://")) {
177
+ throw new Error("Webhook URL must use HTTPS protocol");
178
+ }
179
+ if (params.events !== undefined &&
180
+ (!Array.isArray(params.events) || params.events.length === 0)) {
181
+ throw new Error("Events must be a non-empty array");
182
+ }
183
+ const url = `${this.client["baseUrl"]}/v1/webhooks/${id}`;
184
+ const response = await fetch(url, {
185
+ method: "PATCH",
186
+ headers: {
187
+ Authorization: `Bearer ${this.client["apiKey"]}`,
188
+ "Content-Type": "application/json",
189
+ },
190
+ body: JSON.stringify({
191
+ webhook: params,
192
+ }),
193
+ });
194
+ if (!response.ok) {
195
+ const errorText = await response.text();
196
+ throw new Error(`Failed to update webhook: ${response.status} ${errorText}`);
197
+ }
198
+ const data = (await response.json());
199
+ return "webhook" in data ? data.webhook : data;
200
+ }
201
+ /**
202
+ * Delete a webhook endpoint
203
+ *
204
+ * @param id - Webhook ID
205
+ *
206
+ * @throws {NotFoundError} If webhook not found
207
+ * @throws {OilPriceAPIError} If API request fails
208
+ *
209
+ * @example
210
+ * ```typescript
211
+ * await client.webhooks.delete(webhookId);
212
+ * console.log('Webhook deleted');
213
+ * ```
214
+ */
215
+ async delete(id) {
216
+ if (!id || typeof id !== "string") {
217
+ throw new Error("Webhook ID must be a non-empty string");
218
+ }
219
+ const url = `${this.client["baseUrl"]}/v1/webhooks/${id}`;
220
+ const response = await fetch(url, {
221
+ method: "DELETE",
222
+ headers: {
223
+ Authorization: `Bearer ${this.client["apiKey"]}`,
224
+ "Content-Type": "application/json",
225
+ },
226
+ });
227
+ if (!response.ok) {
228
+ const errorText = await response.text();
229
+ throw new Error(`Failed to delete webhook: ${response.status} ${errorText}`);
230
+ }
231
+ }
232
+ /**
233
+ * Test a webhook endpoint
234
+ *
235
+ * Sends a test payload to the webhook URL to verify it's reachable.
236
+ *
237
+ * @param id - Webhook ID
238
+ * @returns Test results
239
+ *
240
+ * @throws {NotFoundError} If webhook not found
241
+ * @throws {OilPriceAPIError} If API request fails
242
+ *
243
+ * @example
244
+ * ```typescript
245
+ * const test = await client.webhooks.test(webhookId);
246
+ * console.log(`Test ${test.success ? 'passed' : 'failed'}`);
247
+ * console.log(`Response time: ${test.response_time_ms}ms`);
248
+ * if (!test.success) {
249
+ * console.log(`Error: ${test.error}`);
250
+ * }
251
+ * ```
252
+ */
253
+ async test(id) {
254
+ if (!id || typeof id !== "string") {
255
+ throw new Error("Webhook ID must be a non-empty string");
256
+ }
257
+ const url = `${this.client["baseUrl"]}/v1/webhooks/${id}/test`;
258
+ const response = await fetch(url, {
259
+ method: "POST",
260
+ headers: {
261
+ Authorization: `Bearer ${this.client["apiKey"]}`,
262
+ "Content-Type": "application/json",
263
+ },
264
+ });
265
+ if (!response.ok) {
266
+ const errorText = await response.text();
267
+ throw new Error(`Failed to test webhook: ${response.status} ${errorText}`);
268
+ }
269
+ return response.json();
270
+ }
271
+ /**
272
+ * Get webhook event history
273
+ *
274
+ * Returns recent delivery events for a webhook.
275
+ *
276
+ * @param id - Webhook ID
277
+ * @returns Array of webhook events
278
+ *
279
+ * @throws {NotFoundError} If webhook not found
280
+ * @throws {OilPriceAPIError} If API request fails
281
+ *
282
+ * @example
283
+ * ```typescript
284
+ * const events = await client.webhooks.events(webhookId);
285
+ * events.forEach(event => {
286
+ * console.log(`${event.event_type}: ${event.status} (${event.attempts} attempts)`);
287
+ * });
288
+ * ```
289
+ */
290
+ async events(id) {
291
+ if (!id || typeof id !== "string") {
292
+ throw new Error("Webhook ID must be a non-empty string");
293
+ }
294
+ const response = await this.client["request"](`/v1/webhooks/${id}/events`, {});
295
+ return Array.isArray(response) ? response : response.events;
296
+ }
297
+ }
package/dist/types.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Retry backoff strategy
3
3
  */
4
- export type RetryStrategy = 'exponential' | 'linear' | 'fixed';
4
+ export type RetryStrategy = "exponential" | "linear" | "fixed";
5
5
  /**
6
6
  * Configuration options for OilPriceAPI client
7
7
  */
@@ -40,6 +40,18 @@ export interface OilPriceAPIConfig {
40
40
  * @default false
41
41
  */
42
42
  debug?: boolean;
43
+ /**
44
+ * Your application's URL (optional, for telemetry)
45
+ * Helps us understand how the API is being used and may unlock
46
+ * a 10% bonus to your request limit.
47
+ * @example "https://myapp.com"
48
+ */
49
+ appUrl?: string;
50
+ /**
51
+ * Your application's name (optional, for telemetry)
52
+ * @example "MyFuelPriceTracker"
53
+ */
54
+ appName?: string;
43
55
  }
44
56
  /**
45
57
  * Represents a single price data point
@@ -77,22 +89,22 @@ export interface Price {
77
89
  * Price changes over different time periods (24h, 7d, 30d, 90d)
78
90
  */
79
91
  changes?: {
80
- '24h'?: {
92
+ "24h"?: {
81
93
  amount: number;
82
94
  percent: number;
83
95
  previous_price: number;
84
96
  };
85
- '7d'?: {
97
+ "7d"?: {
86
98
  amount: number;
87
99
  percent: number;
88
100
  previous_price: number;
89
101
  };
90
- '30d'?: {
102
+ "30d"?: {
91
103
  amount: number;
92
104
  percent: number;
93
105
  previous_price: number;
94
106
  };
95
- '90d'?: {
107
+ "90d"?: {
96
108
  amount: number;
97
109
  percent: number;
98
110
  previous_price: number;
@@ -119,7 +131,15 @@ export interface LatestPricesOptions {
119
131
  /**
120
132
  * Time period options for historical data
121
133
  */
122
- export type HistoricalPeriod = 'past_week' | 'past_month' | 'past_year';
134
+ export type HistoricalPeriod = "past_week" | "past_month" | "past_year";
135
+ /**
136
+ * Aggregation interval for historical data
137
+ *
138
+ * PERFORMANCE TIP: Use 'daily' or 'weekly' for year-long queries to reduce
139
+ * response times from 74s to <1s. The 'raw' option returns individual price
140
+ * points which can be 600k+ records for a year of BRENT data.
141
+ */
142
+ export type AggregationInterval = "raw" | "hourly" | "daily" | "weekly" | "monthly";
123
143
  /**
124
144
  * Options for fetching historical prices
125
145
  */
@@ -142,6 +162,28 @@ export interface HistoricalPricesOptions {
142
162
  * Example: "2024-12-31"
143
163
  */
144
164
  endDate?: string;
165
+ /**
166
+ * Aggregation interval for the data
167
+ *
168
+ * PERFORMANCE: For year-long queries, use 'daily' (365 points) or 'weekly' (52 points)
169
+ * instead of 'raw' (600k+ points for BRENT) to dramatically improve response times.
170
+ *
171
+ * @default API default (raw for short periods, may be aggregated for long periods)
172
+ */
173
+ interval?: AggregationInterval;
174
+ /**
175
+ * Number of results per page
176
+ *
177
+ * @default 100 (API default)
178
+ * @max 1000
179
+ */
180
+ perPage?: number;
181
+ /**
182
+ * Page number for pagination (1-indexed)
183
+ *
184
+ * @default 1
185
+ */
186
+ page?: number;
145
187
  }
146
188
  /**
147
189
  * Represents commodity metadata
@@ -211,3 +253,61 @@ export interface CommodityCategory {
211
253
  export interface CategoriesResponse {
212
254
  [categoryKey: string]: CommodityCategory;
213
255
  }
256
+ /**
257
+ * BYOS (Bring Your Own Subscription) price from Data Connector
258
+ */
259
+ export interface DataConnectorPrice {
260
+ /**
261
+ * Price value in specified currency
262
+ */
263
+ price: number;
264
+ /**
265
+ * Currency code (e.g., "USD")
266
+ */
267
+ currency: string;
268
+ /**
269
+ * Fuel type (e.g., "VLSFO", "MGO", "IFO380")
270
+ */
271
+ fuel_type: string;
272
+ /**
273
+ * Port name (e.g., "SINGAPORE", "ROTTERDAM")
274
+ */
275
+ port: string;
276
+ /**
277
+ * Geographic region (AMERICAS, EMEA, APAC)
278
+ */
279
+ region: string | null;
280
+ /**
281
+ * Unit of measurement (typically "MT" for metric ton)
282
+ */
283
+ unit: string;
284
+ /**
285
+ * Data source provider (e.g., "shipandbunker")
286
+ */
287
+ source: string;
288
+ /**
289
+ * ISO 8601 timestamp when price was recorded
290
+ */
291
+ timestamp: string;
292
+ }
293
+ /**
294
+ * Options for fetching Data Connector prices
295
+ */
296
+ export interface DataConnectorOptions {
297
+ /**
298
+ * Filter by fuel type (VLSFO, MGO, IFO380)
299
+ */
300
+ fuelType?: string;
301
+ /**
302
+ * Filter by port name
303
+ */
304
+ port?: string;
305
+ /**
306
+ * Filter by region (AMERICAS, EMEA, APAC)
307
+ */
308
+ region?: string;
309
+ /**
310
+ * ISO 8601 timestamp to fetch prices after
311
+ */
312
+ since?: string;
313
+ }
package/dist/version.d.ts CHANGED
@@ -7,7 +7,7 @@
7
7
  * - X-Client-Version header
8
8
  * - Package.json (should match)
9
9
  */
10
- export declare const SDK_VERSION = "0.5.3";
10
+ export declare const SDK_VERSION = "0.7.0";
11
11
  /**
12
12
  * SDK identifier used in User-Agent and X-Api-Client headers
13
13
  */
package/dist/version.js CHANGED
@@ -7,7 +7,7 @@
7
7
  * - X-Client-Version header
8
8
  * - Package.json (should match)
9
9
  */
10
- export const SDK_VERSION = '0.5.3';
10
+ export const SDK_VERSION = '0.7.0';
11
11
  /**
12
12
  * SDK identifier used in User-Agent and X-Api-Client headers
13
13
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oilpriceapi",
3
- "version": "0.5.3",
3
+ "version": "0.7.0",
4
4
  "description": "Official Node.js SDK for Oil Price API - Real-time and historical oil & commodity prices",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -55,8 +55,8 @@
55
55
  },
56
56
  "devDependencies": {
57
57
  "@types/node": "^20.10.0",
58
- "@vitest/coverage-v8": "^1.0.0",
58
+ "@vitest/coverage-v8": "^4.0.16",
59
59
  "typescript": "^5.3.0",
60
- "vitest": "^1.0.0"
60
+ "vitest": "^4.0.16"
61
61
  }
62
62
  }