<commit_before><!--[meta]
section: api
title: Server-side graphQL client
[meta]-->

# Server-side graphQL client

This library provides wrapper functions around `keystone.executeGraphQL` to make it easier to run server-side queries and mutations without needing to write boilerplate GraphQL.

Creating a new `User` item would be written as follows using `keystone.executeGraphQL`:

```js
const { data, errors } = await keystone.executeGraphQL({
  query: `mutation ($item: createUserInput){
    createUser(data: $item) {
      id
      name
    }
  }`,
  variables: { item: { name: 'Alice' } },
});
const user = data.createUserInput;
```

Using `@keystonejs/server-side-graphql-client` we can replace this with

```js
const { createItem } = require('@keystonejs/server-side-graphql-client');

const user = await createItem({
  keystone,
  listKey: 'User',
  item: { name: 'Alice' },
  returnFields: `id name`,
});
```

There are three key differences between `keystone.executeGraphQL` and `createItem` (and other functions from this package):

1. If there is an error, `createItem` will be thrown as an exception, rather than providing the error as a return value.
2. `createItem` runs with _access control disabled_. This is suitable for use cases such as seeding data or other server side scripts where the query is triggered by the system, rather than a specific user. This can be controlled with the `context` option.
3. All queries are internally paginated and all mutations are internally chunked. This can be controlled with the `pageSize` option.

### Use cases

These utilities can be used for a wide range of specific use-cases, some more common examples might include simple data seeding:

```js
const seedUsers = async usersData => {
  await createItems({ keystone, listKey: 'User', items: usersData });
};
```

or fetching data inside hooks:

```js
// This example will copy data from a related field if set
keystone.createList('Page', {
  fields: {
    name: { type: Text },
    content: { type: Text },
    copy: { type: Relationship, ref: 'Page' },
  },
  hooks: {
    resolveInput: async ({ resolvedData }) => {
      // Whenever copy field is set fetch the related data
      const pageToCopy = resolvedData.copy
        ? await getItem({
            keystone,
            listKey: 'Page',
            itemId: resolvedData.copy,
            returnFields: 'name, content',
          })
        : {};
      // resolve data from the copied item and unset the relationship
      return { ...resolvedData, ...pageToCopy, copy: undefined };
    },
  },
});
```

## API

To perform CRUD operations, use the following functions:

