tauri-plugin-graphql icon indicating copy to clipboard operation
tauri-plugin-graphql copied to clipboard

Links for `@apollo/client`

Open mikew opened this issue 1 year ago • 0 comments

I wanted to use urql, but due to the lack of useLazyQuery, wanted to reach for Apollo. Not sure if I will end up using it, but I needed to write some links for it to work, so here you go.

There's two versions:

ApolloLink

This one uses ApolloLink, which as far as I can tell, is the lowest level of these things.

import { ApolloLink, FetchResult, fromPromise } from '@apollo/client'
import { invoke } from '@tauri-apps/api/tauri'
import { GraphQLError, print } from 'graphql'

const tauriGraphqlApolloLink = new ApolloLink((operation) => {
  return fromPromise(
    invoke<[string, boolean]>('plugin:graphql|graphql', {
      query: print(operation.query),
      variables: operation.variables,
    })
      .then(([responseStr]) => {
        const parsed = JSON.parse(responseStr)

        return {
          data: parsed.data,
          errors: parsed.errors,
        }
      })
      .catch((err) => {
        return {
          errors: [new GraphQLError(String(err))],
          context: operation.getContext(),
        }
      }),
  )
})

export default tauriGraphqlApolloLink

HttpLink

This one uses HttpLink, but replaces fetch with something that just calls invoke from tauri.

I'm sure it's "slower", because we need to call JSON.parse to get an object to pass to tauri-plugin-graphql along with the JSON.parse that surely happens later on in HttpLink.

But, @apollo/client does seem to set the abort signal, and this uses it. So it might have some UX considerations that tauriGraphqlApolloLink doesn't.

import { createHttpLink } from '@apollo/client'
import { invoke } from '@tauri-apps/api/tauri'

const tauriGraphqlHttpLink = createHttpLink({
  fetch: async (_input, init) => {
    const [responseStr, isOk] = await invoke<[string, boolean]>(
      'plugin:graphql|graphql',
      JSON.parse(String(init?.body)),
    )

    init?.signal?.throwIfAborted()

    return new Response(responseStr, {
      status: isOk ? 200 : 400,
    })
  },
})

export default tauriGraphqlHttpLink

mikew avatar Sep 12 '23 00:09 mikew