diff --git a/packages/web/docs/src/pages/docs/gateway/other-features/custom-plugins.mdx b/packages/web/docs/src/pages/docs/gateway/other-features/custom-plugins.mdx
index f9339b31b..a2d6ac6e4 100644
--- a/packages/web/docs/src/pages/docs/gateway/other-features/custom-plugins.mdx
+++ b/packages/web/docs/src/pages/docs/gateway/other-features/custom-plugins.mdx
@@ -1,106 +1,501 @@
---
-searchable: false
+description: Add feature or third party integrations with Hive Gateway plugin system.
---
import { Callout } from '@theguild/components'
# Custom Plugins
-Hive Gateway uses
-[GraphQL Yoga](https://the-guild.dev/graphql/yoga-server/docs/features/envelop-plugins), and it uses
-[Envelop](https://the-guild.dev/graphql/envelop) plugin system which allows you to hook into the
-different phases of the GraphQL execution to manipulate or track the entire workflow step-by-step.
+Hive Gateway is built with an highly modular architecture. The core is as small as possible, and
+most of the features are built around a plugin system.
-
-You can both use Yoga or Envelop or Gateway plugins with your GraphQL Gateway.
-But you should always opt-in for the Hive Gateway variant of the plugin, then Yoga then Envelop because each of them have more control over the execution.
-For example, Yoga variant of the plugin leverage HTTP hooks, and Hive Gateway one can leverage more hooks and more control over the context.
+A plugin can hook into each important steps of the lifecycle of the gateway, including the graphql
+request execution.
-We'd recommend to check the features of the gateway first, and if you can't find what you are
-looking for, then you can use this option on your own to add plugins from either GraphQL Yoga or
-[Envelop's Plugin Hub](https://the-guild.dev/graphql/envelop/plugins).
+The gateway is built using Graphql Yoga (a GraphQL HTTP server) and Envelop (a GraphQL execution
+orchestrator), which are also highly modular technologies. Hive Gateway is extending Yoga and
+Envelop plugin system by providing gateway specific hooks.
-
+This means that if a plugin exists in multiple variants, you should follow this priority order:
-You can provide those plugins as an array of objects,
+1. Hive Gateway: is aware of subgraphs and upstream request management.
+2. Yoga: is aware of the HTTP transport. It most of the time provides optimisations over the
+ Envelop variants.
+3. Envelop: is only aware of the GraphQL operation execution.
-```ts filename="gateway.config.ts" {7}
-import { useGraphQLJit } from '@envelop/graphql-jit'
+For example, the Prometheus integration plugin is available for Envelop (`@envelop/prometheus`),
+Yoga(`@graphql-yoga/plugin-prometheus`) and Hive Gateway(`@graphql-mesh/prometheus`). In this case,
+you should pick `@graphql-mesh/prometheus` plugin. It is built on top of Yoga and Envelop variants,
+but adds monitoring capabilities of upstream subgraphs.
+
+For the most used features, you will not have to explicitly setup the dedicated plugin. They will be
+added automatically based on your gateway configuration.
+
+## Configuration
+
+You can add plugins to your gateway using the `plugins` option.
+
+It have to be a function, which will be called each time the gateway have update its configuration.
+For example, if polling is enabled, this function will be called for each poll.
+
+Most Hive Gateway plugins takes an object as a parameter, and expect some common components like a
+`logger`, a `pubsub`, etc... Those components are given in parameters to the `plugins` function. It
+is advised to spread the plugin's factory context into the plugins options, this way plugins will
+have access to all components they need.
+
+```ts filename="gateway.config.ts"
import { defineConfig } from '@graphql-hive/gateway'
+import useNewRelic from '@graphql-mesh/plugin-newrelic'
+import { useSOFA } from '@graphql-yoga/plugin-sofa'
export const gatewayConfig = defineConfig({
- plugins: () => [useGraphQLJit()]
+ plugins: ctx => [
+ useSOFA({
+ ...ctx,
+ basePath: '/rest',
+ swaggerUIEndpoint: '/rest/docs'
+ }),
+ useNewRelic({
+ ...ctx
+ })
+ ]
})
```
-## Writing Plugins
+## Custom Plugins
-Sometimes you might want to build your own plugins. You can write your own gateway plugin and even
-share it with other people by publishing it to `npm`.
+You can take advantage of the plugin system to create your own custom plugin. This allows you to
+integrate your gateway with any technology that we don't officially support, being public or private
+to your company.
-
- A good entry-point for discovering how to write Gateway plugins is to look at the source code of
- the existing plugins maintained by us.
-
+A good entry-point for discovering how to write Gateway plugins is to look at the source code of the
+existing plugins maintained by us.
-The most hooks for Hive Gateway origin from the Envelop and Yoga plugin systems.
-[Please refer to the Envelop Plugin Lifecycle documentation for more information.](https://the-guild.dev/graphql/envelop/docs/plugins/lifecycle)
-and
-[Yoga Plugin Lifecycle documentation](https://the-guild.dev/graphql/yoga-server/docs/features/envelop-plugins).
-In addition, Yoga adds more HTTP specific hooks while Hive Gateway adds more related to the subgraph
-execution. Gateway plugins also uses
-[Explicit Resource Management](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-2.html),
-so all the resources are cleaned up gracefully when Hive Gateway is shut down. You can see
-`Symbol.asyncDispose` below.
+A plugin is an object that can define methods to hook into different phases or events of the gateway
+lifecycle. Each hook will receive a single parameter, the hook payload, containing data related to
+the hooked phase and functions allowing you to modify the behavior of this phase.
-### Plugin Lifecycle
+There are 2 categories of hooks:
-The following diagram shows the plugin lifecycle of Hive Gateway. For a detailed description of each
-hook, please refer to the detail sections of each hook. Please check Yoga and Envelop documentation
-for more information about the hooks except `onSubgraphExecute`.
+- Gateway lifecycle hooks: they are related to the lifecycle or events of the server itself and is
+ not related to a specific request.
+- Request lifecycle hooks: they are tight to a specific phase of a specific request. Those hooks
+ always give access to the related request in there payload.
+
+### Gateway lifecycle
+
+Gateway lifecycle allows to setup long running services, initialize in-memory cache or stores, react
+to general events.
+
+
```mermaid
stateDiagram-v2
- [*] --> onRequest
+ onYogaInit:
onYogaInit
+ onPluginInit:
onPluginInit
+ onDispose:
onDispose
+ listening: Listening for HTTP requests
- state onRequest_if_state <
>
-
- onRequest --> onRequest_if_state
-
- onRequest_if_state --> onResponse: Is not a GraphQL Request
- onRequest_if_state --> GraphQLRequest: Is GraphQL Request
-
- GraphQLRequest: GraphQL Request
-
- state GraphQLRequest {
- [*] --> onRequestParse
- onRequestParse --> onParams
- onParams --> onParse
- onParse --> onValidate
- onValidate --> onContextBuilding
- onContextBuilding --> onExecute
- onContextBuilding --> onSubscribe
-
- onExecute --> onSubgraphExecute
- onSubscribe --> onSubgraphExecute
-
- onSubgraphExecute --> onFetch
- onFetch --> onSubgraphExecuteDone
-
- onSubgraphExecuteDone --> onExecuteDone
- onSubgraphExecuteDone --> onSubscribeDone
-
- onExecuteDone --> onResultProcess
- onSubscribeDone --> onResultProcess
-
- onResultProcess --> [*]
- }
-
- GraphQLRequest --> onResponse
- onResponse --> [*]
+ [*] --> onYogaInit
+ onYogaInit --> onPluginInit
+ onPluginInit --> listening
+ listening --> onDispose: Gateway is shutting down
+ note left of listening: onSchemaChange called for each new schema loaded
+ note left of listening: onFetch called for each outgoing HTTP request
```
+
+
+#### `onYogaInit`
+
+It is the very first hook called just before the gateway starts listening for HTTP requests.
+
+You can use this hook to customize the Yoga instance.
+
+| Payload field | Description |
+| ------------- | -------------------------------------------------------------- |
+| `yoga` | `YogaServer` instance that is about to start with the gateway. |
+
+#### `onPluginInit`
+
+Called before the server starts listening to HTTP requests.
+
+In this hook, you can initialize every long running components, such as values stores, cache, third
+party clients, etc...
+
+You can add other plugin in this hook, which allow you to ensure plugins you depends on are present.
+
+| Payload field | Description |
+| -------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `addPlugin(plugin: Plugin)` | Allows adding a plugin to the plugin list. The new plugin will be added just after the one calling this function. It can be called multiple times, preserving plugin order. |
+| `plugins: Plugin[]` | The current list of plugins. It can be used to verify if a dependent plugin is already in the list or to ensure your plugin is not present twice. This should never be mutated; use `addPlugin` instead. |
+| `setSchema(schema: GraphQLSchema)` | Allows replacing the current schema. |
+| `registerContextErrorHandler(handler)` | Registers a handler that will be called if the GraphQL context factory throws an error. Useful for error reporting. |
+
+#### `onSchemaChange`
+
+This hook is called when the schema changes, either because the Gateway loaded it the first time, or
+because a plugin changed it.
+
+Possible usage examples of this hooks are:
+
+- Monitor changes of schemas
+- Analyse the schema or keep track of it for other hooks
+- Modify the schema
+
+| Payload field | Description |
+| --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `schema` | The new loaded schema |
+| `replaceSchema` | Replace the schema. This will trigger a new call to `onSchemaChange`, so you should keep track of schema already modified by your plugin to avoid infinite change loop. |
+
+#### `onFetch`
+
+This hook is called each time the `fetch` function is called. It can be either a request to an
+upstream subgraph using the http transport, or a request made a plugin to a third party technology.
+
+Possible usage examples of the hooks are:
+
+- Manipulate HTTP [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request) object
+- Manipulate HTTP [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response) object
+- Change [`fetch`](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) implementation
+- Add custom headers
+- Monitor the HTTP request
+
+| Payload field | Description |
+| ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `url` | The target URL of the request |
+| `setUrl` | Replace the target URL |
+| `options` | The `fetch` function options |
+| `setOptions` | Replace the options that will be used to send the request |
+| `info` | The GraphQL operation info |
+| `fetchFn` | The fetch function that will be used to make the request. By default, it is the one provided in the Gateway configuration if provided, or `@whatwg-node/fetch` if not. |
+| `setFetchFn` | Replace the `fetch` function that will be used to make the request. It should be compatible with standard `fetch` API. |
+| `executionRequest` | Present only if the request is an upstream subgraph request. It contains all information about the upstream query, notably the target subgraph name. |
+| `requestId` | A unique ID identifying the client request. This is used to correlate downstream and upstream requests across services. |
+| `logger` | The logger instance for the specific request that includes the details of the request and the response. |
+
+#### `onDispose`
+
+In order to clean up resources when Hive Gateway is shut down, you can use `onDispose`,
+`Symbol.asyncDispose` or `Symbol.syncDispose` to clean up resources.
+
+```ts
+export const useMyPlugin = () => {
+ return {
+ async onDispose() {
+ // Clean up resources
+ await stopConnection()
+ }
+ }
+}
+```
+
+[You can learn more about Explicit Resource Management in Yoga documentation](https://the-guild.dev/graphql/yoga-server/docs/features/explicit-resource-management).
+
+### Request Lifecycle
+
+The following diagram shows the lifecycle of request in Hive Gateway.
+
+Each hook is given a single parameter called payload. Please see detail section of each hook to know
+what contains each of this payloads.
+
+
+
+```mermaid
+stateDiagram-v2
+ onRequest:
onRequest
+ onResponse:
onResponse
+ GraphQLRequest: GraphQL Request
+
+ [*] --> onRequest
+
+ state onRequest_if_state <
>
+
+ onRequest --> onRequest_if_state
+
+ onRequest_if_state --> onResponse: Is not a GraphQL Request
+ onRequest_if_state --> onRequestParse: Is GraphQL Request
+
+ onRequestParse: onRequestParse
+ onParams: onParams
+ onEnveloped: onEnveloped
+ onParse: onParse
+ onValidate: onValidate
+ onContextBuilding: onContextBuilding
+ onExecute: onExecute
+ onSubscribe: onSubscribe
+
+ onExecuteDone: onExecuteDone
+ onFetch: onFetch (HTTP only)
+ onSubscribeDone: onSubscribeDone
+ onExecutionResult: onExecutionResult
+ onResultProcess: onResultProcess
+ onDelegationPlan: onDelegationPlan
+ onDelegationStageExecute: onDelegationStageExecute
+ onSubgraphExecute: onSubgraphExecute
+ onSubgraphExecuteDone: onSubgraphExecuteDone
+
+
+ onRequestParse --> onParams
+ onParams --> onEnveloped
+ onEnveloped --> onParse
+ onParse --> onValidate
+ onValidate --> onContextBuilding
+ onContextBuilding --> onExecute: query or mutation
+ onContextBuilding --> onSubscribe: subscription
+
+ state is_plan_cached <>
+ onExecute --> is_plan_cached
+ onSubscribe --> is_plan_cached
+ is_plan_cached --> onDelegationPlan: Plan is not cached
+ is_plan_cached --> onDelegationStageExecute: Plan is cached
+
+ note left of onDelegationPlan
+ Will be called for each nested selection set of the query
+ end note
+ onDelegationPlan --> onDelegationStageExecute
+ onDelegationStageExecute --> onSubgraphExecute
+ onSubgraphExecute --> onFetch
+ onFetch --> onSubgraphExecuteDone
+
+ state is_plan_finished <>
+ onSubgraphExecuteDone --> is_plan_finished
+ is_plan_finished --> onDelegationStageExecute: plan not finished
+
+ state end_of_execution <>
+ is_plan_finished --> end_of_execution: plan finished
+ end_of_execution --> onExecuteDone: query or mutation
+ end_of_execution --> onSubscribeDone: subscription
+
+ onExecuteDone --> onExecutionResult
+ onSubscribeDone --> onExecutionResult
+
+ onExecutionResult --> onResultProcess
+
+ onResultProcess --> onResponse
+ onResponse --> [*]
+```
+
+
+
+#### `onRequest`
+
+This hook is invoked for ANY incoming HTTP request. Here you can manipulate the request or create a
+short circuit before Yoga handles the request.
+
+
+
+Exceptions thrown by this hook are not caught. This means they will buble up to the HTTP server
+underlying implementation.
+
+For example, the `node:http` server crashes the entire process on uncaught exceptions.
+
+Prefer `onRequestParse` when possible, or wrap the hook code in a `try` block.
+
+
+
+For example, you can shortcut the manually handle an HTTP request, short-circuiting the Hive Gateway
+HTTP handler:
+
+```ts
+import type { GatewayPlugin } from '@graphql-hive/gateway'
+
+function useAuth(): GatewayPlugin {
+ return {
+ onRequest({ request, fetchAPI, endResponse }) {
+ if (!request.headers.get('authorization')) {
+ endResponse(
+ new fetchAPI.Response(null, {
+ status: 401,
+ headers: {
+ 'Content-Type': 'application/json'
+ }
+ })
+ )
+ }
+ }
+ }
+}
+```
+
+Possible usage examples of this hook are:
+
+- Manipulate the request
+- Short circuit before Yoga handles the request
+
+| Payload field | Description |
+| --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
+| `request` | The incoming HTTP request as WHATWG `Request` object. [Learn more about the request](https://developer.mozilla.org/en-US/docs/Web/API/Request). |
+| `serverContext` | The early context object that is shared between all hooks and the GraphQL execution. [Learn more about the context](/docs/features/context). |
+| `fetchAPI` | WHATWG Fetch API implementation. [Learn more about the fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API). |
+| `url` | WHATWG URL object of the incoming request. [Learn more about the URL object](https://developer.mozilla.org/en-US/docs/Web/API/URL). |
+| `endResponse` | A function that allows you to end the request early and send a response to the client. |
+
+#### `onRequestParse`
+
+This hook is invoked for any incoming GraphQL HTTP request and is invoked before attempting to parse
+the GraphQL parameters. Here you can manipulate the request, set a custom request parser or apply
+security measures such as checking for access tokens etc.
+
+Possible usage examples of this hook are:
+
+- Manipulate the request
+- Set custom GraphQL request parser (use custom GraphQL protocol)
+- Apply security measures
+
+| Payload field | Description |
+| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------- |
+| `request` | The incoming HTTP request as WHATWG `Request` object. [Learn more about the request](https://developer.mozilla.org/en-US/docs/Web/API/Request). |
+| `url` | The incoming HTTP request target url |
+| `requestParser` | The function that will be used to extract GraphQL params from the request. |
+| `setRequestParser` | Allows to replace the function that will be used to extract GraphQL params from the request |
+
+#### `onParams`
+
+This hook is invoked for an incoming GraphQL request after the GraphQL parameters (`query`,
+`variables`, `extensions` and `operationName`) have been ATTEMPTED to be parsed.
+
+Within this hook you can manipulate and customize the parameters or even implement a whole new way
+of parsing the parameters (if you wish to diverge from the GraphQL over HTTP specification).
+
+In addition to that you could also short-circuit and skip the GraphQL execution. E.g. you might want
+to serve a result from the cache instead.
+
+Possible usage examples of this hook are:
+
+- **[Response Cache](/docs/features/response-caching)**: Short-circuit GraphQL execution if response
+ can be served from the cache.
+- **[Persisted Operations](/docs/features/persisted-operations):** Load the `query` document string
+ from the persisted operations store before running the execution.
+- **[APQ](/docs/features/automatic-persisted-queries):** Load/persist the `query` document string on
+ the persisted operations store.
+
+| Payload field | Description |
+| ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `request` | The incoming HTTP request as WHATWG `Request` object. [Learn more about the request](https://developer.mozilla.org/en-US/docs/Web/API/Request). |
+| `params` | The `GraphQLParams` extracted from the request. |
+| `setParams` | Allows to replace the `GraphQLParams` for this request |
+| fetchAPI | [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) provided in the Hive Gateway configuration. This should be used to make outgoing HTTP request, since it will trigger the `onFetch` hook. |
+| `context` | The server context. It can contain runtime specific data, such as `req` and `res` object when running in Node for example. |
+
+#### `onParse`
+
+Called for parsing the GraphQL document. This hook has a before and after stage. You can hook into
+before the document is parsed and/or into after the document is parsed.
+
+**Example actions in this hook:**
+
+- Replace GraphQL parser and support future GraphQL syntax
+- Collect metrics about parsing success/failures
+
+| Payload Field | Description |
+| ------------------- | ------------------------------------------------------------------------------------------------------- |
+| `context` | The current context object. |
+| `extendContext` | Extend the context object with a partial. |
+| `params` | The parameters that are passed to the parse call. |
+| `parseFn` | The current parse function. |
+| `setParseFn` | Replace the current parse function. |
+| `setParsedDocument` | Set/overwrite the parsed document. If a parsed document is set the call to the parseFn will be skipped. |
+
+#### `onValidate`
+
+Called for validating the GraphQL document. This hook has a before and after stage. You can hook
+into before the document is parsed and/or into after the document is parsed.
+
+**Example actions in this hook:**
+
+- Register additional validation rules (e.g. [Disable Introspection](/docs/features/introspection))
+- Collect metrics about validation success/failures
+
+| Payload field | Description |
+| ------------------- | ------------------------------------------------------------------------- |
+| `context` | The current context object. |
+| `extendContext` | Extend the context object with a partial. |
+| `params` | The parameters with which the validate function will be invoked. |
+| `addValidationRule` | Register a validation rule that will be used for the validate invocation. |
+| `validateFn` | The current validate function that will be invoked. |
+| `setValidationFn` | Overwrite the current validate function. |
+| `setResult` | Set a validation error result and skip the validate invocation. |
+
+#### `onContextBuilding`
+
+Called for building the GraphQL context. This hook has a before and after stage. You can hook into
+before and after the context is built.
+
+**Example actions in this hook:**
+
+- Authentication
+- Add data to context object (e.g. user data or dataloader instances)
+
+| Payload field | Description |
+| ---------------------- | ---------------------------------------------------- |
+| `context` | The current GraphQL context object. |
+| `extendContext` | Extend the context object with a partial. |
+| `breakContextBuilding` | Prevent calls on any further context building hooks. |
+
+#### `onExecute`
+
+Called for executing a GraphQL mutation or query operation. This hook has a before and after stage.
+You can hook into before and after the GraphQL request is executed.
+
+**Example actions in this hook:**
+
+- Collect metrics about execution time
+- Error logging/reporting
+
+| Payload field | Description |
+| --------------------------- | -------------------------------------------------------------- |
+| `executeFn` | Current execute function that will be used for execution. |
+| `args` | Arguments the execute function will be invoked with. |
+| `setExecuteFn` | Replace the current execute function with a new one. |
+| `setResultAndStopExecution` | Set an execution result and skip calling the execute function. |
+| `extendContext` | Extend the context object with a partial. |
+
+#### `onSubscribe`
+
+Called for subscribing to a GraphQL subscription operation. This hook has a before and after stage.
+You can hook into before and after the GraphQL subscription is executed.
+
+**Example actions in this hook:**
+
+- Collect metrics about execution time
+- Error logging/reporting
+
+| Payload field | Description |
+| --------------------------- | -------------------------------------------------------------------------------------------------------- |
+| `subscribeFn` | Current subscribe function that will be used for setting up the subscription. |
+| `args` | Current arguments with which the subscribe function will be invoked. |
+| `setSubscribeFn` | Replace the current subscribe function with a new one that will be used for setting up the subscription. |
+| `extendContext` | Extend the context object with a partial. |
+| `setResultAndStopExecution` | Set a subscribe result and skip calling the subscribe function. |
+
+#### `onDelegationPlan`
+
+Called each time a delegation plan is calculated for a query. This hook is not called for each
+queries, because the plan is cached. This means it will be called only the first time a query
+document is encountered since the last schema change.
+
+This hook is mostly used for monitoring and tracing purposes.
+
+| Field Name | Description |
+| -------------------------- | -------------------------------------------------------- |
+| `supergraph` | The GraphQL schema of the supergraph. |
+| `subgraph` | The name of the subgraph. |
+| `sourceSubschema` | The source subschema. |
+| `typeName` | The name of the type. |
+| `variables` | The variables used in the request. |
+| `fragments` | The fragments used in the request. |
+| `fieldNodes` | The field nodes of the request. |
+| `context` | The context object. |
+| `requestId` | An optional unique ID identifying the client request. |
+| `logger` | An optional logger instance for the specific request. |
+| `info` | An optional GraphQLResolveInfo object. |
+| `delegationPlanBuilder` | The delegation plan builder. |
+| `setDelegationPlanBuilder` | Function to replace the current delegation plan builder. |
+
+#### `onDelegationStageExecute`
+
#### `onSubgraphExecute`
This hook is invoked for ANY request that is sent to the subgraph.
@@ -114,58 +509,89 @@ This hook is invoked for ANY request that is sent to the subgraph.
You can see [Prometheus plugin](/docs/gateway/authorization-authentication) for an example of how to
use this hook.
-#### `onFetch`
+| Payload Field | Description |
+| --------------------- | ------------------------------------------------------------------------------------------------------- |
+| `subgraph` | The GraphQL schema of the subgraph. |
+| `subgraphName` | The name of the subgraph. |
+| `transportEntry` | The transport entry that will be used to resolve queries for this subgraph |
+| `executionRequest` | The execution request object containing details of the upstream GraphQL operation. |
+| `setExecutionRequest` | Function to replace the current execution request. |
+| `executor` | The executor function used to execute the upstream request. |
+| `setExecutor` | Function to replace the current executor. |
+| `requestId` | A unique ID identifying the client request. |
+| `logger` | The logger instance for the specific request that includes the details of the request and the response. |
-This hook is invoked everytime the gateways sends an outgoing HTTP request to an upstream service.
+#### `onExecutionResult`
+
+This hook is invoked for each result produced for GraphQL operation, before it is processed to be
+sent to client.
+
+In particular, it is useful to handle batched operations. If a request contains batched operations,
+this hook is called once of each operation, while `onResultProcess` will be only called once for the
+entire request.
+
+Here, you can modify the result, to add monitoring or instrumentation extensions for example.
**Example actions in this hook:**
-- Manipulate HTTP [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request) object
-- Manipulate HTTP [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response) object
-- Change [`fetch`](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) implementation
-- Add custom headers
-- Monitor the HTTP request
+- Add metadata to results
+- Collect errors
-**Example plugins:**
+| Payload field | Description |
+| ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
+| `request` | The incoming HTTP request as WHATWG `Request` object. [Learn more about the request](https://developer.mozilla.org/en-US/docs/Web/API/Request). |
+| `result` | The execution result, which can be an `ExecutionResultWithSerializer`, an `AsyncIterable`. |
+| `setResult` | Allows to replace the execution result. |
+| `context` | The GraphQL context. |
-- [Prometheus plugin](/docs/gateway/authorization-authentication)
+#### `onResultProcess`
-##### `API`
+This hook is invoked after a GraphQL request has been processed and before the response is forwarded
+to the client. Here you can customize what transport/response processor format should be used for
+sending the result over the wire.
-- `supergraph`: The unified graph
-- `subgraph`: The subgraph
-- `subgraphName`: The name of the subgraph
-- `transportEntry`: The transport entry for the subgraph including the configuration for the
- upstream communication, and details.
-- `executionRequest`: The execution request object that is sent to the subgraph, that includes
- `document`, `variables`, `contextValue`, `operationName`, and etc.
-- `setExecutionRequest`: A function to replace the execution request object that will be sent to the
- subgraph.
-- `executor`: The executor function that will be used to execute the request to the subgraph, and it
- takes the execution request object.
-- `setExecutor`: A function to replace the executor function
-- `logger`: The logger instance for the specific request that includes the details of the request
- and the response.
+**Example actions in this hook:**
-#### `Symbol.asyncDispose` or `Symbol.dispose`
+- Specify custom response format
+- Logging/Metrics
-In order to clean up resources when Hive Gateway is shut down, you can use `Symbol.asyncDispose` or
-`Symbol.syncDispose` to clean up resources.
+| Field Name | Description |
+| ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `request` | The incoming HTTP request as WHATWG [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request) object. |
+| `result` | The execution result, which can be an `ExecutionResultWithSerializer`, an `AsyncIterable`. If the request contains batch queries, this will be an array |
+| `setResult` | Allows to replace the execution result. |
+| `resultProcessor` | The result processor to be used to turn the result into an HTTP [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Request) object. |
+| `acceptableMediaTypes` | List of acceptable media types for the result processor. |
+| `setResultProcessor` | Allows to set the result processor and the accepted media type. |
+| `serverContext` | The server context which can contain runtime specific data, such as for example `req` and `res` object when running in Node |
-```ts
-export const useMyPlugin = () => {
- return {
- async [Symbol.asyncDispose]() {
- // Clean up resources
- stopConnection()
- }
- }
-}
-```
+#### `onResponse`
-You can learn more about
-[Explicit Resource Management](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-2.html#using-declarations-and-explicit-resource-management)
-here.
+This hook is invoked after a HTTP request (both GraphQL and NON GraphQL) has been processed and
+after the response has been forwarded to the client. Here you can perform any cleanup or logging
+operations, or you can manipulate the outgoing response object.
+
+
+
+Exceptions thrown by this hook are not caught. This means they will buble up to the HTTP server
+underlying implementation.
+
+For example, the `node:http` server crashes the entire process on uncaught exceptions.
+
+Prefer `onRequestParse` when possible, or wrap the hook code in a `try` block.
+
+
+
+**Example actions in this hook:**
+
+- Specify custom response format
+- Logging/Metrics
+
+| Field Name | Description |
+| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `request` | The incoming HTTP request as WHATWG `Request` object. [Learn more about the request](https://developer.mozilla.org/en-US/docs/Web/API/Request). |
+| `serverContext` | The final context object that is shared between all hooks and the GraphQL execution. [Learn more about the context](/docs/features/context). |
+| `response` | The outgoing HTTP response as WHATWG `Response` object. [Learn more about the response interface](https://developer.mozilla.org/en-US/docs/Web/API/Response). |
### Plugin Context
@@ -190,57 +616,3 @@ export const gatewayConfig = defineConfig({
}
})
```
-
-## Example Additional Plugin (SOFA)
-
-GraphQL SOFA allows you to generate a fully documented REST API from your GraphQL schema. This is
-useful when you need to support REST clients or when you want to expose a REST API to the public.
-
-- **Don’t choose between REST and GraphQL**
-- Get most of the **benefits of GraphQL** on the backend and frontend, while using and **exposing
- REST**
-- **Support all your existing clients** with REST while improving your backend stack with GraphQL
-- Create custom, perfectly client-aligned REST endpoints for your frontend simply by naming a route
- and attaching a query
-- In the other way around (REST to GraphQL) you won’t get the best of both worlds. Instead just less
- powerful, harder-to-maintain server implementations with a some of the benefits of GraphQL. It can
- be a good and fast start for a migration though.
-- Fully **generated documentation** that is always up-to-date
-- **GraphQL Subscriptions as Webhooks**
-
-## Installation
-
-```sh npm2yarn
-npm i @graphql-yoga/plugin-sofa
-```
-
-## Quick Start
-
-```ts filename="gateway.config.ts"
-import { defineConfig } from '@graphql-hive/gateway'
-import { useSOFA } from '@graphql-yoga/plugin-sofa'
-
-export const gatewayConfig = defineConfig({
- plugins: pluginCtx => [
- useSOFA({
- // The path where the REST API will be served
- basePath: '/rest',
- // The path where the Swagger UI will be served
- swaggerUIEndpoint: '/rest/docs',
- // OpenAPI Document details
- info: {
- title: 'My API',
- description: 'My API Description',
- version: '1.0.0'
- }
- })
- ]
-})
-```
-
-[Learn more about SOFA](https://the-guild.dev/graphql/sofa-api/docs)
-
-
- You can consume the API using [feTS Client](https://the-guild.dev/openapi/fets/client/quick-start)
- without any code generation!
-