@whereq/cloud 0.2.0 → 0.3.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.
package/README.md CHANGED
@@ -28,6 +28,7 @@ await wq.costOfLiving("us:California,ca:Ontario,m:3958");
28
28
  // Prices — fuel | food | energy | housing | rent
29
29
  await wq.prices({ domain: "rent", region: "us", bedrooms: 2, limit: 10 });
30
30
  await wq.price(3958); // one series + full history
31
+ await wq.prices({ domain: "fuel", geo: "Calgary, Alberta" });
31
32
  const csv = await wq.pricesCsv({ domain: "food", region: "us" });
32
33
 
33
34
  // Fuel — North-America gas & diesel: geolocated stations + aggregated series
@@ -49,6 +50,42 @@ await wq.get("/v1/trending", { limit: 10 });
49
50
  Errors throw `WhereqError` (with `.status`, `.message`, `.url`). A typed response is
50
51
  available via `wq.get<MyType>(…)`.
51
52
 
53
+ ## Fuel stations
54
+
55
+ Station-level retail fuel prices for **Mexico (`MX`)**, the **United States (`US`)**
56
+ and **Canada (`CA`)**. Every price is in **local currency per litre** — `MXN/L`,
57
+ `USD/L` or `CAD/L`.
58
+
59
+ ```ts
60
+ // Canada — by ISO code or by name ("ON" and "Ontario" both match)
61
+ await wq.fuelStations({ country: "CA", state: "ON", limit: 500 });
62
+
63
+ // United States — every product a station quotes
64
+ await wq.fuelStations({ country: "US", state: "TX", product: "diesel" });
65
+
66
+ // A map viewport: "minLon,minLat,maxLon,maxLat"
67
+ await wq.fuelStations({ country: "US", bbox: "-123,37,-122,38" });
68
+
69
+ // One station's price-change timeline
70
+ await wq.fuelStation(436335, { product: "regular", days: 7 });
71
+
72
+ // Every matching station, paging for you
73
+ for await (const station of wq.fuelStationsAll({ country: "CA" })) {
74
+ console.log(station.name, station.prices);
75
+ }
76
+ ```
77
+
78
+ Products are `regular`, `midgrade`, `premium` and `diesel` — `FUEL_PRODUCTS`,
79
+ `FUEL_COUNTRIES` and `FUEL_CURRENCIES` are exported for convenience.
80
+
81
+ > **The preview.** Without an entitled API key the fuel endpoints return a
82
+ > 100-row preview of the *oldest* rows, ignore `limit`/`offset`, and set
83
+ > `demo: true` in the response. Check `response.demo` before paging.
84
+
85
+ `fuelPrices()` is a different thing: the aggregated *series* behind the charts
86
+ (EIA weekly for the US, StatCan monthly for Canada, CRE for Mexico), not
87
+ station-level prices.
88
+
52
89
  ## License
53
90
 
54
91
  MIT © WhereQ
package/dist/index.cjs CHANGED
@@ -3,8 +3,15 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  // src/index.ts
6
- var VERSION = "0.1.0";
6
+ var VERSION = "0.3.0";
7
7
  var DEFAULT_BASE_URL = "https://api.whereq.cloud";
8
+ var FUEL_PRODUCTS = ["regular", "midgrade", "premium", "diesel"];
9
+ var FUEL_COUNTRIES = ["MX", "US", "CA"];
10
+ var FUEL_CURRENCIES = {
11
+ MX: "MXN/L",
12
+ US: "USD/L",
13
+ CA: "CAD/L"
14
+ };
8
15
  var WhereqError = class extends Error {
9
16
  constructor(status, message, url) {
10
17
  super(`whereq.cloud API error ${status} for ${url}: ${message}`);
@@ -58,6 +65,9 @@ var Whereq = class {
58
65
  return res.text();
59
66
  }
60
67
  // -- prices / cost of living ------------------------------------------------
68
+ /** Cost-of-living price series (fuel | food | energy | housing | rent).
69
+ * `region` takes a region slug or a comma-separated list ("us,ca");
70
+ * `geo` is a free-text place name ("Calgary, Alberta"). */
61
71
  prices(p = {}) {
62
72
  return this.get("/v1/prices", p);
63
73
  }
@@ -118,22 +128,60 @@ var Whereq = class {
118
128
  return this.get("/v1/autos/models", p);
119
129
  }
120
130
  // -- fuel (gas & diesel) ----------------------------------------------------
121
- /** Geolocated retail fuel stations (lat/lon, municipality) with latest prices.
122
- * Filters: country, state, municipality, product, bbox, q. */
131
+ /** Geolocated retail fuel stations with their latest prices.
132
+ *
133
+ * Coverage: Mexico (`MX`, CRE open data), the United States (`US`) and
134
+ * Canada (`CA`). Prices are in **local currency per litre** — `MXN/L`,
135
+ * `USD/L` and `CAD/L` respectively.
136
+ *
137
+ * Unentitled callers get a 100-row preview of the oldest rows and the
138
+ * pagination arguments are ignored — check `response.demo`.
139
+ */
123
140
  fuelStations(p = {}) {
124
141
  return this.get("/v1/fuel/stations", p);
125
142
  }
126
- /** One station: location + latest prices + intra-day price-change history. */
127
- fuelStation(id) {
128
- return this.get(`/v1/fuel/stations/${encodeURIComponent(String(id))}`);
143
+ /** One station: location, latest prices and its price-change timeline. */
144
+ fuelStation(id, p = {}) {
145
+ return this.get(
146
+ `/v1/fuel/stations/${encodeURIComponent(String(id))}`,
147
+ p
148
+ );
149
+ }
150
+ /** Yield every matching station, paging through the API for you.
151
+ *
152
+ * Only meaningful with an entitled key. The unentitled preview always
153
+ * returns the *same* oldest 100 rows and ignores the paging arguments,
154
+ * so there is nothing more to fetch: this yields that first page and
155
+ * stops rather than looping on it.
156
+ */
157
+ async *fuelStationsAll(p = {}) {
158
+ const pageSize = Math.min(Math.max(Number(p.limit ?? 500), 1), 500);
159
+ let offset = Number(p.offset ?? 0);
160
+ for (; ; ) {
161
+ const page = await this.fuelStations({ ...p, limit: pageSize, offset });
162
+ const stations = page.stations ?? [];
163
+ if (stations.length === 0) return;
164
+ for (const s of stations) yield s;
165
+ if (page.demo) return;
166
+ offset += stations.length;
167
+ if (page.total != null && offset >= page.total) return;
168
+ }
129
169
  }
130
- /** Aggregated fuel price series (state / national), North-America-wide. */
170
+ /** Aggregated fuel price series (state / national / metro).
171
+ *
172
+ * These are the *series* behind the charts — EIA weekly for the US,
173
+ * StatCan monthly for Canada, CRE for Mexico — not the station-level
174
+ * prices that `fuelStations()` returns.
175
+ */
131
176
  fuelPrices(p = {}) {
132
177
  return this.get("/v1/prices", { domain: "fuel", ...p });
133
178
  }
134
179
  };
135
180
  var index_default = Whereq;
136
181
 
182
+ exports.FUEL_COUNTRIES = FUEL_COUNTRIES;
183
+ exports.FUEL_CURRENCIES = FUEL_CURRENCIES;
184
+ exports.FUEL_PRODUCTS = FUEL_PRODUCTS;
137
185
  exports.VERSION = VERSION;
138
186
  exports.Whereq = Whereq;
139
187
  exports.WhereqError = WhereqError;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * whereq.cloud — official JavaScript/TypeScript SDK for the WhereQ data cloud.\n *\n * A thin, typed wrapper over the versioned `/v1` HTTP API at `api.whereq.cloud`.\n * Public endpoints work with no key; metered endpoints take an API key.\n *\n * ```ts\n * import { Whereq } from \"@whereq/cloud\";\n *\n * const wq = new Whereq(); // public access\n * // const wq = new Whereq({ apiKey: \"wq_live_…\" }); // metered tier\n *\n * await wq.costOfLiving(\"us:California,ca:Ontario\");\n * await wq.prices({ domain: \"rent\", region: \"us\", bedrooms: 2 });\n * await wq.get(\"/v1/trending\", { limit: 10 }); // escape hatch\n * ```\n */\nexport const VERSION = \"0.1.0\";\nconst DEFAULT_BASE_URL = \"https://api.whereq.cloud\";\n\nexport class WhereqError extends Error {\n constructor(\n public readonly status: number,\n message: string,\n public readonly url: string,\n ) {\n super(`whereq.cloud API error ${status} for ${url}: ${message}`);\n this.name = \"WhereqError\";\n }\n}\n\nexport interface ClientOptions {\n /** `wq_live_…` key for metered endpoints (sent as `X-API-Key`). */\n apiKey?: string;\n /** Override the API base (default `https://api.whereq.cloud`). */\n baseUrl?: string;\n /** Custom fetch (e.g. for Node <18 or testing). Defaults to global `fetch`. */\n fetch?: typeof fetch;\n}\n\ntype Params = Record<string, unknown>;\n\nexport class Whereq {\n private readonly baseUrl: string;\n private readonly headers: Record<string, string>;\n private readonly _fetch: typeof fetch;\n\n constructor(opts: ClientOptions = {}) {\n this.baseUrl = (opts.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, \"\");\n this.headers = { Accept: \"application/json\" };\n if (opts.apiKey) this.headers[\"X-API-Key\"] = opts.apiKey;\n const f = opts.fetch ?? globalThis.fetch;\n if (!f) throw new Error(\"No global fetch available — pass `fetch` in options (Node <18).\");\n this._fetch = f;\n }\n\n private url(path: string, params: Params): string {\n const qs = new URLSearchParams();\n for (const [k, v] of Object.entries(params)) {\n if (v !== undefined && v !== null) qs.set(k, String(v));\n }\n const s = qs.toString();\n return `${this.baseUrl}${path}${s ? `?${s}` : \"\"}`;\n }\n\n /** GET any endpoint; `undefined`/`null` params are dropped. Returns parsed JSON. */\n async get<T = unknown>(path: string, params: Params = {}): Promise<T> {\n const url = this.url(path, params);\n const res = await this._fetch(url, { headers: this.headers });\n if (!res.ok) {\n let msg = res.statusText;\n try {\n const j = (await res.json()) as { detail?: string };\n msg = j?.detail || JSON.stringify(j) || msg;\n } catch {\n /* non-JSON error body */\n }\n throw new WhereqError(res.status, msg, url);\n }\n return (await res.json()) as T;\n }\n\n /** GET a non-JSON endpoint (e.g. CSV export) as text. */\n async getText(path: string, params: Params = {}): Promise<string> {\n const url = this.url(path, params);\n const res = await this._fetch(url, { headers: this.headers });\n if (!res.ok) throw new WhereqError(res.status, res.statusText, url);\n return res.text();\n }\n\n // -- prices / cost of living ------------------------------------------------\n prices(p: { domain?: string; region?: string; bedrooms?: number; q?: string; limit?: number; offset?: number } = {}) {\n return this.get(\"/v1/prices\", p);\n }\n price(seriesId: number) {\n return this.get(`/v1/prices/${seriesId}`);\n }\n pricesCsv(p: { domain?: string; region?: string; bedrooms?: number; q?: string } = {}) {\n return this.getText(\"/v1/prices/export\", p);\n }\n /** Compare cost of living across US states / CA provinces / metros.\n * `places`: comma-separated `region:name` or `m:<rent-series-id>`. */\n costOfLiving(places: string) {\n return this.get(\"/v1/cost-of-living\", { places });\n }\n\n // -- discovery / facets -----------------------------------------------------\n catalog() { return this.get(\"/v1/catalog\"); }\n categories() { return this.get(\"/v1/categories\"); }\n regions() { return this.get(\"/v1/regions\"); }\n domains() { return this.get(\"/v1/domains\"); }\n trending(p: Params = {}) { return this.get(\"/v1/trending\", p); }\n\n // -- finance ----------------------------------------------------------------\n hotstocks(limit = 20) { return this.get(\"/v1/hotstocks\", { limit }); }\n quotes(p: Params = {}) { return this.get(\"/v1/quotes\", p); }\n news(p: Params = {}) { return this.get(\"/v1/news\", p); }\n screener(p: Params = {}) { return this.get(\"/v1/screener\", p); }\n search(q: string, p: Params = {}) { return this.get(\"/v1/search\", { q, ...p }); }\n\n // -- autos ------------------------------------------------------------------\n autosRecalls(p: Params = {}) { return this.get(\"/v1/autos/recalls\", p); }\n autosListings(p: Params = {}) { return this.get(\"/v1/autos/listings\", p); }\n autosFuelEconomy(p: Params = {}) { return this.get(\"/v1/autos/fuel-economy\", p); }\n autosModels(p: Params = {}) { return this.get(\"/v1/autos/models\", p); }\n\n // -- fuel (gas & diesel) ----------------------------------------------------\n /** Geolocated retail fuel stations (lat/lon, municipality) with latest prices.\n * Filters: country, state, municipality, product, bbox, q. */\n fuelStations(p: Params = {}) { return this.get(\"/v1/fuel/stations\", p); }\n /** One station: location + latest prices + intra-day price-change history. */\n fuelStation(id: number | string) { return this.get(`/v1/fuel/stations/${encodeURIComponent(String(id))}`); }\n /** Aggregated fuel price series (state / national), North-America-wide. */\n fuelPrices(p: Params = {}) { return this.get(\"/v1/prices\", { domain: \"fuel\", ...p }); }\n}\n\nexport default Whereq;\n"]}
