hasura / hasura/graphql-engine

[SPEC] Building a great Codegen platform for Hasura

Open
#4,078 0 comments 0 reactions 0 assignees View on GitHub
k/ideas
Dominant language
TypeScript
Stars
32.1k
Forks
3k
PR merge metrics
PR metrics pending

Description

# Overview
I wanted to open an issue to get feedback and start a community discussion around how to build an optimal base platform for doing codegen in Hasura.

While setting out to build some codegen plugins of my own, I noticed that the official examples use native JS array methods for working with the GraphQL AST, which leads to things like this:

```js
const operationName = operationDoc.definitions[0].selectionSet.selections.filter(
s => s.name.value.indexOf('__') !== 0
)[0].name.value;
```

Unfortunately, for as much ***general*** tooling as there in the general ecosystem, online you will not find a lot of information about working with the low level bits in `graphql/language` and `graphql/utilities` (I assume because few people want to go mucking about with AST transforms).

The `graphql` library provides a `visit` method, which recursively walks the AST and allows you to pattern-match on node kinds during traversal. With this, you have a lot more power and expressibility/flexibility in ways you can work.

One major factor I wanted to address is **_codegen for language-specific type definitions (e.g. GraphQL type -> Go struct/Kotlin type)_**. The way this is done for Typescript currently is with `graphql-code-generator`. **The problem with this approach is that it only supports a number of plugins/languages, and outside of that you are SOL.** It would be optimum to write a base parser/generator for Codegen so that there is more flexibility here.

**To this end, I spent the past several days diving into the GraphQL source, and have come up with a rough draft using `visit` which you can see here (press RUN):**

https://repl.it/@GavinRay97/OurBlankCygwin

# Details

Given a schema of the following:
```gql
type Mutation {
InsertUserAction(user_info: UserInfo): TokenOutput
}

input UserInfo {
username: String!
password: [String]
}

type TokenOutput {
accessToken: String!
}
```

It produces:

![image](https://user-images.githubusercontent.com/26604994/76375247-bb8bf580-631b-11ea-912d-10ec9c9a85f4.png)

The core of it is very tiny (~30 lines) and only has a [dependency on a library which is a convenience wrapper around `graphql`](https://github.com/vadistic/graphql-extra), so no real dependencies outside of `graphql` itself:

![carbon(9)](https://user-images.githubusercontent.com/26604994/76375476-4ff65800-631c-11ea-82e7-1bb1340a6844.png)

# Conclusion

Now the goal is to provide some class/module which can take a schema string, parse out the typemap, and allow you to do something like:

```js
const hasuraCodegen = new HasuraCoden(schema)
hasuraCodegen.types.forEach(type => {
console.log(type.toGoType())
console.log(type.toJavaType())
console.log(type.toTypescriptType())
})
```

Any ideas/suggestions or help are much appreciated.

Contributor guide

Open the contributing guide

Research direction

Start with the linked repl.it draft, then read the GraphQL AST `visit` API and the existing `graphql-code-generator` approach described in the issue. There are no repository files or tests named; the broad goal is a schema parser/generator supporting language-specific type output, but the concrete scope and completion criteria need to be decided first.

Written by the indexing model from the issue text.

Assessment

Tech stack
graphql, typescript
Domain
api, developer-experience, tooling
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
20/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.