kamilkisiela / apollo-angular

A fully-featured, production ready caching GraphQL client for Angular and every GraphQL server 🎁
https://apollo-angular.com
MIT License
1.5k stars 309 forks source link

Named Client is not created 2 modules exported #1747

Closed Moepkid closed 2 years ago

Moepkid commented 2 years ago

Describe the bug I am trying to combine lazy loading with named clients, and everything works fine if I place the NAMED_OPTIONS provider one module deeper. However, when I place it two modules deeper in, it wont recognize the named client anymore and I get the error:

TypeError: Cannot read properties of undefined (reading 'query')

To Reproduce

The following works correctly:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { ServiceWorkerModule } from '@angular/service-worker';
import { environment } from '../environments/environment';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { HttpClientModule } from '@angular/common/http';
import { AppRoutingModule } from './app-routing/app-routing.module';
import { FooterModule } from './footer/footer.module';
import { HeaderModule } from './header/header.module';
import { PopupModule } from './popup/popup.module';
import { LoadingModule } from './shared/loading/loading.module';
import { GraphqlModule } from './graphql/graphql.module';
import { ResultGraphqlModule } from './graphql/result/result-graphql.module';

@NgModule({
  declarations: [AppComponent],
  imports: [
    /*
     * Angular Modules
     * */
    HttpClientModule,
    BrowserModule.withServerTransition({ appId: 'serverApp' }),
    ServiceWorkerModule.register('ngsw-worker.js', {
      enabled: environment.production,
    }),
    BrowserAnimationsModule,

    /*
     * Feature modules that should be initialized at start of app.
     * */
    GraphqlModule,
    ResultGraphqlModule,
    AppRoutingModule,
    PopupModule,
    HeaderModule,
    LoadingModule,
    FooterModule,
  ],
  providers: [],
  bootstrap: [AppComponent],
})
export class AppModule {}
import { NgModule } from '@angular/core';
import { ResultGraphqlModule } from './result/result-graphql.module';
import { GraphqlDataService } from './service/graphql-data.service';
import { APOLLO_NAMED_OPTIONS } from 'apollo-angular';
import { HttpLink } from 'apollo-angular/http';
import { ErrorService } from '../error/service/error.service';
import { GraphqlHelper } from './helper/graphql.helper';
import { NamedApolloClientOptions } from './model/named-apollo-client-options.model';

@NgModule({
  declarations: [],
  imports: [ResultGraphqlModule],
  providers: [
    GraphqlDataService,
    {
      provide: APOLLO_NAMED_OPTIONS,
      useFactory: (httpLink: HttpLink, errorService: ErrorService) => {
        return {
          result: GraphqlHelper.CreateNamedApolloClient(
            new NamedApolloClientOptions('result', 'results'),
            httpLink,
            errorService
          ),
        };
      },
      deps: [HttpLink, ErrorService],
    },
  ],
  exports: [ResultGraphqlModule],
})
export class GraphqlModule {}

However, when I place the NAMED_OPTIONS provider one module deeper (the ResultGraphqlModule), it does not work:

import { NgModule } from '@angular/core';
import { APOLLO_NAMED_OPTIONS, ApolloModule } from 'apollo-angular';
import { HttpLink } from 'apollo-angular/http';
import { GraphqlHelper } from '../helper/graphql.helper';
import { ErrorService } from '../../error/service/error.service';
import { NamedApolloClientOptions } from '../model/named-apollo-client-options.model';
import { ErrorModule } from '../../error/error.module';

@NgModule({
  declarations: [],
  imports: [ApolloModule, ErrorModule],
  providers: [
    {
      provide: APOLLO_NAMED_OPTIONS,
      useFactory: (httpLink: HttpLink, errorService: ErrorService) => {
        return {
          result: GraphqlHelper.CreateNamedApolloClient(
            new NamedApolloClientOptions('result', 'results'),
            httpLink,
            errorService
          ),
        };
      },
      deps: [HttpLink, ErrorService],
    },
  ],
  exports: [ApolloModule],
})
export class ResultGraphqlModule {}

Expected behavior

I think I am missing a key step in importing the right way.

Environment:

├── @angular/cli@13.1.2 ├── @angular/core@13.1.1 ├── @apollo/client@3.5.6 ├── apollo-angular@3.0.0-alpha.2 ├── graphql@15.8.0 └── typescript@4.5.4

Moepkid commented 2 years ago

Sorry, My bad. I think I exported the module twice somewhere because it runs perfectly now that I cleaned it up. The result:

import { NgModule } from '@angular/core';
import { ResultGraphqlModule } from './result/result-graphql.module';
import { GraphqlDataService } from './service/graphql-data.service';

@NgModule({
  declarations: [],
  imports: [ResultGraphqlModule],
  providers: [GraphqlDataService],
  exports: [ResultGraphqlModule],
})
export class GraphqlModule {}
import { NgModule } from '@angular/core';
import { APOLLO_NAMED_OPTIONS, ApolloModule } from 'apollo-angular';
import { HttpLink } from 'apollo-angular/http';
import { ErrorService } from '../../error/service/error.service';
import { GraphqlHelper } from '../helper/graphql.helper';
import { NamedApolloClientOptions } from '../model/named-apollo-client-options.model';
import { ErrorModule } from '../../error/error.module';

@NgModule({
  declarations: [],
  imports: [ApolloModule, ErrorModule],
  providers: [
    {
      provide: APOLLO_NAMED_OPTIONS,
      useFactory: (httpLink: HttpLink, errorService: ErrorService) => {
        return {
          result: GraphqlHelper.CreateNamedApolloClient(
            new NamedApolloClientOptions('result', 'results'),
            httpLink,
            errorService
          ),
        };
      },
      deps: [HttpLink, ErrorService],
    },
  ],
})
export class ResultGraphqlModule {}
Moepkid commented 2 years ago

Turns out I did not fix it and I do not know whats happening in the imports.

Using a second client, the first one doesnt exist anymore (results).

import { NgModule } from '@angular/core';
import { ResultGraphqlModule } from './result/result-graphql.module';
import { GraphqlDataService } from './service/graphql-data.service';
import { ScheduleGraphqlModule } from './schedule/schedule-graphql.module';

@NgModule({
  declarations: [],
  imports: [ResultGraphqlModule, ScheduleGraphqlModule],
  providers: [GraphqlDataService],
  exports: [ResultGraphqlModule, ScheduleGraphqlModule],
})
export class GraphqlModule {}
import { NgModule } from '@angular/core';
import { NamedApolloClientOptions } from '../../graphql/model/named-apollo-client-options.model';
import { APOLLO_NAMED_OPTIONS, ApolloModule } from 'apollo-angular';
import { HttpLink } from 'apollo-angular/http';
import { ErrorService } from '../../error/service/error.service';
import { GraphqlHelper } from '../helper/graphql.helper';
import { ErrorModule } from '../../error/error.module';

@NgModule({
  declarations: [],
  imports: [ApolloModule, ErrorModule],
  providers: [
    {
      provide: APOLLO_NAMED_OPTIONS,
      useFactory: (httpLink: HttpLink, errorService: ErrorService) => {
        return {
          schedule: GraphqlHelper.CreateNamedApolloClient(
            new NamedApolloClientOptions('schedule', 'schedule'),
            httpLink,
            errorService
          ),
        };
      },
      deps: [HttpLink, ErrorService],
    },
  ],
})
export class ScheduleGraphqlModule {}
Moepkid commented 2 years ago

Is there a way to retrieve the current clients and append a new one to them instead of overwriting the APOLO_NAMED_OPTIONS?

kamilkisiela commented 2 years ago

it should now with with freshly released v3