🚀 DAY 5 OF LAUNCH WEEK: Introducing Socket Firewall Enterprise.Learn more →
Socket
Book a DemoInstallSign in
Socket

graphql-query-to-json

Package Overview
Dependencies
Maintainers
1
Versions
9
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

graphql-query-to-json

Convert graphQL queries and mutations to easily readable JSON representations.

latest
npmnpm
Version
2.0.5
Version published
Maintainers
1
Created
Source

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, floats, objects, arrays, enums)
  • âś… Aliases: Field aliasing with metadata preservation
  • âś… Inline Fragments: Complete support for conditional type-based field selection
  • âś… 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 ElementJSON RepresentationExample
Scalar Fieldstruename → name: true
Object FieldsNested objectsuser { name } → user: { name: true }
Arguments__args propertyuser(id: 1) → user: { __args: { id: 1 } }
AliasesField renaming + __aliasForrenamed: user → renamed: { __aliasFor: "user" }
VariablesSubstituted values$userId → actual variable value
EnumsEnumType wrapperstatus: ACTIVE → status: { "value": "ACTIVE" }
Inline Fragments__on property... on User { name } → __on: { __typeName: "User", name: true }

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: "john@example.com",
        }
    }
})

// Output:
{
  mutation: {
    createUser: {
      __args: {
        input: {
          name: "John Doe",
          email: "john@example.com"
        }
      },
      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

// Float arguments and numeric types
const query = `
query GetProducts {
    products(
        minRating: 4.5,
        maxPrice: 99.99,
        discount: -10.5,
        threshold: 0.001,
        scientific: 2.5e3
    ) {
        name
        rating
        price
    }
    analytics(
        coordinates: {
            lat: 40.7128,
            lng: -74.006
        },
        mixed: [1, 2.5, 3, 4.75]
    ) {
        data
    }
}
`

const result = graphQlQueryToJson(query)

// Output:
{
  query: {
    products: {
      __args: {
        minRating: 4.5,           // âś… Float as number
        maxPrice: 99.99,          // âś… Float as number  
        discount: -10.5,          // âś… Negative float
        threshold: 0.001,         // âś… Small decimal
        scientific: 2500          // âś… Scientific notation (2.5e3)
      },
      name: true,
      rating: true,
      price: true
    },
    analytics: {
      __args: {
        coordinates: {
          lat: 40.7128,           // âś… Nested floats
          lng: -74.006
        },
        mixed: ["1", "2.5", "3", "4.75"]  // Arrays preserve strings
      },
      data: true
    }
  }
}

Inline Fragments

// Single inline fragment
const query = `
query {
    posts {
        title
        ... on TextPost {
            content
            wordCount
        }
    }
}
`

const result = graphQlQueryToJson(query)

// Output:
{
  query: {
    posts: {
      title: true,
      __on: {
        __typeName: "TextPost",
        content: true,
        wordCount: true
      }
    }
  }
}
// Multiple inline fragments
const query = `
query {
    media {
        ... on TextPost {
            content
            author {
                name
            }
        }
        ... on ImagePost {
            imageUrl
            altText
        }
        ... on VideoPost {
            videoUrl
            duration
        }
    }
}
`

const result = graphQlQueryToJson(query)

// Output:
{
  query: {
    media: {
      __on: [
        {
          __typeName: "TextPost",
          content: true,
          author: {
            name: true
          }
        },
        {
          __typeName: "ImagePost",
          imageUrl: true,
          altText: true
        },
        {
          __typeName: "VideoPost", 
          videoUrl: true,
          duration: true
        }
      ]
    }
  }
}
// Inline fragments with arguments and variables
const query = `
query GetPosts($limit: Int!) {
    posts {
        title
        ... on TextPost {
            comments(limit: $limit) {
                text
                author {
                    name
                }
            }
        }
    }
}
`

const result = graphQlQueryToJson(query, {
    variables: { limit: 5 }
})

// Output:
{
  query: {
    posts: {
      title: true,
      __on: {
        __typeName: "TextPost",
        comments: {
          __args: { limit: 5 },
          text: true,
          author: {
            name: true
          }
        }
      }
    }
  }
}

Subscriptions

// Basic subscription
const subscription = `
subscription {
    messageAdded {
        id
        content
        user {
            name
            email
        }
    }
}
`

const result = graphQlQueryToJson(subscription)

// Output:
{
  subscription: {
    messageAdded: {
      id: true,
      content: true,
      user: {
        name: true,
        email: true
      }
    }
  }
}
// Subscription with variables and arguments
const subscription = `
subscription MessageSubscription($userId: ID!, $channel: String!) {
    messageAdded(userId: $userId, channel: $channel) {
        id
        content
        timestamp
    }
}
`

const result = graphQlQueryToJson(subscription, {
    variables: {
        userId: "123",
        channel: "general"
    }
})

// Output:
{
  subscription: {
    messageAdded: {
      __args: {
        userId: "123",
        channel: "general"
      },
      id: true,
      content: true,
      timestamp: true
    }
  }
}
// Subscription with aliases and enums
const subscription = `
subscription {
    latestMessage: messageAdded(channel: PUBLIC) {
        id
        content
    }
}
`

const result = graphQlQueryToJson(subscription)

// Output:
{
  subscription: {
    latestMessage: {
      __aliasFor: "messageAdded",
      __args: {
        channel: { "value": "PUBLIC" }
      },
      id: true,
      content: true
    }
  }
}

API Reference

graphQlQueryToJson(query, options?)

Parameters:

  • query (string): The GraphQL query, mutation, or subscription 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

Limitations

While the library supports the core GraphQL features, there are some limitations:

Fragment Support

  • Inline Fragments: âś… Fully Supported (e.g., ... on TypeName)
  • Named Fragments: Not supported due to multiple definition restriction
// ❌ Named fragments still throw an error
const queryWithFragment = `
query {
    user {
        ...UserFields
    }
}

fragment UserFields on User {
    id
    name
}
`
// Throws: "The parsed query has more than one set of definitions"

// âś… Inline fragments work perfectly
const queryWithInlineFragment = `
query {
    search {
        ... on User {
            name
        }
        ... on Post {
            title
        }
    }
}
`
// Output: { query: { search: { __on: [...] } } }

Directives

  • Directive Handling: Directives like @include, @skip are parsed but ignored
  • The library focuses on structure extraction rather than directive execution
// âś… This works but directives are ignored
const queryWithDirective = `
query($includeEmail: Boolean!) {
    user {
        name
        email @include(if: $includeEmail)
    }
}
`
// The @include directive won't affect the output structure

These limitations apply equally to queries, mutations, and subscriptions since they all use the same AST processing logic.

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:

  • Parse: Uses graphql library to parse query into AST
  • Validate: Ensures all variables are provided
  • Transform: Recursively processes selections, arguments, and aliases
  • 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

  • Fork the repository
  • Create a feature branch
  • Make your changes with tests
  • Run npm run build && npm test
  • Submit a pull request

License

MIT License - see LICENSE file for details

FAQs

Package last updated on 10 Sep 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts