Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
94 commits
Select commit Hold shift + click to select a range
34ab338
WIP apollo-client v4
PowerKiKi Mar 6, 2025
7931818
Use PR preview release
PowerKiKi Mar 7, 2025
3f7ccc4
Prettier
PowerKiKi Mar 7, 2025
94d347e
Update to latest alpha
PowerKiKi Mar 11, 2025
d1a1096
Update to stable 4.0 release
jerelmiller Aug 26, 2025
52ba12c
Require recent versions of graphql, rxjs and apollo client
jerelmiller Aug 26, 2025
57796d9
Run codemod
jerelmiller Aug 26, 2025
e4724d0
Run codemod on demo
jerelmiller Aug 26, 2025
85018f8
Update buildOperationForLink to use updated types/signature
jerelmiller Aug 26, 2025
a690513
Add helper to execute with a client context
jerelmiller Aug 26, 2025
ab98b8c
Adjust opration spec to use util
jerelmiller Aug 26, 2025
aa4fd80
Remove generic on ApolloClient.Options type
jerelmiller Aug 26, 2025
bd2cfa6
Update types to be compatible with v4 types
jerelmiller Aug 26, 2025
eada747
Fix call to execute in headers/index.spec
jerelmiller Aug 26, 2025
197cee7
Update QueryRef to be compatible with v4
jerelmiller Aug 26, 2025
5d8471b
Update queryRef spec
jerelmiller Aug 26, 2025
2d33fd7
Fix multiple subscribers test
jerelmiller Aug 26, 2025
2aaed54
Remove fromObservableQuery helper
jerelmiller Aug 26, 2025
decf8cf
Fix queryRef tests
jerelmiller Aug 26, 2025
83607b9
Use MockLink instead of mockSingleLink
jerelmiller Aug 26, 2025
d5fe5f2
Update Apollo class with updated option types
jerelmiller Aug 26, 2025
4b0e5ff
Remove unneeded generics in testing module
jerelmiller Aug 26, 2025
1f670f8
Adjust types to use DefaultContext
jerelmiller Aug 26, 2025
39f7be8
Adjust some types for HttpLink
jerelmiller Aug 26, 2025
2d66be6
Remove some generics
jerelmiller Aug 26, 2025
2633f3a
Update HttpLink/BatchHttpLink tests
jerelmiller Aug 26, 2025
41c777c
Extract helper execute function
jerelmiller Aug 26, 2025
11e3094
Remove unneeded cast
jerelmiller Aug 26, 2025
d677d75
Fix some operation type variables
jerelmiller Aug 26, 2025
0588682
Update utils with updated types
jerelmiller Aug 26, 2025
1b30398
Add reobserve to QueryRef
jerelmiller Aug 26, 2025
341e8c0
Use SubscribeResult
jerelmiller Aug 26, 2025
8f6e46f
Update persisted queries link
jerelmiller Aug 26, 2025
7cc0753
Update TestOperation
jerelmiller Aug 26, 2025
40776a8
Update demo code
jerelmiller Aug 26, 2025
a61071d
Formatting
jerelmiller Aug 26, 2025
961112a
Formatting
jerelmiller Aug 26, 2025
4c61e4b
Fix flush for subscriptions
jerelmiller Aug 26, 2025
451acd7
Update assertions against operationName in batch link
jerelmiller Aug 26, 2025
15952f2
Fix operation names to make test pass
jerelmiller Aug 26, 2025
2b214d8
Add typename when comparing document nodes
jerelmiller Aug 26, 2025
4472c10
Add __typename to test response
jerelmiller Aug 26, 2025
828821b
Add typename when creating request for execute
jerelmiller Aug 26, 2025
8477c13
Apply prettier
PowerKiKi Sep 5, 2025
1e8ed69
Compat with no prefix component
PowerKiKi Sep 5, 2025
06ae077
All import from `@apollo/client/core` to avoid react/rehackt errors
PowerKiKi Sep 5, 2025
8bc3336
Merge remote-tracking branch 'origin/master' into jerel/apollo-client-v4
PowerKiKi Sep 5, 2025
0133946
Default TData to unknown and add consistent order
jerelmiller Sep 18, 2025
8c84b90
Rename generics to TData and TVariables
jerelmiller Sep 18, 2025
a38dab8
Export HttpHeadersLink and deprecate httpHeaders function
jerelmiller Sep 18, 2025
86663a5
Remove unneeded spread
jerelmiller Sep 18, 2025
d640d1c
Use class in tests
jerelmiller Sep 18, 2025
dec4e1c
Rework HttpLink options by moving into namespace
jerelmiller Sep 18, 2025
a4c5ca5
Fix issue with type for createHeaders
jerelmiller Sep 18, 2025
5a81fdb
Add ObservableStream helper
jerelmiller Sep 18, 2025
567e0ce
Use ObservableStream to test refetch
jerelmiller Sep 18, 2025
50232ff
Add toEmitAnything matcher
jerelmiller Sep 18, 2025
4dbe718
Move toEmitAnything to own file
jerelmiller Sep 18, 2025
a299082
Use toEmitAnything
jerelmiller Sep 18, 2025
fe50eaa
Update another test to ObservableStream
jerelmiller Sep 18, 2025
a040605
Update another failing test to ObservableStream
jerelmiller Sep 18, 2025
498ed50
Remove tests for useInitialLoading
jerelmiller Sep 18, 2025
839e311
Fix ts issue with mocks
jerelmiller Sep 18, 2025
07211ec
Combine parameters in Query class
jerelmiller Sep 18, 2025
4564cb4
Combine variables into options object for Mutation
jerelmiller Sep 18, 2025
847f591
Combine variables into options for Subscription
jerelmiller Sep 18, 2025
1e2e8a9
Move options types into namespaces
jerelmiller Sep 19, 2025
e740baa
Move useZone option into subscription options
jerelmiller Sep 19, 2025
a594a3b
Add result types to namespace
jerelmiller Sep 19, 2025
65d695c
Update useMutationLoading
jerelmiller Sep 19, 2025
1623a2d
Use ObservableStream in another test
jerelmiller Sep 19, 2025
45c011b
Fix wrong loading emit for useMutationLoading
jerelmiller Sep 19, 2025
5a2e6a3
Update another test to ObservableStream
jerelmiller Sep 19, 2025
9e46253
Adjust test for useZone
jerelmiller Sep 19, 2025
5268a7d
Fix some return types for accuracy
jerelmiller Sep 19, 2025
2d8a7dc
Use ApolloClient as namespace for watchFragment
jerelmiller Sep 19, 2025
76814cd
Import from @apollo/client instead of /core
jerelmiller Sep 19, 2025
d7b9a77
Use @apollo/client in schematics
jerelmiller Sep 19, 2025
a15d211
Formatting
jerelmiller Sep 19, 2025
2f5146c
Fix options type in HttpBatchLink
jerelmiller Sep 19, 2025
e1880f3
Remove outdated tsdoc
jerelmiller Sep 19, 2025
ca961db
Use original order of generic args for deprecated WatchQueryOptions
jerelmiller Sep 19, 2025
6bce3e9
Add license
jerelmiller Sep 19, 2025
be2a827
Just check type when asserting takeNext
jerelmiller Sep 19, 2025
891f736
Use ObservableStream in tests
jerelmiller Sep 19, 2025
d902a1c
Document new default of `notifyOnNetworkStatusChange`
PowerKiKi Sep 19, 2025
bdc93df
Drop `httpHeaders` entirely
PowerKiKi Sep 19, 2025
b9c62a5
Document combined parameters of `Query`, `Mutation` and `Subscription…
PowerKiKi Sep 19, 2025
8c0b7f0
Document move `useZone` option into subscription options
PowerKiKi Sep 19, 2025
7e8fd30
Update doc to import from '@apollo/client'
PowerKiKi Sep 19, 2025
aaa54c9
Prettier
PowerKiKi Sep 19, 2025
44ed9a5
Document namespaced types
PowerKiKi Sep 19, 2025
5239c45
Better flow of types
PowerKiKi Sep 19, 2025
226a963
chore(dependencies): updated changesets for modified dependencies
github-actions[bot] Sep 19, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/apollo-angular-2355-dependencies.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"apollo-angular": patch
---
dependencies updates:
- Updated dependency [`@apollo/client@^4.0.1` ↗︎](https://www.npmjs.com/package/@apollo/client/v/4.0.1) (from `^3.13.1`, in `peerDependencies`)
- 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`)
56 changes: 56 additions & 0 deletions .changeset/chatty-cherries-drum.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
---
'apollo-angular': major
---

Namespaced types

Before:

```ts
import type {
Options,
BatchOptions
} from 'apollo-angular/http';

import type {
MutationOptionsAlone,
QueryOptionsAlone,
SubscriptionOptionsAlone,
WatchQueryOptions,
WatchQueryOptionsAlone,
} from 'apollo-angular';

type AllTypes =
| Options
| BatchOptions
| MutationOptionsAlone
| QueryOptionsAlone
| SubscriptionOptionsAlone
| WatchQueryOptions
| WatchQueryOptionsAlone;
```

After:

```ts
import type {
HttpBatchLink,
HttpLink
} from 'apollo-angular/http';

import type {
Apollo,
Mutation,
Query,
Subscription,
} from 'apollo-angular';

type AllTypes =
| HttpLink.Options
| HttpBatchLink.Options
| Mutation.MutateOptions
| Query.FetchOptions
| Subscription.SubscribeOptions
| Apollo.WatchQueryOptions
| Query.WatchOptions;
```
12 changes: 12 additions & 0 deletions .changeset/funny-trainers-look.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
'apollo-angular': major
---

`httpHeaders` is a class

Migrate your code like so:

```diff
- const link = httpHeaders();
+ const link = new HttpHeadersLink();
```
11 changes: 11 additions & 0 deletions .changeset/giant-clouds-shout.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
'apollo-angular': major
---

