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

graphql 16 not supported #9230

Open
erquhart opened this issue Mar 26, 2023 · 8 comments
Open

graphql 16 not supported #9230

erquhart opened this issue Mar 26, 2023 · 8 comments
Assignees
Labels
kind/bug Bug :-( stage/1-reproduction A reproduction exists

Comments

@erquhart
Copy link

erquhart commented Mar 26, 2023

Which packages are impacted by your issue?

@graphql-codegen/cli

Describe the bug

Note - this is not a duplicate of #6937, this is to point out that issue is not actually complete.

The example in the docs does not work with graphql 16: https://the-guild.dev/graphql/codegen/docs/custom-codegen/using-visitor

The example does work if I downgrade to graphql 15.

Specifically this plugin example:

const { getCachedDocumentNodeFromSchema } = require('@graphql-codegen/plugin-helpers')
const { visit } = require('graphql')
 
module.exports = {
  plugin(schema, documents, config) {
    const astNode = getCachedDocumentNodeFromSchema(schema) // Transforms the GraphQLSchema into ASTNode
    const visitor = {
      FieldDefinition(node) {
        // This function triggered per each field
      },
      ObjectTypeDefinition(node) {
        // This function triggered per each type
      }
    }
 
    const result = visit(astNode, { leave: visitor })
 
    return result.definitions.join('\n')
  }
}

Running this results in visitFn.call is not a function.

This is outlined in #6937, which is closed, but the issue persists as other recent comments on that issue indicate.

Your Example Website or App

https://codesandbox.io/p/sandbox/headless-cloud-6z6r45

Steps to Reproduce the Bug or Issue

  1. Go to linked example
  2. Run npm run codegen in the terminal
  3. Observe output

Expected behavior

Visitor function should not error.

Screenshots or Videos

Screenshot 2023-03-26 at 12 23 39 PM

Platform

  • OS: multiple, n/a
  • NodeJS: multiple, n/a
  • graphql version: 16.6
  • @graphql-codegen/* version(s): all latest, see sandbox

Codegen Config File

See sandbox, copied from docs

Additional context

No response

@dotansimha
Copy link
Owner

@saihaj can you please take a look?

@saihaj saihaj self-assigned this Mar 27, 2023
@saihaj saihaj added kind/bug Bug :-( stage/1-reproduction A reproduction exists labels Mar 27, 2023
@saihaj
Copy link
Collaborator

saihaj commented Mar 29, 2023

I tried investigating this, so seems like something specific to plugins that we are creating locally beacuse looking and trying in the repo everything is working as expected.

@rasrafat
Copy link

Ah. Recently bumped the graphql package from v15 to v16 and seeing the same issue. My packages:

"graphql": "16.6.0",
"@graphql-codegen/cli": "3.3.0",
"@graphql-codegen/near-operation-file-preset": "^2.5.0",
"@graphql-codegen/typescript-compatibility": "^2.1.5",
"@graphql-codegen/typescript-operations": "^3.0.3",

The gql-codegen.ts config:

import type { CodegenConfig } from "@graphql-codegen/cli";

const config: CodegenConfig = {
  overwrite: true,
  schema: "<path_to_endpoint>",
  documents: "./**/*.ts",
  generates: {
    "./__generated__/globalTypes.ts": {
      plugins: ["typescript"],
      config: {
        namingConvention: {
          enumValues: "keep",
        },
      },
    },
    "./": {
      preset: "near-operation-file",
      presetConfig: {
        baseTypesPath: "./__generated__/globalTypes.ts",
        importTypesNamespace: "GlobalTypes",
        extension: ".types.ts",
        folder: "__generated__",
        overwrite: true,
      },
      plugins: ["typescript-operations", "typescript-compatibility"],
      config: {
        preResolveTypes: true,
        flattenGeneratedTypes: true,
      },
    },
  },
  hooks: {
    afterAllFileWrite: [
      "eslint --fix --rule '@typescript-eslint/no-namespace: \"off\"'",
      "prettier --write",
    ],
  },
};

