Skip to content

Generate types for the "app" part #273

@lucasavila00

Description

@lucasavila00

I'm currently using graphql-code-generator to generate types for the "app" part of the code and the experience is awesome.

It gives me the types for the public api which I can export for the front-end and use on the server code itself.
With these dependencies:

    "graphql-code-generator": "^0.9.1",
    "graphql-codegen-typescript-template": "^0.9.1",
    "graphql-import": "^0.6.0",

We need to join the schemas because of this kind of modular graphql schema used with prisma,
so we create src/importSchema.ts

import { importSchema } from "graphql-import";
export default importSchema("./src/schema.graphql");

Automate it in prisma.yml:

hooks:
  post-deploy:
    - graphql get-schema --project database
    - graphql codegen
    - gql-gen --require ts-node/register --template typescript --export ./src/importSchema.ts --out ./src/typings/

or package.json

    "foo": "gql-gen --require ts-node/register --template typescript --export ./src/importSchema.ts --out ./src/typings/"

and we can use the types like so, in Query.ts (strict Typescript 👍 )

import { PostQueryArgs, Query } from "../typings/types";
// later...
  post(
    parent: never,
    { id }: PostQueryArgs, // type generated now
    ctx: Context,
    info: never
  ): Promise<Query["post"]> {
    return ctx.db.query.post({ where: { id: id } }, info);
  },

This approach should be added here, like this or with apollo-codegen (which I couldn't get to work like this). It helped me catch a bug on the prisma docs where they have a mutation like this on the app side:

type Mutation {
  createDraft(title: String!, content: String): Post
}

implemented like this

    createDraft(parent, { title, content }, ctx, info): Promise<Mutation["createDraft"]> {
      return ctx.db.mutation.createPost(
        {
          data: {
            title,
            content,
          },
        },
        info,
      )
    },

against a DB structured like this

type Post {
  id: ID!
  title: String!
  content: String!
  published: Boolean!
}

So at app level "content" was optional. At DB level it wasn't. The typescript compiler wouldn't warn if I hadn't taken this approach.
Also, in this project, if we remove a "!" from a type or argument at app level the compiler won't catch this regression unless we generate the types.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions