Files
TheGame/guides/BACKEND.md
2021-10-04 13:48:19 +02:00

314 lines
8.0 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
## MetaGame's BackEnd API Guide
### Stack
- Express
- Hasura
- Docker
### Requirements
To run the MetaGame backend you will the following installed.
- Node.js
- Docker
### Configuration
Before you can start the Docker containers, you must run the following.
```bash
# Copy the example environment
cp .env.sample .env
# Add a github token from https://github.com/settings/tokens to the .env (Default read-only scope is good)
echo "GITHUB_API_TOKEN=<github-token>" >> .env
# Remove potential stale containers
yarn docker:clean
# Install node dependencies
yarn
# Build typescript apps
yarn typecheck
```
### Starting the BackEnd
After the above is configured, you can start the Docker containers.
```bash
yarn docker:start
```
### Getting Started
After running `yarn docker:start` make sure to confirm the backend is running.
```bash
# Confirm the backend works
$ curl localhost:4000
# This should output
ok
```
You can debug further if there are problems by running `docker ps`.
```bash
$ docker ps
# Check to see if there are any issues with the docker containers.
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6355ef5641a0 the-game_backend "docker-entrypoint.s…" 51 minutes ago Up 2 minutes 0.0.0.0:4000->4000/tcp the-game_backend_1
970f1ffb79c8 the-game_hasura "/bin/sh -c '/wait &…" 51 minutes ago Up 2 minutes 0.0.0.0:8080->8080/tcp the-game_hasura_1
38e3140ab632 postgres:12 "docker-entrypoint.s…" 51 minutes ago Up 2 minutes 0.0.0.0:5432->5432/tcp the-game_database_1
```
You can also read the logs of the services by running `docker-compose logs -f $SERVICE` (replace \$SERVICE by `backend` or `hasura`)
```bash
$ docker-compose logs -f backend
...
backend_1 | @metafam/backend: [1] [18:59:07] Generate ./src/lib/autogen/daohaus-sdk.ts [completed]
backend_1 | @metafam/backend: [1] [18:59:07] Generate outputs [completed]
backend_1 | @metafam/backend: [1] Watching for changes...
backend_1 | @metafam/backend: [0] Listening on port 4000
```
After which you can run:
```bash
yarn hasura:seed-local-db
```
Which populates it with testing data.
### Run backend without docker for debugging
If you want to run the NodeJS backend service out of docker to be able to debug with your IDE:
**Add environment variable** to tell hasura where to find the backend (may only work on MacOS)
```shell script
echo 'BACKEND_HOST=host.docker.internal:4000' >> .env
```
**Start the server**
```shell script
yarn backend:dev
```
### Configuring Hasura
Before you can create a new table. You'll need to initialize hasura. The same commands are found in the tooling section of the `README.md`.
```bash
# Start the console
yarn hasura:console
# Confirm that hasura is running
yarn hasura migrate status
...
```
### Adding a table
- First, navigate to `http://localhost:9695/`. The Hasura Dashboard should appear.
- You can click on the `DATA` tab or navigate to `http://localhost:9695/console/data/schema/public`.
- Click "Create Table"
When creating a table, keep in mind a few things.
1. You should have an `id` for all table relationships and all datatypes should use snake_case.
- **Example 1:** Table Name: "hello" && Table ID: "hello_id" (as a UUID)
- **Example 2:** Table Name: "map" && Table ID: "map_id" (as a UUID)
2. You should be mapping objects as foreign keys to their respective UUID. For example if you made a new table that holds a player's messages, it would be something like:
- From: player_id
- To: Player.id
### Updating the GraphQL schemas
Assuming the Docker Containers are running. After creating the table. You will need to run:
```bash
yarn update-schema
# and then
yarn generate
```
This will update the `.graphql` schemas for Hasura and make it easier to create graphql queries for the frontend.
### Updating Permissions
By default, only admins are allowed to change the permissions. In order to query, add and update data as other than the admin, you'll need to change the permissions.
1. You will need to select the new table you created on the data the Data tab in the Hasura Console.
2. You will need to select the table you created under `Tables/Views/Functions`.
3. Select the permissions tab and then select either `insert`, `select`, `update` and `delete` for `player` or `public`.
4. Generally, you will want to have a custom check. For the most part, data should only be inserted and deleted based on their user id. The following is a custom check you could create for `Row insert permissions` or `Pre-update check` or `Row delete permissions`.
```json
{
"id": {
"_eq": "X-Hasura-User-Id"
}
}
```
5. Furthermore, when selecting or updating data. You can add permissions for specific columns. You select which ones should be allowed via the provided checkboxes.
6. Finally, make sure that the changes for permissions are updated in `hasura/metadata/tables.yaml`.
`Pre-update check`nsert and read data immediately. There are pre-generated functions that come with Hasura. For creating new entries. The following are example queries you could send immediately to `http://localhost:8080/v1/graphql`.
### Mutations and Querying
The following are examples of how you can use CRUD to interact with new tables in Hasura.
1. Insert a new item
```graphql
# Insert a new item, assuming `Item` is the table name
mutation insert {
# Built in function with Hasura GraphQL
insert_Item_one(
# The respective columns
object: { data: "..." }
) {
# The keys to return on a successful insertion
id
data
}
}
```
As long as it fits the constraints of the table (ie: Foreign Key uniqueness, Data types), the insertion should be successful.
2. Update an item using the `where` clause
```graphql
mutation update {
# Built in Hasura function
update_Item(
where: {
# Can also use _gt, _gte, _lt, _lte, _neq etc.
# Can also specify any column
id: { _eq: "[UUID]" }
}
# The columns you want to update
_set: { data: "..." }
) {
# you can either supply `returning` or `affected_rows` for the response
affected_rows
}
}
```
You can also update by `id` as well too.
```graphql
mutation updateByKey {
update_Item_by_pk(
pk_columns: {id: "[UUID]"},
_set: { ...data }
) {
# Any columns that exist on the `Item` table
id
...data
}
}
```
3. Delete an item using the `where` clause
```graphql
mutation delete {
delete_Item(
where: {
# Can also use _gt, _gte, _lt, _lte, _neq etc.
# Can also specify any column
id: { _eq: "[UUID]" }
}
) {
# you can either supply `returning` or `affected_rows` for the response
affected_rows
}
}
```
You can also delete by `id` as well too.
```graphql
mutation deleteByKey {
delete_Item_by_pk(id: "[UUID]") {
# Any columns that exist on the `Item` table
id
...data
}
}
```
4. And of course, querying items by using the generated `Item` object
```graphql
query get {
Item(
where: {
# Can also use _gt, _gte, _lt, _lte, _neq etc.
# Can also specify any column
id: { _eq: "[UUID]" }
}
# Maximum number of results
limit: 10
# Pagination
offset: 0
# Sorting
order_by: {
# asc - ascending, desc - descending
# Can also specify any column
id: asc
}
) {
# The keys to return on a successful query
id
data
}
}
```
You can also query by `id` as well too.
```graphql
query getByKey {
Item_by_pk(id: "[UUID]") {
# The keys to return on a successful query
id
...data
}
}
```
---
These requests can be sent on the fly to the backend at any time. In the front end guide, it goes over how to create `urql` and `apollo` requests to update and modify data via a React app.
If you'd like to learn more about the GraphQL syntax check out the guides from Hasura:
- [Hasura Queries](https://hasura.io/docs/1.0/graphql/core/queries/index.html#queries)
- [Hasura Mutations](https://hasura.io/docs/1.0/graphql/core/mutations/index.html)