name: hasura-metadata-apply description: >- Applies Hasura metadata changes (track tables, relationships, permissions) by editing hasura/metadata.json and running scripts/hasura_apply_metadata.sh against local dev compose. Use when tracking a new Postgres table in Hasura, adding relationships or permissions, or when the user asks to update Hasura metadata.
Hasura metadata apply
Overview
This project manages Hasura metadata as a single JSON file (hasura/metadata.json).
Changes are applied via replace_metadata through scripts/hasura_apply_metadata.sh.
When to apply
- Tracking a new Postgres table in Hasura.
- Adding an object or array relationship on an existing tracked table.
- Changing select/insert/update/delete permissions for a role.
- User says "update Hasura", "track table", "add relationship", or "apply metadata".
Workflow
1. Edit metadata
Edit hasura/metadata.json (Hasura v2 metadata format, version 3).
Track a new table — add an entry to metadata.sources[0].tables:
{
"table": { "name": "my_table", "schema": "public" },
"object_relationships": [],
"select_permissions": [
{
"role": "user",
"permission": {
"columns": ["col_a", "col_b"],
"filter": {}
}
}
]
}
Add object relationship (e.g. 1:1 via FK on child table):
{
"name": "my_table",
"using": {
"foreign_key_constraint_on": {
"column": "parent_id",
"table": { "name": "my_table", "schema": "public" }
}
}
}
Add array relationship (parent → children via FK on child):
{
"name": "children",
"using": {
"foreign_key_constraint_on": {
"column": "parent_id",
"table": { "name": "child_table", "schema": "public" }
}
}
}
2. Validate JSON
python3 -m json.tool hasura/metadata.json > /dev/null
3. Apply to local Hasura
./scripts/hasura_apply_metadata.sh
Default endpoint: http://127.0.0.1:8080 (compose.dev.yaml).
Default admin secret: password.
Override with env vars:
HASURA_URL=http://127.0.0.1:8080 HASURA_GRAPHQL_ADMIN_SECRET=mysecret ./scripts/hasura_apply_metadata.sh
The script uses jq (required dependency). It:
- Extracts
.metadatafrom the JSON file. - Sends
replace_metadatato/v1/metadata. - Checks HTTP 200, no
.error, andis_consistent == true.
4. Update client schema
After Hasura accepts metadata, re-introspect if the client's schema.graphql needs new types. The compose dev stack includes an introspection service, or run manually:
get-graphql-schema -h 'x-hasura-admin-secret=password' -h 'x-hasura-role=user' \
http://localhost:8080/v1/graphql > packages/client/lib/data/gql/schema.graphql
Then run Ferry codegen:
cd packages/client && dart run build_runner build -d
5. Bump resource_version
Increment resource_version at the top of metadata.json after each change (convention only; Hasura ignores it on replace_metadata but it helps track edits).
Key conventions
- Permissions: most tables use
"filter": {}(public read) forrole: user. Tables with user-scoped data use"filter": { "user_id": { "_eq": "X-Hasura-User-Id" } }. - Relationship naming: matches Postgres table name in snake_case (e.g.
beacon_review_window). - Computed fields: require
session_argumentand oftentable_argument; see existing examples inmetadata.json. - replace_metadata replaces everything: always edit the full
metadata.json, never partial API calls.
Troubleshooting
| Symptom | Fix |
|---|---|
is_consistent: false | Table or FK doesn't exist in Postgres; run migrations first. |
| HTTP 401 | Wrong admin secret; check HASURA_GRAPHQL_ADMIN_SECRET. |
jq: command not found | Install jq: sudo apt install jq. |
| New field returns null in client | Ensure schema.graphql has the type and the .graphql fragment selects it; re-run codegen. |