postmanlabs / postman-app-support

Postman is an API platform for building and using APIs. Postman simplifies each step of the API lifecycle and streamlines collaboration so you can create better APIs—faster.
https://www.postman.com
5.83k stars 839 forks source link

Allow importing of GraphQL schemas using a URL #6719

Closed galvesribeiro closed 2 years ago

galvesribeiro commented 5 years ago

After the kind comment here and the thread being locked, I've decided to open this issue as I know other people is waiting for proper GraphQL support like myself.

Is your feature request related to a problem? Please describe.

  1. The current GraphQL support rely on people having to describe the schema on the API tabs but doesn't allow people to import the schema using the introspection endpoint, which is how everyone else does the schema import on their tools as the introspection endpoint was designed for that.
  2. The auto-complete/intellisense on the request using that "imported" schema, expect people to know before hand the fields or to be reading the schema elsewhere which beats the purpose of import the schema.

Describe the solution you'd like

  1. On the API tab, when adding a new API, click on "Add schema" would give you an option "Import from URL" which would take an endpoint URL to GraphQL so introspection can be used. In fact, it could expect any OpenAPI schema as well, but that is for another feature request.
  2. Whenever I press ctr/cmd+space, we want the list of fields for that given context. Just like any other tools have.

Additional context Check how Insomnia, GraphiQL or GraphQL Playground. They are enough to make postman customers happy. Simple and direct to the point.

ebonertz commented 5 years ago

Agreed! This would be hugely helpful. At a minimum supporting an Introspection Query Response in JSON format would be nice too. I don't have the SDL schema available to me. Any plans to add this functionality in the near future?

a85 commented 5 years ago

@ebonertz Yes. This feature is still in beta along with our APIs feature. We are gathering use cases from different users. In our head, the mental model is that the schema lives "somwhere" - the somewhere can be a repository, a server URL, or some package. Postman will treat these as sources and integrate with these sources to allow for loading the schema dynamically. GraphQL calls it "introspection" but it is the same idea across multiple schema driven flows that I have come across.

ebonertz commented 5 years ago

@a85 Any updates on this topic and when we may be able to load the schema dynamically through a url or introspection query?

talynone commented 5 years ago

Agreed! This would be hugely helpful. At a minimum supporting an Introspection Query Response in JSON format would be nice too. I don't have the SDL schema available to me. Any plans to add this functionality in the near future?

Just an FYI, I used the following to convert the JSON formatted response to SDL: https://www.npmjs.com/package/graphql-introspection-json-to-sdl

ebonertz commented 5 years ago

@talynone Thanks that worked perfectly! I was able to convert my json to SDL and then insert into my Postman API Schema

ebonertz commented 5 years ago

@a85 I have found a suitable work around but this would need to be manually updated each time the API is updated. Would still love to see Postman support introspection queries via url to update the schema instantly. Could you please let us know if this has been considered for implementation?

pbrink231 commented 4 years ago

I have been using insomnia for all graphql calls and postman for rest calls.

This is the main reason I use insomnia over postman. Having the schema autocomplete makes working with it very easily.

numToStr commented 4 years ago

Can we expect some info on this?

Absence of introspection preventing some code first Graphql developers. Building Graphql APIs with Postman will be great for the teams who use code first approach.

umeshp7 commented 4 years ago

As of 7.15 we have added support for collection generation from GraphQL schema. You can either use a GraphQL SDL or the introspection query result JSON and import it as a collection. This can also be done using the ‘Generate Collection’ button inside the API tab for GraphQL schemas.

Feel free to get back to us with suggestions and concerns regarding the same.

sebastienbarre commented 4 years ago

Could you please provide more details? Or quick walkthrough? Where would I put my GraphQL endpoint for Postman to generate the collection from? Thanks

umeshp7 commented 4 years ago

@sebastienbarre Hi. As I mentioned in the previous comment. For now you can only import using GraphQL SDL or Introspection query result JSON. This can be done using the IMPORT button on the top left corner. Here is an example using an SDL file: ezgif com-video-to-gif(1)

This can also be done using Paste Raw Text option in the import modal. We are working on getting support for importing through GraphQL endpoint/url as well.

