Weather API is a Node.js application that combines information from two different APIs, Musement for cities and WeatherApi for weather information, providing the weather information for each city where Musement has activities to sell. The information can be obtained by calling an API route or by running a script from the command line interface (CLI).
The application could be run directly using package scripts or using Docker container
The project root is under /src
folder, the target for built application is /dist
folder and obviously the folder /test
is used to perform unit and integration tests.
On /src
folder you can find the mail file index.ts
and all others files of the application under the folder app
.
The folders of the application are divided per role, routes, controllers, cli and lib.
The common libraries are under lib
folder, the cli
folder contains all script that could be executed outside the application directly in Command Line Interface (CLI).
Additional documentation could be placed on /docs
folder.
project
│ README.md
│ LICENSE
│ CHANGELOG.md
│
├────src
│ │ index.ts
│ │
│ └─app
│ │ server.ts
│ │
│ ├─controllers
│ │ │ api.controller.ts
│ │
│ ├─routes
│ │ │ index.ts
│ │ │ api.ts
│ │
│ ├─cli
│ │ │ forecast.ts
│ │
│ └─lib
│ │ forecast.ts
│ │ musement.ts
│ │ weather.ts
│
├─test
│ │ index.ts
│
├────dist
│
└────docs
You can run the project directly or better under docker container.
Obviously Node and npm installation is mandatory, the project use the LTS version 14.17.3 and npm version 7.20.1, check if Node is rightly installed, it could be useful use NVM to guarantee the use of the right version of Node and avoid issues dues to the use of a different version.
You have to provide an API Key for the Weather API, if you have no one you can register an account on this page and get one.
-
Clone the repo
git clone https://github.com/zauker/wheater-api.git
-
Install NPM packages
npm install
-
Set Environment (standalone run)
Before run the project you have to set the environment vars. The base URL of the APIs are without protocol, ideally you could use a different protocol (http/https), when the protocol is not specified https will be used. For weather API you have to set a key too.
The API route could perform a call to a limit number of cities, or for a certain number of a forecast days, language could be setted too (so the name of cities and weather condition descriptions will be served in the required language).
The values setted in env vars is used as default setting and used if any params are passed with the call.
These value is used also to perform test, if necessary we could set a different environment set for test purpose.
PORT is the port number of the express server
MUSEMENT_API_BASE_URL=sandbox.musement.com/api/v3/ WEATHER_API_BASE_URL=api.weatherapi.com/v1/ WEATHER_API_AUTH_KEY=**your-key-here** DEFAULT_CITY_LIMIT= DEFAULT_FORECAST_DAYS=2 DEFAULT_LANG=en PORT=3000
There is a
.env.sample
that you can use. -
Set Environment (docker run)
For Docker run you have to set three .env file, on the project you can find three sample .env files that you easily copy and customize. To run the project you have only to provide a valid weather API key.
The approach with .env is different the directly use of the app (without docker).
Run app directly is a possibility but we suppose in next future could be mandatory (or simply easier) using only docker container.
If we introduce in the project other services like Redis or MongoDB for example, run Docker will provide the entire development enviroiment with all needed services.
Dockerfile
anddocker-compose
configuration files use the file .env for customize docker configurations.For example in configuration we can find this setting
ports: - ${EXPOSE_PORT}:${PORT}
EXPOSE_PORT (public port of container) and PORT (running port on container) are retrieved from .env file.
We have two specific enviroinment docker-compose configuration both for dev and prod.
All the enviroimnet setting for produtione are read from specific file
.env.prod
and the same is for development that use the file.env.dev
.In this case we can set the dev and production enviroiment with properly values (sandbox api for dev for example).
In this per enviroment files we expect the params MUSEMENT_API_BASE_URL, WEATHER_API_BASE_URL and WEATHER_API_AUTH_KEY to run calls to external APIs.
DEFAULT_CITY_LIMIT, DEFAULT_FORECAST_DAYS, and DEFAULT_LANG are optional params, if provided they are assumed as default value on external APIs' calls.
For example DEFAULT_FORECAST_DAYS is setted to 2, this means if a call to the app route '/forecast' without any additiona params provide forecast data for next two days.
If this param is not setted the api perform a call and provide the number of forecast data provided by the external Weather API.
You can run the application locally without using Docker. This is an overview of command setted in script section of package.json.
- lint : run linter for code analysis
- test : perform tests
- coverage : perform tests and check the coverage of testing code
- build : build the source typescript code to javascript
- dev : run the application in development mode, the code in src folder are in watch and app restart when updates occurred.
- start : run the built application
So you can start the application run the command:
npm run dev
or the following
npm run build
npm run start
For Docker we use docker-compose that set one container called weather-api
.
We have to different setting for Dev and Prod environment.
Docker build use the .env
variables for building the container, in this step only PORT
and EXPOSE_PORT
are used. The other environment variables are setted inside the container.
You could override the value of env vars setted in the container using specific .env files.
- .env.dev : is used in development configuration
- .env.prod : is used in production configuration
Build dev
docker-compose -f docker-compose.yml -f docker-compose.dev.yml build
Run dev
docker-compose -f docker-compose.yml -f docker-compose.dev.yml up
Build prod
docker-compose -f docker-compose.yml -f docker-compose.prod.yml build
Run prod
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up
The Development container run the command npm run dev
so the application start in watch mode. The Production container run the npm run start
the container has not src and test folder and dev-dependencies installed.
The CLI command return only a text/plain response in console log.
It doesn't handle argvs but it take the setted default value of limit, days and lang from ENV setting.
Run as develop mode (right from TS)
nodemon -r tsconfig-paths/register src/app/cli/forecast.ts
or
npx ts-node -r tsconfig-paths/register src/app/cli/forecast.ts
Run from built (using node)
node dist/app/cli/forecast.js
Override .env setting
DEFAULT_CITY_LIMIT=5 nodemon -r tsconfig-paths/register src/app/cli/forecast.ts
or
DEFAULT_CITY_LIMIT=5 node dist/app/cli/forecast.js
Method: GET
URL: /api/forecast
Full url example: http://localhost:3000/api/forecast
Request Params
-
limit
- description: limit the number of cities retrieved
- type: integer
- default value: 0 (is setted via environment)
- required: false
-
days
- description: number of day of forecast data
- type: integer
- default value: 2 (is setted via environment)
- required: false
-
lang
- description: set the lang to localize data values
- type: string
- default value: en (is setted via environment)
- required: false
-
200 Ok
-
application/json
{ "city": "Rome", "forecast": [ "Partly cloudy", "Moderate rain" ] }
-
text/plain
Processed city Amsterdam | Patchy rain possible, Patchy rain possible<br>\n Processed city Paris | Patchy rain possible, Patchy rain possible<br>\n Processed city Rome | Partly cloudy, Partly cloudy<br>\n
-
text/html
Processed city Amsterdam | Patchy rain possible, Patchy rain possible\n Processed city Paris | Patchy rain possible, Patchy rain possible\n Processed city Rome | Partly cloudy, Partly cloudy\n
-
-
503 Service Unavailable
-
text/html
Service Unavailable
-
See the open issues for a list of proposed features (and known issues).
Add params validator with Express Validator.
Add argvs handling in CLI script.
Localize also the statement Processed city
on responses.
We should consider to introduce a Redis caching system to reduce the use of external API, it improves the performance and might be useful in case of API with a free tier quota or pay per use formula.
We should consider to introduce a mock server for testing external API, in this way test are faster and API doesn't consume the free tier quota for testing.
We plan to build new routes to store and retrieve city/forecast data. All information and documentation about this task are under docs/new-api
folder.
Distributed under the MIT License. See LICENSE
for more information.
Michele Menciassi - m.menciassi@gmail.com
Project Link: https://github.com/zauker/wheater-api