@apollo/client 4.0.0-alpha.18 → 4.0.0-alpha.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +23 -0
- package/__cjs/core/ApolloClient.cjs +3 -1
- package/__cjs/core/ApolloClient.cjs.map +1 -1
- package/__cjs/core/ApolloClient.d.cts +2 -2
- package/__cjs/core/QueryManager.cjs +126 -99
- package/__cjs/core/QueryManager.cjs.map +1 -1
- package/__cjs/core/QueryManager.d.cts +5 -2
- package/__cjs/core/index.cjs.map +1 -1
- package/__cjs/core/index.d.cts +1 -1
- package/__cjs/core/types.d.cts +21 -1
- package/__cjs/invariantErrorCodes.cjs +1 -1
- package/__cjs/react/hooks/useSubscription.cjs +11 -16
- package/__cjs/react/hooks/useSubscription.cjs.map +1 -1
- package/__cjs/utilities/internal/index.cjs +2 -4
- package/__cjs/utilities/internal/index.cjs.map +1 -1
- package/__cjs/utilities/internal/index.d.cts +0 -1
- package/__cjs/version.cjs +1 -1
- package/core/ApolloClient.d.ts +2 -2
- package/core/ApolloClient.js +3 -1
- package/core/ApolloClient.js.map +1 -1
- package/core/QueryManager.d.ts +5 -2
- package/core/QueryManager.js +111 -80
- package/core/QueryManager.js.map +1 -1
- package/core/index.d.ts +1 -1
- package/core/index.js.map +1 -1
- package/core/types.d.ts +21 -1
- package/invariantErrorCodes.js +1 -1
- package/package.json +1 -1
- package/react/hooks/useSubscription.js +11 -16
- package/react/hooks/useSubscription.js.map +1 -1
- package/utilities/internal/index.d.ts +0 -1
- package/utilities/internal/index.js +0 -1
- package/utilities/internal/index.js.map +1 -1
- package/version.js +1 -1
- package/__cjs/utilities/internal/onAnyEvent.cjs +0 -33
- package/__cjs/utilities/internal/onAnyEvent.cjs.map +0 -1
- package/__cjs/utilities/internal/onAnyEvent.d.cts +0 -18
- package/utilities/internal/onAnyEvent.d.ts +0 -18
- package/utilities/internal/onAnyEvent.js +0 -30
- package/utilities/internal/onAnyEvent.js.map +0 -1
package/core/QueryManager.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Trie } from "@wry/trie";
|
|
2
2
|
import { BREAK, Kind, OperationTypeNode, visit } from "graphql";
|
|
3
|
-
import {
|
|
3
|
+
import { Observable } from "rxjs";
|
|
4
|
+
import { catchError, concat, EMPTY, filter, finalize, from, lastValueFrom, map, materialize, mergeMap, mergeWith, of, share, shareReplay, Subject, tap, } from "rxjs";
|
|
4
5
|
import { canonicalStringify } from "@apollo/client/cache";
|
|
5
6
|
import { CombinedGraphQLErrors, graphQLResultHasProtocolErrors, registerLinkError, toErrorLike, } from "@apollo/client/errors";
|
|
6
7
|
import { PROTOCOL_ERRORS_SYMBOL } from "@apollo/client/errors";
|
|
@@ -8,7 +9,7 @@ import { execute } from "@apollo/client/link";
|
|
|
8
9
|
import { maskFragment, maskOperation } from "@apollo/client/masking";
|
|
9
10
|
import { cacheSizes, DocumentTransform, print } from "@apollo/client/utilities";
|
|
10
11
|
import { __DEV__ } from "@apollo/client/utilities/environment";
|
|
11
|
-
import { AutoCleanedWeakCache, checkDocument, filterMap, getDefaultValues, getGraphQLErrorsFromResult, getOperationDefinition, getOperationName, graphQLResultHasError, hasDirectives, hasForcedResolvers, isDocumentNode, isExecutionPatchIncrementalResult, isExecutionPatchResult, isNonEmptyArray, isNonNullObject, makeUniqueId, mergeIncrementalData,
|
|
12
|
+
import { AutoCleanedWeakCache, checkDocument, filterMap, getDefaultValues, getGraphQLErrorsFromResult, getOperationDefinition, getOperationName, graphQLResultHasError, hasDirectives, hasForcedResolvers, isDocumentNode, isExecutionPatchIncrementalResult, isExecutionPatchResult, isNonEmptyArray, isNonNullObject, makeUniqueId, mergeIncrementalData, removeDirectivesFromDocument, toQueryResult, } from "@apollo/client/utilities/internal";
|
|
12
13
|
import { invariant, newInvariantError, } from "@apollo/client/utilities/invariant";
|
|
13
14
|
import { isNetworkRequestInFlight, NetworkStatus } from "./networkStatus.js";
|
|
14
15
|
import { logMissingFieldErrors, ObservableQuery } from "./ObservableQuery.js";
|
|
@@ -139,7 +140,7 @@ export class QueryManager {
|
|
|
139
140
|
...context,
|
|
140
141
|
optimisticResponse: isOptimistic ? optimisticResponse : void 0,
|
|
141
142
|
}, variables, {}, false)
|
|
142
|
-
.pipe(validateDidEmitValue(), mergeMap((result) => {
|
|
143
|
+
.observable.pipe(validateDidEmitValue(), mergeMap((result) => {
|
|
143
144
|
const hasErrors = graphQLResultHasError(result);
|
|
144
145
|
if (hasErrors && errorPolicy === "none") {
|
|
145
146
|
throw new CombinedGraphQLErrors(result);
|
|
@@ -428,6 +429,7 @@ export class QueryManager {
|
|
|
428
429
|
getDocumentInfo(document) {
|
|
429
430
|
const { transformCache } = this;
|
|
430
431
|
if (!transformCache.has(document)) {
|
|
432
|
+
const operationDefinition = getOperationDefinition(document);
|
|
431
433
|
const cacheEntry = {
|
|
432
434
|
// TODO These three calls (hasClientExports, shouldForceResolvers, and
|
|
433
435
|
// usesNonreactiveDirective) are performing independent full traversals
|
|
@@ -445,7 +447,8 @@ export class QueryManager {
|
|
|
445
447
|
{ name: "nonreactive" },
|
|
446
448
|
{ name: "unmask" },
|
|
447
449
|
], document),
|
|
448
|
-
|
|
450
|
+
operationType: operationDefinition?.operation,
|
|
451
|
+
defaultVars: getDefaultValues(operationDefinition),
|
|
449
452
|
// Transform any mutation or subscription operations to query operations
|
|
450
453
|
// so we can read/write them from/to the cache.
|
|
451
454
|
asQuery: {
|
|
@@ -649,65 +652,68 @@ export class QueryManager {
|
|
|
649
652
|
checkDocument(query, OperationTypeNode.SUBSCRIPTION);
|
|
650
653
|
query = this.transform(query);
|
|
651
654
|
variables = this.getVariables(query, variables);
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
});
|
|
663
|
-
}
|
|
664
|
-
this.broadcastQueries();
|
|
665
|
-
}
|
|
666
|
-
const result = {
|
|
667
|
-
data: rawResult.data ?? undefined,
|
|
668
|
-
};
|
|
669
|
-
if (graphQLResultHasError(rawResult)) {
|
|
670
|
-
result.error = new CombinedGraphQLErrors(rawResult);
|
|
671
|
-
}
|
|
672
|
-
else if (graphQLResultHasProtocolErrors(rawResult)) {
|
|
673
|
-
result.error = rawResult.extensions[PROTOCOL_ERRORS_SYMBOL];
|
|
674
|
-
// Don't emit protocol errors added by HttpLink
|
|
675
|
-
delete rawResult.extensions[PROTOCOL_ERRORS_SYMBOL];
|
|
676
|
-
}
|
|
677
|
-
if (rawResult.extensions &&
|
|
678
|
-
Object.keys(rawResult.extensions).length) {
|
|
679
|
-
result.extensions = rawResult.extensions;
|
|
680
|
-
}
|
|
681
|
-
if (result.error && errorPolicy === "none") {
|
|
682
|
-
result.data = undefined;
|
|
683
|
-
}
|
|
684
|
-
if (errorPolicy === "ignore") {
|
|
685
|
-
delete result.error;
|
|
686
|
-
}
|
|
687
|
-
return result;
|
|
688
|
-
}), catchError((error) => {
|
|
689
|
-
if (errorPolicy === "ignore") {
|
|
690
|
-
return of({ data: undefined });
|
|
691
|
-
}
|
|
692
|
-
return of({ data: undefined, error });
|
|
693
|
-
}), filter((result) => !!(result.data || result.error)));
|
|
694
|
-
if (this.getDocumentInfo(query).hasClientExports) {
|
|
695
|
-
if (__DEV__) {
|
|
696
|
-
invariant(this.localState, 89, getOperationName(query, "(anonymous)"));
|
|
697
|
-
}
|
|
698
|
-
const observablePromise = this.localState.getExportedVariables({
|
|
655
|
+
let restart;
|
|
656
|
+
if (__DEV__) {
|
|
657
|
+
invariant(
|
|
658
|
+
!this.getDocumentInfo(query).hasClientExports || this.localState,
|
|
659
|
+
89,
|
|
660
|
+
getOperationName(query, "(anonymous)")
|
|
661
|
+
);
|
|
662
|
+
}
|
|
663
|
+
const observable = (this.getDocumentInfo(query).hasClientExports ?
|
|
664
|
+
from(this.localState.getExportedVariables({
|
|
699
665
|
client: this.client,
|
|
700
666
|
document: query,
|
|
701
667
|
variables,
|
|
702
668
|
context,
|
|
703
|
-
})
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
669
|
+
}))
|
|
670
|
+
: of(variables)).pipe(mergeMap((variables) => {
|
|
671
|
+
const { observable, restart: res } = this.getObservableFromLink(query, context, variables, extensions);
|
|
672
|
+
restart = res;
|
|
673
|
+
return observable.pipe(map((rawResult) => {
|
|
674
|
+
if (fetchPolicy !== "no-cache") {
|
|
675
|
+
// the subscription interface should handle not sending us results we no longer subscribe to.
|
|
676
|
+
// XXX I don't think we ever send in an object with errors, but we might in the future...
|
|
677
|
+
if (shouldWriteResult(rawResult, errorPolicy)) {
|
|
678
|
+
this.cache.write({
|
|
679
|
+
query,
|
|
680
|
+
result: rawResult.data,
|
|
681
|
+
dataId: "ROOT_SUBSCRIPTION",
|
|
682
|
+
variables: variables,
|
|
683
|
+
});
|
|
684
|
+
}
|
|
685
|
+
this.broadcastQueries();
|
|
686
|
+
}
|
|
687
|
+
const result = {
|
|
688
|
+
data: rawResult.data ?? undefined,
|
|
689
|
+
};
|
|
690
|
+
if (graphQLResultHasError(rawResult)) {
|
|
691
|
+
result.error = new CombinedGraphQLErrors(rawResult);
|
|
692
|
+
}
|
|
693
|
+
else if (graphQLResultHasProtocolErrors(rawResult)) {
|
|
694
|
+
result.error = rawResult.extensions[PROTOCOL_ERRORS_SYMBOL];
|
|
695
|
+
// Don't emit protocol errors added by HttpLink
|
|
696
|
+
delete rawResult.extensions[PROTOCOL_ERRORS_SYMBOL];
|
|
697
|
+
}
|
|
698
|
+
if (rawResult.extensions &&
|
|
699
|
+
Object.keys(rawResult.extensions).length) {
|
|
700
|
+
result.extensions = rawResult.extensions;
|
|
701
|
+
}
|
|
702
|
+
if (result.error && errorPolicy === "none") {
|
|
703
|
+
result.data = undefined;
|
|
704
|
+
}
|
|
705
|
+
if (errorPolicy === "ignore") {
|
|
706
|
+
delete result.error;
|
|
707
|
+
}
|
|
708
|
+
return result;
|
|
709
|
+
}), catchError((error) => {
|
|
710
|
+
if (errorPolicy === "ignore") {
|
|
711
|
+
return of({ data: undefined });
|
|
712
|
+
}
|
|
713
|
+
return of({ data: undefined, error });
|
|
714
|
+
}), filter((result) => !!(result.data || result.error)));
|
|
715
|
+
}));
|
|
716
|
+
return Object.assign(observable, { restart: () => restart?.() });
|
|
711
717
|
}
|
|
712
718
|
removeQuery(queryId) {
|
|
713
719
|
// teardown all links
|
|
@@ -738,8 +744,8 @@ export class QueryManager {
|
|
|
738
744
|
// Prefer context.queryDeduplication if specified.
|
|
739
745
|
deduplication = context?.queryDeduplication ??
|
|
740
746
|
this.queryDeduplication) {
|
|
741
|
-
let
|
|
742
|
-
const { serverQuery, clientQuery } = this.getDocumentInfo(query);
|
|
747
|
+
let entry = {};
|
|
748
|
+
const { serverQuery, clientQuery, operationType } = this.getDocumentInfo(query);
|
|
743
749
|
const operationName = getOperationName(query);
|
|
744
750
|
const executeContext = {
|
|
745
751
|
client: this.client,
|
|
@@ -759,29 +765,51 @@ export class QueryManager {
|
|
|
759
765
|
extensions,
|
|
760
766
|
};
|
|
761
767
|
context = operation.context;
|
|
768
|
+
function withRestart(source) {
|
|
769
|
+
return new Observable((observer) => {
|
|
770
|
+
function subscribe() {
|
|
771
|
+
return source.subscribe({
|
|
772
|
+
next: observer.next.bind(observer),
|
|
773
|
+
complete: observer.complete.bind(observer),
|
|
774
|
+
error: observer.error.bind(observer),
|
|
775
|
+
});
|
|
776
|
+
}
|
|
777
|
+
let subscription = subscribe();
|
|
778
|
+
entry.restart ||= () => {
|
|
779
|
+
subscription.unsubscribe();
|
|
780
|
+
subscription = subscribe();
|
|
781
|
+
};
|
|
782
|
+
return () => {
|
|
783
|
+
subscription.unsubscribe();
|
|
784
|
+
entry.restart = undefined;
|
|
785
|
+
};
|
|
786
|
+
});
|
|
787
|
+
}
|
|
762
788
|
if (deduplication) {
|
|
763
789
|
const printedServerQuery = print(serverQuery);
|
|
764
790
|
const varJson = canonicalStringify(variables);
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
!("hasNext" in event.value) ||
|
|
771
|
-
!event.value.hasNext) &&
|
|
772
|
-
inFlightLinkObservables.peek(printedServerQuery, varJson) ===
|
|
773
|
-
entry) {
|
|
791
|
+
entry = inFlightLinkObservables.lookup(printedServerQuery, varJson);
|
|
792
|
+
if (!entry.observable) {
|
|
793
|
+
entry.observable = execute(link, operation, executeContext).pipe(withRestart, finalize(() => {
|
|
794
|
+
if (inFlightLinkObservables.peek(printedServerQuery, varJson) ===
|
|
795
|
+
entry) {
|
|
774
796
|
inFlightLinkObservables.remove(printedServerQuery, varJson);
|
|
775
797
|
}
|
|
776
|
-
}),
|
|
798
|
+
}),
|
|
799
|
+
// We don't want to replay the last emitted value for
|
|
800
|
+
// subscriptions and instead opt to wait to receive updates until
|
|
801
|
+
// the subscription emits new values.
|
|
802
|
+
operationType === OperationTypeNode.SUBSCRIPTION ?
|
|
803
|
+
share()
|
|
804
|
+
: shareReplay({ refCount: true }));
|
|
777
805
|
}
|
|
778
806
|
}
|
|
779
807
|
else {
|
|
780
|
-
observable = execute(link, operation, executeContext);
|
|
808
|
+
entry.observable = execute(link, operation, executeContext).pipe(withRestart);
|
|
781
809
|
}
|
|
782
810
|
}
|
|
783
811
|
else {
|
|
784
|
-
observable = of({ data: {} });
|
|
812
|
+
entry.observable = of({ data: {} });
|
|
785
813
|
}
|
|
786
814
|
if (clientQuery) {
|
|
787
815
|
if (__DEV__) {
|
|
@@ -793,7 +821,7 @@ export class QueryManager {
|
|
|
793
821
|
operationName ?? "(anonymous)"
|
|
794
822
|
);
|
|
795
823
|
}
|
|
796
|
-
observable = observable.pipe(mergeMap((result) => {
|
|
824
|
+
entry.observable = entry.observable.pipe(mergeMap((result) => {
|
|
797
825
|
return from(this.localState.execute({
|
|
798
826
|
client: this.client,
|
|
799
827
|
document: clientQuery,
|
|
@@ -803,11 +831,14 @@ export class QueryManager {
|
|
|
803
831
|
}));
|
|
804
832
|
}));
|
|
805
833
|
}
|
|
806
|
-
return
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
834
|
+
return {
|
|
835
|
+
restart: () => entry.restart?.(),
|
|
836
|
+
observable: entry.observable.pipe(catchError((error) => {
|
|
837
|
+
error = toErrorLike(error);
|
|
838
|
+
registerLinkError(error);
|
|
839
|
+
throw error;
|
|
840
|
+
})),
|
|
841
|
+
};
|
|
811
842
|
}
|
|
812
843
|
getResultsFromLink(queryInfo, cacheWriteBehavior, options) {
|
|
813
844
|
const requestId = (queryInfo.lastRequestId = this.generateRequestId());
|
|
@@ -816,7 +847,7 @@ export class QueryManager {
|
|
|
816
847
|
// missing fragment definitions (for example) before sending this document
|
|
817
848
|
// through the link chain.
|
|
818
849
|
const linkDocument = this.cache.transformForLink(options.query);
|
|
819
|
-
return this.getObservableFromLink(linkDocument, options.context, options.variables).pipe(map((result) => {
|
|
850
|
+
return this.getObservableFromLink(linkDocument, options.context, options.variables).observable.pipe(map((result) => {
|
|
820
851
|
const graphQLErrors = getGraphQLErrorsFromResult(result);
|
|
821
852
|
const hasErrors = graphQLErrors.length > 0;
|
|
822
853
|
// If we interrupted this request by calling getResultsFromLink again
|