home / skills / reactive / data-client / data-client-graphql-setup

data-client-graphql-setup skill

/.cursor/skills/data-client-graphql-setup

This skill configures @data-client/graphql for GraphQL APIs, enabling authenticated endpoints and custom headers with automatic integration after

npx playbooks add skill reactive/data-client --skill data-client-graphql-setup

Review the files below or copy the command above to add this skill to your agents.

Files (1)
SKILL.md
4.5 KB
---
name: data-client-graphql-setup
description: Set up @data-client/graphql for GraphQL APIs. Configures GQLEndpoint with auth and custom options. Use after data-client-setup detects GraphQL patterns.
disable-model-invocation: true
---

# GraphQL Protocol Setup

This skill configures `@data-client/graphql` for a project. It should be applied after `data-client-setup` detects GraphQL patterns.

## Installation

Install the GraphQL package alongside the core package:

```bash
# npm
npm install @data-client/graphql

# yarn
yarn add @data-client/graphql

# pnpm
pnpm add @data-client/graphql
```

## GQLEndpoint Setup

### Basic Configuration

Create a file at `src/api/gql.ts` (or similar):

```ts
import { GQLEndpoint } from '@data-client/graphql';

export const gql = new GQLEndpoint('/graphql');
```

### Detection Checklist

Scan the existing codebase for GraphQL patterns:

1. **GraphQL endpoint URL**: Look for `/graphql` or custom paths
2. **Authentication**: Check for auth headers in existing GraphQL client setup
3. **Custom headers**: API keys, tenant IDs, etc.
4. **Error handling**: GraphQL error parsing patterns

### With Authentication

```ts
import { GQLEndpoint } from '@data-client/graphql';

export const gql = new GQLEndpoint('/graphql', {
  getHeaders() {
    const token = localStorage.getItem('authToken');
    return {
      'Content-Type': 'application/json',
      ...(token && { Authorization: `Bearer ${token}` }),
    };
  },
});
```

### Async Authentication (token refresh)

```ts
import { GQLEndpoint } from '@data-client/graphql';

export const gql = new GQLEndpoint('/graphql', {
  async getHeaders() {
    const token = await getValidToken();
    return {
      'Content-Type': 'application/json',
      Authorization: `Bearer ${token}`,
    };
  },
});
```

### Custom Error Handling

```ts
import { GQLEndpoint } from '@data-client/graphql';

class CustomGQLEndpoint extends GQLEndpoint {
  async fetchResponse(input: RequestInfo, init: RequestInit): Promise<any> {
    const response = await super.fetchResponse(input, init);
    
    // Handle GraphQL errors
    if (response.errors?.length) {
      const authError = response.errors.find(
        e => e.extensions?.code === 'UNAUTHENTICATED'
      );
      if (authError) {
        window.dispatchEvent(new CustomEvent('auth:expired'));
      }
    }
    
    return response;
  }
}

export const gql = new CustomGQLEndpoint('/graphql');
```

## Defining Queries and Mutations

### Query Example

```ts
import { gql } from './gql';
import { User } from '../schemas/User';

export const getUser = gql.query(
  (v: { id: string }) => `
    query GetUser($id: ID!) {
      user(id: $id) {
        id
        name
        email
      }
    }
  `,
  { schema: User },
);
```

### Mutation Example

```ts
import { gql } from './gql';
import { User } from '../schemas/User';

export const updateUser = gql.mutation(
  (v: { id: string; name: string }) => `
    mutation UpdateUser($id: ID!, $name: String!) {
      updateUser(id: $id, name: $name) {
        id
        name
      }
    }
  `,
  { schema: User },
);
```

### With Collection

```ts
import { gql } from './gql';
import { User, UserCollection } from '../schemas/User';

export const listUsers = gql.query(
  () => `
    query ListUsers {
      users {
        id
        name
        email
      }
    }
  `,
  { schema: UserCollection },
);

export const createUser = gql.mutation(
  (v: { name: string; email: string }) => `
    mutation CreateUser($name: String!, $email: String!) {
      createUser(name: $name, email: $email) {
        id
        name
        email
      }
    }
  `,
  { schema: UserCollection.push },
);
```

## Usage in Components

```tsx
import { useSuspense, useController } from '@data-client/react';
import { getUser, updateUser } from './api/users';

function UserProfile({ id }: { id: string }) {
  const user = useSuspense(getUser, { id });
  const ctrl = useController();

  const handleUpdate = async (name: string) => {
    await ctrl.fetch(updateUser, { id, name });
  };

  return (
    <div>
      <h1>{user.name}</h1>
      <button onClick={() => handleUpdate('New Name')}>Update</button>
    </div>
  );
}
```

## Next Steps

1. Apply skill "data-client-schema" to define Entity classes
2. Apply skill "data-client-react" or "data-client-vue" for usage

## References

- [GQLEndpoint](https://dataclient.io/graphql/api/GQLEndpoint) - Full GQLEndpoint API
- [GraphQL Guide](https://dataclient.io/graphql) - GraphQL usage guide
- [Authentication Guide](references/auth.md) - Auth patterns for GraphQL

Overview

This skill sets up @data-client/graphql for GraphQL APIs and creates a ready-to-use GQLEndpoint configured with auth, headers, and custom behavior. It is intended to run after GraphQL patterns are detected by the base data-client setup. The configuration includes examples for synchronous and async authentication, custom error handling, and typical query/mutation definitions. It prepares the project for component usage with suspense and controller fetches.

How this skill works

The skill installs and configures a GQLEndpoint instance (e.g., src/api/gql.ts) and wires common concerns like Content-Type, Authorization headers, and token refresh flows. It can extend GQLEndpoint to parse GraphQL errors and emit application-level events (for example, auth:expired). It also scaffolds query and mutation helpers using provided schemas so responses are normalized and usable by the data-client runtime. Finally, it demonstrates using generated operations with useSuspense and useController in components.

When to use it

  • Your project talks to a GraphQL endpoint and data-client-setup detected GraphQL patterns.
  • You need centralized header and auth handling for GraphQL requests, including token refresh.
  • You want normalized responses with schema integration for queries and mutations.
  • You need custom handling of GraphQL errors (e.g., session expiration hooks).

Best practices

  • Place the GQLEndpoint instance in a single file (src/api/gql.ts) and import it everywhere to keep config centralized.
  • Provide async getHeaders when using token refresh so requests always use valid credentials.
  • Extend GQLEndpoint.fetchResponse to translate GraphQL errors into app events or thrown exceptions consistently.
  • Attach schema definitions to queries and mutations to enable normalization and cache integration.
  • Use useSuspense for reads and useController.fetch for mutations to keep UI and cache in sync.

Example use cases

  • Create a GQLEndpoint that automatically adds Authorization headers from localStorage or an async token provider.
  • Extend GQLEndpoint to detect UNAUTHENTICATED errors and dispatch an auth:expired event to trigger re-auth flows.
  • Define getUser and updateUser operations with attached entity schemas so UI components receive normalized objects.
  • List and create resources using a collection schema and push updates into the cache after mutations.
  • Use useSuspense in React components to read query data and useController.fetch to perform optimistic updates.

FAQ

Do I need to install any package?

Yes. Install @data-client/graphql alongside the core data-client package via npm, yarn, or pnpm.

How do I include auth tokens on every request?

Provide a getHeaders function to GQLEndpoint; make it async if you need to refresh tokens before requests.

How can I handle GraphQL errors globally?

Subclass GQLEndpoint and override fetchResponse to inspect response.errors and emit application events or throw errors.