Schema Definition Language

Defining Schema in IDL/SDL can greatly speed up and simplify code base.

Load schema from SDL

SchemaBuilder class has an extension method for loading types from SDL strings or GraphQL documents.

Schema


        [Fact]
        public void Parse_Document_as_Schema()
        {
            /* Given */
            var idl = @"
                type Query {
                }

                type Mutation {
                }

                type Subscription {

                }

                schema {
                  query: Query
                  mutation: Mutation
                  subscription: Subscription
                }";

            var document = Parser.ParseDocument(idl);

            /* When */
            var actual = new SchemaBuilder().Sdl(document)
                .Build();

            /* Then */
            Assert.NotNull(actual);
            Assert.NotNull(actual.Query);
            Assert.NotNull(actual.Mutation);
            Assert.NotNull(actual.Subscription);
        }

Types


        [Fact]
        public void Parse_Document_with_types()
        {
            /* Given */
            var idl = @"
                scalar JediPowerLevel
                scalar JediTrickLevel

                enum Episode { NEWHOPE, EMPIRE, JEDI }

                interface Character {
                  id: String!
                  name: String
                  friends: [Character]
                  appearsIn: [Episode]
                }

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

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

                input JediPowerInput {
                    power: String
                    level: JediPowerLevel
                }

                type Query {
                }
                schema {
                    query: Query
                }
                ";

            var jediPowerLevel = new ScalarType("JediPowerLevel", new IntConverter());
            var jediTrickLevel = new ScalarType("JediTrickLevel", new DoubleConverter());

            var document = Parser.ParseDocument(idl);
            var reader = new SdlReader(document, new SchemaBuilder()
                .Include(jediPowerLevel)
                .Include(jediTrickLevel));

            /* When */
            var schema = reader.Read().Build();
            var actual = schema.QueryTypes<INamedType>();

            /* Then */
            Assert.Contains(actual, type => type.Name == "Episode" && type is EnumType);
            Assert.Contains(actual, type => type.Name == "Character" && type is InterfaceType);
            Assert.Contains(actual, type => type.Name == "Human" && type is ObjectType);
            Assert.Contains(actual, type => type.Name == "Droid" && type is ObjectType);
            Assert.Contains(actual, type => type.Name == "JediPowerInput" && type is InputObjectType);
            Assert.Contains(actual, type => type.Name == "JediPowerLevel" && type.GetType() == typeof(ScalarType));
            Assert.Contains(actual, type => type.Name == "JediTrickLevel" && type.GetType() == typeof(ScalarType));

            var jediPowerInput = (InputObjectType) actual.Single(t => t.Name == "JediPowerInput");
            var level = schema.GetInputField(jediPowerInput.Name, "level");
            Assert.Equal(jediPowerLevel, level.Type);
        }

Custom scalars

        [Fact]
        public void Parse_custom_scalar()
        {
            /* Given */
            var idl = @"
                scalar Url

                type Query {
                }
                schema {
                    query: Query
                }
                ";
            var urlScalar = new ScalarType("Url", new StringConverter());
            var document = Parser.ParseDocument(idl);
            var reader = new SdlReader(document, new SchemaBuilder()
                .Include(urlScalar));


            /* When */
            var actual = reader.Read().Build().GetNamedType<ScalarType>("Url");

            /* Then */
            Assert.Equal("Url", actual.Name);
            Assert.Equal(urlScalar, actual);
        }

Types can be extended


        [Fact]
        public void Parse_ObjectType_with_extension()
        {
            /* Given */
            var idl = @"
                extend type Human {
                    second: Boolean
                }

                type Human {
                    first: Int
                }

                type Query {
                }
                schema {
                    query: Query
                }
                ";

            var document = Parser.ParseDocument(idl);

            /* When */
            var actual = new SchemaBuilder().Sdl(document).Build();

            /* Then */
            var human = actual.GetNamedType<ObjectType>("Human");
            var humanFields = actual.GetFields(human.Name);

            Assert.NotNull(human);
            Assert.Equal("Human", human.Name);
            Assert.Single(humanFields, f => f.Key == "first");
            Assert.Single(humanFields, f => f.Key == "second");
        }