export default config;

@maoosi
Copy link

maoosi commented Jun 7, 2023

I'm having the exact same issue pointing to a local plugin, using the example code from the docs.

Downgrading to graphql@15.8.0 worked as a temporary fix.

@fcpauldiaz
Copy link

I also updated from v15 to v16 and I'm having the same issue. @saihaj thanks for looking at this.

@geisterfurz007
Copy link

geisterfurz007 commented Sep 16, 2023

I have been poking around in this a bit because I have been increasingly more frustrated with codegen holding back my move to graphql@16 and honestly, this seems like this one might be on the graphql package (more or less).

This is the function responsible for resolving the visitFn (one for enter and one for leave):

https://github.com/graphql/graphql-js/blob/7a6d055defd7a888f50c6133faae2b9010d45fad/src/language/visitor.ts#L375-L394

Note the comments for the different cases as well as the types. The visitor defined is simply not valid anymore in graphql@16.

You can either have a general enter and leave, separate enter and leave per kind or an implementation per kind that's understood as its enter function. What's not allowed is to set leave to an object of functions per kind. It was allowed in graphql@15.

The types reflect this properly, using the visitor in the OP does throw a compiler error.

Poking around some more, I found the PR that removed this form of visitor which argues that such a visitor can always be rewritten to the second form mentioned above: graphql/graphql-js#2957

Knowing this, we can write a helper function to transform an existing visitor of that "4th form" to the "2nd form" (dirty JS because I was running low on time; might revisit with proper typings):

const convertLegacyVisitor = (visitor) => {
    const newVisitor = {};

    const { enter, leave } = visitor;

    if (enter && typeof enter === "object") {
        for (const key in enter) {
            newVisitor[key] = { enter: enter[key]};
        }
    }

    if (leave && typeof leave === "object") {
        for (const key in leave) {
            newVisitor[key] ??= { leave: leave[key]};
        }
    }

    return newVisitor;
};

Which can be used like so:

const visitor = {
    FieldDefinition(node) {
        // This function triggered per each field
    },
    ObjectTypeDefinition(node) {
        // This function triggered per each type
    }
}

const patchedVisitor = convertLegacyVisitor({leave: visitor});

const result = visit(astNode, patchedVisitor);

What I don't know is whether any of the plugins still use the old, now unsupported syntax but I would assume that unless there are any as involved, TypeScript would have yelled already so chances are this might only be an issue for those writing custom plugins in JS?

At the very least it's a docs issue which should be easily remedied. Either by including that ugly piece of code of mine from above or changing the visitor to use one of the three allowed forms.

@geisterfurz007
Copy link

Update: Since I am also developing a custom plugin at work, I was curious how this project solved the issue of not being able to create class instances anymore to handle leaving. Turns out, you can also do much simpler than I did above by replacing const { visit } = require("graphql"); with const { oldVisit } = require("@graphql-codegen/plugin-helpers"); and using oldVisit instead!

@seemX17
Copy link

seemX17 commented Apr 15, 2024

Able to reproduce this bug when trying to use "@graphql-codegen/typescript-compatibility" works fine without typescript-compatibility

"graphql": "^16.8.1"
 "@graphql-codegen/add": "^5.0.2",
  "@graphql-codegen/cli": "^5.0.2",
  "@graphql-codegen/introspection": "^4.0.3",
  "@graphql-codegen/typescript": "^4.0.6",
  "@graphql-codegen/typescript-compatibility": "^2.1.5",[PROBLEM]
  "@graphql-codegen/typescript-operations": "^4.2.0",
  "@graphql-codegen/typescript-react-apollo": "^4.0.0"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind/bug Bug :-( stage/1-reproduction A reproduction exists
Projects
None yet
Development

No branches or pull requests

8 participants