1
+ {"version":3,"sources":["../src/index.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * whereq.cloud — official JavaScript/TypeScript SDK for the WhereQ data cloud.\n *\n * A thin, typed wrapper over the versioned `/v1` HTTP API at `api.whereq.cloud`.\n * Public endpoints work with no key; metered endpoints take an API key.\n *\n * ```ts\n * import { Whereq } from \"@whereq/cloud\";\n *\n * const wq = new Whereq(); // public access\n * // const wq = new Whereq({ apiKey: \"wq_live_…\" }); // metered tier\n *\n * await wq.costOfLiving(\"us:California,ca:Ontario\");\n * await wq.prices({ domain: \"rent\", region: \"us\", bedrooms: 2 });\n * await wq.get(\"/v1/trending\", { limit: 10 }); // escape hatch\n * ```\n */\nexport const VERSION = \"0.3.0\";\nconst DEFAULT_BASE_URL = \"https://api.whereq.cloud\";\n\n/** The products a station can quote. Mexico's CRE feed carries the first,\n * second and fourth; GasBuddy (US/Canada) adds midgrade. */\nexport const FUEL_PRODUCTS = [\"regular\", \"midgrade\", \"premium\", \"diesel\"] as const;\nexport type FuelProduct = (typeof FUEL_PRODUCTS)[number];\n\n/** Countries with station-level fuel data. */\nexport const FUEL_COUNTRIES = [\"MX\", \"US\", \"CA\"] as const;\nexport type FuelCountry = (typeof FUEL_COUNTRIES)[number];\n\n/** The unit each country quotes in — always local currency per litre. */\nexport const FUEL_CURRENCIES: Record<FuelCountry, string> = {\n MX: \"MXN/L\",\n US: \"USD/L\",\n CA: \"CAD/L\",\n};\n\n/** One product's latest price at a station. */\nexport interface FuelStationPrice {\n price: number;\n observed_at: string;\n}\n\n/** A geolocated retail fuel station and its latest prices.\n * `state` is the human label (\"Ontario\", \"Texas\"); `state_iso` is the\n * two-letter code (\"ON\", \"TX\"). */\nexport interface FuelStation {\n id: number;\n source: string;\n ext_id: string;\n country: string;\n name: string;\n brand?: string | null;\n state?: string | null;\n state_iso?: string | null;\n municipality?: string | null;\n lat?: number | null;\n lon?: number | null;\n prices: Record<string, FuelStationPrice>;\n}\n\n/** Filters for `fuelStations()`. */\nexport interface FuelStationsParams {\n /** \"MX\", \"US\" or \"CA\". */\n country?: FuelCountry | string;\n /** State/province name *or* ISO code — \"Ontario\"/\"ON\", \"Texas\"/\"TX\". */\n state?: string;\n /** City name, e.g. \"Mississauga\". */\n municipality?: string;\n product?: FuelProduct | string;\n /** \"minLon,minLat,maxLon,maxLat\" — a map viewport. */\n bbox?: string;\n /** Station-name search. */\n q?: string;\n /** 1–500 rows per page (default 100). */\n limit?: number;\n /** Row offset for paging. */\n offset?: number;\n}\n\n/** Filters for `fuelStation()`. */\nexport interface FuelStationParams {\n /** Restrict the timeline to one product. */\n product?: FuelProduct | string;\n /** How far back the timeline reaches (1–1825, default 90). */\n days?: number;\n}\n\n/** `GET /v1/fuel/stations`. Unentitled callers get a 100-row preview of the\n * oldest rows: `demo` is true, `total` is null and paging is ignored. */\nexport interface FuelStationsResponse {\n demo?: boolean;\n preview_rows?: number;\n note?: string;\n upgrade_url?: string;\n as_of: string;\n count: number;\n total?: number | null;\n stations: FuelStation[];\n}\n\n/** One observed price change — the intra-day timeline for a station. */\nexport interface FuelStationPricePoint {\n product: string;\n observed_at: string;\n price: number;\n}\n\n/** `GET /v1/fuel/stations/{id}`. `days` is null in the unentitled preview. */\nexport interface FuelStationDetail {\n demo?: boolean;\n preview_rows?: number;\n note?: string;\n upgrade_url?: string;\n station: FuelStation;\n days?: number | null;\n prices: FuelStationPricePoint[];\n}\n\n/** Filters for `fuelPrices()`. */\nexport interface FuelPricesParams {\n /** Region slug, or a comma-separated list of them (\"us,ca\"). */\n region?: string;\n /** Free-text place name (\"Calgary, Alberta\"). */\n geo?: string;\n q?: string;\n limit?: number;\n offset?: number;\n}\n\n/** One aggregated price series (state / national / metro). */\nexport interface PriceSeries {\n id: number;\n domain: string;\n source: string;\n region?: string | null;\n geo?: string | null;\n item: string;\n item_cn?: string | null;\n unit?: string | null;\n unit_cn?: string | null;\n frequency?: string | null;\n latest_period?: string | null;\n latest_value?: number | null;\n prev_value?: number | null;\n points?: number | null;\n spark?: number[];\n}\n\n/** `GET /v1/prices` — a page of series plus the page's own metadata. */\nexport interface PriceSeriesResponse {\n count: number;\n domain?: string | null;\n region?: string | null;\n limit: number;\n offset: number;\n data: PriceSeries[];\n}\n\nexport class WhereqError extends Error {\n constructor(\n public readonly status: number,\n message: string,\n public readonly url: string,\n ) {\n super(`whereq.cloud API error ${status} for ${url}: ${message}`);\n this.name = \"WhereqError\";\n }\n}\n\nexport interface ClientOptions {\n /** `wq_live_…` key for metered endpoints (sent as `X-API-Key`). */\n apiKey?: string;\n /** Override the API base (default `https://api.whereq.cloud`). */\n baseUrl?: string;\n /** Custom fetch (e.g. for Node <18 or testing). Defaults to global `fetch`. */\n fetch?: typeof fetch;\n}\n\ntype Params = Record<string, unknown>;\n\nexport class Whereq {\n private readonly baseUrl: string;\n private readonly headers: Record<string, string>;\n private readonly _fetch: typeof fetch;\n\n constructor(opts: ClientOptions = {}) {\n this.baseUrl = (opts.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, \"\");\n this.headers = { Accept: \"application/json\" };\n if (opts.apiKey) this.headers[\"X-API-Key\"] = opts.apiKey;\n const f = opts.fetch ?? globalThis.fetch;\n if (!f) throw new Error(\"No global fetch available — pass `fetch` in options (Node <18).\");\n this._fetch = f;\n }\n\n private url(path: string, params: Params): string {\n const qs = new URLSearchParams();\n for (const [k, v] of Object.entries(params)) {\n if (v !== undefined && v !== null) qs.set(k, String(v));\n }\n const s = qs.toString();\n return `${this.baseUrl}${path}${s ? `?${s}` : \"\"}`;\n }\n\n /** GET any endpoint; `undefined`/`null` params are dropped. Returns parsed JSON. */\n async get<T = unknown>(path: string, params: Params = {}): Promise<T> {\n const url = this.url(path, params);\n const res = await this._fetch(url, { headers: this.headers });\n if (!res.ok) {\n let msg = res.statusText;\n try {\n const j = (await res.json()) as { detail?: string };\n msg = j?.detail || JSON.stringify(j) || msg;\n } catch {\n /* non-JSON error body */\n }\n throw new WhereqError(res.status, msg, url);\n }\n return (await res.json()) as T;\n }\n\n /** GET a non-JSON endpoint (e.g. CSV export) as text. */\n async getText(path: string, params: Params = {}): Promise<string> {\n const url = this.url(path, params);\n const res = await this._fetch(url, { headers: this.headers });\n if (!res.ok) throw new WhereqError(res.status, res.statusText, url);\n return res.text();\n }\n\n // -- prices / cost of living ------------------------------------------------\n /** Cost-of-living price series (fuel | food | energy | housing | rent).\n * `region` takes a region slug or a comma-separated list (\"us,ca\");\n * `geo` is a free-text place name (\"Calgary, Alberta\"). */\n prices(p: { domain?: string; region?: string; geo?: string; bedrooms?: number; q?: string; limit?: number; offset?: number } = {}): Promise<PriceSeriesResponse> {\n return this.get<PriceSeriesResponse>(\"/v1/prices\", p);\n }\n price(seriesId: number) {\n return this.get(`/v1/prices/${seriesId}`);\n }\n pricesCsv(p: { domain?: string; region?: string; geo?: string; bedrooms?: number; q?: string } = {}) {\n return this.getText(\"/v1/prices/export\", p);\n }\n /** Compare cost of living across US states / CA provinces / metros.\n * `places`: comma-separated `region:name` or `m:<rent-series-id>`. */\n costOfLiving(places: string) {\n return this.get(\"/v1/cost-of-living\", { places });\n }\n\n // -- discovery / facets -----------------------------------------------------\n catalog() { return this.get(\"/v1/catalog\"); }\n categories() { return this.get(\"/v1/categories\"); }\n regions() { return this.get(\"/v1/regions\"); }\n domains() { return this.get(\"/v1/domains\"); }\n trending(p: Params = {}) { return this.get(\"/v1/trending\", p); }\n\n // -- finance ----------------------------------------------------------------\n hotstocks(limit = 20) { return this.get(\"/v1/hotstocks\", { limit }); }\n quotes(p: Params = {}) { return this.get(\"/v1/quotes\", p); }\n news(p: Params = {}) { return this.get(\"/v1/news\", p); }\n screener(p: Params = {}) { return this.get(\"/v1/screener\", p); }\n search(q: string, p: Params = {}) { return this.get(\"/v1/search\", { q, ...p }); }\n\n // -- autos ------------------------------------------------------------------\n autosRecalls(p: Params = {}) { return this.get(\"/v1/autos/recalls\", p); }\n autosListings(p: Params = {}) { return this.get(\"/v1/autos/listings\", p); }\n autosFuelEconomy(p: Params = {}) { return this.get(\"/v1/autos/fuel-economy\", p); }\n autosModels(p: Params = {}) { return this.get(\"/v1/autos/models\", p); }\n\n // -- fuel (gas & diesel) ----------------------------------------------------\n /** Geolocated retail fuel stations with their latest prices.\n *\n * Coverage: Mexico (`MX`, CRE open data), the United States (`US`) and\n * Canada (`CA`). Prices are in **local currency per litre** — `MXN/L`,\n * `USD/L` and `CAD/L` respectively.\n *\n * Unentitled callers get a 100-row preview of the oldest rows and the\n * pagination arguments are ignored — check `response.demo`.\n */\n fuelStations(p: FuelStationsParams & Params = {}): Promise<FuelStationsResponse> {\n return this.get<FuelStationsResponse>(\"/v1/fuel/stations\", p);\n }\n\n /** One station: location, latest prices and its price-change timeline. */\n fuelStation(\n id: number | string,\n p: FuelStationParams & Params = {},\n ): Promise<FuelStationDetail> {\n return this.get<FuelStationDetail>(\n `/v1/fuel/stations/${encodeURIComponent(String(id))}`,\n p,\n );\n }\n\n /** Yield every matching station, paging through the API for you.\n *\n * Only meaningful with an entitled key. The unentitled preview always\n * returns the *same* oldest 100 rows and ignores the paging arguments,\n * so there is nothing more to fetch: this yields that first page and\n * stops rather than looping on it.\n */\n async *fuelStationsAll(\n p: FuelStationsParams & Params = {},\n ): AsyncGenerator<FuelStation> {\n const pageSize = Math.min(Math.max(Number(p.limit ?? 500), 1), 500);\n let offset = Number(p.offset ?? 0);\n for (;;) {\n const page = await this.fuelStations({ ...p, limit: pageSize, offset });\n const stations = page.stations ?? [];\n if (stations.length === 0) return;\n for (const s of stations) yield s;\n if (page.demo) return; // preview: every page is the same slice\n offset += stations.length;\n if (page.total != null && offset >= page.total) return;\n }\n }\n\n /** Aggregated fuel price series (state / national / metro).\n *\n * These are the *series* behind the charts — EIA weekly for the US,\n * StatCan monthly for Canada, CRE for Mexico — not the station-level\n * prices that `fuelStations()` returns.\n */\n fuelPrices(p: FuelPricesParams & Params = {}): Promise<PriceSeriesResponse> {\n return this.get<PriceSeriesResponse>(\"/v1/prices\", { domain: \"fuel\", ...p });\n }\n}\n\nexport default Whereq;\n"]}
package/dist/index.d.cts CHANGED
@@ -15,7 +15,128 @@
15
15
  * await wq.get("/v1/trending", { limit: 10 }); // escape hatch
