silverstripe-framework/docs/en/02_Developer_Guides/19_GraphQL/05_plugins/01_overview.md

154 lines
5.6 KiB
Markdown
Raw Normal View History

WIP: Add new graphql 4 docs (#9652) * DOCS: Add new graphql 4 docs * Reorganise docs * Docs done * Basic graphql index page * TOC for getting started * show folders on graphql index page * Add middleware note * Docs update * Update docs to reflect flushless schema * Docs updates * Docs for getByLink * Query caching docs * Docs on nested operations * update docs for new graphql dev admin * Docs for configurable operations * Replace readSiteTrees with readPages * Schema defaults docs * Docs for inherited plugins * Docs for customising * * Docs for field whitelisting * Change whitelist word * New docs on modelConfig * Document dev/build extension * Document default/global plugins * Document new input type fields config * Apply suggestions from code review Co-authored-by: Andre Kiste <bergice@users.noreply.github.com> * Note about when procedural schema gets built * Fix link * Apply suggestions from code review Co-authored-by: Andre Kiste <bergice@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: Andre Kiste <bergice@users.noreply.github.com> * DOCS Note about plugins in custom queries * DOCS Note about filter and custom resolvers * DOCS Note about canview paging * DOCS Updated guidance on _extend See https://github.com/silverstripe/silverstripe-graphql/issues/296 * Apply suggestions from code review Co-authored-by: Andre Kiste <bergice@users.noreply.github.com> * DOCS Pre-release warning Co-authored-by: Ingo Schommer <ingo@silverstripe.com> Co-authored-by: Andre Kiste <bergice@users.noreply.github.com> Co-authored-by: Ingo Schommer <me@chillu.com>
2020-10-19 23:56:17 +02:00
---
title: What are plugins?
summary: An overview of how plugins work with the GraphQL schema
---
# Plugins
[CHILDREN asList]
[alert]
You are viewing docs for a pre-release version of silverstripe/graphql (4.x).
Help us improve it by joining #graphql on the [Community Slack](https://www.silverstripe.org/blog/community-slack-channel/),
and report any issues at [github.com/silverstripe/silverstripe-graphql](https://github.com/silverstripe/silverstripe-graphql).
Docs for the current stable version (3.x) can be found
[here](https://github.com/silverstripe/silverstripe-graphql/tree/3)
[/alert]
## What are plugins?
Plugins are used to distribute reusable functionality across your schema. Some examples of commonly used plugins include:
* Adding versioning arguments to versioned DataObjects
* Adding a custom filter/sort arguments to DataObject queries
* Adding a one-off `VerisionedStage` enum to the schema
* Ensuring `Member` is in the schema
* And many more...
### Default plugins
By default, all schemas ship with some plugins installed that will benefit most use cases:
* The `DataObject` model (i.e. any dataobject based type) has:
* An `inheritance` plugin that builds the `__extends` field, and merges ancestral fields.
* An `inheritedPlugins` plugin (a bit meta!) that merges plugins from ancestral types into descendants.
installed).
* The `read` and `readOne` operations have:
* A `canView` plugin for hiding records that do not pass a `canView()` check
* The `read` operation has:
* A `paginateList` plugin for adding pagination arguments and types (e.g. `nodes`)
In addition to the above, the `default` schema specifically ships with an even richer set of default
plugins, including:
* A `versioning` plugin that adds `version` fields to the dataobject type (if `silverstripe/versioned` is installed)
* A `readVersion` plugin (if `silverstripe/versioned` is installed) that allows versioned operations on
`read` and `readOne` queries.
* A `filter` plugin for filtering queries (adds a `filter` argument)
* A `sort` plugin for sorting queries (adds a `sort` argument)
All of these are defined in the `modelConfig` section of the schema (see [configuring your schema](../getting_started/configuring_your_schema)). For reference, see the graphql configuration in `silverstripe/admin`, which applies
these default plugins to the `default` schema.
#### Overriding default plugins
You can override default plugins generically in the `modelConfig` section.
**app/_graphql/modelConfig.yml**
```yaml
DataObject:
plugins:
inheritance: false # No dataobject models get this plugin unless opted into
operations:
read:
plugins:
paginateList: false # No dataobject models have paginated read operations unless opted into
```
You can override default plugins on your specific dataobject type and these changes will be inherited by descendants.
**app/_graphql/models.yml**
```yaml
Page:
plugins:
inheritance: false
MyProject\MyCustomPage: {} # now has no inheritance plugin
```
Likewise, you can do the same for operations:
**app/_graphql/models.yml**
```yaml
Page:
operations:
read:
plugins:
readVersion: false
MyProject\MyCustomPage:
operations:
read: true # has no readVersion plugin
```
### What plugins must do
There isn't a huge API surface to a plugin. They just have to:
* Implement at least one of several plugin interfaces
* Declare an identifier
* Apply themselves to the schema with the `apply(Schema $schema)` method
* Be registered with the `PluginRegistry`
### Available plugin interfaces
Plugin interfaces are all found in the namespace `SilverStripe\GraphQL\Schema\Interfaces`
* `SchemaUpdater`: Make a one-off, context-free update to the schema
* `QueryPlugin`: Update a generic query
* `MutationPlugin`: Update a generic mutation
* `TypePlugin`: Update a generic type
* `FieldPlugin`: Update a field on a generic type
* `ModelQueryPlugin`: Update queries generated by a model, e.g. `readPages`
* `ModelMutationPlugin`: Update mutations generated by a model, e.g. `createPage`
* `ModelTypePlugin`: Update types that are generated by a model
* `ModelFieldPlugin`: Update a field on types generated by a model
Wow, that's a lot of interfaces, right? This is owing mostly to issues around strict typing between interfaces,
and allows for a more expressive developer experience. Almost all of these interfaces have the same requirements,
just for different types. It's pretty easy to navigate if you know what you want to accomplish.
### Registering plugins
Plugins have to be registered with Injector.
```yaml
SilverStripe\Core\Injector\Injector:
SilverStripe\GraphQL\Schema\Registry\PluginRegistry:
constructor:
2020-11-19 01:27:08 +01:00
- 'MyProject\Plugins\MyPlugin'
WIP: Add new graphql 4 docs (#9652) * DOCS: Add new graphql 4 docs * Reorganise docs * Docs done * Basic graphql index page * TOC for getting started * show folders on graphql index page * Add middleware note * Docs update * Update docs to reflect flushless schema * Docs updates * Docs for getByLink * Query caching docs * Docs on nested operations * update docs for new graphql dev admin * Docs for configurable operations * Replace readSiteTrees with readPages * Schema defaults docs * Docs for inherited plugins * Docs for customising * * Docs for field whitelisting * Change whitelist word * New docs on modelConfig * Document dev/build extension * Document default/global plugins * Document new input type fields config * Apply suggestions from code review Co-authored-by: Andre Kiste <bergice@users.noreply.github.com> * Note about when procedural schema gets built * Fix link * Apply suggestions from code review Co-authored-by: Andre Kiste <bergice@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: Andre Kiste <bergice@users.noreply.github.com> * DOCS Note about plugins in custom queries * DOCS Note about filter and custom resolvers * DOCS Note about canview paging * DOCS Updated guidance on _extend See https://github.com/silverstripe/silverstripe-graphql/issues/296 * Apply suggestions from code review Co-authored-by: Andre Kiste <bergice@users.noreply.github.com> * DOCS Pre-release warning Co-authored-by: Ingo Schommer <ingo@silverstripe.com> Co-authored-by: Andre Kiste <bergice@users.noreply.github.com> Co-authored-by: Ingo Schommer <me@chillu.com>
2020-10-19 23:56:17 +02:00
```
[info]
The key `myPlugin` is arbitrary. The identifier of the plugin is obtained procedurally.
[/info]
### Resolver middleware and afterware
The real power of plugins is the ability to distribute not just configuration across the schema, but
more importantly, _functionality_.
Fields have their own resolvers already, so we can't really get into those to change
their functionality without a massive hack. This is where the idea of **resolver middleware** and
**resolver afterware** comes in really useful.
**Resolver middleware** runs _before_ the field's assigned resolver
**Resolver afterware** runs _after_ the field's assigned resolver
Middlewares and afterwares are pretty straightforward. They get the same `$args`, `$context`, and `$info`
parameters as the assigned resolver, but the first argument, `$result` is mutated with each resolver.
### Further reading
[CHILDREN]