Giter Club home page Giter Club logo

apollo-multi-endpoint-link's People

Contributors

alexisfontaine avatar carolinevp avatar clementlecorre avatar dependabot-preview[bot] avatar dependabot[bot] avatar fclairamb avatar flaviendelangle avatar habx-auto-merge[bot] avatar habxtech avatar jean9696 avatar joelmukuthu avatar renovate-bot avatar renovate[bot] avatar samuelcastro avatar sircoolness avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

apollo-multi-endpoint-link's Issues

Collaborations with similar projects

Hi and thank you for the wonderful library and idea!

We are working on similar solution and would be great to chat and see if we can reuse code or somehow help each other.

We've create GraphQL Mesh - a library that let's you query multiple APIs, they could be multiple GraphQL APIs but also other types of APIs (REST/OpenAPI/gRPC etc that are automatically converted into GraphQL).

GraphQL Mesh can run anywhere, including the client.
So we also worked on a project called Graph Client - it is a client side library that uses GraphQL Mesh under the hood and can expose all this logic as an Apollo Link.

I love the API and the simplicity of your solution, I wonder if somehow our libraries could benefit yours and the other way around

Readme confusing on how to use createHttpLink

createHttpLink: () => new HttpLink({ ... })
hi there i confused about this line... in special with ( ... ) mmmm.. i start with graphql and react but i don understand what must be inside there.. can help me.. thk

Not working within Nuxt 3

For the last week I've trying to make this library work within Nuxt 3. I can't seem to access the multple endpoints

nuxt.config.ts

   ...
  apollo: {
    autoImports: true,
    authType: "XXXXXX",
    authHeader: "Authorization",
    tokenStorage: "cookie",
    proxyCookies: true,
    clients: {
      default: {
        httpEndpoint: "localhost", //placeholder will be replaced at runtime by apollo plugin
        tokenName: "headerAuth",
        httpLinkOptions: {
          credentials: "same-origin",
        },
      },
    },
})

apollo.ts

import { provideApolloClient } from "@vue/apollo-composable"
import { MultiAPILink } from "@habx/apollo-multi-endpoint-link"

export default defineNuxtPlugin((nuxtApp) => {
  const config = useRuntimeConfig()
  let client = new ApolloClient({
    cache: new InMemoryCache(),
    link: ApolloLink.from([
      new MultiAPILink({
        endpoints: {
          exchange: config.public.api,
          trade: config.public.apiTwo,
        },
        createHttpLink: () => createHttpLink(),
        httpSuffix: "",
        getContext: (endpoint) => {
          if (endpoint === "exchange") {
            return {
              headers: {
                Authorization: `Bearer ${config.public.token}`,
              },
            }
          }
          return {
            headers: {
              Authorization: `Bearer ${config.public.token}`,
            },
          }
        },
      }),
    ]),
  })
  provideApolloClient(client)
})

Query

    const query = gql`
      query services {
        services {
          ... on Service {
            name
            identifier {
              externalID
            }
            serviceType {
              name
              identifier {
                externalID
              }
            }
          }
        }
      }
    `

    const { data, error } = await useAsyncQuery(query)

    if (data.value) (this.data = data), (this.loading = false)
    if (error.value) (this.error = error.value), console.log("error: " + error?.value)

    if (data.value) {
      console.log("Exchange: Services")
      console.log(data.value)
    }
  }

It keeps calling the wrong endpoint. I've also tried useQuery. Any suggestions?

What about multiple schemas + introspection?

Hello,

Thank you for publishing this link. I've faced a similar use case and implemented a similar one-off solution that works in a similar way. One thing that I have not found a solution for is the case when there are multiple endpoints and we need to feed Apollo Client with some schema, i.e. with IntrospectionFragmentMatcher. I keep coming to the conclusion that Apollo just wants there to be one schema and that solutions like yours won't stand the test of time in more complex use cases. I'm just curious if you have encountered this problem?

Adding different error links for different endpoints

We are trying to pass an apollo link object instead of string to the two endpoints but we are getting error that the apollo link is not assignable to type string.

  return new ApolloClient({
    ssrMode: typeof window === 'undefined',
    link: ApolloLink.from([
      new MultiAPILink({
          endpoints: {
              laravel: {
                  link: ApolloLink.from([
                      authLink,
                      errorLink,
                      httpLink
                  ])
              },
              wordpress: {
                  link: ApolloLink.from([
                      authLinkwp,
                      errorLinkwp,
                      httpLinkwp
                  ])
              }
          } 
      })
  ]),
  cache: new InMemoryCache(),
  });
}

How can this be fixed and how can we add different cache for each

dynamic endpoints support

I would like to use this neat library, but my multiple endpoints uris are not know upfront, some of them are, but the others are generated dynamically on user interaction with the application. Is there a way to inject more endpoint uris as they become available?

Error here

Here is my problem. I implemented this package into my code. It querys using GraphQL, then it just keep loading...

Does anyone know how to fix?

ApolloError: field 'basic_users' not found in type: 'query_root'

Hello, maybe can you help me with this, I can use this query (hasura endpoint) on GraphiQL and it response well but when I use it on my code this return: field 'basic_users' not found in type: 'query_root' , but when I use nest endpoint it's work correctly.

Thank you

"@apollo/client": "^3.7.14",
"@habx/apollo-multi-endpoint-link": "^2.9.0",
"graphql": "^16.6.0"
import {gql} from '@apollo/client';

export const GET_BASIC_USER = gql`
  query GetBasicUser @api(name: hasura) {
    basic_users {
      name
    }
  }
`;
const getGraphqlClient = (
  token = '',
  roles: BasicUserRoles,
  env: boolean,
) => {
  let currentToken = '';
  return new ApolloClient({
    connectToDevTools: true,
    cache: new InMemoryCache({
      addTypename: true,
      typePolicies: {
        query_root: {queryType: true},
      },
    }),
    link: ApolloLink.from([
      new MultiAPILink({
        getContext: async endpoint => {
          currentToken = `Bearer ${token || (await getPersist())}`;
          if (endpoint === 'hasura') {
            return {
              headers: {
                Authorization: currentToken,
                'x-hasura-allowed-roles': roles,
              },
            };
          }
          return {};
        },
        endpoints: {
          hasura: HASURA_GRAPHQL_ENDPOINT,
          nest: NESTJS_GRAPHQL_ENDPOINT,
        },
        createHttpLink: () => createHttpLink(),
        httpSuffix: '',
      }),
    ]),
  });
};

Endpoints get messed up when querying with a unique @api name

Hi there,

I'm running into an issue with the apollo-multi-endpoint-link, and at this point I have no idea what to do anymore.

I'm using the same configuration as the example, providing 3 different endpoints, and using 3 Graphql queries that use this name as an identifier. Like this:

Queries:

const GET_ACTIVE_ITEMS_GOERLI = gql`
  query GetActiveItems @api(name: goerli) {
    activeItems(
...
`
const GET_ACTIVE_ITEMS_MUMBAI = gql`
  query GetActiveItems @api(name: mumbai) {
...
`
const GET_ACTIVE_ITEMS_ARBITRUM_GOERLI = gql`
  query GetActiveItems @api(name: arbitrumGoerli) {
...
`

Fetching:

const { data: goerliData, loading: goerliDataLoading } = useQuery(
    GET_ACTIVE_ITEMS_GOERLI,
  );
  const { data: mumbaiData, loading: mumbaiDataLoading } = useQuery(
    GET_ACTIVE_ITEMS_MUMBAI,
  );
  const { data: arbitrumGoerliData, loading: arbitrumGoerliDataLoading } =
    useQuery(GET_ACTIVE_ITEMS_ARBITRUM_GOERLI);

Configuration:

const apolloClient = new ApolloClient({
  cache: new InMemoryCache(),
  link: ApolloLink.from([
    errorLink,
    new MultiAPILink({
      endpoints: {
        goerli: process.env.NEXT_PUBLIC_SUBGRAPH_URL_GOERLI,
        mumbai: process.env.NEXT_PUBLIC_SUBGRAPH_URL_MUMBAI,
        arbitrumGoerli: process.env.NEXT_PUBLIC_SUBGRAPH_URL_ARBITRUM_GOERLI,
      },
      createHttpLink: () => createHttpLink(),
      httpSuffix: '',
    }),
  ]),
});

