Install Steps if running locally on linux not on Dgraph Cloud:
docker pull dgraph/standalone
mkdir -p ~/dgraph
docker run -it -p 5080:5080 -p 6080:6080 -p 8080:8080 \
-p 9080:9080 -p 8000:8000 -v ~/dgraph:/dgraph --name dgraph \
dgraph/standalone:master
Set your GraphQL Schema:
touch schema.graphql
nano schema.graphql
type Product {
id: ID!
name: String! @id
reviews: [Review] @hasInverse(field: about)
}
type Customer {
username: String! @id
reviews: [Review] @hasInverse(field: by)
}
type Review {
id: ID!
about: Product!
by: Customer!
comment: String @search(by: [fulltext])
rating: Int @search
}
curl -X POST localhost:8080/admin/schema --data-binary '@schema.graphql'
Fire up your favorite GraphQL Client pointed at http://localhost:8080/graphql
and run mutations and queries
mutation {
addProduct(input: [{ name: "Dgraph" }, { name: "Dgraph Cloud" }]) {
product {
id
name
}
}
addCustomer(input: [{ username: "TonyStark" }]) {
customer {
username
}
}
}
mutation {
addReview(
input: [
{
by: { username: "TonyStark" }
about: { name: "Dgraph" }
comment: "Fantastic, easy to install, worked great. Best GraphQL server available"
rating: 10
}
]
) {
review {
id
comment
rating
by {
username
}
about {
id
name
}
}
}
}
query {
queryReview(
filter: { comment: { alloftext: "server easy install" }, rating: { gt: 5 } }
) {
comment
by {
username
reviews(order: { desc: rating }, first: 10) {
about {
name
reviews(order: { asc: rating, first: 5 }) {
by {
username
}
comment
rating
}
}
rating
}
}
about {
name
}
}
}
To run a GraphQL.js
hello world script from the command line:
npm install graphql
Then run node hello.js
with this code in hello.js
:
var { graphql, buildSchema } = require("graphql")
var schema = buildSchema(`
type Query {
hello: String
}
`)
var rootValue = { hello: () => "Hello world!" }
var source = "{ hello }"
graphql({ schema, source, rootValue }).then(response => {
console.log(response)
})
Relay is a JavaScript framework for building data-driven React applications.
To run a hello world server with Apollo Server:
npm install @apollo/server graphql
Then run node server.js
with this code in server.js
:
import { ApolloServer } from "@apollo/server"
import { startStandaloneServer } from "@apollo/server/standalone"
const server = new ApolloServer({
typeDefs,
resolvers,
})
const { url } = await startStandaloneServer(server)
console.log(`🚀 Server ready at ${url}`)
Apollo Server has a built in standalone HTTP server and middleware for Express, and has an framework integration API that supports all Node.js HTTP server frameworks and serverless environments via community integrations.
Apollo Server has a plugin API, integration with Apollo Studio, and performance and security features such as caching, automatic persisted queries, and CSRF prevention.
urql
is a GraphQL client that exposes a set of helpers for several frameworks.
It’s built to be highly customisable and versatile so you can take it from getting started with your first GraphQL project
all the way to building complex apps and experimenting with GraphQL clients.
@urql/exchange-graphcache
The following class is enough to create both a Relay-compatible GraphQL server and a hypermedia API supporting modern REST formats (JSON-LD, JSONAPI…):
<?php
namespace AppEntity;
use ApiPlatformCoreAnnotationApiResource;
use DoctrineORMMapping as ORM;
/**
* Greet someone!
*
* @ApiResource
* @ORMEntity
*/
class Greeting
{
/**
* @ORMId
* @ORMColumn(type="guid")
*/
public $id;
/**
* @var string Your nice message
*
* @ORMColumn
*/
public $hello;
}
Other API Platform features include data validation, authentication, authorization, deprecations, cache and GraphiQL integration.
Request
& Response
objectsTo run a hello world server with graphql-yoga:
npm install graphql-yoga graphql
Then create a server using the createServer
import:
import { createServer } from "http"
import { createSchema, createYoga } from "graphql-yoga"
createServer(
createYoga({
schema: createSchema({
typeDefs: /* GraphQL */ `
type Query {
hello: String
}
`,
resolvers: {
Query: {
hello: () => "Hello Hello Hello",
},
},
}),
}),
).listen(4000, () => {
console.info("GraphQL Yoga is listening on http://localhost:4000/graphql")
})
Depending on your deployment target, you may need to use an additional library. See the documentation for further details.
To run a Graphene hello world script:
pip install graphene
Then run python hello.py
with this code in hello.py
:
import graphene
class Query(graphene.ObjectType):
hello = graphene.String(name=graphene.String(default_value="World"))
def resolve_hello(self, info, name):
return 'Hello ' + name
schema = graphene.Schema(query=Query)
result = schema.execute('{ hello }')
print(result.data['hello']) # "Hello World"
There are also nice bindings for Relay, Django, SQLAlchemy, and Google App Engine.
See the Getting Started tutorial on the GraphQL Java website.
Code that executes a hello world GraphQL query with graphql-java
:
import graphql.ExecutionResult;
import graphql.GraphQL;
import graphql.schema.GraphQLSchema;
import graphql.schema.StaticDataFetcher;
import graphql.schema.idl.RuntimeWiring;
import graphql.schema.idl.SchemaGenerator;
import graphql.schema.idl.SchemaParser;
import graphql.schema.idl.TypeDefinitionRegistry;
import static graphql.schema.idl.RuntimeWiring.newRuntimeWiring;
public class HelloWorld {
public static void main(String[] args) {
String schema = "type Query{hello: String}";
SchemaParser schemaParser = new SchemaParser();
TypeDefinitionRegistry typeDefinitionRegistry = schemaParser.parse(schema);
RuntimeWiring runtimeWiring = newRuntimeWiring()
.type("Query", builder -> builder.dataFetcher("hello", new StaticDataFetcher("world")))
.build();
SchemaGenerator schemaGenerator = new SchemaGenerator();
GraphQLSchema graphQLSchema = schemaGenerator.makeExecutableSchema(typeDefinitionRegistry, runtimeWiring);
GraphQL build = GraphQL.newGraphQL(graphQLSchema).build();
ExecutionResult executionResult = build.execute("{hello}");
System.out.println(executionResult.getData().toString());
// Prints: {hello=world}
}
}
See the graphql-java docs for further information.
using System;
using System.Threading.Tasks;
using GraphQL;
using GraphQL.Types;
using GraphQL.SystemTextJson; // First add PackageReference to GraphQL.SystemTextJson
public class Program
{
public static async Task Main(string[] args)
{
var schema = Schema.For(@"
type Query {
hello: String
}
");
var json = await schema.ExecuteAsync(_ =>
{
_.Query = "{ hello }";
_.Root = new { Hello = "Hello World!" };
});
Console.WriteLine(json);
}
}
fetch
.To run a hello world script with graphql-ruby
:
gem install graphql
Then run ruby hello.rb
with this code in hello.rb
:
require 'graphql'
class QueryType < GraphQL::Schema::Object
field :hello, String
def hello
"Hello world!"
end
end
class Schema < GraphQL::Schema
query QueryType
end
puts Schema.execute('{ hello }').to_json
There are also nice bindings for Relay and Rails.
Strawberry Shake removes the complexity of state management and lets you interact with local and remote data through GraphQL.
You can use Strawberry Shake to:
client.GetHero
.Watch(ExecutionStrategy.CacheFirst)
.Subscribe(result =>
{
Console.WriteLine(result.Data.Name);
})
Hot Chocolate takes the complexity away from building a fully-fledged GraphQL server and lets you focus on delivering the next big thing.
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
WebHost
.CreateDefaultBuilder(args)
.ConfigureServices(services =>
services
.AddGraphQLServer()
.AddQueryType<Query>())
.Configure(builder =>
builder
.UseRouting()
.UseEndpoints(e => e.MapGraphQL()))
.Build()
.Run();
public class Query
{
public Hero GetHero() => new Hero();
}
public class Hero
{
public string Name => "Luke Skywalker";
}
Here’s an example of a Strawberry hello world, first install the library:
pip install strawberry-graphql
Create an app.py
file with this content:
import strawberry
@strawberry.type
class Query:
@strawberry.field
def hello(self, name: str = "World") -> str:
return f"Hello {name}"
schema = strawberry.Schema(query=Query)
Then run strawberry server app
and you will have a basic schema server
running on http://localhost:8000/
.
Strawberry also has views for ASGI, Flask and Django and provides utilities like dataloaders and tracing.
Apollo Kotlin (formerly known as Apollo Android) is a GraphQL client with support for Android, Java8+, iOS and Kotlin multiplatform in general. It features:
GraphQL Shield helps you create a permission layer for your application. Using an intuitive rule-API, you’ll gain the power of the shield engine on every request and reduce the load time of every request with smart caching. This way you can make sure your application will remain quick, and no internal data will be exposed.
import { rule, shield, and, or, not } from "graphql-shield"
// Rules
const isAuthenticated = rule({ cache: "contextual" })(async (
parent,
args,
ctx,
info,
) => {
return ctx.user !== null
})
const isAdmin = rule({ cache: "contextual" })(async (
parent,
args,
ctx,
info,
) => {
return ctx.user.role === "admin"
})
const isEditor = rule({ cache: "contextual" })(async (
parent,
args,
ctx,
info,
) => {
return ctx.user.role === "editor"
})
// Permissions
const permissions = shield({
Query: {
frontPage: not(isAuthenticated),
fruits: and(isAuthenticated, or(isAdmin, isEditor)),
customers: and(isAuthenticated, isAdmin),
},
Mutation: {
addFruitToBasket: isAuthenticated,
},
Fruit: isAuthenticated,
Customer: isAdmin,
})
// Server
const server = new GraphQLServer({
typeDefs,
resolvers,
middlewares: [permissions],
context: req => ({
...req,
user: getUser(req),
}),
})
use async_graphql::*;
struct Query;
#[Object]
impl Query {
/// Returns the sum of a and b
async fn add(&self, a: i32, b: i32) -> i32 {
a + b
}
}
The DGS Framework (Domain Graph Service) is a GraphQL server framework for Spring Boot, developed by Netflix.
Features include:
See DGS Framework Getting Started for how to get started.
To run an hello world script with mercurius
:
npm install fastify mercurius
Then run node app.js
with this code in app.js
:
const Fastify = require("fastify")
const mercurius = require("mercurius")
const schema = `
type Query {
hello(name: String): String!
}
`
const resolvers = {
Query: {
hello: async (_, { name }) => `hello ${name || "world"}`,
},
}
const app = Fastify()
app.register(mercurius, {
schema,
resolvers,
})
app.listen(3000)
// Call IT!
// curl 'http://localhost:3000/graphql' \
// -H 'content-type: application/json' \
// --data-raw '{"query":"{ hello(name:\"Marcurius\") }" }'
GiraphQL makes writing type-safe schemas simple, and works without a code generator, build process, or extensive manual type definitions.
import { ApolloServer } from "apollo-server"
import SchemaBuilder from "@giraphql/core"
const builder = new SchemaBuilder({})
builder.queryType({
fields: t => ({
hello: t.string({
args: {
name: t.arg.string({}),
},
resolve: (parent, { name }) => `hello, ${name || "World"}`,
}),
}),
})
new ApolloServer({
schema: builder.toSchema({}),
}).listen(3000)
WunderGraph composes all your APIs into a single unified GraphQL API and allows you to expose your Graph as a secure and type-safe JSON-RPC API.
To get started with WunderGraph, you can use create-wundergraph-app
to bootstrap a new project:
npx create-wundergraph-app my-project -E nextjs-swr
On the client side, WunderGraph’s JSON-RPC API integrates very well with frameworks like Next.js, SWR and React Query, while one the backend, we’re able to leverage the power of “Server-Side-Only GraphQL”. Handle authentication, authorization, validation, joins and more right in the Query Layer.
mutation (
$name: String! @fromClaim(name: NAME)
$email: String! @fromClaim(name: EMAIL)
$message: String! @jsonSchema(pattern: "^[a-zA-Z 0-9]+$")
) {
createOnepost(
data: {
message: $message
user: {
connectOrCreate: {
where: { email: $email }
create: { email: $email, name: $name }
}
}
}
) {
id
message
user {
id
name
}
}
}
The Query above requires the user to be authenticated, injects the user’s name and email from the JWT token and validates the message against a JSON Schema.
Here’s another example showcasing how we can use Server-Side GraphQL with WunderGraph’s unique join capabilities, composing data from two different APIs into a single GraphQL response.
query (
$continent: String!
# the @internal directive removes the $capital variable from the public API
# this means, the user can't set it manually
# this variable is our JOIN key
$capital: String! @internal
) {
countries_countries(filter: { continent: { eq: $continent } }) {
code
name
# using the @export directive, we can export the value of the field `capital` into the JOIN key ($capital)
capital @export(as: "capital")
# the _join field returns the type Query!
# it exists on every object type so you can everywhere in your Query documents
_join {
# once we're inside the _join field, we can use the $capital variable to join the weather API
weather_getCityByName(name: $capital) {
weather {
temperature {
max
}
summary {
title
description
}
}
}
}
}
}
The full example can be found on GitHub.
Ariadne can be installed with pip:
$ pip install ariadne
Minimal “Hello world” server example:
from ariadne import ObjectType, gql, make_executable_schema
from ariadne.asgi import GraphQL
type_defs = gql(
"""
type Query {
hello: String!
}
"""
)
query_type = ObjectType("Query")
@query_type.field("hello")
def resolve_hello(*_):
return "Hello world!"
schema = make_executable_schema(type_defs, query_type)
app = GraphQL(schema, debug=True)
Run the server with uvicorn:
$ pip install uvicorn
$ uvicorn example:app
Run Schemathesis via Docker against your GraphQL endpoint:
docker run schemathesis/schemathesis \
run https://your.app.com/graphql
Schemathesis will generate queries matching your GraphQL schema and catch server crashes automatically. Generated queries have arbitrary depth and may contain any subset of GraphQL types defined in the input schema. They expose edge cases in your code that are unlikely to be found otherwise.
Note that you can write your app in any programming language; the tool will communicate with it over HTTP.
For example, running the command above against https://bahnql.herokuapp.com/graphql
uncovers that running the { search(searchTerm: "") { stations { name } } }
query leads to a server error:
{
"errors": [
{
"message": "Cannot read property 'city' of undefined",
"locations": [
{
"line": 1,
"column": 28
}
],
"path": ["search", "stations"]
}
],
"data": null
}
An example of a hello world GraphQL schema and query with sangria
:
import sangria.schema._
import sangria.execution._
import sangria.macros._
val QueryType = ObjectType("Query", fields[Unit, Unit](
Field("hello", StringType, resolve = _ ⇒ "Hello world!")
))
val schema = Schema(QueryType)
val query = graphql"{ hello }"
Executor.execute(schema, query) map println
npm install graphql-hooks
First you’ll need to create a client and wrap your app with the provider:
import { GraphQLClient, ClientContext } from "graphql-hooks"
const client = new GraphQLClient({
url: "/graphql",
})
function App() {
return (
<ClientContext.Provider value={client}>
{/* children */}
</ClientContext.Provider>
)
}
Now in your child components you can make use of useQuery
:
import { useQuery } from "graphql-hooks"
const HOMEPAGE_QUERY = `query HomePage($limit: Int) {
users(limit: $limit) {
id
name
}
}`
function MyComponent() {
const { loading, error, data } = useQuery(HOMEPAGE_QUERY, {
variables: {
limit: 10,
},
})
if (loading) return "Loading..."
if (error) return "Something Bad Happened"
return (
<ul>
{data.users.map(({ id, name }) => (
<li key={id}>{name}</li>
))}
</ul>
)
}
GraphQL Kotlin provides a set of lightweight type-safe GraphQL HTTP clients. The library provides Ktor HTTP client and Spring WebClient based reference implementations as well as allows for custom implementations using other engines. Jackson and kotlinx-serialization type-safe data models are generated at build time by the provided Gradle and Maven plugins.
To generate Jackson models that will be used with GraphQL Kotlin Spring WebClient, add following to your Gradle build file:
// build.gradle.kts
import com.expediagroup.graphql.plugin.gradle.graphql
plugins {
id("com.expediagroup.graphql") version $latestGraphQLKotlinVersion
}
dependencies {
implementation("com.expediagroup:graphql-kotlin-spring-client:$latestGraphQLKotlinVersion")
}
graphql {
client {
// target GraphQL endpoint
endpoint = "http://localhost:8080/graphql"
// package for generated client code
packageName = "com.example.generated"
}
}
By default, GraphQL Kotlin plugins will look for query files under src/main/resources
. Given HelloWorldQuery.graphql
sample query:
query HelloWorldQuery {
helloWorld
}
Plugin will generate classes that are simple POJOs implementing GraphQLClientRequest interface and represent a GraphQL request.
package com.example.generated
import com.expediagroup.graphql.client.types.GraphQLClientRequest
import kotlin.String
import kotlin.reflect.KClass
const val HELLO_WORLD_QUERY: String = "query HelloWorldQuery {\n helloWorld\n}"
class HelloWorldQuery: GraphQLClientRequest<HelloWorldQuery.Result> {
override val query: String = HELLO_WORLD_QUERY
override val operationName: String = "HelloWorldQuery"
override fun responseType(): KClass<HelloWorldQuery.Result> = HelloWorldQuery.Result::class
data class Result(
val helloWorld: String
}
}
We can then execute our queries using target client.
package com.example.client
import com.expediagroup.graphql.client.spring.GraphQLWebClient
import com.expediagroup.graphql.generated.HelloWorldQuery
import kotlinx.coroutines.runBlocking
fun main() {
val client = GraphQLWebClient(url = "http://localhost:8080/graphql")
runBlocking {
val helloWorldQuery = HelloWorldQuery()
val result = client.execute(helloWorldQuery)
println("hello world query result: ${result.data?.helloWorld}")
}
}
See graphql-kotlin client docs for additional details.
GraphQL Kotlin follows a code first approach for generating your GraphQL schemas. Given the similarities between Kotlin and GraphQL, such as the ability to define nullable/non-nullable types, a schema can be generated from Kotlin code without any separate schema specification. To create a reactive GraphQL web server add following dependency to your Gradle build file:
// build.gradle.kts
implementation("com.expediagroup", "graphql-kotlin-spring-server", latestVersion)
We also need to provide a list of supported packages that can be scanned for exposing your schema objects through reflections. Add following configuration to your application.yml
file:
graphql:
packages:
- "com.your.package"
With the above configuration we can now create our schema. In order to expose your queries, mutations and/or subscriptions in the GraphQL schema you simply need to implement corresponding marker interface and they will be automatically picked up by graphql-kotlin-spring-server
auto-configuration library.
@Component
class HelloWorldQuery : Query {
fun helloWorld() = "Hello World!!!"
}
This will result in a reactive GraphQL web application with following schema:
type Query {
helloWorld: String!
}
See graphql-kotlin docs for additial details.
The GraphQL Spring Boot turns any Spring Boot application into a GraphQL Server
Started includes features such as:
See GraphQL Java Kickstart Getting Started for how to get started.
Spring for GraphQL provides support for Spring applications built on GraphQL Java. See the official Spring guide for how to build a GraphQL service in 15 minutes.
Features:
@Controller
public class GreetingController {
@QueryMapping
public String hello() {
return "Hello, world!";
}
}
To get started, check the Spring GraphQL starter on https://start.spring.io and the samples in this repository.
Microcks is a platform for turning your API and microservices assets - GraphQL schemas, OpenAPI specs, AsyncAPI specs, gRPC protobuf, Postman collections, SoapUI projects_ - into live simulations in seconds.
It also reuses these assets for running compliance and non-regression tests against your API implementation. We provide integrations with Jenkins, GitHub Actions, Tekton and many others through a simple CLI.
GraphQL Middleware is a schema wrapper which allows you to manage additional functionality across multiple resolvers efficiently.
💡 Easy to use: An intuitive, yet familiar API that you will pick up in a second. 💪 Powerful: Allows complete control over your resolvers (Before, After). 🌈 Compatible: Works with any GraphQL Schema.
const { ApolloServer } = require("apollo-server")
const { makeExecutableSchema } = require("@graphql-tools/schema")
const typeDefs = `
type Query {
hello(name: String): String
bye(name: String): String
}
`
const resolvers = {
Query: {
hello: (root, args, context, info) => {
console.log(`3. resolver: hello`)
return `Hello ${args.name ? args.name : "world"}!`
},
bye: (root, args, context, info) => {
console.log(`3. resolver: bye`)
return `Bye ${args.name ? args.name : "world"}!`
},
},
}
const logInput = async (resolve, root, args, context, info) => {
console.log(`1. logInput: ${JSON.stringify(args)}`)
const result = await resolve(root, args, context, info)
console.log(`5. logInput`)
return result
}
const logResult = async (resolve, root, args, context, info) => {
console.log(`2. logResult`)
const result = await resolve(root, args, context, info)
console.log(`4. logResult: ${JSON.stringify(result)}`)
return result
}
const schema = makeExecutableSchema({ typeDefs, resolvers })
const schemaWithMiddleware = applyMiddleware(schema, logInput, logResult)
const server = new ApolloServer({
schema: schemaWithMiddleware,
})
await server.listen({ port: 8008 })
To run a Siler hello world script:
type Query {
hello: String
}
<?php
declare(strict_types=1);
require_once '/path/to/vendor/autoload.php';
use SilerDiactoros;
use SilerGraphql;
use SilerHttp;
$typeDefs = file_get_contents(__DIR__.'/schema.graphql');
$resolvers = [
'Query' => [
'hello' => 'world',
],
];
$schema = Graphqlschema($typeDefs, $resolvers);
echo "Server running at http://127.0.0.1:8080";
Httpserver(Graphqlpsr7($schema), function (Throwable $err) {
var_dump($err);
return Diactorosjson([
'error' => true,
'message' => $err->getMessage(),
]);
})()->run();
It also provides functionality for the construction of a WebSocket Subscriptions Server based on how Apollo works.
SpectaQL is a Node.js library that generates static documentation for a GraphQL schema using a variety of options:
Out of the box, SpectaQL generates a single 3-column HTML page and lets you choose between a couple built-in themes. A main goal of the project is to be easily and extremely customizable—it is themeable and just about everything can be overridden or customized.
npm install --dev spectaql
# OR
yarn add -D spectaql
# Then generate your docs
npm run spectaql my-config.yml
# OR
yarn spectaql my-config.yml
genqlient is a Go library to easily generate type-safe code to query a GraphQL API. It takes advantage of the fact that both GraphQL and Go are typed languages to ensure at compile-time that your code is making a valid GraphQL query and using the result correctly, all with a minimum of boilerplate.
genqlient provides:
interface{}
.An example of defining a GraphQL query and running it with caliban
:
// define your query using Scala
val query: SelectionBuilder[RootQuery, List[CharacterView]] =
Query.characters {
(Character.name ~ Character.nicknames ~ Character.origin)
.mapN(CharacterView)
}
import sttp.client3._
// run the query and get the result already parsed into a case class
val result = query.toRequest(uri"http://someUrl").send(HttpClientSyncBackend()).body
An example of a simple GraphQL schema and query with caliban
:
import caliban._
import caliban.schema.Schema.auto._
// schema
case class Query(hello: String)
// resolver
val resolver = RootResolver(Query("Hello world!"))
val api = graphQL(resolver)
for {
interpreter <- api.interpreter
result <- interpreter.execute("{ hello }")
} yield result
require 'agoo'
class Query
def hello
'hello'
end
end
class Schema
attr_reader :query
def initialize
@query = Query.new()
end
end
Agoo::Server.init(6464, 'root', thread_count: 1, graphql: '/graphql')
Agoo::Server.start()
Agoo::GraphQL.schema(Schema.new) {
Agoo::GraphQL.load(%^type Query { hello: String }^)
}
sleep
# To run this GraphQL example type the following then go to a browser and enter
# a URL of localhost:6464/graphql?query={hello}
#
# ruby hello.rb
To run a tartiflette hello world script:
pip install tartiflette
Then run python hello.py
with this code in hello.py
:
import asyncio
from tartiflette import Engine, Resolver
@Resolver("Query.hello")
async def resolver_hello(parent, args, ctx, info):
return "hello " + args["name"]
async def run():
tftt_engine = Engine("""
type Query {
hello(name: String): String
}
""")
result = await tftt_engine.execute(
query='query { hello(name: "Chuck") }'
)
print(result)
# {'data': {'hello': 'hello Chuck'}}
if __name__ == "__main__":
loop = asyncio.get_event_loop()
loop.run_until_complete(run())
There is also a nice HTTP wrapper.
graphql-go-tools implements all basic blocks for building GraphQL Servers, Gateways and Proxy Servers. From lexing, parsing, validation, normalization, all the way up to query planning and execution.
It can also be understood as a GraphQL Compiler, with the ability to add your own backends. Just by implementing a few interfaces, you’re able to teach the compiler how to talk GraphQL to any backend.
The following backends are already implemented: GraphQL, with support for Apollo Federation / Supergraph. Databases: PostgreSQL, MySQL, SQLite, CockroachDB, MongoDB, SQLServer, OpenAPI / REST and Kafka.
To get a sense on how to implement a new backend, check out the Static Data Source, as it’s the simplest one.
It’s used in production by many enterprises for multiple years now, battle tested and actively maintained.
SpringBoot has introduced Spring GraphQL since 2.7. Jimmer provides specialized API for rapid development of Spring GraphQL-based applications.
Support two APIs: Java API & kotlin API.
Powerful and GraphQL friendly caching support.
Faster than other popular ORM solutions, please see the bechmark: https://babyfish-ct.github.io/jimmer/docs/benchmark/
More powerful than other popular ORM solutions.
Three aspects should be considered in ORM design:
a. Query. b. Update. c. Cache.
Each aspect is aimed at object trees with arbitrary depth rather than simple objects. This distinctive design brings convenience unmatched by other popular solutions.
Youtube video: https://www.youtube.com/watch?v=Rt5zNv0YR2E
Documentation: https://babyfish-ct.github.io/jimmer/
Project Home: https://github.com/babyfish-ct/jimmer
GraphQL example for Java: https://github.com/babyfish-ct/jimmer/tree/main/example/java/jimmer-sql-graphql
GraphQL example for Kotlin: https://github.com/babyfish-ct/jimmer/tree/main/example/kotlin/jimmer-sql-graphql-kt
SwiftGraphQL is a Swift code generator and a lightweight GraphQL client. It lets you create queries using Swift, and guarantees that every query you create is valid.
The library is centered around three core principles:
🚀 If your project compiles, your queries work. 🦉 Use Swift in favour of GraphQL wherever possible. 🌳 Your application model should be independent of your schema.
Here’s a short preview of the SwiftGraphQL code
import SwiftGraphQL
// Define a Swift model.
struct Human: Identifiable {
let id: String
let name: String
let homePlanet: String?
}
// Create a selection.
let human = Selection.Human {
Human(
id: try $0.id(),
name: try $0.name(),
homePlanet: try $0.homePlanet()
)
}
// Construct a query.
let query = Selection.Query {
try $0.humans(human.list)
}
// Perform the query.
send(query, to: "http://swift-graphql.heroku.com") { result in
if let data = try? result.get() {
print(data) // [Human]
}
}
It is framework agnostic with bindings available for Symfony and Laravel. This code declares a “product” query and a “Product” Type:
class ProductController
{
/**
* @Query()
*/
public function product(string $id): Product
{
// Some code that looks for a product and returns it.
}
}
/**
* @Type()
*/
class Product
{
/**
* @Field()
*/
public function getName(): string
{
return $this->name;
}
// ...
}
Other GraphQLite features include validation, security, error handling, loading via data-loader pattern…
Run gqt
against your GraphQL endpoint. Build your query in an
intuitive TUI and execute it. The response from the server is written
to standard output.
gqt -e https://your.app.com/graphql
Hello world example with morpheus-graphql
:
# schema.gql
"""
A supernatural being considered divine and sacred
"""
type Deity {
name: String!
power: String @deprecated(reason: "no more supported")
}
type Query {
deity(name: String! = "Morpheus"): Deity!
}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeFamilies #-}
module API (api) where
import Data.ByteString.Lazy.Char8 (ByteString)
import Data.Morpheus (interpreter)
import Data.Morpheus.Document (importGQLDocument)
import Data.Morpheus.Types (RootResolver (..), Undefined (..))
import Data.Text (Text)
importGQLDocument "schema.gql"
rootResolver :: RootResolver IO () Query Undefined Undefined
rootResolver =
RootResolver
{ queryResolver = Query {deity},
mutationResolver = Undefined,
subscriptionResolver = Undefined
}
where
deity DeityArgs {name} =
pure
Deity
{ name = pure name,
power = pure (Just "Shapeshifting")
}
api :: ByteString -> IO ByteString
api = interpreter rootResolver
See morpheus-graphql-examples for more sophisticated APIs.
// expose an exisiting data model with ASP.NET & EF Core
public class Startup {
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<DemoContext>();
// Auto build a schema from DemoContext. Alternatively you can build one from scratch
services.AddGraphQLSchema<DemoContext>(options =>
{
// modify the schema (add/remove fields or types), add other services
});
}
public void Configure(IApplicationBuilder app, DemoContext db)
{
app.UseRouting();
app.UseEndpoints(endpoints =>
{
// defaults to /graphql endpoint
endpoints.MapGraphQL<DemoContext>();
});
}
}
A client library for rust that generates queries from types you provide, verifying that the types match the shape of your schema.
It provides a generator to bootstrap types from existing GraphQL queries.
Usage example:
#[derive(cynic::QueryFragment, Debug)]
#[cynic(
schema_path = "../schemas/starwars.schema.graphql",
query_module = "query_dsl",
graphql_type = "Root",
argument_struct = "FilmArguments"
)]
struct FilmDirectorQuery {
#[arguments(id = &args.id)]
film: Option<Film>,
}
#[derive(cynic::QueryFragment, Debug)]
#[cynic(
schema_path = "../schemas/starwars.schema.graphql",
query_module = "query_dsl",
graphql_type = "Film"
)]
struct Film {
title: Option<String>,
director: Option<String>,
}
#[derive(cynic::FragmentArguments)]
struct FilmArguments {
id: Option<cynic::Id>,
}
fn main() {
use cynic::{QueryBuilder, http::ReqwestBlockingExt};
let query = FilmDirectorQuery::build(&FilmArguments {
id: Some("ZmlsbXM6MQ==".into()),
})
reqwest::blocking::Client::new()
.post("https://swapi-graphql.netlify.com/.netlify/functions/index")
.run_graphql(query)
.unwrap()
}
mod query_dsl {
cynic::query_dsl!("../schemas/starwars.schema.graphql");
}
Example implementation of a GraphQL server with type-level representation of the schema auto-generated:
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE PartialTypeSignatures #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
-- imports omitted for brevity...
graphql "Library" "library.graphql" -- all the magic happens here! 🪄🎩
-- ... a bit more code...
libraryServer :: SqlBackend -> ServerT ObjectMapping i Library ServerErrorIO _
libraryServer conn =
resolver
( object @"Book"
( field @"id" bookId,
field @"title" bookTitle,
field @"author" bookAuthor,
field @"imageUrl" bookImage
),
object @"Author"
( field @"id" authorId,
field @"name" authorName,
field @"books" authorBooks
),
object @"Query"
( method @"authors" allAuthors,
method @"books" allBooks
),
object @"Mutation"
( method @"newAuthor" newAuthor,
method @"newBook" newBook
),
object @"Subscription"
(method @"allBooks" allBooksConduit)
)
where
bookId :: Entity Book -> ServerErrorIO Integer
bookId (Entity (BookKey k) _) = pure $ toInteger k
-- ... more resolvers...
See our docs for more information about how to build your own GraphQL server and the library example for a more end-to-end example that includes a client written in Elm!
Here’s an example on how to create a simple schema based on a kotlin data class plus a property resolver that gets applied onto your class.
data class Article(val id: Int, val text: String)
fun main() {
val schema = KGraphQL.schema {
query("article") {
resolver { id: Int?, text: String ->
Article(id ?: -1, text)
}
}
type<Article> {
property<String>("fullText") {
resolver { article: Article ->
"${article.id}: ${article.text}"
}
}
}
}
schema.execute("""
{
article(id: 5, text: "Hello World") {
id
fullText
}
}
""").let(::println)
}
KGraphQL is using coroutines behind the scenes to provide great asynchronous performance.
See KGraphQL docs for more in depth usage.
KGraphQL has a Ktor plugin which gives you a fully functional GraphQL server with a single install function call. Example below shows how to set up a GraphQL server within Ktor and it will give you a GraphQL Playground out of the box by entering localhost:8080/graphql
.
fun Application.module() {
install(GraphQL) {
playground = true
schema {
query("hello") {
resolver { -> "World!" }
}
}
}
}
You can follow the Ktor tutorial to set up a KGraphQL server with ktor from scratch up.
Code that executes a hello world GraphQL query with graphql-clj
:
(def schema "type QueryRoot {
hello: String
}")
(defn resolver-fn [type-name field-name]
(get-in {"QueryRoot" {"hello" (fn [context parent & rest]
"Hello world!")}}
[type-name field-name]))
(require '[graphql-clj.executor :as executor])
(executor/execute nil schema resolver-fn "{ hello }")
The ZeroQL is a high-performance C#-friendly GraphQL client. It supports Linq-like syntax, and doesn’t require Reflection.Emit or expressions. As a result, at runtime provides performance very close to a raw HTTP call.
You can use ZeroQL to:
var userId = 10;
var response = await qlClient.Query(q => q
.User(userId, o => new
{
o.Id,
o.FirstName,
o.LastName
}));
Install Ariadne Codegen:
$ pip install ariadne-codegen
Create queries.graphql
file:
mutation CreateToken($username: String!, $password: String!) {
createToken(username: $username, password: $password) {
token
errors {
field
message
}
}
}
Add [ariadne-codegen]
section to your pyproject.toml
:
[ariadne-codegen]
queries_path = "queries.graphql"
remote_schema_url = "http://example.com/graphql/"
Generate client:
$ ariadne-codegen
And use it in your Python projects:
from graphql_client import Client
with Client("http://example.com/graphql/") as client:
result = client.create_token(username="Admin", password="Example123)
if result.errors:
error = result.errors[0]
raise ValidationError({error.field: error.message})
auth_token = result.token
require 'rails-graphql'
class GraphQL::AppSchema < GraphQL::Schema
query_fields do
field(:hello).resolve { 'Hello World!' }
end
end
puts GraphQL::AppSchema.execute('{ hello }')
Less is more! Please check it out the docs.
(require '[alumbra.core :as alumbra]
'[claro.data :as data])
(def schema
"type Person { name: String!, friends: [Person!]! }
type QueryRoot { person(id: ID!): Person, me: Person! }
schema { query: QueryRoot }")
(defrecord Person [id]
data/Resolvable
(resolve! [_ _]
{:name (str "Person #" id)
:friends (map ->Person (range (inc id) (+ id 3)))}))
(def QueryRoot
{:person (map->Person {})
:me (map->Person {:id 0})})
(def app
(alumbra/handler
{:schema schema
:query QueryRoot}))
(defonce my-graphql-server
(aleph.http/start-server #'app {:port 3000}))
$ curl -XPOST "http://0:3000" -H'Content-Type: application/json' -d'{
"query": "{ me { name, friends { name } } }"
}'
{"data":{"me":{"name":"Person #0","friends":[{"name":"Person #1"},{"name":"Person #2"}]}}}
To run a ballerina-graphql
client:
bal run graphql_client.bal
to run the service, with this code in the graphql_client.bal
file:import ballerina/graphql;
import ballerina/io;
type Response record {
record { string hello; } data;
};
public function main() returns error? {
graphql:Client helloClient = check new ("localhost:9090/graphql");
string document = "{ hello }";
Response response = check helloClient->execute(document);
io:println(response.data.hello);
}
To run a ballerina-graphql
hello world server:
bal run graphql_service.bal
to run the service, with this code in the graphql_service.bal
file:import ballerina/graphql;
service /graphql on new graphql:Listener(9090) {
resource function get hello() returns string {
return "Hello, world!";
}
}
service
and listener
model, which are first-class citizens in BallerinaGraphQL Calculator is a lightweight graphql calculation engine, which is used to alter execution behavior of graphql query.
Here are some examples on how to use GraphQL Calculator on graphql query.
query basicMapValue($userIds: [Int]) {
userInfoList(userIds: $userIds) {
id
age
firstName
lastName
fullName: stringHolder @map(mapper: "firstName + lastName")
}
}
query filterUserByAge($userId: [Int]) {
userInfoList(userIds: $userId) @filter(predicate: "age>=18") {
userId
age
firstName
lastName
}
}
query parseFetchedValueToAnotherFieldArgumentMap($itemIds: [Int]) {
itemList(itemIds: $itemIds) {
# save sellerId as List<Long> with unique name "sellerIdList"
sellerId @fetchSource(name: "sellerIdList")
name
saleAmount
salePrice
}
userInfoList(userIds: 1)
# transform the argument of "userInfoList" named "userIds" according to expression "sellerIdList" and expression argument,
# which mean replace userIds value by source named "sellerIdList"
@argumentTransform(
argumentName: "userIds"
operateType: MAP
expression: "sellerIdList"
dependencySources: ["sellerIdList"]
) {
userId
name
age
}
}
See graphql-calculator README for more information.
MicroProfile GraphQL is a GraphQL server and client specification for building GraphQL applications. It’s unique annotation-based API approach enables rapid application development. Applications coded to the MP GraphQL APIs are portable, and can be deployed into Java server runtimes such as Open Liberty, Quarkus, Helidon and Wildfly. This means that your applications can make use of other Jakarta and MicroProfile technologies.
MP GraphQL features include:
Want to get started? Check out these resouces:
Or these videos:
Core Library - The GORM GraphQL library provides functionality to generate a GraphQL schema based on your GORM entities. In addition to mapping domain classes to a GraphQL schema, the core library also provides default implementations of “data fetchers” to query, update, and delete data through executions of the schema.
Grails Plugin - In a addition to the Core Library, the GORM GraphQL Grails Plugin:
Provides a controller to receive and respond to GraphQL requests through HTTP, based on their guidelines.
Generates the schema at startup with spring bean configuration to make it easy to extend.
Includes a GraphiQL browser enabled by default in development. The browser is accessible at /graphql/browser.
Overrides the default data binder to use the data binding provided by Grails
Provides a trait to make integration testing of your GraphQL endpoints easier
See the documentation for more information.
Mojolicious-Plugin-GraphQL - connect your GraphQL service to a Mojolicious app
GraphQL-Plugin-Convert-DBIC - automatically connect your DBIx::Class schema to GraphQL
GraphQL-Plugin-Convert-OpenAPI - automatically connect any OpenAPI service (either local Mojolicious one, or remote) to GraphQL
Usage example
use gql_client::Client;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let endpoint = "https://graphqlzero.almansi.me/api";
let query = r#"
query AllPostsQuery {
posts {
data {
id
}
}
}
"#;
let client = Client::new(endpoint);
let data: AllPosts = client.query::<AllPosts>(query).await.unwrap();
println!("{:?}" data);
Ok(())
}
Install with Julia’s package manager
using Pkg; Pkg.add("GraphQLClient")
using GraphQLClient
Connect to a server
client = Client("https://countries.trevorblades.com")
Build a Julia type from a GraphQL object
Country = GraphQLClient.introspect_object(client, "Country")
And query the server, deserializing the response into this new type
response = query(client, "countries", Vector{Country}, output_fields="name")
Alternatively write the query string manually
query_string = """
{
countries{
name
}
}"""
response = GraphQLClient.execute(client, query_string)
graphql_query is complete GraphQL query string builder for python. With graphql_query you can The documentation for graphql_query can be found at https://denisart.github.io/graphql-query.
$ pip install graphql_query
Code for the simple query
{
hero {
name
}
}
it is
from graphql_query import Operation, Query
hero = Query(name="hero", fields=["name"])
operation = Operation(type="query", queries=[hero])
print(operation.render())
"""
query {
hero {
name
}
}
"""
For generation of the following query
query Hero($episode: Episode, $withFriends: Boolean!) {
hero(episode: $episode) {
name
friends @include(if: $withFriends) {
name
}
}
}
we have
from graphql_query import Argument, Directive, Field, Operation, Query, Variable
episode = Variable(name="episode", type="Episode")
withFriends = Variable(name="withFriends", type="Boolean!")
arg_episode = Argument(name="episode", value=episode)
arg_if = Argument(name="if", value=withFriends)
hero = Query(
name="hero",
arguments=[arg_episode],
fields=[
"name",
Field(
name="friends",
fields=["name"],
directives=[Directive(name="include", arguments=[arg_if])]
)
]
)
operation = Operation(
type="query",
name="Hero",
variables=[episode, withFriends],
queries=[hero]
)
print(operation.render())
"""
query Hero(
$episode: Episode
$withFriends: Boolean!
) {
hero(
episode: $episode
) {
name
friends @include(
if: $withFriends
) {
name
}
}
}
"""
Here’s an example of a qlient hello world.
first install the library:
pip install qlient
Create a swapi_client_example.py
file with this content:
from qlient.http import HTTPClient, GraphQLResponse
client = HTTPClient("https://swapi-graphql.netlify.app/.netlify/functions/index")
res: GraphQLResponse = client.query.film(
# swapi graphql input fields
id="ZmlsbXM6MQ==",
# qlient specific
_fields=["id", "title", "episodeID"]
)
print(res.request.query) # query film($id: ID) { film(id: $id) { id title episodeID } }
print(res.request.variables) # {'id': 'ZmlsbXM6MQ=='}
print(res.data) # {'film': {'id': 'ZmlsbXM6MQ==', 'title': 'A New Hope', 'episodeID': 4}}
Close the file and run it using python:
python swapi_client_example.py
GraPHPinator is feature complete PHP implementation of GraphQL server. Its job is transformation of query string into resolved Json result for a given Schema.
array
s, no mixed types, no variable function arguments - this library doesnt try to save you from verbosity, but makes sure you always know what you’ve got.The purpose of Eggql is to make it as simple as possible to create a GraphQL server. You don’t need to create GraphQL schema (though you can view the schema that is created if interested). It is currently in beta release but is a complete implementation of a GraphQL server apart from subscriptions.
Just to be clear it supports all of these GraphQL features: arguments (including defaults), objects/lists/enums/input/interface/union types, aliases, fragments, variables, directives, mutations, inline fragments, descriptions, introspection and custom scalars.
Tests (jMeter) show that it is as fast or faster than other Go implementations for simple queries. We’re working on enhancements for performance including caching, data-loader, complexity-limits, etc.
To run an eggql
hello world server just build and run this Go program:
package main
import "github.com/andrewwphillips/eggql"
func main() {
http.Handle("/graphql", eggql.New(struct{ Message string }{Message: "hello, world"}))
http.ListenAndServe(":80", nil)
}
This creates a root Query object with a single message
field. To test it send a query with curl:
$ curl -XPOST -d '{"query": "{ message }"}' localhost:80/graphql
and you will get this response:
{
"data": {
"message": "hello, world"
}
}
Microfiber is a JavaScript library that allows:
npm install microfiber
# OR
yarn add microfiber
Then in JS:
import { Microfiber } from 'microfiber'
const introspectionQueryResults = {...}
const microfiber = new Microfiber(introspectionQueryResults)
// ...do some things to your schema with `microfiber`
const cleanedIntrospectonQueryResults = microfiber.getResponse()
The example below installs and initializes the GraphQLBox client with a persisted cache and debugging enabled.
npm install @graphql-box/core @graphql-box/client @graphql-box/request-parser @graphql-box/cache-manager @graphql-box/debug-manager @graphql-box/fetch-manager @graphql-box/helpers @cachemap/core @cachemap/reaper @cachemap/indexed-db @cachemap/constants @cachemap/types
import Cachemap from "@cachemap/core"
import indexedDB from "@cachemap/indexed-db"
import reaper from "@cachemap/reaper"
import CacheManager from "@graphql-box/cache-manager"
import Client from "@graphql-box/client"
import DebugManager from "@graphql-box/debug-manager"
import FetchManager from "@graphql-box/fetch-manager"
import RequestParser from "@graphql-box/request-parser"
import introspection from "./introspection-query"
const requestManager = new FetchManager({
apiUrl: "/api/graphql",
batchRequests: true,
logUrl: "/log/graphql",
})
const client = new Client({
cacheManager: new CacheManager({
cache: new Cachemap({
name: "client-cache",
reaper: reaper({ interval: 300000 }),
store: indexedDB(/* configure */),
}),
cascadeCacheControl: true,
typeCacheDirectives: {
// Add any type specific cache control directives in the format:
// TypeName: "public, max-age=3",
},
}),
debugManager: new DebugManager({
environment: "client",
log: (message, data, logLevel) => {
requestManager.log(message, data, logLevel)
},
name: "CLIENT",
performance: self.performance,
}),
requestManager,
requestParser: new RequestParser({ introspection }),
})
// Meanwhile... somewhere else in your code
const { data, errors } = await client.request(queryOrMutation)
The example below installs and initializes the GraphQLBox server with a persisted cache and debugging enabled.
npm install @graphql-box/core @graphql-box/server @graphql-box/client @graphql-box/request-parser @graphql-box/cache-manager @graphql-box/debug-manager @graphql-box/execute @graphql-box/helpers @cachemap/core @cachemap/reaper @cachemap/redis @cachemap/constants @cachemap/types
import Cachemap from "@cachemap/core"
import redis from "@cachemap/redis"
import reaper from "@cachemap/reaper"
import CacheManager from "@graphql-box/cache-manager"
import Client from "@graphql-box/client"
import DebugManager from "@graphql-box/debug-manager"
import Execute from "@graphql-box/execute"
import RequestParser from "@graphql-box/request-parser"
import Server from "@graphql-box/server"
import { makeExecutableSchema } from "@graphql-tools/schema"
import { performance } from "perf_hooks"
import { schemaResolvers, schemaTypeDefs } from "./schema"
import logger from "./logger"
const schema = makeExecutableSchema({
typeDefs: schemaTypeDefs,
resolvers: schemaResolvers,
})
const server = new Server({
client: new Client({
cacheManager: new CacheManager({
cache: new Cachemap({
name: "server-cache",
reaper: reaper({ interval: 300000 }),
store: redis(/* configure */),
}),
cascadeCacheControl: true,
typeCacheDirectives: {
// Add any type specific cache control directives in the format:
// TypeName: "public, max-age=3",
},
}),
debugManager: new DebugManager({
environment: "server",
log: (...args) => {
logger.log(...args)
},
name: "SERVER",
performance,
}),
requestManager: new Execute({ schema }),
requestParser: new RequestParser({ schema }),
}),
})
// Meanwhile... somewhere else in your code
app.use("api/graphql", graphqlServer.request())
One time setup: build schema, deploy as microservice or within server, query SQL database with GraphQL!
A Quickstart for Django Graphbox:
pip install django-graphbox
django-admin startproject myproject
cd myproject
python manage.py startapp myapp
myapp/models.py
:from django.db import models
class MyModel(models.Model):
name = models.CharField(max_length=100)
python manage.py makemigrations
python manage.py migrate
myapp/schema.py
:from django_graphbox.builder import SchemaBuilder
from myapp.models import MyModel
builder = SchemaBuilder()
builder.add_model(MyModel)
query_class = builder.build_schema_query()
mutation_class = builder.build_schema_mutation()
myproject/schema.py
(In this main schema you can add your own queries and mutations):import graphene
from myapp.schema import query_class, mutation_class
class Query(query_class, graphene.ObjectType):
pass
class Mutation(mutation_class, graphene.ObjectType):
pass
schema = graphene.Schema(query=Query, mutation=Mutation)
myproject/urls.py
:from django.urls import path
from graphene_file_upload.django import FileUploadGraphQLView
from django.views.decorators.csrf import csrf_exempt
from myproject.schema import schema
urlpatterns = [
path('graphql/', csrf_exempt(FileUploadGraphQLView.as_view(graphiql=True, schema=schema))),
]
python manage.py runserver
http://localhost:8000/graphql/
and start querying your API!You can find advanced examples with authentication, filters, validations and more on github or pypi.
Brangr - Browse Any Graph
Brangr is a simple, unique tool that any web server can host to provide a user-friendly browser/viewer for any GraphQL service (or many).
Brangr formats GraphQL results attractively, via a selection of user-configurable layouts. It lets users extract the generated HTML, and its source JSON. It provides a clever schema browser. It has built-in docs.
Brangr enables sites hosting it to present users with a collection of pre-fab GraphQL requests, which they can edit if desired, and let them create their own requests. And it allows sites to define custom CSS styling for all aspects of the formatted results.
Try it at the public Brangr site.
Example
query {
<!-- prettier-ignore -->
heroes(_layout: { type: table }) { # _layout arg not sent to service
first
last
}
}
Brangr renders the above query as follows (though not in a quote block):
heroes...
First Last Arthur Dent Ford Prefect Zaphod Beeblebrox