Browse Source

feat(docs): Add docs on resolving union types in plugin examples

Michael Bromley 4 years ago
parent
commit
b84ae33792
1 changed files with 56 additions and 0 deletions
  1. 56 0
      docs/content/plugins/plugin-examples/extending-graphql-api.md

+ 56 - 0
docs/content/plugins/plugin-examples/extending-graphql-api.md

@@ -168,3 +168,59 @@ export class FieldOverrideExampleResolver {
 }
 ```
 
+## Resolving union results
+
+When dealing with operations that return a GraphQL union type, there is an extra step needed.
+
+Union types are commonly returned from mutations in the Vendure APIs. For more detail on this see the section on [ErrorResults]({{< relref "error-handling" >}}#expected-errors-errorresults). For example: 
+
+```GraphQL
+type MyCustomErrorResult implements ErrorResult {
+  errorCode: ErrorCode!
+  message: String!
+}
+
+union MyCustomMutationResult = Order | MyCustomErrorResult
+
+extend type Mutation {
+  myCustomMutation(orderId: ID!): MyCustomMutationResult!
+}
+```
+
+In this example, the resolver which handles the `myCustomMutation` operation will be returning either an `Order` object or a `MyCustomErrorResult` object. The problem here is that the GraphQL server has no way of knowing which one it is at run-time. Luckily Apollo Server (on which Vendure is built) has a means to solve this:
+
+> To fully resolve a union, Apollo Server needs to specify which of the union's types is being returned. To achieve this, you define a `__resolveType` function for the union in your resolver map.
+> 
+> The `__resolveType` function is responsible for determining an object's corresponding GraphQL type and returning the name of that type as a string.
+> 
+-- <cite>Source: [Apollo Server docs](https://www.apollographql.com/docs/apollo-server/schema/unions-interfaces/#resolving-a-union)</cite>
+
+In order to implement a `__resolveType` function as part of your plugin, you need to create a dedicated Resolver class with a single field resolver method which will look like this:
+
+```TypeScript
+import { Parent, ResolveField, Resolver } from '@nestjs/graphql';
+import { Ctx, RequestContext, ProductVariant } from '@vendure/core';
+
+@Resolver('MyCustomMutationResult')
+export class MyCustomMutationResultResolver {
+  
+  @ResolveField()
+  __resolveType(value: any): string {
+    // If it has an "id" property we can assume it is an Order.  
+    return value.hasOwnProperty('id') ? 'Order' : 'MyCustomErrorResult';
+  }
+}
+```
+
+This resolver is then passed in to your plugin metadata like any other resolver:
+
+```TypeScript
+@VendurePlugin({
+  imports: [PluginCommonModule],
+  shopApiExtensions: {
+    schema: gql` ... `,
+    resolvers: [/* ... */, MyCustomMutationResultResolver]
+  }
+})
+export class MyPlugin {}
+```