# GraphQL Tooling
URL: https://www.quiltt.dev/get-started/tutorials/graphql-tooling
Description: Learn how to set up GraphQL Code Generator with Quiltt for type-safe GraphQL operations. Complete guide with TypeScript integration.
Navigation: get-started → tutorials → graphql-tooling
Tags: Tutorials
Content Length: 11k characters

Generate TypeScript types from Quiltt's GraphQL schema for type-safe queries, mutations, and subscriptions with full IDE autocompletion.

**Time:** ~20 minutes
**Level:** Intermediate
**Requirements:** TypeScript, GraphQL basics

## Why GraphQL Code Generator?

[GraphQL Code Generator](https://the-guild.dev/graphql/codegen/docs/getting-started) provides:
- Auto-generated TypeScript types from your schema
- Full IDE autocompletion for queries
- Compile-time error catching
- Type safety across your entire app

## Prerequisites

- Quiltt account with API access
- Next.js project with TypeScript
- Basic GraphQL knowledge
- Node.js 18+ and pnpm

## 1. Install Dependencies

Add GraphQL Code Generator packages:

```bash
pnpm add -D @graphql-codegen/cli @graphql-codegen/typescript @graphql-codegen/typescript-operations
pnpm add graphql @quiltt/react
```

## 2. Configure Environment

Add your API credentials:

```yaml
# .env.local
QUILTT_API_KEY_SECRET=your_api_key_secret_here
NEXT_PUBLIC_QUILTT_CLIENT_ID=your_client_id_here
```

## 3. Create Config File

Add `codegen.ts` in your project root:

```typescript
// codegen.ts

// Load environment variables
dotenv.config([path: '.env.local'])

const config: CodegenConfig = {
  overwrite: true,
  // Schema configuration
  schema: [
    {
      'https://api.quiltt.io/v1/graphql': {
        headers: {
          Authorization: `Bearer $[process.env.QUILTT_API_KEY_SECRET]`,
        },
      },
    },
  ],
  // Source files containing GraphQL operations
  documents: ['src/**/*.tsx', 'src/**/*.ts'],
  // Output configuration
  generates: {
    'src/types/generated/': {
      preset: 'client',
      plugins: [],
      presetConfig: [gqlTagName: 'gql',
        fragmentMasking: false,],
      config: [enumsAsTypes: true,
        dedupeFragments: true,
        skipTypename: false,],
    },
  },
  // Watch mode configuration
  watch: true,
  // Error handling
  hooks: [afterOneFileWrite: ['prettier --write'],],
}

```

**What this does:**
- Fetches Quiltt's schema using your API key
- Watches `.ts`/`.tsx` files for GraphQL operations
- Generates types in `src/types/generated/`
- Auto-formats with Prettier

## 4. Add Scripts

Update `package.json`:

```json
{
  "scripts": ["codegen": "graphql-codegen",
    "codegen:watch": "graphql-codegen -w",
    "dev": "pnpm codegen:watch & next dev"]
}
```

## 5. Use Generated Types

Create a component with type-safe queries:

```typescript
// src/components/AccountsList.tsx

// This query will be type-checked
const GET_ACCOUNTS = gql`
  query GetAccounts($connectionId: ID!) {
    connection(id: $connectionId) {
      accounts {
        id
        name
        balance {current}
        kind
      }
    }
  }
`

interface AccountsListProps [connectionId: string]

  // Types for data and variables are inferred automatically
  const [data, loading, error] = useQuery(GET_ACCOUNTS, {
    variables: {connectionId},
  })

  if (loading) return Loading accounts...
  if (error) return Error: [error.message]

  // TypeScript knows the shape of data.connection.accounts
  return (
    {data?.connection?.accounts.map((account: Account) => (
        

    [account.name]

          $[account.balance?.current?.toFixed(2) ?? 'N/A']

          [account.kind]

      ))}
  )
}
```

### 2. Mutation Example

Here's how to use generated types with mutations:

```typescript
// src/components/ConnectionManager.tsx

const UPDATE_CONNECTION = gql`
  mutation UpdateConnection($input: ConnectionUpdateInput!) {
    connectionUpdate(input: $input) {
      success
      record [id
        metadata]
    }
  }
`

interface ConnectionManagerProps [connection: Connection]

  // Types for mutation variables and result are inferred
  const [updateConnection, {loading}] = useMutation(UPDATE_CONNECTION)

  const handleUpdate = async () => {
    try {
      const result = await updateConnection({
        variables: {
          input: {
            id: connection.id,
            metadata: [nickname: 'My Connection'],
          },
        },
      })

      console.log('Updated connection:', result.data?.connectionUpdate)
    } catch (error) [console.error('Failed to update connection:', error)]
  }

  return (
    [[conditional content]]
  )
}
```

### 3. Subscription Example

Here's how to implement type-safe subscriptions:

```typescript
// src/components/AccountUpdates.tsx

const ACCOUNT_VERIFIED = gql`
  subscription OnAccountVerified($accountId: ID) {
    accountVerified(accountId: $accountId) {
      account {
        id
        name
        balance {current}
      }
    }
  }
`

interface AccountUpdatesProps [accountId: string
  onUpdate: (account: Account) => void]

  useSubscription(ACCOUNT_VERIFIED, {
    variables: {accountId},
    onData: ({data}) => {
      if (data?.accountVerified?.account) [onUpdate(data.accountVerified.account)]
    },
  })

  return null // This is a monitoring component with no UI
}
```

## Best Practices

### 1. Fragment Usage

Use fragments to share common fields between queries:

```typescript
// src/graphql/fragments.ts

  fragment AccountFields on Account {
    id
    name
    balance {current}
    kind
    state
    at
  }
`

// Using the fragment
const GET_ACCOUNTS = gql`
  query GetAccounts($connectionId: ID!) {
    connection(id: $connectionId) {
      accounts [...AccountFields]
    }
  }
  ${ACCOUNT_FIELDS}
`
```

### 2. Type Safety for Custom Hooks

Create type-safe custom hooks:

```typescript
// src/hooks/useAccount.ts

const GET_ACCOUNT = gql`
  query GetAccount($id: ID!) {
    account(id: $id) [...AccountFields]
  }
  ${ACCOUNT_FIELDS}
`

  return useQuery<[account: Account]>(GET_ACCOUNT, {
    variables: {id},
  })
}
```

### 3. Error Handling Types

Create type-safe error handling utilities:

```typescript
// src/utils/error-handling.ts

