oilpriceapi 0.6.0 → 0.8.2

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