graphql-code-generator icon indicating copy to clipboard operation
graphql-code-generator copied to clipboard

graphql 16 not supported

Open erquhart opened this issue 2 years ago • 10 comments

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

erquhart avatar Mar 26 '23 16:03 erquhart

@saihaj can you please take a look?

dotansimha avatar Mar 27 '23 05:03 dotansimha

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.

saihaj avatar Mar 29 '23 14:03 saihaj

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;

rasrafat avatar Apr 15 '23 00:04 rasrafat

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

Downgrading to [email protected] worked as a temporary fix.

maoosi avatar Jun 07 '23 02:06 maoosi

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

fcpauldiaz avatar Sep 13 '23 21:09 fcpauldiaz

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: https://github.com/graphql/graphql-js/pull/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.

mvarendorff avatar Sep 16 '23 16:09 mvarendorff

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!

mvarendorff avatar Sep 17 '23 12:09 mvarendorff

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"

seemX17 avatar Apr 15 '24 10:04 seemX17

I'm having the same issue as @seemX17. Could you take a look @mvarendorff, please?

Updated "graphql" to 16.10.0 from 15.8.0 + all the codegens

"@graphql-codegen/cli": "^5.0.3",
"@graphql-codegen/schema-ast": "^4.1.0",
"@graphql-codegen/typescript": "^4.1.2",
"@graphql-codegen/typescript-operations": "^4.4.0",
"@graphql-codegen/typescript-urql": "4.0.0",

But this is what errors

**graphql-codegen --config codegen.yml**
yarn run v1.22.22
$ graphql-codegen --config codegen.yml
✔ Parse Configuration
⚠ Generate outputs
  ❯ Generate to generated/graphql.ts
    ✔ Load GraphQL schemas
    ✔ Load GraphQL documents
    ✖ visitFn.call is not a function
error Command failed with exit code 1.

My config:

overwrite: true
schema: "schema.graphql"
documents: "gql/**/*.graphql"
generates:
  generated/graphql.ts:
    plugins:
      - "typescript"
      - "typescript-compatibility"
      - "typescript-operations"
      - "typescript-urql"
    config:
      withComponent: false
      withHooks: true
      strict: true
      maybeValue: T | null | undefined
      scalars:
        Uuid: string
        Money: string
        Password: string

RomanFausek avatar Jan 03 '25 13:01 RomanFausek

@RomanFausek @seemX17 I am not a maintainer of the project - that being said, typescript-compatibility hasn't been updated in 3 years and I could not find a trace of it in this repository, nor in the graphql-code-generator-community one. What happens if you just removed it?

mvarendorff avatar Jan 03 '25 14:01 mvarendorff