Apollo-server: use static file schema schema.graphql file!

Created on 14 Jun 2018  路  17Comments  路  Source: apollographql/apollo-server

hi, i want to use a static file for sham operation.

schema file;
schema.graphql

type Query {
  hello: String
}

resolvers file;
index.js

const resolver = {
  hello: () => {
    return "Hello world!";
  }
};
module.exports = resolver;

index file;
server.js

import express from 'express';
import bodyParser from 'body-parser';
import { graphiqlExpress, graphqlExpress } from 'apollo-server-express';
import { makeExecutableSchema } from 'graphql-tools';

import typeDefs from './schema/schema.graphql';
import resolvers from './resolvers/';

const schema = makeExecutableSchema({ 
typeDefs,resolvers 
});

const app = express();
app.use(bodyParser());
app.use('/graphql', bodyParser.json(), graphqlExpress({ schema, context }));
app.use('/graphiql', graphiqlExpress({ endpointURL: '/graphql' }));
app.listen(4000, () => console.log('listening on port 4000!'));

my scheme is not working!
I do not want to use it like this;

const Query = `
type Query {
  hello: String
}
`;

export default Query;

Most helpful comment

you can use fs to read it as a string

import fs from "fs";
import path from "path";

const typeDefs = fs.readFileSync(path.join(__dirname, "schema.graphql", "utf8");

Or if you are using babel/or webpack (what you possible already do since you use import syntax. You can either use the https://github.com/apollographql/graphql-tag#webpack-preprocessing-with-graphql-tagloader (if you are using webpack)

or https://www.npmjs.com/package/preval.macro to do the schema parsing at build time with babel.

import preval from 'preval.macro'

const typeDefs = preval`
  const fs = require("fs");
  const path = require("path");
  module.exports = fs.readFileSync(path.join(__dirname, "schema.graphql", "utf8");
`

All 17 comments

you can use fs to read it as a string

import fs from "fs";
import path from "path";

const typeDefs = fs.readFileSync(path.join(__dirname, "schema.graphql", "utf8");

Or if you are using babel/or webpack (what you possible already do since you use import syntax. You can either use the https://github.com/apollographql/graphql-tag#webpack-preprocessing-with-graphql-tagloader (if you are using webpack)

or https://www.npmjs.com/package/preval.macro to do the schema parsing at build time with babel.

import preval from 'preval.macro'

const typeDefs = preval`
  const fs = require("fs");
  const path = require("path");
  module.exports = fs.readFileSync(path.join(__dirname, "schema.graphql", "utf8");
`

I am currently doing this:

const { importSchema } = require('graphql-import')
const typeDefs = importSchema('./schema.graphql')
const resolvers = require('./resolvers')

const server = new ApolloServer({
  typeDefs,
  resolvers
})

However this doesn't work anymore in the latest betas and I am also looking for a solution that doesn't involve webpack since I would like to keep my server as simple and minimalist as possible.

I like having my schema in .graphql files and I also use the # import * from ... syntax supported by prismagraphql/graphql-import to keep it in order by separating queries, mutations, types, inputs and so on...

thank you @lorlab!

https://github.com/prismagraphql/graphql-import
graphql-import packege is solved my problem.

@lorlab

ApolloServer is not used with importSchema! (Error)
error message;

/Users/furkancelik/Desktop/graphQLBoilerplate/node_modules/apollo-server-core/dist/ApolloServer.js:68
            throw new Error(`typeDefs must be tagged with the gql exported from apollo-server:
            ^

Error: typeDefs must be tagged with the gql exported from apollo-server:

const { gql } = require('apollo-server');

const typeDefs = gql`type Query {
  hello: String
}

@furkancelik @lorlab I am still using version 1.x not the 2.0.0-beta

For 2.0.0 this should work:

const gql = require("graphql-tag")

// schemaString can be provided by graphql-import or fs.readFile or whatever
const typeDefString = `
  type Query {
    hello: String
  }
`
const typeDefs = gql`${schema}`

However I would prefer using graphql-tags webpack loader or https://www.npmjs.com/package/graphql.macro. Since you also do not have the overhead of parsing the schema at runtime.

Thank you @n1ru4l and @lorlab for answering the questions!

For the rc, we have removed the hard requirement to pass in a gql tagged schema. Still gql is exported from apollo-server and integrations directly from gql-tag.

I am currently doing this:

const { importSchema } = require('graphql-import')
const typeDefs = importSchema('./schema.graphql')
const resolvers = require('./resolvers')

const server = new ApolloServer({
  typeDefs,
  resolvers
})

However this doesn't work anymore in the latest betas and I am also looking for a solution that doesn't involve webpack since I would like to keep my server as simple and minimalist as possible.

I like having my schema in .graphql files and I also use the # import * from ... syntax supported by prismagraphql/graphql-import to keep it in order by separating queries, mutations, types, inputs and so on...

I have to add src to the import path to make it work again
const typeDefs = importSchema('./src/schema.graphql')

Just don't forget to use the toString method:

import fs from "fs";
import path from "path";

const typeDefs = fs.readFileSync("./schema.graphql", "utf8").toString();

For anyone having issues with this, I have been trying for days and I've found a solution.

Do not use graphql-import it is completely broken at the minute.

Solution

Simply use the babel-plugin-import-graphql

It reads the # import syntax within .graphql files (and even .gql files) recursively and builds one giant string, without webpack.

To which you can pass to your schema builder

GraphQL-Yoga supports typeDefs: "./schema.graphql" out of the box. Would be a great feature to add.

A small problem with babel-plugin-import-graphql is that it doesn't automatically recompile the schema if you edit the file.

Using typescript I was getting an error when I was trying doing this:

const server = new ApolloServer({
  typeDefs: importSchema('./src/schema.graphql'),
  resolvers
});

Error:

[ts] Type 'string' is not assignable to type 'DocumentNode | DocumentNode[]'

But it was solve using this:

const server = new ApolloServer({
  typeDefs: gql(importSchema('./src/schema.graphql')),
  resolvers
});

With directory structure:

package.json
src
|-index.js
|-schema.graphql

This is working for me:

// index.js
const { importSchema } = require('graphql-import');
const { ApolloServer } = require('apollo-server-express');

const server = new ApolloServer({
  typeDefs: importSchema('src/schema.graphql'), //<-- note no './' in path and no gql
  resolvers,
});

An example from the documentation (migration-two-dot) :

const { ApolloServer, gql } = require('apollo-server');
...
//Some projects use schemas imported from external files
const fs = require('fs');
const typeDefs = gql`${fs.readFileSync(__dirname.concat('/schema.graphql'), 'utf8')}`;

//gql can also be used as regular function to convert a string to an AST
const typeDefs = gql(fs.readFileSync(__dirname.concat('/schema.graphql'), 'utf8'))

schema.graphql

# Comments in GraphQL strings (such as this one) start with the hash (#) symbol.

# This "Book" type defines the queryable fields for every book in our data source.
type Book {
    title: String
    author: String
}

# The "Query" type is special: it lists all of the available queries that
# clients can execute, along with the return type for each. In this
# case, the "books" query returns an array of zero or more Books (defined above).
type Query {
    books: [Book]
}

`const path = require('path');
const { loadFilesSync } = require('@graphql-tools/load-files');
const { mergeTypeDefs } = require('@graphql-tools/merge');

const typesArray = loadFilesSync(path.join(__dirname, './schemas'));

module.exports = mergeTypeDefs(typesArray, { all: true });`

// The schemas folder should have files with .graphql or .gql files

`const path = require('path');
const { loadFilesSync } = require('@graphql-tools/load-files');
const { mergeTypeDefs } = require('@graphql-tools/merge');

const typesArray = loadFilesSync(path.join(__dirname, './schemas'));

module.exports = mergeTypeDefs(typesArray, { all: true });`

// The schemas folder should have files with .graphql or .gql files

how to import?

const path = require('path'); const { loadFilesSync } = require('@graphql-tools/load-files'); const { mergeTypeDefs } = require('@graphql-tools/merge'); const typesArray = loadFilesSync(path.join(__dirname, './schemas')); module.exports = mergeTypeDefs(typesArray, { all: true });
// The schemas folder should have files with .graphql or .gql files

how to import?

@Chavanz assume above code is in a file called schemaAssembler

To import it use:
const graphQLSchema = require('./graphql/schemas/schemaAssembler');

I use it in ApolloServer like this:

const apolloServer = new ApolloServer({
typeDefs: graphQLSchema,
resolvers: graphQLResolvers,
playground: process.env.PLAYGROUND,
});

Was this page helpful?
0 / 5 - 0 ratings