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

Automatic TypeScript Definitions Generation #14185

Closed
Siyfion opened this issue May 20, 2019 · 29 comments
Closed

Automatic TypeScript Definitions Generation #14185

Siyfion opened this issue May 20, 2019 · 29 comments

Comments

@Siyfion
Copy link
Contributor

Siyfion commented May 20, 2019

Summary

This feature request stems from a conversation on the Gatsby discord server that I had with @DSchau in which I asked:

Is there any way to generate TypeScript definitions for the results of each graphql'' query? This would allow us to ensure that all cases are covered, with regards to nullables, etc.

I did think that I might be able to use something like: npx [email protected] client:codegen --endpoint=http://localhost:8000/___graphql --target=typescript however, we use gatsby-image and it complains mightily about Unknown fragment "GatsbyContentfulFluid_withWebp" etc...

It just seems that this is something that Gatsby has the potential to do entirely for you on initial build, and then on each file change... Something to consider?

dschau: @StarvingDragon we've talked about generating the SDL (e.g. a snapshot of the current schema as apollo-like types) but hadn't considered Typescript definitions! Could you perhaps share some more info and/or open an issue with more detail for what you'd like?

Basic example & Motivation

So the benefit of this (auto-generated types) would be that if you're developing in TS, you could type all data passed into the pages/component as props mega simply! And you could also guarantee that after each rebuild, if the types changed, you'd know and have failing TS errors...

eg. imagine changing a field (say "author") in Contentful from required to optional. The next time that Gatsby would start up, it would know that field is now optional and update the TS definition such that author: Author | null. Leading anywhere that you're not handling a null value to throw TS errors.

Progress so far

I have managed to get the apollo:codegen tool to recognise the queries Gatsby uses by changing imports to import { graphql as gql } from 'gatsby', as I believe it's looking for gql tags. However, as stated above, it struggles with the Gatsby Image fragments, as it doesn't know what they are!

@lannonbr
Copy link
Contributor

CC: @pieh I recall you having something similar to this if I am not mistaken

@pieh
Copy link
Contributor

pieh commented May 20, 2019

@Siyfion I'm not sure if this still works - but you can try checking https://github.com/pieh/gatsby-query-result-type-gen

@pieh
Copy link
Contributor

pieh commented May 20, 2019

Yep, it doesn't work anymore after some refactoring done in gatsby (as I was importing some gatsby internals there), but it probably can be updated to work again.

