Skip to content

Commit

Permalink
New provideApollo() and provideNamedApollo()
Browse files Browse the repository at this point in the history
Those two providers make it simpler to provide Apollo with a
options and flags to the application.

Token injections, `APOLLO_OPTIONS`, `APOLLO_NAMED_OPTIONS` and
`APOLLO_FLAGS` are not needed anymore in application code. Though they
might still be used for custom providing techniques.

`ApolloModule` is deprecated because it brings no value. Especially with
the introduction of the two providing functions.
  • Loading branch information
PowerKiKi committed Sep 19, 2024
1 parent b1bef7d commit aa5bece
Show file tree
Hide file tree
Showing 22 changed files with 362 additions and 349 deletions.
6 changes: 3 additions & 3 deletions packages/apollo-angular/http/tests/http-link.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { HttpClientModule, HttpHeaders } from '@angular/common/http';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { TestBed } from '@angular/core/testing';
import { ApolloLink, execute, gql, InMemoryCache } from '@apollo/client/core';
import { Apollo, ApolloModule } from '../../src';
import { Apollo } from '../../src';
import { HttpLink } from '../src/http-link';

const noop = () => {
Expand All @@ -17,8 +17,8 @@ describe('HttpLink', () => {

beforeEach(() => {
TestBed.configureTestingModule({
imports: [ApolloModule, HttpClientModule, HttpClientTestingModule],
providers: [HttpLink],
imports: [HttpClientModule, HttpClientTestingModule],
providers: [HttpLink, Apollo],
});
httpLink = TestBed.inject(HttpLink);
httpBackend = TestBed.inject(HttpTestingController);
Expand Down

This file was deleted.

11 changes: 10 additions & 1 deletion packages/apollo-angular/schematics/install/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,16 @@ function importSetup(options: Schema): Rule {
const mainPath = await getMainFilePath(host, options.project);
if (isStandaloneApp(host, mainPath)) {
return addRootProvider(options.project, ({ code, external }) => {
return code`${external('graphqlProvider', './graphql.provider')}`;
return code`${external('provideApollo', 'apollo-angular')}(() => {
const httpLink = inject(${external('HttpLink', 'apollo-angular/http')});
return {
link: httpLink.create({
uri: '<%= endpoint %>',
}),
cache: new ${external('InMemoryCache', '@apollo/client/core')}(),
};
})`;
});
} else {
await addModuleImportToRootModule(host, 'GraphQLModule', './graphql.module', options.project);
Expand Down
12 changes: 2 additions & 10 deletions packages/apollo-angular/schematics/tests/ng-add.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,18 +90,10 @@ describe('ng-add with standalone', () => {
}
});

test('should add graphqlProviders with GraphQL setup', async () => {
const providerPath = '/projects/apollo/src/app/graphql.provider.ts';
expect(tree.files).toContain(providerPath);

const content = getFileContent(tree, providerPath);
expect(content).toMatch('export const graphqlProvider');
});

test('should import the NgModule with GraphQL setup to the root module', async () => {
test('should use `provideApollo()` to provide Apollo', async () => {
const content = getFileContent(tree, '/projects/apollo/src/app/app.config.ts');

expect(content).toMatch(/import { graphqlProvider } from '.\/graphql.provider'/);
expect(content).toMatch(/provideApollo\(\(\) => {/);
});

test('should import HttpClientModule to the root module', async () => {
Expand Down
51 changes: 47 additions & 4 deletions packages/apollo-angular/src/apollo-module.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,52 @@
import { NgModule } from '@angular/core';
import { NgModule, Provider } from '@angular/core';
import { ApolloClientOptions } from '@apollo/client/core';
import { Apollo } from './apollo';
import { APOLLO_FLAGS, APOLLO_NAMED_OPTIONS, APOLLO_OPTIONS } from './tokens';
import { Flags, NamedOptions } from './types';

export const PROVIDERS = [Apollo];

/**
* This is deprecated and will be removed in the next major version, because
* Angular is moving toward a moduleless ecosystem.
*
* Instead, use either `provideApollo()` or `provideNamedApollo()`.
*
* @deprecated
*/
@NgModule({
providers: PROVIDERS,
providers: [Apollo],
})
export class ApolloModule {}

export function provideApollo<TCacheShape = any>(
optionsFactory: () => ApolloClientOptions<TCacheShape>,
flags: Flags = {},
): Provider {
return [
Apollo,
{
provide: APOLLO_OPTIONS,
useFactory: optionsFactory,
},
{
provide: APOLLO_FLAGS,
useValue: flags,
},
];
}

export function provideNamedApollo(
optionsFactory: () => NamedOptions,
flags: Flags = {},
): Provider {
return [
Apollo,
{
provide: APOLLO_NAMED_OPTIONS,
useFactory: optionsFactory,
},
{
provide: APOLLO_FLAGS,
useValue: flags,
},
];
}
2 changes: 1 addition & 1 deletion packages/apollo-angular/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export type { TypedDocumentNode } from '@apollo/client/core';
export { ApolloModule } from './apollo-module';
export { ApolloModule, provideApollo, provideNamedApollo } from './apollo-module';
export { Apollo, ApolloBase } from './apollo';
export { QueryRef, QueryRefFromDocument } from './query-ref';
export { Query } from './query';
Expand Down
8 changes: 7 additions & 1 deletion packages/apollo-angular/tests/index.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as api from '../src';
import { Apollo } from '../src/apollo';
import { ApolloModule } from '../src/apollo-module';
import { ApolloModule, provideApollo, provideNamedApollo } from '../src/apollo-module';
import { gql, graphql } from '../src/gql';
import { QueryRef } from '../src/query-ref';

Expand All @@ -14,6 +14,12 @@ describe('public api', () => {
test('should export ApolloModule', () => {
expect(api.ApolloModule).toBe(ApolloModule);
});
test('should export provideApollo', () => {
expect(api.provideApollo).toBe(provideApollo);
});
test('should export provideNamedApollo', () => {
expect(api.provideNamedApollo).toBe(provideNamedApollo);
});
test('should export gql', () => {
expect(api.gql).toBe(gql);
});
Expand Down
19 changes: 8 additions & 11 deletions packages/apollo-angular/tests/integration.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,20 @@ import { HttpClientModule } from '@angular/common/http';
import { TestBed } from '@angular/core/testing';
import { InMemoryCache } from '@apollo/client/core';
import { mockSingleLink } from '@apollo/client/testing';
import { Apollo, APOLLO_OPTIONS, ApolloModule } from '../src';
import { Apollo, provideApollo } from '../src';

describe('Integration', () => {
describe('default', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [ApolloModule, HttpClientModule],
imports: [HttpClientModule],
providers: [
{
provide: APOLLO_OPTIONS,
useFactory: () => {
return {
link: mockSingleLink(),
cache: new InMemoryCache(),
};
},
},
provideApollo(() => {
return {
link: mockSingleLink(),
cache: new InMemoryCache(),
};
}),
],
});
});
Expand Down
17 changes: 14 additions & 3 deletions packages/demo/src/app/app.config.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,25 @@
import { provideApollo } from 'apollo-angular';
import { HttpLink } from 'apollo-angular/http';
import { provideHttpClient } from '@angular/common/http';
import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';
import { ApplicationConfig, inject, provideZoneChangeDetection } from '@angular/core';
import { provideRouter } from '@angular/router';
import { InMemoryCache } from '@apollo/client/core';
import { routes } from './app.routes';
import { graphqlProvider } from './graphql.provider';

export const appConfig: ApplicationConfig = {
providers: [
provideZoneChangeDetection({ eventCoalescing: true }),
provideRouter(routes),
provideHttpClient(),
graphqlProvider,
provideApollo(() => {
const httpLink = inject(HttpLink);

return {
link: httpLink.create({
uri: 'https://swapi-graphql.netlify.app/.netlify/functions/index',
}),
cache: new InMemoryCache(),
};
}),
],
};
22 changes: 0 additions & 22 deletions packages/demo/src/app/graphql.provider.ts

This file was deleted.

26 changes: 13 additions & 13 deletions website/src/pages/docs/caching/configuration.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -22,23 +22,23 @@ additional libraries are required.

## Initialization

Create an `InMemoryCache` object and provide it to the `APOLLO_OPTIONS` token, like so:
Create an `InMemoryCache` object and provide to Apollo options, like so:

```ts filename="graphql.provider.ts"
import { HttpBatchLink } from 'apollo-angular/http';
```ts filename="app.config.ts"
import { provideApollo } from 'apollo-angular';
import { HttpLink } from 'apollo-angular/http';
import { inject } from '@angular/core';
import { ApolloClientOptions, InMemoryCache } from '@apollo/client/core';
function apolloOptionsFactory(): ApolloClientOptions<any> {
const httpBatchLink = inject(HttpBatchLink);
import { InMemoryCache } from '@apollo/client/core';

provideApollo(() => {
const httpLink = inject(HttpLink);

return {
link: httpBatchLink.create({ uri: '/graphql' }),
cache: new InMemoryCache({
/* your options here */
}), r options ...
link: httpLink.create({ uri: '/graphql' }),
cache: new InMemoryCache(),
// other options...
};
}
};
}
});
```

The `InMemoryCache` constructor accepts a variety of
Expand Down
36 changes: 14 additions & 22 deletions website/src/pages/docs/data/mutations.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -254,31 +254,23 @@ The result of `Apollo.mutate()` contains `loading` property. By default, it's al
result is emitted with the response from the ApolloLink execution chain. In order to correct it you
can enable `useMutationLoading` flag in configuration.

```ts filename="graphql.provider.ts"
import { Apollo, APOLLO_FLAGS, APOLLO_OPTIONS } from 'apollo-angular';
```ts filename="app.config.ts"
import { provideApollo } from 'apollo-angular';
import { HttpLink } from 'apollo-angular/http';
import { inject, Provider } from '@angular/core';
import { ApolloClientOptions, InMemoryCache } from '@apollo/client/core';
function apolloOptionsFactory(): ApolloClientOptions<any> {
const httpLink = inject(HttpLink);
return {
link: httpLink.create({ uri: '/graphql' }),
cache: new InMemoryCache(), options ...
};
}
};
}
export const graphqlProvider: Provider = [
Apollo,
{ provide: APOLLO_OPTIONS, useFactory: apolloOptionsFactory },
import { inject } from '@angular/core';
import { InMemoryCache } from '@apollo/client/core';

provideApollo(
() => {
return {
link: inject(HttpLink).create({ uri: '/graphql' }),
cache: new InMemoryCache(),
};
},
{
provide: APOLLO_FLAGS,
useValue: {
useMutationLoading: true, it here
},
},
useMutationLoading: true, // enable it here
},
];
);
```

<Callout type="warning">
Expand Down
Loading

0 comments on commit aa5bece

Please sign in to comment.