logo_smallAxellero.io

GraphQL

Execute GraphQL queries and mutations with schema discovery and auto-completion.

GraphQL Node

Execute GraphQL queries and mutations with schema discovery, variable binding, and validation in Axellero workflows.

Features

  • Schema Discovery: Automatic introspection and schema loading
  • Auto-completion: Field, argument, and type suggestions
  • Query & Mutation Support: Execute any GraphQL operation
  • Variable Binding: Dynamic parameter injection from workflow context
  • Result Processing: Structured response handling with error details
  • Authentication Support: Bearer tokens, API keys, and custom headers

Schema-Aware Editing

GraphQL nodes provide schema-aware editing with auto-completion for fields, arguments, and types based on GraphQL endpoint schema.

Quick Navigation

Schema Configuration

Configure your GraphQL endpoint to enable schema discovery and auto-completion:

ParameterTypeRequiredDescription
endpointTEXTYesGraphQL endpoint URL (e.g., https://api.example.com/graphql)
introspectionEnabledBOOLEANNoEnable automatic schema introspection (default: true)
schemaUrlTEXTNoCustom URL for schema.json or schema.graphql file
timeoutINTNoRequest timeout in milliseconds (default: 30000)

Basic Configuration

{
  "endpoint": "https://api.github.com/graphql",
  "introspectionEnabled": true,
  "headers": {
    "Authorization": "Bearer {{ctx.consts.GITHUB_TOKEN}}",
    "User-Agent": "Axellero/1.0"
  }
}

Custom Schema Loading

{
  "endpoint": "https://api.example.com/graphql",
  "schemaUrl": "https://api.example.com/schema.graphql",
  "introspectionEnabled": false
}

Authentication Methods

Authentication Requirements

GraphQL endpoints often require authentication for introspection.

Bearer Token Authentication

Most common for GraphQL APIs:

{
  "endpoint": "https://api.example.com/graphql",
  "headers": {
    "Authorization": "Bearer {{ctx.consts.API_TOKEN}}",
    "Content-Type": "application/json"
  }
}

API Key Authentication

{
  "endpoint": "https://api.example.com/graphql",
  "headers": {
    "X-API-Key": "{{ctx.consts.API_KEY}}",
    "Content-Type": "application/json"
  }
}
{
  "endpoint": "https://api.example.com/graphql",
  "headers": {
    "Authorization": "ApiKey {{ctx.consts.API_KEY}}",
    "Content-Type": "application/json"
  }
}

Custom Authentication Headers

{
  "endpoint": "https://hasura.io/learn/graphql",
  "headers": {
    "x-hasura-admin-secret": "{{ctx.consts.HASURA_SECRET}}",
    "x-hasura-role": "{{ctx.user.roles[0]}}"
  }
}

GraphQL Operations

Simple Data Queries

Execute GraphQL queries with schema validation:

Query Configuration:

query GetUser($userId: ID!) {
  user(id: $userId) {
    id
    name
    email
    profile {
      avatar
      bio
    }
    posts(first: 10) {
      edges {
        node {
          id
          title
          publishedAt
        }
      }
    }
  }
}

Variables:

{
  "userId": "{{ctx.vars.selectedUserId}}"
}

Complex Queries with Fragments

fragment UserProfile on User {
  id
  name
  email
  profile {
    avatar
    bio
    socialLinks {
      platform
      url
    }
  }
}

query GetUserWithPosts($userId: ID!, $postCount: Int = 5) {
  user(id: $userId) {
    ...UserProfile
    posts(first: $postCount, orderBy: CREATED_AT_DESC) {
      pageInfo {
        hasNextPage
        endCursor
      }
      edges {
        node {
          id
          title
          content
          publishedAt
          tags {
            name
            color
          }
        }
      }
    }
  }
}

Variables:

{
  "userId": "{{ctx.nodes.userSelector.outputs.id}}",
  "postCount": "{{ctx.vars.pageSize || 10}}"
}

Pagination with Cursors

query GetPaginatedPosts($after: String, $first: Int = 20) {
  posts(after: $after, first: $first) {
    pageInfo {
      hasNextPage
      hasPreviousPage
      startCursor
      endCursor
    }
    edges {
      cursor
      node {
        id
        title
        author {
          name
          avatar
        }
        publishedAt
      }
    }
  }
}

Creating Data

Execute mutations to modify data on the GraphQL server:

mutation CreatePost($input: CreatePostInput!) {
  createPost(input: $input) {
    post {
      id
      title
      content
      publishedAt
      author {
        id
        name
      }
    }
    errors {
      field
      message
    }
  }
}

Variables:

{
  "input": {
    "title": "{{ctx.nodes.postEditor.outputs.title}}",
    "content": "{{ctx.nodes.postEditor.outputs.content}}",
    "tags": "{{ctx.vars.selectedTags}}",
    "publishedAt": "{{ctx.nodes.timer.outputs.currentTime}}"
  }
}

Updating Existing Data

mutation UpdateUser($id: ID!, $input: UpdateUserInput!) {
  updateUser(id: $id, input: $input) {
    user {
      id
      name
      email
      updatedAt
    }
    success
    errors {
      field
      message
      code
    }
  }
}

Variables:

{
  "id": "{{ctx.user.id}}",
  "input": {
    "name": "{{ctx.nodes.profileForm.outputs.name}}",
    "email": "{{ctx.nodes.profileForm.outputs.email}}",
    "profileAttributes": "{{ctx.nodes.profileForm.outputs.attributes}}"
  }
}

Batch Operations

mutation BatchCreatePosts($posts: [CreatePostInput!]!) {
  createPosts(input: $posts) {
    posts {
      id
      title
      publishedAt
    }
    successCount
    errorCount
    errors {
      index
      field
      message
    }
  }
}

Workflow Context Integration

📖 Reference

For context documentation, see the Workflow Context reference.

Dynamic Query Building

Build queries using workflow data and user context:

query GetUserContent($userId: ID!, $userRole: Role!, $workspaceId: ID!) {
  user(id: $userId) {
    id
    name
    # Conditional fields based on user role
    posts(workspaceId: $workspaceId) @include(if: $canViewPosts) {
      id
      title
      status
    }
    adminData @include(if: $isAdmin) {
      lastLogin
      permissions
    }
  }
}

Variables with Context:

{
  "userId": "{{ctx.vars.targetUserId}}",
  "userRole": "{{ctx.user.roles[0]}}",
  "workspaceId": "{{ctx.workspace_id}}",
  "canViewPosts": "{{ctx.user.roles.includes('viewer')}}",
  "isAdmin": "{{ctx.user.roles.includes('admin')}}"
}

Conditional Mutations

Execute different mutations based on workflow conditions:

mutation UpsertUserProfile($userId: ID!, $profileData: ProfileInput!) {
  upsertProfile(userId: $userId, data: $profileData) {
    profile {
      id
      userId
      displayName
      avatar
      settings {
        theme
        notifications
      }
    }
    isNewProfile
  }
}

Variables:

{
  "userId": "{{ctx.user.id}}",
  "profileData": {
    "displayName": "{{ctx.nodes.userInput.outputs.displayName}}",
    "avatar": "{{ctx.nodes.fileUpload.outputs.imageUrl}}",
    "settings": {
      "theme": "{{ctx.vars.userPreferences.theme}}",
      "notifications": "{{ctx.vars.userPreferences.notifications}}"
    },
    "workspaceId": "{{ctx.workspace_id}}"
  }
}

Response Processing

Success Response Format

{
  "data": {
    "user": {
      "id": "user_123",
      "name": "John Doe",
      "email": "john@example.com",
      "posts": {
        "edges": [
          {
            "node": {
              "id": "post_456",
              "title": "My First Post",
              "publishedAt": "2024-01-15T10:30:00Z"
            }
          }
        ]
      }
    }
  },
  "success": true
}

Error Response Format

{
  "data": null,
  "errors": [
    {
      "message": "Field 'nonExistentField' doesn't exist on type 'User'",
      "locations": [{"line": 3, "column": 5}],
      "path": ["user", "nonExistentField"],
      "extensions": {
        "code": "VALIDATION_ERROR",
        "fieldName": "nonExistentField"
      }
    }
  ],
  "success": false
}

Partial Data with Errors

{
  "data": {
    "user": {
      "id": "user_123",
      "name": "John Doe",
      "posts": null
    }
  },
  "errors": [
    {
      "message": "Access denied for field 'posts'",
      "path": ["user", "posts"],
      "extensions": {
        "code": "FORBIDDEN"
      }
    }
  ],
  "success": false
}

Editor Features

GraphQL Editor Capabilities:

  • Schema Auto-completion: Field names, arguments, and types from introspected schema
  • Query Validation: Syntax and schema validation
  • Variable Extraction: Automatic detection of query variables
  • Fragment Support: Auto-completion for fragments and spreads
  • Error Highlighting: Inline error display with helpful suggestions
  • Query Formatting: Automatic code formatting and indentation

For complete editor details, see Code Editing & Schema Reference.

Schema Explorer

Schema Discovery

The GraphQL editor includes an interactive schema explorer that shows all available types, fields, and their documentation directly in the editing interface.

Explorer Features:

  • Type Browser: Navigate through all GraphQL types and interfaces
  • Field Documentation: View field descriptions and deprecation notices
  • Argument Details: See required arguments and their types
  • Example Generation: Auto-generate query examples from schema

Additional Features

Query Aliasing

query GetMultipleUsers($id1: ID!, $id2: ID!) {
  user1: user(id: $id1) {
    id
    name
    email
  }
  user2: user(id: $id2) {
    id
    name
    email
  }
}

Directive Usage

query GetUserData($includePrivate: Boolean!, $skipCache: Boolean!) {
  user {
    id
    name
    email
    privateData @include(if: $includePrivate) {
      ssn
      bankAccount
    }
    posts @skip(if: $skipCache) {
      id
      title
    }
  }
}

Error Handling

Query Validation Errors

{
  "validationErrors": [
    {
      "message": "Cannot query field 'invalidField' on type 'User'",
      "line": 5,
      "column": 3
    }
  ],
  "success": false
}

Network and Server Errors

{
  "error": "Network timeout after 30000ms",
  "statusCode": 408,
  "success": false
}

Performance Optimization

Query Optimization

Query Complexity

Be mindful of query complexity and depth. Complex nested queries can impact performance and may be rejected by GraphQL servers with query complexity limits.

Best Practices:

  • Use fragments to avoid repetition
  • Limit field selection to only required data
  • Implement pagination for large data sets
  • Use query variables instead of inline values
  • Cache frequently used queries

Connection Patterns

query GetPagedData($first: Int!, $after: String) {
  items(first: $first, after: $after) {
    pageInfo {
      hasNextPage
      endCursor
    }
    edges {
      cursor
      node {
        id
        title
      }
    }
  }
}

Getting Started

  1. Configure Endpoint: Set up your GraphQL endpoint URL and authentication
  2. Enable Schema Discovery: Allow automatic schema introspection for auto-completion
  3. Write Your Query: Use the schema-aware editor to build queries or mutations
  4. Define Variables: Set up query variables using workflow context
  5. Test Execution: Validate your GraphQL operation and response handling
  6. Handle Responses: Process successful data and error cases in your workflow

Resources