- [`createItem`](#createitem)
- [`createItems`](#createitems)
- [`updateItem`](#updateitem)
- [`updateItems`](#updateitems)
- [`deleteItem`](#deleteitem)
- [`deleteItems`](#deleteitems)

For custom queries use [`runCustomQuery`](#runcustomquery).

> NOTE: All functions accept a config object as an argument, and return a `Promise`.

### Shared Config Options

The following config options are common to all server-side graphQL functions.

| Properties     | Type       | Default    | Description                                                                                                                                                                                                         |
| -------------- | ---------- | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `keystone`     | `Keystone` | (required) | Keystone instance.                                                                                                                                                                                                  |
| `listKey`      | `String`   | (required) | Keystone list name.                                                                                                                                                                                                 |
| `returnFields` | `String`   | `id`       | A graphQL fragment of fields to return. Must match the graphQL return type.                                                                                                                                         |
| `context`      | `Object`   | N/A        | An Apollo [`context` object](https://www.apollographql.com/docs/apollo-server/data/resolvers/#the-context-argument). See the [server side graphQL docs](/docs/discussions/server-side-graphql.md) for more details. |

### `createItem`

Create a single item.

#### Usage

```js
const { createItem } = require('@keystonejs/server-side-graphql-client');

keystone.createList('User', {
  fields: {
    name: { type: Text },
    email: { type: String },
  },
});

const addUser = async userInput => {
  const user = await createItem({
    keystone,
    listKey: 'User',
    item: userInput,
    returnFields: `name, email`,
  });
  console.log(user); // { name: 'keystone user', email: '<EMAIL>'}
};

addUser({ name: 'keystone user', email: '<EMAIL>' });
```

#### Config

[Shared Config Options](#shared-config-options) apply to this function.

| Properties | Type                           | Default    | Description             |
| ---------- | ------------------------------ | ---------- | ----------------------- |
| `item`     | GraphQL `[listKey]CreateInput` | (required) | The item to be created. |

### `createItems`

Create multiple items.
<commit_msg>Added an example on how to populate a relationship field in createItem (#3334)<commit_after><!--[meta]
section: api
title: Server-side graphQL client
[meta]-->

# Server-side graphQL client

This library provides wrapper functions around `keystone.executeGraphQL` to make it easier to run server-side queries and mutations without needing to write boilerplate GraphQL.

Creating a new `User` item would be written as follows using `keystone.executeGraphQL`:

```js
const { data, errors } = await keystone.executeGraphQL({
  query: `mutation ($item: createUserInput){
    createUser(data: $item) {
      id
      name
    }
  }`,
  variables: { item: { name: 'Alice' } },
});
const user = data.createUserInput;
```

Using `@keystonejs/server-side-graphql-client` we can replace this with

```js
const { createItem } = require('@keystonejs/server-side-graphql-client');

const user = await createItem({
  keystone,
  listKey: 'User',
  item: { name: 'Alice' },
  returnFields: `id name`,
});
```

There are three key differences between `keystone.executeGraphQL` and `createItem` (and other functions from this package):

1. If there is an error, `createItem` will be thrown as an exception, rather than providing the error as a return value.
2. `createItem` runs with _access control disabled_. This is suitable for use cases such as seeding data or other server side scripts where the query is triggered by the system, rather than a specific user. This can be controlled with the `context` option.
3. All queries are internally paginated and all mutations are internally chunked. This can be controlled with the `pageSize` option.

### Use cases

These utilities can be used for a wide range of specific use-cases, some more common examples might include simple data seeding:

```js
const seedUsers = async usersData => {
  await createItems({ keystone, listKey: 'User', items: usersData });
};
```

or fetching data inside hooks:

```js
// This example will copy data from a related field if set
keystone.createList('Page', {
  fields: {
    name: { type: Text },
    content: { type: Text },
    copy: { type: Relationship, ref: 'Page' },
  },
  hooks: {
    resolveInput: async ({ resolvedData }) => {
      // Whenever copy field is set fetch the related data
      const pageToCopy = resolvedData.copy
        ? await getItem({
            keystone,
            listKey: 'Page',
            itemId: resolvedData.copy,
            returnFields: 'name, content',
          })
        : {};
      // resolve data from the copied item and unset the relationship
      return { ...resolvedData, ...pageToCopy, copy: undefined };
    },
  },
});
```

## API

To perform CRUD operations, use the following functions:

- [`createItem`](#createitem)
- [`createItems`](#createitems)
- [`updateItem`](#updateitem)
- [`updateItems`](#updateitems)
- [`deleteItem`](#deleteitem)
- [`deleteItems`](#deleteitems)

For custom queries use [`runCustomQuery`](#runcustomquery).

> NOTE: All functions accept a config object as an argument, and return a `Promise`.

### Shared Config Options

The following config options are common to all server-side graphQL functions.

| Properties     | Type       | Default    | Description                                                                                                                                                                                                         |
| -------------- | ---------- | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `keystone`     | `Keystone` | (required) | Keystone instance.                                                                                                                                                                                                  |
| `listKey`      | `String`   | (required) | Keystone list name.                                                                                                                                                                                                 |
| `returnFields` | `String`   | `id`       | A graphQL fragment of fields to return. Must match the graphQL return type.                                                                                                                                         |
| `context`      | `Object`   | N/A        | An Apollo [`context` object](https://www.apollographql.com/docs/apollo-server/data/resolvers/#the-context-argument). See the [server side graphQL docs](/docs/discussions/server-side-graphql.md) for more details. |

### `createItem`

Create a single item.

#### Usage

```js
const { createItem } = require('@keystonejs/server-side-graphql-client');

keystone.createList('User', {
  fields: {
    name: { type: Text },
    email: { type: String },
  },
});

const addUser = async userInput => {
  const user = await createItem({
    keystone,
    listKey: 'User',
    item: userInput,
    returnFields: `name, email`,
  });
  console.log(user); // { name: 'keystone user', email: '<EMAIL>'}
};

addUser({ name: 'keystone user', email: '<EMAIL>' });
```

**Note**: The `item` property is a graphQL create input. For Relationship fields it can contain nested mutations with create and connect operations. For examples see the [Relationship API documentation](/packages/fields/src/types/Relationship/README.md#create-and-append-a-related-item).

#### Config

[Shared Config Options](#shared-config-options) apply to this function.

| Properties | Type                           | Default    | Description             |
| ---------- | ------------------------------ | ---------- | ----------------------- |
| `item`     | GraphQL `[listKey]CreateInput` | (required) | The item to be created. |

### `createItems`

Create multiple items.

{'fraction_non_alphanumeric': 0.1594782608695652, 'fraction_numerical': 0.0008695652173913044, 'mean_word_length': 1.7501195600191295, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 17, 'https://': 2, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 66, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6951325', 'n_tokens_mistral': 2805, 'n_tokens_neox': 2697, 'n_words': 967}