graphqlgen icon indicating copy to clipboard operation
graphqlgen copied to clipboard

Automatically generate missing model definitions

Open sapkra opened this issue 7 years ago • 12 comments

Description

I got some problems with missing types & had to fixed them by defining them by myself. I think an easier solution would be to genereate them automatically from the types defined in schema.graphql

Additional context

More information in my old ticket #163.

sapkra avatar Oct 21 '18 22:10 sapkra

Could you provide some more clarifying information please:

  1. When you're saying "missing types": Are you referring to missing model definitions?
  2. The current workflow for missing models is to print a suggestion in the CLI output. Are you aware of this behavior? Where would you suggest the missing models should be generated to?

schickling avatar Oct 22 '18 06:10 schickling

Yeah I mean exactly that what is generated in the CLI. And you were right, I was not aware of this behavior.

First of all user should not be an any I think.

schema.graphql

type AuthPayload {
  token: String!
  user: User!
}

Generated model

export interface AuthPayload {
  token: string
  user: any
}

My suggestion would be to just put them into the generated/graphqlgen.ts so that you also don't need to import them anymore. But yeah it's definitely a design decision which depends on your vision of this project.

sapkra avatar Oct 22 '18 13:10 sapkra

I agree with @sapkra that definining the AuthPayload in types.ts and refers to it in graphqlgen.yml to have finally import { AuthPayload } from "../types"; in generated/graphqlgen.ts could be replaced by just having graphqlgen looking for "extra" models in schema.graphql which have not been referenced in graphqlgen.yml and do it by itself.

I mean actually if you forget to do it yourself, graphqlgen tells you "put this in your types.ts". So it's only about copying what graphqlgen already outputs inside generated/graphqlgen.ts instead of importing it from ../types

I think there is a way to make

# src/schema.graphql
type AuthPayload {
  token: String!
  user: User!
}

generated into

// src/generated/graphqlgen.ts
export interface AuthPayload {
  token: string
  user: UserNode
}

Then all already generated references to AuthPayloadinside graphqlgen.ts should work as the old behavior, but withtout needs to do extra stuff in both graphqlgen.yml & types.ts.

I'm not sure about the UserNode, but it shouldn't be any as @sapkra suggested.

kevinmarrec avatar Oct 24 '18 09:10 kevinmarrec

@schickling Issue was referenced in #237 but I didn't clearly understand how is it related, and is there any thoughts about what me and @sapkra wrote ?

kevinmarrec avatar Nov 05 '18 16:11 kevinmarrec

because of this comment: https://github.com/prisma/graphqlgen/pull/237#issuecomment-435536587

sapkra avatar Nov 05 '18 20:11 sapkra

@schickling Any updates on this ?

Without automatically generating these models It's gonna be a pain for big projects to maintain both the Schema schema.graphql AND their respectives model definitions in a types.ts.

Exemple :

Auto generate

type Test {
  a: String
  b: String!
  c: Int
  d: Int!
}

into

export interface Test {
  a?: string
  b: string
  c?: number
  c: number
}

If it's not auto-generated, graphqlgen is requesting the user to copy/paste from the CLI output, so why graphqlgen can't handle the whole cycle by itself if he already know what code it wants ?

As @sapkra already suggested =>

  1. Improve these model auto-generations (cases where is should not be any type & handle optional fields).
  2. graphqlgen could/should put these generated models around generated/graphqlgen.ts instead of importing them from types.ts (which IMO will be a pain to maintain on big projects). The thing is just about removing the "extra step" of copy/pasting, letting graphqlgen do the job and not having a types.ts to maintain each time the schema changes.

kevinmarrec avatar Nov 22 '18 15:11 kevinmarrec

I would also like to have the types being auto generated, I don't see a point in having to maintain those manually.

For example, I've been experimenting with using graphql-code-generator to generate the types by doing an introspection query of the schema, then run graphqlgen to generate the types for resolvers etc.

emmenko avatar Nov 24 '18 12:11 emmenko

I have literally the exact same use case, would be nice if this could be auto-generated

vjsingh avatar Nov 27 '18 18:11 vjsingh

@schickling Any thoughts ?

kevinmarrec avatar Dec 10 '18 21:12 kevinmarrec

Is the Payload pattern not used by the Prisma team? I'm curious about how they structure input and output types for their mutations. The idea here is to create objects for all inputs and outputs which makes them more maintainable in the future, since clients do not need to worry about getting all the arguments in their correct order, and it seems easier to maintain backward compatibility? There is a medium article somewhere about it...

There is quite a lot of boilerplate currently for this pattern as seen below.

Is the recommendation simply not to use this pattern? Or is there another way of simplifying?

@nikolasburk @divyenduz any thoughts?

schema.graphql: (ideally this would be all you need to write?)

addNote(input: AddNoteInput!): AddNotePayload!
input AddNoteInput {
  note: String!
  ...
}
type AddNotePayload {
  result: String
}

types.ts:

export interface AddNotePayload {
  result: string | null;
}

resolvers/AddNotePayload.ts:

import { AddNotePayloadResolvers } from '../generated/graphqlgen';

export const AddNotePayload: AddNotePayloadResolvers.Type = {
  ...AddNotePayloadResolvers.defaultResolvers,
};

resolvers/index.ts:

import { AddNotePayload } from './AddNotePayload';

export const resolvers: Resolvers = {
  ...
  AddNotePayload,

vjsingh avatar Jan 08 '19 15:01 vjsingh

I think the use for auto generated models really depends on the project. For example; I created a GraphQL gateway where the data being fetched from upstream servers doesn't really match with the GraphQL fields. So I would have no use for autogenerated models, because the models should be based on the shape of the upstream data. For the same reason I have no use for the generated defaultResolvers, hence why I opened an issue to be able to disable generation of them; #350. That said, I'm not against autogenerating models, but it should be an option, not a default.

koenpunt avatar Jan 09 '19 22:01 koenpunt

Need to decide:

  1. which folder/file are model types generated into?

    Good start might be (roughly copying resolver types output file config):

    models:
      output: ./source/generated/models.ts
    
  2. how are generated models merged with manually-created ones?

    • If a developer writes a same-named model, then don't generate one?
    • Or, if a developer writes a same-named model, then merge them via declaration merging? This would require users to write interface Foo { ... } instead of type Foo { ... }
    • allow developers to import the generated model types allowing them full control
  3. how are relations generated?

    For example (https://github.com/prisma/graphqlgen/issues/448):

    type Post {
        id: ID!
        title: String!
        content: String!
        comments: [Comment!]
        user: User!
    }
    
    export interface Post {
        id: string;
        title: string;
        content: string;
    
        // ???
        comments: string[] // comment IDs that other resolvers will fetch data for
        user: string // user ID that another resolver will fetch data for
    }
    

jasonkuhrt avatar Feb 12 '19 04:02 jasonkuhrt