Skip to content

Instantly share code, notes, and snippets.

@voodooattack
Last active October 2, 2017 01:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save voodooattack/c4f7a261ea189ffb1894e9cb5e018587 to your computer and use it in GitHub Desktop.
Save voodooattack/c4f7a261ea189ffb1894e9cb5e018587 to your computer and use it in GitHub Desktop.
Make Vulcan.js self-contained.

Internal GraphQL for Vulcan.js

To make a GraphQL query on a Vulcan.js server, your server has to connect to itself via a new HTTP connection every time it receives a request.

This package makes it so that Vulcan’s GraphQL queries never leave the process. All GraphQL requests are processed with no overhead.

See also: webtoken-session

import { withRenderContextEnvironment, GraphQLSchema, Collections } from 'meteor/vulcan:lib';
import { makeExecutableSchema } from 'graphql-tools';
import { graphql, print } from 'graphql';
import DataLoader from 'dataloader';
import deepmerge from 'deepmerge';
async function findByIds(collection, ids, context) {
// get documents
const documents = await collection.find({ _id: { $in: ids } }).fetch();
// order documents in the same order as the ids passed as argument
return ids.map(id => _.findWhere(documents, {_id: id}));
}
Meteor.startup(() => {
const schema = makeExecutableSchema({
typeDefs: GraphQLSchema.finalSchema,
resolvers: GraphQLSchema.resolvers,
});
withRenderContextEnvironment(function (renderContext, req, res, next) {
const context = deepmerge({
// My own extension to Vulcan.js.
// It's really useful when you have access to the ApolloClient inside resolvers.
// This makes it possible for resolvers to make their own queries.
getRenderContext() { return renderContext; },
// Copy over the userID.
userId: req.loginContext ? req.loginContext.userId : undefined
}, GraphQLSchema.context);
// go over context and add Dataloader to each collection
Collections.forEach(collection => {
context[collection.options.collectionName].loader = new DataLoader(ids => findByIds(collection, ids, context), {
cache: true
});
});
renderContext.apolloClient.networkInterface = {
query: (request) => {
return graphql(schema, print(request.query), {}, context, request.variables, request.debugName);
}
};
next();
}, { order: 23, name: 'internal-graphql-middleware' });
});
Package.describe({
name: 'internal-graphql',
version: '0.0.1',
// Brief, one-line summary of the package.
summary: 'Prevent extraneous HTTP connections created by Vulcan to itself.',
// URL to the Git repository containing the source code for this package.
git: '',
// By default, Meteor will default to using README.md for documentation.
// To avoid submitting documentation, set this field to null.
documentation: 'README.md'
});
Package.onUse(function(api) {
api.versionsFrom('1.5.1');
api.use([
'ecmascript',
'vulcan:lib'
]);
api.mainModule('internal-graphql.js', ['server']);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment