From 8d1f5fb92bb7f6976e14bb7c341d13fdd994c3aa Mon Sep 17 00:00:00 2001 From: eric-burel Date: Mon, 19 Nov 2018 11:37:04 +0100 Subject: [PATCH] split graphQL initialization step and published the executable schema --- packages/vulcan-lib/lib/modules/graphql.js | 20 ++++- .../server/apollo-server/apollo_server2.js | 72 ++-------------- .../lib/server/apollo-server/initGraphQL.js | 83 +++++++++++++++++++ .../lib/server/apollo-ssr/createClient.js | 6 +- packages/vulcan-lib/package.js | 1 + packages/vulcan-lib/test/index.js | 2 +- .../vulcan-lib/test/server/apollo-ssr.test.js | 0 .../vulcan-lib/test/server/graphql.test.js | 22 +++++ packages/vulcan-lib/test/server/index.js | 1 + 9 files changed, 135 insertions(+), 72 deletions(-) create mode 100644 packages/vulcan-lib/lib/server/apollo-server/initGraphQL.js create mode 100644 packages/vulcan-lib/test/server/apollo-ssr.test.js create mode 100644 packages/vulcan-lib/test/server/graphql.test.js create mode 100644 packages/vulcan-lib/test/server/index.js diff --git a/packages/vulcan-lib/lib/modules/graphql.js b/packages/vulcan-lib/lib/modules/graphql.js index 3957b8b38..17174679d 100644 --- a/packages/vulcan-lib/lib/modules/graphql.js +++ b/packages/vulcan-lib/lib/modules/graphql.js @@ -359,13 +359,31 @@ export const GraphQLSchema = { } return graphQLSchema; + }, + + // getters + getSchema() { + if (!(this.finalSchema && this.finalSchema.length)) { + throw new Error('Warning: trying to access schema before it has been created by the server.') + } + return this.finalSchema[0] + }, + getExecutableSchema() { + if (!this.executableSchema) { + throw new Error('Warning: trying to access executable schema before it has been created by the server.') + } + return this.executableSchema } + }; Vulcan.getGraphQLSchema = () => { + if (!GraphQLSchema.finalSchema) { + throw new Error('Warning: trying to access graphQL schema before it has been created by the server.') + } const schema = GraphQLSchema.finalSchema[0]; // eslint-disable-next-line no-console - console.log(schema); + // console.log(schema); return schema; } diff --git a/packages/vulcan-lib/lib/server/apollo-server/apollo_server2.js b/packages/vulcan-lib/lib/server/apollo-server/apollo_server2.js index 942f692ce..f57e4a928 100644 --- a/packages/vulcan-lib/lib/server/apollo-server/apollo_server2.js +++ b/packages/vulcan-lib/lib/server/apollo-server/apollo_server2.js @@ -3,7 +3,6 @@ * @see https://www.apollographql.com/docs/apollo-server/migration-two-dot.html */ -import { makeExecutableSchema } from 'apollo-server'; // Meteor WebApp use a Connect server, so we need to // use apollo-server-express integration //import express from 'express'; @@ -11,23 +10,22 @@ import { ApolloServer } from 'apollo-server-express'; import { Meteor } from 'meteor/meteor'; -import { GraphQLSchema } from '../../modules/graphql.js'; import { WebApp } from 'meteor/webapp'; -import { runCallbacks } from '../../modules/callbacks.js'; // import cookiesMiddleware from 'universal-cookie-express'; // import Cookies from 'universal-cookie'; import voyagerMiddleware from 'graphql-voyager/middleware/express'; import getVoyagerConfig from './voyager'; -export let executableSchema; - +import initGraphQL from './initGraphQL' import './settings'; import { engineConfig } from './engine'; import { defaultConfig, defaultOptions } from './defaults'; import { initContext, computeContextFromReq } from './context.js'; import getPlaygroundConfig from './playground'; +import { GraphQLSchema } from '../../modules/graphql.js'; + // SSR import { ssrMiddleware } from '../apollo-ssr' /** @@ -117,70 +115,10 @@ const createApolloServer = ({ options: givenOptions = {}, config: givenConfig = // createApolloServer when server startup Meteor.startup(() => { - runCallbacks('graphql.init.before'); - - // typeDefs - const generateTypeDefs = () => [ - ` -scalar JSON -scalar Date - -${GraphQLSchema.getAdditionalSchemas()} - -${GraphQLSchema.getCollectionsSchemas()} - -type Query { - -${GraphQLSchema.queries - .map( - q => - `${ - q.description - ? ` # ${q.description} -` - : '' - } ${q.query} - ` - ) - .join('\n')} -} - -${ - GraphQLSchema.mutations.length > 0 - ? `type Mutation { - -${GraphQLSchema.mutations - .map( - m => - `${ - m.description - ? ` # ${m.description} -` - : '' - } ${m.mutation} -` - ) - .join('\n')} -} -` - : '' - } -` - ]; - - const typeDefs = generateTypeDefs(); - - GraphQLSchema.finalSchema = typeDefs; - - executableSchema = makeExecutableSchema({ - typeDefs, - resolvers: GraphQLSchema.resolvers, - schemaDirectives: GraphQLSchema.directives - }); - + initGraphQL() // define executableSchema createApolloServer({ options: { - schema: executableSchema + schema: GraphQLSchema.executableSchema } // config: .... // contextFromReq: .... diff --git a/packages/vulcan-lib/lib/server/apollo-server/initGraphQL.js b/packages/vulcan-lib/lib/server/apollo-server/initGraphQL.js new file mode 100644 index 000000000..bb7732e6a --- /dev/null +++ b/packages/vulcan-lib/lib/server/apollo-server/initGraphQL.js @@ -0,0 +1,83 @@ +/** + * Init the graphQL schema + */ + +import { makeExecutableSchema } from 'apollo-server'; +import { GraphQLSchema } from '../../modules/graphql.js'; +import { runCallbacks } from '../../modules/callbacks.js'; + + +const getQueries = () => ( +`type Query { +${GraphQLSchema.queries + .map( + q => + `${ + q.description + ? ` # ${q.description} +` + : '' + } ${q.query} + ` + ) + .join('\n')} +} + +` +) +const getMutations = () => GraphQLSchema.mutations.length > 0 ? ( +` +${ + GraphQLSchema.mutations.length > 0 + ? `type Mutation { + +${GraphQLSchema.mutations + .map( + m => + `${ + m.description + ? ` # ${m.description} +` + : '' + } ${m.mutation} +` + ) + .join('\n')} +} +` + : '' + } + +` +) : '' +// typeDefs +const generateTypeDefs = () => [ + ` +scalar JSON +scalar Date + +${GraphQLSchema.getAdditionalSchemas()} + +${GraphQLSchema.getCollectionsSchemas()} + +${getQueries()} + +${getMutations()} + +` + ]; + +const initGraphQL = () => { + runCallbacks('graphql.init.before'); + const typeDefs = generateTypeDefs(); + const executableSchema = makeExecutableSchema({ + typeDefs, + resolvers: GraphQLSchema.resolvers, + schemaDirectives: GraphQLSchema.directives + }); + GraphQLSchema.finalSchema = typeDefs; + GraphQLSchema.executableSchema = executableSchema; + return executableSchema +} + +export default initGraphQL \ No newline at end of file diff --git a/packages/vulcan-lib/lib/server/apollo-ssr/createClient.js b/packages/vulcan-lib/lib/server/apollo-ssr/createClient.js index 46989c3b9..4f1a5b152 100644 --- a/packages/vulcan-lib/lib/server/apollo-ssr/createClient.js +++ b/packages/vulcan-lib/lib/server/apollo-ssr/createClient.js @@ -10,15 +10,15 @@ import { ApolloClient } from 'apollo-client'; import { InMemoryCache } from 'apollo-cache-inmemory'; import { SchemaLink } from 'apollo-link-schema'; -// TODO: how to import the schema? -import { GraphQLSchema } from '../../modules/graphql' -const schema = {} // TODO ??? +import { GraphQLSchema } from '../../modules/graphql.js'; // @see https://www.apollographql.com/docs/react/features/server-side-rendering.html#local-queries // import { createHttpLink } from 'apollo-link-http'; // import fetch from 'node-fetch' const createClient = (req) => { + // we need the executable schema + const schema = GraphQLSchema.getExecutableSchema() const client = new ApolloClient({ ssrMode: true, link: new SchemaLink({ schema }), diff --git a/packages/vulcan-lib/package.js b/packages/vulcan-lib/package.js index a59174bf4..4acd5a44f 100644 --- a/packages/vulcan-lib/package.js +++ b/packages/vulcan-lib/package.js @@ -63,4 +63,5 @@ Package.onUse(function(api) { Package.onTest(function(api) { api.use(['ecmascript', 'meteortesting:mocha', 'vulcan:lib']); api.mainModule('./test/index.js'); + api.mainModule('./test/server/index.js', 'server'); }); diff --git a/packages/vulcan-lib/test/index.js b/packages/vulcan-lib/test/index.js index 61cf0435d..1539625cf 100644 --- a/packages/vulcan-lib/test/index.js +++ b/packages/vulcan-lib/test/index.js @@ -1 +1 @@ -import './client/index'; +import './client/index'; \ No newline at end of file diff --git a/packages/vulcan-lib/test/server/apollo-ssr.test.js b/packages/vulcan-lib/test/server/apollo-ssr.test.js new file mode 100644 index 000000000..e69de29bb diff --git a/packages/vulcan-lib/test/server/graphql.test.js b/packages/vulcan-lib/test/server/graphql.test.js new file mode 100644 index 000000000..bda2402d7 --- /dev/null +++ b/packages/vulcan-lib/test/server/graphql.test.js @@ -0,0 +1,22 @@ +import expect from 'expect' + +import { GraphQLSchema } from '../../lib/modules/graphql' +import initGraphQL from '../../lib/server/apollo-server/initGraphQL' + +describe('vulcan:lib/graphql', function(){ + // TODO: handle the graphQL init better to fix those tests + it.skip('throws if graphql schema is not initialized', function(){ + expect(() => GraphQLSchema.getSchema()).toThrow() + }) + it.skip('throws if executable schema is not initialized', function(){ + expect(() => GraphQLSchema.getExecutableSchema()).toThrow() + }) + it('can access the graphql schema', function(){ + initGraphQL() + expect(GraphQLSchema.getSchema()).toBeDefined() + }) + it('can access the executable graphql schema', function(){ + initGraphQL() + expect(GraphQLSchema.getExecutableSchema()).toBeDefined() + }) +}) \ No newline at end of file diff --git a/packages/vulcan-lib/test/server/index.js b/packages/vulcan-lib/test/server/index.js new file mode 100644 index 000000000..91135f0d3 --- /dev/null +++ b/packages/vulcan-lib/test/server/index.js @@ -0,0 +1 @@ +import './graphql.test' \ No newline at end of file