oilpriceapi 0.9.0 → 0.9.1

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.
@@ -7,6 +7,7 @@
7
7
  */
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.FuturesResource = exports.FuturesContractFamily = exports.FUTURES_FAMILY_SLUGS = exports.FUTURES_CONTRACTS = void 0;
10
+ exports.resolveFuturesFamilySlug = resolveFuturesFamilySlug;
10
11
  const errors_js_1 = require("../errors.js");
11
12
  /**
12
13
  * Ergonomic contract codes for the most-requested futures families (issue #1).
@@ -48,15 +49,34 @@ exports.FUTURES_CONTRACTS = {
48
49
  * path segment used by the typed family helpers.
49
50
  */
50
51
  exports.FUTURES_FAMILY_SLUGS = {
51
- [exports.FUTURES_CONTRACTS.BRENT]: "ice-brent",
52
- [exports.FUTURES_CONTRACTS.WTI]: "ice-wti",
53
- [exports.FUTURES_CONTRACTS.GASOIL]: "ice-gasoil",
54
- [exports.FUTURES_CONTRACTS.NATURAL_GAS]: "natural-gas",
55
- [exports.FUTURES_CONTRACTS.TTF_GAS]: "ttf-gas",
56
- [exports.FUTURES_CONTRACTS.LNG_JKM]: "lng-jkm",
57
- [exports.FUTURES_CONTRACTS.EUA_CARBON]: "eua-carbon",
58
- [exports.FUTURES_CONTRACTS.UK_CARBON]: "uk-carbon",
52
+ [exports.FUTURES_CONTRACTS.BRENT]: "ice-brent", // BZ
53
+ [exports.FUTURES_CONTRACTS.WTI]: "ice-wti", // CL
54
+ [exports.FUTURES_CONTRACTS.GASOIL]: "ice-gasoil", // G
55
+ QS: "ice-gasoil", // ICE Gasoil also trades under the QS ticker prefix
56
+ [exports.FUTURES_CONTRACTS.NATURAL_GAS]: "natural-gas", // NG
57
+ [exports.FUTURES_CONTRACTS.TTF_GAS]: "ttf-gas", // TTF
58
+ [exports.FUTURES_CONTRACTS.LNG_JKM]: "lng-jkm", // JKM
59
+ [exports.FUTURES_CONTRACTS.EUA_CARBON]: "eua-carbon", // EUA
60
+ [exports.FUTURES_CONTRACTS.UK_CARBON]: "uk-carbon", // UKA
59
61
  };
62
+ /**
63
+ * Resolve a futures contract code (e.g. `"BZ"`, `"QS"`) or an already-valid
64
+ * family slug (e.g. `"ice-brent"`) to its `/v1/futures/{slug}` path segment.
65
+ *
66
+ * Matching is case-insensitive for codes. Returns `null` if the input maps to
67
+ * neither a known code nor a known family slug.
68
+ */
69
+ function resolveFuturesFamilySlug(codeOrSlug) {
70
+ const trimmed = codeOrSlug.trim();
71
+ // Direct code match (case-insensitive — codes are upper-case).
72
+ const byCode = exports.FUTURES_FAMILY_SLUGS[trimmed.toUpperCase()];
73
+ if (byCode)
74
+ return byCode;
75
+ // Already a valid family slug?
76
+ const lower = trimmed.toLowerCase();
77
+ const isSlug = Object.values(exports.FUTURES_FAMILY_SLUGS).includes(lower);
78
+ return isSlug ? lower : null;
79
+ }
60
80
  /**
61
81
  * Typed helper for a single futures contract family (e.g., ICE Brent, Gasoil).
62
82
  *
@@ -80,9 +100,12 @@ class FuturesContractFamily {
80
100
  }
81
101
  /**
82
102
  * Get the latest price for this contract family.
103
+ *
104
+ * Latest is served from the bare slug path `GET /v1/futures/{slug}` —
105
+ * there is NO `/latest` suffix (that path 404s).
83
106
  */
