Skip to content
This repository has been archived by the owner on Feb 10, 2023. It is now read-only.

Generic implementation of schema directives for GraphQL Ruby

License

Notifications You must be signed in to change notification settings

gmac/graphql-ruby-schema-directives

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

10 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

This repository is no longer relevant

Ruby GraphQL Schema Directives

This gem extends GraphQL Ruby to add support for custom schema directives that annotate an SDL for uses such as Schema Stitching. This is a more generic version of the apollo-federation gem (which is specifically tailored to setting up the federation spec).

This gem has some very basic goals:

  1. allow schema directives to be applied to any GraphQL element, and then printed as an annotated SDL.
  2. allow class-based schemas and parsed GraphQL::Schema.from_definition schemas to be printed together.

Contents

Installation

Add to Gemfile:

gem 'graphql-schema_directives'

Then install:

bundle install

Class-based schemas

There's a typed mixin available for extending all GraphQL schema members. The first thing to include is the schema mixin:

class MySchema < GraphQL::Schema
  include GraphQL::SchemaDirectives::Schema
end

This adds a print_schema_with_directives method to print an SDL that includes custom schema directives:

MySchema.print_schema_with_directives

Field, Object & Interface classes

Setup base abstracts:

class BaseField < GraphQL::Schema::Field
  include GraphQL::SchemaDirectives::Field
end

class BaseObject < GraphQL::Schema::Object
  include GraphQL::SchemaDirectives::Object
  field_class BaseField
end

module BaseInterface
  include GraphQL::Schema::Interface
  include GraphQL::SchemaDirectives::Interface
  field_class BaseField
end

Then extend into concrete implementations:

module Spaceship
  include BaseInterface
  add_directive :attribute, { speed: 'average' }

  field :name, String, null: false, directives: {
    cost: { value: 'FIELD' },
    public: nil
  }
end

class XWing < BaseObject
  implements Spaceship
  add_directive :attribute, { speed: 'fast' }
  add_directive :rebel

  field :name, String, null: false, directives: {
    cost: { value: 'FIELD' },
    public: nil
  }
end

Prints as:

interface Spaceship @attribute(speed: "average") {
  name: String! @cost(value: "FIELD") @public
}

type XWing @attribute(speed: "fast") @rebel {
  name: String! @cost(value: "FIELD") @public
}

Argument & InputObject classes

Base abstracts:

class BaseArgument < GraphQL::Schema::Argument
  include GraphQL::SchemaDirectives::Argument
end

class BaseInputObject < GraphQL::Schema::InputObject
  include GraphQL::SchemaDirectives::InputObject
  argument_class BaseArgument
end

Concrete implementation:

class FormInput < BaseInputObject
  add_directive :oneField
  argument :choice, String, required: true, directives: {
    cost: { value: 'INPUT' },
    public: nil
  }
end

Prints as:

input FormInput @oneField {
  choice: String! @cost(value: "INPUT") @public
}

EnumValue & Enum classes

Base abstracts:

class BaseEnumValue < GraphQL::Schema::EnumValue
  include GraphQL::SchemaDirectives::EnumValue
end

class BaseEnum < GraphQL::Schema::Enum
  include GraphQL::SchemaDirectives::Enum
  enum_value_class BaseEnumValue
end

Concrete implementation:

class FormOption < BaseEnum
  add_directive :dunno
  value 'GET', directives: { cost: { value: 'READ' }, public: nil }
  value 'SET', directives: { cost: { value: 'WRITE' }, public: nil }
end

Prints as:

enum FormOption @dunno {
  GET @cost(value: "READ") @public
  SET @cost(value: "WRITE") @public
}

Other classes

Base abstracts:

class BaseUnion < GraphQL::Schema::Union
  include GraphQL::SchemaDirectives::Union
end

class BaseScalar < GraphQL::Schema::Scalar
  include GraphQL::SchemaDirectives::Scalar
end

Schema from type definitions

You may also parse and print SDLs using the gem's from_definition method:

schema = GraphQL::SchemaDirectives.from_definition(type_defs)
puts schema.print_schema_with_directives

The local from_definition method accepts all the same options as the underlying method. Calling print_schema_with_directives works exactly like the default printer when operating on an unmodified document parse (elements with an original AST will print their schema directives natively).

This feature becomes useful when you start modifying a parsed document with class-based additions:

module Spaceship
  include GraphQL::Schema::Interface
  include GraphQL::SchemaDirectives::Interface
  field :name, String, null: false, directives: { public: nil }
end

type_defs = %(
  type XWing {
    name: String! @public
  }
  type Query {
    ship: XWing
  }
  schema {
    query: Query
  }
)

schema = GraphQL::SchemaDirectives.from_definition(type_defs)
schema.types['XWing'].implements(Spaceship)
puts schema.print_schema_with_directives

Using print_schema_with_directives will include directives from the original AST as well as directives applied to added classes.

Releases

No releases published

Packages

No packages published

Languages