These queries are all fetched, then a useEffect hook sets a new variable activeItems, choosing from the 3 results based on the network.

Unfortunatly, the activeItems result seems completely random, as passing one network name will make the variable change between the queries results with no regularity. All 3 data variables goerliData mumbaiData and arbitrumGoerliData get initialized with the same array on each refresh, as if the 3 query results could not coexist.

Since the network and conditions are working correctly, I believe the @api(name) selector is not working. It looks like it's setting activeItems to one of the 3 queries without respecting the endpoint selection.

I have no idea what I'm doing wrong here. Here is a codesandbox with just the needed parameters.
You can start it as usual yarn && yarn dev, go to index.js and then just change the network variable (line 63) to any of the 3 networks: goerli / mumbai / arbitrumGoerli. Then you just refresh the page. And you can repeat. They should respectively return an array of 9 / 2 / 4 objects, but they don't. Actually, you just need to refresh the page a few times, the results will change sometimes, maybe because it gets set up to the latest query result ? Although each data should get its own query ?

https://codesandbox.io/s/multi-endpoints-issue-dzxdw7?file=/pages/index.js

Thanks already to anyone who will take the time to help me :)

Default endpoint

Is there a way to define a default endpoint? So if { context: { apiName: 'name' } } is not passed it defaults to that endpoint?

Not working with Apollo persistedQueryLink?

TLDR:
The persisted query link requires using the HttpLink. (see link to their doc bellow).
Is it possible to set up MultiAPILink using HttpLink? (instead of createHttpLink)

Longer explanation:

Hello, in apollo-client.ts I had implemented PersistendQueryLink, based on https://www.apollographql.com/docs/react/api/link/persisted-queries/

I have const links = [] and then push there errorLink, authorizationLink, (retry link), following by:

if (process.env.NODE_ENV === 'production') {
  const persistedQueryLink = createPersistedQueryLink({ sha256 })
  links.push(persistedQueryLink)
}

const retryLink = new RetryLink()
links.push(retryLink)

const httpLink = new MultiAPILink({
  createHttpLink: () => createHttpLink(),
  endpoints,
  httpSuffix: '',
  wsSuffix: '',
})

links.push(httpLink)

export const client = new ApolloClient({
  cache,
  link: ApolloLink.from(links),
})

I get error from BE:

"PersistedQueryNotFoundError: PersistedQueryNotFound"
 at processGraphQLRequest (/Users/david/Documents/github/datacatalog-be/node_modules/apollo-server-core/src/requestPipeline.ts:181:40)"
 at processTicksAndRejections (node:internal/process/task_queues:96:5)"
 at processHTTPRequest (/Users/david/Documents/github/datacatalog-be/node_modules/apollo-server-core/src/runHttpQuery.ts:434:24)"
message
: 
"PersistedQueryNotFound"

Before using this library, I connected to 1 endpoint like so:

const httpLink = new HttpLink({
  uri: process.env.NEXT_PUBLIC_API_URL,
})

Thus it is clear my error comes from connecting to multiple endpoints using this library.

I think answer to my problem is in sentence: The persisted query link requires using the HttpLink. (see link to their doc above).
Thus my question is, is it possible to set up MultiAPILink using HttpLink? (instead of createHttpLink). If yes, how?

Mulitple Apis in a single query

How can I use two different apis in a single query, is there anyway to make api directives subquery specific?

  query($id: String!) {
    widgets( id: $id ) @api(name: widgetEndpoint) {
      width
      weight
    }
    gadgets( id: $id ) @api(name: gadgetEndpoint) {
      length
      color
    }
  }
;

Graphql subscription?

Hello, it seems your library allows for using subscriptions-transport-ws to establish graphql subscription, which is not maintained anymore and is not recommended to be used.
Is there a way to make your library work with graphql-ws?
To be clear, I just want to use subscription next to already using query and mutation using this library. Is there an example how apollo-multi-endpoint-link can be used with graphql subscription?

Thank you for any help.

Multi subscription end point