84
107
  async latest() {
85
- return this.client["request"](`/v1/futures/${this.slug}/latest`, {});
108
+ return this.client["request"](`/v1/futures/${this.slug}`, {});
86
109
  }
87
110
  /**
88
111
  * Get historical prices for this contract family.
@@ -156,16 +179,13 @@ exports.FuturesContractFamily = FuturesContractFamily;
156
179
  *
157
180
  * const client = new OilPriceAPI({ apiKey: 'your_key' });
158
181
  *
159
- * // Get latest price
160
- * const latest = await client.futures.latest('CL.1');
182
+ * // Get the latest curve by contract code (resolves to GET /v1/futures/ice-wti)
183
+ * const latest = await client.futures.latest('CL');
161
184
  * console.log(`${latest.contract}: $${latest.price}`);
162
185
  *
163
- * // Get OHLC data
164
- * const ohlc = await client.futures.ohlc('CL.1', '2024-01-15');
165
- * console.log(`High: $${ohlc.high}, Low: $${ohlc.low}`);
166
- *
167
- * // Get futures curve
168
- * const curve = await client.futures.curve('CL');
186
+ * // Typed family helpers are the most ergonomic option:
187
+ * const brent = await client.futures.brent().latest();
188
+ * const curve = await client.futures.brent().curve();
169
189
  * curve.curve.forEach(point => {
170
190
  * console.log(`${point.months_out}mo: $${point.price}`);
171
191
  * });
@@ -176,25 +196,42 @@ class FuturesResource {
176
196
  this.client = client;
177
197
  }
178
198
  /**
179
- * Get latest price for a futures contract
199
+ * Get the latest curve/quote for a futures contract family.
180
200
  *
181
- * @param contract - Contract symbol (e.g., "CL.1", "BZ.2")
182
- * @returns Latest futures price data
201
+ * Accepts an ergonomic contract code (e.g. `"BZ"`, `"CL"`, `"QS"`) or a
202
+ * family slug (e.g. `"ice-brent"`). The code is resolved to its family slug
203
+ * and the request is sent to `GET /v1/futures/{slug}` — the bare slug path,
204
+ * with NO `/latest` suffix (the suffixed path 404s).
183
205
  *
184
- * @throws {NotFoundError} If contract not found
206
+ * Supported codes: BZ (Brent), CL (WTI), G/QS (Gasoil), NG (Natural Gas),
207
+ * TTF, JKM, EUA, UKA. Slugs: ice-brent, ice-wti, ice-gasoil, natural-gas,
208
+ * ttf-gas, lng-jkm, eua-carbon, uk-carbon.
209
+ *
210
+ * @param contract - Contract code (e.g. "BZ") or family slug (e.g. "ice-brent").
211
+ * @returns Latest futures price/curve data
212
+ *
213
+ * @throws {ValidationError} If the code/slug is empty or unrecognized.
185
214
  * @throws {OilPriceAPIError} If API request fails
186
215
  *
187
216
  * @example
188
217
  * ```typescript
189
- * const price = await client.futures.latest('CL.1');
190
- * console.log(`WTI Front Month: $${price.price}`);
218
+ * import { FUTURES_CONTRACTS } from 'oilpriceapi';
219
+ * const price = await client.futures.latest(FUTURES_CONTRACTS.BRENT); // "BZ"
220
+ * const wti = await client.futures.latest('ice-wti');
191
221
  * ```
192
222
  */
