This is a JSON API backend for the Airline Booking System Web Application. There are two types of users: Passengers and Airlines. Airlines can add and remove flights from the system, while Passengers can search for flights between two destinations on desired dates and create bookings. It is a TypeScript Express application that uses Prisma as an ORM and Postgres as the database.
You will need Node.js, and Docker Compose installed on your machine
- clone the repository
$ git clone git@github.com:ttskmnj/flight_booking_api.git
- change directory to repository root directory
$ cd flight_booking_api
- install modules
$ npm install
- download IATA Airport code
- create
data
directory in repository root directory$ mkdir data
- download
airport-codes_json.json
todata
directory.
download json file from here
You will need to create a .env
file in the root of the reposiotory.
POSTGRESDB_USER=<POSTGRES USER>
POSTGRESDB_ROOT_PASSWORD=<POSTGRES PASSWORD>
POSTGRESDB_DATABASE=<POSTGRES DATABASE>
DATABASE_URL=postgresql://<POSTGRES USER>:<POSTGRES PASSWORD>@<POSTGRES URL>:<POSTGRES PORT>/<POSTGRES DATABASE>?schema=public
SECRET=<JWT SECRET>
if you run it with Docker Compose, please choose pg
as <POSTGRES URL>
and 5432
as <POSTGRES PORT>
since it is set in docker-compose.yml
you can use the official postgres docker image to run a local postgres instance.
$ docker run --name local-pg -e POSTGRES_PASSWORD='<POSTGRES PASSWORD>' -e POSTGRES_USER='<POSTGRES USER>' -e POSTGRES_DB='<POSTGRES DATABASE>' -p <POSTGRES PORT>:5432 -d postgres:12
$ npx prisma migrate deploy
$ npx prisma migrate dev --name init
seed script will add IATA aiport code to Airport
table and add following 2 users to User
table to test API.
username | code (IATA 2 letter airline code) |
---|---|
Wizz Air | W6 |
Ryanair | FR |
run following commands in the root of the reposiotory
$ npm run build
$ npm start
run following command in the root of the reposiotory
$ docker-compose up -d
if it is the first time, it will build container, so it might going to take some time.
you might need sudo
in front of the command. it depends on your docker setting
if containers run properly, it will show something as below
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
940332273fd0 flight_booking_api_api "docker-entrypoint.s…" 15 seconds ago Up 3 seconds 0.0.0.0:3001->3000/tcp, :::3001->3000/tcp flight_booking_api-api-1
fa4bba1bbe5c postgres "docker-entrypoint.s…" 15 seconds ago Up 14 seconds (healthy) 0.0.0.0:5433->5432/tcp, :::5433->5432/tcp flight_booking_api-pg-1
make sure there is postgres
and api
cointainers are running.
you can stop containers with following command
$ docker-compose down
There is only airport and user data is set in DB by seed script. To test flight reservation you must first add the flights then you can book a flight.
*if you run API on docker-compose, please choose port 3001
POST
/login
(login to get TOKEN)
Login endpoint receive username
and password
via POST method and return token
in json. token
will be expired after 10minutes.
2 users are added by seed script. please use these username and password to login.
username | password |
---|---|
"Wizz Air" | "wizzair" |
"Ryanair | "ryanair" |
*yes. they are my favourite airlines
name | type | format | description |
---|---|---|---|
username | string | user name | |
password | string | password |
$ curl -X POST http://localhost:3000/login
-H 'Content-Type: application/json'
-d '{"username":"Wizz Air","password":"wizzair"}'
# success
# status: 200
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwibmFtZSI6IldpenogQWlyIiwiY29kZSI6Ilc2IiwiaWF0IjoxNzAxNjk3NTIzLCJleHAiOjE3MDE2OTgxMjN9.k5-9DAhE0AtxZEuiF8wwyIWQnkeHvU7OsJfMgRCTTiU"
}
# error: invalid username or password
{
"error":"invalid username or password"
}
you add,search and delete flight at this endpoint. you need to be autheticated to add and delete flight.
POST
/flight
(add flight :TOKEN authentication needed)
To add flight you need to send 3-letter airport origin and destination, date, flight number, and the number of seats via POST method.
name | type | format | description |
---|---|---|---|
origin | string | 3-letter airport origin | |
dest | string | 3-letter airport destination | |
date | datetime | YYYY-MM-DDThh:mm:ss.mssZ | flight datetime |
numSeat | number | number of seat |
name | type |
---|---|
Authorization | Bearer Token |
$ curl -X POST http://localhost:3000/flight
-H "Content-Type: application/json"
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwibmFtZSI6IldpenogQWlyIiwiY29kZSI6Ilc2IiwiaWF0IjoxNzAxNjk4MzY3LCJleHAiOjE3MDE2OTg5Njd9.H3wjgBOR-5f3uviqO3RfDPJ7cKmSGm_Ny-5YAAANz2E"
-d '{ "origin": "NUP", "dest":"WLR", "date": "2023-11-30T12:34:32.000Z", "numSeat": 5}'
# success
# status: 200
{
"id":1,
"flightNum":"W60",
"numSeat":5,
"originId":8,
"destId":7,
"airlineId":1,
"date":"2023-11-30T12:34:32.000Z"
}
# error: date format is invalid
# status: 401
{
"error":"invalid date"
}
# error: airport origin or destination is wrong
# status: 401
{
"error":"invalid origin or destination"
}
# error: failed to add flight to db
# status: 500
{
error: `failed to create flight`
}
flight number is consists of airline code
and index
.
airline code
: 2 letter IATA code for each airlines and it is save ascode
in User table.index
: index number for each airline's flight
flight number FR384
means that is flight of Ryanair(FR
) and index number is 384
. When airline add flight, hightest index from the same airline will be taken and add 1 to it then it will be used for index number for newly added flight.
DELETE
/flight
(delete flight :TOKEN authentication needed)
To delete flight you need to send flight number via DELETE method.
name | type | format | description |
---|---|---|---|
flightNum | string | 3-letter airport origin |
name | type |
---|---|
Authorization | Bearer Token |
$ curl -X DELETE http://localhost:3000/flight
-H "Content-Type: application/json"
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwibmFtZSI6IldpenogQWlyIiwiY29kZSI6Ilc2IiwiaWF0IjoxNzAxNzAyMzg2LCJleHAiOjE3MDE3MDI5ODZ9.gsoTboX5_9XPathj25aKpkP7PmteQ8i2aq9SeJYlMnQ"
-d '{ "flightNum": "W60"}'
# success
# status: 200
{
"message":"flight number: W60 is deleted"
}
# error: try to delete other airline's flight
# status: 400
{
error: "cannot delete other airline's flight",
}
# error: failed to delete db record
# status: 500
{
error: `failed to delete flight number: ${flightNum}`
}
GET
/flight/:origin/:dest/:date
(search flight)
To search flight you need to send airport origin and destination, date via GET method. It will return all flights match searching criteria.
name | type | format | description |
---|---|---|---|
origin | string | 3-letter airport origin | |
dest | string | 3-letter airport destination | |
date | date | YYYY-MM-DD | date of flight |
$ curl -X GEY http://localhost:3000/flight/NUP/WLR/2023-11-30
-H "Content-Type: application/json"
# success
# status: 200
[
{
"id":2,
"flightNum":"W60",
"numSeat":5,
"originId":8,
"destId":7,
"airlineId":1,
"date":"2023-11-30T12:34:32.000Z"
},
{
"id":3,
"flightNum":"W61",
"numSeat":59,
"originId":5,
"destId":2,
"airlineId":1,
"date":"2023-11-30T12:45:32.000Z"
}
]
# error: date format is invalid
# status: 401
{
"error":"invalid date"
}
# error: airport origin or destination is wrong
# status: 401
{
"error":"invalid origin or destination"
}
you add and search booking at this endpoint.
POST
/booking
(add booking )
To add booking you need to send flight ID, firstname, lastname via POST method.
name | type | format | description |
---|---|---|---|
flightId | number | flight id | |
firstName | string | firstname | |
lastName | string | lastname |
$ curl -X POST http://localhost:3000/booking
-H "Content-Type: application/json"
-d '{ "flightId": 2, "firstName":"tatsuki", "lastName":"monji"}'
# success
# status: 200
{
"id":1,
"confirmNum":852091,
"firstName":"tatsuki",
"lastName":"monji",
"flightId":2
}
# error: flight ID doesn not found
# status: 400
{
error: `flight id: 24 not found`
}
# error: flight is fully booked
# status: 400
{
error: `flight id: 2 is fully booked`
}
# error: failed generate confirmation numnber
# status:500
{
error: `failed to book flight 2. failed to generate confirmation numnber`,
}
GET
/booking/:confirmNum/:lastName/
(search booking )
To search booking you need to send Confirmation number and lastname via GET method.
name | type | format | description |
---|---|---|---|
confirmNum | number | 6 letter Confirmation Number | |
lastName | string | lastname |
$ curl -X GET http://localhost:3000/booking/552837/mnji
-H "Content-Type: application/json"
# success
# status: 200
{
"confirmNum":552837,
"firstName":"tatsk",
"lastName":"mnji",
"flight":{
"id":2,
"flightNum":"W60",
"numSeat":5,
"originId":8,
"destId":7,
"airlineId":1,
"date":"2023-11-30T12:34:32.000Z"
}
}
# error: Confirmation Number is not number
# status: 400
{
error: "Invalid Confirmation Number"
}
# error: Invalid Confirmation Number or last Name
# status: 400
{
error: "Invalid Confirmation Number or last Name"
}