GraphQL Schema Language Compiler


Keywords
clojurescript, graphql, graphql-schema-language, nodejs

Documentation

speako

A simpler interface to GraphQL

Install

  • NPM - npm install speako

Motivation

GraphQL normally requires a GraphQLSchema object passed along with each query you give it to validate, interpret & execute. Typically this schema is constructed by hand-crafting some verbose & noisy JavaScript.

See: starWarsSchema.js.

The equivalent schema in GraphQL Schema Language is much more concise:

enum Episode { NEWHOPE, EMPIRE, JEDI }

type Human {
  id: ID!
  name: String
  friends: [Character]
  appearsIn: [Episode]
  homePlanet: String
}

type Droid {
  id: ID!
  name: String
  friends: [Character]
  appearsIn: [Episode]
  primaryFunction: String
}

union Character = Human | Droid

Given a specification of a data model in GraphQL Schema Language, speako automatically generates the GraphQLSchema instance that GraphQL requires and binds its resolve methods to a specified set of functions for querying (i.e., selecting) and mutating (i.e., insert, update and delete mutations).

Example

$ node --harmony-destructuring
> var speako = require('speako');
> var gql = require('graphql');
> var _ = require('lodash');
> var labels = [
... {'id': 1, 'name': 'Apple Records', 'founded': '1968'},
... {'id': 2, 'name': 'Harvest Records', 'founded': '1969'}];
> var albums = [
... {'id': 1, 'name': 'Dark Side Of The Moon', 'releaseDate': 'March 1, 1973',
...  'artist': 'Pink Floyd', 'label': labels[1]},
... {'id': 2, 'name': 'The Beatles', 'releaseDate': 'November 22, 1968',
...  'artist': 'The Beatles', 'label': labels[0]},
... {'id': 3, 'name': 'The Wall', 'releaseDate': 'August 1, 1982',
...  'artist': 'Pink Floyd', 'label': labels[1]}];
> var dataResolver = {"query":  function (typename, predicate) {
...   console.assert(typename == "Album");
...   var parsed = JSON.parse(predicate);
...   if (_.isEqual(parsed, {"all": true})) return albums;
...   else {
...     var pairs = _.toPairs(parsed);
...     var filters = pairs.map(function (p) {
...       var [field, value] = p;
...       if (typeof value === "object") {
...         console.assert(field == "label");
...         return function(elem) {
...           var innerKey = _.first(_.keys(value));
...           return elem[field][innerKey] == value[innerKey]; };
...       }
...       return function(elem) { return elem[field] == value; };
...     });
...     return albums.filter(function(elem) { return filters.every(function(f) { return f(elem); }); });
...   }
... }, "create": function (typename, inputs) {
...   inputs.id = albums.length   1;
...   albums.push(inputs);
...   return inputs;
... }};
> var schema = speako.getSchema(dataResolver,
... "type Album { id: ID! name: String releaseDate: String artist: String }");
> var schema =
... speako.getSchema(dataResolver,
...               ["type Label { id: ID! name: String founded: String album: Album } ",
...                "type Album { id: ID! name: String releaseDate: String artist: String label: Label }"].join(" "));
> var printer = function(res) { console.log(JSON.stringify(res, null, 2)); };
> gql.graphql(schema,
...  "{ Album(artist: \"Pink Floyd\", label: { name: \"Harvest Records\" }) { name artist releaseDate } }") .then(printer);

{
  "data": {
    "Album": [
      {
        "name": "Dark Side Of The Moon",
        "artist": "Pink Floyd",
        "releaseDate": "March 1, 1973"
      },
      {
        "name": "The Wall",
        "artist": "Pink Floyd",
        "releaseDate": "August 1, 1982"
      }
    ]
  }
}

> gql.graphql(schema, "{ Album(artist: \"Pink Floyd\") { name artist releaseDate } }").then(printer);

{
  "data": {
    "Album": [
      {
        "name": "Dark Side Of The Moon",
        "artist": "Pink Floyd",
        "releaseDate": "March 1, 1973"
      },
      {
        "name": "The Wall",
        "artist": "Pink Floyd",
        "releaseDate": "August 1, 1982"
      }
    ]
  }
}

> gql.graphql(schema, "{ Album(artist: \"Pink Floyd\", name: \"The Wall\") { name artist releaseDate } }").then(printer);

{
  "data": {
    "Album": [
      {
        "name": "The Wall",
        "artist": "Pink Floyd",
        "releaseDate": "August 1, 1982"
      }
    ]
  }
}

> gql.graphql(schema, "{ Album(id: 2) { name artist releaseDate } }").then(printer);

{
  "data": {
    "Album": [
      {
        "name": "The Beatles",
        "artist": "The Beatles",
        "releaseDate": "November 22, 1968"
      }
    ]
  }
}

> gql.graphql(schema, "{ Albums { name artist releaseDate } }").then(printer);

{
  "data": {
    "Albums": [
      {
        "name": "Dark Side Of The Moon",
        "artist": "Pink Floyd",
        "releaseDate": "March 1, 1973"
      },
      {
        "name": "The Beatles",
        "artist": "The Beatles",
        "releaseDate": "November 22, 1968"
      },
      {
        "name": "The Wall",
        "artist": "Pink Floyd",
        "releaseDate": "Auguest 1, 1982"
      }
    ]
  }
}

> gql.graphql(schema, "mutation m { createAlbum(name:\"The Division Bell\", releaseDate: \"March 28, 1994\", artist:\"Pink Floyd\") { id name } }").then(printer);

{
  "data": {
    "createAlbum": {
      "id": "4",
      "name": "The Division Bell"
    }
  }
}

Copyright (c) 2015 Jonathan L. Leonard