JavaScript + Python full stack example application using React + Redux Sagas for the frontend and a GraphQL API backend using FastAPI + AsyncPG.
OTHER License
JavaScript, Vite, Reactjs, Redux Toolkit, Redux Sagas, Python, FastAPI, GraphQL, AsyncPG, Postgres
This example contains a frontend and backend:
React Typescript and Express MVC versions of this same idea are available.
An abandoned branch for the previous version of this repository includes the usage of TortoiseORM.
Context:
Web UI Usage:
API Usage:
Example usage via curl:
# First, grab an access token provided by the API
ACCESS_TOKEN=$(curl -s -X POST \
-H 'accept: application/json' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'grant_type=password&username=example-user&password=example-user' \
"http://localhost:$RESERVATION_PORT/development/token" | jq -r '.access_token')
# List all existing booked reservations
curl http://localhost:$RESERVATION_PORT/development/graphql \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
-d '{"query": "query { getAllReservations { reservations { room_id checkin_date checkout_date } } }"}'
# Create a new reservation
# Note: if there is an overlap, you'll see a
# 'Reservation dates overlap with an existing reservation' error message
# To see the aforementioned error, run this mutation a multiple times
curl http://localhost:$RESERVATION_PORT/development/graphql \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
-d '{ "query": "mutation { createReservation( input: { room_id: \"91754a14-4885-4200-a052-e4042431ffb8\", checkin_date: \"2023-12-31\", checkout_date: \"2024-01-02\" }) { success errors reservation { id room_id checkin_date checkout_date total_charge } } }" }'
# List Available Rooms for a given date range
curl http://localhost:$RESERVATION_PORT/development/graphql \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
-d '{"query": "query { getAvailableRooms( input: { checkin_date: \"2023-12-31\", checkout_date: \"2024-01-02\" }) { success errors rooms { id num_beds allow_smoking daily_rate cleaning_fee } } }" }'
Open API UI Usage:
Navigate to http://localhost:$RESERVATION_PORT/docs.
To run the service, you will need to install the following tools.
The below are optional but highly recommended:
First, we'll need to set up our environment variables. You can do this by either any of the methods mentioned in /tools/ENV.md but I recommend using Direnv.
Execute the following in your terminal:
python -m venv venv
source venv/bin/activate # for Windows, source venv/Scripts/activate
python -m pip install --upgrade pip
pip install -r requirements.txt
Execute the following within your terminal:
nvm use # To eliminate any issues, install/use the version listed in .nvmrc.
npm i # install the packages needed for project
cd ../frontend && npm i # install the packages needed for the frontend
cd ../db && npm i # install the packages needed for database migrations
cd .. # navigate back to the root of the repostiory
Finally, let's create and seed the databases and our Reservations and Rooms tables:
# Create the databases and seed them
NODE_ENV=development | npm run refresh && npm run seed
During development, you can just execute npm run dev:db-baseline
to refresh the database back to the original seed data.
To run both the frontend and backend concurrently:
docker-compose up -d # runs the database in the background
npm run dev
Also, you just execute the backend via npm run dev:backend
. to verify the backend is working:
curl http://localhost:$RESERVATION_PORT/$ENV/about
You can also acces the Ariadne GraphiQL (interactive test playground) instance at http://localhost:$RESERVATION_PORT/$ENV/graphql.
The backend uses Pytest and the frontend uses Jest. To run these tests, simply execute npm run test:backend
or `npm run test:frontend', respectively.
docker build backend/. -t acme-hotel-example-backend:latest \
--build-arg RESERVATION_PORT="80" \
--build-arg ENV="${ENV}" \
--build-arg IS_DEBUG="${IS_DEBUG}" \
--build-arg SECRET_KEY="$SECRET_KEY" \
--build-arg REFRESH_SECRET_KEY="$REFRESH_SECRET_KEY" \
--build-arg PG_URL="$PG_URL"
# finally, to run a named container
docker run --name backend-dev -p 8000:80 acme-hotel-example-backend
To verify the environment variables set, you can execute the following on the named container by:
CONTAINER_ID=$(docker ps -qf "name=backend-dev" -n 1)
# this will display the container's environment variables in console
docker exec $CONTAINER_ID printenv
If you need to re-create the container with the same name, do docker rm (i.e., backend-dev) first.
docker build frontend/. -t acme-hotel-example-frontend:latest \
--build-arg FRONTEND_PORT="80" \
--build-arg NODE_ENV=${NODE_ENV}
# finally, to run a named container
docker run --name frontend-dev -p 3000:80 acme-hotel-example-frontend
To verify, follow similar steps also explained in the above Building the Backend Container section.