@apollo/client 4.0.0-alpha.16 → 4.0.0-alpha.17

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 (90) hide show
  1. package/CHANGELOG.md +88 -0
  2. package/__cjs/core/ObservableQuery.cjs +104 -48
  3. package/__cjs/core/ObservableQuery.cjs.map +1 -1
  4. package/__cjs/core/ObservableQuery.d.cts +19 -2
  5. package/__cjs/core/QueryManager.cjs +19 -2
  6. package/__cjs/core/QueryManager.cjs.map +1 -1
  7. package/__cjs/core/index.cjs.map +1 -1
  8. package/__cjs/core/index.d.cts +1 -1
  9. package/__cjs/core/types.d.cts +25 -3
  10. package/__cjs/react/hooks/useBackgroundQuery.cjs.map +1 -1
  11. package/__cjs/react/hooks/useBackgroundQuery.d.cts +50 -14
  12. package/__cjs/react/hooks/useLazyQuery.cjs +1 -0
  13. package/__cjs/react/hooks/useLazyQuery.cjs.map +1 -1
  14. package/__cjs/react/hooks/useLazyQuery.d.cts +28 -53
  15. package/__cjs/react/hooks/useLoadableQuery.cjs.map +1 -1
  16. package/__cjs/react/hooks/useLoadableQuery.d.cts +7 -8
  17. package/__cjs/react/hooks/useQuery.cjs +3 -2
  18. package/__cjs/react/hooks/useQuery.cjs.map +1 -1
  19. package/__cjs/react/hooks/useQuery.d.cts +10 -48
  20. package/__cjs/react/hooks/useQueryRefHandlers.cjs.map +1 -1
  21. package/__cjs/react/hooks/useQueryRefHandlers.d.cts +2 -2
  22. package/__cjs/react/hooks/useReadQuery.cjs +1 -0
  23. package/__cjs/react/hooks/useReadQuery.cjs.map +1 -1
  24. package/__cjs/react/hooks/useReadQuery.d.cts +4 -11
  25. package/__cjs/react/hooks/useSuspenseQuery.cjs +2 -0
  26. package/__cjs/react/hooks/useSuspenseQuery.cjs.map +1 -1
  27. package/__cjs/react/hooks/useSuspenseQuery.d.cts +12 -24
  28. package/__cjs/react/index.cjs.map +1 -1
  29. package/__cjs/react/index.d.cts +1 -1
  30. package/__cjs/react/internal/cache/QueryReference.cjs +7 -1
  31. package/__cjs/react/internal/cache/QueryReference.cjs.map +1 -1
  32. package/__cjs/react/internal/cache/QueryReference.d.cts +25 -65
  33. package/__cjs/react/internal/cache/SuspenseCache.cjs.map +1 -1
  34. package/__cjs/react/internal/cache/SuspenseCache.d.cts +3 -3
  35. package/__cjs/react/internal/index.cjs.map +1 -1
  36. package/__cjs/react/internal/index.d.cts +1 -1
  37. package/__cjs/react/internal/types.d.cts +2 -2
  38. package/__cjs/react/query-preloader/createQueryPreloader.cjs.map +1 -1
  39. package/__cjs/react/query-preloader/createQueryPreloader.d.cts +4 -5
  40. package/__cjs/react/ssr/prerenderStatic.cjs.map +1 -1
  41. package/__cjs/react/ssr/useSSRQuery.cjs +1 -0
  42. package/__cjs/react/ssr/useSSRQuery.cjs.map +1 -1
  43. package/__cjs/react/types/types.documentation.d.cts +12 -0
  44. package/__cjs/utilities/internal/toQueryResult.cjs.map +1 -1
  45. package/__cjs/version.cjs +1 -1
  46. package/core/ObservableQuery.d.ts +19 -2
  47. package/core/ObservableQuery.js +105 -49
  48. package/core/ObservableQuery.js.map +1 -1
  49. package/core/QueryManager.js +19 -2
  50. package/core/QueryManager.js.map +1 -1
  51. package/core/index.d.ts +1 -1
  52. package/core/index.js.map +1 -1
  53. package/core/types.d.ts +25 -3
  54. package/package.json +1 -1
  55. package/react/hooks/useBackgroundQuery.d.ts +50 -14
  56. package/react/hooks/useBackgroundQuery.js.map +1 -1
  57. package/react/hooks/useLazyQuery.d.ts +28 -53
  58. package/react/hooks/useLazyQuery.js +1 -0
  59. package/react/hooks/useLazyQuery.js.map +1 -1
  60. package/react/hooks/useLoadableQuery.d.ts +7 -8
  61. package/react/hooks/useLoadableQuery.js.map +1 -1
  62. package/react/hooks/useQuery.d.ts +10 -48
  63. package/react/hooks/useQuery.js +3 -2
  64. package/react/hooks/useQuery.js.map +1 -1
  65. package/react/hooks/useQueryRefHandlers.d.ts +2 -2
  66. package/react/hooks/useQueryRefHandlers.js.map +1 -1
  67. package/react/hooks/useReadQuery.d.ts +4 -11
  68. package/react/hooks/useReadQuery.js +1 -0
  69. package/react/hooks/useReadQuery.js.map +1 -1
  70. package/react/hooks/useSuspenseQuery.d.ts +12 -24
  71. package/react/hooks/useSuspenseQuery.js +2 -0
  72. package/react/hooks/useSuspenseQuery.js.map +1 -1
  73. package/react/index.d.ts +1 -1
  74. package/react/index.js.map +1 -1
  75. package/react/internal/cache/QueryReference.d.ts +25 -65
  76. package/react/internal/cache/QueryReference.js +7 -1
  77. package/react/internal/cache/QueryReference.js.map +1 -1
  78. package/react/internal/cache/SuspenseCache.d.ts +3 -3
  79. package/react/internal/cache/SuspenseCache.js.map +1 -1
  80. package/react/internal/index.d.ts +1 -1
  81. package/react/internal/index.js.map +1 -1
  82. package/react/internal/types.d.ts +2 -2
  83. package/react/query-preloader/createQueryPreloader.d.ts +4 -5
  84. package/react/query-preloader/createQueryPreloader.js.map +1 -1
  85. package/react/ssr/prerenderStatic.js.map +1 -1
  86. package/react/ssr/useSSRQuery.js +1 -0
  87. package/react/ssr/useSSRQuery.js.map +1 -1
  88. package/react/types/types.documentation.d.ts +12 -0
  89. package/utilities/internal/toQueryResult.js.map +1 -1
  90. package/version.js +1 -1
