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,221 @@
1
+ /**
2
+ * Analytics Resource
3
+ *
4
+ * Access advanced analytics including performance metrics, statistical analysis,
5
+ * correlations, trend detection, spreads, and forecasts.
6
+ */
7
+ /**
8
+ * Analytics Resource
9
+ *
10
+ * Access advanced analytics including performance metrics, statistical analysis,
11
+ * correlations, trends, spreads, and forecasts.
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * import { OilPriceAPI } from 'oilpriceapi';
16
+ *
17
+ * const client = new OilPriceAPI({ apiKey: 'your_key' });
18
+ *
19
+ * // Get performance metrics
20
+ * const perf = await client.analytics.performance({ commodity: 'WTI_USD', days: 30 });
21
+ * console.log(`30-day return: ${perf.return_percent}%`);
22
+ * console.log(`Volatility: ${perf.volatility}`);
23
+ *
24
+ * // Analyze correlation
25
+ * const corr = await client.analytics.correlation('WTI_USD', 'BRENT_CRUDE_USD', 90);
26
+ * console.log(`Correlation: ${corr.correlation}`);
27
+ * ```
28
+ */
29
+ export class AnalyticsResource {
30
+ constructor(client) {
31
+ this.client = client;
32
+ }
33
+ /**
34
+ * Get performance metrics for a commodity
35
+ *
36
+ * Returns key performance indicators including returns, volatility,
37
+ * and price range over a specified period.
38
+ *
39
+ * @param options - Analysis parameters
40
+ * @returns Performance metrics
41
+ *
42
+ * @throws {OilPriceAPIError} If API request fails
43
+ *
44
+ * @example
45
+ * ```typescript
46
+ * const metrics = await client.analytics.performance({
47
+ * commodity: 'WTI_USD',
48
+ * days: 30
49
+ * });
50
+ * console.log(`Return: ${metrics.return_percent}%`);
51
+ * console.log(`Volatility: ${metrics.volatility}`);
52
+ * console.log(`High: $${metrics.high}, Low: $${metrics.low}`);
53
+ * ```
54
+ */
55
+ async performance(options) {
56
+ const params = {};
57
+ if (options?.commodity)
58
+ params.commodity = options.commodity;
59
+ if (options?.days)
60
+ params.days = options.days.toString();
61
+ return this.client["request"]("/v1/analytics/performance", params);
62
+ }
63
+ /**
64
+ * Get statistical analysis for a commodity
65
+ *
66
+ * Returns comprehensive statistical metrics including mean, median,
67
+ * standard deviation, and distribution characteristics.
68
+ *
69
+ * @param commodity - Commodity code to analyze
70
+ * @param days - Number of days to analyze (default: 30)
71
+ * @returns Statistical analysis
72
+ *
73
+ * @throws {NotFoundError} If commodity not found
74
+ * @throws {OilPriceAPIError} If API request fails
75
+ *
76
+ * @example
77
+ * ```typescript
78
+ * const stats = await client.analytics.statistics('BRENT_CRUDE_USD', 90);
79
+ * console.log(`Mean: $${stats.mean}`);
80
+ * console.log(`Std Dev: ${stats.std_dev}`);
81
+ * console.log(`Range: $${stats.min} - $${stats.max}`);
82
+ * ```
83
+ */
84
+ async statistics(commodity, days) {
85
+ if (!commodity || typeof commodity !== "string") {
86
+ throw new Error("Commodity code must be a non-empty string");
87
+ }
88
+ const params = { commodity };
89
+ if (days)
90
+ params.days = days.toString();
91
+ return this.client["request"]("/v1/analytics/statistics", params);
92
+ }
93
+ /**
94
+ * Analyze correlation between two commodities
95
+ *
96
+ * Calculates the Pearson correlation coefficient to measure how closely
97
+ * two commodities move together.
98
+ *
99
+ * @param commodity1 - First commodity code
100
+ * @param commodity2 - Second commodity code
101
+ * @param days - Number of days to analyze (default: 30)
102
+ * @returns Correlation analysis
103
+ *
104
+ * @throws {NotFoundError} If either commodity not found
105
+ * @throws {OilPriceAPIError} If API request fails
106
+ *
107
+ * @example
108
+ * ```typescript
109
+ * const corr = await client.analytics.correlation('WTI_USD', 'BRENT_CRUDE_USD', 90);
110
+ * console.log(`Correlation: ${corr.correlation}`);
111
+ * console.log(`Strength: ${corr.strength}`);
112
+ * console.log(`R-squared: ${corr.r_squared}`);
113
+ * ```
114
+ */
115
+ async correlation(commodity1, commodity2, days) {
116
+ if (!commodity1 || typeof commodity1 !== "string") {
117
+ throw new Error("First commodity code must be a non-empty string");
118
+ }
119
+ if (!commodity2 || typeof commodity2 !== "string") {
120
+ throw new Error("Second commodity code must be a non-empty string");
121
+ }
122
+ const params = {
123
+ commodity1,
124
+ commodity2,
125
+ };
126
+ if (days)
127
+ params.days = days.toString();
128
+ return this.client["request"]("/v1/analytics/correlation", params);
129
+ }
130
+ /**
131
+ * Analyze price trend for a commodity
132
+ *
133
+ * Detects trend direction, strength, and key levels (support/resistance).
134
+ *
135
+ * @param commodity - Commodity code to analyze
136
+ * @param days - Number of days to analyze (default: 30)
137
+ * @returns Trend analysis
138
+ *
139
+ * @throws {NotFoundError} If commodity not found
140
+ * @throws {OilPriceAPIError} If API request fails
141
+ *
142
+ * @example
143
+ * ```typescript
144
+ * const trend = await client.analytics.trend('WTI_USD', 60);
145
+ * console.log(`Trend: ${trend.trend} (strength: ${trend.strength})`);
146
+ * console.log(`Support: $${trend.support}`);
147
+ * console.log(`Resistance: $${trend.resistance}`);
148
+ * ```
149
+ */
150
+ async trend(commodity, days) {
151
+ if (!commodity || typeof commodity !== "string") {
152
+ throw new Error("Commodity code must be a non-empty string");
153
+ }
154
+ const params = { commodity };
155
+ if (days)
156
+ params.days = days.toString();
157
+ return this.client["request"]("/v1/analytics/trend", params);
158
+ }
159
+ /**
160
+ * Analyze spread between two commodities
161
+ *
162
+ * Calculates current spread and compares to historical patterns.
163
+ *
164
+ * @param commodity1 - First commodity code
165
+ * @param commodity2 - Second commodity code
166
+ * @returns Spread analysis
167
+ *
168
+ * @throws {NotFoundError} If either commodity not found
169
+ * @throws {OilPriceAPIError} If API request fails
170
+ *
171
+ * @example
172
+ * ```typescript
173
+ * const spread = await client.analytics.spread('BRENT_CRUDE_USD', 'WTI_USD');
174
+ * console.log(`Current spread: $${spread.spread}`);
175
+ * console.log(`Average spread: $${spread.average_spread}`);
176
+ * console.log(`Z-score: ${spread.z_score}`);
177
+ * ```
178
+ */
179
+ async spread(commodity1, commodity2) {
180
+ if (!commodity1 || typeof commodity1 !== "string") {
181
+ throw new Error("First commodity code must be a non-empty string");
182
+ }
183
+ if (!commodity2 || typeof commodity2 !== "string") {
184
+ throw new Error("Second commodity code must be a non-empty string");
185
+ }
186
+ return this.client["request"]("/v1/analytics/spread", {
187
+ commodity1,
188
+ commodity2,
189
+ });
190
+ }
191
+ /**
192
+ * Get price forecast for a commodity
193
+ *
194
+ * Returns forecasted prices with confidence intervals.
195
+ *
196
+ * @param commodity - Commodity code to forecast
197
+ * @returns Price forecast
198
+ *
199
+ * @throws {NotFoundError} If commodity not found
200
+ * @throws {OilPriceAPIError} If API request fails
201
+ *
202
+ * @example
203
+ * ```typescript
204
+ * const forecast = await client.analytics.forecast('WTI_USD');
205
+ * console.log(`Forecast model: ${forecast.model}`);
206
+ * console.log(`Horizon: ${forecast.horizon_days} days`);
207
+ *
208
+ * forecast.forecast.forEach(point => {
209
+ * console.log(`${point.date}: $${point.price} (${point.lower_bound}-${point.upper_bound})`);
210
+ * });
211
+ * ```
212
+ */
213
+ async forecast(commodity) {
214
+ if (!commodity || typeof commodity !== "string") {
215
+ throw new Error("Commodity code must be a non-empty string");
216
+ }
217
+ return this.client["request"]("/v1/analytics/forecast", {
218
+ commodity,
219
+ });
220
+ }
221
+ }
@@ -0,0 +1,270 @@
1
+ /**
2
+ * Bunker Fuels Resource
3
+ *
4
+ * Access bunker fuel prices at major ports worldwide, including VLSFO, MGO,
5
+ * and IFO380. Compare prices across ports and track historical trends.
6
+ */
7
+ import type { OilPriceAPI } from "../client.js";
8
+ /**
9
+ * Bunker fuel price data
10
+ */
11
+ export interface BunkerFuelPrice {
12
+ /** Port code */
13
+ port: string;
14
+ /** Port name */
15
+ port_name?: string;
16
+ /** Fuel type (e.g., "VLSFO", "MGO", "IFO380") */
17
+ fuel_type: string;
18
+ /** Price per metric ton */
19
+ price: number;
20
+ /** Currency code (typically "USD") */
21
+ currency: string;
22
+ /** Unit (typically "MT" for metric ton) */
23
+ unit: string;
24
+ /** ISO timestamp when price was recorded */
25
+ timestamp: string;
26
+ /** Price change from previous day */
27
+ change?: number;
28
+ /** Additional metadata */
29
+ metadata?: Record<string, unknown>;
30
+ }
31
+ /**
32
+ * Port-specific bunker fuel prices
33
+ */
34
+ export interface PortBunkerPrices {
35
+ /** Port code */
36
+ port: string;
37
+ /** Port name */
38
+ port_name: string;
39
+ /** Geographic region */
40
+ region?: string;
41
+ /** ISO timestamp */
42
+ timestamp: string;
43
+ /** Fuel prices by type */
44
+ prices: {
45
+ /** VLSFO price */
46
+ VLSFO?: number;
47
+ /** MGO price */
48
+ MGO?: number;
49
+ /** IFO380 price */
50
+ IFO380?: number;
51
+ /** Other fuel types */
52
+ [fuelType: string]: number | undefined;
53
+ };
54
+ /** Currency code */
55
+ currency: string;
56
+ /** Unit of measurement */
57
+ unit: string;
58
+ }
59
+ /**
60
+ * Price comparison between ports
61
+ */
62
+ export interface PortPriceComparison {
63
+ /** Fuel type being compared */
64
+ fuel_type: string;
65
+ /** ISO timestamp */
66
+ timestamp: string;
67
+ /** Array of port prices */
68
+ ports: Array<{
69
+ /** Port code */
70
+ port: string;
71
+ /** Port name */
72
+ port_name: string;
73
+ /** Price */
74
+ price: number;
75
+ /** Rank (1 = cheapest) */
76
+ rank?: number;
77
+ }>;
78
+ /** Currency code */
79
+ currency: string;
80
+ /** Unit of measurement */
81
+ unit: string;
82
+ }
83
+ /**
84
+ * Bunker fuel price spreads
85
+ */
86
+ export interface BunkerFuelSpreads {
87
+ /** ISO timestamp */
88
+ timestamp: string;
89
+ /** Spreads between fuel grades */
90
+ spreads: Array<{
91
+ /** High-grade fuel */
92
+ fuel1: string;
93
+ /** Low-grade fuel */
94
+ fuel2: string;
95
+ /** Average spread across ports */
96
+ average_spread: number;
97
+ /** Spread range */
98
+ min_spread: number;
99
+ max_spread: number;
100
+ }>;
101
+ /** Currency code */
102
+ currency: string;
103
+ }
104
+ /**
105
+ * Historical bunker fuel price data
106
+ */
107
+ export interface HistoricalBunkerPrice {
108
+ /** Date in YYYY-MM-DD format */
109
+ date: string;
110
+ /** Price */
111
+ price: number;
112
+ /** Currency code */
113
+ currency: string;
114
+ /** Unit of measurement */
115
+ unit: string;
116
+ }
117
+ /**
118
+ * Options for historical bunker fuel query
119
+ */
120
+ export interface HistoricalBunkerOptions {
121
+ /** Start date in ISO 8601 format (YYYY-MM-DD) */
122
+ startDate?: string;
123
+ /** End date in ISO 8601 format (YYYY-MM-DD) */
124
+ endDate?: string;
125
+ }
126
+ /**
127
+ * Bunker Fuels Resource
128
+ *
129
+ * Access bunker fuel prices at major ports worldwide. Track VLSFO, MGO, and
130
+ * IFO380 prices, compare across ports, and analyze historical trends.
131
+ *
132
+ * @example
133
+ * ```typescript
134
+ * import { OilPriceAPI } from 'oilpriceapi';
135
+ *
136
+ * const client = new OilPriceAPI({ apiKey: 'your_key' });
137
+ *
138
+ * // Get all bunker fuel prices
139
+ * const prices = await client.bunkerFuels.all();
140
+ *
141
+ * // Get prices for specific port
142
+ * const singapore = await client.bunkerFuels.port('SIN');
143
+ * console.log(`Singapore VLSFO: $${singapore.prices.VLSFO}/MT`);
144
+ *
145
+ * // Compare prices across ports
146
+ * const comparison = await client.bunkerFuels.compare(['SIN', 'RTM', 'HOU']);
147
+ * ```
148
+ */
149
+ export declare class BunkerFuelsResource {
150
+ private client;
151
+ constructor(client: OilPriceAPI);
152
+ /**
153
+ * Get all current bunker fuel prices
154
+ *
155
+ * Returns prices for all tracked ports and fuel types.
156
+ *
157
+ * @returns Array of bunker fuel prices
158
+ *
159
+ * @throws {OilPriceAPIError} If API request fails
160
+ * @throws {AuthenticationError} If API key is invalid
161
+ *
162
+ * @example
163
+ * ```typescript
164
+ * const prices = await client.bunkerFuels.all();
165
+ * prices.forEach(price => {
166
+ * console.log(`${price.port_name} ${price.fuel_type}: $${price.price}/${price.unit}`);
167
+ * });
168
+ * ```
169
+ */
170
+ all(): Promise<BunkerFuelPrice[]>;
171
+ /**
172
+ * Get bunker fuel prices for a specific port
173
+ *
174
+ * @param code - Port code (e.g., "SIN" for Singapore, "RTM" for Rotterdam)
175
+ * @returns Port-specific prices across fuel types
176
+ *
177
+ * @throws {NotFoundError} If port code not found
178
+ * @throws {OilPriceAPIError} If API request fails
179
+ *
180
+ * @example
181
+ * ```typescript
182
+ * const singapore = await client.bunkerFuels.port('SIN');
183
+ * console.log(`Singapore Bunker Prices (${singapore.timestamp}):`);
184
+ * console.log(`VLSFO: $${singapore.prices.VLSFO}/${singapore.unit}`);
185
+ * console.log(`MGO: $${singapore.prices.MGO}/${singapore.unit}`);
186
+ * ```
187
+ */
188
+ port(code: string): Promise<PortBunkerPrices>;
189
+ /**
190
+ * Compare prices across multiple ports
191
+ *
192
+ * @param ports - Array of port codes to compare
193
+ * @returns Price comparison data
194
+ *
195
+ * @throws {OilPriceAPIError} If API request fails
196
+ *
197
+ * @example
198
+ * ```typescript
199
+ * const comparison = await client.bunkerFuels.compare(['SIN', 'RTM', 'HOU', 'FUJ']);
200
+ *
201
+ * console.log(`Comparing ${comparison.fuel_type} prices:`);
202
+ * comparison.ports.forEach((port, index) => {
203
+ * console.log(`${index + 1}. ${port.port_name}: $${port.price}`);
204
+ * });
205
+ * ```
206
+ */
207
+ compare(ports: string[]): Promise<PortPriceComparison>;
208
+ /**
209
+ * Get bunker fuel price spreads
210
+ *
211
+ * Returns spreads between different fuel grades (e.g., VLSFO-IFO380).
212
+ *
213
+ * @returns Fuel price spreads
214
+ *
215
+ * @throws {OilPriceAPIError} If API request fails
216
+ *
217
+ * @example
218
+ * ```typescript
219
+ * const spreads = await client.bunkerFuels.spreads();
220
+ * spreads.spreads.forEach(spread => {
221
+ * console.log(`${spread.fuel1}-${spread.fuel2} spread: $${spread.average_spread}`);
222
+ * });
223
+ * ```
224
+ */
225
+ spreads(): Promise<BunkerFuelSpreads>;
226
+ /**
227
+ * Get historical bunker fuel prices
228
+ *
229
+ * @param port - Port code (e.g., "SIN", "RTM")
230
+ * @param fuelType - Fuel type (e.g., "VLSFO", "MGO", "IFO380")
231
+ * @param options - Date range filters
232
+ * @returns Array of historical prices
233
+ *
234
+ * @throws {NotFoundError} If port or fuel type not found
235
+ * @throws {OilPriceAPIError} If API request fails
236
+ *
237
+ * @example
238
+ * ```typescript
239
+ * const history = await client.bunkerFuels.historical('SIN', 'VLSFO', {
240
+ * startDate: '2024-01-01',
241
+ * endDate: '2024-12-31'
242
+ * });
243
+ *
244
+ * history.forEach(point => {
245
+ * console.log(`${point.date}: $${point.price}/${point.unit}`);
246
+ * });
247
+ * ```
248
+ */
249
+ historical(port: string, fuelType: string, options?: HistoricalBunkerOptions): Promise<HistoricalBunkerPrice[]>;
250
+ /**
251
+ * Export bunker fuel data
252
+ *
253
+ * Export bunker fuel prices in specified format (CSV, JSON, Excel).
254
+ *
255
+ * @param format - Export format (default: "csv")
256
+ * @returns Export data or download URL
257
+ *
258
+ * @throws {OilPriceAPIError} If API request fails
259
+ *
260
+ * @example
261
+ * ```typescript
262
+ * // Export as CSV
263
+ * const csvData = await client.bunkerFuels.export('csv');
264
+ *
265
+ * // Export as JSON
266
+ * const jsonData = await client.bunkerFuels.export('json');
267
+ * ```
268
+ */
269
+ export(format?: string): Promise<any>;
270
+ }
@@ -0,0 +1,191 @@
1
+ /**
2
+ * Bunker Fuels Resource
3
+ *
4
+ * Access bunker fuel prices at major ports worldwide, including VLSFO, MGO,
5
+ * and IFO380. Compare prices across ports and track historical trends.
6
+ */
7
+ /**
8
+ * Bunker Fuels Resource
9
+ *
10
+ * Access bunker fuel prices at major ports worldwide. Track VLSFO, MGO, and
11
+ * IFO380 prices, compare across ports, and analyze historical trends.
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * import { OilPriceAPI } from 'oilpriceapi';
16
+ *
17
+ * const client = new OilPriceAPI({ apiKey: 'your_key' });
18
+ *
19
+ * // Get all bunker fuel prices
20
+ * const prices = await client.bunkerFuels.all();
21
+ *
22
+ * // Get prices for specific port
23
+ * const singapore = await client.bunkerFuels.port('SIN');
24
+ * console.log(`Singapore VLSFO: $${singapore.prices.VLSFO}/MT`);
25
+ *
26
+ * // Compare prices across ports
27
+ * const comparison = await client.bunkerFuels.compare(['SIN', 'RTM', 'HOU']);
28
+ * ```
29
+ */
30
+ export class BunkerFuelsResource {
31
+ constructor(client) {
32
+ this.client = client;
33
+ }
34
+ /**
35
+ * Get all current bunker fuel prices
36
+ *
37
+ * Returns prices for all tracked ports and fuel types.
38
+ *
39
+ * @returns Array of bunker fuel prices
40
+ *
41
+ * @throws {OilPriceAPIError} If API request fails
42
+ * @throws {AuthenticationError} If API key is invalid
43
+ *
44
+ * @example
45
+ * ```typescript
46
+ * const prices = await client.bunkerFuels.all();
47
+ * prices.forEach(price => {
48
+ * console.log(`${price.port_name} ${price.fuel_type}: $${price.price}/${price.unit}`);
49
+ * });
50
+ * ```
51
+ */
52
+ async all() {
53
+ const response = await this.client["request"]("/v1/bunker-fuels", {});
54
+ return Array.isArray(response) ? response : response.prices;
55
+ }
56
+ /**
57
+ * Get bunker fuel prices for a specific port
58
+ *
59
+ * @param code - Port code (e.g., "SIN" for Singapore, "RTM" for Rotterdam)
60
+ * @returns Port-specific prices across fuel types
61
+ *
62
+ * @throws {NotFoundError} If port code not found
63
+ * @throws {OilPriceAPIError} If API request fails
64
+ *
65
+ * @example
66
+ * ```typescript
67
+ * const singapore = await client.bunkerFuels.port('SIN');
68
+ * console.log(`Singapore Bunker Prices (${singapore.timestamp}):`);
69
+ * console.log(`VLSFO: $${singapore.prices.VLSFO}/${singapore.unit}`);
70
+ * console.log(`MGO: $${singapore.prices.MGO}/${singapore.unit}`);
71
+ * ```
72
+ */
73
+ async port(code) {
74
+ if (!code || typeof code !== "string") {
75
+ throw new Error("Port code must be a non-empty string");
76
+ }
77
+ return this.client["request"](`/v1/bunker-fuels/ports/${code}`, {});
78
+ }
79
+ /**
80
+ * Compare prices across multiple ports
81
+ *
82
+ * @param ports - Array of port codes to compare
83
+ * @returns Price comparison data
84
+ *
85
+ * @throws {OilPriceAPIError} If API request fails
86
+ *
87
+ * @example
88
+ * ```typescript
89
+ * const comparison = await client.bunkerFuels.compare(['SIN', 'RTM', 'HOU', 'FUJ']);
90
+ *
91
+ * console.log(`Comparing ${comparison.fuel_type} prices:`);
92
+ * comparison.ports.forEach((port, index) => {
93
+ * console.log(`${index + 1}. ${port.port_name}: $${port.price}`);
94
+ * });
95
+ * ```
96
+ */
97
+ async compare(ports) {
98
+ if (!Array.isArray(ports) || ports.length === 0) {
99
+ throw new Error("Ports must be a non-empty array of port codes");
100
+ }
101
+ return this.client["request"]("/v1/bunker-fuels/compare", {
102
+ ports: ports.join(","),
103
+ });
104
+ }
105
+ /**
106
+ * Get bunker fuel price spreads
107
+ *
108
+ * Returns spreads between different fuel grades (e.g., VLSFO-IFO380).
109
+ *
110
+ * @returns Fuel price spreads
111
+ *
112
+ * @throws {OilPriceAPIError} If API request fails
113
+ *
114
+ * @example
115
+ * ```typescript
116
+ * const spreads = await client.bunkerFuels.spreads();
117
+ * spreads.spreads.forEach(spread => {
118
+ * console.log(`${spread.fuel1}-${spread.fuel2} spread: $${spread.average_spread}`);
119
+ * });
120
+ * ```
121
+ */
122
+ async spreads() {
123
+ return this.client["request"]("/v1/bunker-fuels/spreads", {});
124
+ }
125
+ /**
126
+ * Get historical bunker fuel prices
127
+ *
128
+ * @param port - Port code (e.g., "SIN", "RTM")
129
+ * @param fuelType - Fuel type (e.g., "VLSFO", "MGO", "IFO380")
130
+ * @param options - Date range filters
131
+ * @returns Array of historical prices
132
+ *
133
+ * @throws {NotFoundError} If port or fuel type not found
134
+ * @throws {OilPriceAPIError} If API request fails
135
+ *
136
+ * @example
137
+ * ```typescript
138
+ * const history = await client.bunkerFuels.historical('SIN', 'VLSFO', {
139
+ * startDate: '2024-01-01',
140
+ * endDate: '2024-12-31'
141
+ * });
142
+ *
143
+ * history.forEach(point => {
144
+ * console.log(`${point.date}: $${point.price}/${point.unit}`);
145
+ * });
146
+ * ```
147
+ */
148
+ async historical(port, fuelType, options) {
149
+ if (!port || typeof port !== "string") {
150
+ throw new Error("Port code must be a non-empty string");
151
+ }
152
+ if (!fuelType || typeof fuelType !== "string") {
153
+ throw new Error("Fuel type must be a non-empty string");
154
+ }
155
+ const params = {
156
+ port,
157
+ fuel_type: fuelType,
158
+ };
159
+ if (options?.startDate)
160
+ params.start_date = options.startDate;
161
+ if (options?.endDate)
162
+ params.end_date = options.endDate;
163
+ const response = await this.client["request"]("/v1/bunker-fuels/historical", params);
164
+ return Array.isArray(response) ? response : response.data;
165
+ }
166
+ /**
167
+ * Export bunker fuel data
168
+ *
169
+ * Export bunker fuel prices in specified format (CSV, JSON, Excel).
170
+ *
171
+ * @param format - Export format (default: "csv")
172
+ * @returns Export data or download URL
173
+ *
174
+ * @throws {OilPriceAPIError} If API request fails
175
+ *
176
+ * @example
177
+ * ```typescript
178
+ * // Export as CSV
179
+ * const csvData = await client.bunkerFuels.export('csv');
180
+ *
181
+ * // Export as JSON
182
+ * const jsonData = await client.bunkerFuels.export('json');
183
+ * ```
184
+ */
185
+ async export(format) {
186
+ const params = {};
187
+ if (format)
188
+ params.format = format;
189
+ return this.client["request"]("/v1/bunker-fuels/export", params);
190
+ }
191
+ }