Home

Awesome

hasura-starter

license Hasura v1.1.0 pr welcome

Before Getting Started

Clone this repo.

Copy and edit .env.example file as you want.

cp .env.example .env

The file uses Variable Expansion format to reduce duplication, which dotenv-expand supports. docker-compose doesn't officially mention if it supports the format. It simply says it expects VAR=VAL(docs). However, it seems docker-compose does work with the format. If not, you can use a tool like dotenv-cli for populating "expanded" values. (e.g. dotenv -- docker-compose up -d)

Note that you should uncomment HASURA_GRAPHQL_ADMIN_SECRET from docker-compose.yml and configure it from env file, if you want to enable authentication (Refer to docs for more detail).

Default ports are 8080 for Hasura, 5432 for Postgres. Before you change them, consider reading Networking section.

Getting Started

Run Postgres and Hasura.

docker-compose up -d
# if you name the env file differently,
# you can set "env_file" field for docker-compose (https://docs.docker.com/compose/environment-variables)
# or use a tool like "dotenv-cli" (https://github.com/entropitor/dotenv-cli)
dotenv -e .env.dev -- docker-compose up -d

Stop/Debug/Clear Postgres and Hasura.

# stop hasura and postgres
docker-compose down
# print logs on the terminal. Good for debugging.
docker-compose up
# stop hasura and postgres, and remove docker volumes as well
docker-compose down --volumes

CLI Cheatsheet

Here are hasura CLI cheatsheets for easy copy-and-paste. If you haven't used CLI, first be familar with migrations concept.

There are more available commands. Refer to docs or hasura <COMMAND> --help for more detail.

--project option specifies a directory Hasura CLI should target. If you go into the directory(cd hasura), you don't need to specify it.

If you enabled HASURA_GRAPHQL_ADMIN_SECRET, then you should provide the env var (or the option --admin-secret <ADMIN_SECRET>) to the CLI. For convenience of development, just populate env file to your shell (maybe with a shell plugin like dotenv), or use a tool like dotenv-cli.

(Comments are my personal shorthand notation, which are not executable.)

# hasura:_
hasura --project hasura
# hasura:console => open web console to generate migration files
hasura --project hasura console
# hasura:migrate:_
hasura --project hasura migrate
# hasura:status => show migration status
hasura --project hasura migrate status
# hasura:pull => pull migration from Hasura. Generally only used once (as a first migration) per a project.
hasura --project hasura migrate create --from-server <NAME_OF_SINGLE_MIGRATION>
# hasura:push => push(applies) all applicable migration files to Hasura
hasura --project hasura migrate apply
# hasura:push:count => push a given number of migration(s) to Hasura
hasura --project hasura migrate apply --up <NUMBER>
# hasura:push:version => push a specific version of migration to Hasura
hasura --project hasura migrate apply --version <VERSION>
# => mark an migration is applied, without actual execution. Check out "Squash" section under "Migrations".
hasura --project hasura migrate apply --skip-execution --version <VERSION>
# hasura:rollback:count => roll back a given number of migration(s) from Hasura
hasura --project hasura migrate apply --down <NUMBER>
# hasura:rollback:version => roll back a specific version of migration from Hasura
hasura --project hasura migrate apply --type down --version <VERSION>

To another stage (e.g. production)