16
16
  * ```
17
17
  */
18
- declare const VERSION = "0.1.0";
18
+ declare const VERSION = "0.3.0";
19
+ /** The products a station can quote. Mexico's CRE feed carries the first,
20
+ * second and fourth; GasBuddy (US/Canada) adds midgrade. */
21
+ declare const FUEL_PRODUCTS: readonly ["regular", "midgrade", "premium", "diesel"];
22
+ type FuelProduct = (typeof FUEL_PRODUCTS)[number];
23
+ /** Countries with station-level fuel data. */
24
+ declare const FUEL_COUNTRIES: readonly ["MX", "US", "CA"];
25
+ type FuelCountry = (typeof FUEL_COUNTRIES)[number];
26
+ /** The unit each country quotes in — always local currency per litre. */
27
+ declare const FUEL_CURRENCIES: Record<FuelCountry, string>;
28
+ /** One product's latest price at a station. */
29
+ interface FuelStationPrice {
30
+ price: number;
31
+ observed_at: string;
32
+ }
33
+ /** A geolocated retail fuel station and its latest prices.
34
+ * `state` is the human label ("Ontario", "Texas"); `state_iso` is the
35
+ * two-letter code ("ON", "TX"). */
36
+ interface FuelStation {
37
+ id: number;
38
+ source: string;
39
+ ext_id: string;
40
+ country: string;
41
+ name: string;
42
+ brand?: string | null;
43
+ state?: string | null;
44
+ state_iso?: string | null;
45
+ municipality?: string | null;
46
+ lat?: number | null;
47
+ lon?: number | null;
48
+ prices: Record<string, FuelStationPrice>;
49
+ }
50
+ /** Filters for `fuelStations()`. */
51
+ interface FuelStationsParams {
52
+ /** "MX", "US" or "CA". */
53
+ country?: FuelCountry | string;
54
+ /** State/province name *or* ISO code — "Ontario"/"ON", "Texas"/"TX". */
55
+ state?: string;
56
+ /** City name, e.g. "Mississauga". */
57
+ municipality?: string;
58
+ product?: FuelProduct | string;
59
+ /** "minLon,minLat,maxLon,maxLat" — a map viewport. */
60
+ bbox?: string;
61
+ /** Station-name search. */
62
+ q?: string;
63
+ /** 1–500 rows per page (default 100). */
64
+ limit?: number;
65
+ /** Row offset for paging. */
66
+ offset?: number;
67
+ }
68
+ /** Filters for `fuelStation()`. */
69
+ interface FuelStationParams {
70
+ /** Restrict the timeline to one product. */
71
+ product?: FuelProduct | string;
72
+ /** How far back the timeline reaches (1–1825, default 90). */
73
+ days?: number;
74
+ }
75
+ /** `GET /v1/fuel/stations`. Unentitled callers get a 100-row preview of the
76
+ * oldest rows: `demo` is true, `total` is null and paging is ignored. */
77
+ interface FuelStationsResponse {
78
+ demo?: boolean;
79
+ preview_rows?: number;
80
+ note?: string;
81
+ upgrade_url?: string;
82
+ as_of: string;
83
+ count: number;
84
+ total?: number | null;
85
+ stations: FuelStation[];
86
+ }
87
+ /** One observed price change — the intra-day timeline for a station. */
88
+ interface FuelStationPricePoint {
89
+ product: string;
90
+ observed_at: string;
91
+ price: number;
92
+ }
93
+ /** `GET /v1/fuel/stations/{id}`. `days` is null in the unentitled preview. */
94
+ interface FuelStationDetail {
95
+ demo?: boolean;
96
+ preview_rows?: number;
97
+ note?: string;
98
+ upgrade_url?: string;
99
+ station: FuelStation;
100
+ days?: number | null;
101
+ prices: FuelStationPricePoint[];
102
+ }
103
+ /** Filters for `fuelPrices()`. */
104
+ interface FuelPricesParams {
105
+ /** Region slug, or a comma-separated list of them ("us,ca"). */
106
+ region?: string;
107
+ /** Free-text place name ("Calgary, Alberta"). */
108
+ geo?: string;
109
+ q?: string;
110
+ limit?: number;
111
+ offset?: number;
112
+ }
113
+ /** One aggregated price series (state / national / metro). */
114
+ interface PriceSeries {
115
+ id: number;
116
+ domain: string;
117
+ source: string;
118
+ region?: string | null;
119
+ geo?: string | null;
120
+ item: string;
121
+ item_cn?: string | null;
122
+ unit?: string | null;
123
+ unit_cn?: string | null;
124
+ frequency?: string | null;
125
+ latest_period?: string | null;
126
+ latest_value?: number | null;
127
+ prev_value?: number | null;
128
+ points?: number | null;
129
+ spark?: number[];
130
+ }
131
+ /** `GET /v1/prices` — a page of series plus the page's own metadata. */
132
+ interface PriceSeriesResponse {
133
+ count: number;
134
+ domain?: string | null;
135
+ region?: string | null;
136
+ limit: number;
137
+ offset: number;
138
+ data: PriceSeries[];
139
+ }
19
140
  declare class WhereqError extends Error {
20
141
  readonly status: number;
21
142
  readonly url: string;
@@ -40,18 +161,23 @@ declare class Whereq {
40
161
  get<T = unknown>(path: string, params?: Params): Promise<T>;
41
162
  /** GET a non-JSON endpoint (e.g. CSV export) as text. */
42
163
  getText(path: string, params?: Params): Promise<string>;
164
+ /** Cost-of-living price series (fuel | food | energy | housing | rent).
165
+ * `region` takes a region slug or a comma-separated list ("us,ca");
166
+ * `geo` is a free-text place name ("Calgary, Alberta"). */
43
167
  prices(p?: {
44
168
  domain?: string;
45
169
  region?: string;
170
+ geo?: string;
46
171
  bedrooms?: number;
47
172
  q?: string;
48
173
  limit?: number;
49
174
  offset?: number;
50
- }): Promise<unknown>;
175
+ }): Promise<PriceSeriesResponse>;
51
176
  price(seriesId: number): Promise<unknown>;
52
177
  pricesCsv(p?: {
53
178
  domain?: string;
54
179
  region?: string;
180
+ geo?: string;
55
181
  bedrooms?: number;
56
182
  q?: string;
57
183
  }): Promise<string>;
@@ -72,13 +198,33 @@ declare class Whereq {
72
198
  autosListings(p?: Params): Promise<unknown>;
73
199
  autosFuelEconomy(p?: Params): Promise<unknown>;
74
200
  autosModels(p?: Params): Promise<unknown>;
75
- /** Geolocated retail fuel stations (lat/lon, municipality) with latest prices.
76
- * Filters: country, state, municipality, product, bbox, q. */
77
- fuelStations(p?: Params): Promise<unknown>;
78
- /** One station: location + latest prices + intra-day price-change history. */
79
- fuelStation(id: number | string): Promise<unknown>;
80
- /** Aggregated fuel price series (state / national), North-America-wide. */
81
- fuelPrices(p?: Params): Promise<unknown>;
201
+ /** Geolocated retail fuel stations with their latest prices.
202
+ *
203
+ * Coverage: Mexico (`MX`, CRE open data), the United States (`US`) and
204
+ * Canada (`CA`). Prices are in **local currency per litre** — `MXN/L`,
205
+ * `USD/L` and `CAD/L` respectively.
206
+ *
207
+ * Unentitled callers get a 100-row preview of the oldest rows and the
208
+ * pagination arguments are ignored — check `response.demo`.
209
+ */
210
+ fuelStations(p?: FuelStationsParams & Params): Promise<FuelStationsResponse>;
211
+ /** One station: location, latest prices and its price-change timeline. */
212
+ fuelStation(id: number | string, p?: FuelStationParams & Params): Promise<FuelStationDetail>;
213
+ /** Yield every matching station, paging through the API for you.
214
+ *
215
+ * Only meaningful with an entitled key. The unentitled preview always
216
+ * returns the *same* oldest 100 rows and ignores the paging arguments,
217
+ * so there is nothing more to fetch: this yields that first page and
218
+ * stops rather than looping on it.
219
+ */
220
+ fuelStationsAll(p?: FuelStationsParams & Params): AsyncGenerator<FuelStation>;
221
+ /** Aggregated fuel price series (state / national / metro).
222
+ *
223
+ * These are the *series* behind the charts — EIA weekly for the US,
224
+ * StatCan monthly for Canada, CRE for Mexico — not the station-level
225
+ * prices that `fuelStations()` returns.
226
+ */
227
+ fuelPrices(p?: FuelPricesParams & Params): Promise<PriceSeriesResponse>;
82
228
  }
83
229
 
84
- export { type ClientOptions, VERSION, Whereq, WhereqError, Whereq as default };
230
+ export { type ClientOptions, FUEL_COUNTRIES, FUEL_CURRENCIES, FUEL_PRODUCTS, type FuelCountry, type FuelPricesParams, type FuelProduct, type FuelStation, type FuelStationDetail, type FuelStationParams, type FuelStationPrice, type FuelStationPricePoint, type FuelStationsParams, type FuelStationsResponse, type PriceSeries, type PriceSeriesResponse, VERSION, Whereq, WhereqError, Whereq as default };
package/dist/index.d.ts CHANGED
@@ -15,7 +15,128 @@
15
15
  * await wq.get("/v1/trending", { limit: 10 }); // escape hatch
16
16
  * ```
