Graphql-code-generator: Need help for two issues

Created on 2 Oct 2018  路  24Comments  路  Source: dotansimha/graphql-code-generator

Hey bro,

I do love this package. It's amazing and can help me a lot.
But I have two issues when using this package with typescript.

First issue:
I have some queries like

mutation logout {
    logout @client {
        success
    }
}

Error:

GraphQL Error: Unknown directive "client".

Looks like the generator does not like "@client" syntax. But another generator can generate the code correctly.

Second issue:

    export function HOC<TProps = {}>(
        operationOptions?: ReactApollo.OperationOption<TProps, Query, Variables>
    ) {
        return ReactApollo.graphql<TProps, Query, Variables>(
            Document,
            operationOptions
        );
    }

The HOC is generated correctly but with a type error for operationOptions. It's happening on all queries.

The type error is:

Argument of type 'OperationOption<TProps, Query, Variables, ChildProps<TProps, Query, Variables>> | undefined' is not assignable to parameter of type 'OperationOption<TProps, Query, Variables, Partial<DataProps<Query, Variables>> & Partial<MutateProps<Query, Variables>>> | undefined'.
  Type 'OperationOption<TProps, Query, Variables, ChildProps<TProps, Query, Variables>>' is not assignable to type 'OperationOption<TProps, Query, Variables, Partial<DataProps<Query, Variables>> & Partial<MutateProps<Query, Variables>>>'.
    Types of property 'props' are incompatible.
      Type '((props: OptionProps<TProps, Query, Variables>, lastProps?: void | ChildProps<TProps, Query, Variables> | undefined) => ChildProps<TProps, Query, Variables>) | undefined' is not assignable to type '((props: OptionProps<TProps, Query, Variables>, lastProps?: void | (Partial<DataProps<Query, Variables>> & Partial<MutateProps<Query, Variables>>) | undefined) => Partial<...> & Partial<...>) | undefined'.
        Type '(props: OptionProps<TProps, Query, Variables>, lastProps?: void | ChildProps<TProps, Query, Variables> | undefined) => ChildProps<TProps, Query, Variables>' is not assignable to type '(props: OptionProps<TProps, Query, Variables>, lastProps?: void | (Partial<DataProps<Query, Variables>> & Partial<MutateProps<Query, Variables>>) | undefined) => Partial<...> & Partial<...>'.
          Types of parameters 'lastProps' and 'lastProps' are incompatible.
            Type 'void | (Partial<DataProps<Query, Variables>> & Partial<MutateProps<Query, Variables>>) | undefined' is not assignable to type 'void | ChildProps<TProps, Query, Variables> | undefined'.
              Type 'Partial<DataProps<Query, Variables>> & Partial<MutateProps<Query, Variables>>' is not assignable to type 'void | ChildProps<TProps, Query, Variables> | undefined'.
                Type 'Partial<DataProps<Query, Variables>> & Partial<MutateProps<Query, Variables>>' is not assignable to type 'ChildProps<TProps, Query, Variables>'.
                  Type 'Partial<DataProps<Query, Variables>> & Partial<MutateProps<Query, Variables>>' is not assignable to type 'TProps'.

Please fell free to point out what I did wrong or what I can do to fix them. I really want to use it :)

Thanks again for everyone's effort to build this handy package 馃憤

bug core waiting-for-release

All 24 comments

@cjnoname Which version of graphql, the codegen and the templates do you use?

@cjnoname Which version of graphql, the codegen and the templates do you use?

graphql 0.13.0 is it too old? :)
both codegen and template are at 0.12.6

@cjnoname 0.13.0 should work. I'll take a look at the issue with the @client soon.
@ardatan can you please take a look at the issue with the React HOC template?

@cjnoname 0.13.0 should work. I'll take a look at the issue with the @client soon.
@ardatan can you please take a look at the issue with the React HOC template?

Thank you so much for your quick response :)

@cjnoname the first issue is fixed here: https://github.com/dotansimha/graphql-code-generator/pull/661

@cjnoname And until a stable version, you can use the following alpha versions that includes this fix:

Successfully published:
 - [email protected]
 - [email protected]
 - [email protected]
 - [email protected]
 - [email protected]
 - [email protected]
 - graphql-codegen-typescript-mongodb-template@0.13.0-alpha.cc713899
 - graphql-codegen-typescript-react-apollo-template@0.13.0-alpha.cc713899
 - [email protected]
lerna success publish finished

Generated typings now supports strict TypeScript settings.
It has to be fixed in the following versions;

Successfully published:
 - [email protected]
 - [email protected]
 - [email protected]
 - [email protected]
 - [email protected]
 - [email protected]
 - graphql-codegen-typescript-mongodb-template@0.13.0-alpha.827d6cf4
 - graphql-codegen-typescript-react-apollo-template@0.13.0-alpha.827d6cf4
 - [email protected]

Hi @dotansimha ,

Thanks for your quick fix! That is really impressive.

Now it's not complaining about the @client which is great. However it could not generate things under the client.

For example
mutation handleResetPassword($password: String!, $oobCode: String!) {
verifyPasswordResetCode(password: $password, oobCode: $oobCode) @client
}

mutation login($password: String!, $email: String!) {
auth(password: $password, email: $email) @client {
__typename
email
token
uid
id
loggedIn
}
}

It will complain something like

17:23:25.575 - error: [./src/queries/account.gql] GraphQL Error: Cannot query field "verifyPasswordResetCode" on type "Mutation".
17:23:25.575 - error: [./src/queries/account.gql] GraphQL Error: Cannot query field "auth" on type "Mutation".

Looks like it's trying to fetch the first variable but failed then it threw an error.

Hi @ardatan,

Thanks for your quick fix, the type is way better now.

I think there is only one issue left which is a tiny bug:

export namespace GetOrganisations {
export const Document = gql`
query getOrganisations {
organisations {
...organisationFields
}
}

    ${OrganisationFields.Document}
`;
export class Component extends React.Component<
    Partial<ReactApollo.QueryProps<Query, Variables>>
> {
    render() {
        return (
            <ReactApollo.Query<Query, Variables>
                query={Document}
                {...this["props"] as any}
            />
        );
    }
}
export function HOC<
    TProps = any,
    OperationOptions = ReactApollo.OperationOption<TProps, Query, Variables>
>(operationOptions: OperationOptions) {
    return ReactApollo.graphql<TProps, Query, Variables>(
        Document,
        operationOptions
    );
}

}

Base on the generated code, I got this error from ${OrganisationFields.Document}.

Because OrganisationFields is not existed.

I manually changed it to organisationFields then it's looking all good.

Thanks for your quick fix 馃憤

@ardatan please take a look :)

@cjnoname regarding the @client errors, you have to provide your client-side schema for the codegen as well. there is a flag called --client-schema.

@cjnoname I need to see the declaration of fragment document etc to see what the problem is. Could you share that part?

I am having similar issues, I just tried the latest alpha version but client is still not working for me.

@dotansimha is there some examples of code with a client-schema definition file ?

@ardatan

Here are some of my code samples if it helps

app.ts angular component

import { Component, HostBinding, OnInit } from "@angular/core";
import { OverlayContainer } from "@angular/cdk/overlay";
import gql from "graphql-tag";
import { Apollo } from "apollo-angular";

@Component({
  selector: "help-root",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.sass"]
})
export class AppComponent implements OnInit {
  @HostBinding("class") componentCssClass: string | null = null;
  constructor(
    private overlayContainer: OverlayContainer,
    private apollo: Apollo
  ) {}

  setTheme(theme: string) {
    this.componentCssClass = theme;
  }

  ngOnInit() {
    const query = gql(`
          query {
            currentTheme @client {
              theme
            }
          }
        `);

    this.apollo
      .watchQuery({
        query: query
      })
      .valueChanges.subscribe(({ data }: any) => {
        this.setTheme(data.currentTheme.theme);
      });
  }
}

relevant error

21:13:33.780 - error: [./src/app/app.component.ts] GraphQL Error: Cannot query field "currentTheme" on type "Query". Did you mean "currency"? 
21:13:33.780 - error: [./src/app/app.component.ts] GraphQL Error: Unknown directive "client". 