Use --endpoint option for remote Hasura. The option overrides the default endpoint specified in hasura/config.yaml (So you don't have to specify it when dealing with local Hasura).

For practice, I recommend run migration commands against both local and remote Hasura. You can deploy an instance of Hasura by one(few)-click and free on Heroku. Refer to this very simple Heroku deployment guide.

# e.g. HASURA_ENDPOINT=http://another-graphql-instance.herokuapp.com
hasura --project hasura --endpoint $HASURA_ENDPOINT migrate create --from-server <NAME_OF_SINGLE_MIGRATION>
hasura --project hasura --endpoint $HASURA_ENDPOINT migrate apply
hasura --project hasura --endpoint $HASURA_ENDPOINT migrate apply --up <NUMBER>
hasura --project hasura --endpoint $HASURA_ENDPOINT migrate apply --version <VERSION>
hasura --project hasura --endpoint $HASURA_ENDPOINT migrate apply --down <NUMBER>
hasura --project hasura --endpoint $HASURA_ENDPOINT migrate apply --type down --version <VERSION>
hasura --project hasura --endpoint $HASURA_ENDPOINT migrate status

Examples

hasura:pull 'init'
hasura:push:count 2
hasura:push:version 1550925483858
hasura:rollback:count 2
hasura:rollback:version 1550925483858

Migrations

You don't need to execute hasura init by yourself, as migrations directory(/hasura/migrations) and the config file(/hasura/config.yaml) are already here.

This projects assumes migrations(,which includes metadata) handled by Hasura. But you can choose another migration tool over Hasura. If so, you only need Hasura to handle metadata. For that case, refer to docs for more detail.

cli-migrations

Under /hasura/migrations, there is 1573631107183_init. It's a sample migration which creates User table and make Hasura track it. By the given configuration, not plain hasura/graphql-engine:<version>, but hasura/graphql-engine:<version>.cli-migrations is used as docker image. The image automatically applies migrations when Hasura starts. Remove 1573631107183_init for your migrations.

Squash

You can "squash" multiple migrations into one by taking several steps. But there has been issues(e.g. #2724) about inconvenience. To make it simple, community members developed a tool like hasura-squasher and manual workflow. Finally, a new command hasura migrate squash is introduced with a new migration structure on v1.0.0-beta.9. As of writing(v1.1.0), the command is still in preview(not stable). For more detail, check out the changelog.

Networking

Sync Hasura port

By the given configuration, 8080 port is given to Hasura. To change it, you should sync the port number specified in hasura/config.yaml and HASURA_ENDPOINT_PORT in your env file.

Host networking

By the given configuration, Hasura and Postgres communicates each other by docker's host mode networking. No matter how you configure DB_ENDPOINT_PORT from env file, Postgres is exposed to Hasura by 5432 port, the default value of Postgres image. That's why 5432 is hard-coded at HASURA_GRAPHQL_DATABASE_URL in docker-compose.yml. For the same reason, service name postgres is used rather than localhost on HASURA_GRAPHQL_DATABASE_URL.

environment:
  HASURA_GRAPHQL_DATABASE_URL: "postgres://${POSTGRES_USERNAME}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DATABASE}"

Postgres exposure

By the given configuration, Postgres is exposed to the host(your OS) by the port of DB_ENDPOINT_PORT from env file. This is useful on development as you can directly access to Postgres without Hasura. However, if you want to use docker-compose.yml on production (e.g. docker swarm for docker-compose), you might reconsider how you should configure it.

Seed Data

Automatically seeding sample data can be very useful on local development workflow. Currently, Hasura doesn't support the "seed" feature (or some more generic feature that could be easily used). As a workaround, you can manually put a sql file with INSERT statements into migrations directory. To ensure seeding is executed AFTER Postgres schema is fully migrated, you can manually name it with very high timestamp value. However, as generally seed is only for development environment, "seeding as migration" approach makes migration inconvenient, or even dangerous (e.g. You should be careful to migration for production). There's an issue and discussion about this, and I personally expect this problem to be officially solved soon.

As an another workaround, you can write a little program that calls GraphQL mutations or executes INSERT sql statements.

For example, if you use node.js,

docker-compose up -d && node seed.js

Of course, the program should watches (e.g. continuous health check polling) Hasura endpoint to make sure migrations are completed before inputting data.

Custom Business Logic

Custom logics are to be integrated with Hasura-generated GraphQL, as a single endpoint. They are also useful when Hasura's authorization system can't cover your complex requirements for specific tasks. There are various ways depending on your needs.

GraphQL MSA diagram

Event Trigger

When an event(e.g. INSERT, UPDATE, DELETE) is occurred on a Postgres table, Hasura can invoke webhooks. Refer to docs for more detail.

3Factor App

It's somewhat radical event-driven, async, reactive architecture pattern (Redux-like backend?!). The concept itself is independant from Hasura, however Hasura can be used for the architecture implementation. Refer to 3factor.app or an example.

License

MIT License. Copyright © 2019, Gil B. Chan <bnbcmindnpass@gmail.com> (@jjangga0214)