ljdev1 commented 4 years ago

@umeshp7 - This is a great step closer, thank you! My feedback below...

You mentioned that we can import from the JSON result of an introspection query, however I could not get this to work. I tried both the "import from file" and the "paste raw text" options on the import screen. Instead of the Success toast, it said an Error occurred. Could you show us an example using the JSON result of an introspection query too?

I successfully imported using an SDL schema file, and this generated the collection fine. I noticed that it does not create it as an API, so that we can use that Schema as validation and autocomplete on other collections and requests. Obviously if we already have an SDL we can just paste it into a new API manually, however I was hoping by using the introspection JSON result, I would end up with both a collection and a valid Schema for validation, etc.

I also noticed the collection did not convert the SDL comments into Postman documentation (request descriptions, etc.). One of the things I still go to GraphiQL for is to search the schema documentation. Having searchable schema documentation available directly inside of the Postman IDE would be awesome!

Lastly, I just want to say, I LOVE Postman - lol.. seriously, I have been starting to use many of the features, and have items on my backlog that will make use of more, and its GREAT! Thank you to the whole team! :)

umeshp7 commented 4 years ago

@ljdev1 Thank you for the detailed feedback.

I am surprised to know that the JSON didn't work and the SDL did. One guess would be that when I said, the introspection result, I meant the value of the data key you get from the result. (Though in hindsight I realize this could also be handled from our end). Can you please try pasting the value present in the data key? If that still doesn't work, I would like to go into more detail of this and if you could send your introspection query result over to help@postman.com for us to solve the underlying issue. Or you could also file issues or add feature requests here: https://github.com/postmanlabs/graphql-to-postman/issues.

As far as the SDL comments are concerned - it's a great suggestion. I am opening an issue here: https://github.com/postmanlabs/graphql-to-postman/issues/4 for the community to add more inputs on it and for you to track its progress.

huehnerlady commented 4 years ago

Hi,

I would go further and say you should not have to add a schema, but when you click on "refreshschema" it looks into the URL you handed in and does the introspection.

For me it was exected behaviour and it took me a while to realize that I have to manually do something... 😞

jaruizsys commented 4 years ago

It is important to improve Postman around GraphQL functionality. Postman is a great tool but the lack on some functionality to support 100% GraphQL is avoiding to use as unique tool in my company.

Important features that need to be added:

I have been checking the Postman roadmap but nothing about mentioned above is there: https://trello.com/b/4N7PnHAz/postman-roadmap-for-developers

arlemi commented 4 years ago

Nevermind, wrong issue number on our side, this ask is a bit different.

We've just released v7.22 of the app which gives the ability to import GraphQL schemas as an API and to write GraphQL schemas in JSON!

sebastienbarre commented 4 years ago

If you are referring to the "Import" button on top, and "Import from Link", then no, it's not working when passing it the GraphQL endpoint in the new 7.22 (or Postman Canari). It says: "format not recognized". That same endpoint is recognized and introspected without issues by any GraphiQL app.

justtonytone commented 4 years ago

I've also tried to import our graphql schema from a link and pressing the Import button doesn't do anything on my end. If I update the url to an endpoint that returns the introspect object (or an invalid url just to test), I get an error of Error while importing: format not recognized, which makes sense.

justtonytone commented 4 years ago

@sebastienbarre my guess is that you are importing a url with the introspection json in a format that Postman does not yet recognize. According to this comment, we have to unwrap the data value ourselves: https://github.com/postmanlabs/postman-app-support/issues/6719#issuecomment-583872289

arlemi commented 4 years ago

Reopening since it looks like I had the wrong issue number, my bad! 😬 We'll keep you updated as we pick up this one.

ild0tt0re commented 4 years ago

@arlemi is this issue in done by mistake or has it been released since the last reopening? Thanks

arlemi commented 4 years ago

@ild0tt0re This hasn't yet been released, we'll update here when there's anything new!

pritesh93 commented 4 years ago

Another item that would be interesting is if the comments can also be pulled in, as they both support Markdown, it would make the experience cleaner. As well as allow a flow-through to consume Postman's Documentation features.

