Small Fastify + GraphQL Yoga service that uses Open-Meteo (geocoding + forecast, no API key) for weather by city, and API Ninjas for the dictionary, plus a tiny in-memory webhook debug API.
- Node.js 20+
pnpm(or adapt commands for your package manager)
pnpm install
cp .env.example .envEdit .env and set API_NINJAS_API_KEY from your API Ninjas account.
pnpm devThe server listens on PORT from the environment (default 3000).
| Script | Description |
|---|---|
pnpm dev |
tsx watch mode |
pnpm start |
single run |
pnpm test |
Vitest |
pnpm typecheck |
tsc --noEmit |
| Name | Required | Description |
|---|---|---|
API_NINJAS_API_KEY |
Yes | X-Api-Key for dictionary calls to api.api-ninjas.com only (weather does not use it) |
PORT |
No | HTTP port (default 3000) |
LOG_LEVEL |
No | Optional; consumed when creating the stdout-backed logger (src/lib/logger.ts) |
curl -sS http://localhost:3000/healthcheckDictionary (works with a valid API key):
curl -sS http://localhost:3000/graphql \
-H 'content-type: application/json' \
--data-binary '{"query":"{ dictionary(word: \"computer\") { word valid definition } }"}'Composite insights (uses both upstream endpoints):
curl -sS http://localhost:3000/graphql \
-H 'content-type: application/json' \
--data-binary '{"query":"{ insights(input: { city: \"Amsterdam\", word: \"computer\" }) { summary weather { city tempC humidity windKph } dictionary { word valid definition } } }"}'Weather-only query
curl -sS http://localhost:3000/graphql \
-H 'content-type: application/json' \
--data-binary '{"query":"{ weatherByCity(city: \"Amsterdam\") { city tempC humidity windKph } }"}'Ingest webhook
curl -sS http://localhost:3000/webhook/events \
-H 'content-type: application/json' \
--data-binary '{"type":"order.created","payload":{"id":123}}'Debug: last 10 webhook events
curl -sS http://localhost:3000/debug/state