escape-technologies / graphman Goto Github PK
View Code? Open in Web Editor NEWQuikly scaffold a postman collection for a GraphQL API. Compatible with Postman & Insomnia.
License: MIT License
Quikly scaffold a postman collection for a GraphQL API. Compatible with Postman & Insomnia.
License: MIT License
When I import collection generated by Graphman v1.2.0 to Postman (version 10.8.0 and version 9.31.0) it fails with error message Error while importing: format not recognized
Beginning of generated collection:
{
"postmanCollection": {
"info": {
"name": "rori-editor.backend.doeg8.praha.tmapy.cz-GraphMan",
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
},
"item": [
{
"name": "Queries",
"item": [
{
"name": "mapApp",
"request": {
"method": "POST",
"header": [],
"body": {
"mode": "graphql",
"graphql": {
"query": "query mapApp($id: GlobalID!) {\n mapApp(id: $id) {\n __typename\n id\n slug\n title\n }\n}",
"variables": "{\n\t\"id\": null\n}"
}
},
...
Any hint how to fix it?
I get this error when running the command:
error: Uncaught (in promise) Error: Query type not found
if (!queryType) throw new Error("Query type not found");
^
at createPostmanCollection (https://raw.githubusercontent.com/Escape-Technologies/graphman/main/src/lib.ts:296:25)
at async https://raw.githubusercontent.com/Escape-Technologies/graphman/main/src/index.ts:23:20
Maybe it is because the type of my query is called "MyAppQuery" instead of "Query"? (same thing for mutations).
This is allowed by the GraphQL spec.
In the introspection query this is indicated by this:
{
"_queryType": "MyAppQuery",
"_mutationType": "MyAppMutation"
...
}
Hello, since it's asked in the error message and I didn't find an issue already referencing this - running graphman on my schema returns this error:
error: Uncaught (in promise) Error: Kind INTERFACE for type <TheInterfaceName> is not supported yet. Please open an issue.
Here is an exemple with a public schema:
deno run https://deno.land/x/[email protected]/src/cli.ts https://swapi-graphql.netlify.app/.netlify/functions/index
Introduce a mode to "reverse" graphman:
graphman reverse <path_to_collection>
(temporary command name)#12 and #9 features, and basically any future optional parameter, should be passed through flags.
For instance:
--output <filename>
or -o <filename>
--bearer <token>
We must use cli.ts
instead of lib.ts
?
deno run https://deno.land/x/[email protected]/src/cli.ts http://localhost:5013/graphql
Getting an error
error: Uncaught (in promise) Error: Kind UNION for type WorkItem is not supported yet. Please open an issue.
Is this a known limitation at the moment or maybe I have something configured incorrectly?
Rather than querying the endpoint, graphman would take the introspection or schema as an input param.
When a GraphQL schema is converted to a collection, the queries and mutation are all placed under the default collection folder. Taking a glance at each collection request, you'll find it really hard to know which is a mutation or a query. You'll have to first open up individual requests to find out.
Separating mutations and queries into their respective folders(item groups) helps solve this easily and gives them a designated home in the collection.
GraphQL is a very declarative query language. It provides a declarative approach to data fetching. From the schema, you already know what kind of data to expect and you can choose to request just what you need.
Postman has something called postman scripts that can be used to write unit-like tests. Its assertion and test suite were built atop mocha and chai making it quite similar in usage to them.
Postman scripts can be written and run in the tests tab in Postman, which is a NodeJS runtime environment for collections.
Because of the declarative nature of GraphQL, it is possible to generate sample test cases for GraphQL APIs on postman collections. It doesn't have to be anything fancy, it could be just very basic data validation checks for s start.
I am not familiar with what Escape provides, but we could also have a few security test cases that are auto-generated and can be run on the fly.
Great tool 🔥🔥
Can you please dockerize it?
Deno has the capability to be exported as an npm package, which would allow GraphMan to be used as a node module (for now it's only programmatically usable from deno). See: https://deno.land/[email protected]/node/dnt & https://github.com/denoland/dnt . This needs a little reflection and testing to be done right, but it could be included in a CI at the end to build and deploy new versions when a new tag is added.
GraphMan should be able to take auth and headers as parameters.
Those parameters as well as URLs should be sent in the environment variables.
The process could be to load .env files to generate different environment, or via the CLI.
Currently, the format.ts
module is building the postman collection programmatically from scratch. However, Postman has an npm package: https://github.com/postmanlabs/postman-collection that provides an SDK for doing so.
I decided not to use it in the fireplace as deno support for npm packages was not a thing back then, but it has evolved a lot since then.
It would be interesting to use the SDK for cleaner code, reducing the code-base and future-proofing.
Edit: as of deno 1.26.x npm support is still unstable, I'll get onto this issue when I'm satisfied with this: denoland/deno#15960
I wanted to test just the example deno run https://deno.land/x/[email protected]/src/index.ts https://rickandmortyapi.com/graphql
before testing with my application and I immediately got the following error:
Check https://deno.land/x/[email protected]/src/index.ts
error: TS2322 [ERROR]: Type 'AliasName<K, A>' is not assignable to type 'string | number | symbol'.
Type 'K | (string extends A[K] ? K : A[K] extends string ? K | A[K] : K)' is not assignable to type 'string | number | symbol'.
Type 'string extends A[K] ? K : A[K] extends string ? K | A[K] : K' is not assignable to type 'string | number | symbol'.
Type 'K | (A[K] extends string ? K | A[K] : K)' is not assignable to type 'string | number | symbol'.
Type 'A[K] extends string ? K | A[K] : K' is not assignable to type 'string | number | symbol'.
Type 'K | A[K]' is not assignable to type 'string | number | symbol'.
Type 'A[K]' is not assignable to type 'string | number | symbol'.
Type 'A[string] | A[number] | A[symbol]' is not assignable to type 'string | number | symbol'.
Type 'A[K]' is not assignable to type 'symbol'.
Type 'A[string] | A[number] | A[symbol]' is not assignable to type 'symbol'.
Type 'A[string]' is not assignable to type 'symbol'.
Type 'A[K] extends string ? K | A[K] : K' is not assignable to type 'symbol'.
Type 'K | A[K]' is not assignable to type 'symbol'.
Type 'keyof A & K' is not assignable to type 'symbol'.
Type 'string extends A[K] ? K : A[K] extends string ? K | A[K] : K' is not assignable to type 'symbol'.
Type 'K | (A[K] extends string ? K | A[K] : K)' is not assignable to type 'symbol'.
Type 'keyof A & K' is not assignable to type 'symbol'.
Type 'AliasName<keyof T, A>' is not assignable to type 'string | number | symbol'.
Type 'keyof T | (string extends A[keyof A & keyof T] ? keyof A & keyof T : A[keyof A & keyof T] extends string ? (keyof A & keyof T) | A[keyof A & keyof T] : keyof A & keyof T)' is not assignable to type 'string | number | symbol'.
Type 'string extends A[keyof A & keyof T] ? keyof A & keyof T : A[keyof A & keyof T] extends string ? (keyof A & keyof T) | A[keyof A & keyof T] : keyof A & keyof T' is not assignable to type 'string | number | symbol'.
Type '(keyof A & keyof T) | (A[keyof A & keyof T] extends string ? (keyof A & keyof T) | A[keyof A & keyof T] : keyof A & keyof T)' is not assignable to type 'string | number | symbol'.
Type 'A[keyof A & keyof T] extends string ? (keyof A & keyof T) | A[keyof A & keyof T] : keyof A & keyof T' is not assignable to type 'string | number | symbol'.
Type '(keyof A & keyof T) | A[keyof A & keyof T]' is not assignable to type 'string | number | symbol'.
Type 'A[keyof A & keyof T]' is not assignable to type 'string | number | symbol'.
Type 'A[string] | A[number] | A[symbol]' is not assignable to type 'string | number | symbol'.
Type 'A[string]' is not assignable to type 'string | number | symbol'.
Type 'A[string]' is not assignable to type 'symbol'.
Type 'A[keyof A & keyof T]' is not assignable to type 'symbol'.
Type 'A[string] | A[number] | A[symbol]' is not assignable to type 'symbol'.
Type 'A[string]' is not assignable to type 'symbol'.
Type 'A[keyof A & keyof T] extends string ? (keyof A & keyof T) | A[keyof A & keyof T] : keyof A & keyof T' is not assignable to type 'symbol'.
Type '(keyof A & keyof T) | A[keyof A & keyof T]' is not assignable to type 'symbol'.
Type 'keyof A & keyof T' is not assignable to type 'symbol'.
Type 'string extends A[keyof A & keyof T] ? keyof A & keyof T : A[keyof A & keyof T] extends string ? (keyof A & keyof T) | A[keyof A & keyof T] : keyof A & keyof T' is not assignable to type 'symbol'.
Type '(keyof A & keyof T) | (A[keyof A & keyof T] extends string ? (keyof A & keyof T) | A[keyof A & keyof T] : keyof A & keyof T)' is not assignable to type 'symbol'.
Type 'keyof A & keyof T' is not assignable to type 'symbol'.
Type 'AliasName<string, A> | AliasName<number, A> | AliasName<symbol, A>' is not assignable to type 'string | number | symbol'.
Type 'AliasName<string, A>' is not assignable to type 'string | number | symbol'.
Type 'string | (string extends A[keyof A & string] ? keyof A & string : A[keyof A & string] extends string ? (keyof A & string) | A[keyof A & string] : keyof A & string)' is not assignable to type 'string | number | symbol'.
Type 'string extends A[keyof A & string] ? keyof A & string : A[keyof A & string] extends string ? (keyof A & string) | A[keyof A & string] : keyof A & string' is not assignable to type 'string | number | symbol'.
Type '(keyof A & string) | (A[keyof A & string] extends string ? (keyof A & string) | A[keyof A & string] : keyof A & string)' is not assignable to type 'string | number | symbol'.
Type 'A[keyof A & string] extends string ? (keyof A & string) | A[keyof A & string] : keyof A & string' is not assignable to type 'string | number | symbol'.
Type '(keyof A & string) | A[keyof A & string]' is not assignable to type 'string | number | symbol'.
Type 'A[keyof A & string]' is not assignable to type 'string | number | symbol'.
Type 'A[string]' is not assignable to type 'string | number | symbol'.
Type 'A[string]' is not assignable to type 'symbol'.
Type 'A[keyof A & string]' is not assignable to type 'symbol'.
Type 'A[string]' is not assignable to type 'symbol'.
Type 'A[keyof A & string] extends string ? (keyof A & string) | A[keyof A & string] : keyof A & string' is not assignable to type 'symbol'.
Type '(keyof A & string) | A[keyof A & string]' is not assignable to type 'symbol'.
Type 'keyof A & string' is not assignable to type 'symbol'.
Type 'string extends A[keyof A & string] ? keyof A & string : A[keyof A & string] extends string ? (keyof A & string) | A[keyof A & string] : keyof A & string' is not assignable to type 'symbol'.
Type '(keyof A & string) | (A[keyof A & string] extends string ? (keyof A & string) | A[keyof A & string] : keyof A & string)' is not assignable to type 'symbol'.
Type 'keyof A & string' is not assignable to type 'symbol'.
Type 'AliasName<string, A>' is not assignable to type 'symbol'.
Type 'AliasName<keyof T, A>' is not assignable to type 'symbol'.
Type 'AliasName<K, A>' is not assignable to type 'symbol'.
Type 'K | (string extends A[K] ? K : A[K] extends string ? K | A[K] : K)' is not assignable to type 'symbol'.
Type 'K' is not assignable to type 'symbol'.
Type 'keyof T' is not assignable to type 'symbol'.
Type 'AliasName<keyof T, A>' is not assignable to type 'symbol'.
Type 'keyof T | (string extends A[keyof A & keyof T] ? keyof A & keyof T : A[keyof A & keyof T] extends string ? (keyof A & keyof T) | A[keyof A & keyof T] : keyof A & keyof T)' is not assignable to type 'symbol'.
Type 'keyof T' is not assignable to type 'symbol'.
Type 'string | number | symbol' is not assignable to type 'symbol'.
Type 'string' is not assignable to type 'symbol'.
Type 'AliasName<string, A> | AliasName<number, A> | AliasName<symbol, A>' is not assignable to type 'symbol'.
Type 'AliasName<string, A>' is not assignable to type 'symbol'.
Type 'string | (string extends A[keyof A & string] ? keyof A & string : A[keyof A & string] extends string ? (keyof A & string) | A[keyof A & string] : keyof A & string)' is not assignable to type 'symbol'.
Type 'string' is not assignable to type 'symbol'.
> = { [K in keyof T as AliasName<K, A>]: T[K] };
~~~~~~~~~~~~~~~
at https://deno.land/[email protected]/flags/mod.ts:72:24
GraphQL provides us with the option to include descriptions in our schema. Descriptions can be field or list descriptions. Tools like GraphiQL use these descriptions in the generated documentation for any GraphQL schema.
These same behaviors can be replicated in collections as well. It helps the consumer of that collection with additional with some additional context.
Add the "reverse" feature. After completing your collection in your API client, you export it and generate a query file out of it.
Hello, graphman worked with my local backend, nice <3
I tried to do that
# create a new token
$ open https://github.com/settings/tokens/new
$ export GITHUB_TOKEN="xxxxxxxx"
# works for me
$ curl -H "Authorization: bearer $GITHUB_TOKEN" https://api.github.com/graphql
$ alias graphman="deno run https://deno.land/x/[email protected]/src/index.ts"
$ graphman https://api.github.com/graphql --auth="bearer $GTHUB_TOKEN"
Creating the postman collection for https://api.github.com/graphql
⚠️ ️Deno requests net access to "api.github.com". Run again with --allow-net to bypass this prompt.
Allow? [y/n (y = yes allow, n = no deny)] y
error: Uncaught (in promise) TypeError: Cannot read properties of undefined (reading '__schema')
const queryTypeName = introspectionQuery.__schema.queryType
^
at createPostmanCollection (https://deno.land/x/[email protected]/src/lib.ts:308:44)
at async https://deno.land/x/[email protected]/src/index.ts:38:20
Reference: https://docs.github.com/en/graphql/guides/forming-calls-with-graphql#communicating-with-graphql
EDIT:
The actual issue is the lack of a good error message when the http call fails
As it turns out it was a typo (thanks for the comments)
$ graphman https://api.github.com/graphql --auth="bearer $GITHUB_TOKEN"
Collection saved at ./out/api.github.com-GraphMan.postman_collection.json
Import it in postman and complete the queries ! 🚀
Variables defaults will allow queries to be valid out of the box in most cases and will complete the full support of Insomnia.
Bonjour,
I heard from graphman at https://dev.to/tristankalos/graphman-generate-a-postman-collection-for-any-graphql-endpoint-4hff
Your tool seems like something that is totally needed.
GrapphQL being a standard, I feel like it should nothing in it is specific to Postman no ?
Apart from the very last step where you store the queries in the Postman collection format.
I use https://insomnia.rest/ and the GraphQL plugin for IntelliJ
If you have an option to write the queries simply in a plain folder with plain some-query.graphql
files, I would totally use it.
error: Uncaught (in promise) NotFound: No such file or directory (os error 2), open 'out/rickandmortyapi.com-GraphMan.postman_collection.json'
Deno.writeTextFileSync(path, JSON.stringify(json, null, "\t"));
^
at Object.opSync (deno:core/01_core.js:172:12)
at writeFileSync (deno:runtime/js/40_write_file.js:14:10)
at Object.writeTextFileSync (deno:runtime/js/40_write_file.js:61:12)
at saveJsonFormatted (https://deno.land/x/[email protected]/src/lib.ts:61:8)
at https://deno.land/x/[email protected]/src/index.ts:40:1
Hello, I saw that this issue was closed a few days ago (#30) however when I run graphman, everything is still being placed under the queries folder.
I tried it with other APIs, such as this one: https://graphql-compose.herokuapp.com/northwind/
The end result is something similar to the below, as can be seen, it has mutations but it is stored under the queries array.
As a separate question (not sure where to ask / apologies if it should be a separate issue). Is there a way to organize the apis into named collections? i.e. authentication, checkout etc?
Accepting the output filename as a param.
Separate the lib.ts
file so that it's easier to understand & upgrade GraphMan.
Strings formatting, parsing, and output should be in separated modules.
GraphQL is a very declarative query language. It provides a declarative approach to data fetching. From the schema, you already know what kind of data to expect and you can choose to request just what you need.
We can leverage the declarative nature of GraphQL and generate mock response data that can be included in the generated collection. Having responses pre-generated in a collection means consumers of that collection can create mock servers for that API by just clicking a few buttons without having to worry about populating the collection with sample responses from scratch.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.