Skip to content

Directives

In this section we will go over all the custom fastGQL directives, what they do and how to use them. These directives are added automatically when we augment and generate the server code. You can also use the following command go run github.com/roneli/fastgql init or copy the fastgql_schema_fragment.md.

Augmentation directives

These directives extend the original schema functionality adding filters, pagination, aggregation, ordering etc’ and are commonly used to tell fastgql what parts of the schema we want to augment.

We currently have four augmentation directives:

@generateFilterInput

The @generateFilterInput tells the augmenter on which OBJECT | INTERFACE to generate filter inputs, this is required so fastGQL knows what objects to build filters for giving you more control over which filters are created.

# Generate filter input on an object
directive @generateFilterInput(description: String)
on OBJECT | INTERFACE

Example:

In this example, we can are creating a filter input for the category type, when arguments will be generated for categories in Query the CategoryFilterInput will be used for the filter argument.

type Category @generateFilterInput {
id: Int!
name: String
}
type Query {
categories: [Category] @generate
}

This also works for objects that contain fields of objects, see Object filters

@generate

The @generate tells the augmenter on which FIELD_DEFINTION to generate arguments i.e. filter, pagination and ordering, aggregation. By default, all arguments are created, and are recursive, this means that arguments are generated from the top level OBJECT until exhausted meaning no new OBJECT fields are found in a certain level.

# Generate arguments for a given field or all object fields
directive @generate(filter: Boolean = True, pagination: Boolean = True, ordering: Boolean = True, aggregate: Boolean = True, recursive: Boolean = True, filterTypeName: String) on FIELD_DEFINITION

Example: The following example generates resolvers for posts and users, but doesn’t add aggregation to users.

type Query {
posts: [Post] @generate
users: [User] @generate(aggregate: false)
categories: [Category]
}

@generateMutations

The @generateMutations tells the augmenter on which OBJECT to generate mutations on. There are 3 possible mutations, create, update and delete, by default all of them are set to true.

# Generate filter input on an object
directive @generateMutations(create: Boolean = True, delete: Boolean = True, update: Boolean = True) on OBJECT

Builder directives

Builder directives are used by builders to build queries based on the given GraphQL query requested.

We have two builder directives:

@table

The @table directive is used to define the name of the table of the graphql OBJECT in the database.

By default, the table name is the name of type, we use this directive when the table name is different from the object typename.

If our table resides in a schema that isn’t the one set as the default we need to add the schema argument.

# Used if Object/Interface type name is different then the actual table name or if the table resides in a schema other than default path.
directive @table(name: String!, dialect: String, schema: String) on OBJECT | INTERFACE

Example:

type User @table(name: "users", dialect: "postgres", schema: "app"){
id: Int
name: String
}

@relation

The @relation directive tells the builder about relations in your database.

directive @relation(type: _relationType!, fields: [String!]!, references: [String!]!, manyToManyTable: String = "",
manyToManyFields: [String] = [], manyToManyReferences: [String] = []) on FIELD_DEFINITION

Table Relationships

There are three major types of database relationships:

  • ONE_TO_ONE
  • ONE_TO_MANY
  • MANY_TO_MANY

@typename

The @typename directive is used for interface support (experimental), the typename tell fastgql builder what field in the table we should use to use when scanning into the original type of the interface

interface Animal @table(name: "animals") @typename(name: "type") @generateFilterInput {
id: Int!
name: String!
type: String!
}