@@ -1,23 +1,24 @@
1
1
  import { equal } from "@wry/equality";
2
2
  import { Slot } from "optimism";
3
- import { BehaviorSubject, lastValueFrom, Observable, Subject, tap } from "rxjs";
3
+ import { BehaviorSubject, Observable, share, Subject, tap } from "rxjs";
4
4
  import { __DEV__ } from "@apollo/client/utilities/environment";
5
5
  import { compact, filterMap, getOperationDefinition, getQueryDefinition, preventUnhandledRejection, toQueryResult, } from "@apollo/client/utilities/internal";
6
6
  import { invariant } from "@apollo/client/utilities/invariant";
7
7
  import { equalByQuery } from "./equalByQuery.js";
8
8
  import { isNetworkRequestInFlight, NetworkStatus } from "./networkStatus.js";
9
9
  const { assign, hasOwnProperty } = Object;
10
- const newNetworkStatusSymbol = Symbol();
11
10
  const uninitialized = {
12
11
  loading: true,
13
12
  networkStatus: NetworkStatus.loading,
14
13
  data: undefined,
14
+ dataState: "empty",
15
15
  partial: true,
16
16
  };
17
17
  const empty = {
18
18
  loading: false,
19
19
  networkStatus: NetworkStatus.ready,
20
20
  data: undefined,
21
+ dataState: "empty",
21
22
  partial: true,
22
23
  };