I don't know if this is another feature, but happy to explain in further detail!

Diluka commented 4 years ago

if it can autocomplete queries without creating APIs just using dynamic introspection on endpoints, if support, will be great! @umeshp7

drowhunter commented 4 years ago

to be clear, you shouldn't need to do anything special manually for postman to gather the schema, all post man has to do is run the following query the second you put the url in to your graphql endpoint.

I would expect a refresh schema button that when clicked would run this query again, as when i'm developing i am constantly changing the schema.

here is an example of the introspection query all grphql servers can use. I pulled it from GraphQL Playground

the result of the introspection against the public spotify graphql endpoint is at the bottom

https://spotify-graphql-server.herokuapp.com/graphql

query IntrospectionQuery {
      __schema {
        queryType {
          name
    }
    mutationType {
          name
    }
    subscriptionType {
          name
    }
    types {
          ...FullType
    }
    directives {
          name
      description
      locations
      args {
            ...InputValue
      }
    }
  }
}

fragment FullType on __Type {
      kind
  name
  description
  fields(includeDeprecated: true) {
        name
    description
    args {
          ...InputValue
    }
    type {
          ...TypeRef
    }
    isDeprecated
    deprecationReason
  }
  inputFields {
        ...InputValue
  }
  interfaces {
        ...TypeRef
  }
  enumValues(includeDeprecated: true) {
        name
    description
    isDeprecated
    deprecationReason
  }
  possibleTypes {
        ...TypeRef
  }
}

fragment InputValue on __InputValue {
      name
  description
  type {
        ...TypeRef
  }
  defaultValue
}

fragment TypeRef on __Type {
      kind
  name
  ofType {
        kind
    name
    ofType {
          kind
      name
      ofType {
            kind
        name
        ofType {
              kind
          name
          ofType {
                kind
            name
            ofType {
                  kind
              name
              ofType {
                    kind
                name
              }
            }
          }
        }
      }
    }
  }
}

Spotify public api schema result

