Skip to content

Commit

Permalink
docs: add documentation for discriminator (#531)
Browse files Browse the repository at this point in the history
Co-authored-by: Tushar Mathur <[email protected]>
  • Loading branch information
karatakis and tusharmath authored Nov 18, 2024
1 parent 5d5328a commit 6ba9a29
Show file tree
Hide file tree
Showing 4 changed files with 415 additions and 18 deletions.
35 changes: 18 additions & 17 deletions docs/directives.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,21 @@ Here is a list of all the custom directives supported by Tailcall:

<!-- SORT OPERATOR BY NAME -->

| Operator | Description |
| ----------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
| [`@addField`](./directives/addField.md) | Simplifies data structures and queries by adding, inlining, or flattening fields or nodes within the schema. |
| [`@cache`](./directives/cache.md) | Enables caching for the query, field or type applied to. |
| [`@call`](./directives/call.md) | Invokes a query or mutation from another query or mutation field. |
| [`@expr`](./directives/expr.md) | Allows embedding of a constant response within the schema. |
| [`@graphQL`](./directives/graphQL.md) | Resolves a field or node by a GraphQL API. |
| [`@grpc`](./directives/grpc.md) | Resolves a field or node by a gRPC API. |
| [`@http`](./directives/http.md) | Resolves a field or node by a REST API. |
| [`@link`](./directives/link.md) | Imports external resources such as config files, certs, protobufs, etc in the schema. |
| [`@modify`](./directives/modify.md) | Enables changes to attributes of fields or nodes in the schema. |
| [`@omit`](./directives/omit.md) | Excludes fields or nodes from the generated schema, making them inaccessible through the GraphQL API. |
| [`@protected`](./directives/protected.md) | Adds authentication and authorization controls to fields or nodes in the schema. |
| [`@rest`](./directives/rest.md) | Allows exposing REST endpoints on top of GraphQL. |
| [`@server`](./directives/server.md) | Provides server configurations for behavior tuning and tailcall optimization in specific use-cases. |
| [`@telemetry`](./directives/telemetry.md) | Integrates with open-telemetry to provide observability of the running tailcall service. |
| [`@upstream`](./directives/upstream.md) | Controls aspects of the upstream server connection, including timeouts and keep-alive settings. |
| Operator | Description |
| ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
| [`@addField`](./directives/addField.md) | Simplifies data structures and queries by adding, inlining, or flattening fields or nodes within the schema. |
| [`@cache`](./directives/cache.md) | Enables caching for the query, field or type applied to. |
| [`@call`](./directives/call.md) | Invokes a query or mutation from another query or mutation field. |
| [`@discriminate`](./directives/discriminate.md) | Allows to customize the discriminator while working with union types. |
| [`@expr`](./directives/expr.md) | Allows embedding of a constant response within the schema. |
| [`@graphQL`](./directives/graphQL.md) | Resolves a field or node by a GraphQL API. |
| [`@grpc`](./directives/grpc.md) | Resolves a field or node by a gRPC API. |
| [`@http`](./directives/http.md) | Resolves a field or node by a REST API. |
| [`@link`](./directives/link.md) | Imports external resources such as config files, certs, protobufs, etc in the schema. |
| [`@modify`](./directives/modify.md) | Enables changes to attributes of fields or nodes in the schema. |
| [`@omit`](./directives/omit.md) | Excludes fields or nodes from the generated schema, making them inaccessible through the GraphQL API. |
| [`@protected`](./directives/protected.md) | Adds authentication and authorization controls to fields or nodes in the schema. |
| [`@rest`](./directives/rest.md) | Allows exposing REST endpoints on top of GraphQL. |
| [`@server`](./directives/server.md) | Provides server configurations for behavior tuning and tailcall optimization in specific use-cases. |
| [`@telemetry`](./directives/telemetry.md) | Integrates with open-telemetry to provide observability of the running tailcall service. |
| [`@upstream`](./directives/upstream.md) | Controls aspects of the upstream server connection, including timeouts and keep-alive settings. |
82 changes: 82 additions & 0 deletions docs/directives/discriminate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
---
title: "@discriminate"
description: The `@discriminate` directive is used to customize decoding of union types.
slug: ../discriminate
---

By default a union type expects an object with a wrapper key representing the value type. For example say we have the following GraphQL schema:

```graphql showLineNumbers
type Query {
fooBar: [FooBar]
@http(url: "https://api.example.com/foobar")
}

union FooBar = Foo | Bar

type Foo {
foo: String!
}

type Bar {
bar: String!
}
```

The API is expected to respond with an object that is wrapped with a key representing the type of the value. For example for `Foo` the response should look like:

```json
[
// API Response
{"Foo": {"foo": "Hello"}},
{"Bar": {"bar": "World"}}
]
```

:::note
The **key** is always case sensitive and should match the type name.
:::

This allows Tailcall to correctly decode the response and resolve with the exact variant of the union type. However its also a common practice to have a special field to specify the type. For example:

```json
[
{"type": "Foo", "foo": "Hello"},
{"type": "Boo", "bar": "World"}
]
```

This can be achieved by modifying the schema to leverage the `@discriminate` directive:

```graphql {4}
type Query {
fooBar: FooBar
@http(url: "https://api.example.com/foobar")
@discriminate
}
```

The `@discriminate` directive is used to indicate explicitly that the union type should be resolved using a discriminator field.

The directive can be further customized by providing the discriminator field `name`:

```graphql {4}
type Query {
fooBar: FooBar
@http(url: "https://api.example.com/foobar")
@discriminate(name: "ty")
}
```

In this case the API is expected to respond with an object that has a key `ty` representing the type of the value. For example for `Foo` the response should look like:

```json
{"ty": "Foo","foo": "Hello"}
{"ty": "Bar","bar": "World"}
```

:::note
The value of the discriminator field should match the type name in a case sensitive manner.
:::

Great! Congratulations on learning how to use the `@discriminate` directive to customize decoding of union types. Now you can confidently work with union types in your GraphQL schema. 🎉
Loading

0 comments on commit 6ba9a29

Please sign in to comment.