feat: replace openapi-generator with Hey API generated client
Build and Push Docker Images / build-backend (pull_request) Successful in 1m2s
Build and Push Docker Images / build-frontend (pull_request) Successful in 50s
Build and Push Docker Images / test-backend (pull_request) Failing after 2m11s
Build and Push Docker Images / test-frontend (pull_request) Successful in 10m58s
Build and Push Docker Images / e2e-frontend (pull_request) Failing after 4m18s
Build and Push Docker Images / build-backend (pull_request) Successful in 1m2s
Build and Push Docker Images / build-frontend (pull_request) Successful in 50s
Build and Push Docker Images / test-backend (pull_request) Failing after 2m11s
Build and Push Docker Images / test-frontend (pull_request) Successful in 10m58s
Build and Push Docker Images / e2e-frontend (pull_request) Failing after 4m18s
Backend controllers emit explicit operationIds via [EndpointName], and the frontend now generates its typed client with @hey-api/openapi-ts (exact-pinned 0.99.0) using the client-fetch, sdk, and @tanstack/react-query plugins. - New apiClient/serverClient factory in lib/api.ts + lib/api.server.ts: server requests keep using INTERNAL_API_BASE_URL via a fetch rewrite while query keys are computed from the public base URL, preserving SSR hydration parity and the internal rate-limit exemption. - ApiError wraps non-2xx responses (throwOnError: true); notifications and prefetch error handling updated. - Prefetched/shared queries use generated ...QueryKey() helpers. - Vitest mocks rewritten to stub generated sdk functions; docs updated. Closes #187
This commit is contained in:
1 parent
251dfbe7bb
commit
21fd772304
96 files changed
+4546
-5662
No files matched your search
@@ -5,7 +5,7 @@
|
||||
- **Mono-repo**: `backend/` (.NET 10 Web API) + `frontend/` (Next.js 16 standalone, React 19). No other packages.
|
||||
- **DB**: TimescaleDB (PostgreSQL with hypertables & PostGIS) via EF Core (`Npgsql.EntityFrameworkCore.PostgreSQL`). Schema is **model-first**: all tables owned by EF Core migrations, applied on startup via `MigrateAsync()`. `DatabaseInitialiser` only handles the non-transactional infra migrations can't own (PostGIS extension, `price` hypertable conversion).
|
||||
- Multi-state model (`nsw`/`vic`/`wa`): station identity is unique `(source, source_id)` — NSW `source_id` is `code-state`, WA fabricates a sha256 of name/address/coords; `price` links via `station_id`. `fuel_code_alias` maps source fuel codes to the canonical (NSW) code set; `price` also keeps raw `source_fuel_type` and `is_available`. `last_updated` is the source's effective timestamp (NSW Sydney-parsed, VIC UTC, WA effective-day 00:00 Perth): current-price reads filter `last_updated <= now()`, trends bucket and filter on `last_updated`. Every raw fetch is archived to `source_payload` (jsonb, 30-day purge). Side tables: `vic_brand`, `vic_station_detail`, `wa_station_detail`. Domain enums (`FuelSource`, `SuburbBoundaryState`) persist as lowercase text via EF value converters and serialize camelCase — new source/state values must extend the enum, not add strings. See `docs/superpowers/specs/2026-08-30-multi-state-data-model-design.md`.
|
||||
- **API clients**: Frontend types/fetch wrappers auto-generated from backend OpenAPI spec at `http://localhost:5161/api/openapi/v1.json`. Regenerate with `pnpm generate` — backend must be running. Generated code in `frontend/generated/` is committed, do not hand-edit. Server components use `INTERNAL_API_BASE_URL` (defaults to the internal docker service name in compose) so SSR traffic stays on the docker network and the rate-limit exemption engages; browsers keep `NEXT_PUBLIC_API_BASE_URL`.
|
||||
- **API clients**: Frontend types/SDK/TanStack-Query helpers auto-generated by `@hey-api/openapi-ts` (config: `frontend/openapi-ts.config.ts`) from the backend OpenAPI spec at `http://localhost:5161/api/openapi/v1.json`. Regenerate with `pnpm generate` — backend must be running. Generated code in `frontend/generated/` is committed, do not hand-edit. The spec carries explicit `operationId`s via `[EndpointName("...")]` on each controller action — these become the generated function names, so new endpoints must define one. Server components use `serverClient` (`frontend/lib/api.server.ts`) which keeps request traffic on the docker network (rate-limit exemption via `INTERNAL_API_BASE_URL` fetch rewrite) while query keys use `NEXT_PUBLIC_API_BASE_URL` so SSR hydration matches the browser's `apiClient` (`frontend/lib/api.ts`); query keys for hydrated queries come from the generated `...QueryKey()` helpers on both sides.
|
||||
- **Background jobs**: Hangfire (PostgreSQL storage). Recurring (Sydney timezone unless noted): NSW fuel prices every 20 min, LOVs every 4 hours, suburb boundaries weekly (five sources: NSW/VIC/WA via data.gov.au GeoServer WFS with `srsName` forced to EPSG:7844, ACT/TAS via Geoscape shapefile ZIPs read with `NetTopologySuite.IO.Esri`, GDA2020; upsert/soft-delete scoped per `suburb_boundary.state`), `purge_source_payloads` daily 03:15. VIC (Australia/Melbourne): `refresh_vic_reference_data` every 4 h, `refresh_vic_prices` hourly at :05. WA (Australia/Perth): `refresh_wa_prices` daily 07:00 (`Day=today`), `refresh_wa_tomorrow_prices` daily 14:30 (`Day=tomorrow`); fan-out is sequential at ~500 ms spacing. Dashboard at `/hangfire` — dev only.
|
||||
- **Map tiles**: Self-hosted OpenStreetMap **vector tiles** on `tile.fuelwizard.au` (Planetiler → TileServer GL, all FOSS; host operated separately). Frontend fetches the style list from `https://tile.fuelwizard.au/styles.json` (`NEXT_PUBLIC_TILE_BASE` env var) and loads each style directly by its absolute URL — no URL rewriting, no Next.js proxy rewrites; the tile server must keep CORS enabled (`access-control-allow-origin: *`). Style menu: collapsed layers-button (`frontend/utils/mapStyles.ts`). Default style is "Basic"; the user's chosen style persists to `localStorage["defaultMapStyle"]` (see `userPreferencesUtils.ts`) and does **not** auto-switch with the app theme. Overlays adapt to the selected style's darkness. No raster tile source / no `buildMapStyle` (see `docs/superpowers/specs/2026-08-14-self-hosted-vector-tiles-selectable-styles.md`).
|
||||
- **Rate limiter**: 100 requests per 60s sliding window per client IP (`RateLimiterPolicies`). `RATE_LIMIT_EXEMPT_CIDRS` (comma-separated CIDRs, default empty) exempts matching peer IPs — used for the Next.js server's internal Docker network (pinned to `172.100.0.0/16` in `compose.yaml`). Exemption matches the direct connection IP only, never `X-Forwarded-For`. There are exactly two compose files: root `compose.yaml` (production full stack) and `backend/Database/Deployment/compose.yaml` (dev database only).
|
||||
@@ -30,7 +30,7 @@
|
||||
- `pnpm generate` — regenerate API client (requires backend running on port 5161)
|
||||
- `pnpm e2e` / `pnpm e2e:visual` — Playwright E2E / visual regression against a fixture API (no backend needed; `webServer` builds and starts Next with both API base URLs pointed at `e2e/mock-api/server.mjs`). `pnpm e2e` excludes `@visual` (`--grep-invert`), so it passes on any machine; `@visual` baselines are Linux-only
|
||||
- `scripts/e2e-in-docker.sh` / `scripts/e2e-bless-snapshots.sh` — run inside / bless `@visual` baselines in the official Playwright Docker image
|
||||
- Codebase: `frontend/lib/api.ts` is the shared fetch instance. Do not import `Configuration` directly from generated code — use `api.ts`.
|
||||
- Codebase: `frontend/lib/api.ts` is the shared fetch client factory (browser `apiClient`); do not create clients or import generated client internals directly. Every API/options call must pass a `client` (`apiClient` in browser code, `serverClient` from `lib/api.server.ts` in server code).
|
||||
- Styling: Mantine v9, lime primary (`primaryColor: "lime"`), dark mode default.
|
||||
- **SEO**: Metadata lives in the root layout (`frontend/app/layout.tsx`) plus a `metadata` export per page; `frontend/app/sitemap.ts`, `frontend/app/robots.ts`, and `frontend/app/manifest.ts` serve `/sitemap.xml`, `/robots.txt`, `/manifest.webmanifest`; JSON-LD via `frontend/app/components/seo/JsonLd.tsx`; OG image `frontend/public/og.png` (regenerate with `node frontend/scripts/generate-og.mjs`). `SITE_URL` (canonical site URL, default `https://fuelwizard.au`) feeds `metadataBase`, sitemap, and robots.
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
|
||||
## Gotchas
|
||||
|
||||
- **Generated client is fragile**: after any backend change, regenerate with `pnpm generate`. The `openapi-generator-cli` v2 script hardcodes the API URL — if a port changes, update it in `frontend/package.json` and frontend env files.
|
||||
- **Generated client is fragile**: after any backend change, regenerate with `pnpm generate`. The input URL lives in `frontend/openapi-ts.config.ts`. `@hey-api/openapi-ts` is exact-pinned (0.x churn) and the runtime client config is `frontend/hey-api.ts` (`runtimeConfigPath`). Do not bump TypeScript to 7: openapi-ts 0.99 crashes on it (TS 7 dropped the JS compiler API it imports); the peer range wrongly accepts it.
|
||||
- **Schema is model-first, applied via migrations on startup**: after any EF model change, create a new migration (`dotnet ef migrations add <Name>`) and it is applied automatically on startup via `MigrateAsync()`. `DatabaseInitialiser` only owns non-transactional infra (PostGIS extension, `price` hypertable). The bootstrap `InitialSchema` migration creates all tables and is idempotent (`IF NOT EXISTS`).
|
||||
- **Frontend prod Docker build**: uses docker context with only `.next/standalone/, .next/static/, public/` copied in (`output: "standalone"`). Full `frontend/` is not required for Docker image size.
|
||||
- **Sandbox NSW API keys ship in `.env.sample`** — they are public sandbox values; a deploy without real credentials fails at startup by design. `frontend/.env.*` tracked files hold non-secret build defaults; browser-visible vars are `NEXT_PUBLIC_*` only.
|
||||
|
||||
@@ -21,7 +21,7 @@ Fuel Wizard was a response to limitations with state-government provided fuel pr
|
||||
|
||||
### Front End
|
||||
|
||||
The front end application is a **Next.js 16, TypeScript** web app, which uses the **Mantine** UI library and utilities to display the application data. **react-map-gl** with **MapLibre GL** is used for the map views, rendering self-hosted OpenStreetMap **vector tiles** served from `tile.fuelwizard.au` (styles are loaded from the server's `styles.json` and are user-selectable, with "Basic" as the default — see `frontend/utils/mapStyles.ts`). **openapi-generator** automatically generates types and fetch wrappers for requests to the API, and **TanStack Query** manages front end data fetching. **OSRM** (served at `osrm.fuelwizard.au`) provides the routing API, with **osrm-text-instructions** generating turn-by-turn directions.
|
||||
The front end application is a **Next.js 16, TypeScript** web app, which uses the **Mantine** UI library and utilities to display the application data. **react-map-gl** with **MapLibre GL** is used for the map views, rendering self-hosted OpenStreetMap **vector tiles** served from `tile.fuelwizard.au` (styles are loaded from the server's `styles.json` and are user-selectable, with "Basic" as the default — see `frontend/utils/mapStyles.ts`). **Hey API** (`@hey-api/openapi-ts`) automatically generates types, an SDK, and TanStack Query helpers for requests to the API, and **TanStack Query** manages front end data fetching. **OSRM** (served at `osrm.fuelwizard.au`) provides the routing API, with **osrm-text-instructions** generating turn-by-turn directions.
|
||||
|
||||
### Back End
|
||||
|
||||
@@ -152,7 +152,7 @@ Thank you to these fantastic projects, and their respective communities, without
|
||||
- MapLibre GL (as our interactive map rendering engine): https://maplibre.org
|
||||
- react-map-gl (as our React wrapper for MapLibre GL): https://visgl.github.io/react-map-gl
|
||||
- TanStack Query (as our front end query management library): https://tanstack.com/query/latest
|
||||
- OpenAPI Generator (for automatic generation of front end API interfaces): https://openapi-generator.tech
|
||||
- Hey API (for automatic generation of front end API interfaces): https://heyapi.dev
|
||||
- Day.js (as our time/date library for the front end): https://day.js.org
|
||||
- dayjs-plugin-utc (for UTC timezone support in Day.js): https://github.com/guisturdy/dayjs-plugin-utc
|
||||
- Recharts (for charts in Mantine): https://recharts.org
|
||||
|
||||
@@ -18,6 +18,7 @@ public class BrandController : ControllerBase
|
||||
}
|
||||
|
||||
[HttpGet("all")]
|
||||
[EndpointName("getAllBrands")]
|
||||
[EndpointDescription("Retrieves a list of all available brands.")]
|
||||
[EndpointSummary("Get all brands")]
|
||||
public async Task<ActionResult<IEnumerable<BrandType>>> GetAllBrands()
|
||||
@@ -30,6 +31,7 @@ public class BrandController : ControllerBase
|
||||
}
|
||||
|
||||
[HttpGet("state")]
|
||||
[EndpointName("getBrandsByState")]
|
||||
[EndpointDescription("Retrieves a list of all brands by the state they are located in.")]
|
||||
[EndpointSummary("Get brands by state")]
|
||||
public async Task<ActionResult<IEnumerable<BrandType>>> GetBrandsByState([FromQuery] string state)
|
||||
@@ -42,6 +44,7 @@ public class BrandController : ControllerBase
|
||||
}
|
||||
|
||||
[HttpGet("name")]
|
||||
[EndpointName("getBrandsByName")]
|
||||
[EndpointDescription(
|
||||
"Retrieves a list of all available brands, where the brand name contains the provided search string. Case-insensitive.")]
|
||||
[EndpointSummary("Get brands by name")]
|
||||
|
||||
@@ -18,6 +18,7 @@ public class FuelTypeController : ControllerBase
|
||||
}
|
||||
|
||||
[HttpGet("all")]
|
||||
[EndpointName("getAllFuelTypes")]
|
||||
[EndpointDescription("Retrieves a list of all available fuel types.")]
|
||||
[EndpointSummary("Get all fuel types")]
|
||||
public async Task<ActionResult<IEnumerable<FuelType>>> GetAllFuelTypes()
|
||||
@@ -30,6 +31,7 @@ public class FuelTypeController : ControllerBase
|
||||
}
|
||||
|
||||
[HttpGet("common")]
|
||||
[EndpointName("getCommonFuelTypes")]
|
||||
[EndpointDescription("Retrieves a list of the most common fuel types.")]
|
||||
[EndpointSummary("Get common fuel types")]
|
||||
public async Task<ActionResult<IEnumerable<FuelType>>> GetCommonFuelTypes()
|
||||
|
||||
@@ -23,6 +23,7 @@ public class PriceController : ControllerBase
|
||||
}
|
||||
|
||||
[HttpGet("current")]
|
||||
[EndpointName("getAllCurrentPrices")]
|
||||
[EndpointDescription("Retrieves a list of all available prices, with only the most recent displayed.")]
|
||||
[EndpointSummary("Get all most recent prices")]
|
||||
public async Task<ActionResult<Pagination<Price>>> GetAllCurrentPrices(
|
||||
@@ -45,6 +46,7 @@ public class PriceController : ControllerBase
|
||||
}
|
||||
|
||||
[HttpGet("current/station")]
|
||||
[EndpointName("getPricesByStationCode")]
|
||||
[EndpointDescription(
|
||||
"Retrieves a list of all current prices for the station with the code provided. The optional state narrows the lookup to a single state.")]
|
||||
[EndpointSummary("Get current prices by station code")]
|
||||
@@ -72,6 +74,7 @@ public class PriceController : ControllerBase
|
||||
}
|
||||
|
||||
[HttpGet("current/fuel-type")]
|
||||
[EndpointName("getCurrentPricesByFuelType")]
|
||||
[EndpointDescription("Retrieves a list of all most recent prices for the provided fuel type.")]
|
||||
[EndpointSummary("Get all most recent prices by fuel type")]
|
||||
public async Task<ActionResult<Pagination<Price>>> GetCurrentPricesByFuelType(
|
||||
@@ -95,6 +98,7 @@ public class PriceController : ControllerBase
|
||||
}
|
||||
|
||||
[HttpGet("current/fuel-type/lowest")]
|
||||
[EndpointName("getLowestPricesByFuelType")]
|
||||
[EndpointDescription("Retrieves a list of the lowest prices for the provided fuel type.")]
|
||||
[EndpointSummary("Get lowest prices by fuel type")]
|
||||
public async Task<ActionResult<Pagination<Price>>> GetLowestPricesByFuelType(
|
||||
@@ -119,6 +123,7 @@ public class PriceController : ControllerBase
|
||||
}
|
||||
|
||||
[HttpGet("period")]
|
||||
[EndpointName("getPricesForTimePeriod")]
|
||||
[EndpointDescription(
|
||||
"Retrieves a list of prices aggregated by a default time bucket of one day. Time values are UTC, in ISO 8601 format: yyyy-MM-ddTHH:mm:ss.SSSZ")]
|
||||
[EndpointSummary("Get prices for a specific time period")]
|
||||
|
||||
@@ -21,6 +21,7 @@ public class PriceTrendsController : ControllerBase
|
||||
}
|
||||
|
||||
[HttpGet("")]
|
||||
[EndpointName("getDailyPriceAverages")]
|
||||
[EndpointDescription(
|
||||
"Retrieves a list of days, and the average price for that day, within the given period, and for the fuel type specified.")]
|
||||
[EndpointSummary("Get a list of daily price averages")]
|
||||
@@ -40,6 +41,7 @@ public class PriceTrendsController : ControllerBase
|
||||
}
|
||||
|
||||
[HttpGet("within-radius")]
|
||||
[EndpointName("getDailyPriceAveragesWithinRadius")]
|
||||
[EndpointDescription(
|
||||
"Retrieves a list of days, and the average price for that day, within the given period, and for the fuel type and brand specified. Only stations within the given radius are included in the calculations.")]
|
||||
[EndpointSummary("Get a list of daily price averages for stations within a given radius")]
|
||||
@@ -67,6 +69,7 @@ public class PriceTrendsController : ControllerBase
|
||||
}
|
||||
|
||||
[HttpGet("within-suburb")]
|
||||
[EndpointName("getDailyPriceAveragesWithinSuburb")]
|
||||
[EndpointDescription(
|
||||
"Retrieves a list of days, and the average price for that day, within the given period, and for the fuel type specified. Only stations within the specified suburb are included in the calculations.")]
|
||||
[EndpointSummary("Get a list of daily price averages for stations within a suburb")]
|
||||
@@ -91,6 +94,7 @@ public class PriceTrendsController : ControllerBase
|
||||
}
|
||||
|
||||
[HttpGet("station-ids")]
|
||||
[EndpointName("getDailyPriceAveragesByStationIds")]
|
||||
[EndpointDescription(
|
||||
"Retrieves a list of days, and the price averages for the fuel type on that day across the station ids specified, within the given period.")]
|
||||
[EndpointSummary("Get a history of daily prices for the selected stations")]
|
||||
|
||||
@@ -23,6 +23,7 @@ public class StationController : ControllerBase
|
||||
}
|
||||
|
||||
[HttpGet("all")]
|
||||
[EndpointName("getAllStations")]
|
||||
[EndpointDescription("Retrieves a list of all available stations.")]
|
||||
[EndpointSummary("Get all stations")]
|
||||
public async Task<ActionResult<Pagination<Station>>> GetAllStations(
|
||||
@@ -45,6 +46,7 @@ public class StationController : ControllerBase
|
||||
}
|
||||
|
||||
[HttpGet("station-code")]
|
||||
[EndpointName("getStationsByStationCode")]
|
||||
[EndpointDescription(
|
||||
"Retrieves a single station, where the station code is equal to the provided station code. The optional state narrows the lookup to a single state.")]
|
||||
[EndpointSummary("Get a station by station code")]
|
||||
@@ -60,6 +62,7 @@ public class StationController : ControllerBase
|
||||
}
|
||||
|
||||
[HttpGet("within-radius")]
|
||||
[EndpointName("getStationsWithinRadius")]
|
||||
[EndpointDescription(
|
||||
"Retrieves a list of all stations within the area described by a circle with centre at the provided coordinates and a radius of the provided value in metres.")]
|
||||
[EndpointSummary("Get stations within radius")]
|
||||
|
||||
@@ -25,6 +25,7 @@ public class StationWithPricesController : ControllerBase
|
||||
}
|
||||
|
||||
[HttpGet("station-code")]
|
||||
[EndpointName("getStationWithPricesByStationCode")]
|
||||
[EndpointDescription(
|
||||
"Retrieves a single station along with its current prices, where the station code is equal to the provided station code. The optional state narrows the lookup to a single state.")]
|
||||
[EndpointSummary("Get a station with prices by station code")]
|
||||
@@ -41,6 +42,7 @@ public class StationWithPricesController : ControllerBase
|
||||
}
|
||||
|
||||
[HttpGet("within-radius")]
|
||||
[EndpointName("getStationsWithPricesWithinRadius")]
|
||||
[EndpointDescription(
|
||||
"Retrieves a list of all stations within a specified radius of a given location along with their current prices.")]
|
||||
[EndpointSummary("Get stations with prices within radius")]
|
||||
@@ -82,6 +84,7 @@ public class StationWithPricesController : ControllerBase
|
||||
}
|
||||
|
||||
[HttpGet("within-suburb")]
|
||||
[EndpointName("getStationsWithPricesWithinSuburb")]
|
||||
[EndpointDescription(
|
||||
"Retrieves a list of all stations within a specified suburb boundary along with their current prices.")]
|
||||
[EndpointSummary("Get stations with prices within a suburb")]
|
||||
@@ -119,6 +122,7 @@ public class StationWithPricesController : ControllerBase
|
||||
}
|
||||
|
||||
[HttpGet("lowest-prices")]
|
||||
[EndpointName("getStationsWithLowestPricesByFuelType")]
|
||||
[EndpointDescription("Retrieves a list of stations with the lowest prices for a specific fuel type.")]
|
||||
[EndpointSummary("Get stations with lowest prices by fuel type")]
|
||||
public async Task<ActionResult<Pagination<StationWithPrices>>> GetStationsWithLowestPricesByFuelType(
|
||||
@@ -149,6 +153,7 @@ public class StationWithPricesController : ControllerBase
|
||||
}
|
||||
|
||||
[HttpGet("lowest-prices/by-fuel-type/within-radius")]
|
||||
[EndpointName("getStationsWithLowestPricesByFuelTypeWithinRadius")]
|
||||
[EndpointDescription(
|
||||
"Retrieves a list of stations with the lowest prices for a specific fuel type, within the specified radius.")]
|
||||
[EndpointSummary("Get stations with lowest prices by fuel type, within a radius")]
|
||||
@@ -186,6 +191,7 @@ public class StationWithPricesController : ControllerBase
|
||||
}
|
||||
|
||||
[HttpGet("lowest-prices/by-fuel-type/within-suburb")]
|
||||
[EndpointName("getStationsWithLowestPricesByFuelTypeWithinSuburb")]
|
||||
[EndpointDescription(
|
||||
"Retrieves a list of stations with the lowest prices for a specific fuel type, within the specified suburb.")]
|
||||
[EndpointSummary("Get stations with lowest prices by fuel type, within a suburb")]
|
||||
|
||||
@@ -20,6 +20,7 @@ public class SuburbBoundaryController : ControllerBase
|
||||
}
|
||||
|
||||
[HttpGet("suburbs/all")]
|
||||
[EndpointName("getAllSuburbs")]
|
||||
[EndpointDescription(
|
||||
"Retrieves a list of all of the suburbs available. Optionally filtered by state (lowercase code: nsw, vic, wa, act, tas).")]
|
||||
[EndpointSummary("Get the ID, Name, and State for every Suburb in the DB.")]
|
||||
@@ -33,6 +34,7 @@ public class SuburbBoundaryController : ControllerBase
|
||||
}
|
||||
|
||||
[HttpGet("suburbs/by-name")]
|
||||
[EndpointName("getSuburbsByName")]
|
||||
[EndpointDescription(
|
||||
"Retrieves a list of all of the Suburbs that contain the name input. Optionally filtered by state (lowercase code: nsw, vic, wa, act, tas).")]
|
||||
[EndpointSummary("Search for Suburbs in the DB by name")]
|
||||
@@ -47,6 +49,7 @@ public class SuburbBoundaryController : ControllerBase
|
||||
}
|
||||
|
||||
[HttpGet("by-id")]
|
||||
[EndpointName("getSuburbBoundaryById")]
|
||||
[EndpointDescription("Retrieves the single SuburbBoundary, which matches the input ID.")]
|
||||
[EndpointSummary("Return a single SuburbBoundary")]
|
||||
public async Task<ActionResult<SuburbBoundary?>> GetSuburbBoundaryById([FromQuery] string id)
|
||||
@@ -59,6 +62,7 @@ public class SuburbBoundaryController : ControllerBase
|
||||
}
|
||||
|
||||
[HttpGet("for-location")]
|
||||
[EndpointName("getSuburbBoundaryForLocation")]
|
||||
[EndpointDescription(
|
||||
"Retrieves the single SuburbBoundary containing the provided latitude and longitude coordinates.")]
|
||||
[EndpointSummary("Return the SuburbBoundary for a location")]
|
||||
|
||||
@@ -17,9 +17,17 @@ import { useQuery } from "@tanstack/react-query";
|
||||
import dynamic from "next/dynamic";
|
||||
import { useMemo, useState } from "react";
|
||||
|
||||
import { FuelTypeApi, PriceTrendsApi, Suburb, SuburbBoundary } from "../../generated";
|
||||
import {
|
||||
getAllFuelTypes,
|
||||
getDailyPriceAverages,
|
||||
getDailyPriceAveragesWithinRadius,
|
||||
getDailyPriceAveragesWithinSuburb,
|
||||
Suburb,
|
||||
SuburbBoundary,
|
||||
} from "../../generated";
|
||||
import { getAllFuelTypesQueryKey } from "../../generated/@tanstack/react-query.gen";
|
||||
import { LOV_STALE_TIME } from "../../lib/cacheTimes";
|
||||
import { configuration } from "../../lib/api";
|
||||
import { apiClient } from "../../lib/api";
|
||||
import {
|
||||
getErrorStatus,
|
||||
showErrorNotification,
|
||||
@@ -60,9 +68,6 @@ export default function ChartsClient({
|
||||
const theme = useMantineTheme();
|
||||
const isMobile = useMediaQuery(`(max-width: ${theme.breakpoints.lg})`);
|
||||
|
||||
const fuelTypeApi = new FuelTypeApi(configuration);
|
||||
const priceTrendsApi = new PriceTrendsApi(configuration);
|
||||
|
||||
const [selectedFuelType, setSelectedFuelType] = useHydratedPreference(
|
||||
initialFuelType ?? null,
|
||||
GetDefaultFuelType,
|
||||
@@ -85,8 +90,8 @@ export default function ChartsClient({
|
||||
|
||||
async function FetchFuelTypes() {
|
||||
try {
|
||||
const fuelTypeResponse = await fuelTypeApi.apiFuelTypesAllGet();
|
||||
return fuelTypeResponse;
|
||||
const { data } = await getAllFuelTypes({ client: apiClient });
|
||||
return data;
|
||||
} catch (error) {
|
||||
showErrorNotification(error, {
|
||||
message:
|
||||
@@ -97,12 +102,15 @@ export default function ChartsClient({
|
||||
|
||||
async function FetchPriceTrendsAllStations() {
|
||||
try {
|
||||
const priceTrendsResponse = await priceTrendsApi.apiTrendsDailyAveragesGet({
|
||||
startDate: selectedDateTimeRange.startDate ?? undefined,
|
||||
endDate: selectedDateTimeRange.endDate ?? undefined,
|
||||
fuelType: selectedFuelType || "U91",
|
||||
const { data } = await getDailyPriceAverages({
|
||||
query: {
|
||||
startDate: selectedDateTimeRange.startDate?.toISOString(),
|
||||
endDate: selectedDateTimeRange.endDate?.toISOString(),
|
||||
fuelType: selectedFuelType || "U91",
|
||||
},
|
||||
client: apiClient,
|
||||
});
|
||||
return priceTrendsResponse;
|
||||
return data;
|
||||
} catch (error) {
|
||||
showErrorNotification(error, {
|
||||
message:
|
||||
@@ -113,15 +121,18 @@ export default function ChartsClient({
|
||||
|
||||
async function FetchPriceTrendsWithinRadius() {
|
||||
try {
|
||||
const priceTrendsResponse = await priceTrendsApi.apiTrendsDailyAveragesWithinRadiusGet({
|
||||
startDate: selectedDateTimeRange.startDate ?? undefined,
|
||||
endDate: selectedDateTimeRange.endDate ?? undefined,
|
||||
fuelType: selectedFuelType || "U91",
|
||||
latitude: selectedPosition?.lat || GetDefaultLocation().lat,
|
||||
longitude: selectedPosition?.long || GetDefaultLocation().long,
|
||||
radiusInMetres: selectedRadius * 1000,
|
||||
const { data } = await getDailyPriceAveragesWithinRadius({
|
||||
query: {
|
||||
startDate: selectedDateTimeRange.startDate?.toISOString(),
|
||||
endDate: selectedDateTimeRange.endDate?.toISOString(),
|
||||
fuelType: selectedFuelType || "U91",
|
||||
latitude: selectedPosition?.lat || GetDefaultLocation().lat,
|
||||
longitude: selectedPosition?.long || GetDefaultLocation().long,
|
||||
radiusInMetres: selectedRadius * 1000,
|
||||
},
|
||||
client: apiClient,
|
||||
});
|
||||
return priceTrendsResponse;
|
||||
return data;
|
||||
} catch (error) {
|
||||
if (getErrorStatus(error) === 404) {
|
||||
showInfoNotification({
|
||||
@@ -141,13 +152,16 @@ export default function ChartsClient({
|
||||
async function FetchPriceTrendsWithinSuburb() {
|
||||
if (!selectedSuburb?.id) return null;
|
||||
try {
|
||||
const response = await priceTrendsApi.apiTrendsDailyAveragesWithinSuburbGet({
|
||||
suburbId: selectedSuburb.id,
|
||||
startDate: selectedDateTimeRange.startDate ?? undefined,
|
||||
endDate: selectedDateTimeRange.endDate ?? undefined,
|
||||
fuelType: selectedFuelType || "U91",
|
||||
const { data } = await getDailyPriceAveragesWithinSuburb({
|
||||
query: {
|
||||
suburbId: selectedSuburb.id,
|
||||
startDate: selectedDateTimeRange.startDate?.toISOString(),
|
||||
endDate: selectedDateTimeRange.endDate?.toISOString(),
|
||||
fuelType: selectedFuelType || "U91",
|
||||
},
|
||||
client: apiClient,
|
||||
});
|
||||
return response;
|
||||
return data;
|
||||
} catch (error) {
|
||||
if (getErrorStatus(error) === 404) {
|
||||
showInfoNotification({
|
||||
@@ -169,7 +183,7 @@ export default function ChartsClient({
|
||||
};
|
||||
|
||||
const fuelTypesQuery = useQuery({
|
||||
queryKey: ["chartsPageFuelTypes"],
|
||||
queryKey: getAllFuelTypesQueryKey({ client: apiClient }),
|
||||
queryFn: FetchFuelTypes,
|
||||
staleTime: LOV_STALE_TIME,
|
||||
});
|
||||
@@ -186,7 +200,7 @@ export default function ChartsClient({
|
||||
const allStationsChartData = useMemo(
|
||||
() =>
|
||||
priceTrendsQueryAllStations.data?.dailyAverages?.map((dpa) => ({
|
||||
date: dpa.date,
|
||||
date: dpa.date ? new Date(dpa.date) : undefined,
|
||||
averagePriceValue: dpa.averagePriceValue as number,
|
||||
})),
|
||||
[priceTrendsQueryAllStations.data],
|
||||
@@ -195,7 +209,7 @@ export default function ChartsClient({
|
||||
const withinRadiusChartData = useMemo(
|
||||
() =>
|
||||
priceTrendsQueryWithinRadius.data?.dailyAverages?.map((dpa) => ({
|
||||
date: dpa.date,
|
||||
date: dpa.date ? new Date(dpa.date) : undefined,
|
||||
averagePriceValue: dpa.averagePriceValue as number,
|
||||
})),
|
||||
[priceTrendsQueryWithinRadius.data],
|
||||
|
||||
@@ -3,12 +3,32 @@ import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { priceTrendsFixture, suburbsFixture, suburbBoundaryFixture } from "../../test/fixtures";
|
||||
import { renderWithProviders, screen, waitFor } from "../../test/utils";
|
||||
|
||||
const {
|
||||
getAllFuelTypesMock,
|
||||
getDailyPriceAveragesMock,
|
||||
getDailyPriceAveragesWithinRadiusMock,
|
||||
getDailyPriceAveragesWithinSuburbMock,
|
||||
getSuburbsByNameMock,
|
||||
getSuburbBoundaryByIdMock,
|
||||
} = vi.hoisted(() => ({
|
||||
getAllFuelTypesMock: vi.fn(),
|
||||
getDailyPriceAveragesMock: vi.fn(),
|
||||
getDailyPriceAveragesWithinRadiusMock: vi.fn(),
|
||||
getDailyPriceAveragesWithinSuburbMock: vi.fn(),
|
||||
getSuburbsByNameMock: vi.fn(),
|
||||
getSuburbBoundaryByIdMock: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("../../generated", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("../../generated")>();
|
||||
const { apiClassMocks } = await import("../../test/mocks");
|
||||
return {
|
||||
...actual,
|
||||
...apiClassMocks(["FuelTypeApi", "PriceTrendsApi", "SuburbBoundaryApi"]),
|
||||
getAllFuelTypes: getAllFuelTypesMock,
|
||||
getDailyPriceAverages: getDailyPriceAveragesMock,
|
||||
getDailyPriceAveragesWithinRadius: getDailyPriceAveragesWithinRadiusMock,
|
||||
getDailyPriceAveragesWithinSuburb: getDailyPriceAveragesWithinSuburbMock,
|
||||
getSuburbsByName: getSuburbsByNameMock,
|
||||
getSuburbBoundaryById: getSuburbBoundaryByIdMock,
|
||||
} as typeof actual;
|
||||
});
|
||||
|
||||
@@ -21,74 +41,47 @@ vi.mock("next/cache", () => ({ cacheLife: vi.fn() }));
|
||||
vi.mock("next/headers", () => ({ cookies: vi.fn() }));
|
||||
vi.mock("next/server", () => ({ connection: vi.fn() }));
|
||||
|
||||
import { FuelTypeApi, PriceTrendsApi, SuburbBoundaryApi } from "../../generated";
|
||||
import { cookies } from "next/headers";
|
||||
import { connection } from "next/server";
|
||||
import { SetHomeSuburb } from "../../utils/userPreferencesUtils";
|
||||
import ChartsClient from "./ChartsClient";
|
||||
import ChartsPage from "./page";
|
||||
|
||||
const fuelTypeApiMock = vi.mocked(FuelTypeApi);
|
||||
const priceTrendsApiMock = vi.mocked(PriceTrendsApi);
|
||||
const suburbBoundaryApiMock = vi.mocked(SuburbBoundaryApi);
|
||||
|
||||
const apiFuelTypesAllGet = vi.fn();
|
||||
const apiTrendsDailyAveragesGet = vi.fn();
|
||||
const apiTrendsDailyAveragesWithinRadiusGet = vi.fn();
|
||||
const apiTrendsDailyAveragesWithinSuburbGet = vi.fn();
|
||||
const apiSuburbBoundariesSuburbsByNameGet = vi.fn();
|
||||
const apiSuburbBoundariesByIdGet = vi.fn();
|
||||
|
||||
beforeEach(() => {
|
||||
localStorage.clear();
|
||||
apiFuelTypesAllGet.mockResolvedValue([{ code: "U91", name: "Unleaded 91" }]);
|
||||
apiTrendsDailyAveragesGet.mockResolvedValue(priceTrendsFixture());
|
||||
apiTrendsDailyAveragesWithinRadiusGet.mockResolvedValue(priceTrendsFixture());
|
||||
apiTrendsDailyAveragesWithinSuburbGet.mockResolvedValue(priceTrendsFixture());
|
||||
apiSuburbBoundariesSuburbsByNameGet.mockResolvedValue(suburbsFixture);
|
||||
apiSuburbBoundariesByIdGet.mockResolvedValue(suburbBoundaryFixture);
|
||||
|
||||
fuelTypeApiMock.mockImplementation(
|
||||
class {
|
||||
apiFuelTypesAllGet = apiFuelTypesAllGet;
|
||||
} as unknown as typeof FuelTypeApi,
|
||||
);
|
||||
priceTrendsApiMock.mockImplementation(
|
||||
class {
|
||||
apiTrendsDailyAveragesGet = apiTrendsDailyAveragesGet;
|
||||
apiTrendsDailyAveragesWithinRadiusGet = apiTrendsDailyAveragesWithinRadiusGet;
|
||||
apiTrendsDailyAveragesWithinSuburbGet = apiTrendsDailyAveragesWithinSuburbGet;
|
||||
} as unknown as typeof PriceTrendsApi,
|
||||
);
|
||||
suburbBoundaryApiMock.mockImplementation(
|
||||
class {
|
||||
apiSuburbBoundariesSuburbsByNameGet = apiSuburbBoundariesSuburbsByNameGet;
|
||||
apiSuburbBoundariesByIdGet = apiSuburbBoundariesByIdGet;
|
||||
} as unknown as typeof SuburbBoundaryApi,
|
||||
);
|
||||
getAllFuelTypesMock.mockResolvedValue({ data: [{ code: "U91", name: "Unleaded 91" }] });
|
||||
getDailyPriceAveragesMock.mockResolvedValue({ data: priceTrendsFixture() });
|
||||
getDailyPriceAveragesWithinRadiusMock.mockResolvedValue({ data: priceTrendsFixture() });
|
||||
getDailyPriceAveragesWithinSuburbMock.mockResolvedValue({ data: priceTrendsFixture() });
|
||||
getSuburbsByNameMock.mockResolvedValue({ data: suburbsFixture });
|
||||
getSuburbBoundaryByIdMock.mockResolvedValue({ data: suburbBoundaryFixture });
|
||||
});
|
||||
|
||||
describe("ChartsPage", () => {
|
||||
it("fetches fuel types and both trend queries on mount", async () => {
|
||||
renderWithProviders(<ChartsClient />);
|
||||
|
||||
await waitFor(() => expect(apiFuelTypesAllGet).toHaveBeenCalledTimes(1));
|
||||
await waitFor(() => expect(getAllFuelTypesMock).toHaveBeenCalledTimes(1));
|
||||
await waitFor(() =>
|
||||
expect(apiTrendsDailyAveragesGet).toHaveBeenCalledWith(
|
||||
expect(getDailyPriceAveragesMock).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
fuelType: "U91",
|
||||
startDate: expect.any(Date),
|
||||
endDate: expect.any(Date),
|
||||
query: expect.objectContaining({
|
||||
fuelType: "U91",
|
||||
startDate: expect.any(String),
|
||||
endDate: expect.any(String),
|
||||
}),
|
||||
}),
|
||||
),
|
||||
);
|
||||
await waitFor(() =>
|
||||
expect(apiTrendsDailyAveragesWithinRadiusGet).toHaveBeenCalledWith(
|
||||
expect(getDailyPriceAveragesWithinRadiusMock).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
fuelType: "U91",
|
||||
radiusInMetres: 10000,
|
||||
latitude: -33.856758,
|
||||
longitude: 151.215295,
|
||||
query: expect.objectContaining({
|
||||
fuelType: "U91",
|
||||
radiusInMetres: 10000,
|
||||
latitude: -33.856758,
|
||||
longitude: 151.215295,
|
||||
}),
|
||||
}),
|
||||
),
|
||||
);
|
||||
@@ -101,17 +94,17 @@ describe("ChartsPage", () => {
|
||||
const user = userEvent.setup();
|
||||
renderWithProviders(<ChartsClient />);
|
||||
|
||||
await waitFor(() => expect(apiTrendsDailyAveragesGet).toHaveBeenCalledTimes(1));
|
||||
await waitFor(() => expect(getDailyPriceAveragesMock).toHaveBeenCalledTimes(1));
|
||||
|
||||
await user.click(screen.getByRole("button", { name: "Apply" }));
|
||||
|
||||
await waitFor(() => expect(apiTrendsDailyAveragesGet).toHaveBeenCalledTimes(2));
|
||||
await waitFor(() => expect(apiTrendsDailyAveragesWithinRadiusGet).toHaveBeenCalledTimes(2));
|
||||
await waitFor(() => expect(getDailyPriceAveragesMock).toHaveBeenCalledTimes(2));
|
||||
await waitFor(() => expect(getDailyPriceAveragesWithinRadiusMock).toHaveBeenCalledTimes(2));
|
||||
});
|
||||
|
||||
it("fetches suburb trends and warns on 404", async () => {
|
||||
SetHomeSuburb({ id: "syd", name: "Sydney" });
|
||||
apiTrendsDailyAveragesWithinSuburbGet.mockRejectedValue({
|
||||
getDailyPriceAveragesWithinSuburbMock.mockRejectedValue({
|
||||
response: { status: 404 },
|
||||
});
|
||||
|
||||
@@ -121,8 +114,8 @@ describe("ChartsPage", () => {
|
||||
await user.click(screen.getByText("Suburb"));
|
||||
|
||||
await waitFor(() =>
|
||||
expect(apiTrendsDailyAveragesWithinSuburbGet).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ suburbId: "syd" }),
|
||||
expect(getDailyPriceAveragesWithinSuburbMock).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ query: expect.objectContaining({ suburbId: "syd" }) }),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -151,38 +144,42 @@ describe("ChartsPage (server prefetch)", () => {
|
||||
renderWithProviders(<>{await ChartsPage()}</>);
|
||||
|
||||
await waitFor(() =>
|
||||
expect(apiTrendsDailyAveragesGet).toHaveBeenCalledWith(
|
||||
expect(getDailyPriceAveragesMock).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
fuelType: "P98",
|
||||
startDate: expect.any(Date),
|
||||
endDate: expect.any(Date),
|
||||
query: expect.objectContaining({
|
||||
fuelType: "P98",
|
||||
startDate: expect.any(String),
|
||||
endDate: expect.any(String),
|
||||
}),
|
||||
}),
|
||||
),
|
||||
);
|
||||
await waitFor(() =>
|
||||
expect(apiTrendsDailyAveragesWithinRadiusGet).toHaveBeenCalledWith(
|
||||
expect(getDailyPriceAveragesWithinRadiusMock).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
fuelType: "P98",
|
||||
radiusInMetres: 10000,
|
||||
latitude: -33.856758,
|
||||
longitude: 151.215295,
|
||||
query: expect.objectContaining({
|
||||
fuelType: "P98",
|
||||
radiusInMetres: 10000,
|
||||
latitude: -33.856758,
|
||||
longitude: 151.215295,
|
||||
}),
|
||||
}),
|
||||
),
|
||||
);
|
||||
expect(apiFuelTypesAllGet).toHaveBeenCalled();
|
||||
expect(getAllFuelTypesMock).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("falls back to U91 when no preferences cookie exists", async () => {
|
||||
renderWithProviders(<>{await ChartsPage()}</>);
|
||||
|
||||
await waitFor(() =>
|
||||
expect(apiTrendsDailyAveragesGet).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ fuelType: "U91" }),
|
||||
expect(getDailyPriceAveragesMock).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ query: expect.objectContaining({ fuelType: "U91" }) }),
|
||||
),
|
||||
);
|
||||
await waitFor(() =>
|
||||
expect(apiTrendsDailyAveragesWithinRadiusGet).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ fuelType: "U91" }),
|
||||
expect(getDailyPriceAveragesWithinRadiusMock).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ query: expect.objectContaining({ fuelType: "U91" }) }),
|
||||
),
|
||||
);
|
||||
});
|
||||
@@ -202,17 +199,21 @@ describe("ChartsPage (server prefetch)", () => {
|
||||
renderWithProviders(<>{await ChartsPage()}</>);
|
||||
|
||||
await waitFor(() =>
|
||||
expect(apiTrendsDailyAveragesWithinRadiusGet).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ latitude: -33.87, longitude: 151.2 }),
|
||||
expect(getDailyPriceAveragesWithinRadiusMock).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
query: expect.objectContaining({ latitude: -33.87, longitude: 151.2 }),
|
||||
}),
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
it("passes the cookie fuel type to ChartsClient so the select matches the server HTML", async () => {
|
||||
apiFuelTypesAllGet.mockResolvedValue([
|
||||
{ code: "U91", name: "Unleaded 91" },
|
||||
{ code: "P98", name: "Premium 98" },
|
||||
]);
|
||||
getAllFuelTypesMock.mockResolvedValue({
|
||||
data: [
|
||||
{ code: "U91", name: "Unleaded 91" },
|
||||
{ code: "P98", name: "Premium 98" },
|
||||
],
|
||||
});
|
||||
cookiesMock.mockResolvedValue({
|
||||
get: (name: string) =>
|
||||
name === "fw-preferences"
|
||||
@@ -241,6 +242,10 @@ describe("ChartsPage (server prefetch)", () => {
|
||||
|
||||
renderWithProviders(<>{await ChartsPage()}</>);
|
||||
|
||||
await waitFor(() => expect(apiSuburbBoundariesByIdGet).toHaveBeenCalledWith({ id: "syd" }));
|
||||
await waitFor(() =>
|
||||
expect(getSuburbBoundaryByIdMock).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ query: { id: "syd" } }),
|
||||
),
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -1,6 +1,11 @@
|
||||
import { HydrationBoundary, QueryClient, dehydrate } from "@tanstack/react-query";
|
||||
import { cookies } from "next/headers";
|
||||
import { connection } from "next/server";
|
||||
import {
|
||||
getAllFuelTypesQueryKey,
|
||||
getSuburbBoundaryByIdQueryKey,
|
||||
} from "../../generated/@tanstack/react-query.gen";
|
||||
import { serverClient } from "../../lib/api.server";
|
||||
import {
|
||||
getDailyAverages,
|
||||
getDailyAveragesWithinRadius,
|
||||
@@ -29,7 +34,7 @@ export default async function ChartsPage() {
|
||||
|
||||
await Promise.all([
|
||||
queryClient.fetchQuery({
|
||||
queryKey: ["chartsPageFuelTypes"],
|
||||
queryKey: getAllFuelTypesQueryKey({ client: serverClient }),
|
||||
queryFn: getFuelTypes,
|
||||
retry: false,
|
||||
}),
|
||||
@@ -63,7 +68,10 @@ export default async function ChartsPage() {
|
||||
const homeSuburbId = prefs.homeSuburb?.id;
|
||||
if (homeSuburbId) {
|
||||
await queryClient.fetchQuery({
|
||||
queryKey: ["suburbBoundary", homeSuburbId],
|
||||
queryKey: getSuburbBoundaryByIdQueryKey({
|
||||
query: { id: homeSuburbId },
|
||||
client: serverClient,
|
||||
}),
|
||||
queryFn: () => getSuburbBoundaryById(homeSuburbId),
|
||||
retry: false,
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { screen } from "@testing-library/react";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { ResponseError } from "../../generated";
|
||||
import { ApiError } from "../../lib/apiError";
|
||||
import { renderWithProviders } from "../../test/utils";
|
||||
import ErrorPage from "./ErrorPage";
|
||||
|
||||
@@ -21,7 +21,7 @@ describe("ErrorPage", () => {
|
||||
});
|
||||
|
||||
it("shows rate-limit copy and orange alert for a 429 error", () => {
|
||||
const error = new ResponseError({ status: 429 } as Response, "too many requests");
|
||||
const error = new ApiError({ status: 429 } as Response, "too many requests");
|
||||
renderWithProviders(<ErrorPage error={error} reset={vi.fn()} />);
|
||||
|
||||
expect(screen.getByText("Too many requests")).toBeInTheDocument();
|
||||
|
||||
@@ -3,37 +3,34 @@ import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { fuelTypesFixture } from "../../../test/fixtures";
|
||||
import { renderWithProviders, screen, waitFor } from "../../../test/utils";
|
||||
|
||||
const { getCommonFuelTypesMock, getAllFuelTypesMock } = vi.hoisted(() => ({
|
||||
getCommonFuelTypesMock: vi.fn(),
|
||||
getAllFuelTypesMock: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("../../../generated", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("../../../generated")>();
|
||||
const { apiClassMocks } = await import("../../../test/mocks");
|
||||
return { ...actual, ...apiClassMocks(["FuelTypeApi"]) } as typeof actual;
|
||||
return {
|
||||
...actual,
|
||||
getCommonFuelTypes: getCommonFuelTypesMock,
|
||||
getAllFuelTypes: getAllFuelTypesMock,
|
||||
} as typeof actual;
|
||||
});
|
||||
|
||||
import { FuelTypeApi } from "../../../generated";
|
||||
import { GetDefaultFuelType, SetDefaultFuelType } from "../../../utils/userPreferencesUtils";
|
||||
import FuelTypeSelect from "./FuelTypeSelect";
|
||||
|
||||
const fuelTypeApiMock = vi.mocked(FuelTypeApi);
|
||||
const apiFuelTypesCommonGet = vi.fn();
|
||||
const apiFuelTypesAllGet = vi.fn();
|
||||
|
||||
beforeEach(() => {
|
||||
apiFuelTypesCommonGet.mockResolvedValue(fuelTypesFixture);
|
||||
apiFuelTypesAllGet.mockResolvedValue(fuelTypesFixture);
|
||||
fuelTypeApiMock.mockImplementation(
|
||||
class {
|
||||
apiFuelTypesCommonGet = apiFuelTypesCommonGet;
|
||||
apiFuelTypesAllGet = apiFuelTypesAllGet;
|
||||
} as unknown as typeof FuelTypeApi,
|
||||
);
|
||||
getCommonFuelTypesMock.mockResolvedValue({ data: fuelTypesFixture });
|
||||
getAllFuelTypesMock.mockResolvedValue({ data: fuelTypesFixture });
|
||||
});
|
||||
|
||||
describe("FuelTypeSelect", () => {
|
||||
it("loads the common fuel types on mount", async () => {
|
||||
renderWithProviders(<FuelTypeSelect />);
|
||||
|
||||
await waitFor(() => expect(apiFuelTypesCommonGet).toHaveBeenCalledTimes(1));
|
||||
expect(apiFuelTypesAllGet).not.toHaveBeenCalled();
|
||||
await waitFor(() => expect(getCommonFuelTypesMock).toHaveBeenCalledTimes(1));
|
||||
expect(getAllFuelTypesMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("selecting a fuel type persists it to the preferences cookie", async () => {
|
||||
@@ -57,7 +54,7 @@ describe("FuelTypeSelect", () => {
|
||||
await user.click(screen.getByPlaceholderText("Default fuel type"));
|
||||
await user.click(await screen.findByText("See More"));
|
||||
|
||||
await waitFor(() => expect(apiFuelTypesAllGet).toHaveBeenCalledTimes(1));
|
||||
await waitFor(() => expect(getAllFuelTypesMock).toHaveBeenCalledTimes(1));
|
||||
});
|
||||
|
||||
it("starts with the stored default fuel type", async () => {
|
||||
|
||||
@@ -5,8 +5,12 @@ import { Badge, Group, Select, Stack, useCombobox, useMantineTheme } from "@mant
|
||||
import { useMediaQuery } from "@mantine/hooks";
|
||||
import { useState } from "react";
|
||||
import { FaAnglesDown } from "react-icons/fa6";
|
||||
import { FuelTypeApi } from "../../../generated";
|
||||
import { configuration } from "../../../lib/api";
|
||||
import { getAllFuelTypes, getCommonFuelTypes } from "../../../generated";
|
||||
import {
|
||||
getAllFuelTypesQueryKey,
|
||||
getCommonFuelTypesQueryKey,
|
||||
} from "../../../generated/@tanstack/react-query.gen";
|
||||
import { apiClient } from "../../../lib/api";
|
||||
import { LOV_STALE_TIME } from "../../../lib/cacheTimes";
|
||||
import { showErrorNotification } from "../../../lib/notifications";
|
||||
import { fuelTypeColours } from "../../../utils/fuelTypeUtils";
|
||||
@@ -19,8 +23,6 @@ type FuelTypeSelectProps = {
|
||||
};
|
||||
|
||||
export default function FuelTypeSelect(props: FuelTypeSelectProps) {
|
||||
const fuelTypeApi = new FuelTypeApi(configuration);
|
||||
|
||||
const theme = useMantineTheme();
|
||||
const isMobile = useMediaQuery(`(max-width: ${theme.breakpoints.lg})`);
|
||||
const [selectedFuelType, setSelectedFuelType] = useState<string | null>(GetDefaultFuelType());
|
||||
@@ -29,7 +31,8 @@ export default function FuelTypeSelect(props: FuelTypeSelectProps) {
|
||||
|
||||
async function FetchCommonFuelTypes() {
|
||||
try {
|
||||
return await fuelTypeApi.apiFuelTypesCommonGet();
|
||||
const { data } = await getCommonFuelTypes({ client: apiClient });
|
||||
return data;
|
||||
} catch (error) {
|
||||
showErrorNotification(error, {
|
||||
message:
|
||||
@@ -40,7 +43,8 @@ export default function FuelTypeSelect(props: FuelTypeSelectProps) {
|
||||
|
||||
async function FetchAllFuelTypes() {
|
||||
try {
|
||||
return await fuelTypeApi.apiFuelTypesAllGet();
|
||||
const { data } = await getAllFuelTypes({ client: apiClient });
|
||||
return data;
|
||||
} catch (error) {
|
||||
showErrorNotification(error, {
|
||||
message:
|
||||
@@ -50,12 +54,12 @@ export default function FuelTypeSelect(props: FuelTypeSelectProps) {
|
||||
}
|
||||
|
||||
const commonFuelTypesQuery = useQuery({
|
||||
queryKey: ["fuelTypesCommon"],
|
||||
queryKey: getCommonFuelTypesQueryKey({ client: apiClient }),
|
||||
queryFn: FetchCommonFuelTypes,
|
||||
staleTime: LOV_STALE_TIME,
|
||||
});
|
||||
const allFuelTypesQuery = useQuery({
|
||||
queryKey: ["fuelTypesAll"],
|
||||
queryKey: getAllFuelTypesQueryKey({ client: apiClient }),
|
||||
queryFn: FetchAllFuelTypes,
|
||||
enabled: seeMoreClicked,
|
||||
staleTime: LOV_STALE_TIME,
|
||||
|
||||
@@ -3,10 +3,18 @@ import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { suburbBoundaryFixture } from "../../../test/fixtures";
|
||||
import { renderWithProviders, screen, waitFor } from "../../../test/utils";
|
||||
|
||||
const { getSuburbBoundaryForLocationMock, getSuburbBoundaryByIdMock } = vi.hoisted(() => ({
|
||||
getSuburbBoundaryForLocationMock: vi.fn(),
|
||||
getSuburbBoundaryByIdMock: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("../../../generated", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("../../../generated")>();
|
||||
const { apiClassMocks } = await import("../../../test/mocks");
|
||||
return { ...actual, ...apiClassMocks(["SuburbBoundaryApi"]) } as typeof actual;
|
||||
return {
|
||||
...actual,
|
||||
getSuburbBoundaryForLocation: getSuburbBoundaryForLocationMock,
|
||||
getSuburbBoundaryById: getSuburbBoundaryByIdMock,
|
||||
} as typeof actual;
|
||||
});
|
||||
|
||||
vi.mock("./CustomMap", () => ({
|
||||
@@ -17,23 +25,14 @@ vi.mock("./CustomMap", () => ({
|
||||
),
|
||||
}));
|
||||
|
||||
import { SuburbBoundaryApi } from "../../../generated";
|
||||
import { GetHomeSuburb, SetHomeSuburb } from "../../../utils/userPreferencesUtils";
|
||||
import LocationSelectModal from "./LocationSelectModal";
|
||||
|
||||
const suburbBoundaryApiMock = vi.mocked(SuburbBoundaryApi);
|
||||
const apiSuburbBoundariesForLocationGet = vi.fn();
|
||||
const apiSuburbBoundariesByIdGet = vi.fn();
|
||||
|
||||
beforeEach(() => {
|
||||
apiSuburbBoundariesForLocationGet.mockResolvedValue({ id: "syd", name: "Sydney", state: "nsw" });
|
||||
apiSuburbBoundariesByIdGet.mockResolvedValue(suburbBoundaryFixture);
|
||||
suburbBoundaryApiMock.mockImplementation(
|
||||
class {
|
||||
apiSuburbBoundariesForLocationGet = apiSuburbBoundariesForLocationGet;
|
||||
apiSuburbBoundariesByIdGet = apiSuburbBoundariesByIdGet;
|
||||
} as unknown as typeof SuburbBoundaryApi,
|
||||
);
|
||||
getSuburbBoundaryForLocationMock.mockResolvedValue({
|
||||
data: { id: "syd", name: "Sydney", state: "nsw" },
|
||||
});
|
||||
getSuburbBoundaryByIdMock.mockResolvedValue({ data: suburbBoundaryFixture });
|
||||
});
|
||||
|
||||
describe("LocationSelectModal", () => {
|
||||
@@ -54,10 +53,9 @@ describe("LocationSelectModal", () => {
|
||||
await user.click(screen.getByRole("button", { name: "mock-map-click" }));
|
||||
|
||||
await waitFor(() =>
|
||||
expect(apiSuburbBoundariesForLocationGet).toHaveBeenCalledWith({
|
||||
latitude: -33.8,
|
||||
longitude: 151.2,
|
||||
}),
|
||||
expect(getSuburbBoundaryForLocationMock).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ query: { latitude: -33.8, longitude: 151.2 } }),
|
||||
),
|
||||
);
|
||||
|
||||
await user.click(screen.getByRole("button", { name: "Confirm" }));
|
||||
@@ -69,7 +67,7 @@ describe("LocationSelectModal", () => {
|
||||
|
||||
it("clears the stored suburb when no suburb is inferred", async () => {
|
||||
SetHomeSuburb({ id: "old", name: "Old" });
|
||||
apiSuburbBoundariesForLocationGet.mockResolvedValue({});
|
||||
getSuburbBoundaryForLocationMock.mockResolvedValue({ data: {} });
|
||||
|
||||
const user = userEvent.setup();
|
||||
const onSelect = vi.fn();
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
import { Box, Button, Modal } from "@mantine/core";
|
||||
import dynamic from "next/dynamic";
|
||||
import { useState } from "react";
|
||||
import { Suburb, SuburbBoundary, SuburbBoundaryApi } from "../../../generated";
|
||||
import { configuration } from "../../../lib/api";
|
||||
import { getSuburbBoundaryForLocation, Suburb, SuburbBoundary } from "../../../generated";
|
||||
import { apiClient } from "../../../lib/api";
|
||||
import { Coordinate } from "../../../models/Coordinate";
|
||||
import { SetHomeSuburb } from "../../../utils/userPreferencesUtils";
|
||||
import SuburbSelect from "./SuburbSelect";
|
||||
@@ -21,7 +21,6 @@ type LocationSelectModalProps = {
|
||||
};
|
||||
|
||||
export default function LocationSelectModal(props: LocationSelectModalProps) {
|
||||
const suburbBoundaryApi = new SuburbBoundaryApi(configuration);
|
||||
const [selectedPosition, setSelectedPosition] = useState<{
|
||||
lat: number;
|
||||
long: number;
|
||||
@@ -30,9 +29,11 @@ export default function LocationSelectModal(props: LocationSelectModalProps) {
|
||||
const [suburb, setSuburb] = useState<Suburb>();
|
||||
|
||||
const inferSuburb = (coordinates: { lat: number; long: number }) => {
|
||||
suburbBoundaryApi
|
||||
.apiSuburbBoundariesForLocationGet({ latitude: coordinates.lat, longitude: coordinates.long })
|
||||
.then((boundary) => {
|
||||
getSuburbBoundaryForLocation({
|
||||
query: { latitude: coordinates.lat, longitude: coordinates.long },
|
||||
client: apiClient,
|
||||
})
|
||||
.then(({ data: boundary }) => {
|
||||
if (boundary.id && boundary.name) {
|
||||
setSuburb({ id: boundary.id, name: boundary.name, state: boundary.state });
|
||||
}
|
||||
|
||||
@@ -3,28 +3,25 @@ import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { suburbsFixture, suburbBoundaryFixture } from "../../../test/fixtures";
|
||||
import { renderWithProviders, screen, waitFor } from "../../../test/utils";
|
||||
|
||||
const { getSuburbsByNameMock, getSuburbBoundaryByIdMock } = vi.hoisted(() => ({
|
||||
getSuburbsByNameMock: vi.fn(),
|
||||
getSuburbBoundaryByIdMock: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("../../../generated", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("../../../generated")>();
|
||||
const { apiClassMocks } = await import("../../../test/mocks");
|
||||
return { ...actual, ...apiClassMocks(["SuburbBoundaryApi"]) } as typeof actual;
|
||||
return {
|
||||
...actual,
|
||||
getSuburbsByName: getSuburbsByNameMock,
|
||||
getSuburbBoundaryById: getSuburbBoundaryByIdMock,
|
||||
} as typeof actual;
|
||||
});
|
||||
|
||||
import { SuburbBoundaryApi } from "../../../generated";
|
||||
import SuburbSelect from "./SuburbSelect";
|
||||
|
||||
const suburbBoundaryApiMock = vi.mocked(SuburbBoundaryApi);
|
||||
const apiSuburbBoundariesSuburbsByNameGet = vi.fn();
|
||||
const apiSuburbBoundariesByIdGet = vi.fn();
|
||||
|
||||
beforeEach(() => {
|
||||
apiSuburbBoundariesSuburbsByNameGet.mockResolvedValue(suburbsFixture);
|
||||
apiSuburbBoundariesByIdGet.mockResolvedValue(suburbBoundaryFixture);
|
||||
suburbBoundaryApiMock.mockImplementation(
|
||||
class {
|
||||
apiSuburbBoundariesSuburbsByNameGet = apiSuburbBoundariesSuburbsByNameGet;
|
||||
apiSuburbBoundariesByIdGet = apiSuburbBoundariesByIdGet;
|
||||
} as unknown as typeof SuburbBoundaryApi,
|
||||
);
|
||||
getSuburbsByNameMock.mockResolvedValue({ data: suburbsFixture });
|
||||
getSuburbBoundaryByIdMock.mockResolvedValue({ data: suburbBoundaryFixture });
|
||||
});
|
||||
|
||||
describe("SuburbSelect", () => {
|
||||
@@ -38,7 +35,10 @@ describe("SuburbSelect", () => {
|
||||
await user.type(screen.getByPlaceholderText("Enter a suburb name"), "syd");
|
||||
|
||||
await waitFor(
|
||||
() => expect(apiSuburbBoundariesSuburbsByNameGet).toHaveBeenCalledWith({ name: "syd" }),
|
||||
() =>
|
||||
expect(getSuburbsByNameMock).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ query: { name: "syd" } }),
|
||||
),
|
||||
{ timeout: 3000 },
|
||||
);
|
||||
|
||||
@@ -55,20 +55,24 @@ describe("SuburbSelect", () => {
|
||||
|
||||
rerender(<SuburbSelect value="syd" onSelect={() => {}} onBoundary={onBoundary} />);
|
||||
|
||||
await waitFor(() => expect(apiSuburbBoundariesByIdGet).toHaveBeenCalledWith({ id: "syd" }));
|
||||
await waitFor(() =>
|
||||
expect(getSuburbBoundaryByIdMock).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ query: { id: "syd" } }),
|
||||
),
|
||||
);
|
||||
await waitFor(() => expect(onBoundary).toHaveBeenCalledWith(suburbBoundaryFixture));
|
||||
});
|
||||
|
||||
it("does not search while the query is empty", async () => {
|
||||
renderWithProviders(<SuburbSelect value={null} onSelect={() => {}} onBoundary={() => {}} />);
|
||||
|
||||
await waitFor(() => expect(apiSuburbBoundariesSuburbsByNameGet).not.toHaveBeenCalled(), {
|
||||
await waitFor(() => expect(getSuburbsByNameMock).not.toHaveBeenCalled(), {
|
||||
timeout: 1500,
|
||||
});
|
||||
});
|
||||
|
||||
it("clears the boundary and notifies on fetch error", async () => {
|
||||
apiSuburbBoundariesByIdGet.mockRejectedValue(new Error("boom"));
|
||||
getSuburbBoundaryByIdMock.mockRejectedValue(new Error("boom"));
|
||||
const onBoundary = vi.fn();
|
||||
|
||||
const { rerender } = renderWithProviders(
|
||||
@@ -85,10 +89,12 @@ describe("SuburbSelect", () => {
|
||||
|
||||
it("shows the state name as a description under duplicate options", async () => {
|
||||
const user = userEvent.setup();
|
||||
apiSuburbBoundariesSuburbsByNameGet.mockResolvedValue([
|
||||
{ id: "ascot-vic", name: "Ascot", state: "vic" },
|
||||
{ id: "ascot-wa", name: "Ascot", state: "wa" },
|
||||
]);
|
||||
getSuburbsByNameMock.mockResolvedValue({
|
||||
data: [
|
||||
{ id: "ascot-vic", name: "Ascot", state: "vic" },
|
||||
{ id: "ascot-wa", name: "Ascot", state: "wa" },
|
||||
],
|
||||
});
|
||||
|
||||
renderWithProviders(<SuburbSelect value={null} onSelect={vi.fn()} onBoundary={vi.fn()} />);
|
||||
await user.type(screen.getByPlaceholderText("Enter a suburb name"), "Ascot");
|
||||
|
||||
@@ -6,8 +6,14 @@ import { useQuery } from "@tanstack/react-query";
|
||||
import { useEffect, useMemo, useRef, useState } from "react";
|
||||
import { FaCheck } from "react-icons/fa6";
|
||||
import { LOV_STALE_TIME } from "../../../lib/cacheTimes";
|
||||
import { Suburb, SuburbBoundary, SuburbBoundaryApi } from "../../../generated";
|
||||
import { configuration } from "../../../lib/api";
|
||||
import {
|
||||
getSuburbsByName,
|
||||
getSuburbBoundaryById,
|
||||
Suburb,
|
||||
SuburbBoundary,
|
||||
} from "../../../generated";
|
||||
import { getSuburbBoundaryByIdQueryKey } from "../../../generated/@tanstack/react-query.gen";
|
||||
import { apiClient } from "../../../lib/api";
|
||||
import { showErrorNotification } from "../../../lib/notifications";
|
||||
import { StateLabel } from "../../../utils/stateLabels";
|
||||
|
||||
@@ -26,7 +32,6 @@ type SuburbSelectProps = {
|
||||
type SuburbOption = { value: string; label: string; description?: string };
|
||||
|
||||
export default function SuburbSelect(props: SuburbSelectProps) {
|
||||
const suburbBoundaryApi = new SuburbBoundaryApi(configuration);
|
||||
const [search, setSearch] = useState("");
|
||||
const searchRef = useRef(search);
|
||||
const [selectedSuburbId, setSelectedSuburbId] = useState<string | null>(props.value ?? null);
|
||||
@@ -35,10 +40,8 @@ export default function SuburbSelect(props: SuburbSelectProps) {
|
||||
const query = searchRef.current;
|
||||
if (query === "") return [];
|
||||
try {
|
||||
const response = await suburbBoundaryApi.apiSuburbBoundariesSuburbsByNameGet({
|
||||
name: query,
|
||||
});
|
||||
return response;
|
||||
const { data } = await getSuburbsByName({ query: { name: query }, client: apiClient });
|
||||
return data;
|
||||
} catch (error) {
|
||||
showErrorNotification(error, {
|
||||
message:
|
||||
@@ -75,8 +78,17 @@ export default function SuburbSelect(props: SuburbSelectProps) {
|
||||
}, [props.value]);
|
||||
|
||||
const boundaryQuery = useQuery({
|
||||
queryKey: ["suburbBoundary", props.value],
|
||||
queryFn: () => suburbBoundaryApi.apiSuburbBoundariesByIdGet({ id: props.value as string }),
|
||||
queryKey: getSuburbBoundaryByIdQueryKey({
|
||||
query: { id: props.value as string },
|
||||
client: apiClient,
|
||||
}),
|
||||
queryFn: async () => {
|
||||
const { data } = await getSuburbBoundaryById({
|
||||
query: { id: props.value as string },
|
||||
client: apiClient,
|
||||
});
|
||||
return data;
|
||||
},
|
||||
enabled: !!props.value,
|
||||
staleTime: LOV_STALE_TIME,
|
||||
retry: false,
|
||||
|
||||
@@ -4,6 +4,7 @@ import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { fuelTypesFixture } from "../test/fixtures";
|
||||
|
||||
vi.mock("../lib/serverPrefetch", () => ({ getCommonFuelTypes: vi.fn() }));
|
||||
vi.mock("server-only", () => ({}));
|
||||
vi.mock("next/server", () => ({ connection: vi.fn() }));
|
||||
vi.mock("./components/layout/MainLayout", () => ({
|
||||
default: ({ children }: { children: ReactNode }) => <div>{children}</div>,
|
||||
|
||||
@@ -9,6 +9,8 @@ import type { Metadata, Viewport } from "next";
|
||||
import { ReactNode } from "react";
|
||||
|
||||
import { ColorSchemeScript, mantineHtmlProps } from "@mantine/core";
|
||||
import { getCommonFuelTypesQueryKey } from "../generated/@tanstack/react-query.gen";
|
||||
import { serverClient } from "../lib/api.server";
|
||||
import { getCommonFuelTypes } from "../lib/serverPrefetch";
|
||||
import { SITE_URL } from "../lib/siteUrl";
|
||||
import MainLayout from "./components/layout/MainLayout";
|
||||
@@ -54,7 +56,7 @@ export default async function RootLayout({ children }: { children: ReactNode })
|
||||
const queryClient = new QueryClient();
|
||||
try {
|
||||
await queryClient.fetchQuery({
|
||||
queryKey: ["fuelTypesCommon"],
|
||||
queryKey: getCommonFuelTypesQueryKey({ client: serverClient }),
|
||||
queryFn: getCommonFuelTypes,
|
||||
retry: false,
|
||||
});
|
||||
|
||||
@@ -20,16 +20,21 @@ import dynamic from "next/dynamic";
|
||||
import { useEffect, useState } from "react";
|
||||
import { FaRoute } from "react-icons/fa6";
|
||||
import {
|
||||
BrandApi,
|
||||
getAllBrands,
|
||||
getAllFuelTypes,
|
||||
getStationsWithPricesWithinRadius,
|
||||
getStationsWithPricesWithinSuburb,
|
||||
BrandType,
|
||||
FuelType,
|
||||
FuelTypeApi,
|
||||
StationWithPrices,
|
||||
StationWithPricesApi,
|
||||
Suburb,
|
||||
SuburbBoundary,
|
||||
} from "../../generated";
|
||||
import { configuration } from "../../lib/api";
|
||||
import {
|
||||
getAllBrandsQueryKey,
|
||||
getAllFuelTypesQueryKey,
|
||||
} from "../../generated/@tanstack/react-query.gen";
|
||||
import { apiClient } from "../../lib/api";
|
||||
import {
|
||||
getErrorStatus,
|
||||
showErrorNotification,
|
||||
@@ -70,9 +75,6 @@ export default function MapClient({
|
||||
const isMobile = useMediaQuery(`(max-width: ${theme.breakpoints.lg})`);
|
||||
|
||||
const defaultLocation = GetDefaultLocation();
|
||||
const stationWithPricesApi = new StationWithPricesApi(configuration);
|
||||
const brandApi = new BrandApi(configuration);
|
||||
const fuelTypeApi = new FuelTypeApi(configuration);
|
||||
|
||||
const [selectedPoint, setSelectedPoint] = useState<CustomMapPoint>();
|
||||
const [selectedFuelType, setSelectedFuelType] = useHydratedPreference(
|
||||
@@ -100,8 +102,8 @@ export default function MapClient({
|
||||
|
||||
async function FetchBrands() {
|
||||
try {
|
||||
const brandResponse = await brandApi.apiBrandsAllGet();
|
||||
return brandResponse;
|
||||
const { data } = await getAllBrands({ client: apiClient });
|
||||
return data;
|
||||
} catch (error) {
|
||||
showErrorNotification(error, {
|
||||
message:
|
||||
@@ -112,8 +114,8 @@ export default function MapClient({
|
||||
|
||||
async function FetchFuelTypes() {
|
||||
try {
|
||||
const fuelTypeResponse = await fuelTypeApi.apiFuelTypesAllGet();
|
||||
return fuelTypeResponse;
|
||||
const { data } = await getAllFuelTypes({ client: apiClient });
|
||||
return data;
|
||||
} catch (error) {
|
||||
showErrorNotification(error, {
|
||||
message:
|
||||
@@ -124,8 +126,8 @@ export default function MapClient({
|
||||
|
||||
async function FetchStationsWithPrices() {
|
||||
try {
|
||||
const stationsWithPricesResponse =
|
||||
await stationWithPricesApi.apiStationsWithPricesWithinRadiusGet({
|
||||
const { data: stationsWithPricesResponse } = await getStationsWithPricesWithinRadius({
|
||||
query: {
|
||||
brand: selectedBrand,
|
||||
fuelType: selectedFuelType as string,
|
||||
pageNumber: 1,
|
||||
@@ -133,16 +135,18 @@ export default function MapClient({
|
||||
radiusInMetres: selectedRadius * 1000,
|
||||
latitude: selectedPosition?.lat || defaultLocation?.lat,
|
||||
longitude: selectedPosition?.long || defaultLocation?.long,
|
||||
});
|
||||
},
|
||||
client: apiClient,
|
||||
});
|
||||
|
||||
if (stationsWithPricesResponse.data?.length === 100) {
|
||||
if (stationsWithPricesResponse?.data?.length === 100) {
|
||||
showInfoNotification({
|
||||
title: "Station limit reached",
|
||||
message:
|
||||
"There are a lot of stations within that radius, showing only the cheapest 100 stations.",
|
||||
});
|
||||
}
|
||||
return stationsWithPricesResponse.data;
|
||||
return stationsWithPricesResponse?.data;
|
||||
} catch (error) {
|
||||
if (getErrorStatus(error) === 404) {
|
||||
showInfoNotification({
|
||||
@@ -162,14 +166,17 @@ export default function MapClient({
|
||||
async function FetchStationsWithPricesWithinSuburb() {
|
||||
if (!selectedSuburb?.id) return [];
|
||||
try {
|
||||
const response = await stationWithPricesApi.apiStationsWithPricesWithinSuburbGet({
|
||||
suburbId: selectedSuburb.id,
|
||||
fuelType: selectedFuelType as string,
|
||||
brand: selectedBrand,
|
||||
pageNumber: 1,
|
||||
pageSize: 100,
|
||||
const { data } = await getStationsWithPricesWithinSuburb({
|
||||
query: {
|
||||
suburbId: selectedSuburb.id,
|
||||
fuelType: selectedFuelType as string,
|
||||
brand: selectedBrand,
|
||||
pageNumber: 1,
|
||||
pageSize: 100,
|
||||
},
|
||||
client: apiClient,
|
||||
});
|
||||
return response.data;
|
||||
return data?.data;
|
||||
} catch (error) {
|
||||
if (getErrorStatus(error) === 404) {
|
||||
showInfoNotification({
|
||||
@@ -203,11 +210,11 @@ export default function MapClient({
|
||||
};
|
||||
|
||||
const brandsQuery = useQuery({
|
||||
queryKey: ["mapPageBrands"],
|
||||
queryKey: getAllBrandsQueryKey({ client: apiClient }),
|
||||
queryFn: FetchBrands,
|
||||
});
|
||||
const fuelTypesQuery = useQuery({
|
||||
queryKey: ["mapPageFuelTypes"],
|
||||
queryKey: getAllFuelTypesQueryKey({ client: apiClient }),
|
||||
queryFn: FetchFuelTypes,
|
||||
});
|
||||
const stationsWithPricesQuery = useQuery({
|
||||
|
||||
@@ -11,12 +11,32 @@ import {
|
||||
} from "../../test/fixtures";
|
||||
import { renderWithProviders, screen, waitFor } from "../../test/utils";
|
||||
|
||||
const {
|
||||
getAllBrandsMock,
|
||||
getAllFuelTypesMock,
|
||||
getStationsWithPricesWithinRadiusMock,
|
||||
getStationsWithPricesWithinSuburbMock,
|
||||
getSuburbsByNameMock,
|
||||
getSuburbBoundaryByIdMock,
|
||||
} = vi.hoisted(() => ({
|
||||
getAllBrandsMock: vi.fn(),
|
||||
getAllFuelTypesMock: vi.fn(),
|
||||
getStationsWithPricesWithinRadiusMock: vi.fn(),
|
||||
getStationsWithPricesWithinSuburbMock: vi.fn(),
|
||||
getSuburbsByNameMock: vi.fn(),
|
||||
getSuburbBoundaryByIdMock: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("../../generated", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("../../generated")>();
|
||||
const { apiClassMocks } = await import("../../test/mocks");
|
||||
return {
|
||||
...actual,
|
||||
...apiClassMocks(["StationWithPricesApi", "BrandApi", "FuelTypeApi", "SuburbBoundaryApi"]),
|
||||
getAllBrands: getAllBrandsMock,
|
||||
getAllFuelTypes: getAllFuelTypesMock,
|
||||
getStationsWithPricesWithinRadius: getStationsWithPricesWithinRadiusMock,
|
||||
getStationsWithPricesWithinSuburb: getStationsWithPricesWithinSuburbMock,
|
||||
getSuburbsByName: getSuburbsByNameMock,
|
||||
getSuburbBoundaryById: getSuburbBoundaryByIdMock,
|
||||
} as typeof actual;
|
||||
});
|
||||
|
||||
@@ -55,7 +75,6 @@ vi.mock("next/cache", () => ({ cacheLife: vi.fn() }));
|
||||
vi.mock("next/headers", () => ({ cookies: vi.fn() }));
|
||||
vi.mock("next/server", () => ({ connection: vi.fn() }));
|
||||
|
||||
import { BrandApi, FuelTypeApi, StationWithPricesApi, SuburbBoundaryApi } from "../../generated";
|
||||
import { cookies } from "next/headers";
|
||||
import { connection } from "next/server";
|
||||
import { getRoute } from "../../utils/osrmUtils";
|
||||
@@ -63,71 +82,39 @@ import { SetHomeSuburb } from "../../utils/userPreferencesUtils";
|
||||
import MapClient from "./MapClient";
|
||||
import MapPage from "./page";
|
||||
|
||||
const stationWithPricesApiMock = vi.mocked(StationWithPricesApi);
|
||||
const brandApiMock = vi.mocked(BrandApi);
|
||||
const fuelTypeApiMock = vi.mocked(FuelTypeApi);
|
||||
const suburbBoundaryApiMock = vi.mocked(SuburbBoundaryApi);
|
||||
const getRouteMock = vi.mocked(getRoute);
|
||||
|
||||
const apiStationsWithPricesWithinRadiusGet = vi.fn();
|
||||
const apiStationsWithPricesWithinSuburbGet = vi.fn();
|
||||
const apiBrandsAllGet = vi.fn();
|
||||
const apiFuelTypesAllGet = vi.fn();
|
||||
const apiSuburbBoundariesSuburbsByNameGet = vi.fn();
|
||||
const apiSuburbBoundariesByIdGet = vi.fn();
|
||||
|
||||
beforeEach(() => {
|
||||
localStorage.clear();
|
||||
apiStationsWithPricesWithinRadiusGet.mockResolvedValue(
|
||||
paginatedStationsFixture(stationsWithPricesFixture),
|
||||
);
|
||||
apiStationsWithPricesWithinSuburbGet.mockResolvedValue(
|
||||
paginatedStationsFixture(stationsWithPricesFixture),
|
||||
);
|
||||
apiBrandsAllGet.mockResolvedValue([{ name: "Ampol" }]);
|
||||
apiFuelTypesAllGet.mockResolvedValue([{ code: "U91", name: "Unleaded 91" }]);
|
||||
apiSuburbBoundariesSuburbsByNameGet.mockResolvedValue(suburbsFixture);
|
||||
apiSuburbBoundariesByIdGet.mockResolvedValue(suburbBoundaryFixture);
|
||||
getStationsWithPricesWithinRadiusMock.mockResolvedValue({
|
||||
data: paginatedStationsFixture(stationsWithPricesFixture),
|
||||
});
|
||||
getStationsWithPricesWithinSuburbMock.mockResolvedValue({
|
||||
data: paginatedStationsFixture(stationsWithPricesFixture),
|
||||
});
|
||||
getAllBrandsMock.mockResolvedValue({ data: [{ name: "Ampol" }] });
|
||||
getAllFuelTypesMock.mockResolvedValue({ data: [{ code: "U91", name: "Unleaded 91" }] });
|
||||
getSuburbsByNameMock.mockResolvedValue({ data: suburbsFixture });
|
||||
getSuburbBoundaryByIdMock.mockResolvedValue({ data: suburbBoundaryFixture });
|
||||
getRouteMock.mockResolvedValue(osrmRouteFixture);
|
||||
|
||||
stationWithPricesApiMock.mockImplementation(
|
||||
class {
|
||||
apiStationsWithPricesWithinRadiusGet = apiStationsWithPricesWithinRadiusGet;
|
||||
apiStationsWithPricesWithinSuburbGet = apiStationsWithPricesWithinSuburbGet;
|
||||
} as unknown as typeof StationWithPricesApi,
|
||||
);
|
||||
brandApiMock.mockImplementation(
|
||||
class {
|
||||
apiBrandsAllGet = apiBrandsAllGet;
|
||||
} as unknown as typeof BrandApi,
|
||||
);
|
||||
fuelTypeApiMock.mockImplementation(
|
||||
class {
|
||||
apiFuelTypesAllGet = apiFuelTypesAllGet;
|
||||
} as unknown as typeof FuelTypeApi,
|
||||
);
|
||||
suburbBoundaryApiMock.mockImplementation(
|
||||
class {
|
||||
apiSuburbBoundariesSuburbsByNameGet = apiSuburbBoundariesSuburbsByNameGet;
|
||||
apiSuburbBoundariesByIdGet = apiSuburbBoundariesByIdGet;
|
||||
} as unknown as typeof SuburbBoundaryApi,
|
||||
);
|
||||
});
|
||||
|
||||
describe("MapPage", () => {
|
||||
it("fetches brands, fuel types, and stations on mount with the default location", async () => {
|
||||
renderWithProviders(<MapClient />);
|
||||
|
||||
await waitFor(() => expect(apiBrandsAllGet).toHaveBeenCalledTimes(1));
|
||||
await waitFor(() => expect(apiFuelTypesAllGet).toHaveBeenCalledTimes(1));
|
||||
await waitFor(() => expect(getAllBrandsMock).toHaveBeenCalledTimes(1));
|
||||
await waitFor(() => expect(getAllFuelTypesMock).toHaveBeenCalledTimes(1));
|
||||
await waitFor(() =>
|
||||
expect(apiStationsWithPricesWithinRadiusGet).toHaveBeenCalledWith(
|
||||
expect(getStationsWithPricesWithinRadiusMock).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
pageSize: 100,
|
||||
pageNumber: 1,
|
||||
radiusInMetres: 10000,
|
||||
latitude: -33.856758,
|
||||
longitude: 151.215295,
|
||||
query: expect.objectContaining({
|
||||
pageSize: 100,
|
||||
pageNumber: 1,
|
||||
radiusInMetres: 10000,
|
||||
latitude: -33.856758,
|
||||
longitude: 151.215295,
|
||||
}),
|
||||
}),
|
||||
),
|
||||
);
|
||||
@@ -141,11 +128,11 @@ describe("MapPage", () => {
|
||||
const user = userEvent.setup();
|
||||
renderWithProviders(<MapClient />);
|
||||
|
||||
await waitFor(() => expect(apiStationsWithPricesWithinRadiusGet).toHaveBeenCalledTimes(1));
|
||||
await waitFor(() => expect(getStationsWithPricesWithinRadiusMock).toHaveBeenCalledTimes(1));
|
||||
|
||||
await user.click(screen.getByRole("button", { name: "Apply" }));
|
||||
|
||||
await waitFor(() => expect(apiStationsWithPricesWithinRadiusGet).toHaveBeenCalledTimes(2));
|
||||
await waitFor(() => expect(getStationsWithPricesWithinRadiusMock).toHaveBeenCalledTimes(2));
|
||||
});
|
||||
|
||||
it("warns when the station limit of 100 is reached", async () => {
|
||||
@@ -159,7 +146,9 @@ describe("MapPage", () => {
|
||||
},
|
||||
}),
|
||||
);
|
||||
apiStationsWithPricesWithinRadiusGet.mockResolvedValue(paginatedStationsFixture(manyStations));
|
||||
getStationsWithPricesWithinRadiusMock.mockResolvedValue({
|
||||
data: paginatedStationsFixture(manyStations),
|
||||
});
|
||||
|
||||
renderWithProviders(<MapClient />);
|
||||
|
||||
@@ -168,7 +157,7 @@ describe("MapPage", () => {
|
||||
|
||||
it("fetches stations within a suburb and shows a warning on 404", async () => {
|
||||
SetHomeSuburb({ id: "syd", name: "Sydney" });
|
||||
apiStationsWithPricesWithinSuburbGet.mockRejectedValue({
|
||||
getStationsWithPricesWithinSuburbMock.mockRejectedValue({
|
||||
response: { status: 404 },
|
||||
});
|
||||
|
||||
@@ -178,8 +167,10 @@ describe("MapPage", () => {
|
||||
await user.click(screen.getByText("Suburb"));
|
||||
|
||||
await waitFor(() =>
|
||||
expect(apiStationsWithPricesWithinSuburbGet).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ suburbId: "syd", pageSize: 100 }),
|
||||
expect(getStationsWithPricesWithinSuburbMock).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
query: expect.objectContaining({ suburbId: "syd", pageSize: 100 }),
|
||||
}),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -212,10 +203,12 @@ describe("MapPage", () => {
|
||||
});
|
||||
|
||||
it("picks up a legacy localStorage default fuel type after mount when no initial value is provided", async () => {
|
||||
apiFuelTypesAllGet.mockResolvedValue([
|
||||
{ code: "U91", name: "Unleaded 91" },
|
||||
{ code: "P98", name: "Premium 98" },
|
||||
]);
|
||||
getAllFuelTypesMock.mockResolvedValue({
|
||||
data: [
|
||||
{ code: "U91", name: "Unleaded 91" },
|
||||
{ code: "P98", name: "Premium 98" },
|
||||
],
|
||||
});
|
||||
localStorage.setItem("defaultFuelType", "P98");
|
||||
|
||||
renderWithProviders(<MapClient initialFuelType={null} />);
|
||||
@@ -251,18 +244,20 @@ describe("MapPage (server prefetch)", () => {
|
||||
renderWithProviders(<>{await MapPage()}</>);
|
||||
|
||||
await waitFor(() =>
|
||||
expect(apiStationsWithPricesWithinRadiusGet).toHaveBeenCalledWith(
|
||||
expect(getStationsWithPricesWithinRadiusMock).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
latitude: -33.856758,
|
||||
longitude: 151.215295,
|
||||
radiusInMetres: 10000,
|
||||
pageNumber: 1,
|
||||
pageSize: 100,
|
||||
query: expect.objectContaining({
|
||||
latitude: -33.856758,
|
||||
longitude: 151.215295,
|
||||
radiusInMetres: 10000,
|
||||
pageNumber: 1,
|
||||
pageSize: 100,
|
||||
}),
|
||||
}),
|
||||
),
|
||||
);
|
||||
expect(apiBrandsAllGet).toHaveBeenCalled();
|
||||
expect(apiFuelTypesAllGet).toHaveBeenCalled();
|
||||
expect(getAllBrandsMock).toHaveBeenCalled();
|
||||
expect(getAllFuelTypesMock).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("prefetches stations around the cookie home location and fuel type", async () => {
|
||||
@@ -283,21 +278,25 @@ describe("MapPage (server prefetch)", () => {
|
||||
renderWithProviders(<>{await MapPage()}</>);
|
||||
|
||||
await waitFor(() =>
|
||||
expect(apiStationsWithPricesWithinRadiusGet).toHaveBeenCalledWith(
|
||||
expect(getStationsWithPricesWithinRadiusMock).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
latitude: -33.87,
|
||||
longitude: 151.2,
|
||||
fuelType: "P98",
|
||||
query: expect.objectContaining({
|
||||
latitude: -33.87,
|
||||
longitude: 151.2,
|
||||
fuelType: "P98",
|
||||
}),
|
||||
}),
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
it("passes the cookie fuel type to MapClient so the select matches the server HTML", async () => {
|
||||
apiFuelTypesAllGet.mockResolvedValue([
|
||||
{ code: "U91", name: "Unleaded 91" },
|
||||
{ code: "P98", name: "Premium 98" },
|
||||
]);
|
||||
getAllFuelTypesMock.mockResolvedValue({
|
||||
data: [
|
||||
{ code: "U91", name: "Unleaded 91" },
|
||||
{ code: "P98", name: "Premium 98" },
|
||||
],
|
||||
});
|
||||
cookiesMock.mockResolvedValue({
|
||||
get: (name: string) =>
|
||||
name === "fw-preferences"
|
||||
@@ -326,6 +325,10 @@ describe("MapPage (server prefetch)", () => {
|
||||
|
||||
renderWithProviders(<>{await MapPage()}</>);
|
||||
|
||||
await waitFor(() => expect(apiSuburbBoundariesByIdGet).toHaveBeenCalledWith({ id: "syd" }));
|
||||
await waitFor(() =>
|
||||
expect(getSuburbBoundaryByIdMock).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ query: { id: "syd" } }),
|
||||
),
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -1,6 +1,12 @@
|
||||
import { HydrationBoundary, QueryClient, dehydrate } from "@tanstack/react-query";
|
||||
import { cookies } from "next/headers";
|
||||
import { connection } from "next/server";
|
||||
import {
|
||||
getAllBrandsQueryKey,
|
||||
getAllFuelTypesQueryKey,
|
||||
getSuburbBoundaryByIdQueryKey,
|
||||
} from "../../generated/@tanstack/react-query.gen";
|
||||
import { serverClient } from "../../lib/api.server";
|
||||
import {
|
||||
getBrands,
|
||||
getFuelTypes,
|
||||
@@ -26,12 +32,12 @@ export default async function MapPage() {
|
||||
|
||||
await Promise.all([
|
||||
queryClient.fetchQuery({
|
||||
queryKey: ["mapPageBrands"],
|
||||
queryKey: getAllBrandsQueryKey({ client: serverClient }),
|
||||
queryFn: getBrands,
|
||||
retry: false,
|
||||
}),
|
||||
queryClient.fetchQuery({
|
||||
queryKey: ["mapPageFuelTypes"],
|
||||
queryKey: getAllFuelTypesQueryKey({ client: serverClient }),
|
||||
queryFn: getFuelTypes,
|
||||
retry: false,
|
||||
}),
|
||||
@@ -54,7 +60,10 @@ export default async function MapPage() {
|
||||
const homeSuburbId = prefs.homeSuburb?.id;
|
||||
if (homeSuburbId) {
|
||||
await queryClient.fetchQuery({
|
||||
queryKey: ["suburbBoundary", homeSuburbId],
|
||||
queryKey: getSuburbBoundaryByIdQueryKey({
|
||||
query: { id: homeSuburbId },
|
||||
client: serverClient,
|
||||
}),
|
||||
queryFn: () => getSuburbBoundaryById(homeSuburbId),
|
||||
retry: false,
|
||||
});
|
||||
|
||||
@@ -19,13 +19,17 @@ import { useMediaQuery, usePagination } from "@mantine/hooks";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { useEffect, useMemo, useRef, useState } from "react";
|
||||
import {
|
||||
BrandApi,
|
||||
FuelTypeApi,
|
||||
PriceTrendsApi,
|
||||
getAllBrands,
|
||||
getAllFuelTypes,
|
||||
getDailyPriceAveragesByStationIds,
|
||||
getStationsWithPricesWithinRadius,
|
||||
StationWithPrices,
|
||||
StationWithPricesApi,
|
||||
} from "../../generated";
|
||||
import { configuration } from "../../lib/api";
|
||||
import {
|
||||
getAllBrandsQueryKey,
|
||||
getAllFuelTypesQueryKey,
|
||||
} from "../../generated/@tanstack/react-query.gen";
|
||||
import { apiClient } from "../../lib/api";
|
||||
import { LOV_STALE_TIME } from "../../lib/cacheTimes";
|
||||
import {
|
||||
getErrorStatus,
|
||||
@@ -54,11 +58,6 @@ export default function StationsClient({ initialFuelType }: StationsClientProps)
|
||||
const theme = useMantineTheme();
|
||||
const isMobile = useMediaQuery(`(max-width: ${theme.breakpoints.lg})`);
|
||||
|
||||
const stationWithPricesApi = new StationWithPricesApi(configuration);
|
||||
const brandApi = new BrandApi(configuration);
|
||||
const fuelTypeApi = new FuelTypeApi(configuration);
|
||||
const priceTrendsApi = new PriceTrendsApi(configuration);
|
||||
|
||||
const [selectedBrand, setSelectedBrand] = useState<string>();
|
||||
const [selectedFuelType, setSelectedFuelType] = useHydratedPreference(
|
||||
initialFuelType ?? null,
|
||||
@@ -73,8 +72,8 @@ export default function StationsClient({ initialFuelType }: StationsClientProps)
|
||||
|
||||
async function FetchBrands() {
|
||||
try {
|
||||
const brandResponse = await brandApi.apiBrandsAllGet();
|
||||
return brandResponse;
|
||||
const { data } = await getAllBrands({ client: apiClient });
|
||||
return data;
|
||||
} catch (error) {
|
||||
showErrorNotification(error, {
|
||||
message:
|
||||
@@ -85,8 +84,8 @@ export default function StationsClient({ initialFuelType }: StationsClientProps)
|
||||
|
||||
async function FetchFuelTypes() {
|
||||
try {
|
||||
const fuelTypeResponse = await fuelTypeApi.apiFuelTypesAllGet();
|
||||
return fuelTypeResponse;
|
||||
const { data } = await getAllFuelTypes({ client: apiClient });
|
||||
return data;
|
||||
} catch (error) {
|
||||
showErrorNotification(error, {
|
||||
message:
|
||||
@@ -103,13 +102,16 @@ export default function StationsClient({ initialFuelType }: StationsClientProps)
|
||||
.map((s) => s.station?.id)
|
||||
.filter((id): id is string => id != null);
|
||||
try {
|
||||
const priceTrendsResponse = await priceTrendsApi.apiTrendsDailyAveragesStationIdsGet({
|
||||
startDate: selectedDateTimeRange?.startDate ?? undefined,
|
||||
endDate: selectedDateTimeRange?.endDate ?? undefined,
|
||||
fuelType: (selectedFuelType as string) || "U91",
|
||||
stationIds,
|
||||
const { data } = await getDailyPriceAveragesByStationIds({
|
||||
query: {
|
||||
startDate: selectedDateTimeRange?.startDate?.toISOString(),
|
||||
endDate: selectedDateTimeRange?.endDate?.toISOString(),
|
||||
fuelType: (selectedFuelType as string) || "U91",
|
||||
stationIds,
|
||||
},
|
||||
client: apiClient,
|
||||
});
|
||||
return priceTrendsResponse;
|
||||
return data;
|
||||
} catch (error) {
|
||||
showErrorNotification(error, {
|
||||
message:
|
||||
@@ -122,16 +124,20 @@ export default function StationsClient({ initialFuelType }: StationsClientProps)
|
||||
async function FetchStationsWithPrices() {
|
||||
try {
|
||||
const home = GetHomeLocation();
|
||||
return await stationWithPricesApi.apiStationsWithPricesWithinRadiusGet({
|
||||
brand: selectedBrand,
|
||||
fuelType: selectedFuelType as string,
|
||||
stationName: searchTerm,
|
||||
pageNumber: pagination.active,
|
||||
pageSize: 25,
|
||||
radiusInMetres: selectedRadius * 1000,
|
||||
latitude: home?.lat || GetDefaultLocation()?.lat,
|
||||
longitude: home?.long || GetDefaultLocation()?.long,
|
||||
const { data } = await getStationsWithPricesWithinRadius({
|
||||
query: {
|
||||
brand: selectedBrand,
|
||||
fuelType: selectedFuelType as string,
|
||||
stationName: searchTerm,
|
||||
pageNumber: pagination.active,
|
||||
pageSize: 25,
|
||||
radiusInMetres: selectedRadius * 1000,
|
||||
latitude: home?.lat || GetDefaultLocation()?.lat,
|
||||
longitude: home?.long || GetDefaultLocation()?.long,
|
||||
},
|
||||
client: apiClient,
|
||||
});
|
||||
return data;
|
||||
} catch (error) {
|
||||
if (getErrorStatus(error) === 404) {
|
||||
showInfoNotification({
|
||||
@@ -149,12 +155,12 @@ export default function StationsClient({ initialFuelType }: StationsClientProps)
|
||||
}
|
||||
|
||||
const brandsQuery = useQuery({
|
||||
queryKey: ["stationsPageBrands"],
|
||||
queryKey: getAllBrandsQueryKey({ client: apiClient }),
|
||||
queryFn: FetchBrands,
|
||||
staleTime: LOV_STALE_TIME,
|
||||
});
|
||||
const fuelTypesQuery = useQuery({
|
||||
queryKey: ["stationsPageFuelTypes"],
|
||||
queryKey: getAllFuelTypesQueryKey({ client: apiClient }),
|
||||
queryFn: FetchFuelTypes,
|
||||
staleTime: LOV_STALE_TIME,
|
||||
});
|
||||
@@ -178,7 +184,7 @@ export default function StationsClient({ initialFuelType }: StationsClientProps)
|
||||
|
||||
const chartData = useMemo(() => {
|
||||
return priceTrendsQuery?.data?.dailyAverages?.map((dpa) => ({
|
||||
date: dpa.date,
|
||||
date: dpa.date ? new Date(dpa.date) : undefined,
|
||||
averagePriceValue: dpa.averagePriceValue as number,
|
||||
}));
|
||||
}, [priceTrendsQuery.data]);
|
||||
|
||||
@@ -8,12 +8,26 @@ import {
|
||||
} from "../../test/fixtures";
|
||||
import { renderWithProviders, screen, waitFor } from "../../test/utils";
|
||||
|
||||
const {
|
||||
getAllBrandsMock,
|
||||
getAllFuelTypesMock,
|
||||
getStationsWithPricesWithinRadiusMock,
|
||||
getDailyPriceAveragesByStationIdsMock,
|
||||
} = vi.hoisted(() => ({
|
||||
getAllBrandsMock: vi.fn(),
|
||||
getAllFuelTypesMock: vi.fn(),
|
||||
getStationsWithPricesWithinRadiusMock: vi.fn(),
|
||||
getDailyPriceAveragesByStationIdsMock: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("../../generated", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("../../generated")>();
|
||||
const { apiClassMocks } = await import("../../test/mocks");
|
||||
return {
|
||||
...actual,
|
||||
...apiClassMocks(["StationWithPricesApi", "BrandApi", "FuelTypeApi", "PriceTrendsApi"]),
|
||||
getAllBrands: getAllBrandsMock,
|
||||
getAllFuelTypes: getAllFuelTypesMock,
|
||||
getStationsWithPricesWithinRadius: getStationsWithPricesWithinRadiusMock,
|
||||
getDailyPriceAveragesByStationIds: getDailyPriceAveragesByStationIdsMock,
|
||||
} as typeof actual;
|
||||
});
|
||||
|
||||
@@ -22,51 +36,19 @@ vi.mock("next/cache", () => ({ cacheLife: vi.fn() }));
|
||||
vi.mock("next/headers", () => ({ cookies: vi.fn() }));
|
||||
vi.mock("next/server", () => ({ connection: vi.fn() }));
|
||||
|
||||
import { BrandApi, FuelTypeApi, PriceTrendsApi, StationWithPricesApi } from "../../generated";
|
||||
import { cookies } from "next/headers";
|
||||
import { connection } from "next/server";
|
||||
import StationsClient from "./StationsClient";
|
||||
import StationsPage from "./page";
|
||||
|
||||
const stationWithPricesApiMock = vi.mocked(StationWithPricesApi);
|
||||
const brandApiMock = vi.mocked(BrandApi);
|
||||
const fuelTypeApiMock = vi.mocked(FuelTypeApi);
|
||||
const priceTrendsApiMock = vi.mocked(PriceTrendsApi);
|
||||
|
||||
const apiStationsWithPricesWithinRadiusGet = vi.fn();
|
||||
const apiBrandsAllGet = vi.fn();
|
||||
const apiFuelTypesAllGet = vi.fn();
|
||||
const apiTrendsDailyAveragesStationIdsGet = vi.fn();
|
||||
|
||||
beforeEach(() => {
|
||||
localStorage.clear();
|
||||
apiStationsWithPricesWithinRadiusGet.mockResolvedValue(
|
||||
paginatedStationsFixture(stationsWithPricesFixture, 3),
|
||||
);
|
||||
apiBrandsAllGet.mockResolvedValue([{ name: "Ampol" }]);
|
||||
apiFuelTypesAllGet.mockResolvedValue([{ code: "U91", name: "Unleaded 91" }]);
|
||||
apiTrendsDailyAveragesStationIdsGet.mockResolvedValue(priceTrendsFixture());
|
||||
|
||||
stationWithPricesApiMock.mockImplementation(
|
||||
class {
|
||||
apiStationsWithPricesWithinRadiusGet = apiStationsWithPricesWithinRadiusGet;
|
||||
} as unknown as typeof StationWithPricesApi,
|
||||
);
|
||||
brandApiMock.mockImplementation(
|
||||
class {
|
||||
apiBrandsAllGet = apiBrandsAllGet;
|
||||
} as unknown as typeof BrandApi,
|
||||
);
|
||||
fuelTypeApiMock.mockImplementation(
|
||||
class {
|
||||
apiFuelTypesAllGet = apiFuelTypesAllGet;
|
||||
} as unknown as typeof FuelTypeApi,
|
||||
);
|
||||
priceTrendsApiMock.mockImplementation(
|
||||
class {
|
||||
apiTrendsDailyAveragesStationIdsGet = apiTrendsDailyAveragesStationIdsGet;
|
||||
} as unknown as typeof PriceTrendsApi,
|
||||
);
|
||||
getStationsWithPricesWithinRadiusMock.mockResolvedValue({
|
||||
data: paginatedStationsFixture(stationsWithPricesFixture, 3),
|
||||
});
|
||||
getAllBrandsMock.mockResolvedValue({ data: [{ name: "Ampol" }] });
|
||||
getAllFuelTypesMock.mockResolvedValue({ data: [{ code: "U91", name: "Unleaded 91" }] });
|
||||
getDailyPriceAveragesByStationIdsMock.mockResolvedValue({ data: priceTrendsFixture() });
|
||||
});
|
||||
|
||||
describe("StationsPage", () => {
|
||||
@@ -74,13 +56,15 @@ describe("StationsPage", () => {
|
||||
renderWithProviders(<StationsClient />);
|
||||
|
||||
await waitFor(() =>
|
||||
expect(apiStationsWithPricesWithinRadiusGet).toHaveBeenCalledWith(
|
||||
expect(getStationsWithPricesWithinRadiusMock).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
pageNumber: 1,
|
||||
pageSize: 25,
|
||||
radiusInMetres: 10000,
|
||||
latitude: -33.856758,
|
||||
longitude: 151.215295,
|
||||
query: expect.objectContaining({
|
||||
pageNumber: 1,
|
||||
pageSize: 25,
|
||||
radiusInMetres: 10000,
|
||||
latitude: -33.856758,
|
||||
longitude: 151.215295,
|
||||
}),
|
||||
}),
|
||||
),
|
||||
);
|
||||
@@ -103,20 +87,20 @@ describe("StationsPage", () => {
|
||||
renderWithProviders(<StationsClient />);
|
||||
|
||||
await screen.findByText("Ampol Ultimo");
|
||||
expect(apiTrendsDailyAveragesStationIdsGet).not.toHaveBeenCalled();
|
||||
expect(getDailyPriceAveragesByStationIdsMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("refetches stations on Apply", async () => {
|
||||
const user = userEvent.setup();
|
||||
renderWithProviders(<StationsClient />);
|
||||
|
||||
await waitFor(() => expect(apiStationsWithPricesWithinRadiusGet).toHaveBeenCalled());
|
||||
const initialCount = apiStationsWithPricesWithinRadiusGet.mock.calls.length;
|
||||
await waitFor(() => expect(getStationsWithPricesWithinRadiusMock).toHaveBeenCalled());
|
||||
const initialCount = getStationsWithPricesWithinRadiusMock.mock.calls.length;
|
||||
|
||||
await user.click(screen.getByRole("button", { name: "Apply" }));
|
||||
|
||||
await waitFor(() =>
|
||||
expect(apiStationsWithPricesWithinRadiusGet.mock.calls.length).toBe(initialCount + 1),
|
||||
expect(getStationsWithPricesWithinRadiusMock.mock.calls.length).toBe(initialCount + 1),
|
||||
);
|
||||
});
|
||||
|
||||
@@ -127,8 +111,8 @@ describe("StationsPage", () => {
|
||||
await user.click(await screen.findByRole("button", { name: "2" }));
|
||||
|
||||
await waitFor(() =>
|
||||
expect(apiStationsWithPricesWithinRadiusGet).toHaveBeenLastCalledWith(
|
||||
expect.objectContaining({ pageNumber: 2 }),
|
||||
expect(getStationsWithPricesWithinRadiusMock).toHaveBeenLastCalledWith(
|
||||
expect.objectContaining({ query: expect.objectContaining({ pageNumber: 2 }) }),
|
||||
),
|
||||
);
|
||||
});
|
||||
@@ -141,10 +125,12 @@ describe("StationsPage", () => {
|
||||
await user.click(screen.getByRole("button", { name: "Apply" }));
|
||||
|
||||
await waitFor(() =>
|
||||
expect(apiTrendsDailyAveragesStationIdsGet).toHaveBeenCalledWith(
|
||||
expect(getDailyPriceAveragesByStationIdsMock).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
stationIds: ["00000000-0000-0000-0000-000000000001"],
|
||||
fuelType: "U91",
|
||||
query: expect.objectContaining({
|
||||
stationIds: ["00000000-0000-0000-0000-000000000001"],
|
||||
fuelType: "U91",
|
||||
}),
|
||||
}),
|
||||
),
|
||||
);
|
||||
@@ -164,26 +150,30 @@ describe("StationsPage (server prefetch)", () => {
|
||||
it("prefetches reference data and the initial station list on the server", async () => {
|
||||
renderWithProviders(<>{await StationsPage()}</>);
|
||||
|
||||
await waitFor(() => expect(apiBrandsAllGet).toHaveBeenCalled());
|
||||
await waitFor(() => expect(apiFuelTypesAllGet).toHaveBeenCalled());
|
||||
await waitFor(() => expect(getAllBrandsMock).toHaveBeenCalled());
|
||||
await waitFor(() => expect(getAllFuelTypesMock).toHaveBeenCalled());
|
||||
await waitFor(() =>
|
||||
expect(apiStationsWithPricesWithinRadiusGet).toHaveBeenCalledWith(
|
||||
expect(getStationsWithPricesWithinRadiusMock).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
pageNumber: 1,
|
||||
pageSize: 25,
|
||||
radiusInMetres: 10000,
|
||||
latitude: -33.856758,
|
||||
longitude: 151.215295,
|
||||
query: expect.objectContaining({
|
||||
pageNumber: 1,
|
||||
pageSize: 25,
|
||||
radiusInMetres: 10000,
|
||||
latitude: -33.856758,
|
||||
longitude: 151.215295,
|
||||
}),
|
||||
}),
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
it("passes the cookie fuel type to StationsClient so the select matches the server HTML", async () => {
|
||||
apiFuelTypesAllGet.mockResolvedValue([
|
||||
{ code: "U91", name: "Unleaded 91" },
|
||||
{ code: "P98", name: "Premium 98" },
|
||||
]);
|
||||
getAllFuelTypesMock.mockResolvedValue({
|
||||
data: [
|
||||
{ code: "U91", name: "Unleaded 91" },
|
||||
{ code: "P98", name: "Premium 98" },
|
||||
],
|
||||
});
|
||||
cookiesMock.mockResolvedValue({
|
||||
get: (name: string) =>
|
||||
name === "fw-preferences"
|
||||
@@ -209,8 +199,8 @@ describe("StationsPage (server prefetch)", () => {
|
||||
renderWithProviders(<>{await StationsPage()}</>);
|
||||
|
||||
await waitFor(() =>
|
||||
expect(apiStationsWithPricesWithinRadiusGet).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ fuelType: "P98" }),
|
||||
expect(getStationsWithPricesWithinRadiusMock).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ query: expect.objectContaining({ fuelType: "P98" }) }),
|
||||
),
|
||||
);
|
||||
});
|
||||
@@ -230,8 +220,10 @@ describe("StationsPage (server prefetch)", () => {
|
||||
renderWithProviders(<>{await StationsPage()}</>);
|
||||
|
||||
await waitFor(() =>
|
||||
expect(apiStationsWithPricesWithinRadiusGet).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ latitude: -33.87, longitude: 151.2 }),
|
||||
expect(getStationsWithPricesWithinRadiusMock).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
query: expect.objectContaining({ latitude: -33.87, longitude: 151.2 }),
|
||||
}),
|
||||
),
|
||||
);
|
||||
});
|
||||
@@ -243,6 +235,6 @@ describe("StationsPage (server prefetch)", () => {
|
||||
|
||||
renderWithProviders(<>{await StationsPage()}</>, { queryClient });
|
||||
|
||||
await waitFor(() => expect(apiStationsWithPricesWithinRadiusGet).toHaveBeenCalledTimes(1));
|
||||
await waitFor(() => expect(getStationsWithPricesWithinRadiusMock).toHaveBeenCalledTimes(1));
|
||||
});
|
||||
});
|
||||
@@ -1,6 +1,11 @@
|
||||
import { HydrationBoundary, QueryClient, dehydrate } from "@tanstack/react-query";
|
||||
import { cookies } from "next/headers";
|
||||
import { connection } from "next/server";
|
||||
import {
|
||||
getAllBrandsQueryKey,
|
||||
getAllFuelTypesQueryKey,
|
||||
} from "../../generated/@tanstack/react-query.gen";
|
||||
import { serverClient } from "../../lib/api.server";
|
||||
import { getBrands, getFuelTypes, getStationsWithPricesPage } from "../../lib/serverPrefetch";
|
||||
import { GetDefaultLocation, parsePreferences } from "../../utils/userPreferencesUtils";
|
||||
import type { Metadata } from "next";
|
||||
@@ -22,12 +27,12 @@ export default async function StationsPage() {
|
||||
|
||||
await Promise.all([
|
||||
queryClient.fetchQuery({
|
||||
queryKey: ["stationsPageBrands"],
|
||||
queryKey: getAllBrandsQueryKey({ client: serverClient }),
|
||||
queryFn: getBrands,
|
||||
retry: false,
|
||||
}),
|
||||
queryClient.fetchQuery({
|
||||
queryKey: ["stationsPageFuelTypes"],
|
||||
queryKey: getAllFuelTypesQueryKey({ client: serverClient }),
|
||||
queryFn: getFuelTypes,
|
||||
retry: false,
|
||||
}),
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
# OpenAPI Generator Ignore
|
||||
# Generated by openapi-generator https://github.com/openapitools/openapi-generator
|
||||
|
||||
# Use this file to prevent files from being overwritten by the generator.
|
||||
# The patterns follow closely to .gitignore or .dockerignore.
|
||||
|
||||
# As an example, the C# client generator defines ApiClient.cs.
|
||||
# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line:
|
||||
#ApiClient.cs
|
||||
|
||||
# You can match any string of characters against a directory, file or extension with a single asterisk (*):
|
||||
#foo/*/qux
|
||||
# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux
|
||||
|
||||
# You can recursively match patterns against a directory, file or extension with a double asterisk (**):
|
||||
#foo/**/qux
|
||||
# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux
|
||||
|
||||
# You can also negate patterns with an exclamation (!).
|
||||
# For example, you can ignore all files in a docs folder with the file extension .md:
|
||||
#docs/*.md
|
||||
# Then explicitly reverse the ignore rule for a single file:
|
||||
#!docs/README.md
|
||||
@@ -1,34 +0,0 @@
|
||||
apis/BrandApi.ts
|
||||
apis/FuelTypeApi.ts
|
||||
apis/PriceApi.ts
|
||||
apis/PriceTrendsApi.ts
|
||||
apis/StationApi.ts
|
||||
apis/StationWithPricesApi.ts
|
||||
apis/SuburbBoundaryApi.ts
|
||||
apis/index.ts
|
||||
index.ts
|
||||
models/ApiPricesCurrentGetPageNumberParameter.ts
|
||||
models/ApiPricesCurrentGetPageSizeParameter.ts
|
||||
models/ApiPricesCurrentStationGetStationCodeParameter.ts
|
||||
models/ApiStationsWithPricesLowestPricesByFuelTypeWithinRadiusGetPageSizeParameter.ts
|
||||
models/ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameter.ts
|
||||
models/BrandType.ts
|
||||
models/DailyPriceAverage.ts
|
||||
models/DailyPriceTrends.ts
|
||||
models/DailyPriceTrendsStatistics.ts
|
||||
models/DailyPriceTrendsStatisticsDailyAverageMax.ts
|
||||
models/FuelSource.ts
|
||||
models/FuelType.ts
|
||||
models/NumericReferencePoint.ts
|
||||
models/PaginationOfPrice.ts
|
||||
models/PaginationOfPricePageNumber.ts
|
||||
models/PaginationOfStation.ts
|
||||
models/PaginationOfStationWithPrices.ts
|
||||
models/Price.ts
|
||||
models/Station.ts
|
||||
models/StationWithPrices.ts
|
||||
models/Suburb.ts
|
||||
models/SuburbBoundary.ts
|
||||
models/SuburbBoundaryState.ts
|
||||
models/index.ts
|
||||
runtime.ts
|
||||
@@ -1 +0,0 @@
|
||||
7.8.0
|
||||
@@ -0,0 +1,641 @@
|
||||
// This file is auto-generated by @hey-api/openapi-ts
|
||||
|
||||
import { type DefaultError, type InfiniteData, infiniteQueryOptions, queryOptions } from '@tanstack/react-query';
|
||||
|
||||
import { client } from '../client.gen';
|
||||
import { getAllBrands, getAllCurrentPrices, getAllFuelTypes, getAllStations, getAllSuburbs, getBrandsByName, getBrandsByState, getCommonFuelTypes, getCurrentPricesByFuelType, getDailyPriceAverages, getDailyPriceAveragesByStationIds, getDailyPriceAveragesWithinRadius, getDailyPriceAveragesWithinSuburb, getLowestPricesByFuelType, getPricesByStationCode, getPricesForTimePeriod, getStationsByStationCode, getStationsWithinRadius, getStationsWithLowestPricesByFuelType, getStationsWithLowestPricesByFuelTypeWithinRadius, getStationsWithLowestPricesByFuelTypeWithinSuburb, getStationsWithPricesWithinRadius, getStationsWithPricesWithinSuburb, getStationWithPricesByStationCode, getSuburbBoundaryById, getSuburbBoundaryForLocation, getSuburbsByName, type Options } from '../sdk.gen';
|
||||
import type { GetAllBrandsData, GetAllBrandsResponse, GetAllCurrentPricesData, GetAllCurrentPricesResponse, GetAllFuelTypesData, GetAllFuelTypesResponse, GetAllStationsData, GetAllStationsResponse, GetAllSuburbsData, GetAllSuburbsResponse, GetBrandsByNameData, GetBrandsByNameResponse, GetBrandsByStateData, GetBrandsByStateResponse, GetCommonFuelTypesData, GetCommonFuelTypesResponse, GetCurrentPricesByFuelTypeData, GetCurrentPricesByFuelTypeResponse, GetDailyPriceAveragesByStationIdsData, GetDailyPriceAveragesByStationIdsResponse, GetDailyPriceAveragesData, GetDailyPriceAveragesResponse, GetDailyPriceAveragesWithinRadiusData, GetDailyPriceAveragesWithinRadiusResponse, GetDailyPriceAveragesWithinSuburbData, GetDailyPriceAveragesWithinSuburbResponse, GetLowestPricesByFuelTypeData, GetLowestPricesByFuelTypeResponse, GetPricesByStationCodeData, GetPricesByStationCodeResponse, GetPricesForTimePeriodData, GetPricesForTimePeriodResponse, GetStationsByStationCodeData, GetStationsByStationCodeResponse, GetStationsWithinRadiusData, GetStationsWithinRadiusResponse, GetStationsWithLowestPricesByFuelTypeData, GetStationsWithLowestPricesByFuelTypeResponse, GetStationsWithLowestPricesByFuelTypeWithinRadiusData, GetStationsWithLowestPricesByFuelTypeWithinRadiusResponse, GetStationsWithLowestPricesByFuelTypeWithinSuburbData, GetStationsWithLowestPricesByFuelTypeWithinSuburbResponse, GetStationsWithPricesWithinRadiusData, GetStationsWithPricesWithinRadiusResponse, GetStationsWithPricesWithinSuburbData, GetStationsWithPricesWithinSuburbResponse, GetStationWithPricesByStationCodeData, GetStationWithPricesByStationCodeResponse, GetSuburbBoundaryByIdData, GetSuburbBoundaryByIdResponse, GetSuburbBoundaryForLocationData, GetSuburbBoundaryForLocationResponse, GetSuburbsByNameData, GetSuburbsByNameResponse } from '../types.gen';
|
||||
|
||||
export type QueryKey<TOptions extends Options> = [
|
||||
Pick<TOptions, 'baseUrl' | 'body' | 'headers' | 'path' | 'query'> & {
|
||||
_id: string;
|
||||
_infinite?: boolean;
|
||||
tags?: ReadonlyArray<string>;
|
||||
}
|
||||
];
|
||||
|
||||
const createQueryKey = <TOptions extends Options>(id: string, options?: TOptions, infinite?: boolean, tags?: ReadonlyArray<string>): [
|
||||
QueryKey<TOptions>[0]
|
||||
] => {
|
||||
const params: QueryKey<TOptions>[0] = { _id: id, baseUrl: options?.baseUrl || (options?.client ?? client).getConfig().baseUrl } as QueryKey<TOptions>[0];
|
||||
if (infinite) {
|
||||
params._infinite = infinite;
|
||||
}
|
||||
if (tags) {
|
||||
params.tags = tags;
|
||||
}
|
||||
if (options?.body) {
|
||||
params.body = options.body;
|
||||
}
|
||||
if (options?.headers) {
|
||||
params.headers = options.headers;
|
||||
}
|
||||
if (options?.path) {
|
||||
params.path = options.path;
|
||||
}
|
||||
if (options?.query) {
|
||||
params.query = options.query;
|
||||
}
|
||||
return [params];
|
||||
};
|
||||
|
||||
export const getAllBrandsQueryKey = (options?: Options<GetAllBrandsData>) => createQueryKey('getAllBrands', options);
|
||||
|
||||
/**
|
||||
* Get all brands
|
||||
*
|
||||
* Retrieves a list of all available brands.
|
||||
*/
|
||||
export const getAllBrandsOptions = (options?: Options<GetAllBrandsData>) => queryOptions<GetAllBrandsResponse, DefaultError, GetAllBrandsResponse, ReturnType<typeof getAllBrandsQueryKey>>({
|
||||
queryFn: async ({ queryKey, signal }) => {
|
||||
const { data } = await getAllBrands({
|
||||
...options,
|
||||
...queryKey[0],
|
||||
signal,
|
||||
throwOnError: true
|
||||
});
|
||||
return data;
|
||||
},
|
||||
queryKey: getAllBrandsQueryKey(options)
|
||||
});
|
||||
|
||||
export const getBrandsByStateQueryKey = (options?: Options<GetBrandsByStateData>) => createQueryKey('getBrandsByState', options);
|
||||
|
||||
/**
|
||||
* Get brands by state
|
||||
*
|
||||
* Retrieves a list of all brands by the state they are located in.
|
||||
*/
|
||||
export const getBrandsByStateOptions = (options?: Options<GetBrandsByStateData>) => queryOptions<GetBrandsByStateResponse, DefaultError, GetBrandsByStateResponse, ReturnType<typeof getBrandsByStateQueryKey>>({
|
||||
queryFn: async ({ queryKey, signal }) => {
|
||||
const { data } = await getBrandsByState({
|
||||
...options,
|
||||
...queryKey[0],
|
||||
signal,
|
||||
throwOnError: true
|
||||
});
|
||||
return data;
|
||||
},
|
||||
queryKey: getBrandsByStateQueryKey(options)
|
||||
});
|
||||
|
||||
export const getBrandsByNameQueryKey = (options?: Options<GetBrandsByNameData>) => createQueryKey('getBrandsByName', options);
|
||||
|
||||
/**
|
||||
* Get brands by name
|
||||
*
|
||||
* Retrieves a list of all available brands, where the brand name contains the provided search string. Case-insensitive.
|
||||
*/
|
||||
export const getBrandsByNameOptions = (options?: Options<GetBrandsByNameData>) => queryOptions<GetBrandsByNameResponse, DefaultError, GetBrandsByNameResponse, ReturnType<typeof getBrandsByNameQueryKey>>({
|
||||
queryFn: async ({ queryKey, signal }) => {
|
||||
const { data } = await getBrandsByName({
|
||||
...options,
|
||||
...queryKey[0],
|
||||
signal,
|
||||
throwOnError: true
|
||||
});
|
||||
return data;
|
||||
},
|
||||
queryKey: getBrandsByNameQueryKey(options)
|
||||
});
|
||||
|
||||
export const getAllFuelTypesQueryKey = (options?: Options<GetAllFuelTypesData>) => createQueryKey('getAllFuelTypes', options);
|
||||
|
||||
/**
|
||||
* Get all fuel types
|
||||
*
|
||||
* Retrieves a list of all available fuel types.
|
||||
*/
|
||||
export const getAllFuelTypesOptions = (options?: Options<GetAllFuelTypesData>) => queryOptions<GetAllFuelTypesResponse, DefaultError, GetAllFuelTypesResponse, ReturnType<typeof getAllFuelTypesQueryKey>>({
|
||||
queryFn: async ({ queryKey, signal }) => {
|
||||
const { data } = await getAllFuelTypes({
|
||||
...options,
|
||||
...queryKey[0],
|
||||
signal,
|
||||
throwOnError: true
|
||||
});
|
||||
return data;
|
||||
},
|
||||
queryKey: getAllFuelTypesQueryKey(options)
|
||||
});
|
||||
|
||||
export const getCommonFuelTypesQueryKey = (options?: Options<GetCommonFuelTypesData>) => createQueryKey('getCommonFuelTypes', options);
|
||||
|
||||
/**
|
||||
* Get common fuel types
|
||||
*
|
||||
* Retrieves a list of the most common fuel types.
|
||||
*/
|
||||
export const getCommonFuelTypesOptions = (options?: Options<GetCommonFuelTypesData>) => queryOptions<GetCommonFuelTypesResponse, DefaultError, GetCommonFuelTypesResponse, ReturnType<typeof getCommonFuelTypesQueryKey>>({
|
||||
queryFn: async ({ queryKey, signal }) => {
|
||||
const { data } = await getCommonFuelTypes({
|
||||
...options,
|
||||
...queryKey[0],
|
||||
signal,
|
||||
throwOnError: true
|
||||
});
|
||||
return data;
|
||||
},
|
||||
queryKey: getCommonFuelTypesQueryKey(options)
|
||||
});
|
||||
|
||||
export const getAllCurrentPricesQueryKey = (options?: Options<GetAllCurrentPricesData>) => createQueryKey('getAllCurrentPrices', options);
|
||||
|
||||
/**
|
||||
* Get all most recent prices
|
||||
*
|
||||
* Retrieves a list of all available prices, with only the most recent displayed.
|
||||
*/
|
||||
export const getAllCurrentPricesOptions = (options?: Options<GetAllCurrentPricesData>) => queryOptions<GetAllCurrentPricesResponse, DefaultError, GetAllCurrentPricesResponse, ReturnType<typeof getAllCurrentPricesQueryKey>>({
|
||||
queryFn: async ({ queryKey, signal }) => {
|
||||
const { data } = await getAllCurrentPrices({
|
||||
...options,
|
||||
...queryKey[0],
|
||||
signal,
|
||||
throwOnError: true
|
||||
});
|
||||
return data;
|
||||
},
|
||||
queryKey: getAllCurrentPricesQueryKey(options)
|
||||
});
|
||||
|
||||
export const getPricesByStationCodeQueryKey = (options?: Options<GetPricesByStationCodeData>) => createQueryKey('getPricesByStationCode', options);
|
||||
|
||||
/**
|
||||
* Get current prices by station code
|
||||
*
|
||||
* Retrieves a list of all current prices for the station with the code provided. The optional state narrows the lookup to a single state.
|
||||
*/
|
||||
export const getPricesByStationCodeOptions = (options?: Options<GetPricesByStationCodeData>) => queryOptions<GetPricesByStationCodeResponse, DefaultError, GetPricesByStationCodeResponse, ReturnType<typeof getPricesByStationCodeQueryKey>>({
|
||||
queryFn: async ({ queryKey, signal }) => {
|
||||
const { data } = await getPricesByStationCode({
|
||||
...options,
|
||||
...queryKey[0],
|
||||
signal,
|
||||
throwOnError: true
|
||||
});
|
||||
return data;
|
||||
},
|
||||
queryKey: getPricesByStationCodeQueryKey(options)
|
||||
});
|
||||
|
||||
export const getCurrentPricesByFuelTypeQueryKey = (options?: Options<GetCurrentPricesByFuelTypeData>) => createQueryKey('getCurrentPricesByFuelType', options);
|
||||
|
||||
/**
|
||||
* Get all most recent prices by fuel type
|
||||
*
|
||||
* Retrieves a list of all most recent prices for the provided fuel type.
|
||||
*/
|
||||
export const getCurrentPricesByFuelTypeOptions = (options?: Options<GetCurrentPricesByFuelTypeData>) => queryOptions<GetCurrentPricesByFuelTypeResponse, DefaultError, GetCurrentPricesByFuelTypeResponse, ReturnType<typeof getCurrentPricesByFuelTypeQueryKey>>({
|
||||
queryFn: async ({ queryKey, signal }) => {
|
||||
const { data } = await getCurrentPricesByFuelType({
|
||||
...options,
|
||||
...queryKey[0],
|
||||
signal,
|
||||
throwOnError: true
|
||||
});
|
||||
return data;
|
||||
},
|
||||
queryKey: getCurrentPricesByFuelTypeQueryKey(options)
|
||||
});
|
||||
|
||||
export const getLowestPricesByFuelTypeQueryKey = (options?: Options<GetLowestPricesByFuelTypeData>) => createQueryKey('getLowestPricesByFuelType', options);
|
||||
|
||||
/**
|
||||
* Get lowest prices by fuel type
|
||||
*
|
||||
* Retrieves a list of the lowest prices for the provided fuel type.
|
||||
*/
|
||||
export const getLowestPricesByFuelTypeOptions = (options?: Options<GetLowestPricesByFuelTypeData>) => queryOptions<GetLowestPricesByFuelTypeResponse, DefaultError, GetLowestPricesByFuelTypeResponse, ReturnType<typeof getLowestPricesByFuelTypeQueryKey>>({
|
||||
queryFn: async ({ queryKey, signal }) => {
|
||||
const { data } = await getLowestPricesByFuelType({
|
||||
...options,
|
||||
...queryKey[0],
|
||||
signal,
|
||||
throwOnError: true
|
||||
});
|
||||
return data;
|
||||
},
|
||||
queryKey: getLowestPricesByFuelTypeQueryKey(options)
|
||||
});
|
||||
|
||||
export const getPricesForTimePeriodQueryKey = (options?: Options<GetPricesForTimePeriodData>) => createQueryKey('getPricesForTimePeriod', options);
|
||||
|
||||
/**
|
||||
* Get prices for a specific time period
|
||||
*
|
||||
* Retrieves a list of prices aggregated by a default time bucket of one day. Time values are UTC, in ISO 8601 format: yyyy-MM-ddTHH:mm:ss.SSSZ
|
||||
*/
|
||||
export const getPricesForTimePeriodOptions = (options?: Options<GetPricesForTimePeriodData>) => queryOptions<GetPricesForTimePeriodResponse, DefaultError, GetPricesForTimePeriodResponse, ReturnType<typeof getPricesForTimePeriodQueryKey>>({
|
||||
queryFn: async ({ queryKey, signal }) => {
|
||||
const { data } = await getPricesForTimePeriod({
|
||||
...options,
|
||||
...queryKey[0],
|
||||
signal,
|
||||
throwOnError: true
|
||||
});
|
||||
return data;
|
||||
},
|
||||
queryKey: getPricesForTimePeriodQueryKey(options)
|
||||
});
|
||||
|
||||
const createInfiniteParams = <K extends Pick<QueryKey<Options>[0], 'body' | 'headers' | 'path' | 'query'>>(queryKey: QueryKey<Options>, page: K) => {
|
||||
const params = { ...queryKey[0] };
|
||||
if (page.body) {
|
||||
params.body = {
|
||||
...queryKey[0].body as any,
|
||||
...page.body as any
|
||||
};
|
||||
}
|
||||
if (page.headers) {
|
||||
params.headers = {
|
||||
...queryKey[0].headers,
|
||||
...page.headers
|
||||
};
|
||||
}
|
||||
if (page.path) {
|
||||
params.path = {
|
||||
...queryKey[0].path as any,
|
||||
...page.path as any
|
||||
};
|
||||
}
|
||||
if (page.query) {
|
||||
params.query = {
|
||||
...queryKey[0].query as any,
|
||||
...page.query as any
|
||||
};
|
||||
}
|
||||
return params as unknown as typeof page;
|
||||
};
|
||||
|
||||
export const getPricesForTimePeriodInfiniteQueryKey = (options?: Options<GetPricesForTimePeriodData>): QueryKey<Options<GetPricesForTimePeriodData>> => createQueryKey('getPricesForTimePeriod', options, true);
|
||||
|
||||
/**
|
||||
* Get prices for a specific time period
|
||||
*
|
||||
* Retrieves a list of prices aggregated by a default time bucket of one day. Time values are UTC, in ISO 8601 format: yyyy-MM-ddTHH:mm:ss.SSSZ
|
||||
*/
|
||||
export const getPricesForTimePeriodInfiniteOptions = (options?: Options<GetPricesForTimePeriodData>) => {
|
||||
const opts = infiniteQueryOptions<GetPricesForTimePeriodResponse, DefaultError, InfiniteData<GetPricesForTimePeriodResponse>, QueryKey<Options<GetPricesForTimePeriodData>>, string | Pick<QueryKey<Options<GetPricesForTimePeriodData>>[0], 'body' | 'headers' | 'path' | 'query'>>(
|
||||
// @ts-ignore
|
||||
{
|
||||
queryFn: async ({ pageParam, queryKey, signal }) => {
|
||||
// @ts-ignore
|
||||
const page: Pick<QueryKey<Options<GetPricesForTimePeriodData>>[0], 'body' | 'headers' | 'path' | 'query'> = typeof pageParam === 'object' ? pageParam : {
|
||||
query: {
|
||||
start: pageParam
|
||||
}
|
||||
};
|
||||
const params = createInfiniteParams(queryKey, page);
|
||||
const { data } = await getPricesForTimePeriod({
|
||||
...options,
|
||||
...params,
|
||||
signal,
|
||||
throwOnError: true
|
||||
});
|
||||
return data;
|
||||
},
|
||||
queryKey: getPricesForTimePeriodInfiniteQueryKey(options)
|
||||
});
|
||||
return opts as Omit<typeof opts, 'initialData'>;
|
||||
};
|
||||
|
||||
export const getDailyPriceAveragesQueryKey = (options?: Options<GetDailyPriceAveragesData>) => createQueryKey('getDailyPriceAverages', options);
|
||||
|
||||
/**
|
||||
* Get a list of daily price averages
|
||||
*
|
||||
* Retrieves a list of days, and the average price for that day, within the given period, and for the fuel type specified.
|
||||
*/
|
||||
export const getDailyPriceAveragesOptions = (options?: Options<GetDailyPriceAveragesData>) => queryOptions<GetDailyPriceAveragesResponse, DefaultError, GetDailyPriceAveragesResponse, ReturnType<typeof getDailyPriceAveragesQueryKey>>({
|
||||
queryFn: async ({ queryKey, signal }) => {
|
||||
const { data } = await getDailyPriceAverages({
|
||||
...options,
|
||||
...queryKey[0],
|
||||
signal,
|
||||
throwOnError: true
|
||||
});
|
||||
return data;
|
||||
},
|
||||
queryKey: getDailyPriceAveragesQueryKey(options)
|
||||
});
|
||||
|
||||
export const getDailyPriceAveragesWithinRadiusQueryKey = (options?: Options<GetDailyPriceAveragesWithinRadiusData>) => createQueryKey('getDailyPriceAveragesWithinRadius', options);
|
||||
|
||||
/**
|
||||
* Get a list of daily price averages for stations within a given radius
|
||||
*
|
||||
* Retrieves a list of days, and the average price for that day, within the given period, and for the fuel type and brand specified. Only stations within the given radius are included in the calculations.
|
||||
*/
|
||||
export const getDailyPriceAveragesWithinRadiusOptions = (options?: Options<GetDailyPriceAveragesWithinRadiusData>) => queryOptions<GetDailyPriceAveragesWithinRadiusResponse, DefaultError, GetDailyPriceAveragesWithinRadiusResponse, ReturnType<typeof getDailyPriceAveragesWithinRadiusQueryKey>>({
|
||||
queryFn: async ({ queryKey, signal }) => {
|
||||
const { data } = await getDailyPriceAveragesWithinRadius({
|
||||
...options,
|
||||
...queryKey[0],
|
||||
signal,
|
||||
throwOnError: true
|
||||
});
|
||||
return data;
|
||||
},
|
||||
queryKey: getDailyPriceAveragesWithinRadiusQueryKey(options)
|
||||
});
|
||||
|
||||
export const getDailyPriceAveragesWithinSuburbQueryKey = (options?: Options<GetDailyPriceAveragesWithinSuburbData>) => createQueryKey('getDailyPriceAveragesWithinSuburb', options);
|
||||
|
||||
/**
|
||||
* Get a list of daily price averages for stations within a suburb
|
||||
*
|
||||
* Retrieves a list of days, and the average price for that day, within the given period, and for the fuel type specified. Only stations within the specified suburb are included in the calculations.
|
||||
*/
|
||||
export const getDailyPriceAveragesWithinSuburbOptions = (options?: Options<GetDailyPriceAveragesWithinSuburbData>) => queryOptions<GetDailyPriceAveragesWithinSuburbResponse, DefaultError, GetDailyPriceAveragesWithinSuburbResponse, ReturnType<typeof getDailyPriceAveragesWithinSuburbQueryKey>>({
|
||||
queryFn: async ({ queryKey, signal }) => {
|
||||
const { data } = await getDailyPriceAveragesWithinSuburb({
|
||||
...options,
|
||||
...queryKey[0],
|
||||
signal,
|
||||
throwOnError: true
|
||||
});
|
||||
return data;
|
||||
},
|
||||
queryKey: getDailyPriceAveragesWithinSuburbQueryKey(options)
|
||||
});
|
||||
|
||||
export const getDailyPriceAveragesByStationIdsQueryKey = (options?: Options<GetDailyPriceAveragesByStationIdsData>) => createQueryKey('getDailyPriceAveragesByStationIds', options);
|
||||
|
||||
/**
|
||||
* Get a history of daily prices for the selected stations
|
||||
*
|
||||
* Retrieves a list of days, and the price averages for the fuel type on that day across the station ids specified, within the given period.
|
||||
*/
|
||||
export const getDailyPriceAveragesByStationIdsOptions = (options?: Options<GetDailyPriceAveragesByStationIdsData>) => queryOptions<GetDailyPriceAveragesByStationIdsResponse, DefaultError, GetDailyPriceAveragesByStationIdsResponse, ReturnType<typeof getDailyPriceAveragesByStationIdsQueryKey>>({
|
||||
queryFn: async ({ queryKey, signal }) => {
|
||||
const { data } = await getDailyPriceAveragesByStationIds({
|
||||
...options,
|
||||
...queryKey[0],
|
||||
signal,
|
||||
throwOnError: true
|
||||
});
|
||||
return data;
|
||||
},
|
||||
queryKey: getDailyPriceAveragesByStationIdsQueryKey(options)
|
||||
});
|
||||
|
||||
export const getAllStationsQueryKey = (options?: Options<GetAllStationsData>) => createQueryKey('getAllStations', options);
|
||||
|
||||
/**
|
||||
* Get all stations
|
||||
*
|
||||
* Retrieves a list of all available stations.
|
||||
*/
|
||||
export const getAllStationsOptions = (options?: Options<GetAllStationsData>) => queryOptions<GetAllStationsResponse, DefaultError, GetAllStationsResponse, ReturnType<typeof getAllStationsQueryKey>>({
|
||||
queryFn: async ({ queryKey, signal }) => {
|
||||
const { data } = await getAllStations({
|
||||
...options,
|
||||
...queryKey[0],
|
||||
signal,
|
||||
throwOnError: true
|
||||
});
|
||||
return data;
|
||||
},
|
||||
queryKey: getAllStationsQueryKey(options)
|
||||
});
|
||||
|
||||
export const getStationsByStationCodeQueryKey = (options?: Options<GetStationsByStationCodeData>) => createQueryKey('getStationsByStationCode', options);
|
||||
|
||||
/**
|
||||
* Get a station by station code
|
||||
*
|
||||
* Retrieves a single station, where the station code is equal to the provided station code. The optional state narrows the lookup to a single state.
|
||||
*/
|
||||
export const getStationsByStationCodeOptions = (options?: Options<GetStationsByStationCodeData>) => queryOptions<GetStationsByStationCodeResponse, DefaultError, GetStationsByStationCodeResponse, ReturnType<typeof getStationsByStationCodeQueryKey>>({
|
||||
queryFn: async ({ queryKey, signal }) => {
|
||||
const { data } = await getStationsByStationCode({
|
||||
...options,
|
||||
...queryKey[0],
|
||||
signal,
|
||||
throwOnError: true
|
||||
});
|
||||
return data;
|
||||
},
|
||||
queryKey: getStationsByStationCodeQueryKey(options)
|
||||
});
|
||||
|
||||
export const getStationsWithinRadiusQueryKey = (options?: Options<GetStationsWithinRadiusData>) => createQueryKey('getStationsWithinRadius', options);
|
||||
|
||||
/**
|
||||
* Get stations within radius
|
||||
*
|
||||
* Retrieves a list of all stations within the area described by a circle with centre at the provided coordinates and a radius of the provided value in metres.
|
||||
*/
|
||||
export const getStationsWithinRadiusOptions = (options?: Options<GetStationsWithinRadiusData>) => queryOptions<GetStationsWithinRadiusResponse, DefaultError, GetStationsWithinRadiusResponse, ReturnType<typeof getStationsWithinRadiusQueryKey>>({
|
||||
queryFn: async ({ queryKey, signal }) => {
|
||||
const { data } = await getStationsWithinRadius({
|
||||
...options,
|
||||
...queryKey[0],
|
||||
signal,
|
||||
throwOnError: true
|
||||
});
|
||||
return data;
|
||||
},
|
||||
queryKey: getStationsWithinRadiusQueryKey(options)
|
||||
});
|
||||
|
||||
export const getStationWithPricesByStationCodeQueryKey = (options?: Options<GetStationWithPricesByStationCodeData>) => createQueryKey('getStationWithPricesByStationCode', options);
|
||||
|
||||
/**
|
||||
* Get a station with prices by station code
|
||||
*
|
||||
* Retrieves a single station along with its current prices, where the station code is equal to the provided station code. The optional state narrows the lookup to a single state.
|
||||
*/
|
||||
export const getStationWithPricesByStationCodeOptions = (options?: Options<GetStationWithPricesByStationCodeData>) => queryOptions<GetStationWithPricesByStationCodeResponse, DefaultError, GetStationWithPricesByStationCodeResponse, ReturnType<typeof getStationWithPricesByStationCodeQueryKey>>({
|
||||
queryFn: async ({ queryKey, signal }) => {
|
||||
const { data } = await getStationWithPricesByStationCode({
|
||||
...options,
|
||||
...queryKey[0],
|
||||
signal,
|
||||
throwOnError: true
|
||||
});
|
||||
return data;
|
||||
},
|
||||
queryKey: getStationWithPricesByStationCodeQueryKey(options)
|
||||
});
|
||||
|
||||
export const getStationsWithPricesWithinRadiusQueryKey = (options?: Options<GetStationsWithPricesWithinRadiusData>) => createQueryKey('getStationsWithPricesWithinRadius', options);
|
||||
|
||||
/**
|
||||
* Get stations with prices within radius
|
||||
*
|
||||
* Retrieves a list of all stations within a specified radius of a given location along with their current prices.
|
||||
*/
|
||||
export const getStationsWithPricesWithinRadiusOptions = (options?: Options<GetStationsWithPricesWithinRadiusData>) => queryOptions<GetStationsWithPricesWithinRadiusResponse, DefaultError, GetStationsWithPricesWithinRadiusResponse, ReturnType<typeof getStationsWithPricesWithinRadiusQueryKey>>({
|
||||
queryFn: async ({ queryKey, signal }) => {
|
||||
const { data } = await getStationsWithPricesWithinRadius({
|
||||
...options,
|
||||
...queryKey[0],
|
||||
signal,
|
||||
throwOnError: true
|
||||
});
|
||||
return data;
|
||||
},
|
||||
queryKey: getStationsWithPricesWithinRadiusQueryKey(options)
|
||||
});
|
||||
|
||||
export const getStationsWithPricesWithinSuburbQueryKey = (options?: Options<GetStationsWithPricesWithinSuburbData>) => createQueryKey('getStationsWithPricesWithinSuburb', options);
|
||||
|
||||
/**
|
||||
* Get stations with prices within a suburb
|
||||
*
|
||||
* Retrieves a list of all stations within a specified suburb boundary along with their current prices.
|
||||
*/
|
||||
export const getStationsWithPricesWithinSuburbOptions = (options?: Options<GetStationsWithPricesWithinSuburbData>) => queryOptions<GetStationsWithPricesWithinSuburbResponse, DefaultError, GetStationsWithPricesWithinSuburbResponse, ReturnType<typeof getStationsWithPricesWithinSuburbQueryKey>>({
|
||||
queryFn: async ({ queryKey, signal }) => {
|
||||
const { data } = await getStationsWithPricesWithinSuburb({
|
||||
...options,
|
||||
...queryKey[0],
|
||||
signal,
|
||||
throwOnError: true
|
||||
});
|
||||
return data;
|
||||
},
|
||||
queryKey: getStationsWithPricesWithinSuburbQueryKey(options)
|
||||
});
|
||||
|
||||
export const getStationsWithLowestPricesByFuelTypeQueryKey = (options?: Options<GetStationsWithLowestPricesByFuelTypeData>) => createQueryKey('getStationsWithLowestPricesByFuelType', options);
|
||||
|
||||
/**
|
||||
* Get stations with lowest prices by fuel type
|
||||
*
|
||||
* Retrieves a list of stations with the lowest prices for a specific fuel type.
|
||||
*/
|
||||
export const getStationsWithLowestPricesByFuelTypeOptions = (options?: Options<GetStationsWithLowestPricesByFuelTypeData>) => queryOptions<GetStationsWithLowestPricesByFuelTypeResponse, DefaultError, GetStationsWithLowestPricesByFuelTypeResponse, ReturnType<typeof getStationsWithLowestPricesByFuelTypeQueryKey>>({
|
||||
queryFn: async ({ queryKey, signal }) => {
|
||||
const { data } = await getStationsWithLowestPricesByFuelType({
|
||||
...options,
|
||||
...queryKey[0],
|
||||
signal,
|
||||
throwOnError: true
|
||||
});
|
||||
return data;
|
||||
},
|
||||
queryKey: getStationsWithLowestPricesByFuelTypeQueryKey(options)
|
||||
});
|
||||
|
||||
export const getStationsWithLowestPricesByFuelTypeWithinRadiusQueryKey = (options?: Options<GetStationsWithLowestPricesByFuelTypeWithinRadiusData>) => createQueryKey('getStationsWithLowestPricesByFuelTypeWithinRadius', options);
|
||||
|
||||
/**
|
||||
* Get stations with lowest prices by fuel type, within a radius
|
||||
*
|
||||
* Retrieves a list of stations with the lowest prices for a specific fuel type, within the specified radius.
|
||||
*/
|
||||
export const getStationsWithLowestPricesByFuelTypeWithinRadiusOptions = (options?: Options<GetStationsWithLowestPricesByFuelTypeWithinRadiusData>) => queryOptions<GetStationsWithLowestPricesByFuelTypeWithinRadiusResponse, DefaultError, GetStationsWithLowestPricesByFuelTypeWithinRadiusResponse, ReturnType<typeof getStationsWithLowestPricesByFuelTypeWithinRadiusQueryKey>>({
|
||||
queryFn: async ({ queryKey, signal }) => {
|
||||
const { data } = await getStationsWithLowestPricesByFuelTypeWithinRadius({
|
||||
...options,
|
||||
...queryKey[0],
|
||||
signal,
|
||||
throwOnError: true
|
||||
});
|
||||
return data;
|
||||
},
|
||||
queryKey: getStationsWithLowestPricesByFuelTypeWithinRadiusQueryKey(options)
|
||||
});
|
||||
|
||||
export const getStationsWithLowestPricesByFuelTypeWithinSuburbQueryKey = (options?: Options<GetStationsWithLowestPricesByFuelTypeWithinSuburbData>) => createQueryKey('getStationsWithLowestPricesByFuelTypeWithinSuburb', options);
|
||||
|
||||
/**
|
||||
* Get stations with lowest prices by fuel type, within a suburb
|
||||
*
|
||||
* Retrieves a list of stations with the lowest prices for a specific fuel type, within the specified suburb.
|
||||
*/
|
||||
export const getStationsWithLowestPricesByFuelTypeWithinSuburbOptions = (options?: Options<GetStationsWithLowestPricesByFuelTypeWithinSuburbData>) => queryOptions<GetStationsWithLowestPricesByFuelTypeWithinSuburbResponse, DefaultError, GetStationsWithLowestPricesByFuelTypeWithinSuburbResponse, ReturnType<typeof getStationsWithLowestPricesByFuelTypeWithinSuburbQueryKey>>({
|
||||
queryFn: async ({ queryKey, signal }) => {
|
||||
const { data } = await getStationsWithLowestPricesByFuelTypeWithinSuburb({
|
||||
...options,
|
||||
...queryKey[0],
|
||||
signal,
|
||||
throwOnError: true
|
||||
});
|
||||
return data;
|
||||
},
|
||||
queryKey: getStationsWithLowestPricesByFuelTypeWithinSuburbQueryKey(options)
|
||||
});
|
||||
|
||||
export const getAllSuburbsQueryKey = (options?: Options<GetAllSuburbsData>) => createQueryKey('getAllSuburbs', options);
|
||||
|
||||
/**
|
||||
* Get the ID, Name, and State for every Suburb in the DB.
|
||||
*
|
||||
* Retrieves a list of all of the suburbs available. Optionally filtered by state (lowercase code: nsw, vic, wa, act, tas).
|
||||
*/
|
||||
export const getAllSuburbsOptions = (options?: Options<GetAllSuburbsData>) => queryOptions<GetAllSuburbsResponse, DefaultError, GetAllSuburbsResponse, ReturnType<typeof getAllSuburbsQueryKey>>({
|
||||
queryFn: async ({ queryKey, signal }) => {
|
||||
const { data } = await getAllSuburbs({
|
||||
...options,
|
||||
...queryKey[0],
|
||||
signal,
|
||||
throwOnError: true
|
||||
});
|
||||
return data;
|
||||
},
|
||||
queryKey: getAllSuburbsQueryKey(options)
|
||||
});
|
||||
|
||||
export const getSuburbsByNameQueryKey = (options?: Options<GetSuburbsByNameData>) => createQueryKey('getSuburbsByName', options);
|
||||
|
||||
/**
|
||||
* Search for Suburbs in the DB by name
|
||||
*
|
||||
* Retrieves a list of all of the Suburbs that contain the name input. Optionally filtered by state (lowercase code: nsw, vic, wa, act, tas).
|
||||
*/
|
||||
export const getSuburbsByNameOptions = (options?: Options<GetSuburbsByNameData>) => queryOptions<GetSuburbsByNameResponse, DefaultError, GetSuburbsByNameResponse, ReturnType<typeof getSuburbsByNameQueryKey>>({
|
||||
queryFn: async ({ queryKey, signal }) => {
|
||||
const { data } = await getSuburbsByName({
|
||||
...options,
|
||||
...queryKey[0],
|
||||
signal,
|
||||
throwOnError: true
|
||||
});
|
||||
return data;
|
||||
},
|
||||
queryKey: getSuburbsByNameQueryKey(options)
|
||||
});
|
||||
|
||||
export const getSuburbBoundaryByIdQueryKey = (options?: Options<GetSuburbBoundaryByIdData>) => createQueryKey('getSuburbBoundaryById', options);
|
||||
|
||||
/**
|
||||
* Return a single SuburbBoundary
|
||||
*
|
||||
* Retrieves the single SuburbBoundary, which matches the input ID.
|
||||
*/
|
||||
export const getSuburbBoundaryByIdOptions = (options?: Options<GetSuburbBoundaryByIdData>) => queryOptions<GetSuburbBoundaryByIdResponse, DefaultError, GetSuburbBoundaryByIdResponse, ReturnType<typeof getSuburbBoundaryByIdQueryKey>>({
|
||||
queryFn: async ({ queryKey, signal }) => {
|
||||
const { data } = await getSuburbBoundaryById({
|
||||
...options,
|
||||
...queryKey[0],
|
||||
signal,
|
||||
throwOnError: true
|
||||
});
|
||||
return data;
|
||||
},
|
||||
queryKey: getSuburbBoundaryByIdQueryKey(options)
|
||||
});
|
||||
|
||||
export const getSuburbBoundaryForLocationQueryKey = (options?: Options<GetSuburbBoundaryForLocationData>) => createQueryKey('getSuburbBoundaryForLocation', options);
|
||||
|
||||
/**
|
||||
* Return the SuburbBoundary for a location
|
||||
*
|
||||
* Retrieves the single SuburbBoundary containing the provided latitude and longitude coordinates.
|
||||
*/
|
||||
export const getSuburbBoundaryForLocationOptions = (options?: Options<GetSuburbBoundaryForLocationData>) => queryOptions<GetSuburbBoundaryForLocationResponse, DefaultError, GetSuburbBoundaryForLocationResponse, ReturnType<typeof getSuburbBoundaryForLocationQueryKey>>({
|
||||
queryFn: async ({ queryKey, signal }) => {
|
||||
const { data } = await getSuburbBoundaryForLocation({
|
||||
...options,
|
||||
...queryKey[0],
|
||||
signal,
|
||||
throwOnError: true
|
||||
});
|
||||
return data;
|
||||
},
|
||||
queryKey: getSuburbBoundaryForLocationQueryKey(options)
|
||||
});
|
||||
@@ -1,130 +0,0 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* FuelWizardApi | v1
|
||||
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
||||
*
|
||||
* The version of the OpenAPI document: 1.0.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
|
||||
import * as runtime from '../runtime';
|
||||
import type {
|
||||
BrandType,
|
||||
} from '../models/index';
|
||||
import {
|
||||
BrandTypeFromJSON,
|
||||
BrandTypeToJSON,
|
||||
} from '../models/index';
|
||||
|
||||
export interface ApiBrandsNameGetRequest {
|
||||
name?: string;
|
||||
}
|
||||
|
||||
export interface ApiBrandsStateGetRequest {
|
||||
state?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export class BrandApi extends runtime.BaseAPI {
|
||||
|
||||
/**
|
||||
* Retrieves a list of all available brands.
|
||||
* Get all brands
|
||||
*/
|
||||
async apiBrandsAllGetRaw(initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<Array<BrandType>>> {
|
||||
const queryParameters: any = {};
|
||||
|
||||
const headerParameters: runtime.HTTPHeaders = {};
|
||||
|
||||
const response = await this.request({
|
||||
path: `/api/brands/all`,
|
||||
method: 'GET',
|
||||
headers: headerParameters,
|
||||
query: queryParameters,
|
||||
}, initOverrides);
|
||||
|
||||
return new runtime.JSONApiResponse(response, (jsonValue) => jsonValue.map(BrandTypeFromJSON));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a list of all available brands.
|
||||
* Get all brands
|
||||
*/
|
||||
async apiBrandsAllGet(initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<Array<BrandType>> {
|
||||
const response = await this.apiBrandsAllGetRaw(initOverrides);
|
||||
return await response.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a list of all available brands, where the brand name contains the provided search string. Case-insensitive.
|
||||
* Get brands by name
|
||||
*/
|
||||
async apiBrandsNameGetRaw(requestParameters: ApiBrandsNameGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<Array<BrandType>>> {
|
||||
const queryParameters: any = {};
|
||||
|
||||
if (requestParameters['name'] != null) {
|
||||
queryParameters['name'] = requestParameters['name'];
|
||||
}
|
||||
|
||||
const headerParameters: runtime.HTTPHeaders = {};
|
||||
|
||||
const response = await this.request({
|
||||
path: `/api/brands/name`,
|
||||
method: 'GET',
|
||||
headers: headerParameters,
|
||||
query: queryParameters,
|
||||
}, initOverrides);
|
||||
|
||||
return new runtime.JSONApiResponse(response, (jsonValue) => jsonValue.map(BrandTypeFromJSON));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a list of all available brands, where the brand name contains the provided search string. Case-insensitive.
|
||||
* Get brands by name
|
||||
*/
|
||||
async apiBrandsNameGet(requestParameters: ApiBrandsNameGetRequest = {}, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<Array<BrandType>> {
|
||||
const response = await this.apiBrandsNameGetRaw(requestParameters, initOverrides);
|
||||
return await response.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a list of all brands by the state they are located in.
|
||||
* Get brands by state
|
||||
*/
|
||||
async apiBrandsStateGetRaw(requestParameters: ApiBrandsStateGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<Array<BrandType>>> {
|
||||
const queryParameters: any = {};
|
||||
|
||||
if (requestParameters['state'] != null) {
|
||||
queryParameters['state'] = requestParameters['state'];
|
||||
}
|
||||
|
||||
const headerParameters: runtime.HTTPHeaders = {};
|
||||
|
||||
const response = await this.request({
|
||||
path: `/api/brands/state`,
|
||||
method: 'GET',
|
||||
headers: headerParameters,
|
||||
query: queryParameters,
|
||||
}, initOverrides);
|
||||
|
||||
return new runtime.JSONApiResponse(response, (jsonValue) => jsonValue.map(BrandTypeFromJSON));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a list of all brands by the state they are located in.
|
||||
* Get brands by state
|
||||
*/
|
||||
async apiBrandsStateGet(requestParameters: ApiBrandsStateGetRequest = {}, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<Array<BrandType>> {
|
||||
const response = await this.apiBrandsStateGetRaw(requestParameters, initOverrides);
|
||||
return await response.value();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* FuelWizardApi | v1
|
||||
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
||||
*
|
||||
* The version of the OpenAPI document: 1.0.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
|
||||
import * as runtime from '../runtime';
|
||||
import type {
|
||||
FuelType,
|
||||
} from '../models/index';
|
||||
import {
|
||||
FuelTypeFromJSON,
|
||||
FuelTypeToJSON,
|
||||
} from '../models/index';
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export class FuelTypeApi extends runtime.BaseAPI {
|
||||
|
||||
/**
|
||||
* Retrieves a list of all available fuel types.
|
||||
* Get all fuel types
|
||||
*/
|
||||
async apiFuelTypesAllGetRaw(initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<Array<FuelType>>> {
|
||||
const queryParameters: any = {};
|
||||
|
||||
const headerParameters: runtime.HTTPHeaders = {};
|
||||
|
||||
const response = await this.request({
|
||||
path: `/api/fuel-types/all`,
|
||||
method: 'GET',
|
||||
headers: headerParameters,
|
||||
query: queryParameters,
|
||||
}, initOverrides);
|
||||
|
||||
return new runtime.JSONApiResponse(response, (jsonValue) => jsonValue.map(FuelTypeFromJSON));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a list of all available fuel types.
|
||||
* Get all fuel types
|
||||
*/
|
||||
async apiFuelTypesAllGet(initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<Array<FuelType>> {
|
||||
const response = await this.apiFuelTypesAllGetRaw(initOverrides);
|
||||
return await response.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a list of the most common fuel types.
|
||||
* Get common fuel types
|
||||
*/
|
||||
async apiFuelTypesCommonGetRaw(initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<Array<FuelType>>> {
|
||||
const queryParameters: any = {};
|
||||
|
||||
const headerParameters: runtime.HTTPHeaders = {};
|
||||
|
||||
const response = await this.request({
|
||||
path: `/api/fuel-types/common`,
|
||||
method: 'GET',
|
||||
headers: headerParameters,
|
||||
query: queryParameters,
|
||||
}, initOverrides);
|
||||
|
||||
return new runtime.JSONApiResponse(response, (jsonValue) => jsonValue.map(FuelTypeFromJSON));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a list of the most common fuel types.
|
||||
* Get common fuel types
|
||||
*/
|
||||
async apiFuelTypesCommonGet(initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<Array<FuelType>> {
|
||||
const response = await this.apiFuelTypesCommonGetRaw(initOverrides);
|
||||
return await response.value();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,279 +0,0 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* FuelWizardApi | v1
|
||||
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
||||
*
|
||||
* The version of the OpenAPI document: 1.0.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
|
||||
import * as runtime from '../runtime';
|
||||
import type {
|
||||
ApiPricesCurrentGetPageNumberParameter,
|
||||
ApiPricesCurrentGetPageSizeParameter,
|
||||
ApiPricesCurrentStationGetStationCodeParameter,
|
||||
PaginationOfPrice,
|
||||
} from '../models/index';
|
||||
import {
|
||||
ApiPricesCurrentGetPageNumberParameterFromJSON,
|
||||
ApiPricesCurrentGetPageNumberParameterToJSON,
|
||||
ApiPricesCurrentGetPageSizeParameterFromJSON,
|
||||
ApiPricesCurrentGetPageSizeParameterToJSON,
|
||||
ApiPricesCurrentStationGetStationCodeParameterFromJSON,
|
||||
ApiPricesCurrentStationGetStationCodeParameterToJSON,
|
||||
PaginationOfPriceFromJSON,
|
||||
PaginationOfPriceToJSON,
|
||||
} from '../models/index';
|
||||
|
||||
export interface ApiPricesCurrentFuelTypeGetRequest {
|
||||
fuelType?: string;
|
||||
pageNumber?: ApiPricesCurrentGetPageNumberParameter;
|
||||
pageSize?: ApiPricesCurrentGetPageSizeParameter;
|
||||
}
|
||||
|
||||
export interface ApiPricesCurrentFuelTypeLowestGetRequest {
|
||||
fuelType?: string;
|
||||
pageNumber?: ApiPricesCurrentGetPageNumberParameter;
|
||||
pageSize?: ApiPricesCurrentGetPageSizeParameter;
|
||||
}
|
||||
|
||||
export interface ApiPricesCurrentGetRequest {
|
||||
pageNumber?: ApiPricesCurrentGetPageNumberParameter;
|
||||
pageSize?: ApiPricesCurrentGetPageSizeParameter;
|
||||
}
|
||||
|
||||
export interface ApiPricesCurrentStationGetRequest {
|
||||
stationCode?: ApiPricesCurrentStationGetStationCodeParameter;
|
||||
state?: string;
|
||||
fuelType?: string;
|
||||
pageNumber?: ApiPricesCurrentGetPageNumberParameter;
|
||||
pageSize?: ApiPricesCurrentGetPageSizeParameter;
|
||||
}
|
||||
|
||||
export interface ApiPricesPeriodGetRequest {
|
||||
start?: Date;
|
||||
end?: Date;
|
||||
pageNumber?: ApiPricesCurrentGetPageNumberParameter;
|
||||
pageSize?: ApiPricesCurrentGetPageSizeParameter;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export class PriceApi extends runtime.BaseAPI {
|
||||
|
||||
/**
|
||||
* Retrieves a list of all most recent prices for the provided fuel type.
|
||||
* Get all most recent prices by fuel type
|
||||
*/
|
||||
async apiPricesCurrentFuelTypeGetRaw(requestParameters: ApiPricesCurrentFuelTypeGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<PaginationOfPrice>> {
|
||||
const queryParameters: any = {};
|
||||
|
||||
if (requestParameters['fuelType'] != null) {
|
||||
queryParameters['fuelType'] = requestParameters['fuelType'];
|
||||
}
|
||||
|
||||
if (requestParameters['pageNumber'] != null) {
|
||||
queryParameters['pageNumber'] = requestParameters['pageNumber'];
|
||||
}
|
||||
|
||||
if (requestParameters['pageSize'] != null) {
|
||||
queryParameters['pageSize'] = requestParameters['pageSize'];
|
||||
}
|
||||
|
||||
const headerParameters: runtime.HTTPHeaders = {};
|
||||
|
||||
const response = await this.request({
|
||||
path: `/api/prices/current/fuel-type`,
|
||||
method: 'GET',
|
||||
headers: headerParameters,
|
||||
query: queryParameters,
|
||||
}, initOverrides);
|
||||
|
||||
return new runtime.JSONApiResponse(response, (jsonValue) => PaginationOfPriceFromJSON(jsonValue));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a list of all most recent prices for the provided fuel type.
|
||||
* Get all most recent prices by fuel type
|
||||
*/
|
||||
async apiPricesCurrentFuelTypeGet(requestParameters: ApiPricesCurrentFuelTypeGetRequest = {}, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<PaginationOfPrice> {
|
||||
const response = await this.apiPricesCurrentFuelTypeGetRaw(requestParameters, initOverrides);
|
||||
return await response.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a list of the lowest prices for the provided fuel type.
|
||||
* Get lowest prices by fuel type
|
||||
*/
|
||||
async apiPricesCurrentFuelTypeLowestGetRaw(requestParameters: ApiPricesCurrentFuelTypeLowestGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<PaginationOfPrice>> {
|
||||
const queryParameters: any = {};
|
||||
|
||||
if (requestParameters['fuelType'] != null) {
|
||||
queryParameters['fuelType'] = requestParameters['fuelType'];
|
||||
}
|
||||
|
||||
if (requestParameters['pageNumber'] != null) {
|
||||
queryParameters['pageNumber'] = requestParameters['pageNumber'];
|
||||
}
|
||||
|
||||
if (requestParameters['pageSize'] != null) {
|
||||
queryParameters['pageSize'] = requestParameters['pageSize'];
|
||||
}
|
||||
|
||||
const headerParameters: runtime.HTTPHeaders = {};
|
||||
|
||||
const response = await this.request({
|
||||
path: `/api/prices/current/fuel-type/lowest`,
|
||||
method: 'GET',
|
||||
headers: headerParameters,
|
||||
query: queryParameters,
|
||||
}, initOverrides);
|
||||
|
||||
return new runtime.JSONApiResponse(response, (jsonValue) => PaginationOfPriceFromJSON(jsonValue));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a list of the lowest prices for the provided fuel type.
|
||||
* Get lowest prices by fuel type
|
||||
*/
|
||||
async apiPricesCurrentFuelTypeLowestGet(requestParameters: ApiPricesCurrentFuelTypeLowestGetRequest = {}, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<PaginationOfPrice> {
|
||||
const response = await this.apiPricesCurrentFuelTypeLowestGetRaw(requestParameters, initOverrides);
|
||||
return await response.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a list of all available prices, with only the most recent displayed.
|
||||
* Get all most recent prices
|
||||
*/
|
||||
async apiPricesCurrentGetRaw(requestParameters: ApiPricesCurrentGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<PaginationOfPrice>> {
|
||||
const queryParameters: any = {};
|
||||
|
||||
if (requestParameters['pageNumber'] != null) {
|
||||
queryParameters['pageNumber'] = requestParameters['pageNumber'];
|
||||
}
|
||||
|
||||
if (requestParameters['pageSize'] != null) {
|
||||
queryParameters['pageSize'] = requestParameters['pageSize'];
|
||||
}
|
||||
|
||||
const headerParameters: runtime.HTTPHeaders = {};
|
||||
|
||||
const response = await this.request({
|
||||
path: `/api/prices/current`,
|
||||
method: 'GET',
|
||||
headers: headerParameters,
|
||||
query: queryParameters,
|
||||
}, initOverrides);
|
||||
|
||||
return new runtime.JSONApiResponse(response, (jsonValue) => PaginationOfPriceFromJSON(jsonValue));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a list of all available prices, with only the most recent displayed.
|
||||
* Get all most recent prices
|
||||
*/
|
||||
async apiPricesCurrentGet(requestParameters: ApiPricesCurrentGetRequest = {}, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<PaginationOfPrice> {
|
||||
const response = await this.apiPricesCurrentGetRaw(requestParameters, initOverrides);
|
||||
return await response.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a list of all current prices for the station with the code provided. The optional state narrows the lookup to a single state.
|
||||
* Get current prices by station code
|
||||
*/
|
||||
async apiPricesCurrentStationGetRaw(requestParameters: ApiPricesCurrentStationGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<PaginationOfPrice>> {
|
||||
const queryParameters: any = {};
|
||||
|
||||
if (requestParameters['stationCode'] != null) {
|
||||
queryParameters['stationCode'] = requestParameters['stationCode'];
|
||||
}
|
||||
|
||||
if (requestParameters['state'] != null) {
|
||||
queryParameters['state'] = requestParameters['state'];
|
||||
}
|
||||
|
||||
if (requestParameters['fuelType'] != null) {
|
||||
queryParameters['fuelType'] = requestParameters['fuelType'];
|
||||
}
|
||||
|
||||
if (requestParameters['pageNumber'] != null) {
|
||||
queryParameters['pageNumber'] = requestParameters['pageNumber'];
|
||||
}
|
||||
|
||||
if (requestParameters['pageSize'] != null) {
|
||||
queryParameters['pageSize'] = requestParameters['pageSize'];
|
||||
}
|
||||
|
||||
const headerParameters: runtime.HTTPHeaders = {};
|
||||
|
||||
const response = await this.request({
|
||||
path: `/api/prices/current/station`,
|
||||
method: 'GET',
|
||||
headers: headerParameters,
|
||||
query: queryParameters,
|
||||
}, initOverrides);
|
||||
|
||||
return new runtime.JSONApiResponse(response, (jsonValue) => PaginationOfPriceFromJSON(jsonValue));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a list of all current prices for the station with the code provided. The optional state narrows the lookup to a single state.
|
||||
* Get current prices by station code
|
||||
*/
|
||||
async apiPricesCurrentStationGet(requestParameters: ApiPricesCurrentStationGetRequest = {}, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<PaginationOfPrice> {
|
||||
const response = await this.apiPricesCurrentStationGetRaw(requestParameters, initOverrides);
|
||||
return await response.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a list of prices aggregated by a default time bucket of one day. Time values are UTC, in ISO 8601 format: yyyy-MM-ddTHH:mm:ss.SSSZ
|
||||
* Get prices for a specific time period
|
||||
*/
|
||||
async apiPricesPeriodGetRaw(requestParameters: ApiPricesPeriodGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<PaginationOfPrice>> {
|
||||
const queryParameters: any = {};
|
||||
|
||||
if (requestParameters['start'] != null) {
|
||||
queryParameters['start'] = (requestParameters['start'] as any).toISOString();
|
||||
}
|
||||
|
||||
if (requestParameters['end'] != null) {
|
||||
queryParameters['end'] = (requestParameters['end'] as any).toISOString();
|
||||
}
|
||||
|
||||
if (requestParameters['pageNumber'] != null) {
|
||||
queryParameters['pageNumber'] = requestParameters['pageNumber'];
|
||||
}
|
||||
|
||||
if (requestParameters['pageSize'] != null) {
|
||||
queryParameters['pageSize'] = requestParameters['pageSize'];
|
||||
}
|
||||
|
||||
const headerParameters: runtime.HTTPHeaders = {};
|
||||
|
||||
const response = await this.request({
|
||||
path: `/api/prices/period`,
|
||||
method: 'GET',
|
||||
headers: headerParameters,
|
||||
query: queryParameters,
|
||||
}, initOverrides);
|
||||
|
||||
return new runtime.JSONApiResponse(response, (jsonValue) => PaginationOfPriceFromJSON(jsonValue));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a list of prices aggregated by a default time bucket of one day. Time values are UTC, in ISO 8601 format: yyyy-MM-ddTHH:mm:ss.SSSZ
|
||||
* Get prices for a specific time period
|
||||
*/
|
||||
async apiPricesPeriodGet(requestParameters: ApiPricesPeriodGetRequest = {}, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<PaginationOfPrice> {
|
||||
const response = await this.apiPricesPeriodGetRaw(requestParameters, initOverrides);
|
||||
return await response.value();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,252 +0,0 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* FuelWizardApi | v1
|
||||
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
||||
*
|
||||
* The version of the OpenAPI document: 1.0.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
|
||||
import * as runtime from '../runtime';
|
||||
import type {
|
||||
ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameter,
|
||||
DailyPriceTrends,
|
||||
} from '../models/index';
|
||||
import {
|
||||
ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameterFromJSON,
|
||||
ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameterToJSON,
|
||||
DailyPriceTrendsFromJSON,
|
||||
DailyPriceTrendsToJSON,
|
||||
} from '../models/index';
|
||||
|
||||
export interface ApiTrendsDailyAveragesGetRequest {
|
||||
startDate?: Date;
|
||||
endDate?: Date;
|
||||
fuelType?: string;
|
||||
}
|
||||
|
||||
export interface ApiTrendsDailyAveragesStationIdsGetRequest {
|
||||
startDate?: Date;
|
||||
endDate?: Date;
|
||||
fuelType?: string;
|
||||
stationIds?: Array<string>;
|
||||
}
|
||||
|
||||
export interface ApiTrendsDailyAveragesWithinRadiusGetRequest {
|
||||
startDate?: Date;
|
||||
endDate?: Date;
|
||||
fuelType?: string;
|
||||
brand?: string;
|
||||
latitude?: ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameter;
|
||||
longitude?: ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameter;
|
||||
radiusInMetres?: ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameter;
|
||||
}
|
||||
|
||||
export interface ApiTrendsDailyAveragesWithinSuburbGetRequest {
|
||||
startDate?: Date;
|
||||
endDate?: Date;
|
||||
fuelType?: string;
|
||||
brand?: string;
|
||||
suburbId?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export class PriceTrendsApi extends runtime.BaseAPI {
|
||||
|
||||
/**
|
||||
* Retrieves a list of days, and the average price for that day, within the given period, and for the fuel type specified.
|
||||
* Get a list of daily price averages
|
||||
*/
|
||||
async apiTrendsDailyAveragesGetRaw(requestParameters: ApiTrendsDailyAveragesGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<DailyPriceTrends>> {
|
||||
const queryParameters: any = {};
|
||||
|
||||
if (requestParameters['startDate'] != null) {
|
||||
queryParameters['startDate'] = (requestParameters['startDate'] as any).toISOString();
|
||||
}
|
||||
|
||||
if (requestParameters['endDate'] != null) {
|
||||
queryParameters['endDate'] = (requestParameters['endDate'] as any).toISOString();
|
||||
}
|
||||
|
||||
if (requestParameters['fuelType'] != null) {
|
||||
queryParameters['fuelType'] = requestParameters['fuelType'];
|
||||
}
|
||||
|
||||
const headerParameters: runtime.HTTPHeaders = {};
|
||||
|
||||
const response = await this.request({
|
||||
path: `/api/trends/daily-averages`,
|
||||
method: 'GET',
|
||||
headers: headerParameters,
|
||||
query: queryParameters,
|
||||
}, initOverrides);
|
||||
|
||||
return new runtime.JSONApiResponse(response, (jsonValue) => DailyPriceTrendsFromJSON(jsonValue));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a list of days, and the average price for that day, within the given period, and for the fuel type specified.
|
||||
* Get a list of daily price averages
|
||||
*/
|
||||
async apiTrendsDailyAveragesGet(requestParameters: ApiTrendsDailyAveragesGetRequest = {}, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<DailyPriceTrends> {
|
||||
const response = await this.apiTrendsDailyAveragesGetRaw(requestParameters, initOverrides);
|
||||
return await response.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a list of days, and the price averages for the fuel type on that day across the station ids specified, within the given period.
|
||||
* Get a history of daily prices for the selected stations
|
||||
*/
|
||||
async apiTrendsDailyAveragesStationIdsGetRaw(requestParameters: ApiTrendsDailyAveragesStationIdsGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<DailyPriceTrends>> {
|
||||
const queryParameters: any = {};
|
||||
|
||||
if (requestParameters['startDate'] != null) {
|
||||
queryParameters['startDate'] = (requestParameters['startDate'] as any).toISOString();
|
||||
}
|
||||
|
||||
if (requestParameters['endDate'] != null) {
|
||||
queryParameters['endDate'] = (requestParameters['endDate'] as any).toISOString();
|
||||
}
|
||||
|
||||
if (requestParameters['fuelType'] != null) {
|
||||
queryParameters['fuelType'] = requestParameters['fuelType'];
|
||||
}
|
||||
|
||||
if (requestParameters['stationIds'] != null) {
|
||||
queryParameters['stationIds'] = requestParameters['stationIds'];
|
||||
}
|
||||
|
||||
const headerParameters: runtime.HTTPHeaders = {};
|
||||
|
||||
const response = await this.request({
|
||||
path: `/api/trends/daily-averages/station-ids`,
|
||||
method: 'GET',
|
||||
headers: headerParameters,
|
||||
query: queryParameters,
|
||||
}, initOverrides);
|
||||
|
||||
return new runtime.JSONApiResponse(response, (jsonValue) => DailyPriceTrendsFromJSON(jsonValue));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a list of days, and the price averages for the fuel type on that day across the station ids specified, within the given period.
|
||||
* Get a history of daily prices for the selected stations
|
||||
*/
|
||||
async apiTrendsDailyAveragesStationIdsGet(requestParameters: ApiTrendsDailyAveragesStationIdsGetRequest = {}, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<DailyPriceTrends> {
|
||||
const response = await this.apiTrendsDailyAveragesStationIdsGetRaw(requestParameters, initOverrides);
|
||||
return await response.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a list of days, and the average price for that day, within the given period, and for the fuel type and brand specified. Only stations within the given radius are included in the calculations.
|
||||
* Get a list of daily price averages for stations within a given radius
|
||||
*/
|
||||
async apiTrendsDailyAveragesWithinRadiusGetRaw(requestParameters: ApiTrendsDailyAveragesWithinRadiusGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<DailyPriceTrends>> {
|
||||
const queryParameters: any = {};
|
||||
|
||||
if (requestParameters['startDate'] != null) {
|
||||
queryParameters['startDate'] = (requestParameters['startDate'] as any).toISOString();
|
||||
}
|
||||
|
||||
if (requestParameters['endDate'] != null) {
|
||||
queryParameters['endDate'] = (requestParameters['endDate'] as any).toISOString();
|
||||
}
|
||||
|
||||
if (requestParameters['fuelType'] != null) {
|
||||
queryParameters['fuelType'] = requestParameters['fuelType'];
|
||||
}
|
||||
|
||||
if (requestParameters['brand'] != null) {
|
||||
queryParameters['brand'] = requestParameters['brand'];
|
||||
}
|
||||
|
||||
if (requestParameters['latitude'] != null) {
|
||||
queryParameters['latitude'] = requestParameters['latitude'];
|
||||
}
|
||||
|
||||
if (requestParameters['longitude'] != null) {
|
||||
queryParameters['longitude'] = requestParameters['longitude'];
|
||||
}
|
||||
|
||||
if (requestParameters['radiusInMetres'] != null) {
|
||||
queryParameters['radiusInMetres'] = requestParameters['radiusInMetres'];
|
||||
}
|
||||
|
||||
const headerParameters: runtime.HTTPHeaders = {};
|
||||
|
||||
const response = await this.request({
|
||||
path: `/api/trends/daily-averages/within-radius`,
|
||||
method: 'GET',
|
||||
headers: headerParameters,
|
||||
query: queryParameters,
|
||||
}, initOverrides);
|
||||
|
||||
return new runtime.JSONApiResponse(response, (jsonValue) => DailyPriceTrendsFromJSON(jsonValue));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a list of days, and the average price for that day, within the given period, and for the fuel type and brand specified. Only stations within the given radius are included in the calculations.
|
||||
* Get a list of daily price averages for stations within a given radius
|
||||
*/
|
||||
async apiTrendsDailyAveragesWithinRadiusGet(requestParameters: ApiTrendsDailyAveragesWithinRadiusGetRequest = {}, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<DailyPriceTrends> {
|
||||
const response = await this.apiTrendsDailyAveragesWithinRadiusGetRaw(requestParameters, initOverrides);
|
||||
return await response.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a list of days, and the average price for that day, within the given period, and for the fuel type specified. Only stations within the specified suburb are included in the calculations.
|
||||
* Get a list of daily price averages for stations within a suburb
|
||||
*/
|
||||
async apiTrendsDailyAveragesWithinSuburbGetRaw(requestParameters: ApiTrendsDailyAveragesWithinSuburbGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<DailyPriceTrends>> {
|
||||
const queryParameters: any = {};
|
||||
|
||||
if (requestParameters['startDate'] != null) {
|
||||
queryParameters['startDate'] = (requestParameters['startDate'] as any).toISOString();
|
||||
}
|
||||
|
||||
if (requestParameters['endDate'] != null) {
|
||||
queryParameters['endDate'] = (requestParameters['endDate'] as any).toISOString();
|
||||
}
|
||||
|
||||
if (requestParameters['fuelType'] != null) {
|
||||
queryParameters['fuelType'] = requestParameters['fuelType'];
|
||||
}
|
||||
|
||||
if (requestParameters['brand'] != null) {
|
||||
queryParameters['brand'] = requestParameters['brand'];
|
||||
}
|
||||
|
||||
if (requestParameters['suburbId'] != null) {
|
||||
queryParameters['suburbId'] = requestParameters['suburbId'];
|
||||
}
|
||||
|
||||
const headerParameters: runtime.HTTPHeaders = {};
|
||||
|
||||
const response = await this.request({
|
||||
path: `/api/trends/daily-averages/within-suburb`,
|
||||
method: 'GET',
|
||||
headers: headerParameters,
|
||||
query: queryParameters,
|
||||
}, initOverrides);
|
||||
|
||||
return new runtime.JSONApiResponse(response, (jsonValue) => DailyPriceTrendsFromJSON(jsonValue));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a list of days, and the average price for that day, within the given period, and for the fuel type specified. Only stations within the specified suburb are included in the calculations.
|
||||
* Get a list of daily price averages for stations within a suburb
|
||||
*/
|
||||
async apiTrendsDailyAveragesWithinSuburbGet(requestParameters: ApiTrendsDailyAveragesWithinSuburbGetRequest = {}, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<DailyPriceTrends> {
|
||||
const response = await this.apiTrendsDailyAveragesWithinSuburbGetRaw(requestParameters, initOverrides);
|
||||
return await response.value();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,193 +0,0 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* FuelWizardApi | v1
|
||||
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
||||
*
|
||||
* The version of the OpenAPI document: 1.0.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
|
||||
import * as runtime from '../runtime';
|
||||
import type {
|
||||
ApiPricesCurrentGetPageNumberParameter,
|
||||
ApiPricesCurrentGetPageSizeParameter,
|
||||
ApiPricesCurrentStationGetStationCodeParameter,
|
||||
ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameter,
|
||||
PaginationOfStation,
|
||||
Station,
|
||||
} from '../models/index';
|
||||
import {
|
||||
ApiPricesCurrentGetPageNumberParameterFromJSON,
|
||||
ApiPricesCurrentGetPageNumberParameterToJSON,
|
||||
ApiPricesCurrentGetPageSizeParameterFromJSON,
|
||||
ApiPricesCurrentGetPageSizeParameterToJSON,
|
||||
ApiPricesCurrentStationGetStationCodeParameterFromJSON,
|
||||
ApiPricesCurrentStationGetStationCodeParameterToJSON,
|
||||
ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameterFromJSON,
|
||||
ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameterToJSON,
|
||||
PaginationOfStationFromJSON,
|
||||
PaginationOfStationToJSON,
|
||||
StationFromJSON,
|
||||
StationToJSON,
|
||||
} from '../models/index';
|
||||
|
||||
export interface ApiStationsAllGetRequest {
|
||||
pageNumber?: ApiPricesCurrentGetPageNumberParameter;
|
||||
pageSize?: ApiPricesCurrentGetPageSizeParameter;
|
||||
}
|
||||
|
||||
export interface ApiStationsStationCodeGetRequest {
|
||||
stationCode?: ApiPricesCurrentStationGetStationCodeParameter;
|
||||
state?: string;
|
||||
}
|
||||
|
||||
export interface ApiStationsWithinRadiusGetRequest {
|
||||
latitude?: ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameter;
|
||||
longitude?: ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameter;
|
||||
radiusInMetres?: ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameter;
|
||||
brand?: string;
|
||||
stationName?: string;
|
||||
pageNumber?: ApiPricesCurrentGetPageNumberParameter;
|
||||
pageSize?: ApiPricesCurrentGetPageSizeParameter;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export class StationApi extends runtime.BaseAPI {
|
||||
|
||||
/**
|
||||
* Retrieves a list of all available stations.
|
||||
* Get all stations
|
||||
*/
|
||||
async apiStationsAllGetRaw(requestParameters: ApiStationsAllGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<PaginationOfStation>> {
|
||||
const queryParameters: any = {};
|
||||
|
||||
if (requestParameters['pageNumber'] != null) {
|
||||
queryParameters['pageNumber'] = requestParameters['pageNumber'];
|
||||
}
|
||||
|
||||
if (requestParameters['pageSize'] != null) {
|
||||
queryParameters['pageSize'] = requestParameters['pageSize'];
|
||||
}
|
||||
|
||||
const headerParameters: runtime.HTTPHeaders = {};
|
||||
|
||||
const response = await this.request({
|
||||
path: `/api/stations/all`,
|
||||
method: 'GET',
|
||||
headers: headerParameters,
|
||||
query: queryParameters,
|
||||
}, initOverrides);
|
||||
|
||||
return new runtime.JSONApiResponse(response, (jsonValue) => PaginationOfStationFromJSON(jsonValue));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a list of all available stations.
|
||||
* Get all stations
|
||||
*/
|
||||
async apiStationsAllGet(requestParameters: ApiStationsAllGetRequest = {}, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<PaginationOfStation> {
|
||||
const response = await this.apiStationsAllGetRaw(requestParameters, initOverrides);
|
||||
return await response.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a single station, where the station code is equal to the provided station code. The optional state narrows the lookup to a single state.
|
||||
* Get a station by station code
|
||||
*/
|
||||
async apiStationsStationCodeGetRaw(requestParameters: ApiStationsStationCodeGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<Station>> {
|
||||
const queryParameters: any = {};
|
||||
|
||||
if (requestParameters['stationCode'] != null) {
|
||||
queryParameters['stationCode'] = requestParameters['stationCode'];
|
||||
}
|
||||
|
||||
if (requestParameters['state'] != null) {
|
||||
queryParameters['state'] = requestParameters['state'];
|
||||
}
|
||||
|
||||
const headerParameters: runtime.HTTPHeaders = {};
|
||||
|
||||
const response = await this.request({
|
||||
path: `/api/stations/station-code`,
|
||||
method: 'GET',
|
||||
headers: headerParameters,
|
||||
query: queryParameters,
|
||||
}, initOverrides);
|
||||
|
||||
return new runtime.JSONApiResponse(response, (jsonValue) => StationFromJSON(jsonValue));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a single station, where the station code is equal to the provided station code. The optional state narrows the lookup to a single state.
|
||||
* Get a station by station code
|
||||
*/
|
||||
async apiStationsStationCodeGet(requestParameters: ApiStationsStationCodeGetRequest = {}, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<Station> {
|
||||
const response = await this.apiStationsStationCodeGetRaw(requestParameters, initOverrides);
|
||||
return await response.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a list of all stations within the area described by a circle with centre at the provided coordinates and a radius of the provided value in metres.
|
||||
* Get stations within radius
|
||||
*/
|
||||
async apiStationsWithinRadiusGetRaw(requestParameters: ApiStationsWithinRadiusGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<PaginationOfStation>> {
|
||||
const queryParameters: any = {};
|
||||
|
||||
if (requestParameters['latitude'] != null) {
|
||||
queryParameters['latitude'] = requestParameters['latitude'];
|
||||
}
|
||||
|
||||
if (requestParameters['longitude'] != null) {
|
||||
queryParameters['longitude'] = requestParameters['longitude'];
|
||||
}
|
||||
|
||||
if (requestParameters['radiusInMetres'] != null) {
|
||||
queryParameters['radiusInMetres'] = requestParameters['radiusInMetres'];
|
||||
}
|
||||
|
||||
if (requestParameters['brand'] != null) {
|
||||
queryParameters['brand'] = requestParameters['brand'];
|
||||
}
|
||||
|
||||
if (requestParameters['stationName'] != null) {
|
||||
queryParameters['stationName'] = requestParameters['stationName'];
|
||||
}
|
||||
|
||||
if (requestParameters['pageNumber'] != null) {
|
||||
queryParameters['pageNumber'] = requestParameters['pageNumber'];
|
||||
}
|
||||
|
||||
if (requestParameters['pageSize'] != null) {
|
||||
queryParameters['pageSize'] = requestParameters['pageSize'];
|
||||
}
|
||||
|
||||
const headerParameters: runtime.HTTPHeaders = {};
|
||||
|
||||
const response = await this.request({
|
||||
path: `/api/stations/within-radius`,
|
||||
method: 'GET',
|
||||
headers: headerParameters,
|
||||
query: queryParameters,
|
||||
}, initOverrides);
|
||||
|
||||
return new runtime.JSONApiResponse(response, (jsonValue) => PaginationOfStationFromJSON(jsonValue));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a list of all stations within the area described by a circle with centre at the provided coordinates and a radius of the provided value in metres.
|
||||
* Get stations within radius
|
||||
*/
|
||||
async apiStationsWithinRadiusGet(requestParameters: ApiStationsWithinRadiusGetRequest = {}, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<PaginationOfStation> {
|
||||
const response = await this.apiStationsWithinRadiusGetRaw(requestParameters, initOverrides);
|
||||
return await response.value();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,379 +0,0 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* FuelWizardApi | v1
|
||||
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
||||
*
|
||||
* The version of the OpenAPI document: 1.0.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
|
||||
import * as runtime from '../runtime';
|
||||
import type {
|
||||
ApiPricesCurrentGetPageNumberParameter,
|
||||
ApiPricesCurrentGetPageSizeParameter,
|
||||
ApiPricesCurrentStationGetStationCodeParameter,
|
||||
ApiStationsWithPricesLowestPricesByFuelTypeWithinRadiusGetPageSizeParameter,
|
||||
ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameter,
|
||||
PaginationOfStationWithPrices,
|
||||
StationWithPrices,
|
||||
} from '../models/index';
|
||||
import {
|
||||
ApiPricesCurrentGetPageNumberParameterFromJSON,
|
||||
ApiPricesCurrentGetPageNumberParameterToJSON,
|
||||
ApiPricesCurrentGetPageSizeParameterFromJSON,
|
||||
ApiPricesCurrentGetPageSizeParameterToJSON,
|
||||
ApiPricesCurrentStationGetStationCodeParameterFromJSON,
|
||||
ApiPricesCurrentStationGetStationCodeParameterToJSON,
|
||||
ApiStationsWithPricesLowestPricesByFuelTypeWithinRadiusGetPageSizeParameterFromJSON,
|
||||
ApiStationsWithPricesLowestPricesByFuelTypeWithinRadiusGetPageSizeParameterToJSON,
|
||||
ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameterFromJSON,
|
||||
ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameterToJSON,
|
||||
PaginationOfStationWithPricesFromJSON,
|
||||
PaginationOfStationWithPricesToJSON,
|
||||
StationWithPricesFromJSON,
|
||||
StationWithPricesToJSON,
|
||||
} from '../models/index';
|
||||
|
||||
export interface ApiStationsWithPricesLowestPricesByFuelTypeWithinRadiusGetRequest {
|
||||
fuelType?: string;
|
||||
latitude?: ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameter;
|
||||
longitude?: ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameter;
|
||||
radiusInMetres?: ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameter;
|
||||
pageNumber?: ApiPricesCurrentGetPageNumberParameter;
|
||||
pageSize?: ApiStationsWithPricesLowestPricesByFuelTypeWithinRadiusGetPageSizeParameter;
|
||||
}
|
||||
|
||||
export interface ApiStationsWithPricesLowestPricesByFuelTypeWithinSuburbGetRequest {
|
||||
fuelType?: string;
|
||||
suburbId?: string;
|
||||
pageNumber?: ApiPricesCurrentGetPageNumberParameter;
|
||||
pageSize?: ApiStationsWithPricesLowestPricesByFuelTypeWithinRadiusGetPageSizeParameter;
|
||||
}
|
||||
|
||||
export interface ApiStationsWithPricesLowestPricesGetRequest {
|
||||
fuelType?: string;
|
||||
pageNumber?: ApiPricesCurrentGetPageNumberParameter;
|
||||
pageSize?: ApiPricesCurrentGetPageSizeParameter;
|
||||
}
|
||||
|
||||
export interface ApiStationsWithPricesStationCodeGetRequest {
|
||||
stationCode?: ApiPricesCurrentStationGetStationCodeParameter;
|
||||
state?: string;
|
||||
}
|
||||
|
||||
export interface ApiStationsWithPricesWithinRadiusGetRequest {
|
||||
latitude?: ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameter;
|
||||
longitude?: ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameter;
|
||||
radiusInMetres?: ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameter;
|
||||
fuelType?: string;
|
||||
brand?: string;
|
||||
stationName?: string;
|
||||
pageNumber?: ApiPricesCurrentGetPageNumberParameter;
|
||||
pageSize?: ApiPricesCurrentGetPageSizeParameter;
|
||||
}
|
||||
|
||||
export interface ApiStationsWithPricesWithinSuburbGetRequest {
|
||||
suburbId?: string;
|
||||
fuelType?: string;
|
||||
brand?: string;
|
||||
stationName?: string;
|
||||
pageNumber?: ApiPricesCurrentGetPageNumberParameter;
|
||||
pageSize?: ApiPricesCurrentGetPageSizeParameter;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export class StationWithPricesApi extends runtime.BaseAPI {
|
||||
|
||||
/**
|
||||
* Retrieves a list of stations with the lowest prices for a specific fuel type, within the specified radius.
|
||||
* Get stations with lowest prices by fuel type, within a radius
|
||||
*/
|
||||
async apiStationsWithPricesLowestPricesByFuelTypeWithinRadiusGetRaw(requestParameters: ApiStationsWithPricesLowestPricesByFuelTypeWithinRadiusGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<PaginationOfStationWithPrices>> {
|
||||
const queryParameters: any = {};
|
||||
|
||||
if (requestParameters['fuelType'] != null) {
|
||||
queryParameters['fuelType'] = requestParameters['fuelType'];
|
||||
}
|
||||
|
||||
if (requestParameters['latitude'] != null) {
|
||||
queryParameters['latitude'] = requestParameters['latitude'];
|
||||
}
|
||||
|
||||
if (requestParameters['longitude'] != null) {
|
||||
queryParameters['longitude'] = requestParameters['longitude'];
|
||||
}
|
||||
|
||||
if (requestParameters['radiusInMetres'] != null) {
|
||||
queryParameters['radiusInMetres'] = requestParameters['radiusInMetres'];
|
||||
}
|
||||
|
||||
if (requestParameters['pageNumber'] != null) {
|
||||
queryParameters['pageNumber'] = requestParameters['pageNumber'];
|
||||
}
|
||||
|
||||
if (requestParameters['pageSize'] != null) {
|
||||
queryParameters['pageSize'] = requestParameters['pageSize'];
|
||||
}
|
||||
|
||||
const headerParameters: runtime.HTTPHeaders = {};
|
||||
|
||||
const response = await this.request({
|
||||
path: `/api/stations-with-prices/lowest-prices/by-fuel-type/within-radius`,
|
||||
method: 'GET',
|
||||
headers: headerParameters,
|
||||
query: queryParameters,
|
||||
}, initOverrides);
|
||||
|
||||
return new runtime.JSONApiResponse(response, (jsonValue) => PaginationOfStationWithPricesFromJSON(jsonValue));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a list of stations with the lowest prices for a specific fuel type, within the specified radius.
|
||||
* Get stations with lowest prices by fuel type, within a radius
|
||||
*/
|
||||
async apiStationsWithPricesLowestPricesByFuelTypeWithinRadiusGet(requestParameters: ApiStationsWithPricesLowestPricesByFuelTypeWithinRadiusGetRequest = {}, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<PaginationOfStationWithPrices> {
|
||||
const response = await this.apiStationsWithPricesLowestPricesByFuelTypeWithinRadiusGetRaw(requestParameters, initOverrides);
|
||||
return await response.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a list of stations with the lowest prices for a specific fuel type, within the specified suburb.
|
||||
* Get stations with lowest prices by fuel type, within a suburb
|
||||
*/
|
||||
async apiStationsWithPricesLowestPricesByFuelTypeWithinSuburbGetRaw(requestParameters: ApiStationsWithPricesLowestPricesByFuelTypeWithinSuburbGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<PaginationOfStationWithPrices>> {
|
||||
const queryParameters: any = {};
|
||||
|
||||
if (requestParameters['fuelType'] != null) {
|
||||
queryParameters['fuelType'] = requestParameters['fuelType'];
|
||||
}
|
||||
|
||||
if (requestParameters['suburbId'] != null) {
|
||||
queryParameters['suburbId'] = requestParameters['suburbId'];
|
||||
}
|
||||
|
||||
if (requestParameters['pageNumber'] != null) {
|
||||
queryParameters['pageNumber'] = requestParameters['pageNumber'];
|
||||
}
|
||||
|
||||
if (requestParameters['pageSize'] != null) {
|
||||
queryParameters['pageSize'] = requestParameters['pageSize'];
|
||||
}
|
||||
|
||||
const headerParameters: runtime.HTTPHeaders = {};
|
||||
|
||||
const response = await this.request({
|
||||
path: `/api/stations-with-prices/lowest-prices/by-fuel-type/within-suburb`,
|
||||
method: 'GET',
|
||||
headers: headerParameters,
|
||||
query: queryParameters,
|
||||
}, initOverrides);
|
||||
|
||||
return new runtime.JSONApiResponse(response, (jsonValue) => PaginationOfStationWithPricesFromJSON(jsonValue));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a list of stations with the lowest prices for a specific fuel type, within the specified suburb.
|
||||
* Get stations with lowest prices by fuel type, within a suburb
|
||||
*/
|
||||
async apiStationsWithPricesLowestPricesByFuelTypeWithinSuburbGet(requestParameters: ApiStationsWithPricesLowestPricesByFuelTypeWithinSuburbGetRequest = {}, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<PaginationOfStationWithPrices> {
|
||||
const response = await this.apiStationsWithPricesLowestPricesByFuelTypeWithinSuburbGetRaw(requestParameters, initOverrides);
|
||||
return await response.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a list of stations with the lowest prices for a specific fuel type.
|
||||
* Get stations with lowest prices by fuel type
|
||||
*/
|
||||
async apiStationsWithPricesLowestPricesGetRaw(requestParameters: ApiStationsWithPricesLowestPricesGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<PaginationOfStationWithPrices>> {
|
||||
const queryParameters: any = {};
|
||||
|
||||
if (requestParameters['fuelType'] != null) {
|
||||
queryParameters['fuelType'] = requestParameters['fuelType'];
|
||||
}
|
||||
|
||||
if (requestParameters['pageNumber'] != null) {
|
||||
queryParameters['pageNumber'] = requestParameters['pageNumber'];
|
||||
}
|
||||
|
||||
if (requestParameters['pageSize'] != null) {
|
||||
queryParameters['pageSize'] = requestParameters['pageSize'];
|
||||
}
|
||||
|
||||
const headerParameters: runtime.HTTPHeaders = {};
|
||||
|
||||
const response = await this.request({
|
||||
path: `/api/stations-with-prices/lowest-prices`,
|
||||
method: 'GET',
|
||||
headers: headerParameters,
|
||||
query: queryParameters,
|
||||
}, initOverrides);
|
||||
|
||||
return new runtime.JSONApiResponse(response, (jsonValue) => PaginationOfStationWithPricesFromJSON(jsonValue));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a list of stations with the lowest prices for a specific fuel type.
|
||||
* Get stations with lowest prices by fuel type
|
||||
*/
|
||||
async apiStationsWithPricesLowestPricesGet(requestParameters: ApiStationsWithPricesLowestPricesGetRequest = {}, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<PaginationOfStationWithPrices> {
|
||||
const response = await this.apiStationsWithPricesLowestPricesGetRaw(requestParameters, initOverrides);
|
||||
return await response.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a single station along with its current prices, where the station code is equal to the provided station code. The optional state narrows the lookup to a single state.
|
||||
* Get a station with prices by station code
|
||||
*/
|
||||
async apiStationsWithPricesStationCodeGetRaw(requestParameters: ApiStationsWithPricesStationCodeGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<StationWithPrices>> {
|
||||
const queryParameters: any = {};
|
||||
|
||||
if (requestParameters['stationCode'] != null) {
|
||||
queryParameters['stationCode'] = requestParameters['stationCode'];
|
||||
}
|
||||
|
||||
if (requestParameters['state'] != null) {
|
||||
queryParameters['state'] = requestParameters['state'];
|
||||
}
|
||||
|
||||
const headerParameters: runtime.HTTPHeaders = {};
|
||||
|
||||
const response = await this.request({
|
||||
path: `/api/stations-with-prices/station-code`,
|
||||
method: 'GET',
|
||||
headers: headerParameters,
|
||||
query: queryParameters,
|
||||
}, initOverrides);
|
||||
|
||||
return new runtime.JSONApiResponse(response, (jsonValue) => StationWithPricesFromJSON(jsonValue));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a single station along with its current prices, where the station code is equal to the provided station code. The optional state narrows the lookup to a single state.
|
||||
* Get a station with prices by station code
|
||||
*/
|
||||
async apiStationsWithPricesStationCodeGet(requestParameters: ApiStationsWithPricesStationCodeGetRequest = {}, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<StationWithPrices> {
|
||||
const response = await this.apiStationsWithPricesStationCodeGetRaw(requestParameters, initOverrides);
|
||||
return await response.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a list of all stations within a specified radius of a given location along with their current prices.
|
||||
* Get stations with prices within radius
|
||||
*/
|
||||
async apiStationsWithPricesWithinRadiusGetRaw(requestParameters: ApiStationsWithPricesWithinRadiusGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<PaginationOfStationWithPrices>> {
|
||||
const queryParameters: any = {};
|
||||
|
||||
if (requestParameters['latitude'] != null) {
|
||||
queryParameters['latitude'] = requestParameters['latitude'];
|
||||
}
|
||||
|
||||
if (requestParameters['longitude'] != null) {
|
||||
queryParameters['longitude'] = requestParameters['longitude'];
|
||||
}
|
||||
|
||||
if (requestParameters['radiusInMetres'] != null) {
|
||||
queryParameters['radiusInMetres'] = requestParameters['radiusInMetres'];
|
||||
}
|
||||
|
||||
if (requestParameters['fuelType'] != null) {
|
||||
queryParameters['fuelType'] = requestParameters['fuelType'];
|
||||
}
|
||||
|
||||
if (requestParameters['brand'] != null) {
|
||||
queryParameters['brand'] = requestParameters['brand'];
|
||||
}
|
||||
|
||||
if (requestParameters['stationName'] != null) {
|
||||
queryParameters['stationName'] = requestParameters['stationName'];
|
||||
}
|
||||
|
||||
if (requestParameters['pageNumber'] != null) {
|
||||
queryParameters['pageNumber'] = requestParameters['pageNumber'];
|
||||
}
|
||||
|
||||
if (requestParameters['pageSize'] != null) {
|
||||
queryParameters['pageSize'] = requestParameters['pageSize'];
|
||||
}
|
||||
|
||||
const headerParameters: runtime.HTTPHeaders = {};
|
||||
|
||||
const response = await this.request({
|
||||
path: `/api/stations-with-prices/within-radius`,
|
||||
method: 'GET',
|
||||
headers: headerParameters,
|
||||
query: queryParameters,
|
||||
}, initOverrides);
|
||||
|
||||
return new runtime.JSONApiResponse(response, (jsonValue) => PaginationOfStationWithPricesFromJSON(jsonValue));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a list of all stations within a specified radius of a given location along with their current prices.
|
||||
* Get stations with prices within radius
|
||||
*/
|
||||
async apiStationsWithPricesWithinRadiusGet(requestParameters: ApiStationsWithPricesWithinRadiusGetRequest = {}, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<PaginationOfStationWithPrices> {
|
||||
const response = await this.apiStationsWithPricesWithinRadiusGetRaw(requestParameters, initOverrides);
|
||||
return await response.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a list of all stations within a specified suburb boundary along with their current prices.
|
||||
* Get stations with prices within a suburb
|
||||
*/
|
||||
async apiStationsWithPricesWithinSuburbGetRaw(requestParameters: ApiStationsWithPricesWithinSuburbGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<PaginationOfStationWithPrices>> {
|
||||
const queryParameters: any = {};
|
||||
|
||||
if (requestParameters['suburbId'] != null) {
|
||||
queryParameters['suburbId'] = requestParameters['suburbId'];
|
||||
}
|
||||
|
||||
if (requestParameters['fuelType'] != null) {
|
||||
queryParameters['fuelType'] = requestParameters['fuelType'];
|
||||
}
|
||||
|
||||
if (requestParameters['brand'] != null) {
|
||||
queryParameters['brand'] = requestParameters['brand'];
|
||||
}
|
||||
|
||||
if (requestParameters['stationName'] != null) {
|
||||
queryParameters['stationName'] = requestParameters['stationName'];
|
||||
}
|
||||
|
||||
if (requestParameters['pageNumber'] != null) {
|
||||
queryParameters['pageNumber'] = requestParameters['pageNumber'];
|
||||
}
|
||||
|
||||
if (requestParameters['pageSize'] != null) {
|
||||
queryParameters['pageSize'] = requestParameters['pageSize'];
|
||||
}
|
||||
|
||||
const headerParameters: runtime.HTTPHeaders = {};
|
||||
|
||||
const response = await this.request({
|
||||
path: `/api/stations-with-prices/within-suburb`,
|
||||
method: 'GET',
|
||||
headers: headerParameters,
|
||||
query: queryParameters,
|
||||
}, initOverrides);
|
||||
|
||||
return new runtime.JSONApiResponse(response, (jsonValue) => PaginationOfStationWithPricesFromJSON(jsonValue));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a list of all stations within a specified suburb boundary along with their current prices.
|
||||
* Get stations with prices within a suburb
|
||||
*/
|
||||
async apiStationsWithPricesWithinSuburbGet(requestParameters: ApiStationsWithPricesWithinSuburbGetRequest = {}, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<PaginationOfStationWithPrices> {
|
||||
const response = await this.apiStationsWithPricesWithinSuburbGetRaw(requestParameters, initOverrides);
|
||||
return await response.value();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,190 +0,0 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* FuelWizardApi | v1
|
||||
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
||||
*
|
||||
* The version of the OpenAPI document: 1.0.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
|
||||
import * as runtime from '../runtime';
|
||||
import type {
|
||||
ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameter,
|
||||
Suburb,
|
||||
SuburbBoundary,
|
||||
} from '../models/index';
|
||||
import {
|
||||
ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameterFromJSON,
|
||||
ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameterToJSON,
|
||||
SuburbFromJSON,
|
||||
SuburbToJSON,
|
||||
SuburbBoundaryFromJSON,
|
||||
SuburbBoundaryToJSON,
|
||||
} from '../models/index';
|
||||
|
||||
export interface ApiSuburbBoundariesByIdGetRequest {
|
||||
id?: string;
|
||||
}
|
||||
|
||||
export interface ApiSuburbBoundariesForLocationGetRequest {
|
||||
latitude?: ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameter;
|
||||
longitude?: ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameter;
|
||||
}
|
||||
|
||||
export interface ApiSuburbBoundariesSuburbsAllGetRequest {
|
||||
state?: string;
|
||||
}
|
||||
|
||||
export interface ApiSuburbBoundariesSuburbsByNameGetRequest {
|
||||
name?: string;
|
||||
state?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export class SuburbBoundaryApi extends runtime.BaseAPI {
|
||||
|
||||
/**
|
||||
* Retrieves the single SuburbBoundary, which matches the input ID.
|
||||
* Return a single SuburbBoundary
|
||||
*/
|
||||
async apiSuburbBoundariesByIdGetRaw(requestParameters: ApiSuburbBoundariesByIdGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<SuburbBoundary>> {
|
||||
const queryParameters: any = {};
|
||||
|
||||
if (requestParameters['id'] != null) {
|
||||
queryParameters['id'] = requestParameters['id'];
|
||||
}
|
||||
|
||||
const headerParameters: runtime.HTTPHeaders = {};
|
||||
|
||||
const response = await this.request({
|
||||
path: `/api/suburb-boundaries/by-id`,
|
||||
method: 'GET',
|
||||
headers: headerParameters,
|
||||
query: queryParameters,
|
||||
}, initOverrides);
|
||||
|
||||
return new runtime.JSONApiResponse(response, (jsonValue) => SuburbBoundaryFromJSON(jsonValue));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the single SuburbBoundary, which matches the input ID.
|
||||
* Return a single SuburbBoundary
|
||||
*/
|
||||
async apiSuburbBoundariesByIdGet(requestParameters: ApiSuburbBoundariesByIdGetRequest = {}, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<SuburbBoundary> {
|
||||
const response = await this.apiSuburbBoundariesByIdGetRaw(requestParameters, initOverrides);
|
||||
return await response.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the single SuburbBoundary containing the provided latitude and longitude coordinates.
|
||||
* Return the SuburbBoundary for a location
|
||||
*/
|
||||
async apiSuburbBoundariesForLocationGetRaw(requestParameters: ApiSuburbBoundariesForLocationGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<SuburbBoundary>> {
|
||||
const queryParameters: any = {};
|
||||
|
||||
if (requestParameters['latitude'] != null) {
|
||||
queryParameters['latitude'] = requestParameters['latitude'];
|
||||
}
|
||||
|
||||
if (requestParameters['longitude'] != null) {
|
||||
queryParameters['longitude'] = requestParameters['longitude'];
|
||||
}
|
||||
|
||||
const headerParameters: runtime.HTTPHeaders = {};
|
||||
|
||||
const response = await this.request({
|
||||
path: `/api/suburb-boundaries/for-location`,
|
||||
method: 'GET',
|
||||
headers: headerParameters,
|
||||
query: queryParameters,
|
||||
}, initOverrides);
|
||||
|
||||
return new runtime.JSONApiResponse(response, (jsonValue) => SuburbBoundaryFromJSON(jsonValue));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the single SuburbBoundary containing the provided latitude and longitude coordinates.
|
||||
* Return the SuburbBoundary for a location
|
||||
*/
|
||||
async apiSuburbBoundariesForLocationGet(requestParameters: ApiSuburbBoundariesForLocationGetRequest = {}, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<SuburbBoundary> {
|
||||
const response = await this.apiSuburbBoundariesForLocationGetRaw(requestParameters, initOverrides);
|
||||
return await response.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a list of all of the suburbs available. Optionally filtered by state (lowercase code: nsw, vic, wa, act, tas).
|
||||
* Get the ID, Name, and State for every Suburb in the DB.
|
||||
*/
|
||||
async apiSuburbBoundariesSuburbsAllGetRaw(requestParameters: ApiSuburbBoundariesSuburbsAllGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<Array<Suburb>>> {
|
||||
const queryParameters: any = {};
|
||||
|
||||
if (requestParameters['state'] != null) {
|
||||
queryParameters['state'] = requestParameters['state'];
|
||||
}
|
||||
|
||||
const headerParameters: runtime.HTTPHeaders = {};
|
||||
|
||||
const response = await this.request({
|
||||
path: `/api/suburb-boundaries/suburbs/all`,
|
||||
method: 'GET',
|
||||
headers: headerParameters,
|
||||
query: queryParameters,
|
||||
}, initOverrides);
|
||||
|
||||
return new runtime.JSONApiResponse(response, (jsonValue) => jsonValue.map(SuburbFromJSON));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a list of all of the suburbs available. Optionally filtered by state (lowercase code: nsw, vic, wa, act, tas).
|
||||
* Get the ID, Name, and State for every Suburb in the DB.
|
||||
*/
|
||||
async apiSuburbBoundariesSuburbsAllGet(requestParameters: ApiSuburbBoundariesSuburbsAllGetRequest = {}, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<Array<Suburb>> {
|
||||
const response = await this.apiSuburbBoundariesSuburbsAllGetRaw(requestParameters, initOverrides);
|
||||
return await response.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a list of all of the Suburbs that contain the name input. Optionally filtered by state (lowercase code: nsw, vic, wa, act, tas).
|
||||
* Search for Suburbs in the DB by name
|
||||
*/
|
||||
async apiSuburbBoundariesSuburbsByNameGetRaw(requestParameters: ApiSuburbBoundariesSuburbsByNameGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<Array<Suburb>>> {
|
||||
const queryParameters: any = {};
|
||||
|
||||
if (requestParameters['name'] != null) {
|
||||
queryParameters['name'] = requestParameters['name'];
|
||||
}
|
||||
|
||||
if (requestParameters['state'] != null) {
|
||||
queryParameters['state'] = requestParameters['state'];
|
||||
}
|
||||
|
||||
const headerParameters: runtime.HTTPHeaders = {};
|
||||
|
||||
const response = await this.request({
|
||||
path: `/api/suburb-boundaries/suburbs/by-name`,
|
||||
method: 'GET',
|
||||
headers: headerParameters,
|
||||
query: queryParameters,
|
||||
}, initOverrides);
|
||||
|
||||
return new runtime.JSONApiResponse(response, (jsonValue) => jsonValue.map(SuburbFromJSON));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a list of all of the Suburbs that contain the name input. Optionally filtered by state (lowercase code: nsw, vic, wa, act, tas).
|
||||
* Search for Suburbs in the DB by name
|
||||
*/
|
||||
async apiSuburbBoundariesSuburbsByNameGet(requestParameters: ApiSuburbBoundariesSuburbsByNameGetRequest = {}, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<Array<Suburb>> {
|
||||
const response = await this.apiSuburbBoundariesSuburbsByNameGetRaw(requestParameters, initOverrides);
|
||||
return await response.value();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
export * from './BrandApi';
|
||||
export * from './FuelTypeApi';
|
||||
export * from './PriceApi';
|
||||
export * from './PriceTrendsApi';
|
||||
export * from './StationApi';
|
||||
export * from './StationWithPricesApi';
|
||||
export * from './SuburbBoundaryApi';
|
||||
@@ -0,0 +1,18 @@
|
||||
// This file is auto-generated by @hey-api/openapi-ts
|
||||
|
||||
import { createClientConfig } from '../hey-api';
|
||||
|
||||
import { type Client, type ClientOptions, type Config, createClient, createConfig } from './client';
|
||||
import type { ClientOptions as ClientOptions2 } from './types.gen';
|
||||
|
||||
/**
|
||||
* The `createClientConfig()` function will be called on client initialization
|
||||
* and the returned object will become the client's initial configuration.
|
||||
*
|
||||
* You may want to initialize your client this way instead of calling
|
||||
* `setConfig()`. This is useful for example if you're using Next.js
|
||||
* to ensure your client always has the correct values.
|
||||
*/
|
||||
export type CreateClientConfig<T extends ClientOptions = ClientOptions2> = (override?: Config<ClientOptions & T>) => Config<Required<ClientOptions> & T>;
|
||||
|
||||
export const client: Client = createClient(createClientConfig(createConfig<ClientOptions2>({ baseUrl: 'http://localhost:5161/', throwOnError: true })));
|
||||
@@ -0,0 +1,277 @@
|
||||
// This file is auto-generated by @hey-api/openapi-ts
|
||||
|
||||
import { createSseClient } from '../core/serverSentEvents.gen';
|
||||
import type { HttpMethod } from '../core/types.gen';
|
||||
import { getValidRequestBody } from '../core/utils.gen';
|
||||
import type { Client, Config, RequestOptions, ResolvedRequestOptions } from './types.gen';
|
||||
import {
|
||||
buildUrl,
|
||||
createConfig,
|
||||
createInterceptors,
|
||||
getParseAs,
|
||||
mergeConfigs,
|
||||
mergeHeaders,
|
||||
setAuthParams,
|
||||
} from './utils.gen';
|
||||
|
||||
type ReqInit = Omit<RequestInit, 'body' | 'headers'> & {
|
||||
body?: any;
|
||||
headers: ReturnType<typeof mergeHeaders>;
|
||||
};
|
||||
|
||||
export const createClient = (config: Config = {}): Client => {
|
||||
let _config = mergeConfigs(createConfig(), config);
|
||||
|
||||
const getConfig = (): Config => ({ ..._config });
|
||||
|
||||
const setConfig = (config: Config): Config => {
|
||||
_config = mergeConfigs(_config, config);
|
||||
return getConfig();
|
||||
};
|
||||
|
||||
const interceptors = createInterceptors<Request, Response, unknown, ResolvedRequestOptions>();
|
||||
|
||||
const beforeRequest = async <
|
||||
TData = unknown,
|
||||
TResponseStyle extends 'data' | 'fields' = 'fields',
|
||||
ThrowOnError extends boolean = boolean,
|
||||
Url extends string = string,
|
||||
>(
|
||||
options: RequestOptions<TData, TResponseStyle, ThrowOnError, Url>,
|
||||
) => {
|
||||
const opts = {
|
||||
..._config,
|
||||
...options,
|
||||
fetch: options.fetch ?? _config.fetch ?? globalThis.fetch,
|
||||
headers: mergeHeaders(_config.headers, options.headers),
|
||||
serializedBody: undefined as string | undefined,
|
||||
};
|
||||
|
||||
if (opts.security) {
|
||||
await setAuthParams(opts);
|
||||
}
|
||||
|
||||
if (opts.requestValidator) {
|
||||
await opts.requestValidator(opts);
|
||||
}
|
||||
|
||||
if (opts.body !== undefined && opts.bodySerializer) {
|
||||
opts.serializedBody = opts.bodySerializer(opts.body) as string | undefined;
|
||||
}
|
||||
|
||||
// remove Content-Type header if body is empty to avoid sending invalid requests
|
||||
if (opts.body === undefined || opts.serializedBody === '') {
|
||||
opts.headers.delete('Content-Type');
|
||||
}
|
||||
|
||||
const resolvedOpts = opts as typeof opts &
|
||||
ResolvedRequestOptions<TResponseStyle, ThrowOnError, Url>;
|
||||
const url = buildUrl(resolvedOpts);
|
||||
|
||||
return { opts: resolvedOpts, url };
|
||||
};
|
||||
|
||||
const request: Client['request'] = async (options) => {
|
||||
const throwOnError = options.throwOnError ?? _config.throwOnError;
|
||||
const responseStyle = options.responseStyle ?? _config.responseStyle;
|
||||
|
||||
let request: Request | undefined;
|
||||
let response: Response | undefined;
|
||||
|
||||
try {
|
||||
const { opts, url } = await beforeRequest(options);
|
||||
const requestInit: ReqInit = {
|
||||
redirect: 'follow',
|
||||
...opts,
|
||||
body: getValidRequestBody(opts),
|
||||
};
|
||||
|
||||
request = new Request(url, requestInit);
|
||||
|
||||
for (const fn of interceptors.request.fns) {
|
||||
if (fn) {
|
||||
request = await fn(request, opts);
|
||||
}
|
||||
}
|
||||
|
||||
// fetch must be assigned here, otherwise it would throw the error:
|
||||
// TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation
|
||||
const _fetch = opts.fetch!;
|
||||
|
||||
response = await _fetch(request);
|
||||
|
||||
for (const fn of interceptors.response.fns) {
|
||||
if (fn) {
|
||||
response = await fn(response, request, opts);
|
||||
}
|
||||
}
|
||||
|
||||
const result = {
|
||||
request,
|
||||
response,
|
||||
};
|
||||
|
||||
if (response.ok) {
|
||||
const parseAs =
|
||||
(opts.parseAs === 'auto'
|
||||
? getParseAs(response.headers.get('Content-Type'))
|
||||
: opts.parseAs) ?? 'json';
|
||||
|
||||
if (response.status === 204 || response.headers.get('Content-Length') === '0') {
|
||||
let emptyData: any;
|
||||
switch (parseAs) {
|
||||
case 'arrayBuffer':
|
||||
case 'blob':
|
||||
case 'text':
|
||||
emptyData = await response[parseAs]();
|
||||
break;
|
||||
case 'formData':
|
||||
emptyData = new FormData();
|
||||
break;
|
||||
case 'stream':
|
||||
emptyData = response.body;
|
||||
break;
|
||||
case 'json':
|
||||
default:
|
||||
emptyData = {};
|
||||
break;
|
||||
}
|
||||
return opts.responseStyle === 'data'
|
||||
? emptyData
|
||||
: {
|
||||
data: emptyData,
|
||||
...result,
|
||||
};
|
||||
}
|
||||
|
||||
let data: any;
|
||||
switch (parseAs) {
|
||||
case 'arrayBuffer':
|
||||
case 'blob':
|
||||
case 'formData':
|
||||
case 'text':
|
||||
data = await response[parseAs]();
|
||||
break;
|
||||
case 'json': {
|
||||
// Some servers return 200 with no Content-Length and empty body.
|
||||
// response.json() would throw; read as text and parse if non-empty.
|
||||
const text = await response.text();
|
||||
data = text ? JSON.parse(text) : {};
|
||||
break;
|
||||
}
|
||||
case 'stream':
|
||||
return opts.responseStyle === 'data'
|
||||
? response.body
|
||||
: {
|
||||
data: response.body,
|
||||
...result,
|
||||
};
|
||||
}
|
||||
|
||||
if (parseAs === 'json') {
|
||||
if (opts.responseValidator) {
|
||||
await opts.responseValidator(data);
|
||||
}
|
||||
|
||||
if (opts.responseTransformer) {
|
||||
data = await opts.responseTransformer(data);
|
||||
}
|
||||
}
|
||||
|
||||
return opts.responseStyle === 'data'
|
||||
? data
|
||||
: {
|
||||
data,
|
||||
...result,
|
||||
};
|
||||
}
|
||||
|
||||
const textError = await response.text();
|
||||
let jsonError: unknown;
|
||||
|
||||
try {
|
||||
jsonError = JSON.parse(textError);
|
||||
} catch {
|
||||
// noop
|
||||
}
|
||||
|
||||
throw jsonError ?? textError;
|
||||
} catch (error) {
|
||||
let finalError = error;
|
||||
|
||||
for (const fn of interceptors.error.fns) {
|
||||
if (fn) {
|
||||
finalError = await fn(finalError, response, request, options as ResolvedRequestOptions);
|
||||
}
|
||||
}
|
||||
|
||||
finalError = finalError || {};
|
||||
|
||||
if (throwOnError) {
|
||||
throw finalError;
|
||||
}
|
||||
|
||||
// TODO: we probably want to return error and improve types
|
||||
return responseStyle === 'data'
|
||||
? undefined
|
||||
: {
|
||||
error: finalError,
|
||||
request,
|
||||
response,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
const makeMethodFn = (method: Uppercase<HttpMethod>) => (options: RequestOptions) =>
|
||||
request({ ...options, method });
|
||||
|
||||
const makeSseFn = (method: Uppercase<HttpMethod>) => async (options: RequestOptions) => {
|
||||
const { opts, url } = await beforeRequest(options);
|
||||
return createSseClient({
|
||||
...opts,
|
||||
body: opts.body as BodyInit | null | undefined,
|
||||
method,
|
||||
onRequest: async (url, init) => {
|
||||
let request = new Request(url, init);
|
||||
for (const fn of interceptors.request.fns) {
|
||||
if (fn) {
|
||||
request = await fn(request, opts);
|
||||
}
|
||||
}
|
||||
return request;
|
||||
},
|
||||
serializedBody: getValidRequestBody(opts) as BodyInit | null | undefined,
|
||||
url,
|
||||
});
|
||||
};
|
||||
|
||||
const _buildUrl: Client['buildUrl'] = (options) => buildUrl({ ..._config, ...options });
|
||||
|
||||
return {
|
||||
buildUrl: _buildUrl,
|
||||
connect: makeMethodFn('CONNECT'),
|
||||
delete: makeMethodFn('DELETE'),
|
||||
get: makeMethodFn('GET'),
|
||||
getConfig,
|
||||
head: makeMethodFn('HEAD'),
|
||||
interceptors,
|
||||
options: makeMethodFn('OPTIONS'),
|
||||
patch: makeMethodFn('PATCH'),
|
||||
post: makeMethodFn('POST'),
|
||||
put: makeMethodFn('PUT'),
|
||||
request,
|
||||
setConfig,
|
||||
sse: {
|
||||
connect: makeSseFn('CONNECT'),
|
||||
delete: makeSseFn('DELETE'),
|
||||
get: makeSseFn('GET'),
|
||||
head: makeSseFn('HEAD'),
|
||||
options: makeSseFn('OPTIONS'),
|
||||
patch: makeSseFn('PATCH'),
|
||||
post: makeSseFn('POST'),
|
||||
put: makeSseFn('PUT'),
|
||||
trace: makeSseFn('TRACE'),
|
||||
},
|
||||
trace: makeMethodFn('TRACE'),
|
||||
} as Client;
|
||||
};
|
||||
@@ -0,0 +1,27 @@
|
||||
// This file is auto-generated by @hey-api/openapi-ts
|
||||
|
||||
export type { Auth } from '../core/auth.gen';
|
||||
export type { QuerySerializerOptions } from '../core/bodySerializer.gen';
|
||||
export {
|
||||
formDataBodySerializer,
|
||||
jsonBodySerializer,
|
||||
urlSearchParamsBodySerializer,
|
||||
} from '../core/bodySerializer.gen';
|
||||
export { buildClientParams } from '../core/params.gen';
|
||||
export { serializeQueryKeyValue } from '../core/queryKeySerializer.gen';
|
||||
export type { ServerSentEventsResult } from '../core/serverSentEvents.gen';
|
||||
export type { ClientMeta } from '../core/types.gen';
|
||||
export { createClient } from './client.gen';
|
||||
export type {
|
||||
Client,
|
||||
ClientOptions,
|
||||
Config,
|
||||
CreateClientConfig,
|
||||
Options,
|
||||
RequestOptions,
|
||||
RequestResult,
|
||||
ResolvedRequestOptions,
|
||||
ResponseStyle,
|
||||
TDataShape,
|
||||
} from './types.gen';
|
||||
export { createConfig, mergeHeaders } from './utils.gen';
|
||||
@@ -0,0 +1,218 @@
|
||||
// This file is auto-generated by @hey-api/openapi-ts
|
||||
|
||||
import type { Auth } from '../core/auth.gen';
|
||||
import type {
|
||||
ServerSentEventsOptions,
|
||||
ServerSentEventsResult,
|
||||
} from '../core/serverSentEvents.gen';
|
||||
import type { Client as CoreClient, Config as CoreConfig } from '../core/types.gen';
|
||||
import type { Middleware } from './utils.gen';
|
||||
|
||||
export type ResponseStyle = 'data' | 'fields';
|
||||
|
||||
export interface Config<T extends ClientOptions = ClientOptions>
|
||||
extends Omit<RequestInit, 'body' | 'headers' | 'method'>, CoreConfig {
|
||||
/**
|
||||
* Base URL for all requests made by this client.
|
||||
*/
|
||||
baseUrl?: T['baseUrl'];
|
||||
/**
|
||||
* Fetch API implementation. You can use this option to provide a custom
|
||||
* fetch instance.
|
||||
*
|
||||
* @default globalThis.fetch
|
||||
*/
|
||||
fetch?: typeof fetch;
|
||||
/**
|
||||
* Please don't use the Fetch client for Next.js applications. The `next`
|
||||
* options won't have any effect.
|
||||
*
|
||||
* Install {@link https://www.npmjs.com/package/@hey-api/client-next `@hey-api/client-next`} instead.
|
||||
*/
|
||||
next?: never;
|
||||
/**
|
||||
* Return the response data parsed in a specified format. By default, `auto`
|
||||
* will infer the appropriate method from the `Content-Type` response header.
|
||||
* You can override this behavior with any of the {@link Body} methods.
|
||||
* Select `stream` if you don't want to parse response data at all.
|
||||
*
|
||||
* @default 'auto'
|
||||
*/
|
||||
parseAs?: 'arrayBuffer' | 'auto' | 'blob' | 'formData' | 'json' | 'stream' | 'text';
|
||||
/**
|
||||
* Should we return only data or multiple fields (data, error, response, etc.)?
|
||||
*
|
||||
* @default 'fields'
|
||||
*/
|
||||
responseStyle?: ResponseStyle;
|
||||
/**
|
||||
* Throw an error instead of returning it in the response?
|
||||
*
|
||||
* @default false
|
||||
*/
|
||||
throwOnError?: T['throwOnError'];
|
||||
}
|
||||
|
||||
export interface RequestOptions<
|
||||
TData = unknown,
|
||||
TResponseStyle extends ResponseStyle = 'fields',
|
||||
ThrowOnError extends boolean = boolean,
|
||||
Url extends string = string,
|
||||
>
|
||||
extends
|
||||
Config<{
|
||||
responseStyle: TResponseStyle;
|
||||
throwOnError: ThrowOnError;
|
||||
}>,
|
||||
Pick<
|
||||
ServerSentEventsOptions<TData>,
|
||||
| 'onRequest'
|
||||
| 'onSseError'
|
||||
| 'onSseEvent'
|
||||
| 'sseDefaultRetryDelay'
|
||||
| 'sseMaxRetryAttempts'
|
||||
| 'sseMaxRetryDelay'
|
||||
> {
|
||||
/**
|
||||
* Any body that you want to add to your request.
|
||||
*
|
||||
* {@link https://developer.mozilla.org/docs/Web/API/fetch#body}
|
||||
*/
|
||||
body?: unknown;
|
||||
path?: Record<string, unknown>;
|
||||
query?: Record<string, unknown>;
|
||||
/**
|
||||
* Security mechanism(s) to use for the request.
|
||||
*/
|
||||
security?: ReadonlyArray<Auth>;
|
||||
url: Url;
|
||||
}
|
||||
|
||||
export interface ResolvedRequestOptions<
|
||||
TResponseStyle extends ResponseStyle = 'fields',
|
||||
ThrowOnError extends boolean = boolean,
|
||||
Url extends string = string,
|
||||
> extends RequestOptions<unknown, TResponseStyle, ThrowOnError, Url> {
|
||||
headers: Headers;
|
||||
serializedBody?: string;
|
||||
}
|
||||
|
||||
export type RequestResult<
|
||||
TData = unknown,
|
||||
TError = unknown,
|
||||
ThrowOnError extends boolean = boolean,
|
||||
TResponseStyle extends ResponseStyle = 'fields',
|
||||
> = ThrowOnError extends true
|
||||
? Promise<
|
||||
TResponseStyle extends 'data'
|
||||
? TData extends Record<string, unknown>
|
||||
? TData[keyof TData]
|
||||
: TData
|
||||
: {
|
||||
data: TData extends Record<string, unknown> ? TData[keyof TData] : TData;
|
||||
request: Request;
|
||||
response: Response;
|
||||
}
|
||||
>
|
||||
: Promise<
|
||||
TResponseStyle extends 'data'
|
||||
? (TData extends Record<string, unknown> ? TData[keyof TData] : TData) | undefined
|
||||
: (
|
||||
| {
|
||||
data: TData extends Record<string, unknown> ? TData[keyof TData] : TData;
|
||||
error: undefined;
|
||||
}
|
||||
| {
|
||||
data: undefined;
|
||||
error: TError extends Record<string, unknown> ? TError[keyof TError] : TError;
|
||||
}
|
||||
) & {
|
||||
/** request may be undefined, because error may be from building the request object itself */
|
||||
request?: Request;
|
||||
/** response may be undefined, because error may be from building the request object itself or from a network error */
|
||||
response?: Response;
|
||||
}
|
||||
>;
|
||||
|
||||
export interface ClientOptions {
|
||||
baseUrl?: string;
|
||||
responseStyle?: ResponseStyle;
|
||||
throwOnError?: boolean;
|
||||
}
|
||||
|
||||
type MethodFn = <
|
||||
TData = unknown,
|
||||
TError = unknown,
|
||||
ThrowOnError extends boolean = false,
|
||||
TResponseStyle extends ResponseStyle = 'fields',
|
||||
>(
|
||||
options: Omit<RequestOptions<TData, TResponseStyle, ThrowOnError>, 'method'>,
|
||||
) => RequestResult<TData, TError, ThrowOnError, TResponseStyle>;
|
||||
|
||||
type SseFn = <
|
||||
TData = unknown,
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
_TError = unknown,
|
||||
ThrowOnError extends boolean = false,
|
||||
TResponseStyle extends ResponseStyle = 'fields',
|
||||
>(
|
||||
options: Omit<RequestOptions<never, TResponseStyle, ThrowOnError>, 'method'>,
|
||||
) => Promise<ServerSentEventsResult<TData>>;
|
||||
|
||||
type RequestFn = <
|
||||
TData = unknown,
|
||||
TError = unknown,
|
||||
ThrowOnError extends boolean = false,
|
||||
TResponseStyle extends ResponseStyle = 'fields',
|
||||
>(
|
||||
options: Omit<RequestOptions<TData, TResponseStyle, ThrowOnError>, 'method'> &
|
||||
Pick<Required<RequestOptions<TData, TResponseStyle, ThrowOnError>>, 'method'>,
|
||||
) => RequestResult<TData, TError, ThrowOnError, TResponseStyle>;
|
||||
|
||||
type BuildUrlFn = <
|
||||
TData extends {
|
||||
body?: unknown;
|
||||
path?: Record<string, unknown>;
|
||||
query?: Record<string, unknown>;
|
||||
url: string;
|
||||
},
|
||||
>(
|
||||
options: TData & Options<TData>,
|
||||
) => string;
|
||||
|
||||
export type Client = CoreClient<RequestFn, Config, MethodFn, BuildUrlFn, SseFn> & {
|
||||
interceptors: Middleware<Request, Response, unknown, ResolvedRequestOptions>;
|
||||
};
|
||||
|
||||
/**
|
||||
* The `createClientConfig()` function will be called on client initialization
|
||||
* and the returned object will become the client's initial configuration.
|
||||
*
|
||||
* You may want to initialize your client this way instead of calling
|
||||
* `setConfig()`. This is useful for example if you're using Next.js
|
||||
* to ensure your client always has the correct values.
|
||||
*/
|
||||
export type CreateClientConfig<T extends ClientOptions = ClientOptions> = (
|
||||
override?: Config<ClientOptions & T>,
|
||||
) => Config<Required<ClientOptions> & T>;
|
||||
|
||||
export interface TDataShape {
|
||||
body?: unknown;
|
||||
headers?: unknown;
|
||||
path?: unknown;
|
||||
query?: unknown;
|
||||
url: string;
|
||||
}
|
||||
|
||||
type OmitKeys<T, K> = Pick<T, Exclude<keyof T, K>>;
|
||||
|
||||
export type Options<
|
||||
TData extends TDataShape = TDataShape,
|
||||
ThrowOnError extends boolean = boolean,
|
||||
TResponse = unknown,
|
||||
TResponseStyle extends ResponseStyle = 'fields',
|
||||
> = OmitKeys<
|
||||
RequestOptions<TResponse, TResponseStyle, ThrowOnError>,
|
||||
'body' | 'path' | 'query' | 'url'
|
||||
> &
|
||||
([TData] extends [never] ? unknown : Omit<TData, 'url'>);
|
||||
@@ -0,0 +1,316 @@
|
||||
// This file is auto-generated by @hey-api/openapi-ts
|
||||
|
||||
import { getAuthToken } from '../core/auth.gen';
|
||||
import type { QuerySerializerOptions } from '../core/bodySerializer.gen';
|
||||
import { jsonBodySerializer } from '../core/bodySerializer.gen';
|
||||
import {
|
||||
serializeArrayParam,
|
||||
serializeObjectParam,
|
||||
serializePrimitiveParam,
|
||||
} from '../core/pathSerializer.gen';
|
||||
import { getUrl } from '../core/utils.gen';
|
||||
import type { Client, ClientOptions, Config, RequestOptions } from './types.gen';
|
||||
|
||||
export const createQuerySerializer = <T = unknown>({
|
||||
parameters = {},
|
||||
...args
|
||||
}: QuerySerializerOptions = {}): ((queryParams: T) => string) => {
|
||||
const querySerializer = (queryParams: T): string => {
|
||||
const search: string[] = [];
|
||||
if (queryParams && typeof queryParams === 'object') {
|
||||
for (const name in queryParams) {
|
||||
const value = queryParams[name];
|
||||
|
||||
if (value === undefined || value === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const options = parameters[name] || args;
|
||||
|
||||
if (Array.isArray(value)) {
|
||||
const serializedArray = serializeArrayParam({
|
||||
allowReserved: options.allowReserved,
|
||||
explode: true,
|
||||
name,
|
||||
style: 'form',
|
||||
value,
|
||||
...options.array,
|
||||
});
|
||||
if (serializedArray) search.push(serializedArray);
|
||||
} else if (typeof value === 'object') {
|
||||
const serializedObject = serializeObjectParam({
|
||||
allowReserved: options.allowReserved,
|
||||
explode: true,
|
||||
name,
|
||||
style: 'deepObject',
|
||||
value: value as Record<string, unknown>,
|
||||
...options.object,
|
||||
});
|
||||
if (serializedObject) search.push(serializedObject);
|
||||
} else {
|
||||
const serializedPrimitive = serializePrimitiveParam({
|
||||
allowReserved: options.allowReserved,
|
||||
name,
|
||||
value: value as string,
|
||||
});
|
||||
if (serializedPrimitive) search.push(serializedPrimitive);
|
||||
}
|
||||
}
|
||||
}
|
||||
return search.join('&');
|
||||
};
|
||||
return querySerializer;
|
||||
};
|
||||
|
||||
/**
|
||||
* Infers parseAs value from provided Content-Type header.
|
||||
*/
|
||||
export const getParseAs = (contentType: string | null): Exclude<Config['parseAs'], 'auto'> => {
|
||||
if (!contentType) {
|
||||
// If no Content-Type header is provided, the best we can do is return the raw response body,
|
||||
// which is effectively the same as the 'stream' option.
|
||||
return 'stream';
|
||||
}
|
||||
|
||||
const cleanContent = contentType.split(';')[0]?.trim();
|
||||
|
||||
if (!cleanContent) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (cleanContent.startsWith('application/json') || cleanContent.endsWith('+json')) {
|
||||
return 'json';
|
||||
}
|
||||
|
||||
if (cleanContent === 'multipart/form-data') {
|
||||
return 'formData';
|
||||
}
|
||||
|
||||
if (
|
||||
['application/', 'audio/', 'image/', 'video/'].some((type) => cleanContent.startsWith(type))
|
||||
) {
|
||||
return 'blob';
|
||||
}
|
||||
|
||||
if (cleanContent.startsWith('text/')) {
|
||||
return 'text';
|
||||
}
|
||||
|
||||
return;
|
||||
};
|
||||
|
||||
const checkForExistence = (
|
||||
options: Pick<RequestOptions, 'auth' | 'query'> & {
|
||||
headers: Headers;
|
||||
},
|
||||
name?: string,
|
||||
): boolean => {
|
||||
if (!name) {
|
||||
return false;
|
||||
}
|
||||
if (
|
||||
options.headers.has(name) ||
|
||||
options.query?.[name] ||
|
||||
options.headers.get('Cookie')?.includes(`${name}=`)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
export async function setAuthParams(
|
||||
options: Pick<RequestOptions, 'auth' | 'query' | 'security'> & {
|
||||
headers: Headers;
|
||||
},
|
||||
): Promise<void> {
|
||||
for (const auth of options.security ?? []) {
|
||||
if (checkForExistence(options, auth.name)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const token = await getAuthToken(auth, options.auth);
|
||||
|
||||
if (!token) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const name = auth.name ?? 'Authorization';
|
||||
|
||||
switch (auth.in) {
|
||||
case 'query':
|
||||
if (!options.query) {
|
||||
options.query = {};
|
||||
}
|
||||
options.query[name] = token;
|
||||
break;
|
||||
case 'cookie':
|
||||
options.headers.append('Cookie', `${name}=${token}`);
|
||||
break;
|
||||
case 'header':
|
||||
default:
|
||||
options.headers.set(name, token);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const buildUrl: Client['buildUrl'] = (options) =>
|
||||
getUrl({
|
||||
baseUrl: options.baseUrl as string,
|
||||
path: options.path,
|
||||
query: options.query,
|
||||
querySerializer:
|
||||
typeof options.querySerializer === 'function'
|
||||
? options.querySerializer
|
||||
: createQuerySerializer(options.querySerializer),
|
||||
url: options.url,
|
||||
});
|
||||
|
||||
export const mergeConfigs = (a: Config, b: Config): Config => {
|
||||
const config = { ...a, ...b };
|
||||
if (config.baseUrl?.endsWith('/')) {
|
||||
config.baseUrl = config.baseUrl.substring(0, config.baseUrl.length - 1);
|
||||
}
|
||||
config.headers = mergeHeaders(a.headers, b.headers);
|
||||
return config;
|
||||
};
|
||||
|
||||
const headersEntries = (headers: Headers): Array<[string, string]> => {
|
||||
const entries: Array<[string, string]> = [];
|
||||
headers.forEach((value, key) => {
|
||||
entries.push([key, value]);
|
||||
});
|
||||
return entries;
|
||||
};
|
||||
|
||||
export const mergeHeaders = (
|
||||
...headers: Array<Required<Config>['headers'] | undefined>
|
||||
): Headers => {
|
||||
const mergedHeaders = new Headers();
|
||||
for (const header of headers) {
|
||||
if (!header) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const iterator = header instanceof Headers ? headersEntries(header) : Object.entries(header);
|
||||
|
||||
for (const [key, value] of iterator) {
|
||||
if (value === null) {
|
||||
mergedHeaders.delete(key);
|
||||
} else if (Array.isArray(value)) {
|
||||
for (const v of value) {
|
||||
mergedHeaders.append(key, v as string);
|
||||
}
|
||||
} else if (value !== undefined) {
|
||||
// assume object headers are meant to be JSON stringified, i.e., their
|
||||
// content value in OpenAPI specification is 'application/json'
|
||||
mergedHeaders.set(
|
||||
key,
|
||||
typeof value === 'object' ? JSON.stringify(value) : (value as string),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
return mergedHeaders;
|
||||
};
|
||||
|
||||
type ErrInterceptor<Err, Res, Req, Options> = (
|
||||
error: Err,
|
||||
/** response may be undefined due to a network error where no response object is produced */
|
||||
response: Res | undefined,
|
||||
/** request may be undefined, because error may be from building the request object itself */
|
||||
request: Req | undefined,
|
||||
options: Options,
|
||||
) => Err | Promise<Err>;
|
||||
|
||||
type ReqInterceptor<Req, Options> = (request: Req, options: Options) => Req | Promise<Req>;
|
||||
|
||||
type ResInterceptor<Res, Req, Options> = (
|
||||
response: Res,
|
||||
request: Req,
|
||||
options: Options,
|
||||
) => Res | Promise<Res>;
|
||||
|
||||
class Interceptors<Interceptor> {
|
||||
fns: Array<Interceptor | null> = [];
|
||||
|
||||
clear(): void {
|
||||
this.fns = [];
|
||||
}
|
||||
|
||||
eject(id: number | Interceptor): void {
|
||||
const index = this.getInterceptorIndex(id);
|
||||
if (this.fns[index]) {
|
||||
this.fns[index] = null;
|
||||
}
|
||||
}
|
||||
|
||||
exists(id: number | Interceptor): boolean {
|
||||
const index = this.getInterceptorIndex(id);
|
||||
return Boolean(this.fns[index]);
|
||||
}
|
||||
|
||||
getInterceptorIndex(id: number | Interceptor): number {
|
||||
if (typeof id === 'number') {
|
||||
return this.fns[id] ? id : -1;
|
||||
}
|
||||
return this.fns.indexOf(id);
|
||||
}
|
||||
|
||||
update(id: number | Interceptor, fn: Interceptor): number | Interceptor | false {
|
||||
const index = this.getInterceptorIndex(id);
|
||||
if (this.fns[index]) {
|
||||
this.fns[index] = fn;
|
||||
return id;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
use(fn: Interceptor): number {
|
||||
this.fns.push(fn);
|
||||
return this.fns.length - 1;
|
||||
}
|
||||
}
|
||||
|
||||
export interface Middleware<Req, Res, Err, Options> {
|
||||
error: Interceptors<ErrInterceptor<Err, Res, Req, Options>>;
|
||||
request: Interceptors<ReqInterceptor<Req, Options>>;
|
||||
response: Interceptors<ResInterceptor<Res, Req, Options>>;
|
||||
}
|
||||
|
||||
export const createInterceptors = <Req, Res, Err, Options>(): Middleware<
|
||||
Req,
|
||||
Res,
|
||||
Err,
|
||||
Options
|
||||
> => ({
|
||||
error: new Interceptors<ErrInterceptor<Err, Res, Req, Options>>(),
|
||||
request: new Interceptors<ReqInterceptor<Req, Options>>(),
|
||||
response: new Interceptors<ResInterceptor<Res, Req, Options>>(),
|
||||
});
|
||||
|
||||
const defaultQuerySerializer = createQuerySerializer({
|
||||
allowReserved: false,
|
||||
array: {
|
||||
explode: true,
|
||||
style: 'form',
|
||||
},
|
||||
object: {
|
||||
explode: true,
|
||||
style: 'deepObject',
|
||||
},
|
||||
});
|
||||
|
||||
const defaultHeaders = {
|
||||
'Content-Type': 'application/json',
|
||||
};
|
||||
|
||||
export const createConfig = <T extends ClientOptions = ClientOptions>(
|
||||
override: Config<Omit<ClientOptions, keyof T> & T> = {},
|
||||
): Config<Omit<ClientOptions, keyof T> & T> => ({
|
||||
...jsonBodySerializer,
|
||||
headers: defaultHeaders,
|
||||
parseAs: 'auto',
|
||||
querySerializer: defaultQuerySerializer,
|
||||
...override,
|
||||
});
|
||||
@@ -0,0 +1,48 @@
|
||||
// This file is auto-generated by @hey-api/openapi-ts
|
||||
|
||||
export type AuthToken = string | undefined;
|
||||
|
||||
export interface Auth {
|
||||
/**
|
||||
* Which part of the request do we use to send the auth?
|
||||
*
|
||||
* @default 'header'
|
||||
*/
|
||||
in?: 'header' | 'query' | 'cookie';
|
||||
/**
|
||||
* A unique identifier for the security scheme.
|
||||
*
|
||||
* Defined only when there are multiple security schemes whose `Auth`
|
||||
* shape would otherwise be identical.
|
||||
*/
|
||||
key?: string;
|
||||
/**
|
||||
* Header or query parameter name.
|
||||
*
|
||||
* @default 'Authorization'
|
||||
*/
|
||||
name?: string;
|
||||
scheme?: 'basic' | 'bearer';
|
||||
type: 'apiKey' | 'http';
|
||||
}
|
||||
|
||||
export const getAuthToken = async (
|
||||
auth: Auth,
|
||||
callback: ((auth: Auth) => Promise<AuthToken> | AuthToken) | AuthToken,
|
||||
): Promise<string | undefined> => {
|
||||
const token = typeof callback === 'function' ? await callback(auth) : callback;
|
||||
|
||||
if (!token) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (auth.scheme === 'bearer') {
|
||||
return `Bearer ${token}`;
|
||||
}
|
||||
|
||||
if (auth.scheme === 'basic') {
|
||||
return `Basic ${btoa(token)}`;
|
||||
}
|
||||
|
||||
return token;
|
||||
};
|
||||
@@ -0,0 +1,82 @@
|
||||
// This file is auto-generated by @hey-api/openapi-ts
|
||||
|
||||
import type { ArrayStyle, ObjectStyle, SerializerOptions } from './pathSerializer.gen';
|
||||
|
||||
export type QuerySerializer = (query: Record<string, unknown>) => string;
|
||||
|
||||
export type BodySerializer = (body: unknown) => unknown;
|
||||
|
||||
type QuerySerializerOptionsObject = {
|
||||
allowReserved?: boolean;
|
||||
array?: Partial<SerializerOptions<ArrayStyle>>;
|
||||
object?: Partial<SerializerOptions<ObjectStyle>>;
|
||||
};
|
||||
|
||||
export type QuerySerializerOptions = QuerySerializerOptionsObject & {
|
||||
/**
|
||||
* Per-parameter serialization overrides. When provided, these settings
|
||||
* override the global array/object settings for specific parameter names.
|
||||
*/
|
||||
parameters?: Record<string, QuerySerializerOptionsObject>;
|
||||
};
|
||||
|
||||
const serializeFormDataPair = (data: FormData, key: string, value: unknown): void => {
|
||||
if (typeof value === 'string' || value instanceof Blob) {
|
||||
data.append(key, value);
|
||||
} else if (value instanceof Date) {
|
||||
data.append(key, value.toISOString());
|
||||
} else {
|
||||
data.append(key, JSON.stringify(value));
|
||||
}
|
||||
};
|
||||
|
||||
const serializeUrlSearchParamsPair = (data: URLSearchParams, key: string, value: unknown): void => {
|
||||
if (typeof value === 'string') {
|
||||
data.append(key, value);
|
||||
} else {
|
||||
data.append(key, JSON.stringify(value));
|
||||
}
|
||||
};
|
||||
|
||||
export const formDataBodySerializer = {
|
||||
bodySerializer: (body: unknown): FormData => {
|
||||
const data = new FormData();
|
||||
|
||||
Object.entries(body as Record<string, unknown>).forEach(([key, value]) => {
|
||||
if (value === undefined || value === null) {
|
||||
return;
|
||||
}
|
||||
if (Array.isArray(value)) {
|
||||
value.forEach((v) => serializeFormDataPair(data, key, v));
|
||||
} else {
|
||||
serializeFormDataPair(data, key, value);
|
||||
}
|
||||
});
|
||||
|
||||
return data;
|
||||
},
|
||||
};
|
||||
|
||||
export const jsonBodySerializer = {
|
||||
bodySerializer: (body: unknown): string =>
|
||||
JSON.stringify(body, (_key, value) => (typeof value === 'bigint' ? value.toString() : value)),
|
||||
};
|
||||
|
||||
export const urlSearchParamsBodySerializer = {
|
||||
bodySerializer: (body: unknown): string => {
|
||||
const data = new URLSearchParams();
|
||||
|
||||
Object.entries(body as Record<string, unknown>).forEach(([key, value]) => {
|
||||
if (value === undefined || value === null) {
|
||||
return;
|
||||
}
|
||||
if (Array.isArray(value)) {
|
||||
value.forEach((v) => serializeUrlSearchParamsPair(data, key, v));
|
||||
} else {
|
||||
serializeUrlSearchParamsPair(data, key, value);
|
||||
}
|
||||
});
|
||||
|
||||
return data.toString();
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,178 @@
|
||||
// This file is auto-generated by @hey-api/openapi-ts
|
||||
|
||||
type Slot = 'body' | 'headers' | 'path' | 'query';
|
||||
|
||||
export type Field =
|
||||
| {
|
||||
in: Exclude<Slot, 'body'>;
|
||||
/**
|
||||
* Field name. This is the name we want the user to see and use.
|
||||
*/
|
||||
key: string;
|
||||
/**
|
||||
* Field mapped name. This is the name we want to use in the request.
|
||||
* If omitted, we use the same value as `key`.
|
||||
*/
|
||||
map?: string;
|
||||
}
|
||||
| {
|
||||
in: Extract<Slot, 'body'>;
|
||||
/**
|
||||
* Key isn't required for bodies.
|
||||
*/
|
||||
key?: string;
|
||||
map?: string;
|
||||
}
|
||||
| {
|
||||
/**
|
||||
* Field name. This is the name we want the user to see and use.
|
||||
*/
|
||||
key: string;
|
||||
/**
|
||||
* Field mapped name. This is the name we want to use in the request.
|
||||
* If `in` is omitted, `map` aliases `key` to the transport layer.
|
||||
*/
|
||||
map: Slot;
|
||||
};
|
||||
|
||||
export interface Fields {
|
||||
allowExtra?: Partial<Record<Slot, boolean>>;
|
||||
args?: ReadonlyArray<Field>;
|
||||
}
|
||||
|
||||
export type FieldsConfig = ReadonlyArray<Field | Fields>;
|
||||
|
||||
const extraPrefixesMap: Record<string, Slot> = {
|
||||
$body_: 'body',
|
||||
$headers_: 'headers',
|
||||
$path_: 'path',
|
||||
$query_: 'query',
|
||||
};
|
||||
const extraPrefixes = Object.entries(extraPrefixesMap);
|
||||
|
||||
type KeyMap = Map<
|
||||
string,
|
||||
| {
|
||||
in: Slot;
|
||||
map?: string;
|
||||
}
|
||||
| {
|
||||
in?: never;
|
||||
map: Slot;
|
||||
}
|
||||
>;
|
||||
|
||||
function buildKeyMap(fields: FieldsConfig, map?: KeyMap): KeyMap {
|
||||
if (!map) {
|
||||
map = new Map();
|
||||
}
|
||||
|
||||
for (const config of fields) {
|
||||
if ('in' in config) {
|
||||
if (config.key) {
|
||||
map.set(config.key, {
|
||||
in: config.in,
|
||||
map: config.map,
|
||||
});
|
||||
}
|
||||
} else if ('key' in config) {
|
||||
map.set(config.key, {
|
||||
map: config.map,
|
||||
});
|
||||
} else if (config.args) {
|
||||
buildKeyMap(config.args, map);
|
||||
}
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
interface Params {
|
||||
body?: unknown;
|
||||
headers: Record<string, unknown>;
|
||||
path: Record<string, unknown>;
|
||||
query: Record<string, unknown>;
|
||||
}
|
||||
|
||||
function stripEmptySlots(params: Params): void {
|
||||
for (const [slot, value] of Object.entries(params)) {
|
||||
if (slot === 'body') continue;
|
||||
if (value && typeof value === 'object' && !Array.isArray(value) && !Object.keys(value).length) {
|
||||
delete params[slot as Slot];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function buildClientParams(args: ReadonlyArray<unknown>, fields: FieldsConfig): Params {
|
||||
const params: Params = {
|
||||
headers: Object.create(null),
|
||||
path: Object.create(null),
|
||||
query: Object.create(null),
|
||||
};
|
||||
|
||||
const map = buildKeyMap(fields);
|
||||
|
||||
function writeSlot(slot: Slot, key: string, value: unknown): void {
|
||||
let record = params[slot] as Record<string, unknown> | undefined;
|
||||
if (record === undefined) {
|
||||
record = Object.create(null) as Record<string, unknown>;
|
||||
params[slot] = record;
|
||||
}
|
||||
record[key] = value;
|
||||
}
|
||||
|
||||
let config: FieldsConfig[number] | undefined;
|
||||
|
||||
for (const [index, arg] of args.entries()) {
|
||||
if (fields[index]) {
|
||||
config = fields[index];
|
||||
}
|
||||
|
||||
if (!config) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ('in' in config) {
|
||||
if (config.key) {
|
||||
const field = map.get(config.key)!;
|
||||
const name = field.map || config.key;
|
||||
if (field.in) {
|
||||
writeSlot(field.in, name, arg);
|
||||
}
|
||||
} else {
|
||||
params.body = arg;
|
||||
}
|
||||
} else {
|
||||
for (const [key, value] of Object.entries(arg ?? {})) {
|
||||
const field = map.get(key);
|
||||
|
||||
if (field) {
|
||||
if (field.in) {
|
||||
const name = field.map || key;
|
||||
writeSlot(field.in, name, value);
|
||||
} else {
|
||||
params[field.map] = value;
|
||||
}
|
||||
} else {
|
||||
const extra = extraPrefixes.find(([prefix]) => key.startsWith(prefix));
|
||||
|
||||
if (extra) {
|
||||
const [prefix, slot] = extra;
|
||||
writeSlot(slot, key.slice(prefix.length), value);
|
||||
} else if ('allowExtra' in config && config.allowExtra) {
|
||||
for (const [slot, allowed] of Object.entries(config.allowExtra)) {
|
||||
if (allowed) {
|
||||
writeSlot(slot as Slot, key, value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stripEmptySlots(params);
|
||||
|
||||
return params;
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
// This file is auto-generated by @hey-api/openapi-ts
|
||||
|
||||
interface SerializeOptions<T> extends SerializePrimitiveOptions, SerializerOptions<T> {}
|
||||
|
||||
interface SerializePrimitiveOptions {
|
||||
allowReserved?: boolean;
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface SerializerOptions<T> {
|
||||
/**
|
||||
* @default true
|
||||
*/
|
||||
explode: boolean;
|
||||
style: T;
|
||||
}
|
||||
|
||||
export type ArrayStyle = 'form' | 'spaceDelimited' | 'pipeDelimited';
|
||||
export type ArraySeparatorStyle = ArrayStyle | MatrixStyle;
|
||||
type MatrixStyle = 'label' | 'matrix' | 'simple';
|
||||
export type ObjectStyle = 'form' | 'deepObject';
|
||||
type ObjectSeparatorStyle = ObjectStyle | MatrixStyle;
|
||||
|
||||
interface SerializePrimitiveParam extends SerializePrimitiveOptions {
|
||||
value: string;
|
||||
}
|
||||
|
||||
export const separatorArrayExplode = (style: ArraySeparatorStyle): '.' | ';' | ',' | '&' => {
|
||||
switch (style) {
|
||||
case 'label':
|
||||
return '.';
|
||||
case 'matrix':
|
||||
return ';';
|
||||
case 'simple':
|
||||
return ',';
|
||||
default:
|
||||
return '&';
|
||||
}
|
||||
};
|
||||
|
||||
export const separatorArrayNoExplode = (style: ArraySeparatorStyle): ',' | '|' | '%20' => {
|
||||
switch (style) {
|
||||
case 'form':
|
||||
return ',';
|
||||
case 'pipeDelimited':
|
||||
return '|';
|
||||
case 'spaceDelimited':
|
||||
return '%20';
|
||||
default:
|
||||
return ',';
|
||||
}
|
||||
};
|
||||
|
||||
export const separatorObjectExplode = (style: ObjectSeparatorStyle): '.' | ';' | ',' | '&' => {
|
||||
switch (style) {
|
||||
case 'label':
|
||||
return '.';
|
||||
case 'matrix':
|
||||
return ';';
|
||||
case 'simple':
|
||||
return ',';
|
||||
default:
|
||||
return '&';
|
||||
}
|
||||
};
|
||||
|
||||
export const serializeArrayParam = ({
|
||||
allowReserved,
|
||||
explode,
|
||||
name,
|
||||
style,
|
||||
value,
|
||||
}: SerializeOptions<ArraySeparatorStyle> & {
|
||||
value: unknown[];
|
||||
}): string => {
|
||||
if (!explode) {
|
||||
const joinedValues = (
|
||||
allowReserved ? value : value.map((v) => encodeURIComponent(v as string))
|
||||
).join(separatorArrayNoExplode(style));
|
||||
switch (style) {
|
||||
case 'label':
|
||||
return `.${joinedValues}`;
|
||||
case 'matrix':
|
||||
return `;${name}=${joinedValues}`;
|
||||
case 'simple':
|
||||
return joinedValues;
|
||||
default:
|
||||
return `${name}=${joinedValues}`;
|
||||
}
|
||||
}
|
||||
|
||||
const separator = separatorArrayExplode(style);
|
||||
const joinedValues = value
|
||||
.map((v) => {
|
||||
if (style === 'label' || style === 'simple') {
|
||||
return allowReserved ? v : encodeURIComponent(v as string);
|
||||
}
|
||||
|
||||
return serializePrimitiveParam({
|
||||
allowReserved,
|
||||
name,
|
||||
value: v as string,
|
||||
});
|
||||
})
|
||||
.join(separator);
|
||||
return style === 'label' || style === 'matrix' ? separator + joinedValues : joinedValues;
|
||||
};
|
||||
|
||||
export const serializePrimitiveParam = ({
|
||||
allowReserved,
|
||||
name,
|
||||
value,
|
||||
}: SerializePrimitiveParam): string => {
|
||||
if (value === undefined || value === null) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (typeof value === 'object') {
|
||||
throw new Error(
|
||||
'Deeply-nested arrays/objects aren’t supported. Provide your own `querySerializer()` to handle these.',
|
||||
);
|
||||
}
|
||||
|
||||
return `${name}=${allowReserved ? value : encodeURIComponent(value)}`;
|
||||
};
|
||||
|
||||
export const serializeObjectParam = ({
|
||||
allowReserved,
|
||||
explode,
|
||||
name,
|
||||
style,
|
||||
value,
|
||||
valueOnly,
|
||||
}: SerializeOptions<ObjectSeparatorStyle> & {
|
||||
value: Record<string, unknown> | Date;
|
||||
valueOnly?: boolean;
|
||||
}): string => {
|
||||
if (value instanceof Date) {
|
||||
return valueOnly ? value.toISOString() : `${name}=${value.toISOString()}`;
|
||||
}
|
||||
|
||||
if (style !== 'deepObject' && !explode) {
|
||||
let values: string[] = [];
|
||||
Object.entries(value).forEach(([key, v]) => {
|
||||
values = [...values, key, allowReserved ? (v as string) : encodeURIComponent(v as string)];
|
||||
});
|
||||
const joinedValues = values.join(',');
|
||||
switch (style) {
|
||||
case 'form':
|
||||
return `${name}=${joinedValues}`;
|
||||
case 'label':
|
||||
return `.${joinedValues}`;
|
||||
case 'matrix':
|
||||
return `;${name}=${joinedValues}`;
|
||||
default:
|
||||
return joinedValues;
|
||||
}
|
||||
}
|
||||
|
||||
const separator = separatorObjectExplode(style);
|
||||
const joinedValues = Object.entries(value)
|
||||
.map(([key, v]) =>
|
||||
serializePrimitiveParam({
|
||||
allowReserved,
|
||||
name: style === 'deepObject' ? `${name}[${key}]` : key,
|
||||
value: v as string,
|
||||
}),
|
||||
)
|
||||
.join(separator);
|
||||
return style === 'label' || style === 'matrix' ? separator + joinedValues : joinedValues;
|
||||
};
|
||||
@@ -0,0 +1,117 @@
|
||||
// This file is auto-generated by @hey-api/openapi-ts
|
||||
|
||||
/**
|
||||
* JSON-friendly union that mirrors what Pinia Colada can hash.
|
||||
*/
|
||||
export type JsonValue =
|
||||
| null
|
||||
| string
|
||||
| number
|
||||
| boolean
|
||||
| JsonValue[]
|
||||
| { [key: string]: JsonValue };
|
||||
|
||||
/**
|
||||
* Replacer that converts non-JSON values (bigint, Date, etc.) to safe substitutes.
|
||||
*/
|
||||
export const queryKeyJsonReplacer = (_key: string, value: unknown): unknown | undefined => {
|
||||
if (value === undefined || typeof value === 'function' || typeof value === 'symbol') {
|
||||
return undefined;
|
||||
}
|
||||
if (typeof value === 'bigint') {
|
||||
return value.toString();
|
||||
}
|
||||
if (value instanceof Date) {
|
||||
return value.toISOString();
|
||||
}
|
||||
return value;
|
||||
};
|
||||
|
||||
/**
|
||||
* Safely stringifies a value and parses it back into a JsonValue.
|
||||
*/
|
||||
export const stringifyToJsonValue = (input: unknown): JsonValue | undefined => {
|
||||
try {
|
||||
const json = JSON.stringify(input, queryKeyJsonReplacer);
|
||||
if (json === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
return JSON.parse(json) as JsonValue;
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Detects plain objects (including objects with a null prototype).
|
||||
*/
|
||||
const isPlainObject = (value: unknown): value is Record<string, unknown> => {
|
||||
if (value === null || typeof value !== 'object') {
|
||||
return false;
|
||||
}
|
||||
const prototype = Object.getPrototypeOf(value as object);
|
||||
return prototype === Object.prototype || prototype === null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Turns URLSearchParams into a sorted JSON object for deterministic keys.
|
||||
*/
|
||||
const serializeSearchParams = (params: URLSearchParams): JsonValue => {
|
||||
const entries = Array.from(params.entries()).sort(([a], [b]) => a.localeCompare(b));
|
||||
const result: Record<string, JsonValue> = {};
|
||||
|
||||
for (const [key, value] of entries) {
|
||||
const existing = result[key];
|
||||
if (existing === undefined) {
|
||||
result[key] = value;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Array.isArray(existing)) {
|
||||
(existing as string[]).push(value);
|
||||
} else {
|
||||
result[key] = [existing, value];
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
/**
|
||||
* Normalizes any accepted value into a JSON-friendly shape for query keys.
|
||||
*/
|
||||
export const serializeQueryKeyValue = (value: unknown): JsonValue | undefined => {
|
||||
if (value === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
|
||||
return value;
|
||||
}
|
||||
|
||||
if (value === undefined || typeof value === 'function' || typeof value === 'symbol') {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (typeof value === 'bigint') {
|
||||
return value.toString();
|
||||
}
|
||||
|
||||
if (value instanceof Date) {
|
||||
return value.toISOString();
|
||||
}
|
||||
|
||||
if (Array.isArray(value)) {
|
||||
return stringifyToJsonValue(value);
|
||||
}
|
||||
|
||||
if (typeof URLSearchParams !== 'undefined' && value instanceof URLSearchParams) {
|
||||
return serializeSearchParams(value);
|
||||
}
|
||||
|
||||
if (isPlainObject(value)) {
|
||||
return stringifyToJsonValue(value);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
};
|
||||
@@ -0,0 +1,242 @@
|
||||
// This file is auto-generated by @hey-api/openapi-ts
|
||||
|
||||
import type { Config } from './types.gen';
|
||||
|
||||
export type ServerSentEventsOptions<TData = unknown> = Omit<RequestInit, 'method'> &
|
||||
Pick<Config, 'method' | 'responseTransformer' | 'responseValidator'> & {
|
||||
/**
|
||||
* Fetch API implementation. You can use this option to provide a custom
|
||||
* fetch instance.
|
||||
*
|
||||
* @default globalThis.fetch
|
||||
*/
|
||||
fetch?: typeof fetch;
|
||||
/**
|
||||
* Implementing clients can call request interceptors inside this hook.
|
||||
*/
|
||||
onRequest?: (url: string, init: RequestInit) => Promise<Request>;
|
||||
/**
|
||||
* Callback invoked when a network or parsing error occurs during streaming.
|
||||
*
|
||||
* This option applies only if the endpoint returns a stream of events.
|
||||
*
|
||||
* @param error The error that occurred.
|
||||
*/
|
||||
onSseError?: (error: unknown) => void;
|
||||
/**
|
||||
* Callback invoked when an event is streamed from the server.
|
||||
*
|
||||
* This option applies only if the endpoint returns a stream of events.
|
||||
*
|
||||
* @param event Event streamed from the server.
|
||||
* @returns Nothing (void).
|
||||
*/
|
||||
onSseEvent?: (event: StreamEvent<TData>) => void;
|
||||
serializedBody?: RequestInit['body'];
|
||||
/**
|
||||
* Default retry delay in milliseconds.
|
||||
*
|
||||
* This option applies only if the endpoint returns a stream of events.
|
||||
*
|
||||
* @default 3000
|
||||
*/
|
||||
sseDefaultRetryDelay?: number;
|
||||
/**
|
||||
* Maximum number of retry attempts before giving up.
|
||||
*/
|
||||
sseMaxRetryAttempts?: number;
|
||||
/**
|
||||
* Maximum retry delay in milliseconds.
|
||||
*
|
||||
* Applies only when exponential backoff is used.
|
||||
*
|
||||
* This option applies only if the endpoint returns a stream of events.
|
||||
*
|
||||
* @default 30000
|
||||
*/
|
||||
sseMaxRetryDelay?: number;
|
||||
/**
|
||||
* Optional sleep function for retry backoff.
|
||||
*
|
||||
* Defaults to using `setTimeout`.
|
||||
*/
|
||||
sseSleepFn?: (ms: number) => Promise<void>;
|
||||
url: string;
|
||||
};
|
||||
|
||||
export interface StreamEvent<TData = unknown> {
|
||||
data: TData;
|
||||
event?: string;
|
||||
id?: string;
|
||||
retry?: number;
|
||||
}
|
||||
|
||||
export type ServerSentEventsResult<TData = unknown, TReturn = void, TNext = unknown> = {
|
||||
stream: AsyncGenerator<
|
||||
TData extends Record<string, unknown> ? TData[keyof TData] : TData,
|
||||
TReturn,
|
||||
TNext
|
||||
>;
|
||||
};
|
||||
|
||||
export function createSseClient<TData = unknown>({
|
||||
onRequest,
|
||||
onSseError,
|
||||
onSseEvent,
|
||||
responseTransformer,
|
||||
responseValidator,
|
||||
sseDefaultRetryDelay,
|
||||
sseMaxRetryAttempts,
|
||||
sseMaxRetryDelay,
|
||||
sseSleepFn,
|
||||
url,
|
||||
...options
|
||||
}: ServerSentEventsOptions): ServerSentEventsResult<TData> {
|
||||
let lastEventId: string | undefined;
|
||||
|
||||
const sleep = sseSleepFn ?? ((ms: number) => new Promise((resolve) => setTimeout(resolve, ms)));
|
||||
|
||||
const createStream = async function* () {
|
||||
let retryDelay: number = sseDefaultRetryDelay ?? 3000;
|
||||
let attempt = 0;
|
||||
const signal = options.signal ?? new AbortController().signal;
|
||||
|
||||
while (true) {
|
||||
if (signal.aborted) break;
|
||||
|
||||
attempt++;
|
||||
|
||||
const headers =
|
||||
options.headers instanceof Headers
|
||||
? options.headers
|
||||
: new Headers(options.headers as Record<string, string> | undefined);
|
||||
|
||||
if (lastEventId !== undefined) {
|
||||
headers.set('Last-Event-ID', lastEventId);
|
||||
}
|
||||
|
||||
try {
|
||||
const requestInit: RequestInit = {
|
||||
redirect: 'follow',
|
||||
...options,
|
||||
body: options.serializedBody,
|
||||
headers,
|
||||
signal,
|
||||
};
|
||||
let request = new Request(url, requestInit);
|
||||
if (onRequest) {
|
||||
request = await onRequest(url, requestInit);
|
||||
}
|
||||
// fetch must be assigned here, otherwise it would throw the error:
|
||||
// TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation
|
||||
const _fetch = options.fetch ?? globalThis.fetch;
|
||||
const response = await _fetch(request);
|
||||
|
||||
if (!response.ok) throw new Error(`SSE failed: ${response.status} ${response.statusText}`);
|
||||
|
||||
if (!response.body) throw new Error('No body in SSE response');
|
||||
|
||||
const reader = response.body.pipeThrough(new TextDecoderStream()).getReader();
|
||||
|
||||
let buffer = '';
|
||||
|
||||
const abortHandler = () => {
|
||||
try {
|
||||
reader.cancel();
|
||||
} catch {
|
||||
// noop
|
||||
}
|
||||
};
|
||||
|
||||
signal.addEventListener('abort', abortHandler);
|
||||
|
||||
try {
|
||||
while (true) {
|
||||
const { done, value } = await reader.read();
|
||||
if (done) break;
|
||||
buffer += value;
|
||||
buffer = buffer.replace(/\r\n?/g, '\n'); // normalize line endings
|
||||
|
||||
const chunks = buffer.split('\n\n');
|
||||
buffer = chunks.pop() ?? '';
|
||||
|
||||
for (const chunk of chunks) {
|
||||
const lines = chunk.split('\n');
|
||||
const dataLines: Array<string> = [];
|
||||
let eventName: string | undefined;
|
||||
|
||||
for (const line of lines) {
|
||||
if (line.startsWith('data:')) {
|
||||
dataLines.push(line.replace(/^data:\s*/, ''));
|
||||
} else if (line.startsWith('event:')) {
|
||||
eventName = line.replace(/^event:\s*/, '');
|
||||
} else if (line.startsWith('id:')) {
|
||||
lastEventId = line.replace(/^id:\s*/, '');
|
||||
} else if (line.startsWith('retry:')) {
|
||||
const parsed = Number.parseInt(line.replace(/^retry:\s*/, ''), 10);
|
||||
if (!Number.isNaN(parsed)) {
|
||||
retryDelay = parsed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let data: unknown;
|
||||
let parsedJson = false;
|
||||
|
||||
if (dataLines.length) {
|
||||
const rawData = dataLines.join('\n');
|
||||
try {
|
||||
data = JSON.parse(rawData);
|
||||
parsedJson = true;
|
||||
} catch {
|
||||
data = rawData;
|
||||
}
|
||||
}
|
||||
|
||||
if (parsedJson) {
|
||||
if (responseValidator) {
|
||||
await responseValidator(data);
|
||||
}
|
||||
|
||||
if (responseTransformer) {
|
||||
data = await responseTransformer(data);
|
||||
}
|
||||
}
|
||||
|
||||
onSseEvent?.({
|
||||
data,
|
||||
event: eventName,
|
||||
id: lastEventId,
|
||||
retry: retryDelay,
|
||||
});
|
||||
|
||||
if (dataLines.length) {
|
||||
yield data as any;
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
signal.removeEventListener('abort', abortHandler);
|
||||
reader.releaseLock();
|
||||
}
|
||||
|
||||
break; // exit loop on normal completion
|
||||
} catch (error) {
|
||||
// connection failed or aborted; retry after delay
|
||||
onSseError?.(error);
|
||||
|
||||
if (sseMaxRetryAttempts !== undefined && attempt >= sseMaxRetryAttempts) {
|
||||
break; // stop after firing error
|
||||
}
|
||||
|
||||
// exponential backoff: double retry each attempt, cap at 30s
|
||||
const backoff = Math.min(retryDelay * 2 ** (attempt - 1), sseMaxRetryDelay ?? 30000);
|
||||
await sleep(backoff);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const stream = createStream();
|
||||
|
||||
return { stream };
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
// This file is auto-generated by @hey-api/openapi-ts
|
||||
|
||||
import type { Auth, AuthToken } from './auth.gen';
|
||||
import type { BodySerializer, QuerySerializer, QuerySerializerOptions } from './bodySerializer.gen';
|
||||
|
||||
export type HttpMethod =
|
||||
| 'connect'
|
||||
| 'delete'
|
||||
| 'get'
|
||||
| 'head'
|
||||
| 'options'
|
||||
| 'patch'
|
||||
| 'post'
|
||||
| 'put'
|
||||
| 'trace';
|
||||
|
||||
export type Client<
|
||||
RequestFn = never,
|
||||
Config = unknown,
|
||||
MethodFn = never,
|
||||
BuildUrlFn = never,
|
||||
SseFn = never,
|
||||
> = {
|
||||
/**
|
||||
* Returns the final request URL.
|
||||
*/
|
||||
buildUrl: BuildUrlFn;
|
||||
getConfig: () => Config;
|
||||
request: RequestFn;
|
||||
setConfig: (config: Config) => Config;
|
||||
} & {
|
||||
[K in HttpMethod]: MethodFn;
|
||||
} & ([SseFn] extends [never] ? { sse?: never } : { sse: { [K in HttpMethod]: SseFn } });
|
||||
|
||||
export interface Config {
|
||||
/**
|
||||
* Auth token or a function returning auth token. The resolved value will be
|
||||
* added to the request payload as defined by its `security` array.
|
||||
*/
|
||||
auth?: ((auth: Auth) => Promise<AuthToken> | AuthToken) | AuthToken;
|
||||
/**
|
||||
* A function for serializing request body parameter. By default,
|
||||
* {@link JSON.stringify()} will be used.
|
||||
*/
|
||||
bodySerializer?: BodySerializer | null;
|
||||
/**
|
||||
* An object containing any HTTP headers that you want to pre-populate your
|
||||
* `Headers` object with.
|
||||
*
|
||||
* {@link https://developer.mozilla.org/docs/Web/API/Headers/Headers#init See more}
|
||||
*/
|
||||
headers?:
|
||||
| RequestInit['headers']
|
||||
| Record<
|
||||
string,
|
||||
string | number | boolean | (string | number | boolean)[] | null | undefined | unknown
|
||||
>;
|
||||
/**
|
||||
* The request method.
|
||||
*
|
||||
* {@link https://developer.mozilla.org/docs/Web/API/fetch#method See more}
|
||||
*/
|
||||
method?: Uppercase<HttpMethod>;
|
||||
/**
|
||||
* A function for serializing request query parameters. By default, arrays
|
||||
* will be exploded in form style, objects will be exploded in deepObject
|
||||
* style, and reserved characters are percent-encoded.
|
||||
*
|
||||
* This method will have no effect if the native `paramsSerializer()` Axios
|
||||
* API function is used.
|
||||
*
|
||||
* {@link https://swagger.io/docs/specification/serialization/#query View examples}
|
||||
*/
|
||||
querySerializer?: QuerySerializer | QuerySerializerOptions;
|
||||
/**
|
||||
* A function validating request data. This is useful if you want to ensure
|
||||
* the request conforms to the desired shape, so it can be safely sent to
|
||||
* the server.
|
||||
*/
|
||||
requestValidator?: (data: unknown) => Promise<unknown>;
|
||||
/**
|
||||
* A function transforming response data before it's returned. This is useful
|
||||
* for post-processing data, e.g., converting ISO strings into Date objects.
|
||||
*/
|
||||
responseTransformer?: (data: unknown) => Promise<unknown>;
|
||||
/**
|
||||
* A function validating response data. This is useful if you want to ensure
|
||||
* the response conforms to the desired shape, so it can be safely passed to
|
||||
* the transformers and returned to the user.
|
||||
*/
|
||||
responseValidator?: (data: unknown) => Promise<unknown>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Arbitrary metadata passed through the `meta` request option.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
||||
export interface ClientMeta {}
|
||||
|
||||
type IsExactlyNeverOrNeverUndefined<T> = [T] extends [never]
|
||||
? true
|
||||
: [T] extends [never | undefined]
|
||||
? [undefined] extends [T]
|
||||
? false
|
||||
: true
|
||||
: false;
|
||||
|
||||
export type OmitNever<T extends Record<string, unknown>> = {
|
||||
[K in keyof T as IsExactlyNeverOrNeverUndefined<T[K]> extends true ? never : K]: T[K];
|
||||
};
|
||||
@@ -0,0 +1,140 @@
|
||||
// This file is auto-generated by @hey-api/openapi-ts
|
||||
|
||||
import type { BodySerializer, QuerySerializer } from './bodySerializer.gen';
|
||||
import {
|
||||
type ArraySeparatorStyle,
|
||||
serializeArrayParam,
|
||||
serializeObjectParam,
|
||||
serializePrimitiveParam,
|
||||
} from './pathSerializer.gen';
|
||||
|
||||
export interface PathSerializer {
|
||||
path: Record<string, unknown>;
|
||||
url: string;
|
||||
}
|
||||
|
||||
export const PATH_PARAM_RE: RegExp = /\{[^{}]+\}/g;
|
||||
|
||||
export const defaultPathSerializer = ({ path, url: _url }: PathSerializer): string => {
|
||||
let url = _url;
|
||||
const matches = _url.match(PATH_PARAM_RE);
|
||||
if (matches) {
|
||||
for (const match of matches) {
|
||||
let explode = false;
|
||||
let name = match.substring(1, match.length - 1);
|
||||
let style: ArraySeparatorStyle = 'simple';
|
||||
|
||||
if (name.endsWith('*')) {
|
||||
explode = true;
|
||||
name = name.substring(0, name.length - 1);
|
||||
}
|
||||
|
||||
if (name.startsWith('.')) {
|
||||
name = name.substring(1);
|
||||
style = 'label';
|
||||
} else if (name.startsWith(';')) {
|
||||
name = name.substring(1);
|
||||
style = 'matrix';
|
||||
}
|
||||
|
||||
const value = path[name];
|
||||
|
||||
if (value === undefined || value === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Array.isArray(value)) {
|
||||
url = url.replace(match, serializeArrayParam({ explode, name, style, value }));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (typeof value === 'object') {
|
||||
url = url.replace(
|
||||
match,
|
||||
serializeObjectParam({
|
||||
explode,
|
||||
name,
|
||||
style,
|
||||
value: value as Record<string, unknown>,
|
||||
valueOnly: true,
|
||||
}),
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (style === 'matrix') {
|
||||
url = url.replace(
|
||||
match,
|
||||
`;${serializePrimitiveParam({
|
||||
name,
|
||||
value: value as string,
|
||||
})}`,
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
const replaceValue = encodeURIComponent(
|
||||
style === 'label' ? `.${value as string}` : (value as string),
|
||||
);
|
||||
url = url.replace(match, replaceValue);
|
||||
}
|
||||
}
|
||||
return url;
|
||||
};
|
||||
|
||||
export const getUrl = ({
|
||||
baseUrl,
|
||||
path,
|
||||
query,
|
||||
querySerializer,
|
||||
url: _url,
|
||||
}: {
|
||||
baseUrl?: string;
|
||||
path?: Record<string, unknown>;
|
||||
query?: Record<string, unknown>;
|
||||
querySerializer: QuerySerializer;
|
||||
url: string;
|
||||
}): string => {
|
||||
const pathUrl = _url.startsWith('/') ? _url : `/${_url}`;
|
||||
let url = (baseUrl ?? '') + pathUrl;
|
||||
if (path) {
|
||||
url = defaultPathSerializer({ path, url });
|
||||
}
|
||||
let search = query ? querySerializer(query) : '';
|
||||
if (search.startsWith('?')) {
|
||||
search = search.substring(1);
|
||||
}
|
||||
if (search) {
|
||||
url += `?${search}`;
|
||||
}
|
||||
return url;
|
||||
};
|
||||
|
||||
export function getValidRequestBody(options: {
|
||||
body?: unknown;
|
||||
bodySerializer?: BodySerializer | null;
|
||||
serializedBody?: unknown;
|
||||
}): unknown {
|
||||
const hasBody = options.body !== undefined;
|
||||
const isSerializedBody = hasBody && options.bodySerializer;
|
||||
|
||||
if (isSerializedBody) {
|
||||
if ('serializedBody' in options) {
|
||||
const hasSerializedBody =
|
||||
options.serializedBody !== undefined && options.serializedBody !== '';
|
||||
|
||||
return hasSerializedBody ? options.serializedBody : null;
|
||||
}
|
||||
|
||||
// not all clients implement a serializedBody property (i.e., client-axios)
|
||||
return options.body !== '' ? options.body : null;
|
||||
}
|
||||
|
||||
// plain/text body
|
||||
if (hasBody) {
|
||||
return options.body;
|
||||
}
|
||||
|
||||
// no body was provided
|
||||
return undefined;
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
export * from './runtime';
|
||||
export * from './apis/index';
|
||||
export * from './models/index';
|
||||
// This file is auto-generated by @hey-api/openapi-ts
|
||||
|
||||
export { getAllBrands, getAllCurrentPrices, getAllFuelTypes, getAllStations, getAllSuburbs, getBrandsByName, getBrandsByState, getCommonFuelTypes, getCurrentPricesByFuelType, getDailyPriceAverages, getDailyPriceAveragesByStationIds, getDailyPriceAveragesWithinRadius, getDailyPriceAveragesWithinSuburb, getLowestPricesByFuelType, getPricesByStationCode, getPricesForTimePeriod, getStationsByStationCode, getStationsWithinRadius, getStationsWithLowestPricesByFuelType, getStationsWithLowestPricesByFuelTypeWithinRadius, getStationsWithLowestPricesByFuelTypeWithinSuburb, getStationsWithPricesWithinRadius, getStationsWithPricesWithinSuburb, getStationWithPricesByStationCode, getSuburbBoundaryById, getSuburbBoundaryForLocation, getSuburbsByName, type Options } from './sdk.gen';
|
||||
export type { BrandType, ClientOptions, DailyPriceAverage, DailyPriceTrends, DailyPriceTrendsStatistics, FuelSource, FuelType, GetAllBrandsData, GetAllBrandsResponse, GetAllBrandsResponses, GetAllCurrentPricesData, GetAllCurrentPricesResponse, GetAllCurrentPricesResponses, GetAllFuelTypesData, GetAllFuelTypesResponse, GetAllFuelTypesResponses, GetAllStationsData, GetAllStationsResponse, GetAllStationsResponses, GetAllSuburbsData, GetAllSuburbsResponse, GetAllSuburbsResponses, GetBrandsByNameData, GetBrandsByNameResponse, GetBrandsByNameResponses, GetBrandsByStateData, GetBrandsByStateResponse, GetBrandsByStateResponses, GetCommonFuelTypesData, GetCommonFuelTypesResponse, GetCommonFuelTypesResponses, GetCurrentPricesByFuelTypeData, GetCurrentPricesByFuelTypeResponse, GetCurrentPricesByFuelTypeResponses, GetDailyPriceAveragesByStationIdsData, GetDailyPriceAveragesByStationIdsResponse, GetDailyPriceAveragesByStationIdsResponses, GetDailyPriceAveragesData, GetDailyPriceAveragesResponse, GetDailyPriceAveragesResponses, GetDailyPriceAveragesWithinRadiusData, GetDailyPriceAveragesWithinRadiusResponse, GetDailyPriceAveragesWithinRadiusResponses, GetDailyPriceAveragesWithinSuburbData, GetDailyPriceAveragesWithinSuburbResponse, GetDailyPriceAveragesWithinSuburbResponses, GetLowestPricesByFuelTypeData, GetLowestPricesByFuelTypeResponse, GetLowestPricesByFuelTypeResponses, GetPricesByStationCodeData, GetPricesByStationCodeResponse, GetPricesByStationCodeResponses, GetPricesForTimePeriodData, GetPricesForTimePeriodResponse, GetPricesForTimePeriodResponses, GetStationsByStationCodeData, GetStationsByStationCodeResponse, GetStationsByStationCodeResponses, GetStationsWithinRadiusData, GetStationsWithinRadiusResponse, GetStationsWithinRadiusResponses, GetStationsWithLowestPricesByFuelTypeData, GetStationsWithLowestPricesByFuelTypeResponse, GetStationsWithLowestPricesByFuelTypeResponses, GetStationsWithLowestPricesByFuelTypeWithinRadiusData, GetStationsWithLowestPricesByFuelTypeWithinRadiusResponse, GetStationsWithLowestPricesByFuelTypeWithinRadiusResponses, GetStationsWithLowestPricesByFuelTypeWithinSuburbData, GetStationsWithLowestPricesByFuelTypeWithinSuburbResponse, GetStationsWithLowestPricesByFuelTypeWithinSuburbResponses, GetStationsWithPricesWithinRadiusData, GetStationsWithPricesWithinRadiusResponse, GetStationsWithPricesWithinRadiusResponses, GetStationsWithPricesWithinSuburbData, GetStationsWithPricesWithinSuburbResponse, GetStationsWithPricesWithinSuburbResponses, GetStationWithPricesByStationCodeData, GetStationWithPricesByStationCodeResponse, GetStationWithPricesByStationCodeResponses, GetSuburbBoundaryByIdData, GetSuburbBoundaryByIdResponse, GetSuburbBoundaryByIdResponses, GetSuburbBoundaryForLocationData, GetSuburbBoundaryForLocationResponse, GetSuburbBoundaryForLocationResponses, GetSuburbsByNameData, GetSuburbsByNameResponse, GetSuburbsByNameResponses, NumericReferencePoint, PaginationOfPrice, PaginationOfStation, PaginationOfStationWithPrices, Price, Station, StationWithPrices, Suburb, SuburbBoundary, SuburbBoundaryState } from './types.gen';
|
||||
@@ -1,42 +0,0 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* FuelWizardApi | v1
|
||||
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
||||
*
|
||||
* The version of the OpenAPI document: 1.0.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
import { mapValues } from '../runtime';
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
* @interface ApiPricesCurrentGetPageNumberParameter
|
||||
*/
|
||||
export interface ApiPricesCurrentGetPageNumberParameter {
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given object implements the ApiPricesCurrentGetPageNumberParameter interface.
|
||||
*/
|
||||
export function instanceOfApiPricesCurrentGetPageNumberParameter(value: object): value is ApiPricesCurrentGetPageNumberParameter {
|
||||
return true;
|
||||
}
|
||||
|
||||
export function ApiPricesCurrentGetPageNumberParameterFromJSON(json: any): ApiPricesCurrentGetPageNumberParameter {
|
||||
return ApiPricesCurrentGetPageNumberParameterFromJSONTyped(json, false);
|
||||
}
|
||||
|
||||
export function ApiPricesCurrentGetPageNumberParameterFromJSONTyped(json: any, ignoreDiscriminator: boolean): ApiPricesCurrentGetPageNumberParameter {
|
||||
return json;
|
||||
}
|
||||
|
||||
export function ApiPricesCurrentGetPageNumberParameterToJSON(value?: ApiPricesCurrentGetPageNumberParameter | null): any {
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* FuelWizardApi | v1
|
||||
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
||||
*
|
||||
* The version of the OpenAPI document: 1.0.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
import { mapValues } from '../runtime';
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
* @interface ApiPricesCurrentGetPageSizeParameter
|
||||
*/
|
||||
export interface ApiPricesCurrentGetPageSizeParameter {
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given object implements the ApiPricesCurrentGetPageSizeParameter interface.
|
||||
*/
|
||||
export function instanceOfApiPricesCurrentGetPageSizeParameter(value: object): value is ApiPricesCurrentGetPageSizeParameter {
|
||||
return true;
|
||||
}
|
||||
|
||||
export function ApiPricesCurrentGetPageSizeParameterFromJSON(json: any): ApiPricesCurrentGetPageSizeParameter {
|
||||
return ApiPricesCurrentGetPageSizeParameterFromJSONTyped(json, false);
|
||||
}
|
||||
|
||||
export function ApiPricesCurrentGetPageSizeParameterFromJSONTyped(json: any, ignoreDiscriminator: boolean): ApiPricesCurrentGetPageSizeParameter {
|
||||
return json;
|
||||
}
|
||||
|
||||
export function ApiPricesCurrentGetPageSizeParameterToJSON(value?: ApiPricesCurrentGetPageSizeParameter | null): any {
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* FuelWizardApi | v1
|
||||
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
||||
*
|
||||
* The version of the OpenAPI document: 1.0.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
import { mapValues } from '../runtime';
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
* @interface ApiPricesCurrentStationGetStationCodeParameter
|
||||
*/
|
||||
export interface ApiPricesCurrentStationGetStationCodeParameter {
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given object implements the ApiPricesCurrentStationGetStationCodeParameter interface.
|
||||
*/
|
||||
export function instanceOfApiPricesCurrentStationGetStationCodeParameter(value: object): value is ApiPricesCurrentStationGetStationCodeParameter {
|
||||
return true;
|
||||
}
|
||||
|
||||
export function ApiPricesCurrentStationGetStationCodeParameterFromJSON(json: any): ApiPricesCurrentStationGetStationCodeParameter {
|
||||
return ApiPricesCurrentStationGetStationCodeParameterFromJSONTyped(json, false);
|
||||
}
|
||||
|
||||
export function ApiPricesCurrentStationGetStationCodeParameterFromJSONTyped(json: any, ignoreDiscriminator: boolean): ApiPricesCurrentStationGetStationCodeParameter {
|
||||
return json;
|
||||
}
|
||||
|
||||
export function ApiPricesCurrentStationGetStationCodeParameterToJSON(value?: ApiPricesCurrentStationGetStationCodeParameter | null): any {
|
||||
return value;
|
||||
}
|
||||
|
||||
-42
@@ -1,42 +0,0 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* FuelWizardApi | v1
|
||||
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
||||
*
|
||||
* The version of the OpenAPI document: 1.0.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
import { mapValues } from '../runtime';
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
* @interface ApiStationsWithPricesLowestPricesByFuelTypeWithinRadiusGetPageSizeParameter
|
||||
*/
|
||||
export interface ApiStationsWithPricesLowestPricesByFuelTypeWithinRadiusGetPageSizeParameter {
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given object implements the ApiStationsWithPricesLowestPricesByFuelTypeWithinRadiusGetPageSizeParameter interface.
|
||||
*/
|
||||
export function instanceOfApiStationsWithPricesLowestPricesByFuelTypeWithinRadiusGetPageSizeParameter(value: object): value is ApiStationsWithPricesLowestPricesByFuelTypeWithinRadiusGetPageSizeParameter {
|
||||
return true;
|
||||
}
|
||||
|
||||
export function ApiStationsWithPricesLowestPricesByFuelTypeWithinRadiusGetPageSizeParameterFromJSON(json: any): ApiStationsWithPricesLowestPricesByFuelTypeWithinRadiusGetPageSizeParameter {
|
||||
return ApiStationsWithPricesLowestPricesByFuelTypeWithinRadiusGetPageSizeParameterFromJSONTyped(json, false);
|
||||
}
|
||||
|
||||
export function ApiStationsWithPricesLowestPricesByFuelTypeWithinRadiusGetPageSizeParameterFromJSONTyped(json: any, ignoreDiscriminator: boolean): ApiStationsWithPricesLowestPricesByFuelTypeWithinRadiusGetPageSizeParameter {
|
||||
return json;
|
||||
}
|
||||
|
||||
export function ApiStationsWithPricesLowestPricesByFuelTypeWithinRadiusGetPageSizeParameterToJSON(value?: ApiStationsWithPricesLowestPricesByFuelTypeWithinRadiusGetPageSizeParameter | null): any {
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* FuelWizardApi | v1
|
||||
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
||||
*
|
||||
* The version of the OpenAPI document: 1.0.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
import { mapValues } from '../runtime';
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
* @interface ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameter
|
||||
*/
|
||||
export interface ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameter {
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given object implements the ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameter interface.
|
||||
*/
|
||||
export function instanceOfApiTrendsDailyAveragesWithinRadiusGetLatitudeParameter(value: object): value is ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameter {
|
||||
return true;
|
||||
}
|
||||
|
||||
export function ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameterFromJSON(json: any): ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameter {
|
||||
return ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameterFromJSONTyped(json, false);
|
||||
}
|
||||
|
||||
export function ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameterFromJSONTyped(json: any, ignoreDiscriminator: boolean): ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameter {
|
||||
return json;
|
||||
}
|
||||
|
||||
export function ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameterToJSON(value?: ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameter | null): any {
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* FuelWizardApi | v1
|
||||
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
||||
*
|
||||
* The version of the OpenAPI document: 1.0.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
import { mapValues } from '../runtime';
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
* @interface BrandType
|
||||
*/
|
||||
export interface BrandType {
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof BrandType
|
||||
*/
|
||||
id?: string;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof BrandType
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof BrandType
|
||||
*/
|
||||
state?: string;
|
||||
/**
|
||||
*
|
||||
* @type {Date}
|
||||
* @memberof BrandType
|
||||
*/
|
||||
createdAt?: Date;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given object implements the BrandType interface.
|
||||
*/
|
||||
export function instanceOfBrandType(value: object): value is BrandType {
|
||||
return true;
|
||||
}
|
||||
|
||||
export function BrandTypeFromJSON(json: any): BrandType {
|
||||
return BrandTypeFromJSONTyped(json, false);
|
||||
}
|
||||
|
||||
export function BrandTypeFromJSONTyped(json: any, ignoreDiscriminator: boolean): BrandType {
|
||||
if (json == null) {
|
||||
return json;
|
||||
}
|
||||
return {
|
||||
|
||||
'id': json['id'] == null ? undefined : json['id'],
|
||||
'name': json['name'] == null ? undefined : json['name'],
|
||||
'state': json['state'] == null ? undefined : json['state'],
|
||||
'createdAt': json['createdAt'] == null ? undefined : (new Date(json['createdAt'])),
|
||||
};
|
||||
}
|
||||
|
||||
export function BrandTypeToJSON(value?: BrandType | null): any {
|
||||
if (value == null) {
|
||||
return value;
|
||||
}
|
||||
return {
|
||||
|
||||
'id': value['id'],
|
||||
'name': value['name'],
|
||||
'state': value['state'],
|
||||
'createdAt': value['createdAt'] == null ? undefined : ((value['createdAt']).toISOString()),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* FuelWizardApi | v1
|
||||
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
||||
*
|
||||
* The version of the OpenAPI document: 1.0.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
import { mapValues } from '../runtime';
|
||||
import type { ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameter } from './ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameter';
|
||||
import {
|
||||
ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameterFromJSON,
|
||||
ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameterFromJSONTyped,
|
||||
ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameterToJSON,
|
||||
} from './ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameter';
|
||||
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
* @interface DailyPriceAverage
|
||||
*/
|
||||
export interface DailyPriceAverage {
|
||||
/**
|
||||
*
|
||||
* @type {Date}
|
||||
* @memberof DailyPriceAverage
|
||||
*/
|
||||
date?: Date;
|
||||
/**
|
||||
*
|
||||
* @type {ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameter}
|
||||
* @memberof DailyPriceAverage
|
||||
*/
|
||||
averagePriceValue?: ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given object implements the DailyPriceAverage interface.
|
||||
*/
|
||||
export function instanceOfDailyPriceAverage(value: object): value is DailyPriceAverage {
|
||||
return true;
|
||||
}
|
||||
|
||||
export function DailyPriceAverageFromJSON(json: any): DailyPriceAverage {
|
||||
return DailyPriceAverageFromJSONTyped(json, false);
|
||||
}
|
||||
|
||||
export function DailyPriceAverageFromJSONTyped(json: any, ignoreDiscriminator: boolean): DailyPriceAverage {
|
||||
if (json == null) {
|
||||
return json;
|
||||
}
|
||||
return {
|
||||
|
||||
'date': json['date'] == null ? undefined : (new Date(json['date'])),
|
||||
'averagePriceValue': json['averagePriceValue'] == null ? undefined : ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameterFromJSON(json['averagePriceValue']),
|
||||
};
|
||||
}
|
||||
|
||||
export function DailyPriceAverageToJSON(value?: DailyPriceAverage | null): any {
|
||||
if (value == null) {
|
||||
return value;
|
||||
}
|
||||
return {
|
||||
|
||||
'date': value['date'] == null ? undefined : ((value['date']).toISOString()),
|
||||
'averagePriceValue': ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameterToJSON(value['averagePriceValue']),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* FuelWizardApi | v1
|
||||
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
||||
*
|
||||
* The version of the OpenAPI document: 1.0.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
import { mapValues } from '../runtime';
|
||||
import type { DailyPriceAverage } from './DailyPriceAverage';
|
||||
import {
|
||||
DailyPriceAverageFromJSON,
|
||||
DailyPriceAverageFromJSONTyped,
|
||||
DailyPriceAverageToJSON,
|
||||
} from './DailyPriceAverage';
|
||||
import type { DailyPriceTrendsStatistics } from './DailyPriceTrendsStatistics';
|
||||
import {
|
||||
DailyPriceTrendsStatisticsFromJSON,
|
||||
DailyPriceTrendsStatisticsFromJSONTyped,
|
||||
DailyPriceTrendsStatisticsToJSON,
|
||||
} from './DailyPriceTrendsStatistics';
|
||||
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
* @interface DailyPriceTrends
|
||||
*/
|
||||
export interface DailyPriceTrends {
|
||||
/**
|
||||
*
|
||||
* @type {Array<DailyPriceAverage>}
|
||||
* @memberof DailyPriceTrends
|
||||
*/
|
||||
dailyAverages?: Array<DailyPriceAverage>;
|
||||
/**
|
||||
*
|
||||
* @type {DailyPriceTrendsStatistics}
|
||||
* @memberof DailyPriceTrends
|
||||
*/
|
||||
statistics?: DailyPriceTrendsStatistics;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given object implements the DailyPriceTrends interface.
|
||||
*/
|
||||
export function instanceOfDailyPriceTrends(value: object): value is DailyPriceTrends {
|
||||
return true;
|
||||
}
|
||||
|
||||
export function DailyPriceTrendsFromJSON(json: any): DailyPriceTrends {
|
||||
return DailyPriceTrendsFromJSONTyped(json, false);
|
||||
}
|
||||
|
||||
export function DailyPriceTrendsFromJSONTyped(json: any, ignoreDiscriminator: boolean): DailyPriceTrends {
|
||||
if (json == null) {
|
||||
return json;
|
||||
}
|
||||
return {
|
||||
|
||||
'dailyAverages': json['dailyAverages'] == null ? undefined : ((json['dailyAverages'] as Array<any>).map(DailyPriceAverageFromJSON)),
|
||||
'statistics': json['statistics'] == null ? undefined : DailyPriceTrendsStatisticsFromJSON(json['statistics']),
|
||||
};
|
||||
}
|
||||
|
||||
export function DailyPriceTrendsToJSON(value?: DailyPriceTrends | null): any {
|
||||
if (value == null) {
|
||||
return value;
|
||||
}
|
||||
return {
|
||||
|
||||
'dailyAverages': value['dailyAverages'] == null ? undefined : ((value['dailyAverages'] as Array<any>).map(DailyPriceAverageToJSON)),
|
||||
'statistics': DailyPriceTrendsStatisticsToJSON(value['statistics']),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,105 +0,0 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* FuelWizardApi | v1
|
||||
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
||||
*
|
||||
* The version of the OpenAPI document: 1.0.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
import { mapValues } from '../runtime';
|
||||
import type { ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameter } from './ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameter';
|
||||
import {
|
||||
ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameterFromJSON,
|
||||
ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameterFromJSONTyped,
|
||||
ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameterToJSON,
|
||||
} from './ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameter';
|
||||
import type { DailyPriceTrendsStatisticsDailyAverageMax } from './DailyPriceTrendsStatisticsDailyAverageMax';
|
||||
import {
|
||||
DailyPriceTrendsStatisticsDailyAverageMaxFromJSON,
|
||||
DailyPriceTrendsStatisticsDailyAverageMaxFromJSONTyped,
|
||||
DailyPriceTrendsStatisticsDailyAverageMaxToJSON,
|
||||
} from './DailyPriceTrendsStatisticsDailyAverageMax';
|
||||
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
* @interface DailyPriceTrendsStatistics
|
||||
*/
|
||||
export interface DailyPriceTrendsStatistics {
|
||||
/**
|
||||
*
|
||||
* @type {ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameter}
|
||||
* @memberof DailyPriceTrendsStatistics
|
||||
*/
|
||||
maxPriceValue?: ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameter;
|
||||
/**
|
||||
*
|
||||
* @type {ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameter}
|
||||
* @memberof DailyPriceTrendsStatistics
|
||||
*/
|
||||
minPriceValue?: ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameter;
|
||||
/**
|
||||
*
|
||||
* @type {ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameter}
|
||||
* @memberof DailyPriceTrendsStatistics
|
||||
*/
|
||||
periodAverage?: ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameter;
|
||||
/**
|
||||
*
|
||||
* @type {DailyPriceTrendsStatisticsDailyAverageMax}
|
||||
* @memberof DailyPriceTrendsStatistics
|
||||
*/
|
||||
dailyAverageMax?: DailyPriceTrendsStatisticsDailyAverageMax | null;
|
||||
/**
|
||||
*
|
||||
* @type {DailyPriceTrendsStatisticsDailyAverageMax}
|
||||
* @memberof DailyPriceTrendsStatistics
|
||||
*/
|
||||
dailyAverageMin?: DailyPriceTrendsStatisticsDailyAverageMax | null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given object implements the DailyPriceTrendsStatistics interface.
|
||||
*/
|
||||
export function instanceOfDailyPriceTrendsStatistics(value: object): value is DailyPriceTrendsStatistics {
|
||||
return true;
|
||||
}
|
||||
|
||||
export function DailyPriceTrendsStatisticsFromJSON(json: any): DailyPriceTrendsStatistics {
|
||||
return DailyPriceTrendsStatisticsFromJSONTyped(json, false);
|
||||
}
|
||||
|
||||
export function DailyPriceTrendsStatisticsFromJSONTyped(json: any, ignoreDiscriminator: boolean): DailyPriceTrendsStatistics {
|
||||
if (json == null) {
|
||||
return json;
|
||||
}
|
||||
return {
|
||||
|
||||
'maxPriceValue': json['maxPriceValue'] == null ? undefined : ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameterFromJSON(json['maxPriceValue']),
|
||||
'minPriceValue': json['minPriceValue'] == null ? undefined : ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameterFromJSON(json['minPriceValue']),
|
||||
'periodAverage': json['periodAverage'] == null ? undefined : ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameterFromJSON(json['periodAverage']),
|
||||
'dailyAverageMax': json['dailyAverageMax'] == null ? undefined : DailyPriceTrendsStatisticsDailyAverageMaxFromJSON(json['dailyAverageMax']),
|
||||
'dailyAverageMin': json['dailyAverageMin'] == null ? undefined : DailyPriceTrendsStatisticsDailyAverageMaxFromJSON(json['dailyAverageMin']),
|
||||
};
|
||||
}
|
||||
|
||||
export function DailyPriceTrendsStatisticsToJSON(value?: DailyPriceTrendsStatistics | null): any {
|
||||
if (value == null) {
|
||||
return value;
|
||||
}
|
||||
return {
|
||||
|
||||
'maxPriceValue': ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameterToJSON(value['maxPriceValue']),
|
||||
'minPriceValue': ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameterToJSON(value['minPriceValue']),
|
||||
'periodAverage': ApiTrendsDailyAveragesWithinRadiusGetLatitudeParameterToJSON(value['periodAverage']),
|
||||
'dailyAverageMax': DailyPriceTrendsStatisticsDailyAverageMaxToJSON(value['dailyAverageMax']),
|
||||
'dailyAverageMin': DailyPriceTrendsStatisticsDailyAverageMaxToJSON(value['dailyAverageMin']),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* FuelWizardApi | v1
|
||||
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
||||
*
|
||||
* The version of the OpenAPI document: 1.0.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
import { mapValues } from '../runtime';
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
* @interface DailyPriceTrendsStatisticsDailyAverageMax
|
||||
*/
|
||||
export interface DailyPriceTrendsStatisticsDailyAverageMax {
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given object implements the DailyPriceTrendsStatisticsDailyAverageMax interface.
|
||||
*/
|
||||
export function instanceOfDailyPriceTrendsStatisticsDailyAverageMax(value: object): value is DailyPriceTrendsStatisticsDailyAverageMax {
|
||||
return true;
|
||||
}
|
||||
|
||||
export function DailyPriceTrendsStatisticsDailyAverageMaxFromJSON(json: any): DailyPriceTrendsStatisticsDailyAverageMax {
|
||||
return DailyPriceTrendsStatisticsDailyAverageMaxFromJSONTyped(json, false);
|
||||
}
|
||||
|
||||
export function DailyPriceTrendsStatisticsDailyAverageMaxFromJSONTyped(json: any, ignoreDiscriminator: boolean): DailyPriceTrendsStatisticsDailyAverageMax {
|
||||
return json;
|
||||
}
|
||||
|
||||
export function DailyPriceTrendsStatisticsDailyAverageMaxToJSON(value?: DailyPriceTrendsStatisticsDailyAverageMax | null): any {
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* FuelWizardApi | v1
|
||||
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
||||
*
|
||||
* The version of the OpenAPI document: 1.0.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
*/
|
||||
export const FuelSource = {
|
||||
Nsw: 'nsw',
|
||||
Vic: 'vic',
|
||||
Wa: 'wa'
|
||||
} as const;
|
||||
export type FuelSource = typeof FuelSource[keyof typeof FuelSource];
|
||||
|
||||
|
||||
export function instanceOfFuelSource(value: any): boolean {
|
||||
for (const key in FuelSource) {
|
||||
if (Object.prototype.hasOwnProperty.call(FuelSource, key)) {
|
||||
if (FuelSource[key as keyof typeof FuelSource] === value) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function FuelSourceFromJSON(json: any): FuelSource {
|
||||
return FuelSourceFromJSONTyped(json, false);
|
||||
}
|
||||
|
||||
export function FuelSourceFromJSONTyped(json: any, ignoreDiscriminator: boolean): FuelSource {
|
||||
return json as FuelSource;
|
||||
}
|
||||
|
||||
export function FuelSourceToJSON(value?: FuelSource | null): any {
|
||||
return value as any;
|
||||
}
|
||||
|
||||
@@ -1,92 +0,0 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* FuelWizardApi | v1
|
||||
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
||||
*
|
||||
* The version of the OpenAPI document: 1.0.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
import { mapValues } from '../runtime';
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
* @interface FuelType
|
||||
*/
|
||||
export interface FuelType {
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof FuelType
|
||||
*/
|
||||
id?: string;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof FuelType
|
||||
*/
|
||||
code?: string;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof FuelType
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof FuelType
|
||||
*/
|
||||
state?: string;
|
||||
/**
|
||||
*
|
||||
* @type {Date}
|
||||
* @memberof FuelType
|
||||
*/
|
||||
createdAt?: Date;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given object implements the FuelType interface.
|
||||
*/
|
||||
export function instanceOfFuelType(value: object): value is FuelType {
|
||||
return true;
|
||||
}
|
||||
|
||||
export function FuelTypeFromJSON(json: any): FuelType {
|
||||
return FuelTypeFromJSONTyped(json, false);
|
||||
}
|
||||
|
||||
export function FuelTypeFromJSONTyped(json: any, ignoreDiscriminator: boolean): FuelType {
|
||||
if (json == null) {
|
||||
return json;
|
||||
}
|
||||
return {
|
||||
|
||||
'id': json['id'] == null ? undefined : json['id'],
|
||||
'code': json['code'] == null ? undefined : json['code'],
|
||||
'name': json['name'] == null ? undefined : json['name'],
|
||||
'state': json['state'] == null ? undefined : json['state'],
|
||||