Skip to content

Use a GraphQL Schema Directive to define Javascript logic, have that logic executed as a resolver.

License

Notifications You must be signed in to change notification settings

danstarns/graphql-code-directive

Repository files navigation

graphql-code-directive

npm package Publish Tests

Use a GraphQL Schema Directive to define Javascript logic, have that logic executed as a resolver.

Links

  1. NPM
  2. Examples
  3. Blog Post

What

Its a directive you can use on Fields:

directive @code(source: String!) on FIELD_DEFINITION

You 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-directive

Usage

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:

  1. rootValue
  2. args
  3. context
  4. resolveInfo

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:

  1. typeDefs - A string of the directives type definitions
  2. CodeDirective - A legacy SchemaDirectiveVisitor that you are most likely to be familiar with
  3. codeDirective - 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.