Closed samuelcastro closed 7 months ago
Another solution would be: https://github.com/habx/apollo-multi-endpoint-link
new ApolloClient({
link: ApolloLink.from([
new MultiAPILink({
endpoints: {
housings: 'https://housings.api',
projects: 'https://projects.api',
...
},
createHttpLink: () => new HttpLink({ ... }),
}),
])
})
More info here: https://www.habx.com/tech/micro-graphql-schema
Or maybe an example showing up how to integrate Apollo Server Federation
For the record I use the split
approach in production in my projects, with 3 services, it works perfectly well. It allows our backend team to postpone the creation of a federated GraphQL API until we really really need it, and work service by service instead.
Limitation is that you can't have the same type name in different API (it would break Apollo Client caching), so this is meant to handle API you actually control.
This is the generalization for N links, based on a comment of the article (which I can't access right now sadly) from @naveennazimudeen: https://github.com/VulcanJS/vulcan-next/blob/devel/src/pages/docs/recipes.md#smart-replacement-of-the-http-link
Not sure about the MultiAPILink
approach, I can't tell if it has the same limitation. I don't like using directives though, I prefer to play on the context.
Hi,
I am trying to integrate multiple api routes using graphql. In the following repository I have a toy example where I expose two different services: products and users.
I originally thought of exposing a single file called [...graphql].ts that would capture all the API paths, but I don't know if doing this exposes it as a single serverless function, if so it might affect the performance of all services. That's why I chose to expose different paths in different files inside the api/graphql directory, this way I ensure that each serverless function contains only the packages it needs and that it scales on its own demand. (Is this argument correct?)
Additionally, the directory contains one more path called "super", which in the context of the apollo federation is the super-graph that contains the union of the "products" and "users" subgraphs. This is for development purposes only, in order to view a single graph in development, in production I make sure to omit it.
I recently started exploring apollo federation and finding documentation on it has been difficult, I would appreciate any reference on best practices for integrating nextjs and federated services with apollo federation.
Hi, in my case I use links created with @graphql-codegen, you can use clientName.
//codegenInbox.ts
import type { CodegenConfig } from '@graphql-codegen/cli' const config: CodegenConfig = { schema:
${process.env.NEXT_PUBLIC_API_INBOX}/graphql, documents: './{components, graphql}/**/*.{ts,tsx}', overwrite: true, generates: { './graphql/types.tsx': { plugins: ['typescript', 'typescript-react-apollo','typescript-operations'], config: { defaultBaseOptions: { context: { clientName: "inboxLink" }, }, withMutationFn: true, withHOC: false, withHooks: true, withComponent: false }, }, }, } export default config
in package.json add: "generate-inbox": "graphql-codegen -r dotenv/config codegenInbox.ts" ...
//Add another configs for yours apis
//create apollo.ts
`import { ApolloClient, createHttpLink, InMemoryCache, split, } from '@apollo/client'; import { setContext } from '@apollo/client/link/context'; import { GraphQLWsLink } from '@apollo/client/link/subscriptions'; import { getMainDefinition } from '@apollo/client/utilities'; import { createClient } from 'graphql-ws';
export const config = {
inboxLink: {
url: ${process.env.NEXT_PUBLIC_INBOX_MAIL_API}/graphql
,
hasWebSocket: true,
},
productLink: {
url: ${process.env.NEXT_PUBLIC_PRODUCT}/graphql
,
hasWebSocket: false,
},
};
export default function inicializar(token: string) {
const createHttpLinkForUrl = (url: string) => { return url ? createHttpLink({ uri: url, credentials: 'include', }) : null; };
const createGraphQLWsLinkForUrl = (url: string) => {
return new GraphQLWsLink(createClient({
url: url.replace('http', 'ws'),
connectionParams: {
Authorization: Bearer ${token}
,
credentials: 'include',
},
}));
};
const createSplitLink = (operationName: string, httpLink: any, previousLink: any) => { return split( (operation) => operation.getContext().clientName === operationName, httpLink, previousLink, ); };
const createCombinedHttpLinks = () => { let combinedHttpLinks = null;
Object.entries(config).forEach(([operationName, { url }]) => {
if (url) {
combinedHttpLinks = createSplitLink(operationName, createHttpLinkForUrl(url), combinedHttpLinks);
}
});
return combinedHttpLinks;
};
const createWebSocketSplitLink = (operationName: string, webSocketLink: any, previousLink: any) => { return split( (operation) => operation.getContext().clientName === operationName, webSocketLink, previousLink, ); }; const createCombinedWebSocketLink = () => { let combinedWsLink = null;
Object.entries(config).forEach(([operationName, { url, hasWebSocket }]) => {
if (hasWebSocket && url) {
combinedWsLink = createWebSocketSplitLink(operationName, createGraphQLWsLinkForUrl(url), combinedWsLink);
}
});
return combinedWsLink;
};
const authLink = setContext((_, { headers }) => {
return {
headers: {
...headers,
authorization: Bearer ${token}
,
},
};
});
const link = split( ({ query }) => { const definition = getMainDefinition(query); return ( definition.kind === 'OperationDefinition' && definition.operation === 'subscription' ); }, createCombinedWebSocketLink(), authLink.concat(createCombinedHttpLinks()), );
return new ApolloClient({ link: authLink.concat(link), cache: new InMemoryCache().restore({}), }); }`
Feature request
Is your feature request related to a problem? Please describe.
It'd be super helpful to have an example of a multiple api routes setup using graphql, all examples I can see are considering just one single api route, but in a real world we usually will need multiple APIs, specially when working with serverless functions. Maybe there is some sort of limitation around multiples api server with graphql that I'm not aware of.
Additional context
The solution described in this article would be helpful to connect multiple graphql endpoints into one single graphql instance, something like:
and then:
What's your thoughts?