Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support pre-parsed queries (eg. graphql-tag) #1108

Merged
merged 1 commit into from
Sep 6, 2024

Conversation

voxpelli
Copy link
Contributor

@voxpelli voxpelli commented Sep 5, 2024

If one want to be using eg. graphql-tag to manage queries and fragments, then currently one can't do queries with the Mercurius reply.graphql() or fastify.graphql().

This PR changes that by making Mercurius accept pre-parsed queries.

To achieve that I had to:

  • Swap tiny-lru for a quick-lru as the later is built on top of Map and as such accept non-string keys.
    • Since quick-lru is an ESM-module, its lazy-loaded and buildCache was made async, with minor/no impact to anything
  • When input is already parsed:
    • preParsingHandler is skipped
    • Parsing step is replaced by a structuredClone(source) (to ensure that the cache values will not be saved by reference in any part)

JIT:ing etc still works like it works for any other query

@voxpelli
Copy link
Contributor Author

voxpelli commented Sep 5, 2024

Same failure as in #1109, will work after fix there

@voxpelli voxpelli force-pushed the support-graphql-tag-queries branch from e9781f4 to 1c4671b Compare September 6, 2024 11:44
@voxpelli
Copy link
Contributor Author

voxpelli commented Sep 6, 2024

Rebased after #1109 got merged, now passes tests 👍

Copy link
Collaborator

@mcollina mcollina left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@mcollina mcollina merged commit b6ec1a1 into mercurius-js:master Sep 6, 2024
7 checks passed
@voxpelli voxpelli deleted the support-graphql-tag-queries branch September 6, 2024 12:34
@voxpelli
Copy link
Contributor Author

voxpelli commented Sep 20, 2024

For future reference – this enables having colocated fragments easily:

file-a.js:

import { gql } from 'graphql-tag';

export const linkableNamedEntityFragment = gql`
  fragment LinkableNamedEntity on NamedEntity {
    id
    name
  }
`;

file-b.js:

import { gql } from 'graphql-tag';

import { linkableNamedEntityFragment } from './file-a.js';

export const fooFragment = gql`
  fragment Foo on NamedEntity {
    ... LinkableNamedEntity
    bar
  }
`;

file-c.js:

import { gql } from 'graphql-tag';

import { linkableNamedEntityFragment } from './file-a.js';
import { fooFragment } from './file-b.js';

export const adminEntityQuery = gql`
  query adminEntity($type: EntityType!, $id: ID!) {
    entity(type: $type, id: $id) {
      __typename
      createdAt

      ... LinkableNamedEntity

      ... on OrganizationOwned {
        owner {
          ... LinkableNamedEntity
          ... Foo
        }
      }
  }
  ${linkableNamedEntityFragment}
  ${fooFragment}
`;

Eg. the VSCode extension will understand that the fragments are imported and not complain about invalid names of fragments + graphql-tag will dedupe the fragments, so unlike string concatenation that would result in duplicate definitions of fragment LinkableNamedEntity in the above no such duplication will occur.

So all in all – what might look as a taste in coding style on the surface actually has some distinct benefits beneath the surface :)

(Wanted to add this here for future reference for others now that I had implemented it in my project myself)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants