Skip to content

Commit f36206a

Browse files
authored
Merge pull request #2355 from the-guild-org/apollo-client-v4
2 parents e65bcce + 84d3fb5 commit f36206a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

74 files changed

+1422
-1445
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"apollo-angular": patch
3+
---
4+
dependencies updates:
5+
- Updated dependency [`@apollo/client@^4.0.1` ↗︎](https://www.npmjs.com/package/@apollo/client/v/4.0.1) (from `^3.13.1`, in `peerDependencies`)
6+
- Updated dependency [`rxjs@^7.3.0` ↗︎](https://www.npmjs.com/package/rxjs/v/7.3.0) (from `^6.0.0 || ^7.0.0`, in `peerDependencies`)

.changeset/chatty-cherries-drum.md

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
---
2+
'apollo-angular': major
3+
---
4+
5+
Namespaced types
6+
7+
Before:
8+
9+
```ts
10+
import type {
11+
Options,
12+
BatchOptions
13+
} from 'apollo-angular/http';
14+
15+
import type {
16+
MutationOptionsAlone,
17+
QueryOptionsAlone,
18+
SubscriptionOptionsAlone,
19+
WatchQueryOptions,
20+
WatchQueryOptionsAlone,
21+
} from 'apollo-angular';
22+
23+
type AllTypes =
24+
| Options
25+
| BatchOptions
26+
| MutationOptionsAlone
27+
| QueryOptionsAlone
28+
| SubscriptionOptionsAlone
29+
| WatchQueryOptions
30+
| WatchQueryOptionsAlone;
31+
```
32+
33+
After:
34+
35+
```ts
36+
import type {
37+
HttpBatchLink,
38+
HttpLink
39+
} from 'apollo-angular/http';
40+
41+
import type {
42+
Apollo,
43+
Mutation,
44+
Query,
45+
Subscription,
46+
} from 'apollo-angular';
47+
48+
type AllTypes =
49+
| HttpLink.Options
50+
| HttpBatchLink.Options
51+
| Mutation.MutateOptions
52+
| Query.FetchOptions
53+
| Subscription.SubscribeOptions
54+
| Apollo.WatchQueryOptions
55+
| Query.WatchOptions;
56+
```

.changeset/funny-trainers-look.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
'apollo-angular': major
3+
---
4+
5+
`httpHeaders` is a class
6+
7+
Migrate your code like so:
8+
9+
```diff
10+
- const link = httpHeaders();
11+
+ const link = new HttpHeadersLink();
12+
```

.changeset/giant-clouds-shout.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
'apollo-angular': major
3+
---
4+
5+
Move `useZone` option into subscription options
6+
7+
8+
```diff
9+
- const obs = apollo.subscribe(options, { useZone: false });
10+
+ const obs = apollo.subscribe({ ...options, useZone: false });
11+
```

.changeset/tough-masks-search.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
---
2+
'apollo-angular': major
3+
---
4+
5+
Combined parameters of `Query`, `Mutation` and `Subscription` classes generated via codegen
6+
7+
Migrate your code like so:
8+
9+
```diff
10+
class MyComponent {
11+
myQuery = inject(MyQuery);
12+
myMutation = inject(MyMutation);
13+
mySubscription = inject(MySubscription);
14+
15+
constructor() {
16+
- myQuery.watch({ myVariable: 'foo' }, { fetchPolicy: 'cache-and-network' });
17+
+ myQuery.watch({ variables: { myVariable: 'foo' }, fetchPolicy: 'cache-and-network' })
18+
19+
- myMutation.mutate({ myVariable: 'foo' }, { errorPolicy: 'ignore' });
20+
+ myMutation.mutate({ variables: { myVariable: 'foo' }, errorPolicy: 'ignore' });
21+
22+
- mySubscription.subscribe({ myVariable: 'foo' }, { fetchPolicy: 'network-only' });
23+
+ mySubscription.subscribe({ variables: { myVariable: 'foo' }, fetchPolicy: 'network-only' });
24+
}
25+
}
26+
```

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
"@angular/platform-browser-dynamic": "^18.0.0",
3838
"@angular/platform-server": "^18.0.0",
3939
"@angular/router": "^18.0.0",
40-
"@apollo/client": "^3.13.1",
40+
"@apollo/client": "4.0.1",
4141
"@babel/core": "^7.24.6",
4242
"@babel/preset-env": "^7.24.6",
4343
"@changesets/changelog-github": "^0.5.0",
Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,17 @@
11
import { HttpHeaders } from '@angular/common/http';
2-
import { ApolloLink, NextLink, Operation } from '@apollo/client/core';
2+
import { ApolloLink } from '@apollo/client';
33

4-
export const httpHeaders = () => {
5-
return new ApolloLink((operation: Operation, forward: NextLink) => {
6-
const { getContext, setContext } = operation;
7-
const context = getContext();
4+
export class HttpHeadersLink extends ApolloLink {
5+
constructor() {
6+
super((operation, forward) => {
7+
const { getContext, setContext } = operation;
8+
const context = getContext();
89

9-
if (context.headers) {
10-
setContext({
11-
...context,
12-
headers: new HttpHeaders(context.headers),
13-
});
14-
}
10+
if (context.headers) {
11+
setContext({ headers: new HttpHeaders(context.headers) });
12+
}
1513

16-
return forward(operation);
17-
});
18-
};
14+
return forward(operation);
15+
});
16+
}
17+
}

packages/apollo-angular/headers/tests/index.spec.ts

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1+
import { of } from 'rxjs';
12
import { describe, expect, test } from 'vitest';
23
import { HttpHeaders } from '@angular/common/http';
3-
import { ApolloLink, execute, gql, Observable as LinkObservable } from '@apollo/client/core';
4-
import { httpHeaders } from '../src';
4+
import { ApolloClient, ApolloLink, execute, gql, InMemoryCache } from '@apollo/client';
5+
import { HttpHeadersLink } from '../src';
56

67
const query = gql`
78
query heroes {
@@ -13,52 +14,56 @@ const query = gql`
1314
`;
1415
const data = { heroes: [{ name: 'Foo', __typename: 'Hero' }] };
1516

16-
describe('httpHeaders', () => {
17+
const dummyClient = new ApolloClient({ cache: new InMemoryCache(), link: ApolloLink.empty() });
18+
19+
describe('HttpHeadersLink', () => {
1720
test('should turn object into HttpHeaders', () =>
1821
new Promise<void>(done => {
19-
const headersLink = httpHeaders();
22+
const headersLink = new HttpHeadersLink();
2023

2124
const mockLink = new ApolloLink(operation => {
2225
const { headers } = operation.getContext();
2326

2427
expect(headers instanceof HttpHeaders).toBe(true);
2528
expect(headers.get('Authorization')).toBe('Bearer Foo');
2629

27-
return LinkObservable.of({ data });
30+
return of({ data });
2831
});
2932

3033
const link = headersLink.concat(mockLink);
3134

32-
execute(link, {
33-
query,
34-
context: {
35-
headers: {
36-
Authorization: 'Bearer Foo',
35+
execute(
36+
link,
37+
{
38+
query,
39+
context: {
40+
headers: {
41+
Authorization: 'Bearer Foo',
42+
},
3743
},
3844
},
39-
}).subscribe(result => {
45+
{ client: dummyClient },
46+
).subscribe(result => {
4047
expect(result.data).toEqual(data);
4148
done();
4249
});
4350
}));
4451

4552
test('should not set headers when not defined', () =>
4653
new Promise<void>(done => {
47-
const headersLink = httpHeaders();
54+
const headersLink = new HttpHeadersLink();
4855

4956
const mockLink = new ApolloLink(operation => {
5057
const { headers } = operation.getContext();
5158

5259
expect(headers).toBeUndefined();
5360

54-
return LinkObservable.of({ data });
61+
return of({ data });
5562
});
5663

5764
const link = headersLink.concat(mockLink);
5865

59-
execute(link, {
60-
query,
61-
}).subscribe(result => {
66+
execute(link, { query }, { client: dummyClient }).subscribe(result => {
6267
expect(result.data).toEqual(data);
6368
done();
6469
});

packages/apollo-angular/http/src/http-batch-link.ts

Lines changed: 33 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,21 @@
11
import { print } from 'graphql';
2+
import { Observable } from 'rxjs';
23
import { HttpClient, HttpHeaders } from '@angular/common/http';
34
import { Injectable } from '@angular/core';
4-
import {
5-
ApolloLink,
6-
FetchResult,
7-
Observable as LinkObservable,
8-
Operation,
9-
} from '@apollo/client/core';
10-
import { BatchHandler, BatchLink } from '@apollo/client/link/batch';
11-
import { BatchOptions, Body, Context, OperationPrinter, Options, Request } from './types';
5+
import { ApolloLink } from '@apollo/client';
6+
import { BatchLink } from '@apollo/client/link/batch';
7+
import type { HttpLink } from './http-link';
8+
import { Body, Context, OperationPrinter, Request } from './types';
129
import { createHeadersWithClientAwareness, fetch, mergeHeaders, prioritize } from './utils';
1310

11+
export declare namespace HttpBatchLink {
12+
export type Options = {
13+
batchMax?: number;
14+
batchInterval?: number;
15+
batchKey?: (operation: ApolloLink.Operation) => string;
16+
} & HttpLink.Options;
17+
}
18+
1419
export const defaults = {
1520
batchInterval: 10,
1621
batchMax: 10,
@@ -27,9 +32,9 @@ export const defaults = {
2732
*/
2833
export function pick<K extends keyof Omit<typeof defaults, 'batchInterval' | 'batchMax'>>(
2934
context: Context,
30-
options: Options,
35+
options: HttpBatchLink.Options,
3136
key: K,
32-
): ReturnType<typeof prioritize<Context[K] | Options[K] | (typeof defaults)[K]>> {
37+
): ReturnType<typeof prioritize<Context[K] | HttpBatchLink.Options[K] | (typeof defaults)[K]>> {
3338
return prioritize(context[key], options[key], defaults[key]);
3439
}
3540

@@ -41,7 +46,7 @@ export class HttpBatchLinkHandler extends ApolloLink {
4146

4247
constructor(
4348
private readonly httpClient: HttpClient,
44-
private readonly options: BatchOptions,
49+
private readonly options: HttpBatchLink.Options,
4550
) {
4651
super();
4752

@@ -52,8 +57,8 @@ export class HttpBatchLinkHandler extends ApolloLink {
5257
this.print = this.options.operationPrinter;
5358
}
5459

55-
const batchHandler: BatchHandler = (operations: Operation[]) => {
56-
return new LinkObservable((observer: any) => {
60+
const batchHandler: BatchLink.BatchHandler = (operations: ApolloLink.Operation[]) => {
61+
return new Observable((observer: any) => {
5762
const body = this.createBody(operations);
5863
const headers = this.createHeaders(operations);
5964
const { method, uri, withCredentials } = this.createOptions(operations);
@@ -90,7 +95,7 @@ export class HttpBatchLinkHandler extends ApolloLink {
9095

9196
const batchKey =
9297
options.batchKey ||
93-
((operation: Operation) => {
98+
((operation: ApolloLink.Operation) => {
9499
return this.createBatchKey(operation);
95100
});
96101

@@ -103,8 +108,8 @@ export class HttpBatchLinkHandler extends ApolloLink {
103108
}
104109

105110
private createOptions(
106-
operations: Operation[],
107-
): Required<Pick<Options, 'method' | 'uri' | 'withCredentials'>> {
111+
operations: ApolloLink.Operation[],
112+
): Required<Pick<HttpBatchLink.Options, 'method' | 'uri' | 'withCredentials'>> {
108113
const context: Context = operations[0].getContext();
109114

110115
return {
@@ -114,7 +119,7 @@ export class HttpBatchLinkHandler extends ApolloLink {
114119
};
115120
}
116121

117-
private createBody(operations: Operation[]): Body[] {
122+
private createBody(operations: ApolloLink.Operation[]): Body[] {
118123
return operations.map(operation => {
119124
const includeExtensions = prioritize(
120125
operation.getContext().includeExtensions,
@@ -144,10 +149,11 @@ export class HttpBatchLinkHandler extends ApolloLink {
144149
});
145150
}
146151

147-
private createHeaders(operations: Operation[]): HttpHeaders {
152+
private createHeaders(operations: ApolloLink.Operation[]): HttpHeaders {
148153
return operations.reduce(
149-
(headers: HttpHeaders, operation: Operation) => {
150-
return mergeHeaders(headers, operation.getContext().headers);
154+
(headers: HttpHeaders, operation: ApolloLink.Operation) => {
155+
const { headers: contextHeaders } = operation.getContext();
156+
return contextHeaders ? mergeHeaders(headers, contextHeaders) : headers;
151157
},
152158
createHeadersWithClientAwareness({
153159
headers: this.options.headers,
@@ -156,7 +162,7 @@ export class HttpBatchLinkHandler extends ApolloLink {
156162
);
157163
}
158164

159-
private createBatchKey(operation: Operation): string {
165+
private createBatchKey(operation: ApolloLink.Operation): string {
160166
const context: Context & { skipBatching?: boolean } = operation.getContext();
161167

162168
if (context.skipBatching) {
@@ -175,8 +181,11 @@ export class HttpBatchLinkHandler extends ApolloLink {
175181
return prioritize(context.uri, this.options.uri, '') + opts;
176182
}
177183

178-
public request(op: Operation): LinkObservable<FetchResult> | null {
179-
return this.batcher.request(op);
184+
public request(
185+
op: ApolloLink.Operation,
186+
forward: ApolloLink.ForwardFunction,
187+
): Observable<ApolloLink.Result> {
188+
return this.batcher.request(op, forward);
180189
}
181190
}
182191

@@ -186,7 +195,7 @@ export class HttpBatchLinkHandler extends ApolloLink {
186195
export class HttpBatchLink {
187196
constructor(private readonly httpClient: HttpClient) {}
188197

189-
public create(options: BatchOptions): HttpBatchLinkHandler {
198+
public create(options: HttpBatchLink.Options): HttpBatchLinkHandler {
190199
return new HttpBatchLinkHandler(this.httpClient, options);
191200
}
192201
}

0 commit comments

Comments
 (0)