Unable to generate code for GraphQL endpoint federation

I’m trying to set up federation of the same objects/schemas across a number of GraphQL endpoints.

I’ve followed the federation example in GitHub, but implemented for my use, and I’m getting the following error when trying to generate the files or run the server locally:

$ wunderctl generate
/Users/XXX/Documents/Work/OlympusDAO/treasury-subgraph/node_modules/@wundergraph/sdk/dist/definition/federation-introspection.js:46
    return res.data.data._service.sdl;
                         ^

TypeError: Cannot read properties of undefined (reading '_service')
    at fetchFederationServiceSDL (/Users/XXX/Documents/Work/OlympusDAO/treasury-subgraph/node_modules/@wundergraph/sdk/dist/definition/federation-introspection.js:46:26)

Here’s the repo (pinned at the current commit): Federation example · 0xJem/federated-subgraph@daa33ae · GitHub

What version are you using? It looks weird to me that the access path is res.data.data._service.sdl.

I just set up the repo today, so it must be recent.

Version: 0.146.1
Commit: ada177035c028093afeb4f3e889d15cfe12ddca8
Date: 2023-04-27T18:20:28Z
BuiltBy: ci

I came across this: Custom request headers not working when using `wunderctl generate` · Issue #150 · wundergraph/wundergraph · GitHub

It could be possible that _service is not being provided by the GraphQL endpoint upon introspection?

Does this service implement Apollo Federation?
If not, your wundergraph.config.ts might be incorrect.
Can you share it?

It’s looking like it does not support Apollo Federation.

Here’s the config file: federated-subgraph/wundergraph.config.ts at daa33aec631942a255dcd7719992fbe955cf1649 · 0xJem/federated-subgraph · GitHub

Is there any other way to combine the results from multiple GraphQL endpoints?

You can just use introspect.graphql for both APIs and combine them like so: wundergraph/wundergraph.config.ts at 6abfbf6b5766b8840a39f6f96593ee6e8efc05dd · wundergraph/wundergraph · GitHub

If you wish to join data across the two APIs, here’s how you can do it:
https://docs.wundergraph.com/docs/features/cross-api-joins-to-compose-apis

Let me know if you need anything else.

Btw @Jem I’d love to hear a bit more on what you’re building? I can see from the config that you’re combining multiple APIs from thegraph.

That would result in records with the same schema (e.g. TokenRecord), but with a different prefix for each endpoint, right?

e.g. endpoint1_tokenRecord, endpoint2_tokenRecord

I was hoping (using federation) to collapse it down to one array of tokenRecord results. Is that possible?

We have a dashboard that currently uses multiple GraphQL endpoints: OlympusDAO

End endpoint represents a different blockchain (ethereum, arbitrum, etc).

Currently, we have a really hacky approach to fetching the GraphQL data, as the server (provided by the Graph Protocol) doesn’t support much in the way of pagination. I was hoping to aggregate the results using Wundergraph and provide a simple endpoint for the React frontend to fetch data from.

1 Like

You can give both APIs the same apiNamespace, then the types will be merged.

1 Like

This seems like a very good use case!

You can give both APIs the same apiNamespace, then the types will be merged.

That doesn’t seem to be the case, actually.

The order of entry of the APIs seems to determine what results show up.

e.g.

const protocolMetricsEthereum = introspect.graphql({
	apiNamespace: "protocolMetrics",
	url: `https://gateway.thegraph.com/api/${process.env.SUBGRAPH_API_KEY}/subgraphs/id/DTcDcUSBRJjz9NeoK5VbXCVzYbRTyuBwdPUqMi8x32pY`,
});

const protocolMetricsArbitrum = introspect.graphql({
	apiNamespace: "protocolMetrics",
	url: "https://api.studio.thegraph.com/proxy/28103/protocol-metrics-arbitrum/1.1.6",
});

// configureWunderGraph emits the configuration
configureWunderGraphApplication({
	apis: [protocolMetricsArbitrum, protocolMetricsEthereum],
        ....
});

Querying against this, I received results only from the Arbitrum endpoint.

If I change it to apis: [protocolMetricsEthereum, protocolMetricsArbitrum],, I only receive Ethereum results.

I can work around it by having different api namespaces and combining on the client end, but it would definitely be nice to do this server-side.

Thank you for reporting. Seems like a bug we’d like to fix.

Hello @Jem

We’ve tried to reproduce this problem, but we were not successful. Using the following configuration:

const countries = introspect.graphql({

apiNamespace: 'test',

url: 'https://countries.trevorblades.com/',

});

const weather = introspect.graphql({

apiNamespace: 'test',

url: 'https://weather-api.wundergraph.com/',

introspection: {

pollingIntervalSeconds: 5,

},

});

We can send queries like e.g.

query {
	countries: test_country(code:"DE") {
    code
    name
  }
  test:test_getCityByName(config:{lang:en, units:imperial}, country:"DE", name:"Berlin") {
    id
    country
    name
  }
}

And we receive the correct results. Could you please share with us the resulting schema from .wundergraph/generated/wundergraph.schema.graphql - That would help us determine the problem better. Thanks!