I have a node, express server using expressGraphql. I am trying to declare a type definition for graphql in a .graphql
or .gql
file, because as the
You can use https://github.com/ardatan/graphql-import-node to solve this without webpack.
Install with yarn add graphql-import-node
or npm install --save graphql-import-node
and then either use the graphql-import-node/register
hook (if you're using ts-node):
ts-node -r graphql-import-node/register index.ts
Or import it in your file right at the top like this:
import "graphql-import-node";
I chose the later in my case because I already used ts-node/register
with mocha -r
for my tests.
You also may need to add "esModuleInterop": true
to your compilerOptions in tsconfig.json
.
This answer addresses the concerns brought up by @leogoesger.
Its a modular approach of creating schemas using .graphql
files without needing to define multiple makeExecutableSchema
calls.
The folder structure should look something like this for it to work:
src
- graphql
- schema.ts
- bar
- barResolver.ts
- schema.graphql
- foo
- fooResolver.ts
- schema.graphql
schema.graphql
contains all your type definitions.
The 'feature' Resolver files contain your resolvers which is an object containing your queries and mutations.
Inside your schema.ts
file you would create your merged schema like so:
import { mergeSchemas, makeExecutableSchema } from "graphql-tools";
import { readdirSync, lstatSync, existsSync } from "fs";
import * as path from "path";
import { importSchema } from 'graphql-import'
import { GraphQLSchema } from 'graphql';
const schemas: GraphQLSchema[] = [];
const isDirectory = dirPath => existsSync(dirPath) && lstatSync(dirPath).isDirectory();
const getDirectories = source =>
readdirSync(source).map( name => path.join(source, name) ).filter(isDirectory)
const folders = getDirectories( path.resolve(__dirname, './') )
folders.forEach(folder => {
folder = folder.substr( folder.lastIndexOf("\\")+1 )
const {resolvers} = require(`./${folder}/${folder}Resolver`);
const typeDefs = importSchema( path.join(__dirname, `./${folder}/schema.graphql`) );
schemas.push(makeExecutableSchema({resolvers, typeDefs}))
});
const mergedSchemas = mergeSchemas({ schemas })
export default mergedSchemas;
The idea is to get all the relative directories that exist on the same level as schema.ts
then to loop through each feature name and import the respective resolver and type definition. Next we make the schema executable and add it to our schema array. Lastly we stitch the schemas together using mergeSchemas
to create a single GraphQL schema from multiple API's. (See https://www.apollographql.com/docs/graphql-tools/schema-stitching for more details.)
Then you can create your server as normal
import schema from './graphql/schema';
const server = new GraphQLServer({schema: schema})
AFAIK, there are two ways to import schema files, either 1) by reading the file directly as you describe above, or 2) by wrapping the queries in exported variables.
// bookSchema.ts <- note the file extension is .ts instead of .graphql
export default `
type Book {
message: String
}
`
// anotherSchema.ts <- note the file extension is .ts instead of .graphql
export default `
type User {
name: String
}
`
// main.ts
import bookSchema from 'bookSchema';
import anotherSchema from 'anotherSchema';
const schema = makeExecutableSchema({ typeDefs: [
bookSchema,
anotherSchema,
] });