193
223
  async latest(contract) {
194
224
  if (!contract || typeof contract !== "string") {
195
225
  throw new errors_js_1.ValidationError("Contract symbol must be a non-empty string");
196
226
  }
197
- return this.client["request"](`/v1/futures/${contract}`, {});
227
+ const slug = resolveFuturesFamilySlug(contract);
228
+ if (!slug) {
229
+ throw new errors_js_1.ValidationError(`Unknown futures contract "${contract}". Use a contract code ` +
230
+ `(BZ, CL, G, QS, NG, TTF, JKM, EUA, UKA) or a family slug ` +
231
+ `(ice-brent, ice-wti, ice-gasoil, natural-gas, ttf-gas, lng-jkm, ` +
232
+ `eua-carbon, uk-carbon).`);
233
+ }
234
+ return this.client["request"](`/v1/futures/${slug}`, {});
198
235
  }
199
236
  /**
200
237
  * Get historical prices for a futures contract
@@ -11,7 +11,7 @@ exports.buildUserAgent = buildUserAgent;
11
11
  * - X-Client-Version header
12
12
  * - Package.json (should match)
13
13
  */
14
- exports.SDK_VERSION = "0.9.0";
14
+ exports.SDK_VERSION = "0.9.1";
15
15
  /**
16
16
  * SDK identifier used in User-Agent and X-Api-Client headers
17
17
  */
@@ -6,23 +6,71 @@
6
6
  */
7
7
  import type { OilPriceAPI } from "../client.js";
8
8
  /**
9
- * Futures contract price data
9
+ * A single futures contract month within a {@link FuturesPrice} response.
10
+ *
11
+ * Returned at the top level under `front_month` and for every entry in
12
+ * `contracts[]`. The latest traded price is `last_price`.
13
+ */
14
+ export interface FuturesContractMonth {
15
+ /** Contract code (e.g. "BRENT_FUTURES_2026_08"). */
16
+ code?: string;
17
+ /** Contract month in YYYY-MM form (e.g. "2026-08"). */
18
+ contract_month?: string;
19
+ /** Latest traded/settlement price for this contract month. */
20
+ last_price?: number;
21
+ /** Currency code (e.g. "USD"). */
22
+ currency?: string;
23
+ /** Opening price (may be returned as a string by the API). */
24
+ open?: number | string;
25
+ /** Closing price (may be returned as a string by the API). */
26
+ close?: number | string;
27
+ /** Session high. */
28
+ high?: number | string;
29
+ /** Session low. */
30
+ low?: number | string;
31
+ /** Any additional fields the API returns for a contract month. */
32
+ [key: string]: unknown;
33
+ }
34
+ /**
35
+ * Futures contract price data.
36
+ *
37
+ * `GET /v1/futures/{slug}` returns a TOP-LEVEL object (there is NO
38
+ * `{ status, data }` envelope). The latest price lives at
39
+ * `front_month.last_price`, with the full term structure in `contracts[]`.
40
+ *
41
+ * Legacy flat fields (`contract`, `price`, `currency`, `timestamp`) are kept
42
+ * optional for backward compatibility, but real responses populate
43
+ * `front_month` / `contracts` instead.
10
44
  */
11
45
  export interface FuturesPrice {
12
- /** Contract symbol */
13
- contract: string;
14
- /** Current price */
15
- price: number;
16
- /** Formatted price string */
46
+ /** Commodity identifier (e.g. "BRENT_FUTURES"). */
47
+ commodity?: string;
48
+ /** Data source (e.g. "ICE"). */
49
+ source?: string;
50
+ /** ISO timestamp the data was last updated. */
51
+ updated_at?: string;
52
+ /** Settlement date for the prices. */
53
+ settlement_date?: string;
54
+ /** Front-month contract — the latest price is `front_month.last_price`. */
55
+ front_month?: FuturesContractMonth;
56
+ /** Full forward term structure, one entry per contract month. */
57
+ contracts?: FuturesContractMonth[];
58
+ /** Optional warning when the returned data is stale. */
59
+ data_age_warning?: unknown;
60
+ /** Additional metadata returned by the API. */
61
+ metadata?: Record<string, unknown>;
62
+ /** @deprecated Legacy flat contract symbol — use `front_month.code`. */
63
+ contract?: string;
64
+ /** @deprecated Legacy flat price — use `front_month.last_price`. */
65
+ price?: number;
66
+ /** @deprecated Legacy formatted price string. */
17
67
  formatted?: string;
18
- /** Currency code */
19
- currency: string;
20
- /** Contract expiration date */
68
+ /** @deprecated Legacy currency — use `front_month.currency`. */
69
+ currency?: string;
70
+ /** @deprecated Legacy contract expiration date. */
21
71
  expiration?: string;
22
- /** ISO timestamp when price was recorded */
23
- timestamp: string;
24
- /** Additional metadata */
25
- metadata?: Record<string, unknown>;
72
+ /** @deprecated Legacy ISO timestamp use `updated_at`. */
73
+ timestamp?: string;
26
74
  }
27
75
  /**
28
76
  * Historical futures price data
@@ -141,15 +189,25 @@ export interface FuturesCurvePoint {
141
189
  contract?: string;
142
190
  }
143
191
  /**
144
- * Futures curve data
192
+ * Futures curve data.
193
+ *
194
+ * `GET /v1/futures/{slug}/curve` can legitimately return a no-data response of
195
+ * the form `{ error: "No futures data available for curve analysis", date }`
196
+ * when a curve cannot be built. That is a valid state (not an HTTP error), so
197
+ * `curve` is optional and `error` / `date` are surfaced for callers to detect
198
+ * the no-data case.
145
199
  */
146
200
  export interface FuturesCurveData {
147
201
  /** Base contract */
148
- contract: string;
202
+ contract?: string;
149
203
  /** ISO timestamp when curve was generated */
150
- timestamp: string;
151
- /** Array of curve points */
152
- curve: FuturesCurvePoint[];
204
+ timestamp?: string;
205
+ /** Array of curve points (absent in the no-data response) */
206
+ curve?: FuturesCurvePoint[];
207
+ /** Present in the no-data response: "No futures data available for curve analysis". */
208
+ error?: string;
209
+ /** Date associated with the no-data response. */
210
+ date?: string;
153
211
  }
154
212
  /**
155
213
  * Continuous contract data point
@@ -196,9 +254,10 @@ export interface FuturesSpreadHistory {
196
254
  /**
197
255
  * Slugs for the supported ICE / gas / carbon futures contract families.
198
256
  *
199
- * These map to the `GET /v1/futures/{slug}/...` endpoints. Each family
200
- * supports `/latest`, `/historical`, `/ohlc`, `/intraday`, `/spreads`,
201
- * `/curve`, and `/spread-history`.
257
+ * These map to the `GET /v1/futures/{slug}` (latest) endpoint plus the
258
+ * `GET /v1/futures/{slug}/...` sub-resources. Latest is the bare slug path
259
+ * (there is NO `/latest` suffix). Each family also supports `/historical`,
260
+ * `/ohlc`, `/intraday`, `/spreads`, `/curve`, and `/spread-history`.
202
261
  */
203
262
  export type FuturesContractFamilySlug = "ice-brent" | "ice-gasoil" | "ice-wti" | "natural-gas" | "ttf-gas" | "lng-jkm" | "eua-carbon" | "uk-carbon";
204
263
  /**
@@ -241,6 +300,14 @@ export declare const FUTURES_CONTRACTS: {
241
300
  * path segment used by the typed family helpers.
242
301
  */
243
302
  export declare const FUTURES_FAMILY_SLUGS: Record<string, FuturesContractFamilySlug>;
