Skip to content

A boilerplate, cheatsheet, guide for beginners of Hasura.

License

Notifications You must be signed in to change notification settings

jjangga0214/hasura-starter

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

26 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

hasura-starter

  • A boilerplate for docker-compose and migrations, setting development environment.
  • A cheatsheet for Hasura CLI.
  • A guide for beginners.

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

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.

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.

  • Postgres View: You can expose computed/derived data as GraphQL query/subscription.
  • Postgres Function: You can expose custom GraphQL query/subscription. (Currently not for mutation)
  • Postgres Trigger: You can use Postgres Trigger to add synchronous logic like custom input validation, or arbitrary tasks like insert, update, or delete to other related data.
  • Hasura's Remote Schema: (This is DIFFERENT from graphql-tools'(of Apollo) Remote Schema.) You can develop your own GraphQL server (or external GraphQL API), and integrate it "into" Hasura (Similar to schema stiching).
  • Remote Join(WIP. Comming Soon): You can precisely "join" (as like SQL join) external GraphQL for constructing the schema you exactly want. (Similar to Apollo Federation)
  • Actions(WIP. Comming Soon): You can define a custom mutation in SDL by using types Hasura generates, and write "Action handler", which can be one of 'HTTP handler', 'Postgres functions' or 'Postgres PLV8'. It can be async as well (subscription/query for the result are auto generated by Hasura.).
  • Schema Stitching: (Though schema-stitching is deprecated, Apollo Federation, its alternative, can't be used in this use case.) In some cases, you need to place an additional layer in front of Hasura, in order to handle special requirement. You can override Hasura-generated queries, mutation, and subscription. Here's a good practical guide with examples. If needed, you can also consider graphql-tools' schema transforms feature to Remote Schema as well.
  • GraphQL microservices: Hasura can be an API gateway, with its "Action" and Remote Join, etc. However, you might want to use Apollo Federation, and treat Hasura as a microservice. Then you can transform Hasura's schema to make it federation-spec-compliant. Though you can use graphql-tools' schema transforms, there's a helping package graphql-transform-federation. This is also useful to 3rd party GraphQL API service which you can't fix directly, or some situations where GraphQL directive is not allowed like some code-first approach frameworks (e.g. nexus, type-graphql). Currently, Apollo Federation does not support subscription, though it's on the official roadmap. If you need it, you can place one more gateway that uses schema stitching. If you have a question, leave an issue.

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 <[email protected]> (@jjangga0214)

About

A boilerplate, cheatsheet, guide for beginners of Hasura.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published