Skip to content

This is a simple module that takes a graphQL query string and converts it into a JSON object. Think of it as the reverse of the excellent module json-to-graphql-query.

License

Notifications You must be signed in to change notification settings

trayio/graphql-query-to-json

Repository files navigation

graphql-query-to-json

Statement coverage Function coverage Line coverage Branches badge

A TypeScript library that converts GraphQL query and mutation strings into structured JSON objects. This library serves as the reverse of json-to-graphql-query, enabling programmatic manipulation and analysis of GraphQL queries.

Features

  • âś… Full GraphQL Support: Queries, mutations and subscriptions
  • âś… Variable Handling: Complete variable substitution with validation
  • âś… Arguments: All argument types (strings, integers, objects, arrays, enums)
  • âś… Aliases: Field aliasing with metadata preservation
  • âś… Type Safety: Full TypeScript support with comprehensive type definitions
  • âś… Error Handling: Descriptive error messages for malformed queries and missing variables
  • âś… Framework Agnostic: Works with any JavaScript/TypeScript environment

Installation

npm install graphql-query-to-json
# or
yarn add graphql-query-to-json

Basic Usage

const {graphQlQueryToJson} = require("graphql-query-to-json")

const query = `
query GetThisStuff($name: String, $lastName: String) {
    viewer {
        personal(criteria: {
            name: $name,
            lastName: $lastName
        }) {
            name
            address
        }
    }
}
`
const result = graphQlQueryToJson(query, {
    variables: {
        name: "PETER",
        lastName: "SCHMIDT",
    },
})

console.log(result)
// Output:
{
  query: {
    viewer: {
      personal: {
        __args: {
          criteria: {
            name: "PETER",
            lastName: "SCHMIDT",
          },
        },
        name: true,
        address: true,
      },
    },
  },
}

Transformation Rules

The library follows predictable transformation patterns:

GraphQL Element JSON Representation Example
Scalar Fields true name → name: true
Object Fields Nested objects user { name } → user: { name: true }
Arguments __args property user(id: 1) → user: { __args: { id: 1 } }
Aliases Field renaming + __aliasFor renamed: user → renamed: { __aliasFor: "user" }
Variables Substituted values $userId → actual variable value
Enums EnumType wrapper status: ACTIVE → status: { "value": "ACTIVE" }

Comprehensive Examples

Simple Queries

// Single and multiple fields
const query = `
query {
    viewer {
        name
        email
    }
    user {
        profile {
            avatar
            bio
        }
    }
}
`

const result = graphQlQueryToJson(query)

// Output:
{
  query: {
    viewer: {
      name: true,
      email: true
    },
    user: {
      profile: {
        avatar: true,
        bio: true
      }
    }
  }
}

Variables and Arguments

// Query with variables
const query = `
query GetUser($userId: ID!, $includeProfile: Boolean!) {
    user(id: $userId) {
        name
        email
        profile @include(if: $includeProfile) {
            bio
            avatar
        }
    }
}
`

const result = graphQlQueryToJson(query, {
    variables: {
        userId: "123",
        includeProfile: true
    }
})

// Output:
{
  query: {
    user: {
      __args: { id: "123" },
      name: true,
      email: true,
      profile: {
        bio: true,
        avatar: true
      }
    }
  }
}

Scalar Fields with Arguments

// Scalar fields that accept arguments
const query = `
query {
    userCount(filter: "active")
    totalRevenue(currency: "USD", year: 2024)
    averageRating(precision: 2)
}
`

const result = graphQlQueryToJson(query)

// Output:
{
  query: {
    userCount: {
      __args: { filter: "active" }
    },
    totalRevenue: {
      __args: { currency: "USD", year: 2024 }
    },
    averageRating: {
      __args: { precision: 2 }
    }
  }
}

Mutations with Simple Arguments

const mutation = `
mutation {
    getPersonalStuff(name: "PETER") {
        personal {
            name
            address
        }
        other {
            parents
        }
    }
}
`
const result = graphQlQueryToJson(mutation)

// Output:
{
  mutation: {
    getPersonalStuff: {
      __args: {
        name: "PETER",
      },
      personal: {
        name: true,
        address: true,
      },
      other: {
        parents: true,
      },
    },
  },
}

Mutations with Complex Arguments

// Mutation with nested object arguments
const mutation = `
mutation CreateUser($input: UserInput!) {
    createUser(input: $input) {
        id
        name
        profile {
            email
            settings {
                theme
                notifications
            }
        }
    }
}
`

const result = graphQlQueryToJson(mutation, {
    variables: {
        input: {
            name: "John Doe",
            email: "[email protected]",
        }
    }
})

// Output:
{
  mutation: {
    createUser: {
      __args: {
        input: {
          name: "John Doe",
          email: "[email protected]"
        }
      },
      id: true,
      name: true,
      profile: {
        email: true,
        settings: {
          theme: true,
          notifications: true
        }
      }
    }
  }
}

Aliases and Field Renaming

// Multiple aliases for the same field
const query = `
query {
    currentUser: user(id: 1) {
        name
        email
    }
    adminUser: user(id: 2) {
        name
        permissions
    }
    guestUser: user(id: 3) {
        name
        status
    }
}
`

const result = graphQlQueryToJson(query)

// Output:
{
  query: {
    currentUser: {
      __aliasFor: "user",
      __args: { id: 1 },
      name: true,
      email: true
    },
    adminUser: {
      __aliasFor: "user",
      __args: { id: 2 },
      name: true,
      permissions: true
    },
    guestUser: {
      __aliasFor: "user",
      __args: { id: 3 },
      name: true,
      status: true
    }
  }
}

Enum Types

// Enums in arguments
const query = `
query {
    posts(status: PUBLISHED, orderBy: CREATED_DESC) {
        title
        content
    }
    users(role: ADMIN, sortBy: NAME_ASC) {
        name
        email
    }
}
`

const result = graphQlQueryToJson(query)

// Output (enums are wrapped in EnumType objects):
{
  query: {
    posts: {
      __args: {
        status: { "value": "PUBLISHED" },
        orderBy: { "value": "CREATED_DESC" }
      },
      title: true,
      content: true
    },
    users: {
      __args: {
        role: { "value": "ADMIN" },
        sortBy: { "value": "NAME_ASC" }
      },
      name: true,
      email: true
    }
  }
}

Array Arguments

// Lists and arrays as arguments
const mutation = `
mutation {
    updateUser(
        id: "123",
        tags: ["developer", "typescript", "graphql"],
        permissions: [READ, WRITE, ADMIN]
    ) {
        id
        tags
        permissions
    }
}
`

const result = graphQlQueryToJson(mutation)

// Output:
{
  mutation: {
    updateUser: {
      __args: {
        id: "123",
        tags: ["developer", "typescript", "graphql"],
        permissions: [
          "READ",
          "WRITE",
          "ADMIN"
        ]
      },
      id: true,
      tags: true,
      permissions: true
    }
  }
}

Empty Values and Edge Cases

// Empty strings, objects, and arrays
const mutation = `
mutation {
    createRecord(input: {
        name: "",
        metadata: {},
        tags: [],
        count: 0,
        isActive: false
    }) {
        id
        status
    }
}
`

const result = graphQlQueryToJson(mutation)

// Output:
{
  mutation: {
    createRecord: {
      __args: {
        input: {
          name: "",
          metadata: {},
          tags: [],
          count: 0,
          isActive: false
        }
      },
      id: true,
      status: true
    }
  }
}

Deeply Nested Objects

// Complex nested structures
const query = `
query {
    organization {
        teams {
            members {
                user {
                    profile {
                        personalInfo {
                            address {
                                street
                                city
                                country
                            }
                        }
                    }
                }
            }
        }
    }
}
`

const result = graphQlQueryToJson(query)

// Output:
{
  query: {
    organization: {
      teams: {
        members: {
          user: {
            profile: {
              personalInfo: {
                address: {
                  street: true,
                  city: true,
                  country: true
                }
              }
            }
          }
        }
      }
    }
  }
}

Mixed Variable Types

// Various data types as variables
const query = `
query SearchContent(
    $text: String!,
    $limit: Int!,
    $offset: Int,
    $filters: FilterInput!,
    $includeArchived: Boolean
) {
    search(
        query: $text,
        first: $limit,
        skip: $offset,
        filters: $filters,
        archived: $includeArchived
    ) {
        results {
            id
            title
            excerpt
        }
        totalCount
    }
}
`

const result = graphQlQueryToJson(query, {
    variables: {
        text: "GraphQL tutorial",
        limit: 10,
        offset: 0,
        filters: {
            category: "tutorial",
            difficulty: "beginner",
            tags: ["graphql", "api"]
        },
        includeArchived: false
    }
})

// Output:
{
  query: {
    search: {
      __args: {
        query: "GraphQL tutorial",
        first: 10,
        skip: 0,
        filters: {
          category: "tutorial",
          difficulty: "beginner",
          tags: ["graphql", "api"]
        },
        archived: false
      },
      results: {
        id: true,
        title: true,
        excerpt: true
      },
      totalCount: true
    }
  }
}

API Reference

graphQlQueryToJson(query, options?)

Parameters:

  • query (string): The GraphQL query or mutation string
  • options (object, optional):
    • variables (object): Variables referenced in the query

Returns: JSON object representation of the GraphQL query

Throws:

  • Error if query syntax is invalid
  • Error if variables are referenced but not provided
  • Error if query contains multiple operations

TypeScript Support

Full TypeScript definitions are included:

import { graphQlQueryToJson } from 'graphql-query-to-json'

interface Variables {
  userId: string
  limit: number
}

const variables: Variables = {
  userId: "123",
  limit: 10
}

const result = graphQlQueryToJson(query, { variables })
// Result is properly typed

Development

Building

npm run build        # Compile TypeScript to JavaScript
npm run watch        # Build in watch mode

Testing

npm test              # Run Jest tests
npm run test:coverage # Run tests with coverage

Code Quality

npm run lintFull     # Run Prettier and ESLint with auto-fix

Architecture

The library uses a multi-phase approach:

  1. Parse: Uses graphql library to parse query into AST
  2. Validate: Ensures all variables are provided
  3. Transform: Recursively processes selections, arguments, and aliases
  4. Substitute: Replaces variable placeholders with actual values

Key components:

  • getSelections(): Processes field selections recursively
  • getArguments(): Handles all argument types and nesting
  • replaceVariables(): Deep variable substitution using lodash.mapValues
  • checkEachVariableInQueryIsDefined(): Variable validation with descriptive errors

Use Cases

  • Query Analysis: Programmatically analyse GraphQL query structure
  • Query Transformation: Convert between query formats
  • Testing: Validate query structures in tests
  • Documentation Generation: Extract field usage patterns
  • Caching Keys: Generate cache keys from query structure

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes with tests
  4. Run npm run build && npm test
  5. Submit a pull request

License

MIT License - see LICENSE file for details

About

This is a simple module that takes a graphQL query string and converts it into a JSON object. Think of it as the reverse of the excellent module json-to-graphql-query.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 6