A weather subscription service built with NestJS that allows users to subscribe for regular weather updates by email for a selected city. This project is implemented as part of the Software Engineering School 5.0 case task.
- Weather Subscription API
- Subscribe to weather updates (daily or hourly) by email
- Confirm subscription via unique tokenized email link
- Unsubscribe at any time
- Get real-time weather data (temperature, humidity, description)
- Swagger API documentation
- Fully dockerized setup
- Scheduled email notifications via cron
- Functional tests included
- Backend: NestJS, TypeORM
- Database: PostgreSQL
- Email: Nodemailer
- Scheduler: @nestjs/schedule
- Weather API: weatherapi.com
- Testing: Jest, Supertest
- Containerization: Docker, Docker Compose
- Deployment: Render.com
- API: https://weather-subscription-api-h5i1.onrender.com
- HTML Subscription Page: https://weather-subscription-api-h5i1.onrender.com/subscribe.html
- Swagger UI: https://weather-subscription-api-h5i1.onrender.com/api/docs
Method | Endpoint | Description |
---|---|---|
GET | /api/weather?city={city} |
Get current weather for a given city |
POST | /api/subscribe |
Subscribe email to weather updates |
GET | /api/confirm/{token} |
Confirm the subscription via email token |
GET | /api/unsubscribe/{token} |
Unsubscribe from weather notifications |
π API contract strictly follows the
swagger.yaml
provided with the assignment.
Before you start, make sure the following tools are installed on your machine:
Tool | Version | Download link |
---|---|---|
Git | any | https://git-scm.com/ |
Node.js | >= 20.x | https://nodejs.org/ |
Docker | Desktop v4+ | https://www.docker.com/products/docker-desktop |
npm | bundled with Node.js | β |
β Recommended: Use Docker to simplify local setup and avoid installing PostgreSQL manually.
Run the following commands in your terminal:
git clone https://github.com/Denis-Bredun/Weather-Subscription-API.git
cd Weather-Subscription-API
Copy the example environment file:
copy .env.example .env
Update the .env
file with your configuration β including PostgreSQL credentials, SMTP settings, and your weather API key (e.g., from weatherapi.com).
Before starting, make sure Docker Desktop is running on your machine. To build and run the app using Docker Compose:
docker-compose up --build
This will:
- Start the PostgreSQL database
- Run database migrations automatically
- Launch the API at
http://localhost:3000
- Swagger UI: http://localhost:3000/api/docs
- Subscription Page: http://localhost:3000/subscribe.html
- Example Endpoint:
GET /api/weather?city=Kyiv
The project uses Jest for testing.
Before running tests for the first time, make sure to install dependencies:
npm install
To run all tests, use:
npm test
This command is configured as:
jest --verbose --silent=false --coverage
It runs all tests with:
- Verbose output
- Code coverage report
- Non-silent mode (logs and console output are shown)
All tests are written using Jest and stored next to the source files in src/
.
There are no end-to-end tests in this project.
Mocking is done via jest-mock-extended
.
This project is built with NestJS 11 and follows modular design principles with strong separation of concerns.
- WeatherModule: Fetches real-time weather data using
axios
- SubscriptionModule: Handles subscribing, confirming and unsubscribing emails
- TasksModule: Periodically sends weather emails via cron jobs
- π¦ Dependency injection via NestJS's DI container
- π Scheduled jobs with
@nestjs/schedule
andnode-cron
- π¬ Email sending via
nodemailer
- π Weather data fetching via HTTP using
axios
- π§Ύ API documentation via
@nestjs/swagger
(/api/docs
) - β
Input validation using
class-validator
andValidationPipe
- π§± PostgreSQL with
TypeORM
andtypeorm
CLI for migrations - π UUID-based token confirmation for subscriptions
- ποΈ Static assets served from
public/
(subscribe.html
, etc.)
- Loads
.env
config globally using@nestjs/config
- Registers TypeORM with custom
ormconfig.ts
- Initializes and documents the API using Swagger
- Applies global validation pipe (
whitelist
,transform
, etc.) - Serves static HTML pages via
NestExpressApplication
Runtime:
@nestjs/core
,@nestjs/common
,@nestjs/platform-express
@nestjs/typeorm
,typeorm
,pg
@nestjs/schedule
,node-cron
@nestjs/swagger
,swagger-ui-express
class-validator
,class-transformer
axios
,nodemailer
,uuid
,dotenv
Dev Tools:
jest
,ts-jest
,jest-mock-extended
eslint
,prettier
,typescript
,@nestjs/testing
ts-node
,@swc/cli
for fast builds
This project is fully dockerized using multi-stage builds for optimized performance and portability.
- Dockerfile β builds, compiles, and runs the NestJS application
- docker-compose.yml β defines services for the API and PostgreSQL
- wait-for-it.sh β ensures PostgreSQL is ready before the app starts and migrations run
-
Start the entire stack:
docker-compose up --build
-
Stop and remove containers, networks, and volumes:
docker-compose down -v
-
Fully remove everything (including images):
docker-compose down -v --rmi all
-
Restart from scratch:
docker-compose down -v --rmi all && docker-compose up --build
-
Automatic migration execution on container startup:
npx typeorm migration:run --dataSource dist/config/ormconfig.js
-
PostgreSQL data is persisted in a named Docker volume:
pgdata
- API: http://localhost:3000
- Swagger Docs: http://localhost:3000/api/docs
- Subscribe Page: http://localhost:3000/subscribe.html
- PostgreSQL: localhost:5432
- No e2e tests yet β only core logic is covered with tests
- No rate limiting or CAPTCHA β could be useful to prevent abuse of the subscription form
- No unsubscribe confirmation page β currently returns plain JSON; could be enhanced with an HTML page
- Basic error pages β errors return raw JSON, consider customizing error responses for better UX
- No retry logic for failed emails β mailer currently logs failures without retries
- Token expiration β not implemented for confirmation/unsubscribe tokens
- i18n support β responses and emails are in English only
For feedback, bug reports, or feature requests:
- GitHub Issues: github.com/Denis-Bredun/Weather-Subscription-API/issues
- Author: Denis Bredun
- Email: [email protected]