17
17
  */
18
- declare const VERSION = "0.1.0";
18
+ declare const VERSION = "0.3.0";
19
+ /** The products a station can quote. Mexico's CRE feed carries the first,
20
+ * second and fourth; GasBuddy (US/Canada) adds midgrade. */
21
+ declare const FUEL_PRODUCTS: readonly ["regular", "midgrade", "premium", "diesel"];
22
+ type FuelProduct = (typeof FUEL_PRODUCTS)[number];
23
+ /** Countries with station-level fuel data. */
24
+ declare const FUEL_COUNTRIES: readonly ["MX", "US", "CA"];
25
+ type FuelCountry = (typeof FUEL_COUNTRIES)[number];
26
+ /** The unit each country quotes in — always local currency per litre. */
27
+ declare const FUEL_CURRENCIES: Record<FuelCountry, string>;
28
+ /** One product's latest price at a station. */
29
+ interface FuelStationPrice {
30
+ price: number;
31
+ observed_at: string;
32
+ }
33
+ /** A geolocated retail fuel station and its latest prices.
34
+ * `state` is the human label ("Ontario", "Texas"); `state_iso` is the
35
+ * two-letter code ("ON", "TX"). */
36
+ interface FuelStation {
37
+ id: number;
38
+ source: string;
39
+ ext_id: string;
40
+ country: string;
41
+ name: string;
42
+ brand?: string | null;
43
+ state?: string | null;
44
+ state_iso?: string | null;
45
+ municipality?: string | null;
46
+ lat?: number | null;
47
+ lon?: number | null;
48
+ prices: Record<string, FuelStationPrice>;
49
+ }
50
+ /** Filters for `fuelStations()`. */
51
+ interface FuelStationsParams {
52
+ /** "MX", "US" or "CA". */
53
+ country?: FuelCountry | string;
54
+ /** State/province name *or* ISO code — "Ontario"/"ON", "Texas"/"TX". */
55
+ state?: string;
56
+ /** City name, e.g. "Mississauga". */
57
+ municipality?: string;
58
+ product?: FuelProduct | string;
59
+ /** "minLon,minLat,maxLon,maxLat" — a map viewport. */
60
+ bbox?: string;
61
+ /** Station-name search. */
62
+ q?: string;
63
+ /** 1–500 rows per page (default 100). */
64
+ limit?: number;
65
+ /** Row offset for paging. */
66
+ offset?: number;
67
+ }
68
+ /** Filters for `fuelStation()`. */
69
+ interface FuelStationParams {
70
+ /** Restrict the timeline to one product. */
71
+ product?: FuelProduct | string;
72
+ /** How far back the timeline reaches (1–1825, default 90). */
73
+ days?: number;
74
+ }
75
+ /** `GET /v1/fuel/stations`. Unentitled callers get a 100-row preview of the
76
+ * oldest rows: `demo` is true, `total` is null and paging is ignored. */
77
+ interface FuelStationsResponse {
78
+ demo?: boolean;
79
+ preview_rows?: number;
80
+ note?: string;
81
+ upgrade_url?: string;
82
+ as_of: string;
83
+ count: number;
84
+ total?: number | null;
85
+ stations: FuelStation[];
86
+ }
87
+ /** One observed price change — the intra-day timeline for a station. */
88
+ interface FuelStationPricePoint {
89
+ product: string;
90
+ observed_at: string;
91
+ price: number;
92
+ }
93
+ /** `GET /v1/fuel/stations/{id}`. `days` is null in the unentitled preview. */
94
+ interface FuelStationDetail {
95
+ demo?: boolean;
96
+ preview_rows?: number;
97
+ note?: string;
98
+ upgrade_url?: string;
99
+ station: FuelStation;
100
+ days?: number | null;
101
+ prices: FuelStationPricePoint[];
102
+ }
103
+ /** Filters for `fuelPrices()`. */
104
+ interface FuelPricesParams {
105
+ /** Region slug, or a comma-separated list of them ("us,ca"). */
106
+ region?: string;
107
+ /** Free-text place name ("Calgary, Alberta"). */
108
+ geo?: string;
109
+ q?: string;
110
+ limit?: number;
111
+ offset?: number;
112
+ }
113
+ /** One aggregated price series (state / national / metro). */
114
+ interface PriceSeries {
115
+ id: number;
116
+ domain: string;
117
+ source: string;
118
+ region?: string | null;
119
+ geo?: string | null;
120
+ item: string;
121
+ item_cn?: string | null;
122
+ unit?: string | null;
123
+ unit_cn?: string | null;
124
+ frequency?: string | null;
125
+ latest_period?: string | null;
126
+ latest_value?: number | null;
127
+ prev_value?: number | null;
128
+ points?: number | null;
129
+ spark?: number[];
130
+ }
131
+ /** `GET /v1/prices` — a page of series plus the page's own metadata. */
132
+ interface PriceSeriesResponse {
133
+ count: number;
134
+ domain?: string | null;
135
+ region?: string | null;
136
+ limit: number;
137
+ offset: number;
138
+ data: PriceSeries[];
139
+ }
19
140
  declare class WhereqError extends Error {
20
141
  readonly status: number;
21
142
  readonly url: string;
@@ -40,18 +161,23 @@ declare class Whereq {
40
161
  get<T = unknown>(path: string, params?: Params): Promise<T>;
41
162
  /** GET a non-JSON endpoint (e.g. CSV export) as text. */
42
163
  getText(path: string, params?: Params): Promise<string>;
164
+ /** Cost-of-living price series (fuel | food | energy | housing | rent).
165
+ * `region` takes a region slug or a comma-separated list ("us,ca");
166
+ * `geo` is a free-text place name ("Calgary, Alberta"). */
43
167
  prices(p?: {
44
168
  domain?: string;
45
169
  region?: string;
170
+ geo?: string;
46
171
  bedrooms?: number;
47
172
  q?: string;
48
173
  limit?: number;
49
174
  offset?: number;
50
- }): Promise<unknown>;
175
+ }): Promise<PriceSeriesResponse>;
51
176
  price(seriesId: number): Promise<unknown>;