The fragment blocker you mentioned - please check my code - I was importing "queries" directly from gatsby redux store (and not parsing your project directly). This ensures that any fragments that were used will be attached to queries (i.e. gatsby-image` fragments)

@Siyfion
Copy link
Contributor Author

Siyfion commented May 21, 2019

Ah nice @pieh! Is this something that the Gatsby team would consider incorporating as an official tool in future? I really think it'd be hugely useful!

@Siyfion
Copy link
Contributor Author

Siyfion commented May 21, 2019

I believe that the major breaking change seems to be this refactor: bbb8c36 with maybe an element of 3ca49f2 thrown in for good measure too!

@pieh
Copy link
Contributor

pieh commented May 21, 2019

Ah nice @pieh! Is this something that the Gatsby team would consider incorporating as an official tool in future? I really think it'd be hugely useful!

This was one of my "weekend projects", and I don't think we really talked about it yet.

Now I start to remember more when I was working on this (why I didn't make it a plugin and made "standalone" tool). apollo-codegen used different version of graphql package and this was causing issues (when you have multiple versions of graphql package in node_modules it can cause weird issues ( for example errors like graphile/crystal#677 ) - which also make it hard to incorporate this nicely

@Siyfion
Copy link
Contributor Author

Siyfion commented May 21, 2019

apollo-codegen used different version of graphql package and this was causing issues (when you have multiple versions of graphql package in node_modules it can cause weird issues

Yup, I've been on the receiving end of lots of those issues at various points over the last few months! It does seem to be a constant issue with the Apollo CLI unfortunately. Still, if Gatsby did support this tool as an official way to generate TypeScript Definitions, I'm sure there would be a fair amount of support for it ;)

@andykenward
Copy link
Contributor

andykenward commented May 27, 2019

You should try using graphQL-codegen . They have documentation on using it with Gatsby.

npm i @graphql-codegen/cli @graphql-codegen/typescript @graphql-codegen/typescript-operations --save-dev

There is currently an issue with their suggested config, so use the below config.

# codegen.yml
schema: http://localhost:8000/___graphql
documents:
  - ./src/**/*.{ts,tsx}
  - ./node_modules/gatsby-*/**/*.js
config:
  namingConvention:
    enumValues: keep
generates:
  ./src/graphqlTypes.ts:
    plugins:
      - typescript
      - typescript-operations

@pieh
Copy link
Contributor

pieh commented May 27, 2019

Ooooh, that's interesting! Using programmatic API ( https://graphql-code-generator.com/docs/getting-started/#using-in-runtime ) this could really be turned into gatsby plugin I think

@cameron-martin
Copy link
Contributor

Related: #2374

@Siyfion
Copy link
Contributor Author

Siyfion commented May 29, 2019

Wow, that's really cool @andykenward, though it still seems to struggle with the image fragments, eg:

$ graphql-codegen
  ✔ Parse configuration
  ❯ Generate outputs
    ❯ Generate ./src/graphqlTypes.ts
      ✔ Load GraphQL schemas
      ✔ Load GraphQL documents
      ✖ Generate
        →         at ./node_modules/gatsby-transformer-sharp/src/fragments.js:200:53


 Found 1 error

  ✖ ./src/graphqlTypes.ts
    AggregateError:
        GraphQLDocumentError: Unknown type "ImageSharpFixed".
            at ./node_modules/gatsby-transformer-sharp/src/fragments.js:1:35

Perhaps using their programmatic API we could add these "known" fragments in @pieh?

@andykenward
Copy link
Contributor

andykenward commented May 29, 2019

@Siyfion is works with GatsbyImageSharpFixed fragment.

I've made a Gatsby Starter you can try it out "Gatsby's default starter - TypeScript" with graphql-code-generator setup.

@Siyfion
Copy link
Contributor Author

Siyfion commented May 30, 2019

@andykenward we're using GatsbyContentfulFluid_withWebp and GatsbyContentfulFixed_withWebp throughout our code, so I can only assume that the issue relates to their usage as, like you say, your repo with images seems to work fine!

@andykenward
Copy link
Contributor

@Siyfion I think that's to do with not being able to query the Contentful GraphQL endpoint to generate their fragments. Adding the Gatsby Plugin gatsby-source-contentful and having valid api keys setup. When I try to generate the typings I get an error on any fragment referring to their fragments ContentfulFixed.

at ./node_modules/gatsby-source-contentful/src/fragments.js
 AggregateError:
        GraphQLDocumentError: Unknown type "ContentfulFixed".
            at ./node_modules/gatsby-source-contentful/src/fragments.js:1:35
        GraphQLDocumentError: Unknown type "ContentfulFixed".
            at ./node_modules/gatsby-source-contentful/src/fragments.js:9:45

@Siyfion
Copy link
Contributor Author

Siyfion commented May 30, 2019

Yeah @andykenward, it's weird because they are all there in that ./node_modules/gatsby-source-contentful/src/fragments.js file... Not really sure what's going on 😕

Edit: Ah.. I see they are all fragments on things like ContentfulFixed which ofc are exposed by the Contentful API, which it doesn't seem to be able to read.

@andykenward
Copy link
Contributor

@Siyfion Setting up Gatsby-source-graphql and configuring GraphCMS and GitHub GraphQL Endpoints lets me generate their schemas typings just using http://localhost:8000/___graphql as the one endpoint for "GraphQL code generator".

Perhaps using gatsby-source-graphql and configuring a Contentful GraphQL endpoint will solve it?

@Siyfion
Copy link
Contributor Author

Siyfion commented May 31, 2019

@andykenward but the thing is, I don't think that the gatsby-source-contentful plugin is actually using Contentful's GraphQL API, as it's currently reserved for specific high-throughput/perf. spaces.

So the GraphQL fragments, types, etc. must all be coming from the Gatsby plugin!?

EDIT: Seems to be generated by extend-node-type.js:508:

const fixedNode = fixedNodeType({ name: `ContentfulFixed`, getTracedSVG })

@gatsbot
Copy link

gatsbot bot commented Jun 21, 2019

Hiya!

This issue has gone quiet. Spooky quiet. 👻

We get a lot of issues, so we currently close issues after 30 days of inactivity. It’s been at least 20 days since the last update here.

If we missed this issue or if you want to keep it open, please reply here. You can also add the label "not stale" to keep this issue open!

As a friendly reminder: the best way to see this issue, or any other, fixed is to open a Pull Request. Check out gatsby.dev/contribute for more information about opening PRs, triaging issues, and contributing!

Thanks for being a part of the Gatsby community! 💪💜

@gatsbot gatsbot bot added the stale? Issue that may be closed soon due to the original author not responding any more. label Jun 21, 2019
@Siyfion Siyfion added not stale and removed stale? Issue that may be closed soon due to the original author not responding any more. labels Jul 2, 2019
@Siyfion
Copy link
Contributor Author

Siyfion commented Jul 2, 2019

I've been having a lot of success with graphql-codegen in many other projects, but unfortunately the moment I use a fluid/fixed image the whole thing comes crumbling down with a Gatsby project. Which is a shame! Why aren't the fragments exposed in the introspection query I wonder? @KyleAMathews

@KyleAMathews
Copy link
Contributor

@Siyfion it's tricky as graphiql and other tools don't support it. @pieh has some initial work in that direction so hopefully we'll get there.

@d4rekanguok
Copy link
Contributor

hey folks, run into this issue by chance -- I recently wrote a typescript plugin that does codegen automatically, using graphql-codegen api like pieh mentioned above. I've been using it for awhile, so far so good.

The codegen part can be its own plugin really -- I wanted to spin it out but haven't got the chance to do so yet. Give it a try if you're interested!

@orta
Copy link
Contributor

orta commented Jul 31, 2019

The new GraphiQL 1.0 re-design work should allow plugins which I think would support adding the extra fragments

@RIP21
Copy link
Contributor

RIP21 commented Aug 4, 2019

@Siyfion about Fragments, I just copy-pasted them into the project from the plugin itself and got everything generated.
Just copy-paste this file.
https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby-transformer-sharp/src/fragments.js
And you're good to go with graphql-codegen

If anyone wondering what is my config. Here it is.

overwrite: true
schema: "${SCHEMA:schema.graphql}"
pluckConfig:
  globalIdentifier: "graphql"
documents:
  - "./{src,gatsby-scripts}/**/*.graphql"
  - "./{src,gatsby-scripts}/**/*!(.generated).{ts,tsx}"
generates:
  src/types.generated.ts:
    plugins:
      - "typescript"
    config:
      namingConvention:
        enumValues: keep
  src/:
    preset: near-operation-file
    presetConfig:
      extension: .generated.ts
      baseTypesPath: ./types.generated.ts
    plugins:
      - typescript-operations
  ./schema.graphql:
    plugins:
      - "schema-ast"

Although I must admit strictness of types that are generated needs to be fixed because typings that are getting generated are way too "nullable" causing millions of null checks for no reason..
Please, continue the discussion about it here #16310 anyone who is interested.

@slorber
Copy link
Contributor

slorber commented Aug 23, 2019

hey, has anybody encountered incompatible types between the gatsby image fluid fragments (generated by graphql-codegen) and the gatsby-image fluid prop? => #17003

@daugsbi
Copy link
Contributor

daugsbi commented Sep 2, 2019

Hey,
I've created a plugin for handling TypeScript/Flow generation with apollo-codegen and configure the vscode apollographql plugin for autocomplete.

npm install --save gatsby-plugin-codegen

I would love to hear your feedback.

@bsgreenb
Copy link

bsgreenb commented Oct 31, 2019

For people using Gatsby with Contentful, the problem is that Contentful, everything (Required or not) has | null after it, and none of the generated interfaces match the expected props. This is primarily because Contentful does not set non_null for Required fields, as explained here:

image

Right now I'm having to hard-code non-null types, so not getting the expected benefits of a code generator. Hope that we get a plugin or fundamental improvement from Contentful to improve this situation with nullability.

@TeoTN
Copy link

TeoTN commented Apr 7, 2020

So what is the status of that and what is the state of the art way to integrate gatsby, graphQL, image fragments and typescript?
I currently have ts-graphql-plugin in my tsconfig.json, gatsby-plugin-typegen to generate types and schema, JS GraphQL plugin for WebStorm and gatsby-plugin-typescript, and it fails on the fragment. Is there a simple way to have it all running together?

@LekoArts
Copy link
Contributor

Let's track this in the meta issue: #17934
Please add your comments there, thanks!

@LekoArts
Copy link
Contributor

LekoArts commented May 5, 2022

This is soon a built-in feature to Gatsby: RFC: GraphQL TypeScript Generation

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