Hi, I got multiple Graphql servers, and everyone has their own subscriptions
I'm wondering if your middleware support that or willing to support it in the near future?

Need Sample test case

It would really help to have a complete simple test case. That could be used as an example and to test the library,

Updated?

May I know is this being maintained? I have implemented the solution, it seems like it's always in a loading state when data is fetched from GraphQL API.

Graphql schema interception / types generation with multiple endpoints

Hello, I successfully use your library to query 2 endpoints. Now, how do I auto-generate types from 2 graphql schemas, when using 2 endpoints?

Scripts I used up until now (with standard 1 endpoint) uses Apollo codegen (source):

"schema": "npx apollo service:download --endpoint=http://localhost:8080/graphql graphql-schema.json",
"types": "npm run schema && apollo client:codegen --localSchemaFile=graphql-schema.json --variant=development --target=typescript --addTypename --queries=./src/**/*.graphql --useReadOnlyTypes --globalTypesFile=src/globalTypes.ts . && npm run prettier"

Possible solution is also generating 2 introspection schemas and then merging them together, I just didn't find how.

I'm also open to move to Graphql Code Generator.

Is there any example, guidance, or link please?
Thank you

Action Required: Fix Renovate Configuration

There is an error with this repository's Renovate configuration that needs to be fixed. As a precaution, Renovate will stop PRs until it is resolved.

Error type: Cannot find preset's package (github>habx/devops-repo-shared-configs//renovate/ts-lib-client-public)

How to pass additional variables to query?

Great idea to put together this library! I know the library is pretty young, and thus the documentation is lacking. I was wondering how we can pass in additional parameters/variables to the query?

Is there any limitations?

Hi, thanks for this library! Is there any limitation in regards to using it (support for subscriptions, cache or something else)?

Also it's not clear how headers should be set, don't you support a way of setting headers per endpoints? If we need to set headers in the createHttpLink function, does that mean that all headers are going to be sent to all endpoints? I have 2 different 3rd party services that uses Authorization as headers, therefore I can't send the same headers for all endpoints.

Thanks!

Does the endpoint become part of the cache key?

I have several GraphQL endpoints I'm trying to fetch from that share many of the same field names, but have different schemas and values within those fields. For example, what if I have these 2 queries I want to run:

query {
    products {
        id # UUID string
        seller # string
        price # Int, number of cents
    }
}
query {
    products {
        id # number
        affiliate # string
        price # string of the format "$1.23"
    }
}

Can I use this library to query from both of these endpoints without any caching issues?

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Open

These updates have all been created already. Click a checkbox below to force a retry/rebase of any.

Detected dependencies

circleci
.circleci/config.yml
  • node 1.4.0
npm
package.json
  • @apollo/client ^3.7.3
  • @habx/config-ci-front ^3.9.0
  • @habx/eslint-config-client ^6.10.0
  • @types/jest ^29.2.5
  • apollo-link-rest *
  • bili ^5.0.5
  • cz-conventional-changelog ^3.3.0
  • eslint ^8.30.0
  • graphql ^15.8.0
  • jest ^29.3.1
  • jest-fetch-mock ^3.0.3
  • lint-staged ^13.1.0
  • rimraf ^3.0.2
  • rollup-plugin-typescript2 ^0.34.1
  • ts-jest ^29.0.3
  • typescript ^4.9.4
  • @apollo/client ^3.7.3

  • Check this box to trigger a request for Renovate to run again on this repository

Missing dependencies

Looks like tscov is missing from dev dependencies

Adding this and running

npm run type:coverage

shows error

Error: ENOENT: no such file or directory, stat '/home/mwoodpatrick/projects/git/www/apollo-multi-endpoint-link/@habx/config-ci-front/typescript/library.json'

prefixTypenames doesn't work with fragments?

When using this with fragments and prefixTypenames: true, I end up getting an empty object without any of the fields from the fragments. The network result will include all the id and name values, but the object returned from the Apollo client will not. Is there anything special that we need to add to make those work?

Example:

query myQuery @api(name: myApi) {
    clusterRangeQuery {
        graphId
        clusters {
            ...Cluster
        }
        edges {
            source
            target
        }
    }
}

fragment Cluster on Cluster {
    id
    label
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.