303
+ /**
304
+ * Resolve a futures contract code (e.g. `"BZ"`, `"QS"`) or an already-valid
305
+ * family slug (e.g. `"ice-brent"`) to its `/v1/futures/{slug}` path segment.
306
+ *
307
+ * Matching is case-insensitive for codes. Returns `null` if the input maps to
308
+ * neither a known code nor a known family slug.
309
+ */
310
+ export declare function resolveFuturesFamilySlug(codeOrSlug: string): FuturesContractFamilySlug | null;
244
311
  /**
245
312
  * Typed helper for a single futures contract family (e.g., ICE Brent, Gasoil).
246
313
  *
@@ -264,6 +331,9 @@ export declare class FuturesContractFamily {
264
331
  slug: FuturesContractFamilySlug);
265
332
  /**
266
333
  * Get the latest price for this contract family.
334
+ *
335
+ * Latest is served from the bare slug path `GET /v1/futures/{slug}` —
336
+ * there is NO `/latest` suffix (that path 404s).
267
337
  */
268
338
  latest(): Promise<FuturesPrice>;
269
339
  /**
@@ -307,16 +377,13 @@ export declare class FuturesContractFamily {
307
377
  *
308
378
  * const client = new OilPriceAPI({ apiKey: 'your_key' });
309
379
  *
310
- * // Get latest price
311
- * const latest = await client.futures.latest('CL.1');
380
+ * // Get the latest curve by contract code (resolves to GET /v1/futures/ice-wti)
381
+ * const latest = await client.futures.latest('CL');
312
382
  * console.log(`${latest.contract}: $${latest.price}`);
313
383
  *
314
- * // Get OHLC data
315
- * const ohlc = await client.futures.ohlc('CL.1', '2024-01-15');
316
- * console.log(`High: $${ohlc.high}, Low: $${ohlc.low}`);
317
- *
318
- * // Get futures curve
319
- * const curve = await client.futures.curve('CL');
384
+ * // Typed family helpers are the most ergonomic option:
385
+ * const brent = await client.futures.brent().latest();
386
+ * const curve = await client.futures.brent().curve();
320
387
  * curve.curve.forEach(point => {
321
388
  * console.log(`${point.months_out}mo: $${point.price}`);
322
389
  * });
@@ -326,18 +393,28 @@ export declare class FuturesResource {
326
393
  private client;
327
394
  constructor(client: OilPriceAPI);
328
395
  /**
329
- * Get latest price for a futures contract
396
+ * Get the latest curve/quote for a futures contract family.
330
397
  *
331
- * @param contract - Contract symbol (e.g., "CL.1", "BZ.2")
332
- * @returns Latest futures price data
398
+ * Accepts an ergonomic contract code (e.g. `"BZ"`, `"CL"`, `"QS"`) or a
399
+ * family slug (e.g. `"ice-brent"`). The code is resolved to its family slug
400
+ * and the request is sent to `GET /v1/futures/{slug}` — the bare slug path,
401
+ * with NO `/latest` suffix (the suffixed path 404s).
333
402
  *
334
- * @throws {NotFoundError} If contract not found
403
+ * Supported codes: BZ (Brent), CL (WTI), G/QS (Gasoil), NG (Natural Gas),
404
+ * TTF, JKM, EUA, UKA. Slugs: ice-brent, ice-wti, ice-gasoil, natural-gas,
405
+ * ttf-gas, lng-jkm, eua-carbon, uk-carbon.
406
+ *
407
+ * @param contract - Contract code (e.g. "BZ") or family slug (e.g. "ice-brent").
408
+ * @returns Latest futures price/curve data
409
+ *
410
+ * @throws {ValidationError} If the code/slug is empty or unrecognized.
335
411
  * @throws {OilPriceAPIError} If API request fails
336
412
  *
337
413
  * @example
338
414
  * ```typescript
339
- * const price = await client.futures.latest('CL.1');
340
- * console.log(`WTI Front Month: $${price.price}`);
415
+ * import { FUTURES_CONTRACTS } from 'oilpriceapi';
416
+ * const price = await client.futures.latest(FUTURES_CONTRACTS.BRENT); // "BZ"
417
+ * const wti = await client.futures.latest('ice-wti');
341
418
  * ```
342
419
  */
343
420
  latest(contract: string): Promise<FuturesPrice>;