{
  "data": {
    "__schema": {
      "queryType": {
        "name": "Query"
      },
      "mutationType": null,
      "subscriptionType": null,
      "types": [
        {
          "kind": "OBJECT",
          "name": "Query",
          "description": null,
          "fields": [
            {
              "name": "hi",
              "description": null,
              "args": [
                {
                  "name": "message",
                  "description": null,
                  "type": {
                    "kind": "SCALAR",
                    "name": "String",
                    "ofType": null
                  },
                  "defaultValue": "\"Hi\""
                }
              ],
              "type": {
                "kind": "SCALAR",
                "name": "String",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "queryArtists",
              "description": null,
              "args": [
                {
                  "name": "byName",
                  "description": null,
                  "type": {
                    "kind": "SCALAR",
                    "name": "String",
                    "ofType": null
                  },
                  "defaultValue": "\"Red Hot Chili Peppers\""
                }
              ],
              "type": {
                "kind": "LIST",
                "name": null,
                "ofType": {
                  "kind": "OBJECT",
                  "name": "Artist",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            }
          ],
          "inputFields": null,
          "interfaces": [],
          "enumValues": null,
          "possibleTypes": null
        },
        {
          "kind": "SCALAR",
          "name": "String",
          "description": "The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.",
          "fields": null,
          "inputFields": null,
          "interfaces": null,
          "enumValues": null,
          "possibleTypes": null
        },
        {
          "kind": "OBJECT",
          "name": "Artist",
          "description": null,
          "fields": [
            {
              "name": "name",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "String",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "id",
              "description": null,
              "args": [],
              "type": {
                "kind": "SCALAR",
                "name": "ID",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "image",
              "description": null,
              "args": [],
              "type": {
                "kind": "SCALAR",
                "name": "String",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "albums",
              "description": null,
              "args": [
                {
                  "name": "limit",
                  "description": null,
                  "type": {
                    "kind": "SCALAR",
                    "name": "Int",
                    "ofType": null
                  },
                  "defaultValue": "10"
                }
              ],
              "type": {
                "kind": "LIST",
                "name": null,
                "ofType": {
                  "kind": "OBJECT",
                  "name": "Album",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            }
          ],
          "inputFields": null,
          "interfaces": [],
          "enumValues": null,
          "possibleTypes": null
        },
        {
          "kind": "SCALAR",
          "name": "ID",
          "description": "The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `\"4\"`) or integer (such as `4`) input value will be accepted as an ID.",
          "fields": null,
          "inputFields": null,
          "interfaces": null,
          "enumValues": null,
          "possibleTypes": null
        },
        {
          "kind": "SCALAR",
          "name": "Int",
          "description": "The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1. ",
          "fields": null,
          "inputFields": null,
          "interfaces": null,
          "enumValues": null,
          "possibleTypes": null
        },
        {
          "kind": "OBJECT",
          "name": "Album",
          "description": null,
          "fields": [
            {
              "name": "name",
              "description": null,
              "args": [],
              "type": {
                "kind": "SCALAR",
                "name": "String",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "id",
              "description": null,
              "args": [],
              "type": {
                "kind": "SCALAR",
                "name": "ID",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "image",
              "description": null,
              "args": [],
              "type": {
                "kind": "SCALAR",
                "name": "String",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "tracks",
              "description": null,
              "args": [],
              "type": {
                "kind": "LIST",
                "name": null,
                "ofType": {
                  "kind": "OBJECT",
                  "name": "Track",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            }
          ],
          "inputFields": null,
          "interfaces": [],
          "enumValues": null,
          "possibleTypes": null
        },
        {
          "kind": "OBJECT",
          "name": "Track",
          "description": null,
          "fields": [
            {
              "name": "name",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "String",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "artists",
              "description": null,
              "args": [],
              "type": {
                "kind": "LIST",
                "name": null,
                "ofType": {
                  "kind": "OBJECT",
                  "name": "Artist",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "preview_url",
              "description": null,
              "args": [],
              "type": {
                "kind": "SCALAR",
                "name": "String",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "id",
              "description": null,
              "args": [],
              "type": {
                "kind": "SCALAR",
                "name": "ID",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            }
          ],
          "inputFields": null,
          "interfaces": [],
          "enumValues": null,
          "possibleTypes": null
        },
        {
          "kind": "OBJECT",
          "name": "__Schema",
          "description": "A GraphQL Schema defines the capabilities of a GraphQL server. It exposes all available types and directives on the server, as well as the entry points for query, mutation, and subscription operations.",
          "fields": [
            {
              "name": "types",
              "description": "A list of all types supported by this server.",
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "LIST",
                  "name": null,
                  "ofType": {
                    "kind": "NON_NULL",
                    "name": null,
                    "ofType": {
                      "kind": "OBJECT",
                      "name": "__Type",
                      "ofType": null
                    }
                  }
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "queryType",
              "description": "The type that query operations will be rooted at.",
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "OBJECT",
                  "name": "__Type",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "mutationType",
              "description": "If this server supports mutation, the type that mutation operations will be rooted at.",
              "args": [],
              "type": {
                "kind": "OBJECT",
                "name": "__Type",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "subscriptionType",
              "description": "If this server support subscription, the type that subscription operations will be rooted at.",
              "args": [],
              "type": {
                "kind": "OBJECT",
                "name": "__Type",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "directives",
              "description": "A list of all directives supported by this server.",
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "LIST",
                  "name": null,
                  "ofType": {
                    "kind": "NON_NULL",
                    "name": null,
                    "ofType": {
                      "kind": "OBJECT",
                      "name": "__Directive",
                      "ofType": null
                    }
                  }
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            }
          ],
          "inputFields": null,
          "interfaces": [],
          "enumValues": null,
          "possibleTypes": null
        },
        {
          "kind": "OBJECT",
          "name": "__Type",
          "description": "The fundamental unit of any GraphQL Schema is the type. There are many kinds of types in GraphQL as represented by the `__TypeKind` enum.\n\nDepending on the kind of a type, certain fields describe information about that type. Scalar types provide no information beyond a name and description, while Enum types provide their values. Object and Interface types provide the fields they describe. Abstract types, Union and Interface, provide the Object types possible at runtime. List and NonNull types compose other types.",
          "fields": [
            {
              "name": "kind",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "ENUM",
                  "name": "__TypeKind",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "name",
              "description": null,
              "args": [],
              "type": {
                "kind": "SCALAR",
                "name": "String",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "description",
              "description": null,
              "args": [],
              "type": {
                "kind": "SCALAR",
                "name": "String",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "fields",
              "description": null,
              "args": [
                {
                  "name": "includeDeprecated",
                  "description": null,
                  "type": {
                    "kind": "SCALAR",
                    "name": "Boolean",
                    "ofType": null
                  },
                  "defaultValue": "false"
                }
              ],
              "type": {
                "kind": "LIST",
                "name": null,
                "ofType": {
                  "kind": "NON_NULL",
                  "name": null,
                  "ofType": {
                    "kind": "OBJECT",
                    "name": "__Field",
                    "ofType": null
                  }
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "interfaces",
              "description": null,
              "args": [],
              "type": {
                "kind": "LIST",
                "name": null,
                "ofType": {
                  "kind": "NON_NULL",
                  "name": null,
                  "ofType": {
                    "kind": "OBJECT",
                    "name": "__Type",
                    "ofType": null
                  }
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "possibleTypes",
              "description": null,
              "args": [],
              "type": {
                "kind": "LIST",
                "name": null,
                "ofType": {
                  "kind": "NON_NULL",
                  "name": null,
                  "ofType": {
                    "kind": "OBJECT",
                    "name": "__Type",
                    "ofType": null
                  }
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "enumValues",
              "description": null,
              "args": [
                {
                  "name": "includeDeprecated",
                  "description": null,
                  "type": {
                    "kind": "SCALAR",
                    "name": "Boolean",
                    "ofType": null
                  },
                  "defaultValue": "false"
                }
              ],
              "type": {
                "kind": "LIST",
                "name": null,
                "ofType": {
                  "kind": "NON_NULL",
                  "name": null,
                  "ofType": {
                    "kind": "OBJECT",
                    "name": "__EnumValue",
                    "ofType": null
                  }
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "inputFields",
              "description": null,
              "args": [],
              "type": {
                "kind": "LIST",
                "name": null,
                "ofType": {
                  "kind": "NON_NULL",
                  "name": null,
                  "ofType": {
                    "kind": "OBJECT",
                    "name": "__InputValue",
                    "ofType": null
                  }
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "ofType",
              "description": null,
              "args": [],
              "type": {
                "kind": "OBJECT",
                "name": "__Type",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            }
          ],
          "inputFields": null,
          "interfaces": [],
          "enumValues": null,
          "possibleTypes": null
        },
        {
          "kind": "ENUM",
          "name": "__TypeKind",
          "description": "An enum describing what kind of type a given `__Type` is.",
          "fields": null,
          "inputFields": null,
          "interfaces": null,
          "enumValues": [
            {
              "name": "SCALAR",
              "description": "Indicates this type is a scalar.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "OBJECT",
              "description": "Indicates this type is an object. `fields` and `interfaces` are valid fields.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "INTERFACE",
              "description": "Indicates this type is an interface. `fields` and `possibleTypes` are valid fields.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "UNION",
              "description": "Indicates this type is a union. `possibleTypes` is a valid field.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "ENUM",
              "description": "Indicates this type is an enum. `enumValues` is a valid field.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "INPUT_OBJECT",
              "description": "Indicates this type is an input object. `inputFields` is a valid field.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "LIST",
              "description": "Indicates this type is a list. `ofType` is a valid field.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "NON_NULL",
              "description": "Indicates this type is a non-null. `ofType` is a valid field.",
              "isDeprecated": false,
              "deprecationReason": null
            }
          ],
          "possibleTypes": null
        },
        {
          "kind": "SCALAR",
          "name": "Boolean",
          "description": "The `Boolean` scalar type represents `true` or `false`.",
          "fields": null,
          "inputFields": null,
          "interfaces": null,
          "enumValues": null,
          "possibleTypes": null
        },
        {
          "kind": "OBJECT",
          "name": "__Field",
          "description": "Object and Interface types are described by a list of Fields, each of which has a name, potentially a list of arguments, and a return type.",
          "fields": [
            {
              "name": "name",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "String",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "description",
              "description": null,
              "args": [],
              "type": {
                "kind": "SCALAR",
                "name": "String",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "args",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "LIST",
                  "name": null,
                  "ofType": {
                    "kind": "NON_NULL",
                    "name": null,
                    "ofType": {
                      "kind": "OBJECT",
                      "name": "__InputValue",
                      "ofType": null
                    }
                  }
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "type",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "OBJECT",
                  "name": "__Type",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "isDeprecated",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "Boolean",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "deprecationReason",
              "description": null,
              "args": [],
              "type": {
                "kind": "SCALAR",
                "name": "String",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            }
          ],
          "inputFields": null,
          "interfaces": [],
          "enumValues": null,
          "possibleTypes": null
        },
        {
          "kind": "OBJECT",
          "name": "__InputValue",
          "description": "Arguments provided to Fields or Directives and the input fields of an InputObject are represented as Input Values which describe their type and optionally a default value.",
          "fields": [
            {
              "name": "name",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "String",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "description",
              "description": null,
              "args": [],
              "type": {
                "kind": "SCALAR",
                "name": "String",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "type",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "OBJECT",
                  "name": "__Type",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "defaultValue",
              "description": "A GraphQL-formatted string representing the default value for this input value.",
              "args": [],
              "type": {
                "kind": "SCALAR",
                "name": "String",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            }
          ],
          "inputFields": null,
          "interfaces": [],
          "enumValues": null,
          "possibleTypes": null
        },
        {
          "kind": "OBJECT",
          "name": "__EnumValue",
          "description": "One possible value for a given Enum. Enum values are unique values, not a placeholder for a string or numeric value. However an Enum value is returned in a JSON response as a string.",
          "fields": [
            {
              "name": "name",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "String",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "description",
              "description": null,
              "args": [],
              "type": {
                "kind": "SCALAR",
                "name": "String",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "isDeprecated",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "Boolean",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "deprecationReason",
              "description": null,
              "args": [],
              "type": {
                "kind": "SCALAR",
                "name": "String",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            }
          ],
          "inputFields": null,
          "interfaces": [],
          "enumValues": null,
          "possibleTypes": null
        },
        {
          "kind": "OBJECT",
          "name": "__Directive",
          "description": "A Directive provides a way to describe alternate runtime execution and type validation behavior in a GraphQL document.\n\nIn some cases, you need to provide options to alter GraphQL's execution behavior in ways field arguments will not suffice, such as conditionally including or skipping a field. Directives provide this by describing additional information to the executor.",
          "fields": [
            {
              "name": "name",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "String",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "description",
              "description": null,
              "args": [],
              "type": {
                "kind": "SCALAR",
                "name": "String",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "locations",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "LIST",
                  "name": null,
                  "ofType": {
                    "kind": "NON_NULL",
                    "name": null,
                    "ofType": {
                      "kind": "ENUM",
                      "name": "__DirectiveLocation",
                      "ofType": null
                    }
                  }
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "args",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "LIST",
                  "name": null,
                  "ofType": {
                    "kind": "NON_NULL",
                    "name": null,
                    "ofType": {
                      "kind": "OBJECT",
                      "name": "__InputValue",
                      "ofType": null
                    }
                  }
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "onOperation",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "Boolean",
                  "ofType": null
                }
              },
              "isDeprecated": true,
              "deprecationReason": "Use `locations`."
            },
            {
              "name": "onFragment",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "Boolean",
                  "ofType": null
                }
              },
              "isDeprecated": true,
              "deprecationReason": "Use `locations`."
            },
            {
              "name": "onField",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "Boolean",
                  "ofType": null
                }
              },
              "isDeprecated": true,
              "deprecationReason": "Use `locations`."
            }
          ],
          "inputFields": null,
          "interfaces": [],
          "enumValues": null,
          "possibleTypes": null
        },
        {
          "kind": "ENUM",
          "name": "__DirectiveLocation",
          "description": "A Directive can be adjacent to many parts of the GraphQL language, a __DirectiveLocation describes one such possible adjacencies.",
          "fields": null,
          "inputFields": null,
          "interfaces": null,
          "enumValues": [
            {
              "name": "QUERY",
              "description": "Location adjacent to a query operation.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "MUTATION",
              "description": "Location adjacent to a mutation operation.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "SUBSCRIPTION",
              "description": "Location adjacent to a subscription operation.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "FIELD",
              "description": "Location adjacent to a field.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "FRAGMENT_DEFINITION",
              "description": "Location adjacent to a fragment definition.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "FRAGMENT_SPREAD",
              "description": "Location adjacent to a fragment spread.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "INLINE_FRAGMENT",
              "description": "Location adjacent to an inline fragment.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "SCHEMA",
              "description": "Location adjacent to a schema definition.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "SCALAR",
              "description": "Location adjacent to a scalar definition.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "OBJECT",
              "description": "Location adjacent to an object type definition.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "FIELD_DEFINITION",
              "description": "Location adjacent to a field definition.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "ARGUMENT_DEFINITION",
              "description": "Location adjacent to an argument definition.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "INTERFACE",
              "description": "Location adjacent to an interface definition.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "UNION",
              "description": "Location adjacent to a union definition.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "ENUM",
              "description": "Location adjacent to an enum definition.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "ENUM_VALUE",
              "description": "Location adjacent to an enum value definition.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "INPUT_OBJECT",
              "description": "Location adjacent to an input object type definition.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "INPUT_FIELD_DEFINITION",
              "description": "Location adjacent to an input object field definition.",
              "isDeprecated": false,
              "deprecationReason": null
            }
          ],
          "possibleTypes": null
        }
      ],
      "directives": [
        {
          "name": "skip",
          "description": "Directs the executor to skip this field or fragment when the `if` argument is true.",
          "locations": [
            "FIELD",
            "FRAGMENT_SPREAD",
            "INLINE_FRAGMENT"
          ],
          "args": [
            {
              "name": "if",
              "description": "Skipped when true.",
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "Boolean",
                  "ofType": null
                }
              },
              "defaultValue": null
            }
          ]
        },
        {
          "name": "include",
          "description": "Directs the executor to include this field or fragment only when the `if` argument is true.",
          "locations": [
            "FIELD",
            "FRAGMENT_SPREAD",
            "INLINE_FRAGMENT"
          ],
          "args": [
            {
              "name": "if",
              "description": "Included when true.",
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "Boolean",
                  "ofType": null
                }
              },
              "defaultValue": null
            }
          ]
        },
        {
          "name": "deprecated",
          "description": "Marks an element of a GraphQL schema as no longer supported.",
          "locations": [
            "FIELD_DEFINITION",
            "ENUM_VALUE"
          ],
          "args": [
            {
              "name": "reason",
              "description": "Explains why this element was deprecated, usually also including a suggestion for how to access supported similar data. Formatted in [Markdown](https://daringfireball.net/projects/markdown/).",
              "type": {
                "kind": "SCALAR",
                "name": "String",
                "ofType": null
              },
              "defaultValue": "\"No longer supported\""
            }
          ]
        }
      ]
    }
  }
}
bitcoder commented 4 years ago

this is a must for working with GraphQL. GraphQL is introspective as mentioned above, so there is no need for actual configuration IMO.

eladcandroid commented 4 years ago

Any news about getting the GraphQL scheme using url endpoint?

John0x commented 4 years ago

This is actually the only reason why I'm not using Postman for GraphQL and therefore not at all right now :/ Same goes for a lot of my colleagues

umeshp7 commented 4 years ago

@eladcandroid @drowhunter @John0x

You can import a GraphQL schema using a URL which returns the JSON object of the schema, but currently it is only supported for unauthenticated URLs.

@drowhunter The Spotify Schema that you mentioned also imports successfully in Postman. 🎉 @justtonytone Could you try again importing via the endpoint you created it should work now. 🎉

John0x commented 4 years ago

Will it be possible to fetch the schema automatically like almost all graphql clients do? Fetch the schema once you've entered the url (without having to create an api in postman)

jayShopTO commented 4 years ago

Hi, any news on having the schema fetch automatically? It would greatly benefit a lot of Shopify app devs.

extjbhlego commented 3 years ago

This feature should include support for adding auth headers for the introspection query 👍

illambo commented 3 years ago

Hi! Any news about that ? Currently the feature "Connect Repository" it only allows integration with github and not with any remote url (Postman for Mac - Version 7.35.0)

pm
illambo commented 3 years ago

@umeshp7 about

You can import a GraphQL schema using a URL which returns the JSON object of the schema, but currently it is only supported for unauthenticated URLs.

how u can do that ? thanks!

umeshp7 commented 3 years ago

@illambo As described in this comment, you can click on the IMPORT button on the top left corner of the Postman App,

Screenshot 2020-11-03 at 8 25 07 PM

a modal will open up after that you can go to the Link tab and paste the URL and Continue.

Screenshot 2020-11-03 at 8 28 02 PM

Visit -> https://learning.postman.com/docs/getting-started/importing-and-exporting-data For more info

illambo commented 3 years ago

Thanks for the clarification, this however does not allow to keep the scheme in sync with response url.

Continuing the import anyway as per your info it imports queries and mutations correctly but the autocomplete assistance does not work

pm2

how can i verify the problem? Do you have any suggestions? Thanks

EDIT: It workd with sdl but not with json schema introspection

aradalvand commented 3 years ago

This is strange. I can't believe Postman STILL doesn't have this feature. This has put me off for months and made me have to use Insomnia instead.

When will this be done approximately?

hobailey commented 3 years ago

I know it's not the same feature, but as a workaround I've used the other option available and connected to our Github repo and that allows the schema to stay in sync and it works 👌

cglacet commented 3 years ago

@hobailey not everyone has a schema available, for example if the schema is generated dynamically then using an endpoint on the server to retrieve the schema looks like a solution that would suit anyone (that's the good part of having a standard 😄).

jeromemeichelbeck commented 3 years ago

I mean... this is the basics of GraphQL: schema introspection. How can this issue be opened for this long?

aradalvand commented 3 years ago

It's almost embarrassing to still ask for this in 2021... Such a basic feature... Yet still missing...

devaldana commented 3 years ago

I had to switch to Insomnia as it has incredible GraphQL schema introspection at the same time that offer documentation for the introspected schema. Probably you want to give it a try.

jeromemeichelbeck commented 3 years ago

I had to switch to Insomnia as it has incredible GraphQL schema introspection at the same time that offer documentation for the introspected schema. Probably you want to give it a try.

That's actually what I did. Won't go back :)

bernardoflynn commented 3 years ago

A suggestion for anyone reading this far to find out what's happening with this request - just switch to Insomnia. It took all of 2 mins to export all my collections from Postman and import into Insomnia and then Insomnia gets the schema very easily.

cyberhck commented 3 years ago

yep, just switched to insomnia today at our company as well :slightly_smiling_face:

also, another thing you can do is just use graphiql, the only thing we had issues with is the authorization token, I guess? I just used mod header plugin for basic query, and insomnia for complex query if you need something specific.

ImLuze commented 3 years ago

This issue is on "pending triage" on the API Specifications and Code Generation project, but on "Done" on the API Platform triage project. Is there anywhere else where we can track the progress/roadmap for this issue?

arlemi commented 3 years ago

@ImLuze That's my bad, I closed this issue by mistake a year ago and the automation moved it to Done, I've reverted it. This issue is the best place to get updates when we release it. 🙂

newhouse commented 3 years ago

@arlemi you guys are not open source, are you? I'd submit a PR to add this if you were...

arlemi commented 3 years ago

@newhouse The Postman Runtime and some other parts of the app (code generators, collection format, collection SDK...) are open source, but the source code of the app isn't. You can learn more about it on our Open Philosophy page: https://www.postman.com/company/open-philosophy/

astanciu commented 3 years ago

@arlemi or anyone else on the team, can you provide any clarity on why this has taken so long and is still open? It's very clear that Postman is behind on this, you have customers switching to competitor products, and the ask is for something that is considered table stakes in every other graphql tool. What's going on here?

Some of us really hate the Insomnia UI and are stubbornly sticking with Postman.

At this point, we're close to 2 years on this issue. Will Postman support this? Is there an ETA?