From 34ab338fcc23241114af618c8ab921ae55f839e0 Mon Sep 17 00:00:00 2001 From: Adrien Crivelli Date: Thu, 6 Mar 2025 09:02:43 +0900 Subject: [PATCH 01/97] WIP apollo-client v4 Work in process to migrate to the future apollo-client v4 and its native RxJS support via https://github.com/apollographql/apollo-client/pull/12384 --- .../headers/tests/index.spec.ts | 7 +-- .../http/src/http-batch-link.ts | 12 ++---- packages/apollo-angular/http/src/http-link.ts | 14 +++--- .../http/tests/http-link.spec.ts | 16 ++++--- packages/apollo-angular/src/apollo.ts | 22 ++++------ packages/apollo-angular/src/query-ref.ts | 43 ++----------------- packages/apollo-angular/src/types.ts | 17 +------- packages/apollo-angular/src/utils.ts | 33 ++++++-------- .../apollo-angular/testing/src/backend.ts | 8 ++-- packages/apollo-angular/testing/src/module.ts | 6 +-- .../apollo-angular/tests/QueryRef.spec.ts | 2 +- .../app/pages/movie/movie-page.component.ts | 2 +- .../app/pages/movies/movies-page.component.ts | 2 +- 13 files changed, 56 insertions(+), 128 deletions(-) diff --git a/packages/apollo-angular/headers/tests/index.spec.ts b/packages/apollo-angular/headers/tests/index.spec.ts index 759f93591..30f0eaee1 100644 --- a/packages/apollo-angular/headers/tests/index.spec.ts +++ b/packages/apollo-angular/headers/tests/index.spec.ts @@ -1,6 +1,7 @@ +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 { ApolloLink, execute, gql } from '@apollo/client/core'; import { httpHeaders } from '../src'; const query = gql` @@ -24,7 +25,7 @@ describe('httpHeaders', () => { 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); @@ -51,7 +52,7 @@ describe('httpHeaders', () => { expect(headers).toBeUndefined(); - return LinkObservable.of({ data }); + return of({ data }); }); const link = headersLink.concat(mockLink); diff --git a/packages/apollo-angular/http/src/http-batch-link.ts b/packages/apollo-angular/http/src/http-batch-link.ts index 93a70e434..6663f698a 100644 --- a/packages/apollo-angular/http/src/http-batch-link.ts +++ b/packages/apollo-angular/http/src/http-batch-link.ts @@ -1,12 +1,8 @@ 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 { ApolloLink, FetchResult, Operation } from '@apollo/client/core'; import { BatchHandler, BatchLink } from '@apollo/client/link/batch'; import { BatchOptions, Body, Context, OperationPrinter, Options, Request } from './types'; import { createHeadersWithClientAwareness, fetch, mergeHeaders, prioritize } from './utils'; @@ -53,7 +49,7 @@ export class HttpBatchLinkHandler extends ApolloLink { } const batchHandler: BatchHandler = (operations: Operation[]) => { - return new LinkObservable((observer: any) => { + return new Observable((observer: any) => { const body = this.createBody(operations); const headers = this.createHeaders(operations); const { method, uri, withCredentials } = this.createOptions(operations); @@ -175,7 +171,7 @@ export class HttpBatchLinkHandler extends ApolloLink { return prioritize(context.uri, this.options.uri, '') + opts; } - public request(op: Operation): LinkObservable | null { + public request(op: Operation): Observable | null { return this.batcher.request(op); } } diff --git a/packages/apollo-angular/http/src/http-link.ts b/packages/apollo-angular/http/src/http-link.ts index 7d40d281f..9fe1de4e9 100644 --- a/packages/apollo-angular/http/src/http-link.ts +++ b/packages/apollo-angular/http/src/http-link.ts @@ -1,19 +1,15 @@ import { print } from 'graphql'; +import { Observable } from 'rxjs'; import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; -import { - ApolloLink, - FetchResult, - Observable as LinkObservable, - Operation, -} from '@apollo/client/core'; +import { ApolloLink, FetchResult, Operation } from '@apollo/client/core'; import { pick } from './http-batch-link'; import { Body, Context, OperationPrinter, Options, Request } from './types'; import { createHeadersWithClientAwareness, fetch, mergeHeaders } from './utils'; // XXX find a better name for it export class HttpLinkHandler extends ApolloLink { - public requester: (operation: Operation) => LinkObservable | null; + public requester: (operation: Operation) => Observable | null; private print: OperationPrinter = print; constructor( @@ -27,7 +23,7 @@ export class HttpLinkHandler extends ApolloLink { } this.requester = (operation: Operation) => - new LinkObservable((observer: any) => { + new Observable((observer: any) => { const context: Context = operation.getContext(); let method = pick(context, this.options, 'method'); @@ -89,7 +85,7 @@ export class HttpLinkHandler extends ApolloLink { }); } - public request(op: Operation): LinkObservable | null { + public request(op: Operation): Observable | null { return this.requester(op); } } diff --git a/packages/apollo-angular/http/tests/http-link.spec.ts b/packages/apollo-angular/http/tests/http-link.spec.ts index c0d84ac3c..387e7326d 100644 --- a/packages/apollo-angular/http/tests/http-link.spec.ts +++ b/packages/apollo-angular/http/tests/http-link.spec.ts @@ -1,5 +1,5 @@ import { print, stripIgnoredCharacters } from 'graphql'; -import { mergeMap } from 'rxjs/operators'; +import { map, mergeMap } from 'rxjs/operators'; import { afterEach, beforeEach, describe, expect, test } from 'vitest'; import { HttpHeaders, provideHttpClient } from '@angular/common/http'; import { HttpTestingController, provideHttpClientTesting } from '@angular/common/http/testing'; @@ -512,14 +512,16 @@ describe('HttpLink', () => { test('should set response in context', () => new Promise(done => { const afterware = new ApolloLink((op, forward) => { - return forward(op).map(response => { - const context = op.getContext(); + return forward(op).pipe( + map(response => { + const context = op.getContext(); - expect(context.response).toBeDefined(); - done(); + expect(context.response).toBeDefined(); + done(); - return response; - }); + return response; + }), + ); }); const link = afterware.concat( httpLink.create({ diff --git a/packages/apollo-angular/src/apollo.ts b/packages/apollo-angular/src/apollo.ts index 63b23bcac..a439332f9 100644 --- a/packages/apollo-angular/src/apollo.ts +++ b/packages/apollo-angular/src/apollo.ts @@ -1,4 +1,4 @@ -import { from, Observable } from 'rxjs'; +import { Observable } from 'rxjs'; import { Inject, Injectable, NgZone, Optional } from '@angular/core'; import type { ApolloClientOptions, @@ -23,10 +23,9 @@ import type { WatchFragmentOptions, WatchQueryOptions, } from './types'; -import { fixObservable, fromPromise, useMutationLoading, wrapWithZone } from './utils'; +import { fromLazyPromise, useMutationLoading, wrapWithZone } from './utils'; export class ApolloBase { - private useInitialLoading: boolean; private useMutationLoading: boolean; constructor( @@ -34,7 +33,6 @@ export class ApolloBase { protected readonly flags?: Flags, protected _client?: ApolloClient, ) { - this.useInitialLoading = flags?.useInitialLoading ?? false; this.useMutationLoading = flags?.useMutationLoading ?? false; } @@ -46,24 +44,22 @@ export class ApolloBase { ...options, }) as ObservableQuery, this.ngZone, - { - useInitialLoading: this.useInitialLoading, - ...options, - }, ); } public query( options: QueryOptions, ): Observable> { - return fromPromise>(() => this.ensureClient().query({ ...options })); + return fromLazyPromise>(() => + this.ensureClient().query({ ...options }), + ); } public mutate( options: MutationOptions, ): Observable> { return useMutationLoading( - fromPromise(() => this.ensureClient().mutate({ ...options })), + fromLazyPromise(() => this.ensureClient().mutate({ ...options })), options.useMutationLoading ?? this.useMutationLoading, ); } @@ -75,9 +71,7 @@ export class ApolloBase { options: WatchFragmentOptions, extra?: ExtraSubscriptionOptions, ): Observable> { - const obs = from( - fixObservable(this.ensureClient().watchFragment({ ...options })), - ); + const obs = this.ensureClient().watchFragment({ ...options }); return extra && extra.useZone !== true ? obs : wrapWithZone(obs, this.ngZone); } @@ -86,7 +80,7 @@ export class ApolloBase { options: SubscriptionOptions, extra?: ExtraSubscriptionOptions, ): Observable> { - const obs = from(fixObservable(this.ensureClient().subscribe({ ...options }))); + const obs = this.ensureClient().subscribe({ ...options }); return extra && extra.useZone !== true ? obs : wrapWithZone(obs, this.ngZone); } diff --git a/packages/apollo-angular/src/query-ref.ts b/packages/apollo-angular/src/query-ref.ts index 4d4fb52b5..67504666f 100644 --- a/packages/apollo-angular/src/query-ref.ts +++ b/packages/apollo-angular/src/query-ref.ts @@ -1,4 +1,4 @@ -import { from, Observable } from 'rxjs'; +import { Observable } from 'rxjs'; import { NgZone } from '@angular/core'; import type { ApolloQueryResult, @@ -10,38 +10,8 @@ import type { TypedDocumentNode, Unmasked, } from '@apollo/client/core'; -import { NetworkStatus } from '@apollo/client/core'; -import { EmptyObject, WatchQueryOptions } from './types'; -import { fixObservable, wrapWithZone } from './utils'; - -function useInitialLoading(obsQuery: ObservableQuery) { - return function useInitialLoadingOperator(source: Observable): Observable { - return new Observable(function useInitialLoadingSubscription(subscriber) { - const currentResult = obsQuery.getCurrentResult(); - const { loading, errors, error, partial, data } = currentResult; - const { partialRefetch, fetchPolicy } = obsQuery.options; - - const hasError = errors || error; - - if ( - partialRefetch && - partial && - (!data || Object.keys(data).length === 0) && - fetchPolicy !== 'cache-only' && - !loading && - !hasError - ) { - subscriber.next({ - ...currentResult, - loading: true, - networkStatus: NetworkStatus.loading, - } as any); - } - - return source.subscribe(subscriber); - }); - }; -} +import { EmptyObject } from './types'; +import { fromObservableQuery, wrapWithZone } from './utils'; export type QueryRefFromDocument = T extends TypedDocumentNode ? QueryRef : never; @@ -53,13 +23,8 @@ export class QueryRef, ngZone: NgZone, - options: WatchQueryOptions, ) { - const wrapped = wrapWithZone(from(fixObservable(this.obsQuery)), ngZone); - - this.valueChanges = options.useInitialLoading - ? wrapped.pipe(useInitialLoading(this.obsQuery)) - : wrapped; + this.valueChanges = wrapWithZone(fromObservableQuery(this.obsQuery), ngZone); this.queryId = this.obsQuery.queryId; } diff --git a/packages/apollo-angular/src/types.ts b/packages/apollo-angular/src/types.ts index 1259f49a2..972d4605f 100644 --- a/packages/apollo-angular/src/types.ts +++ b/packages/apollo-angular/src/types.ts @@ -44,15 +44,7 @@ export interface SubscriptionOptionsAlone extends Omit, 'query' | 'variables'> {} export interface WatchQueryOptions - extends CoreWatchQueryOptions { - /** - * Observable starts with `{ loading: true }`. - * There's a big chance the next major version will enable that by default. - * - * Disabled by default - */ - useInitialLoading?: boolean; -} + extends CoreWatchQueryOptions {} export interface MutationOptions extends CoreMutationOptions { @@ -71,13 +63,6 @@ export interface WatchFragmentOptions export type NamedOptions = Record>; export type Flags = { - /** - * Observable starts with `{ loading: true }`. - * There's a big chance the next major version will enable that by default. - * - * Disabled by default - */ - useInitialLoading?: boolean; /** * Observable starts with `{ loading: true }`. * diff --git a/packages/apollo-angular/src/utils.ts b/packages/apollo-angular/src/utils.ts index 02f21136e..6c5ebb0e1 100644 --- a/packages/apollo-angular/src/utils.ts +++ b/packages/apollo-angular/src/utils.ts @@ -1,16 +1,13 @@ -import type { SchedulerAction, SchedulerLike, Subscription } from 'rxjs'; -import { Observable, observable, queueScheduler } from 'rxjs'; +import { Observable, queueScheduler, SchedulerAction, SchedulerLike, Subscription } from 'rxjs'; import { map, observeOn, startWith } from 'rxjs/operators'; import { NgZone } from '@angular/core'; -import type { - Observable as AObservable, - ApolloQueryResult, - FetchResult, - ObservableQuery, -} from '@apollo/client/core'; +import type { ApolloQueryResult, FetchResult, ObservableQuery } from '@apollo/client/core'; import { MutationResult } from './types'; -export function fromPromise(promiseFn: () => Promise): Observable { +/** + * Like RxJS's `fromPromise()`, but starts the promise only when the observable is subscribed to. + */ +export function fromLazyPromise(promiseFn: () => Promise): Observable { return new Observable(subscriber => { promiseFn().then( result => { @@ -54,7 +51,7 @@ export function useMutationLoading(source: Observable>, enable export class ZoneScheduler implements SchedulerLike { constructor(private readonly zone: NgZone) {} - public now = Date.now ? Date.now : () => +new Date(); + public readonly now = Date.now; public schedule( work: (this: SchedulerAction, state?: T) => void, @@ -65,16 +62,12 @@ export class ZoneScheduler implements SchedulerLike { } } -// XXX: Apollo's QueryObservable is not compatible with RxJS -// TODO: remove it in one of future releases -// https://github.com/ReactiveX/rxjs/blob/9fb0ce9e09c865920cf37915cc675e3b3a75050b/src/internal/util/subscribeTo.ts#L32 -export function fixObservable(obs: ObservableQuery): Observable>; -export function fixObservable(obs: AObservable): Observable; -export function fixObservable( - obs: AObservable | ObservableQuery, -): Observable> | Observable { - (obs as any)[observable] = () => obs; - return obs as any; +export function fromObservableQuery( + obsQuery: ObservableQuery, +): Observable> { + return new Observable(subscriber => { + return obsQuery.subscribe(subscriber); + }); } export function wrapWithZone(obs: Observable, ngZone: NgZone): Observable { diff --git a/packages/apollo-angular/testing/src/backend.ts b/packages/apollo-angular/testing/src/backend.ts index 245aadc08..908b89dc3 100644 --- a/packages/apollo-angular/testing/src/backend.ts +++ b/packages/apollo-angular/testing/src/backend.ts @@ -1,7 +1,7 @@ import { DocumentNode, print } from 'graphql'; -import { Observer } from 'rxjs'; +import { Observable, Observer } from 'rxjs'; import { Injectable } from '@angular/core'; -import { FetchResult, Observable as LinkObservable } from '@apollo/client/core'; +import { FetchResult } from '@apollo/client/core'; import { ApolloTestingController, MatchOperation } from './controller'; import { Operation, TestOperation } from './operation'; @@ -23,8 +23,8 @@ export class ApolloTestingBackend implements ApolloTestingController { /** * Handle an incoming operation by queueing it in the list of open operations. */ - public handle(op: Operation): LinkObservable { - return new LinkObservable((observer: Observer) => { + public handle(op: Operation): Observable { + return new Observable((observer: Observer) => { const testOp = new TestOperation(op, observer); this.open.push(testOp); }); diff --git a/packages/apollo-angular/testing/src/module.ts b/packages/apollo-angular/testing/src/module.ts index f5b3a3b53..f7d9de163 100644 --- a/packages/apollo-angular/testing/src/module.ts +++ b/packages/apollo-angular/testing/src/module.ts @@ -55,11 +55,7 @@ export class ApolloTestingModuleCore { return { connectToDevTools: false, link: new ApolloLink(operation => backend.handle(addClient(name, operation))), - cache: - c || - new InMemoryCache({ - addTypename: false, - }), + cache: c || new InMemoryCache(), }; } diff --git a/packages/apollo-angular/tests/QueryRef.spec.ts b/packages/apollo-angular/tests/QueryRef.spec.ts index ba154f59f..b84d47223 100644 --- a/packages/apollo-angular/tests/QueryRef.spec.ts +++ b/packages/apollo-angular/tests/QueryRef.spec.ts @@ -59,7 +59,7 @@ describe('QueryRef', () => { client = createClient(mockedLink); obsQuery = client.watchQuery(heroesOperation); - queryRef = new QueryRef(obsQuery, ngZone, {} as any); + queryRef = new QueryRef(obsQuery, ngZone); }); test('should listen to changes', () => diff --git a/packages/demo/src/app/pages/movie/movie-page.component.ts b/packages/demo/src/app/pages/movie/movie-page.component.ts index 59c7c7291..d95842eab 100644 --- a/packages/demo/src/app/pages/movie/movie-page.component.ts +++ b/packages/demo/src/app/pages/movie/movie-page.component.ts @@ -74,6 +74,6 @@ export class MoviePageComponent implements OnInit { id: this.route.snapshot.paramMap.get('id')!, }, }) - .valueChanges.pipe(map(result => result.data.film)); + .valueChanges.pipe(map(result => result.data!.film)); } } diff --git a/packages/demo/src/app/pages/movies/movies-page.component.ts b/packages/demo/src/app/pages/movies/movies-page.component.ts index 86bb00e83..532bee1ff 100644 --- a/packages/demo/src/app/pages/movies/movies-page.component.ts +++ b/packages/demo/src/app/pages/movies/movies-page.component.ts @@ -56,6 +56,6 @@ export class MoviesPageComponent implements OnInit { } `, }) - .valueChanges.pipe(map(result => result.data.allFilms.films)) as any; + .valueChanges.pipe(map(result => result.data!.allFilms.films)) as any; } } From 79318185dc76997edf58fa758a4d28ed0b7cdbf4 Mon Sep 17 00:00:00 2001 From: Adrien Crivelli Date: Fri, 7 Mar 2025 10:50:01 +0900 Subject: [PATCH 02/97] Use PR preview release --- package.json | 2 +- .../tests/persisted-queries.spec.ts | 3 +- .../testing/tests/integration.spec.ts | 15 +------ .../testing/tests/module.spec.ts | 6 +-- .../src/pages/docs/caching/configuration.mdx | 1 - .../docs/development-and-testing/testing.mdx | 39 +++++++++---------- yarn.lock | 34 +++------------- 7 files changed, 30 insertions(+), 70 deletions(-) diff --git a/package.json b/package.json index 9e6d32354..613dae59f 100644 --- a/package.json +++ b/package.json @@ -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": "https://pkg.pr.new/@apollo/client@12384", "@babel/core": "^7.24.6", "@babel/preset-env": "^7.24.6", "@changesets/changelog-github": "^0.5.0", diff --git a/packages/apollo-angular/persisted-queries/tests/persisted-queries.spec.ts b/packages/apollo-angular/persisted-queries/tests/persisted-queries.spec.ts index 16f662f44..a3b7045c8 100644 --- a/packages/apollo-angular/persisted-queries/tests/persisted-queries.spec.ts +++ b/packages/apollo-angular/persisted-queries/tests/persisted-queries.spec.ts @@ -1,6 +1,7 @@ import { describe, expect, test, vi } from 'vitest'; -import { ApolloLink, execute, FetchResult, gql, Observable, Operation } from '@apollo/client/core'; +import { ApolloLink, execute, FetchResult, gql, Operation } from '@apollo/client/core'; import { createPersistedQueryLink } from '../src'; +import {Observable} from "rxjs"; const query = gql` query heroes { diff --git a/packages/apollo-angular/testing/tests/integration.spec.ts b/packages/apollo-angular/testing/tests/integration.spec.ts index 4143acc2a..283d21a1b 100644 --- a/packages/apollo-angular/testing/tests/integration.spec.ts +++ b/packages/apollo-angular/testing/tests/integration.spec.ts @@ -1,10 +1,10 @@ import { print } from 'graphql'; import { afterEach, beforeEach, describe, expect, test } from 'vitest'; import { TestBed } from '@angular/core/testing'; -import { gql, InMemoryCache } from '@apollo/client/core'; +import { gql } from '@apollo/client/core'; import { addTypenameToDocument } from '@apollo/client/utilities'; import { Apollo } from '../../src'; -import { APOLLO_TESTING_CACHE, ApolloTestingController, ApolloTestingModule } from '../src'; +import { ApolloTestingController, ApolloTestingModule } from '../src'; describe('Integration', () => { let apollo: Apollo; @@ -171,17 +171,6 @@ describe('Integration', () => { test('it should be able to test with fragments', () => new Promise(done => { - TestBed.resetTestingModule(); - TestBed.configureTestingModule({ - imports: [ApolloTestingModule], - providers: [ - { - provide: APOLLO_TESTING_CACHE, - useValue: new InMemoryCache({ addTypename: true }), - }, - ], - }); - const apollo = TestBed.inject(Apollo); const backend = TestBed.inject(ApolloTestingController); diff --git a/packages/apollo-angular/testing/tests/module.spec.ts b/packages/apollo-angular/testing/tests/module.spec.ts index 6a27345f7..0ff46f824 100644 --- a/packages/apollo-angular/testing/tests/module.spec.ts +++ b/packages/apollo-angular/testing/tests/module.spec.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from 'vitest'; import { TestBed } from '@angular/core/testing'; -import { ApolloReducerConfig, gql, InMemoryCache } from '@apollo/client/core'; +import { gql, InMemoryCache } from '@apollo/client/core'; import { Apollo } from '../../src'; import { APOLLO_TESTING_CACHE, ApolloTestingController, ApolloTestingModule } from '../src'; @@ -12,14 +12,12 @@ describe('ApolloTestingModule', () => { const apollo = TestBed.inject(Apollo); const cache = apollo.client.cache as InMemoryCache; - const config: ApolloReducerConfig = (cache as any).config; expect(cache).toBeInstanceOf(InMemoryCache); - expect(config.addTypename).toBe(false); }); test('should allow to use custom ApolloCache', () => { - const cache = new InMemoryCache({ addTypename: true }); + const cache = new InMemoryCache(); TestBed.configureTestingModule({ imports: [ApolloTestingModule], diff --git a/website/src/pages/docs/caching/configuration.mdx b/website/src/pages/docs/caching/configuration.mdx index 1dcb2a3b6..0da05440e 100644 --- a/website/src/pages/docs/caching/configuration.mdx +++ b/website/src/pages/docs/caching/configuration.mdx @@ -61,7 +61,6 @@ object supports the following fields: | Name | Type | Description | | ----------------------------------- | ------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `addTypename` | boolean | If `true`, the cache automatically adds `__typename` fields to all outgoing queries, removing the need to add them manually.
Default: `true` | | `resultCaching` | boolean | If `true`, the cache returns an identical (`===`) response object for every execution of the same query, as long as the underlying data remains unchanged. This makes it easier to detect changes to a query's result.
Default: `true` | | `possibleTypes` | `{ [supertype: string]: string[] }` | Include this object to define polymorphic relationships between your schema's types. Doing so enables you to look up cached data by interface or by union.
The key for each entry is the `__typename` of an interface or union, and the value is an array of the `__typename`s of the types that either belong to the corresponding union or implement the corresponding interface. | | `typePolicies` | `{ [typename: string]: TypePolicy }` | Include this object to customize the cache's behavior on a type-by-type basis.
The key for each entry is a type's `__typename`. For details, see [`TypePolicy` fields](#typepolicy-fields). | diff --git a/website/src/pages/docs/development-and-testing/testing.mdx b/website/src/pages/docs/development-and-testing/testing.mdx index f12d5f2e2..685e40291 100644 --- a/website/src/pages/docs/development-and-testing/testing.mdx +++ b/website/src/pages/docs/development-and-testing/testing.mdx @@ -292,18 +292,13 @@ test('expect to call clientA', () => { ## Using a custom cache -By default, every ApolloCache is created with these options: - -```json -{ - "addTypename": false -} -``` - -If you would like to change it in the default client, do the following: +A `InMemoryCache` is provided by default. If you would like to change it in the default client, you +can provide the `APOLLO_TESTING_CACHE` token: ```ts -import { APOLLO_TESTING_CACHE } from 'apollo-angular/testing'; +import { APOLLO_TESTING_CACHE, ApolloTestingModule } from 'apollo-angular/testing'; +import { TestBed } from '@angular/core/testing'; +import { InMemoryCache } from '@apollo/client/core'; beforeEach(() => { TestBed.configureTestingModule({ @@ -311,9 +306,9 @@ beforeEach(() => { providers: [ { provide: APOLLO_TESTING_CACHE, - useValue: { - addTypename: true, - }, + useValue: new InMemoryCache({ + // Custom options here... + }), }, ], }); @@ -322,10 +317,12 @@ beforeEach(() => { }); ``` -For named clients: +And for named clients: ```ts -import { APOLLO_TESTING_NAMED_CACHE } from 'apollo-angular/testing'; +import { APOLLO_TESTING_NAMED_CACHE, ApolloTestingModule } from 'apollo-angular/testing'; +import { TestBed } from '@angular/core/testing'; +import { InMemoryCache } from '@apollo/client/core'; beforeEach(() => { TestBed.configureTestingModule({ @@ -334,12 +331,12 @@ beforeEach(() => { { provide: APOLLO_TESTING_NAMED_CACHE, useValue: { - clientA: { - addTypename: true, - }, - clientB: { - addTypename: true, - }, + clientA: new InMemoryCache({ + // Custom options for client A here... + }), + clientB: new InMemoryCache({ + // Custom options for client B here... + }), }, }, ], diff --git a/yarn.lock b/yarn.lock index 73814e014..7933d9461 100644 --- a/yarn.lock +++ b/yarn.lock @@ -264,24 +264,19 @@ dependencies: tslib "^2.3.0" -"@apollo/client@^3.13.1": - version "3.13.1" - resolved "https://registry.yarnpkg.com/@apollo/client/-/client-3.13.1.tgz#c0633c69c5446967b0e517a590595eeea61dd176" - integrity sha512-HaAt62h3jNUXpJ1v5HNgUiCzPP1c5zc2Q/FeTb2cTk/v09YlhoqKKHQFJI7St50VCJ5q8JVIc03I5bRcBrQxsg== +"@apollo/client@https://pkg.pr.new/@apollo/client@12384": + version "3.13.0" + resolved "https://pkg.pr.new/@apollo/client@12384#8fb6746f15541854a956115c6a8610e3da7858d8" dependencies: "@graphql-typed-document-node/core" "^3.1.1" "@wry/caches" "^1.0.0" "@wry/equality" "^0.5.6" "@wry/trie" "^0.5.0" graphql-tag "^2.12.6" - hoist-non-react-statics "^3.3.2" optimism "^0.18.0" - prop-types "^15.7.2" rehackt "^0.1.0" - symbol-observable "^4.0.0" ts-invariant "^0.10.3" tslib "^2.3.0" - zen-observable-ts "^1.2.5" "@asamuzakjp/css-color@^2.8.2": version "2.8.3" @@ -6255,13 +6250,6 @@ heap@^0.2.6: resolved "https://registry.yarnpkg.com/heap/-/heap-0.2.7.tgz#1e6adf711d3f27ce35a81fe3b7bd576c2260a8fc" integrity sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg== -hoist-non-react-statics@^3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" - integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== - dependencies: - react-is "^16.7.0" - hosted-git-info@^7.0.0: version "7.0.2" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-7.0.2.tgz#9b751acac097757667f30114607ef7b661ff4f17" @@ -9787,7 +9775,7 @@ react-fast-compare@^3.0.1: resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.2.tgz#929a97a532304ce9fee4bcae44234f1ce2c21d49" integrity sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ== -react-is@^16.13.1, react-is@^16.7.0: +react-is@^16.13.1: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== @@ -11003,7 +10991,7 @@ svgo@^3.2.0: csso "^5.0.5" picocolors "^1.0.0" -symbol-observable@4.0.0, symbol-observable@^4.0.0: +symbol-observable@4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-4.0.0.tgz#5b425f192279e87f2f9b937ac8540d1984b39205" integrity sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ== @@ -12106,18 +12094,6 @@ yocto-queue@^1.0.0: resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-1.1.1.tgz#fef65ce3ac9f8a32ceac5a634f74e17e5b232110" integrity sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g== -zen-observable-ts@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/zen-observable-ts/-/zen-observable-ts-1.2.5.tgz#6c6d9ea3d3a842812c6e9519209365a122ba8b58" - integrity sha512-QZWQekv6iB72Naeake9hS1KxHlotfRpe+WGNbNx5/ta+R3DNjVO2bswf63gXlWDcs+EMd7XY8HfVQyP1X6T4Zg== - dependencies: - zen-observable "0.8.15" - -zen-observable@0.8.15: - version "0.8.15" - resolved "https://registry.yarnpkg.com/zen-observable/-/zen-observable-0.8.15.tgz#96415c512d8e3ffd920afd3889604e30b9eaac15" - integrity sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ== - zod-validation-error@^1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/zod-validation-error/-/zod-validation-error-1.5.0.tgz#2b355007a1c3b7fb04fa476bfad4e7b3fd5491e3" From 3f7ccc4e701fa56575b3c850b0676f1b6379347f Mon Sep 17 00:00:00 2001 From: Adrien Crivelli Date: Fri, 7 Mar 2025 11:08:59 +0900 Subject: [PATCH 03/97] Prettier --- .../persisted-queries/tests/persisted-queries.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/apollo-angular/persisted-queries/tests/persisted-queries.spec.ts b/packages/apollo-angular/persisted-queries/tests/persisted-queries.spec.ts index a3b7045c8..7e06a7761 100644 --- a/packages/apollo-angular/persisted-queries/tests/persisted-queries.spec.ts +++ b/packages/apollo-angular/persisted-queries/tests/persisted-queries.spec.ts @@ -1,7 +1,7 @@ +import { Observable } from 'rxjs'; import { describe, expect, test, vi } from 'vitest'; import { ApolloLink, execute, FetchResult, gql, Operation } from '@apollo/client/core'; import { createPersistedQueryLink } from '../src'; -import {Observable} from "rxjs"; const query = gql` query heroes { From 94d347ef4db1143178db4915b5e77abebf95e5f3 Mon Sep 17 00:00:00 2001 From: Adrien Crivelli Date: Wed, 12 Mar 2025 08:56:46 +0900 Subject: [PATCH 04/97] Update to latest alpha --- package.json | 2 +- .../testing/tests/integration.spec.ts | 2 ++ yarn.lock | 13 +++++++++++++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 613dae59f..5636142fa 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "@angular/platform-browser-dynamic": "^18.0.0", "@angular/platform-server": "^18.0.0", "@angular/router": "^18.0.0", - "@apollo/client": "https://pkg.pr.new/@apollo/client@12384", + "@apollo/client": "https://pkg.pr.new/@apollo/client@12221", "@babel/core": "^7.24.6", "@babel/preset-env": "^7.24.6", "@changesets/changelog-github": "^0.5.0", diff --git a/packages/apollo-angular/testing/tests/integration.spec.ts b/packages/apollo-angular/testing/tests/integration.spec.ts index 283d21a1b..b4452489b 100644 --- a/packages/apollo-angular/testing/tests/integration.spec.ts +++ b/packages/apollo-angular/testing/tests/integration.spec.ts @@ -11,6 +11,7 @@ describe('Integration', () => { let backend: ApolloTestingController; beforeEach(() => { + TestBed.resetTestingModule(); TestBed.configureTestingModule({ imports: [ApolloTestingModule], }); @@ -131,6 +132,7 @@ describe('Integration', () => { query heroes($first: Int!) { heroes(first: $first) { name + __typename } } `, diff --git a/yarn.lock b/yarn.lock index 7933d9461..cfd8f73b8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -264,6 +264,19 @@ dependencies: tslib "^2.3.0" +"@apollo/client@https://pkg.pr.new/@apollo/client@12221": + version "4.0.0-alpha.0" + resolved "https://pkg.pr.new/@apollo/client@12221#d8a470f1993539909177eba396eb583572382185" + dependencies: + "@graphql-typed-document-node/core" "^3.1.1" + "@wry/caches" "^1.0.0" + "@wry/equality" "^0.5.6" + "@wry/trie" "^0.5.0" + graphql-tag "^2.12.6" + optimism "^0.18.0" + rehackt "^0.1.0" + tslib "^2.3.0" + "@apollo/client@https://pkg.pr.new/@apollo/client@12384": version "3.13.0" resolved "https://pkg.pr.new/@apollo/client@12384#8fb6746f15541854a956115c6a8610e3da7858d8" From d1a1096568f204ee3af05b98cb66317d818fd9c2 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 25 Aug 2025 18:12:48 -0600 Subject: [PATCH 05/97] Update to stable 4.0 release --- package.json | 2 +- yarn.lock | 34 ++++------------------------------ 2 files changed, 5 insertions(+), 31 deletions(-) diff --git a/package.json b/package.json index 5636142fa..630b32411 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "@angular/platform-browser-dynamic": "^18.0.0", "@angular/platform-server": "^18.0.0", "@angular/router": "^18.0.0", - "@apollo/client": "https://pkg.pr.new/@apollo/client@12221", + "@apollo/client": "4.0.1", "@babel/core": "^7.24.6", "@babel/preset-env": "^7.24.6", "@changesets/changelog-github": "^0.5.0", diff --git a/yarn.lock b/yarn.lock index cfd8f73b8..d0f7b1637 100644 --- a/yarn.lock +++ b/yarn.lock @@ -264,22 +264,10 @@ dependencies: tslib "^2.3.0" -"@apollo/client@https://pkg.pr.new/@apollo/client@12221": - version "4.0.0-alpha.0" - resolved "https://pkg.pr.new/@apollo/client@12221#d8a470f1993539909177eba396eb583572382185" - dependencies: - "@graphql-typed-document-node/core" "^3.1.1" - "@wry/caches" "^1.0.0" - "@wry/equality" "^0.5.6" - "@wry/trie" "^0.5.0" - graphql-tag "^2.12.6" - optimism "^0.18.0" - rehackt "^0.1.0" - tslib "^2.3.0" - -"@apollo/client@https://pkg.pr.new/@apollo/client@12384": - version "3.13.0" - resolved "https://pkg.pr.new/@apollo/client@12384#8fb6746f15541854a956115c6a8610e3da7858d8" +"@apollo/client@4.0.1": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@apollo/client/-/client-4.0.1.tgz#00fe65c518de241126b3664307ccb26bc5314abc" + integrity sha512-qBW2d6++wmNeVkYuCfcw9vQi2kG007wdwdohLc+NXs2Ojz3XPiTb4r9gPTAjwAF9JXN9i7WSQ45fdcN9JAom8Q== dependencies: "@graphql-typed-document-node/core" "^3.1.1" "@wry/caches" "^1.0.0" @@ -287,8 +275,6 @@ "@wry/trie" "^0.5.0" graphql-tag "^2.12.6" optimism "^0.18.0" - rehackt "^0.1.0" - ts-invariant "^0.10.3" tslib "^2.3.0" "@asamuzakjp/css-color@^2.8.2": @@ -9929,11 +9915,6 @@ regjsparser@^0.9.1: dependencies: jsesc "~0.5.0" -rehackt@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/rehackt/-/rehackt-0.1.0.tgz#a7c5e289c87345f70da8728a7eb878e5d03c696b" - integrity sha512-7kRDOuLHB87D/JESKxQoRwv4DzbIdwkAGQ7p6QKGdVlY1IZheUnVhlk/4UZlNUVxdAXpyxikE3URsG067ybVzw== - rehype-katex@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/rehype-katex/-/rehype-katex-7.0.0.tgz#f5e9e2825981175a7b0a4d58ed9816c33576dfed" @@ -11239,13 +11220,6 @@ ts-interface-checker@^0.1.9: resolved "https://registry.yarnpkg.com/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz#784fd3d679722bc103b1b4b8030bcddb5db2a699" integrity sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA== -ts-invariant@^0.10.3: - version "0.10.3" - resolved "https://registry.yarnpkg.com/ts-invariant/-/ts-invariant-0.10.3.tgz#3e048ff96e91459ffca01304dbc7f61c1f642f6c" - integrity sha512-uivwYcQaxAucv1CzRp2n/QdYPo4ILf9VXgH19zEIjFx2EJufV16P0JtJVpYHy89DItG6Kwj2oIUjrcK5au+4tQ== - dependencies: - tslib "^2.1.0" - ts-morph@^21.0.0: version "21.0.1" resolved "https://registry.yarnpkg.com/ts-morph/-/ts-morph-21.0.1.tgz#712302a0f6e9dbf1aa8d9cf33a4386c4b18c2006" From 52ba12c97faaea055a4ffe5252f725f5c0f76958 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 25 Aug 2025 18:14:02 -0600 Subject: [PATCH 06/97] Require recent versions of graphql, rxjs and apollo client --- packages/apollo-angular/package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/apollo-angular/package.json b/packages/apollo-angular/package.json index fecb00609..8c99fc344 100644 --- a/packages/apollo-angular/package.json +++ b/packages/apollo-angular/package.json @@ -37,9 +37,9 @@ }, "peerDependencies": { "@angular/core": "^17.0.0 || ^18.0.0 || ^19.0.0", - "@apollo/client": "^3.13.1", - "graphql": "^15.0.0 || ^16.0.0", - "rxjs": "^6.0.0 || ^7.0.0" + "@apollo/client": "^4.0.0", + "graphql": "^16.0.0", + "rxjs": "^7.3.0" }, "dependencies": { "tslib": "^2.6.2" From 57796d9bdae8bed2ea9e8859102e1d5c94a884d8 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 25 Aug 2025 18:23:49 -0600 Subject: [PATCH 07/97] Run codemod --- packages/apollo-angular/headers/src/index.ts | 4 +- .../headers/tests/index.spec.ts | 2 +- .../http/src/http-batch-link.ts | 20 ++++----- packages/apollo-angular/http/src/http-link.ts | 8 ++-- packages/apollo-angular/http/src/types.ts | 6 +-- .../http/tests/http-batch-link.spec.ts | 4 +- .../http/tests/http-link.spec.ts | 2 +- .../apollo-angular/http/tests/ssr.spec.ts | 2 +- .../tests/persisted-queries.spec.ts | 10 ++--- .../install/files/module/graphql.module.ts | 4 +- packages/apollo-angular/src/apollo-module.ts | 4 +- packages/apollo-angular/src/gql.ts | 2 +- packages/apollo-angular/src/mutation.ts | 2 +- packages/apollo-angular/src/query.ts | 4 +- packages/apollo-angular/src/subscription.ts | 4 +- packages/apollo-angular/src/tokens.ts | 4 +- packages/apollo-angular/src/types.ts | 22 ++++------ .../apollo-angular/testing/src/backend.ts | 4 +- packages/apollo-angular/testing/src/module.ts | 9 +--- .../apollo-angular/testing/src/operation.ts | 7 ++-- .../testing/tests/integration.spec.ts | 2 +- .../testing/tests/module.spec.ts | 2 +- .../testing/tests/operation.spec.ts | 8 ++-- .../apollo-angular/testing/tests/utils.ts | 2 +- packages/apollo-angular/tests/Apollo.spec.ts | 4 +- .../apollo-angular/tests/QueryRef.spec.ts | 41 +++++++++++++++++-- .../apollo-angular/tests/integration.spec.ts | 4 +- 27 files changed, 107 insertions(+), 80 deletions(-) diff --git a/packages/apollo-angular/headers/src/index.ts b/packages/apollo-angular/headers/src/index.ts index f2ed5f233..2ef2debe4 100644 --- a/packages/apollo-angular/headers/src/index.ts +++ b/packages/apollo-angular/headers/src/index.ts @@ -1,8 +1,8 @@ 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) => { + return new ApolloLink((operation: ApolloLink.Operation, forward: ApolloLink.ForwardFunction) => { const { getContext, setContext } = operation; const context = getContext(); diff --git a/packages/apollo-angular/headers/tests/index.spec.ts b/packages/apollo-angular/headers/tests/index.spec.ts index 30f0eaee1..2f10f48d5 100644 --- a/packages/apollo-angular/headers/tests/index.spec.ts +++ b/packages/apollo-angular/headers/tests/index.spec.ts @@ -1,7 +1,7 @@ import { of } from 'rxjs'; import { describe, expect, test } from 'vitest'; import { HttpHeaders } from '@angular/common/http'; -import { ApolloLink, execute, gql } from '@apollo/client/core'; +import { ApolloLink, execute, gql } from "@apollo/client"; import { httpHeaders } from '../src'; const query = gql` diff --git a/packages/apollo-angular/http/src/http-batch-link.ts b/packages/apollo-angular/http/src/http-batch-link.ts index 6663f698a..65c1babce 100644 --- a/packages/apollo-angular/http/src/http-batch-link.ts +++ b/packages/apollo-angular/http/src/http-batch-link.ts @@ -2,8 +2,8 @@ import { print } from 'graphql'; import { Observable } from 'rxjs'; import { HttpClient, HttpHeaders } from '@angular/common/http'; import { Injectable } from '@angular/core'; -import { ApolloLink, FetchResult, Operation } from '@apollo/client/core'; -import { BatchHandler, BatchLink } from '@apollo/client/link/batch'; +import { ApolloLink } from "@apollo/client"; +import { BatchLink } from '@apollo/client/link/batch'; import { BatchOptions, Body, Context, OperationPrinter, Options, Request } from './types'; import { createHeadersWithClientAwareness, fetch, mergeHeaders, prioritize } from './utils'; @@ -48,7 +48,7 @@ export class HttpBatchLinkHandler extends ApolloLink { this.print = this.options.operationPrinter; } - const batchHandler: BatchHandler = (operations: Operation[]) => { + const batchHandler: BatchLink.BatchHandler = (operations: ApolloLink.Operation[]) => { return new Observable((observer: any) => { const body = this.createBody(operations); const headers = this.createHeaders(operations); @@ -86,7 +86,7 @@ export class HttpBatchLinkHandler extends ApolloLink { const batchKey = options.batchKey || - ((operation: Operation) => { + ((operation: ApolloLink.Operation) => { return this.createBatchKey(operation); }); @@ -99,7 +99,7 @@ export class HttpBatchLinkHandler extends ApolloLink { } private createOptions( - operations: Operation[], + operations: ApolloLink.Operation[], ): Required> { const context: Context = operations[0].getContext(); @@ -110,7 +110,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, @@ -140,9 +140,9 @@ export class HttpBatchLinkHandler extends ApolloLink { }); } - private createHeaders(operations: Operation[]): HttpHeaders { + private createHeaders(operations: ApolloLink.Operation[]): HttpHeaders { return operations.reduce( - (headers: HttpHeaders, operation: Operation) => { + (headers: HttpHeaders, operation: ApolloLink.Operation) => { return mergeHeaders(headers, operation.getContext().headers); }, createHeadersWithClientAwareness({ @@ -152,7 +152,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) { @@ -171,7 +171,7 @@ export class HttpBatchLinkHandler extends ApolloLink { return prioritize(context.uri, this.options.uri, '') + opts; } - public request(op: Operation): Observable | null { + public request(op: ApolloLink.Operation): Observable | null { return this.batcher.request(op); } } diff --git a/packages/apollo-angular/http/src/http-link.ts b/packages/apollo-angular/http/src/http-link.ts index 9fe1de4e9..0a2d2faa4 100644 --- a/packages/apollo-angular/http/src/http-link.ts +++ b/packages/apollo-angular/http/src/http-link.ts @@ -2,14 +2,14 @@ import { print } from 'graphql'; import { Observable } from 'rxjs'; import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; -import { ApolloLink, FetchResult, Operation } from '@apollo/client/core'; +import { ApolloLink } from "@apollo/client"; import { pick } from './http-batch-link'; import { Body, Context, OperationPrinter, Options, Request } from './types'; import { createHeadersWithClientAwareness, fetch, mergeHeaders } from './utils'; // XXX find a better name for it export class HttpLinkHandler extends ApolloLink { - public requester: (operation: Operation) => Observable | null; + public requester: (operation: ApolloLink.Operation) => Observable | null; private print: OperationPrinter = print; constructor( @@ -22,7 +22,7 @@ export class HttpLinkHandler extends ApolloLink { this.print = this.options.operationPrinter; } - this.requester = (operation: Operation) => + this.requester = (operation: ApolloLink.Operation) => new Observable((observer: any) => { const context: Context = operation.getContext(); @@ -85,7 +85,7 @@ export class HttpLinkHandler extends ApolloLink { }); } - public request(op: Operation): Observable | null { + public request(op: ApolloLink.Operation): Observable | null { return this.requester(op); } } diff --git a/packages/apollo-angular/http/src/types.ts b/packages/apollo-angular/http/src/types.ts index 58ddf3612..fb26bdddb 100644 --- a/packages/apollo-angular/http/src/types.ts +++ b/packages/apollo-angular/http/src/types.ts @@ -1,6 +1,6 @@ import { DocumentNode } from 'graphql'; import { HttpHeaders } from '@angular/common/http'; -import { Operation } from '@apollo/client/core'; +import { ApolloLink } from "@apollo/client"; export type HttpRequestOptions = { headers?: HttpHeaders; @@ -8,7 +8,7 @@ export type HttpRequestOptions = { useMultipart?: boolean; }; -export type URIFunction = (operation: Operation) => string; +export type URIFunction = (operation: ApolloLink.Operation) => string; export type FetchOptions = { method?: string; @@ -51,5 +51,5 @@ export type ExtractFiles = (body: Body | Body[]) => ExtractedFiles; export type BatchOptions = { batchMax?: number; batchInterval?: number; - batchKey?: (operation: Operation) => string; + batchKey?: (operation: ApolloLink.Operation) => string; } & Options; diff --git a/packages/apollo-angular/http/tests/http-batch-link.spec.ts b/packages/apollo-angular/http/tests/http-batch-link.spec.ts index 2e348da8e..f369e34d2 100644 --- a/packages/apollo-angular/http/tests/http-batch-link.spec.ts +++ b/packages/apollo-angular/http/tests/http-batch-link.spec.ts @@ -2,7 +2,7 @@ import { afterEach, beforeEach, describe, expect, test } from 'vitest'; import { HttpHeaders, provideHttpClient } from '@angular/common/http'; import { HttpTestingController, provideHttpClientTesting } from '@angular/common/http/testing'; import { TestBed } from '@angular/core/testing'; -import { ApolloLink, execute, gql, Operation } from '@apollo/client/core'; +import { ApolloLink, execute, gql } from "@apollo/client"; import { HttpBatchLink } from '../src/http-batch-link'; const noop = () => { @@ -571,7 +571,7 @@ describe('HttpBatchLink', () => { new Promise(done => { const link = httpLink.create({ uri: 'graphql', - batchKey: (operation: Operation) => operation.getContext().uri || 'graphql', + batchKey: (operation: ApolloLink.Operation) => operation.getContext().uri || 'graphql', }); execute(link, { diff --git a/packages/apollo-angular/http/tests/http-link.spec.ts b/packages/apollo-angular/http/tests/http-link.spec.ts index 387e7326d..61d3cb411 100644 --- a/packages/apollo-angular/http/tests/http-link.spec.ts +++ b/packages/apollo-angular/http/tests/http-link.spec.ts @@ -4,7 +4,7 @@ import { afterEach, beforeEach, describe, expect, test } from 'vitest'; import { HttpHeaders, provideHttpClient } from '@angular/common/http'; import { HttpTestingController, provideHttpClientTesting } from '@angular/common/http/testing'; import { TestBed } from '@angular/core/testing'; -import { ApolloLink, execute, gql, InMemoryCache } from '@apollo/client/core'; +import { ApolloLink, execute, gql, InMemoryCache } from "@apollo/client"; import { Apollo } from '../../src'; import { HttpLink } from '../src/http-link'; diff --git a/packages/apollo-angular/http/tests/ssr.spec.ts b/packages/apollo-angular/http/tests/ssr.spec.ts index 13b43b539..189682e00 100644 --- a/packages/apollo-angular/http/tests/ssr.spec.ts +++ b/packages/apollo-angular/http/tests/ssr.spec.ts @@ -10,7 +10,7 @@ import { renderModule, ServerModule, } from '@angular/platform-server'; -import { execute, gql } from '@apollo/client/core'; +import { execute, gql } from "@apollo/client"; import { HttpLink } from '../src/http-link'; describe.skip('integration', () => { diff --git a/packages/apollo-angular/persisted-queries/tests/persisted-queries.spec.ts b/packages/apollo-angular/persisted-queries/tests/persisted-queries.spec.ts index 7e06a7761..cc2de4e78 100644 --- a/packages/apollo-angular/persisted-queries/tests/persisted-queries.spec.ts +++ b/packages/apollo-angular/persisted-queries/tests/persisted-queries.spec.ts @@ -1,6 +1,6 @@ import { Observable } from 'rxjs'; import { describe, expect, test, vi } from 'vitest'; -import { ApolloLink, execute, FetchResult, gql, Operation } from '@apollo/client/core'; +import { ApolloLink, execute, gql } from "@apollo/client"; import { createPersistedQueryLink } from '../src'; const query = gql` @@ -24,8 +24,8 @@ class MockLink extends ApolloLink { : data; } - public request(operation: Operation) { - return new Observable(observer => { + public request(operation: ApolloLink.Operation) { + return new Observable(observer => { const request: any = {}; if (operation.getContext().includeQuery) { @@ -55,7 +55,7 @@ describe('createPersistedQueryLink', () => { query, }).subscribe(() => { const firstReq = spyRequester.calls[0][0] as any; - const secondOp = spyRequest.calls[1][0] as Operation; + const secondOp = spyRequest.calls[1][0] as ApolloLink.Operation; const secondReq = spyRequester.calls[1][0] as any; const secondContext = secondOp.getContext(); @@ -87,7 +87,7 @@ describe('createPersistedQueryLink', () => { execute(link, { query, }).subscribe(() => { - const op = spyRequest.calls[1][0] as Operation; + const op = spyRequest.calls[1][0] as ApolloLink.Operation; const ctx = op.getContext(); // should be compatible with apollo-angular-link-http diff --git a/packages/apollo-angular/schematics/install/files/module/graphql.module.ts b/packages/apollo-angular/schematics/install/files/module/graphql.module.ts index f1eea19fd..336318576 100644 --- a/packages/apollo-angular/schematics/install/files/module/graphql.module.ts +++ b/packages/apollo-angular/schematics/install/files/module/graphql.module.ts @@ -1,9 +1,9 @@ import { provideApollo } from 'apollo-angular'; import { HttpLink } from 'apollo-angular/http'; import { inject, NgModule } from '@angular/core'; -import { ApolloClientOptions, InMemoryCache } from '@apollo/client/core'; +import { InMemoryCache, ApolloClient } from "@apollo/client"; -export function createApollo(): ApolloClientOptions { +export function createApollo(): ApolloClient.Options { const uri = '<%= endpoint %>'; // <-- add the URL of the GraphQL server here const httpLink = inject(HttpLink); diff --git a/packages/apollo-angular/src/apollo-module.ts b/packages/apollo-angular/src/apollo-module.ts index 889c48ccc..18e564563 100644 --- a/packages/apollo-angular/src/apollo-module.ts +++ b/packages/apollo-angular/src/apollo-module.ts @@ -1,11 +1,11 @@ import { Provider } from '@angular/core'; -import { ApolloClientOptions } from '@apollo/client/core'; +import { ApolloClient } from "@apollo/client"; import { Apollo } from './apollo'; import { APOLLO_FLAGS, APOLLO_NAMED_OPTIONS, APOLLO_OPTIONS } from './tokens'; import { Flags, NamedOptions } from './types'; export function provideApollo( - optionsFactory: () => ApolloClientOptions, + optionsFactory: () => ApolloClient.Options, flags: Flags = {}, ): Provider { return [ diff --git a/packages/apollo-angular/src/gql.ts b/packages/apollo-angular/src/gql.ts index e58ff8d95..fcaf4caaf 100644 --- a/packages/apollo-angular/src/gql.ts +++ b/packages/apollo-angular/src/gql.ts @@ -1,4 +1,4 @@ -import { gql as gqlTag, TypedDocumentNode } from '@apollo/client/core'; +import { gql as gqlTag, TypedDocumentNode } from "@apollo/client"; const typedGQLTag: ( literals: ReadonlyArray | Readonly, diff --git a/packages/apollo-angular/src/mutation.ts b/packages/apollo-angular/src/mutation.ts index 7d706ece6..09932349f 100644 --- a/packages/apollo-angular/src/mutation.ts +++ b/packages/apollo-angular/src/mutation.ts @@ -1,7 +1,7 @@ import type { DocumentNode } from 'graphql'; import type { Observable } from 'rxjs'; import { Injectable } from '@angular/core'; -import type { OperationVariables, TypedDocumentNode } from '@apollo/client/core'; +import type { OperationVariables, TypedDocumentNode } from "@apollo/client"; import { Apollo } from './apollo'; import type { EmptyObject, MutationOptionsAlone, MutationResult } from './types'; diff --git a/packages/apollo-angular/src/query.ts b/packages/apollo-angular/src/query.ts index 00b2a5d82..803eee60d 100644 --- a/packages/apollo-angular/src/query.ts +++ b/packages/apollo-angular/src/query.ts @@ -1,7 +1,7 @@ import type { DocumentNode } from 'graphql'; import type { Observable } from 'rxjs'; import { Injectable } from '@angular/core'; -import type { ApolloQueryResult, OperationVariables, TypedDocumentNode } from '@apollo/client/core'; +import type { OperationVariables, TypedDocumentNode, ObservableQuery } from "@apollo/client"; import { Apollo } from './apollo'; import { QueryRef } from './query-ref'; import { EmptyObject, QueryOptionsAlone, WatchQueryOptionsAlone } from './types'; @@ -21,7 +21,7 @@ export abstract class Query }); } - public fetch(variables?: V, options?: QueryOptionsAlone): Observable> { + public fetch(variables?: V, options?: QueryOptionsAlone): Observable> { return this.apollo.use(this.client).query({ ...options, variables, diff --git a/packages/apollo-angular/src/subscription.ts b/packages/apollo-angular/src/subscription.ts index 5468529c7..cf747bd99 100644 --- a/packages/apollo-angular/src/subscription.ts +++ b/packages/apollo-angular/src/subscription.ts @@ -1,7 +1,7 @@ import type { DocumentNode } from 'graphql'; import type { Observable } from 'rxjs'; import { Injectable } from '@angular/core'; -import type { FetchResult, OperationVariables, TypedDocumentNode } from '@apollo/client/core'; +import type { OperationVariables, TypedDocumentNode, ApolloLink } from "@apollo/client"; import { Apollo } from './apollo'; import { EmptyObject, ExtraSubscriptionOptions, SubscriptionOptionsAlone } from './types'; @@ -16,7 +16,7 @@ export abstract class Subscription, extra?: ExtraSubscriptionOptions, - ): Observable> { + ): Observable> { return this.apollo.use(this.client).subscribe( { ...options, diff --git a/packages/apollo-angular/src/tokens.ts b/packages/apollo-angular/src/tokens.ts index b4bfcd303..82846e768 100644 --- a/packages/apollo-angular/src/tokens.ts +++ b/packages/apollo-angular/src/tokens.ts @@ -1,9 +1,9 @@ import { InjectionToken } from '@angular/core'; -import type { ApolloClientOptions } from '@apollo/client/core'; +import type { ApolloClient } from "@apollo/client"; import type { Flags, NamedOptions } from './types'; export const APOLLO_FLAGS = new InjectionToken('APOLLO_FLAGS'); -export const APOLLO_OPTIONS = new InjectionToken>('APOLLO_OPTIONS'); +export const APOLLO_OPTIONS = new InjectionToken>('APOLLO_OPTIONS'); export const APOLLO_NAMED_OPTIONS = new InjectionToken('APOLLO_NAMED_OPTIONS'); diff --git a/packages/apollo-angular/src/types.ts b/packages/apollo-angular/src/types.ts index 972d4605f..d60d728f2 100644 --- a/packages/apollo-angular/src/types.ts +++ b/packages/apollo-angular/src/types.ts @@ -1,14 +1,10 @@ import type { - ApolloClientOptions, - MutationOptions as CoreMutationOptions, - QueryOptions as CoreQueryOptions, - SubscriptionOptions as CoreSubscriptionOptions, WatchFragmentOptions as CoreWatchFragmentOptions, - WatchQueryOptions as CoreWatchQueryOptions, - FetchResult, OperationVariables, TypedDocumentNode, -} from '@apollo/client/core'; + ApolloClient, + ApolloLink, +} from "@apollo/client"; export type EmptyObject = { [key: string]: any; @@ -23,7 +19,7 @@ export interface ExtraSubscriptionOptions { useZone?: boolean; } -export type MutationResult = FetchResult & { +export type MutationResult = ApolloLink.Result & { loading?: boolean; }; @@ -35,19 +31,19 @@ export interface WatchQueryOptionsAlone< > extends Omit, 'query' | 'variables'> {} export interface QueryOptionsAlone - extends Omit, 'query' | 'variables'> {} + extends Omit, 'query' | 'variables'> {} export interface MutationOptionsAlone extends Omit, 'mutation' | 'variables'> {} export interface SubscriptionOptionsAlone - extends Omit, 'query' | 'variables'> {} + extends Omit, 'query' | 'variables'> {} export interface WatchQueryOptions - extends CoreWatchQueryOptions {} + extends ApolloClient.WatchQueryOptions {} export interface MutationOptions - extends CoreMutationOptions { + extends ApolloClient.MutateOptions { /** * Observable starts with `{ loading: true }`. * There's a big chance the next major version will enable that by default. @@ -60,7 +56,7 @@ export interface MutationOptions export interface WatchFragmentOptions extends CoreWatchFragmentOptions {} -export type NamedOptions = Record>; +export type NamedOptions = Record>; export type Flags = { /** diff --git a/packages/apollo-angular/testing/src/backend.ts b/packages/apollo-angular/testing/src/backend.ts index 908b89dc3..cc0ec6187 100644 --- a/packages/apollo-angular/testing/src/backend.ts +++ b/packages/apollo-angular/testing/src/backend.ts @@ -1,7 +1,7 @@ import { DocumentNode, print } from 'graphql'; import { Observable, Observer } from 'rxjs'; import { Injectable } from '@angular/core'; -import { FetchResult } from '@apollo/client/core'; +import { ApolloLink } from "@apollo/client"; import { ApolloTestingController, MatchOperation } from './controller'; import { Operation, TestOperation } from './operation'; @@ -23,7 +23,7 @@ export class ApolloTestingBackend implements ApolloTestingController { /** * Handle an incoming operation by queueing it in the list of open operations. */ - public handle(op: Operation): Observable { + public handle(op: Operation): Observable { return new Observable((observer: Observer) => { const testOp = new TestOperation(op, observer); this.open.push(testOp); diff --git a/packages/apollo-angular/testing/src/module.ts b/packages/apollo-angular/testing/src/module.ts index f7d9de163..ffb2e8c7f 100644 --- a/packages/apollo-angular/testing/src/module.ts +++ b/packages/apollo-angular/testing/src/module.ts @@ -1,11 +1,6 @@ import { Apollo } from 'apollo-angular'; import { Inject, InjectionToken, NgModule, Optional } from '@angular/core'; -import { - ApolloCache, - ApolloLink, - InMemoryCache, - Operation as LinkOperation, -} from '@apollo/client/core'; +import { ApolloCache, ApolloLink, InMemoryCache } from "@apollo/client"; import { ApolloTestingBackend } from './backend'; import { ApolloTestingController } from './controller'; import { Operation } from './operation'; @@ -24,7 +19,7 @@ export const APOLLO_TESTING_CLIENTS = new InjectionToken( 'apollo-angular/testing named clients', ); -function addClient(name: string, op: LinkOperation): Operation { +function addClient(name: string, op: ApolloLink.Operation): Operation { (op as Operation).clientName = name; return op as Operation; diff --git a/packages/apollo-angular/testing/src/operation.ts b/packages/apollo-angular/testing/src/operation.ts index 4be45d4e0..e0bcc5767 100644 --- a/packages/apollo-angular/testing/src/operation.ts +++ b/packages/apollo-angular/testing/src/operation.ts @@ -1,18 +1,19 @@ import { FormattedExecutionResult, GraphQLError, Kind, OperationTypeNode } from 'graphql'; import { Observer } from 'rxjs'; -import { ApolloError, FetchResult, Operation as LinkOperation } from '@apollo/client/core'; +import { ApolloLink } from "@apollo/client"; +import { ApolloError } from "@apollo/client/v4-migration"; import { getMainDefinition } from '@apollo/client/utilities'; const isApolloError = (err: any): err is ApolloError => err && err.hasOwnProperty('graphQLErrors'); -export type Operation = LinkOperation & { +export type Operation = ApolloLink.Operation & { clientName: string; }; export class TestOperation { constructor( public readonly operation: Operation, - private readonly observer: Observer>, + private readonly observer: Observer>, ) {} public flush(result: FormattedExecutionResult | ApolloError): void { diff --git a/packages/apollo-angular/testing/tests/integration.spec.ts b/packages/apollo-angular/testing/tests/integration.spec.ts index b4452489b..84c282510 100644 --- a/packages/apollo-angular/testing/tests/integration.spec.ts +++ b/packages/apollo-angular/testing/tests/integration.spec.ts @@ -1,7 +1,7 @@ import { print } from 'graphql'; import { afterEach, beforeEach, describe, expect, test } from 'vitest'; import { TestBed } from '@angular/core/testing'; -import { gql } from '@apollo/client/core'; +import { gql } from "@apollo/client"; import { addTypenameToDocument } from '@apollo/client/utilities'; import { Apollo } from '../../src'; import { ApolloTestingController, ApolloTestingModule } from '../src'; diff --git a/packages/apollo-angular/testing/tests/module.spec.ts b/packages/apollo-angular/testing/tests/module.spec.ts index 0ff46f824..987736ee8 100644 --- a/packages/apollo-angular/testing/tests/module.spec.ts +++ b/packages/apollo-angular/testing/tests/module.spec.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from 'vitest'; import { TestBed } from '@angular/core/testing'; -import { gql, InMemoryCache } from '@apollo/client/core'; +import { gql, InMemoryCache } from "@apollo/client"; import { Apollo } from '../../src'; import { APOLLO_TESTING_CACHE, ApolloTestingController, ApolloTestingModule } from '../src'; diff --git a/packages/apollo-angular/testing/tests/operation.spec.ts b/packages/apollo-angular/testing/tests/operation.spec.ts index 4dc586d9f..25d577166 100644 --- a/packages/apollo-angular/testing/tests/operation.spec.ts +++ b/packages/apollo-angular/testing/tests/operation.spec.ts @@ -1,5 +1,5 @@ import { beforeEach, describe, expect, test } from 'vitest'; -import { ApolloLink, execute, FetchResult, gql } from '@apollo/client/core'; +import { ApolloLink, execute, gql } from "@apollo/client"; import { ApolloTestingBackend } from '../src/backend'; import { buildOperationForLink } from './utils'; @@ -73,7 +73,7 @@ describe('TestOperation', () => { test('should leave the operation open for a subscription', () => new Promise(done => { const operation = buildOperationForLink(testSubscription, {}); - const emittedResults: FetchResult[] = []; + const emittedResults: ApolloLink.Result[] = []; execute(link, operation).subscribe({ next(result) { @@ -112,7 +112,7 @@ describe('TestOperation', () => { test('should close the operation after a query', () => new Promise(done => { const operation = buildOperationForLink(testQuery, {}); - const emittedResults: FetchResult[] = []; + const emittedResults: ApolloLink.Result[] = []; execute(link, operation).subscribe({ next(result) { @@ -144,7 +144,7 @@ describe('TestOperation', () => { test('should close the operation after a mutation', () => new Promise(done => { const operation = buildOperationForLink(testMutation, { hero: 'firstHero' }); - const emittedResults: FetchResult[] = []; + const emittedResults: ApolloLink.Result[] = []; execute(link, operation).subscribe({ next(result) { diff --git a/packages/apollo-angular/testing/tests/utils.ts b/packages/apollo-angular/testing/tests/utils.ts index 3305e6e49..dc796e9c3 100644 --- a/packages/apollo-angular/testing/tests/utils.ts +++ b/packages/apollo-angular/testing/tests/utils.ts @@ -1,6 +1,6 @@ import { DocumentNode } from 'graphql'; import type { GraphQLRequest } from '@apollo/client/link/core/types'; -import { getOperationName } from '@apollo/client/utilities'; +import { getOperationName } from "@apollo/client/utilities/internal"; export function buildOperationForLink>( document: DocumentNode, diff --git a/packages/apollo-angular/tests/Apollo.spec.ts b/packages/apollo-angular/tests/Apollo.spec.ts index a123f0ffa..7f676ad80 100644 --- a/packages/apollo-angular/tests/Apollo.spec.ts +++ b/packages/apollo-angular/tests/Apollo.spec.ts @@ -3,8 +3,8 @@ import { mergeMap } from 'rxjs/operators'; import { beforeEach, describe, expect, test, vi } from 'vitest'; import { NgZone } from '@angular/core'; import { TestBed } from '@angular/core/testing'; -import { ApolloLink, InMemoryCache, NetworkStatus } from '@apollo/client/core'; -import { mockSingleLink } from '@apollo/client/testing'; +import { ApolloLink, InMemoryCache, NetworkStatus } from "@apollo/client"; +import { mockSingleLink } from "@apollo/client/v4-migration"; import { Apollo, ApolloBase } from '../src/apollo'; import { gql } from '../src/gql'; import { ZoneScheduler } from '../src/utils'; diff --git a/packages/apollo-angular/tests/QueryRef.spec.ts b/packages/apollo-angular/tests/QueryRef.spec.ts index b84d47223..ced10e0c0 100644 --- a/packages/apollo-angular/tests/QueryRef.spec.ts +++ b/packages/apollo-angular/tests/QueryRef.spec.ts @@ -2,8 +2,10 @@ import { Subject } from 'rxjs'; import { map, takeUntil } from 'rxjs/operators'; import { beforeEach, describe, expect, test, vi } from 'vitest'; import { NgZone } from '@angular/core'; -import { ApolloClient, ApolloLink, InMemoryCache, ObservableQuery } from '@apollo/client/core'; -import { mockSingleLink } from '@apollo/client/testing'; +import { ApolloClient, ApolloLink, InMemoryCache, ObservableQuery } from "@apollo/client"; +import { Defer20220824Handler } from "@apollo/client/incremental"; +import { LocalState } from "@apollo/client/local-state"; +import { mockSingleLink } from "@apollo/client/v4-migration"; import { gql } from '../src/gql'; import { QueryRef } from '../src/query-ref'; @@ -11,6 +13,20 @@ const createClient = (link: ApolloLink) => new ApolloClient({ link, cache: new InMemoryCache(), + + /* + Inserted by Apollo Client 3->4 migration codemod. + If you are not using the `@client` directive in your application, + you can safely remove this option. + */ + localState: new LocalState({}), + + /* + Inserted by Apollo Client 3->4 migration codemod. + If you are not using the `@defer` directive in your application, + you can safely remove this option. + */ + incrementalHandler: new Defer20220824Handler() }); const heroesOperation = { @@ -40,7 +56,7 @@ const Batman = { describe('QueryRef', () => { let ngZone: NgZone; - let client: ApolloClient; + let client: ApolloClient; let obsQuery: ObservableQuery; let queryRef: QueryRef; @@ -379,3 +395,22 @@ describe('QueryRef', () => { done(); })); }); + +/* +Start: Inserted by Apollo Client 3->4 migration codemod. +Copy the contents of this block into a `.d.ts` file in your project to enable correct response types in your custom links. +If you do not use the `@defer` directive in your application, you can safely remove this block. +*/ + + +import "@apollo/client"; +import { Defer20220824Handler } from "@apollo/client/incremental"; + +declare module "@apollo/client" { + export interface TypeOverrides extends Defer20220824Handler.TypeOverrides {} +} + +/* +End: Inserted by Apollo Client 3->4 migration codemod. +*/ + diff --git a/packages/apollo-angular/tests/integration.spec.ts b/packages/apollo-angular/tests/integration.spec.ts index 88170abe0..d7e32a103 100644 --- a/packages/apollo-angular/tests/integration.spec.ts +++ b/packages/apollo-angular/tests/integration.spec.ts @@ -1,8 +1,8 @@ import { beforeEach, describe, expect, test } from 'vitest'; import { provideHttpClient } from '@angular/common/http'; import { TestBed } from '@angular/core/testing'; -import { InMemoryCache } from '@apollo/client/core'; -import { mockSingleLink } from '@apollo/client/testing'; +import { InMemoryCache } from "@apollo/client"; +import { mockSingleLink } from "@apollo/client/v4-migration"; import { Apollo, provideApollo } from '../src'; describe('Integration', () => { From e4724d0f1806fd36205828ba4067e67ab1b1c04c Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 25 Aug 2025 18:24:35 -0600 Subject: [PATCH 08/97] Run codemod on demo --- packages/demo/src/app/app.config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/demo/src/app/app.config.ts b/packages/demo/src/app/app.config.ts index 8dec6e286..e76c72b50 100644 --- a/packages/demo/src/app/app.config.ts +++ b/packages/demo/src/app/app.config.ts @@ -3,7 +3,7 @@ import { HttpLink } from 'apollo-angular/http'; import { provideHttpClient } from '@angular/common/http'; import { ApplicationConfig, inject, provideZoneChangeDetection } from '@angular/core'; import { provideRouter } from '@angular/router'; -import { InMemoryCache } from '@apollo/client/core'; +import { InMemoryCache } from "@apollo/client"; import { routes } from './app.routes'; export const appConfig: ApplicationConfig = { From 85018f87ad034e4e95c0ee57a90cf431333df08e Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 25 Aug 2025 18:28:16 -0600 Subject: [PATCH 09/97] Update buildOperationForLink to use updated types/signature --- packages/apollo-angular/testing/tests/utils.ts | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/packages/apollo-angular/testing/tests/utils.ts b/packages/apollo-angular/testing/tests/utils.ts index dc796e9c3..b025bd480 100644 --- a/packages/apollo-angular/testing/tests/utils.ts +++ b/packages/apollo-angular/testing/tests/utils.ts @@ -1,15 +1,14 @@ import { DocumentNode } from 'graphql'; -import type { GraphQLRequest } from '@apollo/client/link/core/types'; -import { getOperationName } from "@apollo/client/utilities/internal"; +import { OperationVariables } from '@apollo/client'; +import type { ApolloLink } from '@apollo/client/link'; -export function buildOperationForLink>( +export function buildOperationForLink( document: DocumentNode, - variables: TVariables, -): GraphQLRequest { + variables: OperationVariables | undefined, +): ApolloLink.Request { return { query: document, variables, - operationName: getOperationName(document) || undefined, context: {}, }; } From a69051393b424334a09811597b8db1473c5bd098 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 25 Aug 2025 18:31:54 -0600 Subject: [PATCH 10/97] Add helper to execute with a client context --- .../apollo-angular/testing/tests/utils.ts | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/packages/apollo-angular/testing/tests/utils.ts b/packages/apollo-angular/testing/tests/utils.ts index b025bd480..17b35acaf 100644 --- a/packages/apollo-angular/testing/tests/utils.ts +++ b/packages/apollo-angular/testing/tests/utils.ts @@ -1,6 +1,7 @@ import { DocumentNode } from 'graphql'; -import { OperationVariables } from '@apollo/client'; -import type { ApolloLink } from '@apollo/client/link'; +import { Observable } from 'rxjs'; +import { ApolloClient, execute, InMemoryCache, OperationVariables } from '@apollo/client'; +import { ApolloLink } from '@apollo/client/link'; export function buildOperationForLink( document: DocumentNode, @@ -12,3 +13,20 @@ export function buildOperationForLink( context: {}, }; } + +export function createDefaultExecuteContext(): ApolloLink.ExecuteContext { + return { + client: new ApolloClient({ + cache: new InMemoryCache(), + link: ApolloLink.empty(), + }), + }; +} + +export function executeWithDefaultContext( + link: ApolloLink, + request: ApolloLink.Request, + context: ApolloLink.ExecuteContext = createDefaultExecuteContext(), +): Observable { + return execute(link, request, context); +} From ab98b8ce8ea9069480af9701bf3558bf380abfb4 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 25 Aug 2025 18:35:43 -0600 Subject: [PATCH 11/97] Adjust opration spec to use util --- packages/apollo-angular/testing/tests/operation.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/apollo-angular/testing/tests/operation.spec.ts b/packages/apollo-angular/testing/tests/operation.spec.ts index 25d577166..1cd24075e 100644 --- a/packages/apollo-angular/testing/tests/operation.spec.ts +++ b/packages/apollo-angular/testing/tests/operation.spec.ts @@ -1,7 +1,7 @@ import { beforeEach, describe, expect, test } from 'vitest'; -import { ApolloLink, execute, gql } from "@apollo/client"; +import { ApolloLink, gql } from '@apollo/client'; import { ApolloTestingBackend } from '../src/backend'; -import { buildOperationForLink } from './utils'; +import { buildOperationForLink, executeWithDefaultContext as execute } from './utils'; const testQuery = gql` query allHeroes { From aa4fd804f4799e974a46acf23ca9a4446f91d0f8 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 25 Aug 2025 18:38:28 -0600 Subject: [PATCH 12/97] Remove generic on ApolloClient.Options type --- .../schematics/install/files/module/graphql.module.ts | 4 ++-- packages/apollo-angular/src/apollo-module.ts | 6 +++--- packages/apollo-angular/src/tokens.ts | 4 ++-- packages/apollo-angular/src/types.ts | 8 ++++---- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/apollo-angular/schematics/install/files/module/graphql.module.ts b/packages/apollo-angular/schematics/install/files/module/graphql.module.ts index 336318576..7bc609bda 100644 --- a/packages/apollo-angular/schematics/install/files/module/graphql.module.ts +++ b/packages/apollo-angular/schematics/install/files/module/graphql.module.ts @@ -1,9 +1,9 @@ import { provideApollo } from 'apollo-angular'; import { HttpLink } from 'apollo-angular/http'; import { inject, NgModule } from '@angular/core'; -import { InMemoryCache, ApolloClient } from "@apollo/client"; +import { ApolloClient, InMemoryCache } from '@apollo/client'; -export function createApollo(): ApolloClient.Options { +export function createApollo(): ApolloClient.Options { const uri = '<%= endpoint %>'; // <-- add the URL of the GraphQL server here const httpLink = inject(HttpLink); diff --git a/packages/apollo-angular/src/apollo-module.ts b/packages/apollo-angular/src/apollo-module.ts index 18e564563..49fcb62c8 100644 --- a/packages/apollo-angular/src/apollo-module.ts +++ b/packages/apollo-angular/src/apollo-module.ts @@ -1,11 +1,11 @@ import { Provider } from '@angular/core'; -import { ApolloClient } from "@apollo/client"; +import { ApolloClient } from '@apollo/client'; import { Apollo } from './apollo'; import { APOLLO_FLAGS, APOLLO_NAMED_OPTIONS, APOLLO_OPTIONS } from './tokens'; import { Flags, NamedOptions } from './types'; -export function provideApollo( - optionsFactory: () => ApolloClient.Options, +export function provideApollo( + optionsFactory: () => ApolloClient.Options, flags: Flags = {}, ): Provider { return [ diff --git a/packages/apollo-angular/src/tokens.ts b/packages/apollo-angular/src/tokens.ts index 82846e768..0a8bda2f2 100644 --- a/packages/apollo-angular/src/tokens.ts +++ b/packages/apollo-angular/src/tokens.ts @@ -1,9 +1,9 @@ import { InjectionToken } from '@angular/core'; -import type { ApolloClient } from "@apollo/client"; +import type { ApolloClient } from '@apollo/client'; import type { Flags, NamedOptions } from './types'; export const APOLLO_FLAGS = new InjectionToken('APOLLO_FLAGS'); -export const APOLLO_OPTIONS = new InjectionToken>('APOLLO_OPTIONS'); +export const APOLLO_OPTIONS = new InjectionToken('APOLLO_OPTIONS'); export const APOLLO_NAMED_OPTIONS = new InjectionToken('APOLLO_NAMED_OPTIONS'); diff --git a/packages/apollo-angular/src/types.ts b/packages/apollo-angular/src/types.ts index d60d728f2..9ece5a2fe 100644 --- a/packages/apollo-angular/src/types.ts +++ b/packages/apollo-angular/src/types.ts @@ -1,10 +1,10 @@ import type { + ApolloClient, + ApolloLink, WatchFragmentOptions as CoreWatchFragmentOptions, OperationVariables, TypedDocumentNode, - ApolloClient, - ApolloLink, -} from "@apollo/client"; +} from '@apollo/client'; export type EmptyObject = { [key: string]: any; @@ -56,7 +56,7 @@ export interface MutationOptions export interface WatchFragmentOptions extends CoreWatchFragmentOptions {} -export type NamedOptions = Record>; +export type NamedOptions = Record; export type Flags = { /** From bd2cfa6c1a2863ec1148c0a9f44c2e567ef7662f Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 25 Aug 2025 18:44:08 -0600 Subject: [PATCH 13/97] Update types to be compatible with v4 types --- packages/apollo-angular/src/types.ts | 44 ++++++++++++++++++---------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/packages/apollo-angular/src/types.ts b/packages/apollo-angular/src/types.ts index 9ece5a2fe..cd7032815 100644 --- a/packages/apollo-angular/src/types.ts +++ b/packages/apollo-angular/src/types.ts @@ -1,7 +1,7 @@ import type { + ApolloCache, ApolloClient, ApolloLink, - WatchFragmentOptions as CoreWatchFragmentOptions, OperationVariables, TypedDocumentNode, } from '@apollo/client'; @@ -25,25 +25,35 @@ export type MutationResult = ApolloLink.Result & { export type Omit = Pick>; -export interface WatchQueryOptionsAlone< +export type WatchQueryOptionsAlone< TVariables extends OperationVariables = EmptyObject, TData = any, -> extends Omit, 'query' | 'variables'> {} +> = Omit, 'query' | 'variables'>; -export interface QueryOptionsAlone - extends Omit, 'query' | 'variables'> {} +export type QueryOptionsAlone< + TVariables extends OperationVariables = EmptyObject, + TData = any, +> = Omit, 'query' | 'variables'>; -export interface MutationOptionsAlone - extends Omit, 'mutation' | 'variables'> {} +export type MutationOptionsAlone< + TData = EmptyObject, + TVariables extends OperationVariables = any, +> = Omit, 'mutation' | 'variables'>; -export interface SubscriptionOptionsAlone - extends Omit, 'query' | 'variables'> {} +export type SubscriptionOptionsAlone< + TVariables extends OperationVariables = EmptyObject, + TData = any, +> = Omit, 'query' | 'variables'>; -export interface WatchQueryOptions - extends ApolloClient.WatchQueryOptions {} +export type WatchQueryOptions< + TVariables extends OperationVariables = EmptyObject, + TData = any, +> = ApolloClient.WatchQueryOptions; -export interface MutationOptions - extends ApolloClient.MutateOptions { +export type MutationOptions< + TData = any, + TVariables extends OperationVariables = EmptyObject, +> = ApolloClient.MutateOptions & { /** * Observable starts with `{ loading: true }`. * There's a big chance the next major version will enable that by default. @@ -51,10 +61,12 @@ export interface MutationOptions * Disabled by default */ useMutationLoading?: boolean; -} +}; -export interface WatchFragmentOptions - extends CoreWatchFragmentOptions {} +export interface WatchFragmentOptions< + TData = any, + TVariables extends OperationVariables = EmptyObject, +> extends ApolloCache.WatchFragmentOptions {} export type NamedOptions = Record; From eada747eecfeb14a86f8ac3a1781d81fd3d0294a Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 25 Aug 2025 18:47:02 -0600 Subject: [PATCH 14/97] Fix call to execute in headers/index.spec --- .../headers/tests/index.spec.ts | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/packages/apollo-angular/headers/tests/index.spec.ts b/packages/apollo-angular/headers/tests/index.spec.ts index 2f10f48d5..f7fa2193a 100644 --- a/packages/apollo-angular/headers/tests/index.spec.ts +++ b/packages/apollo-angular/headers/tests/index.spec.ts @@ -1,7 +1,7 @@ import { of } from 'rxjs'; import { describe, expect, test } from 'vitest'; import { HttpHeaders } from '@angular/common/http'; -import { ApolloLink, execute, gql } from "@apollo/client"; +import { ApolloClient, ApolloLink, execute, gql, InMemoryCache } from '@apollo/client'; import { httpHeaders } from '../src'; const query = gql` @@ -14,6 +14,8 @@ const query = gql` `; const data = { heroes: [{ name: 'Foo', __typename: 'Hero' }] }; +const dummyClient = new ApolloClient({ cache: new InMemoryCache(), link: ApolloLink.empty() }); + describe('httpHeaders', () => { test('should turn object into HttpHeaders', () => new Promise(done => { @@ -30,14 +32,18 @@ describe('httpHeaders', () => { 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(); }); @@ -57,9 +63,7 @@ describe('httpHeaders', () => { const link = headersLink.concat(mockLink); - execute(link, { - query, - }).subscribe(result => { + execute(link, { query }, { client: dummyClient }).subscribe(result => { expect(result.data).toEqual(data); done(); }); From 197cee77265391f529311c5bf5911a5098661275 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 25 Aug 2025 18:55:38 -0600 Subject: [PATCH 15/97] Update QueryRef to be compatible with v4 --- packages/apollo-angular/src/query-ref.ts | 58 ++++++------------------ 1 file changed, 14 insertions(+), 44 deletions(-) diff --git a/packages/apollo-angular/src/query-ref.ts b/packages/apollo-angular/src/query-ref.ts index 67504666f..6d51c1ad7 100644 --- a/packages/apollo-angular/src/query-ref.ts +++ b/packages/apollo-angular/src/query-ref.ts @@ -1,31 +1,26 @@ -import { Observable } from 'rxjs'; +import { from, Observable } from 'rxjs'; import { NgZone } from '@angular/core'; import type { - ApolloQueryResult, - FetchMoreQueryOptions, + ApolloClient, MaybeMasked, ObservableQuery, OperationVariables, - SubscribeToMoreOptions, TypedDocumentNode, - Unmasked, -} from '@apollo/client/core'; +} from '@apollo/client'; import { EmptyObject } from './types'; -import { fromObservableQuery, wrapWithZone } from './utils'; +import { wrapWithZone } from './utils'; export type QueryRefFromDocument = T extends TypedDocumentNode ? QueryRef : never; export class QueryRef { - public readonly valueChanges: Observable>; - public readonly queryId: ObservableQuery['queryId']; + public readonly valueChanges: Observable>; constructor( private readonly obsQuery: ObservableQuery, ngZone: NgZone, ) { - this.valueChanges = wrapWithZone(fromObservableQuery(this.obsQuery), ngZone); - this.queryId = this.obsQuery.queryId; + this.valueChanges = wrapWithZone(from(this.obsQuery), ngZone); } // ObservableQuery's methods @@ -38,26 +33,10 @@ export class QueryRef['result']> { - return this.obsQuery.result(); - } - public getCurrentResult(): ReturnType['getCurrentResult']> { return this.obsQuery.getCurrentResult(); } - public getLastResult(): ReturnType['getLastResult']> { - return this.obsQuery.getLastResult(); - } - - public getLastError(): ReturnType['getLastError']> { - return this.obsQuery.getLastError(); - } - - public resetLastResults(): ReturnType['resetLastResults']> { - return this.obsQuery.resetLastResults(); - } - public refetch( variables?: Parameters['refetch']>[0], ): ReturnType['refetch']> { @@ -65,16 +44,8 @@ export class QueryRef( - fetchMoreOptions: FetchMoreQueryOptions & { - updateQuery?: ( - previousQueryResult: Unmasked, - options: { - fetchMoreResult: Unmasked; - variables: TFetchVars; - }, - ) => Unmasked; - }, - ): Promise>> { + fetchMoreOptions: ObservableQuery.FetchMoreOptions, + ): Promise>> { return this.obsQuery.fetchMore(fetchMoreOptions); } @@ -82,7 +53,12 @@ export class QueryRef( - options: SubscribeToMoreOptions, + options: ObservableQuery.SubscribeToMoreOptions< + TData, + TSubscriptionVariables, + TSubscriptionData, + TVariables + >, ): ReturnType['subscribeToMore']> { return this.obsQuery.subscribeToMore(options); } @@ -103,12 +79,6 @@ export class QueryRef['setOptions']>[0], - ): ReturnType['setOptions']> { - return this.obsQuery.setOptions(opts); - } - public setVariables( variables: Parameters['setVariables']>[0], ): ReturnType['setVariables']> { From 5d8471b8551fcc3e1ac54e1926598066fcc79b07 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 25 Aug 2025 19:02:05 -0600 Subject: [PATCH 16/97] Update queryRef spec --- .../apollo-angular/tests/QueryRef.spec.ts | 105 ++---------------- 1 file changed, 8 insertions(+), 97 deletions(-) diff --git a/packages/apollo-angular/tests/QueryRef.spec.ts b/packages/apollo-angular/tests/QueryRef.spec.ts index ced10e0c0..1ffe838b1 100644 --- a/packages/apollo-angular/tests/QueryRef.spec.ts +++ b/packages/apollo-angular/tests/QueryRef.spec.ts @@ -2,10 +2,8 @@ import { Subject } from 'rxjs'; import { map, takeUntil } from 'rxjs/operators'; import { beforeEach, describe, expect, test, vi } from 'vitest'; import { NgZone } from '@angular/core'; -import { ApolloClient, ApolloLink, InMemoryCache, ObservableQuery } from "@apollo/client"; -import { Defer20220824Handler } from "@apollo/client/incremental"; -import { LocalState } from "@apollo/client/local-state"; -import { mockSingleLink } from "@apollo/client/v4-migration"; +import { ApolloClient, ApolloLink, InMemoryCache, ObservableQuery } from '@apollo/client'; +import { MockLink } from '@apollo/client/testing'; import { gql } from '../src/gql'; import { QueryRef } from '../src/query-ref'; @@ -13,20 +11,6 @@ const createClient = (link: ApolloLink) => new ApolloClient({ link, cache: new InMemoryCache(), - - /* - Inserted by Apollo Client 3->4 migration codemod. - If you are not using the `@client` directive in your application, - you can safely remove this option. - */ - localState: new LocalState({}), - - /* - Inserted by Apollo Client 3->4 migration codemod. - If you are not using the `@defer` directive in your application, - you can safely remove this option. - */ - incrementalHandler: new Defer20220824Handler() }); const heroesOperation = { @@ -62,7 +46,7 @@ describe('QueryRef', () => { beforeEach(() => { ngZone = { run: vi.fn(cb => cb()) } as any; - const mockedLink = mockSingleLink( + const mockedLink = new MockLink([ { request: heroesOperation, result: { data: { heroes: [Superman] } }, @@ -71,7 +55,7 @@ describe('QueryRef', () => { request: heroesOperation, result: { data: { heroes: [Superman, Batman] } }, }, - ); + ]); client = createClient(mockedLink); obsQuery = client.watchQuery(heroesOperation); @@ -168,16 +152,6 @@ describe('QueryRef', () => { expect(mockCallback.mock.calls[0][0]).toBe(mapFn); }); - test('should be able to call result()', () => { - const mockCallback = vi.fn(); - obsQuery.result = mockCallback.mockReturnValue('expected'); - - const result = queryRef.result(); - - expect(result).toBe('expected'); - expect(mockCallback.mock.calls.length).toBe(1); - }); - test('should be able to call getCurrentResult() and get updated results', () => new Promise(done => { let calls = 0; @@ -206,36 +180,6 @@ describe('QueryRef', () => { }, 200); })); - test('should be able to call getLastResult()', () => { - const mockCallback = vi.fn(); - obsQuery.getLastResult = mockCallback.mockReturnValue('expected'); - - const result = queryRef.getLastResult(); - - expect(result).toBe('expected'); - expect(mockCallback.mock.calls.length).toBe(1); - }); - - test('should be able to call getLastError()', () => { - const mockCallback = vi.fn(); - obsQuery.getLastError = mockCallback.mockReturnValue('expected'); - - const result = queryRef.getLastError(); - - expect(result).toBe('expected'); - expect(mockCallback.mock.calls.length).toBe(1); - }); - - test('should be able to call resetLastResults()', () => { - const mockCallback = vi.fn(); - obsQuery.resetLastResults = mockCallback.mockReturnValue('expected'); - - const result = queryRef.resetLastResults(); - - expect(result).toBe('expected'); - expect(mockCallback.mock.calls.length).toBe(1); - }); - test('should be able to call fetchMore()', () => { const mockCallback = vi.fn(); const opts = { foo: 1 }; @@ -278,18 +222,6 @@ describe('QueryRef', () => { expect(mockCallback.mock.calls[0][0]).toBe(3000); }); - test('should be able to call setOptions()', () => { - const mockCallback = vi.fn(); - const opts = {}; - obsQuery.setOptions = mockCallback.mockReturnValue('expected'); - - const result = queryRef.setOptions(opts); - - expect(result).toBe('expected'); - expect(mockCallback.mock.calls.length).toBe(1); - expect(mockCallback.mock.calls[0][0]).toBe(opts); - }); - test('should be able to call setVariables()', () => { const mockCallback = vi.fn(); const variables = {}; @@ -362,17 +294,16 @@ describe('QueryRef', () => { test('should unsubscribe', () => new Promise(done => { const obs = queryRef.valueChanges; - const id = queryRef.queryId; const sub = obs.subscribe(() => { // }); - expect(client['queryManager'].queries.get(id)).toBeDefined(); + expect(client.getObservableQueries().size).toBe(1); setTimeout(() => { sub.unsubscribe(); - expect(client['queryManager'].queries.get(id)).toBeUndefined(); + expect(client.getObservableQueries().size).toBe(0); done(); }); })); @@ -381,36 +312,16 @@ describe('QueryRef', () => { new Promise(done => { const gate = new Subject(); const obs = queryRef.valueChanges.pipe(takeUntil(gate)); - const id = queryRef.queryId; obs.subscribe(() => { // }); - expect(client['queryManager'].queries.get(id)).toBeDefined(); + expect(client.getObservableQueries().size).toBe(1); gate.next(); - expect(client['queryManager'].queries.get(id)).toBeUndefined(); + expect(client.getObservableQueries().size).toBe(0); done(); })); }); - -/* -Start: Inserted by Apollo Client 3->4 migration codemod. -Copy the contents of this block into a `.d.ts` file in your project to enable correct response types in your custom links. -If you do not use the `@defer` directive in your application, you can safely remove this block. -*/ - - -import "@apollo/client"; -import { Defer20220824Handler } from "@apollo/client/incremental"; - -declare module "@apollo/client" { - export interface TypeOverrides extends Defer20220824Handler.TypeOverrides {} -} - -/* -End: Inserted by Apollo Client 3->4 migration codemod. -*/ - From 2d33fd727f148766cb6d501b5f31560bce8928d5 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 25 Aug 2025 19:14:37 -0600 Subject: [PATCH 17/97] Fix multiple subscribers test --- packages/apollo-angular/tests/QueryRef.spec.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/apollo-angular/tests/QueryRef.spec.ts b/packages/apollo-angular/tests/QueryRef.spec.ts index 1ffe838b1..341700b36 100644 --- a/packages/apollo-angular/tests/QueryRef.spec.ts +++ b/packages/apollo-angular/tests/QueryRef.spec.ts @@ -248,7 +248,8 @@ describe('QueryRef', () => { next: result => { calls.first++; - expect(result.data).toBeDefined(); + // Initial loading state + expect(result.data).not.toBeDefined(); }, error: e => { throw e; @@ -262,7 +263,8 @@ describe('QueryRef', () => { next: result => { calls.second++; - expect(result.data).toBeDefined(); + // Initial loading state + expect(result.data).not.toBeDefined(); setTimeout(() => { subSecond.unsubscribe(); From 2aaed544ea731dbe2fce9c43841148d5f3818d61 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 25 Aug 2025 19:22:06 -0600 Subject: [PATCH 18/97] Remove fromObservableQuery helper --- packages/apollo-angular/src/utils.ts | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/packages/apollo-angular/src/utils.ts b/packages/apollo-angular/src/utils.ts index 6c5ebb0e1..cc246d6e0 100644 --- a/packages/apollo-angular/src/utils.ts +++ b/packages/apollo-angular/src/utils.ts @@ -1,4 +1,11 @@ -import { Observable, queueScheduler, SchedulerAction, SchedulerLike, Subscription } from 'rxjs'; +import { + from, + Observable, + queueScheduler, + SchedulerAction, + SchedulerLike, + Subscription, +} from 'rxjs'; import { map, observeOn, startWith } from 'rxjs/operators'; import { NgZone } from '@angular/core'; import type { ApolloQueryResult, FetchResult, ObservableQuery } from '@apollo/client/core'; @@ -62,14 +69,6 @@ export class ZoneScheduler implements SchedulerLike { } } -export function fromObservableQuery( - obsQuery: ObservableQuery, -): Observable> { - return new Observable(subscriber => { - return obsQuery.subscribe(subscriber); - }); -} - export function wrapWithZone(obs: Observable, ngZone: NgZone): Observable { return obs.pipe(observeOn(new ZoneScheduler(ngZone))); } From decf8cfe18dd0f720dea8cd6563e0a28ef22fb96 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 25 Aug 2025 19:22:17 -0600 Subject: [PATCH 19/97] Fix queryRef tests --- .../apollo-angular/tests/QueryRef.spec.ts | 26 ++++++++++++------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/packages/apollo-angular/tests/QueryRef.spec.ts b/packages/apollo-angular/tests/QueryRef.spec.ts index 341700b36..2a81eca4d 100644 --- a/packages/apollo-angular/tests/QueryRef.spec.ts +++ b/packages/apollo-angular/tests/QueryRef.spec.ts @@ -23,7 +23,6 @@ const heroesOperation = { } `, variables: {}, - operationName: 'allHeroes', }; // tslint:disable:variable-name @@ -66,8 +65,10 @@ describe('QueryRef', () => { new Promise(done => { queryRef.valueChanges.subscribe({ next: result => { - expect(result.data).toBeDefined(); - done(); + if (result.dataState === 'complete') { + expect(result.data).toBeDefined(); + done(); + } }, error: e => { throw e; @@ -92,9 +93,11 @@ describe('QueryRef', () => { next: result => { calls++; - expect(result.data).toBeDefined(); + if (result.dataState === 'complete') { + expect(result.data).toBeDefined(); + } - if (calls === 2) { + if (calls === 4) { done(); } }, @@ -120,9 +123,10 @@ describe('QueryRef', () => { next: result => { calls++; - if (calls === 1) { + // loading -> data; refetch() -> loading -> data + if (calls === 2) { expect(result.heroes.length).toBe(1); - } else if (calls === 2) { + } else if (calls === 4) { expect(result.heroes.length).toBe(2); done(); @@ -160,10 +164,14 @@ describe('QueryRef', () => { obs.pipe(map(result => result.data)).subscribe({ next: result => { calls++; + const currentResult = queryRef.getCurrentResult(); - expect(currentResult.data.heroes.length).toBe(result.heroes.length); - if (calls === 2) { + if (currentResult.dataState === 'complete') { + expect(currentResult.data.heroes.length).toBe(result.heroes.length); + } + + if (calls === 4) { done(); } }, From 83607b9fe427ea5bf7c93a5c0903dbafa0166263 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 25 Aug 2025 19:27:08 -0600 Subject: [PATCH 20/97] Use MockLink instead of mockSingleLink --- packages/apollo-angular/tests/Apollo.spec.ts | 70 +++++++++---------- .../apollo-angular/tests/integration.spec.ts | 6 +- 2 files changed, 38 insertions(+), 38 deletions(-) diff --git a/packages/apollo-angular/tests/Apollo.spec.ts b/packages/apollo-angular/tests/Apollo.spec.ts index 7f676ad80..385ff8600 100644 --- a/packages/apollo-angular/tests/Apollo.spec.ts +++ b/packages/apollo-angular/tests/Apollo.spec.ts @@ -3,8 +3,8 @@ import { mergeMap } from 'rxjs/operators'; import { beforeEach, describe, expect, test, vi } from 'vitest'; import { NgZone } from '@angular/core'; import { TestBed } from '@angular/core/testing'; -import { ApolloLink, InMemoryCache, NetworkStatus } from "@apollo/client"; -import { mockSingleLink } from "@apollo/client/v4-migration"; +import { ApolloLink, InMemoryCache, NetworkStatus } from '@apollo/client'; +import { MockLink } from '@apollo/client/testing'; import { Apollo, ApolloBase } from '../src/apollo'; import { gql } from '../src/gql'; import { ZoneScheduler } from '../src/utils'; @@ -40,7 +40,7 @@ describe('Apollo', () => { const apollo = new Apollo(ngZone); apollo.create({ - link: mockSingleLink(), + link: new MockLink([]), cache: new InMemoryCache(), }); @@ -55,7 +55,7 @@ describe('Apollo', () => { apollo.create( { - link: mockSingleLink(), + link: new MockLink([]), cache: new InMemoryCache(), }, 'extra', @@ -71,7 +71,7 @@ describe('Apollo', () => { const apollo = new Apollo(ngZone); apollo.create({ - link: mockSingleLink(), + link: new MockLink([]), cache: new InMemoryCache(), }); @@ -108,7 +108,7 @@ describe('Apollo', () => { const data2 = { heroes: [{ name: 'Bar', __typename: 'Hero' }] }; const variables2 = { first: 1 }; - const link = mockSingleLink( + const link = new MockLink([ { request: { query, variables: variables1 }, result: { data: data1 }, @@ -117,7 +117,7 @@ describe('Apollo', () => { request: { query, variables: variables2 }, result: { data: data2 }, }, - ); + ]); const apollo = mockApollo(link, ngZone); const options = { query, variables: variables1 }; @@ -166,7 +166,7 @@ describe('Apollo', () => { const apollo = new Apollo(ngZone); apollo.create({ - link: mockSingleLink(), + link: new MockLink([]), cache: new InMemoryCache(), }); @@ -195,7 +195,7 @@ describe('Apollo', () => { const apollo = new Apollo(ngZone); apollo.create({ - link: mockSingleLink(), + link: new MockLink([]), cache: new InMemoryCache(), }); @@ -235,7 +235,7 @@ describe('Apollo', () => { const apollo = new Apollo(ngZone); apollo.create({ - link: mockSingleLink(), + link: new MockLink([]), cache: new InMemoryCache(), }); @@ -278,7 +278,7 @@ describe('Apollo', () => { // create apollo.create({ - link: mockSingleLink({ request: { query }, result: { data } }), + link: new MockLink([{ request: { query }, result: { data } }]), cache: new InMemoryCache(), }); @@ -309,7 +309,7 @@ describe('Apollo', () => { const apollo = new Apollo(ngZone); apollo.create({ - link: mockSingleLink(), + link: new MockLink([]), cache: new InMemoryCache(), }); @@ -353,7 +353,7 @@ describe('Apollo', () => { const apollo = new Apollo(ngZone); apollo.create({ - link: mockSingleLink(), + link: new MockLink([]), cache: new InMemoryCache(), }); @@ -393,7 +393,7 @@ describe('Apollo', () => { const apollo = new Apollo(ngZone); apollo.create({ - link: mockSingleLink(), + link: new MockLink([]), cache: new InMemoryCache(), }); @@ -440,7 +440,7 @@ describe('Apollo', () => { }; apollo.create({ - link: mockSingleLink( + link: new MockLink([ { request: op1, result: { data: data1 }, @@ -449,7 +449,7 @@ describe('Apollo', () => { request: op2, result: { data: data2 }, }, - ), + ]), cache: new InMemoryCache(), }); @@ -493,7 +493,7 @@ describe('Apollo', () => { // create apollo.create({ - link: mockSingleLink({ request: { query }, result: { data } }), + link: new MockLink([{ request: { query }, result: { data } }]), cache: new InMemoryCache(), }); @@ -539,7 +539,7 @@ describe('Apollo', () => { // create apollo.create({ - link: mockSingleLink({ request: { query }, result: { data } }), + link: new MockLink([{ request: { query }, result: { data } }]), cache: new InMemoryCache(), }); @@ -576,7 +576,7 @@ describe('Apollo', () => { const apollo = new Apollo(ngZone); apollo.create({ - link: mockSingleLink(), + link: new MockLink([]), cache: new InMemoryCache(), }); @@ -609,7 +609,7 @@ describe('Apollo', () => { const apollo = new Apollo(ngZone); apollo.create({ - link: mockSingleLink(), + link: new MockLink([]), cache: new InMemoryCache(), }); @@ -628,7 +628,7 @@ describe('Apollo', () => { const apollo = new Apollo(ngZone); apollo.create({ - link: mockSingleLink(), + link: new MockLink([]), cache: new InMemoryCache(), }); @@ -649,7 +649,7 @@ describe('Apollo', () => { const apollo = new Apollo(ngZone); apollo.create({ - link: mockSingleLink(), + link: new MockLink([]), cache: new InMemoryCache(), }); @@ -707,7 +707,7 @@ describe('Apollo', () => { const dataMutation = { addHero: BarHero }; const data2 = { allHeroes: [FooHero, BarHero] }; - const link = mockSingleLink( + const link = new MockLink([ { request: { query }, result: { data: data1 }, @@ -716,7 +716,7 @@ describe('Apollo', () => { request: { query: mutation, variables }, result: { data: dataMutation }, }, - ); + ]); const apollo = mockApollo(link, ngZone); const obs = apollo.watchQuery({ query }); @@ -788,7 +788,7 @@ describe('Apollo', () => { const data2 = { allHeroes: [FooHero, OptimisticHero] }; const data3 = { allHeroes: [FooHero, BarHero] }; - const link = mockSingleLink( + const link = new MockLink([ { request: { query }, result: { data: data1 }, @@ -797,7 +797,7 @@ describe('Apollo', () => { request: { query: mutation, variables }, result: { data: dataMutation }, }, - ); + ]); const apollo = mockApollo(link, ngZone); const obs = apollo.watchQuery({ query }); @@ -865,7 +865,7 @@ describe('Apollo', () => { // create apollo.create({ - link: mockSingleLink({ request: op, result: { data } }), + link: new MockLink([{ request: op, result: { data } }]), cache: new InMemoryCache(), }); @@ -906,7 +906,7 @@ describe('Apollo', () => { // create apollo.create({ - link: mockSingleLink({ request: { query }, result: { data } }), + link: new MockLink([{ request: { query }, result: { data } }]), cache: new InMemoryCache(), }); @@ -967,7 +967,7 @@ describe('Apollo', () => { // create apollo.create({ - link: mockSingleLink({ request: { query }, result: { data } }), + link: new MockLink([{ request: { query }, result: { data } }]), cache, }); @@ -1030,7 +1030,7 @@ describe('Apollo', () => { // create apollo.create({ - link: mockSingleLink({ request: { query }, result: { data } }), + link: new MockLink([{ request: { query }, result: { data } }]), cache, }); @@ -1061,11 +1061,11 @@ describe('Apollo', () => { test('should create default client with named options', () => { const apollo = new Apollo(ngZone, undefined, { default: { - link: mockSingleLink(), + link: new MockLink([]), cache: new InMemoryCache(), }, test: { - link: mockSingleLink(), + link: new MockLink([]), cache: new InMemoryCache(), }, }); @@ -1075,7 +1075,7 @@ describe('Apollo', () => { }); test('should remove default client', () => { - const apollo = mockApollo(mockSingleLink(), ngZone); + const apollo = mockApollo(new MockLink([]), ngZone); expect(apollo.client).toBeDefined(); @@ -1085,10 +1085,10 @@ describe('Apollo', () => { }); test('should remove named client', () => { - const apollo = mockApollo(mockSingleLink(), ngZone); + const apollo = mockApollo(new MockLink([]), ngZone); apollo.createNamed('test', { - link: mockSingleLink(), + link: new MockLink([]), cache: new InMemoryCache(), }); diff --git a/packages/apollo-angular/tests/integration.spec.ts b/packages/apollo-angular/tests/integration.spec.ts index d7e32a103..b07264c32 100644 --- a/packages/apollo-angular/tests/integration.spec.ts +++ b/packages/apollo-angular/tests/integration.spec.ts @@ -1,8 +1,8 @@ import { beforeEach, describe, expect, test } from 'vitest'; import { provideHttpClient } from '@angular/common/http'; import { TestBed } from '@angular/core/testing'; -import { InMemoryCache } from "@apollo/client"; -import { mockSingleLink } from "@apollo/client/v4-migration"; +import { InMemoryCache } from '@apollo/client'; +import { MockLink } from '@apollo/client/testing'; import { Apollo, provideApollo } from '../src'; describe('Integration', () => { @@ -13,7 +13,7 @@ describe('Integration', () => { provideHttpClient(), provideApollo(() => { return { - link: mockSingleLink(), + link: new MockLink([]), cache: new InMemoryCache(), }; }), From d5fe5f2db5faa6a88fc27e58bb1887abefc4af87 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 25 Aug 2025 19:32:56 -0600 Subject: [PATCH 21/97] Update Apollo class with updated option types --- packages/apollo-angular/src/apollo.ts | 61 ++++++++++++--------------- 1 file changed, 26 insertions(+), 35 deletions(-) diff --git a/packages/apollo-angular/src/apollo.ts b/packages/apollo-angular/src/apollo.ts index a439332f9..8e9a1a799 100644 --- a/packages/apollo-angular/src/apollo.ts +++ b/packages/apollo-angular/src/apollo.ts @@ -1,16 +1,7 @@ import { Observable } from 'rxjs'; import { Inject, Injectable, NgZone, Optional } from '@angular/core'; -import type { - ApolloClientOptions, - ApolloQueryResult, - FetchResult, - ObservableQuery, - OperationVariables, - QueryOptions, - SubscriptionOptions, - WatchFragmentResult, -} from '@apollo/client/core'; -import { ApolloClient } from '@apollo/client/core'; +import type { ApolloCache, ObservableQuery, OperationVariables } from '@apollo/client'; +import { ApolloClient } from '@apollo/client'; import { QueryRef } from './query-ref'; import { APOLLO_FLAGS, APOLLO_NAMED_OPTIONS, APOLLO_OPTIONS } from './tokens'; import type { @@ -25,13 +16,13 @@ import type { } from './types'; import { fromLazyPromise, useMutationLoading, wrapWithZone } from './utils'; -export class ApolloBase { +export class ApolloBase { private useMutationLoading: boolean; constructor( protected readonly ngZone: NgZone, protected readonly flags?: Flags, - protected _client?: ApolloClient, + protected _client?: ApolloClient, ) { this.useMutationLoading = flags?.useMutationLoading ?? false; } @@ -48,9 +39,9 @@ export class ApolloBase { } public query( - options: QueryOptions, - ): Observable> { - return fromLazyPromise>(() => + options: ApolloClient.QueryOptions, + ): Observable> { + return fromLazyPromise>(() => this.ensureClient().query({ ...options }), ); } @@ -70,16 +61,16 @@ export class ApolloBase { >( options: WatchFragmentOptions, extra?: ExtraSubscriptionOptions, - ): Observable> { + ): Observable> { const obs = this.ensureClient().watchFragment({ ...options }); return extra && extra.useZone !== true ? obs : wrapWithZone(obs, this.ngZone); } public subscribe( - options: SubscriptionOptions, + options: ApolloClient.SubscribeOptions, extra?: ExtraSubscriptionOptions, - ): Observable> { + ): Observable> { const obs = this.ensureClient().subscribe({ ...options }); return extra && extra.useZone !== true ? obs : wrapWithZone(obs, this.ngZone); @@ -88,7 +79,7 @@ export class ApolloBase { /** * Get an instance of ApolloClient */ - public get client(): ApolloClient { + public get client(): ApolloClient { return this.ensureClient(); } @@ -98,7 +89,7 @@ export class ApolloBase { * * @param client ApolloClient instance */ - public set client(client: ApolloClient) { + public set client(client: ApolloClient) { if (this._client) { throw new Error('Client has been already defined'); } @@ -106,13 +97,13 @@ export class ApolloBase { this._client = client; } - private ensureClient(): ApolloClient { + private ensureClient(): ApolloClient { this.checkInstance(); return this._client!; } - private checkInstance(): this is { _client: ApolloClient } { + private checkInstance(): this is { _client: ApolloClient } { if (this._client) { return true; } else { @@ -122,14 +113,14 @@ export class ApolloBase { } @Injectable() -export class Apollo extends ApolloBase { - private map: Map> = new Map>(); +export class Apollo extends ApolloBase { + private map: Map = new Map(); constructor( ngZone: NgZone, @Optional() @Inject(APOLLO_OPTIONS) - apolloOptions?: ApolloClientOptions, + apolloOptions?: ApolloClient.Options, @Inject(APOLLO_NAMED_OPTIONS) @Optional() apolloNamedOptions?: NamedOptions, @Inject(APOLLO_FLAGS) @Optional() flags?: Flags, ) { @@ -154,18 +145,18 @@ export class Apollo extends ApolloBase { * @param options Options required to create ApolloClient * @param name client's name */ - public create(options: ApolloClientOptions, name?: string): void { + public create(options: ApolloClient.Options, name?: string): void { if (isNamed(name)) { - this.createNamed(name, options); + this.createNamed(name, options); } else { - this.createDefault(options); + this.createDefault(options); } } /** * Use a default ApolloClient */ - public default(): ApolloBase { + public default(): ApolloBase { return this; } @@ -173,7 +164,7 @@ export class Apollo extends ApolloBase { * Use a named ApolloClient * @param name client's name */ - public use(name: string): ApolloBase { + public use(name: string): ApolloBase { if (isNamed(name)) { return this.map.get(name)!; } else { @@ -185,12 +176,12 @@ export class Apollo extends ApolloBase { * Create a default ApolloClient, same as `apollo.create(options)` * @param options ApolloClient's options */ - public createDefault(options: ApolloClientOptions): void { + public createDefault(options: ApolloClient.Options): void { if (this._client) { throw new Error('Apollo has been already created.'); } - this.client = this.ngZone.runOutsideAngular(() => new ApolloClient(options)); + this.client = this.ngZone.runOutsideAngular(() => new ApolloClient(options)); } /** @@ -198,7 +189,7 @@ export class Apollo extends ApolloBase { * @param name client's name * @param options ApolloClient's options */ - public createNamed(name: string, options: ApolloClientOptions): void { + public createNamed(name: string, options: ApolloClient.Options): void { if (this.map.has(name)) { throw new Error(`Client ${name} has been already created`); } @@ -207,7 +198,7 @@ export class Apollo extends ApolloBase { new ApolloBase( this.ngZone, this.flags, - this.ngZone.runOutsideAngular(() => new ApolloClient(options)), + this.ngZone.runOutsideAngular(() => new ApolloClient(options)), ), ); } From 4b0e5ff5bce6d32f07448d9ce0dbba0104f74904 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 25 Aug 2025 19:45:27 -0600 Subject: [PATCH 22/97] Remove unneeded generics in testing module --- packages/apollo-angular/testing/src/module.ts | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/packages/apollo-angular/testing/src/module.ts b/packages/apollo-angular/testing/src/module.ts index ffb2e8c7f..9269d0cd1 100644 --- a/packages/apollo-angular/testing/src/module.ts +++ b/packages/apollo-angular/testing/src/module.ts @@ -1,15 +1,13 @@ import { Apollo } from 'apollo-angular'; import { Inject, InjectionToken, NgModule, Optional } from '@angular/core'; -import { ApolloCache, ApolloLink, InMemoryCache } from "@apollo/client"; +import { ApolloCache, ApolloLink, InMemoryCache } from '@apollo/client'; import { ApolloTestingBackend } from './backend'; import { ApolloTestingController } from './controller'; import { Operation } from './operation'; -export type NamedCaches = Record | undefined | null>; +export type NamedCaches = Record; -export const APOLLO_TESTING_CACHE = new InjectionToken>( - 'apollo-angular/testing cache', -); +export const APOLLO_TESTING_CACHE = new InjectionToken('apollo-angular/testing cache'); export const APOLLO_TESTING_NAMED_CACHE = new InjectionToken( 'apollo-angular/testing named cache', @@ -41,12 +39,12 @@ export class ApolloTestingModuleCore { namedClients?: string[], @Optional() @Inject(APOLLO_TESTING_CACHE) - cache?: ApolloCache, + cache?: ApolloCache, @Optional() @Inject(APOLLO_TESTING_NAMED_CACHE) namedCaches?: NamedCaches, ) { - function createOptions(name: string, c?: ApolloCache | null) { + function createOptions(name: string, c?: ApolloCache | null) { return { connectToDevTools: false, link: new ApolloLink(operation => backend.handle(addClient(name, operation))), From 1f670f87657020169c459bda18ea096aa17c1a17 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 25 Aug 2025 19:51:02 -0600 Subject: [PATCH 23/97] Adjust types to use DefaultContext --- packages/apollo-angular/http/src/types.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/apollo-angular/http/src/types.ts b/packages/apollo-angular/http/src/types.ts index fb26bdddb..57592751a 100644 --- a/packages/apollo-angular/http/src/types.ts +++ b/packages/apollo-angular/http/src/types.ts @@ -1,6 +1,10 @@ import { DocumentNode } from 'graphql'; import { HttpHeaders } from '@angular/common/http'; -import { ApolloLink } from "@apollo/client"; +import { ApolloLink } from '@apollo/client'; + +declare module '@apollo/client' { + export interface DefaultContext extends Context {} +} export type HttpRequestOptions = { headers?: HttpHeaders; From 39f7be859a176c154221224f1bc986f91f87c315 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 25 Aug 2025 19:53:26 -0600 Subject: [PATCH 24/97] Adjust some types for HttpLink --- packages/apollo-angular/http/src/http-batch-link.ts | 9 ++++++--- packages/apollo-angular/http/src/http-link.ts | 6 +++--- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/packages/apollo-angular/http/src/http-batch-link.ts b/packages/apollo-angular/http/src/http-batch-link.ts index 65c1babce..97019ce55 100644 --- a/packages/apollo-angular/http/src/http-batch-link.ts +++ b/packages/apollo-angular/http/src/http-batch-link.ts @@ -2,7 +2,7 @@ import { print } from 'graphql'; import { Observable } from 'rxjs'; import { HttpClient, HttpHeaders } from '@angular/common/http'; import { Injectable } from '@angular/core'; -import { ApolloLink } from "@apollo/client"; +import { ApolloLink } from '@apollo/client'; import { BatchLink } from '@apollo/client/link/batch'; import { BatchOptions, Body, Context, OperationPrinter, Options, Request } from './types'; import { createHeadersWithClientAwareness, fetch, mergeHeaders, prioritize } from './utils'; @@ -171,8 +171,11 @@ export class HttpBatchLinkHandler extends ApolloLink { return prioritize(context.uri, this.options.uri, '') + opts; } - public request(op: ApolloLink.Operation): Observable | null { - return this.batcher.request(op); + public request( + op: ApolloLink.Operation, + forward: ApolloLink.ForwardFunction, + ): Observable { + return this.batcher.request(op, forward); } } diff --git a/packages/apollo-angular/http/src/http-link.ts b/packages/apollo-angular/http/src/http-link.ts index 0a2d2faa4..5048de9c7 100644 --- a/packages/apollo-angular/http/src/http-link.ts +++ b/packages/apollo-angular/http/src/http-link.ts @@ -2,14 +2,14 @@ import { print } from 'graphql'; import { Observable } from 'rxjs'; import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; -import { ApolloLink } from "@apollo/client"; +import { ApolloLink } from '@apollo/client'; import { pick } from './http-batch-link'; import { Body, Context, OperationPrinter, Options, Request } from './types'; import { createHeadersWithClientAwareness, fetch, mergeHeaders } from './utils'; // XXX find a better name for it export class HttpLinkHandler extends ApolloLink { - public requester: (operation: ApolloLink.Operation) => Observable | null; + public requester: (operation: ApolloLink.Operation) => Observable; private print: OperationPrinter = print; constructor( @@ -85,7 +85,7 @@ export class HttpLinkHandler extends ApolloLink { }); } - public request(op: ApolloLink.Operation): Observable | null { + public request(op: ApolloLink.Operation): Observable { return this.requester(op); } } From 2d66be6bc7e5a3763241becd7539a100eaf9baed Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 25 Aug 2025 19:54:21 -0600 Subject: [PATCH 25/97] Remove some generics --- packages/apollo-angular/tests/Apollo.spec.ts | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/packages/apollo-angular/tests/Apollo.spec.ts b/packages/apollo-angular/tests/Apollo.spec.ts index 385ff8600..3fdd6b960 100644 --- a/packages/apollo-angular/tests/Apollo.spec.ts +++ b/packages/apollo-angular/tests/Apollo.spec.ts @@ -277,7 +277,7 @@ describe('Apollo', () => { }; // create - apollo.create({ + apollo.create({ link: new MockLink([{ request: { query }, result: { data } }]), cache: new InMemoryCache(), }); @@ -289,7 +289,6 @@ describe('Apollo', () => { }) .subscribe({ next: result => { - expect(result.loading).toBe(false); expect(result.data).toMatchObject(data); setTimeout(() => { return done(); @@ -492,7 +491,7 @@ describe('Apollo', () => { }; // create - apollo.create({ + apollo.create({ link: new MockLink([{ request: { query }, result: { data } }]), cache: new InMemoryCache(), }); @@ -538,7 +537,7 @@ describe('Apollo', () => { let alreadyCalled = false; // create - apollo.create({ + apollo.create({ link: new MockLink([{ request: { query }, result: { data } }]), cache: new InMemoryCache(), }); @@ -864,7 +863,7 @@ describe('Apollo', () => { }; // create - apollo.create({ + apollo.create({ link: new MockLink([{ request: op, result: { data } }]), cache: new InMemoryCache(), }); @@ -905,7 +904,7 @@ describe('Apollo', () => { let alreadyCalled = false; // create - apollo.create({ + apollo.create({ link: new MockLink([{ request: { query }, result: { data } }]), cache: new InMemoryCache(), }); @@ -966,7 +965,7 @@ describe('Apollo', () => { }); // create - apollo.create({ + apollo.create({ link: new MockLink([{ request: { query }, result: { data } }]), cache, }); @@ -1029,7 +1028,7 @@ describe('Apollo', () => { }); // create - apollo.create({ + apollo.create({ link: new MockLink([{ request: { query }, result: { data } }]), cache, }); From 2633f3a17ab1daa83852bb2f0eec5960b6c481be Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 25 Aug 2025 20:00:19 -0600 Subject: [PATCH 26/97] Update HttpLink/BatchHttpLink tests --- .../http/tests/http-batch-link.spec.ts | 25 +++++++++++-------- .../http/tests/http-link.spec.ts | 14 ++++++++++- 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/packages/apollo-angular/http/tests/http-batch-link.spec.ts b/packages/apollo-angular/http/tests/http-batch-link.spec.ts index f369e34d2..784d69fde 100644 --- a/packages/apollo-angular/http/tests/http-batch-link.spec.ts +++ b/packages/apollo-angular/http/tests/http-batch-link.spec.ts @@ -2,13 +2,25 @@ import { afterEach, beforeEach, describe, expect, test } from 'vitest'; import { HttpHeaders, provideHttpClient } from '@angular/common/http'; import { HttpTestingController, provideHttpClientTesting } from '@angular/common/http/testing'; import { TestBed } from '@angular/core/testing'; -import { ApolloLink, execute, gql } from "@apollo/client"; +import { + ApolloClient, + ApolloLink, + execute as executeLink, + gql, + InMemoryCache, +} from '@apollo/client'; import { HttpBatchLink } from '../src/http-batch-link'; const noop = () => { // }; +function execute(link: ApolloLink, request: ApolloLink.Request) { + return executeLink(link, request, { + client: new ApolloClient({ cache: new InMemoryCache(), link: ApolloLink.empty() }), + }); +} + describe('HttpBatchLink', () => { let httpLink: HttpBatchLink; let httpBackend: HttpTestingController; @@ -534,7 +546,6 @@ describe('HttpBatchLink', () => { variables: { first: 5, }, - operationName: 'op1', }).subscribe(noop); execute(link, { query: gql` @@ -544,7 +555,6 @@ describe('HttpBatchLink', () => { } } `, - operationName: 'op2', }).subscribe(noop); setTimeout(() => { @@ -571,7 +581,8 @@ describe('HttpBatchLink', () => { new Promise(done => { const link = httpLink.create({ uri: 'graphql', - batchKey: (operation: ApolloLink.Operation) => operation.getContext().uri || 'graphql', + batchKey: (operation: ApolloLink.Operation) => + (operation.getContext().uri as string) || 'graphql', }); execute(link, { @@ -582,7 +593,6 @@ describe('HttpBatchLink', () => { } } `, - operationName: 'op1', }).subscribe(noop); execute(link, { @@ -593,7 +603,6 @@ describe('HttpBatchLink', () => { } } `, - operationName: 'op2', context: { uri: 'gql', }, @@ -639,7 +648,6 @@ describe('HttpBatchLink', () => { } } `, - operationName: 'op1', }).subscribe(noop); execute(link, { @@ -650,7 +658,6 @@ describe('HttpBatchLink', () => { } } `, - operationName: 'op2', context: { uri: 'gql', }, @@ -698,7 +705,6 @@ describe('HttpBatchLink', () => { } } `, - operationName: 'op1', }).subscribe(noop); execute(link, { @@ -709,7 +715,6 @@ describe('HttpBatchLink', () => { } } `, - operationName: 'op2', context: { skipBatching: true, }, diff --git a/packages/apollo-angular/http/tests/http-link.spec.ts b/packages/apollo-angular/http/tests/http-link.spec.ts index 61d3cb411..6b54f501c 100644 --- a/packages/apollo-angular/http/tests/http-link.spec.ts +++ b/packages/apollo-angular/http/tests/http-link.spec.ts @@ -4,7 +4,13 @@ import { afterEach, beforeEach, describe, expect, test } from 'vitest'; import { HttpHeaders, provideHttpClient } from '@angular/common/http'; import { HttpTestingController, provideHttpClientTesting } from '@angular/common/http/testing'; import { TestBed } from '@angular/core/testing'; -import { ApolloLink, execute, gql, InMemoryCache } from "@apollo/client"; +import { + ApolloClient, + ApolloLink, + execute as executeLink, + gql, + InMemoryCache, +} from '@apollo/client'; import { Apollo } from '../../src'; import { HttpLink } from '../src/http-link'; @@ -12,6 +18,12 @@ const noop = () => { // }; +function execute(link: ApolloLink, request: ApolloLink.Request) { + return executeLink(link, request, { + client: new ApolloClient({ cache: new InMemoryCache(), link: ApolloLink.empty() }), + }); +} + describe('HttpLink', () => { let httpLink: HttpLink; let httpBackend: HttpTestingController; From 41c777c606ea25ebb224b66bdadea535f69f4a69 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 25 Aug 2025 20:03:41 -0600 Subject: [PATCH 27/97] Extract helper execute function --- .../http/tests/http-batch-link.spec.ts | 15 ++------------- .../http/tests/http-link.spec.ts | 15 ++------------- .../apollo-angular/http/tests/ssr.spec.ts | 3 ++- packages/apollo-angular/http/tests/utils.ts | 19 +++++++++++++++++++ 4 files changed, 25 insertions(+), 27 deletions(-) create mode 100644 packages/apollo-angular/http/tests/utils.ts diff --git a/packages/apollo-angular/http/tests/http-batch-link.spec.ts b/packages/apollo-angular/http/tests/http-batch-link.spec.ts index 784d69fde..ba498389e 100644 --- a/packages/apollo-angular/http/tests/http-batch-link.spec.ts +++ b/packages/apollo-angular/http/tests/http-batch-link.spec.ts @@ -2,25 +2,14 @@ import { afterEach, beforeEach, describe, expect, test } from 'vitest'; import { HttpHeaders, provideHttpClient } from '@angular/common/http'; import { HttpTestingController, provideHttpClientTesting } from '@angular/common/http/testing'; import { TestBed } from '@angular/core/testing'; -import { - ApolloClient, - ApolloLink, - execute as executeLink, - gql, - InMemoryCache, -} from '@apollo/client'; +import { ApolloLink, gql } from '@apollo/client'; import { HttpBatchLink } from '../src/http-batch-link'; +import { executeWithDefaultContext as execute } from './utils'; const noop = () => { // }; -function execute(link: ApolloLink, request: ApolloLink.Request) { - return executeLink(link, request, { - client: new ApolloClient({ cache: new InMemoryCache(), link: ApolloLink.empty() }), - }); -} - describe('HttpBatchLink', () => { let httpLink: HttpBatchLink; let httpBackend: HttpTestingController; diff --git a/packages/apollo-angular/http/tests/http-link.spec.ts b/packages/apollo-angular/http/tests/http-link.spec.ts index 6b54f501c..36516b20e 100644 --- a/packages/apollo-angular/http/tests/http-link.spec.ts +++ b/packages/apollo-angular/http/tests/http-link.spec.ts @@ -4,26 +4,15 @@ import { afterEach, beforeEach, describe, expect, test } from 'vitest'; import { HttpHeaders, provideHttpClient } from '@angular/common/http'; import { HttpTestingController, provideHttpClientTesting } from '@angular/common/http/testing'; import { TestBed } from '@angular/core/testing'; -import { - ApolloClient, - ApolloLink, - execute as executeLink, - gql, - InMemoryCache, -} from '@apollo/client'; +import { ApolloLink, gql, InMemoryCache } from '@apollo/client'; import { Apollo } from '../../src'; import { HttpLink } from '../src/http-link'; +import { executeWithDefaultContext as execute } from './utils'; const noop = () => { // }; -function execute(link: ApolloLink, request: ApolloLink.Request) { - return executeLink(link, request, { - client: new ApolloClient({ cache: new InMemoryCache(), link: ApolloLink.empty() }), - }); -} - describe('HttpLink', () => { let httpLink: HttpLink; let httpBackend: HttpTestingController; diff --git a/packages/apollo-angular/http/tests/ssr.spec.ts b/packages/apollo-angular/http/tests/ssr.spec.ts index 189682e00..6f6e4cf30 100644 --- a/packages/apollo-angular/http/tests/ssr.spec.ts +++ b/packages/apollo-angular/http/tests/ssr.spec.ts @@ -10,8 +10,9 @@ import { renderModule, ServerModule, } from '@angular/platform-server'; -import { execute, gql } from "@apollo/client"; +import { gql } from '@apollo/client'; import { HttpLink } from '../src/http-link'; +import { executeWithDefaultContext as execute } from './utils'; describe.skip('integration', () => { let doc: string; diff --git a/packages/apollo-angular/http/tests/utils.ts b/packages/apollo-angular/http/tests/utils.ts new file mode 100644 index 000000000..177efa97c --- /dev/null +++ b/packages/apollo-angular/http/tests/utils.ts @@ -0,0 +1,19 @@ +import { Observable } from 'rxjs'; +import { ApolloClient, ApolloLink, execute, InMemoryCache } from '@apollo/client'; + +export function createDefaultExecuteContext(): ApolloLink.ExecuteContext { + return { + client: new ApolloClient({ + cache: new InMemoryCache(), + link: ApolloLink.empty(), + }), + }; +} + +export function executeWithDefaultContext( + link: ApolloLink, + request: ApolloLink.Request, + context: ApolloLink.ExecuteContext = createDefaultExecuteContext(), +): Observable { + return execute(link, request, context); +} From 11e30940f168cf341a8c5febefdc47e4c2253526 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 25 Aug 2025 20:08:56 -0600 Subject: [PATCH 28/97] Remove unneeded cast --- packages/apollo-angular/src/apollo.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/apollo-angular/src/apollo.ts b/packages/apollo-angular/src/apollo.ts index 8e9a1a799..5cab08238 100644 --- a/packages/apollo-angular/src/apollo.ts +++ b/packages/apollo-angular/src/apollo.ts @@ -1,6 +1,6 @@ import { Observable } from 'rxjs'; import { Inject, Injectable, NgZone, Optional } from '@angular/core'; -import type { ApolloCache, ObservableQuery, OperationVariables } from '@apollo/client'; +import type { ApolloCache, OperationVariables } from '@apollo/client'; import { ApolloClient } from '@apollo/client'; import { QueryRef } from './query-ref'; import { APOLLO_FLAGS, APOLLO_NAMED_OPTIONS, APOLLO_OPTIONS } from './tokens'; @@ -33,7 +33,7 @@ export class ApolloBase { return new QueryRef( this.ensureClient().watchQuery({ ...options, - }) as ObservableQuery, + }), this.ngZone, ); } From d677d7564cf6a5c24f752ed4e3639e67a75f80f7 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 25 Aug 2025 20:09:14 -0600 Subject: [PATCH 29/97] Fix some operation type variables --- packages/apollo-angular/src/mutation.ts | 4 ++-- packages/apollo-angular/src/query.ts | 11 +++++++---- packages/apollo-angular/src/subscription.ts | 4 ++-- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/packages/apollo-angular/src/mutation.ts b/packages/apollo-angular/src/mutation.ts index 09932349f..8074f21b6 100644 --- a/packages/apollo-angular/src/mutation.ts +++ b/packages/apollo-angular/src/mutation.ts @@ -1,7 +1,7 @@ import type { DocumentNode } from 'graphql'; import type { Observable } from 'rxjs'; import { Injectable } from '@angular/core'; -import type { OperationVariables, TypedDocumentNode } from "@apollo/client"; +import type { OperationVariables, TypedDocumentNode } from '@apollo/client'; import { Apollo } from './apollo'; import type { EmptyObject, MutationOptionsAlone, MutationResult } from './types'; @@ -18,7 +18,7 @@ export abstract class Mutation> { return this.apollo.use(this.client).mutate({ ...options, - variables, + variables: variables as V, mutation: this.document, }); } diff --git a/packages/apollo-angular/src/query.ts b/packages/apollo-angular/src/query.ts index 803eee60d..3db7833d5 100644 --- a/packages/apollo-angular/src/query.ts +++ b/packages/apollo-angular/src/query.ts @@ -1,7 +1,7 @@ import type { DocumentNode } from 'graphql'; import type { Observable } from 'rxjs'; import { Injectable } from '@angular/core'; -import type { OperationVariables, TypedDocumentNode, ObservableQuery } from "@apollo/client"; +import type { ApolloClient, OperationVariables, TypedDocumentNode } from '@apollo/client'; import { Apollo } from './apollo'; import { QueryRef } from './query-ref'; import { EmptyObject, QueryOptionsAlone, WatchQueryOptionsAlone } from './types'; @@ -16,15 +16,18 @@ export abstract class Query public watch(variables?: V, options?: WatchQueryOptionsAlone): QueryRef { return this.apollo.use(this.client).watchQuery({ ...options, - variables, + variables: variables as V, query: this.document, }); } - public fetch(variables?: V, options?: QueryOptionsAlone): Observable> { + public fetch( + variables?: V, + options?: QueryOptionsAlone, + ): Observable> { return this.apollo.use(this.client).query({ ...options, - variables, + variables: variables as V, query: this.document, }); } diff --git a/packages/apollo-angular/src/subscription.ts b/packages/apollo-angular/src/subscription.ts index cf747bd99..09b1db8ad 100644 --- a/packages/apollo-angular/src/subscription.ts +++ b/packages/apollo-angular/src/subscription.ts @@ -1,7 +1,7 @@ import type { DocumentNode } from 'graphql'; import type { Observable } from 'rxjs'; import { Injectable } from '@angular/core'; -import type { OperationVariables, TypedDocumentNode, ApolloLink } from "@apollo/client"; +import type { ApolloLink, OperationVariables, TypedDocumentNode } from '@apollo/client'; import { Apollo } from './apollo'; import { EmptyObject, ExtraSubscriptionOptions, SubscriptionOptionsAlone } from './types'; @@ -20,7 +20,7 @@ export abstract class Subscription( { ...options, - variables, + variables: variables as V, query: this.document, }, extra, From 0588682f4a5f6273c7615f19bbc84849bfb989e3 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 25 Aug 2025 20:09:27 -0600 Subject: [PATCH 30/97] Update utils with updated types --- packages/apollo-angular/src/utils.ts | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/packages/apollo-angular/src/utils.ts b/packages/apollo-angular/src/utils.ts index cc246d6e0..17ed5a1f6 100644 --- a/packages/apollo-angular/src/utils.ts +++ b/packages/apollo-angular/src/utils.ts @@ -1,14 +1,7 @@ -import { - from, - Observable, - queueScheduler, - SchedulerAction, - SchedulerLike, - Subscription, -} from 'rxjs'; +import { Observable, queueScheduler, SchedulerAction, SchedulerLike, Subscription } from 'rxjs'; import { map, observeOn, startWith } from 'rxjs/operators'; import { NgZone } from '@angular/core'; -import type { ApolloQueryResult, FetchResult, ObservableQuery } from '@apollo/client/core'; +import type { ApolloClient } from '@apollo/client'; import { MutationResult } from './types'; /** @@ -34,10 +27,13 @@ export function fromLazyPromise(promiseFn: () => Promise): Observable { }); } -export function useMutationLoading(source: Observable>, enabled: boolean) { +export function useMutationLoading( + source: Observable>, + enabled: boolean, +) { if (!enabled) { return source.pipe( - map, MutationResult>(result => ({ + map, MutationResult>(result => ({ ...result, loading: false, })), From 1b3039883a368820a68c9595db72c4d07bcd23d4 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 25 Aug 2025 20:21:00 -0600 Subject: [PATCH 31/97] Add reobserve to QueryRef --- packages/apollo-angular/src/query-ref.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/apollo-angular/src/query-ref.ts b/packages/apollo-angular/src/query-ref.ts index 6d51c1ad7..90f4d0913 100644 --- a/packages/apollo-angular/src/query-ref.ts +++ b/packages/apollo-angular/src/query-ref.ts @@ -84,4 +84,10 @@ export class QueryRef['setVariables']> { return this.obsQuery.setVariables(variables); } + + public reobserve( + options: ObservableQuery.Options, + ): ReturnType['reobserve']> { + return this.obsQuery.reobserve(options); + } } From 341e8c0a0b37d014eced488142690e07d03a0a5d Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 25 Aug 2025 20:23:10 -0600 Subject: [PATCH 32/97] Use SubscribeResult --- packages/apollo-angular/src/subscription.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/apollo-angular/src/subscription.ts b/packages/apollo-angular/src/subscription.ts index 09b1db8ad..f93b8db81 100644 --- a/packages/apollo-angular/src/subscription.ts +++ b/packages/apollo-angular/src/subscription.ts @@ -1,7 +1,7 @@ import type { DocumentNode } from 'graphql'; import type { Observable } from 'rxjs'; import { Injectable } from '@angular/core'; -import type { ApolloLink, OperationVariables, TypedDocumentNode } from '@apollo/client'; +import type { ApolloClient, OperationVariables, TypedDocumentNode } from '@apollo/client'; import { Apollo } from './apollo'; import { EmptyObject, ExtraSubscriptionOptions, SubscriptionOptionsAlone } from './types'; @@ -16,7 +16,7 @@ export abstract class Subscription, extra?: ExtraSubscriptionOptions, - ): Observable> { + ): Observable> { return this.apollo.use(this.client).subscribe( { ...options, From 8f6e46f039e5ff9631c6ca42e8f376fa01c2af77 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 25 Aug 2025 21:24:26 -0600 Subject: [PATCH 33/97] Update persisted queries link --- .../apollo-angular/persisted-queries/src/index.ts | 14 +++++++------- .../tests/persisted-queries.spec.ts | 14 +++++++++++++- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/packages/apollo-angular/persisted-queries/src/index.ts b/packages/apollo-angular/persisted-queries/src/index.ts index f2ec7ce46..f0c0be207 100644 --- a/packages/apollo-angular/persisted-queries/src/index.ts +++ b/packages/apollo-angular/persisted-queries/src/index.ts @@ -1,10 +1,10 @@ -import { setContext } from '@apollo/client/link/context'; -import { ApolloLink } from '@apollo/client/link/core'; -import { createPersistedQueryLink as _createPersistedQueryLink } from '@apollo/client/link/persisted-queries'; +import { ApolloLink } from '@apollo/client/link'; +import { SetContextLink } from '@apollo/client/link/context'; +import { PersistedQueryLink } from '@apollo/client/link/persisted-queries'; -export type Options = Parameters[0]; +export type Options = PersistedQueryLink.Options; -const transformLink = setContext((_, context) => { +const transformLink = new SetContextLink(context => { const ctx: any = {}; if (context.http) { @@ -19,5 +19,5 @@ const transformLink = setContext((_, context) => { return ctx; }); -export const createPersistedQueryLink = (options: Options) => - ApolloLink.from([_createPersistedQueryLink(options), transformLink as any]); +export const createPersistedQueryLink = (options: PersistedQueryLink.Options) => + ApolloLink.from([new PersistedQueryLink(options), transformLink]); diff --git a/packages/apollo-angular/persisted-queries/tests/persisted-queries.spec.ts b/packages/apollo-angular/persisted-queries/tests/persisted-queries.spec.ts index cc2de4e78..05b3a1dec 100644 --- a/packages/apollo-angular/persisted-queries/tests/persisted-queries.spec.ts +++ b/packages/apollo-angular/persisted-queries/tests/persisted-queries.spec.ts @@ -1,6 +1,12 @@ import { Observable } from 'rxjs'; import { describe, expect, test, vi } from 'vitest'; -import { ApolloLink, execute, gql } from "@apollo/client"; +import { + ApolloClient, + ApolloLink, + execute as executeLink, + gql, + InMemoryCache, +} from '@apollo/client'; import { createPersistedQueryLink } from '../src'; const query = gql` @@ -13,6 +19,12 @@ const query = gql` `; const data = { heroes: [{ name: 'Foo', __typename: 'Hero' }] }; +function execute(link: ApolloLink, request: ApolloLink.Request) { + return executeLink(link, request, { + client: new ApolloClient({ cache: new InMemoryCache(), link: ApolloLink.empty() }), + }); +} + class MockLink extends ApolloLink { public showNotFound: boolean = true; From 7cc0753a9bd226da9228eed8b55132b831049a87 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 25 Aug 2025 21:59:11 -0600 Subject: [PATCH 34/97] Update TestOperation --- .../apollo-angular/testing/src/operation.ts | 34 ++++++------------- 1 file changed, 10 insertions(+), 24 deletions(-) diff --git a/packages/apollo-angular/testing/src/operation.ts b/packages/apollo-angular/testing/src/operation.ts index e0bcc5767..ab9af45ee 100644 --- a/packages/apollo-angular/testing/src/operation.ts +++ b/packages/apollo-angular/testing/src/operation.ts @@ -1,10 +1,7 @@ -import { FormattedExecutionResult, GraphQLError, Kind, OperationTypeNode } from 'graphql'; +import { GraphQLFormattedError, OperationTypeNode } from 'graphql'; import { Observer } from 'rxjs'; -import { ApolloLink } from "@apollo/client"; -import { ApolloError } from "@apollo/client/v4-migration"; -import { getMainDefinition } from '@apollo/client/utilities'; - -const isApolloError = (err: any): err is ApolloError => err && err.hasOwnProperty('graphQLErrors'); +import { ApolloLink, ErrorLike } from '@apollo/client'; +import { isErrorLike } from '@apollo/client/errors'; export type Operation = ApolloLink.Operation & { clientName: string; @@ -16,19 +13,14 @@ export class TestOperation { private readonly observer: Observer>, ) {} - public flush(result: FormattedExecutionResult | ApolloError): void { - if (isApolloError(result)) { + public flush(result: ApolloLink.Result | ErrorLike): void { + if (isErrorLike(result)) { this.observer.error(result); } else { const fetchResult = result ? { ...result } : result; this.observer.next(fetchResult); - const definition = getMainDefinition(this.operation.query); - - if ( - definition.kind === Kind.OPERATION_DEFINITION && - definition.operation !== OperationTypeNode.SUBSCRIPTION - ) { + if (this.operation.operationType === OperationTypeNode.SUBSCRIPTION) { this.complete(); } } @@ -39,20 +31,14 @@ export class TestOperation { } public flushData(data: T | null): void { - this.flush({ - data, - }); + this.flush({ data }); } - public networkError(error: Error): void { - const apolloError = new ApolloError({ - networkError: error, - }); - - this.flush(apolloError); + public networkError(error: ErrorLike): void { + this.flush(error); } - public graphqlErrors(errors: GraphQLError[]): void { + public graphqlErrors(errors: GraphQLFormattedError[]): void { this.flush({ errors, }); From 40776a8c93c336dc92e61d0775102982a0debfc3 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 25 Aug 2025 22:14:38 -0600 Subject: [PATCH 35/97] Update demo code --- packages/demo/src/app/pages/movie/movie-page.component.ts | 7 +++++-- .../demo/src/app/pages/movies/movies-page.component.ts | 7 +++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/packages/demo/src/app/pages/movie/movie-page.component.ts b/packages/demo/src/app/pages/movie/movie-page.component.ts index d95842eab..73e72a628 100644 --- a/packages/demo/src/app/pages/movie/movie-page.component.ts +++ b/packages/demo/src/app/pages/movie/movie-page.component.ts @@ -1,6 +1,6 @@ import { Apollo, gql } from 'apollo-angular'; import { Observable } from 'rxjs'; -import { map } from 'rxjs/operators'; +import { filter, map } from 'rxjs/operators'; import { AsyncPipe } from '@angular/common'; import { Component, OnInit } from '@angular/core'; import { ActivatedRoute, RouterLink } from '@angular/router'; @@ -74,6 +74,9 @@ export class MoviePageComponent implements OnInit { id: this.route.snapshot.paramMap.get('id')!, }, }) - .valueChanges.pipe(map(result => result.data!.film)); + .valueChanges.pipe( + map(result => (result.dataState === 'complete' ? result.data.film : null)), + filter(Boolean), + ); } } diff --git a/packages/demo/src/app/pages/movies/movies-page.component.ts b/packages/demo/src/app/pages/movies/movies-page.component.ts index 532bee1ff..602b74cb5 100644 --- a/packages/demo/src/app/pages/movies/movies-page.component.ts +++ b/packages/demo/src/app/pages/movies/movies-page.component.ts @@ -1,6 +1,6 @@ import { Apollo, gql } from 'apollo-angular'; import { Observable } from 'rxjs'; -import { map } from 'rxjs/operators'; +import { filter, map } from 'rxjs/operators'; import { AsyncPipe } from '@angular/common'; import { Component, OnInit } from '@angular/core'; import { RouterLink } from '@angular/router'; @@ -56,6 +56,9 @@ export class MoviesPageComponent implements OnInit { } `, }) - .valueChanges.pipe(map(result => result.data!.allFilms.films)) as any; + .valueChanges.pipe( + map(result => (result.dataState == 'complete' ? result.data.allFilms.films : null)), + filter(Boolean), + ); } } From a61071d9de593d4de0d0712fdbea57537f44ff9d Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 25 Aug 2025 22:14:43 -0600 Subject: [PATCH 36/97] Formatting --- packages/apollo-angular/src/apollo.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/apollo-angular/src/apollo.ts b/packages/apollo-angular/src/apollo.ts index 5cab08238..48faa80c3 100644 --- a/packages/apollo-angular/src/apollo.ts +++ b/packages/apollo-angular/src/apollo.ts @@ -31,9 +31,7 @@ export class ApolloBase { options: WatchQueryOptions, ): QueryRef { return new QueryRef( - this.ensureClient().watchQuery({ - ...options, - }), + this.ensureClient().watchQuery({ ...options }), this.ngZone, ); } From 961112a8db2088f5e92650ce166a001604aef177 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 25 Aug 2025 22:20:00 -0600 Subject: [PATCH 37/97] Formatting --- packages/apollo-angular/testing/src/backend.ts | 2 +- packages/apollo-angular/testing/tests/integration.spec.ts | 2 +- packages/apollo-angular/testing/tests/module.spec.ts | 2 +- packages/demo/src/app/app.config.ts | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/apollo-angular/testing/src/backend.ts b/packages/apollo-angular/testing/src/backend.ts index cc0ec6187..8e91a9a40 100644 --- a/packages/apollo-angular/testing/src/backend.ts +++ b/packages/apollo-angular/testing/src/backend.ts @@ -1,7 +1,7 @@ import { DocumentNode, print } from 'graphql'; import { Observable, Observer } from 'rxjs'; import { Injectable } from '@angular/core'; -import { ApolloLink } from "@apollo/client"; +import { ApolloLink } from '@apollo/client'; import { ApolloTestingController, MatchOperation } from './controller'; import { Operation, TestOperation } from './operation'; diff --git a/packages/apollo-angular/testing/tests/integration.spec.ts b/packages/apollo-angular/testing/tests/integration.spec.ts index 84c282510..b564b5453 100644 --- a/packages/apollo-angular/testing/tests/integration.spec.ts +++ b/packages/apollo-angular/testing/tests/integration.spec.ts @@ -1,7 +1,7 @@ import { print } from 'graphql'; import { afterEach, beforeEach, describe, expect, test } from 'vitest'; import { TestBed } from '@angular/core/testing'; -import { gql } from "@apollo/client"; +import { gql } from '@apollo/client'; import { addTypenameToDocument } from '@apollo/client/utilities'; import { Apollo } from '../../src'; import { ApolloTestingController, ApolloTestingModule } from '../src'; diff --git a/packages/apollo-angular/testing/tests/module.spec.ts b/packages/apollo-angular/testing/tests/module.spec.ts index 987736ee8..81dc4fb86 100644 --- a/packages/apollo-angular/testing/tests/module.spec.ts +++ b/packages/apollo-angular/testing/tests/module.spec.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from 'vitest'; import { TestBed } from '@angular/core/testing'; -import { gql, InMemoryCache } from "@apollo/client"; +import { gql, InMemoryCache } from '@apollo/client'; import { Apollo } from '../../src'; import { APOLLO_TESTING_CACHE, ApolloTestingController, ApolloTestingModule } from '../src'; diff --git a/packages/demo/src/app/app.config.ts b/packages/demo/src/app/app.config.ts index e76c72b50..03ce48c66 100644 --- a/packages/demo/src/app/app.config.ts +++ b/packages/demo/src/app/app.config.ts @@ -3,7 +3,7 @@ import { HttpLink } from 'apollo-angular/http'; import { provideHttpClient } from '@angular/common/http'; import { ApplicationConfig, inject, provideZoneChangeDetection } from '@angular/core'; import { provideRouter } from '@angular/router'; -import { InMemoryCache } from "@apollo/client"; +import { InMemoryCache } from '@apollo/client'; import { routes } from './app.routes'; export const appConfig: ApplicationConfig = { From 4c61e4b6a3f7ac94559b859650fc372328b866d6 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 25 Aug 2025 22:28:59 -0600 Subject: [PATCH 38/97] Fix flush for subscriptions --- packages/apollo-angular/testing/src/operation.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/apollo-angular/testing/src/operation.ts b/packages/apollo-angular/testing/src/operation.ts index ab9af45ee..1f11257b0 100644 --- a/packages/apollo-angular/testing/src/operation.ts +++ b/packages/apollo-angular/testing/src/operation.ts @@ -20,7 +20,7 @@ export class TestOperation { const fetchResult = result ? { ...result } : result; this.observer.next(fetchResult); - if (this.operation.operationType === OperationTypeNode.SUBSCRIPTION) { + if (this.operation.operationType !== OperationTypeNode.SUBSCRIPTION) { this.complete(); } } From 451acd7d4249dfdc45a2defc9db0c054924882a8 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 25 Aug 2025 23:00:57 -0600 Subject: [PATCH 39/97] Update assertions against operationName in batch link --- .../http/tests/http-batch-link.spec.ts | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/packages/apollo-angular/http/tests/http-batch-link.spec.ts b/packages/apollo-angular/http/tests/http-batch-link.spec.ts index ba498389e..786237e84 100644 --- a/packages/apollo-angular/http/tests/http-batch-link.spec.ts +++ b/packages/apollo-angular/http/tests/http-batch-link.spec.ts @@ -3,6 +3,7 @@ import { HttpHeaders, provideHttpClient } from '@angular/common/http'; import { HttpTestingController, provideHttpClientTesting } from '@angular/common/http/testing'; import { TestBed } from '@angular/core/testing'; import { ApolloLink, gql } from '@apollo/client'; +import { getOperationName } from '@apollo/client/utilities/internal'; import { HttpBatchLink } from '../src/http-batch-link'; import { executeWithDefaultContext as execute } from './utils'; @@ -37,7 +38,6 @@ describe('HttpBatchLink', () => { } } `, - operationName: 'heroes', variables: {}, }; const data = { @@ -72,7 +72,6 @@ describe('HttpBatchLink', () => { } } `, - operationName: 'heroes', variables: {}, }; @@ -97,7 +96,6 @@ describe('HttpBatchLink', () => { } } `, - operationName: 'heroes-1', variables: {}, }; const op2 = { @@ -108,7 +106,6 @@ describe('HttpBatchLink', () => { } } `, - operationName: 'heroes-2', variables: {}, }; @@ -117,8 +114,8 @@ describe('HttpBatchLink', () => { setTimeout(() => { httpBackend.match(req => { - expect(req.body[0].operationName).toEqual(op1.operationName); - expect(req.body[1].operationName).toEqual(op2.operationName); + expect(req.body[0].operationName).toEqual(getOperationName(op1.query)); + expect(req.body[1].operationName).toEqual(getOperationName(op2.query)); done(); return true; }); @@ -136,7 +133,6 @@ describe('HttpBatchLink', () => { } } `, - operationName: 'heroes', variables: {}, }; @@ -144,7 +140,7 @@ describe('HttpBatchLink', () => { setTimeout(() => { httpBackend.match(req => { - expect(req.body[0].operationName).toEqual(op.operationName); + expect(req.body[0].operationName).toEqual(getOperationName(op.query)); expect(req.reportProgress).toEqual(false); expect(req.responseType).toEqual('json'); expect(req.detectContentTypeHeader()).toEqual('application/json'); @@ -165,7 +161,6 @@ describe('HttpBatchLink', () => { } } `, - operationName: 'heroes', variables: {}, }; @@ -174,7 +169,7 @@ describe('HttpBatchLink', () => { setTimeout(() => { httpBackend.match(req => { expect(req.method).toEqual('POST'); - expect(req.body[0].operationName).toEqual(op.operationName); + expect(req.body[0].operationName).toEqual(getOperationName(op.query)); expect(req.detectContentTypeHeader()).toEqual('application/json'); done(); return true; @@ -197,7 +192,6 @@ describe('HttpBatchLink', () => { } } `, - operationName: 'heroes', variables: { up: 'dog' }, extensions: { what: 'what' }, }; @@ -746,7 +740,6 @@ describe('HttpBatchLink', () => { } } `, - operationName: 'heroes', variables: {}, }; From 15952f289fb26020ff856764f0d6bbca4d5452d7 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 25 Aug 2025 23:04:43 -0600 Subject: [PATCH 40/97] Fix operation names to make test pass --- packages/apollo-angular/http/tests/http-batch-link.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/apollo-angular/http/tests/http-batch-link.spec.ts b/packages/apollo-angular/http/tests/http-batch-link.spec.ts index 786237e84..be91a77d1 100644 --- a/packages/apollo-angular/http/tests/http-batch-link.spec.ts +++ b/packages/apollo-angular/http/tests/http-batch-link.spec.ts @@ -520,7 +520,7 @@ describe('HttpBatchLink', () => { execute(link, { query: gql` - query heroes($first: Int!) { + query op1($first: Int!) { heroes(first: $first) { name } @@ -532,7 +532,7 @@ describe('HttpBatchLink', () => { }).subscribe(noop); execute(link, { query: gql` - query heroes { + query op2 { heroes { name } From 2b214d8bfa741a2c82c752605d511e8bbcdf9020 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 25 Aug 2025 23:14:34 -0600 Subject: [PATCH 41/97] Add typename when comparing document nodes --- packages/apollo-angular/testing/src/backend.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/apollo-angular/testing/src/backend.ts b/packages/apollo-angular/testing/src/backend.ts index 8e91a9a40..b1a03c89d 100644 --- a/packages/apollo-angular/testing/src/backend.ts +++ b/packages/apollo-angular/testing/src/backend.ts @@ -2,6 +2,7 @@ import { DocumentNode, print } from 'graphql'; import { Observable, Observer } from 'rxjs'; import { Injectable } from '@angular/core'; import { ApolloLink } from '@apollo/client'; +import { addTypenameToDocument } from '@apollo/client/utilities'; import { ApolloTestingController, MatchOperation } from './controller'; import { Operation, TestOperation } from './operation'; @@ -40,7 +41,9 @@ export class ApolloTestingBackend implements ApolloTestingController { return this.open.filter(testOp => match(testOp.operation)); } else { if (this.isDocumentNode(match)) { - return this.open.filter(testOp => print(testOp.operation.query) === print(match)); + return this.open.filter( + testOp => print(testOp.operation.query) === print(addTypenameToDocument(match)), + ); } return this.open.filter(testOp => this.matchOp(match, testOp)); @@ -54,7 +57,7 @@ export class ApolloTestingBackend implements ApolloTestingController { const sameName = this.compare(match.operationName, testOp.operation.operationName); const sameVariables = this.compare(variables, testOp.operation.variables); - const sameQuery = print(testOp.operation.query) === print(match.query); + const sameQuery = print(testOp.operation.query) === print(addTypenameToDocument(match.query)); const sameExtensions = this.compare(extensions, testOp.operation.extensions); From 4472c108d99efcca3ab84f5e2e46b1f93ad1a555 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 25 Aug 2025 23:16:03 -0600 Subject: [PATCH 42/97] Add __typename to test response --- packages/apollo-angular/testing/tests/integration.spec.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/apollo-angular/testing/tests/integration.spec.ts b/packages/apollo-angular/testing/tests/integration.spec.ts index b564b5453..f88ff42ef 100644 --- a/packages/apollo-angular/testing/tests/integration.spec.ts +++ b/packages/apollo-angular/testing/tests/integration.spec.ts @@ -39,6 +39,7 @@ describe('Integration', () => { heroes: [ { name: 'Superman', + __typename: 'Character', }, ], }; @@ -73,6 +74,7 @@ describe('Integration', () => { heroes: [ { name: 'Superman', + __typename: 'Character', }, ], }; @@ -107,6 +109,7 @@ describe('Integration', () => { heroes: [ { name: 'Superman', + __typename: 'Character', }, ], }; @@ -145,6 +148,7 @@ describe('Integration', () => { heroes: [ { name: 'Superman', + __typename: 'Character', }, ], }; From 828821bd03caf59163f3eb847e087827932a0f3f Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 25 Aug 2025 23:19:02 -0600 Subject: [PATCH 43/97] Add typename when creating request for execute --- packages/apollo-angular/testing/tests/utils.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/apollo-angular/testing/tests/utils.ts b/packages/apollo-angular/testing/tests/utils.ts index 17b35acaf..3140b29c9 100644 --- a/packages/apollo-angular/testing/tests/utils.ts +++ b/packages/apollo-angular/testing/tests/utils.ts @@ -2,13 +2,14 @@ import { DocumentNode } from 'graphql'; import { Observable } from 'rxjs'; import { ApolloClient, execute, InMemoryCache, OperationVariables } from '@apollo/client'; import { ApolloLink } from '@apollo/client/link'; +import { addTypenameToDocument } from '@apollo/client/utilities'; export function buildOperationForLink( document: DocumentNode, variables: OperationVariables | undefined, ): ApolloLink.Request { return { - query: document, + query: addTypenameToDocument(document), variables, context: {}, }; From 8477c1374d6a83fbc05f2dc746f8d735228a2b0b Mon Sep 17 00:00:00 2001 From: Adrien Crivelli Date: Fri, 5 Sep 2025 17:25:25 +0900 Subject: [PATCH 44/97] Apply prettier --- packages/apollo-angular/headers/src/index.ts | 2 +- packages/apollo-angular/src/gql.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/apollo-angular/headers/src/index.ts b/packages/apollo-angular/headers/src/index.ts index 2ef2debe4..2beac3459 100644 --- a/packages/apollo-angular/headers/src/index.ts +++ b/packages/apollo-angular/headers/src/index.ts @@ -1,5 +1,5 @@ import { HttpHeaders } from '@angular/common/http'; -import { ApolloLink } from "@apollo/client"; +import { ApolloLink } from '@apollo/client'; export const httpHeaders = () => { return new ApolloLink((operation: ApolloLink.Operation, forward: ApolloLink.ForwardFunction) => { diff --git a/packages/apollo-angular/src/gql.ts b/packages/apollo-angular/src/gql.ts index fcaf4caaf..b2363efeb 100644 --- a/packages/apollo-angular/src/gql.ts +++ b/packages/apollo-angular/src/gql.ts @@ -1,4 +1,4 @@ -import { gql as gqlTag, TypedDocumentNode } from "@apollo/client"; +import { gql as gqlTag, TypedDocumentNode } from '@apollo/client'; const typedGQLTag: ( literals: ReadonlyArray | Readonly, From 1e8ed6959e68e1bae6e9f12d8688f2fe5fb7a4dd Mon Sep 17 00:00:00 2001 From: Adrien Crivelli Date: Fri, 5 Sep 2025 18:26:36 +0900 Subject: [PATCH 45/97] Compat with no prefix component --- scripts/prepare-e2e.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/scripts/prepare-e2e.js b/scripts/prepare-e2e.js index f3ee2c9ff..d5994d1f1 100755 --- a/scripts/prepare-e2e.js +++ b/scripts/prepare-e2e.js @@ -8,12 +8,19 @@ const [, , name, version] = process.argv; function updateComponent() { let filepath = path.join(cwd, `./${name}/src/app/app.component.ts`); + let suffix = 'Component'; + + if (!fs.existsSync(filepath)) { + filepath = path.join(cwd, `./${name}/src/app/app.ts`); + suffix = ''; + } + const code = `import { Apollo } from 'apollo-angular';\n` + `import { versionInfo } from 'graphql';\n` + fs .readFileSync(filepath, 'utf8') - .replace('AppComponent {', 'AppComponent { constructor(private readonly apollo: Apollo) {}') + + .replace(`App${suffix} {`, `App${suffix} { constructor(private readonly apollo: Apollo) {}`) + `\n (window as any).GRAPHQL_VERSION = versionInfo.major;`; fs.writeFileSync(filepath, code, 'utf8'); From 06ae077bd3feedd56c1d6c4dc35b79d3a0b4f52a Mon Sep 17 00:00:00 2001 From: Adrien Crivelli Date: Fri, 5 Sep 2025 18:27:28 +0900 Subject: [PATCH 46/97] All import from `@apollo/client/core` to avoid react/rehackt errors --- packages/apollo-angular/headers/src/index.ts | 2 +- packages/apollo-angular/headers/tests/index.spec.ts | 2 +- packages/apollo-angular/http/src/http-batch-link.ts | 2 +- packages/apollo-angular/http/src/http-link.ts | 2 +- packages/apollo-angular/http/src/types.ts | 2 +- packages/apollo-angular/http/tests/http-batch-link.spec.ts | 2 +- packages/apollo-angular/http/tests/http-link.spec.ts | 2 +- packages/apollo-angular/http/tests/ssr.spec.ts | 2 +- packages/apollo-angular/http/tests/utils.ts | 2 +- packages/apollo-angular/package.json | 2 +- .../persisted-queries/tests/persisted-queries.spec.ts | 2 +- .../schematics/install/files/module/graphql.module.ts | 2 +- packages/apollo-angular/schematics/install/index.cts | 4 ++-- packages/apollo-angular/src/apollo-module.ts | 2 +- packages/apollo-angular/src/apollo.ts | 4 ++-- packages/apollo-angular/src/gql.ts | 2 +- packages/apollo-angular/src/mutation.ts | 2 +- packages/apollo-angular/src/query-ref.ts | 2 +- packages/apollo-angular/src/query.ts | 2 +- packages/apollo-angular/src/subscription.ts | 2 +- packages/apollo-angular/src/tokens.ts | 2 +- packages/apollo-angular/src/types.ts | 2 +- packages/apollo-angular/src/utils.ts | 2 +- packages/apollo-angular/testing/src/backend.ts | 2 +- packages/apollo-angular/testing/src/module.ts | 2 +- packages/apollo-angular/testing/src/operation.ts | 2 +- packages/apollo-angular/testing/tests/integration.spec.ts | 2 +- packages/apollo-angular/testing/tests/module.spec.ts | 2 +- packages/apollo-angular/testing/tests/operation.spec.ts | 2 +- packages/apollo-angular/testing/tests/utils.ts | 2 +- packages/apollo-angular/tests/Apollo.spec.ts | 2 +- packages/apollo-angular/tests/QueryRef.spec.ts | 2 +- packages/apollo-angular/tests/integration.spec.ts | 2 +- packages/demo/src/app/app.config.ts | 2 +- 34 files changed, 36 insertions(+), 36 deletions(-) diff --git a/packages/apollo-angular/headers/src/index.ts b/packages/apollo-angular/headers/src/index.ts index 2beac3459..a9073a756 100644 --- a/packages/apollo-angular/headers/src/index.ts +++ b/packages/apollo-angular/headers/src/index.ts @@ -1,5 +1,5 @@ import { HttpHeaders } from '@angular/common/http'; -import { ApolloLink } from '@apollo/client'; +import { ApolloLink } from '@apollo/client/core'; export const httpHeaders = () => { return new ApolloLink((operation: ApolloLink.Operation, forward: ApolloLink.ForwardFunction) => { diff --git a/packages/apollo-angular/headers/tests/index.spec.ts b/packages/apollo-angular/headers/tests/index.spec.ts index f7fa2193a..0e746b2cd 100644 --- a/packages/apollo-angular/headers/tests/index.spec.ts +++ b/packages/apollo-angular/headers/tests/index.spec.ts @@ -1,7 +1,7 @@ import { of } from 'rxjs'; import { describe, expect, test } from 'vitest'; import { HttpHeaders } from '@angular/common/http'; -import { ApolloClient, ApolloLink, execute, gql, InMemoryCache } from '@apollo/client'; +import { ApolloClient, ApolloLink, execute, gql, InMemoryCache } from '@apollo/client/core'; import { httpHeaders } from '../src'; const query = gql` diff --git a/packages/apollo-angular/http/src/http-batch-link.ts b/packages/apollo-angular/http/src/http-batch-link.ts index 97019ce55..823aeaf3f 100644 --- a/packages/apollo-angular/http/src/http-batch-link.ts +++ b/packages/apollo-angular/http/src/http-batch-link.ts @@ -2,7 +2,7 @@ import { print } from 'graphql'; import { Observable } from 'rxjs'; import { HttpClient, HttpHeaders } from '@angular/common/http'; import { Injectable } from '@angular/core'; -import { ApolloLink } from '@apollo/client'; +import { ApolloLink } from '@apollo/client/core'; import { BatchLink } from '@apollo/client/link/batch'; import { BatchOptions, Body, Context, OperationPrinter, Options, Request } from './types'; import { createHeadersWithClientAwareness, fetch, mergeHeaders, prioritize } from './utils'; diff --git a/packages/apollo-angular/http/src/http-link.ts b/packages/apollo-angular/http/src/http-link.ts index 5048de9c7..0cf38062e 100644 --- a/packages/apollo-angular/http/src/http-link.ts +++ b/packages/apollo-angular/http/src/http-link.ts @@ -2,7 +2,7 @@ import { print } from 'graphql'; import { Observable } from 'rxjs'; import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; -import { ApolloLink } from '@apollo/client'; +import { ApolloLink } from '@apollo/client/core'; import { pick } from './http-batch-link'; import { Body, Context, OperationPrinter, Options, Request } from './types'; import { createHeadersWithClientAwareness, fetch, mergeHeaders } from './utils'; diff --git a/packages/apollo-angular/http/src/types.ts b/packages/apollo-angular/http/src/types.ts index 57592751a..54f7243e5 100644 --- a/packages/apollo-angular/http/src/types.ts +++ b/packages/apollo-angular/http/src/types.ts @@ -1,6 +1,6 @@ import { DocumentNode } from 'graphql'; import { HttpHeaders } from '@angular/common/http'; -import { ApolloLink } from '@apollo/client'; +import { ApolloLink } from '@apollo/client/core'; declare module '@apollo/client' { export interface DefaultContext extends Context {} diff --git a/packages/apollo-angular/http/tests/http-batch-link.spec.ts b/packages/apollo-angular/http/tests/http-batch-link.spec.ts index be91a77d1..57450cd3e 100644 --- a/packages/apollo-angular/http/tests/http-batch-link.spec.ts +++ b/packages/apollo-angular/http/tests/http-batch-link.spec.ts @@ -2,7 +2,7 @@ import { afterEach, beforeEach, describe, expect, test } from 'vitest'; import { HttpHeaders, provideHttpClient } from '@angular/common/http'; import { HttpTestingController, provideHttpClientTesting } from '@angular/common/http/testing'; import { TestBed } from '@angular/core/testing'; -import { ApolloLink, gql } from '@apollo/client'; +import { ApolloLink, gql } from '@apollo/client/core'; import { getOperationName } from '@apollo/client/utilities/internal'; import { HttpBatchLink } from '../src/http-batch-link'; import { executeWithDefaultContext as execute } from './utils'; diff --git a/packages/apollo-angular/http/tests/http-link.spec.ts b/packages/apollo-angular/http/tests/http-link.spec.ts index 36516b20e..5326a5dfa 100644 --- a/packages/apollo-angular/http/tests/http-link.spec.ts +++ b/packages/apollo-angular/http/tests/http-link.spec.ts @@ -4,7 +4,7 @@ import { afterEach, beforeEach, describe, expect, test } from 'vitest'; import { HttpHeaders, provideHttpClient } from '@angular/common/http'; import { HttpTestingController, provideHttpClientTesting } from '@angular/common/http/testing'; import { TestBed } from '@angular/core/testing'; -import { ApolloLink, gql, InMemoryCache } from '@apollo/client'; +import { ApolloLink, gql, InMemoryCache } from '@apollo/client/core'; import { Apollo } from '../../src'; import { HttpLink } from '../src/http-link'; import { executeWithDefaultContext as execute } from './utils'; diff --git a/packages/apollo-angular/http/tests/ssr.spec.ts b/packages/apollo-angular/http/tests/ssr.spec.ts index 6f6e4cf30..8607c58c0 100644 --- a/packages/apollo-angular/http/tests/ssr.spec.ts +++ b/packages/apollo-angular/http/tests/ssr.spec.ts @@ -10,7 +10,7 @@ import { renderModule, ServerModule, } from '@angular/platform-server'; -import { gql } from '@apollo/client'; +import { gql } from '@apollo/client/core'; import { HttpLink } from '../src/http-link'; import { executeWithDefaultContext as execute } from './utils'; diff --git a/packages/apollo-angular/http/tests/utils.ts b/packages/apollo-angular/http/tests/utils.ts index 177efa97c..8e072ad70 100644 --- a/packages/apollo-angular/http/tests/utils.ts +++ b/packages/apollo-angular/http/tests/utils.ts @@ -1,5 +1,5 @@ import { Observable } from 'rxjs'; -import { ApolloClient, ApolloLink, execute, InMemoryCache } from '@apollo/client'; +import { ApolloClient, ApolloLink, execute, InMemoryCache } from '@apollo/client/core'; export function createDefaultExecuteContext(): ApolloLink.ExecuteContext { return { diff --git a/packages/apollo-angular/package.json b/packages/apollo-angular/package.json index 8c99fc344..7785df297 100644 --- a/packages/apollo-angular/package.json +++ b/packages/apollo-angular/package.json @@ -37,7 +37,7 @@ }, "peerDependencies": { "@angular/core": "^17.0.0 || ^18.0.0 || ^19.0.0", - "@apollo/client": "^4.0.0", + "@apollo/client": "^4.0.1", "graphql": "^16.0.0", "rxjs": "^7.3.0" }, diff --git a/packages/apollo-angular/persisted-queries/tests/persisted-queries.spec.ts b/packages/apollo-angular/persisted-queries/tests/persisted-queries.spec.ts index 05b3a1dec..f715aed6f 100644 --- a/packages/apollo-angular/persisted-queries/tests/persisted-queries.spec.ts +++ b/packages/apollo-angular/persisted-queries/tests/persisted-queries.spec.ts @@ -6,7 +6,7 @@ import { execute as executeLink, gql, InMemoryCache, -} from '@apollo/client'; +} from '@apollo/client/core'; import { createPersistedQueryLink } from '../src'; const query = gql` diff --git a/packages/apollo-angular/schematics/install/files/module/graphql.module.ts b/packages/apollo-angular/schematics/install/files/module/graphql.module.ts index 7bc609bda..4d8b0ecd6 100644 --- a/packages/apollo-angular/schematics/install/files/module/graphql.module.ts +++ b/packages/apollo-angular/schematics/install/files/module/graphql.module.ts @@ -1,7 +1,7 @@ import { provideApollo } from 'apollo-angular'; import { HttpLink } from 'apollo-angular/http'; import { inject, NgModule } from '@angular/core'; -import { ApolloClient, InMemoryCache } from '@apollo/client'; +import { ApolloClient, InMemoryCache } from '@apollo/client/core'; export function createApollo(): ApolloClient.Options { const uri = '<%= endpoint %>'; // <-- add the URL of the GraphQL server here diff --git a/packages/apollo-angular/schematics/install/index.cts b/packages/apollo-angular/schematics/install/index.cts index 0894c4c21..e4a748a2e 100644 --- a/packages/apollo-angular/schematics/install/index.cts +++ b/packages/apollo-angular/schematics/install/index.cts @@ -33,8 +33,8 @@ export function factory(options: Schema): Rule { export function createDependenciesMap(options: Schema): Record { return { - 'apollo-angular': '^7.0.0', - '@apollo/client': '^3.0.0', + 'apollo-angular': '^9.0.0', + '@apollo/client': '^4.0.1', graphql: `^${options.graphql ?? '16.0.0'}`, }; } diff --git a/packages/apollo-angular/src/apollo-module.ts b/packages/apollo-angular/src/apollo-module.ts index 49fcb62c8..4f19b5ee7 100644 --- a/packages/apollo-angular/src/apollo-module.ts +++ b/packages/apollo-angular/src/apollo-module.ts @@ -1,5 +1,5 @@ import { Provider } from '@angular/core'; -import { ApolloClient } from '@apollo/client'; +import { ApolloClient } from '@apollo/client/core'; import { Apollo } from './apollo'; import { APOLLO_FLAGS, APOLLO_NAMED_OPTIONS, APOLLO_OPTIONS } from './tokens'; import { Flags, NamedOptions } from './types'; diff --git a/packages/apollo-angular/src/apollo.ts b/packages/apollo-angular/src/apollo.ts index 48faa80c3..33c32c5b5 100644 --- a/packages/apollo-angular/src/apollo.ts +++ b/packages/apollo-angular/src/apollo.ts @@ -1,7 +1,7 @@ import { Observable } from 'rxjs'; import { Inject, Injectable, NgZone, Optional } from '@angular/core'; -import type { ApolloCache, OperationVariables } from '@apollo/client'; -import { ApolloClient } from '@apollo/client'; +import type { ApolloCache, OperationVariables } from '@apollo/client/core'; +import { ApolloClient } from '@apollo/client/core'; import { QueryRef } from './query-ref'; import { APOLLO_FLAGS, APOLLO_NAMED_OPTIONS, APOLLO_OPTIONS } from './tokens'; import type { diff --git a/packages/apollo-angular/src/gql.ts b/packages/apollo-angular/src/gql.ts index b2363efeb..e58ff8d95 100644 --- a/packages/apollo-angular/src/gql.ts +++ b/packages/apollo-angular/src/gql.ts @@ -1,4 +1,4 @@ -import { gql as gqlTag, TypedDocumentNode } from '@apollo/client'; +import { gql as gqlTag, TypedDocumentNode } from '@apollo/client/core'; const typedGQLTag: ( literals: ReadonlyArray | Readonly, diff --git a/packages/apollo-angular/src/mutation.ts b/packages/apollo-angular/src/mutation.ts index 8074f21b6..23f2a38ce 100644 --- a/packages/apollo-angular/src/mutation.ts +++ b/packages/apollo-angular/src/mutation.ts @@ -1,7 +1,7 @@ import type { DocumentNode } from 'graphql'; import type { Observable } from 'rxjs'; import { Injectable } from '@angular/core'; -import type { OperationVariables, TypedDocumentNode } from '@apollo/client'; +import type { OperationVariables, TypedDocumentNode } from '@apollo/client/core'; import { Apollo } from './apollo'; import type { EmptyObject, MutationOptionsAlone, MutationResult } from './types'; diff --git a/packages/apollo-angular/src/query-ref.ts b/packages/apollo-angular/src/query-ref.ts index 90f4d0913..156c6dc42 100644 --- a/packages/apollo-angular/src/query-ref.ts +++ b/packages/apollo-angular/src/query-ref.ts @@ -6,7 +6,7 @@ import type { ObservableQuery, OperationVariables, TypedDocumentNode, -} from '@apollo/client'; +} from '@apollo/client/core'; import { EmptyObject } from './types'; import { wrapWithZone } from './utils'; diff --git a/packages/apollo-angular/src/query.ts b/packages/apollo-angular/src/query.ts index 3db7833d5..91e9d147f 100644 --- a/packages/apollo-angular/src/query.ts +++ b/packages/apollo-angular/src/query.ts @@ -1,7 +1,7 @@ import type { DocumentNode } from 'graphql'; import type { Observable } from 'rxjs'; import { Injectable } from '@angular/core'; -import type { ApolloClient, OperationVariables, TypedDocumentNode } from '@apollo/client'; +import type { ApolloClient, OperationVariables, TypedDocumentNode } from '@apollo/client/core'; import { Apollo } from './apollo'; import { QueryRef } from './query-ref'; import { EmptyObject, QueryOptionsAlone, WatchQueryOptionsAlone } from './types'; diff --git a/packages/apollo-angular/src/subscription.ts b/packages/apollo-angular/src/subscription.ts index f93b8db81..da138ca5f 100644 --- a/packages/apollo-angular/src/subscription.ts +++ b/packages/apollo-angular/src/subscription.ts @@ -1,7 +1,7 @@ import type { DocumentNode } from 'graphql'; import type { Observable } from 'rxjs'; import { Injectable } from '@angular/core'; -import type { ApolloClient, OperationVariables, TypedDocumentNode } from '@apollo/client'; +import type { ApolloClient, OperationVariables, TypedDocumentNode } from '@apollo/client/core'; import { Apollo } from './apollo'; import { EmptyObject, ExtraSubscriptionOptions, SubscriptionOptionsAlone } from './types'; diff --git a/packages/apollo-angular/src/tokens.ts b/packages/apollo-angular/src/tokens.ts index 0a8bda2f2..8c9ec4280 100644 --- a/packages/apollo-angular/src/tokens.ts +++ b/packages/apollo-angular/src/tokens.ts @@ -1,5 +1,5 @@ import { InjectionToken } from '@angular/core'; -import type { ApolloClient } from '@apollo/client'; +import type { ApolloClient } from '@apollo/client/core'; import type { Flags, NamedOptions } from './types'; export const APOLLO_FLAGS = new InjectionToken('APOLLO_FLAGS'); diff --git a/packages/apollo-angular/src/types.ts b/packages/apollo-angular/src/types.ts index cd7032815..34a0684fa 100644 --- a/packages/apollo-angular/src/types.ts +++ b/packages/apollo-angular/src/types.ts @@ -4,7 +4,7 @@ import type { ApolloLink, OperationVariables, TypedDocumentNode, -} from '@apollo/client'; +} from '@apollo/client/core'; export type EmptyObject = { [key: string]: any; diff --git a/packages/apollo-angular/src/utils.ts b/packages/apollo-angular/src/utils.ts index 17ed5a1f6..cef1f3f39 100644 --- a/packages/apollo-angular/src/utils.ts +++ b/packages/apollo-angular/src/utils.ts @@ -1,7 +1,7 @@ import { Observable, queueScheduler, SchedulerAction, SchedulerLike, Subscription } from 'rxjs'; import { map, observeOn, startWith } from 'rxjs/operators'; import { NgZone } from '@angular/core'; -import type { ApolloClient } from '@apollo/client'; +import type { ApolloClient } from '@apollo/client/core'; import { MutationResult } from './types'; /** diff --git a/packages/apollo-angular/testing/src/backend.ts b/packages/apollo-angular/testing/src/backend.ts index b1a03c89d..9aed45ae5 100644 --- a/packages/apollo-angular/testing/src/backend.ts +++ b/packages/apollo-angular/testing/src/backend.ts @@ -1,7 +1,7 @@ import { DocumentNode, print } from 'graphql'; import { Observable, Observer } from 'rxjs'; import { Injectable } from '@angular/core'; -import { ApolloLink } from '@apollo/client'; +import { ApolloLink } from '@apollo/client/core'; import { addTypenameToDocument } from '@apollo/client/utilities'; import { ApolloTestingController, MatchOperation } from './controller'; import { Operation, TestOperation } from './operation'; diff --git a/packages/apollo-angular/testing/src/module.ts b/packages/apollo-angular/testing/src/module.ts index 9269d0cd1..bfc3aa3e3 100644 --- a/packages/apollo-angular/testing/src/module.ts +++ b/packages/apollo-angular/testing/src/module.ts @@ -1,6 +1,6 @@ import { Apollo } from 'apollo-angular'; import { Inject, InjectionToken, NgModule, Optional } from '@angular/core'; -import { ApolloCache, ApolloLink, InMemoryCache } from '@apollo/client'; +import { ApolloCache, ApolloLink, InMemoryCache } from '@apollo/client/core'; import { ApolloTestingBackend } from './backend'; import { ApolloTestingController } from './controller'; import { Operation } from './operation'; diff --git a/packages/apollo-angular/testing/src/operation.ts b/packages/apollo-angular/testing/src/operation.ts index 1f11257b0..cc56d813b 100644 --- a/packages/apollo-angular/testing/src/operation.ts +++ b/packages/apollo-angular/testing/src/operation.ts @@ -1,6 +1,6 @@ import { GraphQLFormattedError, OperationTypeNode } from 'graphql'; import { Observer } from 'rxjs'; -import { ApolloLink, ErrorLike } from '@apollo/client'; +import { ApolloLink, ErrorLike } from '@apollo/client/core'; import { isErrorLike } from '@apollo/client/errors'; export type Operation = ApolloLink.Operation & { diff --git a/packages/apollo-angular/testing/tests/integration.spec.ts b/packages/apollo-angular/testing/tests/integration.spec.ts index f88ff42ef..dc8dcf4c9 100644 --- a/packages/apollo-angular/testing/tests/integration.spec.ts +++ b/packages/apollo-angular/testing/tests/integration.spec.ts @@ -1,7 +1,7 @@ import { print } from 'graphql'; import { afterEach, beforeEach, describe, expect, test } from 'vitest'; import { TestBed } from '@angular/core/testing'; -import { gql } from '@apollo/client'; +import { gql } from '@apollo/client/core'; import { addTypenameToDocument } from '@apollo/client/utilities'; import { Apollo } from '../../src'; import { ApolloTestingController, ApolloTestingModule } from '../src'; diff --git a/packages/apollo-angular/testing/tests/module.spec.ts b/packages/apollo-angular/testing/tests/module.spec.ts index 81dc4fb86..0ff46f824 100644 --- a/packages/apollo-angular/testing/tests/module.spec.ts +++ b/packages/apollo-angular/testing/tests/module.spec.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from 'vitest'; import { TestBed } from '@angular/core/testing'; -import { gql, InMemoryCache } from '@apollo/client'; +import { gql, InMemoryCache } from '@apollo/client/core'; import { Apollo } from '../../src'; import { APOLLO_TESTING_CACHE, ApolloTestingController, ApolloTestingModule } from '../src'; diff --git a/packages/apollo-angular/testing/tests/operation.spec.ts b/packages/apollo-angular/testing/tests/operation.spec.ts index 1cd24075e..2da241358 100644 --- a/packages/apollo-angular/testing/tests/operation.spec.ts +++ b/packages/apollo-angular/testing/tests/operation.spec.ts @@ -1,5 +1,5 @@ import { beforeEach, describe, expect, test } from 'vitest'; -import { ApolloLink, gql } from '@apollo/client'; +import { ApolloLink, gql } from '@apollo/client/core'; import { ApolloTestingBackend } from '../src/backend'; import { buildOperationForLink, executeWithDefaultContext as execute } from './utils'; diff --git a/packages/apollo-angular/testing/tests/utils.ts b/packages/apollo-angular/testing/tests/utils.ts index 3140b29c9..25e353abc 100644 --- a/packages/apollo-angular/testing/tests/utils.ts +++ b/packages/apollo-angular/testing/tests/utils.ts @@ -1,6 +1,6 @@ import { DocumentNode } from 'graphql'; import { Observable } from 'rxjs'; -import { ApolloClient, execute, InMemoryCache, OperationVariables } from '@apollo/client'; +import { ApolloClient, execute, InMemoryCache, OperationVariables } from '@apollo/client/core'; import { ApolloLink } from '@apollo/client/link'; import { addTypenameToDocument } from '@apollo/client/utilities'; diff --git a/packages/apollo-angular/tests/Apollo.spec.ts b/packages/apollo-angular/tests/Apollo.spec.ts index 3fdd6b960..614d3acc4 100644 --- a/packages/apollo-angular/tests/Apollo.spec.ts +++ b/packages/apollo-angular/tests/Apollo.spec.ts @@ -3,7 +3,7 @@ import { mergeMap } from 'rxjs/operators'; import { beforeEach, describe, expect, test, vi } from 'vitest'; import { NgZone } from '@angular/core'; import { TestBed } from '@angular/core/testing'; -import { ApolloLink, InMemoryCache, NetworkStatus } from '@apollo/client'; +import { ApolloLink, InMemoryCache, NetworkStatus } from '@apollo/client/core'; import { MockLink } from '@apollo/client/testing'; import { Apollo, ApolloBase } from '../src/apollo'; import { gql } from '../src/gql'; diff --git a/packages/apollo-angular/tests/QueryRef.spec.ts b/packages/apollo-angular/tests/QueryRef.spec.ts index 2a81eca4d..75039710e 100644 --- a/packages/apollo-angular/tests/QueryRef.spec.ts +++ b/packages/apollo-angular/tests/QueryRef.spec.ts @@ -2,7 +2,7 @@ import { Subject } from 'rxjs'; import { map, takeUntil } from 'rxjs/operators'; import { beforeEach, describe, expect, test, vi } from 'vitest'; import { NgZone } from '@angular/core'; -import { ApolloClient, ApolloLink, InMemoryCache, ObservableQuery } from '@apollo/client'; +import { ApolloClient, ApolloLink, InMemoryCache, ObservableQuery } from '@apollo/client/core'; import { MockLink } from '@apollo/client/testing'; import { gql } from '../src/gql'; import { QueryRef } from '../src/query-ref'; diff --git a/packages/apollo-angular/tests/integration.spec.ts b/packages/apollo-angular/tests/integration.spec.ts index b07264c32..c4bf35b64 100644 --- a/packages/apollo-angular/tests/integration.spec.ts +++ b/packages/apollo-angular/tests/integration.spec.ts @@ -1,7 +1,7 @@ import { beforeEach, describe, expect, test } from 'vitest'; import { provideHttpClient } from '@angular/common/http'; import { TestBed } from '@angular/core/testing'; -import { InMemoryCache } from '@apollo/client'; +import { InMemoryCache } from '@apollo/client/core'; import { MockLink } from '@apollo/client/testing'; import { Apollo, provideApollo } from '../src'; diff --git a/packages/demo/src/app/app.config.ts b/packages/demo/src/app/app.config.ts index 03ce48c66..8dec6e286 100644 --- a/packages/demo/src/app/app.config.ts +++ b/packages/demo/src/app/app.config.ts @@ -3,7 +3,7 @@ import { HttpLink } from 'apollo-angular/http'; import { provideHttpClient } from '@angular/common/http'; import { ApplicationConfig, inject, provideZoneChangeDetection } from '@angular/core'; import { provideRouter } from '@angular/router'; -import { InMemoryCache } from '@apollo/client'; +import { InMemoryCache } from '@apollo/client/core'; import { routes } from './app.routes'; export const appConfig: ApplicationConfig = { From 0133946b38eb58e4b39eab410a87da10a9a333df Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Thu, 18 Sep 2025 14:36:24 -0600 Subject: [PATCH 47/97] Default TData to unknown and add consistent order --- packages/apollo-angular/src/apollo.ts | 2 +- packages/apollo-angular/src/query.ts | 6 +++--- packages/apollo-angular/src/subscription.ts | 4 ++-- packages/apollo-angular/src/types.ts | 20 ++++++++++---------- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/packages/apollo-angular/src/apollo.ts b/packages/apollo-angular/src/apollo.ts index 33c32c5b5..5944472a9 100644 --- a/packages/apollo-angular/src/apollo.ts +++ b/packages/apollo-angular/src/apollo.ts @@ -28,7 +28,7 @@ export class ApolloBase { } public watchQuery( - options: WatchQueryOptions, + options: WatchQueryOptions, ): QueryRef { return new QueryRef( this.ensureClient().watchQuery({ ...options }), diff --git a/packages/apollo-angular/src/query.ts b/packages/apollo-angular/src/query.ts index 91e9d147f..1d0b0d668 100644 --- a/packages/apollo-angular/src/query.ts +++ b/packages/apollo-angular/src/query.ts @@ -7,13 +7,13 @@ import { QueryRef } from './query-ref'; import { EmptyObject, QueryOptionsAlone, WatchQueryOptionsAlone } from './types'; @Injectable() -export abstract class Query { +export abstract class Query { public abstract readonly document: DocumentNode | TypedDocumentNode; public client = 'default'; constructor(protected readonly apollo: Apollo) {} - public watch(variables?: V, options?: WatchQueryOptionsAlone): QueryRef { + public watch(variables?: V, options?: WatchQueryOptionsAlone): QueryRef { return this.apollo.use(this.client).watchQuery({ ...options, variables: variables as V, @@ -23,7 +23,7 @@ export abstract class Query public fetch( variables?: V, - options?: QueryOptionsAlone, + options?: QueryOptionsAlone, ): Observable> { return this.apollo.use(this.client).query({ ...options, diff --git a/packages/apollo-angular/src/subscription.ts b/packages/apollo-angular/src/subscription.ts index da138ca5f..e15a37fbf 100644 --- a/packages/apollo-angular/src/subscription.ts +++ b/packages/apollo-angular/src/subscription.ts @@ -6,7 +6,7 @@ import { Apollo } from './apollo'; import { EmptyObject, ExtraSubscriptionOptions, SubscriptionOptionsAlone } from './types'; @Injectable() -export abstract class Subscription { +export abstract class Subscription { public abstract readonly document: DocumentNode | TypedDocumentNode; public client = 'default'; @@ -14,7 +14,7 @@ export abstract class Subscription, + options?: SubscriptionOptionsAlone, extra?: ExtraSubscriptionOptions, ): Observable> { return this.apollo.use(this.client).subscribe( diff --git a/packages/apollo-angular/src/types.ts b/packages/apollo-angular/src/types.ts index 34a0684fa..3160796b0 100644 --- a/packages/apollo-angular/src/types.ts +++ b/packages/apollo-angular/src/types.ts @@ -19,39 +19,39 @@ export interface ExtraSubscriptionOptions { useZone?: boolean; } -export type MutationResult = ApolloLink.Result & { +export type MutationResult = ApolloLink.Result & { loading?: boolean; }; export type Omit = Pick>; export type WatchQueryOptionsAlone< + TData = unknown, TVariables extends OperationVariables = EmptyObject, - TData = any, -> = Omit, 'query' | 'variables'>; +> = Omit, 'query' | 'variables'>; export type QueryOptionsAlone< + TData = unknown, TVariables extends OperationVariables = EmptyObject, - TData = any, > = Omit, 'query' | 'variables'>; export type MutationOptionsAlone< - TData = EmptyObject, - TVariables extends OperationVariables = any, + TData = unknown, + TVariables extends OperationVariables = EmptyObject, > = Omit, 'mutation' | 'variables'>; export type SubscriptionOptionsAlone< + TData = unknown, TVariables extends OperationVariables = EmptyObject, - TData = any, > = Omit, 'query' | 'variables'>; export type WatchQueryOptions< + TData = unknown, TVariables extends OperationVariables = EmptyObject, - TData = any, > = ApolloClient.WatchQueryOptions; export type MutationOptions< - TData = any, + TData = unknown, TVariables extends OperationVariables = EmptyObject, > = ApolloClient.MutateOptions & { /** @@ -64,7 +64,7 @@ export type MutationOptions< }; export interface WatchFragmentOptions< - TData = any, + TData = unknown, TVariables extends OperationVariables = EmptyObject, > extends ApolloCache.WatchFragmentOptions {} From 8c84b90f246c6d8daffddfe010c27d8f7794cb79 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Thu, 18 Sep 2025 14:39:49 -0600 Subject: [PATCH 48/97] Rename generics to TData and TVariables --- packages/apollo-angular/src/apollo.ts | 26 ++++++++++----------- packages/apollo-angular/src/mutation.ts | 17 ++++++++------ packages/apollo-angular/src/query-ref.ts | 4 +++- packages/apollo-angular/src/query.ts | 23 ++++++++++-------- packages/apollo-angular/src/subscription.ts | 17 ++++++++------ 5 files changed, 49 insertions(+), 38 deletions(-) diff --git a/packages/apollo-angular/src/apollo.ts b/packages/apollo-angular/src/apollo.ts index 5944472a9..e4565ca17 100644 --- a/packages/apollo-angular/src/apollo.ts +++ b/packages/apollo-angular/src/apollo.ts @@ -36,19 +36,19 @@ export class ApolloBase { ); } - public query( - options: ApolloClient.QueryOptions, - ): Observable> { - return fromLazyPromise>(() => - this.ensureClient().query({ ...options }), + public query( + options: ApolloClient.QueryOptions, + ): Observable> { + return fromLazyPromise>(() => + this.ensureClient().query({ ...options }), ); } - public mutate( - options: MutationOptions, - ): Observable> { + public mutate( + options: MutationOptions, + ): Observable> { return useMutationLoading( - fromLazyPromise(() => this.ensureClient().mutate({ ...options })), + fromLazyPromise(() => this.ensureClient().mutate({ ...options })), options.useMutationLoading ?? this.useMutationLoading, ); } @@ -65,11 +65,11 @@ export class ApolloBase { return extra && extra.useZone !== true ? obs : wrapWithZone(obs, this.ngZone); } - public subscribe( - options: ApolloClient.SubscribeOptions, + public subscribe( + options: ApolloClient.SubscribeOptions, extra?: ExtraSubscriptionOptions, - ): Observable> { - const obs = this.ensureClient().subscribe({ ...options }); + ): Observable> { + const obs = this.ensureClient().subscribe({ ...options }); return extra && extra.useZone !== true ? obs : wrapWithZone(obs, this.ngZone); } diff --git a/packages/apollo-angular/src/mutation.ts b/packages/apollo-angular/src/mutation.ts index 23f2a38ce..15ad37f8f 100644 --- a/packages/apollo-angular/src/mutation.ts +++ b/packages/apollo-angular/src/mutation.ts @@ -6,19 +6,22 @@ import { Apollo } from './apollo'; import type { EmptyObject, MutationOptionsAlone, MutationResult } from './types'; @Injectable() -export abstract class Mutation { - public abstract readonly document: DocumentNode | TypedDocumentNode; +export abstract class Mutation< + TData = unknown, + TVariables extends OperationVariables = EmptyObject, +> { + public abstract readonly document: DocumentNode | TypedDocumentNode; public client = 'default'; constructor(protected readonly apollo: Apollo) {} public mutate( - variables?: V, - options?: MutationOptionsAlone, - ): Observable> { - return this.apollo.use(this.client).mutate({ + variables?: TVariables, + options?: MutationOptionsAlone, + ): Observable> { + return this.apollo.use(this.client).mutate({ ...options, - variables: variables as V, + variables: variables as TVariables, mutation: this.document, }); } diff --git a/packages/apollo-angular/src/query-ref.ts b/packages/apollo-angular/src/query-ref.ts index 156c6dc42..f62dd46b1 100644 --- a/packages/apollo-angular/src/query-ref.ts +++ b/packages/apollo-angular/src/query-ref.ts @@ -11,7 +11,9 @@ import { EmptyObject } from './types'; import { wrapWithZone } from './utils'; export type QueryRefFromDocument = - T extends TypedDocumentNode ? QueryRef : never; + T extends TypedDocumentNode + ? QueryRef + : never; export class QueryRef { public readonly valueChanges: Observable>; diff --git a/packages/apollo-angular/src/query.ts b/packages/apollo-angular/src/query.ts index 1d0b0d668..5c5ae8bda 100644 --- a/packages/apollo-angular/src/query.ts +++ b/packages/apollo-angular/src/query.ts @@ -7,27 +7,30 @@ import { QueryRef } from './query-ref'; import { EmptyObject, QueryOptionsAlone, WatchQueryOptionsAlone } from './types'; @Injectable() -export abstract class Query { - public abstract readonly document: DocumentNode | TypedDocumentNode; +export abstract class Query { + public abstract readonly document: DocumentNode | TypedDocumentNode; public client = 'default'; constructor(protected readonly apollo: Apollo) {} - public watch(variables?: V, options?: WatchQueryOptionsAlone): QueryRef { - return this.apollo.use(this.client).watchQuery({ + public watch( + variables?: TVariables, + options?: WatchQueryOptionsAlone, + ): QueryRef { + return this.apollo.use(this.client).watchQuery({ ...options, - variables: variables as V, + variables: variables as TVariables, query: this.document, }); } public fetch( - variables?: V, - options?: QueryOptionsAlone, - ): Observable> { - return this.apollo.use(this.client).query({ + variables?: TVariables, + options?: QueryOptionsAlone, + ): Observable> { + return this.apollo.use(this.client).query({ ...options, - variables: variables as V, + variables: variables as TVariables, query: this.document, }); } diff --git a/packages/apollo-angular/src/subscription.ts b/packages/apollo-angular/src/subscription.ts index e15a37fbf..8de716065 100644 --- a/packages/apollo-angular/src/subscription.ts +++ b/packages/apollo-angular/src/subscription.ts @@ -6,21 +6,24 @@ import { Apollo } from './apollo'; import { EmptyObject, ExtraSubscriptionOptions, SubscriptionOptionsAlone } from './types'; @Injectable() -export abstract class Subscription { - public abstract readonly document: DocumentNode | TypedDocumentNode; +export abstract class Subscription< + TData = unknown, + TVariables extends OperationVariables = EmptyObject, +> { + public abstract readonly document: DocumentNode | TypedDocumentNode; public client = 'default'; constructor(protected readonly apollo: Apollo) {} public subscribe( - variables?: V, - options?: SubscriptionOptionsAlone, + variables?: TVariables, + options?: SubscriptionOptionsAlone, extra?: ExtraSubscriptionOptions, - ): Observable> { - return this.apollo.use(this.client).subscribe( + ): Observable> { + return this.apollo.use(this.client).subscribe( { ...options, - variables: variables as V, + variables: variables as TVariables, query: this.document, }, extra, From a38dab8261257b5358378eb246acbd6020ec5846 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Thu, 18 Sep 2025 15:00:48 -0600 Subject: [PATCH 49/97] Export HttpHeadersLink and deprecate httpHeaders function --- packages/apollo-angular/headers/src/index.ts | 33 +++++++++++++------- 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/packages/apollo-angular/headers/src/index.ts b/packages/apollo-angular/headers/src/index.ts index a9073a756..e9c995e81 100644 --- a/packages/apollo-angular/headers/src/index.ts +++ b/packages/apollo-angular/headers/src/index.ts @@ -1,18 +1,27 @@ import { HttpHeaders } from '@angular/common/http'; import { ApolloLink } from '@apollo/client/core'; -export const httpHeaders = () => { - return new ApolloLink((operation: ApolloLink.Operation, forward: ApolloLink.ForwardFunction) => { - 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({ - ...context, - headers: new HttpHeaders(context.headers), - }); - } + return forward(operation); + }); + } +} - return forward(operation); - }); +/** + * @deprecated Use `HttpHeadersLink` instead. + */ +export const httpHeaders = () => { + return new HttpHeadersLink(); }; From 86663a5b11db015716480dab1185c0a84b500436 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Thu, 18 Sep 2025 15:01:10 -0600 Subject: [PATCH 50/97] Remove unneeded spread --- packages/apollo-angular/headers/src/index.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/apollo-angular/headers/src/index.ts b/packages/apollo-angular/headers/src/index.ts index e9c995e81..0fe042610 100644 --- a/packages/apollo-angular/headers/src/index.ts +++ b/packages/apollo-angular/headers/src/index.ts @@ -8,10 +8,7 @@ export class HttpHeadersLink extends ApolloLink { const context = getContext(); if (context.headers) { - setContext({ - ...context, - headers: new HttpHeaders(context.headers), - }); + setContext({ headers: new HttpHeaders(context.headers) }); } return forward(operation); From d640d1c40a1c5ed1501758ee2da816ff5357f677 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Thu, 18 Sep 2025 15:03:30 -0600 Subject: [PATCH 51/97] Use class in tests --- packages/apollo-angular/headers/tests/index.spec.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/apollo-angular/headers/tests/index.spec.ts b/packages/apollo-angular/headers/tests/index.spec.ts index 0e746b2cd..c533d1737 100644 --- a/packages/apollo-angular/headers/tests/index.spec.ts +++ b/packages/apollo-angular/headers/tests/index.spec.ts @@ -2,7 +2,7 @@ import { of } from 'rxjs'; import { describe, expect, test } from 'vitest'; import { HttpHeaders } from '@angular/common/http'; import { ApolloClient, ApolloLink, execute, gql, InMemoryCache } from '@apollo/client/core'; -import { httpHeaders } from '../src'; +import { HttpHeadersLink } from '../src'; const query = gql` query heroes { @@ -19,7 +19,7 @@ const dummyClient = new ApolloClient({ cache: new InMemoryCache(), link: ApolloL describe('httpHeaders', () => { test('should turn object into HttpHeaders', () => new Promise(done => { - const headersLink = httpHeaders(); + const headersLink = new HttpHeadersLink(); const mockLink = new ApolloLink(operation => { const { headers } = operation.getContext(); @@ -51,7 +51,7 @@ describe('httpHeaders', () => { test('should not set headers when not defined', () => new Promise(done => { - const headersLink = httpHeaders(); + const headersLink = new HttpHeadersLink(); const mockLink = new ApolloLink(operation => { const { headers } = operation.getContext(); From dec4e1c58240d7f7ff09088a51d4bce870e9e53e Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Thu, 18 Sep 2025 15:17:15 -0600 Subject: [PATCH 52/97] Rework HttpLink options by moving into namespace --- .../apollo-angular/http/src/deprecated.ts | 8 +++++++ .../http/src/http-batch-link.ts | 21 +++++++++++++----- packages/apollo-angular/http/src/http-link.ts | 22 ++++++++++++++++--- packages/apollo-angular/http/src/index.ts | 2 +- packages/apollo-angular/http/src/types.ts | 12 ---------- 5 files changed, 43 insertions(+), 22 deletions(-) create mode 100644 packages/apollo-angular/http/src/deprecated.ts diff --git a/packages/apollo-angular/http/src/deprecated.ts b/packages/apollo-angular/http/src/deprecated.ts new file mode 100644 index 000000000..1f3cde13a --- /dev/null +++ b/packages/apollo-angular/http/src/deprecated.ts @@ -0,0 +1,8 @@ +import { HttpBatchLink } from './http-batch-link'; +import { HttpLink } from './http-link'; + +/** @deprecated Use `HttpLink.Options` instead */ +export type Options = HttpLink.Options; + +/** @deprecated Use `HttpBatchLink.Options` instead */ +export type BatchOptions = HttpBatchLink.Options; diff --git a/packages/apollo-angular/http/src/http-batch-link.ts b/packages/apollo-angular/http/src/http-batch-link.ts index 823aeaf3f..18a3d53d5 100644 --- a/packages/apollo-angular/http/src/http-batch-link.ts +++ b/packages/apollo-angular/http/src/http-batch-link.ts @@ -4,9 +4,18 @@ import { HttpClient, HttpHeaders } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { ApolloLink } from '@apollo/client/core'; import { BatchLink } from '@apollo/client/link/batch'; -import { BatchOptions, Body, Context, OperationPrinter, Options, Request } from './types'; +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, @@ -23,9 +32,9 @@ export const defaults = { */ export function pick>( context: Context, - options: Options, + options: HttpLink.Options, key: K, -): ReturnType> { +): ReturnType> { return prioritize(context[key], options[key], defaults[key]); } @@ -37,7 +46,7 @@ export class HttpBatchLinkHandler extends ApolloLink { constructor( private readonly httpClient: HttpClient, - private readonly options: BatchOptions, + private readonly options: HttpBatchLink.Options, ) { super(); @@ -100,7 +109,7 @@ export class HttpBatchLinkHandler extends ApolloLink { private createOptions( operations: ApolloLink.Operation[], - ): Required> { + ): Required> { const context: Context = operations[0].getContext(); return { @@ -185,7 +194,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); } } diff --git a/packages/apollo-angular/http/src/http-link.ts b/packages/apollo-angular/http/src/http-link.ts index 0cf38062e..a6b8fa703 100644 --- a/packages/apollo-angular/http/src/http-link.ts +++ b/packages/apollo-angular/http/src/http-link.ts @@ -4,9 +4,25 @@ import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { ApolloLink } from '@apollo/client/core'; import { pick } from './http-batch-link'; -import { Body, Context, OperationPrinter, Options, Request } from './types'; +import { + Body, + Context, + ExtractFiles, + FetchOptions, + HttpRequestOptions, + OperationPrinter, + Request, +} from './types'; import { createHeadersWithClientAwareness, fetch, mergeHeaders } from './utils'; +export declare namespace HttpLink { + export interface Options extends FetchOptions, HttpRequestOptions { + operationPrinter?: OperationPrinter; + useGETForQueries?: boolean; + extractFiles?: ExtractFiles; + } +} + // XXX find a better name for it export class HttpLinkHandler extends ApolloLink { public requester: (operation: ApolloLink.Operation) => Observable; @@ -14,7 +30,7 @@ export class HttpLinkHandler extends ApolloLink { constructor( private readonly httpClient: HttpClient, - private readonly options: Options, + private readonly options: HttpLink.Options, ) { super(); @@ -96,7 +112,7 @@ export class HttpLinkHandler extends ApolloLink { export class HttpLink { constructor(private readonly httpClient: HttpClient) {} - public create(options: Options): HttpLinkHandler { + public create(options: HttpLink.Options): HttpLinkHandler { return new HttpLinkHandler(this.httpClient, options); } } diff --git a/packages/apollo-angular/http/src/index.ts b/packages/apollo-angular/http/src/index.ts index 7791a9da5..0c51fba14 100644 --- a/packages/apollo-angular/http/src/index.ts +++ b/packages/apollo-angular/http/src/index.ts @@ -3,4 +3,4 @@ export { HttpLink, HttpLinkHandler } from './http-link'; // http-batch export { HttpBatchLink, HttpBatchLinkHandler } from './http-batch-link'; // common -export { BatchOptions, Options } from './types'; +export { BatchOptions, Options } from './deprecated'; diff --git a/packages/apollo-angular/http/src/types.ts b/packages/apollo-angular/http/src/types.ts index 54f7243e5..56bcdd58d 100644 --- a/packages/apollo-angular/http/src/types.ts +++ b/packages/apollo-angular/http/src/types.ts @@ -23,12 +23,6 @@ export type FetchOptions = { export type OperationPrinter = (operation: DocumentNode) => string; -export interface Options extends FetchOptions, HttpRequestOptions { - operationPrinter?: OperationPrinter; - useGETForQueries?: boolean; - extractFiles?: ExtractFiles; -} - export type Body = { query?: string; variables?: Record; @@ -51,9 +45,3 @@ export type ExtractedFiles = { }; export type ExtractFiles = (body: Body | Body[]) => ExtractedFiles; - -export type BatchOptions = { - batchMax?: number; - batchInterval?: number; - batchKey?: (operation: ApolloLink.Operation) => string; -} & Options; From a4c5ca59f0c6d145a8f7c59ca8695b4465f3905e Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Thu, 18 Sep 2025 15:22:25 -0600 Subject: [PATCH 53/97] Fix issue with type for createHeaders --- packages/apollo-angular/http/src/http-batch-link.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/apollo-angular/http/src/http-batch-link.ts b/packages/apollo-angular/http/src/http-batch-link.ts index 18a3d53d5..587b197c0 100644 --- a/packages/apollo-angular/http/src/http-batch-link.ts +++ b/packages/apollo-angular/http/src/http-batch-link.ts @@ -152,7 +152,8 @@ export class HttpBatchLinkHandler extends ApolloLink { private createHeaders(operations: ApolloLink.Operation[]): HttpHeaders { return operations.reduce( (headers: HttpHeaders, operation: ApolloLink.Operation) => { - return mergeHeaders(headers, operation.getContext().headers); + const { headers: contextHeaders } = operation.getContext(); + return contextHeaders ? mergeHeaders(headers, contextHeaders) : headers; }, createHeadersWithClientAwareness({ headers: this.options.headers, From 5a81fdb288a815fe6d60a14ddb022c96eb7dab25 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Thu, 18 Sep 2025 16:03:10 -0600 Subject: [PATCH 54/97] Add ObservableStream helper --- .../test-utils/ObservableStream.ts | 167 ++++++++++++++++++ packages/apollo-angular/tsconfig.json | 3 +- 2 files changed, 169 insertions(+), 1 deletion(-) create mode 100644 packages/apollo-angular/test-utils/ObservableStream.ts diff --git a/packages/apollo-angular/test-utils/ObservableStream.ts b/packages/apollo-angular/test-utils/ObservableStream.ts new file mode 100644 index 000000000..09127ac5d --- /dev/null +++ b/packages/apollo-angular/test-utils/ObservableStream.ts @@ -0,0 +1,167 @@ +/** + * Adapted from + * https://github.com/apollographql/apollo-client/blob/1d165ba37eca7e5d667055553aacc4c26be56065/src/testing/internal/ObservableStream.ts + * + * The MIT License (MIT) + * + * Copyright (c) 2022 Apollo Graph, Inc. (Formerly Meteor Development Group, Inc.) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +import { ReadableStream } from 'node:stream/web'; +import type { Observable, Subscribable, Unsubscribable } from 'rxjs'; +import { expect } from 'vitest'; +import { equals, iterableEquality, JEST_MATCHERS_OBJECT } from '@vitest/expect'; +import { printDiffOrStringify } from '@vitest/utils/diff'; + +export interface TakeOptions { + timeout?: number; +} +type ObservableEvent = + | { type: 'next'; value: T } + | { type: 'error'; error: any } + | { type: 'complete' }; + +function formatMessage(expected: ObservableEvent, actual: ObservableEvent) { + return printDiffOrStringify(expected, actual, { expand: true }); +} + +export class EventMismatchError extends Error { + static is(error: unknown): error is EventMismatchError { + return error instanceof Error && error.name === 'EventMismatchError'; + } + + constructor(expected: ObservableEvent, actual: ObservableEvent) { + super(formatMessage(expected, actual)); + this.name = 'EventMismatchError'; + + Object.setPrototypeOf(this, EventMismatchError.prototype); + } +} + +export class ObservableStream { + private reader: ReadableStreamDefaultReader>; + private subscription!: Unsubscribable; + private readerQueue: Array>> = []; + + constructor(observable: Observable | Subscribable) { + this.unsubscribe = this.unsubscribe.bind(this); + this.reader = new ReadableStream>({ + start: controller => { + this.subscription = observable.subscribe({ + next: value => controller.enqueue({ type: 'next', value }), + error: error => controller.enqueue({ type: 'error', error }), + complete: () => controller.enqueue({ type: 'complete' }), + }); + }, + }).getReader(); + } + + peek({ timeout = 100 }: TakeOptions = {}) { + // Calling `peek` multiple times in a row should not advance the reader + // multiple times until this value has been consumed. + let readerPromise = this.readerQueue[0]; + + if (!readerPromise) { + // Since this.reader.read() advances the reader in the stream, we don't + // want to consume this promise entirely, otherwise we will miss it when + // calling `take`. Instead, we push it into a queue that can be consumed + // by `take` the next time its called so that we avoid advancing the + // reader until we are finished processing all peeked values. + readerPromise = this.readNextValue(); + this.readerQueue.push(readerPromise); + } + + return Promise.race([ + readerPromise, + new Promise>((_, reject) => { + setTimeout(reject, timeout, new Error('Timeout waiting for next event')); + }), + ]); + } + + take({ timeout = 100 }: TakeOptions = {}) { + return Promise.race([ + this.readerQueue.shift() || this.readNextValue(), + new Promise>((_, reject) => { + setTimeout(reject, timeout, new Error('Timeout waiting for next event')); + }), + ]).then(value => { + if (value.type === 'next') { + this.current = value.value; + } + return value; + }); + } + + [Symbol.dispose]() { + this.unsubscribe(); + } + + unsubscribe() { + this.subscription.unsubscribe(); + } + + async takeNext(options?: TakeOptions): Promise { + const event = await this.take(options); + validateEquals(event, { type: 'next', value: expect.anything() }); + return (event as ObservableEvent & { type: 'next' }).value; + } + + async takeError(options?: TakeOptions): Promise { + const event = await this.take(options); + validateEquals(event, { type: 'error', error: expect.anything() }); + return (event as ObservableEvent & { type: 'error' }).error; + } + + async takeComplete(options?: TakeOptions): Promise { + const event = await this.take(options); + validateEquals(event, { type: 'complete' }); + } + + private async readNextValue() { + return this.reader.read().then(result => result.value!); + } + + private current?: T; + getCurrent() { + return this.current; + } +} + +// Lightweight expect(...).toEqual(...) check that avoids using `expect` so that +// `expect.assertions(num)` does not double count assertions when using the take* +// functions inside of expect(stream).toEmit* matchers. +function validateEquals(actualEvent: ObservableEvent, expectedEvent: ObservableEvent) { + // Uses the same matchers as expect(...).toEqual(...) + // https://github.com/vitest-dev/vitest/blob/438c44e7fb8f3a6a36db8ff504f852c01963ba88/packages/expect/src/jest-expect.ts#L107-L110 + const isEqual = equals(actualEvent, expectedEvent, [ + ...getCustomEqualityTesters(), + iterableEquality, + ]); + + if (!isEqual) { + throw new EventMismatchError(expectedEvent, actualEvent); + } +} + +// https://github.com/vitest-dev/vitest/blob/438c44e7fb8f3a6a36db8ff504f852c01963ba88/packages/expect/src/jest-matcher-utils.ts#L157-L159 +function getCustomEqualityTesters() { + return (globalThis as any)[JEST_MATCHERS_OBJECT].customEqualityTesters; +} diff --git a/packages/apollo-angular/tsconfig.json b/packages/apollo-angular/tsconfig.json index 8bc35a98b..1a56cfd7e 100644 --- a/packages/apollo-angular/tsconfig.json +++ b/packages/apollo-angular/tsconfig.json @@ -14,6 +14,7 @@ "persisted-queries/**/*.ts", "src/**/*.ts", "testing/**/*.ts", - "tests/**/*.ts" + "tests/**/*.ts", + "test-utils/**/*.ts" ] } From 567e0ce7f8297ddbb300b57f0bed0ce63092e559 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Thu, 18 Sep 2025 16:06:43 -0600 Subject: [PATCH 55/97] Use ObservableStream to test refetch --- packages/apollo-angular/tests/Apollo.spec.ts | 121 ++++++++++--------- 1 file changed, 63 insertions(+), 58 deletions(-) diff --git a/packages/apollo-angular/tests/Apollo.spec.ts b/packages/apollo-angular/tests/Apollo.spec.ts index 614d3acc4..5893367bb 100644 --- a/packages/apollo-angular/tests/Apollo.spec.ts +++ b/packages/apollo-angular/tests/Apollo.spec.ts @@ -8,6 +8,7 @@ import { MockLink } from '@apollo/client/testing'; import { Apollo, ApolloBase } from '../src/apollo'; import { gql } from '../src/gql'; import { ZoneScheduler } from '../src/utils'; +import { ObservableStream } from '../test-utils/ObservableStream'; function mockApollo(link: ApolloLink, _ngZone: NgZone) { const apollo = new Apollo(_ngZone); @@ -90,73 +91,77 @@ describe('Apollo', () => { expect(client.watchQuery).toBeCalledWith(options); }); - test('should be able to refetch', () => - new Promise(done => { - expect.assertions(3); - const query = gql` - query refetch($first: Int) { - heroes(first: $first) { - name - __typename - } + test('should be able to refetch', async () => { + const query = gql` + query refetch($first: Int) { + heroes(first: $first) { + name + __typename } - `; + } + `; - const data1 = { heroes: [{ name: 'Foo', __typename: 'Hero' }] }; - const variables1 = { first: 0 }; + const data1 = { heroes: [{ name: 'Foo', __typename: 'Hero' }] }; + const variables1 = { first: 0 }; - const data2 = { heroes: [{ name: 'Bar', __typename: 'Hero' }] }; - const variables2 = { first: 1 }; + const data2 = { heroes: [{ name: 'Bar', __typename: 'Hero' }] }; + const variables2 = { first: 1 }; - const link = new MockLink([ - { - request: { query, variables: variables1 }, - result: { data: data1 }, - }, - { - request: { query, variables: variables2 }, - result: { data: data2 }, - }, - ]); + const link = new MockLink([ + { + request: { query, variables: variables1 }, + result: { data: data1 }, + }, + { + request: { query, variables: variables2 }, + result: { data: data2 }, + }, + ]); - const apollo = mockApollo(link, ngZone); - const options = { query, variables: variables1 }; - const obs = apollo.watchQuery(options); + const apollo = mockApollo(link, ngZone); + const options = { query, variables: variables1 }; + const obs = apollo.watchQuery(options); - let calls = 0; + const stream = new ObservableStream(obs.valueChanges); - obs.valueChanges.subscribe({ - next: ({ data }) => { - calls++; + await expect(stream.takeNext()).resolves.toEqual({ + data: undefined, + dataState: 'empty', + loading: true, + networkStatus: NetworkStatus.loading, + partial: true, + }); - try { - if (calls === 1) { - expect(data).toMatchObject(data1); - } else if (calls === 2) { - expect(data).toMatchObject(data2); - done(); - } else if (calls > 2) { - throw new Error('Called third time'); - } - } catch (e: any) { - throw e; - } - }, - error: err => { - throw err; - }, - }); + await expect(stream.takeNext()).resolves.toEqual({ + data: data1, + dataState: 'complete', + loading: false, + networkStatus: NetworkStatus.ready, + partial: false, + }); - setTimeout(() => { - obs.refetch(variables2).then(({ data }) => { - try { - expect(data).toMatchObject(data2); - } catch (e: any) { - throw e; - } - }); - }); - })); + await expect(stream.peek()).rejects.toThrow(/Timeout waiting/); + + await expect(obs.refetch(variables2)).resolves.toEqual({ data: data2 }); + + await expect(stream.takeNext()).resolves.toEqual({ + data: undefined, + dataState: 'empty', + loading: true, + networkStatus: NetworkStatus.refetch, + partial: true, + }); + + await expect(stream.takeNext()).resolves.toEqual({ + data: data2, + dataState: 'complete', + loading: false, + networkStatus: NetworkStatus.ready, + partial: false, + }); + + await expect(stream.peek()).rejects.toThrow(/Timeout waiting/); + }); }); describe('query()', () => { From 50232ffc6b2cfefa6403f879a726d56373284b25 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Thu, 18 Sep 2025 16:21:37 -0600 Subject: [PATCH 56/97] Add toEmitAnything matcher --- .../apollo-angular/test-utils/matchers.ts | 34 +++++++++++++++++++ packages/apollo-angular/tests/test-setup.ts | 1 + packages/apollo-angular/tests/vitest.d.ts | 11 ++++++ 3 files changed, 46 insertions(+) create mode 100644 packages/apollo-angular/test-utils/matchers.ts create mode 100644 packages/apollo-angular/tests/vitest.d.ts diff --git a/packages/apollo-angular/test-utils/matchers.ts b/packages/apollo-angular/test-utils/matchers.ts new file mode 100644 index 000000000..0afa3f14f --- /dev/null +++ b/packages/apollo-angular/test-utils/matchers.ts @@ -0,0 +1,34 @@ +import { expect } from 'vitest'; +import { ObservableStream, TakeOptions } from './ObservableStream'; + +expect.extend({ + async toEmitAnything(actual: ObservableStream, options: TakeOptions) { + const stream = actual as ObservableStream; + const hint = this.utils.matcherHint('toEmitAnything', 'stream'); + + try { + const value = await stream.peek(options); + + return { + pass: true, + message: () => { + return ( + hint + + '\n\nExpected stream not to emit anything but it did.' + + '\n\nReceived:\n' + + this.utils.printReceived(value) + ); + }, + }; + } catch (error) { + if (error instanceof Error && error.message === 'Timeout waiting for next event') { + return { + pass: false, + message: () => hint + '\n\nExpected stream to emit an event but it did not.', + }; + } else { + throw error; + } + } + }, +}); diff --git a/packages/apollo-angular/tests/test-setup.ts b/packages/apollo-angular/tests/test-setup.ts index b28aa1910..2e2d02241 100644 --- a/packages/apollo-angular/tests/test-setup.ts +++ b/packages/apollo-angular/tests/test-setup.ts @@ -1,4 +1,5 @@ import '@analogjs/vitest-angular/setup-zone'; +import '../test-utils/matchers'; import { getTestBed } from '@angular/core/testing'; import { BrowserDynamicTestingModule, diff --git a/packages/apollo-angular/tests/vitest.d.ts b/packages/apollo-angular/tests/vitest.d.ts new file mode 100644 index 000000000..de05459d6 --- /dev/null +++ b/packages/apollo-angular/tests/vitest.d.ts @@ -0,0 +1,11 @@ +import 'vitest'; +import type { TakeOptions } from '../test-utils/ObservableStream'; + +interface CustomMatchers { + toEmitAnything: (options?: TakeOptions) => Promise; +} + +declare module 'vitest' { + interface Assertion extends CustomMatchers {} + interface AsymmetricMatchersContaining extends CustomMatchers {} +} From 4dbe718bc169174071850edc663f65f055b4dee0 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Thu, 18 Sep 2025 16:25:48 -0600 Subject: [PATCH 57/97] Move toEmitAnything to own file --- .../apollo-angular/test-utils/matchers.ts | 32 ++--------------- .../test-utils/matchers/toEmitAnything.ts | 35 +++++++++++++++++++ 2 files changed, 37 insertions(+), 30 deletions(-) create mode 100644 packages/apollo-angular/test-utils/matchers/toEmitAnything.ts diff --git a/packages/apollo-angular/test-utils/matchers.ts b/packages/apollo-angular/test-utils/matchers.ts index 0afa3f14f..2385bebc8 100644 --- a/packages/apollo-angular/test-utils/matchers.ts +++ b/packages/apollo-angular/test-utils/matchers.ts @@ -1,34 +1,6 @@ import { expect } from 'vitest'; -import { ObservableStream, TakeOptions } from './ObservableStream'; +import { toEmitAnything } from './matchers/toEmitAnything'; expect.extend({ - async toEmitAnything(actual: ObservableStream, options: TakeOptions) { - const stream = actual as ObservableStream; - const hint = this.utils.matcherHint('toEmitAnything', 'stream'); - - try { - const value = await stream.peek(options); - - return { - pass: true, - message: () => { - return ( - hint + - '\n\nExpected stream not to emit anything but it did.' + - '\n\nReceived:\n' + - this.utils.printReceived(value) - ); - }, - }; - } catch (error) { - if (error instanceof Error && error.message === 'Timeout waiting for next event') { - return { - pass: false, - message: () => hint + '\n\nExpected stream to emit an event but it did not.', - }; - } else { - throw error; - } - } - }, + toEmitAnything, }); diff --git a/packages/apollo-angular/test-utils/matchers/toEmitAnything.ts b/packages/apollo-angular/test-utils/matchers/toEmitAnything.ts new file mode 100644 index 000000000..b66fa7a89 --- /dev/null +++ b/packages/apollo-angular/test-utils/matchers/toEmitAnything.ts @@ -0,0 +1,35 @@ +import { ObservableStream, TakeOptions } from 'test-utils/ObservableStream'; +import { RawMatcherFn } from '@vitest/expect'; + +export const toEmitAnything: RawMatcherFn = async function toEmitAnything( + actual, + options?: TakeOptions, +) { + const stream = actual as ObservableStream; + const hint = this.utils.matcherHint('toEmitAnything', 'stream'); + + try { + const value = await stream.peek(options); + + return { + pass: true, + message: () => { + return ( + hint + + '\n\nExpected stream not to emit anything but it did.' + + '\n\nReceived:\n' + + this.utils.printReceived(value) + ); + }, + }; + } catch (error) { + if (error instanceof Error && error.message === 'Timeout waiting for next event') { + return { + pass: false, + message: () => hint + '\n\nExpected stream to emit an event but it did not.', + }; + } else { + throw error; + } + } +}; From a29908223194b57d926aadf1341bfd884254dcf6 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Thu, 18 Sep 2025 16:27:10 -0600 Subject: [PATCH 58/97] Use toEmitAnything --- packages/apollo-angular/tests/Apollo.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/apollo-angular/tests/Apollo.spec.ts b/packages/apollo-angular/tests/Apollo.spec.ts index 5893367bb..36452c978 100644 --- a/packages/apollo-angular/tests/Apollo.spec.ts +++ b/packages/apollo-angular/tests/Apollo.spec.ts @@ -140,7 +140,7 @@ describe('Apollo', () => { partial: false, }); - await expect(stream.peek()).rejects.toThrow(/Timeout waiting/); + await expect(stream).not.toEmitAnything(); await expect(obs.refetch(variables2)).resolves.toEqual({ data: data2 }); @@ -160,7 +160,7 @@ describe('Apollo', () => { partial: false, }); - await expect(stream.peek()).rejects.toThrow(/Timeout waiting/); + await expect(stream).not.toEmitAnything(); }); }); From fe50eaa2feb4b2b5551e34cbebb7894b5854fa43 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Thu, 18 Sep 2025 16:32:12 -0600 Subject: [PATCH 59/97] Update another test to ObservableStream --- packages/apollo-angular/tests/Apollo.spec.ts | 164 +++++++++++-------- 1 file changed, 92 insertions(+), 72 deletions(-) diff --git a/packages/apollo-angular/tests/Apollo.spec.ts b/packages/apollo-angular/tests/Apollo.spec.ts index 36452c978..95f9b9fc8 100644 --- a/packages/apollo-angular/tests/Apollo.spec.ts +++ b/packages/apollo-angular/tests/Apollo.spec.ts @@ -759,88 +759,108 @@ describe('Apollo', () => { }); })); - test('should update a query with Optimistic Response after mutation', () => - new Promise(done => { - expect.assertions(3); - const query = gql` - query heroes { - allHeroes { - id - name - __typename - } + test('should update a query with Optimistic Response after mutation', async () => { + const query = gql` + query heroes { + allHeroes { + id + name + __typename } - `; - const mutation = gql` - mutation addHero($name: String!) { - addHero(name: $name) { - id - name - __typename - } + } + `; + const mutation = gql` + mutation addHero($name: String!) { + addHero(name: $name) { + id + name + __typename } - `; - const variables = { name: 'Bar' }; - const __typename = 'Hero'; + } + `; + const variables = { name: 'Bar' }; + const __typename = 'Hero'; - const FooHero = { id: 1, name: 'Foo', __typename }; - const BarHero = { id: 2, name: 'Bar', __typename }; - const OptimisticHero = { id: null, name: 'Temp', __typename }; + const FooHero = { id: 1, name: 'Foo', __typename }; + const BarHero = { id: 2, name: 'Bar', __typename }; + const OptimisticHero = { id: null, name: 'Temp', __typename }; - const data1 = { allHeroes: [FooHero] }; - const dataMutation = { addHero: BarHero }; - const data2 = { allHeroes: [FooHero, OptimisticHero] }; - const data3 = { allHeroes: [FooHero, BarHero] }; + const data1 = { allHeroes: [FooHero] }; + const dataMutation = { addHero: BarHero }; + const data2 = { allHeroes: [FooHero, OptimisticHero] }; + const data3 = { allHeroes: [FooHero, BarHero] }; - const link = new MockLink([ - { - request: { query }, - result: { data: data1 }, - }, - { - request: { query: mutation, variables }, - result: { data: dataMutation }, - }, - ]); - const apollo = mockApollo(link, ngZone); + const link = new MockLink([ + { + request: { query }, + result: { data: data1 }, + }, + { + request: { query: mutation, variables }, + result: { data: dataMutation }, + }, + ]); + const apollo = mockApollo(link, ngZone); - const obs = apollo.watchQuery({ query }); + const obs = apollo.watchQuery({ query }); + const stream = new ObservableStream(obs.valueChanges); - let calls = 0; - obs.valueChanges.subscribe(({ data }) => { - calls++; + await expect(stream.takeNext()).resolves.toEqual({ + data: undefined, + dataState: 'empty', + loading: true, + networkStatus: NetworkStatus.loading, + partial: true, + }); - if (calls === 1) { - expect(data).toMatchObject(data1); + await expect(stream.takeNext()).resolves.toEqual({ + data: data1, + dataState: 'complete', + loading: false, + networkStatus: NetworkStatus.ready, + partial: false, + }); - apollo - .mutate({ - mutation, - variables, - optimisticResponse: { - addHero: OptimisticHero, - }, - updateQueries: { - heroes: (prev: any, { mutationResult }: any) => { - return { - allHeroes: [...prev.allHeroes, mutationResult.data.addHero], - }; - }, - }, - }) - .subscribe({ - error(error) { - throw error.message; - }, - }); - } else if (calls === 2) { - expect(data).toMatchObject(data2); - } else if (calls === 3) { - expect(data).toMatchObject(data3); - done(); - } + apollo + .mutate({ + mutation, + variables, + optimisticResponse: { + addHero: OptimisticHero, + }, + updateQueries: { + heroes: (prev: any, { mutationResult }: any) => { + return { + allHeroes: [...prev.allHeroes, mutationResult.data.addHero], + }; + }, + }, + }) + .subscribe({ + error(error) { + throw error.message; + }, }); - })); + + // optimistic response + await expect(stream.takeNext()).resolves.toEqual({ + data: data2, + dataState: 'complete', + loading: false, + networkStatus: NetworkStatus.ready, + partial: false, + }); + + await expect(stream.takeNext()).resolves.toEqual({ + data: data3, + dataState: 'complete', + loading: false, + networkStatus: NetworkStatus.ready, + partial: false, + }); + + await expect(stream).not.toEmitAnything(); + }); }); test('should use HttpClient', () => From a040605f6e8476ae7a04be30a2dbc57c1252dffb Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Thu, 18 Sep 2025 16:41:00 -0600 Subject: [PATCH 60/97] Update another failing test to ObservableStream --- packages/apollo-angular/tests/Apollo.spec.ts | 153 ++++++++++--------- 1 file changed, 82 insertions(+), 71 deletions(-) diff --git a/packages/apollo-angular/tests/Apollo.spec.ts b/packages/apollo-angular/tests/Apollo.spec.ts index 95f9b9fc8..2103c6d86 100644 --- a/packages/apollo-angular/tests/Apollo.spec.ts +++ b/packages/apollo-angular/tests/Apollo.spec.ts @@ -681,83 +681,94 @@ describe('Apollo', () => { }); describe('query updates', () => { - test('should update a query after mutation', () => - new Promise(done => { - expect.assertions(3); - const query = gql` - query heroes { - allHeroes { - name - __typename - } + test('should update a query after mutation', async () => { + const query = gql` + query heroes { + allHeroes { + name + __typename } - `; - const mutation = gql` - mutation addHero($name: String!) { - addHero(name: $name) { - name - __typename - } + } + `; + const mutation = gql` + mutation addHero($name: String!) { + addHero(name: $name) { + name + __typename } - `; - const variables = { name: 'Bar' }; - // tslint:disable:variable-name - const __typename = 'Hero'; + } + `; + const variables = { name: 'Bar' }; + // tslint:disable:variable-name + const __typename = 'Hero'; - const FooHero = { name: 'Foo', __typename }; - const BarHero = { name: 'Bar', __typename }; + const FooHero = { name: 'Foo', __typename }; + const BarHero = { name: 'Bar', __typename }; - const data1 = { allHeroes: [FooHero] }; - const dataMutation = { addHero: BarHero }; - const data2 = { allHeroes: [FooHero, BarHero] }; + const data1 = { allHeroes: [FooHero] }; + const dataMutation = { addHero: BarHero }; + const data2 = { allHeroes: [FooHero, BarHero] }; - const link = new MockLink([ - { - request: { query }, - result: { data: data1 }, - }, - { - request: { query: mutation, variables }, - result: { data: dataMutation }, + const link = new MockLink([ + { + request: { query }, + result: { data: data1 }, + }, + { + request: { query: mutation, variables }, + result: { data: dataMutation }, + }, + ]); + const apollo = mockApollo(link, ngZone); + + const obs = apollo.watchQuery({ query }); + const stream = new ObservableStream(obs.valueChanges); + + await expect(stream.takeNext()).resolves.toEqual({ + data: undefined, + dataState: 'empty', + loading: true, + networkStatus: NetworkStatus.loading, + partial: true, + }); + + await expect(stream.takeNext()).resolves.toEqual({ + data: data1, + dataState: 'complete', + loading: false, + networkStatus: NetworkStatus.ready, + partial: false, + }); + + const mutationStream = new ObservableStream( + apollo.mutate({ + mutation, + variables, + updateQueries: { + heroes: (prev: any, { mutationResult }: any) => { + return { + allHeroes: [...prev.allHeroes, mutationResult.data.addHero], + }; + }, }, - ]); - const apollo = mockApollo(link, ngZone); - - const obs = apollo.watchQuery({ query }); - - let calls = 0; - obs.valueChanges.subscribe(({ data }) => { - calls++; - - if (calls === 1) { - expect(data).toMatchObject(data1); - - apollo - .mutate({ - mutation, - variables, - updateQueries: { - heroes: (prev: any, { mutationResult }: any) => { - return { - allHeroes: [...prev.allHeroes, mutationResult.data.addHero], - }; - }, - }, - }) - .subscribe({ - next: result => { - expect(result.data.addHero).toMatchObject(BarHero); - }, - error(error) { - throw error.message; - }, - }); - } else if (calls === 2) { - expect(data).toMatchObject(data2); - done(); - } - }); - })); + }), + ); + + await expect(mutationStream.takeNext()).resolves.toEqual({ + data: { addHero: BarHero }, + loading: false, + }); + + await expect(stream.takeNext()).resolves.toEqual({ + data: data2, + dataState: 'complete', + loading: false, + networkStatus: NetworkStatus.ready, + partial: false, + }); + + await expect(stream).not.toEmitAnything(); + }); test('should update a query with Optimistic Response after mutation', async () => { const query = gql` From 498ed5053601b86e2df1f52e8544cb0900bb166f Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Thu, 18 Sep 2025 16:45:23 -0600 Subject: [PATCH 61/97] Remove tests for useInitialLoading --- packages/apollo-angular/tests/Apollo.spec.ts | 162 ------------------- 1 file changed, 162 deletions(-) diff --git a/packages/apollo-angular/tests/Apollo.spec.ts b/packages/apollo-angular/tests/Apollo.spec.ts index 2103c6d86..df85c622e 100644 --- a/packages/apollo-angular/tests/Apollo.spec.ts +++ b/packages/apollo-angular/tests/Apollo.spec.ts @@ -259,51 +259,6 @@ describe('Apollo', () => { }, }); })); - - test('should NOT useInitialLoading by default', () => - new Promise(done => { - expect.assertions(2); - const apollo = testBed.inject(Apollo); - const query = gql` - query heroes { - heroes { - name - __typename - } - } - `; - const data = { - heroes: [ - { - name: 'Superman', - __typename: 'Hero', - }, - ], - }; - - // create - apollo.create({ - link: new MockLink([{ request: { query }, result: { data } }]), - cache: new InMemoryCache(), - }); - - // query - apollo - .query({ - query, - }) - .subscribe({ - next: result => { - expect(result.data).toMatchObject(data); - setTimeout(() => { - return done(); - }, 3000); - }, - error: e => { - throw e; - }, - }); - })); }); describe('mutate()', () => { @@ -916,123 +871,6 @@ describe('Apollo', () => { }); })); - test('should useInitialLoading', () => - new Promise(done => { - expect.assertions(3); - const apollo = testBed.inject(Apollo); - const query = gql` - query heroes { - heroes { - name - __typename - } - } - `; - const data = { - heroes: [ - { - name: 'Superman', - __typename: 'Hero', - }, - ], - }; - - let alreadyCalled = false; - - // create - apollo.create({ - link: new MockLink([{ request: { query }, result: { data } }]), - cache: new InMemoryCache(), - }); - - // query - apollo - .watchQuery({ - query, - useInitialLoading: true, - }) - .valueChanges.subscribe({ - next: result => { - if (alreadyCalled) { - expect(result.data).toMatchObject(data); - setTimeout(() => { - return done(); - }, 3000); - } else { - expect(result.loading).toBe(true); - expect(result.networkStatus).toBe(NetworkStatus.loading); - alreadyCalled = true; - } - }, - error: e => { - throw e; - }, - }); - })); - - test('useInitialLoading should emit false once when data is already available', () => - new Promise(done => { - expect.assertions(4); - const apollo = testBed.inject(Apollo); - const query = gql` - query heroes { - heroes { - name - __typename - } - } - `; - const data = { - heroes: [ - { - name: 'Superman', - __typename: 'Hero', - }, - ], - }; - - let calls = 0; - - const cache = new InMemoryCache(); - - cache.writeQuery({ - query: query, - data, - }); - - // create - apollo.create({ - link: new MockLink([{ request: { query }, result: { data } }]), - cache, - }); - - // query - apollo - .watchQuery({ - query, - notifyOnNetworkStatusChange: true, - useInitialLoading: true, - }) - .valueChanges.subscribe({ - next: result => { - calls++; - - if (calls === 1) { - setTimeout(() => { - expect(calls).toEqual(1); - expect(result.loading).toEqual(false); - expect(result.networkStatus).toEqual(NetworkStatus.ready); - expect(result.data).toEqual(data); - return done(); - }, 3000); - } - }, - error: e => { - throw e; - }, - }); - })); - test('should emit cached result only once', () => new Promise(done => { expect.assertions(3); From 839e311508dada8b3a08fa47683ec6493f1ef4c9 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Thu, 18 Sep 2025 16:45:31 -0600 Subject: [PATCH 62/97] Fix ts issue with mocks --- packages/apollo-angular/tests/Apollo.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/apollo-angular/tests/Apollo.spec.ts b/packages/apollo-angular/tests/Apollo.spec.ts index df85c622e..5a41da822 100644 --- a/packages/apollo-angular/tests/Apollo.spec.ts +++ b/packages/apollo-angular/tests/Apollo.spec.ts @@ -206,7 +206,7 @@ describe('Apollo', () => { const client = apollo.client; - client.query = vi.fn(options => { + client.query = vi.fn((options: { used: boolean }) => { if (options.used) { throw new Error('options was reused'); } @@ -318,7 +318,7 @@ describe('Apollo', () => { const client = apollo.client; - client.mutate = vi.fn(options => { + client.mutate = vi.fn((options: { used: boolean }) => { if (options.used) { throw new Error('options was reused'); } From 07211ec2e3202f53dc09f496f67be4272af45d94 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Thu, 18 Sep 2025 17:38:46 -0600 Subject: [PATCH 63/97] Combine parameters in Query class --- packages/apollo-angular/src/index.ts | 2 -- packages/apollo-angular/src/query.ts | 30 ++++++++++++++------- packages/apollo-angular/src/types.ts | 10 ------- packages/apollo-angular/tests/Query.spec.ts | 12 ++++----- 4 files changed, 27 insertions(+), 27 deletions(-) diff --git a/packages/apollo-angular/src/index.ts b/packages/apollo-angular/src/index.ts index 0b4484e53..d96e4accb 100644 --- a/packages/apollo-angular/src/index.ts +++ b/packages/apollo-angular/src/index.ts @@ -12,11 +12,9 @@ export type { MutationOptionsAlone, MutationResult, NamedOptions, - QueryOptionsAlone, ResultOf, SubscriptionOptionsAlone, VariablesOf, WatchQueryOptions, - WatchQueryOptionsAlone, } from './types'; export { gql } from './gql'; diff --git a/packages/apollo-angular/src/query.ts b/packages/apollo-angular/src/query.ts index 5c5ae8bda..d54666737 100644 --- a/packages/apollo-angular/src/query.ts +++ b/packages/apollo-angular/src/query.ts @@ -4,7 +4,19 @@ import { Injectable } from '@angular/core'; import type { ApolloClient, OperationVariables, TypedDocumentNode } from '@apollo/client/core'; import { Apollo } from './apollo'; import { QueryRef } from './query-ref'; -import { EmptyObject, QueryOptionsAlone, WatchQueryOptionsAlone } from './types'; +import { EmptyObject, WatchQueryOptions } from './types'; + +export declare namespace Query { + export type WatchOptions< + TData = unknown, + TVariables extends OperationVariables = EmptyObject, + > = Omit, 'query'>; + + export type FetchOptions< + TData = unknown, + TVariables extends OperationVariables = EmptyObject, + > = Omit, 'query'>; +} @Injectable() export abstract class Query { @@ -14,24 +26,24 @@ export abstract class Query, + ...[options]: {} extends TVariables + ? [options?: Query.WatchOptions] + : [options: Query.WatchOptions] ): QueryRef { return this.apollo.use(this.client).watchQuery({ ...options, - variables: variables as TVariables, query: this.document, - }); + } as ApolloClient.WatchQueryOptions); } public fetch( - variables?: TVariables, - options?: QueryOptionsAlone, + ...[options]: {} extends TVariables + ? [options?: Query.FetchOptions] + : [options: Query.FetchOptions] ): Observable> { return this.apollo.use(this.client).query({ ...options, - variables: variables as TVariables, query: this.document, - }); + } as ApolloClient.QueryOptions); } } diff --git a/packages/apollo-angular/src/types.ts b/packages/apollo-angular/src/types.ts index 3160796b0..ad8a4b9ce 100644 --- a/packages/apollo-angular/src/types.ts +++ b/packages/apollo-angular/src/types.ts @@ -25,16 +25,6 @@ export type MutationResult = ApolloLink.Result & { export type Omit = Pick>; -export type WatchQueryOptionsAlone< - TData = unknown, - TVariables extends OperationVariables = EmptyObject, -> = Omit, 'query' | 'variables'>; - -export type QueryOptionsAlone< - TData = unknown, - TVariables extends OperationVariables = EmptyObject, -> = Omit, 'query' | 'variables'>; - export type MutationOptionsAlone< TData = unknown, TVariables extends OperationVariables = EmptyObject, diff --git a/packages/apollo-angular/tests/Query.spec.ts b/packages/apollo-angular/tests/Query.spec.ts index 019a1648a..fd0736237 100644 --- a/packages/apollo-angular/tests/Query.spec.ts +++ b/packages/apollo-angular/tests/Query.spec.ts @@ -84,7 +84,7 @@ describe('Query', () => { }); test('should pass variables to Apollo.watchQuery', () => { - heroesQuery.watch({ foo: 1 }); + heroesQuery.watch({ variables: { foo: 1 } }); expect(apolloMock.watchQuery).toBeCalled(); expect(apolloMock.watchQuery.mock.calls[0][0]).toMatchObject({ @@ -93,7 +93,7 @@ describe('Query', () => { }); test('should pass options to Apollo.watchQuery', () => { - heroesQuery.watch({}, { fetchPolicy: 'network-only' }); + heroesQuery.watch({ fetchPolicy: 'network-only' }); expect(apolloMock.watchQuery).toBeCalled(); expect(apolloMock.watchQuery.mock.calls[0][0]).toMatchObject({ @@ -102,7 +102,7 @@ describe('Query', () => { }); test('should not overwrite query when options object is provided', () => { - heroesQuery.watch({}, { query: 'asd', fetchPolicy: 'cache-first' } as any); + heroesQuery.watch({ query: 'asd', fetchPolicy: 'cache-first' } as any); expect(apolloMock.watchQuery).toBeCalled(); expect(apolloMock.watchQuery.mock.calls[0][0]).toMatchObject({ @@ -133,7 +133,7 @@ describe('Query', () => { }); test('should pass variables to Apollo.query', () => { - heroesQuery.fetch({ foo: 1 }); + heroesQuery.fetch({ variables: { foo: 1 } }); expect(apolloMock.query).toBeCalled(); expect(apolloMock.query.mock.calls[0][0]).toMatchObject({ @@ -142,7 +142,7 @@ describe('Query', () => { }); test('should pass options to Apollo.query', () => { - heroesQuery.fetch({}, { fetchPolicy: 'network-only' }); + heroesQuery.fetch({ fetchPolicy: 'network-only' }); expect(apolloMock.query).toBeCalled(); expect(apolloMock.query.mock.calls[0][0]).toMatchObject({ @@ -151,7 +151,7 @@ describe('Query', () => { }); test('should not overwrite query when options object is provided', () => { - heroesQuery.fetch({}, { query: 'asd', fetchPolicy: 'cache-first' } as any); + heroesQuery.fetch({ query: 'asd', fetchPolicy: 'cache-first' } as any); expect(apolloMock.query).toBeCalled(); expect(apolloMock.query.mock.calls[0][0]).toMatchObject({ From 4564cb4c774be8eac8ffe6d971bdd91054bcafae Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Thu, 18 Sep 2025 17:47:42 -0600 Subject: [PATCH 64/97] Combine variables into options object for Mutation --- packages/apollo-angular/src/index.ts | 1 - packages/apollo-angular/src/mutation.ts | 17 ++++++++++++----- packages/apollo-angular/src/types.ts | 5 ----- packages/apollo-angular/tests/Mutation.spec.ts | 6 +++--- 4 files changed, 15 insertions(+), 14 deletions(-) diff --git a/packages/apollo-angular/src/index.ts b/packages/apollo-angular/src/index.ts index d96e4accb..2d09e7698 100644 --- a/packages/apollo-angular/src/index.ts +++ b/packages/apollo-angular/src/index.ts @@ -9,7 +9,6 @@ export { APOLLO_OPTIONS, APOLLO_NAMED_OPTIONS, APOLLO_FLAGS } from './tokens'; export type { ExtraSubscriptionOptions, Flags, - MutationOptionsAlone, MutationResult, NamedOptions, ResultOf, diff --git a/packages/apollo-angular/src/mutation.ts b/packages/apollo-angular/src/mutation.ts index 15ad37f8f..da1b5a562 100644 --- a/packages/apollo-angular/src/mutation.ts +++ b/packages/apollo-angular/src/mutation.ts @@ -3,7 +3,14 @@ import type { Observable } from 'rxjs'; import { Injectable } from '@angular/core'; import type { OperationVariables, TypedDocumentNode } from '@apollo/client/core'; import { Apollo } from './apollo'; -import type { EmptyObject, MutationOptionsAlone, MutationResult } from './types'; +import type { EmptyObject, MutationOptions, MutationResult } from './types'; + +export declare namespace Mutation { + export type MutateOptions< + TData = unknown, + TVariables extends OperationVariables = EmptyObject, + > = Omit, 'mutation'>; +} @Injectable() export abstract class Mutation< @@ -16,13 +23,13 @@ export abstract class Mutation< constructor(protected readonly apollo: Apollo) {} public mutate( - variables?: TVariables, - options?: MutationOptionsAlone, + ...[options]: {} extends TVariables + ? [options?: Mutation.MutateOptions] + : [options: Mutation.MutateOptions] ): Observable> { return this.apollo.use(this.client).mutate({ ...options, - variables: variables as TVariables, mutation: this.document, - }); + } as MutationOptions); } } diff --git a/packages/apollo-angular/src/types.ts b/packages/apollo-angular/src/types.ts index ad8a4b9ce..cc1f76326 100644 --- a/packages/apollo-angular/src/types.ts +++ b/packages/apollo-angular/src/types.ts @@ -25,11 +25,6 @@ export type MutationResult = ApolloLink.Result & { export type Omit = Pick>; -export type MutationOptionsAlone< - TData = unknown, - TVariables extends OperationVariables = EmptyObject, -> = Omit, 'mutation' | 'variables'>; - export type SubscriptionOptionsAlone< TData = unknown, TVariables extends OperationVariables = EmptyObject, diff --git a/packages/apollo-angular/tests/Mutation.spec.ts b/packages/apollo-angular/tests/Mutation.spec.ts index 76a51ac1c..523396534 100644 --- a/packages/apollo-angular/tests/Mutation.spec.ts +++ b/packages/apollo-angular/tests/Mutation.spec.ts @@ -61,7 +61,7 @@ describe('Mutation', () => { }); test('should pass variables to Apollo.mutate', () => { - addHero.mutate({ foo: 1 }); + addHero.mutate({ variables: { foo: 1 } }); expect(apolloMock.mutate).toBeCalled(); expect(apolloMock.mutate.mock.calls[0][0]).toMatchObject({ @@ -70,7 +70,7 @@ describe('Mutation', () => { }); test('should pass options to Apollo.mutate', () => { - addHero.mutate({}, { fetchPolicy: 'no-cache' }); + addHero.mutate({ fetchPolicy: 'no-cache' }); expect(apolloMock.mutate).toBeCalled(); expect(apolloMock.mutate.mock.calls[0][0]).toMatchObject({ @@ -79,7 +79,7 @@ describe('Mutation', () => { }); test('should not overwrite query when options object is provided', () => { - addHero.mutate({}, { query: 'asd', fetchPolicy: 'cache-first' } as any); + addHero.mutate({ mutation: 'asd', fetchPolicy: 'cache-first' } as any); expect(apolloMock.mutate).toBeCalled(); expect(apolloMock.mutate.mock.calls[0][0]).toMatchObject({ From 847f5912fb78b9625813389de8b0dbc0b669aefc Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Thu, 18 Sep 2025 17:52:15 -0600 Subject: [PATCH 65/97] Combine variables into options for Subscription --- packages/apollo-angular/src/index.ts | 1 - packages/apollo-angular/src/subscription.ts | 24 ++++++++++++++----- packages/apollo-angular/src/types.ts | 5 ---- .../apollo-angular/tests/Subscription.spec.ts | 6 ++--- 4 files changed, 21 insertions(+), 15 deletions(-) diff --git a/packages/apollo-angular/src/index.ts b/packages/apollo-angular/src/index.ts index 2d09e7698..3826bb745 100644 --- a/packages/apollo-angular/src/index.ts +++ b/packages/apollo-angular/src/index.ts @@ -12,7 +12,6 @@ export type { MutationResult, NamedOptions, ResultOf, - SubscriptionOptionsAlone, VariablesOf, WatchQueryOptions, } from './types'; diff --git a/packages/apollo-angular/src/subscription.ts b/packages/apollo-angular/src/subscription.ts index 8de716065..54865169b 100644 --- a/packages/apollo-angular/src/subscription.ts +++ b/packages/apollo-angular/src/subscription.ts @@ -3,7 +3,14 @@ import type { Observable } from 'rxjs'; import { Injectable } from '@angular/core'; import type { ApolloClient, OperationVariables, TypedDocumentNode } from '@apollo/client/core'; import { Apollo } from './apollo'; -import { EmptyObject, ExtraSubscriptionOptions, SubscriptionOptionsAlone } from './types'; +import { EmptyObject, ExtraSubscriptionOptions } from './types'; + +export declare namespace Subscription { + export type SubscribeOptions< + TData = unknown, + TVariables extends OperationVariables = EmptyObject, + > = Omit, 'query'>; +} @Injectable() export abstract class Subscription< @@ -16,16 +23,21 @@ export abstract class Subscription< constructor(protected readonly apollo: Apollo) {} public subscribe( - variables?: TVariables, - options?: SubscriptionOptionsAlone, - extra?: ExtraSubscriptionOptions, + ...[options, extra]: {} extends TVariables + ? [ + options?: Subscription.SubscribeOptions, + extra?: ExtraSubscriptionOptions, + ] + : [ + options: Subscription.SubscribeOptions, + extra?: ExtraSubscriptionOptions, + ] ): Observable> { return this.apollo.use(this.client).subscribe( { ...options, - variables: variables as TVariables, query: this.document, - }, + } as ApolloClient.SubscribeOptions, extra, ); } diff --git a/packages/apollo-angular/src/types.ts b/packages/apollo-angular/src/types.ts index cc1f76326..30829d77f 100644 --- a/packages/apollo-angular/src/types.ts +++ b/packages/apollo-angular/src/types.ts @@ -25,11 +25,6 @@ export type MutationResult = ApolloLink.Result & { export type Omit = Pick>; -export type SubscriptionOptionsAlone< - TData = unknown, - TVariables extends OperationVariables = EmptyObject, -> = Omit, 'query' | 'variables'>; - export type WatchQueryOptions< TData = unknown, TVariables extends OperationVariables = EmptyObject, diff --git a/packages/apollo-angular/tests/Subscription.spec.ts b/packages/apollo-angular/tests/Subscription.spec.ts index 4559b6f44..64903d1f5 100644 --- a/packages/apollo-angular/tests/Subscription.spec.ts +++ b/packages/apollo-angular/tests/Subscription.spec.ts @@ -60,7 +60,7 @@ describe('Subscription', () => { }); test('should pass variables to Apollo.subscribe', () => { - heroes.subscribe({ foo: 1 }); + heroes.subscribe({ variables: { foo: 1 } }); expect(apolloMock.subscribe).toBeCalled(); expect(apolloMock.subscribe.mock.calls[0][0]).toMatchObject({ @@ -69,7 +69,7 @@ describe('Subscription', () => { }); test('should pass options to Apollo.subscribe', () => { - heroes.subscribe({}, { fetchPolicy: 'network-only' }); + heroes.subscribe({ fetchPolicy: 'network-only' }); expect(apolloMock.subscribe).toBeCalled(); expect(apolloMock.subscribe.mock.calls[0][0]).toMatchObject({ @@ -78,7 +78,7 @@ describe('Subscription', () => { }); test('should not overwrite query when options object is provided', () => { - heroes.subscribe({}, { query: 'asd', fetchPolicy: 'cache-first' } as any); + heroes.subscribe({ query: 'asd', fetchPolicy: 'cache-first' } as any); expect(apolloMock.subscribe).toBeCalled(); expect(apolloMock.subscribe.mock.calls[0][0]).toMatchObject({ From 1e2e8a9599c4300e666405aa124d03f3ccea9da6 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Thu, 18 Sep 2025 18:10:51 -0600 Subject: [PATCH 66/97] Move options types into namespaces --- packages/apollo-angular/src/apollo.ts | 48 +++++++++++++++++---- packages/apollo-angular/src/deprecated.ts | 15 +++++++ packages/apollo-angular/src/index.ts | 3 +- packages/apollo-angular/src/mutation.ts | 6 +-- packages/apollo-angular/src/query.ts | 4 +- packages/apollo-angular/src/subscription.ts | 2 +- packages/apollo-angular/src/types.ts | 31 +------------ 7 files changed, 64 insertions(+), 45 deletions(-) create mode 100644 packages/apollo-angular/src/deprecated.ts diff --git a/packages/apollo-angular/src/apollo.ts b/packages/apollo-angular/src/apollo.ts index e4565ca17..2a51010f5 100644 --- a/packages/apollo-angular/src/apollo.ts +++ b/packages/apollo-angular/src/apollo.ts @@ -8,14 +8,46 @@ import type { EmptyObject, ExtraSubscriptionOptions, Flags, - MutationOptions, MutationResult, NamedOptions, - WatchFragmentOptions, - WatchQueryOptions, } from './types'; import { fromLazyPromise, useMutationLoading, wrapWithZone } from './utils'; +export declare namespace Apollo { + export type WatchQueryOptions< + TData = unknown, + TVariables extends OperationVariables = EmptyObject, + > = ApolloClient.WatchQueryOptions; + + export type QueryOptions< + TData = unknown, + TVariables extends OperationVariables = EmptyObject, + > = ApolloClient.QueryOptions; + + export type MutateOptions< + TData = unknown, + TVariables extends OperationVariables = EmptyObject, + > = ApolloClient.MutateOptions & { + /** + * Observable starts with `{ loading: true }`. + * There's a big chance the next major version will enable that by default. + * + * Disabled by default + */ + useMutationLoading?: boolean; + }; + + export type SubscribeOptions< + TData = unknown, + TVariables extends OperationVariables = EmptyObject, + > = ApolloClient.SubscribeOptions; + + export interface WatchFragmentOptions< + TData = unknown, + TVariables extends OperationVariables = EmptyObject, + > extends ApolloCache.WatchFragmentOptions {} +} + export class ApolloBase { private useMutationLoading: boolean; @@ -28,7 +60,7 @@ export class ApolloBase { } public watchQuery( - options: WatchQueryOptions, + options: Apollo.WatchQueryOptions, ): QueryRef { return new QueryRef( this.ensureClient().watchQuery({ ...options }), @@ -37,7 +69,7 @@ export class ApolloBase { } public query( - options: ApolloClient.QueryOptions, + options: Apollo.QueryOptions, ): Observable> { return fromLazyPromise>(() => this.ensureClient().query({ ...options }), @@ -45,7 +77,7 @@ export class ApolloBase { } public mutate( - options: MutationOptions, + options: Apollo.MutateOptions, ): Observable> { return useMutationLoading( fromLazyPromise(() => this.ensureClient().mutate({ ...options })), @@ -57,7 +89,7 @@ export class ApolloBase { TFragmentData = unknown, TVariables extends OperationVariables = EmptyObject, >( - options: WatchFragmentOptions, + options: Apollo.WatchFragmentOptions, extra?: ExtraSubscriptionOptions, ): Observable> { const obs = this.ensureClient().watchFragment({ ...options }); @@ -66,7 +98,7 @@ export class ApolloBase { } public subscribe( - options: ApolloClient.SubscribeOptions, + options: Apollo.SubscribeOptions, extra?: ExtraSubscriptionOptions, ): Observable> { const obs = this.ensureClient().subscribe({ ...options }); diff --git a/packages/apollo-angular/src/deprecated.ts b/packages/apollo-angular/src/deprecated.ts new file mode 100644 index 000000000..494816332 --- /dev/null +++ b/packages/apollo-angular/src/deprecated.ts @@ -0,0 +1,15 @@ +import type { OperationVariables } from '@apollo/client'; +import type { Apollo } from './apollo'; +import type { EmptyObject } from './types'; + +/** @deprecated Use `Apollo.WatchQueryOptions` instead */ +export type WatchQueryOptions< + TData = unknown, + TVariables extends OperationVariables = EmptyObject, +> = Apollo.WatchQueryOptions; + +/** @deprecated Use `Apollo.MutateOptions` instead */ +export type MutationOptions< + TData = unknown, + TVariables extends OperationVariables = EmptyObject, +> = Apollo.MutateOptions; diff --git a/packages/apollo-angular/src/index.ts b/packages/apollo-angular/src/index.ts index 3826bb745..1fa29acaa 100644 --- a/packages/apollo-angular/src/index.ts +++ b/packages/apollo-angular/src/index.ts @@ -13,6 +13,7 @@ export type { NamedOptions, ResultOf, VariablesOf, - WatchQueryOptions, } from './types'; export { gql } from './gql'; + +export { MutationOptions, WatchQueryOptions } from './deprecated'; diff --git a/packages/apollo-angular/src/mutation.ts b/packages/apollo-angular/src/mutation.ts index da1b5a562..963583e93 100644 --- a/packages/apollo-angular/src/mutation.ts +++ b/packages/apollo-angular/src/mutation.ts @@ -3,13 +3,13 @@ import type { Observable } from 'rxjs'; import { Injectable } from '@angular/core'; import type { OperationVariables, TypedDocumentNode } from '@apollo/client/core'; import { Apollo } from './apollo'; -import type { EmptyObject, MutationOptions, MutationResult } from './types'; +import type { EmptyObject, MutationResult } from './types'; export declare namespace Mutation { export type MutateOptions< TData = unknown, TVariables extends OperationVariables = EmptyObject, - > = Omit, 'mutation'>; + > = Omit, 'mutation'>; } @Injectable() @@ -30,6 +30,6 @@ export abstract class Mutation< return this.apollo.use(this.client).mutate({ ...options, mutation: this.document, - } as MutationOptions); + } as Apollo.MutateOptions); } } diff --git a/packages/apollo-angular/src/query.ts b/packages/apollo-angular/src/query.ts index d54666737..af7ed348e 100644 --- a/packages/apollo-angular/src/query.ts +++ b/packages/apollo-angular/src/query.ts @@ -4,13 +4,13 @@ import { Injectable } from '@angular/core'; import type { ApolloClient, OperationVariables, TypedDocumentNode } from '@apollo/client/core'; import { Apollo } from './apollo'; import { QueryRef } from './query-ref'; -import { EmptyObject, WatchQueryOptions } from './types'; +import { EmptyObject } from './types'; export declare namespace Query { export type WatchOptions< TData = unknown, TVariables extends OperationVariables = EmptyObject, - > = Omit, 'query'>; + > = Omit, 'query'>; export type FetchOptions< TData = unknown, diff --git a/packages/apollo-angular/src/subscription.ts b/packages/apollo-angular/src/subscription.ts index 54865169b..bd0b692cb 100644 --- a/packages/apollo-angular/src/subscription.ts +++ b/packages/apollo-angular/src/subscription.ts @@ -9,7 +9,7 @@ export declare namespace Subscription { export type SubscribeOptions< TData = unknown, TVariables extends OperationVariables = EmptyObject, - > = Omit, 'query'>; + > = Omit, 'query'>; } @Injectable() diff --git a/packages/apollo-angular/src/types.ts b/packages/apollo-angular/src/types.ts index 30829d77f..145a68d9d 100644 --- a/packages/apollo-angular/src/types.ts +++ b/packages/apollo-angular/src/types.ts @@ -1,10 +1,4 @@ -import type { - ApolloCache, - ApolloClient, - ApolloLink, - OperationVariables, - TypedDocumentNode, -} from '@apollo/client/core'; +import type { ApolloClient, ApolloLink, TypedDocumentNode } from '@apollo/client/core'; export type EmptyObject = { [key: string]: any; @@ -25,29 +19,6 @@ export type MutationResult = ApolloLink.Result & { export type Omit = Pick>; -export type WatchQueryOptions< - TData = unknown, - TVariables extends OperationVariables = EmptyObject, -> = ApolloClient.WatchQueryOptions; - -export type MutationOptions< - TData = unknown, - TVariables extends OperationVariables = EmptyObject, -> = ApolloClient.MutateOptions & { - /** - * Observable starts with `{ loading: true }`. - * There's a big chance the next major version will enable that by default. - * - * Disabled by default - */ - useMutationLoading?: boolean; -}; - -export interface WatchFragmentOptions< - TData = unknown, - TVariables extends OperationVariables = EmptyObject, -> extends ApolloCache.WatchFragmentOptions {} - export type NamedOptions = Record; export type Flags = { From e740baab7226b2e22c68575d7cad30e4eba9c67c Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Thu, 18 Sep 2025 18:14:28 -0600 Subject: [PATCH 67/97] Move useZone option into subscription options --- packages/apollo-angular/src/apollo.ts | 30 ++++++++++----------- packages/apollo-angular/src/index.ts | 9 +------ packages/apollo-angular/src/subscription.ts | 25 ++++++----------- packages/apollo-angular/src/types.ts | 4 --- 4 files changed, 24 insertions(+), 44 deletions(-) diff --git a/packages/apollo-angular/src/apollo.ts b/packages/apollo-angular/src/apollo.ts index 2a51010f5..082cd1b68 100644 --- a/packages/apollo-angular/src/apollo.ts +++ b/packages/apollo-angular/src/apollo.ts @@ -4,13 +4,7 @@ import type { ApolloCache, OperationVariables } from '@apollo/client/core'; import { ApolloClient } from '@apollo/client/core'; import { QueryRef } from './query-ref'; import { APOLLO_FLAGS, APOLLO_NAMED_OPTIONS, APOLLO_OPTIONS } from './tokens'; -import type { - EmptyObject, - ExtraSubscriptionOptions, - Flags, - MutationResult, - NamedOptions, -} from './types'; +import type { EmptyObject, Flags, MutationResult, NamedOptions } from './types'; import { fromLazyPromise, useMutationLoading, wrapWithZone } from './utils'; export declare namespace Apollo { @@ -40,12 +34,16 @@ export declare namespace Apollo { export type SubscribeOptions< TData = unknown, TVariables extends OperationVariables = EmptyObject, - > = ApolloClient.SubscribeOptions; + > = ApolloClient.SubscribeOptions & { + useZone?: boolean; + }; export interface WatchFragmentOptions< TData = unknown, TVariables extends OperationVariables = EmptyObject, - > extends ApolloCache.WatchFragmentOptions {} + > extends ApolloCache.WatchFragmentOptions { + useZone?: boolean; + } } export class ApolloBase { @@ -90,20 +88,22 @@ export class ApolloBase { TVariables extends OperationVariables = EmptyObject, >( options: Apollo.WatchFragmentOptions, - extra?: ExtraSubscriptionOptions, ): Observable> { - const obs = this.ensureClient().watchFragment({ ...options }); + const { useZone, ...opts } = options; + const obs = this.ensureClient().watchFragment({ ...opts }); - return extra && extra.useZone !== true ? obs : wrapWithZone(obs, this.ngZone); + return useZone !== true ? obs : wrapWithZone(obs, this.ngZone); } public subscribe( options: Apollo.SubscribeOptions, - extra?: ExtraSubscriptionOptions, ): Observable> { - const obs = this.ensureClient().subscribe({ ...options }); + const { useZone, ...opts } = options; + const obs = this.ensureClient().subscribe({ + ...opts, + } as Apollo.SubscribeOptions); - return extra && extra.useZone !== true ? obs : wrapWithZone(obs, this.ngZone); + return useZone !== true ? obs : wrapWithZone(obs, this.ngZone); } /** diff --git a/packages/apollo-angular/src/index.ts b/packages/apollo-angular/src/index.ts index 1fa29acaa..80f64c07e 100644 --- a/packages/apollo-angular/src/index.ts +++ b/packages/apollo-angular/src/index.ts @@ -6,14 +6,7 @@ export { Query } from './query'; export { Mutation } from './mutation'; export { Subscription } from './subscription'; export { APOLLO_OPTIONS, APOLLO_NAMED_OPTIONS, APOLLO_FLAGS } from './tokens'; -export type { - ExtraSubscriptionOptions, - Flags, - MutationResult, - NamedOptions, - ResultOf, - VariablesOf, -} from './types'; +export type { Flags, MutationResult, NamedOptions, ResultOf, VariablesOf } from './types'; export { gql } from './gql'; export { MutationOptions, WatchQueryOptions } from './deprecated'; diff --git a/packages/apollo-angular/src/subscription.ts b/packages/apollo-angular/src/subscription.ts index bd0b692cb..ab9cc8b82 100644 --- a/packages/apollo-angular/src/subscription.ts +++ b/packages/apollo-angular/src/subscription.ts @@ -3,7 +3,7 @@ import type { Observable } from 'rxjs'; import { Injectable } from '@angular/core'; import type { ApolloClient, OperationVariables, TypedDocumentNode } from '@apollo/client/core'; import { Apollo } from './apollo'; -import { EmptyObject, ExtraSubscriptionOptions } from './types'; +import { EmptyObject } from './types'; export declare namespace Subscription { export type SubscribeOptions< @@ -23,22 +23,13 @@ export abstract class Subscription< constructor(protected readonly apollo: Apollo) {} public subscribe( - ...[options, extra]: {} extends TVariables - ? [ - options?: Subscription.SubscribeOptions, - extra?: ExtraSubscriptionOptions, - ] - : [ - options: Subscription.SubscribeOptions, - extra?: ExtraSubscriptionOptions, - ] + ...[options]: {} extends TVariables + ? [options?: Subscription.SubscribeOptions] + : [options: Subscription.SubscribeOptions] ): Observable> { - return this.apollo.use(this.client).subscribe( - { - ...options, - query: this.document, - } as ApolloClient.SubscribeOptions, - extra, - ); + return this.apollo.use(this.client).subscribe({ + ...options, + query: this.document, + } as Apollo.SubscribeOptions); } } diff --git a/packages/apollo-angular/src/types.ts b/packages/apollo-angular/src/types.ts index 145a68d9d..e98603795 100644 --- a/packages/apollo-angular/src/types.ts +++ b/packages/apollo-angular/src/types.ts @@ -9,10 +9,6 @@ export type ResultOf = export type VariablesOf = T extends TypedDocumentNode ? V : never; -export interface ExtraSubscriptionOptions { - useZone?: boolean; -} - export type MutationResult = ApolloLink.Result & { loading?: boolean; }; From a594a3b992f060672cd637638fdd148ef389c199 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Thu, 18 Sep 2025 18:26:05 -0600 Subject: [PATCH 68/97] Add result types to namespace --- packages/apollo-angular/src/apollo.ts | 22 ++++++++++++++++------ packages/apollo-angular/src/deprecated.ts | 3 +++ packages/apollo-angular/src/index.ts | 4 ++-- packages/apollo-angular/src/mutation.ts | 4 ++-- packages/apollo-angular/src/types.ts | 6 +----- 5 files changed, 24 insertions(+), 15 deletions(-) diff --git a/packages/apollo-angular/src/apollo.ts b/packages/apollo-angular/src/apollo.ts index 082cd1b68..828a0d6aa 100644 --- a/packages/apollo-angular/src/apollo.ts +++ b/packages/apollo-angular/src/apollo.ts @@ -4,7 +4,7 @@ import type { ApolloCache, OperationVariables } from '@apollo/client/core'; import { ApolloClient } from '@apollo/client/core'; import { QueryRef } from './query-ref'; import { APOLLO_FLAGS, APOLLO_NAMED_OPTIONS, APOLLO_OPTIONS } from './tokens'; -import type { EmptyObject, Flags, MutationResult, NamedOptions } from './types'; +import type { EmptyObject, Flags, NamedOptions } from './types'; import { fromLazyPromise, useMutationLoading, wrapWithZone } from './utils'; export declare namespace Apollo { @@ -18,6 +18,8 @@ export declare namespace Apollo { TVariables extends OperationVariables = EmptyObject, > = ApolloClient.QueryOptions; + export type QueryResult = ApolloClient.QueryResult; + export type MutateOptions< TData = unknown, TVariables extends OperationVariables = EmptyObject, @@ -31,6 +33,10 @@ export declare namespace Apollo { useMutationLoading?: boolean; }; + export type MutateResult = ApolloClient.MutateResult & { + loading?: boolean; + }; + export type SubscribeOptions< TData = unknown, TVariables extends OperationVariables = EmptyObject, @@ -38,12 +44,16 @@ export declare namespace Apollo { useZone?: boolean; }; + export type SubscribeResult = ApolloClient.SubscribeResult; + export interface WatchFragmentOptions< TData = unknown, TVariables extends OperationVariables = EmptyObject, > extends ApolloCache.WatchFragmentOptions { useZone?: boolean; } + + export type WatchFragmentResult = ApolloCache.WatchFragmentResult; } export class ApolloBase { @@ -68,7 +78,7 @@ export class ApolloBase { public query( options: Apollo.QueryOptions, - ): Observable> { + ): Observable> { return fromLazyPromise>(() => this.ensureClient().query({ ...options }), ); @@ -76,7 +86,7 @@ export class ApolloBase { public mutate( options: Apollo.MutateOptions, - ): Observable> { + ): Observable> { return useMutationLoading( fromLazyPromise(() => this.ensureClient().mutate({ ...options })), options.useMutationLoading ?? this.useMutationLoading, @@ -88,7 +98,7 @@ export class ApolloBase { TVariables extends OperationVariables = EmptyObject, >( options: Apollo.WatchFragmentOptions, - ): Observable> { + ): Observable> { const { useZone, ...opts } = options; const obs = this.ensureClient().watchFragment({ ...opts }); @@ -97,11 +107,11 @@ export class ApolloBase { public subscribe( options: Apollo.SubscribeOptions, - ): Observable> { + ): Observable> { const { useZone, ...opts } = options; const obs = this.ensureClient().subscribe({ ...opts, - } as Apollo.SubscribeOptions); + } as ApolloClient.SubscribeOptions); return useZone !== true ? obs : wrapWithZone(obs, this.ngZone); } diff --git a/packages/apollo-angular/src/deprecated.ts b/packages/apollo-angular/src/deprecated.ts index 494816332..557906267 100644 --- a/packages/apollo-angular/src/deprecated.ts +++ b/packages/apollo-angular/src/deprecated.ts @@ -13,3 +13,6 @@ export type MutationOptions< TData = unknown, TVariables extends OperationVariables = EmptyObject, > = Apollo.MutateOptions; + +/** @deprecated Use `Apollo.MutateResult` instead */ +export type MutationResult = Apollo.MutateResult; diff --git a/packages/apollo-angular/src/index.ts b/packages/apollo-angular/src/index.ts index 80f64c07e..72397c160 100644 --- a/packages/apollo-angular/src/index.ts +++ b/packages/apollo-angular/src/index.ts @@ -6,7 +6,7 @@ export { Query } from './query'; export { Mutation } from './mutation'; export { Subscription } from './subscription'; export { APOLLO_OPTIONS, APOLLO_NAMED_OPTIONS, APOLLO_FLAGS } from './tokens'; -export type { Flags, MutationResult, NamedOptions, ResultOf, VariablesOf } from './types'; +export type { Flags, NamedOptions, ResultOf, VariablesOf } from './types'; export { gql } from './gql'; -export { MutationOptions, WatchQueryOptions } from './deprecated'; +export { MutationOptions, MutationResult, WatchQueryOptions } from './deprecated'; diff --git a/packages/apollo-angular/src/mutation.ts b/packages/apollo-angular/src/mutation.ts index 963583e93..19833d4b5 100644 --- a/packages/apollo-angular/src/mutation.ts +++ b/packages/apollo-angular/src/mutation.ts @@ -3,7 +3,7 @@ import type { Observable } from 'rxjs'; import { Injectable } from '@angular/core'; import type { OperationVariables, TypedDocumentNode } from '@apollo/client/core'; import { Apollo } from './apollo'; -import type { EmptyObject, MutationResult } from './types'; +import type { EmptyObject } from './types'; export declare namespace Mutation { export type MutateOptions< @@ -26,7 +26,7 @@ export abstract class Mutation< ...[options]: {} extends TVariables ? [options?: Mutation.MutateOptions] : [options: Mutation.MutateOptions] - ): Observable> { + ): Observable> { return this.apollo.use(this.client).mutate({ ...options, mutation: this.document, diff --git a/packages/apollo-angular/src/types.ts b/packages/apollo-angular/src/types.ts index e98603795..66945f0aa 100644 --- a/packages/apollo-angular/src/types.ts +++ b/packages/apollo-angular/src/types.ts @@ -1,4 +1,4 @@ -import type { ApolloClient, ApolloLink, TypedDocumentNode } from '@apollo/client/core'; +import type { ApolloClient, TypedDocumentNode } from '@apollo/client/core'; export type EmptyObject = { [key: string]: any; @@ -9,10 +9,6 @@ export type ResultOf = export type VariablesOf = T extends TypedDocumentNode ? V : never; -export type MutationResult = ApolloLink.Result & { - loading?: boolean; -}; - export type Omit = Pick>; export type NamedOptions = Record; From 65d695cfb208c223c119a64aaecd7ad34fb672af Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Thu, 18 Sep 2025 18:26:38 -0600 Subject: [PATCH 69/97] Update useMutationLoading --- packages/apollo-angular/src/utils.ts | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/apollo-angular/src/utils.ts b/packages/apollo-angular/src/utils.ts index cef1f3f39..c837cf8d5 100644 --- a/packages/apollo-angular/src/utils.ts +++ b/packages/apollo-angular/src/utils.ts @@ -2,7 +2,7 @@ import { Observable, queueScheduler, SchedulerAction, SchedulerLike, Subscriptio import { map, observeOn, startWith } from 'rxjs/operators'; import { NgZone } from '@angular/core'; import type { ApolloClient } from '@apollo/client/core'; -import { MutationResult } from './types'; +import { Apollo } from './apollo'; /** * Like RxJS's `fromPromise()`, but starts the promise only when the observable is subscribed to. @@ -33,7 +33,7 @@ export function useMutationLoading( ) { if (!enabled) { return source.pipe( - map, MutationResult>(result => ({ + map, Apollo.MutateResult>(result => ({ ...result, loading: false, })), @@ -41,12 +41,13 @@ export function useMutationLoading( } return source.pipe( - startWith>({ + startWith>({ + data: undefined, loading: true, }), - map, MutationResult>(result => ({ + map, Apollo.MutateResult>(result => ({ ...result, - loading: !!result.loading, + loading: false, })), ); } From 1623a2deca4caedf0c85f0049365d4f6c861bf88 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Thu, 18 Sep 2025 18:30:37 -0600 Subject: [PATCH 70/97] Use ObservableStream in another test --- packages/apollo-angular/tests/Apollo.spec.ts | 84 +++++++++----------- 1 file changed, 37 insertions(+), 47 deletions(-) diff --git a/packages/apollo-angular/tests/Apollo.spec.ts b/packages/apollo-angular/tests/Apollo.spec.ts index 5a41da822..302bae2c8 100644 --- a/packages/apollo-angular/tests/Apollo.spec.ts +++ b/packages/apollo-angular/tests/Apollo.spec.ts @@ -475,57 +475,47 @@ describe('Apollo', () => { }); })); - test('should useMutationLoading on demand', () => - new Promise(done => { - expect.assertions(3); - const apollo = testBed.inject(Apollo); - const query = gql` - mutation addRandomHero { - addRandomHero { - name - __typename - } + test('should useMutationLoading on demand', async () => { + const apollo = testBed.inject(Apollo); + const query = gql` + mutation addRandomHero { + addRandomHero { + name + __typename } - `; - const data = { - addRandomHero: { - name: 'Superman', - __typename: 'Hero', - }, - }; + } + `; + const data = { + addRandomHero: { + name: 'Superman', + __typename: 'Hero', + }, + }; - let alreadyCalled = false; + apollo.create({ + link: new MockLink([{ request: { query }, result: { data } }]), + cache: new InMemoryCache(), + }); - // create - apollo.create({ - link: new MockLink([{ request: { query }, result: { data } }]), - cache: new InMemoryCache(), - }); + const stream = new ObservableStream( + apollo.mutate({ + mutation: query, + useMutationLoading: true, + }), + ); - // mutation - apollo - .mutate({ - mutation: query, - useMutationLoading: true, - }) - .subscribe({ - next: result => { - if (alreadyCalled) { - expect(result.loading).toBe(false); - expect(result.data).toMatchObject(data); - setTimeout(() => { - return done(); - }, 3000); - } else { - expect(result.loading).toBe(true); - alreadyCalled = true; - } - }, - error: e => { - throw e; - }, - }); - })); + await expect(stream.takeNext()).resolves.toEqual({ + data: undefined, + loading: true, + }); + + await expect(stream.takeNext()).resolves.toEqual({ + data, + loading: false, + }); + + await expect(stream).not.toEmitAnything(); + }); }); describe('subscribe', () => { From 45c011bd1cabf98ce294f913d37bc577b22f9c1b Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Thu, 18 Sep 2025 18:30:45 -0600 Subject: [PATCH 71/97] Fix wrong loading emit for useMutationLoading --- packages/apollo-angular/src/utils.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/apollo-angular/src/utils.ts b/packages/apollo-angular/src/utils.ts index c837cf8d5..67a0bd7ef 100644 --- a/packages/apollo-angular/src/utils.ts +++ b/packages/apollo-angular/src/utils.ts @@ -41,14 +41,14 @@ export function useMutationLoading( } return source.pipe( - startWith>({ - data: undefined, - loading: true, - }), map, Apollo.MutateResult>(result => ({ ...result, loading: false, })), + startWith>({ + data: undefined, + loading: true, + }), ); } From 5a2e6a3b98b84f78b2ac9078c11211cedeca8063 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Thu, 18 Sep 2025 18:32:28 -0600 Subject: [PATCH 72/97] Update another test to ObservableStream --- packages/apollo-angular/tests/Apollo.spec.ts | 68 ++++++++------------ 1 file changed, 28 insertions(+), 40 deletions(-) diff --git a/packages/apollo-angular/tests/Apollo.spec.ts b/packages/apollo-angular/tests/Apollo.spec.ts index 302bae2c8..bec0c1451 100644 --- a/packages/apollo-angular/tests/Apollo.spec.ts +++ b/packages/apollo-angular/tests/Apollo.spec.ts @@ -431,49 +431,37 @@ describe('Apollo', () => { }); })); - test('should NOT useMutationLoading by default', () => - new Promise(done => { - expect.assertions(2); - const apollo = testBed.inject(Apollo); - const query = gql` - mutation addRandomHero { - addRandomHero { - name - __typename - } + test('should NOT useMutationLoading by default', async () => { + const apollo = testBed.inject(Apollo); + const query = gql` + mutation addRandomHero { + addRandomHero { + name + __typename } - `; - const data = { - addRandomHero: { - name: 'Superman', - __typename: 'Hero', - }, - }; + } + `; + const data = { + addRandomHero: { + name: 'Superman', + __typename: 'Hero', + }, + }; - // create - apollo.create({ - link: new MockLink([{ request: { query }, result: { data } }]), - cache: new InMemoryCache(), - }); + apollo.create({ + link: new MockLink([{ request: { query }, result: { data } }]), + cache: new InMemoryCache(), + }); - // mutation - apollo - .mutate({ - mutation: query, - }) - .subscribe({ - next: result => { - expect(result.loading).toBe(false); - expect(result.data).toMatchObject(data); - setTimeout(() => { - return done(); - }, 3000); - }, - error: e => { - throw e; - }, - }); - })); + const stream = new ObservableStream(apollo.mutate({ mutation: query })); + + await expect(stream.takeNext()).resolves.toEqual({ + data, + loading: false, + }); + + await expect(stream).not.toEmitAnything(); + }); test('should useMutationLoading on demand', async () => { const apollo = testBed.inject(Apollo); From 9e46253874da1f7e599cfa9cd2aaa3fb8938eee8 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Thu, 18 Sep 2025 18:34:01 -0600 Subject: [PATCH 73/97] Adjust test for useZone --- packages/apollo-angular/tests/Apollo.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/apollo-angular/tests/Apollo.spec.ts b/packages/apollo-angular/tests/Apollo.spec.ts index bec0c1451..af381eda6 100644 --- a/packages/apollo-angular/tests/Apollo.spec.ts +++ b/packages/apollo-angular/tests/Apollo.spec.ts @@ -574,7 +574,7 @@ describe('Apollo', () => { client.subscribe = vi.fn().mockReturnValue(['subscription']); - const obs = apollo.subscribe(options, { useZone: false }); + const obs = apollo.subscribe({ ...options, useZone: false }); const operator = (obs as any).operator; expect(operator).toBeUndefined(); From 5268a7dc59f2b896c04d7ad8f09eb293ab29b7c0 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Thu, 18 Sep 2025 18:41:39 -0600 Subject: [PATCH 74/97] Fix some return types for accuracy --- packages/apollo-angular/src/query.ts | 10 +++++----- packages/apollo-angular/src/subscription.ts | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/apollo-angular/src/query.ts b/packages/apollo-angular/src/query.ts index af7ed348e..1d431a740 100644 --- a/packages/apollo-angular/src/query.ts +++ b/packages/apollo-angular/src/query.ts @@ -1,7 +1,7 @@ import type { DocumentNode } from 'graphql'; import type { Observable } from 'rxjs'; import { Injectable } from '@angular/core'; -import type { ApolloClient, OperationVariables, TypedDocumentNode } from '@apollo/client/core'; +import type { OperationVariables, TypedDocumentNode } from '@apollo/client/core'; import { Apollo } from './apollo'; import { QueryRef } from './query-ref'; import { EmptyObject } from './types'; @@ -15,7 +15,7 @@ export declare namespace Query { export type FetchOptions< TData = unknown, TVariables extends OperationVariables = EmptyObject, - > = Omit, 'query'>; + > = Omit, 'query'>; } @Injectable() @@ -33,17 +33,17 @@ export abstract class Query({ ...options, query: this.document, - } as ApolloClient.WatchQueryOptions); + } as Apollo.WatchQueryOptions); } public fetch( ...[options]: {} extends TVariables ? [options?: Query.FetchOptions] : [options: Query.FetchOptions] - ): Observable> { + ): Observable> { return this.apollo.use(this.client).query({ ...options, query: this.document, - } as ApolloClient.QueryOptions); + } as Apollo.QueryOptions); } } diff --git a/packages/apollo-angular/src/subscription.ts b/packages/apollo-angular/src/subscription.ts index ab9cc8b82..bd577c7ff 100644 --- a/packages/apollo-angular/src/subscription.ts +++ b/packages/apollo-angular/src/subscription.ts @@ -1,7 +1,7 @@ import type { DocumentNode } from 'graphql'; import type { Observable } from 'rxjs'; import { Injectable } from '@angular/core'; -import type { ApolloClient, OperationVariables, TypedDocumentNode } from '@apollo/client/core'; +import type { OperationVariables, TypedDocumentNode } from '@apollo/client/core'; import { Apollo } from './apollo'; import { EmptyObject } from './types'; @@ -26,7 +26,7 @@ export abstract class Subscription< ...[options]: {} extends TVariables ? [options?: Subscription.SubscribeOptions] : [options: Subscription.SubscribeOptions] - ): Observable> { + ): Observable> { return this.apollo.use(this.client).subscribe({ ...options, query: this.document, From 2d8a7dc33d9acc872143fd8f577c436d7fa276d9 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Thu, 18 Sep 2025 18:45:10 -0600 Subject: [PATCH 75/97] Use ApolloClient as namespace for watchFragment --- packages/apollo-angular/src/apollo.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/apollo-angular/src/apollo.ts b/packages/apollo-angular/src/apollo.ts index 828a0d6aa..0a3f55966 100644 --- a/packages/apollo-angular/src/apollo.ts +++ b/packages/apollo-angular/src/apollo.ts @@ -1,6 +1,6 @@ import { Observable } from 'rxjs'; import { Inject, Injectable, NgZone, Optional } from '@angular/core'; -import type { ApolloCache, OperationVariables } from '@apollo/client/core'; +import type { OperationVariables } from '@apollo/client/core'; import { ApolloClient } from '@apollo/client/core'; import { QueryRef } from './query-ref'; import { APOLLO_FLAGS, APOLLO_NAMED_OPTIONS, APOLLO_OPTIONS } from './tokens'; @@ -49,11 +49,11 @@ export declare namespace Apollo { export interface WatchFragmentOptions< TData = unknown, TVariables extends OperationVariables = EmptyObject, - > extends ApolloCache.WatchFragmentOptions { + > extends ApolloClient.WatchFragmentOptions { useZone?: boolean; } - export type WatchFragmentResult = ApolloCache.WatchFragmentResult; + export type WatchFragmentResult = ApolloClient.WatchFragmentResult; } export class ApolloBase { From 76814cd969bb887f093a4adbc396a8f69173b159 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Thu, 18 Sep 2025 18:53:10 -0600 Subject: [PATCH 76/97] Import from @apollo/client instead of /core --- packages/apollo-angular/headers/src/index.ts | 2 +- packages/apollo-angular/headers/tests/index.spec.ts | 2 +- packages/apollo-angular/http/src/http-batch-link.ts | 2 +- packages/apollo-angular/http/src/http-link.ts | 2 +- packages/apollo-angular/http/src/types.ts | 2 +- .../apollo-angular/http/tests/http-batch-link.spec.ts | 2 +- packages/apollo-angular/http/tests/http-link.spec.ts | 2 +- packages/apollo-angular/http/tests/ssr.spec.ts | 2 +- packages/apollo-angular/http/tests/utils.ts | 2 +- .../persisted-queries/tests/persisted-queries.spec.ts | 8 +------- .../schematics/install/files/module/graphql.module.ts | 2 +- packages/apollo-angular/src/apollo-module.ts | 2 +- packages/apollo-angular/src/apollo.ts | 4 ++-- packages/apollo-angular/src/gql.ts | 2 +- packages/apollo-angular/src/index.ts | 2 +- packages/apollo-angular/src/mutation.ts | 2 +- packages/apollo-angular/src/query-ref.ts | 2 +- packages/apollo-angular/src/query.ts | 2 +- packages/apollo-angular/src/subscription.ts | 2 +- packages/apollo-angular/src/tokens.ts | 2 +- packages/apollo-angular/src/types.ts | 2 +- packages/apollo-angular/src/utils.ts | 2 +- packages/apollo-angular/testing/src/backend.ts | 2 +- packages/apollo-angular/testing/src/module.ts | 2 +- packages/apollo-angular/testing/src/operation.ts | 2 +- packages/apollo-angular/testing/tests/integration.spec.ts | 2 +- packages/apollo-angular/testing/tests/module.spec.ts | 2 +- packages/apollo-angular/testing/tests/operation.spec.ts | 2 +- packages/apollo-angular/testing/tests/utils.ts | 2 +- packages/apollo-angular/tests/Apollo.spec.ts | 2 +- packages/apollo-angular/tests/QueryRef.spec.ts | 2 +- packages/apollo-angular/tests/integration.spec.ts | 2 +- packages/demo/src/app/app.config.ts | 2 +- 33 files changed, 34 insertions(+), 40 deletions(-) diff --git a/packages/apollo-angular/headers/src/index.ts b/packages/apollo-angular/headers/src/index.ts index 0fe042610..e4d23f7f8 100644 --- a/packages/apollo-angular/headers/src/index.ts +++ b/packages/apollo-angular/headers/src/index.ts @@ -1,5 +1,5 @@ import { HttpHeaders } from '@angular/common/http'; -import { ApolloLink } from '@apollo/client/core'; +import { ApolloLink } from "@apollo/client"; export class HttpHeadersLink extends ApolloLink { constructor() { diff --git a/packages/apollo-angular/headers/tests/index.spec.ts b/packages/apollo-angular/headers/tests/index.spec.ts index c533d1737..c087c055e 100644 --- a/packages/apollo-angular/headers/tests/index.spec.ts +++ b/packages/apollo-angular/headers/tests/index.spec.ts @@ -1,7 +1,7 @@ import { of } from 'rxjs'; import { describe, expect, test } from 'vitest'; import { HttpHeaders } from '@angular/common/http'; -import { ApolloClient, ApolloLink, execute, gql, InMemoryCache } from '@apollo/client/core'; +import { ApolloClient, ApolloLink, execute, gql, InMemoryCache } from "@apollo/client"; import { HttpHeadersLink } from '../src'; const query = gql` diff --git a/packages/apollo-angular/http/src/http-batch-link.ts b/packages/apollo-angular/http/src/http-batch-link.ts index 587b197c0..b18f34746 100644 --- a/packages/apollo-angular/http/src/http-batch-link.ts +++ b/packages/apollo-angular/http/src/http-batch-link.ts @@ -2,7 +2,7 @@ import { print } from 'graphql'; import { Observable } from 'rxjs'; import { HttpClient, HttpHeaders } from '@angular/common/http'; import { Injectable } from '@angular/core'; -import { ApolloLink } from '@apollo/client/core'; +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'; diff --git a/packages/apollo-angular/http/src/http-link.ts b/packages/apollo-angular/http/src/http-link.ts index a6b8fa703..09a5f059a 100644 --- a/packages/apollo-angular/http/src/http-link.ts +++ b/packages/apollo-angular/http/src/http-link.ts @@ -2,7 +2,7 @@ import { print } from 'graphql'; import { Observable } from 'rxjs'; import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; -import { ApolloLink } from '@apollo/client/core'; +import { ApolloLink } from "@apollo/client"; import { pick } from './http-batch-link'; import { Body, diff --git a/packages/apollo-angular/http/src/types.ts b/packages/apollo-angular/http/src/types.ts index 56bcdd58d..9f3d44700 100644 --- a/packages/apollo-angular/http/src/types.ts +++ b/packages/apollo-angular/http/src/types.ts @@ -1,6 +1,6 @@ import { DocumentNode } from 'graphql'; import { HttpHeaders } from '@angular/common/http'; -import { ApolloLink } from '@apollo/client/core'; +import { ApolloLink } from "@apollo/client"; declare module '@apollo/client' { export interface DefaultContext extends Context {} diff --git a/packages/apollo-angular/http/tests/http-batch-link.spec.ts b/packages/apollo-angular/http/tests/http-batch-link.spec.ts index 57450cd3e..bbb58c4aa 100644 --- a/packages/apollo-angular/http/tests/http-batch-link.spec.ts +++ b/packages/apollo-angular/http/tests/http-batch-link.spec.ts @@ -2,7 +2,7 @@ import { afterEach, beforeEach, describe, expect, test } from 'vitest'; import { HttpHeaders, provideHttpClient } from '@angular/common/http'; import { HttpTestingController, provideHttpClientTesting } from '@angular/common/http/testing'; import { TestBed } from '@angular/core/testing'; -import { ApolloLink, gql } from '@apollo/client/core'; +import { ApolloLink, gql } from "@apollo/client"; import { getOperationName } from '@apollo/client/utilities/internal'; import { HttpBatchLink } from '../src/http-batch-link'; import { executeWithDefaultContext as execute } from './utils'; diff --git a/packages/apollo-angular/http/tests/http-link.spec.ts b/packages/apollo-angular/http/tests/http-link.spec.ts index 5326a5dfa..560e39069 100644 --- a/packages/apollo-angular/http/tests/http-link.spec.ts +++ b/packages/apollo-angular/http/tests/http-link.spec.ts @@ -4,7 +4,7 @@ import { afterEach, beforeEach, describe, expect, test } from 'vitest'; import { HttpHeaders, provideHttpClient } from '@angular/common/http'; import { HttpTestingController, provideHttpClientTesting } from '@angular/common/http/testing'; import { TestBed } from '@angular/core/testing'; -import { ApolloLink, gql, InMemoryCache } from '@apollo/client/core'; +import { ApolloLink, gql, InMemoryCache } from "@apollo/client"; import { Apollo } from '../../src'; import { HttpLink } from '../src/http-link'; import { executeWithDefaultContext as execute } from './utils'; diff --git a/packages/apollo-angular/http/tests/ssr.spec.ts b/packages/apollo-angular/http/tests/ssr.spec.ts index 8607c58c0..171e5829a 100644 --- a/packages/apollo-angular/http/tests/ssr.spec.ts +++ b/packages/apollo-angular/http/tests/ssr.spec.ts @@ -10,7 +10,7 @@ import { renderModule, ServerModule, } from '@angular/platform-server'; -import { gql } from '@apollo/client/core'; +import { gql } from "@apollo/client"; import { HttpLink } from '../src/http-link'; import { executeWithDefaultContext as execute } from './utils'; diff --git a/packages/apollo-angular/http/tests/utils.ts b/packages/apollo-angular/http/tests/utils.ts index 8e072ad70..ccbe64158 100644 --- a/packages/apollo-angular/http/tests/utils.ts +++ b/packages/apollo-angular/http/tests/utils.ts @@ -1,5 +1,5 @@ import { Observable } from 'rxjs'; -import { ApolloClient, ApolloLink, execute, InMemoryCache } from '@apollo/client/core'; +import { ApolloClient, ApolloLink, execute, InMemoryCache } from "@apollo/client"; export function createDefaultExecuteContext(): ApolloLink.ExecuteContext { return { diff --git a/packages/apollo-angular/persisted-queries/tests/persisted-queries.spec.ts b/packages/apollo-angular/persisted-queries/tests/persisted-queries.spec.ts index f715aed6f..196777672 100644 --- a/packages/apollo-angular/persisted-queries/tests/persisted-queries.spec.ts +++ b/packages/apollo-angular/persisted-queries/tests/persisted-queries.spec.ts @@ -1,12 +1,6 @@ import { Observable } from 'rxjs'; import { describe, expect, test, vi } from 'vitest'; -import { - ApolloClient, - ApolloLink, - execute as executeLink, - gql, - InMemoryCache, -} from '@apollo/client/core'; +import { ApolloClient, ApolloLink, execute as executeLink, gql, InMemoryCache } from "@apollo/client"; import { createPersistedQueryLink } from '../src'; const query = gql` diff --git a/packages/apollo-angular/schematics/install/files/module/graphql.module.ts b/packages/apollo-angular/schematics/install/files/module/graphql.module.ts index 4d8b0ecd6..71836d472 100644 --- a/packages/apollo-angular/schematics/install/files/module/graphql.module.ts +++ b/packages/apollo-angular/schematics/install/files/module/graphql.module.ts @@ -1,7 +1,7 @@ import { provideApollo } from 'apollo-angular'; import { HttpLink } from 'apollo-angular/http'; import { inject, NgModule } from '@angular/core'; -import { ApolloClient, InMemoryCache } from '@apollo/client/core'; +import { ApolloClient, InMemoryCache } from "@apollo/client"; export function createApollo(): ApolloClient.Options { const uri = '<%= endpoint %>'; // <-- add the URL of the GraphQL server here diff --git a/packages/apollo-angular/src/apollo-module.ts b/packages/apollo-angular/src/apollo-module.ts index 4f19b5ee7..a88bff25e 100644 --- a/packages/apollo-angular/src/apollo-module.ts +++ b/packages/apollo-angular/src/apollo-module.ts @@ -1,5 +1,5 @@ import { Provider } from '@angular/core'; -import { ApolloClient } from '@apollo/client/core'; +import { ApolloClient } from "@apollo/client"; import { Apollo } from './apollo'; import { APOLLO_FLAGS, APOLLO_NAMED_OPTIONS, APOLLO_OPTIONS } from './tokens'; import { Flags, NamedOptions } from './types'; diff --git a/packages/apollo-angular/src/apollo.ts b/packages/apollo-angular/src/apollo.ts index 0a3f55966..5eb8fbb5e 100644 --- a/packages/apollo-angular/src/apollo.ts +++ b/packages/apollo-angular/src/apollo.ts @@ -1,7 +1,7 @@ import { Observable } from 'rxjs'; import { Inject, Injectable, NgZone, Optional } from '@angular/core'; -import type { OperationVariables } from '@apollo/client/core'; -import { ApolloClient } from '@apollo/client/core'; +import type { OperationVariables } from "@apollo/client"; +import { ApolloClient } from "@apollo/client"; import { QueryRef } from './query-ref'; import { APOLLO_FLAGS, APOLLO_NAMED_OPTIONS, APOLLO_OPTIONS } from './tokens'; import type { EmptyObject, Flags, NamedOptions } from './types'; diff --git a/packages/apollo-angular/src/gql.ts b/packages/apollo-angular/src/gql.ts index e58ff8d95..fcaf4caaf 100644 --- a/packages/apollo-angular/src/gql.ts +++ b/packages/apollo-angular/src/gql.ts @@ -1,4 +1,4 @@ -import { gql as gqlTag, TypedDocumentNode } from '@apollo/client/core'; +import { gql as gqlTag, TypedDocumentNode } from "@apollo/client"; const typedGQLTag: ( literals: ReadonlyArray | Readonly, diff --git a/packages/apollo-angular/src/index.ts b/packages/apollo-angular/src/index.ts index 72397c160..7735c0d08 100644 --- a/packages/apollo-angular/src/index.ts +++ b/packages/apollo-angular/src/index.ts @@ -1,4 +1,4 @@ -export type { TypedDocumentNode } from '@apollo/client/core'; +export type { TypedDocumentNode } from '@apollo/client'; export { provideApollo, provideNamedApollo } from './apollo-module'; export { Apollo, ApolloBase } from './apollo'; export { QueryRef, QueryRefFromDocument } from './query-ref'; diff --git a/packages/apollo-angular/src/mutation.ts b/packages/apollo-angular/src/mutation.ts index 19833d4b5..f9079b6d9 100644 --- a/packages/apollo-angular/src/mutation.ts +++ b/packages/apollo-angular/src/mutation.ts @@ -1,7 +1,7 @@ import type { DocumentNode } from 'graphql'; import type { Observable } from 'rxjs'; import { Injectable } from '@angular/core'; -import type { OperationVariables, TypedDocumentNode } from '@apollo/client/core'; +import type { OperationVariables, TypedDocumentNode } from "@apollo/client"; import { Apollo } from './apollo'; import type { EmptyObject } from './types'; diff --git a/packages/apollo-angular/src/query-ref.ts b/packages/apollo-angular/src/query-ref.ts index f62dd46b1..7c10e822c 100644 --- a/packages/apollo-angular/src/query-ref.ts +++ b/packages/apollo-angular/src/query-ref.ts @@ -6,7 +6,7 @@ import type { ObservableQuery, OperationVariables, TypedDocumentNode, -} from '@apollo/client/core'; +} from "@apollo/client"; import { EmptyObject } from './types'; import { wrapWithZone } from './utils'; diff --git a/packages/apollo-angular/src/query.ts b/packages/apollo-angular/src/query.ts index 1d431a740..a49d6be4c 100644 --- a/packages/apollo-angular/src/query.ts +++ b/packages/apollo-angular/src/query.ts @@ -1,7 +1,7 @@ import type { DocumentNode } from 'graphql'; import type { Observable } from 'rxjs'; import { Injectable } from '@angular/core'; -import type { OperationVariables, TypedDocumentNode } from '@apollo/client/core'; +import type { OperationVariables, TypedDocumentNode } from "@apollo/client"; import { Apollo } from './apollo'; import { QueryRef } from './query-ref'; import { EmptyObject } from './types'; diff --git a/packages/apollo-angular/src/subscription.ts b/packages/apollo-angular/src/subscription.ts index bd577c7ff..2f8917010 100644 --- a/packages/apollo-angular/src/subscription.ts +++ b/packages/apollo-angular/src/subscription.ts @@ -1,7 +1,7 @@ import type { DocumentNode } from 'graphql'; import type { Observable } from 'rxjs'; import { Injectable } from '@angular/core'; -import type { OperationVariables, TypedDocumentNode } from '@apollo/client/core'; +import type { OperationVariables, TypedDocumentNode } from "@apollo/client"; import { Apollo } from './apollo'; import { EmptyObject } from './types'; diff --git a/packages/apollo-angular/src/tokens.ts b/packages/apollo-angular/src/tokens.ts index 8c9ec4280..337256dae 100644 --- a/packages/apollo-angular/src/tokens.ts +++ b/packages/apollo-angular/src/tokens.ts @@ -1,5 +1,5 @@ import { InjectionToken } from '@angular/core'; -import type { ApolloClient } from '@apollo/client/core'; +import type { ApolloClient } from "@apollo/client"; import type { Flags, NamedOptions } from './types'; export const APOLLO_FLAGS = new InjectionToken('APOLLO_FLAGS'); diff --git a/packages/apollo-angular/src/types.ts b/packages/apollo-angular/src/types.ts index 66945f0aa..e1f1141aa 100644 --- a/packages/apollo-angular/src/types.ts +++ b/packages/apollo-angular/src/types.ts @@ -1,4 +1,4 @@ -import type { ApolloClient, TypedDocumentNode } from '@apollo/client/core'; +import type { ApolloClient, TypedDocumentNode } from "@apollo/client"; export type EmptyObject = { [key: string]: any; diff --git a/packages/apollo-angular/src/utils.ts b/packages/apollo-angular/src/utils.ts index 67a0bd7ef..e488beec5 100644 --- a/packages/apollo-angular/src/utils.ts +++ b/packages/apollo-angular/src/utils.ts @@ -1,7 +1,7 @@ import { Observable, queueScheduler, SchedulerAction, SchedulerLike, Subscription } from 'rxjs'; import { map, observeOn, startWith } from 'rxjs/operators'; import { NgZone } from '@angular/core'; -import type { ApolloClient } from '@apollo/client/core'; +import type { ApolloClient } from "@apollo/client"; import { Apollo } from './apollo'; /** diff --git a/packages/apollo-angular/testing/src/backend.ts b/packages/apollo-angular/testing/src/backend.ts index 9aed45ae5..15135db48 100644 --- a/packages/apollo-angular/testing/src/backend.ts +++ b/packages/apollo-angular/testing/src/backend.ts @@ -1,7 +1,7 @@ import { DocumentNode, print } from 'graphql'; import { Observable, Observer } from 'rxjs'; import { Injectable } from '@angular/core'; -import { ApolloLink } from '@apollo/client/core'; +import { ApolloLink } from "@apollo/client"; import { addTypenameToDocument } from '@apollo/client/utilities'; import { ApolloTestingController, MatchOperation } from './controller'; import { Operation, TestOperation } from './operation'; diff --git a/packages/apollo-angular/testing/src/module.ts b/packages/apollo-angular/testing/src/module.ts index bfc3aa3e3..9fecd0746 100644 --- a/packages/apollo-angular/testing/src/module.ts +++ b/packages/apollo-angular/testing/src/module.ts @@ -1,6 +1,6 @@ import { Apollo } from 'apollo-angular'; import { Inject, InjectionToken, NgModule, Optional } from '@angular/core'; -import { ApolloCache, ApolloLink, InMemoryCache } from '@apollo/client/core'; +import { ApolloCache, ApolloLink, InMemoryCache } from "@apollo/client"; import { ApolloTestingBackend } from './backend'; import { ApolloTestingController } from './controller'; import { Operation } from './operation'; diff --git a/packages/apollo-angular/testing/src/operation.ts b/packages/apollo-angular/testing/src/operation.ts index cc56d813b..b67d043d7 100644 --- a/packages/apollo-angular/testing/src/operation.ts +++ b/packages/apollo-angular/testing/src/operation.ts @@ -1,6 +1,6 @@ import { GraphQLFormattedError, OperationTypeNode } from 'graphql'; import { Observer } from 'rxjs'; -import { ApolloLink, ErrorLike } from '@apollo/client/core'; +import { ApolloLink, ErrorLike } from "@apollo/client"; import { isErrorLike } from '@apollo/client/errors'; export type Operation = ApolloLink.Operation & { diff --git a/packages/apollo-angular/testing/tests/integration.spec.ts b/packages/apollo-angular/testing/tests/integration.spec.ts index dc8dcf4c9..e0b57bc48 100644 --- a/packages/apollo-angular/testing/tests/integration.spec.ts +++ b/packages/apollo-angular/testing/tests/integration.spec.ts @@ -1,7 +1,7 @@ import { print } from 'graphql'; import { afterEach, beforeEach, describe, expect, test } from 'vitest'; import { TestBed } from '@angular/core/testing'; -import { gql } from '@apollo/client/core'; +import { gql } from "@apollo/client"; import { addTypenameToDocument } from '@apollo/client/utilities'; import { Apollo } from '../../src'; import { ApolloTestingController, ApolloTestingModule } from '../src'; diff --git a/packages/apollo-angular/testing/tests/module.spec.ts b/packages/apollo-angular/testing/tests/module.spec.ts index 0ff46f824..987736ee8 100644 --- a/packages/apollo-angular/testing/tests/module.spec.ts +++ b/packages/apollo-angular/testing/tests/module.spec.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from 'vitest'; import { TestBed } from '@angular/core/testing'; -import { gql, InMemoryCache } from '@apollo/client/core'; +import { gql, InMemoryCache } from "@apollo/client"; import { Apollo } from '../../src'; import { APOLLO_TESTING_CACHE, ApolloTestingController, ApolloTestingModule } from '../src'; diff --git a/packages/apollo-angular/testing/tests/operation.spec.ts b/packages/apollo-angular/testing/tests/operation.spec.ts index 2da241358..a31b5d1c4 100644 --- a/packages/apollo-angular/testing/tests/operation.spec.ts +++ b/packages/apollo-angular/testing/tests/operation.spec.ts @@ -1,5 +1,5 @@ import { beforeEach, describe, expect, test } from 'vitest'; -import { ApolloLink, gql } from '@apollo/client/core'; +import { ApolloLink, gql } from "@apollo/client"; import { ApolloTestingBackend } from '../src/backend'; import { buildOperationForLink, executeWithDefaultContext as execute } from './utils'; diff --git a/packages/apollo-angular/testing/tests/utils.ts b/packages/apollo-angular/testing/tests/utils.ts index 25e353abc..f29536b3c 100644 --- a/packages/apollo-angular/testing/tests/utils.ts +++ b/packages/apollo-angular/testing/tests/utils.ts @@ -1,6 +1,6 @@ import { DocumentNode } from 'graphql'; import { Observable } from 'rxjs'; -import { ApolloClient, execute, InMemoryCache, OperationVariables } from '@apollo/client/core'; +import { ApolloClient, execute, InMemoryCache, OperationVariables } from "@apollo/client"; import { ApolloLink } from '@apollo/client/link'; import { addTypenameToDocument } from '@apollo/client/utilities'; diff --git a/packages/apollo-angular/tests/Apollo.spec.ts b/packages/apollo-angular/tests/Apollo.spec.ts index af381eda6..6316fffa3 100644 --- a/packages/apollo-angular/tests/Apollo.spec.ts +++ b/packages/apollo-angular/tests/Apollo.spec.ts @@ -3,7 +3,7 @@ import { mergeMap } from 'rxjs/operators'; import { beforeEach, describe, expect, test, vi } from 'vitest'; import { NgZone } from '@angular/core'; import { TestBed } from '@angular/core/testing'; -import { ApolloLink, InMemoryCache, NetworkStatus } from '@apollo/client/core'; +import { ApolloLink, InMemoryCache, NetworkStatus } from "@apollo/client"; import { MockLink } from '@apollo/client/testing'; import { Apollo, ApolloBase } from '../src/apollo'; import { gql } from '../src/gql'; diff --git a/packages/apollo-angular/tests/QueryRef.spec.ts b/packages/apollo-angular/tests/QueryRef.spec.ts index 75039710e..6697a8cf2 100644 --- a/packages/apollo-angular/tests/QueryRef.spec.ts +++ b/packages/apollo-angular/tests/QueryRef.spec.ts @@ -2,7 +2,7 @@ import { Subject } from 'rxjs'; import { map, takeUntil } from 'rxjs/operators'; import { beforeEach, describe, expect, test, vi } from 'vitest'; import { NgZone } from '@angular/core'; -import { ApolloClient, ApolloLink, InMemoryCache, ObservableQuery } from '@apollo/client/core'; +import { ApolloClient, ApolloLink, InMemoryCache, ObservableQuery } from "@apollo/client"; import { MockLink } from '@apollo/client/testing'; import { gql } from '../src/gql'; import { QueryRef } from '../src/query-ref'; diff --git a/packages/apollo-angular/tests/integration.spec.ts b/packages/apollo-angular/tests/integration.spec.ts index c4bf35b64..fe2acbc13 100644 --- a/packages/apollo-angular/tests/integration.spec.ts +++ b/packages/apollo-angular/tests/integration.spec.ts @@ -1,7 +1,7 @@ import { beforeEach, describe, expect, test } from 'vitest'; import { provideHttpClient } from '@angular/common/http'; import { TestBed } from '@angular/core/testing'; -import { InMemoryCache } from '@apollo/client/core'; +import { InMemoryCache } from "@apollo/client"; import { MockLink } from '@apollo/client/testing'; import { Apollo, provideApollo } from '../src'; diff --git a/packages/demo/src/app/app.config.ts b/packages/demo/src/app/app.config.ts index 8dec6e286..03ce48c66 100644 --- a/packages/demo/src/app/app.config.ts +++ b/packages/demo/src/app/app.config.ts @@ -3,7 +3,7 @@ import { HttpLink } from 'apollo-angular/http'; import { provideHttpClient } from '@angular/common/http'; import { ApplicationConfig, inject, provideZoneChangeDetection } from '@angular/core'; import { provideRouter } from '@angular/router'; -import { InMemoryCache } from '@apollo/client/core'; +import { InMemoryCache } from '@apollo/client'; import { routes } from './app.routes'; export const appConfig: ApplicationConfig = { From d7b9a7763c135b5cf26db9c8403f012da3513475 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Thu, 18 Sep 2025 18:54:04 -0600 Subject: [PATCH 77/97] Use @apollo/client in schematics --- packages/apollo-angular/schematics/install/index.cts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/apollo-angular/schematics/install/index.cts b/packages/apollo-angular/schematics/install/index.cts index e4a748a2e..ef6937648 100644 --- a/packages/apollo-angular/schematics/install/index.cts +++ b/packages/apollo-angular/schematics/install/index.cts @@ -98,7 +98,7 @@ function includeAsyncIterableLib(): Rule { '\n' + tags.stripIndent` We couldn't find '${requiredLib}' in the list of library files to be included in the compilation. - It's required by '@apollo/client/core' package so please add it to your tsconfig. + It's required by '@apollo/client' package so please add it to your tsconfig. ` + '\n', ); @@ -151,7 +151,7 @@ function allowSyntheticDefaultImports(): Rule { '\n' + tags.stripIndent` We couldn't enable 'allowSyntheticDefaultImports' flag. - It's required by '@apollo/client/core' package so please add it to your tsconfig. + It's required by '@apollo/client' package so please add it to your tsconfig. ` + '\n', ); @@ -201,7 +201,7 @@ function importSetup(options: Schema): Rule { link: httpLink.create({ uri: '<%= endpoint %>', }), - cache: new ${external('InMemoryCache', '@apollo/client/core')}(), + cache: new ${external('InMemoryCache', '@apollo/client')}(), }; })`; }); From a15d21147ed37591d055df597ab41163fe569212 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Thu, 18 Sep 2025 18:54:55 -0600 Subject: [PATCH 78/97] Formatting --- packages/apollo-angular/headers/src/index.ts | 2 +- packages/apollo-angular/headers/tests/index.spec.ts | 2 +- packages/apollo-angular/http/src/http-batch-link.ts | 2 +- packages/apollo-angular/http/src/http-link.ts | 2 +- packages/apollo-angular/http/src/types.ts | 2 +- .../apollo-angular/http/tests/http-batch-link.spec.ts | 2 +- packages/apollo-angular/http/tests/http-link.spec.ts | 2 +- packages/apollo-angular/http/tests/ssr.spec.ts | 2 +- packages/apollo-angular/http/tests/utils.ts | 2 +- .../persisted-queries/tests/persisted-queries.spec.ts | 8 +++++++- .../schematics/install/files/module/graphql.module.ts | 2 +- packages/apollo-angular/src/apollo-module.ts | 2 +- packages/apollo-angular/src/apollo.ts | 4 ++-- packages/apollo-angular/src/gql.ts | 2 +- packages/apollo-angular/src/mutation.ts | 2 +- packages/apollo-angular/src/query-ref.ts | 2 +- packages/apollo-angular/src/query.ts | 2 +- packages/apollo-angular/src/subscription.ts | 2 +- packages/apollo-angular/src/tokens.ts | 2 +- packages/apollo-angular/src/types.ts | 2 +- packages/apollo-angular/src/utils.ts | 2 +- packages/apollo-angular/testing/src/backend.ts | 2 +- packages/apollo-angular/testing/src/module.ts | 2 +- packages/apollo-angular/testing/src/operation.ts | 2 +- packages/apollo-angular/testing/tests/integration.spec.ts | 2 +- packages/apollo-angular/testing/tests/module.spec.ts | 2 +- packages/apollo-angular/testing/tests/operation.spec.ts | 2 +- packages/apollo-angular/testing/tests/utils.ts | 2 +- packages/apollo-angular/tests/Apollo.spec.ts | 2 +- packages/apollo-angular/tests/QueryRef.spec.ts | 2 +- packages/apollo-angular/tests/integration.spec.ts | 2 +- 31 files changed, 38 insertions(+), 32 deletions(-) diff --git a/packages/apollo-angular/headers/src/index.ts b/packages/apollo-angular/headers/src/index.ts index e4d23f7f8..594293df5 100644 --- a/packages/apollo-angular/headers/src/index.ts +++ b/packages/apollo-angular/headers/src/index.ts @@ -1,5 +1,5 @@ import { HttpHeaders } from '@angular/common/http'; -import { ApolloLink } from "@apollo/client"; +import { ApolloLink } from '@apollo/client'; export class HttpHeadersLink extends ApolloLink { constructor() { diff --git a/packages/apollo-angular/headers/tests/index.spec.ts b/packages/apollo-angular/headers/tests/index.spec.ts index c087c055e..dfdf1b878 100644 --- a/packages/apollo-angular/headers/tests/index.spec.ts +++ b/packages/apollo-angular/headers/tests/index.spec.ts @@ -1,7 +1,7 @@ import { of } from 'rxjs'; import { describe, expect, test } from 'vitest'; import { HttpHeaders } from '@angular/common/http'; -import { ApolloClient, ApolloLink, execute, gql, InMemoryCache } from "@apollo/client"; +import { ApolloClient, ApolloLink, execute, gql, InMemoryCache } from '@apollo/client'; import { HttpHeadersLink } from '../src'; const query = gql` diff --git a/packages/apollo-angular/http/src/http-batch-link.ts b/packages/apollo-angular/http/src/http-batch-link.ts index b18f34746..02d1cb482 100644 --- a/packages/apollo-angular/http/src/http-batch-link.ts +++ b/packages/apollo-angular/http/src/http-batch-link.ts @@ -2,7 +2,7 @@ import { print } from 'graphql'; import { Observable } from 'rxjs'; import { HttpClient, HttpHeaders } from '@angular/common/http'; import { Injectable } from '@angular/core'; -import { ApolloLink } from "@apollo/client"; +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'; diff --git a/packages/apollo-angular/http/src/http-link.ts b/packages/apollo-angular/http/src/http-link.ts index 09a5f059a..4528589a5 100644 --- a/packages/apollo-angular/http/src/http-link.ts +++ b/packages/apollo-angular/http/src/http-link.ts @@ -2,7 +2,7 @@ import { print } from 'graphql'; import { Observable } from 'rxjs'; import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; -import { ApolloLink } from "@apollo/client"; +import { ApolloLink } from '@apollo/client'; import { pick } from './http-batch-link'; import { Body, diff --git a/packages/apollo-angular/http/src/types.ts b/packages/apollo-angular/http/src/types.ts index 9f3d44700..b6802d3cc 100644 --- a/packages/apollo-angular/http/src/types.ts +++ b/packages/apollo-angular/http/src/types.ts @@ -1,6 +1,6 @@ import { DocumentNode } from 'graphql'; import { HttpHeaders } from '@angular/common/http'; -import { ApolloLink } from "@apollo/client"; +import { ApolloLink } from '@apollo/client'; declare module '@apollo/client' { export interface DefaultContext extends Context {} diff --git a/packages/apollo-angular/http/tests/http-batch-link.spec.ts b/packages/apollo-angular/http/tests/http-batch-link.spec.ts index bbb58c4aa..be91a77d1 100644 --- a/packages/apollo-angular/http/tests/http-batch-link.spec.ts +++ b/packages/apollo-angular/http/tests/http-batch-link.spec.ts @@ -2,7 +2,7 @@ import { afterEach, beforeEach, describe, expect, test } from 'vitest'; import { HttpHeaders, provideHttpClient } from '@angular/common/http'; import { HttpTestingController, provideHttpClientTesting } from '@angular/common/http/testing'; import { TestBed } from '@angular/core/testing'; -import { ApolloLink, gql } from "@apollo/client"; +import { ApolloLink, gql } from '@apollo/client'; import { getOperationName } from '@apollo/client/utilities/internal'; import { HttpBatchLink } from '../src/http-batch-link'; import { executeWithDefaultContext as execute } from './utils'; diff --git a/packages/apollo-angular/http/tests/http-link.spec.ts b/packages/apollo-angular/http/tests/http-link.spec.ts index 560e39069..36516b20e 100644 --- a/packages/apollo-angular/http/tests/http-link.spec.ts +++ b/packages/apollo-angular/http/tests/http-link.spec.ts @@ -4,7 +4,7 @@ import { afterEach, beforeEach, describe, expect, test } from 'vitest'; import { HttpHeaders, provideHttpClient } from '@angular/common/http'; import { HttpTestingController, provideHttpClientTesting } from '@angular/common/http/testing'; import { TestBed } from '@angular/core/testing'; -import { ApolloLink, gql, InMemoryCache } from "@apollo/client"; +import { ApolloLink, gql, InMemoryCache } from '@apollo/client'; import { Apollo } from '../../src'; import { HttpLink } from '../src/http-link'; import { executeWithDefaultContext as execute } from './utils'; diff --git a/packages/apollo-angular/http/tests/ssr.spec.ts b/packages/apollo-angular/http/tests/ssr.spec.ts index 171e5829a..6f6e4cf30 100644 --- a/packages/apollo-angular/http/tests/ssr.spec.ts +++ b/packages/apollo-angular/http/tests/ssr.spec.ts @@ -10,7 +10,7 @@ import { renderModule, ServerModule, } from '@angular/platform-server'; -import { gql } from "@apollo/client"; +import { gql } from '@apollo/client'; import { HttpLink } from '../src/http-link'; import { executeWithDefaultContext as execute } from './utils'; diff --git a/packages/apollo-angular/http/tests/utils.ts b/packages/apollo-angular/http/tests/utils.ts index ccbe64158..177efa97c 100644 --- a/packages/apollo-angular/http/tests/utils.ts +++ b/packages/apollo-angular/http/tests/utils.ts @@ -1,5 +1,5 @@ import { Observable } from 'rxjs'; -import { ApolloClient, ApolloLink, execute, InMemoryCache } from "@apollo/client"; +import { ApolloClient, ApolloLink, execute, InMemoryCache } from '@apollo/client'; export function createDefaultExecuteContext(): ApolloLink.ExecuteContext { return { diff --git a/packages/apollo-angular/persisted-queries/tests/persisted-queries.spec.ts b/packages/apollo-angular/persisted-queries/tests/persisted-queries.spec.ts index 196777672..05b3a1dec 100644 --- a/packages/apollo-angular/persisted-queries/tests/persisted-queries.spec.ts +++ b/packages/apollo-angular/persisted-queries/tests/persisted-queries.spec.ts @@ -1,6 +1,12 @@ import { Observable } from 'rxjs'; import { describe, expect, test, vi } from 'vitest'; -import { ApolloClient, ApolloLink, execute as executeLink, gql, InMemoryCache } from "@apollo/client"; +import { + ApolloClient, + ApolloLink, + execute as executeLink, + gql, + InMemoryCache, +} from '@apollo/client'; import { createPersistedQueryLink } from '../src'; const query = gql` diff --git a/packages/apollo-angular/schematics/install/files/module/graphql.module.ts b/packages/apollo-angular/schematics/install/files/module/graphql.module.ts index 71836d472..7bc609bda 100644 --- a/packages/apollo-angular/schematics/install/files/module/graphql.module.ts +++ b/packages/apollo-angular/schematics/install/files/module/graphql.module.ts @@ -1,7 +1,7 @@ import { provideApollo } from 'apollo-angular'; import { HttpLink } from 'apollo-angular/http'; import { inject, NgModule } from '@angular/core'; -import { ApolloClient, InMemoryCache } from "@apollo/client"; +import { ApolloClient, InMemoryCache } from '@apollo/client'; export function createApollo(): ApolloClient.Options { const uri = '<%= endpoint %>'; // <-- add the URL of the GraphQL server here diff --git a/packages/apollo-angular/src/apollo-module.ts b/packages/apollo-angular/src/apollo-module.ts index a88bff25e..49fcb62c8 100644 --- a/packages/apollo-angular/src/apollo-module.ts +++ b/packages/apollo-angular/src/apollo-module.ts @@ -1,5 +1,5 @@ import { Provider } from '@angular/core'; -import { ApolloClient } from "@apollo/client"; +import { ApolloClient } from '@apollo/client'; import { Apollo } from './apollo'; import { APOLLO_FLAGS, APOLLO_NAMED_OPTIONS, APOLLO_OPTIONS } from './tokens'; import { Flags, NamedOptions } from './types'; diff --git a/packages/apollo-angular/src/apollo.ts b/packages/apollo-angular/src/apollo.ts index 5eb8fbb5e..eb14fbbe4 100644 --- a/packages/apollo-angular/src/apollo.ts +++ b/packages/apollo-angular/src/apollo.ts @@ -1,7 +1,7 @@ import { Observable } from 'rxjs'; import { Inject, Injectable, NgZone, Optional } from '@angular/core'; -import type { OperationVariables } from "@apollo/client"; -import { ApolloClient } from "@apollo/client"; +import type { OperationVariables } from '@apollo/client'; +import { ApolloClient } from '@apollo/client'; import { QueryRef } from './query-ref'; import { APOLLO_FLAGS, APOLLO_NAMED_OPTIONS, APOLLO_OPTIONS } from './tokens'; import type { EmptyObject, Flags, NamedOptions } from './types'; diff --git a/packages/apollo-angular/src/gql.ts b/packages/apollo-angular/src/gql.ts index fcaf4caaf..b2363efeb 100644 --- a/packages/apollo-angular/src/gql.ts +++ b/packages/apollo-angular/src/gql.ts @@ -1,4 +1,4 @@ -import { gql as gqlTag, TypedDocumentNode } from "@apollo/client"; +import { gql as gqlTag, TypedDocumentNode } from '@apollo/client'; const typedGQLTag: ( literals: ReadonlyArray | Readonly, diff --git a/packages/apollo-angular/src/mutation.ts b/packages/apollo-angular/src/mutation.ts index f9079b6d9..9f79ddc44 100644 --- a/packages/apollo-angular/src/mutation.ts +++ b/packages/apollo-angular/src/mutation.ts @@ -1,7 +1,7 @@ import type { DocumentNode } from 'graphql'; import type { Observable } from 'rxjs'; import { Injectable } from '@angular/core'; -import type { OperationVariables, TypedDocumentNode } from "@apollo/client"; +import type { OperationVariables, TypedDocumentNode } from '@apollo/client'; import { Apollo } from './apollo'; import type { EmptyObject } from './types'; diff --git a/packages/apollo-angular/src/query-ref.ts b/packages/apollo-angular/src/query-ref.ts index 7c10e822c..0f336e057 100644 --- a/packages/apollo-angular/src/query-ref.ts +++ b/packages/apollo-angular/src/query-ref.ts @@ -6,7 +6,7 @@ import type { ObservableQuery, OperationVariables, TypedDocumentNode, -} from "@apollo/client"; +} from '@apollo/client'; import { EmptyObject } from './types'; import { wrapWithZone } from './utils'; diff --git a/packages/apollo-angular/src/query.ts b/packages/apollo-angular/src/query.ts index a49d6be4c..4b165a6fa 100644 --- a/packages/apollo-angular/src/query.ts +++ b/packages/apollo-angular/src/query.ts @@ -1,7 +1,7 @@ import type { DocumentNode } from 'graphql'; import type { Observable } from 'rxjs'; import { Injectable } from '@angular/core'; -import type { OperationVariables, TypedDocumentNode } from "@apollo/client"; +import type { OperationVariables, TypedDocumentNode } from '@apollo/client'; import { Apollo } from './apollo'; import { QueryRef } from './query-ref'; import { EmptyObject } from './types'; diff --git a/packages/apollo-angular/src/subscription.ts b/packages/apollo-angular/src/subscription.ts index 2f8917010..912de96a6 100644 --- a/packages/apollo-angular/src/subscription.ts +++ b/packages/apollo-angular/src/subscription.ts @@ -1,7 +1,7 @@ import type { DocumentNode } from 'graphql'; import type { Observable } from 'rxjs'; import { Injectable } from '@angular/core'; -import type { OperationVariables, TypedDocumentNode } from "@apollo/client"; +import type { OperationVariables, TypedDocumentNode } from '@apollo/client'; import { Apollo } from './apollo'; import { EmptyObject } from './types'; diff --git a/packages/apollo-angular/src/tokens.ts b/packages/apollo-angular/src/tokens.ts index 337256dae..0a8bda2f2 100644 --- a/packages/apollo-angular/src/tokens.ts +++ b/packages/apollo-angular/src/tokens.ts @@ -1,5 +1,5 @@ import { InjectionToken } from '@angular/core'; -import type { ApolloClient } from "@apollo/client"; +import type { ApolloClient } from '@apollo/client'; import type { Flags, NamedOptions } from './types'; export const APOLLO_FLAGS = new InjectionToken('APOLLO_FLAGS'); diff --git a/packages/apollo-angular/src/types.ts b/packages/apollo-angular/src/types.ts index e1f1141aa..dc45338e0 100644 --- a/packages/apollo-angular/src/types.ts +++ b/packages/apollo-angular/src/types.ts @@ -1,4 +1,4 @@ -import type { ApolloClient, TypedDocumentNode } from "@apollo/client"; +import type { ApolloClient, TypedDocumentNode } from '@apollo/client'; export type EmptyObject = { [key: string]: any; diff --git a/packages/apollo-angular/src/utils.ts b/packages/apollo-angular/src/utils.ts index e488beec5..d4db5d3d8 100644 --- a/packages/apollo-angular/src/utils.ts +++ b/packages/apollo-angular/src/utils.ts @@ -1,7 +1,7 @@ import { Observable, queueScheduler, SchedulerAction, SchedulerLike, Subscription } from 'rxjs'; import { map, observeOn, startWith } from 'rxjs/operators'; import { NgZone } from '@angular/core'; -import type { ApolloClient } from "@apollo/client"; +import type { ApolloClient } from '@apollo/client'; import { Apollo } from './apollo'; /** diff --git a/packages/apollo-angular/testing/src/backend.ts b/packages/apollo-angular/testing/src/backend.ts index 15135db48..b1a03c89d 100644 --- a/packages/apollo-angular/testing/src/backend.ts +++ b/packages/apollo-angular/testing/src/backend.ts @@ -1,7 +1,7 @@ import { DocumentNode, print } from 'graphql'; import { Observable, Observer } from 'rxjs'; import { Injectable } from '@angular/core'; -import { ApolloLink } from "@apollo/client"; +import { ApolloLink } from '@apollo/client'; import { addTypenameToDocument } from '@apollo/client/utilities'; import { ApolloTestingController, MatchOperation } from './controller'; import { Operation, TestOperation } from './operation'; diff --git a/packages/apollo-angular/testing/src/module.ts b/packages/apollo-angular/testing/src/module.ts index 9fecd0746..9269d0cd1 100644 --- a/packages/apollo-angular/testing/src/module.ts +++ b/packages/apollo-angular/testing/src/module.ts @@ -1,6 +1,6 @@ import { Apollo } from 'apollo-angular'; import { Inject, InjectionToken, NgModule, Optional } from '@angular/core'; -import { ApolloCache, ApolloLink, InMemoryCache } from "@apollo/client"; +import { ApolloCache, ApolloLink, InMemoryCache } from '@apollo/client'; import { ApolloTestingBackend } from './backend'; import { ApolloTestingController } from './controller'; import { Operation } from './operation'; diff --git a/packages/apollo-angular/testing/src/operation.ts b/packages/apollo-angular/testing/src/operation.ts index b67d043d7..1f11257b0 100644 --- a/packages/apollo-angular/testing/src/operation.ts +++ b/packages/apollo-angular/testing/src/operation.ts @@ -1,6 +1,6 @@ import { GraphQLFormattedError, OperationTypeNode } from 'graphql'; import { Observer } from 'rxjs'; -import { ApolloLink, ErrorLike } from "@apollo/client"; +import { ApolloLink, ErrorLike } from '@apollo/client'; import { isErrorLike } from '@apollo/client/errors'; export type Operation = ApolloLink.Operation & { diff --git a/packages/apollo-angular/testing/tests/integration.spec.ts b/packages/apollo-angular/testing/tests/integration.spec.ts index e0b57bc48..f88ff42ef 100644 --- a/packages/apollo-angular/testing/tests/integration.spec.ts +++ b/packages/apollo-angular/testing/tests/integration.spec.ts @@ -1,7 +1,7 @@ import { print } from 'graphql'; import { afterEach, beforeEach, describe, expect, test } from 'vitest'; import { TestBed } from '@angular/core/testing'; -import { gql } from "@apollo/client"; +import { gql } from '@apollo/client'; import { addTypenameToDocument } from '@apollo/client/utilities'; import { Apollo } from '../../src'; import { ApolloTestingController, ApolloTestingModule } from '../src'; diff --git a/packages/apollo-angular/testing/tests/module.spec.ts b/packages/apollo-angular/testing/tests/module.spec.ts index 987736ee8..81dc4fb86 100644 --- a/packages/apollo-angular/testing/tests/module.spec.ts +++ b/packages/apollo-angular/testing/tests/module.spec.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from 'vitest'; import { TestBed } from '@angular/core/testing'; -import { gql, InMemoryCache } from "@apollo/client"; +import { gql, InMemoryCache } from '@apollo/client'; import { Apollo } from '../../src'; import { APOLLO_TESTING_CACHE, ApolloTestingController, ApolloTestingModule } from '../src'; diff --git a/packages/apollo-angular/testing/tests/operation.spec.ts b/packages/apollo-angular/testing/tests/operation.spec.ts index a31b5d1c4..1cd24075e 100644 --- a/packages/apollo-angular/testing/tests/operation.spec.ts +++ b/packages/apollo-angular/testing/tests/operation.spec.ts @@ -1,5 +1,5 @@ import { beforeEach, describe, expect, test } from 'vitest'; -import { ApolloLink, gql } from "@apollo/client"; +import { ApolloLink, gql } from '@apollo/client'; import { ApolloTestingBackend } from '../src/backend'; import { buildOperationForLink, executeWithDefaultContext as execute } from './utils'; diff --git a/packages/apollo-angular/testing/tests/utils.ts b/packages/apollo-angular/testing/tests/utils.ts index f29536b3c..3140b29c9 100644 --- a/packages/apollo-angular/testing/tests/utils.ts +++ b/packages/apollo-angular/testing/tests/utils.ts @@ -1,6 +1,6 @@ import { DocumentNode } from 'graphql'; import { Observable } from 'rxjs'; -import { ApolloClient, execute, InMemoryCache, OperationVariables } from "@apollo/client"; +import { ApolloClient, execute, InMemoryCache, OperationVariables } from '@apollo/client'; import { ApolloLink } from '@apollo/client/link'; import { addTypenameToDocument } from '@apollo/client/utilities'; diff --git a/packages/apollo-angular/tests/Apollo.spec.ts b/packages/apollo-angular/tests/Apollo.spec.ts index 6316fffa3..953bcd257 100644 --- a/packages/apollo-angular/tests/Apollo.spec.ts +++ b/packages/apollo-angular/tests/Apollo.spec.ts @@ -3,7 +3,7 @@ import { mergeMap } from 'rxjs/operators'; import { beforeEach, describe, expect, test, vi } from 'vitest'; import { NgZone } from '@angular/core'; import { TestBed } from '@angular/core/testing'; -import { ApolloLink, InMemoryCache, NetworkStatus } from "@apollo/client"; +import { ApolloLink, InMemoryCache, NetworkStatus } from '@apollo/client'; import { MockLink } from '@apollo/client/testing'; import { Apollo, ApolloBase } from '../src/apollo'; import { gql } from '../src/gql'; diff --git a/packages/apollo-angular/tests/QueryRef.spec.ts b/packages/apollo-angular/tests/QueryRef.spec.ts index 6697a8cf2..2a81eca4d 100644 --- a/packages/apollo-angular/tests/QueryRef.spec.ts +++ b/packages/apollo-angular/tests/QueryRef.spec.ts @@ -2,7 +2,7 @@ import { Subject } from 'rxjs'; import { map, takeUntil } from 'rxjs/operators'; import { beforeEach, describe, expect, test, vi } from 'vitest'; import { NgZone } from '@angular/core'; -import { ApolloClient, ApolloLink, InMemoryCache, ObservableQuery } from "@apollo/client"; +import { ApolloClient, ApolloLink, InMemoryCache, ObservableQuery } from '@apollo/client'; import { MockLink } from '@apollo/client/testing'; import { gql } from '../src/gql'; import { QueryRef } from '../src/query-ref'; diff --git a/packages/apollo-angular/tests/integration.spec.ts b/packages/apollo-angular/tests/integration.spec.ts index fe2acbc13..b07264c32 100644 --- a/packages/apollo-angular/tests/integration.spec.ts +++ b/packages/apollo-angular/tests/integration.spec.ts @@ -1,7 +1,7 @@ import { beforeEach, describe, expect, test } from 'vitest'; import { provideHttpClient } from '@angular/common/http'; import { TestBed } from '@angular/core/testing'; -import { InMemoryCache } from "@apollo/client"; +import { InMemoryCache } from '@apollo/client'; import { MockLink } from '@apollo/client/testing'; import { Apollo, provideApollo } from '../src'; From 2f5146caae7db30393d4118fa75b258bfb042f48 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Thu, 18 Sep 2025 18:56:18 -0600 Subject: [PATCH 79/97] Fix options type in HttpBatchLink --- packages/apollo-angular/http/src/http-batch-link.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/apollo-angular/http/src/http-batch-link.ts b/packages/apollo-angular/http/src/http-batch-link.ts index 02d1cb482..be63af9dc 100644 --- a/packages/apollo-angular/http/src/http-batch-link.ts +++ b/packages/apollo-angular/http/src/http-batch-link.ts @@ -32,9 +32,9 @@ export const defaults = { */ export function pick>( context: Context, - options: HttpLink.Options, + options: HttpBatchLink.Options, key: K, -): ReturnType> { +): ReturnType> { return prioritize(context[key], options[key], defaults[key]); } @@ -109,7 +109,7 @@ export class HttpBatchLinkHandler extends ApolloLink { private createOptions( operations: ApolloLink.Operation[], - ): Required> { + ): Required> { const context: Context = operations[0].getContext(); return { From e1880f35ccc15c5c0bb43a5919559b6ac134c3ce Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Thu, 18 Sep 2025 19:02:58 -0600 Subject: [PATCH 80/97] Remove outdated tsdoc --- packages/apollo-angular/src/apollo.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/apollo-angular/src/apollo.ts b/packages/apollo-angular/src/apollo.ts index eb14fbbe4..da82f2863 100644 --- a/packages/apollo-angular/src/apollo.ts +++ b/packages/apollo-angular/src/apollo.ts @@ -26,7 +26,6 @@ export declare namespace Apollo { > = ApolloClient.MutateOptions & { /** * Observable starts with `{ loading: true }`. - * There's a big chance the next major version will enable that by default. * * Disabled by default */ From ca961dbb5d01214c2ba6c7fa7c97345f8489ec99 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Thu, 18 Sep 2025 19:06:28 -0600 Subject: [PATCH 81/97] Use original order of generic args for deprecated WatchQueryOptions --- packages/apollo-angular/src/deprecated.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/apollo-angular/src/deprecated.ts b/packages/apollo-angular/src/deprecated.ts index 557906267..759843532 100644 --- a/packages/apollo-angular/src/deprecated.ts +++ b/packages/apollo-angular/src/deprecated.ts @@ -4,8 +4,8 @@ import type { EmptyObject } from './types'; /** @deprecated Use `Apollo.WatchQueryOptions` instead */ export type WatchQueryOptions< - TData = unknown, TVariables extends OperationVariables = EmptyObject, + TData = unknown, > = Apollo.WatchQueryOptions; /** @deprecated Use `Apollo.MutateOptions` instead */ From 6bce3e9ea213ed77160a507d61d875ddc67db523 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Thu, 18 Sep 2025 19:25:20 -0600 Subject: [PATCH 82/97] Add license --- .../test-utils/matchers/toEmitAnything.ts | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/packages/apollo-angular/test-utils/matchers/toEmitAnything.ts b/packages/apollo-angular/test-utils/matchers/toEmitAnything.ts index b66fa7a89..a4f6730cb 100644 --- a/packages/apollo-angular/test-utils/matchers/toEmitAnything.ts +++ b/packages/apollo-angular/test-utils/matchers/toEmitAnything.ts @@ -1,3 +1,29 @@ +/** + * Adapted from + * https://github.com/apollographql/apollo-client/blob/1d165ba37eca7e5d667055553aacc4c26be56065/src/testing/matchers/toEmitAnything.ts + * + * The MIT License (MIT) + * + * Copyright (c) 2022 Apollo Graph, Inc. (Formerly Meteor Development Group, Inc.) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ import { ObservableStream, TakeOptions } from 'test-utils/ObservableStream'; import { RawMatcherFn } from '@vitest/expect'; From be2a82777c771830102bd80804346126eb9b812e Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Thu, 18 Sep 2025 20:01:22 -0600 Subject: [PATCH 83/97] Just check type when asserting takeNext --- packages/apollo-angular/test-utils/ObservableStream.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/apollo-angular/test-utils/ObservableStream.ts b/packages/apollo-angular/test-utils/ObservableStream.ts index 09127ac5d..4603d3903 100644 --- a/packages/apollo-angular/test-utils/ObservableStream.ts +++ b/packages/apollo-angular/test-utils/ObservableStream.ts @@ -120,7 +120,9 @@ export class ObservableStream { async takeNext(options?: TakeOptions): Promise { const event = await this.take(options); - validateEquals(event, { type: 'next', value: expect.anything() }); + if (event.type !== 'next') { + throw new EventMismatchError({ type: 'next', value: expect.anything() }, event); + } return (event as ObservableEvent & { type: 'next' }).value; } From 891f73672de3241abaf7d44931a576e523596717 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Thu, 18 Sep 2025 20:05:58 -0600 Subject: [PATCH 84/97] Use ObservableStream in tests --- .../apollo-angular/tests/QueryRef.spec.ts | 213 ++++++++++-------- 1 file changed, 120 insertions(+), 93 deletions(-) diff --git a/packages/apollo-angular/tests/QueryRef.spec.ts b/packages/apollo-angular/tests/QueryRef.spec.ts index 2a81eca4d..a65efd73e 100644 --- a/packages/apollo-angular/tests/QueryRef.spec.ts +++ b/packages/apollo-angular/tests/QueryRef.spec.ts @@ -2,10 +2,17 @@ import { Subject } from 'rxjs'; import { map, takeUntil } from 'rxjs/operators'; import { beforeEach, describe, expect, test, vi } from 'vitest'; import { NgZone } from '@angular/core'; -import { ApolloClient, ApolloLink, InMemoryCache, ObservableQuery } from '@apollo/client'; +import { + ApolloClient, + ApolloLink, + InMemoryCache, + NetworkStatus, + ObservableQuery, +} from '@apollo/client'; import { MockLink } from '@apollo/client/testing'; import { gql } from '../src/gql'; import { QueryRef } from '../src/query-ref'; +import { ObservableStream } from '../test-utils/ObservableStream'; const createClient = (link: ApolloLink) => new ApolloClient({ @@ -61,20 +68,14 @@ describe('QueryRef', () => { queryRef = new QueryRef(obsQuery, ngZone); }); - test('should listen to changes', () => - new Promise(done => { - queryRef.valueChanges.subscribe({ - next: result => { - if (result.dataState === 'complete') { - expect(result.data).toBeDefined(); - done(); - } - }, - error: e => { - throw e; - }, - }); - })); + test('should listen to changes', async () => { + const stream = new ObservableStream(queryRef.valueChanges); + + await expect(stream.takeNext()).resolves.toMatchObject({ loading: true }); + + const result = await stream.takeNext(); + expect(result.data).toBeDefined(); + }); test('should be able to call refetch', () => { const mockCallback = vi.fn(); @@ -85,65 +86,59 @@ describe('QueryRef', () => { expect(mockCallback.mock.calls.length).toBe(1); }); - test('should be able refetch and receive new results', () => - new Promise(done => { - let calls = 0; - - queryRef.valueChanges.subscribe({ - next: result => { - calls++; - - if (result.dataState === 'complete') { - expect(result.data).toBeDefined(); - } - - if (calls === 4) { - done(); - } - }, - error: e => { - throw e; - }, - complete: () => { - throw 'Should not be here'; - }, - }); + test('should be able refetch and receive new results', async () => { + const stream = new ObservableStream(queryRef.valueChanges); + + await expect(stream.takeNext()).resolves.toEqual({ + data: undefined, + dataState: 'empty', + loading: true, + networkStatus: NetworkStatus.loading, + partial: true, + }); + + await expect(stream.takeNext()).resolves.toEqual({ + data: { heroes: [Superman] }, + dataState: 'complete', + loading: false, + networkStatus: NetworkStatus.ready, + partial: false, + }); - setTimeout(() => { - queryRef.refetch(); - }, 200); - })); + queryRef.refetch(); - test('should be able refetch and receive new results after using rxjs operator', () => - new Promise(done => { - let calls = 0; - const obs = queryRef.valueChanges; + await expect(stream.takeNext()).resolves.toEqual({ + data: { heroes: [Superman] }, + dataState: 'complete', + loading: true, + networkStatus: NetworkStatus.refetch, + partial: false, + }); + + await expect(stream.takeNext()).resolves.toEqual({ + data: { heroes: [Superman, Batman] }, + dataState: 'complete', + loading: false, + networkStatus: NetworkStatus.ready, + partial: false, + }); + + await expect(stream).not.toEmitAnything(); + }); - obs.pipe(map(result => result.data)).subscribe({ - next: result => { - calls++; + test('should be able refetch and receive new results after using rxjs operator', async () => { + const obs = queryRef.valueChanges.pipe(map(result => result.data)); + const stream = new ObservableStream(obs); - // loading -> data; refetch() -> loading -> data - if (calls === 2) { - expect(result.heroes.length).toBe(1); - } else if (calls === 4) { - expect(result.heroes.length).toBe(2); + await expect(stream.takeNext()).resolves.toBeUndefined(); + await expect(stream.takeNext()).resolves.toEqual({ heroes: [Superman] }); - done(); - } - }, - error: e => { - throw e; - }, - complete: () => { - throw 'Should not be here'; - }, - }); + queryRef.refetch(); - setTimeout(() => { - queryRef.refetch(); - }, 200); - })); + await expect(stream.takeNext()).resolves.toEqual({ heroes: [Superman] }); + await expect(stream.takeNext()).resolves.toEqual({ heroes: [Superman, Batman] }); + await expect(stream).not.toEmitAnything(); + }); test('should be able to call updateQuery()', () => { const mockCallback = vi.fn(); @@ -156,37 +151,69 @@ describe('QueryRef', () => { expect(mockCallback.mock.calls[0][0]).toBe(mapFn); }); - test('should be able to call getCurrentResult() and get updated results', () => - new Promise(done => { - let calls = 0; - const obs = queryRef.valueChanges; + test('should be able to call getCurrentResult() and get updated results', async () => { + const stream = new ObservableStream(queryRef.valueChanges); - obs.pipe(map(result => result.data)).subscribe({ - next: result => { - calls++; + { + const result = await stream.takeNext(); + const currentResult = queryRef.getCurrentResult(); - const currentResult = queryRef.getCurrentResult(); + expect(currentResult).toEqual(result); + expect(currentResult).toEqual({ + data: undefined, + dataState: 'empty', + loading: true, + networkStatus: NetworkStatus.loading, + partial: true, + }); + } - if (currentResult.dataState === 'complete') { - expect(currentResult.data.heroes.length).toBe(result.heroes.length); - } + { + const result = await stream.takeNext(); + const currentResult = queryRef.getCurrentResult(); + + expect(currentResult).toEqual(result); + expect(currentResult).toEqual({ + data: { heroes: [Superman] }, + dataState: 'complete', + loading: false, + networkStatus: NetworkStatus.ready, + partial: false, + }); + } - if (calls === 4) { - done(); - } - }, - error: e => { - throw e; - }, - complete: () => { - throw 'Should not be here'; - }, + queryRef.refetch(); + + { + const result = await stream.takeNext(); + const currentResult = queryRef.getCurrentResult(); + + expect(currentResult).toEqual(result); + expect(currentResult).toEqual({ + data: { heroes: [Superman] }, + dataState: 'complete', + loading: true, + networkStatus: NetworkStatus.refetch, + partial: false, }); + } - setTimeout(() => { - queryRef.refetch(); - }, 200); - })); + { + const result = await stream.takeNext(); + const currentResult = queryRef.getCurrentResult(); + + expect(currentResult).toEqual(result); + expect(currentResult).toEqual({ + data: { heroes: [Superman, Batman] }, + dataState: 'complete', + loading: false, + networkStatus: NetworkStatus.ready, + partial: false, + }); + } + + await expect(stream).not.toEmitAnything(); + }); test('should be able to call fetchMore()', () => { const mockCallback = vi.fn(); From d902a1cd3b5be8fe4b412bb27ca3183a7450f1cb Mon Sep 17 00:00:00 2001 From: Adrien Crivelli Date: Fri, 19 Sep 2025 15:03:50 +0900 Subject: [PATCH 85/97] Document new default of `notifyOnNetworkStatusChange` --- website/src/pages/docs/data/queries.mdx | 27 ++++++++++++++----------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/website/src/pages/docs/data/queries.mdx b/website/src/pages/docs/data/queries.mdx index ae7c044fd..e2efd4efa 100644 --- a/website/src/pages/docs/data/queries.mdx +++ b/website/src/pages/docs/data/queries.mdx @@ -369,9 +369,15 @@ to render partial results. ## Loading State -Every response you get from `Apollo.watchQuery()` contains `loading` property. By default, it's -always `false` and the first result is emitted with the response from the ApolloLink execution -chain. In order to correct it you can enable `useInitialLoading` flag in configuration. +Every response you get from `Apollo.watchQuery()` contains the `loading` property. The option +[`notifyOnNetworkStatusChange`](https://www.apollographql.com/docs/react/data/queries#queryhookoptions-interface-notifyonnetworkstatuschange) +defaults to `true`. That means the observable will emit immediately and synchronously with +`loading: true` and `data: undefined`. When the XHR is completed, the observable will emit with +`loading: false` and with a defined `result`. + +If you prefer to be notified only when result is available, and you are not interested in loading +state, then you can configure `notifyOnNetworkStatusChange` to `false`, globally when constructing +`ApolloClient` of for a specific query only. Something like this: ```ts filename="app.config.ts" import { provideApollo } from 'apollo-angular'; @@ -384,15 +390,12 @@ provideApollo( return { link: inject(HttpLink).create({ uri: '/graphql' }), cache: new InMemoryCache(), + defaultOptions: { + watchQuery: { + notifyOnNetworkStatusChange: false, + }, + }, }; - }, - { - useInitialLoading: true, // enable it here - }, + } ); ``` - - - `useInitialLoading` is disabled to avoid any breaking changes, this may be enabled in next major - version. - From bdc93dfca9c1d408f5bbce45713d63affede0f5c Mon Sep 17 00:00:00 2001 From: Adrien Crivelli Date: Fri, 19 Sep 2025 15:16:02 +0900 Subject: [PATCH 86/97] Drop `httpHeaders` entirely --- .changeset/funny-trainers-look.md | 12 ++++++++++++ packages/apollo-angular/headers/src/index.ts | 7 ------- packages/apollo-angular/headers/tests/index.spec.ts | 2 +- 3 files changed, 13 insertions(+), 8 deletions(-) create mode 100644 .changeset/funny-trainers-look.md diff --git a/.changeset/funny-trainers-look.md b/.changeset/funny-trainers-look.md new file mode 100644 index 000000000..e7f79476a --- /dev/null +++ b/.changeset/funny-trainers-look.md @@ -0,0 +1,12 @@ +--- +'apollo-angular': major +--- + +`httpHeaders` is a class + +Migrate your code like so: + +```diff +- const link = httpHeaders(); ++ const link = new HttpHeadersLink(); +``` diff --git a/packages/apollo-angular/headers/src/index.ts b/packages/apollo-angular/headers/src/index.ts index 594293df5..c88b7d6d2 100644 --- a/packages/apollo-angular/headers/src/index.ts +++ b/packages/apollo-angular/headers/src/index.ts @@ -15,10 +15,3 @@ export class HttpHeadersLink extends ApolloLink { }); } } - -/** - * @deprecated Use `HttpHeadersLink` instead. - */ -export const httpHeaders = () => { - return new HttpHeadersLink(); -}; diff --git a/packages/apollo-angular/headers/tests/index.spec.ts b/packages/apollo-angular/headers/tests/index.spec.ts index dfdf1b878..61bd89308 100644 --- a/packages/apollo-angular/headers/tests/index.spec.ts +++ b/packages/apollo-angular/headers/tests/index.spec.ts @@ -16,7 +16,7 @@ const data = { heroes: [{ name: 'Foo', __typename: 'Hero' }] }; const dummyClient = new ApolloClient({ cache: new InMemoryCache(), link: ApolloLink.empty() }); -describe('httpHeaders', () => { +describe('HttpHeadersLink', () => { test('should turn object into HttpHeaders', () => new Promise(done => { const headersLink = new HttpHeadersLink(); From b9c62a5b4b3b10c408bfb8386286013051bce71d Mon Sep 17 00:00:00 2001 From: Adrien Crivelli Date: Fri, 19 Sep 2025 15:36:59 +0900 Subject: [PATCH 87/97] Document combined parameters of `Query`, `Mutation` and `Subscription` classes --- .changeset/tough-masks-search.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 .changeset/tough-masks-search.md diff --git a/.changeset/tough-masks-search.md b/.changeset/tough-masks-search.md new file mode 100644 index 000000000..150e6bf9f --- /dev/null +++ b/.changeset/tough-masks-search.md @@ -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' }); + } +} +``` From 8c0b7f0b47f4b45ee668a4805edd384f66bf30a2 Mon Sep 17 00:00:00 2001 From: Adrien Crivelli Date: Fri, 19 Sep 2025 15:43:52 +0900 Subject: [PATCH 88/97] Document move `useZone` option into subscription options --- .changeset/giant-clouds-shout.md | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 .changeset/giant-clouds-shout.md diff --git a/.changeset/giant-clouds-shout.md b/.changeset/giant-clouds-shout.md new file mode 100644 index 000000000..e90d9021f --- /dev/null +++ b/.changeset/giant-clouds-shout.md @@ -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 }); +``` From 7e8fd30a8fc11a48ebb2e5cfd75c209839072ca5 Mon Sep 17 00:00:00 2001 From: Adrien Crivelli Date: Fri, 19 Sep 2025 16:06:24 +0900 Subject: [PATCH 89/97] Update doc to import from '@apollo/client' --- website/src/pages/docs/caching/advanced-topics.mdx | 4 ++-- website/src/pages/docs/caching/configuration.mdx | 4 ++-- website/src/pages/docs/data/mutations.mdx | 2 +- website/src/pages/docs/data/network.mdx | 12 ++++++------ website/src/pages/docs/data/pagination.mdx | 4 ++-- website/src/pages/docs/data/queries.mdx | 2 +- website/src/pages/docs/data/subscriptions.mdx | 2 +- .../client-schema-mocking.mdx | 2 +- .../pages/docs/development-and-testing/testing.mdx | 4 ++-- website/src/pages/docs/get-started.mdx | 4 ++-- .../pages/docs/performance/server-side-rendering.mdx | 4 ++-- website/src/pages/docs/recipes/authentication.mdx | 4 ++-- .../docs/recipes/automatic-persisted-queries.mdx | 2 +- website/src/pages/docs/recipes/multiple-clients.mdx | 2 +- website/src/pages/docs/recipes/nativescript.mdx | 2 +- 15 files changed, 27 insertions(+), 27 deletions(-) diff --git a/website/src/pages/docs/caching/advanced-topics.mdx b/website/src/pages/docs/caching/advanced-topics.mdx index 41dc021e5..f781d8c5f 100644 --- a/website/src/pages/docs/caching/advanced-topics.mdx +++ b/website/src/pages/docs/caching/advanced-topics.mdx @@ -314,7 +314,7 @@ a different query, Apollo Client doesn't know that. To tell Apollo Client where existing `book` data, we can define a field policy `read` function for the `book` field: ```ts -import { InMemoryCache } from '@apollo/client/core'; +import { InMemoryCache } from '@apollo/client'; const cache = new InMemoryCache({ typePolicies: { @@ -383,7 +383,7 @@ write to the cache with a short configurable debounce interval. ```ts import { LocalStorageWrapper, persistCacheSync } from 'apollo3-cache-persist'; -import { InMemoryCache } from '@apollo/client/core'; +import { InMemoryCache } from '@apollo/client'; const cache = new InMemoryCache(); diff --git a/website/src/pages/docs/caching/configuration.mdx b/website/src/pages/docs/caching/configuration.mdx index 0da05440e..5caca1672 100644 --- a/website/src/pages/docs/caching/configuration.mdx +++ b/website/src/pages/docs/caching/configuration.mdx @@ -28,7 +28,7 @@ Create an `InMemoryCache` object and provide to Apollo options, like so: import { provideApollo } from 'apollo-angular'; import { HttpLink } from 'apollo-angular/http'; import { inject } from '@angular/core'; -import { InMemoryCache } from '@apollo/client/core'; +import { InMemoryCache } from '@apollo/client'; provideApollo(() => { const httpLink = inject(HttpLink); @@ -167,7 +167,7 @@ If you need to define a single fallback `keyFields` function that isn't specific `__typename`, you can use the `dataIdFromObject` function that was introduced in Apollo Client 2.x: ```ts -import { defaultDataIdFromObject } from '@apollo/client/core'; +import { defaultDataIdFromObject } from '@apollo/client'; const cache = new InMemoryCache({ dataIdFromObject(responseObject) { diff --git a/website/src/pages/docs/data/mutations.mdx b/website/src/pages/docs/data/mutations.mdx index 1a37c5e72..c477146c6 100644 --- a/website/src/pages/docs/data/mutations.mdx +++ b/website/src/pages/docs/data/mutations.mdx @@ -258,7 +258,7 @@ can enable `useMutationLoading` flag in configuration. import { provideApollo } from 'apollo-angular'; import { HttpLink } from 'apollo-angular/http'; import { inject } from '@angular/core'; -import { InMemoryCache } from '@apollo/client/core'; +import { InMemoryCache } from '@apollo/client'; provideApollo( () => { diff --git a/website/src/pages/docs/data/network.mdx b/website/src/pages/docs/data/network.mdx index 4afcf37f1..429bf1520 100644 --- a/website/src/pages/docs/data/network.mdx +++ b/website/src/pages/docs/data/network.mdx @@ -24,7 +24,7 @@ easier testing. import { provideApollo } from 'apollo-angular'; import { HttpLink } from 'apollo-angular/http'; import { inject } from '@angular/core'; -import { InMemoryCache } from '@apollo/client/core'; +import { InMemoryCache } from '@apollo/client'; provideApollo(() => { const httpLink = inject(HttpLink); @@ -96,7 +96,7 @@ apollo.query({ import { provideApollo } from 'apollo-angular'; import { HttpLink } from 'apollo-angular/http'; import { inject } from '@angular/core'; -import { InMemoryCache } from '@apollo/client/core'; +import { InMemoryCache } from '@apollo/client'; provideApollo(() => { const httpLink = inject(HttpLink); @@ -128,7 +128,7 @@ import { HttpLink } from 'apollo-angular/http'; import extractFiles from 'extract-files/extractFiles.mjs'; import isExtractableFile from 'extract-files/isExtractableFile.mjs'; import { inject } from '@angular/core'; -import { InMemoryCache } from '@apollo/client/core'; +import { InMemoryCache } from '@apollo/client'; provideApollo(() => { const httpLink = inject(HttpLink); @@ -162,7 +162,7 @@ import { provideApollo } from 'apollo-angular'; import { HttpLink } from 'apollo-angular/http'; import { HttpHeaders } from '@angular/common/http'; import { inject } from '@angular/core'; -import { ApolloLink, InMemoryCache } from '@apollo/client/core'; +import { ApolloLink, InMemoryCache } from '@apollo/client'; provideApollo(() => { const httpLink = inject(HttpLink); @@ -194,7 +194,7 @@ provideApollo(() => { import { provideApollo } from 'apollo-angular'; import { HttpLink } from 'apollo-angular/http'; import { inject } from '@angular/core'; -import { InMemoryCache } from '@apollo/client/core'; +import { InMemoryCache } from '@apollo/client'; import { onError } from '@apollo/client/link/error'; provideApollo(() => { @@ -226,7 +226,7 @@ An Apollo Link to combine multiple GraphQL operations into single HTTP request. import { provideApollo } from 'apollo-angular'; import { HttpBatchLink } from 'apollo-angular/http'; import { inject } from '@angular/core'; -import { InMemoryCache } from '@apollo/client/core'; +import { InMemoryCache } from '@apollo/client'; provideApollo(() => { const httpBatchLink = inject(HttpBatchLink); diff --git a/website/src/pages/docs/data/pagination.mdx b/website/src/pages/docs/data/pagination.mdx index 176e0b7f5..251f4cb15 100644 --- a/website/src/pages/docs/data/pagination.mdx +++ b/website/src/pages/docs/data/pagination.mdx @@ -34,7 +34,7 @@ field policy for every relevant list field. This example uses `offsetLimitPagination` to generate a field policy for `Query.posts`: ```typescript -import { InMemoryCache } from '@apollo/client/core'; +import { InMemoryCache } from '@apollo/client'; import { offsetLimitPagination } from '@apollo/client/utilities'; const cache = new InMemoryCache({ @@ -197,7 +197,7 @@ class FeedComponent { ``` ```ts -import { InMemoryCache } from '@apollo/client/core'; +import { InMemoryCache } from '@apollo/client'; const cache = new InMemoryCache({ typePolicies: { diff --git a/website/src/pages/docs/data/queries.mdx b/website/src/pages/docs/data/queries.mdx index e2efd4efa..3a299709c 100644 --- a/website/src/pages/docs/data/queries.mdx +++ b/website/src/pages/docs/data/queries.mdx @@ -383,7 +383,7 @@ state, then you can configure `notifyOnNetworkStatusChange` to `false`, globally import { provideApollo } from 'apollo-angular'; import { HttpLink } from 'apollo-angular/http'; import { inject } from '@angular/core'; -import { InMemoryCache } from '@apollo/client/core'; +import { InMemoryCache } from '@apollo/client'; provideApollo( () => { diff --git a/website/src/pages/docs/data/subscriptions.mdx b/website/src/pages/docs/data/subscriptions.mdx index ed4abf7e1..92f2d6999 100644 --- a/website/src/pages/docs/data/subscriptions.mdx +++ b/website/src/pages/docs/data/subscriptions.mdx @@ -105,7 +105,7 @@ import { HttpLink } from 'apollo-angular/http'; import { Kind, OperationTypeNode } from 'graphql'; import { createClient } from 'graphql-ws'; import { inject } from '@angular/core'; -import { InMemoryCache, split } from '@apollo/client/core'; +import { InMemoryCache, split } from '@apollo/client'; import { GraphQLWsLink } from '@apollo/client/link/subscriptions'; import { getMainDefinition } from '@apollo/client/utilities'; diff --git a/website/src/pages/docs/development-and-testing/client-schema-mocking.mdx b/website/src/pages/docs/development-and-testing/client-schema-mocking.mdx index b43290ca3..dd992fe9b 100644 --- a/website/src/pages/docs/development-and-testing/client-schema-mocking.mdx +++ b/website/src/pages/docs/development-and-testing/client-schema-mocking.mdx @@ -30,7 +30,7 @@ data: import { provideApollo } from 'apollo-angular'; import { HttpLink } from 'apollo-angular/http'; import { inject } from '@angular/core'; -import { InMemoryCache } from '@apollo/client/core'; +import { InMemoryCache } from '@apollo/client'; const typeDefs = gql` extend type Rocket { diff --git a/website/src/pages/docs/development-and-testing/testing.mdx b/website/src/pages/docs/development-and-testing/testing.mdx index 685e40291..d49060021 100644 --- a/website/src/pages/docs/development-and-testing/testing.mdx +++ b/website/src/pages/docs/development-and-testing/testing.mdx @@ -298,7 +298,7 @@ can provide the `APOLLO_TESTING_CACHE` token: ```ts import { APOLLO_TESTING_CACHE, ApolloTestingModule } from 'apollo-angular/testing'; import { TestBed } from '@angular/core/testing'; -import { InMemoryCache } from '@apollo/client/core'; +import { InMemoryCache } from '@apollo/client'; beforeEach(() => { TestBed.configureTestingModule({ @@ -322,7 +322,7 @@ And for named clients: ```ts import { APOLLO_TESTING_NAMED_CACHE, ApolloTestingModule } from 'apollo-angular/testing'; import { TestBed } from '@angular/core/testing'; -import { InMemoryCache } from '@apollo/client/core'; +import { InMemoryCache } from '@apollo/client'; beforeEach(() => { TestBed.configureTestingModule({ diff --git a/website/src/pages/docs/get-started.mdx b/website/src/pages/docs/get-started.mdx index 78c9358a6..3da9670f2 100644 --- a/website/src/pages/docs/get-started.mdx +++ b/website/src/pages/docs/get-started.mdx @@ -54,7 +54,7 @@ import { provideApollo } from 'apollo-angular'; import { HttpLink } from 'apollo-angular/http'; import { provideHttpClient } from '@angular/common/http'; import { ApplicationConfig, inject } from '@angular/core'; -import { InMemoryCache } from '@apollo/client/core'; +import { InMemoryCache } from '@apollo/client'; export const appConfig: ApplicationConfig = { providers: [ @@ -76,7 +76,7 @@ Take a closer look what we did there: 1. With `apollo-angular/http` and `HttpLink` service we connect our client to an external GraphQL Server -1. Thanks to `@apollo/client/core` and `InMemoryCache` we have a place to store data in +1. Thanks to `@apollo/client` and `InMemoryCache` we have a place to store data in ## Links and Cache diff --git a/website/src/pages/docs/performance/server-side-rendering.mdx b/website/src/pages/docs/performance/server-side-rendering.mdx index 8a75a494b..ad5dd3499 100644 --- a/website/src/pages/docs/performance/server-side-rendering.mdx +++ b/website/src/pages/docs/performance/server-side-rendering.mdx @@ -28,7 +28,7 @@ import { provideApollo } from 'apollo-angular'; import { HttpLink } from 'apollo-angular/http'; import { provideHttpClient } from '@angular/common/http'; import { ApplicationConfig, inject, InjectionToken } from '@angular/core'; -import { InMemoryCache } from '@apollo/client/core'; +import { InMemoryCache } from '@apollo/client'; const MY_APOLLO_CACHE = new InjectionToken('apollo-cache'); @@ -84,7 +84,7 @@ import { makeStateKey, TransferState, } from '@angular/core'; -import { InMemoryCache, NormalizedCacheObject } from '@apollo/client/core'; +import { InMemoryCache, NormalizedCacheObject } from '@apollo/client'; const MY_APOLLO_CACHE = new InjectionToken('apollo-cache'); const STATE_KEY = makeStateKey('apollo.state'); diff --git a/website/src/pages/docs/recipes/authentication.mdx b/website/src/pages/docs/recipes/authentication.mdx index 3ca48b72b..f5800684a 100644 --- a/website/src/pages/docs/recipes/authentication.mdx +++ b/website/src/pages/docs/recipes/authentication.mdx @@ -24,7 +24,7 @@ backend, it is very easy to tell your network interface to send the cookie along import { provideApollo } from 'apollo-angular'; import { HttpLink } from 'apollo-angular/http'; import { inject } from '@angular/core'; -import { InMemoryCache } from '@apollo/client/core'; +import { InMemoryCache } from '@apollo/client'; provideApollo(() => { const httpLink = inject(HttpLink); @@ -60,7 +60,7 @@ pull the login token from `localStorage` every time a request is sent. import { provideApollo } from 'apollo-angular'; import { HttpLink } from 'apollo-angular/http'; import { inject } from '@angular/core'; -import { ApolloLink, InMemoryCache } from '@apollo/client/core'; +import { ApolloLink, InMemoryCache } from '@apollo/client'; import { setContext } from '@apollo/client/link/context'; provideApollo(() => { diff --git a/website/src/pages/docs/recipes/automatic-persisted-queries.mdx b/website/src/pages/docs/recipes/automatic-persisted-queries.mdx index 7dcea5c8e..5ea4a2105 100644 --- a/website/src/pages/docs/recipes/automatic-persisted-queries.mdx +++ b/website/src/pages/docs/recipes/automatic-persisted-queries.mdx @@ -58,7 +58,7 @@ import { HttpLink } from 'apollo-angular/http'; import { createPersistedQueryLink } from 'apollo-angular/persisted-queries'; import { sha256 } from 'crypto-hash'; import { inject } from '@angular/core'; -import { InMemoryCache } from '@apollo/client/core'; +import { InMemoryCache } from '@apollo/client'; provideApollo(() => { const httpLink = inject(HttpLink); diff --git a/website/src/pages/docs/recipes/multiple-clients.mdx b/website/src/pages/docs/recipes/multiple-clients.mdx index e7a98c890..c0dc8c074 100644 --- a/website/src/pages/docs/recipes/multiple-clients.mdx +++ b/website/src/pages/docs/recipes/multiple-clients.mdx @@ -58,7 +58,7 @@ In our `app.config.ts` file use `provideNamedApollo()` token to configure Apollo import { provideNamedApollo } from 'apollo-angular'; import { HttpLink } from 'apollo-angular/http'; import { inject } from '@angular/core'; -import { InMemoryCache } from '@apollo/client/core'; +import { InMemoryCache } from '@apollo/client'; provideNamedApollo(() => { const httpLink = inject(HttpLink); diff --git a/website/src/pages/docs/recipes/nativescript.mdx b/website/src/pages/docs/recipes/nativescript.mdx index b77d651ce..9a1f0a9cf 100644 --- a/website/src/pages/docs/recipes/nativescript.mdx +++ b/website/src/pages/docs/recipes/nativescript.mdx @@ -27,7 +27,7 @@ import { HttpLink } from 'apollo-angular/http'; import { NativeScriptHttpClientModule } from 'nativescript-angular/http-client'; import { NativeScriptModule } from 'nativescript-angular/nativescript.module'; import { ApplicationConfig, importProvidersFrom, inject } from '@angular/core'; -import { InMemoryCache } from '@apollo/client/core'; +import { InMemoryCache } from '@apollo/client'; export const appConfig: ApplicationConfig = { providers: [ From aaa54c92fab296ff8cadff9a249f6e8b1f06e834 Mon Sep 17 00:00:00 2001 From: Adrien Crivelli Date: Fri, 19 Sep 2025 16:09:22 +0900 Subject: [PATCH 90/97] Prettier --- website/src/pages/docs/data/queries.mdx | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/website/src/pages/docs/data/queries.mdx b/website/src/pages/docs/data/queries.mdx index 3a299709c..105bd0273 100644 --- a/website/src/pages/docs/data/queries.mdx +++ b/website/src/pages/docs/data/queries.mdx @@ -385,17 +385,15 @@ import { HttpLink } from 'apollo-angular/http'; import { inject } from '@angular/core'; import { InMemoryCache } from '@apollo/client'; -provideApollo( - () => { - return { - link: inject(HttpLink).create({ uri: '/graphql' }), - cache: new InMemoryCache(), - defaultOptions: { - watchQuery: { - notifyOnNetworkStatusChange: false, - }, +provideApollo(() => { + return { + link: inject(HttpLink).create({ uri: '/graphql' }), + cache: new InMemoryCache(), + defaultOptions: { + watchQuery: { + notifyOnNetworkStatusChange: false, }, - }; - } -); + }, + }; +}); ``` From 44ed9a53ae686ec758b70ae08b0002dd8f5d919b Mon Sep 17 00:00:00 2001 From: Adrien Crivelli Date: Fri, 19 Sep 2025 16:59:13 +0900 Subject: [PATCH 91/97] Document namespaced types --- .changeset/chatty-cherries-drum.md | 56 +++++++++++++++++++ .../apollo-angular/http/src/deprecated.ts | 8 --- packages/apollo-angular/http/src/index.ts | 2 - packages/apollo-angular/src/deprecated.ts | 18 ------ packages/apollo-angular/src/index.ts | 2 - 5 files changed, 56 insertions(+), 30 deletions(-) create mode 100644 .changeset/chatty-cherries-drum.md delete mode 100644 packages/apollo-angular/http/src/deprecated.ts delete mode 100644 packages/apollo-angular/src/deprecated.ts diff --git a/.changeset/chatty-cherries-drum.md b/.changeset/chatty-cherries-drum.md new file mode 100644 index 000000000..6291b1455 --- /dev/null +++ b/.changeset/chatty-cherries-drum.md @@ -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; +``` diff --git a/packages/apollo-angular/http/src/deprecated.ts b/packages/apollo-angular/http/src/deprecated.ts deleted file mode 100644 index 1f3cde13a..000000000 --- a/packages/apollo-angular/http/src/deprecated.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { HttpBatchLink } from './http-batch-link'; -import { HttpLink } from './http-link'; - -/** @deprecated Use `HttpLink.Options` instead */ -export type Options = HttpLink.Options; - -/** @deprecated Use `HttpBatchLink.Options` instead */ -export type BatchOptions = HttpBatchLink.Options; diff --git a/packages/apollo-angular/http/src/index.ts b/packages/apollo-angular/http/src/index.ts index 0c51fba14..4c05cd559 100644 --- a/packages/apollo-angular/http/src/index.ts +++ b/packages/apollo-angular/http/src/index.ts @@ -2,5 +2,3 @@ export { HttpLink, HttpLinkHandler } from './http-link'; // http-batch export { HttpBatchLink, HttpBatchLinkHandler } from './http-batch-link'; -// common -export { BatchOptions, Options } from './deprecated'; diff --git a/packages/apollo-angular/src/deprecated.ts b/packages/apollo-angular/src/deprecated.ts deleted file mode 100644 index 759843532..000000000 --- a/packages/apollo-angular/src/deprecated.ts +++ /dev/null @@ -1,18 +0,0 @@ -import type { OperationVariables } from '@apollo/client'; -import type { Apollo } from './apollo'; -import type { EmptyObject } from './types'; - -/** @deprecated Use `Apollo.WatchQueryOptions` instead */ -export type WatchQueryOptions< - TVariables extends OperationVariables = EmptyObject, - TData = unknown, -> = Apollo.WatchQueryOptions; - -/** @deprecated Use `Apollo.MutateOptions` instead */ -export type MutationOptions< - TData = unknown, - TVariables extends OperationVariables = EmptyObject, -> = Apollo.MutateOptions; - -/** @deprecated Use `Apollo.MutateResult` instead */ -export type MutationResult = Apollo.MutateResult; diff --git a/packages/apollo-angular/src/index.ts b/packages/apollo-angular/src/index.ts index 7735c0d08..1fb141f72 100644 --- a/packages/apollo-angular/src/index.ts +++ b/packages/apollo-angular/src/index.ts @@ -8,5 +8,3 @@ export { Subscription } from './subscription'; export { APOLLO_OPTIONS, APOLLO_NAMED_OPTIONS, APOLLO_FLAGS } from './tokens'; export type { Flags, NamedOptions, ResultOf, VariablesOf } from './types'; export { gql } from './gql'; - -export { MutationOptions, MutationResult, WatchQueryOptions } from './deprecated'; From 5239c454f01d25b40566de77a692ced33b486984 Mon Sep 17 00:00:00 2001 From: Adrien Crivelli Date: Fri, 19 Sep 2025 17:25:39 +0900 Subject: [PATCH 92/97] Better flow of types --- .../app/pages/movie/movie-page.component.ts | 22 ++++++++----------- .../app/pages/movies/movies-page.component.ts | 11 +++++----- 2 files changed, 15 insertions(+), 18 deletions(-) diff --git a/packages/demo/src/app/pages/movie/movie-page.component.ts b/packages/demo/src/app/pages/movie/movie-page.component.ts index 73e72a628..813a183a9 100644 --- a/packages/demo/src/app/pages/movie/movie-page.component.ts +++ b/packages/demo/src/app/pages/movie/movie-page.component.ts @@ -2,7 +2,7 @@ import { Apollo, gql } from 'apollo-angular'; import { Observable } from 'rxjs'; import { filter, map } from 'rxjs/operators'; import { AsyncPipe } from '@angular/common'; -import { Component, OnInit } from '@angular/core'; +import { Component, inject, OnInit } from '@angular/core'; import { ActivatedRoute, RouterLink } from '@angular/router'; interface Character { @@ -21,6 +21,10 @@ interface Query { film: Film; } +interface Variables { + id: string; +} + @Component({ selector: 'author-page', template: ` @@ -43,21 +47,13 @@ interface Query { }) export class MoviePageComponent implements OnInit { film$!: Observable; - - constructor( - private readonly apollo: Apollo, - private readonly route: ActivatedRoute, - ) {} + private readonly apollo = inject(Apollo); + private readonly route = inject(ActivatedRoute); ngOnInit() { this.film$ = this.apollo - .watchQuery< - Query, - { - id: string; - } - >({ - query: gql` + .watchQuery({ + query: gql` query FilmCharacters($id: ID) { film(id: $id) { title diff --git a/packages/demo/src/app/pages/movies/movies-page.component.ts b/packages/demo/src/app/pages/movies/movies-page.component.ts index 602b74cb5..e7e3e3e9d 100644 --- a/packages/demo/src/app/pages/movies/movies-page.component.ts +++ b/packages/demo/src/app/pages/movies/movies-page.component.ts @@ -2,7 +2,7 @@ import { Apollo, gql } from 'apollo-angular'; import { Observable } from 'rxjs'; import { filter, map } from 'rxjs/operators'; import { AsyncPipe } from '@angular/common'; -import { Component, OnInit } from '@angular/core'; +import { Component, inject, OnInit } from '@angular/core'; import { RouterLink } from '@angular/router'; interface Film { @@ -16,6 +16,8 @@ interface Query { allFilms: { films: Film[] }; } +type Variables = Record; + @Component({ selector: 'movies-page', template: ` @@ -37,13 +39,12 @@ interface Query { }) export class MoviesPageComponent implements OnInit { films$!: Observable; - - constructor(private readonly apollo: Apollo) {} + private readonly apollo = inject(Apollo); ngOnInit() { this.films$ = this.apollo - .watchQuery({ - query: gql` + .watchQuery({ + query: gql` query AllFilms { allFilms { films { From 226a96337f73be26496a9cfd6682230fd61e7304 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 19 Sep 2025 08:28:07 +0000 Subject: [PATCH 93/97] chore(dependencies): updated changesets for modified dependencies --- .changeset/apollo-angular-2355-dependencies.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changeset/apollo-angular-2355-dependencies.md diff --git a/.changeset/apollo-angular-2355-dependencies.md b/.changeset/apollo-angular-2355-dependencies.md new file mode 100644 index 000000000..0315df00a --- /dev/null +++ b/.changeset/apollo-angular-2355-dependencies.md @@ -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`) From bc4a4941f868211110b420c3b2f8ce46fa015888 Mon Sep 17 00:00:00 2001 From: Adrien Crivelli Date: Mon, 22 Sep 2025 12:06:58 +0900 Subject: [PATCH 94/97] Drop requirement of `esnext.asynciterable` and `allowSyntheticDefaultImports` --- .../schematics/install/index.cts | 94 ------------------- .../schematics/tests/ng-add.spec.cts | 14 --- .../schematics/tsconfig.test.json | 1 - tsconfig.json | 2 +- website/src/pages/docs/get-started.mdx | 12 --- 5 files changed, 1 insertion(+), 122 deletions(-) diff --git a/packages/apollo-angular/schematics/install/index.cts b/packages/apollo-angular/schematics/install/index.cts index ef6937648..998598ad6 100644 --- a/packages/apollo-angular/schematics/install/index.cts +++ b/packages/apollo-angular/schematics/install/index.cts @@ -1,6 +1,4 @@ import { dirname } from 'path'; -import { CompilerOptions } from 'typescript'; -import { tags } from '@angular-devkit/core'; import { apply, chain, @@ -23,8 +21,6 @@ import { Schema } from './schema.cjs'; export function factory(options: Schema): Rule { return chain([ addDependencies(options), - includeAsyncIterableLib(), - allowSyntheticDefaultImports(), addSetupFiles(options), importHttpClient(options), importSetup(options), @@ -71,96 +67,6 @@ function addDependencies(options: Schema): Rule { }; } -function includeAsyncIterableLib(): Rule { - const requiredLib = 'esnext.asynciterable'; - - function updateFn(tsconfig: any): boolean { - const compilerOptions: CompilerOptions = tsconfig.compilerOptions; - - if ( - compilerOptions && - compilerOptions.lib && - !compilerOptions.lib.find(lib => lib.toLowerCase() === requiredLib) - ) { - compilerOptions.lib.push(requiredLib); - return true; - } - - return false; - } - - return (host: Tree) => { - if ( - !updateTSConfig('tsconfig.json', host, updateFn) && - !updateTSConfig('tsconfig.base.json', host, updateFn) - ) { - console.error( - '\n' + - tags.stripIndent` - We couldn't find '${requiredLib}' in the list of library files to be included in the compilation. - It's required by '@apollo/client' package so please add it to your tsconfig. - ` + - '\n', - ); - } - - return host; - }; -} - -function updateTSConfig( - tsconfigPath: string, - host: Tree, - updateFn: (tsconfig: any) => boolean, -): boolean { - try { - const tsconfig = getJsonFile(host, tsconfigPath); - - if (updateFn(tsconfig)) { - host.overwrite(tsconfigPath, JSON.stringify(tsconfig, null, 2)); - - return true; - } - } catch (error) { - // - } - - return false; -} - -function allowSyntheticDefaultImports(): Rule { - function updateFn(tsconfig: any): boolean { - if ( - tsconfig?.compilerOptions && - tsconfig?.compilerOptions?.lib && - !tsconfig.compilerOptions.allowSyntheticDefaultImports - ) { - tsconfig.compilerOptions.allowSyntheticDefaultImports = true; - return true; - } - - return false; - } - - return (host: Tree) => { - if ( - !updateTSConfig('tsconfig.json', host, updateFn) && - !updateTSConfig('tsconfig.base.json', host, updateFn) - ) { - console.error( - '\n' + - tags.stripIndent` - We couldn't enable 'allowSyntheticDefaultImports' flag. - It's required by '@apollo/client' package so please add it to your tsconfig. - ` + - '\n', - ); - } - - return host; - }; -} - function addSetupFiles(options: Schema): Rule { return async (host: Tree) => { const mainPath = await getMainFilePath(host, options.project); diff --git a/packages/apollo-angular/schematics/tests/ng-add.spec.cts b/packages/apollo-angular/schematics/tests/ng-add.spec.cts index a6753b2ce..3cab252a5 100644 --- a/packages/apollo-angular/schematics/tests/ng-add.spec.cts +++ b/packages/apollo-angular/schematics/tests/ng-add.spec.cts @@ -50,13 +50,6 @@ describe('ng-add with module', () => { expect(content).toMatch(/import { HttpClientModule } from '@angular\/common\/http'/); }); - - it('should add esnext.asynciterable to tsconfig.json', async () => { - const config = getJsonFile(tree, '/tsconfig.json'); - const compilerOptions: CompilerOptions = config.compilerOptions; - - expect(compilerOptions.lib).toContain('esnext.asynciterable'); - }); }); describe('ng-add with standalone', () => { @@ -98,11 +91,4 @@ describe('ng-add with standalone', () => { expect(content).toMatch(/import { provideHttpClient } from '@angular\/common\/http'/); }); - - it('should add esnext.asynciterable to tsconfig.json', async () => { - const config = getJsonFile(tree, '/tsconfig.json'); - const compilerOptions: CompilerOptions = config.compilerOptions; - - expect(compilerOptions.lib).toContain('esnext.asynciterable'); - }); }); diff --git a/packages/apollo-angular/schematics/tsconfig.test.json b/packages/apollo-angular/schematics/tsconfig.test.json index f905753d8..0f90cae6b 100644 --- a/packages/apollo-angular/schematics/tsconfig.test.json +++ b/packages/apollo-angular/schematics/tsconfig.test.json @@ -2,7 +2,6 @@ "extends": "./tsconfig.json", "compilerOptions": { "emitDecoratorMetadata": true, - "allowSyntheticDefaultImports": true }, "include": ["tests/*.spec.cts"] } diff --git a/tsconfig.json b/tsconfig.json index 13df0b58d..444aa8379 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -9,7 +9,7 @@ "sourceMap": true, "declaration": true, "outDir": "build", - "lib": ["es6", "dom", "esnext.asynciterable"], + "lib": ["es6", "dom"], "downlevelIteration": true, "experimentalDecorators": true, "noImplicitAny": true, diff --git a/website/src/pages/docs/get-started.mdx b/website/src/pages/docs/get-started.mdx index 3da9670f2..99f018c1b 100644 --- a/website/src/pages/docs/get-started.mdx +++ b/website/src/pages/docs/get-started.mdx @@ -33,18 +33,6 @@ npm i apollo-angular @apollo/client graphql - `apollo-angular`: Bridge between Angular and Apollo Client - `graphql`: Second most important package -The `@apollo/client` package requires `AsyncIterable` so make sure your `tsconfig.json` includes -`ES2020` or later: - -```jsonc filename="tsconfig.json" /"es2020"/ -{ - "compilerOptions": { - // ... - "lib": ["es2020", "dom"], - }, -} -``` - Great, now that you have all the dependencies you need, let's create your first Apollo Client. In `app.config.ts` file, provide Apollo with some options: From e4d49daa31db88c3054c4c1ffa21ef7449731e27 Mon Sep 17 00:00:00 2001 From: Adrien Crivelli Date: Mon, 22 Sep 2025 12:32:35 +0900 Subject: [PATCH 95/97] Modern tsconfig --- .../apollo-angular/schematics/install/index.cts | 4 ++-- packages/apollo-angular/tsconfig.json | 6 ++---- tsconfig.json | 16 ++++++---------- 3 files changed, 10 insertions(+), 16 deletions(-) diff --git a/packages/apollo-angular/schematics/install/index.cts b/packages/apollo-angular/schematics/install/index.cts index 998598ad6..262aa1893 100644 --- a/packages/apollo-angular/schematics/install/index.cts +++ b/packages/apollo-angular/schematics/install/index.cts @@ -112,7 +112,7 @@ function importSetup(options: Schema): Rule { })`; }); } else { - await addModuleImportToRootModule(host, 'GraphQLModule', './graphql.module', options.project); + return addModuleImportToRootModule(host, 'GraphQLModule', './graphql.module', options.project); } }; } @@ -125,7 +125,7 @@ function importHttpClient(options: Schema): Rule { return code`${external('provideHttpClient', '@angular/common/http')}()`; }); } else { - await addModuleImportToRootModule( + return addModuleImportToRootModule( host, 'HttpClientModule', '@angular/common/http', diff --git a/packages/apollo-angular/tsconfig.json b/packages/apollo-angular/tsconfig.json index 1a56cfd7e..ddb43ee39 100644 --- a/packages/apollo-angular/tsconfig.json +++ b/packages/apollo-angular/tsconfig.json @@ -3,10 +3,8 @@ "compilerOptions": { "rootDir": ".", "baseUrl": ".", - "outDir": "build" - }, - "angularCompilerOptions": { - "enableIvy": false + "outDir": "build", + "inlineSources": true }, "include": [ "headers/**/*.ts", diff --git a/tsconfig.json b/tsconfig.json index 444aa8379..77d1bc456 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,27 +2,23 @@ "compileOnSave": false, "compilerOptions": { "target": "ES2022", - "module": "esnext", - "moduleResolution": "node", + "module": "preserve", "importHelpers": true, - "inlineSources": true, "sourceMap": true, "declaration": true, "outDir": "build", - "lib": ["es6", "dom"], - "downlevelIteration": true, "experimentalDecorators": true, - "noImplicitAny": true, + "noImplicitOverride": true, + "noImplicitReturns": true, "noUnusedLocals": true, "noUnusedParameters": true, - "strictNullChecks": true, "strict": true }, "angularCompilerOptions": { - "enableResourceInlining": true, - "fullTemplateTypeCheck": true, - "skipTemplateCodegen": true, "strictInjectionParameters": true, + "strictInputAccessModifiers": true, + "typeCheckHostBindings": true, + "strictTemplates": true, "strictMetadataEmit": true } } From 9d499ac208010db5fdaebcb4ae14b6940c2618be Mon Sep 17 00:00:00 2001 From: Adrien Crivelli Date: Mon, 22 Sep 2025 12:35:18 +0900 Subject: [PATCH 96/97] Prettier --- packages/apollo-angular/schematics/install/index.cts | 9 +++++++-- packages/apollo-angular/schematics/tsconfig.test.json | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/apollo-angular/schematics/install/index.cts b/packages/apollo-angular/schematics/install/index.cts index 262aa1893..e1e54457a 100644 --- a/packages/apollo-angular/schematics/install/index.cts +++ b/packages/apollo-angular/schematics/install/index.cts @@ -112,7 +112,12 @@ function importSetup(options: Schema): Rule { })`; }); } else { - return addModuleImportToRootModule(host, 'GraphQLModule', './graphql.module', options.project); + return addModuleImportToRootModule( + host, + 'GraphQLModule', + './graphql.module', + options.project, + ); } }; } @@ -125,7 +130,7 @@ function importHttpClient(options: Schema): Rule { return code`${external('provideHttpClient', '@angular/common/http')}()`; }); } else { - return addModuleImportToRootModule( + return addModuleImportToRootModule( host, 'HttpClientModule', '@angular/common/http', diff --git a/packages/apollo-angular/schematics/tsconfig.test.json b/packages/apollo-angular/schematics/tsconfig.test.json index 0f90cae6b..914541345 100644 --- a/packages/apollo-angular/schematics/tsconfig.test.json +++ b/packages/apollo-angular/schematics/tsconfig.test.json @@ -1,7 +1,7 @@ { "extends": "./tsconfig.json", "compilerOptions": { - "emitDecoratorMetadata": true, + "emitDecoratorMetadata": true }, "include": ["tests/*.spec.cts"] } From 84d3fb552850c03e10b2a2db9c6c8ac78f124906 Mon Sep 17 00:00:00 2001 From: Adrien Crivelli Date: Mon, 22 Sep 2025 12:38:59 +0900 Subject: [PATCH 97/97] Linting --- packages/apollo-angular/schematics/tests/ng-add.spec.cts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/apollo-angular/schematics/tests/ng-add.spec.cts b/packages/apollo-angular/schematics/tests/ng-add.spec.cts index 3cab252a5..c03d39a67 100644 --- a/packages/apollo-angular/schematics/tests/ng-add.spec.cts +++ b/packages/apollo-angular/schematics/tests/ng-add.spec.cts @@ -1,5 +1,3 @@ - -import {CompilerOptions} from 'typescript'; import {UnitTestTree} from '@angular-devkit/schematics/testing'; import {createDependenciesMap} from '../install/index.cjs'; import {getFileContent, getJsonFile, runNgAdd} from '../utils/index.cjs';