0

I have some operations (query/mutation, and sometimes some fragments at the bottom of the file) defined in .gql files, sometimes more than one in a single file.

I would like to import these into my JS/TS files, possibly also generate corresponding types for TypeScript.

I set up a 3 files example here:

https://gist.github.com/balazsorban44/352d5295f604fb4274bfc934937737a1

The queries.gql file is the source. They should generate corresponding module types in a file (see generated-types.d.ts), so I can import these into my index.ts file and use it to make graphql calls with a simple fetch.

What I have tried so far are these tools/packages:

As far as I can tell, none of these above support multiple operations per file exported as a string, only multiple operations as DocumentNode, or the entire file as a string.

Let me know if there are any more questions.

Balázs Orbán
  • 559
  • 1
  • 4
  • 26

1 Answers1

0

A solution using documents-loading of graphql-tools and separateOperations - a utility function for splitting an AST. Here are the steps:

  1. load documents from .gql files
  2. Separate this all-encompasing AST into individual ASTs that represent each operation that could be sent to the server in isolation.
  3. Convert DocumentNode(AST) into a string using print function of graphql package.

E.g.

queries.gql:

query Something {
  name
  id
}

query SomethingElse($email: String!) {
  somethingelse(email: $email) {
    phone
    ...SomeFragment
  }
}

fragment SomeFragment on User {
  email
  address
}

index.ts:

import { loadDocumentsSync } from '@graphql-tools/load';
import { GraphQLFileLoader } from '@graphql-tools/graphql-file-loader';
import path from 'path';
import { separateOperations, print, buildSchema } from 'graphql';
import express from 'express';
import { graphqlHTTP } from 'express-graphql';
import fetch from 'node-fetch';

const documents = loadDocumentsSync(path.resolve(__dirname, './queries.gql'), {
  loaders: [new GraphQLFileLoader()],
});
const { Something, SomethingElse } = separateOperations(documents[0].document!);

console.log(print(Something));
console.log(print(SomethingElse));

// server
const schema = buildSchema(`
  type User {
    id: ID!
    name: String
    email: String
    address: String
    phone: String
  }
  type Query {
    somethingelse(email: String!): User
    Something: User
  }
`);
const root = {
  somethingelse({ email }) {
    return { id: 1, name: 'teresa teng', email, address: 'Japan', phone: '123' };
  },
};
const app = express();
app.use(
  '/graphql',
  graphqlHTTP({
    schema: schema,
    rootValue: root,
    graphiql: true,
  }),
);
app.listen(4000, () => console.log('graphql server running on localhost 4000'));

// test
fetch('http://localhost:4000/graphql', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ query: print(SomethingElse), variables: { email: 'teresa.teng@gmail.com' } }),
})
  .then((res) => res.json())
  .then((res) => console.log(res))
  .catch(console.error);

The execution result:

query Something {
  name
  id
}

query SomethingElse($email: String!) {
  somethingelse(email: $email) {
    phone
    ...SomeFragment
  }
}

fragment SomeFragment on User {
  email
  address
}

graphql server running on localhost 4000
{ data:
   { somethingelse:
      { phone: '123',
        email: 'teresa.teng@gmail.com',
        address: 'Japan' } } }

BTW, if the tools/packages you provided can load documents from .gql files, you can use it instead of using graphql-tools. The rest steps are the same.

Lin Du
  • 88,126
  • 95
  • 281
  • 483