the best ios gas tracking app
1// EIA duoarea code -> 2-letter state abbreviation
2const DUOAREA_TO_STATE: Record<string, string> = {
3 SAK: "AK", SAL: "AL", SAR: "AR", SAZ: "AZ", SCA: "CA",
4 SCO: "CO", SCT: "CT", SDC: "DC", SDE: "DE", SFL: "FL",
5 SGA: "GA", SHI: "HI", SIA: "IA", SID: "ID", SIL: "IL",
6 SIN: "IN", SKS: "KS", SKY: "KY", SLA: "LA", SMA: "MA",
7 SMD: "MD", SME: "ME", SMI: "MI", SMN: "MN", SMO: "MO",
8 SMS: "MS", SMT: "MT", SNC: "NC", SND: "ND", SNE: "NE",
9 SNH: "NH", SNJ: "NJ", SNM: "NM", SNV: "NV", SNY: "NY",
10 SOH: "OH", SOK: "OK", SOR: "OR", SPA: "PA", SRI: "RI",
11 SSC: "SC", SSD: "SD", STN: "TN", STX: "TX", SUT: "UT",
12 SVA: "VA", SVT: "VT", SWA: "WA", SWI: "WI", SWV: "WV",
13 SWY: "WY",
14};
15
16export interface StateAverage {
17 state: string;
18 regular: number | null;
19 period: string; // ISO date string of the week
20}
21
22interface EIADataRow {
23 period: string;
24 duoarea: string;
25 product: string;
26 value: number | null;
27}
28
29interface EIAResponse {
30 response: {
31 data: EIADataRow[];
32 };
33}
34
35export async function fetchStateAverages(): Promise<StateAverage[]> {
36 const apiKey = process.env.EIA_API_KEY;
37 if (!apiKey) throw new Error("EIA_API_KEY not set");
38
39 const params = new URLSearchParams({
40 api_key: apiKey,
41 frequency: "weekly",
42 "data[]": "value",
43 "facets[product][]": "EPM0", // regular unleaded
44 "sort[0][column]": "period",
45 "sort[0][direction]": "desc",
46 length: "60",
47 });
48
49 const res = await fetch(
50 `https://api.eia.gov/v2/petroleum/pri/gnd/data/?${params}`,
51 );
52 if (!res.ok) {
53 throw new Error(`EIA API returned ${res.status}`);
54 }
55
56 const json = (await res.json()) as EIAResponse;
57 const rows = json.response.data;
58
59 // Keep only the most recent entry per state
60 const latestByState = new Map<string, EIADataRow>();
61 for (const row of rows) {
62 const state = DUOAREA_TO_STATE[row.duoarea];
63 if (!state) continue;
64 const existing = latestByState.get(state);
65 if (!existing || row.period > existing.period) {
66 latestByState.set(state, row);
67 }
68 }
69
70 return Array.from(latestByState.entries()).map(([state, row]) => ({
71 state,
72 regular: row.value,
73 period: row.period,
74 }));
75}