6

I'm playing with relay-starter-kit. I've also used sangria to create a graphql server. Now I'm trying to wire the two together.

In relay-starter-kit, every time you alter the schema, you need to run a script to regenerate the schema.json file. But since graphql supports schema introspection I'm wondering if there's a way to configure my relay app to introspect the schema from the server when it starts up.

Does anyone know if this is possible or worked out how to do this?

Nick Siderakis
  • 1,961
  • 2
  • 21
  • 39
jbrown
  • 7,518
  • 16
  • 69
  • 117
  • Isn't it what it does when you run 'npm start'? Introspect the generated schema file with the 'npm run update-schema' – MaC Aug 25 '15 at 11:28
  • That's not introspection, that's loading `schema.json`. What I want is to be able to issue a graphql introspection query to my server so that it can pull down that JSON without me having to keep running `npm run update-schema` or an equivalent for my server. – jbrown Aug 25 '15 at 12:00

3 Answers3

5

Define a babelRelayPlugin.js (which is run by webpack when validating the client graphql queries) as such:

var babelRelayPlugin   = require('babel-relay-plugin');
var introspectionQuery = require('graphql/utilities').introspectionQuery;
var request            = require('sync-request');

var url = 'http://localhost:3000/graphql';

var response = request('POST', url, {
   qs: {
      query: introspectionQuery
   }
});

var schema = JSON.parse(response.body.toString('utf-8'));

module.exports = babelRelayPlugin(schema.data, {
   abortOnError: true,
});

Of course, change the url variable to whatever server url you use for development. In webpack, include the following in your loaders definition:

query: {stage: 0, plugins: ['./babelRelayPlugin']}

and point to the location of the above babelRelayPlugin.js file.

Nik
  • 1,353
  • 13
  • 15
2

Looks like we need something like this (from https://github.com/facebook/relay/blob/master/scripts/jest/updateSchema.js#L25):

import { buildASTSchema, introspectionQuery } from 'graphql/utilities';

var body = fs.readFileSync(inFile, 'utf8');
var ast = parseSchemaIntoAST(body);
var astSchema = buildASTSchema(ast, 'Root', 'Mutation');
graphql(astSchema, introspectionQuery).then(
    function(result) {
      var out = JSON.stringify(result, null, 2);
      fs.writeFileSync(outFile, out);
});
steveluscher
  • 4,144
  • 24
  • 42
jbrown
  • 7,518
  • 16
  • 69
  • 117
0

The introspection product (schema.json) is used by the Babel Relay Plugin to validate and compile Relay.QL expressions. Luckily, the getBabelRelayPlugin method accepts either an introspection product, or a function that returns an introspection product.

It should be possible then to do something like this in your app's build system (eg. Webpack):

// Pseudocode
var SCHEMA_PATH = 'path/to/schema.js';
var introspectionProduct = introspectSchema(SCHEMA_PATH);

watch(SCHEMA_PATH, () => introspectionProduct = introspectSchema(SCHEMA_PATH));

var babelRelayPlugin = getBabelRelayPlugin(() => introspectionProduct);
steveluscher
  • 4,144
  • 24
  • 42
  • I have a GitHub issue out to bake this into the starter-kit. If anyone has time before I get to it, here it is! https://github.com/relayjs/relay-starter-kit/issues/13 – steveluscher Sep 10 '15 at 17:32
  • Does this support hitting an external server? – jbrown Sep 11 '15 at 09:05
  • `getBabelRelayPlugin()` only accepts a string or a synchronous callback. It might be possible to augment it to accept an asynchronous callback, if Babel permits plugins to operate in such a way. @JoeSavona might know more. – steveluscher Sep 11 '15 at 20:42