Skip to content
This repository was archived by the owner on Dec 8, 2021. It is now read-only.

Automatically generate missing model definitions #181

Open
sapkra opened this issue Oct 21, 2018 · 12 comments
Open

Automatically generate missing model definitions #181

sapkra opened this issue Oct 21, 2018 · 12 comments

Comments

@sapkra
Copy link

sapkra commented Oct 21, 2018

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.

@schickling
Copy link
Contributor

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 schickling changed the title Generate TypeScript types from types defined in schema.graphql Automatically generate missing model definitions Oct 22, 2018
@sapkra
Copy link
Author

sapkra commented Oct 22, 2018

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.

@kevinmarrec
Copy link

kevinmarrec commented Oct 24, 2018

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
Copy link

kevinmarrec commented Nov 5, 2018

@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 ?

@sapkra
Copy link
Author

sapkra commented Nov 5, 2018

because of this comment: #237 (comment)

@kevinmarrec
Copy link

kevinmarrec commented Nov 22, 2018

@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.

@emmenko
Copy link

emmenko commented Nov 24, 2018

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.

@vjsingh
Copy link

vjsingh commented Nov 27, 2018

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

@kevinmarrec
Copy link

@schickling Any thoughts ?

@vjsingh
Copy link

vjsingh commented Jan 8, 2019

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,

@koenpunt
Copy link
Contributor

koenpunt commented Jan 9, 2019

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.

@jasonkuhrt
Copy link
Member

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 (Missing custom types properties in suggested model types. #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
    }

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

7 participants