Hasura Metadata SDK
Tags: graphql, graphqljanuary
Published: 2021-02-02 12:49:32

---
title: Hasura Metadata SDK
published: true
date: 2021-01-21 14:06:52 UTC
tags: GraphQL,GraphQLJanuary
canonical_url: https://hasura.io/blog/hasura-metadata-sdk/
---

 ![Hasura Metadata SDK](https://hasura.io/blog/content/images/2021/01/hasura_metadata_sdk-1.png)

_Our #GraphQLJanuary continues with blog posts, live streams, Discord Q&A, office hours, and more. For a schedule of upcoming events, join the community or register at [https://hasura.io/graphql/graphql-january/](https://hasura.io/graphql/graphql-january/)._

## What is it?

The Hasura Metadata SDK is a collection of type definitions for Hasura metadata in various programming languages. Users can also generate definitions in other languages if their preferred language is not readily available.

These pre-generated SDK's included:

- TypeScript (also published on NPM, as `@hasura/metadata-types`)
- Python 3.7 Dataclasses + MyPy
- Golang
- Haskell

## Why was it built, what problems does it solve?

Hasura's workflow is flexible. Some users prefer to interact with & develop their project through our web interface. Other users prefer to stick to purely text-based flows, or integrate with the existing editor tooling they have configured.

We saw two areas where we felt we could better serve the needs of the community and enhance our user experience by augmenting the tooling around metadata:

_Providing our users with a platform to build more complex tooling, and programmatic workflows, around interacting with metadata_

_Providing our users with enhanced integration to maintain flow-state while working in their editor environments on their Hasura projects_

To the first point, we felt that publishing fully type-safe and documented SDK's would allow users to more confidently build the tooling they needed, while feeling comfortable they weren't making mistakes.

![Hasura Metadata SDK](https://hasura.io/blog/content/images/2021/01/Hqhyj80.gif)<figcaption>Type-safe and documented SDK's</figcaption>

To the second point, we realized that users in most modern editors would be able to take advantage of JSON/YAML Schema integrations, so that when working on, or referencing metadata files, there is intellisense, type-checking, and doc-comments on hover.

![Hasura Metadata SDK](https://hasura.io/blog/content/images/2021/01/ctOr7fU.gif)<figcaption>JSON/YAML schema integrations</figcaption>

## How might I use this?

Below is an example to demonstrate the common use cases you may encounter when wanting to script your interactions with metadata. It includes:

- Loading `tables.yaml`, and `actions.yaml` files
- Adding a new table
- Creating a JSON and text diff of `tables.yaml`, and writing it to a `diffs` folder
- Repeating the above process for `metadata.json` (could be `metadata.yaml` as well)

```
import { Convert } from "./customMetadataConverter"
import {
  TableEntry,
  Action,
  CustomTypes,
  HasuraMetadataV2,
} from "../generated/HasuraMetadataV2"

// Read "tables.yaml" file as text from filesystem
const tablesMetadataFile = fs.readFileSync("./metadata/tables.yaml", "utf8")
// Convert it to JSON object with type annotation using loadYAML utility
const tablesMetadata: TableEntry[] = Convert.loadYAML(tablesMetadataFile)
tablesMetadata.forEach(console.log)

// Read "actions.yaml" file as text from filesystem
const actionMetadataFile = fs.readFileSync("./metadata/actions.yaml", "utf8")
// Convert it to JSON object with type annotation using loadYAML utility
const actionMetadata: {
  actions: Action[]
  custom_types: CustomTypes
} = Convert.loadYAML(actionMetadataFile)
actionMetadata.actions.forEach(console.log)
console.log(actionMetadata.custom_types)

// Make a new table object
const newTable: TableEntry = {
  table: { schema: "public", name: "user" },
  select_permissions: [
    {
      role: "user",
      permission: {
        limit: 100,
        allow_aggregations: false,
        columns: ["id", "name", "etc"],
        computed_fields: ["my_computed_field"],
        filter: {
          id: { _eq: "X-Hasura-User-ID" },
        },
      },
    },
  ],
}

// Clone the tables for comparison after changes using diff()
const originalTablesMetadata = Convert.clone(tablesMetadata)
// Add the new table to tables metadata
tablesMetadata.push(newTable)

// Generate a structural and text diff from the changes between original and now
const tableDiff = Convert.diff(originalTablesMetadata, tablesMetadata)
// Write the diffs to /diffs folder, will output "tables.json" and "tables.diff"
Convert.writeDiff({ folder: "diffs", file: "tables", diffs: tableDiff })
// Ouput the updated "tables.yaml" to filesystem
fs.writeFileSync(
  "./tables-updated.yaml",
  Convert.metadataToYAML(tablesMetadata)
)

// Read "metadata.json"
const metadataFile = fs.readFileSync("./metadata.json", "utf-8")
// Convert.to<typeName> does runtime validation of the type
const allMetadata: HasuraMetadataV2 = Convert.toHasuraMetadataV2(metadataFile)
console.log(allMetadata)

// Clone, add table
const beforeMetadataChanges = Convert.clone(allMetadata)
allMetadata.tables.push(newTable)

// Diff, write diff
const metadataDiff = Convert.diff(beforeMetadataChanges, allMetadata)
Convert.writeDiff({ folder: "diffs", file: "metadata", diffs: metadataDiff })

```

## Closing Words

We hope that you enjoyed and learned something from this article, and in this SDK find a valuable tool for your own workflow.

We invite you to check out the [Github repo](https://github.com/hasura/graphql-engine/blob/master/contrib/metadata-types) for more information, play with it, and give us feed back on what works & what doesn't =)

Lastly, we hope you'll join and become a part of our [online community](https://hasura.io/community/).