oilpriceapi 0.7.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 (60) hide show
  1. package/README.md +43 -11
  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 +33 -2
  30. package/dist/client.js +70 -14
  31. package/dist/errors.d.ts +6 -0
  32. package/dist/errors.js +25 -16
  33. package/dist/index.d.ts +16 -2
  34. package/dist/index.js +24 -1
  35. package/dist/resources/alerts.js +31 -77
  36. package/dist/resources/analytics.js +8 -7
  37. package/dist/resources/bunker-fuels.js +5 -4
  38. package/dist/resources/commodities.js +2 -1
  39. package/dist/resources/data-quality.js +2 -1
  40. package/dist/resources/data-sources.js +21 -77
  41. package/dist/resources/diesel.d.ts +1 -1
  42. package/dist/resources/diesel.js +9 -38
  43. package/dist/resources/drilling.js +2 -1
  44. package/dist/resources/ei/drilling-productivity.js +2 -1
  45. package/dist/resources/ei/forecasts.js +2 -1
  46. package/dist/resources/ei/frac-focus.js +4 -3
  47. package/dist/resources/ei/index.js +2 -1
  48. package/dist/resources/ei/oil-inventories.js +2 -1
  49. package/dist/resources/ei/opec-production.js +2 -1
  50. package/dist/resources/ei/rig-counts.js +2 -1
  51. package/dist/resources/ei/well-permits.js +2 -1
  52. package/dist/resources/forecasts.js +2 -1
  53. package/dist/resources/futures.js +9 -8
  54. package/dist/resources/storage.js +2 -1
  55. package/dist/resources/webhooks.d.ts +36 -0
  56. package/dist/resources/webhooks.js +60 -67
  57. package/dist/types.d.ts +2 -1
  58. package/dist/version.d.ts +1 -1
  59. package/dist/version.js +2 -2
  60. package/package.json +15 -6
@@ -3,6 +3,8 @@
3
3
  *
4
4
  * Manage webhook endpoints for real-time event notifications.
5
5
  */
6
+ import { ValidationError } from "../errors.js";
7
+ import { verifyWebhookSignature } from "../index.js";
6
8
  /**
7
9
  * Webhooks Resource
8
10
  *
@@ -85,7 +87,7 @@ export class WebhooksResource {
85
87
  */
86
88
  async get(id) {
87
89
  if (!id || typeof id !== "string") {
88
- throw new Error("Webhook ID must be a non-empty string");
90
+ throw new ValidationError("Webhook ID must be a non-empty string");
89
91
  }
90
92
  const response = await this.client["request"](`/v1/webhooks/${id}`, {});
91
93
  return "webhook" in response ? response.webhook : response;
@@ -113,24 +115,17 @@ export class WebhooksResource {
113
115
  */
114
116
  async create(params) {
115
117
  if (!params.name || typeof params.name !== "string") {
116
- throw new Error("Webhook name is required");
118
+ throw new ValidationError("Webhook name is required");
117
119
  }
118
120
  if (!params.url || !params.url.startsWith("https://")) {
119
- throw new Error("Webhook URL must use HTTPS protocol");
121
+ throw new ValidationError("Webhook URL must use HTTPS protocol");
120
122
  }
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");
123
+ if (!params.events || !Array.isArray(params.events) || params.events.length === 0) {
124
+ throw new ValidationError("At least one event type is required");
125
125
  }
126
- const url = `${this.client["baseUrl"]}/v1/webhooks`;
127
- const response = await fetch(url, {
126
+ const response = await this.client["request"]("/v1/webhooks", {}, {
128
127
  method: "POST",
129
- headers: {
130
- Authorization: `Bearer ${this.client["apiKey"]}`,
131
- "Content-Type": "application/json",
132
- },
133
- body: JSON.stringify({
128
+ body: {
134
129
  webhook: {
135
130
  name: params.name,
136
131
  url: params.url,
@@ -139,14 +134,9 @@ export class WebhooksResource {
139
134
  secret: params.secret,
140
135
  metadata: params.metadata,
141
136
  },
142
- }),
137
+ },
143
138
  });
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;
139
+ return "webhook" in response ? response.webhook : response;
150
140
  }
151
141
  /**
152
142
  * Update a webhook endpoint
@@ -171,32 +161,20 @@ export class WebhooksResource {
171
161
  */
172
162
  async update(id, params) {
173
163
  if (!id || typeof id !== "string") {
174
- throw new Error("Webhook ID must be a non-empty string");
164
+ throw new ValidationError("Webhook ID must be a non-empty string");
175
165
  }
176
166
  if (params.url !== undefined && !params.url.startsWith("https://")) {
177
- throw new Error("Webhook URL must use HTTPS protocol");
167
+ throw new ValidationError("Webhook URL must use HTTPS protocol");
178
168
  }
179
169
  if (params.events !== undefined &&
180
170
  (!Array.isArray(params.events) || params.events.length === 0)) {
181
- throw new Error("Events must be a non-empty array");
171
+ throw new ValidationError("Events must be a non-empty array");
182
172
  }
183
- const url = `${this.client["baseUrl"]}/v1/webhooks/${id}`;
184
- const response = await fetch(url, {
173
+ const response = await this.client["request"](`/v1/webhooks/${id}`, {}, {
185
174
  method: "PATCH",
186
- headers: {
187
- Authorization: `Bearer ${this.client["apiKey"]}`,
188
- "Content-Type": "application/json",
189
- },
190
- body: JSON.stringify({
191
- webhook: params,
192
- }),
175
+ body: { webhook: params },
193
176
  });
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;
177
+ return "webhook" in response ? response.webhook : response;
200
178
  }
201
179
  /**
202
180
  * Delete a webhook endpoint
@@ -214,20 +192,9 @@ export class WebhooksResource {
214
192
  */
215
193
  async delete(id) {
216
194
  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}`);
195
+ throw new ValidationError("Webhook ID must be a non-empty string");
230
196
  }
197
+ await this.client["request"](`/v1/webhooks/${id}`, {}, { method: "DELETE" });
231
198
  }
232
199
  /**
233
200
  * Test a webhook endpoint
@@ -252,21 +219,9 @@ export class WebhooksResource {
252
219
  */
253
220
  async test(id) {
254
221
  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}`);
222
+ throw new ValidationError("Webhook ID must be a non-empty string");
268
223
  }
269
- return response.json();
224
+ return this.client["request"](`/v1/webhooks/${id}/test`, {}, { method: "POST" });
270
225
  }
271
226
  /**
272
227
  * Get webhook event history
@@ -289,9 +244,47 @@ export class WebhooksResource {
289
244
  */
290
245
  async events(id) {
291
246
  if (!id || typeof id !== "string") {
292
- throw new Error("Webhook ID must be a non-empty string");
247
+ throw new ValidationError("Webhook ID must be a non-empty string");
293
248
  }
294
249
  const response = await this.client["request"](`/v1/webhooks/${id}/events`, {});
295
250
  return Array.isArray(response) ? response : response.events;
296
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
+ }
297
290
  }
package/dist/types.d.ts CHANGED
@@ -8,8 +8,9 @@ export type RetryStrategy = "exponential" | "linear" | "fixed";
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"
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.7.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.7.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.7.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": [
@@ -56,7 +63,9 @@
56
63
  "devDependencies": {
57
64
  "@types/node": "^20.10.0",
58
65
  "@vitest/coverage-v8": "^4.0.16",
66
+ "eslint": "^9.39.4",
59
67
  "typescript": "^5.3.0",
68
+ "typescript-eslint": "^8.57.2",
60
69
  "vitest": "^4.0.16"
61
70
  }
62
71
  }