Skip to content

Khan/graphql-flow

Repository files navigation

Graphql Flow Generation

This is a tool for generating flow types from graphql queries in javascript frontends.

Using as a CLI tool

Write a config file, following the schema defined in src/cli/schema.json, either as a .json file, or a .js file that module.exports an object adhering to the schema.

Then run from the CLI, like so:

$ graphql-flow path/to/config.json

Files will be discovered relative to the crawl.root.

Multiple generate configs

To customize type generation for certain directories or files, you can provide multiple generate configs as an array, using match and exclude to customize behavior.

For a given file containing operations, the first generate config that matches that path (and doesn't exclude it) will be used to generate types for those operations. If a generate config doesn't have a match attribute, it will match all files (but might exclude some via the exclude attribute).

For example:

// dev/graphql-flow/config.js

const options = {
    schemaFilePath: "../../gengraphql/composed-schema.graphql",
    regenerateCommand: "make gqlflow",
    generatedDirectory: "__graphql-types__",
    exclude: [
        /_test.js$/,
        /.fixture.js$/,
        /\b__flowtests__\b/,
    ],
};

module.exports = {
    crawl: {
        root: "../../",
    },
    generate: [
        {
            ...options,
            schemaFilePath: "../../gengraphql/course-editor-schema.graphql",
            match: [/\bcourse-editor-package\b/, /\bcourse-editor\b/],
        },
        {
            ...options,
            match: [/\bdiscussion-package\b/]
            experimentalEnums: true,
        },
        options,
    ],
};

Introspecting your backend's graphql schema

Here's how to get your backend's schema in the way that this tool expects, using the builtin 'graphql introspection query':

import {getIntrospectionQuery} from 'graphql';
import fs from 'fs';
import fetch from 'node-fetch';

const query = getIntrospectionQuery({descriptions: true}),

const response = await fetch(`https://my-backend.com`, {
    method: 'POST',
    body: query,
    headers: {
        // You definitely shouldn't be allowing arbitrary queries without
        // some strict access control.
        'X-header-that-allows-arbitrary-queries': 'my-secret-key',
    },
    contentType: 'application/json',
});
const fullResponse = await response.json();
fs.writeFileSync('./server-introspection-response.json', JSON.stringify(fullResponse.data, null, 2));