Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generate Flow and Typescript types #2374

Closed
KyleAMathews opened this issue Oct 7, 2017 · 30 comments
Closed

Generate Flow and Typescript types #2374

KyleAMathews opened this issue Oct 7, 2017 · 30 comments

Comments

@KyleAMathews
Copy link
Contributor

@KyleAMathews
Copy link
Contributor Author

This is for user graphql queries.

@jquense
Copy link
Contributor

jquense commented Oct 7, 2017

I'd add just plain ol "schema generation" as well here, for integration into tooling like https://github.com/apollographql/eslint-plugin-graphql

@fabien0102
Copy link
Contributor

I’ve got a task for this in the typescript starter ;) I think it’s working for flow too ;) (I need to check on my computer)

@fabien0102
Copy link
Contributor

So yeah it's works for flow -> https://github.com/dotansimha/graphql-code-generator
Example in context -> https://github.com/fabien0102/gatsby-starter/blob/master/package.json#L20
(I tested apollo-codegen too, it's basically the same)

BTW, what is the goal of this issue? Improve docs, generate flow/typescript types with gatsby-cli or anything else? 😄

@KyleAMathews
Copy link
Contributor Author

The Relay Compilier has support now for generating Typescript types https://github.com/relay-tools/relay-compiler-language-typescript

@KyleAMathews
Copy link
Contributor Author

Due to the high volume of issues, we're closing out older ones without recent activity. Please open a new issue if you need help!

@levibuzolic
Copy link
Contributor

levibuzolic commented Sep 30, 2018

Originally I tried to use get-graphql-schema to download a schema from the GraphQL server and then relay-compiler which worked great, until it encountered Gatsby's GraphQL query/filter/sort syntax which is incompatible Relay.

graphql`
  query AlbumQuery($id: String!) {
    album(id: { eq: $id }) {
      id
      name
    }

Will produce an error like:

ERROR: RelayCodeGenerator: Complex argument values (Lists or InputObjects with nested variables) are not supported, argument `id` had value:
{
  "kind": "ObjectValue",
  "metadata": null,
  "fields": [
    {
      "kind": "ObjectFieldValue",
      "metadata": null,
      "name": "eq",
      "value": {
        "kind": "Variable",
        "variableName": "id"
      }
    }
  ]
}

Relay has strict argument rules which only allow simple query arguments like:

  query AlbumQuery($id: String!) {
-   album(id: { eq: $id }) {
+   album(id: $id) {
    id
    name
  }

Which you can sort-of get to work, but obviously doesn't allow for the flexibility of Gatsby's query filtering/sorting.

After lots of digging around and trying out different tools and libraries like gql2flow and graphql-generate-flow-schema-assets I eventually landed unexpectedly digging through the apollo-cli codegen docs and found that it actually fits perfectly! It should also work well for TypeScript too. 🎉

My config in package.json:

{
  "apollo": {
    "schemas": {
      "gatsby": {
        "endpoint": "http://localhost:8000/___graphql"
      }
    },
    "queries": {
      "schema": "gatsby",
      "includes": ["./src/**/*.js"],
      "excludes": ["node_modules/**"]
    }
  }
}

I then run

apollo codegen:generate --tagName=graphql --target=flow __generated__

Which will generate flow nice, flat flow type definitions alongside each file containing a graphql query/fragment.

Hope that saves somebody some time. 👌

Next task I'm trying to figure out is to get it to run programatically after the server starts up and to watch the files for changes to generate new types automatically.

@cameron-martin
Copy link
Contributor

@levibuzolic When I follow your steps I get the following error

image

@cameron-martin
Copy link
Contributor

The correct config seems to now be:

{
  "apollo": {
    "client": {
      "service": {
        "name": "gatsby",
        "url": "http://localhost:8000/___graphql"
      }
    }
  }
}

@davidharting
Copy link

Does anyone know how to generate types if your queries use fragments that are defined inside of dependencies?

e.g., I have a page template like:

import  { graphql } from "gatsby";

export const query = graphql`
  query pageQuery($id: String!) {
    page(id: { eq: $id }) {
      id
      slug
      title
      ...BodyFragment
    }
  }
`

But BodyFragment is defined using gatsby.graphql inside a component that I am importing from a dependency.

I don't know if it's possible to make apollo code gen find and use that fragment when generating types.

Currently, it errors out with:

Generating query files with 'typescript' target
    → Validation of GraphQL query document failed
.../src/templates/page.tsx: Unknown fragment "BodyFragment".

@Urigo
Copy link

Urigo commented Feb 3, 2019

For some reason I see a lot of people are still coming from this issue into other issues in Apollo Codegen.
I would highly suggest that is you want to generate Typescript or Flow typings, for your frontend and/or backend, try out https://graphql-code-generator.com , as suggested in one of the comments above

@jakst
Copy link

jakst commented Feb 5, 2019

@Urigo Can gql-gen generate types from string-literal page querys in gatsby? Apollo can do that, and I couldn't find any info on it for gql-gen

@kamilkisiela
Copy link
Contributor

kamilkisiela commented Feb 6, 2019

@jakst Yes, it's possible. GraphQL Code Generator looks for graphql or gql tags both in TypeScript and JavaScript files (including tsx, jsx).

In order to start using GraphQL Code Generator:

$ yarn add -D graphql-code-generator

Then you can use our Wizard tool to guide you through the setup process:

$ gql-gen init

It will ask you couple of questions, one is about the plugins, so please select typescript-client and typescript-common. We got an extra one, special for react-apollo that generates components and HOCs, if you prefer and one that turns GraphQL types into TypeScript interfaces (typescript-client translates operations and fragments).

One of the steps require to setup GraphQL endpoint (schema), I don't know how Gatsby exposes that, maybe through a file or http (http://localhost:8000/___graphql)?

When you will be asked about documents, you want to define a glob there. For example, if your fragments and operations are inside of TypeScript files, you do: src/**/*.ts (or similar, depending where files are).

We would be happy to help you and get your feedback :) There's a still a lot to improve, of course so every suggestion counts!

@jakst
Copy link

jakst commented Feb 6, 2019

Hey @kamilkisiela, thanks for the elaborate answer.

I didn't realise I could target .ts files with the glob pattern. But anyway, it does not seem to work.

codegen.yaml

overwrite: true
schema: 'http://localhost:8000/___graphql'
documents: 'src/**/*.tsx'
generates:
  src/queries.ts:
    plugins:
      - 'typescript-common'
      - 'typescript-client'

In src/pages/index.tsx I have the following:

export const pageQuery = graphql`
  query MainPageQuery {
    allContentfulPage(filter: { name: { eq: "main" } }) {
      edges {
        node {
          id
          title
          ingress
        }
      }
    }
  }
`

It does generate all possible type combinations from the graphql endpoint, but I get no generated type for my pageQuery.

@dotansimha
Copy link

@jakst which version of graphql-code-generator do you use?

@IanVS
Copy link

IanVS commented Feb 20, 2019

@jakst @dotansimha I did a little investigation into what's going on with gatsby + graphql-code-generator in dotansimha/graphql-code-generator#1321. TL;DR is that importing graphql from gatsby instead of gatsby-tag seems to break graphql document detection. And unfortunately it seems we cannot use .graphql files with Gatsby (see: #2827). I'm still learning Gatsby, so maybe there's a way and I just don't know about it.

@jakst
Copy link

jakst commented Feb 20, 2019

Great! I'll follow the issue over there to see if there's any progress

@panzerdp
Copy link

panzerdp commented May 25, 2019

How to setup graphql-code-generator for Gatsby:
https://graphql-code-generator.com/docs/integrations/gatsby.

Worked for me 👍.

@dotansimha
Copy link

as @panzerdp said, we currently support importing gql from a different library. See: https://graphql-code-generator.com/docs/integrations/gatsby

@gentleShark
Copy link

@dotansimha any idea why an error related to generated types from graphql-codegen would get thrown just prior to the Gatsby development server starting? Gatsby bootstrapping succeeds but then an error is thrown for the first type in the generated file.

yarn run v1.16.0
$ gatsby develop
success open and validate gatsby-configs — 0.007 s
success load plugins — 0.267 s
success onPreInit — 0.060 s
success initialize cache — 0.009 s
success copy gatsby files — 0.020 s
success onPreBootstrap — 0.012 s
success source and transform nodes — 0.022 s
success building schema — 0.183 s
success createPages — 0.001 s
success createPagesStatefully — 0.082 s
success onPreExtractQueries — 0.001 s
success update schema — 0.112 s
success extract queries from components — 0.132 s
success run graphql queries — 0.046 s — 12/12 270.50 queries/second
success write out page data — 0.009 s
success write out redirect data — 0.001 s
success onPostBootstrap — 0.073 s

info bootstrap finished - 3.116967083 s

 ERROR  Failed to compile with 1 errors                                                                                                                                                    12:37:59 AM

 error  in ./src/graphql/types.d.ts

Syntax Error: SyntaxError: /FILEPATH/src/graphql/types.d.ts: Unexpected token, expected "=" (6:13)

  4 | import * as ReactApollo from 'react-apollo';
  5 | export type Maybe<T> = T | null;
> 6 | type Address {
    |              ^
  7 |   addr1: String
  8 |   addr2: String
  9 |   city: String


 @ ./src/pages/leads-won.tsx 11:0-53 14:25-40
 @ ./.cache/sync-requires.js
 @ ./.cache/app.js
 @ multi event-source-polyfill (webpack)-hot-middleware/client.js?path=/__webpack_hmr&reload=true&overlay=false ./.cache/app

✖ 「wdm」: 
ERROR in ./src/graphql/types.d.ts
Module build failed (from ./node_modules/gatsby/dist/utils/babel-loader.js):
SyntaxError: /FILEPATH/src/graphql/types.d.ts: Unexpected token, expected "=" (6:13)

  4 | import * as ReactApollo from 'react-apollo';
  5 | export type Maybe<T> = T | null;
> 6 | type Address {
    |              ^
  7 |   addr1: String
  8 |   addr2: String
  9 |   city: String
    at Object.raise (/FILEPATH/node_modules/@babel/parser/lib/index.js:3831:17)
    at Object.unexpected (/FILEPATH/node_modules/@babel/parser/lib/index.js:5143:16)
    at Object.expect (/FILEPATH/node_modules/@babel/parser/lib/index.js:5135:28)
    at tsDoThenParseType (/FILEPATH/node_modules/@babel/parser/lib/index.js:9575:46)
    at tsInType (/FILEPATH/node_modules/@babel/parser/lib/index.js:9584:7)
    at Object.tsInType (/FILEPATH/node_modules/@babel/parser/lib/index.js:9564:14)
    at Object.tsDoThenParseType (/FILEPATH/node_modules/@babel/parser/lib/index.js:9583:17)
    at Object.tsExpectThenParseType (/FILEPATH/node_modules/@babel/parser/lib/index.js:9575:17)
    at Object.tsParseTypeAliasDeclaration (/FILEPATH/node_modules/@babel/parser/lib/index.js:9543:32)
    at Object.tsParseDeclaration (/FILEPATH/node_modules/@babel/parser/lib/index.js:9869:23)
    at Object.tsParseExpressionStatement (/FILEPATH/node_modules/@babel/parser/lib/index.js:9807:21)
    at Object.parseExpressionStatement (/FILEPATH/node_modules/@babel/parser/lib/index.js:10192:52)
    at Object.parseStatementContent (/FILEPATH/node_modules/@babel/parser/lib/index.js:7383:19)
    at Object.parseStatementContent (/FILEPATH/node_modules/@babel/parser/lib/index.js:10130:18)
    at Object.parseStatement (/FILEPATH/node_modules/@babel/parser/lib/index.js:7243:17)
    at Object.parseBlockOrModuleBlockBody (/FILEPATH/node_modules/@babel/parser/lib/index.js:7810:25)
 @ ./src/pages/leads-won.tsx 11:0-53 14:25-40
 @ ./.cache/sync-requires.js
 @ ./.cache/app.js
 @ multi event-source-polyfill (webpack)-hot-middleware/client.js?path=/__webpack_hmr&reload=true&overlay=false ./.cache/app
ℹ 「wdm」: Failed to compile.

@dotansimha
Copy link

@gentleShark It seems like an invalid generated code, but it's hard to point the actual issue.
Can you please open an issue with a reproduction in our repo?

@gentleShark
Copy link

Hi @dotansimha - it was a case of user error. I was missing @graphql-codegen/typescript in my devDependencies. up and running now! thanks!

@slorber
Copy link
Contributor

slorber commented Aug 1, 2019

@panzerdp @dotansimha how does graphql-codegen know what types to generate for Gatsby-image fragments? does it work fine with Gatsby images or only simpler queries?

@panzerdp
Copy link

panzerdp commented Aug 1, 2019

@slorber graphql-codegen generates the types for all graphql queries that it finds, including the ones for childImageSharp (including fixed, fluid, etc). These are fully compatible with Gatsby images.

See an example.

@slorber
Copy link
Contributor

slorber commented Aug 4, 2019

I see thanks @panzerdp

Just not totally sure to understand how graphql-codegen find what to generate when it find sharp fragments?

If I understand correctly, it's this config that enables it to find the fragments right? documents: ./node_modules/gatsby-*/**/*.js

You should maybe add in this doc page that codegen support those sharp fragments ;) read the doc but it was not totally obvious to me it would work: https://graphql-code-generator.com/docs/integrations/gatsby

@slorber
Copy link
Contributor

slorber commented Aug 23, 2019

Thanks @panzerdp it's working.

I've noticed an incompatiblity between typedefs for fluid images and fluid prop of gatsby image, have you seen this too by chance? looked at your code and seems to work fine for you, wonder why...

Can you take a look at this issue? #17003

@panzerdp
Copy link

@slorber,
Sorry, not sure why the problem appears on your side. For me everything works as expected. You might need to check why the 2 types are different. Looking at the issue, I see that the second type has an additional field media.

@slorber
Copy link
Contributor

slorber commented Aug 25, 2019

Thanks, don't think it's related because media is optional.

Actually I think you also have the issue @panzerdp it's just you did not use TS in strict mode (you have "strictNullChecks": false which probably hide this issue)

Not really related but you define your own types for Fluid images: https://github.com/panzerdp/dmitripavlutin.com/blob/master/src/typings/image.d.ts#L1
(you could import this type directly from Gatsby-image normally now)

@slorber
Copy link
Contributor

slorber commented Aug 28, 2019

If it's useful to anyone, here's also a solution to generate gatsby TS using apollo cli instead of graphql codegen:

apollographql/apollo-tooling#923

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests