Skip to content

Commit

Permalink
Merge pull request #29 from rigglo/docs
Browse files Browse the repository at this point in the history
Docs + Apollo Federation
  • Loading branch information
Fontinalis authored Sep 11, 2020
2 parents d56b61e + 4f06f05 commit 1e904de
Show file tree
Hide file tree
Showing 30 changed files with 2,472 additions and 681 deletions.
30 changes: 25 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# gql

![tests](https://github.com/rigglo/gql/workflows/tests/badge.svg)
[![go.dev reference](https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white)](https://pkg.go.dev/github.com/rigglo/gql)
[![PkgGoDev](https://pkg.go.dev/badge/github.com/rigglo/gql)](https://pkg.go.dev/github.com/rigglo/gql)
[![Coverage Status](https://coveralls.io/repos/github/rigglo/gql/badge.svg?branch=master)](https://coveralls.io/github/rigglo/gql?branch=master)

**Note: As the project is still in WIP, there can be breaking changes which may break previous versions.**
Expand All @@ -13,20 +13,26 @@ This project aims to fulfill some of the most common feature requests missing fr
- [x] Custom scalars
- [x] Extensions
- [x] Subscriptions
- [x] Apollo Federation
- [ ] Custom directives
- [x] Field directives
- [ ] Executable directives
- [ ] Type System directives
- [ ] Opentracing
- [ ] Query complexity
- [ ] Apollo File Upload
- [ ] Apollo Federation
- [ ] Custom validation for input and arguments
- [ ] Access to the requested fields in a resolver
- [ ] Custom rules-based introspection
- [ ] Converting structs into GraphQL types
- [ ] Parse inputs into structs

## Examples

There are examples in the `examples` folder, these are only uses this `gql` package, they don't have any other dependencies.

Additional examples can be found for Apollo Federation, Subscriptions in the [rigglo/gql-examples](https://github.com/rigglo/gql-examples) repository.

## Getting started

Defining a type, an object is very easy, let's visit a pizzeria as an example.
Expand Down Expand Up @@ -89,8 +95,8 @@ var PizzeriaSchema = &gql.Schema{

At this point, what's only left is an executor, so we can run our queries, and a handler to be able to serve our schema.

For our example, let's use the default executor, but if you want to experiment, customise it, add extensions, you can create your own the gql.NewExecutor function. 
Let's fire up our handler using the github.com/rigglo/gql/pkg/handler package and also enable the playground, so we can check it from our browser.
For our example, let's use the default executor, but if you want to experiment, customise it, add extensions, you can create your own the `gql.NewExecutor` function. 
Let's fire up our handler using the `github.com/rigglo/gql/pkg/handler` package and also enable the playground, so we can check it from our browser.

```go
func main() {
Expand All @@ -104,4 +110,18 @@ func main() {
}
```

After running the code, you can go to the http://localhost:9999/graphql address in your browser and see the GraphQL Playground, and you can start playing with it.
After running the code, you can go to the http://localhost:9999/graphql address in your browser and see the GraphQL Playground, and you can start playing with it.

### NOTES

#### Directives

Adding directives in the type system is possible, but currently only the field directives are being executed.

#### Apollo Federation

The support for Apollo Federation is provided by the `github.com/rigglo/gql/pkg/federation` package, which adds the required fields, types and directives to your schema.

#### SDL

The support for generating SDL from the Schema is not production ready, in most cases it's enough, but it requires some work, use it for your own risk.
50 changes: 38 additions & 12 deletions directives.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,37 @@ type Directive interface {
GetLocations() []DirectiveLocation
}

/*
type ExecutableDirective interface {
// any Executable Directive specific function comes here
}
*/

type TypeSystemDirective interface {
Directive
GetValues() map[string]interface{}
}

func (ds TypeSystemDirectives) ast() []*ast.Directive {
out := []*ast.Directive{}
for _, d := range ds {
od := ast.Directive{
Name: d.GetName(),
Arguments: make([]*ast.Argument, 0),
}
for an, a := range d.GetArguments() {
od.Arguments = append(od.Arguments, &ast.Argument{
Name: an,
Value: toAstValue(a.Type, d.GetValues()[an]),
})
}
out = append(out, &od)
}
return out
}

type TypeSystemDirectives []TypeSystemDirective

type DirectiveLocation string

const (
Expand Down Expand Up @@ -43,57 +74,46 @@ const (

type SchemaDirective interface {
VisitSchema(context.Context, Schema) *Schema
Variables() map[string]interface{}
}

type ScalarDirective interface {
VisitScalar(context.Context, Scalar) *Scalar
Variables() map[string]interface{}
}

type ObjectDirective interface {
VisitObject(context.Context, Object) *Object
Variables() map[string]interface{}
}

type FieldDefinitionDirective interface {
VisitFieldDefinition(context.Context, Field, Resolver) Resolver
Variables() map[string]interface{}
}

type ArgumentDirective interface {
VisitArgument(context.Context, Argument)
Variables() map[string]interface{}
}

type InterfaceDirective interface {
VisitInterface(context.Context, Interface) *Interface
Variables() map[string]interface{}
}

type UnionDirective interface {
VisitUnion(context.Context, Union) *Union
Variables() map[string]interface{}
}

type EnumDirective interface {
VisitEnum(context.Context, Enum) *Enum
Variables() map[string]interface{}
}

type EnumValueDirective interface {
VisitEnumValue(context.Context, EnumValue) *EnumValue
Variables() map[string]interface{}
}

type InputObjectDirective interface {
VisitInputObject(context.Context, InputObject) *InputObject
Variables() map[string]interface{}
}

type InputFieldDirective interface {
VisitInputField(context.Context, InputField) *InputField
Variables() map[string]interface{}
}

type skip struct{}
Expand Down Expand Up @@ -162,7 +182,7 @@ func (s *include) Include(args []*ast.Argument) bool {
return false
}

func Deprecate(reason string) Directive {
func Deprecate(reason string) TypeSystemDirective {
return &deprecated{reason}
}

Expand Down Expand Up @@ -198,6 +218,12 @@ func (d *deprecated) Reason() string {
return d.reason
}

func (d *deprecated) GetValues() map[string]interface{} {
return map[string]interface{}{
"reason": d.reason,
}
}

var (
skipDirective = &skip{}
includeDirective = &include{}
Expand Down
Empty file added docs/.nojekyll
Empty file.
107 changes: 107 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
# About gql

![tests](https://github.com/rigglo/gql/workflows/tests/badge.svg)
[![PkgGoDev](https://pkg.go.dev/badge/github.com/rigglo/gql)](https://pkg.go.dev/github.com/rigglo/gql)
[![Coverage Status](https://coveralls.io/repos/github/rigglo/gql/badge.svg?branch=master)](https://coveralls.io/github/rigglo/gql?branch=master)

**Note: As the project is still in WIP, there can be breaking changes which may break previous versions.**

This project aims to fulfill some of the most common feature requests missing from existing packages, or ones that could be done differently.

## Roadmap for the package

- [x] Custom scalars
- [x] Extensions
- [x] Subscriptions
- [ ] Custom directives
- [x] Field directives
- [ ] Executable directives
- [ ] Type System directives
- [ ] Opentracing
- [ ] Query complexity
- [ ] Apollo File Upload
- [ ] Apollo Federation
- [ ] Custom validation for input and arguments
- [ ] Access to the requested fields in a resolver
- [ ] Custom rules-based introspection
- [ ] Converting structs into GraphQL types
- [ ] Parse inputs into structs

## Getting started

Defining a type, an object is very easy, let's visit a pizzeria as an example.

```go
var PizzaType = &gql.Object{
Name: "Pizza",
Fields: gql.Fields{
"id": &gql.Field{
Description: "id of the pizza",
Type: gql.ID,
},
"name": &gql.Field{
Description: "name of the pizza",
Type: gql.String,
},
"size": &gql.Field{
Description: "size of the pizza (in cm)",
Type: gql.Int,
},
},
}
```

Next, we need a way to get our pizza, to list them, so let's define the query.

```go
var RootQuery = &gql.Object{
Name: "RootQuery",
Fields: gql.Fields{
"pizzas": &gql.Field{
Description: "lists all the pizzas",
Type: gql.NewList(PizzaType),
Resolver: func(ctx gql.Context) (interface{}, error) {
return []Pizza{
Pizza{
ID:1,
Name: "Veggie",
Size: 32,
},
Pizza{
ID:2,
Name: "Salumi",
Size: 45,
},
}, nil
},
},
},
}
```

To have a schema defined, you need the following little code, that connects your root query and mutations (if there are) to your schema, which can be later executed.

```go
var PizzeriaSchema = &gql.Schema{
Query: RootQuery,
}
```

At this point, what's only left is an executor, so we can run our queries, and a handler to be able to serve our schema.

For our example, let's use the default executor, but if you want to experiment, customise it, add extensions, you can create your own the gql.NewExecutor function. 
Let's fire up our handler using the github.com/rigglo/gql/pkg/handler package and also enable the playground, so we can check it from our browser.

```go
func main() {
http.Handle("/graphql", handler.New(handler.Config{
Executor: gql.DefaultExecutor(PizzeriaSchema),
Playground: true,
}))
if err := http.ListenAndServe(":9999", nil); err != nil {
panic(err)
}
}
```

After running the code, you can go to the http://localhost:9999/graphql address in your browser and see the GraphQL Playground, and you can start playing with it.
4 changes: 4 additions & 0 deletions docs/_sidebar.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
* [About gql](/)
- Examples
* [Type Definitions](/examples/type_defs.md)
* [Subscriptions](/examples/subscriptions.md)
Loading

0 comments on commit 1e904de

Please sign in to comment.