@whereq/cloud 0.3.0 → 0.4.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
@@ -36,6 +36,12 @@ await wq.fuelStations({ country: "MX", municipality: "Tijuana", product: "regula
36
36
  await wq.fuelStation(1); // one station + intra-day price history
37
37
  await wq.fuelPrices({ region: "mx" }); // state / national price series
38
38
 
39
+ // Lottery — draws, per-number frequency, and the game registry
40
+ await wq.lotteryGames({ country: "US", region: "NY" });
41
+ await wq.lotteryDraws({ game: "ny_lotto", days: 30 });
42
+ await wq.lotteryLatestDraw("ny_lotto");
43
+ await wq.lotteryFrequency("ny_lotto", 365);
44
+
39
45
  // Discovery
40
46
  await wq.catalog(); await wq.categories(); await wq.regions(); await wq.domains();
41
47
 
package/dist/index.cjs CHANGED
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  // src/index.ts
6
- var VERSION = "0.3.0";
6
+ var VERSION = "0.4.0";
7
7
  var DEFAULT_BASE_URL = "https://api.whereq.cloud";
8
8
  var FUEL_PRODUCTS = ["regular", "midgrade", "premium", "diesel"];
9
9
  var FUEL_COUNTRIES = ["MX", "US", "CA"];
@@ -127,6 +127,32 @@ var Whereq = class {
127
127
  autosModels(p = {}) {
128
128
  return this.get("/v1/autos/models", p);
129
129
  }
130
+ // -- lottery -----------------------------------------------------------------
131
+ /** Recent lottery draws, newest first.
132
+ *
133
+ * Unentitled callers get the oldest 100 draws instead of the recent
134
+ * ones — check `response.demo`.
135
+ */
136
+ lotteryDraws(p = {}) {
137
+ return this.get("/v1/lottery/draws", p);
138
+ }
139
+ /** The most recent draw for a game. On the unentitled preview this is the
140
+ * *oldest* draw — the recent one is the gated, valuable row. */
141
+ lotteryLatestDraw(game) {
142
+ return this.get(`/v1/lottery/draws/${encodeURIComponent(game)}/latest`);
143
+ }
144
+ /** Per-number frequency for a game over a window (30–1825 days). */
145
+ lotteryFrequency(game, days = 365) {
146
+ return this.get(`/v1/lottery/draws/${encodeURIComponent(game)}/frequency`, { days });
147
+ }
148
+ /** The lottery game registry: names, play rules and draw days. */
149
+ lotteryGames(p = {}) {
150
+ return this.get("/v1/lottery/games", p);
151
+ }
152
+ /** One game's full play rules and metadata. */
153
+ lotteryGame(slug) {
154
+ return this.get(`/v1/lottery/games/${encodeURIComponent(slug)}`);
155
+ }
130
156
  // -- fuel (gas & diesel) ----------------------------------------------------
131
157
  /** Geolocated retail fuel stations with their latest prices.
132
158
  *
@@ -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.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"]}
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.4.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 // -- lottery -----------------------------------------------------------------\n /** Recent lottery draws, newest first.\n *\n * Unentitled callers get the oldest 100 draws instead of the recent\n * ones — check `response.demo`.\n */\n lotteryDraws(p: { game?: string; days?: number; limit?: number } & Params = {}): Promise<any> {\n return this.get(\"/v1/lottery/draws\", p);\n }\n /** The most recent draw for a game. On the unentitled preview this is the\n * *oldest* draw — the recent one is the gated, valuable row. */\n lotteryLatestDraw(game: string): Promise<any> {\n return this.get(`/v1/lottery/draws/${encodeURIComponent(game)}/latest`);\n }\n /** Per-number frequency for a game over a window (30–1825 days). */\n lotteryFrequency(game: string, days = 365): Promise<any> {\n return this.get(`/v1/lottery/draws/${encodeURIComponent(game)}/frequency`, { days });\n }\n /** The lottery game registry: names, play rules and draw days. */\n lotteryGames(p: { country?: string; region?: string } & Params = {}): Promise<any> {\n return this.get(\"/v1/lottery/games\", p);\n }\n /** One game's full play rules and metadata. */\n lotteryGame(slug: string): Promise<any> {\n return this.get(`/v1/lottery/games/${encodeURIComponent(slug)}`);\n }\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,7 @@
15
15
  * await wq.get("/v1/trending", { limit: 10 }); // escape hatch
16
16
  * ```
17
17
  */
18
- declare const VERSION = "0.3.0";
18
+ declare const VERSION = "0.4.0";
19
19
  /** The products a station can quote. Mexico's CRE feed carries the first,
20
20
  * second and fourth; GasBuddy (US/Canada) adds midgrade. */
21
21
  declare const FUEL_PRODUCTS: readonly ["regular", "midgrade", "premium", "diesel"];
@@ -198,6 +198,28 @@ declare class Whereq {
198
198
  autosListings(p?: Params): Promise<unknown>;
199
199
  autosFuelEconomy(p?: Params): Promise<unknown>;
200
200
  autosModels(p?: Params): Promise<unknown>;
201
+ /** Recent lottery draws, newest first.
202
+ *
203
+ * Unentitled callers get the oldest 100 draws instead of the recent
204
+ * ones — check `response.demo`.
205
+ */
206
+ lotteryDraws(p?: {
207
+ game?: string;
208
+ days?: number;
209
+ limit?: number;
210
+ } & Params): Promise<any>;
211
+ /** The most recent draw for a game. On the unentitled preview this is the
212
+ * *oldest* draw — the recent one is the gated, valuable row. */
213
+ lotteryLatestDraw(game: string): Promise<any>;
214
+ /** Per-number frequency for a game over a window (30–1825 days). */
215
+ lotteryFrequency(game: string, days?: number): Promise<any>;
216
+ /** The lottery game registry: names, play rules and draw days. */
217
+ lotteryGames(p?: {
218
+ country?: string;
219
+ region?: string;
220
+ } & Params): Promise<any>;
221
+ /** One game's full play rules and metadata. */
222
+ lotteryGame(slug: string): Promise<any>;
201
223
  /** Geolocated retail fuel stations with their latest prices.
202
224
  *
203
225
  * Coverage: Mexico (`MX`, CRE open data), the United States (`US`) and
package/dist/index.d.ts CHANGED
@@ -15,7 +15,7 @@
15
15
  * await wq.get("/v1/trending", { limit: 10 }); // escape hatch
16
16
  * ```
17
17
  */
18
- declare const VERSION = "0.3.0";
18
+ declare const VERSION = "0.4.0";
19
19
  /** The products a station can quote. Mexico's CRE feed carries the first,
20
20
  * second and fourth; GasBuddy (US/Canada) adds midgrade. */
21
21
  declare const FUEL_PRODUCTS: readonly ["regular", "midgrade", "premium", "diesel"];
@@ -198,6 +198,28 @@ declare class Whereq {
198
198
  autosListings(p?: Params): Promise<unknown>;
199
199
  autosFuelEconomy(p?: Params): Promise<unknown>;
200
200
  autosModels(p?: Params): Promise<unknown>;
201
+ /** Recent lottery draws, newest first.
202
+ *
203
+ * Unentitled callers get the oldest 100 draws instead of the recent
204
+ * ones — check `response.demo`.
205
+ */
206
+ lotteryDraws(p?: {
207
+ game?: string;
208
+ days?: number;
209
+ limit?: number;
210
+ } & Params): Promise<any>;
211
+ /** The most recent draw for a game. On the unentitled preview this is the
212
+ * *oldest* draw — the recent one is the gated, valuable row. */
213
+ lotteryLatestDraw(game: string): Promise<any>;
214
+ /** Per-number frequency for a game over a window (30–1825 days). */
215
+ lotteryFrequency(game: string, days?: number): Promise<any>;
216
+ /** The lottery game registry: names, play rules and draw days. */
217
+ lotteryGames(p?: {
218
+ country?: string;
219
+ region?: string;
220
+ } & Params): Promise<any>;
221
+ /** One game's full play rules and metadata. */
222
+ lotteryGame(slug: string): Promise<any>;
201
223
  /** Geolocated retail fuel stations with their latest prices.
202
224
  *
203
225
  * Coverage: Mexico (`MX`, CRE open data), the United States (`US`) and
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/index.ts
2
- var VERSION = "0.3.0";
2
+ var VERSION = "0.4.0";
3
3
  var DEFAULT_BASE_URL = "https://api.whereq.cloud";
4
4
  var FUEL_PRODUCTS = ["regular", "midgrade", "premium", "diesel"];
5
5
  var FUEL_COUNTRIES = ["MX", "US", "CA"];
@@ -123,6 +123,32 @@ var Whereq = class {
123
123
  autosModels(p = {}) {
124
124
  return this.get("/v1/autos/models", p);
125
125
  }
126
+ // -- lottery -----------------------------------------------------------------
127
+ /** Recent lottery draws, newest first.
128
+ *
129
+ * Unentitled callers get the oldest 100 draws instead of the recent
130
+ * ones — check `response.demo`.
131
+ */
132
+ lotteryDraws(p = {}) {
133
+ return this.get("/v1/lottery/draws", p);
134
+ }
135
+ /** The most recent draw for a game. On the unentitled preview this is the
136
+ * *oldest* draw — the recent one is the gated, valuable row. */
137
+ lotteryLatestDraw(game) {
138
+ return this.get(`/v1/lottery/draws/${encodeURIComponent(game)}/latest`);
139
+ }
140
+ /** Per-number frequency for a game over a window (30–1825 days). */
141
+ lotteryFrequency(game, days = 365) {
142
+ return this.get(`/v1/lottery/draws/${encodeURIComponent(game)}/frequency`, { days });
143
+ }
144
+ /** The lottery game registry: names, play rules and draw days. */
145
+ lotteryGames(p = {}) {
146
+ return this.get("/v1/lottery/games", p);
147
+ }
148
+ /** One game's full play rules and metadata. */
149
+ lotteryGame(slug) {
150
+ return this.get(`/v1/lottery/games/${encodeURIComponent(slug)}`);
151
+ }
126
152
  // -- fuel (gas & diesel) ----------------------------------------------------
127
153
  /** Geolocated retail fuel stations with their latest prices.
128
154
  *
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.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"]}
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.4.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 // -- lottery -----------------------------------------------------------------\n /** Recent lottery draws, newest first.\n *\n * Unentitled callers get the oldest 100 draws instead of the recent\n * ones — check `response.demo`.\n */\n lotteryDraws(p: { game?: string; days?: number; limit?: number } & Params = {}): Promise<any> {\n return this.get(\"/v1/lottery/draws\", p);\n }\n /** The most recent draw for a game. On the unentitled preview this is the\n * *oldest* draw — the recent one is the gated, valuable row. */\n lotteryLatestDraw(game: string): Promise<any> {\n return this.get(`/v1/lottery/draws/${encodeURIComponent(game)}/latest`);\n }\n /** Per-number frequency for a game over a window (30–1825 days). */\n lotteryFrequency(game: string, days = 365): Promise<any> {\n return this.get(`/v1/lottery/draws/${encodeURIComponent(game)}/frequency`, { days });\n }\n /** The lottery game registry: names, play rules and draw days. */\n lotteryGames(p: { country?: string; region?: string } & Params = {}): Promise<any> {\n return this.get(\"/v1/lottery/games\", p);\n }\n /** One game's full play rules and metadata. */\n lotteryGame(slug: string): Promise<any> {\n return this.get(`/v1/lottery/games/${encodeURIComponent(slug)}`);\n }\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.3.0",
3
+ "version": "0.4.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>",