Skip to content

Commit

Permalink
DOC Update documentation for GraphQL v4 (#10325)
Browse files Browse the repository at this point in the history
* DOC Add upgrade guidance for GraphQL v4

* Move docs around

The existing upgrading docs are for upgrading to v4, whereas the new docs are more about how to handle the new .graphql-generated directory.

* Update graphql documentation

* More updates to doc

Co-authored-by: Guy Sartorelli <[email protected]>
  • Loading branch information
Maxime Rainville and GuySartorelli authored Jun 8, 2022
1 parent 2c30438 commit 22d992a
Show file tree
Hide file tree
Showing 41 changed files with 1,215 additions and 942 deletions.
3 changes: 2 additions & 1 deletion docs/en/00_Getting_Started/00_Server_Requirements.md
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,8 @@ noisy, here's some pointers for auto-generated files to trigger and include in a
* `.graphql-generated/` and `public/_graphql/`: Schema and type definitions required by CMS and any GraphQL API endpoint.
Generated by
[silverstripe/graphql v4](https://github.com/silverstripe/silverstripe-graphql). See
[GraphQL Schema Build](/developer_guides/graphql/getting_started/building_the_schema).
[building the schema](/developer_guides/graphql/getting_started/building_the_schema) and
[deploying the schema](/developer_guides/graphql/getting_started/deploying_the_schema).
* Various recipes create default files in `app/` and `public/` on `composer install`
and `composer update` via
[silverstripe/recipe-plugin](https://github.com/silverstripe/recipe-plugin).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,21 @@ Docs for the current stable version (3.x) can be found
GraphQL is used through a single route, typically `/graphql`. You need
to define *types* and *queries* to expose your data via this endpoint. While this recommended
route is left open for you to configure on your own, the modules contained in the [CMS recipe](https://github.com/silverstripe/recipe-cms),
(e.g. `asset-admin`) run off a separate GraphQL server with its own endpoint
(`admin/graphql`) with its own permissions and schema.
(e.g. `silverstripe/asset-admin`) run off a separate GraphQL server with its own endpoint
(`admin/graphql`) with its own permissions and schema.

These separate endpoints have their own identifiers. `default` refers to the GraphQL server
in the user space (e.g. `/graphql`) while `admin` refers to the GraphQL server used by CMS modules
(`admin/graphql`). You can also [set up a new schema](#setting-up-a-custom-graphql-server) if you wish.
in the user space (e.g. `/graphql`) - i.e. your custom schema, while `admin` refers to the
GraphQL server used by CMS modules (`admin/graphql`). You can also [set up a new schema server](#setting-up-a-custom-graphql-server)
if you wish.

By default, this module does not route any GraphQL servers. To activate the default,
public-facing GraphQL server that ships with the module, just add a rule to `Director`.
[info]
The word "server" here refers to a route with its own isolated GraphQL schema. It does
not refer to a web server.
[/info]

By default, `silverstripe/graphql` does not route any GraphQL servers. To activate the default,
public-facing GraphQL server that ships with the module, just add a rule to [`Director`](api:SilverStripe\Control\Director).

```yaml
SilverStripe\Control\Director:
Expand All @@ -52,10 +58,8 @@ SilverStripe\Core\Injector\Injector:
class: SilverStripe\GraphQL\Controller
constructor:
schemaKey: myNewSchema
```


We'll now need to route the controller.

```yaml
Expand All @@ -64,14 +68,8 @@ SilverStripe\Control\Director:
'my-graphql': '%$SilverStripe\GraphQL\Controller.myNewSchema'
```

Now, you're ready to [configure your schema](configuring_your_schema.md).

```yaml
SilverStripe\GraphQL\Schema\Schema:
schemas:
myNewSchema:
# ...
```
Now, once you have [configured](configuring_your_schema) and [built](building_the_schema) your schema, you
can access it at `/my-graphql`.

### Further reading

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
title: Configuring your schema
summary: Add a basic type to the schema configuration
icon: code
---

# Getting started
Expand All @@ -22,10 +23,10 @@ GraphQL is a strongly-typed API layer, so having a schema behind it is essential
* A schema consists of **[types](https://graphql.org/learn/schema/#type-system)**
* **Types** consist of **[fields](https://graphql.org/learn/queries/#fields)**
* **Fields** can have **[arguments](https://graphql.org/learn/queries/#arguments)**.
* **Fields** need to **[resolve](https://graphql.org/learn/execution/#root-fields-resolvers)**
* **Fields** need to be **[resolved](https://graphql.org/learn/execution/#root-fields-resolvers)**

**Queries** are just **fields** on a type called "query". They can take arguments, and they
must resolve.
must be resolved.

There's a bit more to it than that, and if you want to learn more about GraphQL, you can read
the [full documentation](https://graphql.org/learn/), but for now, these three concepts will
Expand All @@ -42,7 +43,7 @@ SilverStripe\GraphQL\Schema\Schema:
# your schemas here
```

Let's populate a schema that is pre-configured for us out of the box, `default`.
Let's populate a schema that is pre-configured for us out of the box called "default".

**app/_config/graphql.yml**
```yml
Expand All @@ -54,7 +55,7 @@ SilverStripe\GraphQL\Schema\Schema:
types:
# your generic types here
models:
# your dataobjects here
# your DataObjects here
queries:
# your queries here
mutations:
Expand All @@ -63,15 +64,21 @@ SilverStripe\GraphQL\Schema\Schema:

### Avoid config flushes

Because the schema YAML is only consumed at build time and never used at runtime, it doesn't
Because the schema definition is only consumed at build time and never used at runtime, it doesn't
make much sense to store it in the configuration layer, because it just means you'll
have to `flush=1` every time you make a schema update, which will slow down your builds.

It is recommended that you store your schema YAML **outside of the _config directory** to
increase performance and remove the need for flushing.
increase performance and remove the need for flushing when you [build your schema](building_the_schema).

We can do this by adding a `src` key to our schema definition that maps to a directory
relative to the project root.
[notice]
This doesn't mean there is never a need to `flush=1` when building your schema. If you were to add a new
schema, make a change to the value of this `src` attribute, or create new PHP classes, those are still
standard config changes which won't take effect without a flush.
[/notice]

We can do this by adding a `src` key to our `app/_config/graphql.yml` schema definition
that maps to a directory relative to the project root.

**app/_config/graphql.yml**
```yml
Expand All @@ -82,13 +89,11 @@ SilverStripe\GraphQL\Schema\Schema:
- app/_graphql
```
Your `src` must be an array. This allows further source files to be merged into your schema.
Your `src` must be an array. This allows further source files to be merged into your schema.
This feature can be use to extend the schema of third party modules.

[info]
Your directory can also be a module reference, e.g. `somevendor/somemodule: _graphql`
[/info]

Your directory can also be relative to a module reference, e.g. `somevendor/somemodule: _graphql`:

**app/_config/graphql.yml**
```yml
Expand All @@ -101,17 +106,9 @@ SilverStripe\GraphQL\Schema\Schema:
# The next line would map to `vendor/somevendor/somemodule/_graphql`
- 'somevendor/somemodule: _graphql'
```
[/info]
Now, in our `app/_graphql` file, we can create YAML file definitions.

[notice]
This doesn't mean there is never a need to flush your schema config. If you were to add a new
one, or make a change to the value of this `src` attribute, those are still a standard config changes.
[/notice]


Now, in the new `app/_graphql` folder, we can create YAML file definitions.

**app/_graphql/schema.yml**
```yaml
Expand All @@ -121,7 +118,7 @@ config:
types:
# your generic types here
models:
# your dataobjects here
# your DataObjects here
bulkLoad:
# your bulk loader directives here
queries:
Expand All @@ -137,77 +134,94 @@ like this. We can tidy this up quite a bit by simply placing the files in direct
to the keys they populate -- e.g. `config/`, `types/`, `models/`, `queries/`, `mutations/`, etc.

There are two approaches to namespacing:

* By filename
* By directory name

##### Namespacing by directory name
##### Namespacing by filename

If you use a parent directory name (at any depth) of one of the four keywords above, it will
be implicitly placed in the corresponding section of the schema.
If the filename is named one of the four keywords above, it will be implicitly placed
in the corresponding section of the schema - e.g. any configuration
added to `app/_graphql/config.yml` will be implicitly added to
`SilverStripe\GraphQL\Schema\Schema.schemas.default.config`.

**app/_graphql/config/config.yml**
**This only works in the root source directory** (i.e. `app/_graphql/some-directory/config.yml`
will not work).

**app/_graphql/config.yml**
```yaml
# my schema config here
# my config here
```

**app/_graphql/types/types.yml**
**app/_graphql/types.yml**
```yaml
# my type definitions here
# my types here
```

**app/_graphql/models/models.yml**
**app/_graphql/models.yml**
```yaml
# my type definitions here
# my models here
```

**app/_graphql/bulkLoad/bulkLoad.yml**
**app/_graphql/bulkLoad.yml**
```yaml
# my bulk loader directives here
```

##### Namespacing by filename
##### Namespacing by directory name

If the filename is named one of the four keywords above, it will be implicitly placed
in the corresponding section of the schema. **This only works in the root source directory**.
If you use a parent directory name (at any depth) of one of the four keywords above, it will
be implicitly placed in the corresponding section of the schema - e.g. any configuration
added to a `.yml` file in `app/_graphql/config/` will be implicitly added to
`SilverStripe\GraphQL\Schema\Schema.schemas.default.config`.

**app/_graphql/types.yml**
[hint]
The names of the actual files here do not matter. You could for example have a separate file
for each of your types, e.g. `app/_graphql/types/my-first-type.yml`.
[/hint]

**app/_graphql/config/config.yml**
```yaml
# my config here
```

**app/_graphql/types/types.yml**
```yaml
# my types here
```

**app/_graphql/models.yml**
**app/_graphql/models/models.yml**
```yaml
# my models here
```

**app/_graphql/bulkLoad.yml**
**app/_graphql/bulkLoad/bulkLoad.yml**
```yaml
# my bulk loader directives here
```

#### Going even more granular
##### Going even more granular

These special directories can contain multiple files that will all merge together, so you can even
create one file per type, or some other convention. All that matters is that the parent directory name
matches one of the schema keys.
_or_ the filename matches one of the schema keys.

The following are perfectly valid:

* `app/_graphql/types/mySingleType.yml`
* `app/_graphql/models/allElementalBlocks.yml`
* `app/_graphql/news-and-blog/models/blog.yml`
* `app/_graphql/mySchema.yml`
* `app/_graphql/config/config.yml` maps to `SilverStripe\GraphQL\Schema\Schema.schemas.default.config`
* `app/_graphql/types/allElementalBlocks.yml` maps to `SilverStripe\GraphQL\Schema\Schema.schemas.default.types`
* `app/_graphql/news-and-blog/models/blog.yml` maps to `SilverStripe\GraphQL\Schema\Schema.schemas.default.models`
* `app/_graphql/mySchema.yml` maps to `SilverStripe\GraphQL\Schema\Schema.schemas.default`

### Schema config

In addition to all the keys mentioned above, each schema can declare a generic
configuration section, `config`. This are mostly used for assigning or removing plugins
and resolvers.
Each schema can declare a generic configuration section, `config`. This is mostly used for assigning
or removing plugins and resolvers.

An important subsection of `config` is `modelConfig`, where you can configure settings for specific
models, e.g. `DataObject`.

Like the other sections, it can have its own `config.yml`, or just be added as a `config:`
Like the other sections, it can have its own `config.yml`, or just be added as a `config:`
mapping to a generic schema yaml document.

**app/_graphql/config.yml**
Expand All @@ -223,11 +237,19 @@ modelConfig:
paginateList: false
```

You can learn more about plugins and resolvers in the [query plugins](../working_with_dataobjects/query_plugins),
[plugins](../plugins), [building a custom query](../working_with_generic_types/building_a_custom_query#building-a-custom-query),
and [resolver discovery](../working_with_generic_types/resolver_discovery) sections.

### Defining a basic type

Let's define a generic type for our GraphQL schema.

[info]
Generic types don't map to `DataObject` classes - they're useful for querying more 'generic' data (hence the name).
You'll learn more about adding DataObjects in [working with DataObjects](../working_with_DataObjects).
[/info]

**app/_graphql/types.yml***
```yaml
Country:
Expand All @@ -238,8 +260,11 @@ Country:
languages: '[String]'
```

If you're familiar with [GraphQL type language](https://graphql.org/learn/schema/#type-language), this should look pretty familiar. There are only a handful of [scalar types](https://graphql.org/learn/schema/#scalar-types) available in
GraphQL by default. They are:
If you're familiar with [GraphQL type language](https://graphql.org/learn/schema/#type-language),
this should look pretty familiar.

There are only a handful of [scalar types](https://graphql.org/learn/schema/#scalar-types)
available in GraphQL by default. They are:

* String
* Int
Expand All @@ -253,13 +278,13 @@ To define a type as required (non-null), you add an exclamation mark: `String!`
Often times, you may want to do both: `[String!]!`

[notice]
Look out for the footgun, here. Make sure your bracketed type is in quotes, otherwise it's valid YAML that will get parsed as an array!
Look out for the footgun, here. Make sure your bracketed type is in quotes
(i.e. `'[String]'`, not `[String]`), otherwise it's valid YAML that will get parsed as an array!
[/notice]

That's all there is to it! To learn how we can take this further, check out the
[working with generic types](../working_with_generic_types) documentation. Otherwise,
let's get started on [**adding some dataobjects**](../working_with_dataobjects).

let's get started on [**adding some DataObjects**](../working_with_DataObjects).

### Further reading

Expand Down
Loading

0 comments on commit 22d992a

Please sign in to comment.