dotansimha / graphql-code-generator-community

MIT License
117 stars 152 forks source link

Add React-query subscription to generator #178

Open maaasyn opened 2 years ago

maaasyn commented 2 years ago

Right now, the plugin doesn't generate use{Operation}Subscribe.

Currently, we are able to have a custom fetcher, so users can decide how to handle subscriptions, and the plugin can just use normal useQuery from the react-query lib.

There is some nice example how it can be done with custom fetcher: https://hasura.io/blog/getting-started-with-react-query-and-graphql/

sample schema with operations:


scalar Date

schema {
  query: Query
  mutation: Mutation
  subscription: Subscription

}

type Query {
  allUsers: [User!]!
}

type Subscription {
  allUsers: [User!]!
}

type Mutation {
  addUser(userInput: UserInput!): User!
}

type User {
  id: ID!
  username: String!
}

input UserInput {
  username: String!
}

Operations :

query getUser{
  allUsers {
      username
  }
}

mutation addUser($userInput: UserInput!) {
    addUser(userInput: $userInput) {
        username
    }
}

subscription subUser{
  allUsers {
      username
  }
}

result (no use{Operator}Subscription generated)

import { useQuery, UseQueryOptions, useMutation, UseMutationOptions } from 'react-query';
export type Maybe<T> = T | null;
export type InputMaybe<T> = Maybe<T>;
export type Exact<T extends { [key: string]: unknown }> = { [K in keyof T]: T[K] };
export type MakeOptional<T, K extends keyof T> = Omit<T, K> & { [SubKey in K]?: Maybe<T[SubKey]> };
export type MakeMaybe<T, K extends keyof T> = Omit<T, K> & { [SubKey in K]: Maybe<T[SubKey]> };

function fetcher<TData, TVariables>(endpoint: string, requestInit: RequestInit, query: string, variables?: TVariables) {
  return async (): Promise<TData> => {
    const res = await fetch(endpoint, {
      method: 'POST',
      ...requestInit,
      body: JSON.stringify({ query, variables }),
    });

    const json = await res.json();

    if (json.errors) {
      const { message } = json.errors[0];

      throw new Error(message);
    }

    return json.data;
  }
}
/** All built-in and custom scalars, mapped to their actual values */
export type Scalars = {
  ID: string;
  String: string;
  Boolean: boolean;
  Int: number;
  Float: number;
  Date: any;
};

export type Query = {
  __typename?: 'Query';
  allUsers: Array<User>;
};

export type Subscription = {
  __typename?: 'Subscription';
  allUsers: Array<User>;
};

export type Mutation = {
  __typename?: 'Mutation';
  addUser: User;
};

export type MutationAddUserArgs = {
  userInput: UserInput;
};

export type User = {
  __typename?: 'User';
  id: Scalars['ID'];
  username: Scalars['String'];
};

export type UserInput = {
  username: Scalars['String'];
};

export type GetUserQueryVariables = Exact<{ [key: string]: never; }>;

export type GetUserQuery = { __typename?: 'Query', allUsers: Array<{ __typename?: 'User', username: string }> };

export type AddUserMutationVariables = Exact<{
  userInput: UserInput;
}>;

export type AddUserMutation = { __typename?: 'Mutation', addUser: { __typename?: 'User', username: string } };

export type SubUserSubscriptionVariables = Exact<{ [key: string]: never; }>;

export type SubUserSubscription = { __typename?: 'Subscription', allUsers: Array<{ __typename?: 'User', username: string }> };

export const GetUserDocument = `
    query getUser {
  allUsers {
    username
  }
}
    `;
export const useGetUserQuery = <
      TData = GetUserQuery,
      TError = unknown
    >(
      dataSource: { endpoint: string, fetchParams?: RequestInit },
      variables?: GetUserQueryVariables,
      options?: UseQueryOptions<GetUserQuery, TError, TData>
    ) =>
    useQuery<GetUserQuery, TError, TData>(
      variables === undefined ? ['getUser'] : ['getUser', variables],
      fetcher<GetUserQuery, GetUserQueryVariables>(dataSource.endpoint, dataSource.fetchParams || {}, GetUserDocument, variables),
      options
    );
export const AddUserDocument = `
    mutation addUser($userInput: UserInput!) {
  addUser(userInput: $userInput) {
    username
  }
}
    `;
export const useAddUserMutation = <
      TError = unknown,
      TContext = unknown
    >(
      dataSource: { endpoint: string, fetchParams?: RequestInit },
      options?: UseMutationOptions<AddUserMutation, TError, AddUserMutationVariables, TContext>
    ) =>
    useMutation<AddUserMutation, TError, AddUserMutationVariables, TContext>(
      ['addUser'],
      (variables?: AddUserMutationVariables) => fetcher<AddUserMutation, AddUserMutationVariables>(dataSource.endpoint, dataSource.fetchParams || {}, AddUserDocument, variables)(),
      options
    );
export const SubUserDocument = `
    subscription subUser {
  allUsers {
    username
  }
}
    `;
synoptase commented 2 years ago

Do you have a working example of how a subscription can be done with the enhanceEndpoints() ?