Move `useZone` option into subscription options


```diff
- const obs = apollo.subscribe(options, { useZone: false });
+ const obs = apollo.subscribe({ ...options, useZone: false });
```
26 changes: 26 additions & 0 deletions .changeset/tough-masks-search.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
---
'apollo-angular': major
---

Combined parameters of `Query`, `Mutation` and `Subscription` classes generated via codegen

Migrate your code like so:

```diff
class MyComponent {
myQuery = inject(MyQuery);
myMutation = inject(MyMutation);
mySubscription = inject(MySubscription);

constructor() {
- myQuery.watch({ myVariable: 'foo' }, { fetchPolicy: 'cache-and-network' });
+ myQuery.watch({ variables: { myVariable: 'foo' }, fetchPolicy: 'cache-and-network' })

- myMutation.mutate({ myVariable: 'foo' }, { errorPolicy: 'ignore' });
+ myMutation.mutate({ variables: { myVariable: 'foo' }, errorPolicy: 'ignore' });

- mySubscription.subscribe({ myVariable: 'foo' }, { fetchPolicy: 'network-only' });
+ mySubscription.subscribe({ variables: { myVariable: 'foo' }, fetchPolicy: 'network-only' });
}
}
```
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
"@angular/platform-browser-dynamic": "^18.0.0",
"@angular/platform-server": "^18.0.0",
"@angular/router": "^18.0.0",
"@apollo/client": "^3.13.1",
"@apollo/client": "4.0.1",
"@babel/core": "^7.24.6",
"@babel/preset-env": "^7.24.6",
"@changesets/changelog-github": "^0.5.0",
Expand Down
27 changes: 13 additions & 14 deletions packages/apollo-angular/headers/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
import { HttpHeaders } from '@angular/common/http';
import { ApolloLink, NextLink, Operation } from '@apollo/client/core';
import { ApolloLink } from '@apollo/client';

export const httpHeaders = () => {
return new ApolloLink((operation: Operation, forward: NextLink) => {
const { getContext, setContext } = operation;
const context = getContext();
export class HttpHeadersLink extends ApolloLink {
constructor() {
super((operation, forward) => {
const { getContext, setContext } = operation;
const context = getContext();

if (context.headers) {
setContext({
...context,
headers: new HttpHeaders(context.headers),
});
}
if (context.headers) {
setContext({ headers: new HttpHeaders(context.headers) });
}

return forward(operation);
});
};
return forward(operation);
});
}
}
37 changes: 21 additions & 16 deletions packages/apollo-angular/headers/tests/index.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { of } from 'rxjs';
import { describe, expect, test } from 'vitest';
import { HttpHeaders } from '@angular/common/http';
import { ApolloLink, execute, gql, Observable as LinkObservable } from '@apollo/client/core';
import { httpHeaders } from '../src';
import { ApolloClient, ApolloLink, execute, gql, InMemoryCache } from '@apollo/client';
import { HttpHeadersLink } from '../src';