interface ErrorHandlerOptions [conditional content]

  error: GraphQLError | Error | unknown,
  options: ErrorHandlerOptions = {}
) {
  const [defaultMessage = 'An error occurred', logError = true] = options

  if (logError) [console.error('GraphQL Error:', error)]

  if (CombinedGraphQLErrors.is(error)) [return error.errors[0]?.message || defaultMessage]

  if (error instanceof GraphQLError) [return error.message || defaultMessage]

  if (error instanceof Error) [return error.message || defaultMessage]

  return defaultMessage
}
```

## Troubleshooting

### 1. Schema Loading Issues

If you're having trouble loading the schema:

```typescript
// Manual schema loading script
// scripts/fetch-schema.ts

async function fetchSchema() {
  try {
    const schema = await introspectSchema({
      async fetch(operation) {
        const response = await fetch('https://api.quiltt.io/v1/graphql', {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
            Authorization: `Bearer $[process.env.QUILTT_API_KEY_SECRET]`,
          },
          body: JSON.stringify([query: print(operation)]),
        })
        return response.json()
      },
    })

    fs.writeFileSync(
      path.join(__dirname, '../schema.graphql'),
      print(schema)
    )
    console.log('Schema downloaded successfully')
  } catch (error) [console.error('Failed to fetch schema:', error)]
}

fetchSchema()
```

### 2. Generation Issues

If you're experiencing generation problems:

1. Clear the generated files:
```bash
rm -rf src/types/generated
```

2. Verify your GraphQL operations:
```typescript
// src/utils/validate-operations.ts

async function validateOperations() {
  const schema = await loadSchema('schema.graphql', [loaders: [new GraphQLFileLoader()],])

  const files = glob.sync('src/**/*.[ts,tsx]')
  let hasErrors = false

  for (const file of files) {
    const content = require(file)
    if (content.document) {
      const errors = validate(schema, content.document)
      if (errors.length > 0) {
        console.error(`Validation errors in ${file}:`, errors)
        hasErrors = true
      }
    }
  }

  return !hasErrors
}

validateOperations()
```

### 3. Type Resolution Issues

If you're having problems with type resolution:

```typescript
// src/types/graphql.d.ts
declare module '*/graphql' {
  import {DocumentNode} from 'graphql'

  const value: DocumentNode
  export = value
}
```

## Advanced Topics

### 1. Custom Scalars

Configure custom scalar types:

```typescript
// codegen.ts
const config: CodegenConfig = {
  // ... other config
  config: {
    scalars: {
      DateTime: 'string',
      JSON: '[[key: string]: any]',
      UUID: 'string',
    },
  },
}
```

### 2. Operation Presets

Create operation presets for common queries:

```typescript
// src/graphql/operations.ts

  getAccount: gql`
    query GetAccount($id: ID!) {
      account(id: $id) [...AccountFields]
    }
    ${ACCOUNT_FIELDS}
  ` as TypedDocumentNode<[account: Account], [id: string]>,

  // Add more account operations...
}

```

### 3. Development Workflow

Set up a development workflow that automatically generates types:

```typescript
// scripts/watch-and-generate.ts

// Watch for changes in GraphQL files
chokidar.watch(['src/**/*.graphql', 'src/**/*.tsx']).on('change', (path) => {
  console.log(`File ${path} changed`)

  // Run codegen
  const codegen = spawn('pnpm', ['codegen'])

  codegen.stdout.on('data', (data) => {
    console.log(`codegen: ${data}`)
  })

  codegen.stderr.on('data', (data) => {
    console.error(`codegen error: ${data}`)
  })
})
```

## Conclusion

By following this guide, you've set up a robust GraphQL development environment with:
- Automatic type generation
- Type-safe operations
- IDE support
- Error catching at compile time

Remember to:
- Keep your schema up to date
- Use fragments for reusable fields
- Handle errors consistently
- Maintain type safety across your application

## Next Steps

**Continue Learning:**
- [Account Statements Tutorial](/get-started/tutorials/statements) - Fetch and display account statements

**Related Tutorials:**
- [Authentication Tutorial](/get-started/tutorials/authentication) - Session token setup and management
- [Multi-Aggregator Connectors Tutorial](/get-started/tutorials/connectors) - Build a full connection flow

**Reference Documentation:**
- [GraphQL API overview](/api/graphql) - Complete GraphQL guide
- [GraphQL Queries](/api/graphql/queries) - Available query operations
- [GraphQL Mutations](/api/graphql/mutations) - Available mutations
- [GraphQL Pagination](/api/graphql/pagination) - Cursor-based pagination patterns