Two endpoints in Apollo Client (Angular)

2.3k Views Asked by At

Beginer here. While using a single endpoint using the default structure made when executing "ng add apollo-angular" works fine, when adding a second one using APOLLO_NAMED_OPTIONS I get two cryptic errors messages. What could be going wrong?

This is my graphql.module.ts file

import {APOLLO_OPTIONS, APOLLO_NAMED_OPTIONS} from 'apollo-angular';
import { InMemoryCache, ApolloLink } from '@apollo/client/core';
import {HttpLink} from 'apollo-angular/http';

const urium = 'https://some.url.here';       //changed for this post
const urips = 'https://some.other.one.here'; //changed for this post


export function createApollo(httpLink: HttpLink) {
  return {
    link: ApolloLink.from([httpLink.create({ uri: urium })]),
    cache: new InMemoryCache()
  }
}


export function createProjectspecApollo(httpLink: HttpLink) {
  return {
    name:'projectspec',
    link: ApolloLink.from([httpLink.create({ uri: urips })]),
    cache: new InMemoryCache()
  }
}

@NgModule({
  providers: [
    {
      provide: APOLLO_OPTIONS,
      useFactory: createApollo,
      deps: [HttpLink]
    },{
      provide: APOLLO_NAMED_OPTIONS,
      useFactory: createProjectspecApollo,
      deps: [HttpLink]
    }
  ]
})
export class GraphQLModule {}

Here is GqlApolloInterfaceService, where I use the client

import { Apollo } from "apollo-angular";



@Injectable({
  providedIn: 'root'
})
export class GqlApolloInterfaceService {
 
  constructor(private apollo:Apollo) { }
  
}

Finaly, my package.json

{
  "name": "frontend",
  "version": "0.0.0",
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e"
  },
  "private": true,
  "dependencies": {
    "@angular/animations": "~11.0.0",
    "@angular/cdk": "^11.0.1",
    "@angular/common": "~11.0.0",
    "@angular/compiler": "~11.0.0",
    "@angular/core": "~11.0.0",
    "@angular/flex-layout": "^11.0.0-beta.33",
    "@angular/forms": "~11.0.0",
    "@angular/material": "^11.0.1",
    "@angular/platform-browser": "~11.0.0",
    "@angular/platform-browser-dynamic": "~11.0.0",
    "@angular/router": "~11.0.0",
    "@apollo/client": "^3.0.0",
    "apollo-angular": "^2.1.0",
    "apollo-angular-link-http": "^1.11.0",
    "apollo-link-context": "^1.0.20",
    "graphql": "^15.0.0",
    "rxjs": "~6.6.0",
    "tslib": "^2.0.0",
    "zone.js": "~0.10.2"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "~0.1100.1",
    "@angular/cli": "~11.0.1",
    "@angular/compiler-cli": "~11.0.0",
    "@types/jasmine": "~3.6.0",
    "@types/node": "^12.11.1",
    "codelyzer": "^6.0.0",
    "jasmine-core": "~3.6.0",
    "jasmine-spec-reporter": "~5.0.0",
    "karma": "~5.1.0",
    "karma-chrome-launcher": "~3.1.0",
    "karma-coverage": "~2.0.3",
    "karma-jasmine": "~4.0.0",
    "karma-jasmine-html-reporter": "^1.5.0",
    "protractor": "~7.0.0",
    "ts-node": "~8.3.0",
    "tslint": "~6.1.0",
    "typescript": "~4.0.2"
  }
}

I get two errors: the first one is only shown first, as soon as I add the second pbject in the providers list:

ERROR Error: Uncaught (in promise): Invariant Violation: To initialize Apollo Client, you must specify a 'cache' property in the options object.

Then, if I refresh the page, I get a different one:

ERROR Error: Uncaught (in promise): Error: NG0200: Circular dependency in DI detected for GqlApolloInterfaceService Error: NG0200: Circular dependency in DI detected for GqlApolloInterfaceService

I'm just starting with Apollo Client so it may be something extremely simple, however, I'm getting the impression that the documentation is very vague and not much effort has been put in making it. What could be happening and, most importantly, how can I make it work?

Regards!

2

There are 2 best solutions below

0
On BEST ANSWER

I solved it by using the uri() function within the link atribute from the return object of createApollo. My case was that some queries/mutations had to be done to one endpoint and others to a different endpoint. All my queries/mutations are implemented as services as seen here

First, I made a function operationFilter that acts as a filter by checking the operation name. Then, the uri funtion uses operationFilter to select between the two different endpoints

My new graphql.module.ts looks like this

import {NgModule} from '@angular/core';
import {APOLLO_OPTIONS } from 'apollo-angular';
import { InMemoryCache, ApolloLink } from '@apollo/client/core';
import {HttpLink} from 'apollo-angular/http';
import { setContext } from '@apollo/client/link/context';

const urium = 'https://some.url.here';       //changed for this post
const urips = 'https://some.other.one.here'; //changed for this post


function operationFilter(operationName:string):boolean{  
  if(...) return true;    //queries that should go to one endpoint
  else return false;      //and the others
 }

export function createApollo(httpLink: HttpLink) {

    const auth = setContext((operation, context) => {
        ...add some header stuff, like jwt...
    });

   return {
       link: ApolloLink.from(
           [
               auth, 
               httpLink.create({
                   uri(operation){ 
                       return operationFilter(operation.operationName)? urium : urips;
                   } 
               })
           ]),
       cache: new InMemoryCache(),
       defaultOptions:{query:{errorPolicy: "all"}}
    } 
}

More information can be found here

I guess it's not the most sophisticated solution, but worked. I'll be happy to learn if there is a cleaner way to do this.

Regards!

1
On

Try named apollo client

apollo.create(option1, "endpoint 1")

apollo.create(option2, "endpoint 2")

apollo.use('endpoint 1').watchQuery({...});

refer https://apollo-angular.com/docs/recipes/multiple-clients/

Alternative, Just for a thought

Instead of configuring multiple graphql end point in UI Use Apollo federation with Apollo server to configure multiple graphql, In that way UI will have only one Apollo client. Any new api/graphql changes only in the Apollo server. No need of changing in UI https://www.apollographql.com/docs/federation/gateway/