52
177
  pricesCsv(p?: {
53
178
  domain?: string;
54
179
  region?: string;
180
+ geo?: string;
55
181
  bedrooms?: number;
56
182
  q?: string;
57
183
  }): Promise<string>;
@@ -72,13 +198,33 @@ declare class Whereq {
72
198
  autosListings(p?: Params): Promise<unknown>;
73
199
  autosFuelEconomy(p?: Params): Promise<unknown>;
74
200
  autosModels(p?: Params): Promise<unknown>;
75
- /** Geolocated retail fuel stations (lat/lon, municipality) with latest prices.
76
- * Filters: country, state, municipality, product, bbox, q. */
77
- fuelStations(p?: Params): Promise<unknown>;
78
- /** One station: location + latest prices + intra-day price-change history. */
79
- fuelStation(id: number | string): Promise<unknown>;
80
- /** Aggregated fuel price series (state / national), North-America-wide. */
81
- fuelPrices(p?: Params): Promise<unknown>;
201
+ /** Geolocated retail fuel stations with their latest prices.
202
+ *
203
+ * Coverage: Mexico (`MX`, CRE open data), the United States (`US`) and
204
+ * Canada (`CA`). Prices are in **local currency per litre** — `MXN/L`,
205
+ * `USD/L` and `CAD/L` respectively.
206
+ *
207
+ * Unentitled callers get a 100-row preview of the oldest rows and the
208
+ * pagination arguments are ignored — check `response.demo`.
209
+ */
210
+ fuelStations(p?: FuelStationsParams & Params): Promise<FuelStationsResponse>;
211
+ /** One station: location, latest prices and its price-change timeline. */
212
+ fuelStation(id: number | string, p?: FuelStationParams & Params): Promise<FuelStationDetail>;
213
+ /** Yield every matching station, paging through the API for you.
214
+ *
215
+ * Only meaningful with an entitled key. The unentitled preview always
216
+ * returns the *same* oldest 100 rows and ignores the paging arguments,
217
+ * so there is nothing more to fetch: this yields that first page and
218
+ * stops rather than looping on it.
219
+ */
220
+ fuelStationsAll(p?: FuelStationsParams & Params): AsyncGenerator<FuelStation>;
221
+ /** Aggregated fuel price series (state / national / metro).
222
+ *
223
+ * These are the *series* behind the charts — EIA weekly for the US,
224
+ * StatCan monthly for Canada, CRE for Mexico — not the station-level
225
+ * prices that `fuelStations()` returns.
226
+ */
227
+ fuelPrices(p?: FuelPricesParams & Params): Promise<PriceSeriesResponse>;
82
228
  }
