How to convert a GraphQL file to a Postman Collection? - graphql

I want to convert a GraphQL file to a Postman collection. I tried with a JavaScript library to do that (https://www.npmjs.com/package/graphql-to-postman).
But I'm getting the following error:
Unhandled Rejection (TypeError): Cannot set property
'includeDeprecatedFields' of undefined
function convert() {
var postmanJson = fileReader.result,
fileDownload = require('js-file-download');
const graphQlToPostman = require('graphql-to-postman');
const collection = graphQlToPostman.convert(postmanJson);
fileDownload(
JSON.stringify(collection),
'postman collection',
);
}
This is the function where I used the library.

To convert graphql to postman collection, first you need graphql schema. Graphql schema can be downloaded by running introspection query on the graphql server end point. Here is how to do it.
Install graphql-cli
npm i -g apollo
Download schema from the graphql server
apollo schema:download --endpoint=http://localhost:4000/graphql schema.json
Convert schema into graphql collection
const fs = require('fs')
const converter = require('graphql-to-postman')
const schema = fs.readFileSync('./schema.json')
converter.convert({
type: 'string',
data: schema.toString(),
}, {}, async function (error, result) {
if (error) {
log.error('Conversion failed')
} else {
const outputData = result.output[0].data
fs.writeFileSync('output-collection.json', JSON.stringify(outputData))
console.log('Conversion success');
}
})

I've built an easy-to-use command-line tool that allows you to automatically generate your Postman collection from your GraphQL endpoint. (https://www.npmjs.com/package/graphql-testkit)
It also comes with out-of-the-box support to control the maximum depth and add headers to all the requests in the collection.
Simply doing this, after replacing the endpoint, and adding or removing headers based on your requirement will auto-generate a Postman Collection with support for variables.
graphql-testkit \
--endpoint=https://api/spacex.land/graphql\
--header="Authorization:123,x-ws-system-id=10" \
--maxDepth=4

Related

Use Apollo server as a pass through of a query from client

I have a use case where I have apollo-server-express running with a React based apollo-client. I have an external graphql-datasource for some queries. Currently, I've configured apollo-datasource-graphql to be used as a data source for my apollo-server-express. However, this requires duplication of work on the resolver in Apollo as well as the resolver on my external graphql system.
Is there a way for me to pass queries made in the client through the Apollo Server and to the external graphql data source?
Maybe you could access the GraphQL AST from the fourth resolver argument (resolveInfo) and pass it into a GraphQL client?
Here is some prototype code:
import { print } from 'graphql/language/printer';
function forwardOperationResolver(root, args, context, resolveInfo) {
return fetch('https://remote.host/graphql', {
method: 'POST',
body: JSON.stringify({
query: print(resolveInfo.operation),
variables: resolverInfo.variableValues,
}),
})
.then(response => response.json())
.then(response => {
if (response.errors) {
// Handle errors
}
return response.data;
});
}
Downside: This breaks a few things that usually work in GraphQL like partial results and error locations...

Apollo GraphQL: Call a Mutation from the Server?

I need to call a mutation from a cron job running on the server. I found this SO post, but the accepted answer said there was no way to do it.
Then I found this on GitHub, from 2017:
graphql-server is a network wrapper for graphql core function. if you
don't want to use it over network, you can just run it standalone:
import scheme from './scheme';
const query = `{
me {
name
}
}`;
const result = graphql(scheme, query);
console.log(result);
function documentation can be found here
That looks pretty good! Is that the best practices approach in 2020?
Yes, if you have access to the GraphQLSchema object used by your GraphQL server, then the simplest approach is to just use the graphql function exported by the graphql module. Note that you should await the returned Promise to access the result:
async function run () {
const { data, errors } = await graphql(
schema,
query,
rootValue,
context,
variables
)
}
However, you can also make requests to the server itself over the network -- if the server is on the same host, you'd just use localhost or 127.0.0.1. In that case, you can use axios, request or any other HTTP client library in a Node.js script. You can also just use curl to make the request directly in a bash script or curl command.
I just found out about this approach as well. It's possible to create an Apollo client directly on the server.
export const getApolloServerClient = () =>
new ApolloClient({
ssrMode: true,
cache: new InMemoryCache(),
link: new SchemaLink({ schema }),
});

Passing query parameters to React Apollo POST requests

Is there a way to configure React Apollo to pass default query string parameters to each query / mutation ?
For now, all my requests have this format :
POST https://domain:8000/graphql;
I would like to have something like :
POST https://domain:8000/graphql?query=queryName
This would help for quick debugging purposes in the Chrome DevTools panel.
You can implement a custom fetch that apollo's http-link will then use.
When instantiating apollo client, do the following:
const customFetch = (uri, options) => {
const { operationName } = JSON.parse(options.body);
return fetch(`${uri}/graph/graphql?opname=${operationName}`, options);
};
const link = createHttpLink({ fetch: customFetch });

Log Query/Mutation actions to database for Auditing

My goal is to run some kind of webhook, cloud function or say I want to perform some kind of action after each query success or mutation success in graphql.
Means I want to log each and every action performed by users (kind of history of when what was created and updated).
How can this be implemented using some kind of middleware between graphql and DB (say mongo for now)?
Means that middleware should be responsible to run the logging action each time a query or mutation is called from front-end.
Tech stack being used is- Node, express, graphQl, Redis etc.
Any suggestions would really be appreciated.
Thanks
The solution I came up with was calling a function manually each time a query or mutate.
If you're using Apollo, you can utilize the formatResponse and formatError options for logging, as outlined in the docs.
const server = new ApolloServer({
typeDefs,
resolvers,
formatError: error => {
console.log(error);
return error;
},
formatResponse: response => {
console.log(response);
return response;
},
});
Using an extension can allow you to hook into different phases of the GraphQL request and allow more granular logging. A simple example:
const _ = require('lodash')
const { GraphQLExtension } = require('graphql-extensions')
module.exports = class LoggingExtension extends GraphQLExtension {
requestDidStart(options) {
logger.info('Operation: ' + options.operationName)
}
willSendResponse(o) {
const errors = _.get(o, 'graphqlResponse.errors', [])
for (const error of errors) {
logger.error(error)
}
}
}
There's a more involved example here. You can then add your extension like this:
const server = new ApolloServer({
typeDefs,
resolvers,
extensions: [() => new YourExtension()]
});
If you're using express-graphql to serve your endpoint, your options are a bit more limited. There's still a formatError option, but no formatResponse. There is a way to pass in an extensions array as well, but the API is different from Apollo's. You can take a look at the repo for more info.

Inspecting a remote graphql endpoint with graphiql

There is a graphql endpoint which I don't own but which provides a public endpoint. I'm hoping to introspect it using graphiql. I'm totally new to graphql, so I don't even know if this sort of thing is possible.
I have the graphiql example running locally and am modifying server.js to try to make it work. Poking around at other SO threads has gotten me this far...
var introspectionQuery = require('graphql/utilities').introspectionQuery;
var request = require('sync-request');
var url = 'http://endpoint.com/graphql';
var response = request('POST', url, { qs: { query: introspectionQuery } } );
var schema = JSON.parse(response.body.toString('utf-8'));
// herein lies the rub
schema = new GraphQLSchema(schema.data.__schema);
var app = express();
app.use(express.static(__dirname));
app.use('/graphql', graphqlHTTP(() => ({
schema: schema,
})));
app.listen(8080);
This code blows up in the GraphQLSchema constructor, trying to make a schema out of that introspection query. Clearly that's not quite the right approach?
What you want to build schema out of the introspection result is buildClientSchema:
var buildClientSchema = require('graphql/utilities').buildClientSchema;
var introspectionQuery = require('graphql/utilities').introspectionQuery;
var request = require('sync-request');
var response = request('POST', url, { qs: { query: introspectionQuery } });
// Assuming we're waiting for the above request to finish (await maybe)
var introspectionResult = JSON.parse(response.body.toString('utf-8'));
var schema = buildClientSchema(introspectionResult);
You could build the schema in two other ways: buildASTSchema and instantiating GraphQLSchema directly, which is what you're trying out. GraphQLSchema constructor takes in an object with GraphQLSchemaConfig type:
type GraphQLSchemaConfig = {
query: GraphQLObjectType;
mutation?: ?GraphQLObjectType;
subscription?: ?GraphQLObjectType;
types?: ?Array<GraphQLNamedType>;
directives?: ?Array<GraphQLDirective>;
};
And those two utility modules provide easier ways to build the schema from either from introspection query result or parsed IDL type definitions, respectively by using buildClientSchema or buildASTSchema. Refer to those modules in graphql-js/src/utilities directory for more information please.
I was trying this with a PHP GraphQL library. I hit lots of issues experimenting with the above around CORS (cross origin security stuff).
Then I discovered GraphIQL is available as a Chrome app. That resolved my need, so noting here in case useful to anyone else who comes across this issue. You don't need to do any coding to get GraphIQL working with a remote endpoint.

Resources