Rain Tracker is a small API to create and serve rainfall reports. It is a Node and TypeScript based application, built with NestJS and Prisma ORM, and uses PostgreSQL for data persistence.
This project can be run as a Docker compose stack. You should have Docker with Docker Compose installed.
Refer to the docker-compose.yaml
file in the project root directory for further information.
First, clone this repository and cd
into it:
git clone https://github.com/darraghenright/rain_tracker.git
cd rain_tracker
Then, make a copy of the .env.dist
called .env
. Use your favourite editor to edit the .env
file and add whatever values you prefer. No other configuration setup should be required as the containers will use the values provided. Refer to the comments in this file for more information.
IMPORTANT: the value of the PG hostname
in the API_DATABASE_URL
connection URL may not be localhost
when running this service. This depends on your operating system and how you run Docker. Please refer to the comments in .env.dist
for advice and further information.
One environment variables are set up, run the Docker compose stack and build the services:
docker compose up --build
This will run services in the foreground. If you want to run the services in the background then run the following command instead:
docker compose up --build --detach
Running either will create a Docker compose stack containing:
- The
postgres
service exposed to your host at port5432
- The Rain Tracker
api
service exposed to your host at port3000
Database migrations should be run automatically which will create the Postgres database structure.
You may interact with the service via the interactive OpenAPI/Swagger UI. Refer to the subsection OpenAPI documentation for further information. Note that all requests must contain an identity — refer to the subsection Identity for further information. Both subsections are found in the Features section of this README.
If you have curl
installed, you can run the following commands to sanity check the API and send some requests. Refer to the Makefile
for more information:
make curl_create RAIN=true
ormake curl_create RAIN=false
make curl_list
Finally, to stop the project:
docker compose stop
# or completely remove all containers and network with `docker compose down`
The postgres
service is configured to persist its data
directory between restarts. This data is saved at the following location in the project ./docker/postgres/data
. You may remove this data at any time by running:
rm -rf ./docker/postgres/data
This directory and associated files will be recreated the next time you run the service.
The API exposes two endpoints for serving and creating RainReport
records. All requests must contain a valid identity. Refer to the Identity section of this README for more information.
All valid requests are identified with a custom x-userid
request header.
This header must be present and contain a non-empty value. If a request does not include a valid x-userid
header it is rejected with a 401 Unauthorized
response.
In addition to enforcing identity x-userid
header performs a slightly different function for each endpoint. These will be discussed further in this README.
Comprehensive and interactive documentation for this project available as an OpenAPI/Swagger UI and a JSON specification. They are available respectively at:
This should provide the canonical and most up to date documentation for this API. A brief summary of functionality follows below.
Fetch all RainReport
records for a provided identity.
The custom request header x-userid
must be provided to assert identity. Each newly created RainReport
persists the x-userid
header value (saved as user_id
) in order to track the ownership of each record in the system.
GET /api/data
N/A
Returns a set of RainReport
records, where each record contains a subset of the persisted data. The id
and user_id
are not included in the response.
{
"data": [
{
"rain": true,
"timestamp": "2024-12-04T00:00:00Z"
},
...
]
}
Create a RainReport
for a provided identity.
The custom request header x-userid
must be provided to assert identity. This header provides a basic form of authentication when retrieving existing RainReport
records. The value of the provided x-userid
header is used to return only records associated with that value, filtered on the user_id
column.
Therefore, it is not possible to retrieve RainReport
records:
- without a valid
x-userid
header - that are associated with another
x-userid
- that return an unfiltered query
POST /api/data
A JSON object stating if it is raining at that moment or not.
{
"rain": true
}
Returns the created RainReport
record, with a subset of the persisted data. The user_id
is not included in the response.
{
"data": {
"id": 1
"rain": true,
"timestamp": "2024-12-04T00:00:00Z"
}
}
A PostgreSQL database instance provides persistence. At the application layer it uses Prisma which is an ORM and query interface for creating and fetching data from the database, as well as defining the data model itself. Refer to the file prisma/schema.prisma
for more information on the data model itself.
The database includes the following tables:
This table is part of Prisma ORM's own functionality and tracks data migration changes over time.
This table tracks all RainReport
records and contains the following columns
id
— autoincrementing primary keyrain
—boolean
field to determine if the record tracks a rain event.timestamp
—datetime
(UTC) field that captures when the record was created.user_id
—string
field that associates the identity that created the record.
This section outlines the prerequisites and steps required to set up this project for local development.
The following tools are required to run the project:
- Docker with Docker Compose
- Node.js
Refer to the .tool-versions
file in the project root for the preferred Node version to install. If you are using adsf you can install this version by running:
asdf install
The Nest CLI tool is required to run various commands such as generators during development. This can be installed globally by running:
npm install -g @nestjs/cli
Clone this repository:
git clone https://github.com/darraghenright/rain_tracker.git
Copy .env.dist
to .env
and update .env
with your preferred values:
cp .env{.dist,}
Install project dependencies:
npm install
Start the postgres
Docker service in the background:
docker compose up postgres --detach
Once the postgres
service is started, you'll have to run migrations manually. Refer to ./prisma/migrations
for further details:
npx prisma migrate dev
Finally, start the Rain Tracker api
on your host in development mode:
npm run start:dev
Visit the OpenAPI/Swagger UI documentation at http://localhost:3000/
To stop the postgres
service:
docker compose stop
# or completely remove all containers and network with `docker compose down`
The postgres
service is configured to persist its data
directory between restarts. This data is saved at the following location in the project ./docker/postgres/data
. You may remove this data at any time by running:
rm -rf ./docker/postgres/data
This directory and associated files will be recreated the next time you run the service.
To run specs, run:
npm run test
# or run tests in watch mode
npm run test:watch
To run end-to-end tests, run:
npm run test:e2e