83
229
 
84
- export { type ClientOptions, VERSION, Whereq, WhereqError, Whereq as default };
230
+ export { type ClientOptions, FUEL_COUNTRIES, FUEL_CURRENCIES, FUEL_PRODUCTS, type FuelCountry, type FuelPricesParams, type FuelProduct, type FuelStation, type FuelStationDetail, type FuelStationParams, type FuelStationPrice, type FuelStationPricePoint, type FuelStationsParams, type FuelStationsResponse, type PriceSeries, type PriceSeriesResponse, VERSION, Whereq, WhereqError, Whereq as default };
package/dist/index.js CHANGED
@@ -1,6 +1,13 @@
1
1
  // src/index.ts
2
- var VERSION = "0.1.0";
2
+ var VERSION = "0.3.0";
3
3
  var DEFAULT_BASE_URL = "https://api.whereq.cloud";
4
+ var FUEL_PRODUCTS = ["regular", "midgrade", "premium", "diesel"];
5
+ var FUEL_COUNTRIES = ["MX", "US", "CA"];
6
+ var FUEL_CURRENCIES = {
7
+ MX: "MXN/L",
8
+ US: "USD/L",
9
+ CA: "CAD/L"
10
+ };
4
11
  var WhereqError = class extends Error {
5
12
  constructor(status, message, url) {
6
13
  super(`whereq.cloud API error ${status} for ${url}: ${message}`);
@@ -54,6 +61,9 @@ var Whereq = class {
54
61
  return res.text();
55
62
  }
56
63
  // -- prices / cost of living ------------------------------------------------
64
+ /** Cost-of-living price series (fuel | food | energy | housing | rent).
65
+ * `region` takes a region slug or a comma-separated list ("us,ca");
66
+ * `geo` is a free-text place name ("Calgary, Alberta"). */
57
67
  prices(p = {}) {
58
68
  return this.get("/v1/prices", p);
59
69
  }
@@ -114,22 +124,57 @@ var Whereq = class {
114
124
  return this.get("/v1/autos/models", p);
115
125
  }
116
126
  // -- fuel (gas & diesel) ----------------------------------------------------
117
- /** Geolocated retail fuel stations (lat/lon, municipality) with latest prices.
118
- * Filters: country, state, municipality, product, bbox, q. */
127
+ /** Geolocated retail fuel stations with their latest prices.
128
+ *
129
+ * Coverage: Mexico (`MX`, CRE open data), the United States (`US`) and
130
+ * Canada (`CA`). Prices are in **local currency per litre** — `MXN/L`,
131
+ * `USD/L` and `CAD/L` respectively.
132
+ *
133
+ * Unentitled callers get a 100-row preview of the oldest rows and the
134
+ * pagination arguments are ignored — check `response.demo`.
135
+ */
119
136
  fuelStations(p = {}) {
120
137
  return this.get("/v1/fuel/stations", p);
121
138
  }
122
- /** One station: location + latest prices + intra-day price-change history. */
123
- fuelStation(id) {
124
- return this.get(`/v1/fuel/stations/${encodeURIComponent(String(id))}`);
139
+ /** One station: location, latest prices and its price-change timeline. */
140
+ fuelStation(id, p = {}) {
141
+ return this.get(
142
+ `/v1/fuel/stations/${encodeURIComponent(String(id))}`,
143
+ p
144
+ );
145
+ }
146
+ /** Yield every matching station, paging through the API for you.
147
+ *
148
+ * Only meaningful with an entitled key. The unentitled preview always
149
+ * returns the *same* oldest 100 rows and ignores the paging arguments,
150
+ * so there is nothing more to fetch: this yields that first page and
151
+ * stops rather than looping on it.
152
+ */
153
+ async *fuelStationsAll(p = {}) {
154
+ const pageSize = Math.min(Math.max(Number(p.limit ?? 500), 1), 500);
155
+ let offset = Number(p.offset ?? 0);
156
+ for (; ; ) {
157
+ const page = await this.fuelStations({ ...p, limit: pageSize, offset });
158
+ const stations = page.stations ?? [];
159
+ if (stations.length === 0) return;
160
+ for (const s of stations) yield s;
161
+ if (page.demo) return;
162
+ offset += stations.length;
163
+ if (page.total != null && offset >= page.total) return;
164
+ }
125
165
  }
126
- /** Aggregated fuel price series (state / national), North-America-wide. */
166
+ /** Aggregated fuel price series (state / national / metro).
167
+ *
168
+ * These are the *series* behind the charts — EIA weekly for the US,
169
+ * StatCan monthly for Canada, CRE for Mexico — not the station-level
170
+ * prices that `fuelStations()` returns.
171
+ */
127
172
  fuelPrices(p = {}) {
128
173
  return this.get("/v1/prices", { domain: "fuel", ...p });
129
174
  }
130
175
  };
131
176
  var index_default = Whereq;
132
177
 
133
- export { VERSION, Whereq, WhereqError, index_default as default };
178
+ export { FUEL_COUNTRIES, FUEL_CURRENCIES, FUEL_PRODUCTS, VERSION, Whereq, WhereqError, index_default as default };
134
179
  //# sourceMappingURL=index.js.map
135
180
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * whereq.cloud — official JavaScript/TypeScript SDK for the WhereQ data cloud.\n *\n * A thin, typed wrapper over the versioned `/v1` HTTP API at `api.whereq.cloud`.\n * Public endpoints work with no key; metered endpoints take an API key.\n *\n * ```ts\n * import { Whereq } from \"@whereq/cloud\";\n *\n * const wq = new Whereq(); // public access\n * // const wq = new Whereq({ apiKey: \"wq_live_…\" }); // metered tier\n *\n * await wq.costOfLiving(\"us:California,ca:Ontario\");\n * await wq.prices({ domain: \"rent\", region: \"us\", bedrooms: 2 });\n * await wq.get(\"/v1/trending\", { limit: 10 }); // escape hatch\n * ```\n */\nexport const VERSION = \"0.1.0\";\nconst DEFAULT_BASE_URL = \"https://api.whereq.cloud\";\n\nexport class WhereqError extends Error {\n constructor(\n public readonly status: number,\n message: string,\n public readonly url: string,\n ) {\n super(`whereq.cloud API error ${status} for ${url}: ${message}`);\n this.name = \"WhereqError\";\n }\n}\n\nexport interface ClientOptions {\n /** `wq_live_…` key for metered endpoints (sent as `X-API-Key`). */\n apiKey?: string;\n /** Override the API base (default `https://api.whereq.cloud`). */\n baseUrl?: string;\n /** Custom fetch (e.g. for Node <18 or testing). Defaults to global `fetch`. */\n fetch?: typeof fetch;\n}\n\ntype Params = Record<string, unknown>;\n\nexport class Whereq {\n private readonly baseUrl: string;\n private readonly headers: Record<string, string>;\n private readonly _fetch: typeof fetch;\n\n constructor(opts: ClientOptions = {}) {\n this.baseUrl = (opts.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, \"\");\n this.headers = { Accept: \"application/json\" };\n if (opts.apiKey) this.headers[\"X-API-Key\"] = opts.apiKey;\n const f = opts.fetch ?? globalThis.fetch;\n if (!f) throw new Error(\"No global fetch available — pass `fetch` in options (Node <18).\");\n this._fetch = f;\n }\n\n private url(path: string, params: Params): string {\n const qs = new URLSearchParams();\n for (const [k, v] of Object.entries(params)) {\n if (v !== undefined && v !== null) qs.set(k, String(v));\n }\n const s = qs.toString();\n return `${this.baseUrl}${path}${s ? `?${s}` : \"\"}`;\n }\n\n /** GET any endpoint; `undefined`/`null` params are dropped. Returns parsed JSON. */\n async get<T = unknown>(path: string, params: Params = {}): Promise<T> {\n const url = this.url(path, params);\n const res = await this._fetch(url, { headers: this.headers });\n if (!res.ok) {\n let msg = res.statusText;\n try {\n const j = (await res.json()) as { detail?: string };\n msg = j?.detail || JSON.stringify(j) || msg;\n } catch {\n /* non-JSON error body */\n }\n throw new WhereqError(res.status, msg, url);\n }\n return (await res.json()) as T;\n }\n\n /** GET a non-JSON endpoint (e.g. CSV export) as text. */\n async getText(path: string, params: Params = {}): Promise<string> {\n const url = this.url(path, params);\n const res = await this._fetch(url, { headers: this.headers });\n if (!res.ok) throw new WhereqError(res.status, res.statusText, url);\n return res.text();\n }\n\n // -- prices / cost of living ------------------------------------------------\n prices(p: { domain?: string; region?: string; bedrooms?: number; q?: string; limit?: number; offset?: number } = {}) {\n return this.get(\"/v1/prices\", p);\n }\n price(seriesId: number) {\n return this.get(`/v1/prices/${seriesId}`);\n }\n pricesCsv(p: { domain?: string; region?: string; bedrooms?: number; q?: string } = {}) {\n return this.getText(\"/v1/prices/export\", p);\n }\n /** Compare cost of living across US states / CA provinces / metros.\n * `places`: comma-separated `region:name` or `m:<rent-series-id>`. */\n costOfLiving(places: string) {\n return this.get(\"/v1/cost-of-living\", { places });\n }\n\n // -- discovery / facets -----------------------------------------------------\n catalog() { return this.get(\"/v1/catalog\"); }\n categories() { return this.get(\"/v1/categories\"); }\n regions() { return this.get(\"/v1/regions\"); }\n domains() { return this.get(\"/v1/domains\"); }\n trending(p: Params = {}) { return this.get(\"/v1/trending\", p); }\n\n // -- finance ----------------------------------------------------------------\n hotstocks(limit = 20) { return this.get(\"/v1/hotstocks\", { limit }); }\n quotes(p: Params = {}) { return this.get(\"/v1/quotes\", p); }\n news(p: Params = {}) { return this.get(\"/v1/news\", p); }\n screener(p: Params = {}) { return this.get(\"/v1/screener\", p); }\n search(q: string, p: Params = {}) { return this.get(\"/v1/search\", { q, ...p }); }\n\n // -- autos ------------------------------------------------------------------\n autosRecalls(p: Params = {}) { return this.get(\"/v1/autos/recalls\", p); }\n autosListings(p: Params = {}) { return this.get(\"/v1/autos/listings\", p); }\n autosFuelEconomy(p: Params = {}) { return this.get(\"/v1/autos/fuel-economy\", p); }\n autosModels(p: Params = {}) { return this.get(\"/v1/autos/models\", p); }\n\n // -- fuel (gas & diesel) ----------------------------------------------------\n /** Geolocated retail fuel stations (lat/lon, municipality) with latest prices.\n * Filters: country, state, municipality, product, bbox, q. */\n fuelStations(p: Params = {}) { return this.get(\"/v1/fuel/stations\", p); }\n /** One station: location + latest prices + intra-day price-change history. */\n fuelStation(id: number | string) { return this.get(`/v1/fuel/stations/${encodeURIComponent(String(id))}`); }\n /** Aggregated fuel price series (state / national), North-America-wide. */\n fuelPrices(p: Params = {}) { return this.get(\"/v1/prices\", { domain: \"fuel\", ...p }); }\n}\n\nexport default Whereq;\n"]}
1
+ {"version":3,"sources":["../src/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * whereq.cloud — official JavaScript/TypeScript SDK for the WhereQ data cloud.\n *\n * A thin, typed wrapper over the versioned `/v1` HTTP API at `api.whereq.cloud`.\n * Public endpoints work with no key; metered endpoints take an API key.\n *\n * ```ts\n * import { Whereq } from \"@whereq/cloud\";\n *\n * const wq = new Whereq(); // public access\n * // const wq = new Whereq({ apiKey: \"wq_live_…\" }); // metered tier\n *\n * await wq.costOfLiving(\"us:California,ca:Ontario\");\n * await wq.prices({ domain: \"rent\", region: \"us\", bedrooms: 2 });\n * await wq.get(\"/v1/trending\", { limit: 10 }); // escape hatch\n * ```\n */\nexport const VERSION = \"0.3.0\";\nconst DEFAULT_BASE_URL = \"https://api.whereq.cloud\";\n\n/** The products a station can quote. Mexico's CRE feed carries the first,\n * second and fourth; GasBuddy (US/Canada) adds midgrade. */\nexport const FUEL_PRODUCTS = [\"regular\", \"midgrade\", \"premium\", \"diesel\"] as const;\nexport type FuelProduct = (typeof FUEL_PRODUCTS)[number];\n\n/** Countries with station-level fuel data. */\nexport const FUEL_COUNTRIES = [\"MX\", \"US\", \"CA\"] as const;\nexport type FuelCountry = (typeof FUEL_COUNTRIES)[number];\n\n/** The unit each country quotes in — always local currency per litre. */\nexport const FUEL_CURRENCIES: Record<FuelCountry, string> = {\n MX: \"MXN/L\",\n US: \"USD/L\",\n CA: \"CAD/L\",\n};\n\n/** One product's latest price at a station. */\nexport interface FuelStationPrice {\n price: number;\n observed_at: string;\n}\n\n/** A geolocated retail fuel station and its latest prices.\n * `state` is the human label (\"Ontario\", \"Texas\"); `state_iso` is the\n * two-letter code (\"ON\", \"TX\"). */\nexport interface FuelStation {\n id: number;\n source: string;\n ext_id: string;\n country: string;\n name: string;\n brand?: string | null;\n state?: string | null;\n state_iso?: string | null;\n municipality?: string | null;\n lat?: number | null;\n lon?: number | null;\n prices: Record<string, FuelStationPrice>;\n}\n\n/** Filters for `fuelStations()`. */\nexport interface FuelStationsParams {\n /** \"MX\", \"US\" or \"CA\". */\n country?: FuelCountry | string;\n /** State/province name *or* ISO code — \"Ontario\"/\"ON\", \"Texas\"/\"TX\". */\n state?: string;\n /** City name, e.g. \"Mississauga\". */\n municipality?: string;\n product?: FuelProduct | string;\n /** \"minLon,minLat,maxLon,maxLat\" — a map viewport. */\n bbox?: string;\n /** Station-name search. */\n q?: string;\n /** 1–500 rows per page (default 100). */\n limit?: number;\n /** Row offset for paging. */\n offset?: number;\n}\n\n/** Filters for `fuelStation()`. */\nexport interface FuelStationParams {\n /** Restrict the timeline to one product. */\n product?: FuelProduct | string;\n /** How far back the timeline reaches (1–1825, default 90). */\n days?: number;\n}\n\n/** `GET /v1/fuel/stations`. Unentitled callers get a 100-row preview of the\n * oldest rows: `demo` is true, `total` is null and paging is ignored. */\nexport interface FuelStationsResponse {\n demo?: boolean;\n preview_rows?: number;\n note?: string;\n upgrade_url?: string;\n as_of: string;\n count: number;\n total?: number | null;\n stations: FuelStation[];\n}\n\n/** One observed price change — the intra-day timeline for a station. */\nexport interface FuelStationPricePoint {\n product: string;\n observed_at: string;\n price: number;\n}\n\n/** `GET /v1/fuel/stations/{id}`. `days` is null in the unentitled preview. */\nexport interface FuelStationDetail {\n demo?: boolean;\n preview_rows?: number;\n note?: string;\n upgrade_url?: string;\n station: FuelStation;\n days?: number | null;\n prices: FuelStationPricePoint[];\n}\n\n/** Filters for `fuelPrices()`. */\nexport interface FuelPricesParams {\n /** Region slug, or a comma-separated list of them (\"us,ca\"). */\n region?: string;\n /** Free-text place name (\"Calgary, Alberta\"). */\n geo?: string;\n q?: string;\n limit?: number;\n offset?: number;\n}\n\n/** One aggregated price series (state / national / metro). */\nexport interface PriceSeries {\n id: number;\n domain: string;\n source: string;\n region?: string | null;\n geo?: string | null;\n item: string;\n item_cn?: string | null;\n unit?: string | null;\n unit_cn?: string | null;\n frequency?: string | null;\n latest_period?: string | null;\n latest_value?: number | null;\n prev_value?: number | null;\n points?: number | null;\n spark?: number[];\n}\n\n/** `GET /v1/prices` — a page of series plus the page's own metadata. */\nexport interface PriceSeriesResponse {\n count: number;\n domain?: string | null;\n region?: string | null;\n limit: number;\n offset: number;\n data: PriceSeries[];\n}\n\nexport class WhereqError extends Error {\n constructor(\n public readonly status: number,\n message: string,\n public readonly url: string,\n ) {\n super(`whereq.cloud API error ${status} for ${url}: ${message}`);\n this.name = \"WhereqError\";\n }\n}\n\nexport interface ClientOptions {\n /** `wq_live_…` key for metered endpoints (sent as `X-API-Key`). */\n apiKey?: string;\n /** Override the API base (default `https://api.whereq.cloud`). */\n baseUrl?: string;\n /** Custom fetch (e.g. for Node <18 or testing). Defaults to global `fetch`. */\n fetch?: typeof fetch;\n}\n\ntype Params = Record<string, unknown>;\n\nexport class Whereq {\n private readonly baseUrl: string;\n private readonly headers: Record<string, string>;\n private readonly _fetch: typeof fetch;\n\n constructor(opts: ClientOptions = {}) {\n this.baseUrl = (opts.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, \"\");\n this.headers = { Accept: \"application/json\" };\n if (opts.apiKey) this.headers[\"X-API-Key\"] = opts.apiKey;\n const f = opts.fetch ?? globalThis.fetch;\n if (!f) throw new Error(\"No global fetch available — pass `fetch` in options (Node <18).\");\n this._fetch = f;\n }\n\n private url(path: string, params: Params): string {\n const qs = new URLSearchParams();\n for (const [k, v] of Object.entries(params)) {\n if (v !== undefined && v !== null) qs.set(k, String(v));\n }\n const s = qs.toString();\n return `${this.baseUrl}${path}${s ? `?${s}` : \"\"}`;\n }\n\n /** GET any endpoint; `undefined`/`null` params are dropped. Returns parsed JSON. */\n async get<T = unknown>(path: string, params: Params = {}): Promise<T> {\n const url = this.url(path, params);\n const res = await this._fetch(url, { headers: this.headers });\n if (!res.ok) {\n let msg = res.statusText;\n try {\n const j = (await res.json()) as { detail?: string };\n msg = j?.detail || JSON.stringify(j) || msg;\n } catch {\n /* non-JSON error body */\n }\n throw new WhereqError(res.status, msg, url);\n }\n return (await res.json()) as T;\n }\n\n /** GET a non-JSON endpoint (e.g. CSV export) as text. */\n async getText(path: string, params: Params = {}): Promise<string> {\n const url = this.url(path, params);\n const res = await this._fetch(url, { headers: this.headers });\n if (!res.ok) throw new WhereqError(res.status, res.statusText, url);\n return res.text();\n }\n\n // -- prices / cost of living ------------------------------------------------\n /** Cost-of-living price series (fuel | food | energy | housing | rent).\n * `region` takes a region slug or a comma-separated list (\"us,ca\");\n * `geo` is a free-text place name (\"Calgary, Alberta\"). */\n prices(p: { domain?: string; region?: string; geo?: string; bedrooms?: number; q?: string; limit?: number; offset?: number } = {}): Promise<PriceSeriesResponse> {\n return this.get<PriceSeriesResponse>(\"/v1/prices\", p);\n }\n price(seriesId: number) {\n return this.get(`/v1/prices/${seriesId}`);\n }\n pricesCsv(p: { domain?: string; region?: string; geo?: string; bedrooms?: number; q?: string } = {}) {\n return this.getText(\"/v1/prices/export\", p);\n }\n /** Compare cost of living across US states / CA provinces / metros.\n * `places`: comma-separated `region:name` or `m:<rent-series-id>`. */\n costOfLiving(places: string) {\n return this.get(\"/v1/cost-of-living\", { places });\n }\n\n // -- discovery / facets -----------------------------------------------------\n catalog() { return this.get(\"/v1/catalog\"); }\n categories() { return this.get(\"/v1/categories\"); }\n regions() { return this.get(\"/v1/regions\"); }\n domains() { return this.get(\"/v1/domains\"); }\n trending(p: Params = {}) { return this.get(\"/v1/trending\", p); }\n\n // -- finance ----------------------------------------------------------------\n hotstocks(limit = 20) { return this.get(\"/v1/hotstocks\", { limit }); }\n quotes(p: Params = {}) { return this.get(\"/v1/quotes\", p); }\n news(p: Params = {}) { return this.get(\"/v1/news\", p); }\n screener(p: Params = {}) { return this.get(\"/v1/screener\", p); }\n search(q: string, p: Params = {}) { return this.get(\"/v1/search\", { q, ...p }); }\n\n // -- autos ------------------------------------------------------------------\n autosRecalls(p: Params = {}) { return this.get(\"/v1/autos/recalls\", p); }\n autosListings(p: Params = {}) { return this.get(\"/v1/autos/listings\", p); }\n autosFuelEconomy(p: Params = {}) { return this.get(\"/v1/autos/fuel-economy\", p); }\n autosModels(p: Params = {}) { return this.get(\"/v1/autos/models\", p); }\n\n // -- fuel (gas & diesel) ----------------------------------------------------\n /** Geolocated retail fuel stations with their latest prices.\n *\n * Coverage: Mexico (`MX`, CRE open data), the United States (`US`) and\n * Canada (`CA`). Prices are in **local currency per litre** — `MXN/L`,\n * `USD/L` and `CAD/L` respectively.\n *\n * Unentitled callers get a 100-row preview of the oldest rows and the\n * pagination arguments are ignored — check `response.demo`.\n */\n fuelStations(p: FuelStationsParams & Params = {}): Promise<FuelStationsResponse> {\n return this.get<FuelStationsResponse>(\"/v1/fuel/stations\", p);\n }\n\n /** One station: location, latest prices and its price-change timeline. */\n fuelStation(\n id: number | string,\n p: FuelStationParams & Params = {},\n ): Promise<FuelStationDetail> {\n return this.get<FuelStationDetail>(\n `/v1/fuel/stations/${encodeURIComponent(String(id))}`,\n p,\n );\n }\n\n /** Yield every matching station, paging through the API for you.\n *\n * Only meaningful with an entitled key. The unentitled preview always\n * returns the *same* oldest 100 rows and ignores the paging arguments,\n * so there is nothing more to fetch: this yields that first page and\n * stops rather than looping on it.\n */\n async *fuelStationsAll(\n p: FuelStationsParams & Params = {},\n ): AsyncGenerator<FuelStation> {\n const pageSize = Math.min(Math.max(Number(p.limit ?? 500), 1), 500);\n let offset = Number(p.offset ?? 0);\n for (;;) {\n const page = await this.fuelStations({ ...p, limit: pageSize, offset });\n const stations = page.stations ?? [];\n if (stations.length === 0) return;\n for (const s of stations) yield s;\n if (page.demo) return; // preview: every page is the same slice\n offset += stations.length;\n if (page.total != null && offset >= page.total) return;\n }\n }\n\n /** Aggregated fuel price series (state / national / metro).\n *\n * These are the *series* behind the charts — EIA weekly for the US,\n * StatCan monthly for Canada, CRE for Mexico — not the station-level\n * prices that `fuelStations()` returns.\n */\n fuelPrices(p: FuelPricesParams & Params = {}): Promise<PriceSeriesResponse> {\n return this.get<PriceSeriesResponse>(\"/v1/prices\", { domain: \"fuel\", ...p });\n }\n}\n\nexport default Whereq;\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@whereq/cloud",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Official JavaScript/TypeScript SDK for the WhereQ data cloud (api.whereq.cloud) — North-America fuel & gas-station prices, cost-of-living prices, autos, lottery, trending, finance & more.",
5
5
  "license": "MIT",
6
6
  "author": "WhereQ <whereq@gmail.com>",