@@ -45,15 +45,34 @@ export const FUTURES_CONTRACTS = {
45
45
  * path segment used by the typed family helpers.
46
46
  */
47
47
  export const FUTURES_FAMILY_SLUGS = {
48
- [FUTURES_CONTRACTS.BRENT]: "ice-brent",
49
- [FUTURES_CONTRACTS.WTI]: "ice-wti",
50
- [FUTURES_CONTRACTS.GASOIL]: "ice-gasoil",
51
- [FUTURES_CONTRACTS.NATURAL_GAS]: "natural-gas",
52
- [FUTURES_CONTRACTS.TTF_GAS]: "ttf-gas",
53
- [FUTURES_CONTRACTS.LNG_JKM]: "lng-jkm",
54
- [FUTURES_CONTRACTS.EUA_CARBON]: "eua-carbon",
55
- [FUTURES_CONTRACTS.UK_CARBON]: "uk-carbon",
48
+ [FUTURES_CONTRACTS.BRENT]: "ice-brent", // BZ
49
+ [FUTURES_CONTRACTS.WTI]: "ice-wti", // CL
50
+ [FUTURES_CONTRACTS.GASOIL]: "ice-gasoil", // G
51
+ QS: "ice-gasoil", // ICE Gasoil also trades under the QS ticker prefix
52
+ [FUTURES_CONTRACTS.NATURAL_GAS]: "natural-gas", // NG
53
+ [FUTURES_CONTRACTS.TTF_GAS]: "ttf-gas", // TTF
54
+ [FUTURES_CONTRACTS.LNG_JKM]: "lng-jkm", // JKM
55
+ [FUTURES_CONTRACTS.EUA_CARBON]: "eua-carbon", // EUA
56
+ [FUTURES_CONTRACTS.UK_CARBON]: "uk-carbon", // UKA
56
57
  };
58
+ /**
59
+ * Resolve a futures contract code (e.g. `"BZ"`, `"QS"`) or an already-valid
60
+ * family slug (e.g. `"ice-brent"`) to its `/v1/futures/{slug}` path segment.
61
+ *
62
+ * Matching is case-insensitive for codes. Returns `null` if the input maps to
63
+ * neither a known code nor a known family slug.
64
+ */
65
+ export function resolveFuturesFamilySlug(codeOrSlug) {
66
+ const trimmed = codeOrSlug.trim();
67
+ // Direct code match (case-insensitive — codes are upper-case).
68
+ const byCode = FUTURES_FAMILY_SLUGS[trimmed.toUpperCase()];
69
+ if (byCode)
70
+ return byCode;
71
+ // Already a valid family slug?
72
+ const lower = trimmed.toLowerCase();
73
+ const isSlug = Object.values(FUTURES_FAMILY_SLUGS).includes(lower);
74
+ return isSlug ? lower : null;
75
+ }
57
76
  /**
58
77
  * Typed helper for a single futures contract family (e.g., ICE Brent, Gasoil).
59
78
  *
@@ -77,9 +96,12 @@ export class FuturesContractFamily {
77
96
  }
78
97
  /**
79
98
  * Get the latest price for this contract family.
99
+ *
100
+ * Latest is served from the bare slug path `GET /v1/futures/{slug}` —
101
+ * there is NO `/latest` suffix (that path 404s).
80
102
  */
81
103
  async latest() {
82
- return this.client["request"](`/v1/futures/${this.slug}/latest`, {});
104
+ return this.client["request"](`/v1/futures/${this.slug}`, {});
83
105
  }
84
106
  /**
85
107
  * Get historical prices for this contract family.
@@ -152,16 +174,13 @@ export class FuturesContractFamily {
152
174
  *
153
175
  * const client = new OilPriceAPI({ apiKey: 'your_key' });
154
176
  *
155
- * // Get latest price
156
- * const latest = await client.futures.latest('CL.1');
177
+ * // Get the latest curve by contract code (resolves to GET /v1/futures/ice-wti)
178
+ * const latest = await client.futures.latest('CL');
157
179
  * console.log(`${latest.contract}: $${latest.price}`);
158
180
  *
159
- * // Get OHLC data
160
- * const ohlc = await client.futures.ohlc('CL.1', '2024-01-15');
161
- * console.log(`High: $${ohlc.high}, Low: $${ohlc.low}`);
162
- *
163
- * // Get futures curve
164
- * const curve = await client.futures.curve('CL');
181
+ * // Typed family helpers are the most ergonomic option:
182
+ * const brent = await client.futures.brent().latest();
183
+ * const curve = await client.futures.brent().curve();
165
184
  * curve.curve.forEach(point => {
166
185
  * console.log(`${point.months_out}mo: $${point.price}`);
167
186
  * });
@@ -172,25 +191,42 @@ export class FuturesResource {
172
191
  this.client = client;
173
192
  }
174
193
  /**
175
- * Get latest price for a futures contract
194
+ * Get the latest curve/quote for a futures contract family.
176
195
  *
177
- * @param contract - Contract symbol (e.g., "CL.1", "BZ.2")
178
- * @returns Latest futures price data
196
+ * Accepts an ergonomic contract code (e.g. `"BZ"`, `"CL"`, `"QS"`) or a
197
+ * family slug (e.g. `"ice-brent"`). The code is resolved to its family slug
198
+ * and the request is sent to `GET /v1/futures/{slug}` — the bare slug path,
199
+ * with NO `/latest` suffix (the suffixed path 404s).
179
200
  *
180
- * @throws {NotFoundError} If contract not found
201
+ * Supported codes: BZ (Brent), CL (WTI), G/QS (Gasoil), NG (Natural Gas),
202
+ * TTF, JKM, EUA, UKA. Slugs: ice-brent, ice-wti, ice-gasoil, natural-gas,
203
+ * ttf-gas, lng-jkm, eua-carbon, uk-carbon.
204
+ *
205
+ * @param contract - Contract code (e.g. "BZ") or family slug (e.g. "ice-brent").
206
+ * @returns Latest futures price/curve data
207
+ *
208
+ * @throws {ValidationError} If the code/slug is empty or unrecognized.
181
209
  * @throws {OilPriceAPIError} If API request fails
182
210
  *
183
211
  * @example
184
212
  * ```typescript
185
- * const price = await client.futures.latest('CL.1');
186
- * console.log(`WTI Front Month: $${price.price}`);
213
+ * import { FUTURES_CONTRACTS } from 'oilpriceapi';
214
+ * const price = await client.futures.latest(FUTURES_CONTRACTS.BRENT); // "BZ"
215
+ * const wti = await client.futures.latest('ice-wti');
187
216
  * ```
188
217
  */
189
218
  async latest(contract) {
190
219
  if (!contract || typeof contract !== "string") {
191
220
  throw new ValidationError("Contract symbol must be a non-empty string");
192
221
  }
193
- return this.client["request"](`/v1/futures/${contract}`, {});
222
+ const slug = resolveFuturesFamilySlug(contract);
223
+ if (!slug) {
224
+ throw new ValidationError(`Unknown futures contract "${contract}". Use a contract code ` +
225
+ `(BZ, CL, G, QS, NG, TTF, JKM, EUA, UKA) or a family slug ` +
226
+ `(ice-brent, ice-wti, ice-gasoil, natural-gas, ttf-gas, lng-jkm, ` +
227
+ `eua-carbon, uk-carbon).`);
228
+ }
229
+ return this.client["request"](`/v1/futures/${slug}`, {});
194
230
  }
195
231
  /**
196
232
  * Get historical prices for a futures contract
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.9.0";
10
+ export declare const SDK_VERSION = "0.9.1";
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.9.0";
10
+ export const SDK_VERSION = "0.9.1";
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.9.0",
3
+ "version": "0.9.1",
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/cjs/index.js",