const query = gql`
query heroes {
Expand All @@ -13,52 +14,56 @@ const query = gql`
`;
const data = { heroes: [{ name: 'Foo', __typename: 'Hero' }] };

describe('httpHeaders', () => {
const dummyClient = new ApolloClient({ cache: new InMemoryCache(), link: ApolloLink.empty() });

describe('HttpHeadersLink', () => {
test('should turn object into HttpHeaders', () =>
new Promise<void>(done => {
const headersLink = httpHeaders();
const headersLink = new HttpHeadersLink();

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

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

return LinkObservable.of({ data });
return of({ data });
});

const link = headersLink.concat(mockLink);

execute(link, {
query,
context: {
headers: {
Authorization: 'Bearer Foo',
execute(
link,
{
query,
context: {
headers: {
Authorization: 'Bearer Foo',
},
},
},
}).subscribe(result => {
{ client: dummyClient },
).subscribe(result => {
expect(result.data).toEqual(data);
done();
});
}));

test('should not set headers when not defined', () =>
new Promise<void>(done => {
const headersLink = httpHeaders();
const headersLink = new HttpHeadersLink();

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

expect(headers).toBeUndefined();

return LinkObservable.of({ data });
return of({ data });
});

const link = headersLink.concat(mockLink);

execute(link, {
query,
}).subscribe(result => {
execute(link, { query }, { client: dummyClient }).subscribe(result => {
expect(result.data).toEqual(data);
done();
});
Expand Down
57 changes: 33 additions & 24 deletions packages/apollo-angular/http/src/http-batch-link.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
import { print } from 'graphql';
import { Observable } from 'rxjs';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';
import {
ApolloLink,
FetchResult,
Observable as LinkObservable,
Operation,
} from '@apollo/client/core';
import { BatchHandler, BatchLink } from '@apollo/client/link/batch';
import { BatchOptions, Body, Context, OperationPrinter, Options, Request } from './types';
import { ApolloLink } from '@apollo/client';
import { BatchLink } from '@apollo/client/link/batch';
import type { HttpLink } from './http-link';
import { Body, Context, OperationPrinter, Request } from './types';
import { createHeadersWithClientAwareness, fetch, mergeHeaders, prioritize } from './utils';

export declare namespace HttpBatchLink {
export type Options = {
batchMax?: number;
batchInterval?: number;
batchKey?: (operation: ApolloLink.Operation) => string;
} & HttpLink.Options;
}

export const defaults = {
batchInterval: 10,
batchMax: 10,
Expand All @@ -27,9 +32,9 @@ export const defaults = {
*/
export function pick<K extends keyof Omit<typeof defaults, 'batchInterval' | 'batchMax'>>(
context: Context,
options: Options,
options: HttpBatchLink.Options,
key: K,
): ReturnType<typeof prioritize<Context[K] | Options[K] | (typeof defaults)[K]>> {
): ReturnType<typeof prioritize<Context[K] | HttpBatchLink.Options[K] | (typeof defaults)[K]>> {
return prioritize(context[key], options[key], defaults[key]);
}

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

constructor(
private readonly httpClient: HttpClient,
private readonly options: BatchOptions,
private readonly options: HttpBatchLink.Options,
) {
super();

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

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

const batchKey =
options.batchKey ||
((operation: Operation) => {
((operation: ApolloLink.Operation) => {
return this.createBatchKey(operation);
});

Expand All @@ -103,8 +108,8 @@ export class HttpBatchLinkHandler extends ApolloLink {
}

private createOptions(
operations: Operation[],
): Required<Pick<Options, 'method' | 'uri' | 'withCredentials'>> {
operations: ApolloLink.Operation[],
): Required<Pick<HttpBatchLink.Options, 'method' | 'uri' | 'withCredentials'>> {
const context: Context = operations[0].getContext();

return {
Expand All @@ -114,7 +119,7 @@ export class HttpBatchLinkHandler extends ApolloLink {
};
}

private createBody(operations: Operation[]): Body[] {
private createBody(operations: ApolloLink.Operation[]): Body[] {
return operations.map(operation => {
const includeExtensions = prioritize(
operation.getContext().includeExtensions,
Expand Down Expand Up @@ -144,10 +149,11 @@ export class HttpBatchLinkHandler extends ApolloLink {
});
}

private createHeaders(operations: Operation[]): HttpHeaders {
private createHeaders(operations: ApolloLink.Operation[]): HttpHeaders {
return operations.reduce(
(headers: HttpHeaders, operation: Operation) => {
return mergeHeaders(headers, operation.getContext().headers);
(headers: HttpHeaders, operation: ApolloLink.Operation) => {
const { headers: contextHeaders } = operation.getContext();
return contextHeaders ? mergeHeaders(headers, contextHeaders) : headers;
},
createHeadersWithClientAwareness({
headers: this.options.headers,
Expand All @@ -156,7 +162,7 @@ export class HttpBatchLinkHandler extends ApolloLink {
);
}

private createBatchKey(operation: Operation): string {
private createBatchKey(operation: ApolloLink.Operation): string {
const context: Context & { skipBatching?: boolean } = operation.getContext();

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

public request(op: Operation): LinkObservable<FetchResult> | null {
return this.batcher.request(op);
public request(
op: ApolloLink.Operation,
forward: ApolloLink.ForwardFunction,
): Observable<ApolloLink.Result> {
return this.batcher.request(op, forward);
}
}

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

public create(options: BatchOptions): HttpBatchLinkHandler {
public create(options: HttpBatchLink.Options): HttpBatchLinkHandler {
return new HttpBatchLinkHandler(this.httpClient, options);
}
}
Loading