23
24
  export class ObservableQuery {
@@ -200,19 +201,23 @@ export class ObservableQuery {
200
201
  : initialFetchPolicy || this.options.fetchPolicy;
201
202
  const defaultResult = {
202
203
  data: undefined,
204
+ dataState: "empty",
203
205
  loading: true,
204
206
  networkStatus: NetworkStatus.loading,
205
207
  partial: true,
206
208
  };
207
209
  const cacheResult = () => {
208
210
  const diff = this.getCacheDiff();
211
+ // TODO: queryInfo.getDiff should handle this since cache.diff returns a
212
+ // null when returnPartialData is false
213
+ const data = this.options.returnPartialData || diff.complete ?
214
+ diff.result ?? undefined
215
+ : undefined;
209
216
  return this.maskResult({
210
- data:
211
- // TODO: queryInfo.getDiff should handle this since cache.diff returns a
212
- // null when returnPartialData is false
213
- this.options.returnPartialData || diff.complete ?
214
- diff.result ?? undefined
215
- : undefined,
217
+ data,
218
+ dataState: diff.complete ? "complete"
219
+ : data === undefined ? "empty"
220
+ : "partial",
216
221
  loading: !diff.complete,
217
222
  networkStatus: diff.complete ? NetworkStatus.ready : NetworkStatus.loading,
218
223
  partial: !diff.complete,
@@ -365,9 +370,8 @@ export class ObservableQuery {
365
370
  this.getVariablesWithDefaults({ ...this.variables, ...variables });
366
371
  }
367
372
  this.queryInfo.resetLastWrite();
368
- return this.reobserve({
369
- ...reobserveOptions,
370
- [newNetworkStatusSymbol]: NetworkStatus.refetch,
373
+ return this._reobserve(reobserveOptions, {
374
+ newNetworkStatus: NetworkStatus.refetch,
371
375
  });
372
376
  }
373
377
  /**
@@ -493,6 +497,7 @@ export class ObservableQuery {
493
497
  // will be overwritten anyways, just here for types sake
494
498
  loading: false,
495
499
  data: data,
500
+ dataState: lastResult.dataState === "streaming" ? "streaming" : "complete",
496
501
  },
497
502
  source: "network",
498
503
  });
@@ -599,12 +604,11 @@ export class ObservableQuery {
599
604
  if (!this.hasObservers()) {
600
605
  return toQueryResult(this.getCurrentResult());
601
606
  }
602
- return this.reobserve({
607
+ return this._reobserve({
603
608
  // Reset options.fetchPolicy to its original value.
604
609
  fetchPolicy: this.options.initialFetchPolicy,
605
610
  variables,
606
- [newNetworkStatusSymbol]: NetworkStatus.setVariables,
607
- });
611
+ }, { newNetworkStatus: NetworkStatus.setVariables });
608
612
  }
609
613
  /**
610
614
  * A function that enables you to update the query's cached result without executing a followup GraphQL operation.
@@ -676,7 +680,7 @@ export class ObservableQuery {
676
680
  }
677
681
  return options.fetchPolicy;
678
682
  }
679
- fetch(options, networkStatus, fetchQuery) {
683
+ fetch(options, networkStatus, fetchQuery, operator) {
680
684
  // TODO Make sure we update the networkStatus (and infer fetchVariables)
681
685
  // before actually committing to the fetch.
682
686
  const initialFetchPolicy = this.options.fetchPolicy;
@@ -727,7 +731,7 @@ export class ObservableQuery {
727
731
  }
728
732
  }
729
733
  });
730
- const { observable, fromLink } = this.queryManager.fetchObservableWithInfo(queryInfo, options, { networkStatus, query: fetchQuery, onCacheHit, fetchQueryOperator });
734
+ let { observable, fromLink } = this.queryManager.fetchObservableWithInfo(queryInfo, options, { networkStatus, query: fetchQuery, onCacheHit, fetchQueryOperator });
731
735
  // track query and variables from the start of the operation
732
736
  const { query, variables } = this;
733
737
  const operation = {
@@ -738,6 +742,7 @@ export class ObservableQuery {
738
742
  this.activeOperations.add(operation);
739
743
  let forceFirstValueEmit = networkStatus == NetworkStatus.refetch ||
740
744
  networkStatus == NetworkStatus.setVariables;
745
+ observable = observable.pipe(operator, share());
741
746
  const subscription = observable
742
747
  .pipe(tap({
743
748
  next: (notification) => {
@@ -787,7 +792,7 @@ export class ObservableQuery {
787
792
  if (this.pollingInfo) {
788
793
  if (!isNetworkRequestInFlight(this.networkStatus) &&
789
794
  !this.options.skipPollAttempt?.()) {
790
- this.reobserve({
795
+ this._reobserve({
791
796
  // Most fetchPolicy options don't make sense to use in a polling context, as
792
797
  // users wouldn't want to be polling the cache directly. However, network-only and
793
798
  // no-cache are both useful for when the user wants to control whether or not the
@@ -795,7 +800,8 @@ export class ObservableQuery {
795
800
  fetchPolicy: this.options.initialFetchPolicy === "no-cache" ?
796
801
  "no-cache"
797
802
  : "network-only",
798
- [newNetworkStatusSymbol]: NetworkStatus.poll,
803
+ }, {
804
+ newNetworkStatus: NetworkStatus.poll,
799
805
  }).then(poll, poll);
800
806
  }
801
807
  else {
@@ -824,13 +830,11 @@ export class ObservableQuery {
824
830
  * merged with the current options when given.
825
831
  */
826
832
  reobserve(newOptions) {
833
+ return this._reobserve(newOptions);
834
+ }
835
+ _reobserve(newOptions, internalOptions) {
827
836
  this.isTornDown = false;
828
- let newNetworkStatus;
829
- if (newOptions) {
830
- newNetworkStatus = newOptions[newNetworkStatusSymbol];
831
- // Avoid setting the symbol option in this.options
832
- delete newOptions[newNetworkStatusSymbol];
833
- }
837
+ let { newNetworkStatus } = internalOptions || {};
834
838
  const useDisposableObservable =
835
839
  // Refetching uses a disposable Observable to allow refetches using different
836
840
  // options, without permanently altering the options of the
@@ -905,32 +909,38 @@ export class ObservableQuery {
905
909
  this.cancelPolling();
906
910
  }
907
911
  this.resubscribeCache();
908
- const { subscription, observable, fromLink } = this.fetch(options, newNetworkStatus, query);
909
- if (!useDisposableObservable && (fromLink || !this.linkSubscription)) {
910
- if (this.linkSubscription) {
911
- this.linkSubscription.unsubscribe();
912
- }
913
- this.linkSubscription = subscription;
914
- }
915
- return preventUnhandledRejection(
916
- // Note: lastValueFrom will create a separate subscription to the
917
- // observable which means that terminating this ObservableQuery will not
918
- // cancel the request from the link chain.
919
- lastValueFrom(observable.pipe(filterMap((value) => {
912
+ const { promise, operator: promiseOperator } = getTrackingOperatorPromise((value) => {
920
913
  switch (value.kind) {
921
914
  case "E":
922
915
  throw value.error;
923
916
  case "N":
924
- if (value.source !== "newNetworkStatus")
917
+ if (value.source !== "newNetworkStatus" && !value.value.loading)
925
918
  return value.value;
926
919
  }
927
- })), {
928
- // This default value should only be used when using a `fetchPolicy` of
929
- // `standby` since that fetch policy completes without emitting a
930
- // result. Since we are converting this to a QueryResult type, we
931
- // omit the extra fields from ApolloQueryResult in the default value.
932
- defaultValue: { data: undefined },
933
- }).then((result) => toQueryResult(this.maskResult(result))));
920
+ },
921
+ // This default value should only be used when using a `fetchPolicy` of
922
+ // `standby` since that fetch policy completes without emitting a
923
+ // result. Since we are converting this to a QueryResult type, we
924
+ // omit the extra fields from ApolloQueryResult in the default value.
925
+ options.fetchPolicy === "standby" ?
926
+ { data: undefined }
927
+ : undefined);
928
+ const { subscription, observable, fromLink } = this.fetch(options, newNetworkStatus, query, promiseOperator);
929
+ if (!useDisposableObservable && (fromLink || !this.linkSubscription)) {
930
+ if (this.linkSubscription) {
931
+ this.linkSubscription.unsubscribe();
932
+ }
933
+ this.linkSubscription = subscription;
934
+ }
935
+ const ret = Object.assign(preventUnhandledRejection(promise.then((result) => toQueryResult(this.maskResult(result)))), {
936
+ retain: () => {
937
+ const subscription = observable.subscribe({});
938
+ const unsubscribe = () => subscription.unsubscribe();
939
+ promise.then(unsubscribe, unsubscribe);
940
+ return ret;
941
+ },
942
+ });
943
+ return ret;
934
944
  }
935
945
  hasObservers() {
936
946
  return this.subject.observed;
@@ -1043,6 +1053,9 @@ export class ObservableQuery {
1043
1053
  kind: "N",
1044
1054
  value: {
1045
1055
  data: diff.result,
1056
+ dataState: diff.complete ? "complete"
1057
+ : diff.result ? "partial"
1058
+ : "empty",
1046
1059
  networkStatus: NetworkStatus.ready,
1047
1060
  loading: false,
1048
1061
  error: undefined,
@@ -1159,14 +1172,17 @@ export class ObservableQuery {
1159
1172
  result =
1160
1173
  notification.kind === "E" ?
1161
1174
  {
1162
- data: undefined,
1163
- partial: true,
1164
- ...(isEqualQuery(previous, notification) ? previous.result : {}),
1175
+ ...(isEqualQuery(previous, notification) ?
1176
+ previous.result
1177
+ : { data: undefined, dataState: "empty", partial: true }),
1165
1178
  error: notification.error,
1166
1179
  networkStatus: NetworkStatus.error,
1167
1180
  loading: false,
1168
1181
  }
1169
1182
  : notification.value;
1183
+ if (result.error && result.dataState === "streaming") {
1184
+ result.dataState = "complete";
1185
+ }
1170
1186
  if (result.error) {
1171
1187
  meta.shouldEmit = 1 /* EmitBehavior.force */;
1172
1188
  }
@@ -1205,7 +1221,7 @@ export class ObservableQuery {
1205
1221
  reobserveCacheFirst() {
1206
1222
  const { fetchPolicy, nextFetchPolicy } = this.options;
1207
1223
  if (fetchPolicy === "cache-and-network" || fetchPolicy === "network-only") {
1208
- return this.reobserve({
1224
+ this.reobserve({
1209
1225
  fetchPolicy: "cache-first",
1210
1226
  // Use a temporary nextFetchPolicy function that replaces itself with the
1211
1227
  // previous nextFetchPolicy value and returns the original fetchPolicy.
@@ -1223,7 +1239,9 @@ export class ObservableQuery {
1223
1239
  },
1224
1240
  });
1225
1241
  }
1226
- return this.reobserve();
1242
+ else {
1243
+ this.reobserve();
1244
+ }
1227
1245
  }
1228
1246
  getVariablesWithDefaults(variables) {
1229
1247
  return this.queryManager.getVariables(this.query, variables);
@@ -1237,4 +1255,42 @@ export function logMissingFieldErrors(missing) {
1237
1255
  function isEqualQuery(a, b) {
1238
1256
  return !!(a && b && a.query === b.query && equal(a.variables, b.variables));
1239
1257
  }
1258
+ function getTrackingOperatorPromise(filterMapCb, defaultValue) {
1259
+ let lastValue = defaultValue, resolve, reject;
1260
+ const promise = new Promise((res, rej) => {
1261
+ resolve = res;
1262
+ reject = rej;
1263
+ });
1264
+ const operator = tap({
1265
+ next(value) {
1266
+ try {
1267
+ const newValue = filterMapCb(value);
1268
+ if (newValue !== undefined) {
1269
+ lastValue = newValue;
1270
+ }
1271
+ }
1272
+ catch (error) {
1273
+ reject(error);
1274
+ }
1275
+ },
1276
+ finalize: () => {
1277
+ if (lastValue) {
1278
+ resolve(lastValue);
1279
+ }
1280
+ else {
1281
+ const message = "The operation was aborted.";
1282
+ const name = "AbortError";
1283
+ reject(typeof DOMException !== "undefined" ?
1284
+ new DOMException(message, name)
1285
+ // some environments do not have `DOMException`, e.g. node
1286
+ // uses a normal `Error` with a `name` property instead: https://github.com/phryneas/node/blob/d0579b64f0f6b722f8e49bf8a471dd0d0604a21e/lib/internal/errors.js#L964
1287
+ // error.code is a legacy property that is not used anymore,
1288
+ // and also inconsistent across environments (in supporting
1289
+ // browsers it is `20`, in node `'ABORT_ERR'`) so we omit that.
1290
+ : Object.assign(new Error(message), { name }));
1291
+ }
1292
+ },
1293
+ });
1294
+ return { promise, operator };
1295
+ }
1240
1296
  //# sourceMappingURL=ObservableQuery.js.map