Skip to content

Commit eaa5365

Browse files
committed
feat: add AccuWeather recipe and update backend-restapi documentation with roadmap items
1 parent b8f21f0 commit eaa5365

4 files changed

Lines changed: 51 additions & 0 deletions

File tree

packages/backend-restapi-recipes/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ REST APIs have wildly different standards for pagination, filtering, and authent
77

88
## Available Recipes
99
- **OpenWeatherMap**: Maps `city`, `lat`, and `lon` filters to the appropriate query strings (`q`, `lat`, `lon`), and automatically injects the `appid` key.
10+
- **AccuWeather**: Translates location searches (`q`, `city`, `locationKey`) and automatically injects `apikey`, `language`, and `details=true`.
1011
- **CoinGecko**: Translates standard Quatrain pagination into CoinGecko's `page` and `per_page` query parameters.
1112

1213
## Basic Usage
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { Filters, Filter, SortAndLimit } from '@quatrain/backend'
2+
import { RestAdapterOptions, QuerySerializer } from '@quatrain/backend-restapi'
3+
import { RestApiRecipe } from './RestApiRecipe'
4+
5+
export class AccuweatherRecipe implements RestApiRecipe {
6+
public name = 'AccuWeather'
7+
public defaultBaseUrl = 'http://dataservice.accuweather.com'
8+
9+
private apiKey: string
10+
11+
constructor(apiKey: string) {
12+
this.apiKey = apiKey
13+
}
14+
15+
public querySerializer: QuerySerializer = (filters: Filters | Filter[] | undefined, pagination: SortAndLimit | undefined) => {
16+
const params: Record<string, string> = {
17+
apikey: this.apiKey,
18+
language: 'en-us',
19+
details: 'true'
20+
}
21+
22+
if (filters) {
23+
const filterArray = Array.isArray(filters) ? filters : [filters]
24+
for (const f of filterArray) {
25+
if ('property' in f && 'value' in f) {
26+
// AccuWeather often uses 'q' for location searches
27+
if (f.property === 'q' || f.property === 'city') params['q'] = String(f.value)
28+
// For geocoding or specific keys
29+
if (f.property === 'locationKey') params['locationKey'] = String(f.value)
30+
}
31+
}
32+
}
33+
34+
return params
35+
}
36+
37+
public getOptions(overrides?: Partial<RestAdapterOptions>): RestAdapterOptions {
38+
return {
39+
baseUrl: this.defaultBaseUrl,
40+
querySerializer: this.querySerializer,
41+
...overrides
42+
}
43+
}
44+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
export * from './RestApiRecipe'
22
export * from './OpenWeatherMapRecipe'
33
export * from './CoinGeckoRecipe'
4+
export * from './AccuweatherRecipe'

packages/backend-restapi/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,8 @@ class CustomRestAdapter extends RestBackendAdapter {
4848

4949
## Recipes
5050
See the `@quatrain/backend-restapi-recipes` package for community-maintained query serializers for famous APIs (OpenWeatherMap, CoinGecko, etc.).
51+
52+
## TODO
53+
- [ ] **Multi-Format Parsing**: Evolve `ApiClient` to respect the `responseType` parameter (avoiding forced `.json()`) to allow ingesting `CSV` or `XML` payloads.
54+
- [ ] **Custom Response Parsers**: Introduce a `responseParser?: (rawResponse: any) => Record<string, any>[]` in `RestAdapterOptions` to parse exotic formats into Quatrain-compatible objects.
55+
- [ ] **Hypertext API Navigation**: Support HTML-based APIs by utilizing `@quatrain/ai` within the `responseParser` to extract JSON from unstructured web pages.

0 commit comments

Comments
 (0)