theme.lgraphql.ts

export const themeResolverMutation = {
  updateCurrentTheme: (_: any, { theme }: any, { cache }: any) => {
    const data = {
      currentTheme: {
        __typename: "CurrentTheme",
        theme
      }
    };
    cache.writeData({ data });
    return null;
  }
};

export const themeDefault = {
  currentTheme: {
    __typename: "CurrentTheme",
    theme: "light-theme"
  }
};

This file is used as a resolver for apollo-link-state

relevant error

21:13:33.783 - error: [./src/app/shared/graphql/theme/theme.lgraphql.spec.ts] GraphQL Error: This anonymous operation must be the only defined operation. 
21:13:33.783 - error: [./src/app/shared/graphql/theme/theme.lgraphql.spec.ts] GraphQL Error: Cannot query field "currentTheme" on type "Query". Did you mean "currency"? 
21:13:33.783 - error: [./src/app/shared/graphql/theme/theme.lgraphql.spec.ts] GraphQL Error: Unknown directive "client". 
21:13:33.783 - error: [./src/app/shared/graphql/theme/theme.lgraphql.spec.ts] GraphQL Error: Cannot query field "updateCurrentTheme" on type "Mutation". 
21:13:33.783 - error: [./src/app/shared/graphql/theme/theme.lgraphql.spec.ts] GraphQL Error: Unknown directive "client". 

I could put this in a sample repo if it would help.

@vespertilian please take a look here: https://github.com/dotansimha/graphql-code-generator/pull/561

@ardatan please take a look :)

@cjnoname regarding the @client errors, you have to provide your client-side schema for the codegen as well. there is a flag called --client-schema.

Thanks mate, it's fixed for me. Thanks for your great work.
By the way, do you know that is there any way to generate the schema json automatically?

@cjnoname I need to see the declaration of fragment document etc to see what the problem is. Could you share that part?

Hi Ardatan,

I think it's just a case issue.

The query is

query getOrganisations {
    organisations {
        ...organisationFields
    }
}

The generated code is

export namespace GetOrganisations {
    export const Document = gql`
        query getOrganisations {
            organisations {
                ...organisationFields
            }
        }

        ${OrganisationFields.Document}
    `;
    export class Component extends React.Component<
        Partial<ReactApollo.QueryProps<Query, Variables>>
    > {
        render() {
            return (
                <ReactApollo.Query<Query, Variables>
                    query={Document}
                    {...this["props"] as any}
                />
            );
        }
    }
    export function HOC<
        TProps = any,
        OperationOptions = ReactApollo.OperationOption<TProps, Query, Variables>
    >(operationOptions: OperationOptions) {
        return ReactApollo.graphql<TProps, Query, Variables>(
            Document,
            operationOptions
        );
    }
}

You can see that OrganisationFields with capital O, which is not exisiting in the file at all. I changed it to lower case then it can work.

Hope it can help.

The whole thing is almost perfect.

@cjnoname You can use introspection template to generate schema json.
I also fixed pascalcase issue in typescript-react-apollo template, so you can use these alpha versions. And let us know if any problem occurs.

Successfully published:
 - [email protected]
 - [email protected]
 - [email protected]
 - [email protected]
 - [email protected]
 - [email protected]
 - graphql-codegen-typescript-mongodb-template@0.13.0-alpha.812f139a
 - graphql-codegen-typescript-react-apollo-template@0.13.0-alpha.812f139a
 - [email protected]

@ardatan hey, thanks for working on that awesome tool. I'm facing similar issues at the moment and using alpha version helped to solve part of them. But I still have a problem with TypeScript typings for generated HOC component. Specifically for operationOptions.

If I change its type operationOptions?: ReactApollo.ChildProps<TProps, Query, Variables> ts-server is happy and removes the error. Is it a problem in my setup or we need a PR to fix that?

TS server even requests for more verbose type description in the other editor:

Argument of type 'ChildProps<TProps, CountQuery, CountVariables> | undefined' is not assignable to parameter of type 'OperationOption<TProps, CountQuery, CountVariables, Partial<DataProps<CountQuery, CountVariables>> & Partial<MutateProps<CountQuery, CountVariables>>> | undefined'.
  Type 'ChildProps<TProps, CountQuery, CountVariables>' is not assignable to type 'OperationOption<TProps, CountQuery, CountVariables, Partial<DataProps<CountQuery, CountVariables>> & Partial<MutateProps<CountQuery, CountVariables>>> | undefined'.
    Type 'ChildProps<TProps, CountQuery, CountVariables>' has no properties in common with type 'OperationOption<TProps, CountQuery, CountVariables, Partial<DataProps<CountQuery, CountVariables>> & Partial<MutateProps<CountQuery, CountVariables>>>'.

If I set it to:

operationOptions?: ReactApollo.OperationOption<TProps, CountQuery, CountVariables, Partial<ReactApollo.DataProps<CountQuery, CountVariables>> & Partial<ReactApollo.MutateProps<CountQuery, CountVariables>>>,

Linter is happy.

Guys, @ardatan @cjnoname, could you suggest is the problem on my side or react-apollo template should be updated? Thanks!

@valerybugakov
Are you using the latest stable version, because it's supposed to be fixed in the following versions;

Successfully published:
 - [email protected]
 - [email protected]
 - [email protected]
 - [email protected]
 - [email protected]
 - [email protected]
 - graphql-codegen-typescript-mongodb-template@0.13.0-alpha.812f139a
 - graphql-codegen-typescript-react-apollo-template@0.13.0-alpha.812f139a
 - [email protected]

@ardatan you're right, the latest version of the react-apollo-template fixes the issue for me, thanks!

This appears to still be an issue with

json "graphql-code-generator": "^0.13.0-alpha.f8c8892a", "graphql-codegen-typescript-react-apollo-template": "^0.13.0-alpha.f8c8892a",

command used:

gql-gen --schema http://localhost:3000/graphql --clientSchema ./src/store/schema.graphql --header "Authorization: Bearer [token removed]" --template graphql-codegen-typescript-react-apollo-template --out ./src/store/types/index.ts "./src/**/*.+(graphql|ts|tsx)

additional info:

12:57:13.123 - error: [./src/store/graphql/taskEventFieldsFragment.graphql] GraphQL Error: Unknown fragment "userFields".
12:57:13.124 - error: [./src/store/graphql/taskEventFieldsFragment.graphql] GraphQL Error: Unknown fragment "leadFields".
12:57:13.124 - error: [./src/store/graphql/taskEventFieldsFragment.graphql] GraphQL Error: Unknown fragment "noteFields".
12:57:13.124 - error: [./src/store/graphql/UserTasks.graphql] GraphQL Error: Unknown fragment "taskEventFields".
12:57:13.124 - error: [./src/store/queries/TaskExpandedQuery.ts] GraphQL Error: Unknown directive "client".
12:57:13.125 - error: [./src/store/queries/TaskExpandedQuery.ts] GraphQL Error: Unknown directive "client".
12:57:13.125 - error: [./src/store/queries/TaskListExpandedQuery.ts] GraphQL Error: This anonymous operation must be the only defined operation.
12:57:13.125 - error: [./src/store/queries/TaskListExpandedQuery.ts] GraphQL Error: Unknown directive "client".
12:57:13.125 - error: [./src/store/queries/TaskListExpandedQuery.ts] GraphQL Error: Unknown directive "client".
12:57:13.125 - error: [./src/store/schema.graphql] GraphQL Error: The TaskExpanded definition is not executable.
12:57:13.125 - error: [./src/store/schema.graphql] GraphQL Error: The Mutation definition is not executable.
12:57:13.125 - error: [./src/store/schema.graphql] GraphQL Error: The Query definition is not executable.

there are additional problems, like no recognition of #import './userFieldsFragment.graphql'

@moonray can you please try 0.13.0?

All fixes are available now in 0.14 馃帀

For the @client support, you can add this following line to any .graphql file containing your schema:
directive @client(always: Boolean) on FIELD
This will let the compiler know you can use a directive @client and that this directive can take a boolean always.

Was this page helpful?
0 / 5 - 0 ratings