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

GQty GraphQL Error Handling for Pylon and maybe Hono #2057

Open
kleberbaum opened this issue Jan 26, 2025 · 0 comments
Open

GQty GraphQL Error Handling for Pylon and maybe Hono #2057

kleberbaum opened this issue Jan 26, 2025 · 0 comments

Comments

@kleberbaum
Copy link

Hi everyone,

Goal: Establish sensible defaults for GQty error handling in generated client for Pylon.

In my previous issue, I provided a general outline of how GQty could function on the server side. This issue is specifically addressing error handling in a Pylon backend services using GQty:

4. Error Handling with resolve

  • Unclear Documentation
    GQty’s documentation doesn’t clearly demonstrate how to handle GraphQL errors when using resolve on the server. If there are recommended patterns or best practices, I’d love to learn about them ❤

Originally posted by [@kleberbaum](https://github.com/kleberbaum) in [#2051 (issue)](#2051)

With some assistance from the Discord community, I implemented a general error handling strategy for my web service by modifying the generated client/index.ts as shown below. Since I’m utilizing GQty’s resolve(), I expect to receive only one GraphQL error per request, so I handle it using error.graphQLErrors[0]:

/**
 * GQty: You can safely modify this file based on your needs.
 */

import {
  Cache,
  createClient,
  defaultResponseHandler,
  GQtyError,
  type QueryFetcher,
} from 'gqty';
import {
  generatedSchema,
  scalarsEnumsHash,
  type GeneratedSchema,
} from './schema.generated';
import { GraphQLError } from 'graphql';

const queryFetcher: QueryFetcher = async function (
  { query, variables, operationName, extensions },
  fetchOptions
) {
  let response;
  let data;

  try {
    // Modify the URL "https://iam.netsnek.workers.dev/graphql" if necessary
    const response = await fetch('https://iam.netsnek.workers.dev/graphql', {
      method: 'POST',
      headers: {
        'Authorization': extensions?.authToken as string,	
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        query,
        variables,
        operationName,
      }),
      ...fetchOptions,
    });

    data = await defaultResponseHandler(response);
  }
  catch (error) {
    if (error instanceof GQtyError && error.graphQLErrors?.[0]) {
      throw new GraphQLError(error.graphQLErrors[0].message, {
        extensions: error.graphQLErrors[0].extensions,
        //path: error.graphQLErrors[0].path,
      });
    }
  }

  return data;
};

const cache = new Cache(
  undefined,
  /**
   * Default option is immediate cache expiry but retain data for 5 minutes,
   * allowing soft refetches in the background.
   */
  {
    maxAge: 0,
    staleWhileRevalidate: 5 * 60 * 1000,
    normalization: true,
  }
);

export const client = createClient<GeneratedSchema>({
  schema: generatedSchema,
  scalars: scalarsEnumsHash,
  cache,
  fetchOptions: {
    fetcher: queryFetcher,
  },
});

// Core functions
export const { resolve, subscribe, schema } = client;

// Legacy functions
export const {
  query,
  mutation,
  mutate,
  subscription,
  resolved,
  refetch,
  track,
} = client;

export * from './schema.generated';

When a GQty error is caught, I extract the GraphQL error and rethrow it to ensure the same error appears in the Pylon playground. I omit the path because it should reflect the Pylon path, but all other error details are preserved from the original GQty error. The result is shown in the image below:

Error Screenshot

I’m looking forward to any feedback or suggestions to further refine this error handling approach @vicary @schettn.

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

No branches or pull requests

1 participant