node package manager
Easy collaboration. Discover, share, and reuse code in your team. Create a free org »

jsonschema-to-graphql

jsonschema-to-graphql

A GraphQL schema generated by reading JSON schemas.

Generate the GraphQL Schema (Non-Relay Compliant) by providing JSON Schema files. Refer examples folder for more sample implementation.
Default knex-based resolver is provided. You can extend the resolver to add your own implementation.

Installation

npm install jsonschema-to-graphql

Running Sample Locally

npm run sample

Usage

var GraphQL = require('jsonschema-to-graphql');
// Add a Resolver, Can be replace with custom resolvers 
var Resolver = require('../dist/knex-resolver');
var resolver = new Resolver(knex);
 
var opts = {
  resolver : resolver,
  skipConstraintModels: false,
  skipOperatorFields: false,
  skipPaginationFields: false,
  skipSortByFields: false
};
 
// Build GraphQL Schema
// This is all you need to do to generate the schema.
var graphQLSchema  = GraphQL.builder(opts)
    .addSchema(require('./schemas/User'), {
    exclude: ['ignoreField']
  })
  .addSchema(require('./schemas/Movie'), {})
  .addCustomQueryFunction(require('./schemas/CustomFunction'))
  .build();

Builder accepts opts parameter:

  • resolver: default resolver is a no-op function return empty array/object.
  • skipConstraintModels: to skip Models generated based on primary keys and unique keys.
  • skipOperatorFields: to skip Operator fields in the list models.
  • skipPaginationFields: to skip pagination fields.
  • skipSortByFields: to skip order related fields.

addSchema accepts two parameters - schema definition and options.
addCustomQueryFunction can be used to add custom query functions.
addCustomMutationFunction can be used to add custom mutation functions.

Sample Schema

{
  tableName: 'Movie',
  description: 'Movie Model',
  primaryKey: 'id',
  foreignKeys: [{
    // Name of the association
    name: 'user',
    description: 'Owner of Movie',
    // joins from
    fields: 'userId',
    // joins to
    reference: {
      datapackage: '',
      resource: 'user',
      fields: 'id'
    }
  }],
  fields: [{
    name: 'id',
    description: 'Movie Id',
    type: 'integer',
    constraints: {
      required: true,
      autoincrement: true
    }
  }, {
    name: 'userId',
    description: 'Movie Owner\'s Id',
    type: 'integer'
  }, {
    name: 'title',
    description: 'Movie Title',
    type: 'string'
  }]
}

Note: Convention followed is tableName is singular and the association are plural.

primarykey: can also be an array of fields.
foreignKeys: bi-directional associations are generated based on singular/plural association name.
type: supports primitive data-types.

Schema Generated

For the above Movie example the schema would be something like -

// Basic GraphQL For Model
User(id: Int!): User
 
// Model for unique fields
UserByUserName(userName: String!): User
 
// Model for required fields.
UsersByEmail(email: String!, limit: Int, offset: Int, sortBy: UserPropertiesEnum, sortByDesc: UserPropertiesEnum): [User]
 
// Basic Model
Movie(id: Int!): Movie  
 
// List Model, with operators.
Movies(  
id_Gt: Int,   
id_Gte: Int,   
id_Lt: Int,   
id_Lte: Int,   
id_Ne: Int,   
id_In: [Int]  
id_NotIn: [Int]  
id: Int,  
id_IsNull: Boolean, ...  
limit: Int,  
offset: Int,  
sortBy: MoviePropertiesEnum,  
sortByDesc: MoviePropertiesEnum): [Movie]  
)

Each of the Model will also contain bi-directional links to fetch related data. for instance, User model will contain movies link, and Movie model will contain user link.

Mutation Support

Basic Mutations for each model is supported through Create<Model>, Update<Model> and Delete<Model>.

// For creating a Movie
CreateMovie(userId: Int, title: String): CreateMovie
// Updating a Movie
UpdateMovie(id: Int!,userId: Int, title: String): UpdateMovie
// Deleting a Movie
DeleteMovie(id: Int!): DeleteMovie