graphql-code-directive v2.0.1
graphql-code-directive
Use a GraphQL Schema Directive to define Javascript logic, have that logic executed as a resolver.
Links
What
Its a directive you can use on Fields:
directive @code(source: String!) on FIELD_DEFINITIONYou define Javascript logic in the source argument. The source is wrapped in an IFFE & passed into a https://nodejs.org/api/vm.html. Supports Promises & you can use dependency injection via the context.
Installing
$ npm install graphql-code-directiveUsage
const { ApolloServer } = require("apollo-server");
const codeDirective = require("graphql-code-directive");
const fetch = require("node-fetch");
const typeDefs = `
type Todo {
id: ID!
userId: ID!
title: String!
completed: Boolean
}
type Query {
todos: [Todo]
@code(
source: """
const response = await context.fetch('https://jsonplaceholder.typicode.com/todos');
return response.json()
"""
)
}
`;
const server = new ApolloServer({
typeDefs: [codeDirective.typeDefs, typeDefs],
schemaDirectives: {
code: codeDirective.CodeDirective,
},
context: () => {
return {
fetch,
};
},
});
server.listen(4000).then(() => console.log("http://localhost:4000"));FAQ
How to dependency inject ?
Inside the code source you have access to the four global variables:
rootValueargscontextresolveInfo
So for example if you were to write a 'Normal' Javascript resolver the variables would map to each argument:
function myResolver(rootValue, args, context, resolveInfo) {}Is this safe ?
Make sure you disable introspection & yes it is safe. You are in control of what the VM has access to, via context, and the Node.js team has done a good job at isolating the VM.
Is it testable ?
Unit testing could become cumbersome, this is because you would have to parse the definitions into an AST in order to access the source. You can however write solid integration tests, why not checkout https://www.apollographql.com/docs/apollo-server/testing/testing/ ?
Can I use the new Schema Directives ?
Yes! There are 3 exports:
typeDefs- A string of the directives type definitionsCodeDirective- A legacySchemaDirectiveVisitorthat you are most likely to be familiar withcodeDirective- A functional approach to Schema Directives that returns a transformer
Using with new Schema Directives
const { codeDirective } = require("graphql-code-directive");
const { makeExecutableSchema } = require("@graphql-tools/schema");
const { codeDirectiveTypeDefs, codeDirectiveTransformer } = codeDirective();
let schema = makeExecutableSchema({
typeDefs: [codeDirectiveTypeDefs, typeDefs],
resolvers: {},
});
schema = codeDirectiveTransformer(schema);Licence
MIT licence.