graphql / graphql/graphql-spec

[RFC] Collections / CollectionTypeDefinition

Open
#937 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
JavaScript
Stars
14.6k
Forks
1.2k
PR merge metrics
No merged PRs in 30d

Description

# TL;DR:
This RFC introduces a new variant of Lists/Arrays that has named entries key-value pairs. Which can be queried exactly like arrays, but a result is an object.

## Problem Statement
If a type object has multiple fields of the same type and it makes sense that they are grouped together and be addressed as a collective instead of being addressed individually, with GraphQL you have three ways you can achieve that. Creating a scalar, creating another type, or using an array and somewhere in the documentation mention which position of an array refers to which named entry.

### Example
Consider the following requirements:
1. a `Build` object consists of 4 `Item`-slots.
2. Slot position matters and it should be readable which slots are equipped.
3. Preferably slots should be grouped together under a common ancestor without any unrelated siblings.
4. Item slots should not be queried/selected individually, the query either includes all slots or non.
5. It's possible to specify which `Item` fields are included.

Initially, the schema may look like this:
```graphql
type Item {
id: String!
name: String!
icon(size: String): String!
}

type Build {
id: String!
slot0Item: Item
slot1Item: Item
slot2Item: Item
slot3Item: Item
}
```

... but that doesn't satisfy the **3rd** and **4th** requirements.

Introducing a new type `ItemSlots` still won't satisfy the **4th** requirement:

```graphql
type Item {
id: String!
name: String!
icon(size: String): String!
}

type ItemSlots {
slot0Item: Item
slot1Item: Item
slot2Item: Item
slot3Item: Item
}

type Build {
id: String!
items: ItemSlots!
}
```

and using a Scalar it's not possible to meet the **5th** requirement.

## 🧑‍💻 Proposed Solution
A new collection type.

## 🎬 Behavior
Collections can be queried exactly as if they were an array/list, but instead of returning an array of `0` to `∞` entries, it returns finite named entries as specified in the schema.

## ✏️ Proposed syntax - `!`
Collections can be defined similarly to how an object type is defined, except fields don't have a type (because all fields are supposed to be of the same type).

```graphql
collection ItemSlots {
slot0
slot1
slot2
slot3
}

type Item {
id: String!
name: String!
icon(size: String): String!
}

type Build {
id: String!
items: ItemSlots! # or `ItemSlots!` if fields are not nullable.
}
```

## ✨ Use cases
* Allows grouping of fields that share the same type and are supposed to be addressed atomically.
* Gets rid of unnecessary/repetitive lines in queries to select the same nested fields across multiple fields.

The `items` field in the above schema can be queried like:
```graphql
query GetBuild($id: String!, $iconSize: String!) {
build(id: $id) {
id
items {
name
icon(iconSize: $iconSize)
}
}
}
```

and the result should look something like this:
```json
{
"data": {
"build": {
"id": "...",
"items": {
"slot0": {
"name": "...",
"icon": "..."
},
"slot1": "...",
"slot2": "...",
"slot3": "..."
}
}
}
}
```

_I should probably note that the template structure of this issue was copied from an RFC of \@\twof. I just found the template very clean and the structure fits my proposal as well. :))_

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.