From 273fc8446154e4e6ebf7fcf7e3eff5ff60dd9ec1 Mon Sep 17 00:00:00 2001 From: Jovi De Croock Date: Fri, 8 Nov 2024 16:33:54 +0100 Subject: [PATCH] Write about `@oneOf` in the graphql-js documentation (#4290) Currently input-unions and by extension the `@oneOf` directive aren't present in the documentation. I have opted to put this into the advanced section. The copy might be up for improvement, honestly fire away if there's more cases to cover, just wanted to get the ball rolling here. CC @benjie --------- Co-authored-by: Benjie --- cspell.yml | 1 + website/pages/_meta.ts | 1 + website/pages/oneof-input-objects.mdx | 91 +++++++++++++++++++++++++++ 3 files changed, 93 insertions(+) create mode 100644 website/pages/oneof-input-objects.mdx diff --git a/cspell.yml b/cspell.yml index 1e6bb26c3d..ff26b0902b 100644 --- a/cspell.yml +++ b/cspell.yml @@ -59,6 +59,7 @@ words: - tailwindcss - svgr - ruru + - oneof # used as href anchors - graphqlerror diff --git a/website/pages/_meta.ts b/website/pages/_meta.ts index 0164d2ec1e..7b0f42dca3 100644 --- a/website/pages/_meta.ts +++ b/website/pages/_meta.ts @@ -17,6 +17,7 @@ const meta = { title: 'Advanced Guides', }, 'constructing-types': '', + 'oneof-input-objects': 'OneOf input objects', 'defer-stream': '', '-- 3': { type: 'separator', diff --git a/website/pages/oneof-input-objects.mdx b/website/pages/oneof-input-objects.mdx new file mode 100644 index 0000000000..95be65d2c2 --- /dev/null +++ b/website/pages/oneof-input-objects.mdx @@ -0,0 +1,91 @@ +--- +title: OneOf input objects +--- + +import { Tabs } from 'nextra/components'; + +Some inputs will behave differently depending on what input we choose. Let's look at the case for +a field named `product`, we can fetch a `Product` by either its `id` or its `name`. Currently we'd +make a tradeoff for this by introducing two arguments that are both nullable, now if both are passed +as null (or both non-null) we'd have to handle that in code - the type system wouldn't indicate that exactly one was required. To fix this, the `@oneOf` directive was introduced so we +can create this "exactly one option" constraint without sacrificing the strictly typed nature of our GraphQL Schema. + + + +```js +const schema = buildSchema(` + type Product { + id: ID! + name: String! + } + + input ProductLocation { + aisleNumber: Int! + shelfNumber: Int! + positionOnShelf: Int! + } + + input ProductSpecifier @oneOf { + id: ID + name: String + location: ProductLocation + } + + type Query { + product(by: ProductSpecifier!): Product + } +`); +``` + + +```js +const Product = new GraphQLObjectType({ + name: 'Product', + fields: { + id: { + type: new GraphQLNonNull(GraphQLID), + }, + name: { + type: new GraphQLNonNull(GraphQLString), + }, + }, +}); + +const ProductLocation = new GraphQLInputObjectType({ + name: 'ProductLocation', + isOneOf: true, + fields: { + aisleNumber: { type: GraphQLInt }, + shelfNumber: { type: GraphQLInt }, + positionOnShelf: { type: GraphQLInt }, + }, +}); + +const ProductSpecifier = new GraphQLInputObjectType({ + name: 'ProductSpecifier', + isOneOf: true, + fields: { + id: { type: GraphQLID }, + name: { type: GraphQLString }, + location: { type: ProductLocation }, + }, +}); + +const schema = new GraphQLSchema({ + query: new GraphQLObjectType({ + name: 'Query', + fields: { + product: { + type: Product, + args: { by: { type: ProductSpecifier } }, + }, + }, + }), +}); +``` + + + +It doesn't matter whether you have 2 or more inputs here, all that matters is +that your user will have to specify one, and only one, for this input to be valid. +The values are not limited to scalars, lists and other input object types are also allowed. \ No newline at end of file