{"id":41874932,"url":"https://github.com/trayio/graphql-query-to-json","last_synced_at":"2026-01-25T12:33:39.448Z","repository":{"id":42391108,"uuid":"225726353","full_name":"trayio/graphql-query-to-json","owner":"trayio","description":"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.","archived":false,"fork":false,"pushed_at":"2025-11-06T09:33:17.000Z","size":368,"stargazers_count":25,"open_issues_count":8,"forks_count":8,"subscribers_count":20,"default_branch":"master","last_synced_at":"2025-11-06T11:19:44.908Z","etag":null,"topics":["developer-tools","graphql","json"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/trayio.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2019-12-03T22:05:57.000Z","updated_at":"2025-11-06T09:33:11.000Z","dependencies_parsed_at":"2024-11-16T12:50:56.513Z","dependency_job_id":"fe74a194-2bcb-458f-ac27-53cac14723c5","html_url":"https://github.com/trayio/graphql-query-to-json","commit_stats":{"total_commits":20,"total_committers":6,"mean_commits":"3.3333333333333335","dds":0.4,"last_synced_commit":"bdba8140386f250c8de8bec496d7d52e840c15f9"},"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"purl":"pkg:github/trayio/graphql-query-to-json","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trayio%2Fgraphql-query-to-json","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trayio%2Fgraphql-query-to-json/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trayio%2Fgraphql-query-to-json/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trayio%2Fgraphql-query-to-json/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/trayio","download_url":"https://codeload.github.com/trayio/graphql-query-to-json/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trayio%2Fgraphql-query-to-json/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28753017,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-25T10:25:12.305Z","status":"ssl_error","status_checked_at":"2026-01-25T10:25:11.933Z","response_time":113,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["developer-tools","graphql","json"],"created_at":"2026-01-25T12:33:38.699Z","updated_at":"2026-01-25T12:33:39.440Z","avatar_url":"https://github.com/trayio.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"graphql-query-to-json\n=====================\n\n![Statement coverage](https://img.shields.io/endpoint?url=https%3A%2F%2F30d15c83-919d-4ca2-bda8-408fae98ad27.trayapp.io%2Fstatements)\n![Function coverage](https://img.shields.io/endpoint?url=https%3A%2F%2F30d15c83-919d-4ca2-bda8-408fae98ad27.trayapp.io%2Ffunctions)\n![Line coverage](https://img.shields.io/endpoint?url=https%3A%2F%2F30d15c83-919d-4ca2-bda8-408fae98ad27.trayapp.io%2Flines)\n![Branches badge](https://img.shields.io/endpoint?url=https%3A%2F%2F30d15c83-919d-4ca2-bda8-408fae98ad27.trayapp.io%2Fbranches)\n\nA TypeScript library that converts GraphQL query and mutation strings into structured JSON objects. This library serves as the reverse of [json-to-graphql-query](https://www.npmjs.com/package/json-to-graphql-query), enabling programmatic manipulation and analysis of GraphQL queries.\n\n## Features\n\n- ✅ **Full GraphQL Support**: Queries, mutations and subscriptions\n- ✅ **Variable Handling**: Complete variable substitution with validation\n- ✅ **Arguments**: All argument types (strings, integers, floats, objects, arrays, enums)\n- ✅ **Aliases**: Field aliasing with metadata preservation\n- ✅ **Inline Fragments**: Complete support for conditional type-based field selection\n- ✅ **Type Safety**: Full TypeScript support with comprehensive type definitions\n- ✅ **Error Handling**: Descriptive error messages for malformed queries and missing variables\n- ✅ **Framework Agnostic**: Works with any JavaScript/TypeScript environment\n\n## Installation\n\n```sh\nnpm install graphql-query-to-json\n# or\nyarn add graphql-query-to-json\n```\n\n## Basic Usage\n\n```ts\nconst {graphQlQueryToJson} = require(\"graphql-query-to-json\")\n\nconst query = `\nquery GetThisStuff($name: String, $lastName: String) {\n    viewer {\n        personal(criteria: {\n            name: $name,\n            lastName: $lastName\n        }) {\n            name\n            address\n        }\n    }\n}\n`\nconst result = graphQlQueryToJson(query, {\n    variables: {\n        name: \"PETER\",\n        lastName: \"SCHMIDT\",\n    },\n})\n\nconsole.log(result)\n// Output:\n{\n  query: {\n    viewer: {\n      personal: {\n        __args: {\n          criteria: {\n            name: \"PETER\",\n            lastName: \"SCHMIDT\",\n          },\n        },\n        name: true,\n        address: true,\n      },\n    },\n  },\n}\n```\n\n## Transformation Rules\n\nThe library follows predictable transformation patterns:\n\n| GraphQL Element | JSON Representation | Example |\n|----------------|-------------------|---------|\n| **Scalar Fields** | `true` | `name` → `name: true` |\n| **Object Fields** | Nested objects | `user { name }` → `user: { name: true }` |\n| **Arguments** | `__args` property | `user(id: 1)` → `user: { __args: { id: 1 } }` |\n| **Aliases** | Field renaming + `__aliasFor` | `renamed: user` → `renamed: { __aliasFor: \"user\" }` |\n| **Variables** | Substituted values | `$userId` → actual variable value |\n| **Enums** | `EnumType` wrapper | `status: ACTIVE` → `status: { \"value\": \"ACTIVE\" }` |\n| **Inline Fragments** | `__on` property | `... on User { name }` → `__on: { __typeName: \"User\", name: true }` |\n\n## Comprehensive Examples\n\n### Simple Queries\n\n```ts\n// Single and multiple fields\nconst query = `\nquery {\n    viewer {\n        name\n        email\n    }\n    user {\n        profile {\n            avatar\n            bio\n        }\n    }\n}\n`\n\nconst result = graphQlQueryToJson(query)\n\n// Output:\n{\n  query: {\n    viewer: {\n      name: true,\n      email: true\n    },\n    user: {\n      profile: {\n        avatar: true,\n        bio: true\n      }\n    }\n  }\n}\n```\n\n### Variables and Arguments\n\n```ts\n// Query with variables\nconst query = `\nquery GetUser($userId: ID!, $includeProfile: Boolean!) {\n    user(id: $userId) {\n        name\n        email\n        profile @include(if: $includeProfile) {\n            bio\n            avatar\n        }\n    }\n}\n`\n\nconst result = graphQlQueryToJson(query, {\n    variables: {\n        userId: \"123\",\n        includeProfile: true\n    }\n})\n\n// Output:\n{\n  query: {\n    user: {\n      __args: { id: \"123\" },\n      name: true,\n      email: true,\n      profile: {\n        bio: true,\n        avatar: true\n      }\n    }\n  }\n}\n```\n\n### Scalar Fields with Arguments\n\n```ts\n// Scalar fields that accept arguments\nconst query = `\nquery {\n    userCount(filter: \"active\")\n    totalRevenue(currency: \"USD\", year: 2024)\n    averageRating(precision: 2)\n}\n`\n\nconst result = graphQlQueryToJson(query)\n\n// Output:\n{\n  query: {\n    userCount: {\n      __args: { filter: \"active\" }\n    },\n    totalRevenue: {\n      __args: { currency: \"USD\", year: 2024 }\n    },\n    averageRating: {\n      __args: { precision: 2 }\n    }\n  }\n}\n```\n\n### Mutations with Simple Arguments\n\n```ts\nconst mutation = `\nmutation {\n    getPersonalStuff(name: \"PETER\") {\n        personal {\n            name\n            address\n        }\n        other {\n            parents\n        }\n    }\n}\n`\nconst result = graphQlQueryToJson(mutation)\n\n// Output:\n{\n  mutation: {\n    getPersonalStuff: {\n      __args: {\n        name: \"PETER\",\n      },\n      personal: {\n        name: true,\n        address: true,\n      },\n      other: {\n        parents: true,\n      },\n    },\n  },\n}\n```\n\n### Mutations with Complex Arguments\n\n```ts\n// Mutation with nested object arguments\nconst mutation = `\nmutation CreateUser($input: UserInput!) {\n    createUser(input: $input) {\n        id\n        name\n        profile {\n            email\n            settings {\n                theme\n                notifications\n            }\n        }\n    }\n}\n`\n\nconst result = graphQlQueryToJson(mutation, {\n    variables: {\n        input: {\n            name: \"John Doe\",\n            email: \"john@example.com\",\n        }\n    }\n})\n\n// Output:\n{\n  mutation: {\n    createUser: {\n      __args: {\n        input: {\n          name: \"John Doe\",\n          email: \"john@example.com\"\n        }\n      },\n      id: true,\n      name: true,\n      profile: {\n        email: true,\n        settings: {\n          theme: true,\n          notifications: true\n        }\n      }\n    }\n  }\n}\n```\n\n### Aliases and Field Renaming\n\n```ts\n// Multiple aliases for the same field\nconst query = `\nquery {\n    currentUser: user(id: 1) {\n        name\n        email\n    }\n    adminUser: user(id: 2) {\n        name\n        permissions\n    }\n    guestUser: user(id: 3) {\n        name\n        status\n    }\n}\n`\n\nconst result = graphQlQueryToJson(query)\n\n// Output:\n{\n  query: {\n    currentUser: {\n      __aliasFor: \"user\",\n      __args: { id: 1 },\n      name: true,\n      email: true\n    },\n    adminUser: {\n      __aliasFor: \"user\",\n      __args: { id: 2 },\n      name: true,\n      permissions: true\n    },\n    guestUser: {\n      __aliasFor: \"user\",\n      __args: { id: 3 },\n      name: true,\n      status: true\n    }\n  }\n}\n```\n\n### Enum Types\n\n```ts\n// Enums in arguments\nconst query = `\nquery {\n    posts(status: PUBLISHED, orderBy: CREATED_DESC) {\n        title\n        content\n    }\n    users(role: ADMIN, sortBy: NAME_ASC) {\n        name\n        email\n    }\n}\n`\n\nconst result = graphQlQueryToJson(query)\n\n// Output (enums are wrapped in EnumType objects):\n{\n  query: {\n    posts: {\n      __args: {\n        status: { \"value\": \"PUBLISHED\" },\n        orderBy: { \"value\": \"CREATED_DESC\" }\n      },\n      title: true,\n      content: true\n    },\n    users: {\n      __args: {\n        role: { \"value\": \"ADMIN\" },\n        sortBy: { \"value\": \"NAME_ASC\" }\n      },\n      name: true,\n      email: true\n    }\n  }\n}\n```\n\n### Array Arguments\n\n```ts\n// Lists and arrays as arguments\nconst mutation = `\nmutation {\n    updateUser(\n        id: \"123\",\n        tags: [\"developer\", \"typescript\", \"graphql\"],\n        permissions: [READ, WRITE, ADMIN]\n    ) {\n        id\n        tags\n        permissions\n    }\n}\n`\n\nconst result = graphQlQueryToJson(mutation)\n\n// Output:\n{\n  mutation: {\n    updateUser: {\n      __args: {\n        id: \"123\",\n        tags: [\"developer\", \"typescript\", \"graphql\"],\n        permissions: [\n          \"READ\",\n          \"WRITE\",\n          \"ADMIN\"\n        ]\n      },\n      id: true,\n      tags: true,\n      permissions: true\n    }\n  }\n}\n```\n\n### Empty Values and Edge Cases\n\n```ts\n// Empty strings, objects, and arrays\nconst mutation = `\nmutation {\n    createRecord(input: {\n        name: \"\",\n        metadata: {},\n        tags: [],\n        count: 0,\n        isActive: false\n    }) {\n        id\n        status\n    }\n}\n`\n\nconst result = graphQlQueryToJson(mutation)\n\n// Output:\n{\n  mutation: {\n    createRecord: {\n      __args: {\n        input: {\n          name: \"\",\n          metadata: {},\n          tags: [],\n          count: 0,\n          isActive: false\n        }\n      },\n      id: true,\n      status: true\n    }\n  }\n}\n```\n\n### Deeply Nested Objects\n\n```ts\n// Complex nested structures\nconst query = `\nquery {\n    organization {\n        teams {\n            members {\n                user {\n                    profile {\n                        personalInfo {\n                            address {\n                                street\n                                city\n                                country\n                            }\n                        }\n                    }\n                }\n            }\n        }\n    }\n}\n`\n\nconst result = graphQlQueryToJson(query)\n\n// Output:\n{\n  query: {\n    organization: {\n      teams: {\n        members: {\n          user: {\n            profile: {\n              personalInfo: {\n                address: {\n                  street: true,\n                  city: true,\n                  country: true\n                }\n              }\n            }\n          }\n        }\n      }\n    }\n  }\n}\n```\n\n### Mixed Variable Types\n\n```ts\n// Float arguments and numeric types\nconst query = `\nquery GetProducts {\n    products(\n        minRating: 4.5,\n        maxPrice: 99.99,\n        discount: -10.5,\n        threshold: 0.001,\n        scientific: 2.5e3\n    ) {\n        name\n        rating\n        price\n    }\n    analytics(\n        coordinates: {\n            lat: 40.7128,\n            lng: -74.006\n        },\n        mixed: [1, 2.5, 3, 4.75]\n    ) {\n        data\n    }\n}\n`\n\nconst result = graphQlQueryToJson(query)\n\n// Output:\n{\n  query: {\n    products: {\n      __args: {\n        minRating: 4.5,           // ✅ Float as number\n        maxPrice: 99.99,          // ✅ Float as number  \n        discount: -10.5,          // ✅ Negative float\n        threshold: 0.001,         // ✅ Small decimal\n        scientific: 2500          // ✅ Scientific notation (2.5e3)\n      },\n      name: true,\n      rating: true,\n      price: true\n    },\n    analytics: {\n      __args: {\n        coordinates: {\n          lat: 40.7128,           // ✅ Nested floats\n          lng: -74.006\n        },\n        mixed: [\"1\", \"2.5\", \"3\", \"4.75\"]  // Arrays preserve strings\n      },\n      data: true\n    }\n  }\n}\n```\n\n### Inline Fragments\n\n```ts\n// Single inline fragment\nconst query = `\nquery {\n    posts {\n        title\n        ... on TextPost {\n            content\n            wordCount\n        }\n    }\n}\n`\n\nconst result = graphQlQueryToJson(query)\n\n// Output:\n{\n  query: {\n    posts: {\n      title: true,\n      __on: {\n        __typeName: \"TextPost\",\n        content: true,\n        wordCount: true\n      }\n    }\n  }\n}\n```\n\n```ts\n// Multiple inline fragments\nconst query = `\nquery {\n    media {\n        ... on TextPost {\n            content\n            author {\n                name\n            }\n        }\n        ... on ImagePost {\n            imageUrl\n            altText\n        }\n        ... on VideoPost {\n            videoUrl\n            duration\n        }\n    }\n}\n`\n\nconst result = graphQlQueryToJson(query)\n\n// Output:\n{\n  query: {\n    media: {\n      __on: [\n        {\n          __typeName: \"TextPost\",\n          content: true,\n          author: {\n            name: true\n          }\n        },\n        {\n          __typeName: \"ImagePost\",\n          imageUrl: true,\n          altText: true\n        },\n        {\n          __typeName: \"VideoPost\", \n          videoUrl: true,\n          duration: true\n        }\n      ]\n    }\n  }\n}\n```\n\n```ts\n// Inline fragments with arguments and variables\nconst query = `\nquery GetPosts($limit: Int!) {\n    posts {\n        title\n        ... on TextPost {\n            comments(limit: $limit) {\n                text\n                author {\n                    name\n                }\n            }\n        }\n    }\n}\n`\n\nconst result = graphQlQueryToJson(query, {\n    variables: { limit: 5 }\n})\n\n// Output:\n{\n  query: {\n    posts: {\n      title: true,\n      __on: {\n        __typeName: \"TextPost\",\n        comments: {\n          __args: { limit: 5 },\n          text: true,\n          author: {\n            name: true\n          }\n        }\n      }\n    }\n  }\n}\n```\n\n### Subscriptions\n\n```ts\n// Basic subscription\nconst subscription = `\nsubscription {\n    messageAdded {\n        id\n        content\n        user {\n            name\n            email\n        }\n    }\n}\n`\n\nconst result = graphQlQueryToJson(subscription)\n\n// Output:\n{\n  subscription: {\n    messageAdded: {\n      id: true,\n      content: true,\n      user: {\n        name: true,\n        email: true\n      }\n    }\n  }\n}\n```\n\n```ts\n// Subscription with variables and arguments\nconst subscription = `\nsubscription MessageSubscription($userId: ID!, $channel: String!) {\n    messageAdded(userId: $userId, channel: $channel) {\n        id\n        content\n        timestamp\n    }\n}\n`\n\nconst result = graphQlQueryToJson(subscription, {\n    variables: {\n        userId: \"123\",\n        channel: \"general\"\n    }\n})\n\n// Output:\n{\n  subscription: {\n    messageAdded: {\n      __args: {\n        userId: \"123\",\n        channel: \"general\"\n      },\n      id: true,\n      content: true,\n      timestamp: true\n    }\n  }\n}\n```\n\n```ts\n// Subscription with aliases and enums\nconst subscription = `\nsubscription {\n    latestMessage: messageAdded(channel: PUBLIC) {\n        id\n        content\n    }\n}\n`\n\nconst result = graphQlQueryToJson(subscription)\n\n// Output:\n{\n  subscription: {\n    latestMessage: {\n      __aliasFor: \"messageAdded\",\n      __args: {\n        channel: { \"value\": \"PUBLIC\" }\n      },\n      id: true,\n      content: true\n    }\n  }\n}\n```\n\n## API Reference\n\n### `graphQlQueryToJson(query, options?)`\n\n**Parameters:**\n- `query` (string): The GraphQL query, mutation, or subscription string\n- `options` (object, optional):\n  - `variables` (object): Variables referenced in the query\n\n**Returns:** JSON object representation of the GraphQL query\n\n**Throws:**\n- Error if query syntax is invalid\n- Error if variables are referenced but not provided\n- Error if query contains multiple operations\n\n## Limitations\n\nWhile the library supports the core GraphQL features, there are some limitations:\n\n### Fragment Support\n- **Inline Fragments**: ✅ **Fully Supported** (e.g., `... on TypeName`)\n- **Named Fragments**: Not supported due to multiple definition restriction\n\n```ts\n// ❌ Named fragments still throw an error\nconst queryWithFragment = `\nquery {\n    user {\n        ...UserFields\n    }\n}\n\nfragment UserFields on User {\n    id\n    name\n}\n`\n// Throws: \"The parsed query has more than one set of definitions\"\n\n// ✅ Inline fragments work perfectly\nconst queryWithInlineFragment = `\nquery {\n    search {\n        ... on User {\n            name\n        }\n        ... on Post {\n            title\n        }\n    }\n}\n`\n// Output: { query: { search: { __on: [...] } } }\n```\n\n### Directives\n- **Directive Handling**: Directives like `@include`, `@skip` are parsed but ignored\n- The library focuses on structure extraction rather than directive execution\n\n```ts\n// ✅ This works but directives are ignored\nconst queryWithDirective = `\nquery($includeEmail: Boolean!) {\n    user {\n        name\n        email @include(if: $includeEmail)\n    }\n}\n`\n// The @include directive won't affect the output structure\n```\n\nThese limitations apply equally to queries, mutations, and subscriptions since they all use the same AST processing logic.\n\n## TypeScript Support\n\nFull TypeScript definitions are included:\n\n```ts\nimport { graphQlQueryToJson } from 'graphql-query-to-json'\n\ninterface Variables {\n  userId: string\n  limit: number\n}\n\nconst variables: Variables = {\n  userId: \"123\",\n  limit: 10\n}\n\nconst result = graphQlQueryToJson(query, { variables })\n// Result is properly typed\n```\n\n## Development\n\n### Building\n```bash\nnpm run build        # Compile TypeScript to JavaScript\nnpm run watch        # Build in watch mode\n```\n\n### Testing\n```bash\nnpm test              # Run Jest tests\nnpm run test:coverage # Run tests with coverage\n```\n\n### Code Quality\n```bash\nnpm run lintFull     # Run Prettier and ESLint with auto-fix\n```\n\n## Architecture\n\nThe library uses a multi-phase approach:\n\n1. **Parse**: Uses `graphql` library to parse query into AST\n2. **Validate**: Ensures all variables are provided\n3. **Transform**: Recursively processes selections, arguments, and aliases\n4. **Substitute**: Replaces variable placeholders with actual values\n\nKey components:\n- `getSelections()`: Processes field selections recursively\n- `getArguments()`: Handles all argument types and nesting\n- `replaceVariables()`: Deep variable substitution using lodash.mapValues\n- `checkEachVariableInQueryIsDefined()`: Variable validation with descriptive errors\n\n## Use Cases\n\n- **Query Analysis**: Programmatically analyse GraphQL query structure\n- **Query Transformation**: Convert between query formats\n- **Testing**: Validate query structures in tests\n- **Documentation Generation**: Extract field usage patterns\n- **Caching Keys**: Generate cache keys from query structure\n\n## Contributing\n\n1. Fork the repository\n2. Create a feature branch\n3. Make your changes with tests\n4. Run `npm run build \u0026\u0026 npm test`\n5. Submit a pull request\n\n## License\n\nMIT License - see [LICENSE](LICENSE) file for details\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftrayio%2Fgraphql-query-to-json","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftrayio%2Fgraphql-query-to-json","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftrayio%2Fgraphql-query-to-json/lists"}