@apollo/client 4.0.0-alpha.19 → 4.0.0-alpha.20

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.
Files changed (50) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/__cjs/core/ApolloClient.cjs +2 -2
  3. package/__cjs/core/ApolloClient.cjs.map +1 -1
  4. package/__cjs/core/ApolloClient.d.cts +1 -1
  5. package/__cjs/core/ObservableQuery.cjs +51 -45
  6. package/__cjs/core/ObservableQuery.cjs.map +1 -1
  7. package/__cjs/core/ObservableQuery.d.cts +16 -16
  8. package/__cjs/core/QueryInfo.cjs +27 -31
  9. package/__cjs/core/QueryInfo.cjs.map +1 -1
  10. package/__cjs/core/QueryInfo.d.cts +23 -6
  11. package/__cjs/core/QueryManager.cjs +66 -121
  12. package/__cjs/core/QueryManager.cjs.map +1 -1
  13. package/__cjs/core/QueryManager.d.cts +14 -8
  14. package/__cjs/react/hooks/useQuery.cjs +1 -1
  15. package/__cjs/react/hooks/useQuery.cjs.map +1 -1
  16. package/__cjs/react/hooks/useQuery.d.cts +2 -2
  17. package/__cjs/react/internal/cache/FragmentReference.cjs +4 -1
  18. package/__cjs/react/internal/cache/FragmentReference.cjs.map +1 -1
  19. package/__cjs/react/internal/cache/QueryReference.cjs +5 -18
  20. package/__cjs/react/internal/cache/QueryReference.cjs.map +1 -1
  21. package/__cjs/react/internal/cache/QueryReference.d.cts +6 -43
  22. package/__cjs/react/query-preloader/createQueryPreloader.cjs +8 -2
  23. package/__cjs/react/query-preloader/createQueryPreloader.cjs.map +1 -1
  24. package/__cjs/react/query-preloader/createQueryPreloader.d.cts +38 -0
  25. package/__cjs/version.cjs +1 -1
  26. package/core/ApolloClient.d.ts +1 -1
  27. package/core/ApolloClient.js +2 -2
  28. package/core/ApolloClient.js.map +1 -1
  29. package/core/ObservableQuery.d.ts +16 -16
  30. package/core/ObservableQuery.js +51 -45
  31. package/core/ObservableQuery.js.map +1 -1
  32. package/core/QueryInfo.d.ts +23 -6
  33. package/core/QueryInfo.js +27 -31
  34. package/core/QueryInfo.js.map +1 -1
  35. package/core/QueryManager.d.ts +14 -8
  36. package/core/QueryManager.js +67 -122
  37. package/core/QueryManager.js.map +1 -1
  38. package/package.json +1 -1
  39. package/react/hooks/useQuery.d.ts +2 -2
  40. package/react/hooks/useQuery.js +2 -2
  41. package/react/hooks/useQuery.js.map +1 -1
  42. package/react/internal/cache/FragmentReference.js +4 -1
  43. package/react/internal/cache/FragmentReference.js.map +1 -1
  44. package/react/internal/cache/QueryReference.d.ts +6 -43
  45. package/react/internal/cache/QueryReference.js +5 -18
  46. package/react/internal/cache/QueryReference.js.map +1 -1
  47. package/react/query-preloader/createQueryPreloader.d.ts +38 -0
  48. package/react/query-preloader/createQueryPreloader.js +9 -3
  49. package/react/query-preloader/createQueryPreloader.js.map +1 -1
  50. package/version.js +1 -1
@@ -47,9 +47,10 @@ class QueryManager {
47
47
  prioritizeCacheValues = false;
48
48
  onBroadcast;
49
49
  mutationStore;
50
- // All the queries that the QueryManager is currently managing (not
51
- // including mutations and subscriptions).
52
- queries = new Map();
50
+ /**
51
+ * All ObservableQueries that currently have at least one subscriber.
52
+ */
53
+ obsQueries = new Set();
53
54
  // Maps from queryId strings to Promise rejection functions for
54
55
  // currently active queries and fetches.
55
56
  // Use protected instead of private field so
@@ -94,9 +95,7 @@ class QueryManager {
94
95
  * to dispose of this QueryManager instance.
95
96
  */
96
97
  stop() {
97
- this.queries.forEach((_info, queryId) => {
98
- this.removeQuery(queryId);
99
- });
98
+ this.obsQueries.forEach((oq) => oq.stop());
100
99
  this.cancelPendingFetches((0, invariant_1.newInvariantError)(82));
101
100
  }
102
101
  cancelPendingFetches(error) {
@@ -147,6 +146,7 @@ class QueryManager {
147
146
  });
148
147
  this.broadcastQueries();
149
148
  return new Promise((resolve, reject) => {
149
+ const cause = {};
150
150
  return this.getObservableFromLink(mutation, {
151
151
  ...context,
152
152
  optimisticResponse: isOptimistic ? optimisticResponse : void 0,
@@ -198,7 +198,7 @@ class QueryManager {
198
198
  document: mutation,
199
199
  data: storeResult.data,
200
200
  fetchPolicy,
201
- id: mutationId,
201
+ cause,
202
202
  }),
203
203
  };
204
204
  if ((0, internal_1.graphQLResultHasError)(storeResult)) {
@@ -273,20 +273,15 @@ class QueryManager {
273
273
  }
274
274
  const { updateQueries } = mutation;
275
275
  if (updateQueries) {
276
- this.queries.forEach(({ observableQuery }, queryId) => {
276
+ this.obsQueries.forEach((observableQuery) => {
277
277
  const queryName = observableQuery && observableQuery.queryName;
278
278
  if (!queryName || !hasOwnProperty.call(updateQueries, queryName)) {
279
279
  return;
280
280
  }
281
281
  const updater = updateQueries[queryName];
282
- const { document, variables } = this.queries.get(queryId);
282
+ const { query: document, variables } = observableQuery;
283
283
  // Read the current query result from the store.
284
- const { result: currentQueryResult, complete } = cache.diff({
285
- query: document,
286
- variables,
287
- returnPartialData: true,
288
- optimistic: false,
289
- });
284
+ const { result: currentQueryResult, complete } = observableQuery.getCacheDiff({ optimistic: false });
290
285
  if (complete && currentQueryResult) {
291
286
  // Run our reducer using the current query result and the mutation result.
292
287
  const nextQueryResult = updater(currentQueryResult, {
@@ -414,8 +409,11 @@ class QueryManager {
414
409
  }, mutation.mutationId);
415
410
  return true;
416
411
  }
417
- fetchQuery(queryId, options, networkStatus) {
418
- return (0, rxjs_2.lastValueFrom)(this.fetchObservableWithInfo(this.getOrCreateQuery(queryId), options, {
412
+ fetchQuery(options, networkStatus) {
413
+ const queryInfo = new QueryInfo_js_1.QueryInfo({
414
+ queryManager: this,
415
+ });
416
+ return (0, rxjs_2.lastValueFrom)(this.fetchObservableWithInfo(queryInfo, options, {
419
417
  networkStatus,
420
418
  }).observable.pipe((0, internal_1.filterMap)((value) => {
421
419
  switch (value.kind) {
@@ -498,38 +496,26 @@ class QueryManager {
498
496
  if (typeof options.notifyOnNetworkStatusChange === "undefined") {
499
497
  options.notifyOnNetworkStatusChange = true;
500
498
  }
501
- const queryInfo = new QueryInfo_js_1.QueryInfo(this);
502
499
  const observable = new ObservableQuery_js_1.ObservableQuery({
503
500
  queryManager: this,
504
- queryInfo,
505
501
  options,
502
+ transformedQuery: query,
506
503
  });
507
- observable["lastQuery"] = query;
508
- if (!ObservableQuery_js_1.ObservableQuery["inactiveOnCreation"].getValue()) {
509
- this.queries.set(observable.queryId, queryInfo);
510
- }
511
- // We give queryInfo the transformed query to ensure the first cache diff
512
- // uses the transformed query instead of the raw query
513
- queryInfo.init({ document: query, variables: observable.variables });
514
- queryInfo.setObservableQuery(observable);
515
504
  return observable;
516
505
  }
517
- async query(options, queryId = this.generateQueryId()) {
506
+ async query(options) {
518
507
  const query = this.transform(options.query);
519
- return this.fetchQuery(queryId, {
508
+ return this.fetchQuery({
520
509
  ...options,
521
510
  query,
522
- })
523
- .then((value) => ({
511
+ }).then((value) => ({
524
512
  ...value,
525
513
  data: this.maskOperation({
526
514
  document: query,
527
515
  data: value?.data,
528
516
  fetchPolicy: options.fetchPolicy,
529
- id: queryId,
530
517
  }),
531
- }))
532
- .finally(() => this.removeQuery(queryId));
518
+ }));
533
519
  }
534
520
  queryIdCounter = 1;
535
521
  generateQueryId() {
@@ -552,10 +538,10 @@ class QueryManager {
552
538
  // store. So, we cancel the promises and observers that we have issued
553
539
  // so far and not yet resolved (in the case of queries).
554
540
  this.cancelPendingFetches((0, invariant_1.newInvariantError)(86));
555
- this.queries.forEach(({ observableQuery }) => {
541
+ this.obsQueries.forEach((observableQuery) => {
556
542
  // Set loading to true so listeners don't trigger unless they want
557
543
  // results with partial data.
558
- observableQuery?.reset();
544
+ observableQuery.reset();
559
545
  });
560
546
  if (this.mutationStore) {
561
547
  this.mutationStore = {};
@@ -564,7 +550,7 @@ class QueryManager {
564
550
  return this.cache.reset(options);
565
551
  }
566
552
  getObservableQueries(include = "active") {
567
- const queries = new Map();
553
+ const queries = new Set();
568
554
  const queryNames = new Map();
569
555
  const queryNamesAndQueryStrings = new Map();
570
556
  const legacyQueryOptions = new Set();
@@ -584,49 +570,36 @@ class QueryManager {
584
570
  }
585
571
  });
586
572
  }
587
- this.queries.forEach(({ observableQuery: oq, document }, queryId) => {
588
- if (oq) {
589
- if (include === "all") {
590
- queries.set(queryId, oq);
591
- return;
592
- }
593
- const { queryName, options: { fetchPolicy }, } = oq;
594
- if (fetchPolicy === "standby" ||
595
- (include === "active" && !oq.hasObservers())) {
596
- return;
597
- }
598
- if (include === "active" ||
599
- (queryName && queryNamesAndQueryStrings.has(queryName)) ||
600
- (document && queryNamesAndQueryStrings.has((0, utilities_1.print)(document)))) {
601
- queries.set(queryId, oq);
602
- if (queryName)
603
- queryNamesAndQueryStrings.set(queryName, true);
604
- if (document)
605
- queryNamesAndQueryStrings.set((0, utilities_1.print)(document), true);
606
- }
573
+ this.obsQueries.forEach((oq) => {
574
+ const document = (0, utilities_1.print)(this.transform(oq.options.query));
575
+ if (include === "all") {
576
+ queries.add(oq);
577
+ return;
578
+ }
579
+ const { queryName, options: { fetchPolicy }, } = oq;
580
+ if (include === "active" && fetchPolicy === "standby") {
581
+ return;
582
+ }
583
+ if (include === "active" ||
584
+ (queryName && queryNamesAndQueryStrings.has(queryName)) ||
585
+ (document && queryNamesAndQueryStrings.has(document))) {
586
+ queries.add(oq);
587
+ if (queryName)
588
+ queryNamesAndQueryStrings.set(queryName, true);
589
+ if (document)
590
+ queryNamesAndQueryStrings.set(document, true);
607
591
  }
608
592
  });
609
593
  if (legacyQueryOptions.size) {
610
594
  legacyQueryOptions.forEach((options) => {
611
- // We will be issuing a fresh network request for this query, so we
612
- // pre-allocate a new query ID here, using a special prefix to enable
613
- // cleaning up these temporary queries later, after fetching.
614
- const queryId = (0, internal_1.makeUniqueId)("legacyOneTimeQuery");
615
- const queryInfo = this.getOrCreateQuery(queryId).init({
616
- document: options.query,
617
- variables: options.variables,
618
- });
619
595
  const oq = new ObservableQuery_js_1.ObservableQuery({
620
596
  queryManager: this,
621
- queryInfo,
622
597
  options: {
623
598
  ...options,
624
599
  fetchPolicy: "network-only",
625
600
  },
626
601
  });
627
- (0, invariant_1.invariant)(oq.queryId === queryId);
628
- queryInfo.setObservableQuery(oq);
629
- queries.set(queryId, oq);
602
+ queries.add(oq);
630
603
  });
631
604
  }
632
605
  if (environment_1.__DEV__ && queryNamesAndQueryStrings.size) {
@@ -646,13 +619,12 @@ class QueryManager {
646
619
  }
647
620
  refetchObservableQueries(includeStandby = false) {
648
621
  const observableQueryPromises = [];
649
- this.getObservableQueries(includeStandby ? "all" : "active").forEach((observableQuery, queryId) => {
622
+ this.getObservableQueries(includeStandby ? "all" : "active").forEach((observableQuery) => {
650
623
  const { fetchPolicy } = observableQuery.options;
651
624
  if (includeStandby ||
652
625
  (fetchPolicy !== "standby" && fetchPolicy !== "cache-only")) {
653
626
  observableQueryPromises.push(observableQuery.refetch());
654
627
  }
655
- (this.queries.get(queryId) || observableQuery["queryInfo"]).resetDiff();
656
628
  });
657
629
  this.broadcastQueries();
658
630
  return Promise.all(observableQueryPromises);
@@ -726,27 +698,10 @@ class QueryManager {
726
698
  }));
727
699
  return Object.assign(observable, { restart: () => restart?.() });
728
700
  }
729
- removeQuery(queryId) {
730
- // teardown all links
731
- // Both `QueryManager.fetchRequest` and `QueryManager.query` create separate promises
732
- // that each add their reject functions to fetchCancelFns.
733
- // A query created with `QueryManager.query()` could trigger a `QueryManager.fetchRequest`.
734
- // The same queryId could have two rejection fns for two promises
735
- this.fetchCancelFns.delete(queryId);
736
- if (this.queries.has(queryId)) {
737
- const oq = this.queries.get(queryId).observableQuery;
738
- if (oq) {
739
- oq["resetNotifications"]();
740
- oq["unsubscribeFromCache"]?.();
741
- oq.stopPolling();
742
- }
743
- this.queries.delete(queryId);
744
- }
745
- }
746
701
  broadcastQueries() {
747
702
  if (this.onBroadcast)
748
703
  this.onBroadcast();
749
- this.queries.forEach((info) => info.observableQuery?.notify());
704
+ this.obsQueries.forEach((observableQuery) => observableQuery.notify());
750
705
  }
751
706
  // Use protected instead of private field so
752
707
  // @apollo/experimental-nextjs-app-support can access type info.
@@ -972,10 +927,6 @@ class QueryManager {
972
927
  // in case concast creation synchronously cancels the request.
973
928
  const cleanupCancelFn = () => {
974
929
  this.fetchCancelFns.delete(queryInfo.queryId);
975
- // We need to call `complete` on the subject here otherwise the merged
976
- // observable will never complete since it waits for all source
977
- // observables to complete before itself completes.
978
- fetchCancelSubject.complete();
979
930
  };
980
931
  this.fetchCancelFns.set(queryInfo.queryId, (error) => {
981
932
  fetchCancelSubject.next({
@@ -983,8 +934,6 @@ class QueryManager {
983
934
  error,
984
935
  source: "network",
985
936
  });
986
- fetchCancelSubject.complete();
987
- cleanupCancelFn();
988
937
  });
989
938
  const fetchCancelSubject = new rxjs_2.Subject();
990
939
  let observable, containsDataFromLink;
@@ -1022,16 +971,22 @@ class QueryManager {
1022
971
  observable = sourcesWithInfo.observable;
1023
972
  }
1024
973
  return {
1025
- observable: observable.pipe((0, rxjs_2.tap)({ error: cleanupCancelFn, complete: cleanupCancelFn }), (0, rxjs_2.mergeWith)(fetchCancelSubject), (0, rxjs_2.share)()),
974
+ // Merge `observable` with `fetchCancelSubject`, in a way that completing or
975
+ // erroring either of them will complete the merged obserable.
976
+ observable: new rxjs_1.Observable((observer) => {
977
+ observer.add(cleanupCancelFn);
978
+ observable.subscribe(observer);
979
+ fetchCancelSubject.subscribe(observer);
980
+ }).pipe((0, rxjs_2.share)()),
1026
981
  fromLink: containsDataFromLink,
1027
982
  };
1028
983
  }
1029
984
  refetchQueries({ updateCache, include, optimistic = false, removeOptimistic = optimistic ? (0, internal_1.makeUniqueId)("refetchQueries") : void 0, onQueryUpdated, }) {
1030
- const includedQueriesById = new Map();
985
+ const includedQueriesByOq = new Map();
1031
986
  if (include) {
1032
- this.getObservableQueries(include).forEach((oq, queryId) => {
987
+ this.getObservableQueries(include).forEach((oq) => {
1033
988
  const current = oq.getCurrentResult();
1034
- includedQueriesById.set(queryId, {
989
+ includedQueriesByOq.set(oq, {
1035
990
  oq,
1036
991
  lastDiff: {
1037
992
  result: current?.data,
@@ -1085,13 +1040,13 @@ class QueryManager {
1085
1040
  removeOptimistic,
1086
1041
  onWatchUpdated(watch, diff, lastDiff) {
1087
1042
  const oq = watch.watcher;
1088
- if (oq instanceof ObservableQuery_js_1.ObservableQuery) {
1089
- if (onQueryUpdated && !handled.has(oq)) {
1090
- handled.add(oq);
1043
+ if (oq instanceof ObservableQuery_js_1.ObservableQuery && !handled.has(oq)) {
1044
+ handled.add(oq);
1045
+ if (onQueryUpdated) {
1091
1046
  // Since we're about to handle this query now, remove it from
1092
1047
  // includedQueriesById, in case it was added earlier because of
1093
1048
  // options.include.
1094
- includedQueriesById.delete(oq.queryId);
1049
+ includedQueriesByOq.delete(oq);
1095
1050
  let result = onQueryUpdated(oq, diff, lastDiff);
1096
1051
  if (result === true) {
1097
1052
  // The onQueryUpdated function requested the default refetching
@@ -1113,20 +1068,20 @@ class QueryManager {
1113
1068
  // If we don't have an onQueryUpdated function, and onQueryUpdated
1114
1069
  // was not disabled by passing null, make sure this query is
1115
1070
  // "included" like any other options.include-specified query.
1116
- includedQueriesById.set(oq.queryId, { oq, lastDiff, diff });
1071
+ includedQueriesByOq.set(oq, { oq, lastDiff, diff });
1117
1072
  }
1118
1073
  }
1119
1074
  },
1120
1075
  });
1121
1076
  }
1122
- if (includedQueriesById.size) {
1123
- includedQueriesById.forEach(({ oq, lastDiff, diff }, queryId) => {
1077
+ if (includedQueriesByOq.size) {
1078
+ includedQueriesByOq.forEach(({ oq, lastDiff, diff }) => {
1124
1079
  let result;
1125
1080
  // If onQueryUpdated is provided, we want to use it for all included
1126
1081
  // queries, even the QueryOptions ones.
1127
1082
  if (onQueryUpdated) {
1128
1083
  if (!diff) {
1129
- diff = this.cache.diff(oq["queryInfo"].getDiffOptions());
1084
+ diff = oq.getCacheDiff();
1130
1085
  }
1131
1086
  result = onQueryUpdated(oq, diff, lastDiff);
1132
1087
  }
@@ -1139,9 +1094,6 @@ class QueryManager {
1139
1094
  if (result !== false) {
1140
1095
  results.set(oq, result);
1141
1096
  }
1142
- if (queryId.indexOf("legacyOneTimeQuery") >= 0) {
1143
- this.removeQuery(queryId);
1144
- }
1145
1097
  });
1146
1098
  }
1147
1099
  if (removeOptimistic) {
@@ -1156,18 +1108,17 @@ class QueryManager {
1156
1108
  }
1157
1109
  return results;
1158
1110
  }
1159
- noCacheWarningsByQueryId = new Set();
1111
+ noCacheWarningsByCause = new WeakSet();
1160
1112
  maskOperation(options) {
1161
1113
  const { document, data } = options;
1162
1114
  if (environment_1.__DEV__) {
1163
- const { fetchPolicy, id } = options;
1115
+ const { fetchPolicy, cause = {} } = options;
1164
1116
  const operationType = (0, internal_1.getOperationDefinition)(document)?.operation;
1165
- const operationId = (operationType?.[0] ?? "o") + id;
1166
1117
  if (this.dataMasking &&
1167
1118
  fetchPolicy === "no-cache" &&
1168
1119
  !isFullyUnmaskedOperation(document) &&
1169
- !this.noCacheWarningsByQueryId.has(operationId)) {
1170
- this.noCacheWarningsByQueryId.add(operationId);
1120
+ !this.noCacheWarningsByCause.has(cause)) {
1121
+ this.noCacheWarningsByCause.add(cause);
1171
1122
  __DEV__ && invariant_1.invariant.warn(
1172
1123
  92,
1173
1124
  (0, internal_1.getOperationName)(document, `Unnamed ${operationType ?? "operation"}`)
@@ -1311,12 +1262,6 @@ class QueryManager {
1311
1262
  return { fromLink: false, observable: rxjs_2.EMPTY };
1312
1263
  }
1313
1264
  }
1314
- getOrCreateQuery(queryId) {
1315
- if (queryId && !this.queries.has(queryId)) {
1316
- this.queries.set(queryId, new QueryInfo_js_1.QueryInfo(this, queryId));
1317
- }
1318
- return this.queries.get(queryId);
1319
- }
1320
1265
  }
1321
1266
  exports.QueryManager = QueryManager;
1322
1267
  function validateDidEmitValue() {